Skip to content

Commit a3a84fa

Browse files
authored
Implement smooth visualizer unlock (#139)
* Clean up unused parameter * Implement smooth unlock
1 parent 47ff152 commit a3a84fa

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

Runtime/Input/Controllers/BaseControllerVisualizer.cs

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public abstract class BaseControllerVisualizer : ControllerPoseSynchronizer, ICo
2121
/// <inheritdoc />
2222
public GameObject GameObject => gameObject;
2323

24+
/// <inheritdoc />
25+
public Pose SourcePose { get; private set; }
26+
2427
/// <inheritdoc />
2528
public bool OverrideSourcePose { get; set; }
2629

@@ -41,6 +44,8 @@ public Transform GripPose
4144
/// <inheritdoc />
4245
public override void OnSourcePoseChanged(SourcePoseEventData<Pose> eventData)
4346
{
47+
SourcePose = eventData.SourceData;
48+
4449
if (OverrideSourcePose)
4550
{
4651
return;
@@ -52,6 +57,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData<Pose> eventData)
5257
/// <inheritdoc />
5358
public override void OnSourcePoseChanged(SourcePoseEventData<Quaternion> eventData)
5459
{
60+
SourcePose = new Pose(SourcePose.position, eventData.SourceData);
61+
5562
if (OverrideSourcePose)
5663
{
5764
return;
@@ -63,6 +70,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData<Quaternion> eventDa
6370
/// <inheritdoc />
6471
public override void OnSourcePoseChanged(SourcePoseEventData<Vector2> eventData)
6572
{
73+
SourcePose = new Pose(eventData.SourceData, SourcePose.rotation);
74+
6675
if (OverrideSourcePose)
6776
{
6877
return;
@@ -74,6 +83,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData<Vector2> eventData)
7483
/// <inheritdoc />
7584
public override void OnSourcePoseChanged(SourcePoseEventData<Vector3> eventData)
7685
{
86+
SourcePose = new Pose(eventData.SourceData, SourcePose.rotation);
87+
7788
if (OverrideSourcePose)
7889
{
7990
return;

Runtime/Input/Controllers/IControllerVisualizer.cs

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ public interface IControllerVisualizer : IControllerPoseSynchronizer
1818
/// </remarks>
1919
GameObject GameObject { get; }
2020

21+
/// <summary>
22+
/// This is the actual pose of this controller, regardless of <see cref="OverrideSourcePose"/>
23+
/// and the <see cref="IControllerPoseSynchronizer.PoseDriver"/> pose.
24+
/// </summary>
25+
Pose SourcePose { get; }
26+
2127
/// <summary>
2228
/// If set, the <see cref="IControllerPoseSynchronizer.PoseDriver"/>'s pose in the scene
2329
/// is override and the actual <see cref="IController.InputSource"/> pose is ignored.

Runtime/Input/InteractionBehaviours/LockControllerVisualizerBehaviour.cs

+42-9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class LockControllerVisualizerBehaviour : BaseInteractionBehaviour
3333
private float syncDuration = 1f;
3434

3535
private readonly Dictionary<IControllerVisualizer, bool> lockedVisualizers = new();
36+
private readonly Dictionary<IControllerVisualizer, bool> pendingUnlockVisualizers = new();
3637
private readonly Dictionary<IControllerVisualizer, Pose> smoothingStartPose = new();
3738
private readonly Dictionary<IControllerVisualizer, float> smoothingStartTime = new();
3839
private readonly Dictionary<IControllerVisualizer, float> smoothingProgress = new();
@@ -50,15 +51,32 @@ protected override void Update()
5051

5152
foreach (var visualizer in visualizers)
5253
{
53-
var shouldLock = HasFinishedSmoothTransition(visualizer, lockPose);
54-
55-
if (!shouldLock)
54+
if (pendingUnlockVisualizers.TryGetValue(visualizer, out _))
5655
{
57-
lockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, lockPose.position, smoothingProgress[visualizer]);
58-
lockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, lockPose.rotation, smoothingProgress[visualizer]);
56+
var finishedUnlock = HasFinishedSmoothTransition(pendingUnlockVisualizers, visualizer);
57+
if (finishedUnlock)
58+
{
59+
CleanUpVisualizer(visualizer);
60+
continue;
61+
}
62+
63+
var unlockPose = visualizer.SourcePose;
64+
unlockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, unlockPose.position, smoothingProgress[visualizer]);
65+
unlockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, unlockPose.rotation, smoothingProgress[visualizer]);
66+
visualizer.PoseDriver.SetPositionAndRotation(unlockPose.position, unlockPose.rotation);
5967
}
68+
else
69+
{
70+
var shouldLock = HasFinishedSmoothTransition(lockedVisualizers, visualizer);
6071

61-
visualizer.PoseDriver.SetPositionAndRotation(lockPose.position, lockPose.rotation);
72+
if (!shouldLock)
73+
{
74+
lockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, lockPose.position, smoothingProgress[visualizer]);
75+
lockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, lockPose.rotation, smoothingProgress[visualizer]);
76+
}
77+
78+
visualizer.PoseDriver.SetPositionAndRotation(lockPose.position, lockPose.rotation);
79+
}
6280
}
6381
}
6482

@@ -120,19 +138,34 @@ private void LockVisualizer(IControllerVisualizer visualizer)
120138
}
121139

122140
private void UnlockVisualizer(IControllerVisualizer visualizer)
141+
{
142+
if (!smoothSyncPose)
143+
{
144+
CleanUpVisualizer(visualizer);
145+
return;
146+
}
147+
148+
pendingUnlockVisualizers.EnsureDictionaryItem(visualizer, false, true);
149+
smoothingStartPose.EnsureDictionaryItem(visualizer, GetLockPose(), true);
150+
smoothingStartTime.EnsureDictionaryItem(visualizer, Time.time, true);
151+
smoothingProgress.EnsureDictionaryItem(visualizer, 0f, true);
152+
}
153+
154+
private void CleanUpVisualizer(IControllerVisualizer visualizer)
123155
{
124156
lockedVisualizers.SafeRemoveDictionaryItem(visualizer);
125157
smoothingStartPose.SafeRemoveDictionaryItem(visualizer);
126158
smoothingStartTime.SafeRemoveDictionaryItem(visualizer);
127159
smoothingProgress.SafeRemoveDictionaryItem(visualizer);
160+
pendingUnlockVisualizers.SafeRemoveDictionaryItem(visualizer);
128161
visualizer.OverrideSourcePose = false;
129162
}
130163

131164
private Pose GetLockPose() => new Pose(transform.TransformPoint(localOffsetPose.position), transform.rotation * Quaternion.Euler(localOffsetPose.rotation.eulerAngles));
132165

133-
private bool HasFinishedSmoothTransition(IControllerVisualizer visualizer, Pose snapPose)
166+
private bool HasFinishedSmoothTransition(Dictionary<IControllerVisualizer, bool> smoothingStateDictionary, IControllerVisualizer visualizer)
134167
{
135-
if (lockedVisualizers[visualizer])
168+
if (smoothingStateDictionary[visualizer])
136169
{
137170
return true;
138171
}
@@ -145,7 +178,7 @@ private bool HasFinishedSmoothTransition(IControllerVisualizer visualizer, Pose
145178
return false;
146179
}
147180

148-
lockedVisualizers[visualizer] = true;
181+
smoothingStateDictionary[visualizer] = true;
149182
return true;
150183
}
151184
}

0 commit comments

Comments
 (0)