123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /* GCSx
- ** UNDO.H
- **
- ** Editor undo and redo functionality
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #ifndef __GCSx_UNDO_H_
- #define __GCSx_UNDO_H_
- class UndoBuffer {
- public:
- enum UndoType {
- UNDO_EMPTY = 0, // An empty chunk at end of undo buffer at all times
- UNDO_PAINTSEL, // Change of selection; Data1-2 is selection x/y offs, 3 is selection type
- // Only valid if paint window still open
- // item1 points to where selection surface is stored
-
- UNDO_WORLDNAME,
- UNDO_SCENENAME, // Name changes-
- UNDO_TILENAME, // Y size 1, X size length of string; X is actual length
- UNDO_LAYERNAME, // Size is larger of current or new name
- UNDO_ANIMGROUPNAME,
- UNDO_SCRIPTNAME,
- UNDO_SPAWNNAME, // Spawn includes layer in subid (0 for non-scene spawn)
- UNDO_FOLDERNAME,
-
- UNDO_SCENEDELETE, // Deletions-
- UNDO_TILEDELETE, // object is kept in item1
- UNDO_LAYERDELETE, // Layer includes scene in subid and pos in x
- UNDO_ANIMGROUPDELETE,
- UNDO_SCRIPTDELETE,
- UNDO_SPAWNDELETE, // Spawn includes layer in subid (0 for non-scene spawn)
- UNDO_FOLDERDELETE,
- UNDO_SCENECREATE, // Creations-
- UNDO_TILECREATE, // no object, id is only data
- UNDO_LAYERCREATE, // Layer includes scene in subid and pos in x
- UNDO_ANIMGROUPCREATE,
- UNDO_SCRIPTCREATE,
- UNDO_SPAWNCREATE, // Spawn includes layer in subid (0 for non-scene spawn)
- UNDO_FOLDERCREATE,
-
- UNDO_WORLDSTART, // X is old id
-
- UNDO_FOLDERADD, // subid item added, data1 blocktype, data2 pos
- UNDO_FOLDERREMOVE,// subid item erase, data1 blocktype, data2 pos
-
- // All spawn undos include layer in subid (0 for non-scene spawn)
- UNDO_SPAWNMOVE, // X/Y are old position
- UNDO_SPAWNSPRITE, // data1-3 are old data (ids)
- UNDO_SPAWNSCRIPT, // data1 is old script (id)
-
- // For these, changes are stored as a pointer to a list of strings
- // Undo data itself is 3 TextPoint structures (insertion/sel/selend)
- UNDO_SCRIPTINSERT,// Inserting one or more lines of code- xpos where, ypos # of lines
- UNDO_SCRIPTREMOVE,// Deleting one or more lines (same)
- UNDO_SCRIPTMODIFY,// Modifying one or more lines (same)
- UNDO_SCRIPTDEFAULT,
- UNDO_TILE, // A change to a tile, represented as a blit
- UNDO_TILECOLL, // Change to collision map (a blit also)
- UNDO_TILESIZE, // Sizing/count change, old surface/etc stored
- // X/Y are width/height, data1 is count, data2 maps count
- // item1 surface item2 fontwidths item3 collmaps
- UNDO_TILEPERLINE, // X is old value
- UNDO_TILETRANS, // X is old value
- UNDO_TILEGLYPH, // X is old value
- UNDO_LAYERMOVE, // id is scene; x/y are the two positions swapped
- UNDO_LAYERTILE, // A change to a tile layer
- UNDO_LAYERTILEEXT,//A change to a tile layer extended data
- UNDO_LAYERTILEFX, // A change to a tile layer effects data
- UNDO_LAYERTYPE, // X is old type
- UNDO_LAYERSIZE, // Sizing change, old data/fx stored
- // X/Y are width/height
- // item1 data item2 fx item3 coll
- UNDO_LAYEREXT, // X is previous Ext setting (UNDO_LAYERSIZE stores data change)
- UNDO_LAYERFX, // X is previous Fx setting (UNDO_LAYERSIZE stores data change)
- UNDO_LAYERTILESET,// X is previous tileset id
- UNDO_LAYERTILECUR,// Data1 = layersAffect, Data2 = view, Data3 = dim
- UNDO_LAYERTILETMP,// A change to tile layer data within a window, as part of selection
- // (item1 points to where data is stored; item2 to fx; item3 coll)
- // (layers are just "reset", not exchanged, when this is encountered)
- // h is doubled if fx or coll present; tripled for both (item2/item3 not null)
- // must ALWAYS be preceded/followed by the next...
- UNDO_LAYERTILESEL,// Change of selection; Data1-2 is selection x/y offs, 3 is selection type
- // x is in bytes; width rounded to dword
- // Actual width (in bytes) is in id
- // Pitch (in bytes) is in subid
- // Only valid if tile layer edit window still open
- // item1 points to where selection data is stored
- UNDO_LAYERSPAWNSEL,// Change of spawns selected
- // item1 points to set<int> where spawn selection is stored
- // item2 points to a newly allocated set<int> storing undo data
- };
- enum {
- // Undo buffer- sizes in K
- UNDO_DEFAULT_BUFFER = 8192,
- UNDO_MAX_BUFFER = 65536,
- };
-
- #ifndef NDEBUG
- static void setUndoThreshold(int level);
- #endif
- private:
- enum {
- // OR in to denote this chunk and the previous are one operation
- UNDO_MERGE = 128,
- };
-
- // What world we apply to
- class WorldEdit* world;
-
- // Undo buffer
- int requestedSize; // Requested size in K
- int undoSizeAlloc; // Size allocated
- Uint32* undoBuffer; // Allocated data
- int undoPos; // Current undo position- place next undo here or read redo from previous
-
- #ifndef NDEBUG
- // Number of actions before we fail further undos; < 0 to disable feature
- static int undoThresh;
- #endif
-
- // If we're currently undoing/redoing, which throttles any other undo/redo attempts
- // as we're taking care of it already
- int inUndo;
- int suspendUndo;
-
- // Undo block level and whether we're still waiting for our first item
- int undoBlock;
- int undoBlockDidFirst;
- int undoBlockFirstPos;
- int undoNonUndoable; // If true, user was warned and chose to go ahead
-
- // Undo data chunk header format-
- struct UndoHeader {
- int sourceWindow; // editor window this originated from
- int prevChunkSize; // 0 if first chunk
- UndoType type;
- int id; // Id of item affected
- int subid; // Sub id, such as tile number affected
- int xSize;
- int ySize;
- int xPos;
- int yPos;
- int data1; // Data specific to chunk
- int data2;
- int data3;
- void* item1; // An item that was deleted or swapped goes here
- void* item2; // These are cleared when the undo chunks are discarded
- void* item3;
- };
- static int undoHeaderSize; // Size in Uint32s
-
- // When you undo, the chunk becomes a redo block, swapping new data for old
- // Same format, it's a redo chunk because it's after the undopos pointer instead of before
-
- // Returns pointer to write data if space is now available (empty chunk is
- // moved as needed) NULL if space could not be made available and undo is being skipped
- 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;
- // If undo block contains pointers to something, frees it up
- void deleteUndoBlock(int offset);
- // Clears all redo blocks after the current spot
- void clearRedo();
-
- // Some internal undo-block-writing functions
- void storeUndoScript(UndoType type, int id, const std::list<std::string>& source, int lineNum, int count, EditBox* editbox, Window* srcWin) throw_Undo;
-
- public:
- UndoBuffer(class WorldEdit* myWorld);
- ~UndoBuffer();
-
- // Size of 0 = no undo; changing size clears buffer!
- // Size is in K; clips to valid range
- int bufferSize() const { return requestedSize; }
- int bufferSize(int requested);
-
- int undoAvailable() const;
- void undoPerform(int doRedo = 0);
-
- int redoAvailable() const;
- void redoPerform();
- // Call if you do any action that you choose not to make undoable
- void clearUndo();
-
- // Call before and after one or more undos to "link" them all as one item
- // Can also be used to allow use of cancelUndoBlock()
- // If the entire block doesn't fit in the buffer, user will be warned one time;
- // if user cancels, anything done so far is undone (without redo) and UndoException is
- // thrown; if user chooses to continue or a non-undoable item occurs, entire block
- // will be non-undoable; nested blocks work, ultimately generating a single block
- void preUndoBlock();
- void postUndoBlock(); // No need to call on UndoException
- // Undoes all of a block started, entirely, removing possibility of redo
- // No need to call postUndoBlock() after this
- // Keep in mind that this will delete created objects, etc.
- void cancelUndoBlock();
- // This cancels the last undone item without actually "undo"ing anything
- // removes redo possibility and deletes any objects.
- // @TODO: This hasn't actually been tested yet
- void cancelLastUndo();
- // Temporarily disables undo; will clear undo buffer if any undoable events occur
- void disableUndo();
- void enableUndo();
-
- // @TODO: windowIds not all being used as should be
-
- // Various things you can undo
- // Throws UndoException if undo space could not be created and user cancelled as a result
- // Typically, pass frame windows
- void storeUndoWorldStart(int oldStart, Window* srcWin = NULL) throw_Undo;
- void storeUndoTile(int tileSetId, int tileNum, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
- void storeUndoColl(int tileSetId, int collNum, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
- void storeUndoTileGlyph(int tileSetId, int tileNum, int oldWidth, Window* srcWin = NULL) throw_Undo;
- void storeUndoTileSize(int tileSetId, int oldWidth, int oldHeight, int oldCount, int oldMaps, SDL_Surface* surface, Uint32* fontWidths, Uint32* collisionMaps, Window* srcWin = NULL) throw_Undo;
- void storeUndoTilePerLine(int tileSetId, int oldPerLine, Window* srcWin = NULL) throw_Undo;
- void storeUndoTileTrans(int tileSetId, int oldDefaultTransparent, Window* srcWin = NULL) throw_Undo;
- // (does fx/coll as well, together as a block, if fx/coll data present)
- void storeUndoLayerTile(int layerId, int x, int y, int w, int h, Window* srcWin = NULL) throw_Undo;
- // (x/w are in bits; pitch is in bytes; you must ensure x/y/w/h are bound yourself)
- 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;
- // (x/w/pitch is in U32s; you must ensure x/y/w/h are bound yourself;
- // only call in conjunction with storeUndoLayerTileSelection)
- void storeUndoLayerTileTemp(Uint32** data, Uint32** dataExt, Uint32** dataFx, int x, int y, int w, int h, int pitch, Window* srcWin = NULL) throw_Undo;
- // Call this before and after any sel/temp change
- void storeUndoLayerTileCur(Uint32 layerAffect, Uint32 layerView, Uint32 layerDim, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerSpawnSelection(std::set<int>* selectionData, Window* srcWin = NULL) throw_Undo;
- // (doesn't undo any data changes- layer types assumed to be changed only at creation!)
- void storeUndoLayerType(int layerId, int oldType, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerSize(int layerId, int oldWidth, int oldHeight, Uint32* data, Uint32* dataExt, Uint32* dataFx, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerExt(int layerId, int oldUsesExt, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerFx(int layerId, int oldUsesFx, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerTileSet(int layerId, int oldTileSet, Window* srcWin = NULL) throw_Undo;
- void storeUndoLayerSwap(int sceneId, int layer1, int layer2, Window* srcWin = NULL) throw_Undo;
- void storeUndoScriptModify(int id, const std::list<std::string>& source, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
- void storeUndoScriptRemove(int id, const std::list<std::string>& source, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
- void storeUndoScriptInsert(int id, int lineNum, int count, class EditBox* editbox, Window* srcWin = NULL) throw_Undo;
- void storeUndoScriptDefault(int id, int animId, int tileId, int subId, Window* srcWin = NULL) throw_Undo;
- void storeUndoSpawnMove(int id, int layerId, int oldX, int oldY, Window* srcWin = NULL) throw_Undo;
- void storeUndoSpawnSprite(int id, int layerId, int animId, int tileId, int subId, Window* srcWin = NULL) throw_Undo;
- void storeUndoSpawnScript(int id, int layerId, int scriptId, Window* srcWin = NULL) throw_Undo;
- void storeUndoFolderAdd(int id, SaveLoad* item, int pos, Window* srcWin = NULL) throw_Undo;
- void storeUndoFolderRemove(int id, SaveLoad* item, int pos, Window* srcWin = NULL) throw_Undo;
- // (assumes surface is 32bit)
- 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;
- // Type is UNDO_FOLDERNAME, UNDO_SPAWNNAME, UNDO_WORLDNAME, UNDO_SCENENAME, UNDO_TILENAME, UNDO_LAYERNAME, UNDO_ANIMGROUPNAME, UNDO_SCRIPTNAME
- void storeUndoName(UndoType type, int id, const std::string& oldName, const std::string& newName, Window* srcWin = NULL) throw_Undo;
- // Type is UNDO_FOLDERDELETE, UNDO_SCENEDELETE, UNDO_TILEDELETE, UNDO_ANIMGROUPDELETE, UNDO_SCRIPTDELETE
- // Object should be the Edit variation; Returns true if undo successsful
- // False means you have to delete the object yourself
- int storeUndoDelete(UndoType type, int id, void* object, Window* srcWin = NULL) throw_Undo;
- int storeUndoLayerDelete(int id, int sceneId, int pos, class LayerEdit* object, Window* srcWin = NULL) throw_Undo;
- int storeUndoSpawnDelete(int id, int layerId, class SpawnEdit* object, Window* srcWin = NULL) throw_Undo;
- // Type is UNDO_FOLDERCREATE, UNDO_SCENECREATE, UNDO_TILECREATE, UNDO_ANIMGROUPCREATE, UNDO_SCRIPTCREATE
- // Returns true if undo stored successful and a later undo will delete the object
- // False means you have to delete the object if a cancel/exception occurs
- int storeUndoCreate(UndoType type, int id, Window* srcWin = NULL) throw_Undo;
- int storeUndoLayerCreate(int id, int sceneId, int pos, Window* srcWin = NULL) throw_Undo;
- int storeUndoSpawnCreate(int id, int layerId, Window* srcWin = NULL) throw_Undo;
-
- // Warn user that something cannot be undone; returns if OK, throws if cancel
- // If user says OK, undo buffer is cleared!
- // If user cancels, any partial undo block is undone!
- void warnUser();
- };
- #endif
|