use std::collections::HashMap;
use VRDisplayPtr;
use VREvent;
use VRGamepadPtr;
use VRService;
use VRServiceCreator;
#[cfg(target_os = "android")]
#[cfg(feature = "googlevr")]
use api::GoogleVRServiceCreator;
#[cfg(target_os = "windows")]
#[cfg(feature = "openvr")]
use api::OpenVRServiceCreator;
#[cfg(target_os = "android")]
#[cfg(feature = "oculusvr")]
use api::OculusVRServiceCreator;
#[cfg(feature = "mock")]
use api::{MockServiceCreator, MockVRControlMsg, MockVRInit};
#[cfg(feature = "vrexternal")]
use api::VRExternalShmemPtr;
#[cfg(target_os = "android")]
#[cfg(feature = "vrexternal")]
use api::VRExternalServiceCreator;
pub struct VRServiceManager {
initialized: bool,
services: Vec<Box<dyn VRService>>,
displays: HashMap<u32, VRDisplayPtr>,
gamepads: HashMap<u32, VRGamepadPtr>
}
unsafe impl Send for VRServiceManager {}
impl Drop for VRServiceManager {
fn drop(&mut self) {
self.gamepads.clear();
self.displays.clear();
self.services.clear();
}
}
impl VRServiceManager {
pub fn new() -> VRServiceManager {
VRServiceManager {
initialized: false,
services: Vec::new(),
displays: HashMap::new(),
gamepads: HashMap::new()
}
}
pub fn register_defaults(&mut self) {
let creators: Vec<Box<dyn VRServiceCreator>> = vec!(
#[cfg(target_os = "windows")]
#[cfg(feature = "openvr")]
OpenVRServiceCreator::new(),
#[cfg(target_os = "android")]
#[cfg(feature = "googlevr")]
GoogleVRServiceCreator::new(),
#[cfg(target_os = "android")]
#[cfg(feature = "oculusvr")]
OculusVRServiceCreator::new(),
);
for creator in &creators {
self.register(creator.new_service());
}
}
#[cfg(target_os = "android")]
#[cfg(feature = "vrexternal")]
pub fn register_vrexternal(&mut self, ptr: VRExternalShmemPtr) {
let creator = VRExternalServiceCreator::new(ptr);
self.register(creator.new_service());
}
#[cfg(not(target_os = "android"))]
#[cfg(feature = "vrexternal")]
pub fn register_vrexternal(&mut self, _: VRExternalShmemPtr) {
unimplemented!();
}
#[cfg(feature = "mock")]
pub fn register_mock(&mut self) {
let creator = MockServiceCreator::new();
self.register(creator.new_service());
}
#[cfg(feature = "mock")]
pub fn register_mock_with_remote(&mut self, init: MockVRInit) -> std::sync::mpsc::Sender<MockVRControlMsg> {
let (service, remote) = MockServiceCreator::new_service_with_remote(init);
self.register(service);
remote
}
pub fn register(&mut self, service: Box<dyn VRService>) {
self.services.push(service);
}
pub fn initialize_services(&mut self) {
if self.initialized {
return;
}
for service in &mut self.services {
if let Err(msg) = service.initialize() {
error!("Error initializing VRService: {:?}", msg);
}
}
self.initialized = true;
}
pub fn get_displays(&mut self) -> Vec<VRDisplayPtr> {
self.fetch_displays();
let mut result = Vec::new();
for (_, display) in &self.displays {
result.push(display.clone());
}
result.sort_by(|a, b| a.borrow().id().cmp(&b.borrow().id()));
result
}
pub fn get_gamepads(&mut self) -> Vec<VRGamepadPtr> {
self.fetch_gamepads();
let mut result = Vec::new();
for (_, gamepad) in &self.gamepads {
result.push(gamepad.clone());
}
result.sort_by(|a, b| a.borrow().id().cmp(&b.borrow().id()));
result
}
pub fn get_display(&self, display_id: u32) -> Option<&VRDisplayPtr> {
self.displays.get(&display_id)
}
pub fn poll_events(&mut self) -> Vec<VREvent> {
let mut events = Vec::new();
for service in &mut self.services {
events.append(&mut service.poll_events());
}
events
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
}
impl VRServiceManager {
fn fetch_displays(&mut self) {
self.initialize_services();
for service in &mut self.services {
let displays = service.fetch_displays();
if let Ok(displays) = displays {
for display in displays {
let key = display.borrow().id();
if !self.displays.contains_key(&key) {
self.displays.insert(key, display.clone());
}
}
}
}
}
fn fetch_gamepads(&mut self) {
self.initialize_services();
for service in &mut self.services {
let gamepads = service.fetch_gamepads();
if let Ok(gamepads) = gamepads {
for gamepad in gamepads {
let key = gamepad.borrow().id();
if !self.gamepads.contains_key(&key) {
self.gamepads.insert(key, gamepad.clone());
}
}
}
}
}
}