Skip to content

Commit

Permalink
Merge pull request #16 from techno-dwarf-works/feature/clean-up
Browse files Browse the repository at this point in the history
Version 0.1.9
  • Loading branch information
OpOpYaDev committed May 20, 2024
1 parent 9378096 commit 35b1624
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 50 deletions.
42 changes: 25 additions & 17 deletions Runtime/Implementations/StateMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
namespace Better.StateMachine.Runtime
{
[Serializable]
public class StateMachine<TState, TTransitionSequence> : IStateMachine<TState>
public class StateMachine<TState, TSequence> : IStateMachine<TState>
where TState : BaseState
where TTransitionSequence : ISequence<TState>, new()
where TSequence : Sequence<TState>, new()
{
public event Action<TState> StateChanged;

private readonly TTransitionSequence _transitionSequence;
private readonly TSequence _sequence;
private readonly Locator<Module<TState>> _modulesLocator;

private CancellationTokenSource _runningTokenSource;
Expand All @@ -30,14 +30,14 @@ public class StateMachine<TState, TTransitionSequence> : IStateMachine<TState>
public Task TransitionTask => InTransition ? _stateChangeCompletionSource.Task : Task.CompletedTask;
public TState CurrentState { get; protected set; }

public StateMachine(TTransitionSequence transitionSequence)
public StateMachine(TSequence sequence)
{
if (transitionSequence == null)
if (sequence == null)
{
throw new ArgumentNullException(nameof(transitionSequence));
throw new ArgumentNullException(nameof(sequence));
}

_transitionSequence = transitionSequence;
_sequence = sequence;
_modulesLocator = new();
}

Expand Down Expand Up @@ -103,16 +103,16 @@ public virtual void Stop()

#region States

public async Task ChangeStateAsync(TState newState, CancellationToken cancellationToken)
public async Task ChangeStateAsync(TState state, CancellationToken cancellationToken)
{
if (!ValidateRunning(true))
{
return;
}

if (newState == null)
if (state == null)
{
DebugUtility.LogException<ArgumentNullException>(nameof(newState));
DebugUtility.LogException<ArgumentNullException>(nameof(state));
return;
}

Expand All @@ -122,9 +122,9 @@ public async Task ChangeStateAsync(TState newState, CancellationToken cancellati
var modules = _modulesLocator.GetElements();
foreach (var module in modules)
{
if (!module.AllowChangeState(this, newState))
if (!module.AllowChangeState(this, state))
{
var message = $"{module} not allow change state to {newState}";
var message = $"{module} not allow change state to {state}";
Debug.LogWarning(message);

return;
Expand All @@ -133,10 +133,18 @@ public async Task ChangeStateAsync(TState newState, CancellationToken cancellati

_transitionTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_runningTokenSource.Token, cancellationToken);
_stateChangeCompletionSource = new TaskCompletionSource<bool>();
var rootState = CurrentState;

OnStatePreChanged(newState);
CurrentState = await _transitionSequence.ChangingStateAsync(CurrentState, newState, _transitionTokenSource.Token);
OnStateChanged(CurrentState);
OnStatePreChanged(state);
await _sequence.PreProcessingAsync(rootState, state, cancellationToken);

if (!cancellationToken.IsCancellationRequested
&& await _sequence.ProcessingAsync(rootState, state, cancellationToken))
{
CurrentState = state;
await _sequence.PostProcessingAsync(rootState, state, cancellationToken);
OnStateChanged(CurrentState);
}

_stateChangeCompletionSource.TrySetResult(true);
_stateChangeCompletionSource = null;
Expand Down Expand Up @@ -284,7 +292,7 @@ protected bool ValidateRunning(bool targetState, bool logException = true)
public class StateMachine<TState> : StateMachine<TState, DefaultSequence<TState>>
where TState : BaseState
{
public StateMachine(DefaultSequence<TState> transitionSequence) : base(transitionSequence)
public StateMachine(DefaultSequence<TState> sequence) : base(sequence)
{
}

Expand All @@ -296,7 +304,7 @@ public StateMachine() : this(new())
[Serializable]
public class StateMachine : StateMachine<BaseState>
{
public StateMachine(DefaultSequence<BaseState> transitionSequence) : base(transitionSequence)
public StateMachine(DefaultSequence<BaseState> sequence) : base(sequence)
{
}

Expand Down
2 changes: 1 addition & 1 deletion Runtime/Interfaces/IStateMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface IStateMachine<TState> where TState : BaseState

void Run();
bool InState<T>() where T : TState;
Task ChangeStateAsync(TState newState, CancellationToken cancellationToken = default);
Task ChangeStateAsync(TState state, CancellationToken cancellationToken = default);
void Stop();

public bool TryAddModule<TModule>(TModule module) where TModule : Module<TState>;
Expand Down
40 changes: 24 additions & 16 deletions Runtime/Sequences/DefaultSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,43 @@
namespace Better.StateMachine.Runtime.Sequences
{
[Serializable]
public class DefaultSequence<TState> : ISequence<TState> where TState : BaseState
public class DefaultSequence<TState> : Sequence<TState> where TState : BaseState
{
async Task<TState> ISequence<TState>.ChangingStateAsync(TState currentState, TState newState, CancellationToken cancellationToken)
protected internal override Task PreProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
Debug.LogWarning("Was canceled before the start");
return default;
}
return Task.CompletedTask;
}

if (newState == currentState)
protected internal override async Task<bool> ProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
Debug.LogWarning($"{nameof(newState)} equaled {nameof(currentState)}, operation was cancelled");
return currentState;
var message = "Was canceled before the start";
Debug.LogWarning(message);
return false;
}

if (currentState != null)
if (fromState != null)
{
await currentState.ExitAsync(cancellationToken);
await fromState.ExitAsync(cancellationToken);
if (cancellationToken.IsCancellationRequested)
{
return default;
return false;
}
}

await newState.EnterAsync(cancellationToken);
if (cancellationToken.IsCancellationRequested) return default;
await toState.EnterAsync(cancellationToken);

var success = !cancellationToken.IsCancellationRequested;
return success;
}

protected internal override Task PostProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken)
{
fromState?.OnExited();
toState?.OnEntered();

return newState;
return Task.CompletedTask;
}
}
}
11 changes: 0 additions & 11 deletions Runtime/Sequences/ISequence.cs

This file was deleted.

3 changes: 0 additions & 3 deletions Runtime/Sequences/ISequence.cs.meta

This file was deleted.

15 changes: 15 additions & 0 deletions Runtime/Sequences/Sequence.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Better.StateMachine.Runtime.States;

namespace Better.StateMachine.Runtime.Sequences
{
[Serializable]
public abstract class Sequence<TState> where TState : BaseState
{
protected internal abstract Task PreProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken);
protected internal abstract Task<bool> ProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken);
protected internal abstract Task PostProcessingAsync(TState fromState, TState toState, CancellationToken cancellationToken);
}
}
3 changes: 3 additions & 0 deletions Runtime/Sequences/Sequence.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Runtime/States/BaseState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ public abstract class BaseState
{
/// <summary> Called once, when the StateMachine enters this state </summary>
public abstract Task EnterAsync(CancellationToken token);

public abstract void OnEntered();

/// <summary> Called once, when the State Machine exits from this state </summary>
public abstract Task ExitAsync(CancellationToken token);


public abstract void OnExited();

public override string ToString()
{
return GetType().Name;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "com.tdw.better.statemachine",
"displayName": "Better State Machine",
"version": "0.1.8",
"version": "0.1.9",
"unity": "2021.3",
"description": " ",
"dependencies": {
Expand Down

0 comments on commit 35b1624

Please sign in to comment.