using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.Common;
namespace Svelto.ECS
{
///
/// SortedEnginesGroup is a practical way to group engines that need to be ticked in order. The class requires a
/// SequenceOrder struct that defines the order of execution. The pattern to use is the following:
/// First define as many enums as you want with the IDs of the engines to use. E.G.:
/// public enum WiresCompositionEngineNames
///{
/// WiresTimeRunningGroup,
/// WiresPreInitTimeRunningGroup,
/// WiresInitTimeRunningGroup
///}
///
/// then link these ID to the actual engines, using the attribute Sequenced:
///
/// [Sequenced(nameof(WiresCompositionEngineNames.WiresTimeRunningGroup))]
/// class WiresTimeRunningGroup : UnsortedDeterministicEnginesGroup {}
///
/// Note that the engine can be another engines group itself.
///
/// then define the ISequenceOrder struct to define the order of execution. E.G.:
/// public struct DeterministicTimeRunningEnginesOrder: ISequenceOrder
/// {
/// private static readonly string[] order =
/// {
/// nameof(TriggerEngineNames.PreWiresTimeRunningTriggerGroup),
/// nameof(TimerEnginesNames.PreWiresTimeRunningTimerGroup),
/// nameof(WiresCompositionEngineNames.WiresTimeRunningGroup),
/// nameof(SyncGroupEnginesGroups.UnsortedDeterministicTimeRunningGroup)
/// };
/// public string[] enginesOrder => order;
/// }
///
/// Now you can use the Type you just created (i.e.: DeterministicTimeRunningEnginesOrder) as generic parameter
/// of the SortedEnginesGroup. like this:
///
/// public class SortedDoofusesEnginesExecutionGroup : SortedEnginesGroup
/// {
/// public SortedDoofusesEnginesExecutionGroup(FasterList engines) : base(engines)
/// {
/// }
/// }
///
/// This will then Tick the engines passed by constructor with the order defined in the DeterministicTimeRunningEnginesOrder
/// calling _enginesGroup.Step();
///
/// While the system may look convoluted, is an effective way to keep the engines assemblies decoupled from
/// each other
/// The class is abstract and it requires a user defined interface to push the user to use recognisable names meaningful
/// to the context where they are used.
///
/// user defined interface that implements IStepEngine
public abstract class SortedEnginesGroup : IStepGroupEngine
where SequenceOrder : struct, ISequenceOrder where Interface : class, IStepEngine
{
protected SortedEnginesGroup(FasterList engines)
{
_name = "SortedEnginesGroup - "+GetType().Name;
_instancedSequence = new Sequence(engines);
}
public void Step()
{
var sequenceItems = _instancedSequence.items;
using (var profiler = new PlatformProfiler(_name))
{
for (var index = 0; index < sequenceItems.count; index++)
{
var engine = sequenceItems[index];
using (profiler.Sample(engine.name)) engine.Step();
}
}
}
public string name => _name;
public IEnumerable engines
{
get
{
for (int i = 0; i < _instancedSequence.items.count; i++)
yield return _instancedSequence.items[i];
}
}
readonly string _name;
readonly Sequence _instancedSequence;
}
///
/// Similar to SortedEnginesGroup except for the fact that an optional parameter can be passed to the engines
///
///
/// Specialised Parameter that can be passed to all the engines in the group
public abstract class SortedEnginesGroup: IStepGroupEngine
where SequenceOrder : struct, ISequenceOrder where Interface : class, IStepEngine
{
protected SortedEnginesGroup(FasterList engines)
{
_name = "SortedEnginesGroup - "+GetType().Name;
_instancedSequence = new Sequence(engines);
}
public void Step(in Parameter time)
{
var sequenceItems = _instancedSequence.items;
using (var profiler = new PlatformProfiler(_name))
{
for (var index = 0; index < sequenceItems.count; index++)
{
var engine = sequenceItems[index];
using (profiler.Sample(engine.name)) engine.Step(time);
}
}
}
public string name => _name;
public IEnumerable engines
{
get
{
for (int i = 0; i < _instancedSequence.items.count; i++)
yield return _instancedSequence.items[i];
}
}
readonly string _name;
readonly Sequence _instancedSequence;
}
}