1use dom_struct::dom_struct;
6use euclid::RigidTransform3D;
7use js::jsapi::Heap;
8use js::jsval::{JSVal, UndefinedValue};
9use js::rust::MutableHandleValue;
10use script_bindings::conversions::SafeToJSValConvertible;
11use webxr_api::{Viewer, ViewerPose, Views};
12
13use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
14use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding::XRViewerPoseMethods;
15use crate::dom::bindings::reflector::reflect_dom_object;
16use crate::dom::bindings::root::DomRoot;
17use crate::dom::globalscope::GlobalScope;
18use crate::dom::window::Window;
19use crate::dom::xrpose::XRPose;
20use crate::dom::xrrigidtransform::XRRigidTransform;
21use crate::dom::xrsession::{BaseSpace, BaseTransform, XRSession, cast_transform};
22use crate::dom::xrview::XRView;
23use crate::realms::enter_realm;
24use crate::script_runtime::{CanGc, JSContext};
25
26#[dom_struct]
27pub(crate) struct XRViewerPose {
28 pose: XRPose,
29 #[ignore_malloc_size_of = "mozjs"]
30 views: Heap<JSVal>,
31}
32
33impl XRViewerPose {
34 fn new_inherited(transform: &XRRigidTransform) -> XRViewerPose {
35 XRViewerPose {
36 pose: XRPose::new_inherited(transform),
37 views: Heap::default(),
38 }
39 }
40
41 pub(crate) fn new(
42 window: &Window,
43 session: &XRSession,
44 to_base: BaseTransform,
45 viewer_pose: &ViewerPose,
46 can_gc: CanGc,
47 ) -> DomRoot<XRViewerPose> {
48 let _ac = enter_realm(window);
49 rooted_vec!(let mut views);
50 match &viewer_pose.views {
51 Views::Inline => views.push(XRView::new(
52 window,
53 session,
54 &session.inline_view(),
55 XREye::None,
56 0,
57 &to_base,
58 can_gc,
59 )),
60 Views::Mono(view) => views.push(XRView::new(
61 window,
62 session,
63 view,
64 XREye::None,
65 0,
66 &to_base,
67 can_gc,
68 )),
69 Views::Stereo(left, right) => {
70 views.push(XRView::new(
71 window,
72 session,
73 left,
74 XREye::Left,
75 0,
76 &to_base,
77 can_gc,
78 ));
79 views.push(XRView::new(
80 window,
81 session,
82 right,
83 XREye::Right,
84 1,
85 &to_base,
86 can_gc,
87 ));
88 },
89 Views::StereoCapture(left, right, third_eye) => {
90 views.push(XRView::new(
91 window,
92 session,
93 left,
94 XREye::Left,
95 0,
96 &to_base,
97 can_gc,
98 ));
99 views.push(XRView::new(
100 window,
101 session,
102 right,
103 XREye::Right,
104 1,
105 &to_base,
106 can_gc,
107 ));
108 views.push(XRView::new(
109 window,
110 session,
111 third_eye,
112 XREye::None,
113 2,
114 &to_base,
115 can_gc,
116 ));
117 },
118 Views::Cubemap(front, left, right, top, bottom, back) => {
119 views.push(XRView::new(
120 window,
121 session,
122 front,
123 XREye::None,
124 0,
125 &to_base,
126 can_gc,
127 ));
128 views.push(XRView::new(
129 window,
130 session,
131 left,
132 XREye::None,
133 1,
134 &to_base,
135 can_gc,
136 ));
137 views.push(XRView::new(
138 window,
139 session,
140 right,
141 XREye::None,
142 2,
143 &to_base,
144 can_gc,
145 ));
146 views.push(XRView::new(
147 window,
148 session,
149 top,
150 XREye::None,
151 3,
152 &to_base,
153 can_gc,
154 ));
155 views.push(XRView::new(
156 window,
157 session,
158 bottom,
159 XREye::None,
160 4,
161 &to_base,
162 can_gc,
163 ));
164 views.push(XRView::new(
165 window,
166 session,
167 back,
168 XREye::None,
169 5,
170 &to_base,
171 can_gc,
172 ));
173 },
174 };
175 let transform: RigidTransform3D<f32, Viewer, BaseSpace> =
176 viewer_pose.transform.then(&to_base);
177 let transform = XRRigidTransform::new(window, cast_transform(transform), can_gc);
178 let pose = reflect_dom_object(
179 Box::new(XRViewerPose::new_inherited(&transform)),
180 window,
181 can_gc,
182 );
183
184 let cx = GlobalScope::get_cx();
185 rooted!(in(*cx) let mut jsval = UndefinedValue());
186 views.safe_to_jsval(cx, jsval.handle_mut());
187 pose.views.set(jsval.get());
188
189 pose
190 }
191}
192
193impl XRViewerPoseMethods<crate::DomTypeHolder> for XRViewerPose {
194 fn Views(&self, _cx: JSContext, mut retval: MutableHandleValue) {
196 retval.set(self.views.get())
197 }
198}