| using UnityEngine; | 
|   | 
| namespace Flexalon | 
| { | 
|     /// <summary> | 
|     /// 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. | 
|     /// </summary> | 
|     [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; | 
|         /// <summary> Determines if the animation should be performed in world space. </summary> | 
|         public bool AnimateInWorldSpace | 
|         { | 
|             get => _animateInWorldSpace; | 
|             set { _animateInWorldSpace = value; } | 
|         } | 
|   | 
|         [SerializeField] | 
|         private float _interpolationSpeed = 5.0f; | 
|         /// <summary> Amount the object should be interpolated towards the target at each frame. | 
|         /// This value is multiplied by Time.deltaTime. </summary> | 
|         public float InterpolationSpeed | 
|         { | 
|             get => _interpolationSpeed; | 
|             set { _interpolationSpeed = value; } | 
|         } | 
|   | 
|         [SerializeField] | 
|         private bool _animatePosition = true; | 
|         /// <summary> Determines if the position should be animated. </summary> | 
|         public bool AnimatePosition | 
|         { | 
|             get => _animatePosition; | 
|             set { _animatePosition = value; } | 
|         } | 
|   | 
|         [SerializeField] | 
|         private bool _animateRotation = true; | 
|         /// <summary> Determines if the rotation should be animated. </summary> | 
|         public bool AnimateRotation | 
|         { | 
|             get => _animateRotation; | 
|             set { _animateRotation = value; } | 
|         } | 
|   | 
|         [SerializeField] | 
|         private bool _animateScale = true; | 
|         /// <summary> Determines if the rotation should be animated. </summary> | 
|         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; | 
|         } | 
|   | 
|         /// <inheritdoc /> | 
|         public void PreUpdate(FlexalonNode node) | 
|         { | 
|             _fromPosition = transform.position; | 
|             _fromRotation = transform.rotation; | 
|             _fromScale = transform.lossyScale; | 
|         } | 
|   | 
|         /// <inheritdoc /> | 
|         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; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         /// <inheritdoc /> | 
|         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; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         /// <inheritdoc /> | 
|         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; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         /// <inheritdoc /> | 
|         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; | 
|         } | 
|     } | 
| } |