From 49b25e755b70ec412feaaf0b898d6f7e09d2bea6 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 28 Jun 2022 09:40:37 +0800 Subject: +node example --- .../Assets/UNEB/Utility/StateMachine.cs | 300 +++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 Other/NodeEditorExamples/Assets/UNEB/Utility/StateMachine.cs (limited to 'Other/NodeEditorExamples/Assets/UNEB/Utility/StateMachine.cs') diff --git a/Other/NodeEditorExamples/Assets/UNEB/Utility/StateMachine.cs b/Other/NodeEditorExamples/Assets/UNEB/Utility/StateMachine.cs new file mode 100644 index 00000000..9c3a8992 --- /dev/null +++ b/Other/NodeEditorExamples/Assets/UNEB/Utility/StateMachine.cs @@ -0,0 +1,300 @@ +using UnityEngine; +using System; +using System.Collections.Generic; + +namespace Bonsai.Utility +{ + /// + /// A finite state machine. + /// + /// The date type to be stored by the machine states. + public class StateMachine + { + /// + /// An event that fires when the machine finishes transitioning to another state. + /// + public event Action OnStateChangedEvent = delegate { }; + + protected Dictionary _states = new Dictionary(); + + /// + /// Get all the state data. + /// + /// + public IEnumerable Data() + { + return _states.Keys; + } + + protected State _currentState; + + public State CurrentState + { + get { return _currentState; } + } + + /// + /// Adds a state to the machine. + /// + /// + public void AddState(T data) + { + var s = new State(data); + _states.Add(data, s); ; + } + + public void AddState(State s) + { + _states.Add(s.Value, s); + } + + public void AddTransition(State start, State end, Func condition, Func onMakingTransition) + { + var t = new Transition(condition); + t.onMakingTransition = onMakingTransition; + + AddTransition(start, end, t); + } + + public void AddTransition(State start, State end, Transition t) + { + start.Add(t); + t.SetNextState(end); + } + + /// + /// Add a transition that goes from start to end state. + /// + /// + /// + /// + public void AddTransition(T start, T end, Transition t) + { + var startST = GetState(start); + var endST = GetState(end); + + if (startST == null || endST == null) { + Debug.LogError("State(s) are not in the state machine"); + return; + } + + AddTransition(startST, endST, t); + } + + /// + /// Add two transitions. + /// One from start to end. + /// Another from end to start. + /// + /// + /// + /// + /// + public void AddBiTransition(T start, T end, Transition startToEnd, Transition endToStart) + { + var startST = GetState(start); + var endST = GetState(end); + + if (startST == null || endST == null) { + Debug.LogError("State(s) are not in the state machine"); + return; + } + + AddTransition(startST, endST, startToEnd); + AddTransition(endST, startST, endToStart); + } + + /// + /// Gets the state associated with the data. + /// + /// + /// + public State GetState(T data) + { + if (_states.ContainsKey(data)) { + return _states[data]; + } + + return null; + } + + /// + /// Sets the current active state of the machine. + /// + /// + public void SetCurrentState(T data) + { + + var state = GetState(data); + + if (state == null) { + Debug.LogError(data + " is not in the state machine."); + } + + else { + _currentState = state; + } + } + + /// + /// Handles moving to next state when conditions are met. + /// + public void Update() + { + if (_currentState == null) { + return; + } + + Transition validTrans = null; + + // Pick the next state if the transition conditions are met. + for (int i = 0; i < _currentState.Transitions.Count; i++) { + + if (_currentState.Transitions[i].AllConditionsMet()) { + validTrans = _currentState.Transitions[i]; + break; + } + } + + if (validTrans != null) { + + // Call on making transition. + if (validTrans.onMakingTransition()) { + + // Call on state exit. + if (_currentState.onStateExit != null) + _currentState.onStateExit(); + + // Change the state to the next one. + _currentState = validTrans.NextState; + + // Call on state enter. + if (_currentState.onStateEnter != null) + _currentState.onStateEnter(); + + OnStateChangedEvent(); + } + } + } + + /// + /// A transition between two states than only occurs if all + /// its conditions are satisfied. + /// + public class Transition + { + private State _nextState = null; + private List> _conditions = new List>(); + + /// + /// Called after the 'from' state exits and before the 'to' state enters. + /// If this fails, then it goes back to the starting state. + /// + public Func onMakingTransition = () => { return true; }; + + public Transition() + { + + } + + /// + /// Pass in initial conditions + /// + /// + public Transition(params Func[] conditions) + { + foreach (var c in conditions) { + AddCondition(c); + } + } + + /// + /// Adds a condition that must be satisfied in order to do the transition. + /// + /// + public void AddCondition(Func cond) + { + _conditions.Add(cond); + } + + /// + /// Tests if all the conditions of the transition are satisfied. + /// + /// + public bool AllConditionsMet() + { + for (int i = 0; i < _conditions.Count; i++) { + + if (!_conditions[i]()) return false; + } + + // All conditions returned true. + return true; + } + + /// + /// Set the state that transition goes to. + /// + /// + public void SetNextState(State next) + { + _nextState = next; + } + + /// + /// The state that transition goes to. + /// + public State NextState + { + get { return _nextState; } + } + } + + /// + /// A state of the machine. + /// + public class State + { + private T _data; + private List _transitions = new List(); + + /// + /// Executes when the machine transitions into this state. + /// + public Action onStateEnter; + + /// + /// Executes when the machine transitions out of this state. + /// + public Action onStateExit; + + /// + /// Construct a state with its data. + /// + /// + public State(T data) + { + _data = data; + } + + /// + /// Adds a transition to the state. + /// + /// + public void Add(Transition t) + { + _transitions.Add(t); + } + + /// + /// The data held by the state. + /// + public T Value { get { return _data; } } + + /// + /// The transitions connected to the state. + /// + public List Transitions { get { return _transitions; } } + } + } +} \ No newline at end of file -- cgit v1.1-26-g67d0