undoActions.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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 "platform/platform.h"
  23. #include "gui/worldEditor/undoActions.h"
  24. #include "gui/editor/inspector/field.h"
  25. #include "gui/editor/guiInspector.h"
  26. #include "console/consoleTypes.h"
  27. #include "console/engineAPI.h"
  28. IMPLEMENT_CONOBJECT( MECreateUndoAction );
  29. ConsoleDocClass( MECreateUndoAction,
  30. "@brief Material Editor create undo instance\n\n"
  31. "Not intended for game development, for editors or internal use only.\n\n "
  32. "@internal");
  33. MECreateUndoAction::MECreateUndoAction( const UTF8* actionName )
  34. : UndoAction( actionName )
  35. {
  36. }
  37. MECreateUndoAction::~MECreateUndoAction()
  38. {
  39. }
  40. void MECreateUndoAction::initPersistFields()
  41. {
  42. Parent::initPersistFields();
  43. }
  44. void MECreateUndoAction::addObject( SimObject *object )
  45. {
  46. AssertFatal( object, "MECreateUndoAction::addObject() - Got null object!" );
  47. mObjects.increment();
  48. mObjects.last().id = object->getId();
  49. }
  50. DefineConsoleMethod( MECreateUndoAction, addObject, void, (SimObject *obj), , "( SimObject obj )")
  51. {
  52. if (obj)
  53. object->addObject( obj );
  54. }
  55. void MECreateUndoAction::undo()
  56. {
  57. for ( S32 i= mObjects.size()-1; i >= 0; i-- )
  58. {
  59. ObjectState &state = mObjects[i];
  60. SimObject *object = Sim::findObject( state.id );
  61. if ( !object )
  62. continue;
  63. // Save the state.
  64. if ( !state.memento.hasState() )
  65. state.memento.save( object );
  66. // Store the group.
  67. SimGroup *group = object->getGroup();
  68. if ( group )
  69. state.groupId = group->getId();
  70. // We got what we need... delete it.
  71. object->deleteObject();
  72. }
  73. Con::executef( this, "onUndone" );
  74. }
  75. void MECreateUndoAction::redo()
  76. {
  77. for ( S32 i=0; i < mObjects.size(); i++ )
  78. {
  79. const ObjectState &state = mObjects[i];
  80. // Create the object.
  81. SimObject::setForcedId(state.id); // Restore the object's Id
  82. SimObject *object = state.memento.restore();
  83. if ( !object )
  84. continue;
  85. // Now restore its group.
  86. SimGroup *group;
  87. if ( Sim::findObject( state.groupId, group ) )
  88. group->addObject( object );
  89. }
  90. Con::executef( this, "onRedone" );
  91. }
  92. IMPLEMENT_CONOBJECT( MEDeleteUndoAction );
  93. ConsoleDocClass( MEDeleteUndoAction,
  94. "@brief Material Editor delete undo instance\n\n"
  95. "Not intended for game development, for editors or internal use only.\n\n "
  96. "@internal");
  97. MEDeleteUndoAction::MEDeleteUndoAction( const UTF8 *actionName )
  98. : UndoAction( actionName )
  99. {
  100. }
  101. MEDeleteUndoAction::~MEDeleteUndoAction()
  102. {
  103. }
  104. void MEDeleteUndoAction::initPersistFields()
  105. {
  106. Parent::initPersistFields();
  107. }
  108. void MEDeleteUndoAction::deleteObject( SimObject *object )
  109. {
  110. AssertFatal( object, "MEDeleteUndoAction::deleteObject() - Got null object!" );
  111. AssertFatal( object->isProperlyAdded(),
  112. "MEDeleteUndoAction::deleteObject() - Object should be registered!" );
  113. mObjects.increment();
  114. ObjectState& state = mObjects.last();
  115. // Capture the object id.
  116. state.id = object->getId();
  117. // Save the state.
  118. state.memento.save( object );
  119. // Store the group.
  120. SimGroup *group = object->getGroup();
  121. if ( group )
  122. state.groupId = group->getId();
  123. // Now delete the object.
  124. object->deleteObject();
  125. }
  126. void MEDeleteUndoAction::deleteObject( const Vector<SimObject*> &objectList )
  127. {
  128. for ( S32 i = 0; i < objectList.size(); i++ )
  129. deleteObject( objectList[i] );
  130. }
  131. DefineConsoleMethod( MEDeleteUndoAction, deleteObject, void, (SimObject *obj ), , "( SimObject obj )")
  132. {
  133. if (obj)
  134. object->deleteObject( obj );
  135. }
  136. void MEDeleteUndoAction::undo()
  137. {
  138. for ( S32 i= mObjects.size()-1; i >= 0; i-- )
  139. {
  140. const ObjectState &state = mObjects[i];
  141. // Create the object.
  142. SimObject::setForcedId(state.id); // Restore the object's Id
  143. SimObject *object = state.memento.restore();
  144. if ( !object )
  145. continue;
  146. // Now restore its group.
  147. SimGroup *group;
  148. if ( Sim::findObject( state.groupId, group ) )
  149. group->addObject( object );
  150. }
  151. Con::executef( this, "onUndone" );
  152. }
  153. void MEDeleteUndoAction::redo()
  154. {
  155. for ( S32 i=0; i < mObjects.size(); i++ )
  156. {
  157. const ObjectState& state = mObjects[i];
  158. SimObject *object = Sim::findObject( state.id );
  159. if ( object )
  160. object->deleteObject();
  161. }
  162. Con::executef( this, "onRedone" );
  163. }
  164. IMPLEMENT_CONOBJECT( InspectorFieldUndoAction );
  165. ConsoleDocClass( InspectorFieldUndoAction,
  166. "@brief Inspector Field undo action instance\n\n"
  167. "Not intended for game development, for editors or internal use only.\n\n "
  168. "@internal");
  169. InspectorFieldUndoAction::InspectorFieldUndoAction()
  170. {
  171. mObjId = 0;
  172. mField = NULL;
  173. mSlotName = StringTable->insert("");
  174. mArrayIdx = StringTable->insert("");
  175. }
  176. InspectorFieldUndoAction::InspectorFieldUndoAction( const UTF8 *actionName )
  177. : UndoAction( actionName )
  178. {
  179. mInspector = NULL;
  180. mObjId = 0;
  181. mField = NULL;
  182. mSlotName = StringTable->insert("");
  183. mArrayIdx = StringTable->insert("");
  184. }
  185. void InspectorFieldUndoAction::initPersistFields()
  186. {
  187. addField( "inspectorGui", TYPEID< GuiInspector >(), Offset( mInspector, InspectorFieldUndoAction ) );
  188. addField( "objectId", TypeS32, Offset( mObjId, InspectorFieldUndoAction ) );
  189. addField( "fieldName", TypeString, Offset( mSlotName, InspectorFieldUndoAction ) );
  190. addField( "fieldValue", TypeRealString, Offset( mData, InspectorFieldUndoAction ) );
  191. addField( "arrayIndex", TypeString, Offset( mArrayIdx, InspectorFieldUndoAction ) );
  192. Parent::initPersistFields();
  193. }
  194. void InspectorFieldUndoAction::undo()
  195. {
  196. SimObject *obj = NULL;
  197. if ( !Sim::findObject( mObjId, obj ) )
  198. return;
  199. if ( mArrayIdx && dStricmp( mArrayIdx, "(null)" ) == 0 )
  200. mArrayIdx = NULL;
  201. // Grab the current data.
  202. String data = obj->getDataField( mSlotName, mArrayIdx );
  203. // Call this to mirror the way field changes are done through the inspector.
  204. obj->inspectPreApply();
  205. // Restore the data from the UndoAction
  206. obj->setDataField( mSlotName, mArrayIdx, mData.c_str() );
  207. // Call this to mirror the way field changes are done through the inspector.
  208. obj->inspectPostApply();
  209. // If the affected object is still being inspected,
  210. // update the InspectorField to reflect the changed value.
  211. if ( mInspector && mInspector->getNumInspectObjects() > 0 && mInspector->getInspectObject() == obj )
  212. mInspector->updateFieldValue( mSlotName, mArrayIdx );
  213. // Now save the previous data in this UndoAction
  214. // since an undo action must become a redo action and vice-versa
  215. mData = data;
  216. }