undoActions.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. IMPLEMENT_CONOBJECT( MECreateUndoAction );
  28. ConsoleDocClass( MECreateUndoAction,
  29. "@brief Material Editor create undo instance\n\n"
  30. "Not intended for game development, for editors or internal use only.\n\n "
  31. "@internal");
  32. MECreateUndoAction::MECreateUndoAction( const UTF8* actionName )
  33. : UndoAction( actionName )
  34. {
  35. }
  36. MECreateUndoAction::~MECreateUndoAction()
  37. {
  38. }
  39. void MECreateUndoAction::initPersistFields()
  40. {
  41. Parent::initPersistFields();
  42. }
  43. void MECreateUndoAction::addObject( SimObject *object )
  44. {
  45. AssertFatal( object, "MECreateUndoAction::addObject() - Got null object!" );
  46. mObjects.increment();
  47. mObjects.last().id = object->getId();
  48. }
  49. ConsoleMethod( MECreateUndoAction, addObject, void, 3, 3, "( SimObject obj )")
  50. {
  51. SimObject *obj = NULL;
  52. if ( Sim::findObject( argv[2], obj ) && 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. ConsoleMethod( MEDeleteUndoAction, deleteObject, void, 3, 3, "( SimObject obj )")
  132. {
  133. SimObject *obj = NULL;
  134. if ( Sim::findObject( argv[2], obj ) && obj )
  135. object->deleteObject( obj );
  136. }
  137. void MEDeleteUndoAction::undo()
  138. {
  139. for ( S32 i= mObjects.size()-1; i >= 0; i-- )
  140. {
  141. const ObjectState &state = mObjects[i];
  142. // Create the object.
  143. SimObject::setForcedId(state.id); // Restore the object's Id
  144. SimObject *object = state.memento.restore();
  145. if ( !object )
  146. continue;
  147. // Now restore its group.
  148. SimGroup *group;
  149. if ( Sim::findObject( state.groupId, group ) )
  150. group->addObject( object );
  151. }
  152. Con::executef( this, "onUndone" );
  153. }
  154. void MEDeleteUndoAction::redo()
  155. {
  156. for ( S32 i=0; i < mObjects.size(); i++ )
  157. {
  158. const ObjectState& state = mObjects[i];
  159. SimObject *object = Sim::findObject( state.id );
  160. if ( object )
  161. object->deleteObject();
  162. }
  163. Con::executef( this, "onRedone" );
  164. }
  165. IMPLEMENT_CONOBJECT( InspectorFieldUndoAction );
  166. ConsoleDocClass( InspectorFieldUndoAction,
  167. "@brief Inspector Field undo action instance\n\n"
  168. "Not intended for game development, for editors or internal use only.\n\n "
  169. "@internal");
  170. InspectorFieldUndoAction::InspectorFieldUndoAction()
  171. {
  172. mObjId = 0;
  173. mField = NULL;
  174. mSlotName = StringTable->insert("");
  175. mArrayIdx = StringTable->insert("");
  176. }
  177. InspectorFieldUndoAction::InspectorFieldUndoAction( const UTF8 *actionName )
  178. : UndoAction( actionName )
  179. {
  180. mInspector = NULL;
  181. mObjId = 0;
  182. mField = NULL;
  183. mSlotName = StringTable->insert("");
  184. mArrayIdx = StringTable->insert("");
  185. }
  186. void InspectorFieldUndoAction::initPersistFields()
  187. {
  188. addField( "inspectorGui", TYPEID< GuiInspector >(), Offset( mInspector, InspectorFieldUndoAction ) );
  189. addField( "objectId", TypeS32, Offset( mObjId, InspectorFieldUndoAction ) );
  190. addField( "fieldName", TypeString, Offset( mSlotName, InspectorFieldUndoAction ) );
  191. addField( "fieldValue", TypeRealString, Offset( mData, InspectorFieldUndoAction ) );
  192. addField( "arrayIndex", TypeString, Offset( mArrayIdx, InspectorFieldUndoAction ) );
  193. Parent::initPersistFields();
  194. }
  195. void InspectorFieldUndoAction::undo()
  196. {
  197. SimObject *obj = NULL;
  198. if ( !Sim::findObject( mObjId, obj ) )
  199. return;
  200. if ( mArrayIdx && dStricmp( mArrayIdx, "(null)" ) == 0 )
  201. mArrayIdx = NULL;
  202. // Grab the current data.
  203. String data = obj->getDataField( mSlotName, mArrayIdx );
  204. // Call this to mirror the way field changes are done through the inspector.
  205. obj->inspectPreApply();
  206. // Restore the data from the UndoAction
  207. obj->setDataField( mSlotName, mArrayIdx, mData.c_str() );
  208. // Call this to mirror the way field changes are done through the inspector.
  209. obj->inspectPostApply();
  210. // If the affected object is still being inspected,
  211. // update the InspectorField to reflect the changed value.
  212. if ( mInspector && mInspector->getNumInspectObjects() > 0 && mInspector->getInspectObject() == obj )
  213. mInspector->updateFieldValue( mSlotName, mArrayIdx );
  214. // Now save the previous data in this UndoAction
  215. // since an undo action must become a redo action and vice-versa
  216. mData = data;
  217. }