From 602b957a8750944b5cb34a126342d6012831d897 Mon Sep 17 00:00:00 2001 From: lawwong Date: Tue, 25 Sep 2018 16:13:47 +0800 Subject: [PATCH 1/3] Add VIU_STEAMVR_2_0_0_OR_NEWER symbal --- .gitignore | 2 + .../VRModule/Editor/VRModuleManagerEditor.cs | 123 +++++++++++++++++- .../VRModule/Modules/SteamVRModule.cs | 4 + .../VRModule/VRModuleManager.cs | 3 + .../ExCamConfigInterfacePanelController.cs | 3 + .../Scripts/Misc/ExternalCameraHook.cs | 7 + .../Scripts/Misc/OverlayKeyboardSample.cs | 3 + .../Scripts/Misc/RenderModelHook.cs | 3 + .../Scripts/Misc/Teleportable.cs | 3 + .../Scripts/Misc/VRCameraHook.cs | 3 + .../BindingInterfaceSpriteManager.cs | 1 - 11 files changed, 149 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e4c93f6b..9df7cefb 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUProjectSettings.asset. *.cfg *.log +*.json +*.vrmanifest # Autogenerated VS/MD/Consulo solution and project files ExportedObj/ diff --git a/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs b/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs index be7e651f..05192896 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs @@ -36,9 +36,12 @@ public class ReqMethodInfo public string symbol = string.Empty; public string[] reqTypeNames = null; + public string[] reqAnyTypeNames = null; public string[] reqFileNames = null; public ReqFieldInfo[] reqFields = null; + public ReqFieldInfo[] reqAnyFields = null; public ReqMethodInfo[] reqMethods = null; + public ReqMethodInfo[] reqAnyMethods = null; public Func validateFunc = null; public static Dictionary s_foundTypes; @@ -61,6 +64,14 @@ public void FindRequiredTypesInAssembly(Assembly assembly) } } + if (reqAnyTypeNames != null) + { + foreach (var name in reqAnyTypeNames) + { + TryAddTypeFromAssembly(name, assembly); + } + } + if (reqFields != null) { foreach (var field in reqFields) @@ -69,6 +80,14 @@ public void FindRequiredTypesInAssembly(Assembly assembly) } } + if (reqAnyFields != null) + { + foreach (var field in reqAnyFields) + { + TryAddTypeFromAssembly(field.typeName, assembly); + } + } + if (reqMethods != null) { foreach (var method in reqMethods) @@ -84,6 +103,22 @@ public void FindRequiredTypesInAssembly(Assembly assembly) } } } + + if (reqAnyMethods != null) + { + foreach (var method in reqAnyMethods) + { + TryAddTypeFromAssembly(method.typeName, assembly); + + if (method.argTypeNames != null) + { + foreach (var typeName in method.argTypeNames) + { + TryAddTypeFromAssembly(typeName, assembly); + } + } + } + } } private bool TryAddTypeFromAssembly(string name, Assembly assembly) @@ -113,6 +148,22 @@ public bool Validate() } } + if (reqAnyTypeNames != null) + { + var found = false; + + foreach (var name in reqAnyTypeNames) + { + if (s_foundTypes.ContainsKey(name)) + { + found = true; + break; + } + } + + if (!found) { return false; } + } + if (reqFields != null) { foreach (var field in reqFields) @@ -123,6 +174,23 @@ public bool Validate() } } + if (reqAnyFields != null) + { + var found = false; + + foreach (var field in reqAnyFields) + { + Type type; + if (!s_foundTypes.TryGetValue(field.typeName, out type)) { continue; } + if (type.GetField(field.name, field.bindingAttr) == null) { continue; } + + found = true; + break; + } + + if (!found) { return false; } + } + if (reqMethods != null) { foreach (var method in reqMethods) @@ -140,6 +208,30 @@ public bool Validate() } } + if (reqAnyMethods != null) + { + var found = false; + + foreach (var method in reqAnyMethods) + { + Type type; + if (!s_foundTypes.TryGetValue(method.typeName, out type)) { continue; } + + var argTypes = new Type[method.argTypeNames == null ? 0 : method.argTypeNames.Length]; + for (int i = argTypes.Length - 1; i >= 0; --i) + { + if (!s_foundTypes.TryGetValue(method.argTypeNames[i], out argTypes[i])) { continue; } + } + + if (type.GetMethod(method.name, method.bindingAttr, null, CallingConventions.Any, argTypes, method.argModifiers ?? new ParameterModifier[0]) == null) { continue; } + + found = true; + break; + } + + if (!found) { return false; } + } + if (reqFileNames != null) { foreach (var requiredFile in reqFileNames) @@ -158,6 +250,7 @@ public bool Validate() } } + private static List s_symbolReqList; static VRModuleManagerEditor() @@ -174,7 +267,7 @@ static VRModuleManagerEditor() s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_STEAMVR", - reqTypeNames = new string[] { "SteamVR" }, + reqAnyTypeNames = new string[] { "SteamVR", "Valve.VR.SteamVR" }, reqFileNames = new string[] { "SteamVR.cs" }, }); @@ -188,14 +281,14 @@ static VRModuleManagerEditor() s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_STEAMVR_1_2_0_OR_NEWER", - reqTypeNames = new string[] { "SteamVR_Events" }, + reqAnyTypeNames = new string[] { "SteamVR_Events", "Valve.VR.SteamVR_Events" }, reqFileNames = new string[] { "SteamVR_Events.cs" }, }); s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_STEAMVR_1_2_1_OR_NEWER", - reqMethods = new SymbolRequirement.ReqMethodInfo[] + reqAnyMethods = new SymbolRequirement.ReqMethodInfo[] { new SymbolRequirement.ReqMethodInfo() { @@ -203,6 +296,13 @@ static VRModuleManagerEditor() name = "System", argTypeNames = new string[] { "Valve.VR.EVREventType" }, bindingAttr = BindingFlags.Public | BindingFlags.Static, + }, + new SymbolRequirement.ReqMethodInfo() + { + typeName = "Valve.VR.SteamVR_Events", + name = "System", + argTypeNames = new string[] { "Valve.VR.EVREventType" }, + bindingAttr = BindingFlags.Public | BindingFlags.Static, } }, reqFileNames = new string[] { "SteamVR_Events.cs" }, @@ -211,13 +311,19 @@ static VRModuleManagerEditor() s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_STEAMVR_1_2_2_OR_NEWER", - reqFields = new SymbolRequirement.ReqFieldInfo[] + reqAnyFields = new SymbolRequirement.ReqFieldInfo[] { new SymbolRequirement.ReqFieldInfo() { typeName = "SteamVR_ExternalCamera+Config", name = "r", bindingAttr = BindingFlags.Public | BindingFlags.Instance, + }, + new SymbolRequirement.ReqFieldInfo() + { + typeName = "Valve.VR.SteamVR_ExternalCamera+Config", + name = "r", + bindingAttr = BindingFlags.Public | BindingFlags.Instance, } }, reqFileNames = new string[] { "SteamVR_ExternalCamera.cs" }, @@ -238,6 +344,13 @@ static VRModuleManagerEditor() reqFileNames = new string[] { "openvr_api.cs" }, }); + s_symbolReqList.Add(new SymbolRequirement() + { + symbol = "VIU_STEAMVR_2_0_0_OR_NEWER", + reqTypeNames = new string[] { "Valve.VR.SteamVR" }, + reqFileNames = new string[] { "SteamVR.cs" }, + }); + s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_OCULUSVR", @@ -282,7 +395,7 @@ static VRModuleManagerEditor() }, reqFileNames = new string[] { "wvr.cs" }, }); - + s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_WAVEVR_2_1_0_OR_NEWER", diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs index 4f2d461a..54f82b56 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs @@ -94,7 +94,11 @@ public override void Update() { if (SteamVR.active) { +#if VIU_STEAMVR_2_0_0_OR_NEWER + SteamVR.settings.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; +#else SteamVR_Render.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; +#endif } } diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs index c5054240..f5b8aad5 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs @@ -3,6 +3,9 @@ using HTC.UnityPlugin.Utility; using System.Collections.Generic; using UnityEngine; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.VRModuleManagement { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExCamConfigInterface/ExCamConfigInterfacePanelController.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExCamConfigInterface/ExCamConfigInterfacePanelController.cs index 3369103d..ec7d9b21 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExCamConfigInterface/ExCamConfigInterfacePanelController.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExCamConfigInterface/ExCamConfigInterfacePanelController.cs @@ -5,6 +5,9 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.Vive.ExCamConfigInterface { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs index df3ef041..d2961aae 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs @@ -5,6 +5,9 @@ using System; using System.IO; using UnityEngine; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.Vive { @@ -195,7 +198,11 @@ private static void ResolveDefaultExCam() var oldExternalCam = SteamVR_Render.instance.externalCamera; if (oldExternalCam != null) { +#if VIU_STEAMVR_2_0_0_OR_NEWER + if (oldExternalCam.transform.parent != null) +#else if (oldExternalCam.transform.parent != null && oldExternalCam.transform.parent.GetComponent() != null) +#endif { Destroy(oldExternalCam.transform.parent.gameObject); SteamVR_Render.instance.externalCamera = null; diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/OverlayKeyboardSample.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/OverlayKeyboardSample.cs index 5d9bbeff..65dc184c 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/OverlayKeyboardSample.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/OverlayKeyboardSample.cs @@ -3,6 +3,9 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif [RequireComponent(typeof(InputField))] public class OverlayKeyboardSample : MonoBehaviour diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs index 91ad0f63..063253cc 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs @@ -4,6 +4,9 @@ using HTC.UnityPlugin.VRModuleManagement; using System.Collections.Generic; using UnityEngine; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.Vive { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs index 472edce2..996bfd6f 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs @@ -5,6 +5,9 @@ using System.Collections; using UnityEngine; using UnityEngine.EventSystems; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.Vive { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs index 815f46d6..6232e526 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs @@ -2,6 +2,9 @@ using HTC.UnityPlugin.VRModuleManagement; using UnityEngine; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +#endif namespace HTC.UnityPlugin.Vive { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceSpriteManager.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceSpriteManager.cs index 63c00241..9f30ae90 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceSpriteManager.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceSpriteManager.cs @@ -75,7 +75,6 @@ public static void SetupDeviceIcon(Image image, VRModuleDeviceModel deviceModel, public static void SetupTrackingDeviceIcon(Image image, IVRModuleDeviceState deviceState, bool bound) { - VRModuleDeviceModel deviceModel; string spriteName; var scale = Vector3.one; switch (deviceState.deviceModel) From 0636cc8cb50fffb6cd30d2a6ffb452968e27be21 Mon Sep 17 00:00:00 2001 From: lawwong Date: Wed, 3 Oct 2018 16:38:34 +0800 Subject: [PATCH 2/3] Connect to proper pose update event for SteamVR plugin v2 Knowen issue: With SteamVR Plugin v2, you won't get any button input event from VIU, instead you should use SteamVR_Input. Root cause: https://github.com/ValveSoftware/steamvr_unity_plugin/issues/128 Solusion: 1. Use SteamVR_Input to get input (with proper Actions/Bindings settings, read SteamVR documents for more detail) 2. Use older version of the plugin like SteamVR plugin v1.2.3 (https://github.com/ValveSoftware/steamvr_unity_plugin/releases/download/1.2.3/SteamVR.Plugin.unitypackage) --- .../VRModule/Modules/SteamVRModule.cs | 57 ++++++++++--------- .../VRModule/VRModuleManager.cs | 17 ++++-- .../Scripts/Misc/VRCameraHook.cs | 4 +- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs index 54f82b56..88794766 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs @@ -22,7 +22,6 @@ public sealed class SteamVRModule : VRModule.ModuleBase private static readonly StringBuilder s_sb = new StringBuilder(); private ETrackingUniverseOrigin m_prevTrackingSpace; - private VRControllerState_t m_ctrlState; private readonly TrackedDevicePose_t[] m_rawPoses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; private readonly TrackedDevicePose_t[] m_rawGamePoses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; @@ -48,6 +47,7 @@ public override void OnActivated() m_prevTrackingSpace = compositor.GetTrackingSpace(); UpdateTrackingSpaceType(); } + #if VIU_STEAMVR_1_2_1_OR_NEWER SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).AddListener(OnTrackedDeviceRoleChanged); #elif VIU_STEAMVR_1_2_0_OR_NEWER @@ -73,20 +73,24 @@ public override void OnDeactivated() #endif } + private static ETrackingUniverseOrigin GetTrackingUniverse() + { + switch (VRModule.trackingSpaceType) + { + case VRModuleTrackingSpaceType.RoomScale: + return ETrackingUniverseOrigin.TrackingUniverseStanding; + case VRModuleTrackingSpaceType.Stationary: + default: + return ETrackingUniverseOrigin.TrackingUniverseSeated; + } + } + public override void UpdateTrackingSpaceType() { var compositor = OpenVR.Compositor; if (compositor != null) { - switch (VRModule.trackingSpaceType) - { - case VRModuleTrackingSpaceType.RoomScale: - compositor.SetTrackingSpace(ETrackingUniverseOrigin.TrackingUniverseStanding); - break; - case VRModuleTrackingSpaceType.Stationary: - compositor.SetTrackingSpace(ETrackingUniverseOrigin.TrackingUniverseSeated); - break; - } + compositor.SetTrackingSpace(GetTrackingUniverse()); } } @@ -204,30 +208,31 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu if (currState[i].deviceClass == VRModuleDeviceClass.Controller || currState[i].deviceClass == VRModuleDeviceClass.GenericTracker) { // get device state from openvr api + var ctrlState = default(VRControllerState_t); + if (system != null) + { #if VIU_STEAMVR_1_2_0_OR_NEWER - if (system == null || !system.GetControllerState(i, ref m_ctrlState, s_sizeOfControllerStats)) + system.GetControllerState(i, ref ctrlState, s_sizeOfControllerStats); #else - if (system == null || !system.GetControllerState(i, ref m_ctrlState)) + system.GetControllerState(i, ref ctrlState); #endif - { - m_ctrlState = default(VRControllerState_t); } // update device input button - currState[i].buttonPressed = m_ctrlState.ulButtonPressed; - currState[i].buttonTouched = m_ctrlState.ulButtonTouched; + currState[i].buttonPressed = ctrlState.ulButtonPressed; + currState[i].buttonTouched = ctrlState.ulButtonTouched; // update device input axis - currState[i].SetAxisValue(VRModuleRawAxis.Axis0X, m_ctrlState.rAxis0.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis0Y, m_ctrlState.rAxis0.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis1X, m_ctrlState.rAxis1.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis1Y, m_ctrlState.rAxis1.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis2X, m_ctrlState.rAxis2.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis2Y, m_ctrlState.rAxis2.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis3X, m_ctrlState.rAxis3.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis3Y, m_ctrlState.rAxis3.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis4X, m_ctrlState.rAxis4.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis4Y, m_ctrlState.rAxis4.y); + currState[i].SetAxisValue(VRModuleRawAxis.Axis0X, ctrlState.rAxis0.x); + currState[i].SetAxisValue(VRModuleRawAxis.Axis0Y, ctrlState.rAxis0.y); + currState[i].SetAxisValue(VRModuleRawAxis.Axis1X, ctrlState.rAxis1.x); + currState[i].SetAxisValue(VRModuleRawAxis.Axis1Y, ctrlState.rAxis1.y); + currState[i].SetAxisValue(VRModuleRawAxis.Axis2X, ctrlState.rAxis2.x); + currState[i].SetAxisValue(VRModuleRawAxis.Axis2Y, ctrlState.rAxis2.y); + currState[i].SetAxisValue(VRModuleRawAxis.Axis3X, ctrlState.rAxis3.x); + currState[i].SetAxisValue(VRModuleRawAxis.Axis3Y, ctrlState.rAxis3.y); + currState[i].SetAxisValue(VRModuleRawAxis.Axis4X, ctrlState.rAxis4.x); + currState[i].SetAxisValue(VRModuleRawAxis.Axis4Y, ctrlState.rAxis4.y); } } else diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs index f5b8aad5..9297d4a1 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs @@ -191,7 +191,9 @@ private void ActivateModule(VRModuleActiveEnum module) { #if VIU_STEAMVR case VRModuleActiveEnum.SteamVR: -#if VIU_STEAMVR_1_2_3_OR_NEWER && !UNITY_2017_1_OR_NEWER && !UNITY_5_3 +#if VIU_STEAMVR_2_0_0_OR_NEWER + SteamVR_Input.OnPosesUpdated += OnSteamVRInputPosesUpdated; +#elif 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); @@ -216,9 +218,10 @@ private void ActivateModule(VRModuleActiveEnum module) } #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 OnSteamVRInputPosesUpdated(bool obj) { UpdateActiveModuleDeviceState(); } + + private void OnSteamVRNewPoseArgs(params object[] args) { UpdateActiveModuleDeviceState(); } + private void OnSteamVRNewPose(Valve.VR.TrackedDevicePose_t[] poses) { UpdateActiveModuleDeviceState(); } #endif @@ -312,7 +315,11 @@ private void DeactivateModule() { #if VIU_STEAMVR case VRModuleActiveEnum.SteamVR: -#if VIU_STEAMVR_1_2_3_OR_NEWER && !UNITY_2017_1_OR_NEWER && !UNITY_5_3 +#if VIU_STEAMVR_2_0_0_OR_NEWER + SteamVR_Input.OnPosesUpdated -= OnSteamVRInputPosesUpdated; +#elif VIU_STEAMVR_2_0_0_OR_NEWER && !UNITY_2017_1_OR_NEWER + Camera.onPreCull -= OnCameraPreCull; +#elif 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); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs index 6232e526..ce164f00 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs @@ -2,7 +2,7 @@ using HTC.UnityPlugin.VRModuleManagement; using UnityEngine; -#if VIU_STEAMVR_2_0_0_OR_NEWER +#if !UNITY_5_4_OR_NEWER && VIU_STEAMVR_2_0_0_OR_NEWER using Valve.VR; #endif @@ -30,7 +30,7 @@ private void OnModuleActivated(VRModuleActiveEnum activatedModule) { switch (activatedModule) { -#if VIU_STEAMVR +#if !UNITY_5_4_OR_NEWER && VIU_STEAMVR case VRModuleActiveEnum.SteamVR: if (GetComponent() == null) { From 831c9a73479a74d9263eaaa8aed8c743495cd87c Mon Sep 17 00:00:00 2001 From: lawwong Date: Wed, 12 Dec 2018 22:52:51 +0800 Subject: [PATCH 3/3] Add new SteamVR Input System support --- .../VRModule/Editor/VRModuleManagerEditor.cs | 20 +- .../VRModule/Modules/GoogleVRModule.cs | 408 +++++++++-- .../VRModule/Modules/OculusVRModule.cs | 283 ++++---- .../VRModule/Modules/SimulatorModule.cs | 63 +- .../VRModule/Modules/SteamVRModule.cs | 365 ++++++---- .../VRModule/Modules/SteamVRv2Module.cs | 666 ++++++++++++++++++ .../VRModule/Modules/SteamVRv2Module.cs.meta | 11 + .../Modules/UnityEngineVRModule_2017_1.cs | 201 +++--- .../Modules/UnityEngineVRModule_5_5.cs | 38 +- .../VRModule/Modules/WaveVRModule.cs | 348 +++++---- Assets/HTC.UnityPlugin/VRModule/VRModule.cs | 35 +- .../HTC.UnityPlugin/VRModule/VRModuleBase.cs | 76 +- .../VRModule/VRModuleDeviceState.cs | 46 +- .../HTC.UnityPlugin/VRModule/VRModuleEvent.cs | 11 + .../VRModule/VRModuleManager.cs | 330 +++++---- .../Examples/3.3DDrag/Scripts/Draggable.cs | 5 +- .../Scripts/Editor/VIUProjectSettings.cs | 17 + .../Scripts/Editor/VIUSettingsEditor.cs | 79 ++- .../Scripts/Editor/VIUVersionCheck.cs | 118 ++++ .../Scripts/Misc/BasicGrabbable.cs | 5 +- .../Scripts/Misc/ExternalCameraHook.cs | 9 +- .../Scripts/Misc/RenderModelHook.cs | 29 +- .../Scripts/Misc/SteamVRExtension.meta | 8 + .../Scripts/Misc/SteamVRExtension/Editor.meta | 8 + .../Editor/VIUSteamVRActionFile.cs | 228 ++++++ .../Editor/VIUSteamVRActionFile.cs.meta | 11 + .../Editor/VIUSteamVRBindingFile.cs | 166 +++++ .../Editor/VIUSteamVRBindingFile.cs.meta | 11 + .../Editor/VIUSteamVRLoadJsonFileBase.cs | 416 +++++++++++ .../Editor/VIUSteamVRLoadJsonFileBase.cs.meta | 11 + .../Editor/VIUSteamVRRenderModelEditor.cs | 117 +++ .../VIUSteamVRRenderModelEditor.cs.meta | 11 + .../PartialInputBindings.meta | 8 + .../PartialInputBindings/actions.json | 327 +++++++++ .../PartialInputBindings/actions.json.meta | 7 + .../bindings_holographic_controller.json | 135 ++++ .../bindings_holographic_controller.json.meta | 7 + .../bindings_holographic_hmd.json.meta | 9 + .../bindings_knuckles.json | 4 + .../bindings_knuckles.json.meta | 7 + .../bindings_oculus_touch.json | 171 +++++ .../bindings_oculus_touch.json.meta | 7 + .../bindings_rift.json.meta | 7 + .../bindings_vive.json.meta | 7 + .../bindings_vive_controller.json | 241 +++++++ .../bindings_vive_controller.json.meta | 7 + .../bindings_vive_pro.json.meta | 7 + .../bindings_vive_tracker.json | 548 ++++++++++++++ .../bindings_vive_tracker.json.meta | 7 + .../SteamVRExtension/VIUSteamVRRenderModel.cs | 368 ++++++++++ .../VIUSteamVRRenderModel.cs.meta | 11 + .../VIUSteamVRRenderModelLoader.cs | 477 +++++++++++++ .../VIUSteamVRRenderModelLoader.cs.meta | 11 + .../Scripts/Misc/StickyGrabbable.cs | 5 +- .../Scripts/Misc/Teleportable.cs | 2 +- .../Scripts/Misc/VRCameraHook.cs | 5 +- .../ViveInputUtility/Scripts/VIUVersion.cs | 2 +- .../Scripts/ViveInput/ControllerState.cs | 21 + .../Scripts/ViveInput/ViveInput.cs | 20 +- .../BindingInterfaceDevicePanelController.cs | 2 +- .../Scripts/ViveRole/RoleMaps/BodyRole.cs | 2 +- .../Scripts/ViveRole/RoleMaps/HandRole.cs | 2 +- 62 files changed, 5767 insertions(+), 817 deletions(-) create mode 100644 Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs create mode 100644 Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_hmd.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_rift.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_pro.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs.meta create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs create mode 100644 Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs.meta diff --git a/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs b/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs index 05192896..8d60a84d 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Editor/VRModuleManagerEditor.cs @@ -267,8 +267,8 @@ static VRModuleManagerEditor() s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_STEAMVR", - reqAnyTypeNames = new string[] { "SteamVR", "Valve.VR.SteamVR" }, - reqFileNames = new string[] { "SteamVR.cs" }, + reqTypeNames = new string[] { "Valve.VR.OpenVR" }, + reqFileNames = new string[] { "openvr_api.cs" }, }); s_symbolReqList.Add(new SymbolRequirement() @@ -348,7 +348,12 @@ static VRModuleManagerEditor() { symbol = "VIU_STEAMVR_2_0_0_OR_NEWER", reqTypeNames = new string[] { "Valve.VR.SteamVR" }, - reqFileNames = new string[] { "SteamVR.cs" }, + }); + + s_symbolReqList.Add(new SymbolRequirement() + { + symbol = "VIU_STEAMVR_2_1_0_OR_NEWER", + reqTypeNames = new string[] { "Valve.VR.SteamVR_ActionSet_Manager" }, }); s_symbolReqList.Add(new SymbolRequirement() @@ -365,6 +370,13 @@ static VRModuleManagerEditor() reqFileNames = new string[] { "GvrUnitySdkVersion.cs" }, }); + s_symbolReqList.Add(new SymbolRequirement() + { + symbol = "VIU_GOOGLEVR_1_150_0_NEWER", + reqTypeNames = new string[] { "GvrControllerInputDevice" }, + reqFileNames = new string[] { "GvrControllerInputDevice.cs" }, + }); + s_symbolReqList.Add(new SymbolRequirement() { symbol = "VIU_WAVEVR", @@ -508,6 +520,8 @@ public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetO foreach (var symbolReq in s_symbolReqList) { + if (symbolReq == null || symbolReq.reqFileNames == null) { continue; } + foreach (var reqFileName in symbolReq.reqFileNames) { if (isDir) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/GoogleVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/GoogleVRModule.cs index 70a44fd3..9cd78030 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/GoogleVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/GoogleVRModule.cs @@ -22,143 +22,399 @@ namespace HTC.UnityPlugin.VRModuleManagement public sealed class GoogleVRModule : VRModule.ModuleBase { #if VIU_GOOGLEVR && UNITY_5_6_OR_NEWER - public const uint CONTROLLER_DEVICE_INDEX = 1u; + private const uint HEAD_INDEX = 0u; - private GvrHeadset m_gvrHeadSetInstance; - private GvrControllerInput m_gvrCtrlInputInstance; - private GvrArmModel m_gvrArmModelInstance; + private uint m_rightIndex = INVALID_DEVICE_INDEX; + private uint m_leftIndex = INVALID_DEVICE_INDEX; - public override uint GetRightControllerDeviceIndex() { return CONTROLLER_DEVICE_INDEX; } + public override uint GetRightControllerDeviceIndex() { return m_rightIndex; } + + public override uint GetLeftControllerDeviceIndex() { return m_leftIndex; } public override bool ShouldActiveModule() { return VIUSettings.activateGoogleVRModule && XRSettings.enabled && XRSettings.loadedDeviceName == "daydream"; } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + public override void Update() + { + UpdateDeviceInput(); + ProcessDeviceInputChanged(); + } + + public override void BeforeRenderUpdate() + { + FlushDeviceState(); + UpdateConnectedDevices(); + ProcessConnectedDeviceChanged(); + UpdateDevicePose(); + ProcessDevicePoseChanged(); + } + +#if VIU_GOOGLEVR_1_150_0_NEWER + private const uint RIGHT_HAND_INDEX = 1u; + private const uint LEFT_HAND_INDEX = 2u; + + private GvrControllerInputDevice m_rightDevice; + private GvrControllerInputDevice m_leftDevice; + private GvrArmModel m_rightArm; + private GvrArmModel m_leftArm; + + public override void OnActivated() { - if (m_gvrCtrlInputInstance == null) + EnsureDeviceStateLength(3); + + if (Object.FindObjectOfType() == null) { - m_gvrCtrlInputInstance = Object.FindObjectOfType(); + VRModule.Instance.gameObject.AddComponent(); + } - if (m_gvrCtrlInputInstance == null) - { - m_gvrCtrlInputInstance = VRModule.Instance.gameObject.AddComponent(); - } + if (Object.FindObjectOfType() == null) + { + VRModule.Instance.gameObject.AddComponent(); } - if (GvrControllerInput.State == GvrConnectionState.Error) + m_rightDevice = GvrControllerInput.GetDevice(GvrControllerHand.Right); + m_leftDevice = GvrControllerInput.GetDevice(GvrControllerHand.Left); + + var armModels = VRModule.Instance.GetComponents(); + + if (armModels != null && armModels.Length >= 1) { - Debug.LogError(GvrControllerInput.ErrorDetails); - return; + m_rightArm = armModels[0]; } + else + { + m_rightArm = VRModule.Instance.GetComponent(); + } + m_rightArm.ControllerInputDevice = m_rightDevice; - if (m_gvrArmModelInstance == null) + if (armModels != null && armModels.Length >= 2) + { + m_leftArm = armModels[1]; + } + else { - m_gvrArmModelInstance = VRModule.Instance.GetComponent(); + m_leftArm = VRModule.Instance.GetComponent(); + } + m_leftArm.ControllerInputDevice = m_leftDevice; + } - if (m_gvrArmModelInstance == null) + // update connected devices + private void UpdateConnectedDevices() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(HEAD_INDEX, out prevState, out currState); + if (!XRDevice.isPresent) + { + if (prevState.isConnected) { - m_gvrArmModelInstance = VRModule.Instance.gameObject.AddComponent(); + currState.Reset(); } } - - if (m_gvrHeadSetInstance == null) + else { - m_gvrHeadSetInstance = Object.FindObjectOfType(); - - if (m_gvrHeadSetInstance == null) + if (!prevState.isConnected) { - m_gvrHeadSetInstance = VRModule.Instance.gameObject.AddComponent(); + currState.isConnected = true; + currState.deviceClass = VRModuleDeviceClass.HMD; + currState.serialNumber = XRDevice.model + " HMD"; + currState.modelNumber = XRDevice.model + " HMD"; + currState.deviceModel = VRModuleDeviceModel.DaydreamHMD; + currState.renderModelName = string.Empty; } } - var headPrevState = prevState[VRModule.HMD_DEVICE_INDEX]; - var headCurrState = currState[VRModule.HMD_DEVICE_INDEX]; - - headCurrState.isConnected = XRDevice.isPresent; - - if (headCurrState.isConnected) + EnsureValidDeviceState(RIGHT_HAND_INDEX, out prevState, out currState); + if (m_rightDevice.State != GvrConnectionState.Connected) { - if (!headPrevState.isConnected) + if (prevState.isConnected) { - headCurrState.deviceClass = VRModuleDeviceClass.HMD; - headCurrState.serialNumber = XRDevice.model + " HMD"; - headCurrState.modelNumber = XRDevice.model + " HMD"; - - headCurrState.deviceModel = VRModuleDeviceModel.DaydreamHMD; - headCurrState.renderModelName = string.Empty; + currState.Reset(); + m_rightIndex = INVALID_DEVICE_INDEX; } + } + else + { + if (!prevState.isConnected) + { + currState.isConnected = true; + currState.deviceClass = VRModuleDeviceClass.Controller; + currState.serialNumber = XRDevice.model + " Controller Right"; + currState.modelNumber = XRDevice.model + " Controller Right"; + currState.deviceModel = VRModuleDeviceModel.DaydreamController; + currState.renderModelName = string.Empty; + m_rightIndex = RIGHT_HAND_INDEX; + } + } - headCurrState.position = InputTracking.GetLocalPosition(XRNode.Head); - headCurrState.rotation = InputTracking.GetLocalRotation(XRNode.Head); - headCurrState.isPoseValid = headCurrState.pose != RigidPose.identity; - - headCurrState.pose = headCurrState.pose; + EnsureValidDeviceState(LEFT_HAND_INDEX, out prevState, out currState); + if (m_leftDevice.State != GvrConnectionState.Connected) + { + if (prevState.isConnected) + { + currState.Reset(); + m_leftIndex = INVALID_DEVICE_INDEX; + } } else { - if (headPrevState.isConnected) + if (!prevState.isConnected) { - headCurrState.Reset(); + currState.isConnected = true; + currState.deviceClass = VRModuleDeviceClass.Controller; + currState.serialNumber = XRDevice.model + " Controller Left"; + currState.modelNumber = XRDevice.model + " Controller Left"; + currState.deviceModel = VRModuleDeviceModel.DaydreamController; + currState.renderModelName = string.Empty; + m_leftIndex = RIGHT_HAND_INDEX; } } + } + + private void UpdateDevicePose() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(HEAD_INDEX, out prevState, out currState); + if (currState.isConnected) + { + currState.position = InputTracking.GetLocalPosition(XRNode.Head); + currState.rotation = InputTracking.GetLocalRotation(XRNode.Head); + currState.isPoseValid = currState.pose != RigidPose.identity; + } - var ctrlPrevState = prevState[CONTROLLER_DEVICE_INDEX]; - var ctrlCurrState = currState[CONTROLLER_DEVICE_INDEX]; + EnsureValidDeviceState(RIGHT_HAND_INDEX, out prevState, out currState); + if (currState.isConnected) + { + currState.position = m_rightArm.ControllerPositionFromHead; + currState.rotation = m_rightArm.ControllerRotationFromHead; + currState.isPoseValid = m_rightDevice.Orientation != Quaternion.identity; + } - ctrlCurrState.isConnected = GvrControllerInput.State == GvrConnectionState.Connected; + EnsureValidDeviceState(LEFT_HAND_INDEX, out prevState, out currState); + if (currState.isConnected) + { + currState.position = m_leftArm.ControllerPositionFromHead; + currState.rotation = m_leftArm.ControllerRotationFromHead; + currState.isPoseValid = m_leftDevice.Orientation != Quaternion.identity; + } + } - if (ctrlCurrState.isConnected) + private void UpdateDeviceInput() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(RIGHT_HAND_INDEX, out prevState, out currState); + if (currState.isConnected) { - if (!ctrlPrevState.isConnected) + var appPressed = m_rightDevice.GetButton(GvrControllerButton.App); + var systemPressed = m_rightDevice.GetButton(GvrControllerButton.System); + var padPressed = m_rightDevice.GetButton(GvrControllerButton.TouchPadButton); + var padTouched = m_rightDevice.GetButton(GvrControllerButton.TouchPadTouch); + var padAxis = m_rightDevice.TouchPos; + + currState.SetButtonPress(VRModuleRawButton.Touchpad, padPressed); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, appPressed); + currState.SetButtonPress(VRModuleRawButton.System, systemPressed); + + currState.SetButtonTouch(VRModuleRawButton.Touchpad, padTouched); + + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, padAxis.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, padAxis.y); + + if (VIUSettings.daydreamSyncPadPressToTrigger) { - ctrlCurrState.deviceClass = VRModuleDeviceClass.Controller; - ctrlCurrState.serialNumber = XRDevice.model + " Controller"; - ctrlCurrState.modelNumber = XRDevice.model + " Controller"; + currState.SetButtonPress(VRModuleRawButton.Trigger, padPressed); + currState.SetButtonTouch(VRModuleRawButton.Trigger, padTouched); + currState.SetAxisValue(VRModuleRawAxis.Trigger, padPressed ? 1f : 0f); + } + } + + EnsureValidDeviceState(LEFT_HAND_INDEX, out prevState, out currState); + if (currState.isConnected) + { + var appPressed = m_leftDevice.GetButton(GvrControllerButton.App); + var systemPressed = m_leftDevice.GetButton(GvrControllerButton.System); + var padPressed = m_leftDevice.GetButton(GvrControllerButton.TouchPadButton); + var padTouched = m_leftDevice.GetButton(GvrControllerButton.TouchPadTouch); + var padAxis = m_leftDevice.TouchPos; - ctrlCurrState.deviceModel = VRModuleDeviceModel.DaydreamController; - ctrlCurrState.renderModelName = string.Empty; + currState.SetButtonPress(VRModuleRawButton.Touchpad, padPressed); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, appPressed); + currState.SetButtonPress(VRModuleRawButton.System, systemPressed); + + currState.SetButtonTouch(VRModuleRawButton.Touchpad, padTouched); + + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, padAxis.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, padAxis.y); + + if (VIUSettings.daydreamSyncPadPressToTrigger) + { + currState.SetButtonPress(VRModuleRawButton.Trigger, padPressed); + currState.SetButtonTouch(VRModuleRawButton.Trigger, padTouched); + currState.SetAxisValue(VRModuleRawAxis.Trigger, padPressed ? 1f : 0f); } + } + } +#else + public const uint CONTROLLER_INDEX = 1u; - ctrlCurrState.pose = new RigidPose(m_gvrArmModelInstance.ControllerPositionFromHead, m_gvrArmModelInstance.ControllerRotationFromHead); - ctrlCurrState.isPoseValid = GvrControllerInput.Orientation != Quaternion.identity; - ctrlCurrState.velocity = GvrControllerInput.Accel; - ctrlCurrState.angularVelocity = GvrControllerInput.Gyro; + private GvrArmModel m_gvrArmModel; - ctrlCurrState.SetButtonPress(VRModuleRawButton.Touchpad, GvrControllerInput.ClickButton); - ctrlCurrState.SetButtonPress(VRModuleRawButton.ApplicationMenu, GvrControllerInput.AppButton); - ctrlCurrState.SetButtonPress(VRModuleRawButton.System, GvrControllerInput.HomeButtonState); + public override void OnActivated() + { + EnsureDeviceStateLength(2); - ctrlCurrState.SetButtonTouch(VRModuleRawButton.Touchpad, GvrControllerInput.IsTouching); + if (Object.FindObjectOfType() == null) + { + VRModule.Instance.gameObject.AddComponent(); + } - if (GvrControllerInput.IsTouching) + if (Object.FindObjectOfType() == null) + { + VRModule.Instance.gameObject.AddComponent(); + } + + m_gvrArmModel = VRModule.Instance.GetComponent(); + if (m_gvrArmModel == null) + { + m_gvrArmModel = VRModule.Instance.gameObject.AddComponent(); + } + } + + // update connected devices + private void UpdateConnectedDevices() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(HEAD_INDEX, out prevState, out currState); + if (!XRDevice.isPresent) + { + if (prevState.isConnected) { - var touchPadPosCentered = GvrControllerInput.TouchPosCentered; - ctrlCurrState.SetAxisValue(VRModuleRawAxis.TouchpadX, touchPadPosCentered.x); - ctrlCurrState.SetAxisValue(VRModuleRawAxis.TouchpadY, touchPadPosCentered.y); + currState.Reset(); } - else + } + else + { + if (!prevState.isConnected) { - ctrlCurrState.SetAxisValue(VRModuleRawAxis.TouchpadX, 0f); - ctrlCurrState.SetAxisValue(VRModuleRawAxis.TouchpadY, 0f); + currState.isConnected = true; + currState.deviceClass = VRModuleDeviceClass.HMD; + currState.serialNumber = XRDevice.model + " HMD"; + currState.modelNumber = XRDevice.model + " HMD"; + currState.deviceModel = VRModuleDeviceModel.DaydreamHMD; + currState.renderModelName = string.Empty; } + } - if (VIUSettings.daydreamSyncPadPressToTrigger) + var controllerRoleChanged = false; + EnsureValidDeviceState(CONTROLLER_INDEX, out prevState, out currState); + if (GvrControllerInput.State != GvrConnectionState.Connected) + { + if (prevState.isConnected) { - ctrlCurrState.SetButtonPress(VRModuleRawButton.Trigger, GvrControllerInput.ClickButton); - ctrlCurrState.SetButtonTouch(VRModuleRawButton.Trigger, GvrControllerInput.IsTouching); - ctrlCurrState.SetAxisValue(VRModuleRawAxis.Trigger, GvrControllerInput.ClickButton ? 1f : 0f); + currState.Reset(); } } else { - if (ctrlPrevState.isConnected) + if (!prevState.isConnected) { - ctrlCurrState.Reset(); + currState.isConnected = true; + currState.deviceClass = VRModuleDeviceClass.Controller; + currState.serialNumber = XRDevice.model + " Controller"; + currState.modelNumber = XRDevice.model + " Controller"; + currState.deviceModel = VRModuleDeviceModel.DaydreamController; + currState.renderModelName = string.Empty; } + + switch (GvrSettings.Handedness) + { + case GvrSettings.UserPrefsHandedness.Right: + controllerRoleChanged = !VRModule.IsValidDeviceIndex(m_rightIndex) && m_leftIndex == CONTROLLER_INDEX; + m_rightIndex = CONTROLLER_INDEX; + m_leftIndex = INVALID_DEVICE_INDEX; + break; + case GvrSettings.UserPrefsHandedness.Left: + controllerRoleChanged = m_rightIndex == CONTROLLER_INDEX && !VRModule.IsValidDeviceIndex(m_leftIndex); + m_rightIndex = INVALID_DEVICE_INDEX; + m_leftIndex = CONTROLLER_INDEX; + break; + case GvrSettings.UserPrefsHandedness.Error: + default: + Debug.LogError("GvrSettings.Handedness error"); + break; + } + } + + if (controllerRoleChanged) + { + InvokeControllerRoleChangedEvent(); + } + } + + private void UpdateDevicePose() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(HEAD_INDEX, out prevState, out currState); + if (currState.isConnected) + { + currState.position = InputTracking.GetLocalPosition(XRNode.Head); + currState.rotation = InputTracking.GetLocalRotation(XRNode.Head); + currState.isPoseValid = currState.pose != RigidPose.identity; + } + + EnsureValidDeviceState(CONTROLLER_INDEX, out prevState, out currState); + if (currState.isConnected) + { + currState.position = m_gvrArmModel.ControllerPositionFromHead; + currState.rotation = m_gvrArmModel.ControllerRotationFromHead; + currState.isPoseValid = GvrControllerInput.Orientation != Quaternion.identity; } } + + private void UpdateDeviceInput() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(CONTROLLER_INDEX, out prevState, out currState); + if (currState.isConnected) + { + var appPressed = GvrControllerInput.AppButton; + var homePressed = GvrControllerInput.HomeButtonState; + var padPressed = GvrControllerInput.ClickButton; + var padTouched = GvrControllerInput.IsTouching; + var padAxis = GvrControllerInput.TouchPosCentered; + + currState.SetButtonPress(VRModuleRawButton.Touchpad, padPressed); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, appPressed); + currState.SetButtonPress(VRModuleRawButton.System, homePressed); + + currState.SetButtonTouch(VRModuleRawButton.Touchpad, padTouched); + + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, padAxis.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, padAxis.y); + + if (VIUSettings.daydreamSyncPadPressToTrigger) + { + currState.SetButtonPress(VRModuleRawButton.Trigger, padPressed); + currState.SetButtonTouch(VRModuleRawButton.Trigger, padTouched); + currState.SetAxisValue(VRModuleRawAxis.Trigger, padPressed ? 1f : 0f); + } + } + } +#endif + #endif } } \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/OculusVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/OculusVRModule.cs index ad416674..9e3a09bc 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/OculusVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/OculusVRModule.cs @@ -17,6 +17,7 @@ namespace HTC.UnityPlugin.VRModuleManagement public sealed class OculusVRModule : VRModule.ModuleBase { #if VIU_OCULUSVR + public const int VALID_NODE_COUNT = 7; private static readonly OVRPlugin.Node[] s_index2node; private static readonly uint[] s_node2index; private static readonly VRModuleDeviceClass[] s_node2class; @@ -25,7 +26,7 @@ public sealed class OculusVRModule : VRModule.ModuleBase static OculusVRModule() { - s_index2node = new OVRPlugin.Node[VRModule.MAX_DEVICE_COUNT]; + s_index2node = new OVRPlugin.Node[VALID_NODE_COUNT]; for (int i = 0; i < s_index2node.Length; ++i) { s_index2node[i] = OVRPlugin.Node.None; } s_index2node[0] = OVRPlugin.Node.Head; s_index2node[1] = OVRPlugin.Node.HandLeft; @@ -62,6 +63,8 @@ public override void OnActivated() { m_prevTrackingSpace = OVRPlugin.GetTrackingOriginType(); UpdateTrackingSpaceType(); + + EnsureDeviceStateLength(VALID_NODE_COUNT); } public override void OnDeactivated() @@ -112,166 +115,176 @@ private static RigidPose ToPose(OVRPlugin.Posef value) return new RigidPose(ovrPose.position, ovrPose.orientation); } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + public override void BeforeRenderUpdate() { - for (uint i = 0; i < MAX_DEVICE_COUNT; ++i) + FlushDeviceState(); + + for (uint i = 0u, imax = GetDeviceStateLength(); i < imax; ++i) { var node = s_index2node[i]; if (node == OVRPlugin.Node.None) { continue; } - currState[i].isConnected = OVRPlugin.GetNodePresent(node); + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + EnsureValidDeviceState(i, out prevState, out currState); - if (currState[i].isConnected) + if (!OVRPlugin.GetNodePresent(node)) { - if (!prevState[i].isConnected) + if (prevState.isConnected) { - var ovrProductName = OVRPlugin.productName; - var deviceClass = s_node2class[(int)node]; - - switch (deviceClass) - { - case VRModuleDeviceClass.HMD: - currState[i].deviceModel = VRModuleDeviceModel.OculusHMD; - break; - case VRModuleDeviceClass.TrackingReference: - currState[i].deviceModel = VRModuleDeviceModel.OculusSensor; - break; - case VRModuleDeviceClass.Controller: - switch (ovrProductName) - { - case "Oculus Go": - currState[i].deviceModel = VRModuleDeviceModel.OculusGoController; - break; - case "Gear VR": - currState[i].deviceModel = VRModuleDeviceModel.OculusGearVrController; - break; - case "Oculus Rift": - default: - switch (node) - { - case OVRPlugin.Node.HandLeft: - currState[i].deviceModel = VRModuleDeviceModel.OculusTouchLeft; - break; - case OVRPlugin.Node.HandRight: - default: - currState[i].deviceModel = VRModuleDeviceModel.OculusTouchRight; - break; - } - break; - } - break; - } - - currState[i].deviceClass = deviceClass; - // FIXME: how to get device id from OVRPlugin? - currState[i].modelNumber = ovrProductName + " " + deviceClass; - currState[i].renderModelName = ovrProductName + " " + deviceClass; - currState[i].serialNumber = ovrProductName + " " + deviceClass; + currState.Reset(); } - // update device status - currState[i].pose = ToPose(OVRPlugin.GetNodePose(node, OVRPlugin.Step.Render)); - currState[i].velocity = OVRPlugin.GetNodeVelocity(node, OVRPlugin.Step.Render).FromFlippedZVector3f(); - currState[i].angularVelocity = OVRPlugin.GetNodeAngularVelocity(node, OVRPlugin.Step.Render).FromFlippedZVector3f(); + continue; + } + + // update device connected state + if (!prevState.isConnected) + { + var ovrProductName = OVRPlugin.productName; + var deviceClass = s_node2class[(int)node]; - currState[i].isPoseValid = currState[i].pose != RigidPose.identity; + currState.isConnected = true; + currState.deviceClass = deviceClass; + // FIXME: how to get device id from OVRPlugin? + currState.modelNumber = ovrProductName + " " + deviceClass; + currState.renderModelName = ovrProductName + " " + deviceClass; + currState.serialNumber = ovrProductName + " " + deviceClass; - // update device input - switch (currState[i].deviceModel) + switch (deviceClass) { - case VRModuleDeviceModel.OculusTouchLeft: - { - var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.LTouch); - - currState[i].SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Y) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.A, (ctrlState.Buttons & (uint)OVRInput.RawButton.X) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.LThumbstick) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Trigger, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.Trigger), ctrlState.LIndexTrigger, 0.55f, 0.45f)); - currState[i].SetButtonPress(VRModuleRawButton.Grip, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.Grip), ctrlState.LHandTrigger, 0.55f, 0.45f)); - currState[i].SetButtonPress(VRModuleRawButton.CapSenseGrip, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.CapSenseGrip), ctrlState.LHandTrigger, 0.55f, 0.45f)); - - currState[i].SetButtonTouch(VRModuleRawButton.ApplicationMenu, (ctrlState.Touches & (uint)OVRInput.RawTouch.Y) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.A, (ctrlState.Touches & (uint)OVRInput.RawTouch.X) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.LThumbstick) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.Trigger, (ctrlState.Touches & (uint)OVRInput.RawTouch.LIndexTrigger) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.CapSenseGrip, AxisToPress(currState[i].GetButtonTouch(VRModuleRawButton.CapSenseGrip), ctrlState.LHandTrigger, 0.25f, 0.20f)); - - currState[i].SetAxisValue(VRModuleRawAxis.TouchpadX, ctrlState.LThumbstick.x); - currState[i].SetAxisValue(VRModuleRawAxis.TouchpadY, ctrlState.LThumbstick.y); - currState[i].SetAxisValue(VRModuleRawAxis.Trigger, ctrlState.LIndexTrigger); - currState[i].SetAxisValue(VRModuleRawAxis.CapSenseGrip, ctrlState.LHandTrigger); - break; - } - case VRModuleDeviceModel.OculusTouchRight: - { - var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.RTouch); - - currState[i].SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.B) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.A, (ctrlState.Buttons & (uint)OVRInput.RawButton.A) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.RThumbstick) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Trigger, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.Trigger), ctrlState.RIndexTrigger, 0.55f, 0.45f)); - currState[i].SetButtonPress(VRModuleRawButton.Grip, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.Grip), ctrlState.RHandTrigger, 0.55f, 0.45f)); - currState[i].SetButtonPress(VRModuleRawButton.CapSenseGrip, AxisToPress(currState[i].GetButtonPress(VRModuleRawButton.CapSenseGrip), ctrlState.RHandTrigger, 0.55f, 0.45f)); - - currState[i].SetButtonTouch(VRModuleRawButton.ApplicationMenu, (ctrlState.Touches & (uint)OVRInput.RawTouch.B) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.A, (ctrlState.Touches & (uint)OVRInput.RawTouch.A) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.RThumbstick) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.Trigger, (ctrlState.Touches & (uint)OVRInput.RawTouch.RIndexTrigger) != 0u); - currState[i].SetButtonTouch(VRModuleRawButton.CapSenseGrip, AxisToPress(currState[i].GetButtonTouch(VRModuleRawButton.CapSenseGrip), ctrlState.RHandTrigger, 0.25f, 0.20f)); - - currState[i].SetAxisValue(VRModuleRawAxis.TouchpadX, ctrlState.RThumbstick.x); - currState[i].SetAxisValue(VRModuleRawAxis.TouchpadY, ctrlState.RThumbstick.y); - currState[i].SetAxisValue(VRModuleRawAxis.Trigger, ctrlState.RIndexTrigger); - currState[i].SetAxisValue(VRModuleRawAxis.CapSenseGrip, ctrlState.RHandTrigger); - break; - } - case VRModuleDeviceModel.OculusGoController: - case VRModuleDeviceModel.OculusGearVrController: - switch (node) + case VRModuleDeviceClass.HMD: + currState.deviceModel = VRModuleDeviceModel.OculusHMD; + break; + case VRModuleDeviceClass.TrackingReference: + currState.deviceModel = VRModuleDeviceModel.OculusSensor; + break; + case VRModuleDeviceClass.Controller: + switch (ovrProductName) { - case OVRPlugin.Node.HandLeft: - { - var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.LTrackedRemote); - - currState[i].SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.LTouchpad) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Back) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Trigger, (ctrlState.Buttons & (uint)(OVRInput.RawButton.A | OVRInput.RawButton.LIndexTrigger)) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadLeft, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadLeft) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadUp, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadUp) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadRight, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadRight) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadDown, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadDown) != 0u); - - currState[i].SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.LTouchpad) != 0u); - } + case "Oculus Go": + currState.deviceModel = VRModuleDeviceModel.OculusGoController; break; - case OVRPlugin.Node.HandRight: + case "Gear VR": + currState.deviceModel = VRModuleDeviceModel.OculusGearVrController; + break; + case "Oculus Rift": default: + switch (node) { - var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.RTrackedRemote); - - currState[i].SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & unchecked((uint)OVRInput.RawButton.RTouchpad)) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Back) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.Trigger, (ctrlState.Buttons & (uint)(OVRInput.RawButton.A | OVRInput.RawButton.RIndexTrigger)) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadLeft, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadLeft) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadUp, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadUp) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadRight, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadRight) != 0u); - currState[i].SetButtonPress(VRModuleRawButton.DPadDown, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadDown) != 0u); - - currState[i].SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & unchecked((uint)OVRInput.RawTouch.RTouchpad)) != 0u); + case OVRPlugin.Node.HandLeft: + currState.deviceModel = VRModuleDeviceModel.OculusTouchLeft; + break; + case OVRPlugin.Node.HandRight: + default: + currState.deviceModel = VRModuleDeviceModel.OculusTouchRight; + break; } break; } break; } } - else + + // update device pose + currState.pose = ToPose(OVRPlugin.GetNodePose(node, OVRPlugin.Step.Render)); + currState.velocity = OVRPlugin.GetNodeVelocity(node, OVRPlugin.Step.Render).FromFlippedZVector3f(); + currState.angularVelocity = OVRPlugin.GetNodeAngularVelocity(node, OVRPlugin.Step.Render).FromFlippedZVector3f(); + currState.isPoseValid = currState.pose != RigidPose.identity; + currState.isConnected = OVRPlugin.GetNodePresent(node); + + // update device input + switch (currState.deviceModel) { - if (prevState[i].isConnected) - { - currState[i].Reset(); - } + case VRModuleDeviceModel.OculusTouchLeft: + { + var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.LTouch); + + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Y) != 0u); + currState.SetButtonPress(VRModuleRawButton.A, (ctrlState.Buttons & (uint)OVRInput.RawButton.X) != 0u); + currState.SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.LThumbstick) != 0u); + currState.SetButtonPress(VRModuleRawButton.Trigger, AxisToPress(currState.GetButtonPress(VRModuleRawButton.Trigger), ctrlState.LIndexTrigger, 0.55f, 0.45f)); + currState.SetButtonPress(VRModuleRawButton.Grip, AxisToPress(currState.GetButtonPress(VRModuleRawButton.Grip), ctrlState.LHandTrigger, 0.55f, 0.45f)); + currState.SetButtonPress(VRModuleRawButton.CapSenseGrip, AxisToPress(currState.GetButtonPress(VRModuleRawButton.CapSenseGrip), ctrlState.LHandTrigger, 0.55f, 0.45f)); + + currState.SetButtonTouch(VRModuleRawButton.ApplicationMenu, (ctrlState.Touches & (uint)OVRInput.RawTouch.Y) != 0u); + currState.SetButtonTouch(VRModuleRawButton.A, (ctrlState.Touches & (uint)OVRInput.RawTouch.X) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.LThumbstick) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Trigger, (ctrlState.Touches & (uint)OVRInput.RawTouch.LIndexTrigger) != 0u); + currState.SetButtonTouch(VRModuleRawButton.CapSenseGrip, AxisToPress(currState.GetButtonTouch(VRModuleRawButton.CapSenseGrip), ctrlState.LHandTrigger, 0.25f, 0.20f)); + + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, ctrlState.LThumbstick.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, ctrlState.LThumbstick.y); + currState.SetAxisValue(VRModuleRawAxis.Trigger, ctrlState.LIndexTrigger); + currState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, ctrlState.LHandTrigger); + break; + } + case VRModuleDeviceModel.OculusTouchRight: + { + var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.RTouch); + + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.B) != 0u); + currState.SetButtonPress(VRModuleRawButton.A, (ctrlState.Buttons & (uint)OVRInput.RawButton.A) != 0u); + currState.SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.RThumbstick) != 0u); + currState.SetButtonPress(VRModuleRawButton.Trigger, AxisToPress(currState.GetButtonPress(VRModuleRawButton.Trigger), ctrlState.RIndexTrigger, 0.55f, 0.45f)); + currState.SetButtonPress(VRModuleRawButton.Grip, AxisToPress(currState.GetButtonPress(VRModuleRawButton.Grip), ctrlState.RHandTrigger, 0.55f, 0.45f)); + currState.SetButtonPress(VRModuleRawButton.CapSenseGrip, AxisToPress(currState.GetButtonPress(VRModuleRawButton.CapSenseGrip), ctrlState.RHandTrigger, 0.55f, 0.45f)); + + currState.SetButtonTouch(VRModuleRawButton.ApplicationMenu, (ctrlState.Touches & (uint)OVRInput.RawTouch.B) != 0u); + currState.SetButtonTouch(VRModuleRawButton.A, (ctrlState.Touches & (uint)OVRInput.RawTouch.A) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.RThumbstick) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Trigger, (ctrlState.Touches & (uint)OVRInput.RawTouch.RIndexTrigger) != 0u); + currState.SetButtonTouch(VRModuleRawButton.CapSenseGrip, AxisToPress(currState.GetButtonTouch(VRModuleRawButton.CapSenseGrip), ctrlState.RHandTrigger, 0.25f, 0.20f)); + + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, ctrlState.RThumbstick.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, ctrlState.RThumbstick.y); + currState.SetAxisValue(VRModuleRawAxis.Trigger, ctrlState.RIndexTrigger); + currState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, ctrlState.RHandTrigger); + break; + } + case VRModuleDeviceModel.OculusGoController: + case VRModuleDeviceModel.OculusGearVrController: + switch (node) + { + case OVRPlugin.Node.HandLeft: + { + var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.LTrackedRemote); + + currState.SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & (uint)OVRInput.RawButton.LTouchpad) != 0u); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Back) != 0u); + currState.SetButtonPress(VRModuleRawButton.Trigger, (ctrlState.Buttons & (uint)(OVRInput.RawButton.A | OVRInput.RawButton.LIndexTrigger)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadLeft, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadLeft) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadUp, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadUp) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadRight, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadRight) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadDown, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadDown) != 0u); + + currState.SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & (uint)OVRInput.RawTouch.LTouchpad) != 0u); + } + break; + case OVRPlugin.Node.HandRight: + default: + { + var ctrlState = OVRPlugin.GetControllerState((uint)OVRPlugin.Controller.RTrackedRemote); + + currState.SetButtonPress(VRModuleRawButton.Touchpad, (ctrlState.Buttons & unchecked((uint)OVRInput.RawButton.RTouchpad)) != 0u); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (ctrlState.Buttons & (uint)OVRInput.RawButton.Back) != 0u); + currState.SetButtonPress(VRModuleRawButton.Trigger, (ctrlState.Buttons & (uint)(OVRInput.RawButton.A | OVRInput.RawButton.RIndexTrigger)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadLeft, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadLeft) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadUp, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadUp) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadRight, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadRight) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadDown, (ctrlState.Buttons & (uint)OVRInput.RawButton.DpadDown) != 0u); + + currState.SetButtonTouch(VRModuleRawButton.Touchpad, (ctrlState.Touches & unchecked((uint)OVRInput.RawTouch.RTouchpad)) != 0u); + } + break; + } + break; } } + + ProcessConnectedDeviceChanged(); + ProcessDevicePoseChanged(); + ProcessDeviceInputChanged(); } #endif } diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SimulatorModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/SimulatorModule.cs index e828a92d..9a6fe549 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/SimulatorModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SimulatorModule.cs @@ -36,6 +36,8 @@ public sealed class SimulatorVRModule : VRModule.ModuleBase, ISimulatorVRModule private bool m_prevXREnabled; private bool m_resetDevices; private IMGUIHandle m_guiHandle; + private IVRModuleDeviceState[] m_prevStates; + private IVRModuleDeviceStateRW[] m_currStates; public event Action onActivated; public event Action onDeactivated; @@ -66,6 +68,14 @@ public override void OnActivated() m_guiHandle.simulator = this; } + m_prevStates = new IVRModuleDeviceState[SIMULATOR_MAX_DEVICE_COUNT]; + m_currStates = new IVRModuleDeviceStateRW[SIMULATOR_MAX_DEVICE_COUNT]; + EnsureDeviceStateLength(SIMULATOR_MAX_DEVICE_COUNT); + for (uint i = 0u; i < SIMULATOR_MAX_DEVICE_COUNT; ++i) + { + EnsureValidDeviceState(i, out m_prevStates[i], out m_currStates[i]); + } + if (onActivated != null) { onActivated(); @@ -106,7 +116,16 @@ public override void Update() } } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + public override void BeforeRenderUpdate() + { + FlushDeviceState(); + InternalUpdateDeviceState(m_prevStates, m_currStates); + ProcessConnectedDeviceChanged(); + ProcessDevicePoseChanged(); + ProcessDeviceInputChanged(); + } + + public void InternalUpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) { if (VIUSettings.enableSimulatorKeyboardMouseControl && hasControlFocus) { @@ -307,6 +326,7 @@ private void DeselectDevice() private bool m_resetAllKeyPressed; private bool m_escapeKeyPressed; private bool m_shiftKeyPressed; + private bool m_backQuotePressed; private bool[] m_alphaKeyDownState = new bool[10]; private void UpdateKeyDown() @@ -316,6 +336,7 @@ private void UpdateKeyDown() m_resetAllKeyPressed = Input.GetKeyDown(KeyCode.F3); m_escapeKeyPressed = Input.GetKeyDown(KeyCode.Escape); m_shiftKeyPressed = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); + m_backQuotePressed = Input.GetKey(KeyCode.BackQuote); m_alphaKeyDownState[0] = Input.GetKeyDown(KeyCode.Alpha0) || Input.GetKeyDown(KeyCode.Keypad0); m_alphaKeyDownState[1] = Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1); m_alphaKeyDownState[2] = Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2); @@ -333,27 +354,31 @@ private void UpdateKeyDown() private bool IsResetDevicesKeyDown() { return m_resetDevicesKeyPressed; } private bool IsEscapeKeyDown() { return m_escapeKeyPressed; } private bool IsShiftKeyPressed() { return m_shiftKeyPressed; } - private bool IsAlphaKeyDown(int num) { return m_alphaKeyDownState[num]; } private bool GetDeviceByInputDownKeyCode(IVRModuleDeviceStateRW[] deviceStates, out IVRModuleDeviceStateRW deviceState) { - var backQuotePressed = Input.GetKey(KeyCode.BackQuote); - if (!backQuotePressed && IsAlphaKeyDown(0)) { deviceState = deviceStates[0]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(1)) { deviceState = deviceStates[1]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(2)) { deviceState = deviceStates[2]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(3)) { deviceState = deviceStates[3]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(4)) { deviceState = deviceStates[4]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(5)) { deviceState = deviceStates[5]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(6)) { deviceState = deviceStates[6]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(7)) { deviceState = deviceStates[7]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(8)) { deviceState = deviceStates[8]; return true; } - if (!backQuotePressed && IsAlphaKeyDown(9)) { deviceState = deviceStates[9]; return true; } - if (backQuotePressed && IsAlphaKeyDown(0)) { deviceState = deviceStates[10]; return true; } - if (backQuotePressed && IsAlphaKeyDown(1)) { deviceState = deviceStates[11]; return true; } - if (backQuotePressed && IsAlphaKeyDown(2)) { deviceState = deviceStates[12]; return true; } - if (backQuotePressed && IsAlphaKeyDown(3)) { deviceState = deviceStates[13]; return true; } - if (backQuotePressed && IsAlphaKeyDown(4)) { deviceState = deviceStates[14]; return true; } - if (backQuotePressed && IsAlphaKeyDown(5)) { deviceState = deviceStates[15]; return true; } + if (!m_backQuotePressed) + { + if (m_alphaKeyDownState[0]) { deviceState = deviceStates[0]; return true; } + if (m_alphaKeyDownState[1]) { deviceState = deviceStates[1]; return true; } + if (m_alphaKeyDownState[2]) { deviceState = deviceStates[2]; return true; } + if (m_alphaKeyDownState[3]) { deviceState = deviceStates[3]; return true; } + if (m_alphaKeyDownState[4]) { deviceState = deviceStates[4]; return true; } + if (m_alphaKeyDownState[5]) { deviceState = deviceStates[5]; return true; } + if (m_alphaKeyDownState[6]) { deviceState = deviceStates[6]; return true; } + if (m_alphaKeyDownState[7]) { deviceState = deviceStates[7]; return true; } + if (m_alphaKeyDownState[8]) { deviceState = deviceStates[8]; return true; } + if (m_alphaKeyDownState[9]) { deviceState = deviceStates[9]; return true; } + } + else + { + if (m_alphaKeyDownState[0]) { deviceState = deviceStates[10]; return true; } + if (m_alphaKeyDownState[1]) { deviceState = deviceStates[11]; return true; } + if (m_alphaKeyDownState[2]) { deviceState = deviceStates[12]; return true; } + if (m_alphaKeyDownState[3]) { deviceState = deviceStates[13]; return true; } + if (m_alphaKeyDownState[4]) { deviceState = deviceStates[14]; return true; } + if (m_alphaKeyDownState[5]) { deviceState = deviceStates[15]; return true; } + } deviceState = null; return false; diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs index 88794766..1a074771 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRModule.cs @@ -15,16 +15,12 @@ namespace HTC.UnityPlugin.VRModuleManagement { - public sealed class SteamVRModule : VRModule.ModuleBase + public sealed partial class SteamVRModule : VRModule.ModuleBase { -#if VIU_STEAMVR +#if VIU_STEAMVR && !VIU_STEAMVR_2_0_0_OR_NEWER private static readonly uint s_sizeOfControllerStats = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t)); - private static readonly StringBuilder s_sb = new StringBuilder(); private ETrackingUniverseOrigin m_prevTrackingSpace; - private readonly TrackedDevicePose_t[] m_rawPoses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; - private readonly TrackedDevicePose_t[] m_rawGamePoses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; - private bool m_hasInputFocus = true; public override bool ShouldActiveModule() @@ -41,89 +37,268 @@ public override void OnActivated() // Make sure SteamVR_Render instance exist. It Polls New Poses Event if (SteamVR_Render.instance == null) { } - var compositor = OpenVR.Compositor; - if (compositor != null) - { - m_prevTrackingSpace = compositor.GetTrackingSpace(); - UpdateTrackingSpaceType(); - } + // setup tracking space + m_prevTrackingSpace = trackingSpace; + UpdateTrackingSpaceType(); + + EnsureDeviceStateLength(OpenVR.k_unMaxTrackedDeviceCount); + + m_hasInputFocus = inputFocus; #if VIU_STEAMVR_1_2_1_OR_NEWER + SteamVR_Events.NewPoses.AddListener(OnSteamVRNewPose); + SteamVR_Events.InputFocus.AddListener(OnInputFocus); SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).AddListener(OnTrackedDeviceRoleChanged); #elif VIU_STEAMVR_1_2_0_OR_NEWER + SteamVR_Events.NewPoses.AddListener(OnSteamVRNewPose); + SteamVR_Events.InputFocus.AddListener(OnInputFocus); SteamVR_Events.System("TrackedDeviceRoleChanged").AddListener(OnTrackedDeviceRoleChanged); -#else +#elif VIU_STEAMVR_1_1_1 + SteamVR_Utils.Event.Listen("new_poses", OnSteamVRNewPoseArgs); + SteamVR_Utils.Event.Listen("input_focus", OnInputFocusArgs); SteamVR_Utils.Event.Listen("TrackedDeviceRoleChanged", OnTrackedDeviceRoleChangedArgs); #endif } public override void OnDeactivated() { - var compositor = OpenVR.Compositor; - if (compositor != null) - { - compositor.SetTrackingSpace(m_prevTrackingSpace); - } + trackingSpace = m_prevTrackingSpace; + #if VIU_STEAMVR_1_2_1_OR_NEWER + SteamVR_Events.NewPoses.RemoveListener(OnSteamVRNewPose); + SteamVR_Events.InputFocus.RemoveListener(OnInputFocus); SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).RemoveListener(OnTrackedDeviceRoleChanged); #elif VIU_STEAMVR_1_2_0_OR_NEWER + SteamVR_Events.NewPoses.RemoveListener(OnSteamVRNewPose); + SteamVR_Events.InputFocus.RemoveListener(OnInputFocus); SteamVR_Events.System("TrackedDeviceRoleChanged").RemoveListener(OnTrackedDeviceRoleChanged); -#else +#elif VIU_STEAMVR_1_1_1 + SteamVR_Utils.Event.Remove("new_poses", OnSteamVRNewPoseArgs); + SteamVR_Utils.Event.Remove("input_focus", OnInputFocusArgs); SteamVR_Utils.Event.Remove("TrackedDeviceRoleChanged", OnTrackedDeviceRoleChangedArgs); #endif } - private static ETrackingUniverseOrigin GetTrackingUniverse() + public override void Update() { - switch (VRModule.trackingSpaceType) + if (SteamVR.active) { - case VRModuleTrackingSpaceType.RoomScale: - return ETrackingUniverseOrigin.TrackingUniverseStanding; - case VRModuleTrackingSpaceType.Stationary: - default: - return ETrackingUniverseOrigin.TrackingUniverseSeated; + SteamVR_Render.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; } + + UpdateDeviceInput(); + ProcessDeviceInputChanged(); } - public override void UpdateTrackingSpaceType() + private void UpdateConnectedDevice(TrackedDevicePose_t[] poses) { - var compositor = OpenVR.Compositor; - if (compositor != null) + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + var system = OpenVR.System; + + if (system == null) { - compositor.SetTrackingSpace(GetTrackingUniverse()); + for (uint i = 0, imax = GetDeviceStateLength(); i < imax; ++i) + { + if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected) + { + currState.Reset(); + } + } + + return; + } + + for (uint i = 0u, imax = (uint)poses.Length; i < imax; ++i) + { + if (!poses[i].bDeviceIsConnected) + { + if (TryGetValidDeviceState(i, out prevState, out currState) && prevState.isConnected) + { + currState.Reset(); + } + } + else + { + EnsureValidDeviceState(i, out prevState, out currState); + + if (!prevState.isConnected) + { + currState.isConnected = true; + currState.deviceClass = (VRModuleDeviceClass)system.GetTrackedDeviceClass(i); + currState.serialNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_SerialNumber_String); + currState.modelNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_ModelNumber_String); + currState.renderModelName = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_RenderModelName_String); + + SetupKnownDeviceModel(currState); + } + } } } - public override void Update() + private void UpdateDevicePose(TrackedDevicePose_t[] poses) { - if (SteamVR.active) + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + for (uint i = 0u, imax = (uint)poses.Length; i < imax; ++i) { -#if VIU_STEAMVR_2_0_0_OR_NEWER - SteamVR.settings.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; + if (!TryGetValidDeviceState(i, out prevState, out currState) || !currState.isConnected) { continue; } + + // update device status + currState.isPoseValid = poses[i].bPoseIsValid; + currState.isOutOfRange = poses[i].eTrackingResult == ETrackingResult.Running_OutOfRange || poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; + currState.isCalibrating = poses[i].eTrackingResult == ETrackingResult.Calibrating_InProgress || poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; + currState.isUninitialized = poses[i].eTrackingResult == ETrackingResult.Uninitialized; + currState.velocity = new Vector3(poses[i].vVelocity.v0, poses[i].vVelocity.v1, -poses[i].vVelocity.v2); + currState.angularVelocity = new Vector3(-poses[i].vAngularVelocity.v0, -poses[i].vAngularVelocity.v1, poses[i].vAngularVelocity.v2); + + // update poses + if (poses[i].bPoseIsValid) + { + var rigidTransform = new SteamVR_Utils.RigidTransform(poses[i].mDeviceToAbsoluteTracking); + currState.position = rigidTransform.pos; + currState.rotation = rigidTransform.rot; + } + else if (prevState.isPoseValid) + { + currState.pose = RigidPose.identity; + } + } + } + + private void UpdateDeviceInput() + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + VRControllerState_t ctrlState; + var system = OpenVR.System; + + for (uint i = 0; i < OpenVR.k_unMaxTrackedDeviceCount; ++i) + { + if (!TryGetValidDeviceState(i, out prevState, out currState) || !currState.isConnected) { continue; } + + // get device state from openvr api + GetConrollerState(system, i, out ctrlState); + + // update device input button + currState.buttonPressed = ctrlState.ulButtonPressed; + currState.buttonTouched = ctrlState.ulButtonTouched; + + // update device input axis + currState.SetAxisValue(VRModuleRawAxis.Axis0X, ctrlState.rAxis0.x); + currState.SetAxisValue(VRModuleRawAxis.Axis0Y, ctrlState.rAxis0.y); + currState.SetAxisValue(VRModuleRawAxis.Axis1X, ctrlState.rAxis1.x); + currState.SetAxisValue(VRModuleRawAxis.Axis1Y, ctrlState.rAxis1.y); + currState.SetAxisValue(VRModuleRawAxis.Axis2X, ctrlState.rAxis2.x); + currState.SetAxisValue(VRModuleRawAxis.Axis2Y, ctrlState.rAxis2.y); + currState.SetAxisValue(VRModuleRawAxis.Axis3X, ctrlState.rAxis3.x); + currState.SetAxisValue(VRModuleRawAxis.Axis3Y, ctrlState.rAxis3.y); + currState.SetAxisValue(VRModuleRawAxis.Axis4X, ctrlState.rAxis4.x); + currState.SetAxisValue(VRModuleRawAxis.Axis4Y, ctrlState.rAxis4.y); + } + } + + private void UpdateInputFocusState() + { + if (ChangeProp.Set(ref m_hasInputFocus, inputFocus)) + { + InvokeInputFocusEvent(m_hasInputFocus); + } + } + + private static ETrackingUniverseOrigin trackingSpace + { + get + { + var compositor = OpenVR.Compositor; + if (compositor == null) { return default(ETrackingUniverseOrigin); } + + return compositor.GetTrackingSpace(); + } + set + { + var compositor = OpenVR.Compositor; + if (compositor == null) { return; } + + compositor.SetTrackingSpace(value); + } + } + + private static bool inputFocus + { + get + { + var system = OpenVR.System; + if (system == null) { return false; } + +#if VIU_STEAMVR_1_2_3_OR_NEWER + return system.IsInputAvailable(); #else - SteamVR_Render.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; + return !system.IsInputFocusCapturedByAnotherProcess(); #endif } } - public override bool HasInputFocus() + public override void UpdateTrackingSpaceType() { - return m_hasInputFocus; + switch (VRModule.trackingSpaceType) + { + case VRModuleTrackingSpaceType.RoomScale: + trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding; + break; + case VRModuleTrackingSpaceType.Stationary: + trackingSpace = ETrackingUniverseOrigin.TrackingUniverseSeated; + break; + } } -#if VIU_STEAMVR_1_1_1 - private void OnTrackedDeviceRoleChangedArgs(params object[] args) { OnTrackedDeviceRoleChanged((VREvent_t)args[0]); } + + private static void GetConrollerState(CVRSystem system, uint index, out VRControllerState_t ctrlState) + { + ctrlState = default(VRControllerState_t); + + if (system != null) + { +#if VIU_STEAMVR_1_2_0_OR_NEWER + system.GetControllerState(index, ref ctrlState, s_sizeOfControllerStats); +#else + system.GetControllerState(index, ref ctrlState); #endif + } + } + + private void OnSteamVRNewPoseArgs(params object[] args) { OnSteamVRNewPose((TrackedDevicePose_t[])args[0]); } + private void OnSteamVRNewPose(TrackedDevicePose_t[] poses) + { + FlushDeviceState(); + + UpdateConnectedDevice(poses); + ProcessConnectedDeviceChanged(); + + UpdateDevicePose(poses); + ProcessDevicePoseChanged(); + + UpdateInputFocusState(); + } + + private void OnInputFocusArgs(params object[] args) { OnInputFocus((bool)args[0]); } private void OnInputFocus(bool value) { m_hasInputFocus = value; InvokeInputFocusEvent(value); } + private void OnTrackedDeviceRoleChangedArgs(params object[] args) { OnTrackedDeviceRoleChanged((VREvent_t)args[0]); } private void OnTrackedDeviceRoleChanged(VREvent_t arg) { InvokeControllerRoleChangedEvent(); } + public override bool HasInputFocus() + { + return m_hasInputFocus; + } + public override uint GetLeftControllerDeviceIndex() { var system = OpenVR.System; @@ -145,117 +320,21 @@ public override void TriggerViveControllerHaptic(uint deviceIndex, ushort durati } } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) - { - var system = OpenVR.System; - var compositor = OpenVR.Compositor; - -#if VIU_STEAMVR_1_2_3_OR_NEWER - m_hasInputFocus = system == null ? false : system.IsInputAvailable(); -#else - m_hasInputFocus = system == null ? false : !system.IsInputFocusCapturedByAnotherProcess(); -#endif - - if (compositor != null) - { - compositor.GetLastPoses(m_rawPoses, m_rawGamePoses); - } - else - { - for (uint i = 0; i < MAX_DEVICE_COUNT; ++i) - { - if (prevState[i].isConnected) { currState[i].Reset(); } - } - return; - } - - for (uint i = 0; i < MAX_DEVICE_COUNT && i < OpenVR.k_unMaxTrackedDeviceCount; ++i) - { - currState[i].isConnected = m_rawPoses[i].bDeviceIsConnected; - - if (currState[i].isConnected) - { - if (!prevState[i].isConnected) - { - currState[i].deviceClass = (VRModuleDeviceClass)system.GetTrackedDeviceClass(i); - currState[i].serialNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_SerialNumber_String); - currState[i].modelNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_ModelNumber_String); - currState[i].renderModelName = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_RenderModelName_String); - - SetupKnownDeviceModel(currState[i]); - } - - // update device status - currState[i].isPoseValid = m_rawPoses[i].bPoseIsValid; - currState[i].isOutOfRange = m_rawPoses[i].eTrackingResult == ETrackingResult.Running_OutOfRange || m_rawPoses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; - currState[i].isCalibrating = m_rawPoses[i].eTrackingResult == ETrackingResult.Calibrating_InProgress || m_rawPoses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; - currState[i].isUninitialized = m_rawPoses[i].eTrackingResult == ETrackingResult.Uninitialized; - currState[i].velocity = new Vector3(m_rawPoses[i].vVelocity.v0, m_rawPoses[i].vVelocity.v1, -m_rawPoses[i].vVelocity.v2); - currState[i].angularVelocity = new Vector3(-m_rawPoses[i].vAngularVelocity.v0, -m_rawPoses[i].vAngularVelocity.v1, m_rawPoses[i].vAngularVelocity.v2); - - // update poses - if (prevState[i].isPoseValid && !currState[i].isPoseValid) - { - currState[i].pose = RigidPose.identity; - } - else if (currState[i].isPoseValid) - { - var rigidTransform = new SteamVR_Utils.RigidTransform(m_rawPoses[i].mDeviceToAbsoluteTracking); - currState[i].position = rigidTransform.pos; - currState[i].rotation = rigidTransform.rot; - } - - if (currState[i].deviceClass == VRModuleDeviceClass.Controller || currState[i].deviceClass == VRModuleDeviceClass.GenericTracker) - { - // get device state from openvr api - var ctrlState = default(VRControllerState_t); - if (system != null) - { -#if VIU_STEAMVR_1_2_0_OR_NEWER - system.GetControllerState(i, ref ctrlState, s_sizeOfControllerStats); -#else - system.GetControllerState(i, ref ctrlState); -#endif - } - - // update device input button - currState[i].buttonPressed = ctrlState.ulButtonPressed; - currState[i].buttonTouched = ctrlState.ulButtonTouched; - - // update device input axis - currState[i].SetAxisValue(VRModuleRawAxis.Axis0X, ctrlState.rAxis0.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis0Y, ctrlState.rAxis0.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis1X, ctrlState.rAxis1.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis1Y, ctrlState.rAxis1.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis2X, ctrlState.rAxis2.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis2Y, ctrlState.rAxis2.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis3X, ctrlState.rAxis3.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis3Y, ctrlState.rAxis3.y); - currState[i].SetAxisValue(VRModuleRawAxis.Axis4X, ctrlState.rAxis4.x); - currState[i].SetAxisValue(VRModuleRawAxis.Axis4Y, ctrlState.rAxis4.y); - } - } - else - { - if (prevState[i].isConnected) - { - currState[i].Reset(); - } - } - } - } - - private static string QueryDeviceStringProperty(CVRSystem system, uint deviceIndex, ETrackedDeviceProperty prop) + private StringBuilder m_sb; + private string QueryDeviceStringProperty(CVRSystem system, uint deviceIndex, ETrackedDeviceProperty prop) { var error = default(ETrackedPropertyError); var capacity = (int)system.GetStringTrackedDeviceProperty(deviceIndex, prop, null, 0, ref error); if (capacity <= 1 || capacity > 128) { return string.Empty; } - system.GetStringTrackedDeviceProperty(deviceIndex, prop, s_sb, (uint)s_sb.EnsureCapacity(capacity), ref error); + if (m_sb == null) { m_sb = new StringBuilder(capacity); } + else { m_sb.EnsureCapacity(capacity); } + + system.GetStringTrackedDeviceProperty(deviceIndex, prop, m_sb, (uint)m_sb.Capacity, ref error); if (error != ETrackedPropertyError.TrackedProp_Success) { return string.Empty; } - var result = s_sb.ToString(); - s_sb.Length = 0; + var result = m_sb.ToString(); + m_sb.Length = 0; return result; } diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs new file mode 100644 index 00000000..83c282d4 --- /dev/null +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs @@ -0,0 +1,666 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +#if VIU_STEAMVR +using HTC.UnityPlugin.Utility; +using HTC.UnityPlugin.Vive; +using System.Text; +using UnityEngine; +using Valve.VR; +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Collections; +#if UNITY_2017_2_OR_NEWER +using UnityEngine.XR; +#elif UNITY_5_4_OR_NEWER +using XRSettings = UnityEngine.VR.VRSettings; +#endif +#endif + +namespace HTC.UnityPlugin.VRModuleManagement +{ + public sealed partial class SteamVRModule : VRModule.ModuleBase + { +#if VIU_STEAMVR_2_0_0_OR_NEWER + public class ActionArray where T : struct + { + private static readonly EnumUtils.EnumDisplayInfo s_enumInfo; + private static readonly T[] s_enums; + private static readonly ulong[] s_actionOrigins; + public static readonly int Len; + + private string m_pathPrefix; + private string m_dataType; + private string[] m_aliases; + private string[] m_paths; + private ulong[] m_handles; + + private int m_iterator = -1; + private int m_originIterator = -1; + + static ActionArray() + { + s_enumInfo = EnumUtils.GetDisplayInfo(typeof(T)); + Len = s_enumInfo.maxValue - s_enumInfo.minValue + 1; + + var ints = new int[Len]; + for (int i = 0; i < Len; ++i) + { + ints[i] = s_enumInfo.minValue + i; + } + + s_enums = ints as T[]; + + s_actionOrigins = new ulong[OpenVR.k_unMaxActionOriginCount]; + } + + public ActionArray(string pathPrefix, string dataType) + { + m_pathPrefix = pathPrefix; + m_dataType = dataType; + + m_aliases = new string[Len]; + m_paths = new string[Len]; + m_handles = new ulong[Len]; + + } + + public string DataType { get { return m_dataType; } } + public T Current { get { return s_enums[m_iterator]; } } + public string CurrentAlias { get { return m_aliases[m_iterator]; } } + public string CurrentPath { get { return m_paths[m_iterator]; } } + public ulong CurrentHandle { get { return m_handles[m_iterator]; } } + public void MoveNext() { ++m_iterator; } + public bool IsCurrentValid() { return m_iterator >= 0 && m_iterator < Len; } + public void Reset() { m_iterator = 0; } + + public ulong CurrentOrigin { get { return s_actionOrigins[m_originIterator]; } } + public void MoveNextOrigin() { ++m_originIterator; } + public bool IsCurrentOriginValid() { return m_originIterator >= 0 && m_originIterator < s_actionOrigins.Length && s_actionOrigins[m_originIterator] != OpenVR.k_ulInvalidInputValueHandle; } + public void ResetOrigins(CVRInput vrInput) + { + if (CurrentHandle == OpenVR.k_ulInvalidActionHandle) + { + m_originIterator = -1; + return; + } + + m_originIterator = 0; + var error = vrInput.GetActionOrigins(s_actionSetHandle, CurrentHandle, s_actionOrigins); + if (error != EVRInputError.None) + { + Debug.LogError("GetActionOrigins failed! action=" + CurrentPath + " error=" + error); + } + } + + public bool TryGetCurrentDigitalData(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, ref InputDigitalActionData_t data) + { + ulong originDevicePath; + if (!TryGetCurrentOriginDataAndDeviceState(vrInput, out prevState, out currState, out originDevicePath)) { return false; } + + var error = vrInput.GetDigitalActionData(CurrentHandle, ref data, s_moduleInstance.m_digitalDataSize, originDevicePath); + if (error != EVRInputError.None) + { + Debug.LogError("GetDigitalActionData failed! action=" + CurrentPath + " error=" + error); + return false; + } + + return true; + } + + public bool TryGetCurrentAnalogData(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, ref InputAnalogActionData_t data) + { + ulong originDevicePath; + if (!TryGetCurrentOriginDataAndDeviceState(vrInput, out prevState, out currState, out originDevicePath)) { return false; } + + var error = vrInput.GetAnalogActionData(CurrentHandle, ref data, s_moduleInstance.m_analogDataSize, originDevicePath); + if (error != EVRInputError.None) + { + Debug.LogError("GetAnalogActionData failed! action=" + CurrentPath + " error=" + error); + return false; + } + + return true; + } + + private bool TryGetCurrentOriginDataAndDeviceState(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, out ulong originDevicePath) + { + OriginData originData; + EVRInputError error; + if (!s_moduleInstance.TryGetDeviceIndexFromOrigin(vrInput, CurrentOrigin, out originData, out error)) + { + Debug.Log("GetOriginTrackedDeviceInfo failed! error=" + error + " action=" + pressActions.CurrentPath); + prevState = null; + currState = null; + originDevicePath = 0ul; + return false; + } + + originDevicePath = originData.devicePath; + return s_moduleInstance.TryGetValidDeviceState(originData.deviceIndex, out prevState, out currState) && currState.isConnected; + } + + public void Set(T e, string pathName, string alias) + { + var index = EqualityComparer.Default.GetHashCode(e) - s_enumInfo.minValue; + m_aliases[index] = alias; + m_paths[index] = ACTION_SET_NAME + m_pathPrefix + pathName; + } + + public void InitiateHandles(CVRInput vrInput) + { + for (int i = 0; i < Len; ++i) + { + m_handles[i] = SafeGetActionHandle(vrInput, m_paths[i]); + } + } + } + + public const string ACTION_SET_NAME = "/actions/htc_viu"; + + private static SteamVRModule s_moduleInstance; + + private static bool s_pathInitialized; + private static bool s_actionInitialized; + + public static ActionArray pressActions { get; private set; } + public static ActionArray touchActions { get; private set; } + public static ActionArray v1Actions { get; private set; } + public static ActionArray v2Actions { get; private set; } + + private static ulong[] s_devicePathHandles; + private static ulong s_actionSetHandle; + + private uint m_digitalDataSize; + private uint m_analogDataSize; + private uint m_originInfoSize; + private uint m_activeActionSetSize; + + private ETrackingUniverseOrigin m_prevTrackingSpace; + private bool m_hasInputFocus = true; + private TrackedDevicePose_t[] m_poses; + private TrackedDevicePose_t[] m_gamePoses; + private VRActiveActionSet_t[] m_activeActionSets; + + private struct OriginData + { + public ulong devicePath; + public uint deviceIndex; + } + + private Dictionary m_originDataCache; + + private static ETrackingUniverseOrigin trackingSpace + { + get + { + var compositor = OpenVR.Compositor; + if (compositor == null) { return default(ETrackingUniverseOrigin); } + + return compositor.GetTrackingSpace(); + } + set + { + var compositor = OpenVR.Compositor; + if (compositor == null) { return; } + + compositor.SetTrackingSpace(value); + } + } + + private static bool inputFocus + { + get + { + var system = OpenVR.System; + if (system == null) { return false; } + return system.IsInputAvailable(); + } + } + + public static void InitializePaths() + { + if (s_pathInitialized) { return; } + s_pathInitialized = true; + + pressActions = new ActionArray("/in/viu_press_", "boolean"); + pressActions.Set(VRModuleRawButton.System, "00", "Press00 (System)"); + pressActions.Set(VRModuleRawButton.ApplicationMenu, "01", "Press01 (ApplicationMenu)"); + pressActions.Set(VRModuleRawButton.Grip, "02", "Press02 (Grip)"); + pressActions.Set(VRModuleRawButton.DPadLeft, "03", "Press03 (DPadLeft)"); + pressActions.Set(VRModuleRawButton.DPadUp, "04", "Press04 (DPadUp)"); + pressActions.Set(VRModuleRawButton.DPadRight, "05", "Press05 (DPadRight)"); + pressActions.Set(VRModuleRawButton.DPadDown, "06", "Press06 (DPadDown)"); + pressActions.Set(VRModuleRawButton.A, "07", "Press07 (A)"); + pressActions.Set(VRModuleRawButton.ProximitySensor, "31", "Press31 (ProximitySensor)"); + pressActions.Set(VRModuleRawButton.Touchpad, "32", "Press32 (Touchpad)"); + pressActions.Set(VRModuleRawButton.Trigger, "33", "Press33 (Trigger)"); + pressActions.Set(VRModuleRawButton.CapSenseGrip, "34", "Press34 (CapSenseGrip)"); + + touchActions = new ActionArray("/in/viu_touch_", "boolean"); + touchActions.Set(VRModuleRawButton.System, "00", "Touch00 (System)"); + touchActions.Set(VRModuleRawButton.ApplicationMenu, "01", "Touch01 (ApplicationMenu)"); + touchActions.Set(VRModuleRawButton.Grip, "02", "Touch02 (Grip)"); + touchActions.Set(VRModuleRawButton.DPadLeft, "03", "Touch03 (DPadLeft)"); + touchActions.Set(VRModuleRawButton.DPadUp, "04", "Touch04 (DPadUp)"); + touchActions.Set(VRModuleRawButton.DPadRight, "05", "Touch05 (DPadRight)"); + touchActions.Set(VRModuleRawButton.DPadDown, "06", "Touch06 (DPadDown)"); + touchActions.Set(VRModuleRawButton.A, "07", "Touch07 (A)"); + touchActions.Set(VRModuleRawButton.ProximitySensor, "31", "Touch31 (ProximitySensor)"); + touchActions.Set(VRModuleRawButton.Touchpad, "32", "Touch32 (Touchpad)"); + touchActions.Set(VRModuleRawButton.Trigger, "33", "Touch33 (Trigger)"); + touchActions.Set(VRModuleRawButton.CapSenseGrip, "34", "Touch34 (CapSenseGrip)"); + + v1Actions = new ActionArray("/in/viu_axis_", "vector1"); + v1Actions.Set(VRModuleRawAxis.Axis0X, "0x", "Axis0 X (TouchpadX)"); + v1Actions.Set(VRModuleRawAxis.Axis0Y, "0y", "Axis0 Y (TouchpadY)"); + v1Actions.Set(VRModuleRawAxis.Axis1X, "1x", "Axis1 X (Trigger)"); + v1Actions.Set(VRModuleRawAxis.Axis1Y, "1y", "Axis1 Y"); + v1Actions.Set(VRModuleRawAxis.Axis2X, "2x", "Axis2 X (CapSenseGrip)"); + v1Actions.Set(VRModuleRawAxis.Axis2Y, "2y", "Axis2 Y"); + v1Actions.Set(VRModuleRawAxis.Axis3X, "3x", "Axis3 X (IndexCurl)"); + v1Actions.Set(VRModuleRawAxis.Axis3Y, "3y", "Axis3 Y (MiddleCurl)"); + v1Actions.Set(VRModuleRawAxis.Axis4X, "4x", "Axis4 X (RingCurl)"); + v1Actions.Set(VRModuleRawAxis.Axis4Y, "4y", "Axis4 Y (PinkyCurl)"); + + v2Actions = new ActionArray("/in/viu_axis_", "vector2"); + v2Actions.Set(VRModuleRawAxis.Axis0X, "0xy", "Axis0 X&Y (Touchpad)"); + v2Actions.Set(VRModuleRawAxis.Axis1X, "1xy", "Axis1 X&Y"); + v2Actions.Set(VRModuleRawAxis.Axis2X, "2xy", "Axis2 X&Y (Thumbstick)"); + v2Actions.Set(VRModuleRawAxis.Axis3X, "3xy", "Axis3 X&Y"); + v2Actions.Set(VRModuleRawAxis.Axis4X, "4xy", "Axis4 X&Y"); + } + + public static void InitializeHandles() + { + if (!Application.isPlaying || s_actionInitialized) { return; } + s_actionInitialized = true; + + InitializePaths(); + + SteamVR.Initialize(); +#if VIU_STEAMVR_2_1_0_OR_NEWER + SteamVR_ActionSet_Manager.UpdateActionSetsState(); +#else + SteamVR_ActionSet.UpdateActionSetsState(); +#endif + + var vrInput = OpenVR.Input; + if (vrInput == null) + { + Debug.LogError("Fail loading OpenVR.Input"); + return; + } + + pressActions.InitiateHandles(vrInput); + touchActions.InitiateHandles(vrInput); + v1Actions.InitiateHandles(vrInput); + v2Actions.InitiateHandles(vrInput); + + s_actionSetHandle = SafeGetActionSetHandle(vrInput, ACTION_SET_NAME); + } + + private static ulong SafeGetActionSetHandle(CVRInput vrInput, string path) + { + if (string.IsNullOrEmpty(path)) { return 0ul; } + + var handle = OpenVR.k_ulInvalidActionHandle; + var error = vrInput.GetActionSetHandle(path, ref handle); + if (error != EVRInputError.None) + { + Debug.LogError("Load " + path + " action failed! error=" + error); + return OpenVR.k_ulInvalidActionHandle; + } + else + { + return handle; + } + } + + private static ulong SafeGetActionHandle(CVRInput vrInput, string path) + { + if (string.IsNullOrEmpty(path)) { return 0ul; } + + var handle = OpenVR.k_ulInvalidActionHandle; + var error = vrInput.GetActionHandle(path, ref handle); + if (error != EVRInputError.None) + { + Debug.LogError("Load " + path + " action failed! error=" + error); + return OpenVR.k_ulInvalidActionHandle; + } + else + { + return handle; + } + } + + public static ulong GetInputSrouceHandleForDevice(uint deviceIndex) + { + if (s_devicePathHandles == null || deviceIndex >= s_devicePathHandles.Length) + { + return OpenVR.k_ulInvalidInputValueHandle; + } + else + { + return s_devicePathHandles[deviceIndex]; + } + } + + public override bool ShouldActiveModule() + { +#if UNITY_5_4_OR_NEWER + return VIUSettings.activateSteamVRModule && XRSettings.enabled && XRSettings.loadedDeviceName == "OpenVR"; +#else + return VIUSettings.activateSteamVRModule && SteamVR.enabled; +#endif + } + + public override void OnActivated() + { + m_digitalDataSize = (uint)Marshal.SizeOf(new InputDigitalActionData_t()); + m_analogDataSize = (uint)Marshal.SizeOf(new InputAnalogActionData_t()); + m_originInfoSize = (uint)Marshal.SizeOf(new InputOriginInfo_t()); + m_activeActionSetSize = (uint)Marshal.SizeOf(new VRActiveActionSet_t()); + + + m_poses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; + m_gamePoses = new TrackedDevicePose_t[0]; + m_originDataCache = new Dictionary((int)OpenVR.k_unMaxActionOriginCount); + + InitializeHandles(); + + m_activeActionSets = new VRActiveActionSet_t[1] { new VRActiveActionSet_t() { ulActionSet = s_actionSetHandle, } }; + + SteamVR_Input.OnNonVisualActionsUpdated += UpdateDeviceInput; + SteamVR_Input.OnPosesUpdated += UpdateDevicePose; + + s_devicePathHandles = new ulong[OpenVR.k_unMaxTrackedDeviceCount]; + EnsureDeviceStateLength(OpenVR.k_unMaxTrackedDeviceCount); + + // preserve previous tracking space + m_prevTrackingSpace = trackingSpace; + + m_hasInputFocus = inputFocus; + + SteamVR_Events.InputFocus.AddListener(OnInputFocus); + SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).AddListener(OnTrackedDeviceRoleChanged); + + s_moduleInstance = this; + } + + public override void OnDeactivated() + { + SteamVR_Events.InputFocus.RemoveListener(OnInputFocus); + SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).RemoveListener(OnTrackedDeviceRoleChanged); + + SteamVR_Input.OnNonVisualActionsUpdated -= UpdateDeviceInput; + SteamVR_Input.OnPosesUpdated -= UpdateDevicePose; + + trackingSpace = m_prevTrackingSpace; + + s_moduleInstance = null; + } + + private void UpdateDeviceInput() + { + EVRInputError error; + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + var vrInput = OpenVR.Input; + if (vrInput == null) + { + for (uint i = 0, iMax = GetDeviceStateLength(); i < iMax; ++i) + { + if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected) + { + currState.buttonPressed = 0ul; + currState.buttonTouched = 0ul; + currState.ResetAxisValues(); + } + } + } + else + { + // FIXME: Should update by SteamVR_Input? SteamVR_Input.GetActionSetFromPath(ACTIONSET_PATH).ActivatePrimary(); + error = vrInput.UpdateActionState(m_activeActionSets, m_activeActionSetSize); + if (error != EVRInputError.None) + { + Debug.LogError("UpdateActionState failed! " + ACTION_SET_NAME + " error=" + error); + } + + for (pressActions.Reset(); pressActions.IsCurrentValid(); pressActions.MoveNext()) + { + for (pressActions.ResetOrigins(vrInput); pressActions.IsCurrentOriginValid(); pressActions.MoveNextOrigin()) + { + var data = default(InputDigitalActionData_t); + if (pressActions.TryGetCurrentDigitalData(vrInput, out prevState, out currState, ref data)) + { + currState.SetButtonPress(pressActions.Current, data.bState); + } + } + } + + for (touchActions.Reset(); touchActions.IsCurrentValid(); touchActions.MoveNext()) + { + for (touchActions.ResetOrigins(vrInput); touchActions.IsCurrentOriginValid(); touchActions.MoveNextOrigin()) + { + var data = default(InputDigitalActionData_t); + if (touchActions.TryGetCurrentDigitalData(vrInput, out prevState, out currState, ref data)) + { + currState.SetButtonTouch(touchActions.Current, data.bState); + } + } + } + + for (v1Actions.Reset(); v1Actions.IsCurrentValid(); v1Actions.MoveNext()) + { + for (v1Actions.ResetOrigins(vrInput); v1Actions.IsCurrentOriginValid(); v1Actions.MoveNextOrigin()) + { + var data = default(InputAnalogActionData_t); + if (v1Actions.TryGetCurrentAnalogData(vrInput, out prevState, out currState, ref data)) + { + currState.SetAxisValue(v1Actions.Current, data.x); + } + } + } + + for (v2Actions.Reset(); v2Actions.IsCurrentValid(); v2Actions.MoveNext()) + { + for (v2Actions.ResetOrigins(vrInput); v2Actions.IsCurrentOriginValid(); v2Actions.MoveNextOrigin()) + { + var data = default(InputAnalogActionData_t); + if (v2Actions.TryGetCurrentAnalogData(vrInput, out prevState, out currState, ref data)) + { + currState.SetAxisValue(v2Actions.Current, data.x); + currState.SetAxisValue(v2Actions.Current + 1, data.y); + } + } + } + } + + ProcessDeviceInputChanged(); + } + + private void UpdateDevicePose(bool obj) + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + FlushDeviceState(); + + var vrSystem = OpenVR.System; + var vrCompositor = OpenVR.Compositor; + if (vrSystem == null || vrCompositor == null) + { + for (uint i = 0, imax = GetDeviceStateLength(); i < imax; ++i) + { + if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected) + { + currState.Reset(); + } + } + + return; + } + + vrCompositor.GetLastPoses(m_poses, m_gamePoses); + + for (uint i = 0u, imax = (uint)m_poses.Length; i < imax; ++i) + { + if (!m_poses[i].bDeviceIsConnected) + { + if (TryGetValidDeviceState(i, out prevState, out currState) && prevState.isConnected) + { + s_devicePathHandles[i] = OpenVR.k_ulInvalidInputValueHandle; + currState.Reset(); + } + } + else + { + EnsureValidDeviceState(i, out prevState, out currState); + + if (!prevState.isConnected) + { + currState.isConnected = true; + currState.deviceClass = (VRModuleDeviceClass)vrSystem.GetTrackedDeviceClass(i); + currState.serialNumber = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_SerialNumber_String); + currState.modelNumber = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_ModelNumber_String); + currState.renderModelName = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_RenderModelName_String); + + SetupKnownDeviceModel(currState); + + m_originDataCache.Clear(); + } + + // update device status + currState.isPoseValid = m_poses[i].bPoseIsValid; + currState.isOutOfRange = m_poses[i].eTrackingResult == ETrackingResult.Running_OutOfRange || m_poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; + currState.isCalibrating = m_poses[i].eTrackingResult == ETrackingResult.Calibrating_InProgress || m_poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange; + currState.isUninitialized = m_poses[i].eTrackingResult == ETrackingResult.Uninitialized; + currState.velocity = new Vector3(m_poses[i].vVelocity.v0, m_poses[i].vVelocity.v1, -m_poses[i].vVelocity.v2); + currState.angularVelocity = new Vector3(-m_poses[i].vAngularVelocity.v0, -m_poses[i].vAngularVelocity.v1, m_poses[i].vAngularVelocity.v2); + + var rigidTransform = new SteamVR_Utils.RigidTransform(m_poses[i].mDeviceToAbsoluteTracking); + currState.position = rigidTransform.pos; + currState.rotation = rigidTransform.rot; + } + } + + ProcessConnectedDeviceChanged(); + ProcessDevicePoseChanged(); + } + + public override void Update() + { + if (SteamVR.active) + { + SteamVR_Settings.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency; + } + } + + public override void UpdateTrackingSpaceType() + { + switch (VRModule.trackingSpaceType) + { + case VRModuleTrackingSpaceType.RoomScale: + trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding; + break; + case VRModuleTrackingSpaceType.Stationary: + trackingSpace = ETrackingUniverseOrigin.TrackingUniverseSeated; + break; + } + } + + private bool TryGetDeviceIndexFromOrigin(CVRInput vrInput, ulong origin, out OriginData originData, out EVRInputError error) + { + if (!m_originDataCache.TryGetValue(origin, out originData)) + { + var originInfo = default(InputOriginInfo_t); + error = vrInput.GetOriginTrackedDeviceInfo(origin, ref originInfo, m_originInfoSize); + if (error != EVRInputError.None) + { + originData = new OriginData() + { + devicePath = OpenVR.k_ulInvalidInputValueHandle, + deviceIndex = OpenVR.k_unTrackedDeviceIndexInvalid, + }; + return false; + } + else + { + originData = new OriginData() + { + devicePath = originInfo.devicePath, + deviceIndex = originInfo.trackedDeviceIndex, + }; + + s_devicePathHandles[originInfo.trackedDeviceIndex] = originInfo.devicePath; + //Debug.Log("Set device path " + originInfo.trackedDeviceIndex + " to " + originInfo.devicePath); + m_originDataCache.Add(origin, originData); + return true; + } + } + else + { + error = EVRInputError.None; + return true; + } + } + + private void OnInputFocus(bool value) + { + m_hasInputFocus = value; + InvokeInputFocusEvent(value); + } + + public override bool HasInputFocus() { return m_hasInputFocus; } + + private void OnTrackedDeviceRoleChanged(VREvent_t arg) + { + InvokeControllerRoleChangedEvent(); + m_originDataCache.Clear(); + } + + public override uint GetLeftControllerDeviceIndex() + { + var system = OpenVR.System; + return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); + } + + public override uint GetRightControllerDeviceIndex() + { + var system = OpenVR.System; + return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); + } + + private StringBuilder m_sb; + private string QueryDeviceStringProperty(CVRSystem system, uint deviceIndex, ETrackedDeviceProperty prop) + { + var error = default(ETrackedPropertyError); + var capacity = (int)system.GetStringTrackedDeviceProperty(deviceIndex, prop, null, 0, ref error); + if (capacity <= 1 || capacity > 128) { return string.Empty; } + + if (m_sb == null) { m_sb = new StringBuilder(capacity); } + else { m_sb.EnsureCapacity(capacity); } + + system.GetStringTrackedDeviceProperty(deviceIndex, prop, m_sb, (uint)m_sb.Capacity, ref error); + if (error != ETrackedPropertyError.TrackedProp_Success) { return string.Empty; } + + var result = m_sb.ToString(); + m_sb.Length = 0; + + return result; + } + + public override void TriggerViveControllerHaptic(uint deviceIndex, ushort durationMicroSec = 500) + { + var system = OpenVR.System; + if (system != null) + { + system.TriggerHapticPulse(deviceIndex, (uint)EVRButtonId.k_EButton_SteamVR_Touchpad - (uint)EVRButtonId.k_EButton_Axis0, (char)durationMicroSec); + } + } +#endif + } +} diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs.meta b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs.meta new file mode 100644 index 00000000..08a74d7b --- /dev/null +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/SteamVRv2Module.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63112e2cdad1c0945ade1ed20474623b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_2017_1.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_2017_1.cs index 98ee85a0..fa39f425 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_2017_1.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_2017_1.cs @@ -23,26 +23,48 @@ namespace HTC.UnityPlugin.VRModuleManagement public sealed partial class UnityEngineVRModule : VRModule.ModuleBase { #if UNITY_2017_1_OR_NEWER + private static readonly VRModuleDeviceClass[] s_nodeType2DeviceClass; + private uint m_leftIndex = INVALID_DEVICE_INDEX; private uint m_rightIndex = INVALID_DEVICE_INDEX; - private Dictionary m_node2Index = new Dictionary(); - private bool[] m_nodeStatesValid = new bool[MAX_DEVICE_COUNT]; private List m_nodeStateList = new List(); - - private IndexedSet m_prevExistNodeUids = new IndexedSet(); - private IndexedSet m_currExistNodeUids = new IndexedSet(); + private Dictionary m_node2Index = new Dictionary(); + private ulong[] m_index2nodeID; + private bool[] m_index2nodeValidity; + private bool[] m_index2nodeTouched; private TrackingSpaceType m_prevTrackingSpace; + static UnityEngineVRModule() + { + s_nodeType2DeviceClass = new VRModuleDeviceClass[EnumUtils.GetMaxValue(typeof(XRNode)) + 1]; + for (int i = 0; i < s_nodeType2DeviceClass.Length; ++i) { s_nodeType2DeviceClass[i] = VRModuleDeviceClass.Invalid; } + s_nodeType2DeviceClass[(int)XRNode.Head] = VRModuleDeviceClass.HMD; + s_nodeType2DeviceClass[(int)XRNode.RightHand] = VRModuleDeviceClass.Controller; + s_nodeType2DeviceClass[(int)XRNode.LeftHand] = VRModuleDeviceClass.Controller; + s_nodeType2DeviceClass[(int)XRNode.GameController] = VRModuleDeviceClass.Controller; + s_nodeType2DeviceClass[(int)XRNode.HardwareTracker] = VRModuleDeviceClass.GenericTracker; + s_nodeType2DeviceClass[(int)XRNode.TrackingReference] = VRModuleDeviceClass.TrackingReference; + } + public override void OnActivated() { m_prevTrackingSpace = XRDevice.GetTrackingSpaceType(); UpdateTrackingSpaceType(); + + EnsureDeviceStateLength(16); + m_index2nodeID = new ulong[GetDeviceStateLength()]; + m_index2nodeValidity = new bool[GetDeviceStateLength()]; + m_index2nodeTouched = new bool[GetDeviceStateLength()]; } public override void OnDeactivated() { + m_rightIndex = INVALID_DEVICE_INDEX; + m_leftIndex = INVALID_DEVICE_INDEX; + + RemoveAllValidNodes(); XRDevice.SetTrackingSpaceType(m_prevTrackingSpace); } @@ -79,10 +101,10 @@ private bool IsTrackingDeviceNode(XRNodeState nodeState) } } - private bool TryGetNodeDeviceIndex(XRNodeState nodeState, out uint deviceIndex) + private bool TryGetAndTouchNodeDeviceIndex(XRNodeState nodeState, out uint deviceIndex) { // only tracking certain type of node (some nodes share same uniqueID) - if (!IsTrackingDeviceNode(nodeState)) { deviceIndex = 0; return false; } + if (!IsTrackingDeviceNode(nodeState)) { deviceIndex = INVALID_DEVICE_INDEX; return false; } //Debug.Log(Time.frameCount + " TryGetNodeDeviceIndex " + nodeState.nodeType + " tracked=" + nodeState.tracked + " id=" + nodeState.uniqueID + " name=" + (InputTracking.GetNodeName(nodeState.uniqueID) ?? string.Empty)); if (!m_node2Index.TryGetValue(nodeState.uniqueID, out deviceIndex)) { @@ -93,33 +115,29 @@ private bool TryGetNodeDeviceIndex(XRNodeState nodeState, out uint deviceIndex) if (nodeState.nodeType == XRNode.Head) { - if (m_nodeStatesValid[0]) + if (m_index2nodeValidity[0]) { //Debug.LogWarning("[" + Time.frameCount + "] Multiple Head node found! drop node id:" + nodeState.uniqueID.ToString("X8") + " type:" + nodeState.nodeType + " name:" + InputTracking.GetNodeName(nodeState.uniqueID) + " tracked=" + nodeState.tracked); + deviceIndex = INVALID_DEVICE_INDEX; return false; } validIndexFound = true; - m_nodeStatesValid[0] = true; + m_index2nodeID[0] = nodeState.uniqueID; + m_index2nodeValidity[0] = true; m_node2Index.Add(nodeState.uniqueID, 0u); deviceIndex = 0; } else { - for (uint i = 1; i < MAX_DEVICE_COUNT; ++i) + for (uint i = 1u, imax = (uint)m_index2nodeValidity.Length; i < imax; ++i) { - if (!m_nodeStatesValid[i]) + if (!m_index2nodeValidity[i]) { validIndexFound = true; - m_nodeStatesValid[i] = true; + m_index2nodeID[i] = nodeState.uniqueID; + m_index2nodeValidity[i] = true; m_node2Index.Add(nodeState.uniqueID, i); - - switch (nodeState.nodeType) - { - case XRNode.RightHand: m_rightIndex = i; break; - case XRNode.LeftHand: m_leftIndex = i; break; - } - deviceIndex = i; break; @@ -130,113 +148,116 @@ private bool TryGetNodeDeviceIndex(XRNodeState nodeState, out uint deviceIndex) if (!validIndexFound) { Debug.LogWarning("[" + Time.frameCount + "] XRNode added, but device index out of range, drop the node id:" + nodeState.uniqueID.ToString("X8") + " type:" + nodeState.nodeType + " name:" + InputTracking.GetNodeName(nodeState.uniqueID) + " tracked=" + nodeState.tracked); + deviceIndex = INVALID_DEVICE_INDEX; return false; } //Debug.Log("[" + Time.frameCount + "] Add node device index [" + deviceIndex + "] id=" + nodeState.uniqueID.ToString("X8") + " type=" + nodeState.nodeType + " tracked=" + nodeState.tracked); } + m_index2nodeTouched[deviceIndex] = true; return true; } - private uint RemoveNodeDeviceIndex(ulong uniqueID) + private void TrimUntouchedNodes(System.Action onTrimmed) { - var deviceIndex = INVALID_DEVICE_INDEX; - if (m_node2Index.TryGetValue(uniqueID, out deviceIndex)) + for (uint i = 0u, imax = (uint)m_index2nodeValidity.Length; i < imax; ++i) { - m_node2Index.Remove(uniqueID); - m_nodeStatesValid[deviceIndex] = false; + if (!m_index2nodeTouched[i]) + { + if (m_index2nodeValidity[i]) + { + m_node2Index.Remove(m_index2nodeID[i]); + //m_index2nodeID[i] = 0; + m_index2nodeValidity[i] = false; - if (deviceIndex == m_rightIndex) { m_rightIndex = INVALID_DEVICE_INDEX; } - if (deviceIndex == m_leftIndex) { m_leftIndex = INVALID_DEVICE_INDEX; } + onTrimmed(i); + } + } + else + { + Debug.Assert(m_index2nodeValidity[i]); + m_index2nodeTouched[i] = false; + } } - - return deviceIndex; } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + private void RemoveAllValidNodes() { - if (XRSettings.isDeviceActive && XRDevice.isPresent) + for (int i = 0, imax = m_index2nodeValidity.Length; i < imax; ++i) { - InputTracking.GetNodeStates(m_nodeStateList); + if (m_index2nodeValidity[i]) + { + m_node2Index.Remove(m_index2nodeID[i]); + m_index2nodeID[i] = 0; + m_index2nodeValidity[i] = false; + m_index2nodeTouched[i] = false; + } } + } + public override void BeforeRenderUpdate() + { var rightIndex = INVALID_DEVICE_INDEX; var leftIndex = INVALID_DEVICE_INDEX; + FlushDeviceState(); + + if (XRSettings.isDeviceActive && XRDevice.isPresent) + { + InputTracking.GetNodeStates(m_nodeStateList); + } + for (int i = 0, imax = m_nodeStateList.Count; i < imax; ++i) { uint deviceIndex; - if (!TryGetNodeDeviceIndex(m_nodeStateList[i], out deviceIndex)) - { - continue; - } - - m_prevExistNodeUids.Remove(m_nodeStateList[i].uniqueID); - m_currExistNodeUids.Add(m_nodeStateList[i].uniqueID); - - var prevDeviceState = prevState[deviceIndex]; - var currDeviceState = currState[deviceIndex]; - - currDeviceState.isConnected = true; + if (!TryGetAndTouchNodeDeviceIndex(m_nodeStateList[i], out deviceIndex)) { continue; } switch (m_nodeStateList[i].nodeType) { - case XRNode.Head: - currDeviceState.deviceClass = VRModuleDeviceClass.HMD; - break; - case XRNode.RightHand: - currDeviceState.deviceClass = VRModuleDeviceClass.Controller; - rightIndex = deviceIndex; - break; - case XRNode.LeftHand: - currDeviceState.deviceClass = VRModuleDeviceClass.Controller; - leftIndex = deviceIndex; - break; - case XRNode.GameController: - currDeviceState.deviceClass = VRModuleDeviceClass.Controller; - break; - case XRNode.HardwareTracker: - currDeviceState.deviceClass = VRModuleDeviceClass.GenericTracker; - break; - case XRNode.TrackingReference: - currDeviceState.deviceClass = VRModuleDeviceClass.TrackingReference; - break; - default: - currDeviceState.deviceClass = VRModuleDeviceClass.Invalid; - break; + case XRNode.RightHand: rightIndex = deviceIndex; break; + case XRNode.LeftHand: leftIndex = deviceIndex; break; } - if (!prevDeviceState.isConnected) + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + EnsureValidDeviceState(deviceIndex, out prevState, out currState); + + if (!prevState.isConnected) { + currState.isConnected = true; + currState.deviceClass = s_nodeType2DeviceClass[(int)m_nodeStateList[i].nodeType]; // FIXME: getting wrong name in Unity 2017.1f1 //currDeviceState.serialNumber = InputTracking.GetNodeName(m_nodeStateList[i].uniqueID) ?? string.Empty; - currDeviceState.serialNumber = XRDevice.model + " " + m_nodeStateList[i].uniqueID.ToString("X8"); - currDeviceState.modelNumber = XRDevice.model + " " + m_nodeStateList[i].nodeType; - currDeviceState.renderModelName = XRDevice.model + " " + m_nodeStateList[i].nodeType; + //Debug.Log("connected " + InputTracking.GetNodeName(m_nodeStateList[i].uniqueID)); + currState.serialNumber = XRDevice.model + " " + m_nodeStateList[i].uniqueID.ToString("X8"); + currState.modelNumber = XRDevice.model + " " + m_nodeStateList[i].nodeType; + currState.renderModelName = XRDevice.model + " " + m_nodeStateList[i].nodeType; - SetupKnownDeviceModel(currDeviceState); + SetupKnownDeviceModel(currState); } // update device status - currDeviceState.isPoseValid = m_nodeStateList[i].tracked; + currState.isPoseValid = m_nodeStateList[i].tracked; var velocity = default(Vector3); - if (m_nodeStateList[i].TryGetVelocity(out velocity)) { currDeviceState.velocity = velocity; } + if (m_nodeStateList[i].TryGetVelocity(out velocity)) { currState.velocity = velocity; } var position = default(Vector3); - if (m_nodeStateList[i].TryGetPosition(out position)) { currDeviceState.position = position; } + if (m_nodeStateList[i].TryGetPosition(out position)) { currState.position = position; } var rotation = default(Quaternion); - if (m_nodeStateList[i].TryGetRotation(out rotation)) { currDeviceState.rotation = rotation; } + if (m_nodeStateList[i].TryGetRotation(out rotation)) { currState.rotation = rotation; } } m_nodeStateList.Clear(); + // update right hand input if (VRModule.IsValidDeviceIndex(rightIndex)) { - var rightCurrState = currState[m_rightIndex]; - var rightPrevState = prevState[m_rightIndex]; + IVRModuleDeviceState rightPrevState; + IVRModuleDeviceStateRW rightCurrState; + EnsureValidDeviceState(rightIndex, out rightPrevState, out rightCurrState); var rightMenuPress = Input.GetKey(ButtonKeyCode.RMenuPress); var rightAButtonPress = Input.GetKey(ButtonKeyCode.RAKeyPress); @@ -271,10 +292,12 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu rightCurrState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, rightGrip); } + // update left hand input if (VRModule.IsValidDeviceIndex(leftIndex)) { - var leftCurrState = currState[m_leftIndex]; - var leftPrevState = prevState[m_leftIndex]; + IVRModuleDeviceState leftPrevState; + IVRModuleDeviceStateRW leftCurrState; + EnsureValidDeviceState(leftIndex, out leftPrevState, out leftCurrState); var leftMenuPress = Input.GetKey(ButtonKeyCode.LMenuPress); var leftAButtonPress = Input.GetKey(ButtonKeyCode.LAKeyPress); @@ -309,20 +332,17 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu leftCurrState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, leftGrip); } - // remove disconnected nodes - for (int i = m_prevExistNodeUids.Count - 1; i >= 0; --i) + TrimUntouchedNodes(trimmedIndex => { - var removedIndex = RemoveNodeDeviceIndex(m_prevExistNodeUids[i]); - if (VRModule.IsValidDeviceIndex(removedIndex)) + IVRModuleDeviceState ps; + IVRModuleDeviceStateRW cs; + if (TryGetValidDeviceState(trimmedIndex, out ps, out cs)) { - currState[removedIndex].Reset(); + cs.Reset(); } - } + }); - var temp = m_prevExistNodeUids; - m_prevExistNodeUids = m_currExistNodeUids; - m_currExistNodeUids = temp; - m_currExistNodeUids.Clear(); + ProcessConnectedDeviceChanged(); if (m_rightIndex != rightIndex || m_leftIndex != leftIndex) { @@ -330,6 +350,9 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu m_leftIndex = leftIndex; InvokeControllerRoleChangedEvent(); } + + ProcessDevicePoseChanged(); + ProcessDeviceInputChanged(); } #endif } diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_5_5.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_5_5.cs index f1ba9426..6675af82 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_5_5.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityEngineVRModule_5_5.cs @@ -17,9 +17,12 @@ public sealed partial class UnityEngineVRModule : VRModule.ModuleBase private static readonly Regex m_leftRgx = new Regex("^.*left.*$", RegexOptions.IgnoreCase); private static readonly Regex m_rightRgx = new Regex("^.*right.*$", RegexOptions.IgnoreCase); - private readonly uint m_headIndex = 0u; - private readonly uint m_leftIndex = 1u; - private readonly uint m_rightIndex = 2u; + private const uint HEAD_INDEX = 0u; + private const uint LEFT_INDEX = 1u; + private const uint RIGHT_INDEX = 2u; + + private uint m_leftIndex = INVALID_DEVICE_INDEX; + private uint m_rightIndex = INVALID_DEVICE_INDEX; private string m_leftJoystickName = string.Empty; private string m_rightJoystickName = string.Empty; @@ -33,6 +36,8 @@ public override void OnActivated() { m_prevTrackingSpace = VRDevice.GetTrackingSpaceType(); UpdateTrackingSpaceType(); + + EnsureDeviceStateLength(3); } public override void OnDeactivated() @@ -58,13 +63,16 @@ public override void UpdateTrackingSpaceType() public override uint GetRightControllerDeviceIndex() { return m_rightIndex; } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + public override void BeforeRenderUpdate() { var joystickNames = default(string[]); + FlushDeviceState(); + // head - var headCurrState = currState[m_headIndex]; - var headPrevState = prevState[m_headIndex]; + IVRModuleDeviceState headPrevState; + IVRModuleDeviceStateRW headCurrState; + EnsureValidDeviceState(HEAD_INDEX, out headPrevState, out headCurrState); headCurrState.isConnected = VRDevice.isPresent; @@ -105,8 +113,9 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu } // right - var rightCurrState = currState[m_rightIndex]; - var rightPrevState = prevState[m_rightIndex]; + IVRModuleDeviceState rightPrevState; + IVRModuleDeviceStateRW rightCurrState; + EnsureValidDeviceState(RIGHT_INDEX, out rightPrevState, out rightCurrState); rightCurrState.position = InputTracking.GetLocalPosition(VRNode.RightHand); rightCurrState.rotation = InputTracking.GetLocalRotation(VRNode.RightHand); @@ -125,6 +134,7 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu rightCurrState.isConnected = true; m_rightJoystickName = joystickNames[i]; m_rightJoystickNameIndex = i; + m_rightIndex = RIGHT_INDEX; break; } } @@ -140,6 +150,7 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu rightCurrState.isConnected = false; m_rightJoystickName = string.Empty; m_rightJoystickNameIndex = -1; + m_rightIndex = INVALID_DEVICE_INDEX; } } } @@ -209,8 +220,9 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu } // left - var leftCurrState = currState[m_leftIndex]; - var leftPrevState = prevState[m_leftIndex]; + IVRModuleDeviceState leftPrevState; + IVRModuleDeviceStateRW leftCurrState; + EnsureValidDeviceState(LEFT_INDEX, out leftPrevState, out leftCurrState); leftCurrState.position = InputTracking.GetLocalPosition(VRNode.LeftHand); leftCurrState.rotation = InputTracking.GetLocalRotation(VRNode.LeftHand); @@ -228,6 +240,7 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu leftCurrState.isConnected = true; m_leftJoystickName = joystickNames[i]; m_leftJoystickNameIndex = i; + m_leftIndex = LEFT_INDEX; break; } } @@ -243,6 +256,7 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu leftCurrState.isConnected = false; m_leftJoystickName = string.Empty; m_leftJoystickNameIndex = -1; + m_leftIndex = INVALID_DEVICE_INDEX; } } } @@ -310,6 +324,10 @@ public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModu leftCurrState.Reset(); } } + + ProcessConnectedDeviceChanged(); + ProcessDevicePoseChanged(); + ProcessDeviceInputChanged(); } #endif } diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs index 8cd66c92..24a5dddb 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs @@ -1,5 +1,6 @@ using HTC.UnityPlugin.Utility; using HTC.UnityPlugin.Vive; +using System; using UnityEngine; #if VIU_WAVEVR && UNITY_ANDROID using wvr; @@ -24,10 +25,14 @@ public sealed class WaveVRModule : VRModule.ModuleBase private static readonly VRModuleDeviceModel[] s_type2model; private bool m_hasInputFocus; - private Vector3 m_handedMultiplier; - private WVR_DevicePosePair_t[] m_poses = new WVR_DevicePosePair_t[DEVICE_COUNT]; // HMD, R, L controllers. - private WVR_AnalogState_t[] m_analogStates = new WVR_AnalogState_t[2]; private WVR_PoseOriginModel m_poseOrigin; + private readonly WVR_DevicePosePair_t[] m_poses = new WVR_DevicePosePair_t[DEVICE_COUNT]; // HMD, R, L controllers. + private readonly bool[] m_index2deviceTouched = new bool[DEVICE_COUNT]; + private WVR_AnalogState_t[] m_analogStates = new WVR_AnalogState_t[2]; + private Vector3 m_handedMultiplier; + private IVRModuleDeviceStateRW m_headState; + private IVRModuleDeviceStateRW m_rightState; + private IVRModuleDeviceStateRW m_leftState; #region 6Dof Controller Simulation @@ -44,7 +49,7 @@ private enum Simulate6DoFControllerMode static WaveVRModule() { - s_index2type = new WVR_DeviceType[VRModule.MAX_DEVICE_COUNT]; + s_index2type = new WVR_DeviceType[DEVICE_COUNT]; s_index2type[0] = WVR_DeviceType.WVR_DeviceType_HMD; s_index2type[1] = WVR_DeviceType.WVR_DeviceType_Controller_Right; s_index2type[2] = WVR_DeviceType.WVR_DeviceType_Controller_Left; @@ -77,17 +82,16 @@ public override bool ShouldActiveModule() public override void OnActivated() { - var instance = Object.FindObjectOfType(); - if (instance == null) + if (UnityEngine.Object.FindObjectOfType() == null) { VRModule.Instance.gameObject.AddComponent(); } + EnsureDeviceStateLength(DEVICE_COUNT); + UpdateTrackingSpaceType(); } - public override void OnDeactivated() { } - public override void UpdateTrackingSpaceType() { switch (VRModule.trackingSpaceType) @@ -101,155 +105,243 @@ public override void UpdateTrackingSpaceType() } } - // FIXME: WVR_IsInputFocusCapturedBySystem currently not implemented yet - //public override bool HasInputFocus() - //{ - // return m_hasInputFocus; - //} + public override void Update() + { + for (uint deviceIndex = 0u; deviceIndex < DEVICE_COUNT; ++deviceIndex) + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + if (!TryGetValidDeviceState(deviceIndex, out prevState, out currState) || !currState.isConnected) { continue; } + + var deviceType = s_index2type[deviceIndex]; + // update input + var buttons = 0u; + var touches = 0u; + // FIXME: What does WVR_GetInputTypeCount means? + var analogCount = Interop.WVR_GetInputTypeCount(deviceType, WVR_InputType.WVR_InputType_Analog); + if (m_analogStates == null || m_analogStates.Length < analogCount) { m_analogStates = new WVR_AnalogState_t[analogCount]; } + const uint inputType = (uint)(WVR_InputType.WVR_InputType_Button | WVR_InputType.WVR_InputType_Touch | WVR_InputType.WVR_InputType_Analog); +#if VIU_WAVEVR_2_0_32_OR_NEWER + if (Interop.WVR_GetInputDeviceState(deviceType, inputType, ref buttons, ref touches, m_analogStates, (uint)analogCount)) +#else + if (Interop.WVR_GetInputDeviceState(deviceType, inputType, ref buttons, ref touches, m_analogStates, analogCount)) +#endif + { + const uint dpadMask = + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Touchpad)) | + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Left)) | + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Up)) | + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Right)) | + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Down)); + + const uint triggerBumperMask = + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Trigger)) | +#if VIU_WAVEVR_2_1_0_OR_NEWER + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Digital_Trigger)); +#else + (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Bumper)); +#endif - public override uint GetRightControllerDeviceIndex() { return s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Right]; } + currState.SetButtonPress(VRModuleRawButton.System, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u); + currState.SetButtonPress(VRModuleRawButton.Touchpad, (buttons & dpadMask) != 0u); + currState.SetButtonPress(VRModuleRawButton.Trigger, (buttons & triggerBumperMask) != 0u); + currState.SetButtonPress(VRModuleRawButton.Grip, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadLeft, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadUp, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadRight, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u); + currState.SetButtonPress(VRModuleRawButton.DPadDown, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u); + + currState.SetButtonTouch(VRModuleRawButton.System, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.ApplicationMenu, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Touchpad, (touches & dpadMask) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Trigger, (touches & triggerBumperMask) != 0u); + currState.SetButtonTouch(VRModuleRawButton.Grip, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.DPadLeft, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.DPadUp, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.DPadRight, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u); + currState.SetButtonTouch(VRModuleRawButton.DPadDown, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u); + + for (int j = 0, jmax = m_analogStates.Length; j < jmax; ++j) + { + switch (m_analogStates[j].id) + { + case WVR_InputId.WVR_InputId_Alias1_Trigger: + if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_Trigger) + { + currState.SetAxisValue(VRModuleRawAxis.Trigger, m_analogStates[j].axis.x); + } + break; + case WVR_InputId.WVR_InputId_Alias1_Touchpad: + if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_TouchPad && currState.GetButtonTouch(VRModuleRawButton.Touchpad)) + { + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, m_analogStates[j].axis.x); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, m_analogStates[j].axis.y); + } + else + { + currState.SetAxisValue(VRModuleRawAxis.TouchpadX, 0f); + currState.SetAxisValue(VRModuleRawAxis.TouchpadY, 0f); + } + break; + } + } + } + else + { + currState.buttonPressed = 0u; + currState.buttonTouched = 0u; + currState.ResetAxisValues(); + } + } - public override uint GetLeftControllerDeviceIndex() { return s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Left]; } + ProcessDeviceInputChanged(); + } - public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) + public override void BeforeRenderUpdate() { if (WaveVR.Instance == null) { return; } - // FIXME: WVR_IsInputFocusCapturedBySystem currently not implemented yet - //m_hasInputFocus = Interop.WVR_IsInputFocusCapturedBySystem(); - Interop.WVR_GetSyncPose(m_poseOrigin, m_poses, DEVICE_COUNT); - for (int i = 0; i < DEVICE_COUNT; ++i) + FlushDeviceState(); + + for (int i = 0, imax = m_poses.Length; i < imax; ++i) { + uint deviceIndex; var deviceType = m_poses[i].type; - if (deviceType < 0 || (int)deviceType >= s_type2index.Length) { continue; } - - var deviceIndex = s_type2index[(int)deviceType]; - if (!VRModule.IsValidDeviceIndex(deviceIndex)) { continue; } + if (!TryGetAndTouchDeviceIndexByType(deviceType, out deviceIndex)) { continue; } - var cState = currState[deviceIndex]; - var pState = prevState[deviceIndex]; + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + EnsureValidDeviceState(deviceIndex, out prevState, out currState); - cState.isConnected = Interop.WVR_IsDeviceConnected(deviceType); + if (!Interop.WVR_IsDeviceConnected(deviceType)) + { + if (prevState.isConnected) + { + currState.Reset(); - if (cState.isConnected) + switch (deviceType) + { + case WVR_DeviceType.WVR_DeviceType_HMD: m_headState = null; break; + case WVR_DeviceType.WVR_DeviceType_Controller_Right: m_rightState = null; break; + case WVR_DeviceType.WVR_DeviceType_Controller_Left: m_leftState = null; break; + } + } + } + else { - if (!pState.isConnected) + if (!prevState.isConnected) { - cState.deviceClass = s_type2class[(int)deviceType]; - cState.deviceModel = s_type2model[(int)deviceType]; + currState.isConnected = true; + currState.deviceClass = s_type2class[(int)deviceType]; + currState.deviceModel = s_type2model[(int)deviceType]; + currState.serialNumber = deviceType.ToString(); + currState.modelNumber = deviceType.ToString(); + currState.renderModelName = deviceType.ToString(); + + switch (deviceType) + { + case WVR_DeviceType.WVR_DeviceType_HMD: m_headState = currState; break; + case WVR_DeviceType.WVR_DeviceType_Controller_Right: m_rightState = currState; break; + case WVR_DeviceType.WVR_DeviceType_Controller_Left: m_leftState = currState; break; + } } - // fetch tracking data - cState.isOutOfRange = false; - cState.isCalibrating = false; - cState.isUninitialized = false; - + // update pose var devicePose = m_poses[i].pose; - cState.velocity = new Vector3(devicePose.Velocity.v0, devicePose.Velocity.v1, -devicePose.Velocity.v2); - cState.angularVelocity = new Vector3(-devicePose.AngularVelocity.v0, -devicePose.AngularVelocity.v1, devicePose.AngularVelocity.v2); + currState.velocity = new Vector3(devicePose.Velocity.v0, devicePose.Velocity.v1, -devicePose.Velocity.v2); + currState.angularVelocity = new Vector3(-devicePose.AngularVelocity.v0, -devicePose.AngularVelocity.v1, devicePose.AngularVelocity.v2); var rigidTransform = new WaveVR_Utils.RigidTransform(devicePose.PoseMatrix); - cState.position = rigidTransform.pos; - cState.rotation = rigidTransform.rot; - - cState.isPoseValid = cState.pose != RigidPose.identity; - - // fetch buttons input - var buttons = 0u; - var touches = 0u; - // FIXME: What does WVR_GetInputTypeCount means? - var analogCount = Interop.WVR_GetInputTypeCount(deviceType, WVR_InputType.WVR_InputType_Analog); - if (m_analogStates == null || m_analogStates.Length < analogCount) { m_analogStates = new WVR_AnalogState_t[analogCount]; } - const uint inputType = (uint)(WVR_InputType.WVR_InputType_Button | WVR_InputType.WVR_InputType_Touch | WVR_InputType.WVR_InputType_Analog); -#if VIU_WAVEVR_2_0_32_OR_NEWER - if (Interop.WVR_GetInputDeviceState(deviceType, inputType, ref buttons, ref touches, m_analogStates, (uint)analogCount)) -#else - if (Interop.WVR_GetInputDeviceState(deviceType, inputType, ref buttons, ref touches, m_analogStates, analogCount)) -#endif - { - const uint dpadMask = - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Touchpad)) | - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Left)) | - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Up)) | - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Right)) | - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_DPad_Down)); - - const uint triggerBumperMask = - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Trigger)) | -#if VIU_WAVEVR_2_1_0_OR_NEWER - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Digital_Trigger)); -#else - (1 << (int)(WVR_InputId.WVR_InputId_Alias1_Bumper)); -#endif + currState.position = rigidTransform.pos; + currState.rotation = rigidTransform.rot; - cState.SetButtonPress(VRModuleRawButton.System, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u); - cState.SetButtonPress(VRModuleRawButton.ApplicationMenu, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u); - cState.SetButtonPress(VRModuleRawButton.Touchpad, (buttons & dpadMask) != 0u); - cState.SetButtonPress(VRModuleRawButton.Trigger, (buttons & triggerBumperMask) != 0u); - cState.SetButtonPress(VRModuleRawButton.Grip, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u); - cState.SetButtonPress(VRModuleRawButton.DPadLeft, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u); - cState.SetButtonPress(VRModuleRawButton.DPadUp, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u); - cState.SetButtonPress(VRModuleRawButton.DPadRight, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u); - cState.SetButtonPress(VRModuleRawButton.DPadDown, (buttons & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u); - - cState.SetButtonTouch(VRModuleRawButton.System, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_System)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.ApplicationMenu, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Menu)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.Touchpad, (touches & dpadMask) != 0u); - cState.SetButtonTouch(VRModuleRawButton.Trigger, (touches & triggerBumperMask) != 0u); - cState.SetButtonTouch(VRModuleRawButton.Grip, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_Grip)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.DPadLeft, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Left)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.DPadUp, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Up)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.DPadRight, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Right)) != 0u); - cState.SetButtonTouch(VRModuleRawButton.DPadDown, (touches & (1 << (int)WVR_InputId.WVR_InputId_Alias1_DPad_Down)) != 0u); - - for (int j = 0, jmax = m_analogStates.Length; j < jmax; ++j) - { - switch (m_analogStates[j].id) - { - case WVR_InputId.WVR_InputId_Alias1_Trigger: - if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_Trigger) - { - cState.SetAxisValue(VRModuleRawAxis.Trigger, m_analogStates[j].axis.x); - } - break; - case WVR_InputId.WVR_InputId_Alias1_Touchpad: - if (m_analogStates[j].type == WVR_AnalogType.WVR_AnalogType_TouchPad && cState.GetButtonTouch(VRModuleRawButton.Touchpad)) - { - cState.SetAxisValue(VRModuleRawAxis.TouchpadX, m_analogStates[j].axis.x); - cState.SetAxisValue(VRModuleRawAxis.TouchpadY, m_analogStates[j].axis.y); - } - else - { - cState.SetAxisValue(VRModuleRawAxis.TouchpadX, 0f); - cState.SetAxisValue(VRModuleRawAxis.TouchpadY, 0f); - } - break; - } - } - } - else + currState.isPoseValid = currState.pose != RigidPose.identity; + } + } + + ApplyVirtualArmAndSimulateInput(m_rightState, m_headState, RIGHT_ARM_MULTIPLIER); + ApplyVirtualArmAndSimulateInput(m_leftState, m_headState, LEFT_ARM_MULTIPLIER); + + ResetAndDisconnectUntouchedDevices(); + + ProcessConnectedDeviceChanged(); + ProcessDevicePoseChanged(); + } + + public override void OnDeactivated() + { + m_headState = null; + m_rightState = null; + m_leftState = null; + ResetTouchState(); + } + + // FIXME: WVR_IsInputFocusCapturedBySystem currently not implemented yet + //public override bool HasInputFocus() + //{ + // return m_hasInputFocus; + //} + + public override uint GetRightControllerDeviceIndex() { return s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Right]; } + + public override uint GetLeftControllerDeviceIndex() { return s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Left]; } + + private bool TryGetAndTouchDeviceIndexByType(WVR_DeviceType type, out uint deviceIndex) + { + if (type < 0 || (int)type >= s_type2index.Length) + { + deviceIndex = INVALID_DEVICE_INDEX; + return false; + } + + deviceIndex = s_type2index[(int)type]; + if (VRModule.IsValidDeviceIndex(deviceIndex)) + { + m_index2deviceTouched[deviceIndex] = true; + return true; + } + else + { + return false; + } + } + + private int ResetAndDisconnectUntouchedDevices() + { + var disconnectedCout = 0; + for (uint i = 0u, imax = (uint)m_index2deviceTouched.Length; i < imax; ++i) + { + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + if (!TryGetValidDeviceState(i, out prevState, out currState)) + { + Debug.Assert(!m_index2deviceTouched[i]); + continue; + } + + if (!m_index2deviceTouched[i]) + { + if (currState.isConnected) { - cState.buttonPressed = 0u; - cState.buttonTouched = 0u; - for (int j = 0, jmax = cState.axisValue.Length; j < jmax; ++j) { cState.axisValue[j] = 0f; } + currState.Reset(); + ++disconnectedCout; } } else { - if (pState.isConnected) - { - cState.Reset(); - } + m_index2deviceTouched[i] = false; } } - var headState = currState[s_type2index[(int)WVR_DeviceType.WVR_DeviceType_HMD]]; - var rightState = currState[s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Right]]; - var leftState = currState[s_type2index[(int)WVR_DeviceType.WVR_DeviceType_Controller_Left]]; - ApplyVirtualArmAndSimulateInput(rightState, headState, RIGHT_ARM_MULTIPLIER); - ApplyVirtualArmAndSimulateInput(leftState, headState, LEFT_ARM_MULTIPLIER); + return disconnectedCout; + } + + private void ResetTouchState() + { + Array.Clear(m_index2deviceTouched, 0, m_index2deviceTouched.Length); } private void ApplyVirtualArmAndSimulateInput(IVRModuleDeviceStateRW ctrlState, IVRModuleDeviceStateRW headState, Vector3 handSideMultiplier) diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModule.cs b/Assets/HTC.UnityPlugin/VRModule/VRModule.cs index db9ba4c3..658f8829 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModule.cs @@ -88,7 +88,8 @@ public static IVRModuleDeviceState defaultDeviceState public static bool IsValidDeviceIndex(uint deviceIndex) { - return deviceIndex < MAX_DEVICE_COUNT; + if (!Active) { return false; } + return deviceIndex < Instance.GetDeviceStateLength(); } public static bool HasInputFocus() @@ -98,34 +99,52 @@ public static bool HasInputFocus() public static bool IsDeviceConnected(string deviceSerialNumber) { - return s_deviceSerialNumberTable.ContainsKey(deviceSerialNumber); + return (string.IsNullOrEmpty(deviceSerialNumber) || s_deviceSerialNumberTable == null) ? false : s_deviceSerialNumberTable.ContainsKey(deviceSerialNumber); } public static uint GetConnectedDeviceIndex(string deviceSerialNumber) { uint deviceIndex; - if (s_deviceSerialNumberTable.TryGetValue(deviceSerialNumber, out deviceIndex)) { return deviceIndex; } - return INVALID_DEVICE_INDEX; + if (string.IsNullOrEmpty(deviceSerialNumber) || s_deviceSerialNumberTable == null || !s_deviceSerialNumberTable.TryGetValue(deviceSerialNumber, out deviceIndex)) + { + return INVALID_DEVICE_INDEX; + } + else + { + return deviceIndex; + } } public static bool TryGetConnectedDeviceIndex(string deviceSerialNumber, out uint deviceIndex) { - return s_deviceSerialNumberTable.TryGetValue(deviceSerialNumber, out deviceIndex); + if (string.IsNullOrEmpty(deviceSerialNumber) || s_deviceSerialNumberTable == null) + { + deviceIndex = INVALID_DEVICE_INDEX; + return false; + } + else + { + return s_deviceSerialNumberTable.TryGetValue(deviceSerialNumber, out deviceIndex); + } } + public static uint GetDeviceStateCount() { return Instance == null ? 0u : Instance.GetDeviceStateLength(); } + public static IVRModuleDeviceState GetCurrentDeviceState(uint deviceIndex) { - return Instance == null || !IsValidDeviceIndex(deviceIndex) ? s_defaultState : Instance.m_currStates[deviceIndex]; + if (!IsValidDeviceIndex(deviceIndex) || Instance == null || Instance.m_currStates == null) { return s_defaultState; } + return Instance.m_currStates[deviceIndex] ?? s_defaultState; } public static IVRModuleDeviceState GetPreviousDeviceState(uint deviceIndex) { - return Instance == null || !IsValidDeviceIndex(deviceIndex) ? s_defaultState : Instance.m_prevStates[deviceIndex]; + if (!IsValidDeviceIndex(deviceIndex) || Instance == null || Instance.m_prevStates == null) { return s_defaultState; } + return Instance.m_prevStates[deviceIndex] ?? s_defaultState; } public static IVRModuleDeviceState GetDeviceState(uint deviceIndex, bool usePrevious = false) { - return Instance == null || !IsValidDeviceIndex(deviceIndex) ? s_defaultState : (usePrevious ? Instance.m_prevStates[deviceIndex] : Instance.m_currStates[deviceIndex]); + return usePrevious ? GetPreviousDeviceState(deviceIndex) : GetCurrentDeviceState(deviceIndex); } public static uint GetLeftControllerDeviceIndex() diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs index cad57786..f048782f 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs @@ -1,6 +1,7 @@ //========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== using HTC.UnityPlugin.Utility; +using System; using System.Text.RegularExpressions; namespace HTC.UnityPlugin.VRModuleManagement @@ -9,6 +10,7 @@ public partial class VRModule : SingletonBehaviour { public abstract class ModuleBase { + [Obsolete("Module should set their own MAX_DEVICE_COUNT, use EnsureDeviceStateLength to set, VRModule.GetDeviceStateCount() to get")] protected const uint MAX_DEVICE_COUNT = VRModule.MAX_DEVICE_COUNT; protected const uint INVALID_DEVICE_INDEX = VRModule.INVALID_DEVICE_INDEX; @@ -16,6 +18,7 @@ public abstract class ModuleBase private static readonly Regex s_oculusRgx = new Regex("^.*(oculus).*$", RegexOptions.IgnoreCase); private static readonly Regex s_knucklesRgx = new Regex("^.*(knuckles).*$", RegexOptions.IgnoreCase); private static readonly Regex s_daydreamRgx = new Regex("^.*(daydream).*$", RegexOptions.IgnoreCase); + private static readonly Regex s_wmrRgx = new Regex("^.*(asus|acer|dell|lenovo|hp|samsung)", RegexOptions.IgnoreCase); private static readonly Regex s_leftRgx = new Regex("^.*left.*$", RegexOptions.IgnoreCase); private static readonly Regex s_rightRgx = new Regex("^.*right.*$", RegexOptions.IgnoreCase); @@ -30,14 +33,12 @@ public virtual void OnDeactivated() { } public virtual uint GetRightControllerDeviceIndex() { return INVALID_DEVICE_INDEX; } public virtual void UpdateTrackingSpaceType() { } public virtual void Update() { } + public virtual void FixedUpdate() { } + public virtual void LateUpdate() { } + public virtual void BeforeRenderUpdate() { } - public virtual void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) - { - for (uint i = 0; i < MAX_DEVICE_COUNT; ++i) - { - if (prevState[i].isConnected) { currState[i].Reset(); } - } - } + [Obsolete] + public virtual void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState) { } public virtual void TriggerViveControllerHaptic(uint deviceIndex, ushort durationMicroSec = 500) { } @@ -51,6 +52,46 @@ protected void InvokeControllerRoleChangedEvent() VRModule.InvokeControllerRoleChangedEvent(); } + protected uint GetDeviceStateLength() + { + return Instance.GetDeviceStateLength(); + } + + protected void EnsureDeviceStateLength(uint capacity) + { + Instance.EnsureDeviceStateLength(capacity); + } + + protected bool TryGetValidDeviceState(uint index, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState) + { + return Instance.TryGetValidDeviceState(index, out prevState, out currState); + } + + protected void EnsureValidDeviceState(uint index, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState) + { + Instance.EnsureValidDeviceState(index, out prevState, out currState); + } + + protected void FlushDeviceState() + { + Instance.ModuleFlushDeviceState(); + } + + protected void ProcessConnectedDeviceChanged() + { + Instance.ModuleConnectedDeviceChanged(); + } + + protected void ProcessDevicePoseChanged() + { + InvokeNewPosesEvent(); + } + + protected void ProcessDeviceInputChanged() + { + InvokeNewInputEvent(); + } + protected static void SetupKnownDeviceModel(IVRModuleDeviceStateRW deviceState) { if (s_viveRgx.IsMatch(deviceState.modelNumber) || s_viveRgx.IsMatch(deviceState.renderModelName)) @@ -95,6 +136,27 @@ protected static void SetupKnownDeviceModel(IVRModuleDeviceStateRW deviceState) return; } } + else if (s_wmrRgx.IsMatch(deviceState.modelNumber) || s_wmrRgx.IsMatch(deviceState.renderModelName)) + { + switch (deviceState.deviceClass) + { + case VRModuleDeviceClass.HMD: + deviceState.deviceModel = VRModuleDeviceModel.WMRHMD; + return; + case VRModuleDeviceClass.Controller: + if (s_leftRgx.IsMatch(deviceState.modelNumber)) + { + deviceState.deviceModel = VRModuleDeviceModel.WMRControllerLeft; + return; + } + else if (s_rightRgx.IsMatch(deviceState.modelNumber)) + { + deviceState.deviceModel = VRModuleDeviceModel.WMRControllerRight; + return; + } + break; + } + } else if (deviceState.deviceClass == VRModuleDeviceClass.Controller && s_knucklesRgx.IsMatch(deviceState.modelNumber)) { if (s_leftRgx.IsMatch(deviceState.renderModelName)) diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleDeviceState.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleDeviceState.cs index 8d4c13e5..8886f48c 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleDeviceState.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleDeviceState.cs @@ -34,6 +34,9 @@ public enum VRModuleDeviceModel ViveFocusFinch, OculusGoController, OculusGearVrController, + WMRHMD, + WMRControllerLeft, + WMRControllerRight, } public enum VRModuleRawButton @@ -47,22 +50,35 @@ public enum VRModuleRawButton DPadDown = 6, A = 7, ProximitySensor = 31, + DashboardBack = 2, // Grip + Touchpad = 32, // Axis0 + Trigger = 33, // Axis1 + CapSenseGrip = 34, // Axis2 + + // alias Axis0 = 32, Axis1 = 33, Axis2 = 34, Axis3 = 35, Axis4 = 36, - - // alias - DashboardBack = 2, // Grip - Touchpad = 32, // Axis0 - Trigger = 33, // Axis1 - CapSenseGrip = 34, // Axis2 } public enum VRModuleRawAxis { - Axis0X, + TouchpadX = Axis0X, + TouchpadY = Axis0Y, + Trigger = Axis1X, + CapSenseGrip = Axis2X, + IndexCurl = Axis3X, + MiddleCurl = Axis3Y, + RingCurl = Axis4X, + PinkyCurl = Axis4Y, + + JoystickX = Axis2X, + JoystickY = Axis2Y, + + // alias + Axis0X = 0, Axis0Y, Axis1X, Axis1Y, @@ -72,16 +88,6 @@ public enum VRModuleRawAxis Axis3Y, Axis4X, Axis4Y, - - // alias - TouchpadX = Axis0X, - TouchpadY = Axis0Y, - Trigger = Axis1X, - CapSenseGrip = Axis2X, - IndexCurl = Axis3X, - MiddleCurl = Axis3Y, - RingCurl = Axis4X, - PinkyCurl = Axis4Y, } public interface IVRModuleDeviceStateRW @@ -203,11 +209,11 @@ private class DeviceState : IVRModuleDeviceState, IVRModuleDeviceStateRW // device input state [SerializeField] - public ulong m_buttonPressed; + private ulong m_buttonPressed; [SerializeField] - public ulong m_buttonTouched; + private ulong m_buttonTouched; [SerializeField] - public float[] m_axisValue; + private float[] m_axisValue; public ulong buttonPressed { get { return m_buttonPressed; } set { m_buttonPressed = value; } } public ulong buttonTouched { get { return m_buttonTouched; } set { m_buttonTouched = value; } } diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleEvent.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleEvent.cs index 88e82c78..1ecfafa9 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleEvent.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleEvent.cs @@ -11,6 +11,8 @@ public partial class VRModule : SingletonBehaviour [Serializable] public class NewPosesEvent : UnityEvent { } [Serializable] + public class NewInputEvent : UnityEvent { } + [Serializable] public class ControllerRoleChangedEvent : UnityEvent { } [Serializable] public class InputFocusEvent : UnityEvent { } @@ -20,18 +22,21 @@ public class DeviceConnectedEvent : UnityEvent { } public class ActiveModuleChangedEvent : UnityEvent { } public delegate void NewPosesListener(); + public delegate void NesInputListener(); public delegate void ControllerRoleChangedListener(); public delegate void InputFocusListener(bool value); public delegate void DeviceConnectedListener(uint deviceIndex, bool connected); public delegate void ActiveModuleChangedListener(VRModuleActiveEnum activeModule); private static NewPosesListener s_onNewPoses; + private static NesInputListener s_onNewInput; private static ControllerRoleChangedListener s_onControllerRoleChanged; private static InputFocusListener s_onInputFocus; private static DeviceConnectedListener s_onDeviceConnected; private static ActiveModuleChangedListener s_onActiveModuleChanged; public static event NewPosesListener onNewPoses { add { s_onNewPoses += value; } remove { s_onNewPoses -= value; } } // invoke by manager + public static event NesInputListener onNewInput { add { s_onNewInput += value; } remove { s_onNewInput -= value; } } // invoke by manager public static event ControllerRoleChangedListener onControllerRoleChanged { add { s_onControllerRoleChanged += value; } remove { s_onControllerRoleChanged -= value; } } // invoke by module public static event InputFocusListener onInputFocus { add { s_onInputFocus += value; } remove { s_onInputFocus -= value; } } // invoke by module public static event DeviceConnectedListener onDeviceConnected { add { s_onDeviceConnected += value; } remove { s_onDeviceConnected -= value; } }// invoke by manager @@ -43,6 +48,12 @@ private static void InvokeNewPosesEvent() if (Active) { Instance.m_onNewPoses.Invoke(); } } + private static void InvokeNewInputEvent() + { + if (s_onNewInput != null) { s_onNewInput(); } + if (Active) { Instance.m_onNewInput.Invoke(); } + } + private static void InvokeControllerRoleChangedEvent() { if (s_onControllerRoleChanged != null) { s_onControllerRoleChanged(); } diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs index 9297d4a1..6253a4f9 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleManager.cs @@ -13,7 +13,7 @@ public partial class VRModule : SingletonBehaviour { private static readonly DeviceState s_defaultState; private static readonly SimulatorVRModule s_simulator; - private static readonly Dictionary s_deviceSerialNumberTable = new Dictionary((int)MAX_DEVICE_COUNT); + private static readonly Dictionary s_deviceSerialNumberTable; [SerializeField] private bool m_dontDestroyOnLoad = true; @@ -27,6 +27,8 @@ public partial class VRModule : SingletonBehaviour [SerializeField] private NewPosesEvent m_onNewPoses = new NewPosesEvent(); [SerializeField] + private NewInputEvent m_onNewInput = new NewInputEvent(); + [SerializeField] private ControllerRoleChangedEvent m_onControllerRoleChanged = new ControllerRoleChangedEvent(); [SerializeField] private InputFocusEvent m_onInputFocus = new InputFocusEvent(); @@ -35,7 +37,7 @@ public partial class VRModule : SingletonBehaviour [SerializeField] private ActiveModuleChangedEvent m_onActiveModuleChanged = new ActiveModuleChangedEvent(); - private bool m_isUpdating = false; + private bool m_delayDeactivate = false; private bool m_isDestoryed = false; private ModuleBase[] m_modules; @@ -50,6 +52,7 @@ static VRModule() s_defaultState = new DeviceState(INVALID_DEVICE_INDEX); s_simulator = new SimulatorVRModule(); + s_deviceSerialNumberTable = new Dictionary(16); } private static GameObject GetDefaultInitGameObject() @@ -80,22 +83,68 @@ protected override void OnSingletonBehaviourInitialized() m_modules[(int)VRModuleActiveEnum.OculusVR] = new OculusVRModule(); m_modules[(int)VRModuleActiveEnum.DayDream] = new GoogleVRModule(); m_modules[(int)VRModuleActiveEnum.WaveVR] = new WaveVRModule(); + } - s_deviceSerialNumberTable.Clear(); + private uint GetDeviceStateLength() { return m_currStates == null ? 0u : (uint)m_currStates.Length; } - m_currStates = new DeviceState[MAX_DEVICE_COUNT]; - for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) { m_currStates[i] = new DeviceState(i); } + private void EnsureDeviceStateLength(uint capacity) + { + // NOTE: this will clear out the array + var cap = Mathf.Min((int)capacity, (int)MAX_DEVICE_COUNT); + if (GetDeviceStateLength() < cap) + { + m_prevStates = new DeviceState[cap]; + m_currStates = new DeviceState[cap]; + } + } - m_prevStates = new DeviceState[MAX_DEVICE_COUNT]; - for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) { m_prevStates[i] = new DeviceState(i); } + private bool TryGetValidDeviceState(uint index, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState) + { + DeviceState prevRawState; + DeviceState currRawState; + if (TryGetValidDeviceState(index, out prevRawState, out currRawState)) + { + prevState = prevRawState; + currState = currRawState; + return true; + } + else + { + prevState = null; + currState = null; + return false; + } + } + + private bool TryGetValidDeviceState(uint index, out DeviceState prevState, out DeviceState currState) + { + if (m_currStates == null || m_currStates[index] == null) + { + prevState = null; + currState = null; + return false; + } + else + { + prevState = m_prevStates[index]; + currState = m_currStates[index]; + return true; + } + } + + private void EnsureValidDeviceState(uint index, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState) + { + if (!TryGetValidDeviceState(index, out prevState, out currState)) + { + prevState = m_prevStates[index] = new DeviceState(index); + currState = m_currStates[index] = new DeviceState(index); + } } private void Update() { if (!IsInstance) { return; } - m_isUpdating = true; - // Get should activate module var shouldActivateModule = GetShouldActivateModule(); @@ -114,17 +163,30 @@ private void Update() } } - if (m_activatedModule != VRModuleActiveEnum.Uninitialized) + if (m_activatedModuleBase != null) { m_activatedModuleBase.Update(); } + } - if (m_isDestoryed) + private void FixedUpdate() + { + if (!IsInstance) { return; } + + if (m_activatedModuleBase != null) { - DeactivateModule(); + m_activatedModuleBase.FixedUpdate(); } + } - m_isUpdating = false; + private void LateUpdate() + { + if (!IsInstance) { return; } + + if (m_activatedModuleBase != null) + { + m_activatedModuleBase.LateUpdate(); + } } protected override void OnDestroy() @@ -133,7 +195,7 @@ protected override void OnDestroy() { m_isDestoryed = true; - if (!m_isUpdating) + if (!m_delayDeactivate) { DeactivateModule(); } @@ -144,6 +206,8 @@ protected override void OnDestroy() private VRModuleActiveEnum GetShouldActivateModule() { + if (m_isDestoryed) { return VRModuleActiveEnum.Uninitialized; } + if (m_selectModule == VRModuleSelectEnum.Auto) { for (int i = m_modules.Length - 1; i >= 0; --i) @@ -154,7 +218,7 @@ private VRModuleActiveEnum GetShouldActivateModule() } } } - else if ((int)m_selectModule >= 0 && (int)m_selectModule < m_modules.Length) + else if (m_selectModule >= 0 && (int)m_selectModule < m_modules.Length) { return (VRModuleActiveEnum)m_selectModule; } @@ -185,118 +249,37 @@ private void ActivateModule(VRModuleActiveEnum 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_2_0_0_OR_NEWER - SteamVR_Input.OnPosesUpdated += OnSteamVRInputPosesUpdated; -#elif 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; + Application.onBeforeRender += BeforeRenderUpdateModule; #else - Camera.onPreCull += OnCameraPreCull; + Camera.onPreCull += OnCameraPreCull; #endif - break; - } - } - -#if VIU_STEAMVR - private void OnSteamVRInputPosesUpdated(bool obj) { UpdateActiveModuleDeviceState(); } - private void OnSteamVRNewPoseArgs(params object[] args) { UpdateActiveModuleDeviceState(); } - - private void OnSteamVRNewPose(Valve.VR.TrackedDevicePose_t[] poses) { UpdateActiveModuleDeviceState(); } -#endif - -#if VIU_WAVEVR - private void OnWaveVRNewPoseArgs(params object[] args) { UpdateActiveModuleDeviceState(); } -#endif + InvokeActiveModuleChangedEvent(m_activatedModule); + } #if !UNITY_2017_1_OR_NEWER - private int m_poseUpdatedFrame = -1; + private int m_preCullOnceFrame = -1; private void OnCameraPreCull(Camera cam) { var thisFrame = Time.frameCount; - if (m_poseUpdatedFrame == thisFrame) { return; } - + if (m_preCullOnceFrame == thisFrame) { return; } #if UNITY_5_5_OR_NEWER - if (cam.cameraType != CameraType.Game && cam.cameraType != CameraType.VR) { return; } + if ((cam.cameraType & (CameraType.Game | CameraType.VR)) == 0) { return; } #else - if (cam.cameraType != CameraType.Game) { return; } + if ((cam.cameraType & CameraType.Game) == 0) { return; } #endif - - m_poseUpdatedFrame = thisFrame; - UpdateActiveModuleDeviceState(); + m_preCullOnceFrame = thisFrame; + BeforeRenderUpdateModule(); } #endif - private void UpdateActiveModuleDeviceState() + private void BeforeRenderUpdateModule() { - 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) + if (m_activatedModuleBase != null) { - DeactivateModule(); + m_activatedModuleBase.BeforeRenderUpdate(); } - - m_isUpdating = false; } private void DeactivateModule() @@ -311,64 +294,115 @@ private void DeactivateModule() return; } - switch (m_activatedModule) - { -#if VIU_STEAMVR - case VRModuleActiveEnum.SteamVR: -#if VIU_STEAMVR_2_0_0_OR_NEWER - SteamVR_Input.OnPosesUpdated -= OnSteamVRInputPosesUpdated; -#elif VIU_STEAMVR_2_0_0_OR_NEWER && !UNITY_2017_1_OR_NEWER - Camera.onPreCull -= OnCameraPreCull; -#elif 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: + m_delayDeactivate = false; + #if UNITY_2017_1_OR_NEWER - Application.onBeforeRender -= UpdateActiveModuleDeviceState; + Application.onBeforeRender -= BeforeRenderUpdateModule; #else - Camera.onPreCull -= OnCameraPreCull; + Camera.onPreCull -= OnCameraPreCull; #endif - break; - } + DeviceState prevState; + DeviceState currState; // copy status to from current state to previous state, and reset current state - for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) + for (uint i = 0u, imax = GetDeviceStateLength(); i < imax; ++i) { - if (m_prevStates[i].isConnected || m_currStates[i].isConnected) + if (!TryGetValidDeviceState(i, out prevState, out currState)) { continue; } + + if (prevState.isConnected || currState.isConnected) { - m_prevStates[i].CopyFrom(m_currStates[i]); - m_currStates[i].Reset(); + prevState.CopyFrom(currState); + currState.Reset(); } } + s_deviceSerialNumberTable.Clear(); + // send disconnect event - for (var i = 0u; i < MAX_DEVICE_COUNT; ++i) + SendAllDeviceConnectedEvent(); + + var deactivatedModuleBase = m_activatedModuleBase; + m_activatedModule = VRModuleActiveEnum.Uninitialized; + m_activatedModuleBase = null; + deactivatedModuleBase.OnDeactivated(); + + InvokeActiveModuleChangedEvent(VRModuleActiveEnum.Uninitialized); + } + + private void ModuleFlushDeviceState() + { + DeviceState prevState; + DeviceState currState; + + // copy status to from current state to previous state + for (uint i = 0u, imax = GetDeviceStateLength(); i < imax; ++i) + { + if (!TryGetValidDeviceState(i, out prevState, out currState)) { continue; } + + if (prevState.isConnected || currState.isConnected) + { + prevState.CopyFrom(currState); + } + } + } + + private void ModuleConnectedDeviceChanged() + { + DeviceState prevState; + DeviceState currState; + + m_delayDeactivate = true; + // send connect/disconnect event + for (uint i = 0u, imax = GetDeviceStateLength(); i < imax; ++i) { - if (m_prevStates[i].isConnected) + if (!TryGetValidDeviceState(i, out prevState, out currState)) { continue; } + + if (prevState.isConnected == currState.isConnected) { continue; } + + if (currState.isConnected) { - VRModule.InvokeDeviceConnectedEvent(i, false); + if (string.IsNullOrEmpty(currState.serialNumber)) + { + Debug.LogError("Device connected with empty serialNumber. index:" + i); + } + else if (s_deviceSerialNumberTable.ContainsKey(currState.serialNumber)) + { + Debug.LogError("Device connected with duplicate serialNumber: " + currState.serialNumber + " index:" + i + "(" + s_deviceSerialNumberTable[currState.serialNumber] + ")"); + } + else + { + s_deviceSerialNumberTable.Add(currState.serialNumber, i); + } + } + else + { + s_deviceSerialNumberTable.Remove(prevState.serialNumber); } } - var deactivatedModuleBase = m_activatedModuleBase; + SendAllDeviceConnectedEvent(); - m_activatedModule = VRModuleActiveEnum.Uninitialized; - m_activatedModuleBase = null; + m_delayDeactivate = false; + if (m_isDestoryed) + { + DeactivateModule(); + } + } - deactivatedModuleBase.OnDeactivated(); + private void SendAllDeviceConnectedEvent() + { + DeviceState prevState; + DeviceState currState; + + for (uint i = 0u, imax = GetDeviceStateLength(); i < imax; ++i) + { + if (!TryGetValidDeviceState(i, out prevState, out currState)) { continue; } - VRModule.InvokeActiveModuleChangedEvent(VRModuleActiveEnum.Uninitialized); + if (prevState.isConnected != currState.isConnected) + { + InvokeDeviceConnectedEvent(i, currState.isConnected); + } + } } } } \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs index 9d758f76..ba554bb4 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs @@ -5,6 +5,7 @@ using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.Serialization; +using GrabberPool = HTC.UnityPlugin.Utility.ObjectPool; // demonstrate of dragging things useing built in EventSystem handlers public class Draggable : GrabbableBase @@ -18,13 +19,13 @@ public class UnityEventDraggable : UnityEvent { } public class Grabber : IGrabber { - private static ObjectPool m_pool; + private static GrabberPool m_pool; public static Grabber Get(PointerEventData eventData) { if (m_pool == null) { - m_pool = new ObjectPool(() => new Grabber()); + m_pool = new GrabberPool(() => new Grabber()); } var grabber = m_pool.Get(); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUProjectSettings.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUProjectSettings.cs index 853d1a4d..e24178fc 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUProjectSettings.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUProjectSettings.cs @@ -1,6 +1,7 @@ //========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== using System.Collections.Generic; +using System.IO; using UnityEditor; using UnityEngine; @@ -10,6 +11,7 @@ public class VIUProjectSettings : ScriptableObject, ISerializationCallbackReceiv { private static VIUProjectSettings s_instance = null; private static string s_defaultAssetPath; + private static string s_partialActionDirPath; [SerializeField] private List m_ignoreKeys; @@ -45,6 +47,21 @@ public static string defaultAssetPath } } + public static string partialActionDirPath + { + get + { + if (string.IsNullOrEmpty(s_partialActionDirPath)) + { + s_partialActionDirPath = Path.GetFullPath(Path.GetDirectoryName(defaultAssetPath) + "/../Misc/SteamVRExtension/PartialInputBindings"); + } + + return s_partialActionDirPath; + } + } + + public static string partialActionFileName { get { return "actions.json"; } } + public static bool hasChanged { get { return Instance.m_isDirty; } } public void OnBeforeSerialize() diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUSettingsEditor.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUSettingsEditor.cs index 23202258..450e69e6 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUSettingsEditor.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUSettingsEditor.cs @@ -680,6 +680,13 @@ public static void SetGraphicsAPI(BuildTarget buildTarget, params GraphicsDevice [PreferenceItem("VIU Settings")] private static void OnVIUPreferenceGUI() { +#if UNITY_2017_1_OR_NEWER + if (EditorApplication.isCompiling) + { + EditorGUILayout.LabelField("Compiling..."); + return; + } +#endif if (s_labelStyle == null) { s_labelStyle = new GUIStyle(EditorStyles.label); @@ -693,7 +700,9 @@ private static void OnVIUPreferenceGUI() s_scrollValue = EditorGUILayout.BeginScrollView(s_scrollValue); EditorGUILayout.LabelField("VIVE Input Utility v" + VIUVersion.current + "", s_labelStyle); + EditorGUI.BeginChangeCheck(); VIUSettings.autoCheckNewVIUVersion = EditorGUILayout.ToggleLeft("Auto Check Latest Version", VIUSettings.autoCheckNewVIUVersion); + s_guiChanged |= EditorGUI.EndChangeCheck(); GUILayout.BeginHorizontal(); ShowUrlLinkButton(URL_VIU_GITHUB_RELEASE_PAGE, "Get Latest Release"); @@ -990,7 +999,7 @@ private static void OnVIUPreferenceGUI() { EditorGUI.indentLevel += 2; - VIUSettings.waveVRAddVirtualArmTo3DoFController = EditorGUILayout.ToggleLeft(new GUIContent("Add Airtual Arm for 3 Dof Controller"), VIUSettings.waveVRAddVirtualArmTo3DoFController); + VIUSettings.waveVRAddVirtualArmTo3DoFController = EditorGUILayout.ToggleLeft(new GUIContent("Add Virtual Arm for 3 Dof Controller"), VIUSettings.waveVRAddVirtualArmTo3DoFController); if (!VIUSettings.waveVRAddVirtualArmTo3DoFController) { GUI.enabled = false; } { EditorGUI.indentLevel++; @@ -1201,6 +1210,74 @@ private static void OnVIUPreferenceGUI() GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); + //if (GUILayout.Button("Create Partial Action Set", GUILayout.ExpandWidth(false))) + //{ + // var actionFile = new SteamVRExtension.VIUSteamVRActionFile() + // { + // dirPath = VIUProjectSettings.partialActionDirPath, + // fileName = VIUProjectSettings.partialActionFileName, + // }; + + // actionFile.action_sets.Add(new SteamVRExtension.VIUSteamVRActionFile.ActionSet() + // { + // name = SteamVRModule.ACTION_SET_NAME, + // usage = "leftright", + // }); + + // actionFile.localization.Add(new SteamVRExtension.VIUSteamVRActionFile.Localization() + // { + // { "language_tag", "en_US" }, + // }); + + // SteamVRModule.InitializePaths(); + // for (SteamVRModule.pressActions.Reset(); SteamVRModule.pressActions.IsCurrentValid(); SteamVRModule.pressActions.MoveNext()) + // { + // if (string.IsNullOrEmpty(SteamVRModule.pressActions.CurrentPath)) { continue; } + // actionFile.actions.Add(new SteamVRExtension.VIUSteamVRActionFile.Action() + // { + // name = SteamVRModule.pressActions.CurrentPath, + // type = SteamVRModule.pressActions.DataType, + // requirement = "optional", + // }); + // actionFile.localization[0].Add(SteamVRModule.pressActions.CurrentPath, SteamVRModule.pressActions.CurrentAlias); + // } + // for (SteamVRModule.touchActions.Reset(); SteamVRModule.touchActions.IsCurrentValid(); SteamVRModule.touchActions.MoveNext()) + // { + // if (string.IsNullOrEmpty(SteamVRModule.touchActions.CurrentPath)) { continue; } + // actionFile.actions.Add(new SteamVRExtension.VIUSteamVRActionFile.Action() + // { + // name = SteamVRModule.touchActions.CurrentPath, + // type = SteamVRModule.touchActions.DataType, + // requirement = "optional", + // }); + // actionFile.localization[0].Add(SteamVRModule.touchActions.CurrentPath, SteamVRModule.touchActions.CurrentAlias); + // } + // for (SteamVRModule.v1Actions.Reset(); SteamVRModule.v1Actions.IsCurrentValid(); SteamVRModule.v1Actions.MoveNext()) + // { + // if (string.IsNullOrEmpty(SteamVRModule.v1Actions.CurrentPath)) { continue; } + // actionFile.actions.Add(new SteamVRExtension.VIUSteamVRActionFile.Action() + // { + // name = SteamVRModule.v1Actions.CurrentPath, + // type = SteamVRModule.v1Actions.DataType, + // requirement = "optional", + // }); + // actionFile.localization[0].Add(SteamVRModule.v1Actions.CurrentPath, SteamVRModule.v1Actions.CurrentAlias); + // } + // for (SteamVRModule.v2Actions.Reset(); SteamVRModule.v2Actions.IsCurrentValid(); SteamVRModule.v2Actions.MoveNext()) + // { + // if (string.IsNullOrEmpty(SteamVRModule.v2Actions.CurrentPath)) { continue; } + // actionFile.actions.Add(new SteamVRExtension.VIUSteamVRActionFile.Action() + // { + // name = SteamVRModule.v2Actions.CurrentPath, + // type = SteamVRModule.v2Actions.DataType, + // requirement = "optional", + // }); + // actionFile.localization[0].Add(SteamVRModule.v2Actions.CurrentPath, SteamVRModule.v2Actions.CurrentAlias); + // } + + // actionFile.Save(); + //} + EditorGUILayout.EndScrollView(); } diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUVersionCheck.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUVersionCheck.cs index ff3a27a2..e692ab91 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUVersionCheck.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Editor/VIUVersionCheck.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using UnityEditor; #if UNITY_5_4_OR_NEWER @@ -13,6 +14,10 @@ using UnityEditorInternal; using UnityEngine; using UnityEngine.Rendering; +#if VIU_STEAMVR_2_0_0_OR_NEWER +using Valve.VR; +using HTC.UnityPlugin.Vive.SteamVRExtension; +#endif namespace HTC.UnityPlugin.Vive { @@ -115,6 +120,108 @@ public void DeleteIgnore() } } +#if VIU_STEAMVR_2_0_0_OR_NEWER + private class RecommendedSteamVRInputFileSettings : RecommendedSetting + { + private readonly string m_mainDirPath; + private readonly string m_partialDirPath; + private readonly string m_partialFileName = "actions.json"; + private DateTime m_mainFileVersion; + private DateTime m_partialFileVersion; + private bool m_lastCheckMergedResult; + + private string mainFileName { get { return SteamVR_Settings.instance.actionsFilePath; } } + + private string exampleDirPath + { + get + { + var monoScripts = MonoImporter.GetAllRuntimeMonoScripts(); + var monoScript = monoScripts.FirstOrDefault(script => script.GetClass() == typeof(SteamVR_Input)); + return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(AssetDatabase.GetAssetPath(monoScript)), SteamVR_CopyExampleInputFiles.exampleJSONFolderName)); + } + } + + public RecommendedSteamVRInputFileSettings() + { + m_mainDirPath = Path.GetFullPath(Application.dataPath + "/../"); + m_partialDirPath = VIUProjectSettings.partialActionDirPath; + m_partialFileName = VIUProjectSettings.partialActionFileName; + + settingTitle = "Apply VIU Action Set for SteamVR Input"; + skipCheckFunc = () => !VIUSettingsEditor.canSupportOpenVR; + currentValueFunc = IsMerged; + setValueFunc = Merge; + recommendedValue = true; + } + + private bool IsMerged() + { + VIUSteamVRActionFile mainFile; + VIUSteamVRActionFile partialFile; + + if (!VIUSteamVRActionFile.TryLoad(m_mainDirPath, mainFileName, out mainFile)) { return false; } + if (!VIUSteamVRActionFile.TryLoad(m_partialDirPath, m_partialFileName, out partialFile)) { return true; } + + if (m_mainFileVersion != mainFile.lastWriteTime || m_partialFileVersion != partialFile.lastWriteTime) + { + m_mainFileVersion = mainFile.lastWriteTime; + m_partialFileVersion = partialFile.lastWriteTime; + m_lastCheckMergedResult = mainFile.IsMerged(partialFile); + } + + return m_lastCheckMergedResult; + } + + private void Merge(bool value) + { + if (!value) { return; } + + VIUSteamVRActionFile mainFile; + VIUSteamVRActionFile exampleFile; + VIUSteamVRActionFile partialFile; + + if (SteamVR_Input.actionFile != null) + { + GetWindow(false, "SteamVR Input", true).Close(); + } + + if (!VIUSteamVRActionFile.TryLoad(m_partialDirPath, m_partialFileName, out partialFile)) { return; } + + VIUSteamVRActionFile.TryLoad(m_mainDirPath, mainFileName, out mainFile); + VIUSteamVRActionFile.TryLoad(exampleDirPath, mainFileName, out exampleFile); + + if (exampleFile != null && (mainFile == null || !mainFile.IsMerged(exampleFile))) + { + if (EditorUtility.DisplayDialog("Import SteamVR Example Inputs", "Would you also like to import SteamVR Example Input File? Click yes if you want SteamVR plugin example scene to work.", "Yes", "No")) + { + if (mainFile == null) + { + mainFile = exampleFile; + } + else + { + mainFile.Merge(exampleFile); + } + + EditorPrefs.SetBool(SteamVR_CopyExampleInputFiles.steamVRInputExampleJSONCopiedKey, true); + } + } + + mainFile.Merge(partialFile); + mainFile.Save(m_mainDirPath); + + m_mainFileVersion = m_partialFileVersion = default(DateTime); + + EditorApplication.delayCall += () => + { + GetWindow(false, "SteamVR Input", true); + SteamVR_Input_Generator.BeginGeneration(); + }; + } + } +#endif + public const string lastestVersionUrl = "https://api.github.com/repos/ViveSoftware/ViveInputUtility-Unity/releases/latest"; public const string pluginUrl = "https://github.com/ViveSoftware/ViveInputUtility-Unity/releases"; public const double versionCheckIntervalMinutes = 30.0; @@ -791,6 +898,10 @@ private static void InitializeSettins() recommendedValue = true, }); #endif + +#if VIU_STEAMVR_2_0_0_OR_NEWER + s_settings.Add(new RecommendedSteamVRInputFileSettings()); +#endif } private static void WrightVersionCheckLog(string msg) @@ -1000,6 +1111,13 @@ private string GetResourcePath() public void OnGUI() { +#if UNITY_2017_1_OR_NEWER + if (EditorApplication.isCompiling) + { + EditorGUILayout.LabelField("Compiling..."); + return; + } +#endif if (viuLogo == null) { var currentDir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this))); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs index 75744625..5296a782 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs @@ -6,6 +6,7 @@ using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; +using GrabberPool = HTC.UnityPlugin.Utility.ObjectPool; namespace HTC.UnityPlugin.Vive { @@ -21,13 +22,13 @@ public class UnityEventGrabbable : UnityEvent { } public class Grabber : IGrabber { - private static ObjectPool m_pool; + private static GrabberPool m_pool; public static Grabber Get(ColliderButtonEventData eventData) { if (m_pool == null) { - m_pool = new ObjectPool(() => new Grabber()); + m_pool = new GrabberPool(() => new Grabber()); } var grabber = m_pool.Get(); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs index d2961aae..9ecafc73 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs @@ -195,19 +195,20 @@ private static void ResolveDefaultExCam() SteamVR_Render.instance.externalCameraConfigPath = string.Empty; +#if !VIU_STEAMVR_2_0_0_OR_NEWER var oldExternalCam = SteamVR_Render.instance.externalCamera; if (oldExternalCam != null) { -#if VIU_STEAMVR_2_0_0_OR_NEWER - if (oldExternalCam.transform.parent != null) -#else + // FIXME: SteamVR_ControllerManager is removed in SteamVR 2.0, what to replace? if (oldExternalCam.transform.parent != null && oldExternalCam.transform.parent.GetComponent() != null) -#endif + { Destroy(oldExternalCam.transform.parent.gameObject); SteamVR_Render.instance.externalCamera = null; } + } +#endif } private void OnEnable() diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs index 063253cc..d4334c27 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/RenderModelHook.cs @@ -110,10 +110,7 @@ protected virtual void OnDisable() VRModule.onActiveModuleChanged -= UpdateModel; m_viveRole.onDeviceIndexChanged -= OnDeviceIndexChanged; - if (!m_isQuiting) - { - UpdateModel(); - } + UpdateModel(); } private void OnApplicationQuit() @@ -151,6 +148,8 @@ private void OnDeviceIndexChanged(uint deviceIndex) private void UpdateModel() { + if (m_isQuiting) { return; } + var overrideModelChanged = ChangeProp.Set(ref m_currentOverrideModel, m_overrideModel); if (m_currentOverrideModel == OverrideModelEnum.DontOverride) @@ -193,7 +192,7 @@ private void UpdateModel() } #if VIU_STEAMVR - private SteamVR_RenderModel m_renderModel; + private VIUSteamVRRenderModel m_renderModel; private void UpdateSteamVRModel() { @@ -211,7 +210,7 @@ private void UpdateSteamVRModel() // find SteamVR_RenderModel in child object for (int i = 0, imax = transform.childCount; i < imax; ++i) { - if ((m_renderModel = GetComponentInChildren()) != null) + if ((m_renderModel = GetComponentInChildren()) != null) { m_modelObj = m_renderModel.gameObject; break; @@ -222,17 +221,17 @@ private void UpdateSteamVRModel() { m_modelObj = new GameObject("Model"); m_modelObj.transform.SetParent(transform, false); - m_renderModel = m_modelObj.AddComponent(); + m_renderModel = m_modelObj.AddComponent(); } if (m_overrideShader != null) { - m_renderModel.shader = m_overrideShader; + m_renderModel.shaderOverride = m_overrideShader; } } m_modelObj.SetActive(true); - m_renderModel.SetDeviceIndex((int)m_currentDeviceIndex); + m_renderModel.SetDeviceIndex(m_currentDeviceIndex); } else { @@ -385,18 +384,24 @@ private void UpdateDefaultModel() { if (VRModule.IsValidDeviceIndex(m_currentDeviceIndex)) { - if (ChangeProp.Set(ref m_currentLoadedStaticModel, VRModule.GetCurrentDeviceState(m_currentDeviceIndex).deviceModel) || m_modelObj == null) + if (ChangeProp.Set(ref m_currentLoadedStaticModel, VRModule.GetCurrentDeviceState(m_currentDeviceIndex).deviceModel)) { ReloadedStaticModel(m_currentLoadedStaticModel); } else { - m_modelObj.SetActive(true); + if (m_modelObj != null) + { + m_modelObj.SetActive(true); + } } } else { - m_modelObj.SetActive(false); + if (m_modelObj != null) + { + m_modelObj.SetActive(false); + } } } } diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension.meta new file mode 100644 index 00000000..60b49a70 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5fb8f04ff35142047a6735b76350f13b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor.meta new file mode 100644 index 00000000..57d3fe92 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 944deec9325e4d148b31cc1f16621dd6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs new file mode 100644 index 00000000..bd84014b --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs @@ -0,0 +1,228 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +#if VIU_STEAMVR_2_0_0_OR_NEWER +using System; +using System.Collections.Generic; +using Valve.Newtonsoft.Json; + +namespace HTC.UnityPlugin.Vive.SteamVRExtension +{ + [Serializable] + public class VIUSteamVRActionFile : VIUSteamVRLoadJsonFileBase + { + public List actions = new List(); + public List action_sets = new List(); + public List default_bindings = new List(); + public List localization = new List(); + + [JsonIgnore] + private MergableDictionary m_actionTable; + [JsonIgnore] + private MergableDictionary m_actionSetTable; + [JsonIgnore] + private MergableDictionary m_defaultBindingTable; + [JsonIgnore] + private MergableDictionary m_localizationTable; + [JsonIgnore] + private MergableDictionary m_bindingFiles; + + protected override void OnAfterLoaded() + { + m_actionTable = actions.ToMergableDictionary(); + m_actionSetTable = action_sets.ToMergableDictionary(); + m_defaultBindingTable = default_bindings.ToMergableDictionary(); + m_localizationTable = localization.ToMergableDictionary(); + + m_actionTable.onNewItemWhenMerge += item => actions.Add(item); + m_actionSetTable.onNewItemWhenMerge += item => action_sets.Add(item); + m_defaultBindingTable.onNewItemWhenMerge += item => default_bindings.Add(item); + m_localizationTable.onNewItemWhenMerge += item => localization.Add(item); + + // load binding files + m_bindingFiles = new MergableDictionary(); + m_bindingFiles.onNewItemWhenMerge += item => item.dirPath = dirPath; + foreach (var pair in m_defaultBindingTable) + { + var controllerType = pair.Key; + var bindingUrl = pair.Value.binding_url; + + VIUSteamVRBindingFile bindingFile; + if (VIUSteamVRBindingFile.TryLoad(dirPath, bindingUrl, out bindingFile)) + { + m_bindingFiles.Add(controllerType, bindingFile); + } + else + { + UnityEngine.Debug.LogWarning("Missing default bindings file for " + controllerType + ":" + System.IO.Path.Combine(dirPath, bindingUrl) + "!"); + } + } + } + + public bool IsMerged(VIUSteamVRActionFile dst) + { + if (!m_actionTable.IsMerged(dst.m_actionTable)) { return false; } + if (!m_actionSetTable.IsMerged(dst.m_actionSetTable)) { return false; } + if (!m_defaultBindingTable.IsMerged(dst.m_defaultBindingTable)) { return false; } + if (!m_localizationTable.IsMerged(dst.m_localizationTable)) { return false; } + if (!m_bindingFiles.IsMerged(dst.m_bindingFiles)) { return false; } + return true; + } + + public void Merge(VIUSteamVRActionFile dst) + { + m_actionTable.Merge(dst.m_actionTable); + m_actionSetTable.Merge(dst.m_actionSetTable); + m_defaultBindingTable.Merge(dst.m_defaultBindingTable); + m_localizationTable.Merge(dst.m_localizationTable); + m_bindingFiles.Merge(dst.m_bindingFiles); + } + + protected override void OnBeforeSave(string dirPash) + { + if (m_bindingFiles == null || m_bindingFiles.Count == 0) { return; } + foreach (var pair in m_bindingFiles) + { + var bindingFile = pair.Value; + bindingFile.Save(dirPash); + } + } + + [Serializable] + public class Action : IMergable, IStringKey + { + public string name; + public string type; + public string scope; + public string skeleton; + public string requirement; + + [JsonIgnore] + public string stringKey { get { return name; } } + + public bool IsMerged(Action obj) + { + if (name != obj.name) { return false; } + if (type != obj.type) { return false; } + if (scope != obj.scope) { return false; } + if (skeleton != obj.skeleton) { return false; } + if (requirement != obj.requirement) { return false; } + return true; + } + + public void Merge(Action obj) + { + type = obj.type; + scope = obj.scope; + skeleton = obj.skeleton; + requirement = obj.requirement; + } + + public Action Copy() + { + return new Action() + { + name = name, + type = type, + scope = scope, + skeleton = skeleton, + requirement = requirement, + }; + } + } + + [Serializable] + public class ActionSet : IMergable, IStringKey + { + public string name; + public string usage; + + [JsonIgnore] + public string stringKey { get { return name; } } + + public bool IsMerged(ActionSet obj) + { + if (name != obj.name) { return false; } + if (usage != obj.usage) { return false; } + return true; + } + + public void Merge(ActionSet obj) + { + usage = obj.usage; + } + + public ActionSet Copy() + { + return new ActionSet() + { + name = name, + usage = usage, + }; + } + } + + [Serializable] + public class DefaultBinding : IMergable, IStringKey + { + public string controller_type; + public string binding_url; + + [JsonIgnore] + public string stringKey { get { return controller_type; } } + + public bool IsMerged(DefaultBinding obj) + { + if (controller_type != obj.controller_type) { return false; } + return true; + } + + public void Merge(DefaultBinding obj) + { + // do nothing, don't override path, use old one + } + + public DefaultBinding Copy() + { + return new DefaultBinding() + { + controller_type = controller_type, + binding_url = binding_url, + }; + } + } + + [Serializable] + public class Localization : MergableDictionary, IMergable, IStringKey + { + [JsonIgnore] + public string stringKey + { + get + { + string lang; + return TryGetValue("language_tag", out lang) ? lang : string.Empty; + } + } + + public Localization() : base() { } + + public Localization(Localization src) : base(src) { } + + public bool IsMerged(Localization obj) + { + return ((MergableDictionary)this).IsMerged(obj); + } + + Localization IMergable.Copy() + { + return new Localization(this); + } + + public void Merge(Localization obj) + { + ((MergableDictionary)this).Merge(obj); + } + } + } +} +#endif \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs.meta new file mode 100644 index 00000000..ded38480 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRActionFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7396a895f6aa9584998a6012e966b5c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs new file mode 100644 index 00000000..626f8992 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs @@ -0,0 +1,166 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +#if VIU_STEAMVR_2_0_0_OR_NEWER +using System; + +namespace HTC.UnityPlugin.Vive.SteamVRExtension +{ + [Serializable] + public class VIUSteamVRBindingFile : VIUSteamVRLoadJsonFileBase, IMergable + { + public string app_key; + public string controller_type; + public string description; + public string name; + public MergableDictionary bindings = new MergableDictionary(); + + public bool IsMerged(VIUSteamVRBindingFile dst) + { + if (!bindings.IsMerged(dst.bindings)) { return false; } + return true; + } + + public void Merge(VIUSteamVRBindingFile dst) + { + bindings.Merge(dst.bindings); + } + + public VIUSteamVRBindingFile Copy() + { + return new VIUSteamVRBindingFile() + { + dirPath = dirPath, + fileName = fileName, + + app_key = app_key, + controller_type = controller_type, + description = description, + name = name, + bindings = bindings.Copy(), + }; + } + + [Serializable] + public class ActionList : IMergable + { + public OverridableList chords = new OverridableList(); + public OverridableList sources = new OverridableList(); + public OverridableList poses = new OverridableList(); + public OverridableList haptics = new OverridableList(); + public OverridableList skeleton = new OverridableList(); + + public bool IsMerged(ActionList obj) + { + if (!chords.IsMerged(obj.chords)) { return false; } + if (!sources.IsMerged(obj.sources)) { return false; } + if (!poses.IsMerged(obj.poses)) { return false; } + if (!haptics.IsMerged(obj.haptics)) { return false; } + if (!skeleton.IsMerged(obj.skeleton)) { return false; } + return true; + } + + public ActionList Copy() + { + return new ActionList() + { + chords = chords.Copy(), + poses = poses.Copy(), + haptics = haptics.Copy(), + sources = sources.Copy(), + skeleton = skeleton.Copy(), + }; + } + + public void Merge(ActionList obj) + { + chords.Merge(obj.chords); + sources.Merge(obj.sources); + poses.Merge(obj.poses); + haptics.Merge(obj.haptics); + skeleton.Merge(obj.skeleton); + } + + [Serializable] + public class Chords : IMergable + { + public string output; + public OverridableDictionary inputs = new OverridableDictionary(); + + public bool IsMerged(Chords obj) + { + if (output != obj.output) { return false; } + if (!inputs.IsMerged(obj.inputs)) { return false; } + return true; + } + + public Chords Copy() + { + return new Chords() + { + output = output, + inputs = inputs.Copy(), + }; + } + + public void Merge(Chords obj) { throw new NotImplementedException(); } + } + + [Serializable] + public class Source : IMergable + { + public string path; + public string mode; + public OverridableDictionary parameters = new OverridableDictionary(); + public OverridableDictionary inputs = new OverridableDictionary(); + + public bool IsMerged(Source obj) + { + if (path != obj.path) { return false; } + if (mode != obj.mode) { return false; } + if (!parameters.IsMerged(obj.parameters)) { return false; } + if (!inputs.IsMerged(obj.inputs)) { return false; } + return true; + } + + public Source Copy() + { + return new Source() + { + path = path, + mode = mode, + parameters = parameters.Copy(), + inputs = inputs.Copy(), + }; + } + + public void Merge(Source obj) { throw new NotImplementedException(); } + } + + [Serializable] + public class StandardBinding : IMergable + { + public string output; + public string path; + + public bool IsMerged(StandardBinding obj) + { + if (output != obj.output) { return false; } + if (path != obj.path) { return false; } + return true; + } + + public StandardBinding Copy() + { + return new StandardBinding() + { + output = output, + path = path, + }; + } + + public void Merge(StandardBinding obj) { throw new NotImplementedException(); } + } + } + } +} +#endif \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs.meta new file mode 100644 index 00000000..0c8e7e3d --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRBindingFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5645441d9f4d8b94980d01d300678bed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs new file mode 100644 index 00000000..b9c915fb --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs @@ -0,0 +1,416 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +#if VIU_STEAMVR_2_0_0_OR_NEWER +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using Valve.Newtonsoft.Json; + +namespace HTC.UnityPlugin.Vive.SteamVRExtension +{ + [Serializable] + public class VIUSteamVRLoadJsonFileBase where T : VIUSteamVRLoadJsonFileBase + { + private static Dictionary s_fileCache; + + [JsonIgnore] + public string dirPath { get; set; } + [JsonIgnore] + public string fileName { get; set; } + [JsonIgnore] + public string fullPath { get { return Path.Combine(dirPath, fileName); } } + [JsonIgnore] + public DateTime lastWriteTime { get; private set; } + + public static bool TryLoad(string dirPath, string fileName, out T file, bool force = false) + { + try + { + var fullPath = Path.Combine(dirPath, fileName); + if (!File.Exists(fullPath)) { file = null; return false; } + + var lastWriteTime = File.GetLastWriteTime(fullPath); + + // check cached file + if (!force && s_fileCache != null && s_fileCache.TryGetValue(fullPath, out file)) + { + if (file.lastWriteTime == lastWriteTime) + { + return true; + } + } + + file = JsonConvert.DeserializeObject(File.ReadAllText(fullPath)); + file.dirPath = dirPath; + file.fileName = fileName; + file.lastWriteTime = lastWriteTime; + + if (s_fileCache == null) { s_fileCache = new Dictionary() { { fullPath, file } }; } + else { s_fileCache[fullPath] = file; } + + file.OnAfterLoaded(); + return true; + } + catch (Exception e) + { + Debug.LogError(e); + if (s_fileCache != null) { s_fileCache.Clear(); } + file = null; + return false; + } + } + + protected virtual void OnAfterLoaded() { } + + public void Save() { Save(dirPath); } + + public void Save(string dirPath) + { + if (string.IsNullOrEmpty(dirPath)) + { + Debug.LogWarning("dirPath is empty"); + return; + } + + if (string.IsNullOrEmpty(fileName)) + { + Debug.LogWarning("fileName is empty"); + return; + } + + try + { + OnBeforeSave(dirPath); + + var json = JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + File.WriteAllText(Path.Combine(dirPath, fileName), json); + + } + catch (Exception e) + { + Debug.LogError(e); + } + } + + protected virtual void OnBeforeSave(string dirPash) { } + } + + public interface IStringKey + { + string stringKey { get; } + } + + public interface IMergable + { + bool IsMerged(T obj); + void Merge(T obj); + T Copy(); + } + + [Serializable] + public class MergableDictionary : Dictionary, IMergable> where T : IMergable + { + public event Action onNewItemWhenMerge; + + public MergableDictionary() : base() { } + + public MergableDictionary(MergableDictionary src) : base(src) { } + + public bool IsMerged(MergableDictionary obj) + { + if (this == obj) { return true; } + + foreach (var pair in obj) + { + T srcV; + if (!TryGetValue(pair.Key, out srcV)) { return false; } + + if (!srcV.IsMerged(pair.Value)) { return false; } + } + + return true; + } + + public MergableDictionary Copy() + { + return new MergableDictionary(this); + } + + public void Merge(MergableDictionary obj) + { + if (this == obj) { return; } + + foreach (var pair in obj) + { + T srcV; + if (!TryGetValue(pair.Key, out srcV)) + { + srcV = pair.Value.Copy(); + Add(pair.Key, srcV); + if (onNewItemWhenMerge != null) { onNewItemWhenMerge(srcV); } + } + else + { + srcV.Merge(pair.Value); + } + } + } + } + + [Serializable] + public class OverridableDictionary : Dictionary, IMergable> where T : IMergable + { + public OverridableDictionary() : base() { } + + public OverridableDictionary(OverridableDictionary src) : base(src) { } + + public bool IsMerged(OverridableDictionary obj) + { + if (this == obj) { return true; } + if (Count != obj.Count) { return false; } + + foreach (var pair in obj) + { + T srcV; + if (!TryGetValue(pair.Key, out srcV)) { return false; } + + if (!srcV.IsMerged(pair.Value)) { return false; } + } + + return true; + } + + public OverridableDictionary Copy() + { + return new OverridableDictionary(this); + } + + public void Merge(OverridableDictionary obj) + { + if (this == obj) { return; } + + Clear(); + foreach (var pair in obj) + { + Add(pair.Key, pair.Value.Copy()); + } + } + } + + [Serializable] + public class MergableList : List, IMergable> where T : IMergable + { + private static List s_checkList; + + private void ResetCheckList() + { + if (s_checkList == null) + { + s_checkList = new List(); + } + else + { + s_checkList.Clear(); + } + + foreach (var item in this) { s_checkList.Add(false); } + } + + private bool FoundInCheckList(T item) + { + for (int i = 0, imax = s_checkList.Count; i < imax; ++i) + { + if (s_checkList[i]) { continue; } + + if (this[i].IsMerged(item)) + { + s_checkList[i] = true; + return true; + } + } + return false; + } + + public MergableList() : base() { } + + public MergableList(MergableList src) : base(src) { } + + public bool IsMerged(MergableList obj) + { + if (this == obj) { return true; } + + ResetCheckList(); + + foreach (var item in obj) + { + if (!FoundInCheckList(item)) { return false; } + } + + return true; + } + + public MergableList Copy() + { + return new MergableList(this); + } + + public void Merge(MergableList obj) + { + if (this == obj) { return; } + + ResetCheckList(); + + foreach (var item in obj) + { + if (!FoundInCheckList(item)) { Add(item.Copy()); } + } + } + } + + [Serializable] + public class OverridableList : MergableList, IMergable> where T : IMergable + { + public OverridableList() : base() { } + + public OverridableList(OverridableList src) : base(src) { } + + public bool IsMerged(OverridableList obj) + { + if (this == obj) { return true; } + if (Count != obj.Count) { return false; } + return base.IsMerged(obj); + } + + public new OverridableList Copy() + { + return new OverridableList(this); + } + + public void Merge(OverridableList obj) + { + if (this == obj) { return; } + + Clear(); + foreach (var item in obj) + { + Add(item.Copy()); + } + } + } + + [Serializable] + public class MergableDictionary : Dictionary, IMergable + { + public event Action onNewItemWhenMerge; + + public MergableDictionary() : base() { } + + public MergableDictionary(MergableDictionary src) : base(src) { } + + public bool IsMerged(MergableDictionary obj) + { + if (this == obj) { return true; } + + foreach (var pair in obj) + { + string srcV; + if (!TryGetValue(pair.Key, out srcV)) { return false; } + + if (srcV != pair.Value) { return false; } + } + + return true; + } + + public MergableDictionary Copy() + { + return new MergableDictionary(this); + } + + public void Merge(MergableDictionary obj) + { + if (this == obj) { return; } + + foreach (var pair in obj) + { + string srcV; + if (!TryGetValue(pair.Key, out srcV)) + { + srcV = pair.Value; + Add(pair.Key, srcV); + if (onNewItemWhenMerge != null) { onNewItemWhenMerge(srcV); } + } + else + { + this[pair.Key] = pair.Value; + } + } + } + } + + [Serializable] + public class OverridableDictionary : Dictionary, IMergable + { + public OverridableDictionary() : base() { } + + public OverridableDictionary(OverridableDictionary src) : base(src) { } + + public bool IsMerged(OverridableDictionary obj) + { + if (this == obj) { return true; } + if (Count != obj.Count) { return false; } + + foreach (var pair in obj) + { + string srcV; + if (!TryGetValue(pair.Key, out srcV)) { return false; } + + if (srcV != pair.Value) { return false; } + } + + return true; + } + + public OverridableDictionary Copy() + { + return new OverridableDictionary(this); + } + + public void Merge(OverridableDictionary obj) + { + if (this == obj) { return; } + + Clear(); + foreach (var pair in obj) + { + this[pair.Key] = pair.Value; + } + } + } + + public static class SerializeExtension + { + public static MergableDictionary ToMergableDictionary(this List list) where T : IMergable, IStringKey + { + var result = new MergableDictionary(); + foreach (var item in list) + { + if (string.IsNullOrEmpty(item.stringKey)) + { + Debug.LogWarning("MergableDictionary key cannot be null"); + } + else if (result.ContainsKey(item.stringKey)) + { + Debug.LogWarning("Duplicate key(" + item.stringKey + ") found"); + } + else + { + result.Add(item.stringKey, item); + } + } + return result; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs.meta new file mode 100644 index 00000000..16ff1216 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRLoadJsonFileBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26b018b07b2f1d34bb2d1f2518fa10a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs new file mode 100644 index 00000000..b5909a27 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs @@ -0,0 +1,117 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +using System.Text; +using UnityEditor; +using UnityEngine; +#if VIU_STEAMVR +using Valve.VR; +#endif + +namespace HTC.UnityPlugin.Vive +{ + [CustomEditor(typeof(VIUSteamVRRenderModel)), CanEditMultipleObjects] + public class VIUSteamVRRenderModelEditr : Editor + { + private static GUIContent[] s_renderModelNames; + + private SerializedProperty m_scriptProp; + private SerializedProperty m_modelOverrideProp; + private SerializedProperty m_shaderOverrideProp; + private SerializedProperty m_updateDynamicallyProp; + + private int m_selectedModelIndex; + + protected virtual void OnEnable() + { + m_scriptProp = serializedObject.FindProperty("m_Script"); + m_modelOverrideProp = serializedObject.FindProperty("m_modelOverride"); + m_shaderOverrideProp = serializedObject.FindProperty("m_shaderOverride"); + m_updateDynamicallyProp = serializedObject.FindProperty("m_updateDynamically"); + + // Load render model names if necessary. + if (s_renderModelNames == null) + { + s_renderModelNames = LoadRenderModelNames(); + } + + // Update renderModelIndex based on current modelOverride value. + m_selectedModelIndex = 0; + var selectedModelName = m_modelOverrideProp.stringValue; + if (!string.IsNullOrEmpty(selectedModelName)) + { + for (int i = 1, imax = s_renderModelNames.Length; i < imax; i++) + { + if (selectedModelName == s_renderModelNames[i].text) + { + m_selectedModelIndex = i; + break; + } + } + } + } + + private static GUIContent[] LoadRenderModelNames() + { + var results = default(GUIContent[]); +#if VIU_STEAMVR + var needsShutdown = false; + var vrRenderModels = OpenVR.RenderModels; + if (vrRenderModels == null) + { + var error = EVRInitError.None; + if (!SteamVR.active && !SteamVR.usingNativeSupport) + { + OpenVR.Init(ref error, EVRApplicationType.VRApplication_Utility); + vrRenderModels = OpenVR.RenderModels; + needsShutdown = true; + } + } + + if (vrRenderModels != null) + { + var strBuilder = new StringBuilder(); + var count = vrRenderModels.GetRenderModelCount(); + results = new GUIContent[count + 1]; + results[0] = new GUIContent("None"); + + for (uint i = 0; i < count; i++) + { + var strLen = vrRenderModels.GetRenderModelName(i, strBuilder, 0); + if (strLen == 0) { continue; } + + strBuilder.EnsureCapacity((int)strLen); + vrRenderModels.GetRenderModelName(i, strBuilder, strLen); + results[i + 1] = new GUIContent(strBuilder.ToString()); + } + } + + if (needsShutdown) + { + OpenVR.Shutdown(); + } +#endif + return results == null ? new GUIContent[] { new GUIContent("None") } : results; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + GUI.enabled = false; + EditorGUILayout.PropertyField(m_scriptProp); + GUI.enabled = true; + + var selectedIndex = EditorGUILayout.Popup(new GUIContent("Model Override", VIUSteamVRRenderModel.MODEL_OVERRIDE_WARNNING), m_selectedModelIndex, s_renderModelNames); + if (selectedIndex != m_selectedModelIndex) + { + m_selectedModelIndex = selectedIndex; + m_modelOverrideProp.stringValue = selectedIndex == 0 ? string.Empty : s_renderModelNames[selectedIndex].text; + } + + EditorGUILayout.PropertyField(m_shaderOverrideProp); + EditorGUILayout.PropertyField(m_updateDynamicallyProp); + + serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs.meta new file mode 100644 index 00000000..1e54c537 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/Editor/VIUSteamVRRenderModelEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9e021993f4995244a993c9ea9116761d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings.meta new file mode 100644 index 00000000..02308693 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e8b05c9946c6cdf479952d366a19fccd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json new file mode 100644 index 00000000..390293fb --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json @@ -0,0 +1,327 @@ +{ + "actions": [ + { + "name": "/actions/htc_viu/in/viu_press_00", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_01", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_02", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_03", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_04", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_05", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_06", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_07", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_31", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_32", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_33", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_press_34", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_00", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_01", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_02", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_03", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_04", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_05", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_06", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_07", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_31", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_32", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_33", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_touch_34", + "type": "boolean", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_0x", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_0y", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_1x", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_1y", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_2x", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_2y", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_3x", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_3y", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_4x", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_4y", + "type": "vector1", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_0xy", + "type": "vector2", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_1xy", + "type": "vector2", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_2xy", + "type": "vector2", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_3xy", + "type": "vector2", + "requirement": "optional" + }, + { + "name": "/actions/htc_viu/in/viu_axis_4xy", + "type": "vector2", + "requirement": "optional" + } + ], + "action_sets": [ + { + "name": "/actions/htc_viu", + "usage": "leftright" + } + ], + "default_bindings": [ + { + "controller_type": "holographic_hmd", + "binding_url": "binding_holographic_hmd.json" + }, + { + "controller_type": "holographic_controller", + "binding_url": "bindings_holographic_controller.json" + }, + { + "controller_type": "rift", + "binding_url": "bindings_rift.json" + }, + { + "controller_type": "oculus_touch", + "binding_url": "bindings_oculus_touch.json" + }, + { + "controller_type": "knuckles", + "binding_url": "bindings_knuckles.json" + }, + { + "controller_type": "vive", + "binding_url": "bindings_vive.json" + }, + { + "controller_type": "vive_pro", + "binding_url": "bindings_vive_pro.json" + }, + { + "controller_type": "vive_controller", + "binding_url": "bindings_vive_controller.json" + }, + { + "controller_type": "vive_tracker", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_handed", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_left_foot", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_right_foot", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_left_shoulder", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_right_shoulder", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_waist", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_chest", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_gamepad", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_camera", + "binding_url": "bindings_vive_tracker.json" + }, + { + "controller_type": "vive_tracker_keyboard", + "binding_url": "bindings_vive_tracker.json" + } + ], + "localization": [ + { + "language_tag": "en_US", + "/actions/htc_viu/in/viu_press_00": "Press00 (System)", + "/actions/htc_viu/in/viu_press_01": "Press01 (ApplicationMenu)", + "/actions/htc_viu/in/viu_press_02": "Press02 (Grip)", + "/actions/htc_viu/in/viu_press_03": "Press03 (DPadLeft)", + "/actions/htc_viu/in/viu_press_04": "Press04 (DPadUp)", + "/actions/htc_viu/in/viu_press_05": "Press05 (DPadRight)", + "/actions/htc_viu/in/viu_press_06": "Press06 (DPadDown)", + "/actions/htc_viu/in/viu_press_07": "Press07 (A)", + "/actions/htc_viu/in/viu_press_31": "Press31 (ProximitySensor)", + "/actions/htc_viu/in/viu_press_32": "Press32 (Touchpad)", + "/actions/htc_viu/in/viu_press_33": "Press33 (Trigger)", + "/actions/htc_viu/in/viu_press_34": "Press34 (CapSenseGrip)", + "/actions/htc_viu/in/viu_touch_00": "Touch00 (System)", + "/actions/htc_viu/in/viu_touch_01": "Touch01 (ApplicationMenu)", + "/actions/htc_viu/in/viu_touch_02": "Touch02 (Grip)", + "/actions/htc_viu/in/viu_touch_03": "Touch03 (DPadLeft)", + "/actions/htc_viu/in/viu_touch_04": "Touch04 (DPadUp)", + "/actions/htc_viu/in/viu_touch_05": "Touch05 (DPadRight)", + "/actions/htc_viu/in/viu_touch_06": "Touch06 (DPadDown)", + "/actions/htc_viu/in/viu_touch_07": "Touch07 (A)", + "/actions/htc_viu/in/viu_touch_31": "Touch31 (ProximitySensor)", + "/actions/htc_viu/in/viu_touch_32": "Touch32 (Touchpad)", + "/actions/htc_viu/in/viu_touch_33": "Touch33 (Trigger)", + "/actions/htc_viu/in/viu_touch_34": "Touch34 (CapSenseGrip)", + "/actions/htc_viu/in/viu_axis_0x": "Axis0 X (TouchpadX)", + "/actions/htc_viu/in/viu_axis_0y": "Axis0 Y (TouchpadY)", + "/actions/htc_viu/in/viu_axis_1x": "Axis1 X (Trigger)", + "/actions/htc_viu/in/viu_axis_1y": "Axis1 Y", + "/actions/htc_viu/in/viu_axis_2x": "Axis2 X (CapSenseGrip)", + "/actions/htc_viu/in/viu_axis_2y": "Axis2 Y", + "/actions/htc_viu/in/viu_axis_3x": "Axis3 X (IndexCurl)", + "/actions/htc_viu/in/viu_axis_3y": "Axis3 Y (MiddleCurl)", + "/actions/htc_viu/in/viu_axis_4x": "Axis4 X (RingCurl)", + "/actions/htc_viu/in/viu_axis_4y": "Axis4 Y (PinkyCurl)", + "/actions/htc_viu/in/viu_axis_0xy": "Axis0 X&Y (Touchpad)", + "/actions/htc_viu/in/viu_axis_1xy": "Axis1 X&Y", + "/actions/htc_viu/in/viu_axis_2xy": "Axis2 X&Y (Thumbstick)", + "/actions/htc_viu/in/viu_axis_3xy": "Axis3 X&Y", + "/actions/htc_viu/in/viu_axis_4xy": "Axis4 X&Y" + } + ] +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json.meta new file mode 100644 index 00000000..a470f7a1 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/actions.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 05ca4e26fdf42724dacba2c263f97647 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json new file mode 100644 index 00000000..979e571a --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json @@ -0,0 +1,135 @@ +{ + "controller_type": "holographic_controller", + "bindings": { + "/actions/htc_viu": { + "sources": [ + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + }, + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "trigger", + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + }, + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "trigger", + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_32" + } + }, + "mode": "trackpad", + "path": "/user/hand/left/input/trackpad" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_32" + } + }, + "mode": "trackpad", + "path": "/user/hand/right/input/trackpad" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_02" + } + }, + "mode": "button", + "path": "/user/hand/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_01" + } + }, + "mode": "button", + "path": "/user/hand/left/input/application_menu" + }, + { + "inputs": { + "position": { + "output": "/actions/htc_viu/in/viu_axis_2xy" + } + }, + "mode": "joystick", + "path": "/user/hand/left/input/joystick" + }, + { + "inputs": { + "position": { + "output": "/actions/htc_viu/in/viu_axis_2xy" + } + }, + "mode": "joystick", + "path": "/user/hand/right/input/joystick" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_01" + } + }, + "mode": "button", + "path": "/user/hand/right/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_02" + } + }, + "mode": "button", + "path": "/user/hand/right/input/grip" + } + ] + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json.meta new file mode 100644 index 00000000..8c3bb7d7 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_controller.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b9138783eeba3be41bdbaa018dc7c856 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_hmd.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_hmd.json.meta new file mode 100644 index 00000000..5294491b --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_holographic_hmd.json.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 568ed493229001f46974af3fcc6f661e +timeCreated: 1544604280 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json new file mode 100644 index 00000000..b470cc49 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json @@ -0,0 +1,4 @@ +{ + "controller_type": "knuckles", + "bindings": {} +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json.meta new file mode 100644 index 00000000..e275cac6 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_knuckles.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 01616f3a33adf5b4f84bb491b07c2214 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json new file mode 100644 index 00000000..74f3e872 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json @@ -0,0 +1,171 @@ +{ + "controller_type" : "oculus_touch", + "bindings": { + "/actions/htc_viu": { + "sources": [ + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + }, + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "trigger", + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_32" + } + }, + "mode": "joystick", + "path": "/user/hand/left/input/joystick" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_07" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_07" + } + }, + "mode": "button", + "path": "/user/hand/left/input/x" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_01" + } + }, + "mode": "button", + "path": "/user/hand/left/input/y" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + }, + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "trigger", + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_32" + } + }, + "mode": "joystick", + "path": "/user/hand/right/input/joystick" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_touch_02" + } + }, + "mode": "button", + "path": "/user/hand/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_touch_02" + } + }, + "mode": "button", + "path": "/user/hand/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_07" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_07" + } + }, + "mode": "button", + "path": "/user/hand/right/input/a" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_01" + } + }, + "mode": "button", + "path": "/user/hand/right/input/b" + }, + { + "inputs": { + "position": { + "output": "/actions/htc_viu/in/viu_axis_2xy" + } + }, + "mode": "joystick", + "path": "/user/hand/left/input/joystick" + }, + { + "inputs": { + "position": { + "output": "/actions/htc_viu/in/viu_axis_2xy" + } + }, + "mode": "joystick", + "path": "/user/hand/right/input/joystick" + } + ] + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json.meta new file mode 100644 index 00000000..1e1cb6a4 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_oculus_touch.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 355fee3a63ac5ff459016973f40e528e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_rift.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_rift.json.meta new file mode 100644 index 00000000..1121556d --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_rift.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 29e4f13e0b006684d9ef8c6a98937a65 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive.json.meta new file mode 100644 index 00000000..3fd8d6b2 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bd0ed27250acc854cb197eb0bb5d5ffa +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json new file mode 100644 index 00000000..655897c9 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json @@ -0,0 +1,241 @@ +{ + "controller_type" : "vive_controller", + "bindings": { + "/actions/htc_viu": { + "sources": [ + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/hand/right/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/hand/left/input/application_menu" + }, + { + "inputs": { + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "trigger", + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "pull": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "trigger", + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "trackpad", + "path": "/user/hand/left/input/trackpad" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + }, + "position": { + "output": "/actions/htc_viu/in/viu_axis_0xy" + }, + "touch": { + "output": "/actions/htc_viu/in/viu_touch_32" + } + }, + "mode": "trackpad", + "path": "/user/hand/right/input/trackpad" + }, + { + "inputs": { + "center": { + "output": "/actions/htc_viu/in/viu_press_07" + }, + "east": { + "output": "/actions/htc_viu/in/viu_press_03" + }, + "north": { + "output": "/actions/htc_viu/in/viu_press_04" + }, + "south": { + "output": "/actions/htc_viu/in/viu_press_06" + }, + "west": { + "output": "/actions/htc_viu/in/viu_press_03" + } + }, + "mode": "dpad", + "parameters": { + "sub_mode": "click" + }, + "path": "/user/hand/left/input/trackpad" + }, + { + "inputs": { + "center": { + "output": "/actions/htc_viu/in/viu_press_07" + }, + "east": { + "output": "/actions/htc_viu/in/viu_press_03" + }, + "north": { + "output": "/actions/htc_viu/in/viu_press_04" + }, + "south": { + "output": "/actions/htc_viu/in/viu_press_06" + }, + "west": { + "output": "/actions/htc_viu/in/viu_press_05" + } + }, + "mode": "dpad", + "parameters": { + "sub_mode": "click" + }, + "path": "/user/hand/right/input/trackpad" + }, + { + "inputs": { + "center": { + "output": "/actions/htc_viu/in/viu_touch_07" + }, + "east": { + "output": "/actions/htc_viu/in/viu_touch_03" + }, + "north": { + "output": "/actions/htc_viu/in/viu_touch_04" + }, + "south": { + "output": "/actions/htc_viu/in/viu_touch_06" + }, + "west": { + "output": "/actions/htc_viu/in/viu_touch_05" + } + }, + "mode": "dpad", + "parameters": { + "sub_mode": "touch" + }, + "path": "/user/hand/left/input/trackpad" + }, + { + "inputs": { + "center": { + "output": "/actions/htc_viu/in/viu_touch_07" + }, + "east": { + "output": "/actions/htc_viu/in/viu_touch_03" + }, + "north": { + "output": "/actions/htc_viu/in/viu_touch_04" + }, + "south": { + "output": "/actions/htc_viu/in/viu_touch_06" + }, + "west": { + "output": "/actions/htc_viu/in/viu_touch_05" + } + }, + "mode": "dpad", + "parameters": { + "sub_mode": "touch" + }, + "path": "/user/hand/right/input/trackpad" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "parameters": { + "click_activate_threshold": "0.55", + "click_deactivate_threshold": "0.45", + "haptic_amplitude": "0.2" + }, + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "parameters": { + "click_activate_threshold": "0.55", + "click_deactivate_threshold": "0.45", + "haptic_amplitude": "0.2" + }, + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_touch_33" + } + }, + "mode": "button", + "parameters": { + "haptic_amplitude": "0" + }, + "path": "/user/hand/right/input/trigger" + } + ] + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json.meta new file mode 100644 index 00000000..72e54ae6 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_controller.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1c91c9920a3427348aab88c310a6e0d5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_pro.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_pro.json.meta new file mode 100644 index 00000000..4c38d0dd --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_pro.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e2f5201bb7a424246b89c3f2e571d5b6 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json new file mode 100644 index 00000000..e3283013 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json @@ -0,0 +1,548 @@ +{ + "bindings": { + "/actions/htc_viu": { + "sources": [ + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/hand/left/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/hand/left/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/hand/left/input/thumb" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/hand/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/hand/right/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/hand/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/hand/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/hand/right/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/hand/right/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/foot/left/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/foot/left/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/foot/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/foot/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/foot/left/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/foot/left/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/foot/right/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/foot/right/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/foot/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/foot/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/foot/right/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/foot/right/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/shoulder/left/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/shoulder/left/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/shoulder/left/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/shoulder/left/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/shoulder/left/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/shoulder/left/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/shoulder/right/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/shoulder/right/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/shoulder/right/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/shoulder/right/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/shoulder/right/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/shoulder/right/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/waist/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/waist/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/waist/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/waist/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/waist/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/waist/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/chest/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/chest/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/chest/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/chest/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/chest/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/chest/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/camera/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/camera/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/camera/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/camera/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/camera/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/camera/input/thumb" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_00" + } + }, + "mode": "button", + "path": "/user/keyboard/input/power" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_33" + } + }, + "mode": "button", + "path": "/user/keyboard/input/trigger" + }, + { + "inputs": { + "value": { + "output": "/actions/htc_viu/in/viu_axis_1x" + } + }, + "mode": "scalar_constant", + "path": "/user/keyboard/input/trigger" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_02" + } + }, + "mode": "button", + "path": "/user/keyboard/input/grip" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_01" + } + }, + "mode": "button", + "path": "/user/keyboard/input/application_menu" + }, + { + "inputs": { + "click": { + "output": "/actions/htc_viu/in/viu_press_32" + } + }, + "mode": "button", + "path": "/user/keyboard/input/thumb" + } + ] + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json.meta new file mode 100644 index 00000000..db5bd056 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/PartialInputBindings/bindings_vive_tracker.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f6bf52c82ecf8cd4bbd0e5b87ea95c0d +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs new file mode 100644 index 00000000..3a1f1d27 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs @@ -0,0 +1,368 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +using HTC.UnityPlugin.Utility; +using HTC.UnityPlugin.VRModuleManagement; +using System.Collections.Generic; +using UnityEngine; +#if VIU_STEAMVR +using Valve.VR; +#endif + +namespace HTC.UnityPlugin.Vive +{ + // Only works in playing mode + public class VIUSteamVRRenderModel : MonoBehaviour + { + private struct ChildTransforms + { + public Transform root; + public Transform attach; + } + + // Name of the sub-object which represents the "local" coordinate space for each component. + public const string LOCAL_TRANSFORM_NAME = "attach"; + + public const string MODEL_OVERRIDE_WARNNING = "Model override is really only meant to be used in " + + "the scene view for lining things up. Use tracked device " + + "index instead to ensure the correct model is displayed for all users."; + + [Tooltip(MODEL_OVERRIDE_WARNNING)] + [SerializeField] + private string m_modelOverride; + + [Tooltip("Shader to apply to model.")] + [SerializeField] + private Shader m_shaderOverride; + + [Tooltip("Update transforms of components at runtime to reflect user action.")] + [SerializeField] + private bool m_updateDynamically = true; + + private uint m_deviceIndex = VRModule.INVALID_DEVICE_INDEX; + private MeshFilter m_meshFilter; + private MeshRenderer m_meshRenderer; + private IndexedTable m_chilTransforms = new IndexedTable(); + private IndexedTable m_materials = new IndexedTable(); + private HashSet m_loadingRenderModels = new HashSet(); + private bool m_isAppQuit; + + private string preferedModelName + { + get + { + if (!string.IsNullOrEmpty(m_modelOverride)) { return m_modelOverride; } +#if UNITY_EDITOR + if (!Application.isPlaying) + { + return string.Empty; + } + else +#endif + { + return VRModule.GetCurrentDeviceState(m_deviceIndex).renderModelName; + } + } + } + + private Shader preferedShader { get { return m_shaderOverride == null ? Shader.Find("Standard") : m_shaderOverride; } } + + public bool updateDynamically { get { return m_updateDynamically; } set { m_updateDynamically = value; } } + public bool isLoadingModel { get { return m_loadingRenderModels.Count > 0; } } + public string loadedModelName { get; private set; } + public bool isModelLoaded { get { return !string.IsNullOrEmpty(loadedModelName); } } + public Shader loadedShader { get; private set; } + + public string modelOverride + { + get + { + return m_modelOverride; + } + set + { + m_modelOverride = value; + LoadPreferedModel(); + } + } + + public Shader shaderOverride + { + get + { + return m_shaderOverride; + } + set + { + m_shaderOverride = value; + SetPreferedShader(); + } + } + +#if UNITY_EDITOR + private void OnValidate() + { + if (Application.isPlaying) + { + UnityEditor.EditorApplication.delayCall += () => + { + if (!m_isAppQuit && this != null && isActiveAndEnabled) + { + LoadPreferedModel(); + SetPreferedShader(); + } + }; + } + } +#endif + + private void Update() + { + if (m_updateDynamically) + { + UpdateComponents(); + } + } + + private void OnEnable() + { + LoadPreferedModel(); + } + + private void OnDestroy() + { + ClearModel(); + } + + private void OnApplicationQuit() + { + m_isAppQuit = true; + } + + public void ClearModel() + { + if (!isModelLoaded) { return; } + + if (m_meshRenderer != null) { Destroy(m_meshRenderer); } + if (m_meshFilter != null) { Destroy(m_meshFilter); } + + for (int i = 0, imax = m_chilTransforms.Count; i < imax; ++i) + { + var c = m_chilTransforms.GetValueByIndex(i); + if (c.root == null) { continue; } + Destroy(c.root.gameObject); + } + + m_chilTransforms.Clear(); + m_materials.Clear(); + loadedModelName = string.Empty; + loadedShader = null; + } + + private void SetPreferedShader() + { + SetShader(preferedShader); + } + + private void SetShader(Shader newShader) + { + if (loadedShader == newShader) { return; } + + loadedShader = newShader; + + if (m_materials == null) { return; } + + for (int i = 0, imax = m_materials.Count; i < imax; ++i) + { + var mat = m_materials.GetValueByIndex(i); + if (mat != null) + { + mat.shader = newShader; + } + } + } + + private void LoadPreferedModel() + { + LoadModel(preferedModelName); + } + + private void LoadModel(string renderModelName) + { + //Debug.Log(transform.parent.parent.name + " Try LoadModel " + renderModelName); +#if UNITY_EDITOR + if (!Application.isPlaying) + { + Debug.LogWarning("LoadModel failed! This function only works in playing mode"); + return; + } +#endif + if (string.IsNullOrEmpty(loadedModelName) && string.IsNullOrEmpty(renderModelName)) { return; } + + if (loadedModelName == renderModelName) { return; } + + if (m_loadingRenderModels.Contains(renderModelName)) { return; } + + ClearModel(); + + if (!m_isAppQuit && !string.IsNullOrEmpty(renderModelName)) + { + //Debug.Log(transform.parent.parent.name + " LoadModel " + renderModelName); + m_loadingRenderModels.Add(renderModelName); + VIUSteamVRRenderModelLoader.Load(renderModelName, OnLoadModelComplete); + } + } + + private void OnLoadModelComplete(string renderModelName) + { + m_loadingRenderModels.Remove(renderModelName); + + if (loadedModelName == renderModelName) { return; } + if (preferedModelName != renderModelName) { return; } + if (!isActiveAndEnabled) { return; } + //Debug.Log(transform.parent.parent.name + " OnLoadModelComplete " + renderModelName); + ClearModel(); + + VIUSteamVRRenderModelLoader.RenderModel renderModel; + if (!VIUSteamVRRenderModelLoader.renderModelsCache.TryGetValue(renderModelName, out renderModel)) { return; } + + if (loadedShader == null) { loadedShader = preferedShader; } + + if (renderModel.childCount == 0) + { + VIUSteamVRRenderModelLoader.Model model; + if (VIUSteamVRRenderModelLoader.modelsCache.TryGetValue(renderModelName, out model)) + { + Material material; + if (!m_materials.TryGetValue(model.textureID, out material)) + { + material = new Material(loadedShader) + { + mainTexture = renderModel.textures[model.textureID] + }; + + m_materials.Add(model.textureID, material); + } + + m_meshFilter = gameObject.AddComponent(); + m_meshFilter.mesh = model.mesh; + m_meshRenderer = gameObject.AddComponent(); + m_meshRenderer.sharedMaterial = material; + } + } + else + { + for (int i = 0, imax = renderModel.childCount; i < imax; ++i) + { + var childName = renderModel.childCompNames[i]; + var modelName = renderModel.childModelNames[i]; + if (string.IsNullOrEmpty(childName) || string.IsNullOrEmpty(modelName)) { continue; } + + if (!m_chilTransforms.ContainsKey(childName)) + { + var root = new GameObject(childName).transform; + + root.SetParent(transform, false); + root.gameObject.layer = gameObject.layer; + + VIUSteamVRRenderModelLoader.Model model; + if (VIUSteamVRRenderModelLoader.modelsCache.TryGetValue(modelName, out model)) + { + Material material; + if (!m_materials.TryGetValue(model.textureID, out material)) + { + material = new Material(loadedShader) + { + mainTexture = renderModel.textures[model.textureID] + }; + + m_materials.Add(model.textureID, material); + } + + root.gameObject.AddComponent().mesh = model.mesh; + root.gameObject.AddComponent().sharedMaterial = material; + } + + // Also create a child 'attach' object for attaching things. + var attach = new GameObject(LOCAL_TRANSFORM_NAME).transform; + attach.SetParent(root, false); + attach.gameObject.layer = gameObject.layer; + + m_chilTransforms.Add(childName, new ChildTransforms() + { + root = root, + attach = attach, + }); + } + } + } + + loadedModelName = renderModelName; + } + + private void UpdateComponents() + { +#if VIU_STEAMVR + if (!isModelLoaded) { return; } + + if (m_chilTransforms.Count == 0) { return; } + + var vrSystem = OpenVR.System; + if (vrSystem == null) { return; } + + var vrRenderModels = OpenVR.RenderModels; + if (vrRenderModels == null) { return; } + + for (int i = 0, imax = m_chilTransforms.Count; i < imax; ++i) + { + var name = m_chilTransforms.GetKeyByIndex(i); + + RenderModel_ComponentState_t state; + if (!TryGetComponentState(vrSystem, vrRenderModels, name, out state)) { continue; } + + var comp = m_chilTransforms.GetValueByIndex(i); + + var compPose = new SteamVR_Utils.RigidTransform(state.mTrackingToComponentRenderModel); + comp.root.localPosition = compPose.pos; + comp.root.localRotation = compPose.rot; + + var attachPose = new SteamVR_Utils.RigidTransform(state.mTrackingToComponentLocal); + comp.attach.position = transform.TransformPoint(attachPose.pos); + comp.attach.rotation = transform.rotation * attachPose.rot; + + var visible = (state.uProperties & (uint)EVRComponentProperty.IsVisible) != 0; + if (visible != comp.root.gameObject.activeSelf) + { + comp.root.gameObject.SetActive(visible); + } + } +#endif + } + +#if VIU_STEAMVR_2_0_0_OR_NEWER + private bool TryGetComponentState(CVRSystem vrSystem, CVRRenderModels vrRenderModels, string componentName, out RenderModel_ComponentState_t componentState) + { + componentState = default(RenderModel_ComponentState_t); + var modeState = default(RenderModel_ControllerMode_State_t); + return vrRenderModels.GetComponentStateForDevicePath(loadedModelName, componentName, SteamVRModule.GetInputSrouceHandleForDevice(m_deviceIndex), ref modeState, ref componentState); + } +#elif VIU_STEAMVR + private static readonly uint s_sizeOfControllerStats = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t)); + private bool TryGetComponentState(CVRSystem vrSystem, CVRRenderModels vrRenderModels, string componentName, out RenderModel_ComponentState_t componentState) + { + componentState = default(RenderModel_ComponentState_t); + var modeState = default(RenderModel_ControllerMode_State_t); + var controllerState = default(VRControllerState_t); + if (!vrSystem.GetControllerState(0, ref controllerState, s_sizeOfControllerStats)) { return false; } + if (!vrRenderModels.GetComponentState(loadedModelName, componentName, ref controllerState, ref modeState, ref componentState)) { return false; } + return true; + } +#endif + + public void SetDeviceIndex(uint index) + { + //Debug.Log(transform.parent.parent.name + " SetDeviceIndex " + index); + m_deviceIndex = index; + LoadPreferedModel(); + } + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs.meta new file mode 100644 index 00000000..163bc8d9 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1948bdcd9101994fad6a52bc97f1747 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs new file mode 100644 index 00000000..3712b3a2 --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs @@ -0,0 +1,477 @@ +//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using UnityEngine; +using UnityEngine.Rendering; +#if VIU_STEAMVR +using Valve.VR; +#endif + +namespace HTC.UnityPlugin.Vive +{ + public static class VIUSteamVRRenderModelLoader + { + public class RenderModel + { + public string name; + public string[] childCompNames; + public string[] childModelNames; + public int childCount; + public Dictionary textures; + } + + public class Model + { + public Mesh mesh; + public int textureID; + } + + private class LoadRenderModelJob + { + private struct PtrPack + { + public IntPtr model; + public IntPtr texture; + public IntPtr textureD3D11; + } + + private static int s_nextJobID; + private int m_jobID; + private int m_startFrame; + private string m_name; + private Action m_callback; + private bool m_isDone; + private RenderModel m_unreadyRM; + private PtrPack m_loadedPtr; + private PtrPack[] m_loadedChildPtrs; + + public int jobID { get { return m_jobID; } } + + public LoadRenderModelJob(string name, Action callback) + { + m_name = name; + m_callback = callback; + m_jobID = s_nextJobID++; + } + + private void DoComplete() + { + m_isDone = true; + if (m_callback != null) + { + m_callback(m_name); + m_callback = null; + } + } + +#if VIU_STEAMVR + private static readonly bool s_verbose = false; + // Should not do job after interrupted + public void InterruptAndComplete() + { + var vrRenderModels = OpenVR.RenderModels; + if (vrRenderModels == null) { DoComplete(); return; } + + if (m_loadedPtr.texture != IntPtr.Zero) { vrRenderModels.FreeTexture(m_loadedPtr.texture); } + if (m_loadedPtr.model != IntPtr.Zero) { vrRenderModels.FreeRenderModel(m_loadedPtr.model); } + + foreach (var ptrPack in m_loadedChildPtrs) + { + if (ptrPack.texture != IntPtr.Zero) { vrRenderModels.FreeTexture(ptrPack.texture); } + if (ptrPack.model != IntPtr.Zero) { vrRenderModels.FreeRenderModel(ptrPack.model); } + } + + DoComplete(); + } + + // return true if is done + public bool DoJob() + { + if (m_isDone) { return true; } + + if (!s_renderModelsCache.ContainsKey(m_name)) + { + var vrRenderModels = OpenVR.RenderModels; + if (vrRenderModels == null) { DoComplete(); return true; } + + if (m_unreadyRM == null) + { + var childCount = (int)vrRenderModels.GetComponentCount(m_name); + if (childCount > 0) + { + var childCompNames = new string[childCount]; + var childModelNames = new string[childCount]; + var strBuilder = new StringBuilder(16); + + for (int iChild = 0; iChild < childCount; ++iChild) + { + var strCap = vrRenderModels.GetComponentName(m_name, (uint)iChild, null, 0); + if (strCap == 0) { continue; } + strBuilder.Length = 0; + strBuilder.EnsureCapacity((int)strCap); + if (vrRenderModels.GetComponentName(m_name, (uint)iChild, strBuilder, strCap) == 0) { continue; } + childCompNames[iChild] = strBuilder.ToString(); + if (s_verbose) { Debug.Log("[" + m_jobID + "]+0 GetComponentName " + m_name + "[" + iChild + "]=" + childCompNames[iChild]); } + + strCap = vrRenderModels.GetComponentRenderModelName(m_name, childCompNames[iChild], null, 0); + if (strCap == 0) { continue; } + strBuilder.Length = 0; + strBuilder.EnsureCapacity((int)strCap); + if (vrRenderModels.GetComponentRenderModelName(m_name, childCompNames[iChild], strBuilder, strCap) == 0) { continue; } + childModelNames[iChild] = strBuilder.ToString(); + if (s_verbose) { Debug.Log("[" + m_jobID + "]+0 GetComponentRenderModelName " + m_name + "[" + childCompNames[iChild] + "]=" + System.IO.Path.GetFileName(childModelNames[iChild])); } + } + + m_unreadyRM = new RenderModel() + { + name = m_name, + childCompNames = childCompNames, + childModelNames = childModelNames, + childCount = childCount, + textures = new Dictionary(), + }; + + m_loadedChildPtrs = new PtrPack[childCount]; + } + else + { + m_unreadyRM = new RenderModel() + { + name = m_name, + textures = new Dictionary(), + }; + } + + m_startFrame = Time.frameCount; + } + + if (m_unreadyRM.childCount == 0) + { + if (!DoLoadModelJob(vrRenderModels, m_name, m_unreadyRM.textures, ref m_loadedPtr.model, ref m_loadedPtr.texture, ref m_loadedPtr.textureD3D11)) + { + return false; + } + + if (m_loadedPtr.texture != IntPtr.Zero) { vrRenderModels.FreeTexture(m_loadedPtr.texture); } + if (m_loadedPtr.model != IntPtr.Zero) { vrRenderModels.FreeRenderModel(m_loadedPtr.model); } + } + else + { + var loadChildModelsDone = true; + for (int i = 0, imax = m_unreadyRM.childCount; i < imax; ++i) + { + loadChildModelsDone = DoLoadModelJob(vrRenderModels, m_unreadyRM.childModelNames[i], m_unreadyRM.textures, ref m_loadedChildPtrs[i].model, ref m_loadedChildPtrs[i].texture, ref m_loadedChildPtrs[i].textureD3D11) && loadChildModelsDone; + } + + if (!loadChildModelsDone) { return false; } + + foreach (var ptrPack in m_loadedChildPtrs) + { + if (ptrPack.texture != IntPtr.Zero) { vrRenderModels.FreeTexture(ptrPack.texture); } + if (ptrPack.model != IntPtr.Zero) { vrRenderModels.FreeRenderModel(ptrPack.model); } + } + } + + s_renderModelsCache.Add(m_name, m_unreadyRM); + } + + DoComplete(); + return true; + } + + // return true if is done + private bool DoLoadModelJob(CVRRenderModels vrRenderModels, string modelName, Dictionary texturesCache, ref IntPtr modelPtr, ref IntPtr texturePtr, ref IntPtr d3d11TexturePtr) + { + if (string.IsNullOrEmpty(modelName)) { return true; } + + EVRRenderModelError error; + Model model; + if (!s_modelsCache.TryGetValue(modelName, out model)) + { + switch (error = vrRenderModels.LoadRenderModel_Async(modelName, ref modelPtr)) + { + default: + Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async failed! " + System.IO.Path.GetFileName(modelName) + " EVRRenderModelError=" + error); + return true; + case EVRRenderModelError.Loading: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async loading... " + System.IO.Path.GetFileName(modelName)); } + return false; + case EVRRenderModelError.None: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async succeed! " + System.IO.Path.GetFileName(modelName)); } + RenderModel_t modelData = MarshalRenderModel(modelPtr); + + var vertices = new Vector3[modelData.unVertexCount]; + var normals = new Vector3[modelData.unVertexCount]; + var uv = new Vector2[modelData.unVertexCount]; + + Type type = typeof(RenderModel_Vertex_t); + for (int iVert = 0; iVert < modelData.unVertexCount; iVert++) + { + var ptr = new IntPtr(modelData.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type)); + var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type); + + vertices[iVert] = new Vector3(vert.vPosition.v0, vert.vPosition.v1, -vert.vPosition.v2); + normals[iVert] = new Vector3(vert.vNormal.v0, vert.vNormal.v1, -vert.vNormal.v2); + uv[iVert] = new Vector2(vert.rfTextureCoord0, vert.rfTextureCoord1); + } + + var indexCount = (int)modelData.unTriangleCount * 3; + var indices = new short[indexCount]; + Marshal.Copy(modelData.rIndexData, indices, 0, indices.Length); + + var triangles = new int[indexCount]; + for (int iTri = 0; iTri < modelData.unTriangleCount; iTri++) + { + triangles[iTri * 3 + 0] = indices[iTri * 3 + 2]; + triangles[iTri * 3 + 1] = indices[iTri * 3 + 1]; + triangles[iTri * 3 + 2] = indices[iTri * 3 + 0]; + } + + model = new Model() + { + textureID = modelData.diffuseTextureId, + mesh = new Mesh() + { + hideFlags = HideFlags.HideAndDontSave, + vertices = vertices, + normals = normals, + uv = uv, + triangles = triangles, + }, + }; + + s_modelsCache.Add(modelName, model); + break; + } + } + + Texture2D texture; + if (!texturesCache.TryGetValue(model.textureID, out texture)) + { + switch (error = vrRenderModels.LoadTexture_Async(model.textureID, ref texturePtr)) + { + default: + Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async failed! " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "] EVRRenderModelError=" + error); + return true; + case EVRRenderModelError.Loading: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async loading... " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } + return false; + case EVRRenderModelError.None: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async succeed! " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } + var textureMap = MarshalRenderModelTextureMap(texturePtr); + texture = new Texture2D(textureMap.unWidth, textureMap.unHeight, TextureFormat.RGBA32, false); + + if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11) + { + texture.Apply(); + d3d11TexturePtr = texture.GetNativeTexturePtr(); + } + else + { + var textureMapData = new byte[textureMap.unWidth * textureMap.unHeight * 4]; // RGBA + Marshal.Copy(textureMap.rubTextureMapData, textureMapData, 0, textureMapData.Length); + + var colors = new Color32[textureMap.unWidth * textureMap.unHeight]; + int iColor = 0; + for (int iHeight = 0; iHeight < textureMap.unHeight; iHeight++) + { + for (int iWidth = 0; iWidth < textureMap.unWidth; iWidth++) + { + var r = textureMapData[iColor++]; + var g = textureMapData[iColor++]; + var b = textureMapData[iColor++]; + var a = textureMapData[iColor++]; + colors[iHeight * textureMap.unWidth + iWidth] = new Color32(r, g, b, a); + } + } + + texture.SetPixels32(colors); + texture.Apply(); + } + + texturesCache.Add(model.textureID, texture); + break; + } + } + + if (d3d11TexturePtr != IntPtr.Zero) + { + while (true) + { + switch (error = vrRenderModels.LoadIntoTextureD3D11_Async(model.textureID, d3d11TexturePtr)) + { + default: + Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async failed! " + System.IO.Path.GetFileName(modelName) + " EVRRenderModelError=" + error); + d3d11TexturePtr = IntPtr.Zero; + return true; + case EVRRenderModelError.Loading: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async loading... " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } + break; + case EVRRenderModelError.None: + if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async succeed! " + System.IO.Path.GetFileName(modelName)); } + d3d11TexturePtr = IntPtr.Zero; + return true; + } + // FIXME: LoadIntoTextureD3D11_Async blocks main thread? Crashes when not calling it in while loop +#if !UNITY_METRO + System.Threading.Thread.Sleep(1); +#endif + } + } + + return true; + } + + /// + /// Helper function to handle the inconvenient fact that the packing for RenderModel_t is + /// different on Linux/OSX (4) than it is on Windows (8) + /// + /// native pointer to the RenderModel_t + /// + private static RenderModel_t MarshalRenderModel(IntPtr pRenderModel) + { + if ((Environment.OSVersion.Platform == PlatformID.MacOSX) || + (Environment.OSVersion.Platform == PlatformID.Unix)) + { + var packedModel = (RenderModel_t_Packed)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t_Packed)); + var model = new RenderModel_t(); + packedModel.Unpack(ref model); + return model; + } + else + { + return (RenderModel_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t)); + } + } + + /// + /// Helper function to handle the inconvenient fact that the packing for RenderModel_TextureMap_t is + /// different on Linux/OSX (4) than it is on Windows (8) + /// + /// native pointer to the RenderModel_TextureMap_t + /// + private static RenderModel_TextureMap_t MarshalRenderModelTextureMap(IntPtr pTextureMap) + { + if ((Environment.OSVersion.Platform == PlatformID.MacOSX) || + (Environment.OSVersion.Platform == PlatformID.Unix)) + { + var packedModel = (RenderModel_TextureMap_t_Packed)Marshal.PtrToStructure(pTextureMap, typeof(RenderModel_TextureMap_t_Packed)); + var model = new RenderModel_TextureMap_t(); + packedModel.Unpack(ref model); + return model; + } + else + { + return (RenderModel_TextureMap_t)Marshal.PtrToStructure(pTextureMap, typeof(RenderModel_TextureMap_t)); + } + } +#else + public void InterruptAndComplete() + { + DoComplete(); + } + + public bool DoJob() + { + if (m_isDone) { return true; } + + DoComplete(); + return true; + } +#endif + } + + + private static Dictionary s_renderModelsCache = new Dictionary(); + private static Dictionary s_modelsCache = new Dictionary(); + + public static Dictionary renderModelsCache { get { return s_renderModelsCache; } } + public static Dictionary modelsCache { get { return s_modelsCache; } } + + public static void ClearCache() + { + s_renderModelsCache.Clear(); + s_modelsCache.Clear(); + } + + // NOTICE: Avoid calling Load after applicaion quit, this function will create worker gameobject + public static void Load(string name, Action onComplete) + { + WorkerBehaviour.EnqueueJob(new LoadRenderModelJob(name, onComplete)); + } + + #region Worker Behaviour + private class WorkerBehaviour : MonoBehaviour + { + private static WorkerBehaviour s_worker; + private static Queue s_jobQueue; + + private Coroutine m_coroutine; + + private bool isWorking + { + get { return m_coroutine != null; } + set + { + if (isWorking == value) { return; } + if (value) { m_coroutine = StartCoroutine(WorkingCoroutine()); } + else { StopCoroutine(m_coroutine); m_coroutine = null; } + } + } + + public static void EnqueueJob(LoadRenderModelJob job) + { + if (s_worker == null) + { + var workerObj = new GameObject(typeof(VIUSteamVRRenderModelLoader).Name + "." + typeof(WorkerBehaviour).Name) + { + hideFlags = HideFlags.HideAndDontSave, + }; + DontDestroyOnLoad(workerObj); + s_worker = workerObj.AddComponent(); + } + + if (s_jobQueue == null) + { + s_jobQueue = new Queue(); + } + + s_jobQueue.Enqueue(job); + + s_worker.isWorking = true; + } + + private void OnDestroy() + { + isWorking = false; + + while (s_jobQueue.Count > 0) + { + s_jobQueue.Dequeue().InterruptAndComplete(); + } + } + + private IEnumerator WorkingCoroutine() + { + while (s_jobQueue.Count > 0) + { + if (s_jobQueue.Peek().DoJob()) + { + s_jobQueue.Dequeue(); + } + else + { + yield return null; + } + } + + isWorking = false; + } + } + #endregion + } +} \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs.meta b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs.meta new file mode 100644 index 00000000..0672ae9b --- /dev/null +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/SteamVRExtension/VIUSteamVRRenderModelLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6d4e377c0cb877c4aa40fbac96daab75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs index 6b50698f..3797fbc2 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs @@ -6,6 +6,7 @@ using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; +using GrabberPool = HTC.UnityPlugin.Utility.ObjectPool; namespace HTC.UnityPlugin.Vive { @@ -15,7 +16,7 @@ public class StickyGrabbable : GrabbableBase { public class Grabber : IGrabber { - private static ObjectPool m_pool; + private static GrabberPool m_pool; public ColliderButtonEventData eventData { get; private set; } @@ -40,7 +41,7 @@ public static Grabber Get(ColliderButtonEventData eventData) { if (m_pool == null) { - m_pool = new ObjectPool(() => new Grabber()); + m_pool = new GrabberPool(() => new Grabber()); } var grabber = m_pool.Get(); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs index 996bfd6f..41022ec7 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/Teleportable.cs @@ -115,7 +115,7 @@ public void OnPointer3DPressExit(Pointer3DEventData eventData) public IEnumerator StartTeleport(Vector3 position, float duration) { -#if VIU_STEAMVR +#if VIU_STEAMVR && !VIU_STEAMVR_2_0_0_OR_NEWER var halfDuration = Mathf.Max(0f, duration * 0.5f); if (VRModule.activeModule == VRModuleActiveEnum.SteamVR && !Mathf.Approximately(halfDuration, 0f)) diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs index ce164f00..3bfed0af 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/VRCameraHook.cs @@ -2,7 +2,7 @@ using HTC.UnityPlugin.VRModuleManagement; using UnityEngine; -#if !UNITY_5_4_OR_NEWER && VIU_STEAMVR_2_0_0_OR_NEWER +#if VIU_STEAMVR_2_0_0_OR_NEWER using Valve.VR; #endif @@ -30,10 +30,11 @@ private void OnModuleActivated(VRModuleActiveEnum activatedModule) { switch (activatedModule) { -#if !UNITY_5_4_OR_NEWER && VIU_STEAMVR +#if VIU_STEAMVR && !VIU_STEAMVR_2_0_0_OR_NEWER case VRModuleActiveEnum.SteamVR: if (GetComponent() == null) { + // FIXME: SteamVR_Camera 2.0 is removed gameObject.AddComponent(); } break; diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs index d27e0f0f..94a19366 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs @@ -6,6 +6,6 @@ namespace HTC.UnityPlugin.Vive { public static class VIUVersion { - public static readonly Version current = new Version("1.9.0.0"); + public static readonly Version current = new Version("1.9.0.1"); } } \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ControllerState.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ControllerState.cs index 13b9b8a5..54abaeab 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ControllerState.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ControllerState.cs @@ -126,6 +126,15 @@ public override bool Update() EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.Axis4, currState.GetButtonPress(VRModuleRawButton.Axis4)); EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.Axis4Touch, currState.GetButtonTouch(VRModuleRawButton.Axis4)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadRightTouch, currState.GetButtonPress(VRModuleRawButton.DPadRight)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadUpTouch, currState.GetButtonPress(VRModuleRawButton.DPadUp)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadLeftTouch, currState.GetButtonPress(VRModuleRawButton.DPadLeft)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadDownTouch, currState.GetButtonPress(VRModuleRawButton.DPadDown)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadRight, currState.GetButtonTouch(VRModuleRawButton.DPadRight)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadUp, currState.GetButtonTouch(VRModuleRawButton.DPadUp)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadLeft, currState.GetButtonTouch(VRModuleRawButton.DPadLeft)); + EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.DPadDown, currState.GetButtonTouch(VRModuleRawButton.DPadDown)); + // update axis values currAxisValue[(int)ControllerAxis.PadX] = currState.GetAxisValue(VRModuleRawAxis.TouchpadX); currAxisValue[(int)ControllerAxis.PadY] = currState.GetAxisValue(VRModuleRawAxis.TouchpadY); @@ -136,10 +145,22 @@ public override bool Update() currAxisValue[(int)ControllerAxis.RingCurl] = currState.GetAxisValue(VRModuleRawAxis.RingCurl); currAxisValue[(int)ControllerAxis.PinkyCurl] = currState.GetAxisValue(VRModuleRawAxis.PinkyCurl); + if (trackedDeviceModel.Equals(VRModuleDeviceModel.WMRControllerLeft) || trackedDeviceModel.Equals(VRModuleDeviceModel.WMRControllerRight)) + { + currAxisValue[(int)ControllerAxis.JoystickX] = currState.GetAxisValue(VRModuleRawAxis.JoystickX); + currAxisValue[(int)ControllerAxis.JoystickY] = currState.GetAxisValue(VRModuleRawAxis.JoystickY); + } + else + { + currAxisValue[(int)ControllerAxis.JoystickX] = currState.GetAxisValue(VRModuleRawAxis.TouchpadX); + currAxisValue[(int)ControllerAxis.JoystickY] = currState.GetAxisValue(VRModuleRawAxis.TouchpadY); + } + // update hair trigger var currTriggerValue = currAxisValue[(int)ControllerAxis.Trigger]; EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.FullTrigger, currTriggerValue == 1f); + if (EnumUtils.GetFlag(prevButtonPressed, (int)ControllerButton.HairTrigger)) { EnumUtils.SetFlag(ref currButtonPressed, (int)ControllerButton.HairTrigger, currTriggerValue >= (hairTriggerLimit - hairDelta) && currTriggerValue > 0.0f); diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ViveInput.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ViveInput.cs index 9f1f7789..b172a60d 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ViveInput.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveInput/ViveInput.cs @@ -50,6 +50,11 @@ public enum ControllerButton AKey = 12, // Oculus Touch only, RightHandA or LeftHandX pressed AKeyTouch = 13, // Oculus Touch only, RightHandA or LeftHandX touched + BKey = Menu, + BkeyTouch = MenuTouch, + Bumper = Axis3, + BumperTouch = Axis3Touch, + // button alias OuterFaceButton = Menu, // 7 OuterFaceButtonTouch = MenuTouch, // 9 @@ -75,10 +80,20 @@ public enum ControllerButton Axis3Touch = 16, [HideInInspector] Axis4Touch = 17, - + // virtual buttons HairTrigger = 5, // Pressed if trigger button is pressing, unpressed if trigger button is releasing FullTrigger = 6, // on:1.00 off:1.00 + + DPadLeft = 18, + DPadUp = 19, + DPadRight = 20, + DPadDown = 21, + + DPadLeftTouch = 22, + DPadUpTouch = 23, + DPadRightTouch = 24, + DPadDownTouch = 25, } public enum ControllerAxis @@ -92,6 +107,9 @@ public enum ControllerAxis MiddleCurl, // Knuckles only RingCurl, // Knuckles only PinkyCurl, // Knuckles only + + JoystickX, + JoystickY, } public enum ScrollType diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceDevicePanelController.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceDevicePanelController.cs index 68a5bd0c..00c63bae 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceDevicePanelController.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/BindingInterface/BindingInterfaceDevicePanelController.cs @@ -78,7 +78,7 @@ public void EnableTracking() m_inputDeviceSN.text = string.Empty; CheckInputDeviceSN(string.Empty); - for (uint deviceIndex = 0; deviceIndex < VRModule.MAX_DEVICE_COUNT; ++deviceIndex) + for (uint deviceIndex = 0, imax = VRModule.GetDeviceStateCount(); deviceIndex < imax; ++deviceIndex) { if (VRModule.GetCurrentDeviceState(deviceIndex).isConnected) { diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/BodyRole.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/BodyRole.cs index 35a6c450..c9a640e0 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/BodyRole.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/BodyRole.cs @@ -67,7 +67,7 @@ public void Refresh() hmdPose.pos = Vector3.Scale(hmdPose.pos, new Vector3(1f, 0.5f, 1f)); var halfHeight = hmdPose.pos.y; var centerPoseInverse = hmdPose.GetInverse(); - for (uint i = 1; i < VRModule.MAX_DEVICE_COUNT; ++i) + for (uint i = 1, imax = VRModule.GetDeviceStateCount(); i < imax; ++i) { if (!IsTrackingDevice(i)) { continue; } diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/HandRole.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/HandRole.cs index 1f16800e..b73a638f 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/HandRole.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/HandRole.cs @@ -174,7 +174,7 @@ private void MappingLeftRightHands() else #endif { - for (uint deviceIndex = 1u; deviceIndex < VRModule.MAX_DEVICE_COUNT; ++deviceIndex) + for (uint deviceIndex = 1u, imax = VRModule.GetDeviceStateCount(); deviceIndex < imax; ++deviceIndex) { if (IsController(deviceIndex) && deviceIndex != rightIndex && deviceIndex != leftIndex && !RoleMap.IsDeviceConnectedAndBound(deviceIndex)) {