stateMachineComponent.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "T3D/components/game/stateMachineComponent.h"
  23. #include "platform/platform.h"
  24. #include "console/consoleTypes.h"
  25. #include "core/util/safeDelete.h"
  26. #include "core/resourceManager.h"
  27. #include "core/stream/fileStream.h"
  28. #include "console/consoleTypes.h"
  29. #include "console/consoleObject.h"
  30. #include "ts/tsShapeInstance.h"
  31. #include "core/stream/bitStream.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "console/engineAPI.h"
  34. #include "lighting/lightQuery.h"
  35. IMPLEMENT_CALLBACK( StateMachineComponent, onStateChange, void, (), (),
  36. "@brief Called when we collide with another object.\n\n"
  37. "@param obj The ShapeBase object\n"
  38. "@param collObj The object we collided with\n"
  39. "@param vec Collision impact vector\n"
  40. "@param len Length of the impact vector\n" );
  41. //////////////////////////////////////////////////////////////////////////
  42. // Constructor/Destructor
  43. //////////////////////////////////////////////////////////////////////////
  44. StateMachineComponent::StateMachineComponent() : Component()
  45. {
  46. mFriendlyName = "State Machine";
  47. mComponentType = "Game";
  48. mDescription = getDescriptionText("A generic state machine.");
  49. mStateMachineFile = "";
  50. //doesn't need to be networked
  51. mNetworked = false;
  52. }
  53. StateMachineComponent::~StateMachineComponent()
  54. {
  55. for(S32 i = 0;i < mFields.size();++i)
  56. {
  57. ComponentField &field = mFields[i];
  58. SAFE_DELETE_ARRAY(field.mFieldDescription);
  59. }
  60. SAFE_DELETE_ARRAY(mDescription);
  61. }
  62. IMPLEMENT_CO_NETOBJECT_V1(StateMachineComponent);
  63. bool StateMachineComponent::onAdd()
  64. {
  65. if(! Parent::onAdd())
  66. return false;
  67. // Register for the resource change signal.
  68. ResourceManager::get().getChangedSignal().notify(this, &StateMachineComponent::_onResourceChanged);
  69. mStateMachine.onStateChanged.notify(this, &StateMachineComponent::onStateChanged);
  70. return true;
  71. }
  72. void StateMachineComponent::onRemove()
  73. {
  74. Parent::onRemove();
  75. }
  76. U32 StateMachineComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  77. {
  78. U32 retMask = Parent::packUpdate(con, mask, stream);
  79. return retMask;
  80. }
  81. void StateMachineComponent::unpackUpdate(NetConnection *con, BitStream *stream)
  82. {
  83. Parent::unpackUpdate(con, stream);
  84. }
  85. //This is mostly a catch for situations where the behavior is re-added to the object and the like and we may need to force an update to the behavior
  86. void StateMachineComponent::onComponentAdd()
  87. {
  88. Parent::onComponentAdd();
  89. }
  90. void StateMachineComponent::onComponentRemove()
  91. {
  92. Parent::onComponentRemove();
  93. }
  94. void StateMachineComponent::initPersistFields()
  95. {
  96. Parent::initPersistFields();
  97. addProtectedField("stateMachineFile", TypeFilename, Offset(mStateMachineFile, StateMachineComponent),
  98. &_setSMFile, &defaultProtectedGetFn, "The sim time of when we started this state");
  99. }
  100. bool StateMachineComponent::_setSMFile(void *object, const char *index, const char *data)
  101. {
  102. StateMachineComponent* smComp = static_cast<StateMachineComponent*>(object);
  103. if (smComp)
  104. {
  105. smComp->setStateMachineFile(data);
  106. smComp->loadStateMachineFile();
  107. return true;
  108. }
  109. return false;
  110. }
  111. void StateMachineComponent::_onResourceChanged(const Torque::Path &path)
  112. {
  113. if (path != Torque::Path(mStateMachineFile))
  114. return;
  115. loadStateMachineFile();
  116. }
  117. void StateMachineComponent::loadStateMachineFile()
  118. {
  119. if (!dStrIsEmpty(mStateMachineFile))
  120. {
  121. mStateMachine.mStateMachineFile = mStateMachineFile;
  122. mStateMachine.loadStateMachineFile();
  123. //now that it's loaded, we need to parse the SM's fields and set them as script vars on ourselves
  124. S32 smFieldCount = mStateMachine.getFieldsCount();
  125. for (U32 i = 0; i < smFieldCount; i++)
  126. {
  127. StateMachine::StateField field = mStateMachine.getField(i);
  128. char buffer[128];
  129. if (field.fieldType == StateMachine::StateField::BooleanType)
  130. {
  131. dSprintf(buffer, sizeof(buffer), "%b", field.triggerBoolVal);
  132. setDataField(field.name, NULL, buffer);
  133. }
  134. else if (field.fieldType == StateMachine::StateField::NumberType)
  135. {
  136. dSprintf(buffer, sizeof(buffer), "%g", field.triggerNumVal);
  137. setDataField(field.name, NULL, buffer);
  138. }
  139. else if (field.fieldType == StateMachine::StateField::StringType)
  140. {
  141. setDataField(field.name, NULL, field.triggerStringVal);
  142. }
  143. }
  144. }
  145. }
  146. void StateMachineComponent::processTick()
  147. {
  148. if (!isServerObject() || !isActive())
  149. return;
  150. mStateMachine.update();
  151. }
  152. void StateMachineComponent::onDynamicModified( const char* slotName, const char* newValue )
  153. {
  154. Parent::onDynamicModified(slotName, newValue);
  155. StringTableEntry fieldName = StringTable->insert(slotName);
  156. mStateMachine.checkTransitions(fieldName, newValue);
  157. }
  158. void StateMachineComponent::onStaticModified( const char* slotName, const char* newValue )
  159. {
  160. Parent::onStaticModified(slotName, newValue);
  161. StringTableEntry fieldName = StringTable->insert(slotName);
  162. mStateMachine.checkTransitions(fieldName, newValue);
  163. }
  164. void StateMachineComponent::onStateChanged(StateMachine* sm, S32 stateIdx)
  165. {
  166. //do a script callback, if we have one
  167. //check if we have a function for that, and then also check if our owner does
  168. StringTableEntry callbackName = mStateMachine.getCurrentState().callbackName;
  169. if (isMethod(callbackName))
  170. Con::executef(this, callbackName);
  171. if (mOwner->isMethod(callbackName))
  172. Con::executef(mOwner, callbackName);
  173. }