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