script/dom/webxr/
xrreferencespace.rs1use dom_struct::dom_struct;
6use euclid::{Point2D, RigidTransform3D};
7use webxr_api::{self, Floor, Frame, Space};
8
9use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::{
10 XRReferenceSpaceMethods, XRReferenceSpaceType,
11};
12use crate::dom::bindings::inheritance::Castable;
13use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::globalscope::GlobalScope;
16use crate::dom::window::Window;
17use crate::dom::xrrigidtransform::XRRigidTransform;
18use crate::dom::xrsession::{ApiPose, BaseTransform, XRSession, cast_transform};
19use crate::dom::xrspace::XRSpace;
20use crate::script_runtime::CanGc;
21
22#[dom_struct]
23pub(crate) struct XRReferenceSpace {
24 xrspace: XRSpace,
25 offset: Dom<XRRigidTransform>,
26 ty: XRReferenceSpaceType,
27}
28
29impl XRReferenceSpace {
30 pub(crate) fn new_inherited(
31 session: &XRSession,
32 offset: &XRRigidTransform,
33 ty: XRReferenceSpaceType,
34 ) -> XRReferenceSpace {
35 XRReferenceSpace {
36 xrspace: XRSpace::new_inherited(session),
37 offset: Dom::from_ref(offset),
38 ty,
39 }
40 }
41
42 #[allow(unused)]
43 pub(crate) fn new(
44 window: &Window,
45 session: &XRSession,
46 ty: XRReferenceSpaceType,
47 can_gc: CanGc,
48 ) -> DomRoot<XRReferenceSpace> {
49 let offset = XRRigidTransform::identity(window, can_gc);
50 Self::new_offset(&window.global(), session, ty, &offset, can_gc)
51 }
52
53 #[allow(unused)]
54 pub(crate) fn new_offset(
55 global: &GlobalScope,
56 session: &XRSession,
57 ty: XRReferenceSpaceType,
58 offset: &XRRigidTransform,
59 can_gc: CanGc,
60 ) -> DomRoot<XRReferenceSpace> {
61 reflect_dom_object(
62 Box::new(XRReferenceSpace::new_inherited(session, offset, ty)),
63 global,
64 can_gc,
65 )
66 }
67
68 pub(crate) fn space(&self) -> Space {
69 let base = match self.ty {
70 XRReferenceSpaceType::Local => webxr_api::BaseSpace::Local,
71 XRReferenceSpaceType::Viewer => webxr_api::BaseSpace::Viewer,
72 XRReferenceSpaceType::Local_floor => webxr_api::BaseSpace::Floor,
73 XRReferenceSpaceType::Bounded_floor => webxr_api::BaseSpace::BoundedFloor,
74 _ => panic!("unsupported reference space found"),
75 };
76 let offset = self.offset.transform();
77 Space { base, offset }
78 }
79
80 pub(crate) fn ty(&self) -> XRReferenceSpaceType {
81 self.ty
82 }
83}
84
85impl XRReferenceSpaceMethods<crate::DomTypeHolder> for XRReferenceSpace {
86 fn GetOffsetReferenceSpace(&self, new: &XRRigidTransform, can_gc: CanGc) -> DomRoot<Self> {
88 let offset = new.transform().then(&self.offset.transform());
89 let offset = XRRigidTransform::new(self.global().as_window(), offset, can_gc);
90 Self::new_offset(
91 &self.global(),
92 self.upcast::<XRSpace>().session(),
93 self.ty,
94 &offset,
95 CanGc::note(),
96 )
97 }
98
99 event_handler!(reset, GetOnreset, SetOnreset);
101}
102
103impl XRReferenceSpace {
104 pub(crate) fn get_base_transform(&self, base_pose: &Frame) -> Option<BaseTransform> {
109 let pose = self.get_pose(base_pose)?;
110 Some(pose.inverse().cast_unit())
111 }
112
113 pub(crate) fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
119 let pose = self.get_unoffset_pose(base_pose)?;
120 let offset = self.offset.transform();
121 Some(offset.then(&pose))
126 }
127
128 pub(crate) fn get_unoffset_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
132 match self.ty {
133 XRReferenceSpaceType::Local => {
134 Some(RigidTransform3D::identity())
137 },
138 XRReferenceSpaceType::Local_floor | XRReferenceSpaceType::Bounded_floor => {
139 let native_to_floor = self
140 .upcast::<XRSpace>()
141 .session()
142 .with_session(|s| s.floor_transform())?;
143 Some(cast_transform(native_to_floor.inverse()))
144 },
145 XRReferenceSpaceType::Viewer => {
146 Some(cast_transform(base_pose.pose.as_ref()?.transform))
147 },
148 _ => unimplemented!(),
149 }
150 }
151
152 pub(crate) fn get_bounds(&self) -> Option<Vec<Point2D<f32, Floor>>> {
153 self.upcast::<XRSpace>()
154 .session()
155 .with_session(|s| s.reference_space_bounds())
156 }
157}