// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System.Collections.Generic; using UltimateXR.Animation.Interpolation; using UltimateXR.Core.Components; using UnityEngine; namespace UltimateXR.Manipulation.Helpers { /// /// Aligns an object smoothly whenever it is released to keep it leveled. Should be used on non physics-driven /// grabbable objects, which remain floating in the air when being released. /// public class UxrAlignOnRelease : UxrComponent { #region Inspector Properties/Serialized Fields [SerializeField] private bool _onlyLevel = true; [SerializeField] [Range(0.0f, 1.0f)] private float _smoothFactor = 0.2f; [SerializeField] private List _grabbableObjects; #endregion #region Unity /// /// Caches the transform component. /// protected override void Awake() { base.Awake(); _selfTransform = transform; } /// /// Updates the transform while the object is not being grabbed. /// private void Update() { if (!IsBeingGrabbed) { // Smoothly rotate towards horizontal orientation when not being grabbed if (_onlyLevel == false) { _selfTransform.rotation = UxrInterpolator.SmoothDampRotation(_selfTransform.rotation, Quaternion.FromToRotation(_selfTransform.up, Vector3.up) * _selfTransform.rotation, _smoothFactor); } else { Vector3 projectedRight = Vector3.ProjectOnPlane(transform.right, Vector3.up); Quaternion targetRotation = Quaternion.FromToRotation(_selfTransform.right, projectedRight) * _selfTransform.rotation; if ((targetRotation * Vector3.up).y < 0.0f) { targetRotation = targetRotation * Quaternion.AngleAxis(180.0f, Vector3.forward); } _selfTransform.rotation = UxrInterpolator.SmoothDampRotation(_selfTransform.rotation, targetRotation, _smoothFactor); } } } #endregion #region Private Types & Data /// /// Gets whether the object is being grabbed using any of the registered grabbable objects. /// private bool IsBeingGrabbed { get { foreach (UxrGrabbableObject grabbableObject in _grabbableObjects) { if (UxrGrabManager.Instance.IsBeingGrabbed(grabbableObject)) { return true; } } return false; } } private Transform _selfTransform; #endregion } }