60 lines
1.6 KiB
C#

using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Serialization;
namespace Syntriax.Engine.Systems.StateMachine;
public class StateMachine : Behaviour, IUpdate
{
public Event<StateMachine, StateChangedArguments> OnStateChanged { get; } = new();
private readonly Event<IState, IState.StateTransitionReadyArguments>.EventHandler delegateOnStateTransitionReady = null!;
private IState _state = new State();
public StateMachine()
{
delegateOnStateTransitionReady = OnStateTransitionReady;
}
[Serialize]
public IState State
{
get => _state;
set
{
if (_state == value)
return;
IState previousState = _state;
previousState.OnStateTransitionReady.RemoveListener(delegateOnStateTransitionReady);
_state = value;
previousState.TransitionFrom(value);
value.TransitionTo(_state);
OnStateChanged?.Invoke(this, new(value, previousState));
value.OnStateTransitionReady.AddListener(delegateOnStateTransitionReady);
}
}
private void OnStateTransitionReady(IState sender, IState.StateTransitionReadyArguments args)
{
State = args.ToState;
while (State.GetNextState() is IState nextState)
State = nextState;
}
public void Update()
{
if (State is null)
return;
while (State.GetNextState() is IState nextState)
State = nextState;
State.Update();
}
public readonly record struct StateChangedArguments(IState CurrentState, IState PreviousState);
}