Fill in some additional System methods

This commit is contained in:
Benjamin Saunders
2017-07-23 18:30:56 -07:00
parent d20c4de1c5
commit bec9c95c1a
4 changed files with 115 additions and 1 deletions

View File

@ -181,3 +181,25 @@ pub struct ControllerState {
pub button_touched: u64,
pub axis: [ControllerAxis; 5],
}
pub mod button_id {
use super::sys;
pub const SYSTEM: sys::EVRButtonId = sys::EVRButtonId_k_EButton_System;
pub const APPLICATION_MENU: sys::EVRButtonId = sys::EVRButtonId_k_EButton_ApplicationMenu;
pub const GRIP: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Grip;
pub const DPAD_LEFT: sys::EVRButtonId = sys::EVRButtonId_k_EButton_DPad_Left;
pub const DPAD_UP: sys::EVRButtonId = sys::EVRButtonId_k_EButton_DPad_Up;
pub const DPAD_RIGHT: sys::EVRButtonId = sys::EVRButtonId_k_EButton_DPad_Right;
pub const DPAD_DOWN: sys::EVRButtonId = sys::EVRButtonId_k_EButton_DPad_Down;
pub const A: sys::EVRButtonId = sys::EVRButtonId_k_EButton_A;
pub const PROXIMITY_SENSOR: sys::EVRButtonId = sys::EVRButtonId_k_EButton_ProximitySensor;
pub const AXIS0: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Axis0;
pub const AXIS1: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Axis1;
pub const AXIS2: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Axis2;
pub const AXIS3: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Axis3;
pub const AXIS4: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Axis4;
pub const STEAM_VR_TOUCHPAD: sys::EVRButtonId = sys::EVRButtonId_k_EButton_SteamVR_Touchpad;
pub const STEAM_VR_TRIGGER: sys::EVRButtonId = sys::EVRButtonId_k_EButton_SteamVR_Trigger;
pub const DASHBOARD_BACK: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Dashboard_Back;
pub const MAX: sys::EVRButtonId = sys::EVRButtonId_k_EButton_Max;
}

View File

