From d2ab30e7a69bfe7efda63ae75812207377917bd3 Mon Sep 17 00:00:00 2001 From: miepzerino <o.skotnik@gmail.com> Date: Sun, 30 Mar 2025 18:50:27 +0000 Subject: [PATCH] Merge branch 'Flexalon-UI-Layouts' into develop --- Assets/Flexalon/Runtime/Animators/FlexalonLerpAnimator.cs | 194 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 194 insertions(+), 0 deletions(-) diff --git a/Assets/Flexalon/Runtime/Animators/FlexalonLerpAnimator.cs b/Assets/Flexalon/Runtime/Animators/FlexalonLerpAnimator.cs new file mode 100644 index 0000000..7b9bdcb --- /dev/null +++ b/Assets/Flexalon/Runtime/Animators/FlexalonLerpAnimator.cs @@ -0,0 +1,194 @@ +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; + } + } +} \ No newline at end of file -- Gitblit v1.9.3