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;
}
}
}