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