112 lines
3.4 KiB
C#
112 lines
3.4 KiB
C#
using System;
|
|
using PrimeTween;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
public class UIVisibilityAnimation
|
|
{
|
|
private VisualElement _element;
|
|
|
|
private Action<bool> _onCompleted;
|
|
|
|
private Sequence _visibilityAnimation;
|
|
|
|
public UIVisibilityAnimation(VisualElement element, Action<bool> onCompleted)
|
|
{
|
|
_element = element;
|
|
_onCompleted = onCompleted;
|
|
|
|
IsOpen = element.resolvedStyle.display != DisplayStyle.None;
|
|
TargetIsOpen = IsOpen;
|
|
|
|
ApplyCommittedState(IsOpen);
|
|
}
|
|
|
|
public bool IsOpen { get; private set; }
|
|
|
|
public bool TargetIsOpen { get; private set; }
|
|
|
|
public bool IsAnimating => _visibilityAnimation.isAlive;
|
|
|
|
public void Show(bool show, bool animate = false)
|
|
{
|
|
TargetIsOpen = show;
|
|
|
|
if (IsAnimating) return;
|
|
if (IsOpen == TargetIsOpen) return;
|
|
|
|
if (!animate)
|
|
{
|
|
ApplyCommittedState(TargetIsOpen);
|
|
IsOpen = TargetIsOpen;
|
|
_onCompleted?.Invoke(IsOpen);
|
|
return;
|
|
}
|
|
|
|
TryAdvance();
|
|
}
|
|
|
|
private void TryAdvance()
|
|
{
|
|
if (IsAnimating) return;
|
|
if (IsOpen == TargetIsOpen) return;
|
|
|
|
if (TargetIsOpen)
|
|
PlayOpenAnimation();
|
|
else
|
|
PlayCloseAnimation();
|
|
}
|
|
|
|
private void PlayOpenAnimation()
|
|
{
|
|
_element.style.display = DisplayStyle.Flex;
|
|
_visibilityAnimation = PlayShowTween(_element).OnComplete(() => CompleteTransition(true));
|
|
}
|
|
|
|
private void PlayCloseAnimation()
|
|
{
|
|
_element.style.display = DisplayStyle.Flex;
|
|
_visibilityAnimation = PlayHideTween(_element).OnComplete(() => CompleteTransition(false));
|
|
}
|
|
|
|
private void CompleteTransition(bool isOpen)
|
|
{
|
|
_visibilityAnimation = default;
|
|
ApplyCommittedState(isOpen);
|
|
IsOpen = isOpen;
|
|
_onCompleted?.Invoke(IsOpen);
|
|
TryAdvance();
|
|
}
|
|
|
|
private void ApplyCommittedState(bool isOpen)
|
|
{
|
|
_element.style.display = isOpen ? DisplayStyle.Flex : DisplayStyle.None;
|
|
_element.style.opacity = isOpen ? 1 : 0;
|
|
if (isOpen)
|
|
_element.style.scale = StyleKeyword.Null;
|
|
else
|
|
_element.SetScale(0.8f);
|
|
}
|
|
|
|
public static Sequence PlayShowTween(VisualElement element, float duration = 0.3f)
|
|
{
|
|
element.style.opacity = 0;
|
|
element.SetScale(0.8f);
|
|
|
|
return Sequence.Create(useUnscaledTime: true)
|
|
.Group(Tween.Custom(0.8f, 1, duration, element.SetScale, Ease.OutQuad))
|
|
.Group(Tween.Custom(0, 1, duration, value => element.style.opacity = value, Ease.OutQuad));
|
|
}
|
|
|
|
public static Sequence PlayHideTween(VisualElement element, float duration = 0.2f)
|
|
{
|
|
element.style.opacity = 1;
|
|
element.SetScale(1);
|
|
|
|
return Sequence.Create(useUnscaledTime: true)
|
|
.Group(Tween.Custom(1, 0.8f, duration, value => element.SetScale(value), Ease.OutQuad))
|
|
.Group(Tween.Custom(1, 0, duration, value => element.style.opacity = value, Ease.OutQuad));
|
|
}
|
|
}
|
|
} |