Skip to content

Commit a1ab073

Browse files
committed
Added support for XR controllers in the editor
1 parent 67909db commit a1ab073

File tree

10 files changed

+218
-34
lines changed

10 files changed

+218
-34
lines changed

Build/Build/Build.data.unityweb

11.7 KB
Binary file not shown.

Build/Build/Build.wasm

84.5 KB
Binary file not shown.

Build/Build/Build.wasm.framework.unityweb

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

Packages/webxr-interactions/Runtime/Scripts/ControllerInteraction.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ void Start()
2525

2626
void Update()
2727
{
28+
controller.TryUpdateButtons();
29+
2830
float normalizedTime = controller.GetButton("Trigger") ? 1 : controller.GetAxis("Grip");
2931

3032
if (controller.GetButtonDown("Trigger") || controller.GetButtonDown("Grip"))

Packages/webxr-interactions/Samples~/Desert/ControllersMap/LeftControllerMap.asset

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,5 @@ MonoBehaviour:
1515
inputs:
1616
- actionName: Trigger
1717
gamepadId: 0
18-
gamepadIsButton: 1
19-
unityInputName: TriggerLeft
20-
unityInputIsButton: 0
2118
- actionName: Grip
2219
gamepadId: 1
23-
gamepadIsButton: 1
24-
unityInputName: GripLeft
25-
unityInputIsButton: 0

Packages/webxr-interactions/Samples~/Desert/ControllersMap/RightControllerMap.asset

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,5 @@ MonoBehaviour:
1515
inputs:
1616
- actionName: Trigger
1717
gamepadId: 0
18-
gamepadIsButton: 1
19-
unityInputName: TriggerRight
20-
unityInputIsButton: 0
2118
- actionName: Grip
2219
gamepadId: 1
23-
gamepadIsButton: 1
24-
unityInputName: GripRight
25-
unityInputIsButton: 0

Packages/webxr-interactions/Samples~/Desert/Prefabs/WebXRCameraSet.prefab

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,9 +977,6 @@ MonoBehaviour:
977977
m_Script: {fileID: 11500000, guid: 519f6ee6510174b44bbe9a8a2d3b6a6a, type: 3}
978978
m_Name:
979979
m_EditorClassIdentifier:
980-
dontDestroyOnLoad: 1
981-
DefaultHeight: 1.2
982-
xrState: 2
983980
--- !u!1 &1644691530447244
984981
GameObject:
985982
m_ObjectHideFlags: 0
@@ -1277,6 +1274,7 @@ GameObject:
12771274
- component: {fileID: 135139238002636258}
12781275
- component: {fileID: 114128207473628304}
12791276
- component: {fileID: 114589835210473740}
1277+
- component: {fileID: 7185579886917944061}
12801278
m_Layer: 0
12811279
m_Name: handL
12821280
m_TagString: Untagged
@@ -1396,6 +1394,24 @@ MonoBehaviour:
13961394
m_Script: {fileID: 11500000, guid: 580e3dd931df2bd42b042a7e8fde2aa8, type: 3}
13971395
m_Name:
13981396
m_EditorClassIdentifier:
1397+
--- !u!114 &7185579886917944061
1398+
MonoBehaviour:
1399+
m_ObjectHideFlags: 0
1400+
m_CorrespondingSourceObject: {fileID: 0}
1401+
m_PrefabInstance: {fileID: 0}
1402+
m_PrefabAsset: {fileID: 0}
1403+
m_GameObject: {fileID: 1799026754646168}
1404+
m_Enabled: 1
1405+
m_EditorHideFlags: 0
1406+
m_Script: {fileID: 11500000, guid: 5a2a9c34df4095f47b9ca8f975175f5b, type: 3}
1407+
m_Name:
1408+
m_EditorClassIdentifier:
1409+
m_Device: 1
1410+
m_PoseSource: 4
1411+
m_PoseProviderComponent: {fileID: 0}
1412+
m_TrackingType: 0
1413+
m_UpdateType: 0
1414+
m_UseRelativeTransform: 0
13991415
--- !u!1 &1836701339249518
14001416
GameObject:
14011417
m_ObjectHideFlags: 0
@@ -1437,6 +1453,7 @@ GameObject:
14371453
m_Component:
14381454
- component: {fileID: 4684771153913254}
14391455
- component: {fileID: 20092747195267750}
1456+
- component: {fileID: 2441852088187987231}
14401457
m_Layer: 0
14411458
m_Name: CameraMain
14421459
m_TagString: Untagged
@@ -1501,6 +1518,24 @@ Camera:
15011518
m_OcclusionCulling: 1
15021519
m_StereoConvergence: 10
15031520
m_StereoSeparation: 0.022
1521+
--- !u!114 &2441852088187987231
1522+
MonoBehaviour:
1523+
m_ObjectHideFlags: 0
1524+
m_CorrespondingSourceObject: {fileID: 0}
1525+
m_PrefabInstance: {fileID: 0}
1526+
m_PrefabAsset: {fileID: 0}
1527+
m_GameObject: {fileID: 1854678450583440}
1528+
m_Enabled: 1
1529+
m_EditorHideFlags: 0
1530+
m_Script: {fileID: 11500000, guid: 5a2a9c34df4095f47b9ca8f975175f5b, type: 3}
1531+
m_Name:
1532+
m_EditorClassIdentifier:
1533+
m_Device: 0
1534+
m_PoseSource: 2
1535+
m_PoseProviderComponent: {fileID: 0}
1536+
m_TrackingType: 0
1537+
m_UpdateType: 0
1538+
m_UseRelativeTransform: 0
15041539
--- !u!1 &1859026024318526
15051540
GameObject:
15061541
m_ObjectHideFlags: 0
@@ -1730,6 +1765,7 @@ GameObject:
17301765
- component: {fileID: 135505933631826540}
17311766
- component: {fileID: 114546255618804366}
17321767
- component: {fileID: 114372649503696970}
1768+
- component: {fileID: 1966769163579045322}
17331769
m_Layer: 0
17341770
m_Name: handR
17351771
m_TagString: Untagged
@@ -1849,6 +1885,24 @@ MonoBehaviour:
18491885
m_Script: {fileID: 11500000, guid: 580e3dd931df2bd42b042a7e8fde2aa8, type: 3}
18501886
m_Name:
18511887
m_EditorClassIdentifier:
1888+
--- !u!114 &1966769163579045322
1889+
MonoBehaviour:
1890+
m_ObjectHideFlags: 0
1891+
m_CorrespondingSourceObject: {fileID: 0}
1892+
m_PrefabInstance: {fileID: 0}
1893+
m_PrefabAsset: {fileID: 0}
1894+
m_GameObject: {fileID: 1986733487743170}
1895+
m_Enabled: 1
1896+
m_EditorHideFlags: 0
1897+
m_Script: {fileID: 11500000, guid: 5a2a9c34df4095f47b9ca8f975175f5b, type: 3}
1898+
m_Name:
1899+
m_EditorClassIdentifier:
1900+
m_Device: 1
1901+
m_PoseSource: 5
1902+
m_PoseProviderComponent: {fileID: 0}
1903+
m_TrackingType: 0
1904+
m_UpdateType: 0
1905+
m_UseRelativeTransform: 0
18521906
--- !u!1 &3250837035476248814
18531907
GameObject:
18541908
m_ObjectHideFlags: 0

Packages/webxr/Runtime/Scripts/WebXRController.cs

Lines changed: 149 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using UnityEngine;
2+
#if UNITY_EDITOR
3+
using UnityEngine.XR;
4+
#endif
25
using System;
36
using System.Collections.Generic;
47

@@ -43,6 +46,78 @@ public class WebXRController : MonoBehaviour
4346
private Dictionary<int, Transform> handJoints = new Dictionary<int, Transform>();
4447
private bool handJointsVisible = false;
4548

49+
#if UNITY_EDITOR
50+
private InputDeviceCharacteristics xrHand = InputDeviceCharacteristics.Controller;
51+
private InputDevice? inputDevice;
52+
private HapticCapabilities? hapticCapabilities;
53+
#endif
54+
55+
public void TryUpdateButtons()
56+
{
57+
#if UNITY_EDITOR
58+
if (!WebXRManager.Instance.isSubsystemAvailable && inputDevice != null)
59+
{
60+
inputDevice.Value.TryGetFeatureValue(CommonUsages.trigger, out trigger);
61+
inputDevice.Value.TryGetFeatureValue(CommonUsages.grip, out squeeze);
62+
if (trigger <= 0.02)
63+
{
64+
trigger = 0;
65+
}
66+
else if (trigger >= 0.98)
67+
{
68+
trigger = 1;
69+
}
70+
71+
if (squeeze <= 0.02)
72+
{
73+
squeeze = 0;
74+
}
75+
else if (squeeze >= 0.98)
76+
{
77+
squeeze = 1;
78+
}
79+
80+
Vector2 axis2D;
81+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.primary2DAxis, out axis2D))
82+
{
83+
thumbstickX = axis2D.x;
84+
thumbstickY = axis2D.y;
85+
}
86+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.secondary2DAxis, out axis2D))
87+
{
88+
touchpadX = axis2D.x;
89+
touchpadY = axis2D.y;
90+
}
91+
bool buttonPressed;
92+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out buttonPressed))
93+
{
94+
thumbstick = buttonPressed ? 1 : 0;
95+
}
96+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.secondary2DAxisClick, out buttonPressed))
97+
{
98+
touchpad = buttonPressed ? 1 : 0;
99+
}
100+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.primaryButton, out buttonPressed))
101+
{
102+
buttonA = buttonPressed ? 1 : 0;
103+
}
104+
if (inputDevice.Value.TryGetFeatureValue(CommonUsages.secondaryButton, out buttonPressed))
105+
{
106+
buttonB = buttonPressed ? 1 : 0;
107+
}
108+
109+
WebXRControllerButton[] buttons = new WebXRControllerButton[6];
110+
buttons[0] = new WebXRControllerButton(trigger == 1, trigger);
111+
buttons[1] = new WebXRControllerButton(squeeze == 1, squeeze);
112+
buttons[2] = new WebXRControllerButton(thumbstick == 1, thumbstick);
113+
buttons[3] = new WebXRControllerButton(touchpad == 1, touchpad);
114+
buttons[4] = new WebXRControllerButton(buttonA == 1, buttonA);
115+
buttons[5] = new WebXRControllerButton(buttonB == 1, buttonB);
116+
UpdateButtons(buttons);
117+
}
118+
#endif
119+
}
120+
46121
// Updates button states from Web gamepad API.
47122
private void UpdateButtons(WebXRControllerButton[] buttons)
48123
{
@@ -161,12 +236,12 @@ private void OnControllerUpdate(WebXRControllerData controllerData)
161236
buttonB = controllerData.buttonB;
162237

163238
WebXRControllerButton[] buttons = new WebXRControllerButton[6];
164-
buttons[0] = new WebXRControllerButton(trigger==1, trigger);
165-
buttons[1] = new WebXRControllerButton(squeeze==1, squeeze);
166-
buttons[2] = new WebXRControllerButton(thumbstick==1, thumbstick);
167-
buttons[3] = new WebXRControllerButton(touchpad==1, touchpad);
168-
buttons[4] = new WebXRControllerButton(buttonA==1, buttonA);
169-
buttons[5] = new WebXRControllerButton(buttonB==1, buttonB);
239+
buttons[0] = new WebXRControllerButton(trigger == 1, trigger);
240+
buttons[1] = new WebXRControllerButton(squeeze == 1, squeeze);
241+
buttons[2] = new WebXRControllerButton(thumbstick == 1, thumbstick);
242+
buttons[3] = new WebXRControllerButton(touchpad == 1, touchpad);
243+
buttons[4] = new WebXRControllerButton(buttonA == 1, buttonA);
244+
buttons[5] = new WebXRControllerButton(buttonB == 1, buttonB);
170245
UpdateButtons(buttons);
171246
}
172247
}
@@ -188,7 +263,7 @@ private void OnHandUpdate(WebXRHandData handData)
188263

