diff --git a/Runtime/Input/Controllers/BaseControllerVisualizer.cs b/Runtime/Input/Controllers/BaseControllerVisualizer.cs
index f35b4764..6c2f5f43 100644
--- a/Runtime/Input/Controllers/BaseControllerVisualizer.cs
+++ b/Runtime/Input/Controllers/BaseControllerVisualizer.cs
@@ -21,6 +21,9 @@ public abstract class BaseControllerVisualizer : ControllerPoseSynchronizer, ICo
///
public GameObject GameObject => gameObject;
+ ///
+ public Pose SourcePose { get; private set; }
+
///
public bool OverrideSourcePose { get; set; }
@@ -41,6 +44,8 @@ public Transform GripPose
///
public override void OnSourcePoseChanged(SourcePoseEventData eventData)
{
+ SourcePose = eventData.SourceData;
+
if (OverrideSourcePose)
{
return;
@@ -52,6 +57,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData eventData)
///
public override void OnSourcePoseChanged(SourcePoseEventData eventData)
{
+ SourcePose = new Pose(SourcePose.position, eventData.SourceData);
+
if (OverrideSourcePose)
{
return;
@@ -63,6 +70,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData eventDa
///
public override void OnSourcePoseChanged(SourcePoseEventData eventData)
{
+ SourcePose = new Pose(eventData.SourceData, SourcePose.rotation);
+
if (OverrideSourcePose)
{
return;
@@ -74,6 +83,8 @@ public override void OnSourcePoseChanged(SourcePoseEventData eventData)
///
public override void OnSourcePoseChanged(SourcePoseEventData eventData)
{
+ SourcePose = new Pose(eventData.SourceData, SourcePose.rotation);
+
if (OverrideSourcePose)
{
return;
diff --git a/Runtime/Input/Controllers/IControllerVisualizer.cs b/Runtime/Input/Controllers/IControllerVisualizer.cs
index 07e34e87..3dd7fc04 100644
--- a/Runtime/Input/Controllers/IControllerVisualizer.cs
+++ b/Runtime/Input/Controllers/IControllerVisualizer.cs
@@ -18,6 +18,12 @@ public interface IControllerVisualizer : IControllerPoseSynchronizer
///
GameObject GameObject { get; }
+ ///
+ /// This is the actual pose of this controller, regardless of
+ /// and the pose.
+ ///
+ Pose SourcePose { get; }
+
///
/// If set, the 's pose in the scene
/// is override and the actual pose is ignored.
diff --git a/Runtime/Input/InteractionBehaviours/LockControllerVisualizerBehaviour.cs b/Runtime/Input/InteractionBehaviours/LockControllerVisualizerBehaviour.cs
index 44cb3e0e..21367ca0 100644
--- a/Runtime/Input/InteractionBehaviours/LockControllerVisualizerBehaviour.cs
+++ b/Runtime/Input/InteractionBehaviours/LockControllerVisualizerBehaviour.cs
@@ -33,6 +33,7 @@ public class LockControllerVisualizerBehaviour : BaseInteractionBehaviour
private float syncDuration = 1f;
private readonly Dictionary lockedVisualizers = new();
+ private readonly Dictionary pendingUnlockVisualizers = new();
private readonly Dictionary smoothingStartPose = new();
private readonly Dictionary smoothingStartTime = new();
private readonly Dictionary smoothingProgress = new();
@@ -50,15 +51,32 @@ protected override void Update()
foreach (var visualizer in visualizers)
{
- var shouldLock = HasFinishedSmoothTransition(visualizer, lockPose);
-
- if (!shouldLock)
+ if (pendingUnlockVisualizers.TryGetValue(visualizer, out _))
{
- lockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, lockPose.position, smoothingProgress[visualizer]);
- lockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, lockPose.rotation, smoothingProgress[visualizer]);
+ var finishedUnlock = HasFinishedSmoothTransition(pendingUnlockVisualizers, visualizer);
+ if (finishedUnlock)
+ {
+ CleanUpVisualizer(visualizer);
+ continue;
+ }
+
+ var unlockPose = visualizer.SourcePose;
+ unlockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, unlockPose.position, smoothingProgress[visualizer]);
+ unlockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, unlockPose.rotation, smoothingProgress[visualizer]);
+ visualizer.PoseDriver.SetPositionAndRotation(unlockPose.position, unlockPose.rotation);
}
+ else
+ {
+ var shouldLock = HasFinishedSmoothTransition(lockedVisualizers, visualizer);
- visualizer.PoseDriver.SetPositionAndRotation(lockPose.position, lockPose.rotation);
+ if (!shouldLock)
+ {
+ lockPose.position = Vector3.Slerp(smoothingStartPose[visualizer].position, lockPose.position, smoothingProgress[visualizer]);
+ lockPose.rotation = Quaternion.Slerp(smoothingStartPose[visualizer].rotation, lockPose.rotation, smoothingProgress[visualizer]);
+ }
+
+ visualizer.PoseDriver.SetPositionAndRotation(lockPose.position, lockPose.rotation);
+ }
}
}
@@ -120,19 +138,34 @@ private void LockVisualizer(IControllerVisualizer visualizer)
}
private void UnlockVisualizer(IControllerVisualizer visualizer)
+ {
+ if (!smoothSyncPose)
+ {
+ CleanUpVisualizer(visualizer);
+ return;
+ }
+
+ pendingUnlockVisualizers.EnsureDictionaryItem(visualizer, false, true);
+ smoothingStartPose.EnsureDictionaryItem(visualizer, GetLockPose(), true);
+ smoothingStartTime.EnsureDictionaryItem(visualizer, Time.time, true);
+ smoothingProgress.EnsureDictionaryItem(visualizer, 0f, true);
+ }
+
+ private void CleanUpVisualizer(IControllerVisualizer visualizer)
{
lockedVisualizers.SafeRemoveDictionaryItem(visualizer);
smoothingStartPose.SafeRemoveDictionaryItem(visualizer);
smoothingStartTime.SafeRemoveDictionaryItem(visualizer);
smoothingProgress.SafeRemoveDictionaryItem(visualizer);
+ pendingUnlockVisualizers.SafeRemoveDictionaryItem(visualizer);
visualizer.OverrideSourcePose = false;
}
private Pose GetLockPose() => new Pose(transform.TransformPoint(localOffsetPose.position), transform.rotation * Quaternion.Euler(localOffsetPose.rotation.eulerAngles));
- private bool HasFinishedSmoothTransition(IControllerVisualizer visualizer, Pose snapPose)
+ private bool HasFinishedSmoothTransition(Dictionary smoothingStateDictionary, IControllerVisualizer visualizer)
{
- if (lockedVisualizers[visualizer])
+ if (smoothingStateDictionary[visualizer])
{
return true;
}
@@ -145,7 +178,7 @@ private bool HasFinishedSmoothTransition(IControllerVisualizer visualizer, Pose
return false;
}
- lockedVisualizers[visualizer] = true;
+ smoothingStateDictionary[visualizer] = true;
return true;
}
}