Transition.cs
using System;
using Sandbox.Diagnostics;
namespace Sandbox.States;
public sealed class Transition : IComparable<Transition>, IValid
{
private float? _delay;
private Func<bool>? _condition;
/// <summary>
/// The state machine containing this transition.
/// </summary>
public StateMachineComponent StateMachine => Source.StateMachine;
/// <summary>
/// Unique ID of this transition in the <see cref="StateMachineComponent"/>.
/// </summary>
public int Id { get; }
/// <summary>
/// The state this transition originates from.
/// </summary>
public State Source { get; }
/// <summary>
/// The destination of this transition.
/// </summary>
public State Target { get; }
/// <summary>
/// Does this transition still belong to a state.
/// </summary>
public bool IsValid { get; internal set; }
internal Transition( int id, State source, State target )
{
Source = source;
Target = target;
Id = id;
}
/// <summary>
/// Optional delay before this transition is taken.
/// If null, this transition can be taken at any time.
/// </summary>
public float? Delay
{
get => _delay;
set
{
_delay = value;
Source.InvalidateTransitions();
}
}
/// <summary>
/// Optional condition to evaluate.
/// </summary>
public Func<bool>? Condition
{
get => _condition;
set
{
_condition = value;
Source.InvalidateTransitions();
}
}
/// <summary>
/// Action performed when this transition is taken.
/// </summary>
public Action? OnTransition { get; set; }
public void Remove()
{
if ( !IsValid ) return;
StateMachine.RemoveTransition( this );
}
public int CompareTo( Transition? other )
{
if ( other is null ) return 1;
var delayCompare = (Delay ?? float.PositiveInfinity).CompareTo( other.Delay ?? float.PositiveInfinity );
if ( delayCompare != 0 ) return delayCompare;
var conditionCompare = (Condition is null).CompareTo( other.Condition is null );
if ( conditionCompare != 0 ) return conditionCompare;
return Target.Id.CompareTo( other.Target.Id );
}
internal record Model( int Id, int SourceId, int TargetId, float? Delay, Func<bool>? Condition, Action? OnTransition );
internal Model Serialize()
{
return new Model( Id, Source.Id, Target.Id, Delay, Condition, OnTransition );
}
internal void Deserialize( Model model )
{
Assert.AreEqual( Id, model.Id );
Assert.AreEqual( Source.Id, model.SourceId );
Assert.AreEqual( Target.Id, model.TargetId );
Delay = model.Delay;
Condition = model.Condition;
OnTransition = model.OnTransition;
}
}