gcsx_undo.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /* GCSx
  2. ** UNDO.H
  3. **
  4. ** Editor undo and redo functionality
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #ifndef __GCSx_UNDO_H_
  24. #define __GCSx_UNDO_H_
  25. class UndoBuffer {
  26. public:
  27. enum UndoType {
  28. UNDO_EMPTY = 0, // An empty chunk at end of undo buffer at all times
  29. UNDO_PAINTSEL, // Change of selection; Data1-2 is selection x/y offs, 3 is selection type
  30. // Only valid if paint window still open
  31. // item1 points to where selection surface is stored
  32. UNDO_WORLDNAME,
  33. UNDO_SCENENAME, // Name changes-
  34. UNDO_TILENAME, // Y size 1, X size length of string; X is actual length
  35. UNDO_LAYERNAME, // Size is larger of current or new name
  36. UNDO_ANIMGROUPNAME,
  37. UNDO_SCRIPTNAME,
  38. UNDO_SPAWNNAME, // Spawn includes layer in subid (0 for non-scene spawn)
  39. UNDO_FOLDERNAME,
  40. UNDO_SCENEDELETE, // Deletions-
  41. UNDO_TILEDELETE, // object is kept in item1
  42. UNDO_LAYERDELETE, // Layer includes scene in subid and pos in x
  43. UNDO_ANIMGROUPDELETE,
  44. UNDO_SCRIPTDELETE,
  45. UNDO_SPAWNDELETE, // Spawn includes layer in subid (0 for non-scene spawn)
  46. UNDO_FOLDERDELETE,
  47. UNDO_SCENECREATE, // Creations-
  48. UNDO_TILECREATE, // no object, id is only data
  49. UNDO_LAYERCREATE, // Layer includes scene in subid and pos in x
  50. UNDO_ANIMGROUPCREATE,
  51. UNDO_SCRIPTCREATE,
  52. UNDO_SPAWNCREATE, // Spawn includes layer in subid (0 for non-scene spawn)
  53. UNDO_FOLDERCREATE,
  54. UNDO_WORLDSTART, // X is old id
  55. UNDO_FOLDERADD, // subid item added, data1 blocktype, data2 pos
  56. UNDO_FOLDERREMOVE,// subid item erase, data1 blocktype, data2 pos
  57. // All spawn undos include layer in subid (0 for non-scene spawn)
  58. UNDO_SPAWNMOVE, // X/Y are old position
  59. UNDO_SPAWNSPRITE, // data1-3 are old data (ids)
  60. UNDO_SPAWNSCRIPT, // data1 is old script (id)
  61. // For these, changes are stored as a pointer to a list of strings
  62. // Undo data itself is 3 TextPoint structures (insertion/sel/selend)
  63. UNDO_SCRIPTINSERT,// Inserting one or more lines of code- xpos where, ypos # of lines
  64. UNDO_SCRIPTREMOVE,// Deleting one or more lines (same)
  65. UNDO_SCRIPTMODIFY,// Modifying one or more lines (same)
  66. UNDO_SCRIPTDEFAULT,
  67. UNDO_TILE, // A change to a tile, represented as a blit
  68. UNDO_TILECOLL, // Change to collision map (a blit also)
  69. UNDO_TILESIZE, // Sizing/count change, old surface/etc stored
  70. // X/Y are width/height, data1 is count, data2 maps count
  71. // item1 surface item2 fontwidths item3 collmaps
  72. UNDO_TILEPERLINE, // X is old value
  73. UNDO_TILETRANS, // X is old value
  74. UNDO_TILEGLYPH, // X is old value
  75. UNDO_LAYERMOVE, // id is scene; x/y are the two positions swapped
  76. UNDO_LAYERTILE, // A change to a tile layer
  77. UNDO_LAYERTILEEXT,//A change to a tile layer extended data
  78. UNDO_LAYERTILEFX, // A change to a tile layer effects data
  79. UNDO_LAYERTYPE, // X is old type
  80. UNDO_LAYERSIZE, // Sizing change, old data/fx stored
  81. // X/Y are width/height
  82. // item1 data item2 fx item3 coll
  83. UNDO_LAYEREXT, // X is previous Ext setting (UNDO_LAYERSIZE stores data change)
  84. UNDO_LAYERFX, // X is previous Fx setting (UNDO_LAYERSIZE stores data change)
  85. UNDO_LAYERTILESET,// X is previous tileset id
  86. UNDO_LAYERTILECUR,// Data1 = layersAffect, Data2 = view, Data3 = dim
  87. UNDO_LAYERTILETMP,// A change to tile layer data within a window, as part of selection
  88. // (item1 points to where data is stored; item2 to fx; item3 coll)
  89. // (layers are just "reset", not exchanged, when this is encountered)
  90. // h is doubled if fx or coll present; tripled for both (item2/item3 not null)
  91. // must ALWAYS be preceded/followed by the next...
  92. UNDO_LAYERTILESEL,// Change of selection; Data1-2 is selection x/y offs, 3 is selection type
  93. // x is in bytes; width rounded to dword
  94. // Actual width (in bytes) is in id
  95. // Pitch (in bytes) is in subid
  96. // Only valid if tile layer edit window still open
  97. // item1 points to where selection data is stored
  98. UNDO_LAYERSPAWNSEL,// Change of spawns selected
  99. // item1 points to set<int> where spawn selection is stored
  100. // item2 points to a newly allocated set<int> storing undo data
  101. };
  102. enum {
  103. // Undo buffer- sizes in K
  104. UNDO_DEFAULT_BUFFER = 8192,
  105. UNDO_MAX_BUFFER = 65536,
  106. };
  107. #ifndef NDEBUG
  108. static void setUndoThreshold(int level);
  109. #endif
  110. private:
  111. enum {
  112. // OR in to denote this chunk and the previous are one operation
  113. UNDO_MERGE = 128,
  114. };
  115. // What world we apply to
  116. class WorldEdit* world;
  117. // Undo buffer
  118. int requestedSize; // Requested size in K
  119. int undoSizeAlloc; // Size allocated
  120. Uint32* undoBuffer; // Allocated data
  121. int undoPos; // Current undo position- place next undo here or read redo from previous
  122. #ifndef NDEBUG
  123. // Number of actions before we fail further undos; < 0 to disable feature
  124. static int undoThresh;
  125. #endif
  126. // If we're currently undoing/redoing, which throttles any other undo/redo attempts
  127. // as we're taking care of it already
  128. int inUndo;
  129. int suspendUndo;
  130. // Undo block level and whether we're still waiting for our first item
  131. int undoBlock;
  132. int undoBlockDidFirst;
  133. int undoBlockFirstPos;
  134. int undoNonUndoable; // If true, user was warned and chose to go ahead
  135. // Undo data chunk header format-
  136. struct UndoHeader {
  137. int sourceWindow; // editor window this originated from
  138. int prevChunkSize; // 0 if first chunk
  139. UndoType type;
  140. int id; // Id of item affected
  141. int subid; // Sub id, such as tile number affected
  142. int xSize;
  143. int ySize;
  144. int xPos;
  145. int yPos;
  146. int data1; // Data specific to chunk
  147. int data2;
  148. int data3;
  149. void* item1; // An item that was deleted or swapped goes here
  150. void* item2; // These are cleared when the undo chunks are discarded
  151. void* item3;
  152. };
  153. static int undoHeaderSize; // Size in Uint32s
  154. // When you undo, the chunk becomes a redo block, swapping new data for old
  155. // Same format, it's a redo chunk because it's after the undopos pointer instead of before
  156. // Returns pointer to write data if space is now available (empty chunk is
  157. // moved as needed) NULL if space could not be made available and undo is being skipped
  158. Uint32* createUndoSpace(UndoType chunkType, int id, int subid, int xPos, int yPos, int xSize, int ySize, Window* srcWin = NULL, Uint32 data1 = 0, Uint32 data2 = 0, Uint32 data3 = 0, void* item1 = NULL, void* item2 = NULL, void* item3 = NULL) throw_Undo;
  159. // If undo block contains pointers to something, frees it up
  160. void deleteUndoBlock(int offset);
  161. // Clears all redo blocks after the current spot
  162. void clearRedo();
  163. // Some internal undo-block-writing functions
  164. void storeUndoScript(UndoType type, int id, const std::list<std::string>& source, int lineNum, int count, EditBox* editbox, Window* srcWin) throw_Undo;
  165. public:
  166. UndoBuffer(class WorldEdit* myWorld);
  167. ~UndoBuffer();
  168. // Size of 0 = no undo; changing size clears buffer!
  169. // Size is in K; clips to valid range
  170. int bufferSize() const { return requestedSize; }
  171. int bufferSize(int requested);
  172. int undoAvailable() const;
  173. void undoPerform(int doRedo = 0);
  174. int redoAvailable() const;
  175. void redoPerform();
  176. // Call if you do any action that you choose not to make undoable
  177. void clearUndo();
  178. // Call before and after one or more undos to "link" them all as one item
  179. // Can also be used to allow use of cancelUndoBlock()
  180. // If the entire block doesn't fit in the buffer, user will be warned one time;
  181. // if user cancels, anything done so far is undone (without redo) and UndoException is
  182. // thrown; if user chooses to continue or a non-undoable item occurs, entire block
  183. // will be non-undoable; nested blocks work, ultimately generating a single block
  184. void preUndoBlock();
  185. void postUndoBlock(); // No need to call on UndoException
  186. // Undoes all of a block started, entirely, removing possibility of redo
  187. // No need to call postUndoBlock() after this
  188. // Keep in mind that this will delete created objects, etc.
  189. void cancelUndoBlock();
  190. // This cancels the last undone item without actually "undo"ing anything
  191. // removes redo possibility and deletes any objects.
  192. // @TODO: This hasn't actually been tested yet
  193. void cancelLastUndo();
  194. // Temporarily disables undo; will clear undo buffer if any undoable events occur
  195. void disableUndo();
  196. void enableUndo();
  197. // @TODO: windowIds not all being used as should be
  198. // Various things you can undo
  199. // Throws UndoException if undo space could not be created and user cancelled as a result
  200. // Typically, pass frame windows
  201. void storeUndoWorldStart(int oldStart, Window* srcWin = NULL) throw_Undo;
  202. void storeUndoTile(int tileSetId, int tileNum, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
  203. void storeUndoColl(int tileSetId, int collNum, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
  204. void storeUndoTileGlyph(int tileSetId, int tileNum, int oldWidth, Window* srcWin = NULL) throw_Undo;
  205. void storeUndoTileSize(int tileSetId, int oldWidth, int oldHeight, int oldCount, int oldMaps, SDL_Surface* surface, Uint32* fontWidths, Uint32* collisionMaps, Window* srcWin = NULL) throw_Undo;
  206. void storeUndoTilePerLine(int tileSetId, int oldPerLine, Window* srcWin = NULL) throw_Undo;
  207. void storeUndoTileTrans(int tileSetId, int oldDefaultTransparent, Window* srcWin = NULL) throw_Undo;
  208. // (does fx/coll as well, together as a block, if fx/coll data present)
  209. void storeUndoLayerTile(int layerId, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
  210. // (x/w are in bits; pitch is in bytes; you must ensure x/y/w/h are bound yourself)
  211. void storeUndoLayerTileSelection(Uint8** selectionData, int x, int y, int w, int h, int pitch, int selectXOffs, int selectYOffs, int selectType, Window* srcWin = NULL) throw_Undo;
  212. // (x/w/pitch is in U32s; you must ensure x/y/w/h are bound yourself;
  213. // only call in conjunction with storeUndoLayerTileSelection)
  214. void storeUndoLayerTileTemp(Uint32** data, Uint32** dataExt, Uint32** dataFx, int x, int y, int w, int h, int pitch, Window* srcWin = NULL) throw_Undo;
  215. // Call this before and after any sel/temp change
  216. void storeUndoLayerTileCur(Uint32 layerAffect, Uint32 layerView, Uint32 layerDim, Window* srcWin = NULL) throw_Undo;
  217. void storeUndoLayerSpawnSelection(std::set<int>* selectionData, Window* srcWin = NULL) throw_Undo;
  218. // (doesn't undo any data changes- layer types assumed to be changed only at creation!)
  219. void storeUndoLayerType(int layerId, int oldType, Window* srcWin = NULL) throw_Undo;
  220. void storeUndoLayerSize(int layerId, int oldWidth, int oldHeight, Uint32* data, Uint32* dataExt, Uint32* dataFx, Window* srcWin = NULL) throw_Undo;
  221. void storeUndoLayerExt(int layerId, int oldUsesExt, Window* srcWin = NULL) throw_Undo;
  222. void storeUndoLayerFx(int layerId, int oldUsesFx, Window* srcWin = NULL) throw_Undo;
  223. void storeUndoLayerTileSet(int layerId, int oldTileSet, Window* srcWin = NULL) throw_Undo;
  224. void storeUndoLayerSwap(int sceneId, int layer1, int layer2, Window* srcWin = NULL) throw_Undo;
  225. void storeUndoScriptModify(int id, const std::list<std::string>& source, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
  226. void storeUndoScriptRemove(int id, const std::list<std::string>& source, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
  227. void storeUndoScriptInsert(int id, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
  228. void storeUndoScriptDefault(int id, int animId, int tileId, int subId, Window* srcWin = NULL) throw_Undo;
  229. void storeUndoSpawnMove(int id, int layerId, int oldX, int oldY, Window* srcWin = NULL) throw_Undo;
  230. void storeUndoSpawnSprite(int id, int layerId, int animId, int tileId, int subId, Window* srcWin = NULL) throw_Undo;
  231. void storeUndoSpawnScript(int id, int layerId, int scriptId, Window* srcWin = NULL) throw_Undo;
  232. void storeUndoFolderAdd(int id, SaveLoad* item, int pos, Window* srcWin = NULL) throw_Undo;
  233. void storeUndoFolderRemove(int id, SaveLoad* item, int pos, Window* srcWin = NULL) throw_Undo;
  234. // (assumes surface is 32bit)
  235. void storeUndoPaintSelection(struct SDL_Surface** selectionData, int x, int y, int w, int h, int selectXOffs, int selectYOffs, int selectType, Window* srcWin = NULL) throw_Undo;
  236. // Type is UNDO_FOLDERNAME, UNDO_SPAWNNAME, UNDO_WORLDNAME, UNDO_SCENENAME, UNDO_TILENAME, UNDO_LAYERNAME, UNDO_ANIMGROUPNAME, UNDO_SCRIPTNAME
  237. void storeUndoName(UndoType type, int id, const std::string& oldName, const std::string& newName, Window* srcWin = NULL) throw_Undo;
  238. // Type is UNDO_FOLDERDELETE, UNDO_SCENEDELETE, UNDO_TILEDELETE, UNDO_ANIMGROUPDELETE, UNDO_SCRIPTDELETE
  239. // Object should be the Edit variation; Returns true if undo successsful
  240. // False means you have to delete the object yourself
  241. int storeUndoDelete(UndoType type, int id, void* object, Window* srcWin = NULL) throw_Undo;
  242. int storeUndoLayerDelete(int id, int sceneId, int pos, class LayerEdit* object, Window* srcWin = NULL) throw_Undo;
  243. int storeUndoSpawnDelete(int id, int layerId, class SpawnEdit* object, Window* srcWin = NULL) throw_Undo;
  244. // Type is UNDO_FOLDERCREATE, UNDO_SCENECREATE, UNDO_TILECREATE, UNDO_ANIMGROUPCREATE, UNDO_SCRIPTCREATE
  245. // Returns true if undo stored successful and a later undo will delete the object
  246. // False means you have to delete the object if a cancel/exception occurs
  247. int storeUndoCreate(UndoType type, int id, Window* srcWin = NULL) throw_Undo;
  248. int storeUndoLayerCreate(int id, int sceneId, int pos, Window* srcWin = NULL) throw_Undo;
  249. int storeUndoSpawnCreate(int id, int layerId, Window* srcWin = NULL) throw_Undo;
  250. // Warn user that something cannot be undone; returns if OK, throws if cancel
  251. // If user says OK, undo buffer is cleared!
  252. // If user cancels, any partial undo block is undone!
  253. void warnUser();
  254. };
  255. #endif