using UnityEngine; using System.Collections; using System; #if MM_UI using UnityEngine.UI; #endif using MoreMountains.Tools; namespace MoreMountains.Tools { /// /// An event used to stop fades /// public struct MMFadeStopEvent { /// an ID that has to match the one on the fader public int ID; public bool Restore; public MMFadeStopEvent(int id = 0, bool restore = false) { Restore = restore; ID = id; } static MMFadeStopEvent e; public static void Trigger(int id = 0, bool restore = false) { e.ID = id; e.Restore = restore; MMEventManager.TriggerEvent(e); } } /// /// Events used to trigger faders on or off /// public struct MMFadeEvent { /// an ID that has to match the one on the fader public int ID; /// the duration of the fade, in seconds public float Duration; /// the alpha to aim for public float TargetAlpha; /// the curve to apply to the fade public MMTweenType Curve; /// whether or not this fade should ignore timescale public bool IgnoreTimeScale; /// a world position for a target object. Useless for regular fades, but can be useful for alt implementations (circle fade for example) public Vector3 WorldPosition; /// /// Initializes a new instance of the struct. /// /// Duration, in seconds. /// Target alpha, from 0 to 1. public MMFadeEvent(float duration, float targetAlpha, MMTweenType tween, int id=0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { ID = id; Duration = duration; TargetAlpha = targetAlpha; Curve = tween; IgnoreTimeScale = ignoreTimeScale; WorldPosition = worldPosition; } static MMFadeEvent e; public static void Trigger(float duration, float targetAlpha) { Trigger(duration, targetAlpha, new MMTweenType(MMTween.MMTweenCurve.EaseInCubic)); } public static void Trigger(float duration, float targetAlpha, MMTweenType tween, int id = 0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { e.ID = id; e.Duration = duration; e.TargetAlpha = targetAlpha; e.Curve = tween; e.IgnoreTimeScale = ignoreTimeScale; e.WorldPosition = worldPosition; MMEventManager.TriggerEvent(e); } } public struct MMFadeInEvent { /// an ID that has to match the one on the fader public int ID; /// the duration of the fade, in seconds public float Duration; /// the curve to apply to the fade public MMTweenType Curve; /// whether or not this fade should ignore timescale public bool IgnoreTimeScale; /// a world position for a target object. Useless for regular fades, but can be useful for alt implementations (circle fade for example) public Vector3 WorldPosition; /// /// Initializes a new instance of the struct. /// /// Duration. public MMFadeInEvent(float duration, MMTweenType tween, int id = 0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { ID = id; Duration = duration; Curve = tween; IgnoreTimeScale = ignoreTimeScale; WorldPosition = worldPosition; } static MMFadeInEvent e; public static void Trigger(float duration, MMTweenType tween, int id = 0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { e.ID = id; e.Duration = duration; e.Curve = tween; e.IgnoreTimeScale = ignoreTimeScale; e.WorldPosition = worldPosition; MMEventManager.TriggerEvent(e); } } public struct MMFadeOutEvent { /// an ID that has to match the one on the fader public int ID; /// the duration of the fade, in seconds public float Duration; /// the curve to apply to the fade public MMTweenType Curve; /// whether or not this fade should ignore timescale public bool IgnoreTimeScale; /// a world position for a target object. Useless for regular fades, but can be useful for alt implementations (circle fade for example) public Vector3 WorldPosition; /// /// Initializes a new instance of the struct. /// /// Duration. public MMFadeOutEvent(float duration, MMTweenType tween, int id = 0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { ID = id; Duration = duration; Curve = tween; IgnoreTimeScale = ignoreTimeScale; WorldPosition = worldPosition; } static MMFadeOutEvent e; public static void Trigger(float duration, MMTweenType tween, int id = 0, bool ignoreTimeScale = true, Vector3 worldPosition = new Vector3()) { e.ID = id; e.Duration = duration; e.Curve = tween; e.IgnoreTimeScale = ignoreTimeScale; e.WorldPosition = worldPosition; MMEventManager.TriggerEvent(e); } } /// /// The Fader class can be put on an Image, and it'll intercept MMFadeEvents and turn itself on or off accordingly. /// [RequireComponent(typeof(CanvasGroup))] #if MM_UI [RequireComponent(typeof(Image))] #endif [AddComponentMenu("More Mountains/Tools/GUI/MMFader")] public class MMFader : MMMonoBehaviour, MMEventListener, MMEventListener, MMEventListener, MMEventListener { public enum ForcedInitStates { None, Active, Inactive } [MMInspectorGroup("Identification", true, 122)] /// the ID for this fader (0 is default), set more IDs if you need more than one fader [Tooltip("the ID for this fader (0 is default), set more IDs if you need more than one fader")] public int ID; [MMInspectorGroup("Opacity", true, 123)] /// the opacity the fader should be at when inactive [Tooltip("the opacity the fader should be at when inactive")] public float InactiveAlpha = 0f; /// the opacity the fader should be at when active [Tooltip("the opacity the fader should be at when active")] public float ActiveAlpha = 1f; /// determines whether a state should be forced on init [Tooltip("determines whether a state should be forced on init")] public ForcedInitStates ForcedInitState = ForcedInitStates.Inactive; [MMInspectorGroup("Timing", true, 124)] /// the default duration of the fade in/out [Tooltip("the default duration of the fade in/out")] public float DefaultDuration = 0.2f; /// the default curve to use for this fader [Tooltip("the default curve to use for this fader")] public MMTweenType DefaultTween = new MMTweenType(MMTween.MMTweenCurve.LinearTween); /// whether or not the fade should happen in unscaled time [Tooltip("whether or not the fade should happen in unscaled time")] public bool IgnoreTimescale = true; /// whether or not this fader can cause a fade if the requested final alpha is the same as the current one [Tooltip("whether or not this fader can cause a fade if the requested final alpha is the same as the current one")] public bool CanFadeToCurrentAlpha = true; [MMInspectorGroup("Interaction", true, 125)] /// whether or not the fader should block raycasts when visible [Tooltip("whether or not the fader should block raycasts when visible")] public bool ShouldBlockRaycasts = false; [MMInspectorGroup("Debug", true, 126)] [MMInspectorButtonBar(new string[] { "FadeIn1Second", "FadeOut1Second", "DefaultFade", "ResetFader" }, new string[] { "FadeIn1Second", "FadeOut1Second", "DefaultFade", "ResetFader" }, new bool[] { true, true, true, true }, new string[] { "main-call-to-action", "", "", "" })] public bool DebugToolbar; protected CanvasGroup _canvasGroup; #if MM_UI protected Image _image; #endif protected float _initialAlpha; protected float _currentTargetAlpha; protected float _currentDuration; protected MMTweenType _currentCurve; protected bool _fading = false; protected float _fadeStartedAt; protected bool _frameCountOne; /// /// Test method triggered by an inspector button /// protected virtual void ResetFader() { _canvasGroup.alpha = InactiveAlpha; } /// /// Test method triggered by an inspector button /// protected virtual void DefaultFade() { MMFadeEvent.Trigger(DefaultDuration, ActiveAlpha, DefaultTween, ID); } /// /// Test method triggered by an inspector button /// protected virtual void FadeIn1Second() { MMFadeInEvent.Trigger(1f, new MMTweenType(MMTween.MMTweenCurve.LinearTween)); } /// /// Test method triggered by an inspector button /// protected virtual void FadeOut1Second() { MMFadeOutEvent.Trigger(1f, new MMTweenType(MMTween.MMTweenCurve.LinearTween)); } /// /// On Start, we initialize our fader /// protected virtual void Awake() { Initialization(); } /// /// On init, we grab our components, and disable/hide everything /// protected virtual void Initialization() { _canvasGroup = GetComponent(); #if MM_UI _image = GetComponent(); if (ForcedInitState == ForcedInitStates.Inactive) { _canvasGroup.alpha = InactiveAlpha; _image.enabled = false; } else if (ForcedInitState == ForcedInitStates.Active) { _canvasGroup.alpha = ActiveAlpha; _image.enabled = true; } #endif } /// /// On Update, we update our alpha /// protected virtual void Update() { if (_canvasGroup == null) { return; } if (_fading) { Fade(); } } /// /// Fades the canvasgroup towards its target alpha /// protected virtual void Fade() { float currentTime = IgnoreTimescale ? Time.unscaledTime : Time.time; if (_frameCountOne) { if (Time.frameCount <= 2) { _canvasGroup.alpha = _initialAlpha; return; } _fadeStartedAt = IgnoreTimescale ? Time.unscaledTime : Time.time; currentTime = _fadeStartedAt; _frameCountOne = false; } float endTime = _fadeStartedAt + _currentDuration; if (currentTime - _fadeStartedAt < _currentDuration) { float result = MMTween.Tween(currentTime, _fadeStartedAt, endTime, _initialAlpha, _currentTargetAlpha, _currentCurve); _canvasGroup.alpha = result; } else { StopFading(); } } /// /// Stops the fading. /// protected virtual void StopFading() { _canvasGroup.alpha = _currentTargetAlpha; _fading = false; if (_canvasGroup.alpha == InactiveAlpha) { DisableFader(); } } /// /// Disables the fader. /// protected virtual void DisableFader() { #if MM_UI _image.enabled = false; #endif if (ShouldBlockRaycasts) { _canvasGroup.blocksRaycasts = false; } } /// /// Enables the fader. /// protected virtual void EnableFader() { #if MM_UI _image.enabled = true; #endif if (ShouldBlockRaycasts) { _canvasGroup.blocksRaycasts = true; } } /// /// Starts fading this fader from the specified initial alpha to the target /// /// /// /// /// /// /// protected virtual void StartFading(float initialAlpha, float endAlpha, float duration, MMTweenType curve, bool ignoreTimeScale) { if ((!CanFadeToCurrentAlpha) && (_canvasGroup.alpha == endAlpha)) { return; } IgnoreTimescale = ignoreTimeScale; EnableFader(); _fading = true; _initialAlpha = initialAlpha; _currentTargetAlpha = endAlpha; _fadeStartedAt = IgnoreTimescale ? Time.unscaledTime : Time.time; _currentCurve = curve; _currentDuration = duration; if (Time.frameCount == 1) { _frameCountOne = true; } } /// /// When catching a fade event, we fade our image in or out /// /// Fade event. public virtual void OnMMEvent(MMFadeEvent fadeEvent) { if (fadeEvent.ID != ID) { return; } Fade(fadeEvent.TargetAlpha, fadeEvent.Duration, fadeEvent.Curve, fadeEvent.IgnoreTimeScale); } /// /// When catching an MMFadeInEvent, we fade our image in /// /// Fade event. public virtual void OnMMEvent(MMFadeInEvent fadeEvent) { if (fadeEvent.ID != ID) { return; } FadeIn(fadeEvent.Duration, fadeEvent.Curve, fadeEvent.IgnoreTimeScale); } /// /// When catching an MMFadeOutEvent, we fade our image out /// /// Fade event. public virtual void OnMMEvent(MMFadeOutEvent fadeEvent) { if (fadeEvent.ID != ID) { return; } FadeOut(fadeEvent.Duration, fadeEvent.Curve, fadeEvent.IgnoreTimeScale); } /// /// Use this method to fade towards the specified target alpha /// /// /// /// /// public virtual void Fade(float targetAlpha, float duration, MMTweenType curve, bool ignoreTimeScale) { _currentTargetAlpha = (targetAlpha == -1) ? ActiveAlpha : targetAlpha; StartFading(_canvasGroup.alpha, _currentTargetAlpha, duration, curve, ignoreTimeScale); } /// /// Use this method to cause a fade in over the specified duration and curve /// /// /// /// public virtual void FadeIn(float duration, MMTweenType curve, bool ignoreTimeScale = true) { StartFading(InactiveAlpha, ActiveAlpha, duration, curve, ignoreTimeScale); } /// /// Use this method to cause a fade out over the specified duration and curve /// /// /// /// public virtual void FadeOut(float duration, MMTweenType curve, bool ignoreTimeScale = true) { StartFading(ActiveAlpha, InactiveAlpha, duration, curve, ignoreTimeScale); } /// /// When catching an MMFadeStopEvent, we stop our fade /// /// Fade event. public virtual void OnMMEvent(MMFadeStopEvent fadeStopEvent) { if (fadeStopEvent.ID == ID) { _fading = false; if (fadeStopEvent.Restore) { _canvasGroup.alpha = _initialAlpha; } } } /// /// On enable, we start listening to events /// protected virtual void OnEnable() { this.MMEventStartListening(); this.MMEventStartListening(); this.MMEventStartListening(); this.MMEventStartListening(); } /// /// On disable, we stop listening to events /// protected virtual void OnDisable() { this.MMEventStopListening(); this.MMEventStopListening(); this.MMEventStopListening(); this.MMEventStopListening(); } } }