Skip to content

Commit c793e32

Browse files
committed
Add haptic and input profiles support
1 parent d3704fd commit c793e32

File tree

6 files changed

+114
-72
lines changed

6 files changed

+114
-72
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#if UNITY_INPUT_SYSTEM_1_4_4_OR_NEWER
2+
using System.Runtime.InteropServices;
3+
using UnityEngine.InputSystem.LowLevel;
4+
using UnityEngine.InputSystem.Utilities;
5+
6+
namespace WebXR.InputSystem
7+
{
8+
[StructLayout(LayoutKind.Explicit, Size = kSize)]
9+
internal struct InternalSendHapticImpulseCommand
10+
{
11+
internal static FourCC Type => new FourCC('X', 'H', 'I', '0');
12+
13+
private const int kSize = InputDeviceCommand.BaseCommandSize + sizeof(int) + (sizeof(float) * 2);
14+
15+
[FieldOffset(0)]
16+
internal InputDeviceCommand baseCommand;
17+
18+
[FieldOffset(InputDeviceCommand.BaseCommandSize)]
19+
internal int channel;
20+
21+
[FieldOffset(InputDeviceCommand.BaseCommandSize + sizeof(int))]
22+
internal float amplitude;
23+
24+
[FieldOffset(InputDeviceCommand.BaseCommandSize + sizeof(int) + (sizeof(float)))]
25+
internal float duration;
26+
}
27+
}
28+
#endif

Packages/webxr-interactions/Runtime/InputSystem/InternalSendHapticImpulseCommand.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Packages/webxr-interactions/Runtime/InputSystem/WebXR.InputSystem.asmdef

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
"references": [
55
"GUID:fd4abe4ffe74ef1448afe15c6cb36bb7",
66
"GUID:75469ad4d38634e559750d17036d5f7c",
7-
"GUID:ce522b6ed64c8be4c989a1d26d0e3275"
7+
"GUID:ce522b6ed64c8be4c989a1d26d0e3275",
8+
"GUID:fe685ec1767f73d42b749ea8045bfe43",
9+
"GUID:84a2d09f0bb073f40922f5ea5362abe7"
810
],
911
"includePlatforms": [],
1012
"excludePlatforms": [],
11-
"allowUnsafeCode": false,
13+
"allowUnsafeCode": true,
1214
"overrideReferences": false,
1315
"precompiledReferences": [],
1416
"autoReferenced": false,
@@ -23,6 +25,11 @@
2325
"name": "com.unity.xr.hands",
2426
"expression": "1.1.0",
2527
"define": "XR_HANDS_1_1_OR_NEWER"
28+
},
29+
{
30+
"name": "com.de-panther.webxr-input-profiles-loader",
31+
"expression": "0.4.0",
32+
"define": "WEBXR_INPUT_PROFILES"
2633
}
2734
],
2835
"noEngineReferences": false

Packages/webxr-interactions/Runtime/InputSystem/WebXRInputDevices.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ public struct WebXRControllerState : IInputStateTypeInfo
144144
[InputControl(bit = 0, offset = 48, sizeInBits = 1, layout = "Button")]
145145
public bool isTracked;
146146

147-
[InputControl(bit = 0, offset = 52, layout = "Vector3")]
147+
[InputControl(bit = 0, offset = 52, layout = "Vector3", alias = "gripPosition")]
148148
public Vector3 devicePosition;
149149

150-
[InputControl(bit = 0, offset = 64, layout = "Quaternion")]
150+
[InputControl(bit = 0, offset = 64, layout = "Quaternion", alias = "gripOrientation")]
151151
public Quaternion deviceRotation;
152152

153153
[InputControl(bit = 0, offset = 80, layout = "Vector3", noisy = true, dontReset = true)]

Packages/webxr-interactions/Runtime/InputSystem/WebXRInputSystem.cs