@ -271,6 +271,7 @@ pub enum Event {
Notification_BeginInteraction,
Notification_Destroyed,
/// The application has been asked to quit
Quit(Process),
ProcessQuit(Process),
QuitAborted_UserPrompt(Process),

View File

@ -1,8 +1,9 @@
//! The `System` interface provides access to display configuration information, tracking data, controller state,
//! events, and device properties. It is the main interface of OpenVR.
use std::mem;
use std::{mem, slice, ptr};
use std::ffi::CString;
use std::marker::PhantomData;
use openvr_sys as sys;
@ -210,6 +211,25 @@ impl<'a> System<'a> {
}
}
/// Returns the hidden area mesh for the current HMD.
///
/// The pixels covered by this mesh will never be seen by the user after the lens distortion is applied based on
/// visibility to the panels. If this HMD does not have a hidden area mesh, None is returned. This mesh is meant to
/// be rendered into the stencil buffer (or into the depth buffer setting nearz) before rendering each eye's view.
/// This will improve performance by letting the GPU early-reject pixels the user will never see before running the
/// pixel shader.
///
/// NOTE: Render this mesh with backface culling disabled since the winding order of the vertices can
/// be different per-HMD or per-eye.
///
/// Passing `HiddenAreaMeshType::Inverse` will produce the visible area mesh that is commonly used in place of
/// full-screen quads. The visible area mesh covers all of the pixels the hidden area mesh does not cover.
// TODO: Handle line loops with a separate method and return type, since HiddenAreaMesh assumes triangles.
pub fn hidden_area_mesh(&self, eye: Eye, ty: HiddenAreaMeshType) -> Option<HiddenAreaMesh> {
let mesh = unsafe { self.0.GetHiddenAreaMesh.unwrap()(eye as sys::EVREye, ty as sys::EHiddenAreaMeshType) };
if mesh.pVertexData == ptr::null_mut() { None } else { Some(HiddenAreaMesh { mesh, _phantom: PhantomData }) }
}
/// Looks up the current input state of a controller.
///
/// Returns None if the device is not a controller, or if the user is currently in the system menu.
@ -226,6 +246,46 @@ impl<'a> System<'a> {
}
}
}
pub fn controller_state_with_pose(&self, origin: TrackingUniverseOrigin, device: TrackedDeviceIndex) -> Option<(ControllerState, TrackedDevicePose)> {
unsafe {
let mut state = mem::uninitialized();
let mut pose = mem::uninitialized();
if self.0.GetControllerStateWithPose.unwrap()(
origin as sys::ETrackingUniverseOrigin,
device, &mut state as *mut _ as *mut _, mem::size_of_val(&state) as u32,
&mut pose) {
Some((state, pose.into()))
} else {
None
}
}
}
/// Trigger a single haptic pulse on a controller.
///
/// After this call the application may not trigger another haptic pulse on this controller and axis combination for
/// 5ms.
///
/// Vive controller haptics respond to axis 0. OpenVR seems to reject durations longer than 3999us.
pub fn trigger_haptic_pulse(&self, device: TrackedDeviceIndex, axis: u32, microseconds: u16) {
unsafe { self.0.TriggerHapticPulse.unwrap()(device, axis, microseconds) }
}
/// Call this to acknowledge to the system that `Event::Quit` has been received and that the process is exiting.
///
/// This extends the timeout until the process is killed.
pub fn acknowledge_quit_exiting(&self) {
unsafe { self.0.AcknowledgeQuit_Exiting.unwrap()(); }
}
/// Call this to tell the system that the user is being prompted to save data.
///
/// This halts the timeout and dismisses the dashboard (if it was up). Applications should be sure to actually
/// prompt the user to save and then exit afterward, otherwise the user will be left in a confusing state.
pub fn acknowledge_quit_user_prompt(&self) {
unsafe { self.0.AcknowledgeQuit_Exiting.unwrap()(); }
}
}
/// Values represent the tangents of the half-angles from the center view axis
@ -300,3 +360,30 @@ impl fmt::Display for TrackedPropertyError {
f.pad(::std::error::Error::description(self))
}
}
pub enum HiddenAreaMeshType {
/// The mesh that covers pixels which cannot be seen by the wearer of the HMD for optical reasons.
Standard = sys::EHiddenAreaMeshType_k_eHiddenAreaMesh_Standard as isize,
/// The inverse of `Standard`, useful for doing full-screen render passes such as postprocessing.
Inverse = sys::EHiddenAreaMeshType_k_eHiddenAreaMesh_Inverse as isize,
}
impl Default for HiddenAreaMeshType {
fn default() -> Self { HiddenAreaMeshType::Standard }
}
/// A triangle mesh containing geometry determined by `HiddenAreaMeshType`.
///
/// Render this mesh with backface culling disabled since the winding order of the vertices can be different per-HMD or
/// per-eye.
pub struct HiddenAreaMesh<'a> {
mesh: sys::HiddenAreaMesh_t,
_phantom: PhantomData<&'a [[f32; 2]]>,
}
impl<'a> ::std::ops::Deref for HiddenAreaMesh<'a> {
type Target = [[f32; 2]];
fn deref(&self) -> &Self::Target {
unsafe { slice::from_raw_parts(&(*self.mesh.pVertexData).v, self.mesh.unTriangleCount as usize * 3) }
}
}

View File

@ -30,6 +30,10 @@ impl TrackedDevicePose {
pub fn device_is_connected(&self) -> bool { self.0.bDeviceIsConnected }
}
impl From<sys::TrackedDevicePose_t> for TrackedDevicePose {
fn from(x: sys::TrackedDevicePose_t) -> Self { TrackedDevicePose(x) }
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TrackingResult {
Uninitialized = sys::ETrackingResult_TrackingResult_Uninitialized as isize,