using UnityEngine; namespace Flexalon { /// /// The lerp animator constnatly performs a linear interpolation between /// the object's current position and its layout position. This is useful /// if the layout position is continuously changing. /// [AddComponentMenu("Flexalon/Flexalon Lerp Animator"), HelpURL("https://www.flexalon.com/docs/animators")] public class FlexalonLerpAnimator : MonoBehaviour, TransformUpdater { private FlexalonNode _node; private RectTransform _rectTransform; [SerializeField] private bool _animateInWorldSpace = true; /// Determines if the animation should be performed in world space. public bool AnimateInWorldSpace { get => _animateInWorldSpace; set { _animateInWorldSpace = value; } } [SerializeField] private float _interpolationSpeed = 5.0f; /// Amount the object should be interpolated towards the target at each frame. /// This value is multiplied by Time.deltaTime. public float InterpolationSpeed { get => _interpolationSpeed; set { _interpolationSpeed = value; } } [SerializeField] private bool _animatePosition = true; /// Determines if the position should be animated. public bool AnimatePosition { get => _animatePosition; set { _animatePosition = value; } } [SerializeField] private bool _animateRotation = true; /// Determines if the rotation should be animated. public bool AnimateRotation { get => _animateRotation; set { _animateRotation = value; } } [SerializeField] private bool _animateScale = true; /// Determines if the rotation should be animated. public bool AnimateScale { get => _animateScale; set { _animateScale = value; } } private Vector3 _fromPosition; private Quaternion _fromRotation; private Vector3 _fromScale; void OnEnable() { _node = Flexalon.GetOrCreateNode(gameObject); _node.SetTransformUpdater(this); _rectTransform = (transform is RectTransform) ? (RectTransform)transform : null; } void OnDisable() { _node?.SetTransformUpdater(null); _node = null; } /// public void PreUpdate(FlexalonNode node) { _fromPosition = transform.position; _fromRotation = transform.rotation; _fromScale = transform.lossyScale; } /// public bool UpdatePosition(FlexalonNode node, Vector3 position) { if (_animateInWorldSpace) { var worldPosition = transform.parent ? transform.parent.localToWorldMatrix.MultiplyPoint(position) : position; if (!_animatePosition || Vector3.Distance(_fromPosition, worldPosition) < 0.001f) { transform.localPosition = position; return true; } else { transform.position = Vector3.Lerp(_fromPosition, worldPosition, _interpolationSpeed * Time.smoothDeltaTime); return false; } } else { if (!_animatePosition || Vector3.Distance(transform.localPosition, position) < 0.001f) { transform.localPosition = position; return true; } else { transform.localPosition = Vector3.Lerp(transform.localPosition, position, _interpolationSpeed * Time.smoothDeltaTime); return false; } } } /// public bool UpdateRotation(FlexalonNode node, Quaternion rotation) { if (_animateInWorldSpace) { var worldRotation = transform.parent ? transform.parent.rotation * rotation : rotation; if (!_animateRotation || Mathf.Abs(Quaternion.Angle(_fromRotation, worldRotation)) < 0.001f) { transform.localRotation = rotation; return true; } else { transform.rotation = Quaternion.Slerp(_fromRotation, worldRotation, _interpolationSpeed * Time.smoothDeltaTime); return false; } } else { if (!_animateRotation || Mathf.Abs(Quaternion.Angle(transform.localRotation, rotation)) < 0.001f) { transform.localRotation = rotation; return true; } else { transform.localRotation = Quaternion.Slerp(transform.localRotation, rotation, _interpolationSpeed * Time.smoothDeltaTime); return false; } } } /// public bool UpdateScale(FlexalonNode node, Vector3 scale) { if (_animateInWorldSpace) { var worldScale = transform.parent ? Math.Mul(scale, transform.parent.lossyScale) : scale; if (!_animateScale || Vector3.Distance(_fromScale, worldScale) < 0.001f) { transform.localScale = scale; return true; } else { var newWorldScale = Vector3.Lerp(_fromScale, worldScale, _interpolationSpeed * Time.smoothDeltaTime); transform.localScale = transform.parent ? Math.Div(newWorldScale, transform.parent.lossyScale) : newWorldScale; return false; } } else { if (!_animateScale || Vector3.Distance(transform.localScale, scale) < 0.001f) { transform.localScale = scale; return true; } else { transform.localScale = Vector3.Lerp(transform.localScale, scale, _interpolationSpeed * Time.smoothDeltaTime); return false; } } } /// public bool UpdateRectSize(FlexalonNode node, Vector2 size) { bool done = !_animateScale || Vector2.Distance(_rectTransform.sizeDelta, size) < 0.001f; var newSize = done ? size : Vector2.Lerp(_rectTransform.sizeDelta, size, _interpolationSpeed * Time.smoothDeltaTime); _rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, newSize.x); _rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, newSize.y); return done; } } }