Lines changed: 63 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using UnityEngine;
2-
using InputDevice = UnityEngine.XR.InputDevice;
2+
using UnityEngine.Events;
33
#if UNITY_INPUT_SYSTEM_1_4_4_OR_NEWER
44
using UnityEngine.InputSystem;
55
using UnityEngine.InputSystem.Layouts;
6+
using UnityEngine.InputSystem.LowLevel;
67
#if XR_HANDS_1_1_OR_NEWER
78
using System.Collections;
89
using System.Collections.Generic;
@@ -19,15 +20,35 @@ namespace WebXR.InputSystem
1920
#endif
2021
public class WebXRInputSystem : MonoBehaviour
2122
{
22-
public Transform[] leftHandTransforms;
23-
public Transform[] rightHandTransforms;
24-
private Pose[] leftPoses;
25-
private Pose[] rightPoses;
26-
public Vector3 rightPos;
27-
public Vector3 leftPos;
28-
public Vector3 headPos;
29-
public int devicesType;
23+
[SerializeField]
24+
private UnityEvent onLeftControllerProfiles;
25+
public UnityEvent OnLeftControllerProfiles
26+
{
27+
get => onLeftControllerProfiles;
28+
set => onLeftControllerProfiles = value;
29+
}
30+
31+
[SerializeField]
32+
private UnityEvent onRightControllerProfiles;
33+
public UnityEvent OnRightControllerProfiles
34+
{
35+
get => onRightControllerProfiles;
36+
set => onRightControllerProfiles = value;
37+
}
38+
private string[] leftProfiles = null;
39+
private string[] rightProfiles = null;
40+
private bool hasLeftProfiles = false;
41+
private bool hasRightProfiles = false;
3042

43+
public string[] GetLeftProfiles()
44+
{
45+
return leftProfiles;
46+
}
47+
48+
public string[] GetRightProfiles()
49+
{
50+
return rightProfiles;
51+
}
3152
#if UNITY_INPUT_SYSTEM_1_4_4_OR_NEWER
3253
private static bool initialized = false;
3354
WebXRController left = null;
@@ -65,19 +86,15 @@ private void Awake()
6586
}
6687
}
6788
subsystemUpdater = new XRHandProviderUtility.SubsystemUpdater(webXRHandsSubsystem);
68-
69-
leftPoses = new Pose[leftHandTransforms.Length];
70-
rightPoses = new Pose[rightHandTransforms.Length];
71-
for (int i = 0; i < leftHandTransforms.Length; i++)
72-
{
73-
leftPoses[i] = new Pose(leftHandTransforms[i].position, leftHandTransforms[i].rotation);
74-
rightPoses[i] = new Pose(rightHandTransforms[i].position, rightHandTransforms[i].rotation);
75-
}
7689
#endif
7790
}
7891

