diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs index 2387cb8f6d5..e8ae7aa4990 100644 --- a/components/script/dom/dompointreadonly.rs +++ b/components/script/dom/dompointreadonly.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::{ DOMPointReadOnlyMethods, Wrap, }; @@ -50,6 +51,10 @@ impl DOMPointReadOnly { ) -> Fallible> { Ok(DOMPointReadOnly::new(global, x, y, z, w)) } + + pub fn new_from_init(global: &GlobalScope, p: &DOMPointInit) -> DomRoot { + DOMPointReadOnly::new(global, p.x, p.y, p.z, p.w) + } } impl DOMPointReadOnlyMethods for DOMPointReadOnly { diff --git a/components/script/dom/webidls/XRFrame.webidl b/components/script/dom/webidls/XRFrame.webidl index 6c40306755d..24f714fcb76 100644 --- a/components/script/dom/webidls/XRFrame.webidl +++ b/components/script/dom/webidls/XRFrame.webidl @@ -8,6 +8,6 @@ interface XRFrame { readonly attribute XRSession session; - XRViewerPose? getViewerPose(optional XRReferenceSpace referenceSpace); + XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); // XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace); }; diff --git a/components/script/dom/webidls/XRReferenceSpace.webidl b/components/script/dom/webidls/XRReferenceSpace.webidl index fdedfe0bb4f..43236ea338c 100644 --- a/components/script/dom/webidls/XRReferenceSpace.webidl +++ b/components/script/dom/webidls/XRReferenceSpace.webidl @@ -4,18 +4,8 @@ // https://immersive-web.github.io/webxr/#xrreferencespace-interface -enum XRReferenceSpaceType { - "stationary", - "bounded", - "unbounded" -}; - -dictionary XRReferenceSpaceOptions { - required XRReferenceSpaceType type; -}; - [SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] interface XRReferenceSpace : XRSpace { - // attribute XRRigidTransform originOffset; + attribute XRRigidTransform originOffset; // attribute EventHandler onreset; }; diff --git a/components/script/dom/webidls/XRRigidTransform.webidl b/components/script/dom/webidls/XRRigidTransform.webidl index f7ccd0fb188..91b4f92dc3c 100644 --- a/components/script/dom/webidls/XRRigidTransform.webidl +++ b/components/script/dom/webidls/XRRigidTransform.webidl @@ -4,10 +4,10 @@ // https://immersive-web.github.io/webxr/#xrrigidtransform-interface -[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] -// [Constructor(optional DOMPointInit position, optional DOMPointInit orientation)] +[SecureContext, Exposed=Window, Pref="dom.webxr.enabled", + Constructor(optional DOMPointInit position, optional DOMPointInit orientation)] interface XRRigidTransform { - // readonly attribute DOMPointReadOnly position; - // readonly attribute DOMPointReadOnly orientation; + readonly attribute DOMPointReadOnly position; + readonly attribute DOMPointReadOnly orientation; // readonly attribute Float32Array matrix; }; diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index a07fa355e6e..fa8d13b7cb3 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -24,8 +24,7 @@ interface XRSession : EventTarget { attribute XRLayer? baseLayer; // // Methods - // Promise requestReferenceSpace(XRReferenceSpaceType type, - // optional XRReferenceSpaceOptions options); + Promise requestReferenceSpace(XRReferenceSpaceOptions options); // FrozenArray getInputSources(); @@ -43,3 +42,15 @@ interface XRSession : EventTarget { // attribute EventHandler onselectstart; // attribute EventHandler onselectend; }; + +enum XRReferenceSpaceType { + "identity", + "stationary", + "bounded", + "unbounded" +}; + +dictionary XRReferenceSpaceOptions { + required XRReferenceSpaceType type; + XRStationaryReferenceSpaceSubtype subtype; +}; diff --git a/components/script/dom/webidls/XRStationaryReferenceSpace.webidl b/components/script/dom/webidls/XRStationaryReferenceSpace.webidl index 3580ac94602..b04100dac6d 100644 --- a/components/script/dom/webidls/XRStationaryReferenceSpace.webidl +++ b/components/script/dom/webidls/XRStationaryReferenceSpace.webidl @@ -10,10 +10,6 @@ enum XRStationaryReferenceSpaceSubtype { "position-disabled" }; -dictionary XRStationaryReferenceSpaceOptions : XRReferenceSpaceOptions { - required XRStationaryReferenceSpaceSubtype subtype; -}; - [SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] interface XRStationaryReferenceSpace: XRReferenceSpace { // readonly attribute XRStationaryReferenceSpaceSubtype subtype; diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index 8343bb76420..b569f7d9e46 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -5,11 +5,13 @@ use crate::dom::bindings::codegen::Bindings::XRFrameBinding; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods; use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye; +use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; +use crate::dom::xrstationaryreferencespace::XRStationaryReferenceSpace; use crate::dom::xrview::XRView; use crate::dom::xrviewerpose::XRViewerPose; use dom_struct::dom_struct; @@ -52,16 +54,17 @@ impl XRFrameMethods for XRFrame { } /// https://immersive-web.github.io/webxr/#dom-xrframe-getviewerpose - fn GetViewerPose(&self, reference: Option<&XRReferenceSpace>) -> Option> { - // We assume the reference space is eye level for now - // since it's the only one 3DOF devices support - if reference.is_some() { - // it's not possible to obtain a reference - // space at all yet - return None; + fn GetViewerPose(&self, reference: &XRReferenceSpace) -> Option> { + if let Some(_) = reference.downcast::() { + // For 3DOF devices all three kinds of reference spaces are identical + // FIXME(#23070, Manishearth) support originOffset + let left = XRView::new(&self.global(), &self.session, XREye::Left, &self.data); + let right = XRView::new(&self.global(), &self.session, XREye::Right, &self.data); + Some(XRViewerPose::new(&self.global(), &left, &right)) + } else { + // FIXME(#23070, Manishearth) support identity reference spaces + // depends on https://github.com/immersive-web/webxr/issues/565 + None } - let left = XRView::new(&self.global(), &self.session, XREye::Left, &self.data); - let right = XRView::new(&self.global(), &self.session, XREye::Right, &self.data); - Some(XRViewerPose::new(&self.global(), &left, &right)) } } diff --git a/components/script/dom/xrreferencespace.rs b/components/script/dom/xrreferencespace.rs index 308b710d928..a24ab48d0c1 100644 --- a/components/script/dom/xrreferencespace.rs +++ b/components/script/dom/xrreferencespace.rs @@ -3,30 +3,64 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding; +use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceMethods; use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::root::DomRoot; -use crate::dom::globalscope::GlobalScope; +use crate::dom::bindings::root::{DomRoot, MutDom}; +use crate::dom::dompointreadonly::DOMPointReadOnly; +use crate::dom::window::Window; +use crate::dom::xrrigidtransform::XRRigidTransform; +use crate::dom::xrsession::XRSession; use crate::dom::xrspace::XRSpace; use dom_struct::dom_struct; #[dom_struct] pub struct XRReferenceSpace { xrspace: XRSpace, + transform: MutDom, } impl XRReferenceSpace { - pub fn new_inherited() -> XRReferenceSpace { + pub fn new_inherited(session: &XRSession, transform: &XRRigidTransform) -> XRReferenceSpace { XRReferenceSpace { - xrspace: XRSpace::new_inherited(), + xrspace: XRSpace::new_inherited(session), + transform: MutDom::new(transform), } } #[allow(unused)] - pub fn new(global: &GlobalScope) -> DomRoot { + pub fn new( + global: &Window, + session: &XRSession, + position: &DOMPointReadOnly, + orientation: &DOMPointReadOnly, + ) -> DomRoot { + let transform = XRRigidTransform::new(global, position, orientation); reflect_dom_object( - Box::new(XRReferenceSpace::new_inherited()), + Box::new(XRReferenceSpace::new_inherited(session, &transform)), + global, + XRReferenceSpaceBinding::Wrap, + ) + } + + #[allow(unused)] + pub fn identity(global: &Window, session: &XRSession) -> DomRoot { + let transform = XRRigidTransform::identity(global); + reflect_dom_object( + Box::new(XRReferenceSpace::new_inherited(session, &transform)), global, XRReferenceSpaceBinding::Wrap, ) } } + +impl XRReferenceSpaceMethods for XRReferenceSpace { + /// https://immersive-web.github.io/webxr/#dom-xrreferencespace-originoffset + fn SetOriginOffset(&self, transform: &XRRigidTransform) { + self.transform.set(transform); + } + + /// https://immersive-web.github.io/webxr/#dom-xrreferencespace-originoffset + fn OriginOffset(&self) -> DomRoot { + self.transform.get() + } +} diff --git a/components/script/dom/xrrigidtransform.rs b/components/script/dom/xrrigidtransform.rs index b147e274810..3f726475517 100644 --- a/components/script/dom/xrrigidtransform.rs +++ b/components/script/dom/xrrigidtransform.rs @@ -2,30 +2,81 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; use crate::dom::bindings::codegen::Bindings::XRRigidTransformBinding; +use crate::dom::bindings::codegen::Bindings::XRRigidTransformBinding::XRRigidTransformMethods; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::DomRoot; -use crate::dom::globalscope::GlobalScope; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::dompointreadonly::DOMPointReadOnly; +use crate::dom::window::Window; use dom_struct::dom_struct; #[dom_struct] pub struct XRRigidTransform { reflector_: Reflector, + position: Dom, + orientation: Dom, } impl XRRigidTransform { - fn new_inherited() -> XRRigidTransform { + fn new_inherited( + position: &DOMPointReadOnly, + orientation: &DOMPointReadOnly, + ) -> XRRigidTransform { XRRigidTransform { reflector_: Reflector::new(), + position: Dom::from_ref(position), + orientation: Dom::from_ref(orientation), } } #[allow(unused)] - pub fn new(global: &GlobalScope) -> DomRoot { + pub fn new( + global: &Window, + position: &DOMPointReadOnly, + orientation: &DOMPointReadOnly, + ) -> DomRoot { reflect_dom_object( - Box::new(XRRigidTransform::new_inherited()), + Box::new(XRRigidTransform::new_inherited(position, orientation)), global, XRRigidTransformBinding::Wrap, ) } + + #[allow(unused)] + pub fn identity(window: &Window) -> DomRoot { + let global = window.global(); + let position = DOMPointReadOnly::new(&global, 0., 0., 0., 1.); + let orientation = DOMPointReadOnly::new(&global, 0., 0., 0., 1.); + reflect_dom_object( + Box::new(XRRigidTransform::new_inherited(&position, &orientation)), + window, + XRRigidTransformBinding::Wrap, + ) + } + + // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-xrrigidtransform + pub fn Constructor( + window: &Window, + position: &DOMPointInit, + orientation: &DOMPointInit, + ) -> Fallible> { + let global = window.global(); + let position = DOMPointReadOnly::new_from_init(&global, &position); + let orientation = DOMPointReadOnly::new_from_init(&global, &orientation); + Ok(XRRigidTransform::new(window, &position, &orientation)) + } +} + +impl XRRigidTransformMethods for XRRigidTransform { + // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-position + fn Position(&self) -> DomRoot { + DomRoot::from_ref(&self.position) + } + // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-orientation + fn Orientation(&self) -> DomRoot { + DomRoot::from_ref(&self.orientation) + } } diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index 997d88b34bf..f756b0e5fa5 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -7,17 +7,23 @@ use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionMode; use crate::dom::bindings::codegen::Bindings::XRSessionBinding; use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XREnvironmentBlendMode; use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback; +use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRReferenceSpaceOptions; +use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRReferenceSpaceType; use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRSessionMethods; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods; +use crate::dom::bindings::error::Error; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::promise::Promise; use crate::dom::vrdisplay::VRDisplay; use crate::dom::xrlayer::XRLayer; +use crate::dom::xrreferencespace::XRReferenceSpace; +use crate::dom::xrstationaryreferencespace::XRStationaryReferenceSpace; use crate::dom::xrwebgllayer::XRWebGLLayer; use dom_struct::dom_struct; use std::rc::Rc; @@ -111,4 +117,42 @@ impl XRSessionMethods for XRSession { fn EnvironmentBlendMode(&self) -> XREnvironmentBlendMode { self.blend_mode } + + /// https://immersive-web.github.io/webxr/#dom-xrsession-requestreferencespace + fn RequestReferenceSpace(&self, options: &XRReferenceSpaceOptions) -> Rc { + let p = Promise::new(&self.global()); + + // https://immersive-web.github.io/webxr/#create-a-reference-space + + // XXXManishearth reject based on session type + // https://github.com/immersive-web/webxr/blob/master/spatial-tracking-explainer.md#practical-usage-guidelines + + match options.type_ { + XRReferenceSpaceType::Identity => { + p.resolve_native(&XRReferenceSpace::identity( + &self.global().as_window(), + self, + )); + }, + XRReferenceSpaceType::Stationary => { + if let Some(subtype) = options.subtype { + p.resolve_native(&XRStationaryReferenceSpace::new( + &self.global().as_window(), + self, + subtype, + )); + } else { + p.reject_error(Error::Type(format!( + "stationary XRReferenceSpaces must specify a subtype" + ))) + } + }, + XRReferenceSpaceType::Bounded | XRReferenceSpaceType::Unbounded => { + // XXXManishearth eventually support these + p.reject_error(Error::NotSupported) + }, + } + + p + } } diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 00e20df2c22..e0d4ce75cf3 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -4,27 +4,30 @@ use crate::dom::bindings::codegen::Bindings::XRSpaceBinding; use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; +use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; #[dom_struct] pub struct XRSpace { eventtarget: EventTarget, + session: Dom, } impl XRSpace { - pub fn new_inherited() -> XRSpace { + pub fn new_inherited(session: &XRSession) -> XRSpace { XRSpace { eventtarget: EventTarget::new_inherited(), + session: Dom::from_ref(session), } } #[allow(unused)] - pub fn new(global: &GlobalScope) -> DomRoot { + pub fn new(global: &GlobalScope, session: &XRSession) -> DomRoot { reflect_dom_object( - Box::new(XRSpace::new_inherited()), + Box::new(XRSpace::new_inherited(session)), global, XRSpaceBinding::Wrap, ) diff --git a/components/script/dom/xrstationaryreferencespace.rs b/components/script/dom/xrstationaryreferencespace.rs index 92c0dce0196..33d96f1488f 100644 --- a/components/script/dom/xrstationaryreferencespace.rs +++ b/components/script/dom/xrstationaryreferencespace.rs @@ -3,29 +3,45 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding; +use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding::XRStationaryReferenceSpaceSubtype; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::DomRoot; -use crate::dom::globalscope::GlobalScope; +use crate::dom::window::Window; use crate::dom::xrreferencespace::XRReferenceSpace; +use crate::dom::xrrigidtransform::XRRigidTransform; +use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; #[dom_struct] pub struct XRStationaryReferenceSpace { xrreferencespace: XRReferenceSpace, + ty: XRStationaryReferenceSpaceSubtype, } #[allow(unused)] impl XRStationaryReferenceSpace { - pub fn new_inherited() -> XRStationaryReferenceSpace { + pub fn new_inherited( + session: &XRSession, + ty: XRStationaryReferenceSpaceSubtype, + transform: &XRRigidTransform, + ) -> XRStationaryReferenceSpace { XRStationaryReferenceSpace { - xrreferencespace: XRReferenceSpace::new_inherited(), + xrreferencespace: XRReferenceSpace::new_inherited(session, transform), + ty, } } - pub fn new(global: &GlobalScope) -> DomRoot { + pub fn new( + window: &Window, + session: &XRSession, + ty: XRStationaryReferenceSpaceSubtype, + ) -> DomRoot { + let transform = XRRigidTransform::identity(window); reflect_dom_object( - Box::new(XRStationaryReferenceSpace::new_inherited()), - global, + Box::new(XRStationaryReferenceSpace::new_inherited( + session, ty, &transform, + )), + window, XRStationaryReferenceSpaceBinding::Wrap, ) }