script/dom/webxr/
xrviewerpose.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    /// <https://immersive-web.github.io/webxr/#dom-xrviewerpose-views>
195    fn Views(&self, _cx: JSContext, mut retval: MutableHandleValue) {
196        retval.set(self.views.get())
197    }
198}