OldBlueWater/BlueWater/Assets/Doozy/Runtime/UIManager/Animators/UISelectableUIAnimator.cs

353 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using Doozy.Runtime.Common.Layouts;
using Doozy.Runtime.Common.Utils;
using Doozy.Runtime.Reactor;
using Doozy.Runtime.Reactor.Animations;
using Doozy.Runtime.Reactor.Ticker;
using Doozy.Runtime.UIManager.Components;
using UnityEngine;
using UnityEngine.UI;
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Runtime.UIManager.Animators
{
/// <summary>
/// Specialized animator component used to animate a RectTransforms position, rotation, scale and alpha
/// by listening to a target UISelectable (controller) selection state changes.
/// </summary>
[RequireComponent(typeof(CanvasGroup))]
[RequireComponent(typeof(RectTransform))]
[AddComponentMenu("Doozy/UI/Components/Animators/UISelectable UIAnimator")]
public class UISelectableUIAnimator : BaseUISelectableAnimator
{
private CanvasGroup m_CanvasGroup;
/// <summary> Reference to the CanvasGroup component </summary>
public CanvasGroup canvasGroup => m_CanvasGroup ? m_CanvasGroup : m_CanvasGroup = GetComponent<CanvasGroup>();
[SerializeField] private UIAnimation NormalAnimation;
/// <summary> Animation for the Normal selection state </summary>
public UIAnimation normalAnimation => NormalAnimation ?? (NormalAnimation = new UIAnimation(rectTransform));
[SerializeField] private UIAnimation HighlightedAnimation;
/// <summary> Animation for the Highlighted selection state </summary>
public UIAnimation highlightedAnimation => HighlightedAnimation ?? (HighlightedAnimation = new UIAnimation(rectTransform));
[SerializeField] private UIAnimation PressedAnimation;
/// <summary> Animation for the Pressed selection state </summary>
public UIAnimation pressedAnimation => PressedAnimation ?? (PressedAnimation = new UIAnimation(rectTransform));
[SerializeField] private UIAnimation SelectedAnimation;
/// <summary> Animation for the Selected selection state </summary>
public UIAnimation selectedAnimation => SelectedAnimation ?? (SelectedAnimation = new UIAnimation(rectTransform));
[SerializeField] private UIAnimation DisabledAnimation;
/// <summary> Animation for the Disabled selection state </summary>
public UIAnimation disabledAnimation => DisabledAnimation ?? (DisabledAnimation = new UIAnimation(rectTransform));
/// <summary> Returns TRUE if any animation is active </summary>
public bool anyAnimationIsActive =>
normalAnimation.isActive ||
highlightedAnimation.isActive ||
pressedAnimation.isActive ||
selectedAnimation.isActive ||
disabledAnimation.isActive;
private bool isInLayoutGroup { get; set; }
private Vector3 localPosition { get; set; }
private UIBehaviourHandler uiBehaviourHandler { get; set; }
private bool updateStartPositionInLateUpdate { get; set; }
private bool playStateAnimationFromLateUpdate { get; set; }
/// <summary> Get the Animation triggered by the given selection state </summary>
/// <param name="state"> Target selection state </param>
public UIAnimation GetAnimation(UISelectionState state) =>
state switch
{
UISelectionState.Normal => normalAnimation,
UISelectionState.Highlighted => highlightedAnimation,
UISelectionState.Pressed => pressedAnimation,
UISelectionState.Selected => selectedAnimation,
UISelectionState.Disabled => disabledAnimation,
_ => throw new ArgumentOutOfRangeException(nameof(state), state, null)
};
#if UNITY_EDITOR
protected override void Reset()
{
foreach (UISelectionState state in UISelectable.uiSelectionStates)
ResetAnimation(GetAnimation(state));
NormalAnimation.animationType = UIAnimationType.Reset;
NormalAnimation.Move.enabled = true;
NormalAnimation.Rotate.enabled = true;
NormalAnimation.Scale.enabled = true;
NormalAnimation.Fade.enabled = true;
base.Reset();
}
#endif
protected override void Awake()
{
if (!Application.isPlaying) return;
animatorInitialized = false;
m_RectTransform = GetComponent<RectTransform>();
m_CanvasGroup = GetComponent<CanvasGroup>();
UpdateLayout();
}
protected override void OnEnable()
{
if (!Application.isPlaying) return;
playStateAnimationFromLateUpdate = true;
base.OnEnable();
UpdateLayout();
updateStartPositionInLateUpdate = true;
}
protected override void OnDisable()
{
if (!Application.isPlaying) return;
base.OnDisable();
RefreshLayout();
}
protected override void OnDestroy()
{
base.OnDestroy();
foreach (UISelectionState state in UISelectable.uiSelectionStates)
GetAnimation(state)?.Recycle();
}
private void OnRectTransformDimensionsChange()
{
if (!isConnected) return;
if (!isInLayoutGroup) return;
updateStartPositionInLateUpdate = true;
}
private void LateUpdate()
{
if (!animatorInitialized) return;
if (playStateAnimationFromLateUpdate)
{
if (isConnected)
{
Play(controller.currentUISelectionState);
playStateAnimationFromLateUpdate = false;
}
}
if (!isInLayoutGroup) return;
if (!isConnected) return;
if (anyAnimationIsActive) return;
if (!updateStartPositionInLateUpdate && localPosition == rectTransform.localPosition) return;
if (controller.currentUISelectionState != UISelectionState.Normal) return;
if (CanvasUpdateRegistry.IsRebuildingLayout()) return;
RefreshLayout();
UpdateStartPosition();
}
private void UpdateLayout()
{
isInLayoutGroup = rectTransform.IsInLayoutGroup();
uiBehaviourHandler = null;
if (!isInLayoutGroup) return;
LayoutGroup layout = rectTransform.GetLayoutGroupInParent();
if (layout == null) return;
uiBehaviourHandler = layout.GetUIBehaviourHandler();
System.Diagnostics.Debug.Assert(uiBehaviourHandler != null, nameof(uiBehaviourHandler) + " != null");
uiBehaviourHandler.SetDirty();
}
/// <summary> Refresh the layout the selectable is in </summary>
private void RefreshLayout()
{
if (uiBehaviourHandler == null) return;
uiBehaviourHandler.RefreshLayout();
}
/// <summary> Update the start position of the selectable </summary>
public void UpdateStartPosition()
{
foreach (UISelectionState state in UISelectable.uiSelectionStates)
{
UIAnimation uiAnimation = GetAnimation(state);
uiAnimation.startPosition = rectTransform.anchoredPosition3D;
if (uiAnimation.Move.isPlaying) uiAnimation.Move.UpdateValues();
}
localPosition = rectTransform.localPosition;
updateStartPositionInLateUpdate = false;
}
/// <summary> Returns True if the givens selection state is enabled and the animation is not null. </summary>
/// <param name="state"> Selection state </param>
public override bool IsStateEnabled(UISelectionState state) =>
GetAnimation(state).isEnabled;
/// <summary> Update the animations settings </summary>
public override void UpdateSettings()
{
foreach (UISelectionState state in UISelectable.uiSelectionStates)
GetAnimation(state).SetTarget(rectTransform, canvasGroup);
}
/// <summary> Stop all animations </summary>
public override void StopAllReactions()
{
foreach (UISelectionState state in UISelectable.uiSelectionStates)
GetAnimation(state)?.Stop();
}
/// <summary> Reset all the reactions to their initial values (if the animation is enabled) </summary>
/// <param name="forced"> If true, forced will ignore if the animation is enabled or not </param>
public override void ResetToStartValues(bool forced = false)
{
if (normalAnimation.isActive) normalAnimation.Stop();
if (highlightedAnimation.isActive) highlightedAnimation.Stop();
if (pressedAnimation.isActive) pressedAnimation.Stop();
if (selectedAnimation.isActive) selectedAnimation.Stop();
if (disabledAnimation.isActive) disabledAnimation.Stop();
normalAnimation.ResetToStartValues();
highlightedAnimation.ResetToStartValues();
pressedAnimation.ResetToStartValues();
selectedAnimation.ResetToStartValues();
disabledAnimation.ResetToStartValues();
if (m_RectTransform == null)
return;
rectTransform.anchoredPosition3D = normalAnimation.startPosition;
rectTransform.localEulerAngles = normalAnimation.startRotation;
rectTransform.localScale = normalAnimation.startScale;
canvasGroup.alpha = normalAnimation.startAlpha;
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty(rectTransform);
UnityEditor.SceneView.RepaintAll();
#endif
}
/// <summary> Set animation heartbeat </summary>*
public override List<Heartbeat> SetHeartbeat<T>()
{
var list = new List<Heartbeat>();
for (int i = 0; i < 20; i++) list.Add(new T());
normalAnimation.Move.SetHeartbeat(list[0]);
normalAnimation.Rotate.SetHeartbeat(list[1]);
normalAnimation.Scale.SetHeartbeat(list[2]);
normalAnimation.Fade.SetHeartbeat(list[3]);
highlightedAnimation.Move.SetHeartbeat(list[4]);
highlightedAnimation.Rotate.SetHeartbeat(list[5]);
highlightedAnimation.Scale.SetHeartbeat(list[6]);
highlightedAnimation.Fade.SetHeartbeat(list[7]);
pressedAnimation.Move.SetHeartbeat(list[8]);
pressedAnimation.Rotate.SetHeartbeat(list[9]);
pressedAnimation.Scale.SetHeartbeat(list[10]);
pressedAnimation.Fade.SetHeartbeat(list[11]);
selectedAnimation.Move.SetHeartbeat(list[12]);
selectedAnimation.Rotate.SetHeartbeat(list[13]);
selectedAnimation.Scale.SetHeartbeat(list[14]);
selectedAnimation.Fade.SetHeartbeat(list[15]);
disabledAnimation.Move.SetHeartbeat(list[16]);
disabledAnimation.Rotate.SetHeartbeat(list[17]);
disabledAnimation.Scale.SetHeartbeat(list[18]);
disabledAnimation.Fade.SetHeartbeat(list[19]);
return list;
}
/// <summary> Play the animation for the given selection state </summary>
/// <param name="state"> Selection state </param>
public override void Play(UISelectionState state)
{
if (playStateAnimationFromLateUpdate)
{
GetAnimation(state)?.SetProgressAtOne();
return;
}
GetAnimation(state)?.Play();
}
/// <summary> Set a new start position value (RectTransform.anchoredPosition3D) for all state animations </summary>
/// <param name="value"> New start position </param>
public void SetStartPosition(Vector3 value)
{
normalAnimation.startPosition = value;
highlightedAnimation.startPosition = value;
pressedAnimation.startPosition = value;
selectedAnimation.startPosition = value;
disabledAnimation.startPosition = value;
}
/// <summary> Set a new start rotation value (RectTransform.localEulerAngles) for all state animations </summary>
/// <param name="value"> New start rotation </param>
public void SetStartRotation(Vector3 value)
{
normalAnimation.startRotation = value;
highlightedAnimation.startRotation = value;
pressedAnimation.startRotation = value;
selectedAnimation.startRotation = value;
disabledAnimation.startRotation = value;
}
/// <summary> Set a new start scale value (RectTransform.localScale) for all state animations </summary>
/// <param name="value"> New start scale </param>
public void SetStartScale(Vector3 value)
{
normalAnimation.startScale = value;
highlightedAnimation.startScale = value;
pressedAnimation.startScale = value;
selectedAnimation.startScale = value;
disabledAnimation.startScale = value;
}
/// <summary> Set a new start alpha value (CanvasGroup.alpha) for all state animations </summary>
/// <param name="value"> New start scale </param>
public void SetStartAlpha(float value)
{
normalAnimation.startAlpha = value;
highlightedAnimation.startAlpha = value;
pressedAnimation.startAlpha = value;
selectedAnimation.startAlpha = value;
disabledAnimation.startAlpha = value;
}
/// <summary> Reset the give animation to a set of default values </summary>
/// <param name="target"> Target animation </param>
private static void ResetAnimation(UIAnimation target)
{
target.Move.Reset();
target.Rotate.Reset();
target.Scale.Reset();
target.Fade.Reset();
target.animationType = UIAnimationType.State;
target.Move.fromReferenceValue = ReferenceValue.CurrentValue;
target.Rotate.fromReferenceValue = ReferenceValue.CurrentValue;
target.Scale.fromReferenceValue = ReferenceValue.CurrentValue;
target.Fade.fromReferenceValue = ReferenceValue.CurrentValue;
target.Move.settings.duration = UISelectable.k_DefaultAnimationDuration;
target.Rotate.settings.duration = UISelectable.k_DefaultAnimationDuration;
target.Scale.settings.duration = UISelectable.k_DefaultAnimationDuration;
target.Fade.settings.duration = UISelectable.k_DefaultAnimationDuration;
}
}
}