You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
364 lines
12 KiB
364 lines
12 KiB
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== |
|
|
|
using HTC.UnityPlugin.Utility; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
|
|
namespace HTC.UnityPlugin.VRModuleManagement |
|
{ |
|
public partial class VRModule : SingletonBehaviour<VRModule> |
|
{ |
|
private static readonly DeviceState s_defaultState; |
|
private static readonly SimulatorVRModule s_simulator; |
|
private static readonly Dictionary<string, uint> s_deviceSerialNumberTable = new Dictionary<string, uint>((int)MAX_DEVICE_COUNT); |
|
|
|
[SerializeField] |
|
private bool m_dontDestroyOnLoad = true; |
|
[SerializeField] |
|
private bool m_lockPhysicsUpdateRateToRenderFrequency = true; |
|
[SerializeField] |
|
private VRModuleSelectEnum m_selectModule = VRModuleSelectEnum.Auto; |
|
[SerializeField] |
|
private VRModuleTrackingSpaceType m_trackingSpaceType = VRModuleTrackingSpaceType.RoomScale; |
|
|
|
[SerializeField] |
|
private NewPosesEvent m_onNewPoses = new NewPosesEvent(); |
|
[SerializeField] |
|
private ControllerRoleChangedEvent m_onControllerRoleChanged = new ControllerRoleChangedEvent(); |
|
[SerializeField] |
|
private InputFocusEvent m_onInputFocus = new InputFocusEvent(); |
|
[SerializeField] |
|
private DeviceConnectedEvent m_onDeviceConnected = new DeviceConnectedEvent(); |
|
[SerializeField] |
|
private ActiveModuleChangedEvent m_onActiveModuleChanged = new ActiveModuleChangedEvent(); |
|
|
|
private bool m_isUpdating = false; |
|
private bool m_isDestoryed = false; |
|
|
|
private ModuleBase[] m_modules; |
|
private VRModuleActiveEnum m_activatedModule = VRModuleActiveEnum.Uninitialized; |
|
private ModuleBase m_activatedModuleBase; |
|
private DeviceState[] m_prevStates; |
|
private DeviceState[] m_currStates; |
|
|
|
static VRModule() |
|
{ |
|
SetDefaultInitGameObjectGetter(GetDefaultInitGameObject); |
|
|
|
s_defaultState = new DeviceState(INVALID_DEVICE_INDEX); |
|
s_simulator = new SimulatorVRModule(); |
|
} |
|
|
|
private static GameObject GetDefaultInitGameObject() |
|
{ |
|
return new GameObject("[ViveInputUtility]"); |
|
} |
|
|
|
public static GameObject GetInstanceGameObject() |
|
{ |
|
return Instance.gameObject; |
|
} |
|
|
|
protected override void OnSingletonBehaviourInitialized() |
|
{ |
|
if (m_dontDestroyOnLoad && transform.parent == null && Application.isPlaying) |
|
{ |
|
DontDestroyOnLoad(gameObject); |
|
} |
|
|
|
m_activatedModule = VRModuleActiveEnum.Uninitialized; |
|
m_activatedModuleBase = null; |
|
|
|
m_modules = new ModuleBase[EnumUtils.GetMaxValue(typeof(VRModuleActiveEnum)) + 1]; |
|
m_modules[(int)VRModuleActiveEnum.None] = new DefaultModule(); |
|
m_modules[(int)VRModuleActiveEnum.Simulator] = s_simulator; |
|
m_modules[(int)VRModuleActiveEnum.UnityNativeVR] = new UnityEngineVRModule(); |
|
m_modules[(int)VRModuleActiveEnum.SteamVR] = new SteamVRModule(); |
|
m_modules[(int)VRModuleActiveEnum.OculusVR] = new OculusVRModule(); |
|
m_modules[(int)VRModuleActiveEnum.DayDream] = new GoogleVRModule(); |
|
m_modules[(int)VRModuleActiveEnum.WaveVR] = new WaveVRModule(); |
|
|
|
s_deviceSerialNumberTable.Clear(); |
|
|
|
m_currStates = new DeviceState[MAX_DEVICE_COUNT]; |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) { m_currStates[i] = new DeviceState(i); } |
|
|
|
m_prevStates = new DeviceState[MAX_DEVICE_COUNT]; |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) { m_prevStates[i] = new DeviceState(i); } |
|
} |
|
|
|
private void Update() |
|
{ |
|
if (!IsInstance) { return; } |
|
|
|
m_isUpdating = true; |
|
|
|
// Get should activate module |
|
var shouldActivateModule = GetShouldActivateModule(); |
|
|
|
// Update module activity |
|
if (m_activatedModule != shouldActivateModule) |
|
{ |
|
// Do clean up |
|
if (m_activatedModule != VRModuleActiveEnum.Uninitialized) |
|
{ |
|
DeactivateModule(); |
|
} |
|
|
|
if (shouldActivateModule != VRModuleActiveEnum.Uninitialized) |
|
{ |
|
ActivateModule(shouldActivateModule); |
|
} |
|
} |
|
|
|
if (m_activatedModule != VRModuleActiveEnum.Uninitialized) |
|
{ |
|
m_activatedModuleBase.Update(); |
|
} |
|
|
|
if (m_isDestoryed) |
|
{ |
|
DeactivateModule(); |
|
} |
|
|
|
m_isUpdating = false; |
|
} |
|
|
|
protected override void OnDestroy() |
|
{ |
|
if (IsInstance) |
|
{ |
|
m_isDestoryed = true; |
|
|
|
if (!m_isUpdating) |
|
{ |
|
DeactivateModule(); |
|
} |
|
} |
|
|
|
base.OnDestroy(); |
|
} |
|
|
|
private VRModuleActiveEnum GetShouldActivateModule() |
|
{ |
|
if (m_selectModule == VRModuleSelectEnum.Auto) |
|
{ |
|
for (int i = m_modules.Length - 1; i >= 0; --i) |
|
{ |
|
if (m_modules[i] != null && m_modules[i].ShouldActiveModule()) |
|
{ |
|
return (VRModuleActiveEnum)i; |
|
} |
|
} |
|
} |
|
else if ((int)m_selectModule >= 0 && (int)m_selectModule < m_modules.Length) |
|
{ |
|
return (VRModuleActiveEnum)m_selectModule; |
|
} |
|
else |
|
{ |
|
return VRModuleActiveEnum.None; |
|
} |
|
|
|
return VRModuleActiveEnum.Uninitialized; |
|
} |
|
|
|
private void ActivateModule(VRModuleActiveEnum module) |
|
{ |
|
if (m_activatedModule != VRModuleActiveEnum.Uninitialized) |
|
{ |
|
Debug.LogError("Must deactivate before activate module! Current activatedModule:" + m_activatedModule); |
|
return; |
|
} |
|
|
|
if (module == VRModuleActiveEnum.Uninitialized) |
|
{ |
|
Debug.LogError("Activate module cannot be Uninitialized! Use DeactivateModule instead"); |
|
return; |
|
} |
|
|
|
m_activatedModule = module; |
|
|
|
m_activatedModuleBase = m_modules[(int)module]; |
|
m_activatedModuleBase.OnActivated(); |
|
|
|
VRModule.InvokeActiveModuleChangedEvent(m_activatedModule); |
|
|
|
switch (m_activatedModule) |
|
{ |
|
#if VIU_STEAMVR |
|
case VRModuleActiveEnum.SteamVR: |
|
#if VIU_STEAMVR_1_2_3_OR_NEWER && !UNITY_2017_1_OR_NEWER && !UNITY_5_3 |
|
Camera.onPreCull += OnCameraPreCull; |
|
#elif VIU_STEAMVR_1_2_0_OR_NEWER |
|
SteamVR_Events.NewPoses.AddListener(OnSteamVRNewPose); |
|
#else |
|
SteamVR_Utils.Event.Listen("new_poses", OnSteamVRNewPoseArgs); |
|
#endif |
|
break; |
|
#endif |
|
#if VIU_WAVEVR |
|
case VRModuleActiveEnum.WaveVR: |
|
WaveVR_Utils.Event.Listen(WaveVR_Utils.Event.NEW_POSES, OnWaveVRNewPoseArgs); |
|
break; |
|
#endif |
|
default: |
|
#if UNITY_2017_1_OR_NEWER |
|
Application.onBeforeRender += UpdateActiveModuleDeviceState; |
|
#else |
|
Camera.onPreCull += OnCameraPreCull; |
|
#endif |
|
break; |
|
} |
|
} |
|
|
|
#if VIU_STEAMVR |
|
#if VIU_STEAMVR_1_1_1 |
|
private void OnSteamVRNewPoseArgs(params object[] args) { OnSteamVRNewPose((Valve.VR.TrackedDevicePose_t[])args[0]); } |
|
#endif |
|
private void OnSteamVRNewPose(Valve.VR.TrackedDevicePose_t[] poses) { UpdateActiveModuleDeviceState(); } |
|
#endif |
|
|
|
#if VIU_WAVEVR |
|
private void OnWaveVRNewPoseArgs(params object[] args) { UpdateActiveModuleDeviceState(); } |
|
#endif |
|
|
|
#if !UNITY_2017_1_OR_NEWER |
|
private int m_poseUpdatedFrame = -1; |
|
private void OnCameraPreCull(Camera cam) |
|
{ |
|
var thisFrame = Time.frameCount; |
|
if (m_poseUpdatedFrame == thisFrame) { return; } |
|
|
|
#if UNITY_5_5_OR_NEWER |
|
if (cam.cameraType != CameraType.Game && cam.cameraType != CameraType.VR) { return; } |
|
#else |
|
if (cam.cameraType != CameraType.Game) { return; } |
|
#endif |
|
|
|
m_poseUpdatedFrame = thisFrame; |
|
UpdateActiveModuleDeviceState(); |
|
} |
|
#endif |
|
|
|
private void UpdateActiveModuleDeviceState() |
|
{ |
|
m_isUpdating = true; |
|
|
|
// copy status to from current state to previous state |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) |
|
{ |
|
if (m_prevStates[i].isConnected || m_currStates[i].isConnected) |
|
{ |
|
m_prevStates[i].CopyFrom(m_currStates[i]); |
|
} |
|
} |
|
|
|
// update status |
|
m_activatedModuleBase.UpdateDeviceState(m_prevStates, m_currStates); |
|
|
|
// send connect/disconnect event |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) |
|
{ |
|
if (m_prevStates[i].isConnected != m_currStates[i].isConnected) |
|
{ |
|
if (m_currStates[i].isConnected) |
|
{ |
|
try |
|
{ |
|
s_deviceSerialNumberTable.Add(m_currStates[i].serialNumber, i); |
|
} |
|
catch (System.Exception e) |
|
{ |
|
Debug.LogError(m_currStates[i].serialNumber + ":" + e.ToString()); |
|
} |
|
} |
|
else |
|
{ |
|
s_deviceSerialNumberTable.Remove(m_prevStates[i].serialNumber); |
|
} |
|
|
|
VRModule.InvokeDeviceConnectedEvent(i, m_currStates[i].isConnected); |
|
} |
|
} |
|
|
|
// send new poses event |
|
VRModule.InvokeNewPosesEvent(); |
|
|
|
if (m_isDestoryed) |
|
{ |
|
DeactivateModule(); |
|
} |
|
|
|
m_isUpdating = false; |
|
} |
|
|
|
private void DeactivateModule() |
|
{ |
|
if (m_activatedModule == VRModuleActiveEnum.Uninitialized) |
|
{ |
|
return; |
|
} |
|
|
|
if (m_activatedModuleBase == null) |
|
{ |
|
return; |
|
} |
|
|
|
switch (m_activatedModule) |
|
{ |
|
#if VIU_STEAMVR |
|
case VRModuleActiveEnum.SteamVR: |
|
#if VIU_STEAMVR_1_2_3_OR_NEWER && !UNITY_2017_1_OR_NEWER && !UNITY_5_3 |
|
Camera.onPreCull -= OnCameraPreCull; |
|
#elif VIU_STEAMVR_1_2_0_OR_NEWER |
|
SteamVR_Events.NewPoses.RemoveListener(OnSteamVRNewPose); |
|
#else |
|
SteamVR_Utils.Event.Remove("new_poses", OnSteamVRNewPoseArgs); |
|
#endif |
|
break; |
|
#endif |
|
#if VIU_WAVEVR |
|
case VRModuleActiveEnum.WaveVR: |
|
WaveVR_Utils.Event.Remove(WaveVR_Utils.Event.NEW_POSES, OnWaveVRNewPoseArgs); |
|
break; |
|
#endif |
|
default: |
|
#if UNITY_2017_1_OR_NEWER |
|
Application.onBeforeRender -= UpdateActiveModuleDeviceState; |
|
#else |
|
Camera.onPreCull -= OnCameraPreCull; |
|
#endif |
|
break; |
|
} |
|
|
|
// copy status to from current state to previous state, and reset current state |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) |
|
{ |
|
if (m_prevStates[i].isConnected || m_currStates[i].isConnected) |
|
{ |
|
m_prevStates[i].CopyFrom(m_currStates[i]); |
|
m_currStates[i].Reset(); |
|
} |
|
} |
|
|
|
// send disconnect event |
|
for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) |
|
{ |
|
if (m_prevStates[i].isConnected) |
|
{ |
|
VRModule.InvokeDeviceConnectedEvent(i, false); |
|
} |
|
} |
|
|
|
var deactivatedModuleBase = m_activatedModuleBase; |
|
|
|
m_activatedModule = VRModuleActiveEnum.Uninitialized; |
|
m_activatedModuleBase = null; |
|
|
|
deactivatedModuleBase.OnDeactivated(); |
|
|
|
VRModule.InvokeActiveModuleChangedEvent(VRModuleActiveEnum.Uninitialized); |
|
} |
|
} |
|
} |