namespace Zinnia.Process.Component
{
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Zinnia.Data.Type;
///
/// An that runs a set method on each (or the first active) source collection against a collection of targets.
///
public abstract class SourceTargetProcessor : MonoBehaviour, IProcessable where TEvent : UnityEvent, new()
{
///
/// Emitted if the value is going to change with the new value as the payload.
///
public TEvent ActiveSourceChanging = new TEvent();
[Header("Process Settings")]
[Tooltip("Whether to cease the processing of the source collection after the first valid source is processed.")]
[SerializeField]
private bool ceaseAfterFirstSourceProcessed = true;
///
/// Whether to cease the processing of the source collection after the first valid source is processed.
///
public bool CeaseAfterFirstSourceProcessed
{
get
{
return ceaseAfterFirstSourceProcessed;
}
set
{
ceaseAfterFirstSourceProcessed = value;
}
}
///
/// The that is currently the active source for the process.
///
public TSource ActiveSource
{
get;
protected set;
}
///
/// Executes the relevant process to apply between the source and target.
///
public abstract void Process();
///
/// Sets the current indices of the source and target collections.
///
/// The source index.
/// The target index.
protected abstract void SetCurrentIndices(int sourceIndex, int targetIndex);
///
/// Applies the source data to the target data.
///
/// The source to apply the data from.
/// The target to apply the data to.
protected abstract void ApplySourceToTarget(TSource source, TTarget target);
///
/// Determines if the given source is valid to process.
///
/// The source to check.
/// if the source is valid to process.
protected virtual bool IsSourceValid(TSource source)
{
return !EqualityComparer.Default.Equals(source, default);
}
///
/// Determines if the given target is valid to process.
///
/// The target to check.
/// if the target is valid to process.
protected virtual bool IsTargetValid(TTarget target)
{
return !EqualityComparer.Default.Equals(target, default);
}
///
/// Applies each (or the first active) source data to every (or only active) targets.
///
/// The sources to apply the data from.
/// The targets to apply the data to.
protected virtual void ApplySourcesToTargets(HeapAllocationFreeReadOnlyList sources, HeapAllocationFreeReadOnlyList targets)
{
bool foundValidSource = false;
for (int sourceIndex = 0; sourceIndex < sources.Count; sourceIndex++)
{
TSource currentSource = sources[sourceIndex];
if (!IsSourceValid(currentSource))
{
continue;
}
for (int targetIndex = 0; targetIndex < targets.Count; targetIndex++)
{
TTarget currentTarget = targets[targetIndex];
if (!IsTargetValid(currentTarget))
{
continue;
}
SetCurrentIndices(sourceIndex, targetIndex);
ApplySourceToTarget(currentSource, currentTarget);
}
if (!EqualityComparer.Default.Equals(ActiveSource, currentSource))
{
ActiveSourceChanging?.Invoke(currentSource);
}
ActiveSource = currentSource;
foundValidSource = true;
if (CeaseAfterFirstSourceProcessed)
{
break;
}
}
if (!foundValidSource && !EqualityComparer.Default.Equals(ActiveSource, default))
{
ActiveSource = default;
ActiveSourceChanging?.Invoke(default);
}
}
}
}