Phase
Outerminds edited this page Feb 9, 2019
·
12 revisions
A phase describes an execution 'time' that is executed as a block. This means that a phase must be completely executed before another can execute. Phases are executed through a controller using its Run<T>
method. They are linked with system interfaces by schedulers.
A phase must:
- be a
struct
- implement the
IPhase
empty interface
A phase should:
- contain only
public
instance non-readonly fields (no methods, constructors, properties, events, etc.) - not have fields that stores an Entia type (such as a component, a system, a message, a queryable, an injectable, etc.)
using System;
using System.Collections.Generic;
using Entia;
using Entia.Core;
using Entia.Modules;
using Entia.Modules.Control;
using Entia.Modules.Schedule;
using Entia.Nodes;
using Entia.Phases;
using Entia.Schedulables;
using Entia.Systems;
using static Entia.Nodes.Node;
namespace Phases
{
// This phase is meant to execute before the 'Run' phase.
// 'IResolve' is a phase interface that signals that the world should be
// resolved after executing the phase.
public struct PreRun : IPhase, IResolve { }
}
namespace Systems
{
// This interface will allow to define systems that will be called during the
// 'PreRun' phase.
// A default 'IScheduler' implementation must be linked using the 'T'
// in the 'ISchedulable<T>' interface.
public interface IPreRun : ISchedulable<Schedulers.PreRun>
{
void PreRun();
}
}
namespace Schedulers
{
// 'Scheduler<T>' is an 'IScheduler' that automatically casts the
// instance to the provided type 'T'
public sealed class PreRun : Entia.Schedulers.Scheduler<Systems.IPreRun>
{
// Declare which phase types the schedule will schedule.
public override Type[] Phases => new[] { typeof(Phases.PreRun) };
public override Phase[] Schedule(
Systems.IPreRun instance,
Controller controller)
{
// Here is where the phase is linked with the system interface.
var phase = Phase.From<Phases.PreRun>(instance.PreRun);
// A scheduler may register a system interface to multiple phases.
return new[] { phase };
}
}
}
namespace Resources
{
public struct Game : IResource { public bool Quit; }
}
public static class Game
{
public static readonly Node Node = Sequence();
public static void Run()
{
var world = new World();
var controllers = world.Controllers();
var resources = world.Resources();
if (controllers.Control(Node).TryValue(out var controller))
{
ref var game = ref resources.Get<Resources.Game>();
// This is the typical execution routine.
controller.Run<Initialize>();
controller.Run<React.Initialize>();
while (!game.Quit)
{
// The custom phase is inserted here.
controller.Run<Phases.PreRun>();
controller.Run<Run>();
}
controller.Run<React.Dispose>();
controller.Run<Dispose>();
}
}
}