189264
Quaternion rotationOffset = Quaternion.Inverse(handData.joints[0].rotation);
190265

191-
for(int i=0; i<=WebXRHandData.LITTLE_PHALANX_TIP; i++)
266+
for (int i = 0; i <= WebXRHandData.LITTLE_PHALANX_TIP; i++)
192267
{
193268
if (handData.joints[i].enabled)
194269
{
@@ -220,8 +295,8 @@ private void OnHandUpdate(WebXRHandData handData)
220295
squeeze = handData.squeeze;
221296

222297
WebXRControllerButton[] buttons = new WebXRControllerButton[2];
223-
buttons[0] = new WebXRControllerButton(trigger==1, trigger);
224-
buttons[1] = new WebXRControllerButton(squeeze==1, squeeze);
298+
buttons[0] = new WebXRControllerButton(trigger == 1, trigger);
299+
buttons[1] = new WebXRControllerButton(squeeze == 1, squeeze);
225300
UpdateButtons(buttons);
226301
}
227302
}
@@ -268,7 +343,19 @@ private void SetHandJointsVisible(bool visible)
268343
// intensity 0 to 1, duration milliseconds
269344
public void Pulse(float intensity, float duration)
270345
{
271-
WebXRManager.Instance.HapticPulse(hand, intensity, duration);
346+
if (WebXRManager.Instance.isSubsystemAvailable)
347+
{
348+
WebXRManager.Instance.HapticPulse(hand, intensity, duration);
349+
}
350+
#if UNITY_EDITOR
351+
else if (inputDevice != null && hapticCapabilities != null
352+
&& hapticCapabilities.Value.supportsImpulse)
353+
{
354+
// duration in seconds
355+
duration = duration * 0.001f;
356+
inputDevice.Value.SendHapticImpulse(0, intensity, duration);
357+
}
358+
#endif
272359
}
273360

