script/dom/webxr/
xrview.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use euclid::RigidTransform3D;
9use js::context::JSContext;
10use js::typedarray::{Float32, HeapFloat32Array};
11use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
12use script_bindings::trace::RootedTraceableBox;
13use webxr_api::{ApiSpace, View};
14
15use crate::dom::bindings::buffer_source::HeapBufferSource;
16use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
17use crate::dom::bindings::num::Finite;
18use crate::dom::bindings::root::{Dom, DomRoot};
19use crate::dom::window::Window;
20use crate::dom::xrrigidtransform::XRRigidTransform;
21use crate::dom::xrsession::{BaseSpace, BaseTransform, XRSession, cast_transform};
22
23#[dom_struct]
24pub(crate) struct XRView {
25 reflector_: Reflector,
26 session: Dom<XRSession>,
27 eye: XREye,
28 viewport_index: usize,
29 #[ignore_malloc_size_of = "mozjs"]
30 proj: HeapBufferSource<Float32>,
31 #[no_trace]
32 view: View<ApiSpace>,
33 transform: Dom<XRRigidTransform>,
34 requested_viewport_scale: Cell<f64>,
35}
36
37impl XRView {
38 fn new_inherited(
39 session: &XRSession,
40 transform: &XRRigidTransform,
41 eye: XREye,
42 viewport_index: usize,
43 view: View<ApiSpace>,
44 ) -> XRView {
45 XRView {
46 reflector_: Reflector::new(),
47 session: Dom::from_ref(session),
48 eye,
49 viewport_index,
50 proj: HeapBufferSource::default(),
51 view,
52 transform: Dom::from_ref(transform),
53 requested_viewport_scale: Cell::new(1.0),
54 }
55 }
56
57 pub(crate) fn new<V: Copy>(
58 cx: &mut JSContext,
59 window: &Window,
60 session: &XRSession,
61 view: &View<V>,
62 eye: XREye,
63 viewport_index: usize,
64 to_base: &BaseTransform,
65 ) -> DomRoot<XRView> {
66 let transform: RigidTransform3D<f32, V, BaseSpace> = view.transform.then(to_base);
67 let transform = XRRigidTransform::new(cx, window, cast_transform(transform));
68
69 reflect_dom_object_with_cx(
70 Box::new(XRView::new_inherited(
71 session,
72 &transform,
73 eye,
74 viewport_index,
75 view.cast_unit(),
76 )),
77 window,
78 cx,
79 )
80 }
81
82 pub(crate) fn session(&self) -> &XRSession {
83 &self.session
84 }
85
86 pub(crate) fn viewport_index(&self) -> usize {
87 self.viewport_index
88 }
89}
90
91impl XRViewMethods<crate::DomTypeHolder> for XRView {
92 fn Eye(&self) -> XREye {
94 self.eye
95 }
96
97 fn ProjectionMatrix(&self, cx: &mut JSContext) -> RootedTraceableBox<HeapFloat32Array> {
99 if !self.proj.is_initialized() {
100 let proj = self.view.projection.to_array();
102 self.proj
103 .set_data(cx, &proj)
104 .expect("Failed to set projection matrix.")
105 }
106 self.proj
107 .get_typed_array()
108 .expect("Failed to get projection matrix.")
109 }
110
111 fn Transform(&self) -> DomRoot<XRRigidTransform> {
113 DomRoot::from_ref(&self.transform)
114 }
115
116 fn GetRecommendedViewportScale(&self) -> Option<Finite<f64>> {
118 Finite::new(1.0)
120 }
121
122 fn RequestViewportScale(&self, scale: Option<Finite<f64>>) {
124 if let Some(scale) = scale &&
125 *scale > 0.0
126 {
127 let clamped_scale = scale.clamp(0.0, 1.0);
128 self.requested_viewport_scale.set(clamped_scale);
129 }
130 }
131
132 fn IsFirstPersonObserver(&self) -> bool {
134 false
136 }
137}