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