using UnityEngine; using System.Collections; using System; using UnityEngine.UI; 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 MMFadeStopEvent(int id = 0) { ID = id; } static MMFadeStopEvent e; public static void Trigger(int id = 0) { e.ID = id; 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))] [RequireComponent(typeof(Image))] [AddComponentMenu("More Mountains/Tools/GUI/MMFader")] public class MMFader : MonoBehaviour, MMEventListener, MMEventListener, MMEventListener, MMEventListener { [Header("Identification")] /// the ID for this fader (0 is default), set more IDs if you need more than one fader public int ID; [Header("Opacity")] /// the opacity the fader should be at when inactive public float InactiveAlpha = 0f; /// the opacity the fader should be at when active public float ActiveAlpha = 1f; [Header("Timing")] /// the default duration of the fade in/out public float DefaultDuration = 0.2f; /// 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 public bool IgnoreTimescale = true; [Header("Interaction")] /// whether or not the fader should block raycasts when visible public bool ShouldBlockRaycasts = false; [Header("Debug")] [MMInspectorButton("FadeIn1Second")] public bool FadeIn1SecondButton; [MMInspectorButton("FadeOut1Second")] public bool FadeOut1SecondButton; [MMInspectorButton("DefaultFade")] public bool DefaultFadeButton; [MMInspectorButton("ResetFader")] public bool ResetFaderButton; protected CanvasGroup _canvasGroup; protected Image _image; 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(); _canvasGroup.alpha = InactiveAlpha; _image = GetComponent(); _image.enabled = false; } /// /// 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() { _image.enabled = false; if (ShouldBlockRaycasts) { _canvasGroup.blocksRaycasts = false; } } /// /// Enables the fader. /// protected virtual void EnableFader() { _image.enabled = true; 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, int id, bool ignoreTimeScale) { if (id != ID) { 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) { _currentTargetAlpha = (fadeEvent.TargetAlpha == -1) ? ActiveAlpha : fadeEvent.TargetAlpha; StartFading(_canvasGroup.alpha, _currentTargetAlpha, fadeEvent.Duration, fadeEvent.Curve, fadeEvent.ID, fadeEvent.IgnoreTimeScale); } /// /// When catching an MMFadeInEvent, we fade our image in /// /// Fade event. public virtual void OnMMEvent(MMFadeInEvent fadeEvent) { StartFading(InactiveAlpha, ActiveAlpha, fadeEvent.Duration, fadeEvent.Curve, fadeEvent.ID, fadeEvent.IgnoreTimeScale); } /// /// When catching an MMFadeOutEvent, we fade our image out /// /// Fade event. public virtual void OnMMEvent(MMFadeOutEvent fadeEvent) { StartFading(ActiveAlpha, InactiveAlpha, fadeEvent.Duration, fadeEvent.Curve, fadeEvent.ID, fadeEvent.IgnoreTimeScale); } /// /// When catching an MMFadeStopEvent, we stop our fade /// /// Fade event. public virtual void OnMMEvent(MMFadeStopEvent fadeStopEvent) { if (fadeStopEvent.ID == ID) { _fading = false; } } /// /// 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(); } } }