stateMachineComponent.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. mNetFlags.clear();
  53. }
  54. StateMachineComponent::~StateMachineComponent()
  55. {
  56. for(S32 i = 0;i < mFields.size();++i)
  57. {
  58. ComponentField &field = mFields[i];
  59. SAFE_DELETE_ARRAY(field.mFieldDescription);
  60. }
  61. SAFE_DELETE_ARRAY(mDescription);
  62. }
  63. IMPLEMENT_CO_NETOBJECT_V1(StateMachineComponent);
  64. bool StateMachineComponent::onAdd()
  65. {
  66. if(! Parent::onAdd())
  67. return false;
  68. // Register for the resource change signal.
  69. ResourceManager::get().getChangedSignal().notify(this, &StateMachineComponent::_onResourceChanged);
  70. mStateMachine.onStateChanged.notify(this, &StateMachineComponent::onStateChanged);
  71. return true;
  72. }
  73. void StateMachineComponent::onRemove()
  74. {
  75. Parent::onRemove();
  76. }
  77. U32 StateMachineComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  78. {
  79. U32 retMask = Parent::packUpdate(con, mask, stream);
  80. return retMask;
  81. }
  82. void StateMachineComponent::unpackUpdate(NetConnection *con, BitStream *stream)
  83. {
  84. Parent::unpackUpdate(con, stream);
  85. }
  86. //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
  87. void StateMachineComponent::onComponentAdd()
  88. {
  89. Parent::onComponentAdd();
  90. }
  91. void StateMachineComponent::onComponentRemove()
  92. {
  93. Parent::onComponentRemove();
  94. }
  95. void StateMachineComponent::initPersistFields()
  96. {
  97. Parent::initPersistFields();
  98. addProtectedField("stateMachineFile", TypeFilename, Offset(mStateMachineFile, StateMachineComponent),
  99. &_setSMFile, &defaultProtectedGetFn, "The sim time of when we started this state");
  100. }
  101. bool StateMachineComponent::_setSMFile(void *object, const char *index, const char *data)
  102. {
  103. StateMachineComponent* smComp = static_cast<StateMachineComponent*>(object);
  104. if (smComp)
  105. {
  106. smComp->setStateMachineFile(data);
  107. smComp->loadStateMachineFile();
  108. return true;
  109. }
  110. return false;
  111. }
  112. void StateMachineComponent::_onResourceChanged(const Torque::Path &path)
  113. {
  114. if (path != Torque::Path(mStateMachineFile))
  115. return;
  116. loadStateMachineFile();
  117. }
  118. void StateMachineComponent::loadStateMachineFile()
  119. {
  120. if (!dStrIsEmpty(mStateMachineFile))
  121. {
  122. mStateMachine.mStateMachineFile = mStateMachineFile;
  123. mStateMachine.loadStateMachineFile();
  124. //now that it's loaded, we need to parse the SM's fields and set them as script vars on ourselves
  125. S32 smFieldCount = mStateMachine.getFieldsCount();
  126. for (U32 i = 0; i < smFieldCount; i++)
  127. {
  128. StateMachine::StateField field = mStateMachine.getField(i);
  129. char buffer[128];
  130. if (field.fieldType == StateMachine::StateField::BooleanType)
  131. {
  132. dSprintf(buffer, sizeof(buffer), "%b", field.triggerBoolVal);
  133. setDataField(field.name, NULL, buffer);
  134. }
  135. else if (field.fieldType == StateMachine::StateField::NumberType)
  136. {
  137. dSprintf(buffer, sizeof(buffer), "%g", field.triggerNumVal);
  138. setDataField(field.name, NULL, buffer);
  139. }
  140. else if (field.fieldType == StateMachine::StateField::StringType)
  141. {
  142. setDataField(field.name, NULL, field.triggerStringVal);
  143. }
  144. }
  145. }
  146. }
  147. void StateMachineComponent::processTick()
  148. {
  149. if (!isServerObject() || !isActive())
  150. return;
  151. mStateMachine.update();
  152. }
  153. void StateMachineComponent::onDynamicModified( const char* slotName, const char* newValue )
  154. {
  155. Parent::onDynamicModified(slotName, newValue);
  156. StringTableEntry fieldName = StringTable->insert(slotName);
  157. mStateMachine.checkTransitions(fieldName, newValue);
  158. }
  159. void StateMachineComponent::onStaticModified( const char* slotName, const char* newValue )
  160. {
  161. Parent::onStaticModified(slotName, newValue);
  162. StringTableEntry fieldName = StringTable->insert(slotName);
  163. mStateMachine.checkTransitions(fieldName, newValue);
  164. }
  165. void StateMachineComponent::onStateChanged(StateMachine* sm, S32 stateIdx)
  166. {
  167. //do a script callback, if we have one
  168. //check if we have a function for that, and then also check if our owner does
  169. StringTableEntry callbackName = mStateMachine.getCurrentState().callbackName;
  170. if (isMethod(callbackName))
  171. Con::executef(this, callbackName);
  172. if (mOwner->isMethod(callbackName))
  173. Con::executef(mOwner, callbackName);
  174. }