using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using DuloGames.UI.Tweens; namespace DuloGames.UI { [ExecuteInEditMode, AddComponentMenu("UI/Toggle Active Transition")] public class UIToggleActiveTransition : MonoBehaviour, IEventSystemHandler { public enum VisualState { Normal, Active } public enum Transition { None, ColorTint, SpriteSwap, Animation, TextColor, CanvasGroup } [SerializeField] private Transition m_Transition = Transition.None; [SerializeField] private Color m_NormalColor = new Color(1f, 1f, 1f, 0f); [SerializeField] private Color m_ActiveColor = Color.white; [SerializeField] private float m_Duration = 0.1f; [SerializeField, Range(1f, 6f)] private float m_ColorMultiplier = 1f; [SerializeField] private Sprite m_ActiveSprite; [SerializeField] private string m_NormalTrigger = "Normal"; [SerializeField] private string m_ActiveBool = "Active"; [SerializeField][Range(0f, 1f)] private float m_NormalAlpha = 0f; [SerializeField][Range(0f, 1f)] private float m_ActiveAlpha = 1f; [SerializeField, Tooltip("Graphic that will have the selected transtion applied.")] private Graphic m_TargetGraphic; [SerializeField, Tooltip("GameObject that will have the selected transtion applied.")] private GameObject m_TargetGameObject; [SerializeField, Tooltip("CanvasGroup that will have the selected transtion applied.")] private CanvasGroup m_TargetCanvasGroup; [SerializeField] private Toggle m_TargetToggle; private bool m_Active = false; /// /// Gets or sets the transition type. /// /// The transition. public Transition transition { get { return this.m_Transition; } set { this.m_Transition = value; } } /// /// Gets or sets the target graphic. /// /// The target graphic. public Graphic targetGraphic { get { return this.m_TargetGraphic; } set { this.m_TargetGraphic = value; } } /// /// Gets or sets the target game object. /// /// The target game object. public GameObject targetGameObject { get { return this.m_TargetGameObject; } set { this.m_TargetGameObject = value; } } /// /// Gets or sets the target canvas group. /// /// The target canvas group. public CanvasGroup targetCanvasGroup { get { return this.m_TargetCanvasGroup; } set { this.m_TargetCanvasGroup = value; } } /// /// Gets the animator. /// /// The animator. public Animator animator { get { if (this.m_TargetGameObject != null) return this.m_TargetGameObject.GetComponent(); // Default return null; } } // Tween controls [System.NonSerialized] private readonly TweenRunner m_ColorTweenRunner; [System.NonSerialized] private readonly TweenRunner m_FloatTweenRunner; // Called by Unity prior to deserialization, // should not be called by users protected UIToggleActiveTransition() { if (this.m_ColorTweenRunner == null) this.m_ColorTweenRunner = new TweenRunner(); if (this.m_FloatTweenRunner == null) this.m_FloatTweenRunner = new TweenRunner(); this.m_ColorTweenRunner.Init(this); this.m_FloatTweenRunner.Init(this); } protected void Awake() { if (this.m_TargetToggle == null) this.m_TargetToggle = this.gameObject.GetComponent(); if (this.m_TargetToggle != null) this.m_Active = this.m_TargetToggle.isOn; } protected void OnEnable() { if (this.m_TargetToggle != null) this.m_TargetToggle.onValueChanged.AddListener(OnToggleValueChange); this.InternalEvaluateAndTransitionToNormalState(true); } protected void OnDisable() { if (this.m_TargetToggle != null) this.m_TargetToggle.onValueChanged.RemoveListener(OnToggleValueChange); this.InstantClearState(); } /// /// Internally evaluates and transitions to normal state. /// /// If set to true instant. private void InternalEvaluateAndTransitionToNormalState(bool instant) { this.DoStateTransition(this.m_Active ? VisualState.Active : VisualState.Normal, instant); } #if UNITY_EDITOR protected void OnValidate() { this.m_Duration = Mathf.Max(this.m_Duration, 0f); if (this.isActiveAndEnabled) { this.DoSpriteSwap(null); if (this.m_Transition != Transition.CanvasGroup) this.InternalEvaluateAndTransitionToNormalState(true); } } #endif protected void OnToggleValueChange(bool value) { if (this.m_TargetToggle == null) return; this.m_Active = this.m_TargetToggle.isOn; if (this.m_Transition == Transition.Animation) { if (this.targetGameObject == null || this.animator == null || !this.animator.isActiveAndEnabled || this.animator.runtimeAnimatorController == null || string.IsNullOrEmpty(this.m_ActiveBool)) return; this.animator.SetBool(this.m_ActiveBool, this.m_Active); } this.DoStateTransition(this.m_Active ? VisualState.Active : VisualState.Normal, false); } /// /// Instantly clears the visual state. /// protected void InstantClearState() { switch (this.m_Transition) { case Transition.ColorTint: this.StartColorTween(Color.white, true); break; case Transition.SpriteSwap: this.DoSpriteSwap(null); break; case Transition.TextColor: this.SetTextColor(this.m_NormalColor); break; case Transition.CanvasGroup: this.SetCanvasGroupAlpha(1f); break; } } /// /// Does the state transition. /// /// State. /// If set to true instant. protected virtual void DoStateTransition(VisualState state, bool instant) { // Check if active in the scene if (!this.gameObject.activeInHierarchy) return; Color color = this.m_NormalColor; Sprite newSprite = null; string triggername = this.m_NormalTrigger; float alpha = this.m_NormalAlpha; // Prepare the transition values switch (state) { case VisualState.Normal: color = this.m_NormalColor; newSprite = null; triggername = this.m_NormalTrigger; alpha = this.m_NormalAlpha; break; case VisualState.Active: color = this.m_ActiveColor; newSprite = this.m_ActiveSprite; triggername = this.m_NormalTrigger; alpha = this.m_ActiveAlpha; break; } // Do the transition switch (this.m_Transition) { case Transition.ColorTint: this.StartColorTween(color * this.m_ColorMultiplier, instant); break; case Transition.SpriteSwap: this.DoSpriteSwap(newSprite); break; case Transition.Animation: this.TriggerAnimation(triggername); break; case Transition.TextColor: this.StartTextColorTween(color, false); break; case Transition.CanvasGroup: this.StartCanvasGroupTween(alpha, instant); break; } } /// /// Starts the color tween. /// /// Target color. /// If set to true instant. private void StartColorTween(Color targetColor, bool instant) { if (this.m_TargetGraphic == null) return; if (instant || this.m_Duration == 0f || !Application.isPlaying) { this.m_TargetGraphic.canvasRenderer.SetColor(targetColor); } else { this.m_TargetGraphic.CrossFadeColor(targetColor, this.m_Duration, true, true); } } private void DoSpriteSwap(Sprite newSprite) { Image image = this.m_TargetGraphic as Image; if (image == null) return; image.overrideSprite = newSprite; } private void TriggerAnimation(string triggername) { if (this.targetGameObject == null || this.animator == null || !this.animator.isActiveAndEnabled || this.animator.runtimeAnimatorController == null || !this.animator.hasBoundPlayables || string.IsNullOrEmpty(triggername)) return; this.animator.ResetTrigger(this.m_NormalTrigger); this.animator.SetTrigger(triggername); } private void StartTextColorTween(Color targetColor, bool instant) { if (this.m_TargetGraphic == null) return; if ((this.m_TargetGraphic is Text) == false) return; if (instant || this.m_Duration == 0f || !Application.isPlaying) { (this.m_TargetGraphic as Text).color = targetColor; } else { var colorTween = new ColorTween { duration = this.m_Duration, startColor = (this.m_TargetGraphic as Text).color, targetColor = targetColor }; colorTween.AddOnChangedCallback(SetTextColor); colorTween.ignoreTimeScale = true; this.m_ColorTweenRunner.StartTween(colorTween); } } /// /// Sets the text color. /// /// Target color. private void SetTextColor(Color targetColor) { if (this.m_TargetGraphic == null) return; if (this.m_TargetGraphic is Text) { (this.m_TargetGraphic as Text).color = targetColor; } } /// /// Starts the color tween. /// /// Target alpha. /// If set to true instant. private void StartCanvasGroupTween(float targetAlpha, bool instant) { if (this.m_TargetCanvasGroup == null) return; if (instant || this.m_Duration == 0f || !Application.isPlaying) { this.SetCanvasGroupAlpha(targetAlpha); } else { var floatTween = new FloatTween { duration = this.m_Duration, startFloat = this.m_TargetCanvasGroup.alpha, targetFloat = targetAlpha }; floatTween.AddOnChangedCallback(SetCanvasGroupAlpha); floatTween.ignoreTimeScale = true; this.m_FloatTweenRunner.StartTween(floatTween); } } /// /// Sets the canvas group alpha value. /// /// The alpha value. private void SetCanvasGroupAlpha(float alpha) { if (this.m_TargetCanvasGroup == null) return; this.m_TargetCanvasGroup.alpha = alpha; } } }