stateMachine.h

Engine/source/T3D/components/game/stateMachine.h

More...

Classes:

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef STATE_MACHINE_H
 25#define STATE_MACHINE_H
 26
 27#ifndef _SIMBASE_H_
 28#include "console/simBase.h"
 29#endif
 30#ifndef _OBJECTTYPES_H_
 31#include "T3D/objectTypes.h"
 32#endif
 33#ifndef _MMATH_H_
 34#include "math/mMath.h"
 35#endif
 36#ifndef _XMLDOC_H_
 37#include "console/SimXMLDocument.h"
 38#endif
 39
 40class StateMachine
 41{
 42public:
 43   struct StateField
 44   {
 45      StringTableEntry name;
 46      
 47      bool         triggerBoolVal;
 48      float        triggerNumVal;
 49      Point3F      triggerVectorVal;
 50      String       triggerStringVal;
 51
 52      enum Type
 53      {
 54         BooleanType = 0,
 55         NumberType,
 56         VectorType,
 57         StringType
 58      }fieldType;
 59   };
 60
 61   struct UniqueReference
 62   {
 63      SimObject* referenceObj;
 64      const char* referenceVar;
 65      const char* uniqueName;
 66   };
 67
 68   struct StateTransition
 69   {
 70      struct Condition
 71      {
 72         enum TriggerValueTarget
 73         {
 74            Equals = 0,
 75            GeaterThan,
 76            LessThan,
 77            GreaterOrEqual,
 78            LessOrEqual,
 79            True,
 80            False,
 81            Positive,
 82            Negative,
 83            DoesNotEqual
 84         };
 85
 86         StateField field;
 87
 88         TriggerValueTarget   triggerComparitor;
 89
 90         UniqueReference      *valUniqueRef;
 91      };
 92
 93      StringTableEntry  mName;
 94      StringTableEntry  mStateTarget;
 95      Vector<Condition> mTransitionRules;
 96   };
 97
 98   struct State 
 99   {
100      Vector<StateTransition> mTransitions;
101
102      StringTableEntry stateName;
103
104      StringTableEntry callbackName;
105   };
106
107   StringTableEntry     mStateMachineFile;
108
109protected:
110   Vector<State> mStates;
111
112   Vector<StateField> mFields;
113
114   Vector<UniqueReference> mUniqueReferences;
115
116   State mCurrentState;
117
118   F32 mStateStartTime;
119   F32 mStateTime;
120
121   StringTableEntry mStartingState;
122
123   State *mCurCreateSuperState;
124   State *mCurCreateState;
125
126   SimObjectPtr<SimXMLDocument> mXMLReader;
127
128public:
129   StateMachine();
130   virtual ~StateMachine();
131
132   void update();
133
134   void loadStateMachineFile();
135   void readStates();
136   void readTransitions(State &currentState);
137   void readConditions(StateTransition &newTransition);
138
139   void setState(const char* stateName, bool clearFields = true);
140
141   const char* getCurrentStateName() { return mCurrentState.stateName; }
142   State& getCurrentState() {
143      return mCurrentState;
144   }
145
146   S32 getStateCount() { return mStates.size(); }
147   const char* getStateByIndex(S32 index);
148   State& getStateByName(const char* name);
149
150   void checkTransitions(const char* slotName, const char* newValue);
151
152   bool passComparitorCheck(const char* var, StateTransition::Condition transitionRule);
153
154   S32 findFieldByName(const char* name);
155
156   S32 getFieldsCount() { return mFields.size(); }
157
158   StateField getField(U32 index)
159   {
160      if (index <= mFields.size())
161         return mFields[index];
162   }
163
164   Signal< void(StateMachine*, S32 stateIdx) > onStateChanged;
165
166   //
167   inline bool readStateName(State* state, SimXMLDocument* reader)
168   {
169      if (reader->pushFirstChildElement("Name"))
170      {
171         state->stateName = reader->getData();
172         reader->popElement();
173
174         return true;
175      }
176
177      return false;
178   }
179   inline bool readStateScriptFunction(State* state, SimXMLDocument* reader)
180   {
181      if (reader->pushFirstChildElement("ScriptFunction"))
182      {
183         state->callbackName = reader->getData();
184         reader->popElement();
185
186         return true;
187      }
188
189      return false;
190   }
191   inline bool readTransitonTarget(StateTransition* transition, SimXMLDocument* reader)
192   {
193      if (reader->pushFirstChildElement("StateTarget"))
194      {
195         transition->mStateTarget = reader->getData();
196         reader->popElement();
197
198         return true;
199      }
200
201      return false;
202   }
203   //
204   inline bool readFieldName(StateField* newField, SimXMLDocument* reader)
205   {
206      if (reader->pushFirstChildElement("FieldName"))
207      {
208         newField->name = reader->getData();
209         reader->popElement();
210
211         return true;
212      }
213
214      return false;
215   }
216   inline bool readFieldComparitor(StateTransition::Condition* condition, SimXMLDocument* reader)
217   {
218      if (reader->pushFirstChildElement("Comparitor"))
219      {
220         S32 compIdx = parseComparitor(reader->getData());
221         condition->triggerComparitor = static_cast<StateTransition::Condition::TriggerValueTarget>(compIdx);
222         reader->popElement();
223
224         return true;
225      }
226
227      return false;
228   }
229   inline bool readFieldValue(StateField* field, SimXMLDocument* reader)
230   {
231      if (reader->pushFirstChildElement("NumValue"))
232      {
233         field->fieldType = StateField::NumberType;
234         field->triggerNumVal = dAtof(reader->getData());
235         reader->popElement();
236         return true;
237      }
238      else if (reader->pushFirstChildElement("StringValue"))
239      {
240         field->fieldType = StateField::StringType;
241         field->triggerStringVal = reader->getData();
242         reader->popElement();
243         return true;
244      }
245      else if (reader->pushFirstChildElement("BoolValue"))
246      {
247         field->fieldType = StateField::BooleanType;
248         field->triggerBoolVal = dAtob(reader->getData());
249         reader->popElement();
250         return true;
251      }
252
253      return false;
254   }
255
256private:
257   S32 parseComparitor(const char* comparitorName);
258};
259
260#endif
261