Skip to content

Commit 157bfcf

Browse files
authored
Add support for operating steering wheel behaviour with more than one hand (#142)
1 parent cee98a5 commit 157bfcf

File tree

1 file changed

+36
-29
lines changed

1 file changed

+36
-29
lines changed

Runtime/Input/InteractionBehaviours/SteeringWheelBehaviour.cs

+36-29
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright (c) Reality Collective. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4+
using RealityCollective.Utilities.Extensions;
45
using RealityToolkit.Input.Events;
56
using RealityToolkit.Input.Interactors;
7+
using System.Collections.Generic;
68
using UnityEngine;
79
using UnityEngine.Events;
810

@@ -18,7 +20,7 @@ public class SteeringWheelBehaviour : BaseInteractionBehaviour
1820
{
1921
[SerializeField]
2022
[Tooltip("Controls the threshold angle for steering when at maximum steering in either direction.")]
21-
[Range(1f, 179f)]
23+
[Range(1f, 45)]
2224
private float steeringAngleLimit = 45f;
2325

2426
[SerializeField, Tooltip("If set, the steering resets to neutral on release.")]
@@ -39,7 +41,7 @@ public class SteeringWheelBehaviour : BaseInteractionBehaviour
3941
private float elapsedResetTime;
4042
private Quaternion resetStartRotation;
4143
private Quaternion neutralSteeringRotation = Quaternion.Euler(0f, 0f, 0f);
42-
private IControllerInteractor currentInteractor;
44+
private readonly List<IControllerInteractor> interactors = new();
4345
private float currentAngle;
4446

4547
/// <summary>
@@ -103,7 +105,7 @@ protected override void Awake()
103105
/// <inheritdoc/>
104106
protected override void Update()
105107
{
106-
if (currentInteractor == null && !resetting)
108+
if (interactors.Count == 0 && !resetting)
107109
{
108110
return;
109111
}
@@ -123,64 +125,69 @@ protected override void Update()
123125
return;
124126
}
125127

126-
var angle = FindSteeringWheelAngle();
128+
var angle = FindWheelAngle();
127129
var angleDifference = currentAngle - angle;
128130
Rotate(-angleDifference);
129131
currentAngle = angle;
130132
}
131133

132134
/// <inheritdoc/>
133-
protected override void OnFirstGrabEntered(InteractionEventArgs eventArgs)
135+
protected override void OnGrabEntered(InteractionEventArgs eventArgs)
134136
{
135137
if (eventArgs.Interactor is not IControllerInteractor controllerInteractor)
136138
{
137139
return;
138140
}
139141

140-
currentInteractor = controllerInteractor;
141-
currentAngle = FindSteeringWheelAngle();
142+
interactors.EnsureListItem(controllerInteractor);
143+
currentAngle = FindWheelAngle();
142144
}
143145

144146
/// <inheritdoc/>
145-
protected override void OnLastGrabExited(InteractionExitEventArgs eventArgs)
147+
protected override void OnGrabExited(InteractionExitEventArgs eventArgs)
146148
{
147-
currentAngle = FindSteeringWheelAngle();
148-
currentInteractor = null;
149+
if (eventArgs.Interactor is not IControllerInteractor controllerInteractor)
150+
{
151+
return;
152+
}
153+
154+
interactors.SafeRemoveListItem(controllerInteractor);
155+
currentAngle = FindWheelAngle();
149156

150157
if (resetsToNeutral)
151158
{
152159
ReturnToNeutral();
153160
}
154161
}
155162

156-
/// <summary>
157-
/// Rotates the steering wheel by <paramref name="angle"/>.
158-
/// </summary>
159-
/// <param name="angle">The euler angle to rotate by.</param>
160-
private void Rotate(float angle)
163+
private float FindWheelAngle()
161164
{
162-
resetting = false;
165+
var totalAngle = 0f;
163166

164-
var rotation = transform.localEulerAngles;
165-
var updated = rotation.z + angle;
166-
CurrentSteeringAngle = updated;
167-
}
167+
foreach (var interactor in interactors)
168+
{
169+
var direction = FindLocalPoint(interactor.GameObject.transform.position);
170+
totalAngle += FindRotationSensitivity() * ConvertToAngle(direction);
171+
}
168172

169-
private float FindSteeringWheelAngle()
170-
{
171-
var direction = FindLocalPoint(currentInteractor.GameObject.transform.position);
172-
return ConvertToAngle(direction) * FindRotationSensitivity();
173+
return totalAngle;
173174
}
174175

175-
private Vector2 FindLocalPoint(Vector3 position) => upTransform.InverseTransformPoint(position);
176+
private Vector2 FindLocalPoint(Vector3 position) => upTransform.InverseTransformPoint(position).normalized;
176177

177178
private float ConvertToAngle(Vector2 direction) => Vector2.SignedAngle(upTransform.up, direction);
178179

179-
private float FindRotationSensitivity() => 1f;
180+
private float FindRotationSensitivity() => 1f / interactors.Count;
181+
182+
private void Rotate(float angle)
183+
{
184+
resetting = false;
185+
186+
var rotation = transform.localEulerAngles;
187+
var updated = rotation.z + angle;
188+
CurrentSteeringAngle = updated;
189+
}
180190

181-
/// <summary>
182-
/// Returns the steering wheel to neutral position.
183-
/// </summary>
184191
private void ReturnToNeutral()
185192
{
186193
if (resetting)

0 commit comments

Comments
 (0)