274361
void OnEnable()
@@ -282,6 +369,27 @@ void OnEnable()
282369
WebXRManager.OnHandUpdate += OnHandUpdate;
283370
WebXRManager.OnHeadsetUpdate += onHeadsetUpdate;
284371
SetVisible(false);
372+
#if UNITY_EDITOR
373+
switch (hand)
374+
{
375+
case WebXRControllerHand.LEFT:
376+
xrHand = InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left;
377+
break;
378+
case WebXRControllerHand.RIGHT:
379+
xrHand = InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right;
380+
break;
381+
}
382+
383+
List<InputDevice> allDevices = new List<InputDevice>();
384+
InputDevices.GetDevicesWithCharacteristics(xrHand, allDevices);
385+
foreach (InputDevice device in allDevices)
386+
{
387+
HandleInputDevicesConnected(device);
388+
}
389+
390+
InputDevices.deviceConnected += HandleInputDevicesConnected;
391+
InputDevices.deviceDisconnected += HandleInputDevicesDisconnected;
392+
#endif
285393
}
286394

287395
void OnDisabled()
@@ -290,6 +398,37 @@ void OnDisabled()
290398
WebXRManager.OnHandUpdate -= OnHandUpdate;
291399
WebXRManager.OnHeadsetUpdate -= onHeadsetUpdate;
292400
SetVisible(false);
401+
#if UNITY_EDITOR
402+
InputDevices.deviceConnected -= HandleInputDevicesConnected;
403+
InputDevices.deviceDisconnected -= HandleInputDevicesDisconnected;
404+
inputDevice = null;
405+
#endif
406+
}
407+
408+
#if UNITY_EDITOR
409+
private void HandleInputDevicesConnected(InputDevice device)
410+
{
411+
if (device.characteristics.HasFlag(xrHand))
412+
{
413+
inputDevice = device;
414+
HapticCapabilities capabilities;
415+
if (device.TryGetHapticCapabilities(out capabilities))
416+
{
417+
hapticCapabilities = capabilities;
418+
}
419+
SetVisible(true);
420+
}
421+
}
422+
423+
private void HandleInputDevicesDisconnected(InputDevice device)
424+
{
425+
if (inputDevice != null && inputDevice.Value == device)
426+
{
427+
inputDevice = null;
428+
hapticCapabilities = null;
429+
SetVisible(false);
430+
}
293431
}
432+
#endif
294433
}
295434
}

