mirror of
https://github.com/mii443/rust-openvr.git
synced 2025-08-23 00:35:31 +00:00
Draft changes for OpenVR 1.0.7
This commit is contained in:
179
src/lib.rs
179
src/lib.rs
@ -1,62 +1,143 @@
|
||||
extern crate openvr_sys;
|
||||
|
||||
use openvr_sys::EVRInitError::*;
|
||||
use openvr_sys::EVRApplicationType::*;
|
||||
use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT};
|
||||
use std::{fmt, error, slice};
|
||||
use std::ffi::CStr;
|
||||
|
||||
pub mod common;
|
||||
pub mod error;
|
||||
pub mod tracking;
|
||||
pub mod system;
|
||||
pub mod extended_display;
|
||||
pub mod compositor;
|
||||
pub mod render_models;
|
||||
pub mod tracked_camera;
|
||||
pub mod subsystems;
|
||||
use openvr_sys as sys;
|
||||
|
||||
pub use system::IVRSystem;
|
||||
pub use extended_display::IVRExtendedDisplay;
|
||||
pub use compositor::IVRCompositor;
|
||||
pub use render_models::IVRRenderModels;
|
||||
pub use tracked_camera::IVRTrackedCamera;
|
||||
mod tracking;
|
||||
|
||||
pub use subsystems::*;
|
||||
pub use error::*;
|
||||
mod system;
|
||||
mod compositor;
|
||||
|
||||
pub use common::Eye;
|
||||
pub use tracking::*;
|
||||
|
||||
/// Inits the open vr interface and returns the system
|
||||
pub fn init() -> Result<system::IVRSystem, Error<openvr_sys::EVRInitError>> {
|
||||
let mut err = EVRInitError_VRInitError_None;
|
||||
let app_type = EVRApplicationType_VRApplication_Scene;
|
||||
static INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
|
||||
// try to initialize base vr eco
|
||||
unsafe {
|
||||
openvr_sys::VR_InitInternal(&mut err, app_type);
|
||||
};
|
||||
/// Initialize OpenVR
|
||||
///
|
||||
/// # Panics
|
||||
/// When the library has already been initialized
|
||||
pub fn init(ty: ApplicationType) -> Result<Context, InitError> {
|
||||
if INITIALIZED.swap(true, Ordering::AcqRel) {
|
||||
panic!("OpenVR has already been initialized!");
|
||||
}
|
||||
|
||||
// check for errors
|
||||
match err {
|
||||
EVRInitError_VRInitError_None => {
|
||||
// get system
|
||||
let result = system();
|
||||
match result {
|
||||
Ok(sys) => {
|
||||
return Ok(sys);
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(Error::from_raw(err));
|
||||
}
|
||||
};
|
||||
let mut error = sys::EVRInitError_EVRInitError_VRInitError_None;
|
||||
unsafe { sys::VR_InitInternal(&mut error, ty as sys::EVRApplicationType) };
|
||||
if error != sys::EVRInitError_EVRInitError_VRInitError_None {
|
||||
return Err(InitError(error));
|
||||
}
|
||||
if !unsafe { sys::VR_IsInterfaceVersionValid(sys::IVRSystem_Version.as_ptr() as *const i8) } {
|
||||
unsafe { sys::VR_ShutdownInternal() }
|
||||
return Err(InitError(sys::EVRInitError_EVRInitError_VRInitError_Init_InterfaceNotFound));
|
||||
}
|
||||
Ok(unsafe { Context::new() }?)
|
||||
}
|
||||
|
||||
/// Shutdowns all openvr related systems
|
||||
pub fn shutdown() {
|
||||
unsafe {
|
||||
openvr_sys::VR_ShutdownInternal();
|
||||
pub struct System<'a>(&'a sys::VR_IVRSystem_FnTable);
|
||||
pub struct Compositor<'a>(&'a sys::VR_IVRCompositor_FnTable);
|
||||
|
||||
/// Entry points into OpenVR.
|
||||
///
|
||||
/// At most one of this object may exist at a time.
|
||||
pub struct Context {
|
||||
system: *const sys::VR_IVRSystem_FnTable,
|
||||
compositor: *const sys::VR_IVRCompositor_FnTable,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Must be called after sys::VR_InitInternal
|
||||
unsafe fn new() -> Result<Self, InitError> {
|
||||
fn load<T>(suffix: &[u8]) -> Result<*const T, InitError> {
|
||||
let mut magic = Vec::from(b"FnTable:".as_ref());
|
||||
magic.extend(suffix);
|
||||
let mut error = sys::EVRInitError_EVRInitError_VRInitError_None;
|
||||
let result = unsafe { sys::VR_GetGenericInterface(magic.as_ptr() as *const i8, &mut error) };
|
||||
if error != sys::EVRInitError_EVRInitError_VRInitError_None {
|
||||
return Err(InitError(sys::EVRInitError_EVRInitError_VRInitError_Init_InterfaceNotFound));
|
||||
}
|
||||
Ok(result as *const T)
|
||||
}
|
||||
|
||||
Ok(Context {
|
||||
system: load(sys::IVRSystem_Version)?,
|
||||
compositor: load(sys::IVRCompositor_Version)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn system(&self) -> System { unsafe { System(&*self.system) } }
|
||||
pub fn compositor(&self) -> Compositor { unsafe { Compositor(&*self.compositor) } }
|
||||
}
|
||||
|
||||
impl Drop for Context {
|
||||
fn drop(&mut self) {
|
||||
unsafe { sys::VR_ShutdownInternal() }
|
||||
INITIALIZED.store(false, Ordering::AcqRel);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum ApplicationType {
|
||||
/// Some other kind of application that isn't covered by the other entries
|
||||
Other = sys::EVRApplicationType_EVRApplicationType_VRApplication_Other as isize,
|
||||
/// Application will submit 3D frames
|
||||
Scene = sys::EVRApplicationType_EVRApplicationType_VRApplication_Scene as isize,
|
||||
/// Application only interacts with overlays
|
||||
Overlay = sys::EVRApplicationType_EVRApplicationType_VRApplication_Overlay as isize,
|
||||
/// Application should not start SteamVR if it's not already running, and should not keep it running if everything
|
||||
/// else quits.
|
||||
Background = sys::EVRApplicationType_EVRApplicationType_VRApplication_Background as isize,
|
||||
/// Init should not try to load any drivers. The application needs access to utility interfaces (like IVRSettings
|
||||
/// and IVRApplications) but not hardware.
|
||||
Utility = sys::EVRApplicationType_EVRApplicationType_VRApplication_Utility as isize,
|
||||
/// Reserved for vrmonitor
|
||||
VRMonitor = sys::EVRApplicationType_EVRApplicationType_VRApplication_VRMonitor as isize,
|
||||
/// Reserved for Steam
|
||||
SteamWatchdog = sys::EVRApplicationType_EVRApplicationType_VRApplication_SteamWatchdog as isize,
|
||||
/// Start up SteamVR
|
||||
Bootstrapper = sys::EVRApplicationType_EVRApplicationType_VRApplication_Bootstrapper as isize,
|
||||
}
|
||||
|
||||
pub struct InitError(sys::EVRInitError);
|
||||
|
||||
impl fmt::Debug for InitError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let msg = unsafe {
|
||||
CStr::from_ptr(sys::VR_GetVRInitErrorAsSymbol(self.0))
|
||||
};
|
||||
f.pad(msg.to_str().expect("OpenVR init error symbol was not valid UTF-8"))
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for InitError {
|
||||
fn description(&self) -> &str {
|
||||
let msg = unsafe {
|
||||
CStr::from_ptr(sys::VR_GetVRInitErrorAsEnglishDescription(self.0))
|
||||
};
|
||||
msg.to_str().expect("OpenVR init error description was not valid UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InitError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad(error::Error::description(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Eye {
|
||||
Left = sys::EVREye_EVREye_Eye_Left as isize,
|
||||
Right = sys::EVREye_EVREye_Eye_Right as isize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TrackedDevicePoses {
|
||||
data: [TrackedDevicePose; sys::k_unMaxTrackedDeviceCount as usize]
|
||||
}
|
||||
|
||||
impl TrackedDevicePoses {
|
||||
pub fn iter(&self) -> slice::Iter<TrackedDevicePose> { self.data.iter() }
|
||||
pub fn len(&self) -> usize { self.data.len() }
|
||||
}
|
||||
|
Reference in New Issue
Block a user