From 8cb69cccc790ba6e49e6a0debfc6bd718826657e Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Fri, 4 Jun 2021 17:08:26 +0800 Subject: [PATCH 01/13] Fix ControllerRole typo error --- .../Scripts/ViveRole/RoleMaps/ControllerRole.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/ControllerRole.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/ControllerRole.cs index 97788286..02c903ca 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/ControllerRole.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/ControllerRole.cs @@ -72,7 +72,7 @@ public void Refresh() } else { - var index = VRModule.GetRightControllerDeviceIndex(); + var index = VRModule.GetLeftControllerDeviceIndex(); if (VRModule.GetDeviceState(index).deviceClass == VRModuleDeviceClass.Controller) { leftIndex = index; From aba21f586dab4c45c5b1d9e4cb2904c32f76d96f Mon Sep 17 00:00:00 2001 From: lawwong Date: Fri, 21 May 2021 11:10:20 +0800 Subject: [PATCH 02/13] Fix Finch trigger button --- Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs index 9fc21303..c3a111fd 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs @@ -639,7 +639,7 @@ private void UpdateViveFocusFinchControllerState(IVRModuleDeviceStateRW state, I bool primary2DAxisTouch = GetDeviceFeatureValueOrDefault(device, CommonUsages.primary2DAxisTouch); // Touchpad bool secondary2DAxisClick = GetDeviceFeatureValueOrDefault(device, new InputFeatureUsage("Secondary2DAxisClick")); // No data bool secondary2DAxisTouch = GetDeviceFeatureValueOrDefault(device, new InputFeatureUsage("Secondary2DAxisTouch")); // No data - bool gripButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.gripButton); // Trigger + bool triggerButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.triggerButton); bool menuButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.menuButton); // No Data float trigger = GetDeviceFeatureValueOrDefault(device, CommonUsages.trigger); // No Data Vector2 primary2DAxis = GetDeviceFeatureValueOrDefault(device, CommonUsages.primary2DAxis); // Touchpad @@ -647,7 +647,7 @@ private void UpdateViveFocusFinchControllerState(IVRModuleDeviceStateRW state, I Vector2 dPad = GetDeviceFeatureValueOrDefault(device, new InputFeatureUsage("DPad")); // No Data state.SetButtonPress(VRModuleRawButton.Touchpad, primary2DAxisClick); - state.SetButtonPress(VRModuleRawButton.Trigger, gripButton); + state.SetButtonPress(VRModuleRawButton.Trigger, triggerButton); state.SetButtonPress(VRModuleRawButton.ApplicationMenu, menuButton); state.SetButtonPress(VRModuleRawButton.DPadUp, dPad.y > 0); state.SetButtonPress(VRModuleRawButton.DPadDown, dPad.y < 0); From a5a0c5f97854d086f2b8765d8e5288e2c15b63a4 Mon Sep 17 00:00:00 2001 From: lawwong Date: Thu, 27 May 2021 17:50:35 +0800 Subject: [PATCH 03/13] Support ViveHandTracking v0.10 Also move StartDetection to background thread --- .../Editor/ViveHandTrackingSubmoduleEditor.cs | 7 + .../Submodules/ViveHandTrackingSubmodule.cs | 205 +++++++++++++----- 2 files changed, 157 insertions(+), 55 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Submodules/Editor/ViveHandTrackingSubmoduleEditor.cs b/Assets/HTC.UnityPlugin/VRModule/Submodules/Editor/ViveHandTrackingSubmoduleEditor.cs index fa243acd..a46d5a78 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Submodules/Editor/ViveHandTrackingSubmoduleEditor.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Submodules/Editor/ViveHandTrackingSubmoduleEditor.cs @@ -15,6 +15,13 @@ public ViveHandTrackingRequirementCollection() reqTypeNames = new string[] { "ViveHandTracking.GestureInterface", "ViveHandTracking.GestureOption" }, reqFileNames = new string[] { "aristo_interface.dll", "GestureInterface.cs" }, }); + + Add(new SymbolRequirement() + { + symbol = "VIU_VIVE_HAND_TRACKING_0_10_0_OR_NEWER", + reqFileNames = new string[] { "GestureResultExtension.cs" }, + }); + } } } \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs b/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs index b515cdb6..805c0bae 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs @@ -4,6 +4,8 @@ using UnityEngine; using System.Runtime.InteropServices; using System; +using System.Collections; +using HTC.UnityPlugin.LiteCoroutineSystem; #if VIU_VIVE_HAND_TRACKING using ViveHandTracking; #endif @@ -16,12 +18,10 @@ public class ViveHandTrackingSubmodule : VRModule.SubmoduleBase private struct HandResultData { public bool isConnected; - public Vector3[] joints; - public GestureType gesture; - public float confidence; - public float pinchLevel; + public GestureResult rawData; } + private static readonly string LOG_PREFIX = "[" + typeof(ViveHandTrackingSubmodule).Name + "] "; private const int RETRY_COUNT = 5; private const float RETRY_INTERVAL = 1f; private static readonly int sizeofGestureResult = Marshal.SizeOf(typeof(GestureResult)); @@ -29,7 +29,9 @@ private struct HandResultData private GestureOption option = new GestureOption(); private bool isStarted; private int retryCount; - private float nextRetryTime; + private WaitForTicks retryInterval = WaitForTicks.Seconds(RETRY_INTERVAL); + private LiteCoroutine startDetectionCoroutine; + private LiteTask startDetectionTask = new LiteTask(); private int lastResultFrame; private HandResultData leftResult; @@ -42,61 +44,75 @@ private struct HandResultData protected override void OnActivated() { retryCount = RETRY_COUNT; - nextRetryTime = 0f; GestureInterface.UseExternalTransform(true); } protected override void OnDeactivated() { GestureInterface.StopGestureDetection(); + startDetectionTask.Cancel(); } public override uint GetRightHandedIndex() { return rightDeviceIndex; } public override uint GetLeftHandedIndex() { return leftDeviceIndex; } - protected override void OnUpdateDeviceConnectionAndPoses() + private IEnumerator StartDetectionCoroutine() { - // try start engine detection - if (!isStarted) + while (true) { - var now = Time.unscaledTime; - if (now >= nextRetryTime && retryCount >= 0) - { - --retryCount; - nextRetryTime = now + RETRY_INTERVAL; + var error = GestureInterface.StartGestureDetection(option); - var error = GestureInterface.StartGestureDetection(option); + lock (this) + { switch (error) { case GestureFailure.None: retryCount = RETRY_COUNT; lastResultFrame = -1; isStarted = true; - Debug.Log("[ViveHandTrackingSubmodule] StartGestureDetection"); + Debug.Log(LOG_PREFIX + "StartGestureDetection"); break; case GestureFailure.Camera: --retryCount; - nextRetryTime = now + RETRY_INTERVAL; if (retryCount >= 0) { - Debug.LogWarning("[ViveHandTrackingSubmodule] StartGestureDetection fail. Front camera function not found. retrying..."); + Debug.LogWarning(LOG_PREFIX + "StartGestureDetection fail. Front camera function not found. retrying(" + (retryCount + 1) + ")..."); } else { - Debug.LogWarning("[ViveHandTrackingSubmodule] StartGestureDetection fail. Front camera function not found."); + Debug.LogWarning(LOG_PREFIX + "StartGestureDetection fail. Front camera function not found."); } break; default: retryCount = 0; - Debug.LogWarning("[ViveHandTrackingSubmodule] StartGestureDetection fail. error:" + error); + Debug.LogWarning(LOG_PREFIX + "StartGestureDetection fail. error:" + error); break; } + + if (retryCount <= 0 || isStarted) { yield break; } } + + yield return retryInterval; } + } - if (!isStarted) { return; } + protected override void OnUpdateDeviceConnectionAndPoses() + { + lock (this) + { + if (!isStarted && retryCount > 0 && startDetectionTask.IsDone) + { + // try start engine detection + LiteCoroutine.StartCoroutine(ref startDetectionCoroutine, startDetectionTask.RestartTask(StartDetectionCoroutine())); + } + + if (!isStarted) { return; } + } + + var hmdPose = VRModule.GetDeviceState(VRModule.HMD_DEVICE_INDEX).pose; + GestureInterface.SetCameraTransform(hmdPose.pos, hmdPose.rot); // fetch raw data from engine IntPtr resultPtr; @@ -109,7 +125,7 @@ protected override void OnUpdateDeviceConnectionAndPoses() isStarted = false; return; } - else if (resultFrame < lastResultFrame) + else if (resultFrame <= lastResultFrame) { // skip frame return; @@ -128,10 +144,7 @@ protected override void OnUpdateDeviceConnectionAndPoses() leftResult = new HandResultData() { isConnected = true, - joints = result.points, - gesture = result.gesture, - confidence = result.confidence, - pinchLevel = result.pinchLevel, + rawData = result, }; } else @@ -139,10 +152,7 @@ protected override void OnUpdateDeviceConnectionAndPoses() rightResult = new HandResultData() { isConnected = true, - joints = result.points, - gesture = result.gesture, - confidence = result.confidence, - pinchLevel = result.pinchLevel, + rawData = result, }; } #if NET_4_6 @@ -184,7 +194,7 @@ private void UpdateDeviceConnectionAndPoses(ref HandResultData resultData, ref u currState.isConnected = true; currState.isPoseValid = true; - UpdateDeviceJoints(currState, resultData.joints, isLeft); + UpdateDeviceJoints(currState, ref resultData, isLeft); } else { @@ -205,6 +215,22 @@ protected override void OnUpdateDeviceInput() UpdateDeviceInput(ref rightResult, rightDeviceIndex); } +#if VIU_VIVE_HAND_TRACKING_0_10_0_OR_NEWER + [StructLayout(LayoutKind.Sequential)] + private struct GestureResult + { + [MarshalAs(UnmanagedType.I1)] + public bool isLeft; + public Vector3 position; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)] + public Vector3[] points; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)] + public Quaternion[] rotations; + public GestureType gesture; + public float confidence; + public PinchInfo pinch; + } + private void UpdateDeviceInput(ref HandResultData resultData, uint index) { if (!resultData.isConnected) { return; } @@ -214,12 +240,12 @@ private void UpdateDeviceInput(ref HandResultData resultData, uint index) EnsureValidDeviceState(index, out prevState, out currState); - var pinched = resultData.pinchLevel >= 0.95f; - var gFist = resultData.gesture == GestureType.Fist && resultData.confidence > 0.1f; - var gFive = resultData.gesture == GestureType.Five && resultData.confidence > 0.1f; - var gOK = resultData.gesture == GestureType.OK && resultData.confidence > 0.1f; - var gLike = resultData.gesture == GestureType.Like && resultData.confidence > 0.1f; - var gPoint = resultData.gesture == GestureType.Point && resultData.confidence > 0.1f; + var pinched = resultData.rawData.pinch.pinchLevel >= 0.95f; + var gFist = resultData.rawData.gesture == GestureType.Fist && resultData.rawData.confidence > 0.1f; + var gFive = resultData.rawData.gesture == GestureType.Five && resultData.rawData.confidence > 0.1f; + var gOK = resultData.rawData.gesture == GestureType.OK && resultData.rawData.confidence > 0.1f; + var gLike = resultData.rawData.gesture == GestureType.Like && resultData.rawData.confidence > 0.1f; + var gPoint = resultData.rawData.gesture == GestureType.Point && resultData.rawData.confidence > 0.1f; currState.SetButtonPress(VRModuleRawButton.GestureIndexPinch, pinched); currState.SetButtonTouch(VRModuleRawButton.GestureIndexPinch, pinched); currState.SetButtonPress(VRModuleRawButton.GestureFist, gFist); @@ -234,13 +260,93 @@ private void UpdateDeviceInput(ref HandResultData resultData, uint index) currState.SetButtonTouch(VRModuleRawButton.GestureIndexUp, gPoint); currState.SetButtonPress(VRModuleRawButton.Grip, gFist); currState.SetButtonTouch(VRModuleRawButton.Grip, gFist); - currState.SetAxisValue(VRModuleRawAxis.Trigger, resultData.pinchLevel); + currState.SetAxisValue(VRModuleRawAxis.Trigger, resultData.rawData.pinch.pinchLevel); } - private static void UpdateDeviceJoints(IVRModuleDeviceStateRW state, Vector3[] rawJoints, bool isLeft) + private static readonly Quaternion rotOffset = Quaternion.Inverse(Quaternion.LookRotation(Vector3.down, Vector3.forward)); + private static void UpdateDeviceJoints(IVRModuleDeviceStateRW state, ref HandResultData resultData, bool isLeft) { - var hmdPose = VRModule.GetDeviceState(VRModule.HMD_DEVICE_INDEX).pose; - GestureInterface.SetCameraTransform(hmdPose.pos, hmdPose.rot); + var joints = resultData.rawData.points; + var rotations = resultData.rawData.rotations; + + state.pose = new RigidPose(joints[0], rotations[0] * rotOffset); + + state.handJoints[HandJointName.Wrist] = new JointPose(new RigidPose(joints[0], rotations[0] * rotOffset)); + + state.handJoints[HandJointName.ThumbMetacarpal] = new JointPose(new RigidPose(joints[1], rotations[1] * rotOffset)); + state.handJoints[HandJointName.ThumbProximal] = new JointPose(new RigidPose(joints[2], rotations[2] * rotOffset)); + state.handJoints[HandJointName.ThumbDistal] = new JointPose(new RigidPose(joints[3], rotations[3] * rotOffset)); + state.handJoints[HandJointName.ThumbTip] = new JointPose(new RigidPose(joints[4], rotations[4] * rotOffset)); + + state.handJoints[HandJointName.IndexProximal] = new JointPose(new RigidPose(joints[5], rotations[5] * rotOffset)); + state.handJoints[HandJointName.IndexIntermediate] = new JointPose(new RigidPose(joints[6], rotations[6] * rotOffset)); + state.handJoints[HandJointName.IndexDistal] = new JointPose(new RigidPose(joints[7], rotations[7] * rotOffset)); + state.handJoints[HandJointName.IndexTip] = new JointPose(new RigidPose(joints[8], rotations[8] * rotOffset)); + + state.handJoints[HandJointName.MiddleProximal] = new JointPose(new RigidPose(joints[9], rotations[9] * rotOffset)); + state.handJoints[HandJointName.MiddleIntermediate] = new JointPose(new RigidPose(joints[10], rotations[10] * rotOffset)); + state.handJoints[HandJointName.MiddleDistal] = new JointPose(new RigidPose(joints[11], rotations[11] * rotOffset)); + state.handJoints[HandJointName.MiddleTip] = new JointPose(new RigidPose(joints[12], rotations[12] * rotOffset)); + + state.handJoints[HandJointName.RingProximal] = new JointPose(new RigidPose(joints[13], rotations[13] * rotOffset)); + state.handJoints[HandJointName.RingIntermediate] = new JointPose(new RigidPose(joints[14], rotations[14] * rotOffset)); + state.handJoints[HandJointName.RingDistal] = new JointPose(new RigidPose(joints[15], rotations[15] * rotOffset)); + state.handJoints[HandJointName.RingTip] = new JointPose(new RigidPose(joints[16], rotations[16] * rotOffset)); + + state.handJoints[HandJointName.PinkyProximal] = new JointPose(new RigidPose(joints[17], rotations[17] * rotOffset)); + state.handJoints[HandJointName.PinkyIntermediate] = new JointPose(new RigidPose(joints[18], rotations[18] * rotOffset)); + state.handJoints[HandJointName.PinkyDistal] = new JointPose(new RigidPose(joints[19], rotations[19] * rotOffset)); + state.handJoints[HandJointName.PinkyTip] = new JointPose(new RigidPose(joints[20], rotations[20] * rotOffset)); + } +#else + [StructLayout(LayoutKind.Sequential)] + private struct GestureResult + { + [MarshalAs(UnmanagedType.I1)] + public bool isLeft; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)] + public Vector3[] points; + public GestureType gesture; + public float confidence; + public float pinchLevel; + } + + private void UpdateDeviceInput(ref HandResultData resultData, uint index) + { + if (!resultData.isConnected) { return; } + + IVRModuleDeviceState prevState; + IVRModuleDeviceStateRW currState; + + EnsureValidDeviceState(index, out prevState, out currState); + + var pinched = resultData.rawData.pinchLevel >= 0.95f; + var gFist = resultData.rawData.gesture == GestureType.Fist && resultData.rawData.confidence > 0.1f; + var gFive = resultData.rawData.gesture == GestureType.Five && resultData.rawData.confidence > 0.1f; + var gOK = resultData.rawData.gesture == GestureType.OK && resultData.rawData.confidence > 0.1f; + var gLike = resultData.rawData.gesture == GestureType.Like && resultData.rawData.confidence > 0.1f; + var gPoint = resultData.rawData.gesture == GestureType.Point && resultData.rawData.confidence > 0.1f; + currState.SetButtonPress(VRModuleRawButton.GestureIndexPinch, pinched); + currState.SetButtonTouch(VRModuleRawButton.GestureIndexPinch, pinched); + currState.SetButtonPress(VRModuleRawButton.GestureFist, gFist); + currState.SetButtonTouch(VRModuleRawButton.GestureFist, gFist); + currState.SetButtonPress(VRModuleRawButton.GestureFive, gFive); + currState.SetButtonTouch(VRModuleRawButton.GestureFive, gFive); + currState.SetButtonPress(VRModuleRawButton.GestureOk, gOK); + currState.SetButtonTouch(VRModuleRawButton.GestureOk, gOK); + currState.SetButtonPress(VRModuleRawButton.GestureThumbUp, gLike); + currState.SetButtonTouch(VRModuleRawButton.GestureThumbUp, gLike); + currState.SetButtonPress(VRModuleRawButton.GestureIndexUp, gPoint); + currState.SetButtonTouch(VRModuleRawButton.GestureIndexUp, gPoint); + currState.SetButtonPress(VRModuleRawButton.Grip, gFist); + currState.SetButtonTouch(VRModuleRawButton.Grip, gFist); + currState.SetAxisValue(VRModuleRawAxis.Trigger, resultData.rawData.pinchLevel); + } + + private static void UpdateDeviceJoints(IVRModuleDeviceStateRW state, ref HandResultData resultData, bool isLeft) + { + var rawJoints = resultData.rawData.points; + var roomSpaceWrist2index = rawJoints[5] - rawJoints[0]; var roomSpaceWrist2middle = rawJoints[9] - rawJoints[0]; var roomSpaceWrist2pinky = rawJoints[17] - rawJoints[0]; @@ -299,18 +405,7 @@ private static Quaternion CalculateJointRot(Vector3[] joints, int i, int iChild, var forward = joints[iChild] - joints[i]; return Quaternion.LookRotation(forward, Vector3.Cross(forward, right)); } - - [StructLayout(LayoutKind.Sequential)] - private struct GestureResult - { - [MarshalAs(UnmanagedType.I1)] - public bool isLeft; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)] - public Vector3[] points; - public GestureType gesture; - public float confidence; - public float pinchLevel; - } +#endif private static class GestureInterface { @@ -332,5 +427,5 @@ private static class GestureInterface internal static extern void SetCameraTransform(Vector3 position, Quaternion rotation); } #endif - } - } \ No newline at end of file + } +} \ No newline at end of file From 793f63c82f6e8a77a03962f7d703d1e5f4fb414e Mon Sep 17 00:00:00 2001 From: lawwong Date: Thu, 3 Jun 2021 22:47:23 +0800 Subject: [PATCH 04/13] Add UnknownControllerState from CommonUsages --- .../VRModule/Modules/UnityXRModule.cs | 44 ++++++++++++++++++- .../Submodules/ViveHandTrackingSubmodule.cs | 4 +- .../HTC.UnityPlugin/VRModule/VRModuleBase.cs | 1 + 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs index c3a111fd..74aac5e5 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs @@ -120,7 +120,7 @@ protected override void UpdateNewConnectedInputDevice(IVRModuleDeviceStateRW sta updateFunc = UpdateWaveCRControllerState; break; default: - updateFunc = null; + updateFunc = UpdateUnknownControllerState; break; } @@ -176,6 +176,48 @@ private void UpdateControllerState(IVRModuleDeviceStateRW state, InputDevice dev } } + private void UpdateUnknownControllerState(IVRModuleDeviceStateRW state, InputDevice device) + { + bool primaryButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.primaryButton); + bool primaryTouch = GetDeviceFeatureValueOrDefault(device, CommonUsages.primaryTouch); + bool secondaryButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.secondaryButton); + bool secondaryTouch = GetDeviceFeatureValueOrDefault(device, CommonUsages.secondaryTouch); + bool gripButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.gripButton); + bool triggerButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.triggerButton); + bool menuButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.menuButton); + bool primary2DAxisClick = GetDeviceFeatureValueOrDefault(device, CommonUsages.primary2DAxisClick); + bool primary2DAxisTouch = GetDeviceFeatureValueOrDefault(device, CommonUsages.primary2DAxisTouch); + bool secondary2DAxisClick = GetDeviceFeatureValueOrDefault(device, CommonUsages.secondary2DAxisClick); + bool secondary2DAxisTouch = GetDeviceFeatureValueOrDefault(device, CommonUsages.secondary2DAxisTouch); + + float triggerValue = GetDeviceFeatureValueOrDefault(device, CommonUsages.trigger); + float gripValue = GetDeviceFeatureValueOrDefault(device, CommonUsages.grip); + + Vector2 primary2DAxisValue = GetDeviceFeatureValueOrDefault(device, CommonUsages.primary2DAxis); + Vector2 secondary2DAxisValue = GetDeviceFeatureValueOrDefault(device, CommonUsages.secondary2DAxis); + + state.SetButtonPress(VRModuleRawButton.A, primaryButton); + state.SetButtonPress(VRModuleRawButton.ApplicationMenu, secondaryButton | menuButton); + state.SetButtonPress(VRModuleRawButton.Trigger, triggerButton); + state.SetButtonPress(VRModuleRawButton.Grip, gripButton); + state.SetButtonPress(VRModuleRawButton.Touchpad, primary2DAxisClick); + state.SetButtonPress(VRModuleRawButton.Joystick, secondary2DAxisClick); + + state.SetButtonTouch(VRModuleRawButton.A, primaryTouch); + state.SetButtonTouch(VRModuleRawButton.ApplicationMenu, secondaryTouch | menuButton); + state.SetButtonTouch(VRModuleRawButton.Trigger, triggerButton); + state.SetButtonTouch(VRModuleRawButton.Grip, gripButton); + state.SetButtonTouch(VRModuleRawButton.Touchpad, primary2DAxisTouch); + state.SetButtonTouch(VRModuleRawButton.Joystick, secondary2DAxisTouch); + + state.SetAxisValue(VRModuleRawAxis.Trigger, triggerValue); + state.SetAxisValue(VRModuleRawAxis.CapSenseGrip, gripValue); + state.SetAxisValue(VRModuleRawAxis.TouchpadX, primary2DAxisValue.x); + state.SetAxisValue(VRModuleRawAxis.TouchpadY, primary2DAxisValue.y); + state.SetAxisValue(VRModuleRawAxis.JoystickX, secondary2DAxisValue.x); + state.SetAxisValue(VRModuleRawAxis.JoystickY, secondary2DAxisValue.y); + } + private void UpdateViveControllerState(IVRModuleDeviceStateRW state, InputDevice device) { bool menuButton = GetDeviceFeatureValueOrDefault(device, CommonUsages.menuButton); diff --git a/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs b/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs index 805c0bae..b3e40a9d 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Submodules/ViveHandTrackingSubmodule.cs @@ -71,7 +71,7 @@ private IEnumerator StartDetectionCoroutine() retryCount = RETRY_COUNT; lastResultFrame = -1; isStarted = true; - Debug.Log(LOG_PREFIX + "StartGestureDetection"); + Debug.Log(LOG_PREFIX + "Detection started"); break; case GestureFailure.Camera: --retryCount; @@ -121,7 +121,7 @@ protected override void OnUpdateDeviceConnectionAndPoses() if (resultFrame < 0) { - Debug.Log("[ViveHandTrackingSubmodule] Detection stopped!"); + Debug.Log(LOG_PREFIX + "Detection stopped"); isStarted = false; return; } diff --git a/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs b/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs index 1f22d01c..5df91334 100644 --- a/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs +++ b/Assets/HTC.UnityPlugin/VRModule/VRModuleBase.cs @@ -386,6 +386,7 @@ protected static void SetupKnownDeviceModel(IVRModuleDeviceStateRW deviceState) } deviceState.deviceModel = VRModuleDeviceModel.Unknown; + deviceState.input2DType = VRModuleInput2DType.Unknown; } public static bool AxisToPress(bool previousPressedState, float currentAxisValue, float setThreshold, float unsetThreshold) From a59d93e7b7baaa4fd6a63a2f1d9cec5717402650 Mon Sep 17 00:00:00 2001 From: lawwong Date: Thu, 10 Jun 2021 15:08:23 +0800 Subject: [PATCH 05/13] Fix Oculus CapSenseGrip returns JoystickX value --- Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs index 74aac5e5..e19101b9 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModule.cs @@ -373,8 +373,8 @@ private void UpdateOculusControllerState(IVRModuleDeviceStateRW state, InputDevi state.SetAxisValue(VRModuleRawAxis.Trigger, trigger); state.SetAxisValue(VRModuleRawAxis.CapSenseGrip, grip); - state.SetAxisValue(VRModuleRawAxis.JoystickX, primary2DAxis.x); - state.SetAxisValue(VRModuleRawAxis.JoystickY, primary2DAxis.y); + state.SetAxisValue(VRModuleRawAxis.TouchpadX, primary2DAxis.x); + state.SetAxisValue(VRModuleRawAxis.TouchpadY, primary2DAxis.y); if (KnownActiveInputSubsystem == VRModuleKnownXRInputSubsystem.OpenVR) { From 986110b6d3be959bbcdc204c4cc92149b08be337 Mon Sep 17 00:00:00 2001 From: lawwong Date: Thu, 10 Jun 2021 18:11:15 +0800 Subject: [PATCH 06/13] Now grabbable can be stretched when there're more then 2 grabbers Must have valid min/maxScaleOnStretch value (min < max) or it won't scale (stretch only) Must enable "multiple grabbers" option --- .../Examples/3.3DDrag/Scripts/Draggable.cs | 28 +- .../Scripts/Misc/BasicGrabbable.cs | 8 + .../Scripts/Misc/GrabbableBase.cs | 240 ++++++++++++++++-- .../Scripts/Misc/StickyGrabbable.cs | 8 + 4 files changed, 249 insertions(+), 35 deletions(-) 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 aea283e5..e633b88c 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/3.3DDrag/Scripts/Draggable.cs @@ -53,11 +53,11 @@ public override RigidPose grabberOrigin { var cam = eventData.pointerPressRaycast.module.eventCamera; var ray = cam.ScreenPointToRay(eventData.position); - return new RigidPose(ray.origin, Quaternion.LookRotation(ray.direction, cam.transform.up)); + return new RigidPose(ray.origin, Quaternion.LookRotation(ray.direction, cam.transform.up)) * grabber2hit; } } - public override RigidPose grabOffset { get { return grabber2hit * hit2pivot; } set { hit2pivot = grabber2hit.GetInverse() * value; } } + public override RigidPose grabOffset { get { return hit2pivot; } set { hit2pivot = value; } } public RigidPose grabber2hit { get; set; } @@ -94,6 +94,10 @@ public float hitDistance [SerializeField] [FormerlySerializedAs("m_scrollDelta")] private float m_scrollingSpeed = 0.01f; + [SerializeField] + private float m_minStretchScale = 1f; + [SerializeField] + private float m_maxStretchScale = 1f; [FormerlySerializedAs("afterGrabbed")] [SerializeField] private UnityEventDraggable m_afterGrabbed = new UnityEventDraggable(); @@ -116,6 +120,10 @@ public float hitDistance public bool unblockableGrab { get { return m_unblockableGrab; } set { m_unblockableGrab = value; } } + public override float minScaleOnStretch { get { return m_minStretchScale; } set { m_minStretchScale = value; } } + + public override float maxScaleOnStretch { get { return m_maxStretchScale; } set { m_maxStretchScale = value; } } + public UnityEventDraggable afterGrabbed { get { return m_afterGrabbed; } } public UnityEventDraggable beforeRelease { get { return m_beforeRelease; } } @@ -189,15 +197,16 @@ public virtual void OnBeginDrag(PointerEventData eventData) } } + private static WaitForFixedUpdate waitForFixedUpdate = new WaitForFixedUpdate(); private IEnumerator PhysicsGrabUpdate() { - yield return new WaitForFixedUpdate(); + yield return waitForFixedUpdate; while (isGrabbed) { OnGrabRigidbody(); - yield return new WaitForFixedUpdate(); + yield return waitForFixedUpdate; } yield break; @@ -209,11 +218,14 @@ private IEnumerator DragUpdate() while (isGrabbed) { - var grabber = currentGrabber; - var scrollDelta = grabber.eventData.scrollDelta * m_scrollingSpeed; - if (scrollDelta != Vector2.zero) + for (int i = allGrabbers.Count - 1; i >= 0; --i) { - grabber.hitDistance = Mathf.Max(0f, grabber.hitDistance + scrollDelta.y); + var grabber = allGrabbers.GetValueByIndex(i); + var scrollDelta = grabber.eventData.scrollDelta * m_scrollingSpeed; + if (scrollDelta != Vector2.zero) + { + grabber.hitDistance = Mathf.Max(0f, grabber.hitDistance + scrollDelta.y); + } } if (!moveByVelocity) diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs index 4a30cc08..4988bd4d 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/BasicGrabbable.cs @@ -80,6 +80,10 @@ public static void Release(Grabber grabber) private bool m_allowMultipleGrabbers = true; [SerializeField] private bool m_grabOnLastEntered = false; + [SerializeField] + private float m_minStretchScale = 1f; + [SerializeField] + private float m_maxStretchScale = 1f; [FormerlySerializedAs("afterGrabbed")] [SerializeField] private UnityEventGrabbable m_afterGrabbed = new UnityEventGrabbable(); @@ -98,6 +102,10 @@ public static void Release(Grabber grabber) public bool grabOnLastEntered { get { return m_grabOnLastEntered; } set { m_grabOnLastEntered = value; } } + public override float minScaleOnStretch { get { return m_minStretchScale; } set { m_minStretchScale = value; } } + + public override float maxScaleOnStretch { get { return m_maxStretchScale; } set { m_maxStretchScale = value; } } + public UnityEventGrabbable afterGrabbed { get { return m_afterGrabbed; } } public UnityEventGrabbable beforeRelease { get { return m_beforeRelease; } } diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/GrabbableBase.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/GrabbableBase.cs index 41a95a6a..8b69c7c0 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/GrabbableBase.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/GrabbableBase.cs @@ -40,6 +40,8 @@ private struct PoseSample public abstract bool isGrabbed { get; } public abstract bool isChangingGrabber { get; } public abstract GrabberBase currentGrabberBase { get; } + public abstract float minScaleOnStretch { get; set; } + public abstract float maxScaleOnStretch { get; set; } public Rigidbody grabRigidbody { get; protected set; } private Queue m_poseSamples = new Queue(); @@ -63,32 +65,6 @@ protected void RecordLatestPosesForDrop(float currentTime, float recordLength) }); } - protected virtual void OnGrabRigidbody() - { - var currentGrabber = currentGrabberBase; - var targetPose = currentGrabber.grabberOrigin * currentGrabber.grabOffset; - ModifyPose(ref targetPose, true); - - RigidPose.SetRigidbodyVelocity(grabRigidbody, grabRigidbody.position, targetPose.pos, followingDuration); - RigidPose.SetRigidbodyAngularVelocity(grabRigidbody, grabRigidbody.rotation, targetPose.rot, followingDuration, overrideMaxAngularVelocity); - } - - protected virtual void OnGrabTransform() - { - var currentGrabber = currentGrabberBase; - var targetPose = currentGrabber.grabberOrigin * currentGrabber.grabOffset; - ModifyPose(ref targetPose, true); - - if (grabRigidbody != null) - { - grabRigidbody.velocity = Vector3.zero; - grabRigidbody.angularVelocity = Vector3.zero; - } - - transform.position = targetPose.pos; - transform.rotation = targetPose.rot; - } - protected virtual void DoDrop() { if (grabRigidbody != null && !grabRigidbody.isKinematic && m_poseSamples.Count > 0) @@ -102,6 +78,82 @@ protected virtual void DoDrop() m_poseSamples.Clear(); } } + + protected abstract void OnGrabRigidbody(); + + protected abstract void OnGrabTransform(); + + public struct StretchAnchors + { + // A1: first anchor + // A2: second anchor + // C: strethable center + // P: closest point on line A1-A2 away from C + private Vector3 originScale; + private float A1A2Len; + private float A1PLen; + private float PCLen; + private Quaternion originRotOffset; + private Quaternion lastRot; + + public void SetupStartingAnchors(Vector3 anchor1, Vector3 anchor2, Vector3 originPos, Quaternion originRot, Vector3 originScale) + { + // FIXME: what if anchor1 == anchor2? + this.originScale = originScale; + + var vectorS1S2 = anchor2 - anchor1; + A1A2Len = Vector3.Magnitude(vectorS1S2); + + var vectorS1C = originPos - anchor1; + A1PLen = Vector3.Dot(vectorS1C, vectorS1S2) / A1A2Len; + PCLen = Mathf.Sqrt(vectorS1C.sqrMagnitude - A1PLen * A1PLen); + + var normal = Vector3.Cross(vectorS1S2, vectorS1C); + var rot = Quaternion.LookRotation(vectorS1S2, normal); + originRotOffset = Quaternion.Inverse(rot) * originRot; + + lastRot = rot; + } + + public void UpdateAnchors(Vector3 anchor1, Vector3 anchor2, out Vector3 newPos, out Quaternion newRot, out Vector3 newScale, float minScale, float maxScale) + { + // determin scale ratio + var vectorS1S2 = anchor2 - anchor1; + var vectorS1S2Len = vectorS1S2.magnitude; + var vectorS1S2Norm = vectorS1S2 / vectorS1S2Len; + var posScale = vectorS1S2Len / A1A2Len; + + lastRot = Quaternion.FromToRotation(lastRot * Vector3.forward, vectorS1S2Norm) * lastRot; + var tangent = lastRot * Vector3.right; + + var transformScale = 1f; + minScale = Mathf.Abs(minScale); + maxScale = Mathf.Abs(maxScale); + if (minScale < maxScale) + { + // FIXME: what if originScale have zero value? + var originScaleAbs = new Vector3(Mathf.Abs(originScale.x), Mathf.Abs(originScale.y), Mathf.Abs(originScale.z)); + if (originScaleAbs.x == originScaleAbs.y && originScaleAbs.y == originScaleAbs.z) + { + transformScale = Mathf.Clamp(posScale, minScale / originScaleAbs.x, maxScale / originScaleAbs.x); + } + else + { + // when scale is irregular, clamp the scale factor to make sure no scale value is out of min/max range + var minScaleAxis = Mathf.Min(originScaleAbs.x, originScaleAbs.y, originScaleAbs.z); + var maxScaleAxis = Mathf.Max(originScaleAbs.x, originScaleAbs.y, originScaleAbs.z); + if (minScaleAxis / maxScaleAxis >= minScale / maxScale) + { + transformScale = Mathf.Clamp(posScale, minScale / minScaleAxis, maxScale / maxScaleAxis); + } + } + } + + newPos = anchor1 + vectorS1S2Norm * A1PLen * posScale + tangent * PCLen * transformScale; + newRot = lastRot * originRotOffset; + newScale = originScale * transformScale; + } + } } public abstract class GrabbableBase : GrabbableBase where TGrabber : GrabberBase where TEventData : BaseEventData @@ -119,6 +171,10 @@ public abstract class GrabbableBase : GrabbableBase where public event Action beforeGrabberReleased; // get grabber that about to release here public event Action onGrabberDrop; // manually change drop velocity here + private TGrabber anchorGabber1; + private TGrabber anchorGabber2; + private StretchAnchors stretchAnchors; + protected bool IsGrabberExists(TEventData eventData) { return m_grabbers.ContainsKey(eventData); @@ -129,6 +185,35 @@ protected bool TryGetExistsGrabber(TEventData eventData, out TGrabber grabber) return m_grabbers.TryGetValue(eventData, out grabber); } + protected bool TryGetValidAnchors(out TGrabber grabber1, out TGrabber grabber2, out Vector3 pose1, out Vector3 pose2) + { + var i = m_grabbers.Count - 1; + if (i >= 1) + { + var g1 = m_grabbers.GetValueByIndex(i); + var p1 = g1.grabberOrigin.pos; + for (--i; i >= 0; --i) + { + var g2 = m_grabbers.GetValueByIndex(i); + var p2 = g2.grabberOrigin.pos; + if (!Mathf.Approximately((p2 - p1).magnitude, 0f)) + { + grabber1 = g1; + grabber2 = g2; + pose1 = p1; + pose2 = p2; + return true; + } + } + } + + grabber1 = default(TGrabber); + grabber2 = default(TGrabber); + pose1 = default(Vector3); + pose2 = default(Vector3); + return false; + } + protected abstract TGrabber CreateGrabber(TEventData eventData); protected abstract void DestoryGrabber(TGrabber grabber); @@ -146,6 +231,18 @@ protected bool AddGrabber(TEventData eventData) if (isGrabbed) { beforeGrabberReleased(); } m_grabbers.Add(eventData, newGrabber); + + Vector3 p1, p2; + if (TryGetValidAnchors(out anchorGabber1, out anchorGabber2, out p1, out p2)) + { + stretchAnchors.SetupStartingAnchors( + p1, + p2, + transform.position, + transform.rotation, + transform.localScale); + } + afterGrabberGrabbed(); return true; } @@ -177,6 +274,21 @@ protected bool RemoveGrabber(TEventData eventData) finally { ExitGrabberChangingLock(); } } + Vector3 p1, p2; + if (TryGetValidAnchors(out anchorGabber1, out anchorGabber2, out p1, out p2)) + { + stretchAnchors.SetupStartingAnchors( + p1, + p2, + transform.position, + transform.rotation, + transform.localScale); + } + else if (m_grabbers.Count > 0) + { + currentGrabber.grabOffset = currentGrabber.grabberOrigin.GetInverse() * new RigidPose(transform); + } + return true; } @@ -216,9 +328,83 @@ private void ExitGrabberChangingLock() { m_grabberChangingLock = false; } + + protected override void OnGrabRigidbody() + { + if (anchorGabber1 != null && anchorGabber2 != null) + { + Vector3 pos; + Quaternion rot; + Vector3 scale; + stretchAnchors.UpdateAnchors( + anchorGabber1.grabberOrigin.pos, + anchorGabber2.grabberOrigin.pos, + out pos, + out rot, + out scale, + minScaleOnStretch, + maxScaleOnStretch); + + GrabRigidbodyToPose(new RigidPose(pos, rot)); + transform.localScale = scale; + } + else + { + var currentGrabber = currentGrabberBase; + GrabRigidbodyToPose(currentGrabber.grabberOrigin * currentGrabber.grabOffset); + } + } + + protected override void OnGrabTransform() + { + if (anchorGabber1 != null && anchorGabber2 != null) + { + Vector3 pos; + Quaternion rot; + Vector3 scale; + stretchAnchors.UpdateAnchors( + anchorGabber1.grabberOrigin.pos, + anchorGabber2.grabberOrigin.pos, + out pos, + out rot, + out scale, + minScaleOnStretch, + maxScaleOnStretch); + + GrabTransformToPose(new RigidPose(pos, rot)); + transform.localScale = scale; + } + else + { + var currentGrabber = currentGrabberBase; + GrabTransformToPose(currentGrabber.grabberOrigin * currentGrabber.grabOffset); + } + } + + protected void GrabRigidbodyToPose(RigidPose targetPose) + { + ModifyPose(ref targetPose, true); + + RigidPose.SetRigidbodyVelocity(grabRigidbody, grabRigidbody.position, targetPose.pos, followingDuration); + RigidPose.SetRigidbodyAngularVelocity(grabRigidbody, grabRigidbody.rotation, targetPose.rot, followingDuration, overrideMaxAngularVelocity); + } + + protected void GrabTransformToPose(RigidPose targetPose) + { + ModifyPose(ref targetPose, true); + + if (grabRigidbody != null) + { + grabRigidbody.velocity = Vector3.zero; + grabRigidbody.angularVelocity = Vector3.zero; + } + + transform.position = targetPose.pos; + transform.rotation = targetPose.rot; + } } - [Obsolete("Use GrabbableBase.Generic instead")] + [Obsolete("Use GrabbableBase instead")] public abstract class GrabbableBase : BasePoseTracker where TGrabber : class, GrabbableBase.IGrabber { public const float MIN_FOLLOWING_DURATION = 0.02f; diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs index 32ea46cf..831f45d7 100644 --- a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs +++ b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/StickyGrabbable.cs @@ -100,6 +100,10 @@ private struct ButtonProcessedState private bool m_allowMultipleGrabbers = false; [SerializeField] private bool m_grabOnLastEntered = false; + [SerializeField] + private float m_minStretchScale = 1f; + [SerializeField] + private float m_maxStretchScale = 1f; [FormerlySerializedAs("afterGrabbed")] [SerializeField] private UnityEventGrabbable m_afterGrabbed = new UnityEventGrabbable(); @@ -120,6 +124,10 @@ private struct ButtonProcessedState public bool grabOnLastEntered { get { return m_grabOnLastEntered; } set { m_grabOnLastEntered = value; } } + public override float minScaleOnStretch { get { return m_minStretchScale; } set { m_minStretchScale = value; } } + + public override float maxScaleOnStretch { get { return m_maxStretchScale; } set { m_maxStretchScale = value; } } + public UnityEventGrabbable afterGrabbed { get { return m_afterGrabbed; } } public UnityEventGrabbable beforeRelease { get { return m_beforeRelease; } } From 8258b57ea62b3bf1fe4045995492ee136a1302c9 Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Sat, 19 Jun 2021 13:49:31 +0800 Subject: [PATCH 07/13] Add A, B, X, Y buttons support using Unity 2018 * App built with Unity 2018 and run on Focus 3 * Using Wave SDK 3.2 --- .../VRModule/Modules/WaveVRModule.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs index 8a42d492..e4d3d1c8 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs @@ -437,14 +437,18 @@ public override void OnActivated() WaveVR_ButtonList.EControllerButtons.Grip, WaveVR_ButtonList.EControllerButtons.Menu, WaveVR_ButtonList.EControllerButtons.Touchpad, - WaveVR_ButtonList.EControllerButtons.Trigger + WaveVR_ButtonList.EControllerButtons.Trigger, + WaveVR_ButtonList.EControllerButtons.A_X, + WaveVR_ButtonList.EControllerButtons.B_Y }; buttonList.NonDominantButtons = new List() { WaveVR_ButtonList.EControllerButtons.Grip, WaveVR_ButtonList.EControllerButtons.Menu, WaveVR_ButtonList.EControllerButtons.Touchpad, - WaveVR_ButtonList.EControllerButtons.Trigger + WaveVR_ButtonList.EControllerButtons.Trigger, + WaveVR_ButtonList.EControllerButtons.A_X, + WaveVR_ButtonList.EControllerButtons.B_Y }; } } @@ -584,6 +588,9 @@ private void UpdateDeviceInput(uint deviceIndex, WaveVR_Controller.Device device var dpadUpPressed = deviceInput.GetPress(WVR_InputId.WVR_InputId_Alias1_DPad_Up); var dpadRightPressed = deviceInput.GetPress(WVR_InputId.WVR_InputId_Alias1_DPad_Right); var dpadDownPressed = deviceInput.GetPress(WVR_InputId.WVR_InputId_Alias1_DPad_Down); + var buttonAPressed = deviceInput.GetPress(WVR_InputId.WVR_InputId_Alias1_A); + var buttonBPressed = deviceInput.GetPress(WVR_InputId.WVR_InputId_Alias1_B); + currState.SetButtonPress(VRModuleRawButton.System, systemPressed); currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, menuPressed); currState.SetButtonPress(VRModuleRawButton.Touchpad, touchpadPressed || dpadLeftPressed || dpadUpPressed || dpadRightPressed || dpadDownPressed); @@ -593,6 +600,8 @@ private void UpdateDeviceInput(uint deviceIndex, WaveVR_Controller.Device device currState.SetButtonPress(VRModuleRawButton.DPadUp, dpadUpPressed); currState.SetButtonPress(VRModuleRawButton.DPadRight, dpadRightPressed); currState.SetButtonPress(VRModuleRawButton.DPadDown, dpadDownPressed); + currState.SetButtonPress(VRModuleRawButton.A, buttonAPressed); + currState.SetButtonPress(VRModuleRawButton.ApplicationMenu, buttonBPressed); var systemTouched = deviceInput.GetTouch(WVR_InputId.WVR_InputId_Alias1_System); var menuTouched = deviceInput.GetTouch(WVR_InputId.WVR_InputId_Alias1_Menu); From 1fa42f7f7b960be1a06885d6834d238a7a80a82d Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Thu, 24 Jun 2021 09:45:11 +0800 Subject: [PATCH 08/13] Add grip button axis support using Unity 2018 * App built with Unity 2018 and run on Focus 3 * Using Wave SDK 3.2 and patch files --- Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs index e4d3d1c8..995c91e4 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs @@ -625,7 +625,10 @@ private void UpdateDeviceInput(uint deviceIndex, WaveVR_Controller.Device device var triggerAxis = deviceInput.GetAxis(WVR_InputId.WVR_InputId_Alias1_Trigger); var touchAxis = deviceInput.GetAxis(WVR_InputId.WVR_InputId_Alias1_Touchpad); + var gripAxis = deviceInput.GetAxis(WVR_InputId.WVR_InputId_Alias1_Grip); + currState.SetAxisValue(VRModuleRawAxis.Trigger, triggerAxis.x); + currState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, gripAxis.x); currState.SetAxisValue(VRModuleRawAxis.TouchpadX, touchAxis.x); currState.SetAxisValue(VRModuleRawAxis.TouchpadY, touchAxis.y); } From b56ca33379ecfa9ba9bc723b7497573035b9f4e7 Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Thu, 24 Jun 2021 10:04:11 +0800 Subject: [PATCH 09/13] Remove extra currState.deviceClass assignment --- .../VRModule/Submodules/WaveHandTrackingSubmodule.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Submodules/WaveHandTrackingSubmodule.cs b/Assets/HTC.UnityPlugin/VRModule/Submodules/WaveHandTrackingSubmodule.cs index b7c16351..f8c19491 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Submodules/WaveHandTrackingSubmodule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Submodules/WaveHandTrackingSubmodule.cs @@ -87,7 +87,6 @@ protected override void OnUpdateDeviceConnectionAndPoses() { leftDeviceIndex = FindAndEnsureUnusedNotHMDDeviceState(out prevState, out currState); - currState.deviceClass = VRModuleDeviceClass.TrackedHand; currState.serialNumber = "WaveTrackedHandLeft"; currState.modelNumber = "WaveTrackedHandLeft"; currState.renderModelName = "WaveTrackedHandLeft"; @@ -120,7 +119,6 @@ protected override void OnUpdateDeviceConnectionAndPoses() { rightDeviceIndex = FindAndEnsureUnusedNotHMDDeviceState(out prevState, out currState); - currState.deviceClass = VRModuleDeviceClass.TrackedHand; currState.serialNumber = "WaveTrackedHandRight"; currState.modelNumber = "WaveTrackedHandRight"; currState.renderModelName = "WaveTrackedHandRight"; From 69caf015b7f279652d1704865b063a016656262f Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Thu, 24 Jun 2021 10:42:55 +0800 Subject: [PATCH 10/13] Fix always new GameObject for Wave render model * This case will only happen when user turns on/off controllers --- .../VRModule/Modules/WaveVRModule.cs | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs index 995c91e4..224b5c3d 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/WaveVRModule.cs @@ -79,19 +79,23 @@ public override void UpdateRenderModel() { UpdateDefaultRenderModel(false); - m_modelObj = new GameObject("Model"); - m_modelObj.SetActive(false); - m_modelObj.transform.SetParent(hook.transform, false); + if (m_modelObj == null) + { + m_modelObj = new GameObject("Model"); + m_modelObj.transform.SetParent(hook.transform, false); + m_modelObj.SetActive(false); #if VIU_WAVEXR_ESSENCE_CONTROLLER_MODEL #if VIU_WAVE_XRSDK_3_99_31_OR_NEWER - m_modelObj.transform.parent.gameObject.AddComponent(); + m_modelObj.transform.parent.gameObject.AddComponent(); #endif - m_modelObj.AddComponent(); - m_modelObj.AddComponent(); + m_modelObj.AddComponent(); + m_modelObj.AddComponent(); #elif VIU_WAVEXR_ESSENCE_RENDERMODEL - m_modelObj.AddComponent(); - m_modelObj.AddComponent(); + m_modelObj.AddComponent(); + m_modelObj.AddComponent(); #endif + } + m_modelObj.SetActive(true); } } @@ -112,24 +116,28 @@ public override void UpdateRenderModel() { UpdateDefaultRenderModel(false); - m_modelObj = new GameObject("Model"); - m_modelObj.SetActive(false); - m_modelObj.transform.SetParent(hook.transform, false); + if (m_modelObj == null) + { + m_modelObj = new GameObject("Model"); + m_modelObj.transform.SetParent(hook.transform, false); + m_modelObj.SetActive(false); #if VIU_WAVEXR_ESSENCE_CONTROLLER_MODEL #if VIU_WAVE_XRSDK_3_99_31_OR_NEWER - var pm = m_modelObj.transform.parent.gameObject.AddComponent(); - pm.WhichHand = XR_Hand.NonDominant; + var pm = m_modelObj.transform.parent.gameObject.AddComponent(); + pm.WhichHand = XR_Hand.NonDominant; #endif - var rm = m_modelObj.AddComponent(); - rm.WhichHand = XR_Hand.NonDominant; - var be = m_modelObj.AddComponent(); - be.HandType = XR_Hand.NonDominant; + var rm = m_modelObj.AddComponent(); + rm.WhichHand = XR_Hand.NonDominant; + var be = m_modelObj.AddComponent(); + be.HandType = XR_Hand.NonDominant; #elif VIU_WAVEXR_ESSENCE_RENDERMODEL - var rm = m_modelObj.AddComponent(); - rm.WhichHand = XR_Hand.NonDominant; - var be = m_modelObj.AddComponent(); - be.HandType = XR_Hand.NonDominant; + var rm = m_modelObj.AddComponent(); + rm.WhichHand = XR_Hand.NonDominant; + var be = m_modelObj.AddComponent(); + be.HandType = XR_Hand.NonDominant; #endif + } + m_modelObj.SetActive(true); } } From 8c7772f8ce122792fde9819c1bf5fc7e2760601c Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Thu, 24 Jun 2021 11:52:01 +0800 Subject: [PATCH 11/13] Add Interaction Mode support for Wave XR Plugin v4.1 --- .../Modules/Editor/WaveVRModuleEditor.cs | 19 +++++++++++++++++++ .../VRModule/Modules/UnityXRModuleBase.cs | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs index 834fafea..42521fcb 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs @@ -39,6 +39,25 @@ public WaveVRSymbolRequirementCollection() reqFileNames = new string[] { "RenderModel.cs", "ButtonEffect.cs", "ControllerTips.cs" }, }); + Add(new SymbolRequirement() + { + symbol = "VIU_WAVE_XRSDK_4_1_0_OR_NEWER", + reqTypeNames = new string[] { "Wave.Native.WVR_EventType" }, + validateFunc = (req) => + { + Type wvrEventType; + if (SymbolRequirement.s_foundTypes.TryGetValue("Wave.Native.WVR_EventType", out wvrEventType) && wvrEventType.IsEnum) + { + if (Enum.IsDefined(wvrEventType, "WVR_EventType_ArenaChanged")) + { + return true; + } + } + return false; + }, + reqFileNames = new string[] { "wvr.cs" }, + }); + Add(new SymbolRequirement() { symbol = "VIU_WAVE_XRSDK_3_99_31_OR_NEWER", diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs index 80ccf243..36054a3d 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs @@ -226,10 +226,16 @@ public sealed override void BeforeRenderUpdate() submodules.UpdateModulesDeviceConnectionAndPoses(); // process hand role +#if VIU_WAVE_XRSDK_4_1_0_OR_NEWER + var currentRight = submodules.GetFirstRightHandedIndex() != INVALID_DEVICE_INDEX ? submodules.GetFirstRightHandedIndex() : uxrRightIndex; + var currentLeft = submodules.GetFirstLeftHandedIndex() != INVALID_DEVICE_INDEX ? submodules.GetFirstLeftHandedIndex(): uxrLeftIndex; +#else var currentRight = uxrRightIndex != INVALID_DEVICE_INDEX ? uxrRightIndex : submodules.GetFirstRightHandedIndex(); var currentLeft = uxrLeftIndex != INVALID_DEVICE_INDEX ? uxrLeftIndex : submodules.GetFirstLeftHandedIndex(); +#endif var roleChanged = ChangeProp.Set(ref moduleRightIndex, currentRight); roleChanged |= ChangeProp.Set(ref moduleLeftIndex, currentLeft); + if (roleChanged) { InvokeControllerRoleChangedEvent(); From c0f18e7fe8cc0accd4481d69abbe302213a64626 Mon Sep 17 00:00:00 2001 From: ChengNan Yang Date: Fri, 25 Jun 2021 14:31:54 +0800 Subject: [PATCH 12/13] Update logic for interaction mode * Remove Wave XRSDK 4.1 tag --- .../Modules/Editor/WaveVRModuleEditor.cs | 19 ------------------- .../VRModule/Modules/UnityXRModuleBase.cs | 11 ++++------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs index 42521fcb..834fafea 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/Editor/WaveVRModuleEditor.cs @@ -39,25 +39,6 @@ public WaveVRSymbolRequirementCollection() reqFileNames = new string[] { "RenderModel.cs", "ButtonEffect.cs", "ControllerTips.cs" }, }); - Add(new SymbolRequirement() - { - symbol = "VIU_WAVE_XRSDK_4_1_0_OR_NEWER", - reqTypeNames = new string[] { "Wave.Native.WVR_EventType" }, - validateFunc = (req) => - { - Type wvrEventType; - if (SymbolRequirement.s_foundTypes.TryGetValue("Wave.Native.WVR_EventType", out wvrEventType) && wvrEventType.IsEnum) - { - if (Enum.IsDefined(wvrEventType, "WVR_EventType_ArenaChanged")) - { - return true; - } - } - return false; - }, - reqFileNames = new string[] { "wvr.cs" }, - }); - Add(new SymbolRequirement() { symbol = "VIU_WAVE_XRSDK_3_99_31_OR_NEWER", diff --git a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs index 36054a3d..e429c915 100644 --- a/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs +++ b/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleBase.cs @@ -226,13 +226,10 @@ public sealed override void BeforeRenderUpdate() submodules.UpdateModulesDeviceConnectionAndPoses(); // process hand role -#if VIU_WAVE_XRSDK_4_1_0_OR_NEWER - var currentRight = submodules.GetFirstRightHandedIndex() != INVALID_DEVICE_INDEX ? submodules.GetFirstRightHandedIndex() : uxrRightIndex; - var currentLeft = submodules.GetFirstLeftHandedIndex() != INVALID_DEVICE_INDEX ? submodules.GetFirstLeftHandedIndex(): uxrLeftIndex; -#else - var currentRight = uxrRightIndex != INVALID_DEVICE_INDEX ? uxrRightIndex : submodules.GetFirstRightHandedIndex(); - var currentLeft = uxrLeftIndex != INVALID_DEVICE_INDEX ? uxrLeftIndex : submodules.GetFirstLeftHandedIndex(); -#endif + var subRightIndex = submodules.GetFirstRightHandedIndex(); + var currentRight = (subRightIndex == INVALID_DEVICE_INDEX || (TryGetValidDeviceState(uxrRightIndex, out prevState, out currState) && currState.isPoseValid)) ? uxrRightIndex : subRightIndex; + var subLeftIndex = submodules.GetFirstLeftHandedIndex(); + var currentLeft = (subLeftIndex == INVALID_DEVICE_INDEX || (TryGetValidDeviceState(uxrLeftIndex, out prevState, out currState) && currState.isPoseValid)) ? uxrLeftIndex : subLeftIndex; var roleChanged = ChangeProp.Set(ref moduleRightIndex, currentRight); roleChanged |= ChangeProp.Set(ref moduleLeftIndex, currentLeft); From ae60aac6f195e9470b5a8c2c97e7e3add21b44c4 Mon Sep 17 00:00:00 2001 From: lawwong Date: Sat, 26 Jun 2021 01:44:39 +0800 Subject: [PATCH 13/13] Update version code to v1.13.2.0 --- Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs | 2 +- Assets/HTC.UnityPlugin/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs b/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/VIUVersion.cs index d69416b9..6cc858f9 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.13.1.0"); + public static readonly Version current = new Version("1.13.2.0"); } } \ No newline at end of file diff --git a/Assets/HTC.UnityPlugin/package.json b/Assets/HTC.UnityPlugin/package.json index b0ee9a21..4afb867d 100644 --- a/Assets/HTC.UnityPlugin/package.json +++ b/Assets/HTC.UnityPlugin/package.json @@ -1,6 +1,6 @@ { "name": "com.htc.upm.vive-input-utility", - "version": "1.13.0-preview.9", + "version": "1.13.2", "displayName": "VIVE Input Utility", "description": "The VIVE Input Utility (VIU) is a toolkit for developing VR experiences in Unity, especially with the VIVE/VIVE Pro but also targeting many platforms from a common code base including Oculus Rift, Rift S Go, Quest, Google Daydream, VIVE Wave SDK (e.g. VIVE Focus standalone) and additional VR platforms as supported by Unity such as Microsoft's 'Mixed Reality' VR headsets and more.\n\nCompatible with SteamVR 2.4.0+ and Oculus Integration 16.0+.\n\nView license:\nhttps://github.com/ViveSoftware/ViveInputUtility-Unity/blob/develop/LICENSE.md", "keywords": [