servo-webxr-api 0.1.0

A safe Rust API that provides a way to interact with virtual reality and augmented reality devices and integration with OpenXR. The API is inspired by the WebXR Device API (https://www.w3.org/TR/webxr/) but adapted to Rust design patterns.
Documentation
/* This Source Code Form is subject to the terms of the Mozilla Public
 * 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 euclid::{Point2D, Rect, RigidTransform3D, Transform3D};
use profile_traits::generic_callback::GenericCallback as ProfileGenericCallback;
use serde::{Deserialize, Serialize};
use servo_base::generic_channel::GenericReceiver;

use crate::{
    DiscoveryAPI, Display, EntityType, Error, Floor, Handedness, Input, InputId, InputSource,
    LeftEye, Native, RightEye, SelectEvent, SelectKind, TargetRayMode, Triangle, Viewer, Viewport,
    Visibility,
};

/// A trait for discovering mock XR devices
pub trait MockDiscoveryAPI<GL>: 'static {
    fn simulate_device_connection(
        &mut self,
        init: MockDeviceInit,
        receiver: GenericReceiver<MockDeviceMsg>,
    ) -> Result<Box<dyn DiscoveryAPI<GL>>, Error>;
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockDeviceInit {
    pub floor_origin: Option<RigidTransform3D<f32, Floor, Native>>,
    pub supports_inline: bool,
    pub supports_vr: bool,
    pub supports_ar: bool,
    pub viewer_origin: Option<RigidTransform3D<f32, Viewer, Native>>,
    pub views: MockViewsInit,
    pub supported_features: Vec<String>,
    pub world: Option<MockWorld>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockViewInit<Eye> {
    pub transform: RigidTransform3D<f32, Viewer, Eye>,
    pub projection: Transform3D<f32, Eye, Display>,
    pub viewport: Rect<i32, Viewport>,
    /// field of view values, in radians
    pub fov: Option<(f32, f32, f32, f32)>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum MockViewsInit {
    Mono(MockViewInit<Viewer>),
    Stereo(MockViewInit<LeftEye>, MockViewInit<RightEye>),
}

#[derive(Debug, Serialize, Deserialize)]
pub enum MockDeviceMsg {
    SetViewerOrigin(Option<RigidTransform3D<f32, Viewer, Native>>),
    SetFloorOrigin(Option<RigidTransform3D<f32, Floor, Native>>),
    SetViews(MockViewsInit),
    AddInputSource(MockInputInit),
    MessageInputSource(InputId, MockInputMsg),
    VisibilityChange(Visibility),
    SetWorld(MockWorld),
    ClearWorld,
    Disconnect(ProfileGenericCallback<()>),
    SetBoundsGeometry(Vec<Point2D<f32, Floor>>),
    SimulateResetPose,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockInputInit {
    pub source: InputSource,
    pub pointer_origin: Option<RigidTransform3D<f32, Input, Native>>,
    pub grip_origin: Option<RigidTransform3D<f32, Input, Native>>,
    pub supported_buttons: Vec<MockButton>,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum MockInputMsg {
    SetHandedness(Handedness),
    SetTargetRayMode(TargetRayMode),
    SetProfiles(Vec<String>),
    SetPointerOrigin(Option<RigidTransform3D<f32, Input, Native>>),
    SetGripOrigin(Option<RigidTransform3D<f32, Input, Native>>),
    /// Note: SelectEvent::Select here refers to a complete Select event,
    /// not just the end event, i.e. it refers to
    /// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-simulateselect>
    TriggerSelect(SelectKind, SelectEvent),
    Disconnect,
    Reconnect,
    SetSupportedButtons(Vec<MockButton>),
    UpdateButtonState(MockButton),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockRegion {
    pub faces: Vec<Triangle>,
    pub ty: EntityType,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockWorld {
    pub regions: Vec<MockRegion>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum MockButtonType {
    Grip,
    Touchpad,
    Thumbstick,
    OptionalButton,
    OptionalThumbstick,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockButton {
    pub button_type: MockButtonType,
    pub pressed: bool,
    pub touched: bool,
    pub pressed_value: f32,
    pub x_value: f32,
    pub y_value: f32,
}