Development Merge 2025.04.01 #1
13
Engine.Systems/Engine.Systems.csproj
Normal file
13
Engine.Systems/Engine.Systems.csproj
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Engine.Core\Engine.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
22
Engine.Systems/StateMachine/IState.cs
Normal file
22
Engine.Systems/StateMachine/IState.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
|
public interface IState
|
||||||
|
{
|
||||||
|
event StateUpdateEventHandler? OnStateUpdate;
|
||||||
|
event StateTransitionedFromEventHandler? OnStateTransitionedFrom;
|
||||||
|
event StateTransitionedToEventHandler? OnStateTransitionedTo;
|
||||||
|
event StateTransitionReadyEventHandler? OnStateTransitionReady;
|
||||||
|
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
IState? GetNextState();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
void TransitionTo(IState from);
|
||||||
|
void TransitionFrom(IState to);
|
||||||
|
|
||||||
|
delegate void StateUpdateEventHandler(IState sender);
|
||||||
|
delegate void StateTransitionedFromEventHandler(IState sender, IState toState);
|
||||||
|
delegate void StateTransitionedToEventHandler(IState sender, IState fromState);
|
||||||
|
delegate void StateTransitionReadyEventHandler(IState sender, IState toState);
|
||||||
|
}
|
52
Engine.Systems/StateMachine/State.cs
Normal file
52
Engine.Systems/StateMachine/State.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
|
public class State : IState
|
||||||
|
{
|
||||||
|
public event IState.StateUpdateEventHandler? OnStateUpdate = null;
|
||||||
|
public event IState.StateTransitionedFromEventHandler? OnStateTransitionedFrom = null;
|
||||||
|
public event IState.StateTransitionedToEventHandler? OnStateTransitionedTo = null;
|
||||||
|
public event IState.StateTransitionReadyEventHandler? OnStateTransitionReady = null;
|
||||||
|
|
||||||
|
private readonly List<StateTransition> transitions = [];
|
||||||
|
private readonly Dictionary<string, StateTransition> possibleTransitions = [];
|
||||||
|
|
||||||
|
public string Name { get; set; } = "Default State Name";
|
||||||
|
public IReadOnlyList<StateTransition> Transitions => transitions;
|
||||||
|
public IReadOnlyDictionary<string, StateTransition> PossibleTransitions => possibleTransitions;
|
||||||
|
|
||||||
|
public void RemoveTransition(string name)
|
||||||
|
{
|
||||||
|
if (!possibleTransitions.TryGetValue(name, out StateTransition stateTransition))
|
||||||
|
return;
|
||||||
|
|
||||||
|
transitions.Remove(stateTransition);
|
||||||
|
possibleTransitions.Remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTransition(string name, StateTransition stateTransition)
|
||||||
|
{
|
||||||
|
if (transitions.Contains(stateTransition))
|
||||||
|
return;
|
||||||
|
|
||||||
|
transitions.Add(stateTransition);
|
||||||
|
possibleTransitions.Add(name, stateTransition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (GetNextState() is IState transitionState)
|
||||||
|
OnStateTransitionReady?.Invoke(this, transitionState);
|
||||||
|
OnStateUpdate?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TransitionTo(IState from) => OnStateTransitionedTo?.Invoke(this, from);
|
||||||
|
public void TransitionFrom(IState to) => OnStateTransitionedFrom?.Invoke(this, to);
|
||||||
|
|
||||||
|
public IState? GetNextState()
|
||||||
|
{
|
||||||
|
foreach (StateTransition stateTransition in transitions)
|
||||||
|
if (stateTransition.CanTransition)
|
||||||
|
return stateTransition.State;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
37
Engine.Systems/StateMachine/StateBehaviourBase.cs
Normal file
37
Engine.Systems/StateMachine/StateBehaviourBase.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
|
public abstract class StateBehaviourBase : Behaviour, IState
|
||||||
|
{
|
||||||
|
public event IState.StateUpdateEventHandler? OnStateUpdate = null;
|
||||||
|
public event IState.StateTransitionedFromEventHandler? OnStateTransitionedFrom = null;
|
||||||
|
public event IState.StateTransitionedToEventHandler? OnStateTransitionedTo = null;
|
||||||
|
|
||||||
|
public abstract event IState.StateTransitionReadyEventHandler? OnStateTransitionReady;
|
||||||
|
|
||||||
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
protected virtual void OnUpdateState() { }
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
OnUpdateState();
|
||||||
|
OnStateUpdate?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnTransitionedToState(IState from) { }
|
||||||
|
public void TransitionTo(IState from)
|
||||||
|
{
|
||||||
|
OnTransitionedToState(from);
|
||||||
|
OnStateTransitionedTo?.Invoke(this, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnTransitionedFromState(IState to) { }
|
||||||
|
public void TransitionFrom(IState to)
|
||||||
|
{
|
||||||
|
OnTransitionedFromState(to);
|
||||||
|
OnStateTransitionedFrom?.Invoke(this, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract IState? GetNextState();
|
||||||
|
}
|
49
Engine.Systems/StateMachine/StateMachine.cs
Normal file
49
Engine.Systems/StateMachine/StateMachine.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
|
public class StateMachine : Behaviour
|
||||||
|
{
|
||||||
|
public event OnStateChangedEventHandler? OnStateChanged = null;
|
||||||
|
|
||||||
|
private IState _state = new State();
|
||||||
|
public IState State
|
||||||
|
{
|
||||||
|
get => _state;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_state == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IState previousState = _state;
|
||||||
|
previousState.OnStateTransitionReady -= OnStateTransitionReady;
|
||||||
|
|
||||||
|
_state = value;
|
||||||
|
previousState.TransitionFrom(value);
|
||||||
|
value.TransitionTo(_state);
|
||||||
|
OnStateChanged?.Invoke(this, previousState, value);
|
||||||
|
|
||||||
|
value.OnStateTransitionReady += OnStateTransitionReady;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStateTransitionReady(IState sender, IState toState)
|
||||||
|
{
|
||||||
|
State = toState;
|
||||||
|
while (State.GetNextState() is IState nextState)
|
||||||
|
State = nextState;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate()
|
||||||
|
{
|
||||||
|
if (State is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (State.GetNextState() is IState nextState)
|
||||||
|
State = nextState;
|
||||||
|
|
||||||
|
State.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void OnStateChangedEventHandler(StateMachine sender, IState previousState, IState newState);
|
||||||
|
}
|
11
Engine.Systems/StateMachine/StateTransition.cs
Normal file
11
Engine.Systems/StateMachine/StateTransition.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
|
public readonly record struct StateTransition(IState State, IReadOnlyList<Func<bool>> Conditions)
|
||||||
|
{
|
||||||
|
public static implicit operator (IState state, IReadOnlyList<Func<bool>> conditions)(StateTransition value)
|
||||||
|
=> (value.State, value.Conditions);
|
||||||
|
public static implicit operator StateTransition((IState state, IReadOnlyList<Func<bool>> conditions) value)
|
||||||
|
=> new(value.state, value.conditions);
|
||||||
|
|
||||||
|
public bool CanTransition => !Conditions.Any(c => !c.Invoke());
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user