using UnityEngine; using UnityEngine.Events; using System.Collections.Generic; using Lean.Transition; using Lean.Common; namespace Lean.Gui { /// This component allows you to trigger a transition and/or event at regular intervals. [HelpURL(LeanGui.HelpUrlPrefix + "LeanPulse")] [AddComponentMenu(LeanGui.ComponentMenuPrefix + "Pulse")] public class LeanPulse : MonoBehaviour { [System.Serializable] public class IntEvent : UnityEvent {} /// This stores all active and enabled LeanPulse instances, so you can manually pulse them by name from anywhere. public static LinkedList Instances = new LinkedList(); /// This tells you how many pulses remain until this component stops. /// -1 = unlimited public int RemainingPulses { set { remainingPulses = value; } get { return remainingPulses; } } [SerializeField] private int remainingPulses = -1; /// When this reaches 0, and RemainingPulses is not 0, this component will pulse. public float RemainingTime { set { remainingTime = value; } get { return remainingTime; } } [SerializeField] private float remainingTime; /// This allows you to control the amount of seconds between each pulse. /// -1 = Manual Pulses Only public float TimeInterval { set { timeInterval = value; } get { return timeInterval; } } [SerializeField] private float timeInterval = 1.0f; /// This allows you to choose where in the game loop this pulse will update. public LeanTiming Timing { set { timing = value; } get { return timing; } } [SerializeField] private LeanTiming timing; /// This allows you to perform an animation when this UI element pulses. /// You can create a new transition GameObject by right clicking the transition name, and selecting Create. /// For example, the LeanPlaySound (Play Sound Transition) component can be used to play a pulse sound. public LeanPlayer PulseTransitions { get { if (pulseTransitions == null) pulseTransitions = new LeanPlayer(); return pulseTransitions; } } [SerializeField] private LeanPlayer pulseTransitions; /// This allows you to perform an action when this UI element pulses. /// int = RemainingPulses public IntEvent OnPulse { get { if (onPulse == null) onPulse = new IntEvent(); return onPulse; } } [SerializeField] private IntEvent onPulse; [System.NonSerialized] private LinkedListNode link; /// This will pulse, as long as you have remaining pulses. [ContextMenu("Try Pulse")] public void TryPulse() { if (remainingPulses >= 0) { if (remainingPulses > 0) { remainingPulses--; } else { return; } } remainingTime = timeInterval; Pulse(); } /// This allows you to manually force this component to pulse right now. [ContextMenu("Pulse")] public void Pulse() { if (pulseTransitions != null) { pulseTransitions.Begin(); } if (onPulse != null) { onPulse.Invoke(remainingPulses); } } /// This method calls TryPulse on all active and enabled LeanPulse instances with the specified GameObject name. public static void TryPulseAll(string name) { var node = Instances.First; for (var i = Instances.Count - 1; i >= 0; i--) { var instance = node.Value; if (instance.name == name) { instance.TryPulse(); } node = node.Next; } } /// This method calls Pulse on all active and enabled LeanPulse instances with the specified GameObject name. public static void PulseAll(string name) { var node = Instances.First; for (var i = Instances.Count - 1; i >= 0; i--) { var instance = node.Value; if (instance.name == name) { instance.Pulse(); } node = node.Next; } } protected virtual void OnEnable() { link = Instances.AddLast(this); } protected virtual void OnDisable() { Instances.Remove(link); link = null; } protected virtual void Update() { var finalUpdate = LeanTransition.GetTiming(timing); if (LeanTransition.GetTimingAbs(finalUpdate) == LeanTiming.Update) { UpdatePulse(finalUpdate > 0 ? Time.deltaTime : Time.unscaledDeltaTime); } } protected virtual void LateUpdate() { var finalUpdate = LeanTransition.GetTiming(timing); if (LeanTransition.GetTimingAbs(finalUpdate) == LeanTiming.LateUpdate) { UpdatePulse(finalUpdate > 0 ? Time.deltaTime : Time.unscaledDeltaTime); } } protected virtual void FixedUpdate() { var finalUpdate = LeanTransition.GetTiming(timing); if (LeanTransition.GetTimingAbs(finalUpdate) == LeanTiming.FixedUpdate) { UpdatePulse(finalUpdate > 0 ? Time.fixedDeltaTime : Time.fixedUnscaledDeltaTime); } } private void UpdatePulse(float delta) { remainingTime -= delta; if (remainingTime <= 0.0f) { remainingTime = timeInterval; TryPulse(); } } } } #if UNITY_EDITOR namespace Lean.Gui.Editor { using TARGET = LeanPulse; [UnityEditor.CanEditMultipleObjects] [UnityEditor.CustomEditor(typeof(TARGET))] public class LeanPulse_Editor : LeanEditor { protected override void OnInspector() { TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts); Draw("remainingPulses", "This tells you how many pulses remain until this component stops.\n\n-1 = unlimited"); Draw("remainingTime", "When this reaches 0, and RemainingPulses is not 0, this component will pulse."); Draw("timeInterval", "This allows you to control the amount of seconds between each pulse.\n\n-1 = Manual Pulses Only"); Draw("timing", "This allows you to choose where in the game loop this pulse will update."); Separator(); Draw("pulseTransitions", "This allows you to perform an animation when this UI element pulses."); Separator(); Draw("onPulse"); } } } #endif