1 /** 2 * This is a state machine for the Engine. The state machine manages a set of states, 3 * each of which has a set of System providers. When the state machine changes the state, it removes 4 * Systems associated with the previous state and adds Systems associated with the new state. 5 */ 6 module ashd.fsm.engineStateMachine; 7 8 import ashd.core.engine : Engine; 9 import ashd.core.system : System; 10 import ashd.fsm.engineState : EngineState; 11 import ashd.fsm.ISystemProvider: ISystemProvider; 12 13 14 15 16 public class EngineStateMachine 17 { 18 private 19 { 20 Engine mEngine; 21 EngineState[string] mStates; 22 EngineState mCurrentState; 23 } 24 /** 25 * Constructor. Creates an SystemStateMachine. 26 */ 27 public this( Engine engine_a ) 28 { 29 mEngine = engine_a; 30 } 31 32 /** 33 * Add a state to this state machine. 34 * 35 * @param name The name of this state - used to identify it later in the changeState method call. 36 * @param state The state. 37 * @return This state machine, so methods can be chained. 38 */ 39 public EngineStateMachine addState( string name_a, EngineState state_a ) 40 { 41 mStates[name_a] = state_a; 42 return this; 43 } 44 45 /** 46 * Create a new state in this state machine. 47 * 48 * @param name The name of the new state - used to identify it later in the changeState method call. 49 * @return The new EntityState object that is the state. This will need to be configured with 50 * the appropriate component providers. 51 */ 52 public EngineState createState( string name_a ) 53 { 54 EngineState state = new EngineState(); 55 56 mStates[name_a] = state; 57 return state; 58 } 59 60 /** 61 * Change to a new state. The Systems from the old state will be removed and the Systems 62 * for the new state will be added. 63 * 64 * @param name The name of the state to change to. 65 */ 66 public void changeState( string name_a ) 67 { 68 if ( name_a !in mStates ) 69 { 70 throw( new Exception( "Engine state "~name_a~" doesn't exist" ) ); 71 } 72 73 EngineState newState = mStates[name_a]; 74 if ( newState == mCurrentState ) 75 { 76 newState = null; 77 return; 78 } 79 80 81 ISystemProvider[ClassInfo] toAdd = newState.providers(); 82 83 if ( mCurrentState ) 84 { 85 foreach ( key, provider; mCurrentState.providers ) 86 { 87 hash_t id = provider.identifier; 88 if ( (key in toAdd) && (toAdd[key].identifier == id) ) 89 { 90 toAdd.remove(key); 91 } 92 else 93 { 94 mEngine.removeSystem( provider.getSystem(key) ); 95 } 96 } 97 } 98 99 foreach ( key, provider; toAdd ) 100 { 101 System tmpSystem = provider.getSystem(key); 102 mEngine.addSystem( tmpSystem, key, provider.priority ); 103 } 104 mCurrentState = newState; 105 } 106 }