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; } }