namespace Zinnia.Process.Moment
{
using UnityEngine;
using UnityEngine.Rendering;
using Zinnia.Extension;
using Zinnia.Process.Moment.Collection;
///
/// Iterates through a given collection and executes the method on the given Unity game loop moment.
///
public class MomentProcessor : MonoBehaviour, IProcessable
{
///
/// The point in the Unity game loop when to execute the processes.
///
public enum Moment
{
///
/// Executes the processes only when the method is called.
///
None,
///
/// Execute the processes in the FixedUpdate physics part of the Unity game loop.
///
FixedUpdate,
///
/// Executes the processes in the Update game logic part of the Unity game loop.
///
Update,
///
/// Executes the processes in the LateUpdate game logic part of the Unity game loop.
///
LateUpdate,
///
/// Executes the processes in the camera PreCull scene rendering part of the Unity game loop.
///
PreCull,
///
/// Executes the processes in the camera PreRender scene rendering part of the Unity game loop.
///
PreRender,
///
/// Executes the processes in the Application BeforeRender scene rendering part of the Unity game loop.
///
BeforeRender
}
[Tooltip("The moment in which to process the given processes.")]
[SerializeField]
private Moment processMoment = Moment.PreRender;
///
/// The moment in which to process the given processes.
///
public Moment ProcessMoment
{
get
{
return processMoment;
}
set
{
if (this.IsMemberChangeAllowed())
{
OnBeforeProcessMomentChange();
}
processMoment = value;
if (this.IsMemberChangeAllowed())
{
OnAfterProcessMomentChange();
}
}
}
[Tooltip("A collection of MomentProcess to process.")]
[SerializeField]
private MomentProcessObservableList processes;
///
/// A collection of to process.
///
public MomentProcessObservableList Processes
{
get
{
return processes;
}
set
{
processes = value;
}
}
///
/// Sets the .
///
/// The index of the .
public virtual void SetProcessMoment(int index)
{
ProcessMoment = EnumExtensions.GetByIndex(index);
}
///
public virtual void Process()
{
ProcessMoments();
}
protected virtual void OnEnable()
{
SubscribeMoment();
}
protected virtual void OnDisable()
{
UnsubscribeMoment();
}
protected virtual void FixedUpdate()
{
if (ProcessMoment == Moment.FixedUpdate)
{
ProcessMoments();
}
}
protected virtual void Update()
{
if (ProcessMoment == Moment.Update)
{
ProcessMoments();
}
}
protected virtual void LateUpdate()
{
if (ProcessMoment == Moment.LateUpdate)
{
ProcessMoments();
}
}
#if UNITY_2019_1_OR_NEWER
protected virtual void OnSrpCameraPreRender(ScriptableRenderContext context, Camera givenCamera)
{
Process();
}
#endif
protected virtual void OnCameraPreRender(Camera givenCamera)
{
ProcessMoments();
}
protected virtual void OnCameraPreCull(Camera givenCamera)
{
ProcessMoments();
}
protected virtual void OnApplicationBeforeRender()
{
ProcessMoments();
}
///
/// Handles unsubscribing to the chosen subscribed moment event.
///
protected virtual void UnsubscribeMoment()
{
switch (ProcessMoment)
{
case Moment.PreRender:
if (GraphicsSettings.renderPipelineAsset != null)
{
#if UNITY_2019_1_OR_NEWER
RenderPipelineManager.beginCameraRendering -= OnSrpCameraPreRender;
#endif
}
else
{
Camera.onPreRender -= OnCameraPreRender;
}
break;
case Moment.PreCull:
Camera.onPreCull -= OnCameraPreCull;
break;
case Moment.BeforeRender:
Application.onBeforeRender -= OnApplicationBeforeRender;
break;
}
}
///
/// Handles subscribing to the chosen moment to process event.
///
protected virtual void SubscribeMoment()
{
switch (ProcessMoment)
{
case Moment.PreRender:
if (GraphicsSettings.renderPipelineAsset != null)
{
#if UNITY_2019_1_OR_NEWER
RenderPipelineManager.beginCameraRendering += OnSrpCameraPreRender;
#else
Debug.LogWarning("SRP is only supported on Unity 2019.1 or above");
#endif
}
else
{
Camera.onPreRender += OnCameraPreRender;
}
break;
case Moment.PreCull:
Camera.onPreCull += OnCameraPreCull;
break;
case Moment.BeforeRender:
Application.onBeforeRender += OnApplicationBeforeRender;
break;
}
}
///
/// Iterates through the given and calls on each one.
///
protected virtual void ProcessMoments()
{
if (Processes == null)
{
return;
}
foreach (MomentProcess currentProcess in Processes.NonSubscribableElements)
{
currentProcess.Process();
}
}
///
/// Called before has been changed.
///
protected virtual void OnBeforeProcessMomentChange()
{
UnsubscribeMoment();
}
///
/// Called after has been changed.
///
protected virtual void OnAfterProcessMomentChange()
{
SubscribeMoment();
}
}
}