7992
private void OnEnable()
8093
{
94+
unsafe
95+
{
96+
InputSystem.onDeviceCommand += HandleOnDeviceCommand;
97+
}
8198
WebXRManager.OnXRChange += OnXRChange;
8299
WebXRManager.OnHeadsetUpdate += OnHeadsetUpdate;
83100
WebXRManager.OnControllerUpdate += OnControllerUpdate;
@@ -90,6 +107,10 @@ private void OnEnable()
90107

91108
private void OnDisable()
92109
{
110+
unsafe
111+
{
112+
InputSystem.onDeviceCommand -= HandleOnDeviceCommand;
113+
}
93114
RemoveAllDevices();
94115
WebXRManager.OnXRChange -= OnXRChange;
95116
WebXRManager.OnHeadsetUpdate -= OnHeadsetUpdate;
@@ -121,64 +142,26 @@ private void OnDestroy()
121142
}
122143
#endif
123144

124-
/*
125-
private void Update1()
145+
private unsafe long? HandleOnDeviceCommand(
146+
UnityEngine.InputSystem.InputDevice inputDevice,
147+
InputDeviceCommand* command)
126148
{
127-
OnHeadsetUpdate(
128-
Matrix4x4.identity,
129-
Matrix4x4.identity,
130-
Quaternion.identity,
131-
Quaternion.identity,
132-
headPos,
133-
headPos
134-
);
135-
WebXRHandData handDataLeft = new();
136-
handDataLeft.frame = Time.frameCount;
137-
handDataLeft.enabled = devicesType == 2;
138-
handDataLeft.hand = 1;
139-
handDataLeft.trigger = 1;
140-
for (int i = 0; i < handDataLeft.joints.Length; i++)
149+
if (inputDevice != left && inputDevice != right)
141150
{
142-
handDataLeft.joints[i].radius = 0.01f;
143-
handDataLeft.joints[i].position = leftPoses[i].position;
144-
handDataLeft.joints[i].rotation = leftPoses[i].rotation;
145-
handDataLeft.joints[i].position += leftPos;
151+
return null;
146152
}
147-
OnHandUpdate(handDataLeft);
148-
WebXRHandData handDataRight = new();
149-
handDataRight.frame = Time.frameCount;
150-
handDataRight.enabled = devicesType == 2;
151-
handDataRight.hand = 2;
152-
handDataRight.trigger = 1;
153-
for (int i = 0; i < handDataRight.joints.Length; i++)
153+
if (command->type != InternalSendHapticImpulseCommand.Type)
154154
{
155-
handDataRight.joints[i].radius = 0.01f;
156-
handDataRight.joints[i].position = rightPoses[i].position;
157-
handDataRight.joints[i].rotation = rightPoses[i].rotation;
158-
handDataRight.joints[i].position += rightPos;
155+
return null;
159156
}
160-
OnHandUpdate(handDataRight);
161157

162-
WebXRControllerData controllerDataLeft = new WebXRControllerData();
163-
controllerDataLeft.frame = Time.frameCount;
164-
controllerDataLeft.enabled = devicesType == 1;
165-
controllerDataLeft.hand = 1;
166-
controllerDataLeft.position = leftPos;
167-
controllerDataLeft.rotation = Quaternion.identity;
168-
controllerDataLeft.gripPosition = leftPos;
169-
controllerDataLeft.gripRotation = Quaternion.identity;
170-
OnControllerUpdate(controllerDataLeft);
171-
WebXRControllerData controllerDataRight = new WebXRControllerData();
172-
controllerDataRight.frame = Time.frameCount;
173-
controllerDataRight.enabled = devicesType == 1;
174-
controllerDataRight.hand = 2;
175-
controllerDataRight.position = rightPos;
176-
controllerDataRight.rotation = Quaternion.identity;
177-
controllerDataRight.gripPosition = rightPos;
178-
controllerDataRight.gripRotation = Quaternion.identity;
179-
OnControllerUpdate(controllerDataRight);
158+
var impulseCommand = *(InternalSendHapticImpulseCommand*)command;
159+
WebXRManager.Instance.HapticPulse(
160+
inputDevice == left ? WebXRControllerHand.LEFT : WebXRControllerHand.RIGHT,
161+
impulseCommand.amplitude,
162+
impulseCommand.duration * 1000f);
163+
return 0;
180164
}
181-
*/
182165

183166
private void OnXRChange(
184167
WebXRState state,
@@ -232,9 +215,21 @@ private void OnControllerUpdate(WebXRControllerData controllerData)
232215
{
233216
case 1:
234217
UpdateController(controllerData, ref left);
218+
if (!hasLeftProfiles && controllerData.profiles != null)
219+
{
220+
leftProfiles = controllerData.profiles;
221+
hasLeftProfiles = true;
222+
onLeftControllerProfiles?.Invoke();
223+
}
235224
break;
236225
case 2:
237226
UpdateController(controllerData, ref right);
227+
if (!hasRightProfiles && controllerData.profiles != null)
228+
{
229+
rightProfiles = controllerData.profiles;
230+
hasRightProfiles = true;
231+
onRightControllerProfiles?.Invoke();
232+
}
238233
break;
239234
}
240235
}

Packages/webxr/Runtime/Scripts/WebXRManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public void ToggleVR()
106106
subsystem?.ToggleVR();
107107
}
108108

109+
// duration in milliseconds
109110
public void HapticPulse(WebXRControllerHand hand, float intensity, float duration)
110111
{
111112
subsystem?.HapticPulse(hand, intensity, duration);

0 commit comments

Comments
 (0)