namespace Zinnia.Event { using System.Collections; using UnityEngine; using UnityEngine.Events; using Zinnia.Data.Collection.List; using Zinnia.Extension; /// /// Emits an event once a list of s all are . /// public class BehaviourEnabledObserver : MonoBehaviour { [Tooltip("The time between each Behaviour.enabled check.")] [SerializeField] private float checkDelay = 0.000011f; /// /// The time between each check. /// public float CheckDelay { get { return checkDelay; } set { checkDelay = value; if (this.IsMemberChangeAllowed()) { OnAfterCheckDelayChange(); } } } [Tooltip("The maximum amount of time to perform the Behaviour.enabled check before ending.")] [SerializeField] private float maximumRunTime = float.PositiveInfinity; /// /// The maximum amount of time to perform the check before ending. /// public float MaximumRunTime { get { return maximumRunTime; } set { maximumRunTime = value; if (this.IsMemberChangeAllowed()) { OnAfterMaximumRunTimeChange(); } } } [Tooltip("The Behaviours to observe.")] [SerializeField] private BehaviourObservableList behaviours; /// /// The s to observe. /// public BehaviourObservableList Behaviours { get { return behaviours; } set { behaviours = value; } } /// /// Emitted when all are . /// public UnityEvent ActiveAndEnabled = new UnityEvent(); /// /// A reference to the started routine. /// protected Coroutine behaviourCheckRoutine; /// /// Delays the by seconds. /// protected WaitForSeconds checkDelayYieldInstruction; /// /// The amount of time until the is cancelled. /// protected float timeUntilCheckIsCancelled; /// /// Initiates the check of the state if no existing check is already running. /// public virtual void BeginCheck() { if (behaviourCheckRoutine == null) { behaviourCheckRoutine = StartCoroutine(Check()); } } /// /// Cancels any running check of the state. /// public virtual void EndCheck() { if (behaviourCheckRoutine == null) { return; } StopCoroutine(behaviourCheckRoutine); behaviourCheckRoutine = null; } protected virtual void OnEnable() { OnAfterCheckDelayChange(); OnAfterMaximumRunTimeChange(); BeginCheck(); } protected virtual void OnDisable() { EndCheck(); } /// /// Checks to see if the specified have been enabled in the scene. /// /// An Enumerator to manage the running of the Coroutine. protected virtual IEnumerator Check() { timeUntilCheckIsCancelled = Time.time + MaximumRunTime; while (Time.time < timeUntilCheckIsCancelled) { if (AreBehavioursEnabled()) { break; } yield return checkDelayYieldInstruction; } behaviourCheckRoutine = null; } /// /// Checks whether all are and emits if they are. /// /// Whether all are active and enabled. protected virtual bool AreBehavioursEnabled() { if (Behaviours == null || Behaviours.NonSubscribableElements.Count == 0) { return false; } foreach (Behaviour behaviour in Behaviours.NonSubscribableElements) { if (!behaviour.CheckIsActiveAndEnabled()) { return false; } } ActiveAndEnabled?.Invoke(); return true; } /// /// Called after has been changed. /// protected virtual void OnAfterCheckDelayChange() { checkDelayYieldInstruction = new WaitForSeconds(CheckDelay); } /// /// Called after has been changed. /// protected virtual void OnAfterMaximumRunTimeChange() { float remainingRunTime = timeUntilCheckIsCancelled - Time.time; timeUntilCheckIsCancelled = MaximumRunTime - remainingRunTime; } } }