script/dom/webxr/
xrspace.rs1use dom_struct::dom_struct;
6use euclid::RigidTransform3D;
7use webxr_api::{BaseSpace, Frame, Space};
8
9use crate::dom::bindings::inheritance::Castable;
10use crate::dom::bindings::reflector::reflect_dom_object;
11use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
12use crate::dom::eventtarget::EventTarget;
13use crate::dom::globalscope::GlobalScope;
14use crate::dom::xrinputsource::XRInputSource;
15use crate::dom::xrjointspace::XRJointSpace;
16use crate::dom::xrreferencespace::XRReferenceSpace;
17use crate::dom::xrsession::{ApiPose, XRSession, cast_transform};
18use crate::script_runtime::CanGc;
19
20#[dom_struct]
21pub(crate) struct XRSpace {
22 eventtarget: EventTarget,
23 session: Dom<XRSession>,
24 input_source: MutNullableDom<XRInputSource>,
25 is_grip_space: bool,
27}
28
29impl XRSpace {
30 pub(crate) fn new_inherited(session: &XRSession) -> XRSpace {
31 XRSpace {
32 eventtarget: EventTarget::new_inherited(),
33 session: Dom::from_ref(session),
34 input_source: Default::default(),
35 is_grip_space: false,
36 }
37 }
38
39 fn new_inputspace_inner(
40 session: &XRSession,
41 input: &XRInputSource,
42 is_grip_space: bool,
43 ) -> XRSpace {
44 XRSpace {
45 eventtarget: EventTarget::new_inherited(),
46 session: Dom::from_ref(session),
47 input_source: MutNullableDom::new(Some(input)),
48 is_grip_space,
49 }
50 }
51
52 pub(crate) fn new_inputspace(
53 global: &GlobalScope,
54 session: &XRSession,
55 input: &XRInputSource,
56 is_grip_space: bool,
57 can_gc: CanGc,
58 ) -> DomRoot<XRSpace> {
59 reflect_dom_object(
60 Box::new(XRSpace::new_inputspace_inner(session, input, is_grip_space)),
61 global,
62 can_gc,
63 )
64 }
65
66 pub(crate) fn space(&self) -> Space {
67 if let Some(rs) = self.downcast::<XRReferenceSpace>() {
68 rs.space()
69 } else if let Some(j) = self.downcast::<XRJointSpace>() {
70 j.space()
71 } else if let Some(source) = self.input_source.get() {
72 let base = if self.is_grip_space {
73 BaseSpace::Grip(source.id())
74 } else {
75 BaseSpace::TargetRay(source.id())
76 };
77 Space {
78 base,
79 offset: RigidTransform3D::identity(),
80 }
81 } else {
82 panic!("invalid space found")
83 }
84 }
85}
86
87impl XRSpace {
88 pub(crate) fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
94 if let Some(reference) = self.downcast::<XRReferenceSpace>() {
95 reference.get_pose(base_pose)
96 } else if let Some(joint) = self.downcast::<XRJointSpace>() {
97 joint.get_pose(base_pose)
98 } else if let Some(source) = self.input_source.get() {
99 let id = source.id();
104 let frame = base_pose
106 .inputs
107 .iter()
108 .find(|i| i.id == id)
109 .expect("no input found");
110 if self.is_grip_space {
111 frame.grip_origin.map(cast_transform)
112 } else {
113 frame.target_ray_origin.map(cast_transform)
114 }
115 } else {
116 unreachable!()
117 }
118 }
119
120 pub(crate) fn session(&self) -> &XRSession {
121 &self.session
122 }
123}