Packages/webxr/Runtime/Scripts/WebXRControllerInputMap.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using UnityEngine;
3+
using UnityEngine.XR;
34

45
namespace WebXR
56
{
@@ -19,13 +20,5 @@ public class WebXRControllerInput
1920
[Header("Web Gamepad API configuration")]
2021
[Tooltip("Button or axes ID from Web Gamepad API.")]
2122
public int gamepadId;
22-
[Tooltip("Whether gesture derives its value from a Gamepad API `GamepadButton.pressed` property.")]
23-
public bool gamepadIsButton;
24-
25-
[Header("Unity Input Manager configuration")]
26-
[Tooltip("Input name defined in Unity Input Manager.")]
27-
public string unityInputName;
28-
[Tooltip("Whether gesture derives its value from Unity using `Input.GetButton` function.")]
29-
public bool unityInputIsButton;
3023
}
3124
}

Packages/webxr/Runtime/XRPlugin/XRSystemLifecycleManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ public class SubsystemLifecycleManager<TSubsystem, TSubsystemDescriptor> : MonoB
1313
/// </summary>
1414
public TSubsystem subsystem { get; private set; }
1515

16+
public bool isSubsystemAvailable
17+
{
18+
get
19+
{
20+
return subsystem != null;
21+
}
22+
}
23+
1624
protected virtual void Awake()
1725
{
1826
EnsureSubsystem();

0 commit comments

Comments
 (0)