Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Runtime/Event/BehaviourEnabledObserver2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace Zinnia.Event
{
using UnityEngine;
using UnityEngine.Events;
using Malimbe.BehaviourStateRequirementMethod;
using Malimbe.MemberClearanceMethod;
using Malimbe.PropertySerializationAttribute;
using Malimbe.XmlDocumentationAttribute;
using Zinnia.Data.Collection.List;
using Zinnia.Extension;
using Zinnia.Process;
using Zinnia.Rule;

/// <summary>
/// Emits an event once a list of <see cref="Behaviour"/>s all are <see cref="Behaviour.isActiveAndEnabled"/>.
/// </summary>
public class BehaviourEnabledObserver2 : MonoBehaviour, IProcessable
{
/// <summary>
/// The <see cref="Behaviour"/>s to observe.
/// </summary>
[Serialized]
[field: DocumentedByXml]
public BehaviourObservableList Behaviours { get; set; }

/// <summary>
/// The rule to match against the Behaviours.
/// </summary>
[Serialized, Cleared]
[field: DocumentedByXml]
public RuleContainer Rule { get; set; }

/// <summary>
/// Emitted when all <see cref="Behaviours"/> are <see cref="Behaviour.isActiveAndEnabled"/>.
/// </summary>
[DocumentedByXml]
public UnityEvent ActiveAndEnabled = new UnityEvent();

/// <summary>
/// Checks whether all <see cref="Behaviours"/> are <see cref="Behaviour.isActiveAndEnabled"/> and emits <see cref="ActiveAndEnabled"/> if they are.
/// </summary>
/// <returns>Whether all <see cref="Behaviours"/> are active and enabled.</returns>
[RequiresBehaviourState]
public virtual void Process()
{
if (Behaviours == null || Behaviours.NonSubscribableElements.Count == 0)
{
return;
}

foreach (Behaviour behaviour in Behaviours.NonSubscribableElements)
{
if (!Rule.Accepts(behaviour))
{
return;
}
}

ActiveAndEnabled?.Invoke();
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Event/BehaviourEnabledObserver2.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

136 changes: 136 additions & 0 deletions Runtime/Process/Moment/CoroutineMomentProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
namespace Zinnia.Process.Moment
{
using UnityEngine;
using System.Collections;
using Malimbe.MemberChangeMethod;
using Malimbe.PropertySerializationAttribute;
using Malimbe.XmlDocumentationAttribute;
using Zinnia.Process.Moment.Collection;

/// <summary>
/// Iterates through a given <see cref="MomentProcess"/> collection and executes the <see cref="IProcessable.Process"/> method using Unity coroutine.
/// </summary>
public class CoroutineMomentProcessor : MonoBehaviour
{
/// <summary>
/// The amount of time to pause after each process iteration.
/// </summary>
[Serialized]
[field: DocumentedByXml]
public float Interval { get; set; } = 0.000011f;
/// <summary>
/// The maximum amount of time to perform the process before ending.
/// </summary>
[Serialized]
[field: DocumentedByXml]
public float MaximumRunTime { get; set; } = float.PositiveInfinity;

/// <summary>
/// A collection of <see cref="MomentProcess"/> to process.
/// </summary>
[Serialized]
[field: DocumentedByXml]
public MomentProcessObservableList Processes { get; set; }

/// <summary>
/// A reference to the started routine.
/// </summary>
protected Coroutine processRoutine;
/// <summary>
/// Delays the <see cref="processRoutine"/> by <see cref="Interval"/> seconds.
/// </summary>
protected WaitForSeconds delayYieldInstruction;
/// <summary>
/// The amount of time until the <see cref="processRoutine"/> is cancelled.
/// </summary>
protected float timeUntilProcessIsCancelled;

/// <summary>
/// Initiates the process if no existing process is already running.
/// </summary>
public virtual void BeginProcess()
{
if (processRoutine == null)
{
processRoutine = StartCoroutine(ProcessRoutine());
}
}

/// <summary>
/// Cancels any running process.
/// </summary>
public virtual void EndProcess()
{
if (processRoutine == null)
{
return;
}

StopCoroutine(processRoutine);
processRoutine = null;
}

protected virtual void OnEnable()
{
OnAfterCheckDelayChange();
OnAfterMaximumRunTimeChange();
BeginProcess();
}

protected virtual void OnDisable()
{
EndProcess();
}

/// <summary>
/// Calls <see cref="Process"/> on every frame.
/// </summary>
/// <returns>An Enumerator to manage the running of the Coroutine.</returns>
protected virtual IEnumerator ProcessRoutine()
{
timeUntilProcessIsCancelled = Time.time + MaximumRunTime;
while (Time.time < timeUntilProcessIsCancelled)
{
Process();
yield return delayYieldInstruction;
}
processRoutine = null;
}

/// <summary>
/// Iterates through the given <see cref="MomentProcess"/> and calls <see cref="MomentProcess.Process"/> on each one.
/// </summary>
protected virtual void Process()
{
if (Processes == null)
{
return;
}

foreach (MomentProcess currentProcess in Processes.NonSubscribableElements)
{
currentProcess.Process();
}
}


/// <summary>
/// Called after <see cref="Interval"/> has been changed.
/// </summary>
[CalledAfterChangeOf(nameof(Interval))]
protected virtual void OnAfterCheckDelayChange()
{
delayYieldInstruction = new WaitForSeconds(Interval);
}

/// <summary>
/// Called after <see cref="MaximumRunTime"/> has been changed.
/// </summary>
[CalledAfterChangeOf(nameof(MaximumRunTime))]
protected virtual void OnAfterMaximumRunTimeChange()
{
float remainingRunTime = timeUntilProcessIsCancelled - Time.time;
timeUntilProcessIsCancelled = MaximumRunTime - remainingRunTime;
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Process/Moment/CoroutineMomentProcessor.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions Runtime/Rule/IsActiveAndEnabledRule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Zinnia.Rule
{
using UnityEngine;
using Malimbe.BehaviourStateRequirementMethod;

/// <summary>
/// Determines whether a <see cref="Behaviour"/> is active in the scene hierarchy.
/// </summary>
public class IsActiveAndEnabledRule : MonoBehaviour, IRule
{
/// <inheritdoc />
[RequiresBehaviourState]
public bool Accepts(object target)
{
Behaviour behaviour = target as Behaviour;
return behaviour != null && behaviour.isActiveAndEnabled;
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Rule/IsActiveAndEnabledRule.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.