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 pub(crate) fn new(
43 window: &Window,
44 session: &XRSession,
45 ty: XRReferenceSpaceType,
46 can_gc: CanGc,
47 ) -> DomRoot<XRReferenceSpace> {
48 let offset = XRRigidTransform::identity(window, can_gc);
49 Self::new_offset(&window.global(), session, ty, &offset, can_gc)
50 }
51
52 pub(crate) fn new_offset(
53 global: &GlobalScope,
54 session: &XRSession,
55 ty: XRReferenceSpaceType,
56 offset: &XRRigidTransform,
57 can_gc: CanGc,
58 ) -> DomRoot<XRReferenceSpace> {
59 reflect_dom_object(
60 Box::new(XRReferenceSpace::new_inherited(session, offset, ty)),
61 global,
62 can_gc,
63 )
64 }
65
66 pub(crate) fn space(&self) -> Space {
67 let base = match self.ty {
68 XRReferenceSpaceType::Local => webxr_api::BaseSpace::Local,
69 XRReferenceSpaceType::Viewer => webxr_api::BaseSpace::Viewer,
70 XRReferenceSpaceType::Local_floor => webxr_api::BaseSpace::Floor,
71 XRReferenceSpaceType::Bounded_floor => webxr_api::BaseSpace::BoundedFloor,
72 _ => panic!("unsupported reference space found"),
73 };
74 let offset = self.offset.transform();
75 Space { base, offset }
76 }
77
78 pub(crate) fn ty(&self) -> XRReferenceSpaceType {
79 self.ty
80 }
81}
82
83impl XRReferenceSpaceMethods<crate::DomTypeHolder> for XRReferenceSpace {
84 fn GetOffsetReferenceSpace(&self, new: &XRRigidTransform, can_gc: CanGc) -> DomRoot<Self> {
86 let offset = new.transform().then(&self.offset.transform());
87 let offset = XRRigidTransform::new(self.global().as_window(), offset, can_gc);
88 Self::new_offset(
89 &self.global(),
90 self.upcast::<XRSpace>().session(),
91 self.ty,
92 &offset,
93 CanGc::note(),
94 )
95 }
96
97 event_handler!(reset, GetOnreset, SetOnreset);
99}
100
101impl XRReferenceSpace {
102 pub(crate) fn get_base_transform(&self, base_pose: &Frame) -> Option<BaseTransform> {
107 let pose = self.get_pose(base_pose)?;
108 Some(pose.inverse().cast_unit())
109 }
110
111 pub(crate) fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
117 let pose = self.get_unoffset_pose(base_pose)?;
118 let offset = self.offset.transform();
119 Some(offset.then(&pose))
124 }
125
126 pub(crate) fn get_unoffset_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
130 match self.ty {
131 XRReferenceSpaceType::Local => {
132 Some(RigidTransform3D::identity())
135 },
136 XRReferenceSpaceType::Local_floor | XRReferenceSpaceType::Bounded_floor => {
137 let native_to_floor = self
138 .upcast::<XRSpace>()
139 .session()
140 .with_session(|s| s.floor_transform())?;
141 Some(cast_transform(native_to_floor.inverse()))
142 },
143 XRReferenceSpaceType::Viewer => {
144 Some(cast_transform(base_pose.pose.as_ref()?.transform))
145 },
146 _ => unimplemented!(),
147 }
148 }
149
150 pub(crate) fn get_bounds(&self) -> Option<Vec<Point2D<f32, Floor>>> {
151 self.upcast::<XRSpace>()
152 .session()
153 .with_session(|s| s.reference_space_bounds())
154 }
155}