From fb77b9bd5d846b3c34b1eeebce94e09654f539ee Mon Sep 17 00:00:00 2001 From: Explos Date: Fri, 4 Aug 2023 20:50:02 +0100 Subject: [PATCH] Undo redo (#68) * Remove unnecessary editionmode baseclass * Rename ObjectsEditionMode to EditManager * Add undostack to LevelEditorWindow * Implement undo actions for layer toggles * Prevent resize object on placement if not selected * Implement undo for sprite interaction toggle * Implement undo for path interaction toggle * Implement undo for entrance interaction toggle * Implement undo for location interaction toggle * Cleanup * Add raise undo command * Rename commands * Add lower undo command * Add raise layer undo command * Add lower layer undo command * Add delete undo command * Implement insertion undo commands * Implement undo for cloning * Undo for object movement * Clear selection on Undo * Implement Area Editor Undo * Implement objectswap undo * Implement undo for tileset swap * Implement undo for spritedata * Resolve multiple memory leaks * Fix bug with tileset picker * Implement undo for entrance editor * Implement undo for zone editor * Implement undo for location editor * Implement undo for path editor * Implement undo for progresspath editor * Cleanup project structure * Update editor status via edit history * Implement settings dialog --- CoinKiller.pro | 201 +++-- areaeditorwidget.h | 59 -- coinkiller_data/icons/redo.png | Bin 0 -> 410 bytes coinkiller_data/icons/undo.png | Bin 0 -> 409 bytes coinkiller_data/spritedata.xml | 765 +++++++++++------- ctpk.cpp | 1 + ctpk.h | 2 +- editionmode.h | 65 -- eventeditorwidget.cpp | 96 --- eventeditorwidget.h | 32 - .../externalfile.cpp | 0 externalfile.h => filesystem/externalfile.h | 0 .../externalfilesystem.cpp | 0 .../externalfilesystem.h | 0 filebase.cpp => filesystem/filebase.cpp | 0 filebase.h => filesystem/filebase.h | 0 filesystem.h => filesystem/filesystem.h | 0 .../filesystembase.h | 0 memoryfile.cpp => filesystem/memoryfile.cpp | 0 memoryfile.h => filesystem/memoryfile.h | 0 .../sarcfilesystem.cpp | 3 +- .../sarcfilesystem.h | 0 game.cpp | 38 +- game.h | 2 +- level.cpp | 162 ++-- level.h | 27 +- .../areaeditorwidget.cpp | 87 +- leveleditor/areaeditorwidget.h | 61 ++ leveleditor/commands/bgdatcommands.cpp | 24 + leveleditor/commands/bgdatcommands.h | 28 + leveleditor/commands/commandids.h | 19 + leveleditor/commands/editorcommands.cpp | 107 +++ leveleditor/commands/editorcommands.h | 82 ++ leveleditor/commands/entrancecommands.cpp | 150 ++++ leveleditor/commands/entrancecommands.h | 146 ++++ leveleditor/commands/levelcommands.cpp | 582 +++++++++++++ leveleditor/commands/levelcommands.h | 392 +++++++++ leveleditor/commands/locationcommands.cpp | 20 + leveleditor/commands/locationcommands.h | 26 + leveleditor/commands/objectcommands.cpp | 123 +++ leveleditor/commands/objectcommands.h | 88 ++ leveleditor/commands/pathcommands.cpp | 77 ++ leveleditor/commands/pathcommands.h | 73 ++ leveleditor/commands/pathnodecommands.cpp | 100 +++ leveleditor/commands/pathnodecommands.h | 101 +++ leveleditor/commands/progresspathcommands.cpp | 63 ++ leveleditor/commands/progresspathcommands.h | 58 ++ leveleditor/commands/setvalue.h | 70 ++ leveleditor/commands/spritecommands.cpp | 95 +++ leveleditor/commands/spritecommands.h | 91 +++ leveleditor/commands/zonebgcommands.cpp | 86 ++ leveleditor/commands/zonebgcommands.h | 86 ++ leveleditor/commands/zoneboundingcommands.cpp | 101 +++ leveleditor/commands/zoneboundingcommands.h | 102 +++ leveleditor/commands/zonecommands.cpp | 116 +++ leveleditor/commands/zonecommands.h | 116 +++ .../editmanager.cpp | 634 ++++++++++----- .../editmanager.h | 87 +- .../entranceeditorwidget.cpp | 84 +- .../entranceeditorwidget.h | 31 +- leveleditor/eventeditorwidget.cpp | 112 +++ leveleditor/eventeditorwidget.h | 36 + leveleditor/layermask.h | 15 + .../leveleditorwindow.cpp | 606 ++++++++------ .../leveleditorwindow.h | 79 +- .../leveleditorwindow.ui | 69 +- .../levelminimap.cpp | 0 levelminimap.h => leveleditor/levelminimap.h | 0 levelview.cpp => leveleditor/levelview.cpp | 162 +--- levelview.h => leveleditor/levelview.h | 29 +- .../locationeditorwidget.cpp | 19 +- .../locationeditorwidget.h | 7 +- .../patheditorwidget.cpp | 95 +-- .../patheditorwidget.h | 8 +- .../progresspatheditorwidget.cpp | 30 +- .../progresspatheditorwidget.h | 7 +- leveleditor/settingsdialog.cpp | 108 +++ leveleditor/settingsdialog.h | 43 + leveleditor/settingsdialog.ui | 189 +++++ .../spriteeditorwidget.cpp | 219 +++-- .../spriteeditorwidget.h | 56 +- .../spriteidswidget.cpp | 0 .../spriteidswidget.h | 0 leveleditor/tilesetpalette.cpp | 243 ++++++ leveleditor/tilesetpalette.h | 45 ++ .../zoneeditorwidget.cpp | 264 +++--- .../zoneeditorwidget.h | 31 +- levelmanager.cpp | 2 +- mainwindow.cpp | 38 +- objectrenderer.cpp | 1 + objectrenderer.h | 54 +- objects.cpp | 29 +- objects.h | 53 +- .../translations/English.ts | 0 German.ts => resource/translations/German.ts | 0 .../translations/Italian.ts | 0 sarcexplorerwindow.h | 2 +- settingsmanager.cpp | 113 +-- settingsmanager.h | 22 +- tileset.cpp | 2 + tileset.h | 2 +- .../tileseteditorwidgets.cpp | 0 .../tileseteditorwidgets.h | 0 .../tileseteditorwindow.cpp | 0 .../tileseteditorwindow.h | 0 .../tileseteditorwindow.ui | 0 tilesetpalette.cpp | 227 ------ tilesetpalette.h | 47 -- unitsconvert.cpp | 3 +- 109 files changed, 6261 insertions(+), 2365 deletions(-) delete mode 100644 areaeditorwidget.h create mode 100644 coinkiller_data/icons/redo.png create mode 100644 coinkiller_data/icons/undo.png delete mode 100644 editionmode.h delete mode 100644 eventeditorwidget.cpp delete mode 100644 eventeditorwidget.h rename externalfile.cpp => filesystem/externalfile.cpp (100%) rename externalfile.h => filesystem/externalfile.h (100%) rename externalfilesystem.cpp => filesystem/externalfilesystem.cpp (100%) rename externalfilesystem.h => filesystem/externalfilesystem.h (100%) rename filebase.cpp => filesystem/filebase.cpp (100%) rename filebase.h => filesystem/filebase.h (100%) rename filesystem.h => filesystem/filesystem.h (100%) rename filesystembase.h => filesystem/filesystembase.h (100%) rename memoryfile.cpp => filesystem/memoryfile.cpp (100%) rename memoryfile.h => filesystem/memoryfile.h (100%) rename sarcfilesystem.cpp => filesystem/sarcfilesystem.cpp (99%) rename sarcfilesystem.h => filesystem/sarcfilesystem.h (100%) rename areaeditorwidget.cpp => leveleditor/areaeditorwidget.cpp (59%) create mode 100644 leveleditor/areaeditorwidget.h create mode 100644 leveleditor/commands/bgdatcommands.cpp create mode 100644 leveleditor/commands/bgdatcommands.h create mode 100644 leveleditor/commands/commandids.h create mode 100644 leveleditor/commands/editorcommands.cpp create mode 100644 leveleditor/commands/editorcommands.h create mode 100644 leveleditor/commands/entrancecommands.cpp create mode 100644 leveleditor/commands/entrancecommands.h create mode 100644 leveleditor/commands/levelcommands.cpp create mode 100644 leveleditor/commands/levelcommands.h create mode 100644 leveleditor/commands/locationcommands.cpp create mode 100644 leveleditor/commands/locationcommands.h create mode 100644 leveleditor/commands/objectcommands.cpp create mode 100644 leveleditor/commands/objectcommands.h create mode 100644 leveleditor/commands/pathcommands.cpp create mode 100644 leveleditor/commands/pathcommands.h create mode 100644 leveleditor/commands/pathnodecommands.cpp create mode 100644 leveleditor/commands/pathnodecommands.h create mode 100644 leveleditor/commands/progresspathcommands.cpp create mode 100644 leveleditor/commands/progresspathcommands.h create mode 100644 leveleditor/commands/setvalue.h create mode 100644 leveleditor/commands/spritecommands.cpp create mode 100644 leveleditor/commands/spritecommands.h create mode 100644 leveleditor/commands/zonebgcommands.cpp create mode 100644 leveleditor/commands/zonebgcommands.h create mode 100644 leveleditor/commands/zoneboundingcommands.cpp create mode 100644 leveleditor/commands/zoneboundingcommands.h create mode 100644 leveleditor/commands/zonecommands.cpp create mode 100644 leveleditor/commands/zonecommands.h rename objectseditionmode.cpp => leveleditor/editmanager.cpp (65%) rename objectseditionmode.h => leveleditor/editmanager.h (56%) rename entranceeditorwidget.cpp => leveleditor/entranceeditorwidget.cpp (69%) rename entranceeditorwidget.h => leveleditor/entranceeditorwidget.h (75%) create mode 100644 leveleditor/eventeditorwidget.cpp create mode 100644 leveleditor/eventeditorwidget.h create mode 100644 leveleditor/layermask.h rename leveleditorwindow.cpp => leveleditor/leveleditorwindow.cpp (56%) rename leveleditorwindow.h => leveleditor/leveleditorwindow.h (72%) rename leveleditorwindow.ui => leveleditor/leveleditorwindow.ui (92%) rename levelminimap.cpp => leveleditor/levelminimap.cpp (100%) rename levelminimap.h => leveleditor/levelminimap.h (100%) rename levelview.cpp => leveleditor/levelview.cpp (87%) rename levelview.h => leveleditor/levelview.h (81%) rename locationeditorwidget.cpp => leveleditor/locationeditorwidget.cpp (81%) rename locationeditorwidget.h => leveleditor/locationeditorwidget.h (82%) rename patheditorwidget.cpp => leveleditor/patheditorwidget.cpp (67%) rename patheditorwidget.h => leveleditor/patheditorwidget.h (90%) rename progresspatheditorwidget.cpp => leveleditor/progresspatheditorwidget.cpp (72%) rename progresspatheditorwidget.h => leveleditor/progresspatheditorwidget.h (85%) create mode 100644 leveleditor/settingsdialog.cpp create mode 100644 leveleditor/settingsdialog.h create mode 100644 leveleditor/settingsdialog.ui rename spriteeditorwidget.cpp => leveleditor/spriteeditorwidget.cpp (75%) rename spriteeditorwidget.h => leveleditor/spriteeditorwidget.h (76%) rename spriteidswidget.cpp => leveleditor/spriteidswidget.cpp (100%) rename spriteidswidget.h => leveleditor/spriteidswidget.h (100%) create mode 100644 leveleditor/tilesetpalette.cpp create mode 100644 leveleditor/tilesetpalette.h rename zoneeditorwidget.cpp => leveleditor/zoneeditorwidget.cpp (74%) rename zoneeditorwidget.h => leveleditor/zoneeditorwidget.h (86%) rename English.ts => resource/translations/English.ts (100%) rename German.ts => resource/translations/German.ts (100%) rename Italian.ts => resource/translations/Italian.ts (100%) rename tileseteditorwidgets.cpp => tileseteditor/tileseteditorwidgets.cpp (100%) rename tileseteditorwidgets.h => tileseteditor/tileseteditorwidgets.h (100%) rename tileseteditorwindow.cpp => tileseteditor/tileseteditorwindow.cpp (100%) rename tileseteditorwindow.h => tileseteditor/tileseteditorwindow.h (100%) rename tileseteditorwindow.ui => tileseteditor/tileseteditorwindow.ui (100%) delete mode 100644 tilesetpalette.cpp delete mode 100644 tilesetpalette.h diff --git a/CoinKiller.pro b/CoinKiller.pro index 663199d4..e1cdaa5a 100644 --- a/CoinKiller.pro +++ b/CoinKiller.pro @@ -48,103 +48,138 @@ isEmpty(CK_VERSION) { DEFINES += CK_VERSION=\\\"$$CK_VERSION\\\" -SOURCES += main.cpp\ - eventeditorwidget.cpp \ - mainwindow.cpp \ - newleveldialog.cpp \ - rg_etc1.cpp \ - sarcfilesystem.cpp \ - externalfilesystem.cpp \ - externalfile.cpp \ - memoryfile.cpp \ - filebase.cpp \ - leveleditorwindow.cpp \ - levelview.cpp \ +SOURCES += \ + filesystem/externalfile.cpp \ + filesystem/externalfilesystem.cpp \ + filesystem/filebase.cpp \ + filedownloader.cpp \ + filesystem/memoryfile.cpp \ + filesystem/sarcfilesystem.cpp \ + leveleditor/commands/bgdatcommands.cpp \ + leveleditor/commands/editorcommands.cpp \ + leveleditor/commands/entrancecommands.cpp \ + leveleditor/commands/levelcommands.cpp \ + leveleditor/commands/locationcommands.cpp \ + leveleditor/commands/objectcommands.cpp \ + leveleditor/commands/pathcommands.cpp \ + leveleditor/commands/pathnodecommands.cpp \ + leveleditor/commands/progresspathcommands.cpp \ + leveleditor/commands/spritecommands.cpp \ + leveleditor/commands/zonebgcommands.cpp \ + leveleditor/commands/zoneboundingcommands.cpp \ + leveleditor/commands/zonecommands.cpp \ + leveleditor/areaeditorwidget.cpp \ + leveleditor/editmanager.cpp \ + leveleditor/entranceeditorwidget.cpp \ + leveleditor/eventeditorwidget.cpp \ + leveleditor/leveleditorwindow.cpp \ + leveleditor/levelminimap.cpp \ + leveleditor/levelview.cpp \ + leveleditor/locationeditorwidget.cpp \ + leveleditor/patheditorwidget.cpp \ + leveleditor/progresspatheditorwidget.cpp \ + leveleditor/settingsdialog.cpp \ + leveleditor/spriteeditorwidget.cpp \ + leveleditor/spriteidswidget.cpp \ + leveleditor/tilesetpalette.cpp \ + leveleditor/zoneeditorwidget.cpp \ + tileseteditor/tileseteditorwidgets.cpp \ + tileseteditor/tileseteditorwindow.cpp \ + clickablelabel.cpp \ ctpk.cpp \ - level.cpp \ - tileset.cpp \ game.cpp \ - objects.cpp \ - unitsconvert.cpp \ - objectrenderer.cpp \ - tileseteditorwindow.cpp \ - tileseteditorwidgets.cpp \ - spritedata.cpp \ - tilesetpalette.cpp \ - entranceeditorwidget.cpp \ - spriteeditorwidget.cpp \ - areaeditorwidget.cpp \ - zoneeditorwidget.cpp \ - locationeditorwidget.cpp \ + imagecache.cpp \ + level.cpp \ levelmanager.cpp \ - patheditorwidget.cpp \ - progresspatheditorwidget.cpp \ - settingsmanager.cpp \ - filedownloader.cpp \ - levelminimap.cpp \ - objectseditionmode.cpp \ - sarcexplorerwindow.cpp \ + main.cpp\ + mainwindow.cpp \ + newleveldialog.cpp \ newtilesetdialog.cpp \ - imagecache.cpp \ - spriteidswidget.cpp \ - clickablelabel.cpp + objectrenderer.cpp \ + objects.cpp \ + rg_etc1.cpp \ + sarcexplorerwindow.cpp \ + settingsmanager.cpp \ + spritedata.cpp \ + tileset.cpp \ + unitsconvert.cpp -HEADERS += mainwindow.h \ +HEADERS += \ + filesystem/externalfile.h \ + filesystem/externalfilesystem.h \ + filesystem/filebase.h \ + filesystem/filesystem.h \ + filesystem/filesystembase.h \ + filesystem/memoryfile.h \ + filesystem/sarcfilesystem.h \ + leveleditor/commands/bgdatcommands.h \ + leveleditor/commands/commandids.h \ + leveleditor/commands/editorcommands.h \ + leveleditor/commands/entrancecommands.h \ + leveleditor/commands/levelcommands.h \ + leveleditor/commands/locationcommands.h \ + leveleditor/commands/objectcommands.h \ + leveleditor/commands/pathcommands.h \ + leveleditor/commands/pathnodecommands.h \ + leveleditor/commands/progresspathcommands.h \ + leveleditor/commands/setvalue.h \ + leveleditor/commands/spritecommands.h \ + leveleditor/commands/zonebgcommands.h \ + leveleditor/commands/zoneboundingcommands.h \ + leveleditor/commands/zonecommands.h \ + leveleditor/areaeditorwidget.h \ + leveleditor/editmanager.h \ + leveleditor/entranceeditorwidget.h \ + leveleditor/eventeditorwidget.h \ + leveleditor/layermask.h \ + leveleditor/leveleditorwindow.h \ + leveleditor/levelminimap.h \ + leveleditor/levelview.h \ + leveleditor/locationeditorwidget.h \ + leveleditor/patheditorwidget.h \ + leveleditor/progresspatheditorwidget.h \ + leveleditor/settingsdialog.h \ + leveleditor/spriteeditorwidget.h \ + leveleditor/spriteidswidget.h \ + leveleditor/tilesetpalette.h \ + leveleditor/zoneeditorwidget.h \ + tileseteditor/tileseteditorwidgets.h \ + tileseteditor/tileseteditorwindow.h \ + clickablelabel.h \ crc32.h \ - eventeditorwidget.h \ - filesystembase.h \ - filebase.h \ - newleveldialog.h \ - sarcfilesystem.h \ - externalfilesystem.h \ - externalfile.h \ - shit.h \ - memoryfile.h \ - filesystem.h \ - leveleditorwindow.h \ - levelview.h \ ctpk.h \ - level.h \ - tileset.h \ + filedownloader.h \ game.h \ - objects.h \ - unitsconvert.h \ - objectrenderer.h \ - tileseteditorwindow.h \ - tileseteditorwidgets.h \ + imagecache.h \ is.h \ - editionmode.h \ - spritedata.h \ - tilesetpalette.h \ - entranceeditorwidget.h \ - spriteeditorwidget.h \ - areaeditorwidget.h \ - zoneeditorwidget.h \ + level.h \ levelmanager.h \ - patheditorwidget.h \ - progresspatheditorwidget.h \ - locationeditorwidget.h \ - settingsmanager.h \ - filedownloader.h \ - levelminimap.h \ - objectseditionmode.h \ - sarcexplorerwindow.h \ + mainwindow.h \ + newleveldialog.h \ newtilesetdialog.h \ - imagecache.h \ - spriteidswidget.h \ - clickablelabel.h \ - windowbase.h \ + objectrenderer.h \ + objects.h \ rg_etc1.h \ + sarcexplorerwindow.h \ + settingsmanager.h \ + shit.h \ + spritedata.h \ + tileset.h \ + unitsconvert.h \ + windowbase.h -FORMS += mainwindow.ui \ - leveleditorwindow.ui \ +FORMS += \ + leveleditor/leveleditorwindow.ui \ + leveleditor/settingsdialog.ui \ + tileseteditor/tileseteditorwindow.ui \ + mainwindow.ui \ newleveldialog.ui \ - tileseteditorwindow.ui \ - sarcexplorerwindow.ui \ - newtilesetdialog.ui + newtilesetdialog.ui \ + sarcexplorerwindow.ui -TRANSLATIONS += English.ts \ - German.ts \ - Italian.ts +TRANSLATIONS += \ + resource/translations/English.ts \ + resource/translations/German.ts \ + resource/translations/Italian.ts CONFIG += c++17 diff --git a/areaeditorwidget.h b/areaeditorwidget.h deleted file mode 100644 index 8a4c855e..00000000 --- a/areaeditorwidget.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef AREAEDITORWIDGET_H -#define AREAEDITORWIDGET_H - -#include "level.h" -#include "eventeditorwidget.h" - -#include -#include -#include -#include -#include -#include -#include - -class AreaEditorWidget : public QWidget -{ - Q_OBJECT -public: - AreaEditorWidget(Level* level, Game* game); - -signals: - void updateLevelView(); - void relaodTilesetPicker(); - void editMade(); -private: - Level* level; - Game* game; - - QSpinBox* timeLimit; - QSpinBox* coinRushtimeLimit; - QSpinBox* levelEntranceID; - QComboBox* specialLevelFlag1; - QComboBox* specialLevelFlag2; - QSpinBox* unk1Editor; - QSpinBox* unk2Editor; - - EventEditorWidget* eventEditor; - - QMap specialLevelFlags1; - QMap specialLevelFlags2; - - bool handleChanges = true; - void updateInfo(); - - class HorLine : public QFrame { public: HorLine() { setFrameStyle(QFrame::HLine | QFrame::Sunken); } }; - -private slots: - void handleTimeLimitChange(int timeLimitVal); - void handleCoinRushTimeLimitChange(int timeLimitVal); - void handleSpecialLevelFlag1Change(QString text); - void handleSpecialLevelFlag2Change(QString text); - void handleUnk1Change(int unk); - void handleUnk2Change(int unk); - void handlelevelEntranceIDChanged(int id); - void passEditMade() { emit editMade(); } - -}; - -#endif // AREAEDITORWIDGET_H diff --git a/coinkiller_data/icons/redo.png b/coinkiller_data/icons/redo.png new file mode 100644 index 0000000000000000000000000000000000000000..520142279f29c482a5fb2a10e8b5b5e89610052c GIT binary patch literal 410 zcmV;L0cHM)P)j0n$Bx1~@nI4U$u&>D1(hhcb^yPC#;z3)$=8kAY!b z{y&_zW*Mw;$-xy$?htFInmCyQuzXD}UbI9X^9zk9F57tz>k_YI;Ce6%*7sV)E46^+ z+?_FN2kH~;_u07*qoM6N<$ Ef^Ax`g#Z8m literal 0 HcmV?d00001 diff --git a/coinkiller_data/icons/undo.png b/coinkiller_data/icons/undo.png new file mode 100644 index 0000000000000000000000000000000000000000..1380ef97a57b6f67df28ee1abfb4ead1dc891563 GIT binary patch literal 409 zcmV;K0cQS*P)UZNrzIx7kayK*mCHkq~V+L_zjFFEz^n>lCB0695nD3u0abp@Gl z8jXVF0whP_!>vq%j09)dhWBXeMVatJ(Pr_mQ?5piYRc?*ST5ZFwyLfXITAZHSfX;wz~L-m0UyNawr=Ck~&Of$xnDk z0eJ=KD!gLb2?! - - Strongest - Strong - Weak - Weakest + + Strongest (7 Blocks) + Strong (6 Blocks) + Weak (5 Blocks) + Weakest (4 Blocks) + Large Bubbles (4 Blocks) Pipe Up @@ -84,7 +85,7 @@ Flies when directly under - + One Two @@ -132,85 +133,78 @@ - + No Movement - Up Normal - Up Fast - Up Faster - Up Slow - Up Slowest - Up Slower - Up Normal + Up - Normal + Up - Fast + Up - Faster + Up - Slow + Up - Slowest + Up - Slower + Up - Normal No Movement - Down Normal - Down Fast - Down Faster - Down Slow - Down Slowest - Down Slower - Down Normal + Down - Normal + Down - Fast + Down - Faster + Down - Slow + Down - Slowest + Down - Slower + Down - Normal - - Normal - Rises and Lowers - Unknown 4 - Unknown 5 - Topless Liquid - + + + - + No Movement - Up Normal - Up Fast - Up Faster - Up Slow - Up Slowest - Up Slower - Up Normal + Up - Normal + Up - Fast + Up - Faster + Up - Slow + Up - Slowest + Up - Slower + Up - Normal No Movement - Down Normal - Down Fast - Down Faster - Down Slow - Down Slowest - Down Slower - Down Normal + Down - Normal + Down - Fast + Down - Faster + Down - Slow + Down - Slowest + Down - Slower + Down - Normal - - Normal - Rises and Lowers - Topless Liquid - + + - + No Movement - Up Normal - Up Fast - Up Faster - Up Slow - Up Slowest - Up Slower - Up Normal + Up - Normal + Up - Fast + Up - Faster + Up - Slow + Up - Slowest + Up - Slower + Up - Normal No Movement - Down Normal - Down Fast - Down Faster - Down Slow - Down Slowest - Down Slower - Down Normal + Down - Normal + Down - Fast + Down - Faster + Down - Slow + Down - Slowest + Down - Slower + Down - Normal @@ -219,7 +213,9 @@ - + + + @@ -299,7 +295,7 @@ Coin Fire Flower None 2 - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -315,7 +311,7 @@ - + On contact with edge On contact with center @@ -337,11 +333,17 @@ - - - - - + + + Left + Right + + + + Up + Down + + @@ -360,17 +362,17 @@ Nothing Coin - Super Mushroom if small and Fire Flower if big - Super Mushroom if small and Super Leaf if big + Fire Flower + Super Leaf Gold Flower Mini Mushroom Super Star - Coin if not invincible and Super Star if invincible + Super Star/Coin Mega Mushroom Ten Coins 1-Up Mushroom Trampoline - Super Mushroom if small and coin if big + Super Mushroom/Coin @@ -464,14 +466,29 @@ - + Left Right - - + + + 12 Blocks Horizontal - 6 Vertical + 10 Blocks Horizontal - 8 Vertical + 18 Blocks Horizontal - 6 Vertical + 18 Blocks Horizontal - 7 Vertical (Fast) + 9 Blocks Horizontal - 7 Vertical (Fast) + 6 Blocks Horizontal - 9 Vertical + 16 Blocks Horizontal - 9 Vertical + Up (Permanent) + Nothing? + Up (Permanent and Fast) + Up and opposite direction (Permanent) + Static and Facing Drection + Static and Facing Drection + Up (Permanent) + @@ -507,18 +524,19 @@ - + - - Normal - Fast - Faster - Fastest + Slowest Slower Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest Up/Right @@ -526,20 +544,21 @@ - + - + - - Normal - Fast - Faster - Fastest + Slowest Slower Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest Up/Right @@ -547,20 +566,21 @@ - + - + - - Normal - Fast - Faster - Fastest + Slowest Slower Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest Up/Right @@ -568,20 +588,21 @@ - + - + - - Normal - Fast - Faster - Fastest + Slowest Slower Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest Up/Right @@ -589,20 +610,21 @@ - + - + - - Normal - Fast - Faster - Fastest + Slowest Slower Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest Up/Right @@ -610,7 +632,7 @@ - + @@ -627,10 +649,20 @@ + - - - + + Slowest + Slower + Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest + + + @@ -786,7 +818,12 @@ - + + Small Height / Medium Width + Small Height / Small Width + Medium Height / Medium Width + Large Height / Small Width + Up Down @@ -817,7 +854,7 @@ Coin Faces Controller - + @@ -843,10 +880,10 @@ - Normal (Default) - Gimbal Rotation - Upside Down Gimbal Rotation - Normal + Normal + Coin Starts Upside Down + Coin Faces Screen + Coin Faces Controller @@ -854,28 +891,48 @@ - - + + Fast + Faster, but return time is as fast + Medium + Slow + + + No Offset + Launch delayed + Spawn launched + + 16 Tiles 7 Tiles 14 Tiles 10 Tiles - - - + + + - - + + Fast + Faster, but return time is as fast + Medium + Slow + + + No Offset + Launch delayed + Spawn launched + + 16 Tiles 7 Tiles 14 Tiles 10 Tiles - - - + + + @@ -890,10 +947,15 @@ - + - + + Short + Medium + Long + Spawn once + Goomba @@ -906,7 +968,7 @@ Left Right - + @@ -962,14 +1024,32 @@ - + Nothing Three 1-Ups Mega Mushroom Star - - - + 1-Up + + + 0 + 10 + 20 + 30 + 40 + 50 + 60 + 70 + 80 + 90 + 100 + 110 + 120 + 130 + 140 + 150 + + Up Down @@ -984,11 +1064,28 @@ Left Right - - + + + 2 Tiles + 2 Tiles + 3.25 Tiles + 5 Tiles + 6.5 Tiles + 8.25 Tiles + 10 Tiles + 11.75 Tiles + 13.5 Tiles + 15.25 Tiles + 17 Tiles + 18.75 Tiles + 20.5 Tiles + 22.25 Tiles + 24 Tiles + 25.75 Tiles + - + @@ -1003,7 +1100,7 @@ - + @@ -1036,16 +1133,16 @@ Super Fire Mini - Tanooki + Super Leaf Unknown 6 - Unknown 7 + Mega Mario Star No Requirement Standing In the air - On vine + Climbing Ground-pound On Horizontal Rope On Swinging Rope/Vine @@ -1070,7 +1167,7 @@ Disables Event - + @@ -1083,7 +1180,7 @@ Disables Event - + @@ -1104,22 +1201,31 @@ - + + - - - - Left/Up - Right/Down + + + Slowest + Slower + Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest - + + - - - - Moves down slowly,then goes back up slowly - Falls down,then goes back up slowly + + + + + + Already Climbing + Falls @@ -1209,7 +1315,7 @@ Towards Player - Right + Moves towards the Direction Mario faces @@ -1286,7 +1392,7 @@ Towards Player - Right + Moves towards the Direction Mario faces @@ -1311,7 +1417,7 @@ Nothing Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -1328,7 +1434,7 @@ Empty Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -1431,19 +1537,24 @@ - - - + Normal - Explode after a while + Upside Down + Shifted Up A Tile - - Both + + + + Chase + Chase & Explode + + + Towards Player Left Right - - + + Normal Bull's-Eye @@ -1455,16 +1566,27 @@ - - - Both + + + Towards Player Left Right + - - + + Show + Hide + + + + + + + Right + Left + Right Left @@ -1474,14 +1596,27 @@ Down-Right Up-Right Up-Left + Use Blaster Direction - + + Show + Hide + + + + + + + Right + Left + Right Left + Use Blaster Direction @@ -1593,7 +1728,12 @@ Normal Blue - + + Up + Down + Left + Right + @@ -1613,7 +1753,7 @@ - + Two (Default) One @@ -1663,7 +1803,10 @@ - + + + + Right/Up @@ -1674,13 +1817,14 @@ Stone - - Slowest - Slower - Slow - Fast - Faster - Fastest + + + Slowest + Slower + Slow + Fast + Faster + Fastest @@ -1818,8 +1962,13 @@ Camera Stays Above Camera Stays Below - - + + Always Limit + Limit in Solo Play + Limit in Co-op Play + Unknown Value 3 + + @@ -1830,8 +1979,13 @@ Camera Stays Above Camera Stays Below - - + + Always Limit + Limit in Solo Play + Limit in Co-op Play + Unknown Value 3 + + @@ -1867,6 +2021,12 @@ Camera Stays to The Left Camera Stays to the Right + + Always Limit + Limit in Solo Play + Limit Until Both Players Cross + Unknown Value 3 + @@ -1876,6 +2036,12 @@ Camera Stays to The Left Camera Stays to the Right + + Always Limit + Limit in Solo Play + Limit Until Both Players Cross + Unknown Value 3 + @@ -1883,7 +2049,7 @@ - + Green Red @@ -1898,19 +2064,19 @@ - + Above layer 1 Tiles Below Layer 1 Tiles - + Normal - Ignore Collision - Unk - Unk2 + No Collider + Smaller Bottom Sensor + Smaller Bottom Sensor (Until Hit) - - + + Green Red @@ -1926,7 +2092,13 @@ - + + No Movement + Slowest + Slow + Medium + Fast + @@ -2020,6 +2192,8 @@ Jump Fly Horizontally Fly Vertically + Jump (Lower) + Jump (Faster) Green @@ -2368,7 +2542,7 @@ Right - + Fastest Slow Fast @@ -2475,7 +2649,7 @@ Nothing Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -2492,7 +2666,7 @@ Nothing Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -2562,7 +2736,7 @@ - + @@ -2596,7 +2770,7 @@ 13 Tiles 14 Tiles 15 Tiles - 16 Tiles + 16 Tiles Flat @@ -2616,20 +2790,16 @@ Down Two Tiles Down One Tiles - - Both Joints Visible - Right Joint Only - Left Joint Only - No Joints - + + - - + + 3 4 @@ -2706,7 +2876,7 @@ 17 Blocks 18 Blocks - + Stops Jumps Right Falls Down @@ -2774,9 +2944,9 @@ Normal - Upside Down Coin - Gimbal Rotation - Upside Down Coin + Coin Starts Upside Down + Coin Faces Screen + Coin Faces Controller @@ -2800,7 +2970,7 @@ - + Activates Event Deactivates Event @@ -2868,13 +3038,13 @@ - + - + - + Activates Event Deactivates Event @@ -2887,11 +3057,11 @@ - + - + Activates Event @@ -2913,7 +3083,7 @@ - + @@ -2949,7 +3119,7 @@ - + Normal Spiny Egg @@ -2958,6 +3128,7 @@ + Hanging Already Falling @@ -2968,6 +3139,7 @@ Left Right + Facing Player Only Moves on Slope @@ -2977,7 +3149,7 @@ Super Fast - + Normal Stationary @@ -2990,6 +3162,7 @@ Left Right + Facing Player Only Moves on Slope @@ -2999,8 +3172,8 @@ Super Fast - - + + Normal Stationary Pass Through Walls @@ -3010,9 +3183,10 @@ - + Left Right + Facing Player Slow @@ -3023,8 +3197,8 @@ Only Moves on Slope - - + + Normal Stationary Pass Through Walls @@ -3045,25 +3219,7 @@ Towards Player - - - 2 Frames - 3 Frames - 4 Frames - 5 Frames - 6 Frames - 7 Frames - 8 Frames - 9 Frames - 10 Frames - 11 Frames - 12 Frames - 13 Frames - 14 Frames - 15 Frames - 16 Frames - 17 Frames - + Both Tiles Single Tile @@ -3080,7 +3236,7 @@ Remain at One Height - + Only Moves on Slope @@ -3095,25 +3251,7 @@ Towards Player - - - 2 Frames - 3 Frames - 4 Frames - 5 Frames - 6 Frames - 7 Frames - 8 Frames - 9 Frames - 10 Frames - 11 Frames - 12 Frames - 13 Frames - 14 Frames - 15 Frames - 16 Frames - 17 Frames - + Both Tiles Single Tile @@ -3132,7 +3270,7 @@ - + @@ -3167,9 +3305,13 @@ - - Down-left - Up-left + + Left + Right + + + Down + Up @@ -3317,7 +3459,7 @@ - + @@ -3372,7 +3514,7 @@ Empty Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -3424,14 +3566,16 @@ Tall and Skinny - + + Left Right + Facing Player Only Moves on Slope @@ -3440,6 +3584,8 @@ Fast Super Fast + + Normal Stationary @@ -3448,9 +3594,11 @@ + Left Right + Facing Player Only Moves on Slope @@ -3459,6 +3607,8 @@ Fast Super Fast + + Normal Stationary @@ -3499,7 +3649,7 @@ Empty Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -3510,12 +3660,12 @@ Mushroom/Coin - + Empty Coin Fire Flower - Tanooki Leaf + Super Leaf Gold Flower Mini Mushroom Star @@ -3529,7 +3679,7 @@ - + @@ -3539,7 +3689,6 @@ - @@ -3548,7 +3697,7 @@ 10 Mario Seconds (Blue) - + @@ -3684,27 +3833,22 @@ - + - - Right - Left - Right - Left - - - No Flip + + + No Switching Fall When Hit Start on Bottom Start on Top - - Fastest - Fast - Medium Fast - Medium Slow - Slow - Slowest + + Slowest + Slower + Slow + Medium + Fast + Fastest 3x3 @@ -3768,7 +3912,7 @@ - + @@ -3975,7 +4119,7 @@ - + @@ -4023,10 +4167,19 @@ - - - - + + + Slowest + Slower + Slow + Medium Slow + Medium Fast + Fast + Faster + Fastest + + + diff --git a/ctpk.cpp b/ctpk.cpp index 415eaada..95c13907 100644 --- a/ctpk.cpp +++ b/ctpk.cpp @@ -90,6 +90,7 @@ Ctpk::Ctpk(FileBase* file) Ctpk::~Ctpk() { delete file; + qDeleteAll(entries); } Ctpk::CtpkEntry* Ctpk::getEntryByFilename(QString filename) diff --git a/ctpk.h b/ctpk.h index 47a84b26..0f5d2fff 100644 --- a/ctpk.h +++ b/ctpk.h @@ -1,7 +1,7 @@ #ifndef CTPK_H #define CTPK_H -#include "filesystem.h" +#include "filesystem/filesystem.h" #include diff --git a/editionmode.h b/editionmode.h deleted file mode 100644 index 84025064..00000000 --- a/editionmode.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef EDITIONMODE_H -#define EDITIONMODE_H - -#include "level.h" - -#include -#include - -enum EditMode -{ - EditMode_ObjectsMode -}; - -class EditionMode : public QObject -{ - Q_OBJECT -public: - EditionMode() {} - virtual ~EditionMode() {} - - virtual void mouseDown(int, int, Qt::MouseButtons, Qt::KeyboardModifiers, QRect) {} - virtual void mouseDrag(int, int, Qt::KeyboardModifiers, QRect) {} - virtual void mouseMove(int, int) {} - virtual void mouseUp(int, int) {} - - virtual void keyPress(QKeyEvent *) {} - - virtual void activate() {} - virtual void deactivate() {} - - virtual void render(QPainter*) {} - - virtual void deleteSelection() {} - virtual void copy() {} - virtual void cut() {} - virtual void paste(int, int, int, int) {} - virtual void raise() {} - virtual void lower() {} - virtual void raiseLayer() {} - virtual void lowerLayer() {} - - virtual void setLayerMask(quint8) {} - virtual void toggleSprites(bool) {} - virtual void togglePaths(bool) {} - virtual void toggleLocations(bool) {} - virtual void toggleEntrances(bool) {} - - virtual void select(Object*) {} - virtual void selectAll() {} - - Qt::CursorShape getActualCursor() { return actualCursor; } - -protected: - Level *level; - Qt::CursorShape actualCursor; - -signals: - void deselected(); - void selectdObjectChanged(Object* obj); - void updateEditors(); - void updateLevelView(); - void editMade(); -}; - -#endif // EDITIONMODE_H diff --git a/eventeditorwidget.cpp b/eventeditorwidget.cpp deleted file mode 100644 index f4d92e23..00000000 --- a/eventeditorwidget.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "eventeditorwidget.h" - -#include -#include -#include -#include - -EventEditorWidget::EventEditorWidget(Level* level) -{ - this->level = level; - - QVBoxLayout* layout = new QVBoxLayout(); - setLayout(layout); - - // Filters - QHBoxLayout* filterLayout = new QHBoxLayout(); - - QLabel* filterLabel = new QLabel(tr("Filter:")); - filterLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - filterLayout->addWidget(filterLabel); - viewFilter = new QComboBox(); - QStringList filters; - - filters << tr("All") - << tr("Enabled") - << tr("Disabled"); - - viewFilter->insertItems(0, filters); - filterLayout->addWidget(viewFilter); - - layout->addLayout(filterLayout); - - // List - eventsList = new QListWidget(); - layout->addWidget(eventsList); - - quint64 states = level->eventState; - - for (int i = 0; i < 64; i++) - { - QListWidgetItem* listItem = new QListWidgetItem(tr("Event %1").arg(i+1), eventsList); - listItem->setCheckState(((states >> i) & 1ULL) ? Qt::Checked : Qt::Unchecked); - listItem->setData(Qt::UserRole, i); - eventsList->addItem(listItem); - } - - connect(eventsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(handleEventListItemChanged(QListWidgetItem*))); - connect(viewFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(handleFilterChanged(int))); -} - -void EventEditorWidget::handleEventListItemChanged(QListWidgetItem* item) -{ - level->eventState ^= 1ULL << item->data(Qt::UserRole).toInt(); - emit editMade(); -} - -void EventEditorWidget::handleFilterChanged(int filter) -{ - switch (filter) - { - case 1: // Enabled - { - for (int i = 0; i < eventsList->count(); i++) - { - QListWidgetItem* item = eventsList->item(i); - - if (item->checkState() == Qt::Checked) - item->setHidden(false); - else - item->setHidden(true); - } - } break; - case 2: // Disabled - { - for (int i = 0; i < eventsList->count(); i++) - { - QListWidgetItem* item = eventsList->item(i); - - if (item->checkState() == Qt::Unchecked) - item->setHidden(false); - else - item->setHidden(true); - } - } break; - default: - { - for (int i = 0; i < eventsList->count(); i++) - { - QListWidgetItem* item = eventsList->item(i); - item->setHidden(false); - } - } break; - } - - -} diff --git a/eventeditorwidget.h b/eventeditorwidget.h deleted file mode 100644 index b6397b1f..00000000 --- a/eventeditorwidget.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef EVENTEDITORWIDGET_H -#define EVENTEDITORWIDGET_H - -#include -#include -#include - -#include "level.h" - -class EventEditorWidget : public QWidget -{ - Q_OBJECT -public: - EventEditorWidget(Level* level); - -signals: - void editMade(); - -public slots: - -private: - QListWidget* eventsList; - QComboBox* viewFilter; - - Level* level; - -private slots: - void handleEventListItemChanged(QListWidgetItem* item); - void handleFilterChanged(int filter); -}; - -#endif // EVENTEDITORWIDGET_H diff --git a/externalfile.cpp b/filesystem/externalfile.cpp similarity index 100% rename from externalfile.cpp rename to filesystem/externalfile.cpp diff --git a/externalfile.h b/filesystem/externalfile.h similarity index 100% rename from externalfile.h rename to filesystem/externalfile.h diff --git a/externalfilesystem.cpp b/filesystem/externalfilesystem.cpp similarity index 100% rename from externalfilesystem.cpp rename to filesystem/externalfilesystem.cpp diff --git a/externalfilesystem.h b/filesystem/externalfilesystem.h similarity index 100% rename from externalfilesystem.h rename to filesystem/externalfilesystem.h diff --git a/filebase.cpp b/filesystem/filebase.cpp similarity index 100% rename from filebase.cpp rename to filesystem/filebase.cpp diff --git a/filebase.h b/filesystem/filebase.h similarity index 100% rename from filebase.h rename to filesystem/filebase.h diff --git a/filesystem.h b/filesystem/filesystem.h similarity index 100% rename from filesystem.h rename to filesystem/filesystem.h diff --git a/filesystembase.h b/filesystem/filesystembase.h similarity index 100% rename from filesystembase.h rename to filesystem/filesystembase.h diff --git a/memoryfile.cpp b/filesystem/memoryfile.cpp similarity index 100% rename from memoryfile.cpp rename to filesystem/memoryfile.cpp diff --git a/memoryfile.h b/filesystem/memoryfile.h similarity index 100% rename from memoryfile.h rename to filesystem/memoryfile.h diff --git a/sarcfilesystem.cpp b/filesystem/sarcfilesystem.cpp similarity index 99% rename from sarcfilesystem.cpp rename to filesystem/sarcfilesystem.cpp index 159364fd..5ed27990 100644 --- a/sarcfilesystem.cpp +++ b/filesystem/sarcfilesystem.cpp @@ -70,6 +70,7 @@ SarcFilesystem::SarcFilesystem(FileBase* file) SarcFilesystem::~SarcFilesystem() { delete sarc; + qDeleteAll(files); } @@ -94,7 +95,7 @@ bool SarcFilesystem::directoryExists(QString path) void SarcFilesystem::directoryContents(QString path, QDir::Filter filter, QList& out) { - if (path[0] == '/') + if (path.startsWith('/')) path.remove(0,1); if (path != "" && !path.endsWith("/")) diff --git a/sarcfilesystem.h b/filesystem/sarcfilesystem.h similarity index 100% rename from sarcfilesystem.h rename to filesystem/sarcfilesystem.h diff --git a/game.cpp b/game.cpp index 6037f559..e2e58f12 100644 --- a/game.cpp +++ b/game.cpp @@ -93,8 +93,10 @@ QStandardItemModel* Game::getCourseModel() { fs->directoryContents("/Course/", QDir::Files, courseList); - if (courseList.isEmpty()) + delete dirItem; + if (courseList.isEmpty()) { continue; + } dirItem = model->invisibleRootItem(); } @@ -102,8 +104,10 @@ QStandardItemModel* Game::getCourseModel() { fs->directoryContents("/Course/" + dir, QDir::Files, courseList); - if (courseList.isEmpty()) + if (courseList.isEmpty()) { + delete dirItem; continue; + } model->invisibleRootItem()->appendRow(dirItem); } @@ -289,6 +293,19 @@ QStandardItemModel* Game::getTilesetModel(int id, bool includeNoneItem) QString fileName = tilesetfiles[i]; fileName.chop(5); + if (id == 0 && !fileName.startsWith("J_")){ + continue; + } + else if (id == 1 && !fileName.startsWith("M_")){ + continue; + } + else if (id == 2 && !fileName.startsWith("S1_")){ + continue; + } + else if (id == 3 && !fileName.startsWith("S2_")){ + continue; + } + QString tilesetname; tilesetname = defaultNames.value(fileName, fileName); @@ -303,22 +320,7 @@ QStandardItemModel* Game::getTilesetModel(int id, bool includeNoneItem) fileNameItem->setData(fileName); items.append(fileNameItem); - if (id == 0 && fileName.startsWith("J_")) - { - model->appendRow(items); - } - else if (id == 1 && fileName.startsWith("M_")) - { - model->appendRow(items); - } - else if (id == 2 && fileName.startsWith("S1_")) - { - model->appendRow(items); - } - else if (id == 3 && fileName.startsWith("S2_")) - { - model->appendRow(items); - } + model->appendRow(items); } return model; diff --git a/game.h b/game.h index cc5432bc..6603a2f2 100644 --- a/game.h +++ b/game.h @@ -1,7 +1,7 @@ #ifndef GAME_H #define GAME_H -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "tileset.h" #include "levelmanager.h" diff --git a/level.cpp b/level.cpp index d9d713c7..62f6cf94 100644 --- a/level.cpp +++ b/level.cpp @@ -28,7 +28,7 @@ #include Level::Level(Game *game, SarcFilesystem* archive, int area, QString lvlName) -{ +{ this->game = game; this->archive = archive; @@ -71,7 +71,7 @@ Level::Level(Game *game, SarcFilesystem* archive, int area, QString lvlName) tilesets[t] = game->getTileset(tilesetname); } catch (const std::exception &e) - { + { QMessageBox::warning(nullptr, "CoinKiller", QObject::tr("Tileset %1 could not be found!").arg(tilesetname)); tilesets[t] = nullptr; } @@ -176,7 +176,9 @@ Level::Level(Game *game, SarcFilesystem* archive, int area, QString lvlName) spr->setRect(); sprites.append(spr); - sortCameraLimits(spr); + if (isCameraLimit(spr)) { + insertCameraLimit(spr); + } } // Block 8: Sprites Used List (no need to read this) @@ -332,14 +334,14 @@ Level::~Level() delete objects[l][o]; } - for (int s = 0; s < sprites.size(); s++) - delete sprites[s]; - - for (int e = 0; e < entrances.size(); e++) - delete entrances[e]; - - for (int l = 0; l < locations.size(); l++) - delete locations[l]; + qDeleteAll(sprites); + qDeleteAll(entrances); + qDeleteAll(locations); + qDeleteAll(zones); + qDeleteAll(paths); + qDeleteAll(progressPaths); + qDeleteAll(boundings); + qDeleteAll(backgrounds); } qint8 Level::save() @@ -803,87 +805,6 @@ void Level::add(Object *obj) locations.append(dynamic_cast(obj)); } -void Level::remove(QList objs) -{ - foreach (Object* obj, objs) - remove(obj); -} - -void Level::remove(Object* obj) -{ - if (is(obj)) - { - BgdatObject* bgdatobj = dynamic_cast(obj); - objects[bgdatobj->getLayer()].removeOne(bgdatobj); - delete obj; - } - else if (is(obj)) - { - Sprite* spr = dynamic_cast(obj); - sprites.removeOne(spr); - int id = spr->getid(); - - switch (id) { - case 156: - leftCamLimits.removeOne(spr); - break; - case 157: - rightCamLimits.removeOne(spr); - break; - case 160: - bottomCamLimits.removeOne(spr); - break; - case 161: - topCamLimits.removeOne(spr); - break; - } - - delete obj; - } - else if (is(obj)) - { - entrances.removeOne(dynamic_cast(obj)); - delete obj; - } - else if (is(obj)) - { - zones.removeOne(dynamic_cast(obj)); - delete obj; - } - else if (is(obj)) - { - locations.removeOne(dynamic_cast(obj)); - delete obj; - } - else if (is(obj)) - { - PathNode* node = dynamic_cast(obj); - Path* path = node->getParentPath(); - - path->removeNode(node); - delete obj; - - if (path->getNumberOfNodes() <= 0) - { - paths.removeOne(path); - delete path; - } - } - else if (is(obj)) - { - ProgressPathNode* node = dynamic_cast(obj); - ProgressPath* path = node->getParentPath(); - - path->removeNode(node); - delete obj; - - if (path->getNumberOfNodes() <= 0) - { - progressPaths.removeOne(path); - delete path; - } - } -} void Level::move(QList objs, int deltax, int deltay) { @@ -1065,25 +986,66 @@ ProgressPath* Level::newProgressPath() return new ProgressPath(id, 0); } -void Level::sortCameraLimits(Sprite *spr) +bool Level::isCameraLimit(Sprite *spr) { int id = spr->getid(); if (id != 156 && id != 157 && id != 160 && id != 161) + return false; + + return true; +} + +void Level::insertCameraLimit(Sprite *spr) +{ + if (!isCameraLimit(spr)) return; - if (id == 156) + switch (spr->getid()) { + case 156: leftCamLimits.append(spr); - - if (id == 157) + break; + case 157: rightCamLimits.append(spr); - - if (id == 160) + break; + case 160: bottomCamLimits.append(spr); - - if (id == 161) + break; + case 161: topCamLimits.append(spr); + break; + default: + break; + } + + sortCameraLimits(); +} + +void Level::removeCameraLimit(Sprite *spr) +{ + if (!isCameraLimit(spr)) + return; + switch (spr->getid()) { + case 156: + leftCamLimits.removeOne(spr); + break; + case 157: + rightCamLimits.removeOne(spr); + break; + case 160: + bottomCamLimits.removeOne(spr); + break; + case 161: + topCamLimits.removeOne(spr); + break; + default: + break; + } +} + +void Level::sortCameraLimits() +{ // Sort right limits from smallest to largest xPos std::sort(rightCamLimits.begin(), rightCamLimits.end(), [](const Sprite* a, const Sprite* b) -> bool { return a->getx() < b->getx(); }); diff --git a/level.h b/level.h index 635947eb..272c5283 100644 --- a/level.h +++ b/level.h @@ -18,7 +18,7 @@ #ifndef LEVEL_H #define LEVEL_H -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "tileset.h" #include "objects.h" @@ -61,14 +61,12 @@ class Level } void add(QList objs); - void add(Object* obj); - void remove(QList objs); - void remove(Object* obj); + void add(Object *obj); void move(QList objs, int deltax, int deltay); void raise(Object *obj); - void lower(Object* obj); + void lower(Object *obj); void raiseLayer(BgdatObject *obj); - void lowerLayer(BgdatObject* obj); + void lowerLayer(BgdatObject *obj); Entrance* newEntrance(int x, int y); Zone* newZone(int x, int y); @@ -80,12 +78,14 @@ class Level void setAreaID(int id) { this->area = id; } // Camera Limits - void sortCameraLimits(Sprite* spr); + bool isCameraLimit(Sprite* spr); + void insertCameraLimit(Sprite* spr); + void removeCameraLimit(Sprite* spr); - QList getLeftCamLimits() { return leftCamLimits; } - QList getRightCamLimits() { return rightCamLimits; } - QList getBottomCamLimits() { return bottomCamLimits; } - QList getTopCamLimits() { return topCamLimits; } + QList leftCamLimits; + QList rightCamLimits; + QList bottomCamLimits; + QList topCamLimits; private: SarcFilesystem* archive; @@ -94,10 +94,7 @@ class Level quint8 getNextZoneID(Object* obj); - QList leftCamLimits; - QList rightCamLimits; - QList bottomCamLimits; - QList topCamLimits; + void sortCameraLimits(); }; #endif // LEVEL_H diff --git a/areaeditorwidget.cpp b/leveleditor/areaeditorwidget.cpp similarity index 59% rename from areaeditorwidget.cpp rename to leveleditor/areaeditorwidget.cpp index 9816c089..e51b36ad 100644 --- a/areaeditorwidget.cpp +++ b/leveleditor/areaeditorwidget.cpp @@ -8,10 +8,10 @@ #include #include -AreaEditorWidget::AreaEditorWidget(Level* level, Game *game) -{ - this->level = level; - this->game = game; +#include "commands/setvalue.h" + +AreaEditorWidget::AreaEditorWidget(Level *level, Game *game, QUndoStack *undoStack) : + level(level), game(game), undoStack(undoStack) { specialLevelFlags1.insert(0, tr("Normal")); specialLevelFlags1.insert(2, tr("Powerup Toad House")); @@ -25,81 +25,84 @@ AreaEditorWidget::AreaEditorWidget(Level* level, Game *game) specialLevelFlags2.insert(1, tr("Ghost House")); specialLevelFlags2.insert(7, tr("Reznor Battle")); - QVBoxLayout* layout = new QVBoxLayout(); + QVBoxLayout *layout = new QVBoxLayout(); setLayout(layout); - QGroupBox* areaSettingsBox = new QGroupBox(); + QGroupBox *areaSettingsBox = new QGroupBox(); areaSettingsBox->setTitle(tr("Area Settings")); layout->addWidget(areaSettingsBox); - QGridLayout* settingsLayout = new QGridLayout(); + QGridLayout *settingsLayout = new QGridLayout(); areaSettingsBox->setLayout(settingsLayout); settingsLayout->addWidget(new QLabel(tr("Time Limit:")), 0, 0, 1, 1, Qt::AlignRight); timeLimit = new QSpinBox(); timeLimit->setRange(0, 999); - connect(timeLimit, SIGNAL(valueChanged(int)), this, SLOT(handleTimeLimitChange(int))); - timeLimit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // All Controls at maximum possible width + connect(timeLimit, &QSpinBox::valueChanged, this, qOverload(&AreaEditorWidget::timeLimitChanged)); + timeLimit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(timeLimit, 0, 1); settingsLayout->addWidget(new QLabel(tr("CoinRush Time Limit:")), 1, 0, 1, 1, Qt::AlignRight); coinRushtimeLimit = new QSpinBox(); coinRushtimeLimit->setRange(0, 999); - connect(coinRushtimeLimit, SIGNAL(valueChanged(int)), this, SLOT(handleCoinRushTimeLimitChange(int))); + connect(coinRushtimeLimit, &QSpinBox::valueChanged, this, qOverload(&AreaEditorWidget::coinRushTimeLimitChanged)); coinRushtimeLimit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(coinRushtimeLimit, 1, 1); settingsLayout->addWidget(new QLabel(tr("Level Setting 1:")), 2, 0, 1, 1, Qt::AlignRight); specialLevelFlag1 = new QComboBox(); specialLevelFlag1->addItems(specialLevelFlags1.values()); - connect(specialLevelFlag1, SIGNAL(currentTextChanged(QString)), this, SLOT(handleSpecialLevelFlag1Change(QString))); + connect(specialLevelFlag1, &QComboBox::currentTextChanged, this, &AreaEditorWidget::specialLevelFlag1Changed); specialLevelFlag1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(specialLevelFlag1, 2, 1); settingsLayout->addWidget(new QLabel(tr("Level Setting 2:")), 3, 0, 1, 1, Qt::AlignRight); specialLevelFlag2 = new QComboBox(); specialLevelFlag2->addItems(specialLevelFlags2.values()); - connect(specialLevelFlag2, SIGNAL(currentTextChanged(QString)), this, SLOT(handleSpecialLevelFlag2Change(QString))); + connect(specialLevelFlag2, &QComboBox::currentTextChanged, this, &AreaEditorWidget::specialLevelFlag2Changed); specialLevelFlag2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(specialLevelFlag2, 3, 1); settingsLayout->addWidget(new QLabel(tr("Unknown 1:")), 4, 0, 1, 1, Qt::AlignRight); unk1Editor = new QSpinBox(); unk1Editor->setRange(0, 255); - connect(unk1Editor, SIGNAL(valueChanged(int)), this, SLOT(handleUnk1Change(int))); + connect(unk1Editor, &QSpinBox::valueChanged, this, &AreaEditorWidget::unk1Changed); unk1Editor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(unk1Editor, 4, 1); settingsLayout->addWidget(new QLabel(tr("Unknown 2:")), 5, 0, 1, 1, Qt::AlignRight); unk2Editor = new QSpinBox(); unk2Editor->setRange(0, 255); - connect(unk2Editor, SIGNAL(valueChanged(int)), this, SLOT(handleUnk2Change(int))); + connect(unk2Editor, &QSpinBox::valueChanged, this, &AreaEditorWidget::unk2Changed); unk2Editor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(unk2Editor, 5, 1); settingsLayout->addWidget(new QLabel(tr("Level Entrance ID:")), 6, 0, 1, 1, Qt::AlignRight); levelEntranceID = new QSpinBox(); levelEntranceID->setRange(0, 255); - connect(levelEntranceID, SIGNAL(valueChanged(int)), this, SLOT(handlelevelEntranceIDChanged(int))); + connect(levelEntranceID, &QSpinBox::valueChanged, this, &AreaEditorWidget::levelEntranceIDChanged); levelEntranceID->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); settingsLayout->addWidget(levelEntranceID, 6, 1, 1, 1); - QGroupBox* eventEditorBox = new QGroupBox(); + QGroupBox *eventEditorBox = new QGroupBox(); eventEditorBox->setTitle(tr("Initial Area Event States")); layout->addWidget(eventEditorBox); - QVBoxLayout* eventBoxLayout = new QVBoxLayout(); + QVBoxLayout *eventBoxLayout = new QVBoxLayout(); eventEditorBox->setLayout(eventBoxLayout); - eventEditor = new EventEditorWidget(level); - connect(eventEditor, SIGNAL(editMade()), this, SLOT(passEditMade())); + eventEditor = new EventEditorWidget(level, undoStack); eventBoxLayout->addWidget(eventEditor); updateInfo(); } -void AreaEditorWidget::updateInfo() -{ +void AreaEditorWidget::updateEditor() { + this->updateInfo(); + eventEditor->updateEditor(); +} + +void AreaEditorWidget::updateInfo() { handleChanges = false; timeLimit->setValue(level->timeLimit); coinRushtimeLimit->setValue(level->coinRushTimeLimit); @@ -111,51 +114,37 @@ void AreaEditorWidget::updateInfo() handleChanges = true; } -void AreaEditorWidget::handleTimeLimitChange(int timeLimitVal) -{ +void AreaEditorWidget::timeLimitChanged(quint16 timeLimitVal) { if (!handleChanges) return; - level->timeLimit = timeLimitVal; - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->timeLimit, timeLimitVal, tr("Changed Area Time Limit"))); } -void AreaEditorWidget::handleCoinRushTimeLimitChange(int timeLimitVal) -{ +void AreaEditorWidget::coinRushTimeLimitChanged(quint16 timeLimitVal) { if (!handleChanges) return; - level->coinRushTimeLimit = timeLimitVal; - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->coinRushTimeLimit, timeLimitVal, tr("Changed Area CoinRush Time Limit"))); } -void AreaEditorWidget::handleSpecialLevelFlag1Change(QString text) -{ +void AreaEditorWidget::specialLevelFlag1Changed(QString text) { if (!handleChanges) return; - level->specialLevelFlag = specialLevelFlags1.key(text, 0); - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->specialLevelFlag, specialLevelFlags1.key(text, 0), tr("Changed Area Special Flag 1"))); } -void AreaEditorWidget::handleSpecialLevelFlag2Change(QString text) -{ +void AreaEditorWidget::specialLevelFlag2Changed(QString text) { if (!handleChanges) return; - level->specialLevelFlag2 = specialLevelFlags2.key(text, 0); - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->specialLevelFlag2, specialLevelFlags2.key(text, 0), tr("Changed Area Special Flag 2"))); } -void AreaEditorWidget::handlelevelEntranceIDChanged(int id) -{ +void AreaEditorWidget::levelEntranceIDChanged(quint8 id) { if (!handleChanges) return; - level->levelEntranceID = id; - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->levelEntranceID, id, tr("Changed Area Entrance ID"))); } -void AreaEditorWidget::handleUnk1Change(int unk) -{ +void AreaEditorWidget::unk1Changed(quint16 val) { if (!handleChanges) return; - level->unk1 = unk; - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->unk1, val, tr("Changed Area Unknown 1"))); } -void AreaEditorWidget::handleUnk2Change(int unk) -{ +void AreaEditorWidget::unk2Changed(quint8 val) { if (!handleChanges) return; - level->unk2 = unk; - emit editMade(); + undoStack->push(new EditorCommand::SetValue(&level->unk2, val, tr("Changed Area Unknown 2"))); } diff --git a/leveleditor/areaeditorwidget.h b/leveleditor/areaeditorwidget.h new file mode 100644 index 00000000..9dc0e3b2 --- /dev/null +++ b/leveleditor/areaeditorwidget.h @@ -0,0 +1,61 @@ +#ifndef AREAEDITORWIDGET_H +#define AREAEDITORWIDGET_H + +#include "level.h" +#include "eventeditorwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class AreaEditorWidget : public QWidget +{ + Q_OBJECT +public: + AreaEditorWidget(Level *level, Game *game, QUndoStack *undoStack); + + void updateEditor(); + +signals: + void relaodTilesetPicker(); + +private: + Level *level; + Game *game; + + QUndoStack *undoStack; + + QSpinBox *timeLimit; + QSpinBox *coinRushtimeLimit; + QSpinBox *levelEntranceID; + QComboBox *specialLevelFlag1; + QComboBox *specialLevelFlag2; + QSpinBox *unk1Editor; + QSpinBox *unk2Editor; + + EventEditorWidget *eventEditor; + + QMap specialLevelFlags1; + QMap specialLevelFlags2; + + bool handleChanges = true; + void updateInfo(); + + class HorLine : public QFrame { public: HorLine() { setFrameStyle(QFrame::HLine | QFrame::Sunken); } }; + +private slots: + void timeLimitChanged(quint16 timeLimitVal); + void coinRushTimeLimitChanged(quint16 timeLimitVal); + void specialLevelFlag1Changed(QString text); + void specialLevelFlag2Changed(QString text); + void levelEntranceIDChanged(quint8 id); + void unk1Changed(quint16 val); + void unk2Changed(quint8 val); +}; + +#endif // AREAEDITORWIDGET_H diff --git a/leveleditor/commands/bgdatcommands.cpp b/leveleditor/commands/bgdatcommands.cpp new file mode 100644 index 00000000..d8b3bd5e --- /dev/null +++ b/leveleditor/commands/bgdatcommands.cpp @@ -0,0 +1,24 @@ +#include "bgdatcommands.h" + +namespace Commands::BgdatCmd { + +ChangeObject::ChangeObject(BgdatObject *obj, qint32 objId, qint32 tilesetId) : + obj(obj), + newObjId(objId), + oldObjId(obj->getObjID()), + newTilesetId(tilesetId), + oldTilesetId(obj->getTsID()) { + this->setText(QObject::tr("Changed Object")); +} + +void ChangeObject::undo() { + obj->setObjID(oldObjId); + obj->setTsID(oldTilesetId); +} + +void ChangeObject::redo() { + obj->setObjID(newObjId); + obj->setTsID(newTilesetId); +} + +} // namespace Commands::BgdatCmd diff --git a/leveleditor/commands/bgdatcommands.h b/leveleditor/commands/bgdatcommands.h new file mode 100644 index 00000000..16318e42 --- /dev/null +++ b/leveleditor/commands/bgdatcommands.h @@ -0,0 +1,28 @@ +#ifndef COMMANDS_BGDATOBJCMD_H +#define COMMANDS_BGDATOBJCMD_H + +#include + +#include "objects.h" + +namespace Commands::BgdatCmd { + +class ChangeObject : public QUndoCommand +{ +public: + ChangeObject(BgdatObject *obj, qint32 objId, qint32 tilesetId); + + void undo() override; + void redo() override; + +private: + BgdatObject *obj; + qint32 newObjId; + qint32 oldObjId; + qint32 newTilesetId; + qint32 oldTilesetId; +}; + +} // namespace Commands::BgdatCmd + +#endif // COMMANDS_BGDATOBJCMD_H diff --git a/leveleditor/commands/commandids.h b/leveleditor/commands/commandids.h new file mode 100644 index 00000000..83f1af32 --- /dev/null +++ b/leveleditor/commands/commandids.h @@ -0,0 +1,19 @@ +#ifndef COMMANDIDS_H +#define COMMANDIDS_H + +namespace Commands { + +enum CommandID { + // Level View + Cmd_Move, + Cmd_Resize, + Cmd_IncreasePosition, + Cmd_SetValue, + + // Sprites + Cmd_SetSpriteByte +}; + +} // namespace Commands + +#endif // COMMANDIDS_H diff --git a/leveleditor/commands/editorcommands.cpp b/leveleditor/commands/editorcommands.cpp new file mode 100644 index 00000000..29035ede --- /dev/null +++ b/leveleditor/commands/editorcommands.cpp @@ -0,0 +1,107 @@ +#include "editorcommands.h" + +namespace Commands::EditorCmd { + +SetLayerMask::SetLayerMask(quint8 *layerMask, LAYER_MASK layer, bool state) : + layerMask(layerMask), + layer(layer), + state(state) +{ + QString enabledStr = (state) ? "Enabled" : "Disabled"; + + switch (layer) { + case LAYER_MASK::LAYER_ONE: + this->setText(QObject::tr("%1 Layer 1").arg(enabledStr)); + break; + case LAYER_MASK::LAYER_TWO: + this->setText(QObject::tr("%1 Layer 2").arg(enabledStr)); + break; + default: + this->setText(QObject::tr("%1 Layer (Unknown)").arg(enabledStr)); + break; + } +} + +void SetLayerMask::undo() { + if (state) { + *layerMask &= ~layer; + } + else { + *layerMask |= layer; + } +} + +void SetLayerMask::redo() { + if (state) { + *layerMask |= layer; + } + else { + *layerMask &= ~layer; + } +} + + +SetSpriteInteraction::SetSpriteInteraction(bool *spriteInteraction, bool state) : + spriteInteraction(spriteInteraction), + state(state) { + QString enabledStr = (state) ? "Enabled" : "Disabled"; + this->setText(QObject::tr("%1 Sprites").arg(enabledStr)); +} + +void SetSpriteInteraction::undo() { + *spriteInteraction = !state; +} + +void SetSpriteInteraction::redo() { + *spriteInteraction = state; +} + + +SetEntranceInteraction::SetEntranceInteraction(bool *entranceInteraction, bool state) : + entranceInteraction(entranceInteraction), + state(state) { + QString enabledStr = (state) ? "Enabled" : "Disabled"; + this->setText(QObject::tr("%1 Entrances").arg(enabledStr)); +} + +void SetEntranceInteraction::undo() { + *entranceInteraction = !state; +} + +void SetEntranceInteraction::redo() { + *entranceInteraction = state; +} + + +SetPathInteraction::SetPathInteraction(bool *pathInteraction, bool state) : + pathInteraction(pathInteraction), + state(state) { + QString enabledStr = (state) ? "Enabled" : "Disabled"; + this->setText(QObject::tr("%1 Paths").arg(enabledStr)); +} + +void SetPathInteraction::undo() { + *pathInteraction = !state; +} + +void SetPathInteraction::redo() { + *pathInteraction = state; +} + + +SetLocationInteraction::SetLocationInteraction(bool *locationInteraction, bool state) : + locationInteraction(locationInteraction), + state(state) { + QString enabledStr = (state) ? "Enabled" : "Disabled"; + this->setText(QObject::tr("%1 Locations").arg(enabledStr)); +} + +void SetLocationInteraction::undo() { + *locationInteraction = !state; +} + +void SetLocationInteraction::redo() { + *locationInteraction = state; +} + +} // namespace Commands::EditorCmd diff --git a/leveleditor/commands/editorcommands.h b/leveleditor/commands/editorcommands.h new file mode 100644 index 00000000..9be0c5b6 --- /dev/null +++ b/leveleditor/commands/editorcommands.h @@ -0,0 +1,82 @@ +#ifndef COMMANDS_EDITORCMD_H +#define COMMANDS_EDITORCMD_H + +#include + +#include "leveleditor/layermask.h" + +namespace Commands::EditorCmd { + +class SetLayerMask : public QUndoCommand +{ +public: + SetLayerMask(quint8 *layerMask, LAYER_MASK layer, bool state); + + void undo() override; + void redo() override; + +private: + quint8 *layerMask; + LAYER_MASK layer; + bool state; +}; + + +class SetSpriteInteraction : public QUndoCommand +{ +public: + SetSpriteInteraction(bool *spriteInteraction, bool state); + + void undo() override; + void redo() override; + +private: + bool *spriteInteraction; + bool state; +}; + + +class SetEntranceInteraction : public QUndoCommand +{ +public: + SetEntranceInteraction(bool *entranceInteraction, bool state); + + void undo() override; + void redo() override; + +private: + bool *entranceInteraction; + bool state; +}; + + +class SetPathInteraction : public QUndoCommand +{ +public: + SetPathInteraction(bool *pathInteraction, bool state); + + void undo() override; + void redo() override; + +private: + bool *pathInteraction; + bool state; +}; + + +class SetLocationInteraction : public QUndoCommand +{ +public: + SetLocationInteraction(bool *locationInteraction, bool state); + + void undo() override; + void redo() override; + +private: + bool *locationInteraction; + bool state; +}; + +} // namespace Commands::EditorCmd + +#endif // COMMANDS_EDITORCMD_H diff --git a/leveleditor/commands/entrancecommands.cpp b/leveleditor/commands/entrancecommands.cpp new file mode 100644 index 00000000..2329151e --- /dev/null +++ b/leveleditor/commands/entrancecommands.cpp @@ -0,0 +1,150 @@ +#include "entrancecommands.h" + +namespace Commands::EntranceCmd { + +SetType::SetType(Entrance *entr, quint8 type) : + entr(entr), + newType(type), + oldType(entr->getEntrType()) { + this->setText(QObject::tr("Set Entrance Type")); +} + +void SetType::undo() { + this->entr->setEntrType(oldType); + this->entr->setRect(); +} + +void SetType::redo() { + this->entr->setEntrType(newType); + this->entr->setRect(); +} + + +SetId::SetId(Entrance *entr, quint8 id) : + entr(entr), + newId(id), + oldId(entr->getid()) { + this->setText(QObject::tr("Set Entrance ID")); +} + +void SetId::undo() { + this->entr->setId(oldId); +} + +void SetId::redo() { + this->entr->setId(newId); +} + + +SetDestEntr::SetDestEntr(Entrance *entr, quint8 destEntrId) : + entr(entr), + newDest(destEntrId), + oldDest(entr->getDestEntr()) { + this->setText(QObject::tr("Set Entrance Dest Entrance")); +} + +void SetDestEntr::undo() { + this->entr->setDestEntr(oldDest); +} + +void SetDestEntr::redo() { + this->entr->setDestEntr(newDest); +} + + +SetDestArea::SetDestArea(Entrance *entr, quint8 destAreaId) : + entr(entr), + newDest(destAreaId), + oldDest(entr->getDestArea()) { + this->setText(QObject::tr("Set Entrance Dest Area")); +} + +void SetDestArea::undo() { + this->entr->setDestArea(oldDest); +} + +void SetDestArea::redo() { + this->entr->setDestArea(newDest); +} + + +SetCamXOffset::SetCamXOffset(Entrance *entr, qint16 xOffset) : + entr(entr), + newXOffset(xOffset), + oldXOffset(entr->getCameraX()) { + this->setText(QObject::tr("Set Entrance Camera X Offset")); +} + +void SetCamXOffset::undo() { + this->entr->setCameraX(oldXOffset); +} + +void SetCamXOffset::redo() { + this->entr->setCameraX(newXOffset); +} + + +SetCamYOffset::SetCamYOffset(Entrance *entr, qint16 yOffset) : + entr(entr), + newYOffset(yOffset), + oldYOffset(entr->getCameraY()) { + this->setText(QObject::tr("Set Entrance Camera Y Offset")); +} + +void SetCamYOffset::undo() { + this->entr->setCameraY(oldYOffset); +} + +void SetCamYOffset::redo() { + this->entr->setCameraY(newYOffset); +} + + +SetUnk1::SetUnk1(Entrance *entr, quint8 unk1) : + entr(entr), + newUnk1(unk1), + oldUnk1(entr->getUnk1()) { + this->setText(QObject::tr("Set Entrance Unk1")); +} + +void SetUnk1::undo() { + this->entr->setUnk1(oldUnk1); +} + +void SetUnk1::redo() { + this->entr->setUnk1(newUnk1); +} + + +SetUnk2::SetUnk2(Entrance *entr, quint8 unk2) : + entr(entr), + newUnk2(unk2), + oldUnk2(entr->getUnk2()) { + this->setText(QObject::tr("Set Entrance Unk2")); +} + +void SetUnk2::undo() { + this->entr->setUnk2(oldUnk2); +} + +void SetUnk2::redo() { + this->entr->setUnk2(newUnk2); +} + + +SetSettingsBit::SetSettingsBit(Entrance *entr, bool value, qint32 bit) : + entr(entr), + bitValue(value), + bitIndex(bit) { + this->setText(QObject::tr("Set Entrance Setting Bit")); +} + +void SetSettingsBit::undo() { + this->entr->setSettingsBit(!bitValue, bitIndex); +} + +void SetSettingsBit::redo() { + this->entr->setSettingsBit(bitValue, bitIndex); +} + +} // namespace Commands::EntranceCmd diff --git a/leveleditor/commands/entrancecommands.h b/leveleditor/commands/entrancecommands.h new file mode 100644 index 00000000..413d5790 --- /dev/null +++ b/leveleditor/commands/entrancecommands.h @@ -0,0 +1,146 @@ +#ifndef COMMANDS_ENTRANCECMD_H +#define COMMANDS_ENTRANCECMD_H + +#include + +#include "objects.h" + +namespace Commands::EntranceCmd { + +class SetType : public QUndoCommand +{ +public: + SetType(Entrance *entr, quint8 type); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newType; + const quint8 oldType; +}; + + +class SetId : public QUndoCommand +{ +public: + SetId(Entrance *entr, quint8 id); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newId; + const quint8 oldId; +}; + + +class SetDestEntr : public QUndoCommand +{ +public: + SetDestEntr(Entrance *entr, quint8 destEntrId); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newDest; + const quint8 oldDest; +}; + + +class SetDestArea : public QUndoCommand +{ +public: + SetDestArea(Entrance *entr, quint8 destAreaId); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newDest; + const quint8 oldDest; +}; + + +class SetCamXOffset : public QUndoCommand +{ +public: + SetCamXOffset(Entrance *entr, qint16 xOffset); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const qint16 newXOffset; + const qint16 oldXOffset; +}; + + +class SetCamYOffset : public QUndoCommand +{ +public: + SetCamYOffset(Entrance *entr, qint16 yOffset); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const qint16 newYOffset; + const qint16 oldYOffset; +}; + + +class SetUnk1 : public QUndoCommand +{ +public: + SetUnk1(Entrance *entr, quint8 unk1); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newUnk1; + const quint8 oldUnk1; +}; + + +class SetUnk2 : public QUndoCommand +{ +public: + SetUnk2(Entrance *entr, quint8 unk2); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const quint8 newUnk2; + const quint8 oldUnk2; +}; + + +class SetSettingsBit : public QUndoCommand +{ +public: + SetSettingsBit(Entrance *entr, bool value, qint32 bit); + + void undo() override; + void redo() override; + +private: + Entrance *const entr; + const bool bitValue; + const qint32 bitIndex; +}; + +} // namespace Commands::EntranceCmd + +#endif // COMMANDS_ENTRANCECMD_H diff --git a/leveleditor/commands/levelcommands.cpp b/leveleditor/commands/levelcommands.cpp new file mode 100644 index 00000000..5adcde5e --- /dev/null +++ b/leveleditor/commands/levelcommands.cpp @@ -0,0 +1,582 @@ +#include "levelcommands.h" + +namespace Commands::LevelCmd { + +RaiseObject::RaiseObject(Level *level, Object *obj) : + level(level), + obj(obj) { + this->setText(QObject::tr("Raised Object")); +} + +void RaiseObject::undo() { + level->lower(obj); +} + +void RaiseObject::redo() { + level->raise(obj); +} + + +LowerObject::LowerObject(Level *level, Object *obj) : + level(level), + obj(obj) { + this->setText(QObject::tr("Lowered Object")); +} + +void LowerObject::undo() { + level->raise(obj); +} + +void LowerObject::redo() { + level->lower(obj); +} + + +SetTileset::SetTileset(Level *level, quint8 tsSlot, Tileset* tileset) : + level(level), + tsSlot(tsSlot), + newTs(tileset), + oldTs(level->tilesets[tsSlot]) { + this->setText(QObject::tr("Changed Tileset")); +} + +SetTileset::~SetTileset() { + if (newTsDeletable) { + delete newTs; + } else { + delete oldTs; + } +} + +void SetTileset::undo() { + level->tilesets[tsSlot] = oldTs; + newTsDeletable = true; +} + +void SetTileset::redo() { + level->tilesets[tsSlot] = newTs; + newTsDeletable = false; +} + + +InsertBgdatObj::InsertBgdatObj(Level *level, BgdatObject *obj) : + level(level), + obj(obj) { + this->setText(QObject::tr("Inserted Object at X: %1 Y: %2").arg(obj->getx()).arg(obj->gety())); +} + +InsertBgdatObj::~InsertBgdatObj() { + if (deletable) { + delete obj; + } +} + +void InsertBgdatObj::undo() { + level->objects[obj->getLayer()].removeOne(obj); + deletable = true; +} + +void InsertBgdatObj::redo() { + level->objects[obj->getLayer()].append(obj); + deletable = false; +} + + +DeleteBgdatObject::DeleteBgdatObject(Level *level, BgdatObject *obj) : + level(level), + obj(obj), + oldIndex(level->objects[obj->getLayer()].indexOf(obj)) { + this->setText(QObject::tr("Deleted BgdatObject")); +} + +DeleteBgdatObject::~DeleteBgdatObject() { + if (deletable) { + delete obj; + } +} + +void DeleteBgdatObject::undo() { + level->objects[obj->getLayer()].insert(oldIndex, obj); + deletable = false; +} + +void DeleteBgdatObject::redo() { + level->objects[obj->getLayer()].removeOne(obj); + deletable = true; +} + + +RaiseBgdatLayer::RaiseBgdatLayer(Level *level, BgdatObject *obj) : + level(level), + obj(obj), + prevLayer(obj->getLayer()), + prevIndex(level->objects[prevLayer].indexOf(obj)) { + this->setText(QObject::tr("Raised Layer of Object")); +} + +void RaiseBgdatLayer::undo() { + level->objects[newLayer].removeOne(obj); + level->objects[prevLayer].insert(prevIndex, obj); + obj->setLayer(prevLayer); +} + +void RaiseBgdatLayer::redo() { + level->raiseLayer(obj); + newLayer = obj->getLayer(); +} + + +LowerBgdatLayer::LowerBgdatLayer(Level *level, BgdatObject *obj) : + level(level), + obj(obj), + prevLayer(obj->getLayer()), + prevIndex(level->objects[prevLayer].indexOf(obj)) { + this->setText(QObject::tr("Lowered Layer of Object")); +} + +void LowerBgdatLayer::undo() { + level->objects[newLayer].removeOne(obj); + level->objects[prevLayer].insert(prevIndex, obj); + obj->setLayer(prevLayer); +} + +void LowerBgdatLayer::redo() { + level->lowerLayer(obj); + newLayer = obj->getLayer(); +} + + +InsertSprite::InsertSprite(Level *level, Sprite *spr) : + level(level), + spr(spr) { + this->setText(QObject::tr("Inserted Sprite %1 at X: %2 Y: %3").arg(spr->getid()).arg(spr->getx()).arg(spr->gety())); +} + +InsertSprite::~InsertSprite() { + if (deletable) { + delete spr; + } +} + +void InsertSprite::undo() { + level->sprites.removeOne(spr); + + if (level->isCameraLimit(spr)) { + level->removeCameraLimit(spr); + } + + deletable = true; +} + +void InsertSprite::redo() { + level->sprites.append(spr); + + if (level->isCameraLimit(spr)) { + level->insertCameraLimit(spr); + } + + deletable = false; +} + + +DeleteSprite::DeleteSprite(Level *level, Sprite *spr) : + level(level), + spr(spr), + oldIndex(level->sprites.indexOf(spr)) { + this->setText(QObject::tr("Deleted Sprite")); +} + +DeleteSprite::~DeleteSprite() { + if (deletable) { + delete spr; + } +} + +void DeleteSprite::undo() { + level->sprites.insert(oldIndex, spr); + + if (level->isCameraLimit(spr)) { + level->insertCameraLimit(spr); + } + + deletable = false; +} + +void DeleteSprite::redo() { + level->sprites.removeOne(spr); + + if (level->isCameraLimit(spr)) { + level->removeCameraLimit(spr); + } + + deletable = true; +} + + +InsertEntrance::InsertEntrance(Level *level, Entrance *entr) : + level(level), + entr(entr) { + this->setText(QObject::tr("Inserted Entrance at X: %1 Y: %2").arg(entr->getx()).arg(entr->gety())); +} + +InsertEntrance::~InsertEntrance() { + if (deletable) { + delete entr; + } +} + +void InsertEntrance::undo() { + level->entrances.removeOne(entr); + deletable = true; +} + +void InsertEntrance::redo() { + level->entrances.append(entr); + deletable = false; +} + + +DeleteEntrance::DeleteEntrance(Level *level, Entrance *entr) : + level(level), + entr(entr), + oldIndex(level->entrances.indexOf(entr)) { + this->setText(QObject::tr("Deleted Entrance")); +} + +DeleteEntrance::~DeleteEntrance() { + if (deletable) { + delete entr; + } +} + +void DeleteEntrance::undo() { + level->entrances.insert(oldIndex, entr); + deletable = false; +} + +void DeleteEntrance::redo() { + level->entrances.removeOne(entr); + deletable = true; +} + + +InsertZone::InsertZone(Level *level, Zone *zone) : + level(level), + zone(zone) { + this->setText(QObject::tr("Inserted Zone at X: %1 Y: %2").arg(zone->getx()).arg(zone->gety())); +} + +InsertZone::~InsertZone() { + if (deletable) { + delete zone; + } +} + +void InsertZone::undo() { + level->zones.removeOne(zone); + deletable = true; +} + +void InsertZone::redo() { + level->zones.append(zone); + deletable = false; +} + + +DeleteZone::DeleteZone(Level *level, Zone *zone) : + level(level), + zone(zone), + oldIndex(level->zones.indexOf(zone)) { + this->setText(QObject::tr("Deleted Zone")); +} + +DeleteZone::~DeleteZone() { + if (deletable) { + delete zone; + } +} + +void DeleteZone::undo() { + level->zones.insert(oldIndex, zone); + deletable = false; +} + +void DeleteZone::redo() { + level->zones.removeOne(zone); + deletable = true; +} + + +InsertZoneBackground::InsertZoneBackground(Level *level, ZoneBackground *background) : + level(level), + background(background) { + this->setText(QObject::tr("Inserted Zone Background")); +} + +InsertZoneBackground::~InsertZoneBackground() { + if (deletable) { + delete background; + } +} + +void InsertZoneBackground::undo() { + level->backgrounds.removeOne(background); + deletable = true; +} + +void InsertZoneBackground::redo() { + level->backgrounds.append(background); + deletable = false; +} + + +DeleteZoneBackground::DeleteZoneBackground(Level *level, ZoneBackground *background) : + level(level), + background(background) { + this->setText(QObject::tr("Deleted Zone Background")); +} + +DeleteZoneBackground::~DeleteZoneBackground() { + if (deletable) { + delete background; + } +} + +void DeleteZoneBackground::undo() { + level->backgrounds.append(background); + deletable = false; +} + +void DeleteZoneBackground::redo() { + level->backgrounds.removeOne(background); + deletable = true; +} + + +InsertZoneBounding::InsertZoneBounding(Level *level, ZoneBounding *bounding) : + level(level), + bounding(bounding) { + this->setText(QObject::tr("Inserted Zone Bounding")); +} + +InsertZoneBounding::~InsertZoneBounding() { + if (deletable) { + delete bounding; + } +} + +void InsertZoneBounding::undo() { + level->boundings.removeOne(bounding); + deletable = true; +} + +void InsertZoneBounding::redo() { + level->boundings.append(bounding); + deletable = false; +} + + +DeleteZoneBounding::DeleteZoneBounding(Level *level, ZoneBounding *bounding) : + level(level), + bounding(bounding) { + this->setText(QObject::tr("Deleted Zone Bounding")); +} + +DeleteZoneBounding::~DeleteZoneBounding() { + if (deletable) { + delete bounding; + } +} + +void DeleteZoneBounding::undo() { + level->boundings.append(bounding); + deletable = false; +} + +void DeleteZoneBounding::redo() { + level->boundings.removeOne(bounding); + deletable = true; +} + + +InsertLocation::InsertLocation(Level *level, Location *location) : + level(level), + location(location) { + this->setText(QObject::tr("Inserted Location at X: %1 Y: %2").arg(location->getx()).arg(location->gety())); +} + +InsertLocation::~InsertLocation() { + if (deletable) { + delete location; + } +} + +void InsertLocation::undo() { + level->locations.removeOne(location); + deletable = true; +} + +void InsertLocation::redo() { + level->locations.append(location); + deletable = false; +} + + +DeleteLocation::DeleteLocation(Level *level, Location *loc) : + level(level), + loc(loc), + oldIndex(level->locations.indexOf(loc)) { + this->setText(QObject::tr("Deleted Location")); +} + +DeleteLocation::~DeleteLocation() { + if (deletable) { + delete loc; + } +} + +void DeleteLocation::undo() { + level->locations.insert(oldIndex, loc); + deletable = false; +} + +void DeleteLocation::redo() { + level->locations.removeOne(loc); + deletable = true; +} + + +InsertPath::InsertPath(Level *level, Path *path) : + level(level), + path(path) { + this->setText(QObject::tr("Inserted Path %1").arg(path->getid())); +} + +InsertPath::~InsertPath() { + if (deletable) { + delete path; + } +} + +void InsertPath::undo() { + level->paths.removeOne(path); + deletable = true; +} + +void InsertPath::redo() { + level->paths.append(path); + deletable = false; +} + + +DeletePathNode::DeletePathNode(Level *level, PathNode *node) : + level(level), + node(node), + path(node->getParentPath()), + oldNodeIndex(path->getIndexOfNode(node)) { + + if (path->getNumberOfNodes() <= 1) { + wasLastNode = true; + oldPathIndex = level->paths.indexOf(path); + } + + this->setText(QObject::tr("Deleted PathNode")); +} + +DeletePathNode::~DeletePathNode() { + if (deletable) { + delete node; + + if (wasLastNode) { + delete path; + } + } +} + +void DeletePathNode::undo() { + if (wasLastNode) { + level->paths.insert(oldPathIndex, path); + } + + path->insertNode(node, oldNodeIndex); + deletable = false; +} + +void DeletePathNode::redo() { + path->removeNode(node); + + if (wasLastNode) { + level->paths.removeOne(path); + } + + deletable = true; +} + + +InsertProgressPath::InsertProgressPath(Level *level, ProgressPath *path) : + level(level), + path(path) { + this->setText(QObject::tr("Inserted Progress Path %1").arg(path->getid())); +} + +InsertProgressPath::~InsertProgressPath() { + if (deletable) { + delete path; + } +} + +void InsertProgressPath::undo() { + level->progressPaths.removeOne(path); + deletable = true; +} + +void InsertProgressPath::redo() { + level->progressPaths.append(path); + deletable = false; +} + + +DeleteProgressPathNode::DeleteProgressPathNode(Level *level, ProgressPathNode *node) : + level(level), + node(node), + path(node->getParentPath()), + oldNodeIndex(path->getIndexOfNode(node)) { + + if (path->getNumberOfNodes() <= 1) { + wasLastNode = true; + oldPathIndex = level->progressPaths.indexOf(path); + } + + this->setText(QObject::tr("Deleted ProgressPathNode")); +} + +DeleteProgressPathNode::~DeleteProgressPathNode() { + if (deletable) { + delete node; + + if (wasLastNode) { + delete path; + } + } +} + +void DeleteProgressPathNode::undo() { + if (wasLastNode) { + level->progressPaths.insert(oldPathIndex, path); + } + + path->insertNode(node, oldNodeIndex); + deletable = false; +} + +void DeleteProgressPathNode::redo() { + path->removeNode(node); + + if (wasLastNode) { + level->progressPaths.removeOne(path); + } + + deletable = true; +} + +} // namespace Commands::LevelCmd diff --git a/leveleditor/commands/levelcommands.h b/leveleditor/commands/levelcommands.h new file mode 100644 index 00000000..304e99ff --- /dev/null +++ b/leveleditor/commands/levelcommands.h @@ -0,0 +1,392 @@ +#ifndef COMMANDS_LEVELCMD_H +#define COMMANDS_LEVELCMD_H + +#include + +#include "level.h" + +namespace Commands::LevelCmd { + +class RaiseObject : public QUndoCommand +{ +public: + RaiseObject(Level *level, Object *obj); + + void undo() override; + void redo() override; + +private: + Level *const level; + Object *const obj; +}; + + +class LowerObject : public QUndoCommand +{ +public: + LowerObject(Level *level, Object *obj); + + void undo() override; + void redo() override; + +private: + Level *level; + Object *obj; +}; + + +class SetTileset : public QUndoCommand +{ +public: + SetTileset(Level *level, quint8 tsSlot, Tileset* tileset); + ~SetTileset() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + const quint8 tsSlot; + Tileset *newTs; + Tileset *oldTs; + bool newTsDeletable = false; +}; + + +class InsertBgdatObj : public QUndoCommand +{ +public: + InsertBgdatObj(Level *level, BgdatObject *obj); + ~InsertBgdatObj() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + BgdatObject *obj; + bool deletable = false; +}; + + +class DeleteBgdatObject : public QUndoCommand +{ +public: + DeleteBgdatObject(Level *level, BgdatObject *obj); + ~DeleteBgdatObject() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + BgdatObject *obj; + quint32 oldIndex; + bool deletable = false; +}; + + +class RaiseBgdatLayer : public QUndoCommand +{ +public: + RaiseBgdatLayer(Level *level, BgdatObject *obj); + + void undo() override; + void redo() override; + +private: + Level *level; + BgdatObject *obj; + quint32 prevLayer; + quint32 newLayer; + quint32 prevIndex; +}; + + +class LowerBgdatLayer : public QUndoCommand +{ +public: + LowerBgdatLayer(Level *level, BgdatObject *obj); + + void undo() override; + void redo() override; + +private: + Level *level; + BgdatObject *obj; + quint32 prevLayer; + quint32 newLayer; + quint32 prevIndex; +}; + + +class InsertSprite : public QUndoCommand +{ +public: + InsertSprite(Level *level, Sprite *spr); + ~InsertSprite() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Sprite *spr; + bool deletable = false; +}; + + +class DeleteSprite : public QUndoCommand +{ +public: + DeleteSprite(Level *level, Sprite *spr); + ~DeleteSprite() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Sprite *spr; + quint32 oldIndex; + bool deletable; +}; + + +class InsertEntrance : public QUndoCommand +{ +public: + InsertEntrance(Level *level, Entrance *entr); + ~InsertEntrance() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Entrance *entr; + bool deletable = false; +}; + + +class DeleteEntrance : public QUndoCommand +{ +public: + DeleteEntrance(Level *level, Entrance *entr); + ~DeleteEntrance() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Entrance *entr; + quint32 oldIndex; + bool deletable = false; +}; + + +class InsertZone : public QUndoCommand +{ +public: + InsertZone(Level *level, Zone *zone); + ~InsertZone() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Zone *zone; + bool deletable = false; +}; + + +class DeleteZone : public QUndoCommand +{ +public: + DeleteZone(Level *level, Zone *zone); + ~DeleteZone() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Zone *zone; + quint32 oldIndex; + bool deletable = false; +}; + + +class InsertZoneBackground : public QUndoCommand +{ +public: + InsertZoneBackground(Level *level, ZoneBackground *background); + ~InsertZoneBackground() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ZoneBackground *background; + bool deletable = false; +}; + + +class DeleteZoneBackground : public QUndoCommand +{ +public: + DeleteZoneBackground(Level *level, ZoneBackground *background); + ~DeleteZoneBackground() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ZoneBackground *background; + bool deletable = false; +}; + + +class InsertZoneBounding : public QUndoCommand +{ +public: + InsertZoneBounding(Level *level, ZoneBounding *bounding); + ~InsertZoneBounding() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ZoneBounding *bounding; + bool deletable = false; +}; + + +class DeleteZoneBounding : public QUndoCommand +{ +public: + DeleteZoneBounding(Level *level, ZoneBounding *bounding); + ~DeleteZoneBounding() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ZoneBounding *bounding; + bool deletable = false; +}; + + +class InsertLocation : public QUndoCommand +{ +public: + InsertLocation(Level *level, Location *location); + ~InsertLocation() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Location *location; + bool deletable = false; +}; + + +class DeleteLocation : public QUndoCommand +{ +public: + DeleteLocation(Level *level, Location *loc); + ~DeleteLocation() override; + + void undo() override; + void redo() override; + +private: + Level *level; + Location *loc; + quint32 oldIndex; + bool deletable = false; +}; + + +class InsertPath : public QUndoCommand +{ +public: + InsertPath(Level *level, Path *path); + ~InsertPath() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + Path *path; + bool deletable = false; +}; + + +class DeletePathNode : public QUndoCommand +{ +public: + DeletePathNode(Level *level, PathNode *node); + ~DeletePathNode() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + PathNode *node; + Path *path; + quint32 oldNodeIndex; + quint32 oldPathIndex; + bool wasLastNode = false; + bool deletable = false; +}; + + +class InsertProgressPath : public QUndoCommand +{ +public: + InsertProgressPath(Level *level, ProgressPath *path); + ~InsertProgressPath() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ProgressPath *path; + bool deletable = false; +}; + + +class DeleteProgressPathNode : public QUndoCommand +{ +public: + DeleteProgressPathNode(Level *level, ProgressPathNode *node); + ~DeleteProgressPathNode() override; + + void undo() override; + void redo() override; + +private: + Level *const level; + ProgressPathNode *node; + ProgressPath *path; + quint32 oldNodeIndex; + quint32 oldPathIndex; + bool wasLastNode = false; + bool deletable = false; +}; + +} // namespace Commands::LevelCmd + +#endif // EDITORCOMMAND_LEVELCMD_H diff --git a/leveleditor/commands/locationcommands.cpp b/leveleditor/commands/locationcommands.cpp new file mode 100644 index 00000000..12c23b13 --- /dev/null +++ b/leveleditor/commands/locationcommands.cpp @@ -0,0 +1,20 @@ +#include "locationcommands.h" + +namespace Commands::LocationCmd { + +SetId::SetId(Location *loc, quint8 id) : + loc(loc), + newId(id), + oldId(loc->getid()) { + this->setText(QObject::tr("Location ID Changed")); +} + +void SetId::undo() { + loc->setId(oldId); +} + +void SetId::redo() { + loc->setId(newId); +} + +} // namespace Commands::LocationCmd diff --git a/leveleditor/commands/locationcommands.h b/leveleditor/commands/locationcommands.h new file mode 100644 index 00000000..6b32fe9a --- /dev/null +++ b/leveleditor/commands/locationcommands.h @@ -0,0 +1,26 @@ +#ifndef COMMANDS_LOCATIONCMD_H +#define COMMANDS_LOCATIONCMD_H + +#include + +#include "objects.h" + +namespace Commands::LocationCmd { + +class SetId : public QUndoCommand +{ +public: + SetId(Location *loc, quint8 id); + + void undo() override; + void redo() override; + +private: + Location *const loc; + const quint8 newId; + const quint8 oldId; +}; + +} // namespace Commands::LocationCmd + +#endif // COMMANDS_LOCATIONCMD_H diff --git a/leveleditor/commands/objectcommands.cpp b/leveleditor/commands/objectcommands.cpp new file mode 100644 index 00000000..f57235c7 --- /dev/null +++ b/leveleditor/commands/objectcommands.cpp @@ -0,0 +1,123 @@ +#include "objectcommands.h" + +namespace Commands::ObjectCmd { + +IncreasePosition::IncreasePosition(Object *obj, quint32 deltaX, quint32 deltaY, quint32 snap) : + obj(obj), + deltaX(deltaX), + deltaY(deltaY), + snap(snap), + oldX(obj->getx()), + oldY(obj->gety()) { + this->setText(QObject::tr("Increased object position")); +} + +void IncreasePosition::undo() { + obj->setPosition(oldX, oldY); +} + +void IncreasePosition::redo() { + obj->increasePosition(deltaX, deltaY, snap); +} + +bool IncreasePosition::mergeWith(const QUndoCommand *otherCommand) { + if (otherCommand->id() != this->id()) + return false; + + const IncreasePosition* otherIncrease = static_cast(otherCommand); + + if (otherIncrease->obj != this->obj) { + return false; + } + + deltaX += otherIncrease->deltaX; + deltaY += otherIncrease->deltaY; + return true; +} + + +Move::Move(Object *obj, quint32 x, quint32 y) : + obj(obj), + newX(x), + newY(y), + oldX(obj->getx()), + oldY(obj->gety()) { + this->setText(QObject::tr("Object Moved to X: %1 Y: %2").arg(newX).arg(newY)); +} + +void Move::undo() { + obj->setPosition(oldX, oldY); +} + +void Move::redo() { + obj->setPosition(newX, newY); +} + +bool Move::mergeWith(const QUndoCommand *otherCommand) { + if (otherCommand->id() != this->id()) + return false; + + const Move* otherMove = static_cast(otherCommand); + + if (otherMove->obj != this->obj) { + return false; + } + + newX = otherMove->newX; + newY = otherMove->newY; + return true; +} + + +Resize::Resize(Object *obj, quint32 w, quint32 h) : + obj(obj), + oldW(obj->getwidth()), + oldH(obj->getheight()), + newW(w), + newH(h) { + this->setText(QObject::tr("Object Resized to W: %1 H: %2").arg(newW).arg(newH)); +} + +void Resize::undo() { + obj->resize(oldW, oldH); +} + +void Resize::redo() { + obj->resize(newW, newH); +} + +bool Resize::mergeWith(const QUndoCommand *otherCommand) { + if (otherCommand->id() != this->id()) + return false; + + const Resize* otherResize = static_cast(otherCommand); + + if (otherResize->obj != this->obj) { + return false; + } + + newW = otherResize->newW; + newH = otherResize->newH; + return true; +} + + +IncreaseSize::IncreaseSize(Object *obj, quint32 deltaX, quint32 deltaY, quint32 snap) : + obj(obj), + deltaX(deltaX), + deltaY(deltaY), + snap(snap), + oldW(obj->getwidth()), + oldH(obj->getheight()) { + this->setText(QObject::tr("Increased object size")); +} + +void IncreaseSize::undo() { + obj->resize(oldW, oldH); +} + +void IncreaseSize::redo() { + obj->increaseSize(deltaX, deltaY, snap); +} + +} // namespace Commands::ObjectCmd diff --git a/leveleditor/commands/objectcommands.h b/leveleditor/commands/objectcommands.h new file mode 100644 index 00000000..7286684e --- /dev/null +++ b/leveleditor/commands/objectcommands.h @@ -0,0 +1,88 @@ +#ifndef COMMANDS_OBJECTCMD_H +#define COMMANDS_OBJECTCMD_H + +#include + +#include "commandids.h" +#include "objects.h" + +namespace Commands::ObjectCmd { + +class IncreasePosition : public QUndoCommand +{ +public: + IncreasePosition(Object *obj, quint32 deltaX, quint32 deltaY, quint32 snap = 0); + + void undo() override; + void redo() override; + int id() const override { return CommandID::Cmd_IncreasePosition; } + bool mergeWith(const QUndoCommand *otherCommand) override; + +private: + Object *obj; + quint32 deltaX; + quint32 deltaY; + quint32 snap; + quint32 oldX; + quint32 oldY; +}; + + +class Move : public QUndoCommand +{ +public: + Move(Object *obj, quint32 x, quint32 y); + + void undo() override; + void redo() override; + int id() const override { return CommandID::Cmd_Move; } + bool mergeWith(const QUndoCommand *otherCommand) override; + +private: + Object *obj; + quint32 newX; + quint32 newY; + quint32 oldX; + quint32 oldY; +}; + + +class Resize : public QUndoCommand +{ +public: + Resize(Object *obj, quint32 w, quint32 h); + + void undo() override; + void redo() override; + int id() const override { return CommandID::Cmd_Resize; } + bool mergeWith(const QUndoCommand *otherCommand) override; + +private: + Object *obj; + quint32 oldW; + quint32 oldH; + quint32 newW; + quint32 newH; +}; + + +class IncreaseSize : public QUndoCommand +{ +public: + IncreaseSize(Object *obj, quint32 deltaX, quint32 deltaY, quint32 snap = 0); + + void undo() override; + void redo() override; + +private: + Object *obj; + quint32 deltaX; + quint32 deltaY; + quint32 snap; + quint32 oldW; + quint32 oldH; +}; + +} // namespace Commands::ObjectCmd + +#endif // COMMANDS_OBJECTCMD_H diff --git a/leveleditor/commands/pathcommands.cpp b/leveleditor/commands/pathcommands.cpp new file mode 100644 index 00000000..7a4c0ae0 --- /dev/null +++ b/leveleditor/commands/pathcommands.cpp @@ -0,0 +1,77 @@ +#include "pathcommands.h" + +namespace Commands::PathCmd { + + +InsertNode::InsertNode(Path *path, PathNode *node, quint32 index) : + path(path), + node(node), + index(index) { + this->setText(QObject::tr("Inserted Node into Path %1 at X: %2 Y: %3").arg(path->getid()).arg(node->getx()).arg(node->gety())); +} + +InsertNode::~InsertNode() { + if (deletable) { + delete node; + } +} + +void InsertNode::undo() { + path->removeNode(node); + deletable = true; +} + +void InsertNode::redo() { + path->insertNode(node, index); + deletable = false; +} + + +SetId::SetId(Path *path, qint32 id) : + path(path), + newId(id), + oldId(path->getid()) { + this->setText(QObject::tr("Changed Path ID")); +} + +void SetId::undo() { + path->setId(oldId); +} + +void SetId::redo() { + path->setId(newId); +} + + +SetLoop::SetLoop(Path *path, qint32 loop) : + path(path), + newLoop(loop), + oldLoop(path->getLoop()) { + this->setText(QObject::tr("Changed Path Loop")); +} + +void SetLoop::undo() { + path->setLoop(oldLoop); +} + +void SetLoop::redo() { + path->setLoop(newLoop); +} + + +SwapNodes::SwapNodes(Path *path, qsizetype node1, qsizetype node2) : + path(path), + node1(node1), + node2(node2) { + this->setText(QObject::tr("Swapped Path Nodes")); +} + +void SwapNodes::undo() { + path->swapNodes(node2, node1); +} + +void SwapNodes::redo() { + path->swapNodes(node1, node2); +} + +} // namespace Commands::PathCmd diff --git a/leveleditor/commands/pathcommands.h b/leveleditor/commands/pathcommands.h new file mode 100644 index 00000000..ecda2f33 --- /dev/null +++ b/leveleditor/commands/pathcommands.h @@ -0,0 +1,73 @@ +#ifndef COMMANDS_PATHCMD_H +#define COMMANDS_PATHCMD_H + +#include + +#include "objects.h" + +namespace Commands::PathCmd { + +class InsertNode : public QUndoCommand +{ +public: + InsertNode(Path *path, PathNode *node, quint32 index = -1); + ~InsertNode() override; + + void undo() override; + void redo() override; + +private: + Path *const path; + PathNode *node; + const quint32 index; + bool deletable = false; +}; + + +class SetId : public QUndoCommand +{ +public: + SetId(Path *path, qint32 id); + + void undo() override; + void redo() override; + +private: + Path *const path; + const qint32 newId; + const qint32 oldId; +}; + + +class SetLoop : public QUndoCommand +{ +public: + SetLoop(Path *path, qint32 loop); + + void undo() override; + void redo() override; + +private: + Path *const path; + const qint32 newLoop; + const qint32 oldLoop; +}; + + +class SwapNodes : public QUndoCommand +{ +public: + SwapNodes(Path *path, qsizetype node1, qsizetype node2); + + void undo() override; + void redo() override; + +private: + Path *const path; + const qsizetype node1; + const qsizetype node2; +}; + +} // namespace Commands::PathCmd + +#endif // COMMANDS_PATHCMD_H diff --git a/leveleditor/commands/pathnodecommands.cpp b/leveleditor/commands/pathnodecommands.cpp new file mode 100644 index 00000000..d0ef3bcf --- /dev/null +++ b/leveleditor/commands/pathnodecommands.cpp @@ -0,0 +1,100 @@ +#include "pathnodecommands.h" + +namespace Commands::PathNodeCmd { + +SetSpeed::SetSpeed(PathNode *node, float speed) : + node(node), + newSpeed(speed), + oldSpeed(node->getSpeed()) { + this->setText(QObject::tr("Changed Path Node Speed")); +} + +void SetSpeed::undo() { + node->setSpeed(oldSpeed); +} + +void SetSpeed::redo() { + node->setSpeed(newSpeed); +} + + +SetAccel::SetAccel(PathNode *node, float accel) : + node(node), + newAccel(accel), + oldAccel(node->getAccel()) { + this->setText(QObject::tr("Changed Path Node Acceleration")); +} + +void SetAccel::undo() { + node->setAccel(oldAccel); +} + +void SetAccel::redo() { + node->setAccel(newAccel); +} + + +SetDelay::SetDelay(PathNode *node, quint16 delay) : + node(node), + newDelay(delay), + oldDelay(node->getDelay()) { + this->setText(QObject::tr("Changed Path Node Delay")); +} + +void SetDelay::undo() { + node->setDelay(oldDelay); +} + +void SetDelay::redo() { + node->setDelay(newDelay); +} + + +SetRotation::SetRotation(PathNode *node, qint16 rotation) : + node(node), + newRotation(rotation), + oldRotation(node->getRotation()) { + this->setText(QObject::tr("Changed Path Node Rotation")); +} + +void SetRotation::undo() { + node->setRotation(oldRotation); +} + +void SetRotation::redo() { + node->setRotation(newRotation); +} + + +SetVariableField::SetVariableField(PathNode *node, quint8 value) : + node(node), + newValue(value), + oldValue(node->getVariableField()) { + this->setText(QObject::tr("Changed Path Node Variable Field")); +} + +void SetVariableField::undo() { + node->setVariableField(oldValue); +} + +void SetVariableField::redo() { + node->setVariableField(newValue); +} + + +SetNextPathID::SetNextPathID(PathNode *node, quint8 id) : + node(node), + newId(id), + oldId(node->getNextPathID()) { + this->setText(QObject::tr("Changed Path Node Next Path ID")); +} + +void SetNextPathID::undo() { + node->setNextPathID(oldId); +} + +void SetNextPathID::redo() { + node->setNextPathID(newId); +} + +} // namespace Commands::PathNodeCmd diff --git a/leveleditor/commands/pathnodecommands.h b/leveleditor/commands/pathnodecommands.h new file mode 100644 index 00000000..0e3fc0eb --- /dev/null +++ b/leveleditor/commands/pathnodecommands.h @@ -0,0 +1,101 @@ +#ifndef COMMANDS_PATHNODECMD_H +#define COMMANDS_PATHNODECMD_H + +#include + +#include "objects.h" + +namespace Commands::PathNodeCmd { + +class SetSpeed : public QUndoCommand +{ +public: + SetSpeed(PathNode *node, float speed); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const float newSpeed; + const float oldSpeed; +}; + + +class SetAccel : public QUndoCommand +{ +public: + SetAccel(PathNode *node, float accel); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const float newAccel; + const float oldAccel; +}; + + +class SetDelay : public QUndoCommand +{ +public: + SetDelay(PathNode *node, quint16 delay); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const quint16 newDelay; + const quint16 oldDelay; +}; + + +class SetRotation : public QUndoCommand +{ +public: + SetRotation(PathNode *node, qint16 rotation); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const qint16 newRotation; + const qint16 oldRotation; +}; + + +class SetVariableField : public QUndoCommand +{ +public: + SetVariableField(PathNode *node, quint8 value); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const quint8 newValue; + const quint8 oldValue; +}; + + +class SetNextPathID : public QUndoCommand +{ +public: + SetNextPathID(PathNode *node, quint8 id); + + void undo() override; + void redo() override; + +private: + PathNode *const node; + const quint8 newId; + const quint8 oldId; +}; + +} // namespace Commands::PathNodeCmd + +#endif // COMMANDS_PATHNODECMD_H diff --git a/leveleditor/commands/progresspathcommands.cpp b/leveleditor/commands/progresspathcommands.cpp new file mode 100644 index 00000000..c6b21bfb --- /dev/null +++ b/leveleditor/commands/progresspathcommands.cpp @@ -0,0 +1,63 @@ +#include "progresspathcommands.h" + +namespace Commands::ProgressPathCmd { + +InsertNode::InsertNode(ProgressPath *path, ProgressPathNode *node, quint32 index) : + path(path), + node(node), + index(index) { + this->setText(QObject::tr("Inserted Node into Progress Path %1 at X: %2 Y: %3").arg(path->getid()).arg(node->getx()).arg(node->gety())); +} + +InsertNode::~InsertNode() { + if (deletable) { + delete node; + } +} + +void InsertNode::undo() { + path->removeNode(node); + deletable = true; +} + +void InsertNode::redo() { + path->insertNode(node, index); + deletable = false; +} + + +SetId::SetId(ProgressPath *path, qint32 id) : + path(path), + newId(id), + oldId(path->getid()) { + this->setText(QObject::tr("Changed Progress Path ID")); +} + +void SetId::undo() { + path->setId(oldId); +} + +void SetId::redo() { + path->setId(newId); +} + + +SetAltPathFlag::SetAltPathFlag(ProgressPath *path, quint8 flag) : + path(path), + newFlag(flag), + oldFlag(path->getAlternatePathFlag()) { + this->setText(QObject::tr("Changed Progress Alt Flag")); + if (flag == path->getAlternatePathFlag()) { + this->setObsolete(true); + } +} + +void SetAltPathFlag::undo() { + path->setAlternatePathFlag(oldFlag); +} + +void SetAltPathFlag::redo() { + path->setAlternatePathFlag(newFlag); +} + +} // namespace Commands::ProgressPathCmd diff --git a/leveleditor/commands/progresspathcommands.h b/leveleditor/commands/progresspathcommands.h new file mode 100644 index 00000000..c668534f --- /dev/null +++ b/leveleditor/commands/progresspathcommands.h @@ -0,0 +1,58 @@ +#ifndef COMMANDS_PROGRESSPATHCMD_H +#define COMMANDS_PROGRESSPATHCMD_H + +#include + +#include "objects.h" + +namespace Commands::ProgressPathCmd { + +class InsertNode : public QUndoCommand +{ +public: + InsertNode(ProgressPath *path, ProgressPathNode *node, quint32 index = -1); + ~InsertNode() override; + + void undo() override; + void redo() override; + +private: + ProgressPath *path; + ProgressPathNode *node; + quint32 index; + bool deletable = false; +}; + + +class SetId : public QUndoCommand +{ +public: + SetId(ProgressPath *path, qint32 id); + + void undo() override; + void redo() override; + +private: + ProgressPath *const path; + const qint32 newId; + const qint32 oldId; +}; + + +class SetAltPathFlag : public QUndoCommand +{ +public: + SetAltPathFlag(ProgressPath *path, quint8 flag); + + void undo() override; + void redo() override; + +private: + ProgressPath *const path; + const quint8 newFlag; + const quint8 oldFlag; +}; + +} // namespace Commands::ProgressPathCmd + +#endif // COMMANDS_PROGRESSPATHCMD_H diff --git a/leveleditor/commands/setvalue.h b/leveleditor/commands/setvalue.h new file mode 100644 index 00000000..ce4e0eb0 --- /dev/null +++ b/leveleditor/commands/setvalue.h @@ -0,0 +1,70 @@ +#ifndef EDITORCOMMAND_SETVALUE_H +#define EDITORCOMMAND_SETVALUE_H + +#include +#include + +#include "commandids.h" + +using namespace Commands; + +namespace EditorCommand { + +template +class SetValue : public QUndoCommand { +public: + SetValue(T *value, T newValue, QString message); + ~SetValue() {} + + void undo() override; + void redo() override; + int id() const override; + bool mergeWith(const QUndoCommand *otherCommand) override; + +private: + T *value; + T newValue; + T oldValue; +}; + +template +SetValue::SetValue(T *value, T newValue, QString message) : + value(value), newValue(newValue) { + oldValue = *value; + this->setText(message); +} + +template +void SetValue::undo() { + *value = oldValue; +} + +template +void SetValue::redo() { + *value = newValue; +} + +template +int SetValue::id() const { + return CommandID::Cmd_SetValue; +} + +template +bool SetValue::mergeWith(const QUndoCommand *otherCommand) { + if (otherCommand->id() != this->id()) { + return false; + } + + const SetValue *otherSetValue = static_cast(otherCommand); + + if (otherSetValue->value != this->value) { + return false; + } + + newValue = otherSetValue->newValue; + return true; +} + +} // namespace EditorCommand + +#endif // EDITORCOMMAND_SETVALUE_H diff --git a/leveleditor/commands/spritecommands.cpp b/leveleditor/commands/spritecommands.cpp new file mode 100644 index 00000000..67ee526e --- /dev/null +++ b/leveleditor/commands/spritecommands.cpp @@ -0,0 +1,95 @@ +#include "spritecommands.h" + +namespace Commands::SpriteCmd { + +SetId::SetId(Sprite *spr, quint16 id) : + spr(spr), + newId(id), + oldId(spr->getid()){ + this->setText(QObject::tr("Set Sprite Id")); +} + +void SetId::undo() { + this->spr->setid(oldId); +} + +void SetId::redo() { + this->spr->setid(newId); +} + + +SetLayer::SetLayer(Sprite *spr, quint8 layer) : + spr(spr), + newLayer(layer), + oldLayer(spr->getLayer()) { + this->setText(QObject::tr("Set Sprite Layer")); +} + +void SetLayer::undo() { + this->spr->setLayer(oldLayer); +} + +void SetLayer::redo() { + this->spr->setLayer(newLayer); +} + + +SetBits::SetBits(Sprite *spr, qint32 data, qint32 start, qint32 end) : + spr(spr), + newData(data), + oldData(spr->getNybbleData(start, end)), + start(start), + end(end) { + this->setText(QObject::tr("Set Sprite Bits")); +} + +void SetBits::undo() { + this->spr->setBits(oldData, start, end); + this->spr->setRect(); +} + +void SetBits::redo() { + this->spr->setBits(newData, start, end); + this->spr->setRect(); +} + + +SetByte::SetByte(Sprite *spr, qint32 byteIndex, quint8 value) : + spr(spr), + byteIndex(byteIndex), + newValue(value), + oldValue(spr->getByte(byteIndex)) { + this->setText(QObject::tr("Set Byte")); +} + +void SetByte::undo() { + this->spr->setByte(byteIndex, oldValue); + this->spr->setRect(); +} + +void SetByte::redo() { + this->spr->setByte(byteIndex, newValue); + this->spr->setRect(); +} + + +SetNybbleData::SetNybbleData(Sprite *spr, qint32 data, qint32 start, qint32 end) : + spr(spr), + newData(data), + oldData(spr->getNybbleData(start, end)), + start(start), + end(end) { + this->setText(QObject::tr("Set Sprite Nybble Data")); +} + +void SetNybbleData::undo() { + this->spr->setNybbleData(oldData, start, end); + this->spr->setRect(); +} + +void SetNybbleData::redo() { + this->spr->setNybbleData(newData, start, end); + this->spr->setRect(); +} + +} // namespace Commands::SpriteCmd diff --git a/leveleditor/commands/spritecommands.h b/leveleditor/commands/spritecommands.h new file mode 100644 index 00000000..7824779d --- /dev/null +++ b/leveleditor/commands/spritecommands.h @@ -0,0 +1,91 @@ +#ifndef COMMANDS_SPRITECMD_H +#define COMMANDS_SPRITECMD_H + +#include + +#include "objects.h" + +namespace Commands::SpriteCmd { + +class SetId : public QUndoCommand +{ +public: + SetId(Sprite *spr, quint16 id); + + void undo() override; + void redo() override; + +private: + Sprite *spr; + quint16 newId; + quint16 oldId; +}; + + +class SetLayer : public QUndoCommand +{ +public: + SetLayer(Sprite *spr, quint8 layer); + + void undo() override; + void redo() override; + +private: + Sprite *const spr; + const quint8 newLayer; + const quint8 oldLayer; +}; + + +class SetBits : public QUndoCommand +{ +public: + SetBits(Sprite *spr, qint32 data, qint32 start, qint32 end); + + void undo() override; + void redo() override; + +private: + Sprite *const spr; + const qint32 newData; + const qint32 oldData; + const qint32 start; + const qint32 end; +}; + + +class SetByte : public QUndoCommand +{ +public: + SetByte(Sprite *spr, qint32 byteIndex, quint8 value); + + void undo() override; + void redo() override; + +private: + Sprite *const spr; + const qint32 byteIndex; + const quint8 newValue; + const quint8 oldValue; +}; + + +class SetNybbleData : public QUndoCommand +{ +public: + SetNybbleData(Sprite *spr, qint32 data, qint32 start, qint32 end); + + void undo() override; + void redo() override; + +private: + Sprite *const spr; + const qint32 newData; + const qint32 oldData; + const qint32 start; + const qint32 end; +}; + +} // namespace Commands::SpriteCmd + +#endif // COMMANDS_SPRITECMD_H diff --git a/leveleditor/commands/zonebgcommands.cpp b/leveleditor/commands/zonebgcommands.cpp new file mode 100644 index 00000000..2ed3bd64 --- /dev/null +++ b/leveleditor/commands/zonebgcommands.cpp @@ -0,0 +1,86 @@ +#include "zonebgcommands.h" + +#include + +namespace Commands::ZoneBgCmd { + +SetParallaxMode::SetParallaxMode(ZoneBackground *background, quint8 parallax) : + background(background), + oldParallax(background->getParallaxMode()), + newParallax(parallax) { + this->setText(QObject::tr("Set Zone Background Parallax Mode")); +} + +void SetParallaxMode::undo() { + background->setParallaxMode(oldParallax); +} + +void SetParallaxMode::redo() { + background->setParallaxMode(newParallax); +} + + +SetXPos::SetXPos(ZoneBackground *background, qint16 xPos) : + background(background), + oldXPos(background->getXPos()), + newXPos(xPos) { + this->setText(QObject::tr("Set Zone Background X Pos")); +} + +void SetXPos::undo() { + background->setXPos(oldXPos); +} + +void SetXPos::redo() { + background->setXPos(newXPos); +} + + +SetYPos::SetYPos(ZoneBackground *background, qint16 xPos) : + background(background), + oldYPos(background->getYPos()), + newYPos(xPos) { + this->setText(QObject::tr("Set Zone Background Y Pos")); +} + +void SetYPos::undo() { + background->setYPos(oldYPos); +} + +void SetYPos::redo() { + background->setYPos(newYPos); +} + + +SetId::SetId(ZoneBackground *background, quint16 id) : + background(background), + oldId(background->getId()), + newId(id) { + this->setText(QObject::tr("Set Zone Background ID")); +} + +void SetId::undo() { + background->setId(oldId); +} + +void SetId::redo() { + background->setId(newId); +} + + +SetName::SetName(ZoneBackground *background, QString name) : + background(background), + oldName(background->getName()), + newName(std::move(name)) { + this->setText(QObject::tr("Set Zone Background Name")); +} + +void SetName::undo() { + background->setName(oldName); +} + +void SetName::redo() { + background->setName(newName); +} + +} // namespace Commands::ZoneBgCmd diff --git a/leveleditor/commands/zonebgcommands.h b/leveleditor/commands/zonebgcommands.h new file mode 100644 index 00000000..ffb0608a --- /dev/null +++ b/leveleditor/commands/zonebgcommands.h @@ -0,0 +1,86 @@ +#ifndef COMMANDS_ZONEBGCMD_H +#define COMMANDS_ZONEBGCMD_H + +#include + +#include "objects.h" + +namespace Commands::ZoneBgCmd { + +class SetParallaxMode : public QUndoCommand +{ +public: + SetParallaxMode(ZoneBackground *background, quint8 parallax); + + void undo() override; + void redo() override; + +private: + ZoneBackground *const background; + const quint8 oldParallax; + const quint8 newParallax; +}; + + +class SetXPos : public QUndoCommand +{ +public: + SetXPos(ZoneBackground *background, qint16 xPos); + + void undo() override; + void redo() override; + +private: + ZoneBackground *const background; + const qint16 oldXPos; + const qint16 newXPos; +}; + + +class SetYPos : public QUndoCommand +{ +public: + SetYPos(ZoneBackground *background, qint16 yPos); + + void undo() override; + void redo() override; + +private: + ZoneBackground *const background; + const qint16 oldYPos; + const qint16 newYPos; +}; + + +class SetId : public QUndoCommand +{ +public: + SetId(ZoneBackground *background, quint16 id); + + void undo() override; + void redo() override; + +private: + ZoneBackground *const background; + const quint16 oldId; + const quint16 newId; +}; + + +class SetName : public QUndoCommand +{ +public: + SetName(ZoneBackground *background, QString id); + + void undo() override; + void redo() override; + +private: + ZoneBackground *const background; + const QString oldName; + const QString newName; +}; + +} // namespace Commands::ZoneBgCmd + +#endif // COMMANDS_ZONEBGCMD_H diff --git a/leveleditor/commands/zoneboundingcommands.cpp b/leveleditor/commands/zoneboundingcommands.cpp new file mode 100644 index 00000000..87681d7b --- /dev/null +++ b/leveleditor/commands/zoneboundingcommands.cpp @@ -0,0 +1,101 @@ +#include "zoneboundingcommands.h" + +namespace Commands::ZoneBoundingCmd { + +SetUpScrolling::SetUpScrolling(ZoneBounding *bounding, quint16 value) : + bounding(bounding), + newValue(value), + oldValue(bounding->getUpScrolling()) { + this->setText(QObject::tr("Set Zone Bounding Upscrolling")); +} + +void SetUpScrolling::undo() { + bounding->setUpScrolling(oldValue); +} + +void SetUpScrolling::redo() { + bounding->setUpScrolling(newValue); +} + + +SetPrimaryUpperBound::SetPrimaryUpperBound(ZoneBounding *bounding, qint32 value) : + bounding(bounding), + newValue(value), + oldValue(bounding->getPrimaryUpperBound()) { + this->setText(QObject::tr("Set Zone Bounding Primary Upper Bound")); +} + +void SetPrimaryUpperBound::undo() { + bounding->setPrimaryUpperBound(oldValue); +} + +void SetPrimaryUpperBound::redo() { + bounding->setPrimaryUpperBound(newValue); +} + + +SetPrimaryLowerBound::SetPrimaryLowerBound(ZoneBounding *bounding, qint32 value) : + bounding(bounding), + newValue(value), + oldValue(bounding->getPrimaryLowerBound()) { + this->setText(QObject::tr("Set Zone Bounding Primary Lower Bound")); +} + +void SetPrimaryLowerBound::undo() { + bounding->setPrimaryLowerBound(oldValue); +} + +void SetPrimaryLowerBound::redo() { + bounding->setPrimaryLowerBound(newValue); +} + + +SetSecondaryUpperBound::SetSecondaryUpperBound(ZoneBounding *bounding, qint32 value) : + bounding(bounding), + newValue(value), + oldValue(bounding->getSecondaryUpperBound()) { + this->setText(QObject::tr("Set Zone Bounding Secondary Upper Bound")); +} + +void SetSecondaryUpperBound::undo() { + bounding->setSecondaryUpperBound(oldValue); +} + +void SetSecondaryUpperBound::redo() { + bounding->setSecondaryUpperBound(newValue); +} + + +SetSecondaryLowerBound::SetSecondaryLowerBound(ZoneBounding *bounding, qint32 value) : + bounding(bounding), + newValue(value), + oldValue(bounding->getSecondaryLowerBound()) { + this->setText(QObject::tr("Set Zone Bounding Secondary Lower Bound")); +} + +void SetSecondaryLowerBound::undo() { + bounding->setSecondaryLowerBound(oldValue); +} + +void SetSecondaryLowerBound::redo() { + bounding->setSecondaryLowerBound(newValue); +} + + +SetId::SetId(ZoneBounding *bounding, quint16 id) : + bounding(bounding), + newId(id), + oldId(bounding->getId()) { + this->setText(QObject::tr("Set Zone Bounding ID")); +} + +void SetId::undo() { + bounding->setId(oldId); +} + +void SetId::redo() { + bounding->setId(newId); +} + +} // namespace Commands::ZoneBoundingCmd + diff --git a/leveleditor/commands/zoneboundingcommands.h b/leveleditor/commands/zoneboundingcommands.h new file mode 100644 index 00000000..ba3ea33f --- /dev/null +++ b/leveleditor/commands/zoneboundingcommands.h @@ -0,0 +1,102 @@ +#ifndef COMMANDS_ZONEBOUNDINGCMD_H +#define COMMANDS_ZONEBOUNDINGCMD_H + +#include + +#include "objects.h" + +namespace Commands::ZoneBoundingCmd { + +class SetUpScrolling : public QUndoCommand +{ +public: + SetUpScrolling(ZoneBounding *bounding, quint16 value); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const quint16 newValue; + const quint16 oldValue; +}; + + +class SetPrimaryUpperBound : public QUndoCommand +{ +public: + SetPrimaryUpperBound(ZoneBounding *bounding, qint32 value); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const qint32 newValue; + const qint32 oldValue; +}; + + +class SetPrimaryLowerBound : public QUndoCommand +{ +public: + SetPrimaryLowerBound(ZoneBounding *bounding, qint32 value); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const qint32 newValue; + const qint32 oldValue; +}; + + +class SetSecondaryUpperBound : public QUndoCommand +{ +public: + SetSecondaryUpperBound(ZoneBounding *bounding, qint32 value); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const qint32 newValue; + const qint32 oldValue; +}; + + +class SetSecondaryLowerBound : public QUndoCommand +{ +public: + SetSecondaryLowerBound(ZoneBounding *bounding, qint32 value); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const qint32 newValue; + const qint32 oldValue; +}; + + +class SetId : public QUndoCommand +{ +public: + SetId(ZoneBounding *bounding, quint16 id); + + void undo() override; + void redo() override; + +private: + ZoneBounding *const bounding; + const quint16 newId; + const quint16 oldId; +}; + + +} // namespace Commands::ZoneBoundingCmd + +#endif // COMMANDS_ZONEBOUNDINGCMD_H diff --git a/leveleditor/commands/zonecommands.cpp b/leveleditor/commands/zonecommands.cpp new file mode 100644 index 00000000..8e563058 --- /dev/null +++ b/leveleditor/commands/zonecommands.cpp @@ -0,0 +1,116 @@ +#include "zonecommands.h" + +namespace Commands::ZoneCmd { + +SetId::SetId(Zone *zone, quint8 id) : + zone(zone), + newId(id), + oldId(zone->getid()) { + this->setText(QObject::tr("Set Zone ID")); +} + +void SetId::undo() { + zone->setID(oldId); +} + +void SetId::redo() { + zone->setID(newId); +} + + +SetProgPathId::SetProgPathId(Zone *zone, quint8 id) : + zone(zone), + newId(id), + oldId(zone->getProgPathId()) { + this->setText(QObject::tr("Set Zone Progress Path ID")); +} + +void SetProgPathId::undo() { + zone->setProgPathId(oldId); +} + +void SetProgPathId::redo() { + zone->setProgPathId(newId); +} + + +SetMusicId::SetMusicId(Zone *zone, quint8 id) : + zone(zone), + newId(id), + oldId(zone->getMusicId()) { + this->setText(QObject::tr("Set Zone Music ID")); +} + +void SetMusicId::undo() { + zone->setMusicID(oldId); +} + +void SetMusicId::redo() { + zone->setMusicID(newId); +} + + +SetMultiplayerTracking::SetMultiplayerTracking(Zone *zone, quint8 tracking) : + zone(zone), + newTracking(tracking), + oldTracking(zone->getMultiplayerTracking()) { + this->setText(QObject::tr("Set Zone Multiplayer Tracking")); +} + +void SetMultiplayerTracking::undo() { + zone->setMultiplayerTracking(oldTracking); +} + +void SetMultiplayerTracking::redo() { + zone->setMultiplayerTracking(newTracking); +} + + +SetUnk1::SetUnk1(Zone *zone, quint32 value) : + zone(zone), + newValue(value), + oldValue(zone->getUnk1()) { + this->setText(QObject::tr("Set Zone Unk1")); +} + +void SetUnk1::undo() { + zone->setUnk1(oldValue); +} + +void SetUnk1::redo() { + zone->setUnk1(newValue); +} + + +SetBoundingId::SetBoundingId(Zone *zone, quint8 id) : + zone(zone), + newId(id), + oldId(zone->getBoundingId()) { + this->setText(QObject::tr("Set Zone Bounding ID")); +} + +void SetBoundingId::undo() { + zone->setBoundingId(oldId); +} + +void SetBoundingId::redo() { + zone->setBoundingId(newId); +} + + +SetBackgroundId::SetBackgroundId(Zone *zone, quint8 id) : + zone(zone), + newId(id), + oldId(zone->getBackgroundId()) { + this->setText(QObject::tr("Set Zone Background ID")); +} + +void SetBackgroundId::undo() { + zone->setBackgroundId(oldId); +} + +void SetBackgroundId::redo() { + zone->setBackgroundId(newId); +} + +} // namespace Commands::ZoneCmd diff --git a/leveleditor/commands/zonecommands.h b/leveleditor/commands/zonecommands.h new file mode 100644 index 00000000..5ab84220 --- /dev/null +++ b/leveleditor/commands/zonecommands.h @@ -0,0 +1,116 @@ +#ifndef COMMANDS_ZONECMD_H +#define COMMANDS_ZONECMD_H + +#include + +#include "objects.h" + +namespace Commands::ZoneCmd { + +class SetId : public QUndoCommand +{ +public: + SetId(Zone *zone, quint8 id); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newId; + const quint8 oldId; +}; + + +class SetProgPathId : public QUndoCommand +{ +public: + SetProgPathId(Zone *zone, quint8 id); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newId; + const quint8 oldId; +}; + + +class SetMusicId : public QUndoCommand +{ +public: + SetMusicId(Zone *zone, quint8 id); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newId; + const quint8 oldId; +}; + + +class SetMultiplayerTracking : public QUndoCommand +{ +public: + SetMultiplayerTracking(Zone *zone, quint8 tracking); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newTracking; + const quint8 oldTracking; +}; + + +class SetUnk1 : public QUndoCommand +{ +public: + SetUnk1(Zone *zone, quint32 value); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint32 newValue; + const quint32 oldValue; +}; + + +class SetBoundingId : public QUndoCommand +{ +public: + SetBoundingId(Zone *zone, quint8 id); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newId; + const quint8 oldId; +}; + + +class SetBackgroundId : public QUndoCommand +{ +public: + SetBackgroundId(Zone *zone, quint8 id); + + void undo() override; + void redo() override; + +private: + Zone *const zone; + const quint8 newId; + const quint8 oldId; +}; + +} // namespace Commands::ZoneCmd + +#endif // COMMANDS_ZONECMD_H diff --git a/objectseditionmode.cpp b/leveleditor/editmanager.cpp similarity index 65% rename from objectseditionmode.cpp rename to leveleditor/editmanager.cpp index e48edd68..b76a3a3a 100644 --- a/objectseditionmode.cpp +++ b/leveleditor/editmanager.cpp @@ -1,21 +1,28 @@ -#include "objectseditionmode.h" +#include "editmanager.h" #include "unitsconvert.h" #include "settingsmanager.h" #include "is.h" +#include "commands/editorcommands.h" +#include "commands/setvalue.h" +#include "commands/spritecommands.h" +#include "commands/bgdatcommands.h" +#include "commands/pathcommands.h" +#include "commands/levelcommands.h" +#include "commands/objectcommands.h" +#include "commands/progresspathcommands.h" + #include #include #include #include -ObjectsEditonMode::ObjectsEditonMode(Level *level) +EditManager::EditManager(Level *level, QUndoStack *undoStack) : + level(level), undoStack(undoStack) { - this->level = level; this->selectAfterPlacement = SettingsManager::getInstance()->get("SelectAfterPlacement").toBool(); - - selectionMode = false; } -void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, QRect drawrect) +void EditManager::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, QRect drawrect) { dx = x; dy = y; @@ -24,90 +31,8 @@ void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::Ke if (buttons == Qt::RightButton) { - selectedObjects.clear(); - - if (drawType == 0) - { - if (selTileset == -1 || selObject == -1) return; - int id = selTileset << 12; - id = (id & 0xF000) | selObject; - ObjectDef* obj = level->tilesets[selTileset]->getObjectDef(selObject); - BgdatObject* bgdatobj = new BgdatObject(toNext20(x-10), toNext20(y-10), obj->width*20, obj->height*20, id, selLayer); - level->objects[selLayer].append(bgdatobj); - newObject = bgdatobj; - creatNewObject = true; - if (selectAfterPlacement) - selectedObjects.append(bgdatobj); - } - else if (drawType == 1) - { - if (selSprite == -1) return; - Sprite* spr = new Sprite(0, 0, selSprite); - spr->setRect(); - int xpos = toNext10(dx-spr->getwidth()/2-spr->getOffsetX()); - int ypos = toNext10(dy-spr->getheight()/2-spr->getOffsetY()); - if (xpos < 0) xpos = 0; - if (ypos < 0) ypos = 0; - spr->setPosition(xpos, ypos); - level->sprites.append(spr); - level->sortCameraLimits(spr); - if (selectAfterPlacement) - selectedObjects.append(spr); - } - else if (drawType == 2) - { - Entrance* entr = level->newEntrance(x-10, y-10); - entr->setRect(); - level->entrances.append(entr); - if (selectAfterPlacement) - selectedObjects.append(entr); - } - else if (drawType == 3) - { - Zone* zone = level->newZone(x-200, y-120); - level->zones.append(zone); - - if (level->backgrounds.isEmpty()) - level->backgrounds.append(new ZoneBackground()); - - if (level->boundings.isEmpty()) - level->boundings.append(new ZoneBounding()); - - if (selectAfterPlacement) - selectedObjects.append(zone); - } - else if (drawType == 4) - { - Location* loc = level->newLocation(x, y); - level->locations.append(loc); - newObject = loc; - creatNewObject = true; - if (selectAfterPlacement) - selectedObjects.append(loc); - } - else if (drawType == 5) - { - Path* path = level->newPath(); - level->paths.append(path); - PathNode* node = new PathNode(qMax(toNext10(x), 0), qMax(toNext10(y), 0), 0, 0, 0, 0, 0, 0, path); - path->insertNode(node); - if (selectAfterPlacement) - selectedObjects.append(node); - } - else if (drawType == 6) - { - ProgressPath* path = level->newProgressPath(); - level->progressPaths.append(path); - ProgressPathNode* node = new ProgressPathNode(qMax(toNext10(x), 0), qMax(toNext10(y), 0), path); - path->insertNode(node); - if (selectAfterPlacement) - selectedObjects.append(node); - } - - checkEmits(); - emit updateEditors(); - if (selectedObjects.size() == 1) emit selectdObjectChanged(selectedObjects[0]); - emit editMade(); + CreateObject(x, y); + return; } if (buttons == Qt::LeftButton) @@ -123,31 +48,34 @@ void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::Ke { PathNode* oldPNode = dynamic_cast(oldNode); Path* parentPath = oldPNode->getParentPath(); - PathNode* newNode = new PathNode(toNext10(x), toNext10(y), 0, 0, 0, 0, 0, 0, parentPath); - if (mouseAct.pAdd == AddBefore) - parentPath->insertNode(newNode, parentPath->getIndexOfNode(oldPNode)); - else - parentPath->insertNode(newNode, parentPath->getIndexOfNode(oldPNode)+1); - selectedObjects.append(newNode); + PathNode* newNode = new PathNode(toNext10(x), toNext10(y), parentPath); + quint32 index = parentPath->getIndexOfNode(oldPNode); - emit editMade(); + if (mouseAct.pAdd == AddAfter) { + index += 1; + } + + undoStack->push(new Commands::PathCmd::InsertNode(parentPath, newNode, index)); + selectedObjects.append(newNode); } else { ProgressPathNode* oldPNode = dynamic_cast(oldNode); ProgressPath* parentPath = oldPNode->getParentPath(); - ProgressPathNode* newNode = new ProgressPathNode(toNext10(x), toNext10(y), parentPath); - if (mouseAct.pAdd == AddBefore) - parentPath->insertNode(newNode, parentPath->getIndexOfNode(oldPNode)); - else - parentPath->insertNode(newNode, parentPath->getIndexOfNode(oldPNode)+1); - selectedObjects.append(newNode); + quint32 index = parentPath->getIndexOfNode(oldPNode); + + if (mouseAct.pAdd == AddAfter) { + index += 1; + } - emit editMade(); + undoStack->push(new Commands::ProgressPathCmd::InsertNode(parentPath, newNode, index)); + selectedObjects.append(newNode); } - if (selectedObjects.size() == 1) emit selectdObjectChanged(selectedObjects[0]); + if (selectedObjects.size() == 1) { + emit selectdObjectChanged(selectedObjects[0]); + } } else if (!mouseAct.drag || (mouseAct.hor == ResizeNone && mouseAct.vert == ResizeNone)) @@ -155,8 +83,9 @@ void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::Ke QList tempSelObjects = selectedObjects; bool shift = false; - if (modifiers != Qt::ShiftModifier) + if (modifiers != Qt::ShiftModifier) { selectedObjects = getObjectsAtPos(dx, dy, dx, dy, true, drawrect); + } else if (modifiers != Qt::ControlModifier) { shift = true; @@ -177,15 +106,13 @@ void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::Ke if (selectedObjects.size() == 0) { - selectionMode = true; + interactMode = InteractionMode::Selection; } else if (modifiers == Qt::ControlModifier) { sortSelection(); - selectedObjects = cloneObjects(selectedObjects); - level->add(selectedObjects); + cloneObjects(selectedObjects); emit updateEditors(); - emit editMade(); clone = true; } @@ -199,9 +126,9 @@ void ObjectsEditonMode::mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::Ke } } -void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres, QRect drawrect) +void EditManager::mouseDrag(int x, int y, Qt::KeyboardModifiers modifiers, QRect drawrect) { - if (creatNewObject) + if (interactMode == InteractionMode::Creation) { lx = x; ly = y; @@ -211,6 +138,11 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres return; } + if (!resizingObjects) { + undoStack->beginMacro(tr("Resized Selection")); + resizingObjects = true; + } + int xpos = typeRound(dx, newObject->getType()); int ypos = typeRound(dy, newObject->getType()); @@ -220,7 +152,7 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres int w = qAbs(mX-xpos); int h = qAbs(mY-ypos); - if (newObject->getType() == 0) + if (newObject->getType() == ObjectType::BGDATOBJECT) { if (mX < 0) mX = 0; else w += 20; @@ -228,15 +160,15 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres else h += 20; } - newObject->setPosition(qMin(xpos, mX), qMin(ypos, mY)); - newObject->resize(w, h); + undoStack->push(new Commands::ObjectCmd::Move(newObject, qMin(xpos, mX), qMin(ypos, mY))); + undoStack->push(new Commands::ObjectCmd::Resize(newObject, w, h)); emit updateEditors(); return; } - if (selectionMode) + if (interactMode == InteractionMode::Selection) { lx = x; ly = y; @@ -270,7 +202,7 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres yDelta = toNext20(yDelta); snap = 20; } - else if (modifieres == Qt::AltModifier) + else if (modifiers == Qt::AltModifier) { xDelta = toNext16Compatible(xDelta); xDelta = toNext16Compatible(xDelta); @@ -282,9 +214,14 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres snap = 10; } + if (!movingObjects) { + undoStack->beginMacro(tr("Moved Selection")); + movingObjects = true; + } + foreach (Object* obj, selectedObjects) { - obj->increasePosition(xDelta, yDelta, snap); + undoStack->push(new Commands::ObjectCmd::IncreasePosition(obj, xDelta, yDelta, snap)); } minBoundX += xDelta; @@ -293,7 +230,6 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres ly += yDelta; emit updateEditors(); - emit editMade(); } // Resize else @@ -310,7 +246,7 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres minSize = 20; snap = 0; } - else if (modifieres == Qt::AltModifier) + else if (modifiers == Qt::AltModifier) { xDelta = toNext16Compatible(xDelta); xDelta = toNext16Compatible(xDelta); @@ -361,37 +297,181 @@ void ObjectsEditonMode::mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres minSizeX += xResizeDelta; minSizeY += yResizeDelta; + if (!resizingObjects) { + undoStack->beginMacro(tr("Resized Selection")); + resizingObjects = true; + } + foreach (Object* obj, selectedObjects) { - obj->increasePosition(xMoveDelta, yMoveDelta); - if (obj->isResizable()) obj->increaseSize(xResizeDelta, yResizeDelta, snap); + undoStack->push(new Commands::ObjectCmd::IncreasePosition(obj, xMoveDelta, yMoveDelta)); + + if (obj->isResizable()) { + undoStack->push(new Commands::ObjectCmd::IncreaseSize(obj, xResizeDelta, yResizeDelta, snap)); + } } lx += xDelta; ly += yDelta; emit updateEditors(); - emit editMade(); } } } -void ObjectsEditonMode::mouseMove(int x, int y) +void EditManager::mouseMove(int x, int y) { actualCursor = getCursorAtPos(x, y); } -void ObjectsEditonMode::mouseUp(int x, int y) +void EditManager::mouseUp(int x, int y) { mouseAct = getActionAtPos(x, y); actualCursor = getCursorAtPos(x, y); - if (selectionMode) checkEmits(); - selectionMode = false; - creatNewObject = false; + + checkEmits(); + + if (movingObjects) { + undoStack->endMacro(); + movingObjects = false; + } + + if (resizingObjects) { + undoStack->endMacro(); + resizingObjects = false; + } + + interactMode = InteractionMode::None; clone = false; } -void ObjectsEditonMode::render(QPainter *painter) +void EditManager::CreateObject(quint32 x, quint32 y) +{ + selectedObjects.clear(); + + if (drawType == ObjectType::INVALID) { + return; + } + + if (drawType == ObjectType::BGDATOBJECT) + { + if (selTileset == -1 || selObject == -1) { + return; + } + + int id = selTileset << 12; + id = (id & 0xF000) | selObject; + ObjectDef *obj = level->tilesets[selTileset]->getObjectDef(selObject); + BgdatObject *bgdatObj = new BgdatObject(toNext20(x-10), toNext20(y-10), obj->width*20, obj->height*20, id, selLayer); + + undoStack->push(new Commands::LevelCmd::InsertBgdatObj(level, bgdatObj)); + + if (selectAfterPlacement) { + newObject = bgdatObj; + interactMode = InteractionMode::Creation; + selectedObjects.append(bgdatObj); + } + } + else if (drawType == ObjectType::SPRITE) + { + if (selSprite == -1) { + return; + } + + Sprite *spr = new Sprite(0, 0, selSprite); + spr->setRect(); + int xpos = qMax(0, toNext10(dx-spr->getwidth()/2-spr->getOffsetX())); + int ypos = qMax(0, toNext10(dy-spr->getheight()/2-spr->getOffsetY())); + + spr->setPosition(xpos, ypos); + + undoStack->push(new Commands::LevelCmd::InsertSprite(level, spr)); + + if (selectAfterPlacement) { + selectedObjects.append(spr); + } + } + else if (drawType == ObjectType::ENTRANCE) + { + Entrance *entr = level->newEntrance(x-10, y-10); + entr->setRect(); + + undoStack->push(new Commands::LevelCmd::InsertEntrance(level, entr)); + + if (selectAfterPlacement) { + selectedObjects.append(entr); + } + } + else if (drawType == ObjectType::ZONE) + { + Zone* zone = level->newZone(x-200, y-120); + + undoStack->beginMacro(tr("Inserted Zone at X: %1 Y: %2").arg(zone->getx()).arg(zone->gety())); + undoStack->push(new Commands::LevelCmd::InsertZone(level, zone)); + + if (level->backgrounds.isEmpty()) { + undoStack->push(new Commands::LevelCmd::InsertZoneBackground(level, new ZoneBackground())); + } + + if (level->boundings.isEmpty()) { + undoStack->push(new Commands::LevelCmd::InsertZoneBounding(level, new ZoneBounding())); + } + + undoStack->endMacro(); + + if (selectAfterPlacement) { + selectedObjects.append(zone); + } + } + else if (drawType == ObjectType::LOCATION) + { + Location* loc = level->newLocation(toNext20(x-10), toNext20(y-10)); + + undoStack->push(new Commands::LevelCmd::InsertLocation(level, loc)); + + if (selectAfterPlacement) { + newObject = loc; + interactMode = InteractionMode::Creation; + selectedObjects.append(loc); + } + } + else if (drawType == ObjectType::PATHNODE) + { + Path* path = level->newPath(); + PathNode* node = new PathNode(qMax(toNext10(x), 0), qMax(toNext10(y), 0), path); + + undoStack->beginMacro(tr("Inserted Path %1 at X: %2 Y: %3").arg(path->getid()).arg(node->getx()).arg(node->gety())); + undoStack->push(new Commands::LevelCmd::InsertPath(level, path)); + undoStack->push(new Commands::PathCmd::InsertNode(path, node)); + undoStack->endMacro(); + + if (selectAfterPlacement) { + selectedObjects.append(node); + } + } + else if (drawType == ObjectType::PROGRESSPATHNODE) + { + ProgressPath* path = level->newProgressPath(); + ProgressPathNode* node = new ProgressPathNode(qMax(toNext10(x), 0), qMax(toNext10(y), 0), path); + + undoStack->beginMacro(tr("Inserted Progress Path %1 at X: %2 Y: %3").arg(path->getid()).arg(node->getx()).arg(node->gety())); + undoStack->push(new Commands::LevelCmd::InsertProgressPath(level, path)); + undoStack->push(new Commands::ProgressPathCmd::InsertNode(path, node)); + undoStack->endMacro(); + + if (selectAfterPlacement) { + selectedObjects.append(node); + } + } + + checkEmits(); + emit updateEditors(); + if (selectedObjects.size() == 1) { + emit selectdObjectChanged(selectedObjects[0]); + } +} + +void EditManager::render(QPainter *painter) { foreach (Object* obj, selectedObjects) { @@ -457,7 +537,7 @@ void ObjectsEditonMode::render(QPainter *painter) } } - if (selectionMode) + if (interactMode == InteractionMode::Selection) { QRect selArea(qMin(dx, lx), qMin(dy, ly), qAbs(lx-dx), qAbs(ly-dy)); painter->setPen(QPen(QColor(0,80,180), 0.5)); @@ -466,12 +546,7 @@ void ObjectsEditonMode::render(QPainter *painter) } } -void ObjectsEditonMode::deactivate() -{ - selectedObjects.clear(); -} - -void ObjectsEditonMode::drawPlus(QPainter *painter, int x, int y) +void EditManager::drawPlus(QPainter *painter, int x, int y) { QPainterPath path1; path1.addRoundedRect(x+9, y+4, 2, 12 , 2.0, 2.0); @@ -481,12 +556,12 @@ void ObjectsEditonMode::drawPlus(QPainter *painter, int x, int y) painter->fillPath(path2, Qt::white); } -void ObjectsEditonMode::drawResizeKnob(int x, int y, QPainter *painter) +void EditManager::drawResizeKnob(int x, int y, QPainter *painter) { painter->fillRect(x-2, y-2, 4, 4, QBrush(Qt::white)); } -QList ObjectsEditonMode::getObjectsAtPos(int x1, int y1, int x2, int y2, bool firstOnly, QRect drawrect) +QList EditManager::getObjectsAtPos(int x1, int y1, int x2, int y2, bool firstOnly, QRect drawrect) { QList objects; @@ -541,21 +616,44 @@ QList ObjectsEditonMode::getObjectsAtPos(int x1, int y1, int x2, int y2 return objects; } -QList ObjectsEditonMode::cloneObjects(QList objects) +void EditManager::cloneObjects(QList objects) { - QList newObjects; + selectedObjects.clear(); + undoStack->beginMacro("Cloned Objects"); + foreach (Object* o, objects) { - if (is(o)) newObjects.append(new BgdatObject(dynamic_cast(o))); - if (is(o)) newObjects.append(new Sprite(dynamic_cast(o))); - if (is(o)) newObjects.append(new Entrance(dynamic_cast(o))); - if (is(o)) newObjects.append(new Location(dynamic_cast(o))); - if (is(o)) newObjects.append(new Zone(dynamic_cast(o))); + if (is(o)) { + BgdatObject *obj = new BgdatObject(dynamic_cast(o)); + undoStack->push(new Commands::LevelCmd::InsertBgdatObj(level, obj)); + selectedObjects.append(obj); + } + if (is(o)) { + Sprite *spr = new Sprite(dynamic_cast(o)); + undoStack->push(new Commands::LevelCmd::InsertSprite(level, spr)); + selectedObjects.append(spr); + } + if (is(o)) { + Entrance *entr = new Entrance(dynamic_cast(o)); + undoStack->push(new Commands::LevelCmd::InsertEntrance(level, entr)); + selectedObjects.append(entr); + } + if (is(o)) { + Location *loc = new Location(dynamic_cast(o)); + undoStack->push(new Commands::LevelCmd::InsertLocation(level, loc)); + selectedObjects.append(loc); + } + if (is(o)) { + Zone *zone = new Zone(dynamic_cast(o)); + undoStack->push(new Commands::LevelCmd::InsertZone(level, zone)); + selectedObjects.append(zone); + } } - return newObjects; + + undoStack->endMacro(); } -ObjectsEditonMode::mouseAction ObjectsEditonMode::getActionAtPos(int x, int y) +EditManager::mouseAction EditManager::getActionAtPos(int x, int y) { mouseAction act; @@ -703,7 +801,7 @@ ObjectsEditonMode::mouseAction ObjectsEditonMode::getActionAtPos(int x, int y) return act; } -Qt::CursorShape ObjectsEditonMode::getCursorAtPos(int x, int y) +Qt::CursorShape EditManager::getCursorAtPos(int x, int y) { mouseAction act = getActionAtPos(x, y); @@ -720,7 +818,7 @@ Qt::CursorShape ObjectsEditonMode::getCursorAtPos(int x, int y) return Qt::ArrowCursor; } -void ObjectsEditonMode::updateSelectionBounds() +void EditManager::updateSelectionBounds() { minBoundX = 2147483647; minBoundY = 2147483647; @@ -756,7 +854,7 @@ void ObjectsEditonMode::updateSelectionBounds() } } -void ObjectsEditonMode::sortSelection() +void EditManager::sortSelection() { QList sortedObjects; @@ -769,13 +867,13 @@ void ObjectsEditonMode::sortSelection() selectedObjects = sortedObjects; } -void ObjectsEditonMode::select(Object *obj) +void EditManager::select(Object *obj) { selectedObjects.clear(); selectedObjects.append(obj); } -void ObjectsEditonMode::selectAll() +void EditManager::selectAll() { selectedObjects.clear(); @@ -788,7 +886,7 @@ void ObjectsEditonMode::selectAll() foreach (ProgressPath* path, level->progressPaths) foreach (ProgressPathNode* node, path->getNodes()) selectedObjects.append(node); } -void ObjectsEditonMode::selectZoneContents(Zone* zone) +void EditManager::selectZoneContents(Zone* zone) { selectAll(); @@ -803,18 +901,55 @@ void ObjectsEditonMode::selectZoneContents(Zone* zone) } } -void ObjectsEditonMode::deleteSelection() +void EditManager::deleteSelection() { - level->remove(selectedObjects); + if (selectedObjects.isEmpty()) { + return; + } + + undoStack->beginMacro(tr("Deleted %1 Object(s)").arg(selectedObjects.count())); + foreach (Object* obj, selectedObjects) + { + if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteBgdatObject(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteSprite(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteEntrance(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteZone(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteLocation(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeletePathNode(level, dynamic_cast(obj))); + } + else if (is(obj)) + { + undoStack->push(new Commands::LevelCmd::DeleteProgressPathNode(level, dynamic_cast(obj))); + } + } + undoStack->endMacro(); + selectedObjects.clear(); actualCursor = Qt::ArrowCursor; mouseAction act; mouseAct = act; checkEmits(); - updateEditors(); + emit updateEditors(); } -void ObjectsEditonMode::copy() +void EditManager::copy() { if (selectedObjects.size() == 0) return; @@ -828,7 +963,7 @@ void ObjectsEditonMode::copy() foreach (Object* obj, selectedObjects) { - if (obj->getType() == 0) + if (obj->getType() == ObjectType::BGDATOBJECT) hasBgDats = true; if (obj->getx()+obj->getOffsetX() < minX) minX = obj->getx()+obj->getOffsetX(); @@ -935,13 +1070,13 @@ void ObjectsEditonMode::copy() QApplication::clipboard()->setText(clipboardText); } -void ObjectsEditonMode::cut() +void EditManager::cut() { copy(); deleteSelection(); } -void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) +void EditManager::paste(int currX, int currY, int currW, int currH) { QStringList sections = QApplication::clipboard()->text().split('|'); @@ -957,6 +1092,8 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) selectedObjects.clear(); + undoStack->beginMacro(tr("Pasted")); + for (int i = 2; i < sections.size(); i++) { QStringList params = sections[i].split(':'); @@ -966,7 +1103,7 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) case 0: // BG dat { BgdatObject* newObj = new BgdatObject(params[3].toInt()+pOffsetX, params[4].toInt()+pOffsetY, params[5].toInt(), params[6].toInt(), params[1].toInt(), params[2].toInt()); - level->objects[newObj->getLayer()].append(newObj); + undoStack->push(new Commands::LevelCmd::InsertBgdatObj(level, newObj)); selectedObjects.append(newObj); break; } @@ -974,10 +1111,11 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) { Sprite* newSpr = new Sprite(params[2].toInt()+pOffsetX, params[3].toInt()+pOffsetY, params[1].toInt()); newSpr->setLayer(params[4].toInt()); - for (int i=0; i<12; i++) newSpr->setByte(i, params[i+5].toUInt()); + for (int i = 0; i < 12; i++) { + newSpr->setByte(i, params[i+5].toUInt()); + } newSpr->setRect(); - level->sprites.append(newSpr); - level->sortCameraLimits(newSpr); + undoStack->push(new Commands::LevelCmd::InsertSprite(level, newSpr)); selectedObjects.append(newSpr); break; } @@ -985,40 +1123,37 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) { Entrance* newEntr = new Entrance(params[3].toInt()+pOffsetX, params[4].toInt()+pOffsetY, params[7].toInt(), params[8].toInt(), params[1].toInt(), params[5].toInt(), params[6].toInt(), params[2].toInt(), params[9].toInt(), params[10].toInt(), params[11].toInt()); newEntr->setRect(); - level->entrances.append(newEntr); + undoStack->push(new Commands::LevelCmd::InsertEntrance(level, newEntr)); selectedObjects.append(newEntr); break; } case 3: // Zone { Zone* newZone = new Zone(params[1].toInt()+pOffsetX, params[2].toInt()+pOffsetY, params[3].toInt(), params[4].toInt(), params[5].toInt(), params[6].toInt(), params[7].toInt(), params[8].toInt(), params[9].toInt(), params[10].toInt(), params[11].toInt()); - - level->zones.append(newZone); + undoStack->push(new Commands::LevelCmd::InsertZone(level, newZone)); selectedObjects.append(newZone); break; } case 4: // Location { Location* newLoc = new Location(params[2].toInt()+pOffsetX, params[3].toInt()+pOffsetY, params[4].toInt(), params[5].toInt(), params[1].toInt()); - level->locations.append(newLoc); + undoStack->push(new Commands::LevelCmd::InsertLocation(level, newLoc)); selectedObjects.append(newLoc); break; } case 5: // Path { Path* newPath = level->newPath(); - level->paths.append(newPath); - newPath->setId(params[1].toInt()); newPath->setLoop(params[2].toInt()); + undoStack->push(new Commands::LevelCmd::InsertPath(level, newPath)); QStringList pathNodes = params[3].split(';'); for (int i = 0; i < pathNodes.size(); i++) { QStringList nodeData = pathNodes[i].split(','); PathNode* newNode = new PathNode(nodeData[1].toInt()+pOffsetX, nodeData[2].toInt()+pOffsetY, nodeData[3].toFloat(), nodeData[4].toFloat(), nodeData[5].toInt(), nodeData[6].toInt(), nodeData[7].toInt(), nodeData[8].toInt(), newPath); - newPath->insertNode(newNode, nodeData[0].toInt()); - + undoStack->push(new Commands::PathCmd::InsertNode(newPath, newNode, nodeData[0].toInt())); selectedObjects.append(newPath->getNode(i)); } break; @@ -1026,18 +1161,16 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) case 6: // Progress Path { ProgressPath* newProgPath = level->newProgressPath(); - level->progressPaths.append(newProgPath); - newProgPath->setId(params[1].toInt()); newProgPath->setAlternatePathFlag(params[2].toInt()); + undoStack->push(new Commands::LevelCmd::InsertProgressPath(level, newProgPath)); QStringList progPathNodes = params[3].split(';'); for (int i = 0; i < progPathNodes.size(); i++) { QStringList nodeData = progPathNodes[i].split(','); ProgressPathNode* newProgPathNode = new ProgressPathNode(nodeData[1].toInt()+pOffsetX, nodeData[2].toInt()+pOffsetY, newProgPath); - newProgPath->insertNode(newProgPathNode, nodeData[0].toInt()); - + undoStack->push(new Commands::ProgressPathCmd::InsertNode(newProgPath, newProgPathNode, nodeData[0].toInt())); selectedObjects.append(newProgPath->getNode(i)); } break; @@ -1045,48 +1178,83 @@ void ObjectsEditonMode::paste(int currX, int currY, int currW, int currH) default: { break; } } } + undoStack->endMacro(); emit updateEditors(); checkEmits(); } -void ObjectsEditonMode::raise() +void EditManager::raise() { + if (selectedObjects.isEmpty()) { + return; + } + sortSelection(); + undoStack->beginMacro(tr("Raised %1 Object(s)").arg(selectedObjects.count())); foreach (Object* obj, selectedObjects) { - level->raise(obj); + undoStack->push(new Commands::LevelCmd::RaiseObject(level, obj)); } + undoStack->endMacro(); } -void ObjectsEditonMode::lower() +void EditManager::lower() { + if (selectedObjects.isEmpty()) { + return; + } + sortSelection(); + undoStack->beginMacro(tr("Lowered %1 Object(s)").arg(selectedObjects.count())); foreach (Object* obj, selectedObjects) { - level->lower(obj); + undoStack->push(new Commands::LevelCmd::LowerObject(level, obj)); } + undoStack->endMacro(); } -void ObjectsEditonMode::raiseLayer() +void EditManager::raiseLayer() { + if (selectedObjects.isEmpty()) { + return; + } + sortSelection(); + // TODO: Count should show number of tiles raised NOT number of objects in selection + undoStack->beginMacro(tr("Raised Layer of %1 Object(s)").arg(selectedObjects.count())); foreach (Object* obj, selectedObjects) { - if (is(obj)) level->raiseLayer(dynamic_cast(obj)); + if (!is(obj)) { + continue; + } + + undoStack->push(new Commands::LevelCmd::RaiseBgdatLayer(level, dynamic_cast(obj))); } + undoStack->endMacro(); } -void ObjectsEditonMode::lowerLayer() +void EditManager::lowerLayer() { + if (selectedObjects.isEmpty()) { + return; + } + sortSelection(); + // TODO: Count should show number of tiles lowered NOT number of objects in selection + undoStack->beginMacro(tr("Lowered Layer of %1 Object(s)").arg(selectedObjects.count())); foreach (Object* obj, selectedObjects) { - if (is(obj)) level->lowerLayer(dynamic_cast(obj)); + if (!is(obj)) { + continue; + } + + undoStack->push(new Commands::LevelCmd::LowerBgdatLayer(level, dynamic_cast(obj))); } + undoStack->endMacro(); } -void ObjectsEditonMode::checkEmits() +void EditManager::checkEmits() { if (selectedObjects.size() != 1) emit deselected(); @@ -1094,37 +1262,103 @@ void ObjectsEditonMode::checkEmits() emit selectdObjectChanged(selectedObjects[0]); } -void ObjectsEditonMode::setObject(int selObject, int selTileset) +void EditManager::setObject(int selObject, int selTileset) { + if (this->selObject == selObject && this->selTileset == selTileset) { + return; + } + this->selObject = selObject; this->selTileset = selTileset; - foreach (Object* o, selectedObjects) - { - if(is(o)) - { + swapSelectedBgdatObjects(); + + emit updateLevelView(); +} + +void EditManager::swapSelectedBgdatObjects() +{ + QList swappableObjects; + + foreach (Object* o, selectedObjects) { + if(is(o)) { BgdatObject* obj = dynamic_cast(o); - obj->setObjID(selObject); - obj->setTsID(selTileset); + if (obj->getObjID() != selObject || obj->getTsID() != selTileset) { + swappableObjects.append(obj); + } } } - emit updateLevelView(); + if (!swappableObjects.empty()) { + undoStack->beginMacro(tr("Swapped Object(s)")); + foreach (BgdatObject* obj, swappableObjects) { + undoStack->push(new Commands::BgdatCmd::ChangeObject(obj, selObject, selTileset)); + } + undoStack->endMacro(); + } } -void ObjectsEditonMode::setSprite(int selSprite) +void EditManager::setSprite(int selSprite) { + if (this->selSprite == selSprite) { + return; + } + this->selSprite = selSprite; - foreach (Object* o, selectedObjects) - { - if(is(o)) - { + swapSelectedSprites(); + + emit updateLevelView(); +} + +void EditManager::swapSelectedSprites() +{ + QList swappableSprites; + + foreach (Object* o, selectedObjects) { + if(is(o)) { Sprite* spr = dynamic_cast(o); - spr->setid(selSprite); + if (spr->getid() != selSprite) { + swappableSprites.append(spr); + } } } - emit updateLevelView(); + if (!swappableSprites.isEmpty()) { + undoStack->beginMacro(tr("Swapped Sprites(s)")); + foreach (Sprite* spr, swappableSprites) { + undoStack->push(new Commands::SpriteCmd::SetId(spr, selSprite)); + } + undoStack->endMacro(); + } } +void EditManager::setLayerMask(LAYER_MASK layer, bool state) +{ + QUndoCommand *layerMaskCmd = new Commands::EditorCmd::SetLayerMask(&layerMask, layer, state); + undoStack->push(layerMaskCmd); +} + +void EditManager::enableSpriteInteraction(bool state) +{ + QUndoCommand *spriteInteractionCmd = new Commands::EditorCmd::SetSpriteInteraction(&spriteInteraction, state); + undoStack->push(spriteInteractionCmd); +} + +void EditManager::enablePathInteraction(bool state) +{ + QUndoCommand *pathInteractionCmd = new Commands::EditorCmd::SetPathInteraction(&pathInteraction, state); + undoStack->push(pathInteractionCmd); +} + +void EditManager::enableEntranceInteraction(bool state) +{ + QUndoCommand *entranceInteractionCmd = new Commands::EditorCmd::SetEntranceInteraction(&entranceInteraction, state); + undoStack->push(entranceInteractionCmd); +} + +void EditManager::enableLocationInteraction(bool state) +{ + QUndoCommand *locationInteractionCmd = new Commands::EditorCmd::SetLocationInteraction(&locationInteraction, state); + undoStack->push(locationInteractionCmd); +} diff --git a/objectseditionmode.h b/leveleditor/editmanager.h similarity index 56% rename from objectseditionmode.h rename to leveleditor/editmanager.h index 93b72b41..0c0d6a42 100644 --- a/objectseditionmode.h +++ b/leveleditor/editmanager.h @@ -1,25 +1,28 @@ -#ifndef OBJECTSEDITIONMODE_H -#define OBJECTSEDITIONMODE_H +#ifndef EDITMANAGER_H +#define EDITMANAGER_H -#include "editionmode.h" +#include "level.h" +#include "layermask.h" -class ObjectsEditonMode: public EditionMode +#include +#include +#include + +class EditManager : public QObject { Q_OBJECT public: - ObjectsEditonMode(Level *level); - ~ObjectsEditonMode() {} + EditManager(Level *level, QUndoStack *undoStack); + ~EditManager() {} void mouseDown(int x, int y, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, QRect drawrect); - void mouseDrag(int x, int y, Qt::KeyboardModifiers modifieres, QRect drawrect); + void mouseDrag(int x, int y, Qt::KeyboardModifiers modifiers, QRect drawrect); void mouseMove(int x, int y); void mouseUp(int x, int y); void keyPress(QKeyEvent *) {} void render(QPainter *painter); - void activate() {} - void deactivate(); void deleteSelection(); void copy(); @@ -30,25 +33,47 @@ class ObjectsEditonMode: public EditionMode void raiseLayer(); void lowerLayer(); - void setLayerMask(quint8 mask) { layerMask = mask; } - void toggleSprites(bool toggle) { spriteInteraction = toggle; } - void togglePaths(bool toggle) { pathInteraction = toggle; } - void toggleLocations(bool toggle) { locationInteraction = toggle; } - void toggleEntrances(bool toggle) { entranceInteraction = toggle; } + void setLayerMask(LAYER_MASK layer, bool state); + const quint8 getLayerMask() { return layerMask; } + + void enableSpriteInteraction(bool state); + const bool spriteInteractionEnabled() { return spriteInteraction; } + + void enableEntranceInteraction(bool state); + const bool entranceInteractionEnabled() { return entranceInteraction; } + + void enablePathInteraction(bool state); + const bool pathInteractionEnabled() { return pathInteraction; } + + void enableLocationInteraction(bool state); + const bool locationInteractionEnabled() { return locationInteraction; } void select(Object* obj); void selectAll(); void selectZoneContents(Zone* zone); - void setDrawType(int drawType) { this->drawType = drawType; } + void setDrawType(ObjectType drawType) { this->drawType = drawType; } void setObject(int selObject, int selTileset); void setLayer(int selLayer) { this->selLayer = selLayer; } void setSprite(int selSprite); void toggleSelectAfterPlacement(bool toggle) { this->selectAfterPlacement = toggle; } + void clearSelection() { this->selectedObjects.clear(); } + + Qt::CursorShape getActualCursor() { return actualCursor; } + +signals: + void deselected(); + void selectdObjectChanged(Object* obj); + void updateEditors(); + void updateLevelView(); + private: + Level *level; + QUndoStack *undoStack; + Qt::CursorShape actualCursor; QList selectedObjects; @@ -78,27 +103,27 @@ class ObjectsEditonMode: public EditionMode int lx, ly; mouseAction mouseAct; - bool selectionMode; bool selectionHasBGDats; int minBoundX, minBoundY; int maxBoundX, maxBoundY; int minSizeX, minSizeY; - bool creatNewObject = false; + enum InteractionMode + { + None, + Creation, + Selection + }; + + InteractionMode interactMode = InteractionMode::None; + Object* newObject; // Only to prevent resizing when cloning bool clone = false; - int drawType = -1; - // -1: Invalid - // 0: BGDat - // 1: Sprite - // 2: Entrance - // 3: Zone - // 4: Location - // etc + ObjectType drawType = ObjectType::INVALID; int selTileset = -1; int selObject = -1; @@ -109,7 +134,7 @@ class ObjectsEditonMode: public EditionMode mouseAction getActionAtPos(int x, int y); Qt::CursorShape getCursorAtPos(int x, int y); - QList cloneObjects(QList objects); + void cloneObjects(QList objects); void updateSelectionBounds(); @@ -127,12 +152,18 @@ class ObjectsEditonMode: public EditionMode quint8 layerMask; bool pathInteraction; + bool entranceInteraction; bool spriteInteraction; bool locationInteraction; - bool entranceInteraction; bool selectAfterPlacement; + void CreateObject(quint32 x, quint32 y); + bool movingObjects = false; + bool resizingObjects = false; + + void swapSelectedBgdatObjects(); + void swapSelectedSprites(); }; -#endif // OBJECTSEDITIONMODE_H +#endif // EDITMANAGER_H diff --git a/entranceeditorwidget.cpp b/leveleditor/entranceeditorwidget.cpp similarity index 69% rename from entranceeditorwidget.cpp rename to leveleditor/entranceeditorwidget.cpp index 31777f5f..4a0885d5 100644 --- a/entranceeditorwidget.cpp +++ b/leveleditor/entranceeditorwidget.cpp @@ -6,52 +6,55 @@ #include #include -EntranceEditorWidget::EntranceEditorWidget(QList *entrances) -{ - this->entrances = entrances; +#include "commands/entrancecommands.h" + +EntranceEditorWidget::EntranceEditorWidget(QList *entrances, QUndoStack *undoStack, QWidget *parent) : + QWidget(parent), + entrances(entrances), + undoStack(undoStack) { loadEntranceTypes(); id = new QSpinBox(); id->setRange(0, 255); - connect(id, SIGNAL(valueChanged(int)), this, SLOT(handleIDChanged(int))); + connect(id, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleIDChanged); type = new QComboBox(); type->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon); type->addItems(entranceTypes); - connect(type, SIGNAL(currentIndexChanged(int)), this, SLOT(handleTypeChanged(int))); + connect(type, &QComboBox::currentIndexChanged, this, &EntranceEditorWidget::handleTypeChanged); destId = new QSpinBox(); destId->setRange(0, 255); - connect(destId, SIGNAL(valueChanged(int)), this, SLOT(handleDestEntrChange(int))); + connect(destId, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleDestEntrChange); destArea = new QSpinBox(); destArea->setRange(0, 4); - connect(destArea, SIGNAL(valueChanged(int)), this, SLOT(handleDestAreaChange(int))); + connect(destArea, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleDestAreaChange); camXOffset = new QSpinBox(); camXOffset->setRange(-32768, 32767); - connect(camXOffset, SIGNAL(valueChanged(int)), this, SLOT(handleCamXChange(int))); + connect(camXOffset, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleCamXChange); camYOffset = new QSpinBox(); camYOffset->setRange(-32768, 32767); - connect(camYOffset, SIGNAL(valueChanged(int)), this, SLOT(handleCamYChange(int))); + connect(camYOffset, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleCamYChange); unk1 = new QSpinBox(); unk1->setRange(0, 255); - connect(unk1, SIGNAL(valueChanged(int)), this, SLOT(handleUnk1Change(int))); + connect(unk1, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleUnk1Change); unk2 = new QSpinBox(); unk2->setRange(0, 255); - connect(unk2, SIGNAL(valueChanged(int)), this, SLOT(handleUnk2Change(int))); + connect(unk2, &QSpinBox::valueChanged, this, &EntranceEditorWidget::handleUnk2Change); enterable = new QCheckBox(tr("Enterable")); - connect(enterable, SIGNAL(toggled(bool)), this, SLOT(handleEnterableChange(bool))); + connect(enterable, &QAbstractButton::toggled, this, &EntranceEditorWidget::handleEnterableChange); returnToWM = new QCheckBox(tr("Return to Worldmap")); - connect(returnToWM, SIGNAL(toggled(bool)), this, SLOT(handleReturnToWMChange(bool))); + connect(returnToWM, &QAbstractButton::toggled, this, &EntranceEditorWidget::handleReturnToWMChange); entrancesList = new QListWidget(); - connect(entrancesList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleEntranceListIndexChanged(QListWidgetItem*))); + connect(entrancesList, &QListWidget::itemClicked, this, &EntranceEditorWidget::handleEntranceListIndexChanged); QVBoxLayout* layout = new QVBoxLayout(); setLayout(layout); @@ -212,77 +215,64 @@ void EntranceEditorWidget::handleEntranceListIndexChanged(QListWidgetItem *item) emit selectedEntrChanged(editEntrance); } -void EntranceEditorWidget::handleTypeChanged(int typeVal) +void EntranceEditorWidget::handleTypeChanged(int type) { if (!handleChanges) return; - editEntrance->setEntrType(typeVal); - editEntrance->setRect(); + undoStack->push(new Commands::EntranceCmd::SetType(editEntrance, type)); updateList(); - emit updateLevelView(); - emit editMade(); } -void EntranceEditorWidget::handleIDChanged(int idVal) +void EntranceEditorWidget::handleIDChanged(int id) { if (!handleChanges) return; - editEntrance->setId(idVal); + undoStack->push(new Commands::EntranceCmd::SetId(editEntrance, id)); updateList(); - emit updateLevelView(); - emit editMade(); } -void EntranceEditorWidget::handleDestEntrChange(int destEntrVal) +void EntranceEditorWidget::handleDestEntrChange(int destEntrId) { if (!handleChanges) return; - editEntrance->setDestEntr(destEntrVal); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetDestEntr(editEntrance, destEntrId)); } -void EntranceEditorWidget::handleDestAreaChange(int destAreaVal) +void EntranceEditorWidget::handleDestAreaChange(int destAreaId) { if (!handleChanges) return; - editEntrance->setDestArea(destAreaVal); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetDestArea(editEntrance, destAreaId)); } -void EntranceEditorWidget::handleCamXChange(int camXVal) +void EntranceEditorWidget::handleCamXChange(int xOffset) { if (!handleChanges) return; - editEntrance->setCameraX(camXVal); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetCamXOffset(editEntrance, static_cast(xOffset))); } -void EntranceEditorWidget::handleCamYChange(int camYVal) +void EntranceEditorWidget::handleCamYChange(int yOffset) { if (!handleChanges) return; - editEntrance->setCameraY(camYVal); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetCamYOffset(editEntrance, static_cast(yOffset))); } -void EntranceEditorWidget::handleUnk1Change(int unk1Val) +void EntranceEditorWidget::handleUnk1Change(int unk1) { if (!handleChanges) return; - editEntrance->setUnk1(unk1Val); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetUnk1(editEntrance, unk1)); } -void EntranceEditorWidget::handleUnk2Change(int unk2Val) +void EntranceEditorWidget::handleUnk2Change(int unk2) { if (!handleChanges) return; - editEntrance->setUnk2(unk2Val); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetUnk2(editEntrance, unk2)); } -void EntranceEditorWidget::handleEnterableChange(bool enterableVal) +void EntranceEditorWidget::handleEnterableChange(bool enterable) { if (!handleChanges) return; - editEntrance->setSettingsBit(!enterableVal, 7); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetSettingsBit(editEntrance, !enterable, 7)); } -void EntranceEditorWidget::handleReturnToWMChange(bool returnToWMVal) +void EntranceEditorWidget::handleReturnToWMChange(bool returnToWM) { if (!handleChanges) return; - editEntrance->setSettingsBit(returnToWMVal, 4); - emit editMade(); + undoStack->push(new Commands::EntranceCmd::SetSettingsBit(editEntrance, returnToWM, 4)); } diff --git a/entranceeditorwidget.h b/leveleditor/entranceeditorwidget.h similarity index 75% rename from entranceeditorwidget.h rename to leveleditor/entranceeditorwidget.h index 2bb3c046..f04d6033 100644 --- a/entranceeditorwidget.h +++ b/leveleditor/entranceeditorwidget.h @@ -8,34 +8,33 @@ #include #include #include +#include class EntranceEditorWidget : public QWidget { Q_OBJECT public: - EntranceEditorWidget(QList *entrances); + EntranceEditorWidget(QList *entrances, QUndoStack *undoStack, QWidget *parent = nullptr); void deselect(); void select(Entrance* entr); void updateEditor(); signals: - void updateLevelView(); void selectedEntrChanged(Object* entr); - void editMade(); private: - QListWidget* entrancesList; - QWidget* edits; - QComboBox* type; - QSpinBox* id; - QSpinBox* destId; - QSpinBox* destArea; - QSpinBox* camXOffset; - QSpinBox* camYOffset; - QSpinBox* unk1; - QSpinBox* unk2; - QCheckBox* enterable; - QCheckBox* returnToWM; + QListWidget *entrancesList; + QWidget *edits; + QComboBox *type; + QSpinBox *id; + QSpinBox *destId; + QSpinBox *destArea; + QSpinBox *camXOffset; + QSpinBox *camYOffset; + QSpinBox *unk1; + QSpinBox *unk2; + QCheckBox *enterable; + QCheckBox *returnToWM; QList *entrances; Entrance* editEntrance; @@ -52,6 +51,8 @@ class EntranceEditorWidget : public QWidget bool editingAnEntrance = false; bool handleChanges = true; + QUndoStack *undoStack; + private slots: void handleEntranceListIndexChanged(QListWidgetItem* item); void handleTypeChanged(int typeVal); diff --git a/leveleditor/eventeditorwidget.cpp b/leveleditor/eventeditorwidget.cpp new file mode 100644 index 00000000..1e8e218f --- /dev/null +++ b/leveleditor/eventeditorwidget.cpp @@ -0,0 +1,112 @@ +#include "eventeditorwidget.h" + +#include +#include +#include +#include + +#include "commands/setvalue.h" + +EventEditorWidget::EventEditorWidget(Level *level, QUndoStack* undoStack) : + level(level), undoStack(undoStack) { + + QVBoxLayout *layout = new QVBoxLayout(); + setLayout(layout); + + // Filters + QHBoxLayout* filterLayout = new QHBoxLayout(); + + QLabel* filterLabel = new QLabel(tr("Filter:")); + filterLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + filterLayout->addWidget(filterLabel); + viewFilter = new QComboBox(); + QStringList filters; + + filters << tr("All") + << tr("Enabled") + << tr("Disabled"); + + viewFilter->insertItems(0, filters); + filterLayout->addWidget(viewFilter); + + layout->addLayout(filterLayout); + + // List + eventsList = new QListWidget(); + layout->addWidget(eventsList); + + updateEventStates(); + + connect(eventsList, &QListWidget::itemChanged, this, &EventEditorWidget::eventListItemChanged); + connect(viewFilter, &QComboBox::currentIndexChanged, this, &EventEditorWidget::filterChanged); +} + +void EventEditorWidget::updateEventStates() { + quint64 states = level->eventState; + + eventsList->blockSignals(true); + eventsList->clear(); + + for (int i = 0; i < 64; i++) { + QListWidgetItem* listItem = new QListWidgetItem(tr("Event %1").arg(i+1), eventsList); + listItem->setCheckState(((states >> i) & 1ULL) ? Qt::Checked : Qt::Unchecked); + listItem->setData(Qt::UserRole, i); + eventsList->addItem(listItem); // TODO Should set at index + } + + eventsList->blockSignals(false); +} + +void EventEditorWidget::updateEditor() { + + updateEventStates(); + updateFilter(); +} + +void EventEditorWidget::updateFilter() { + switch (filter) + { + case 1: // Enabled + { + for (int i = 0; i < eventsList->count(); i++) + { + QListWidgetItem* item = eventsList->item(i); + + if (item->checkState() == Qt::Checked) + item->setHidden(false); + else + item->setHidden(true); + } + } break; + case 2: // Disabled + { + for (int i = 0; i < eventsList->count(); i++) + { + QListWidgetItem* item = eventsList->item(i); + + if (item->checkState() == Qt::Unchecked) + item->setHidden(false); + else + item->setHidden(true); + } + } break; + default: + { + for (int i = 0; i < eventsList->count(); i++) + { + QListWidgetItem* item = eventsList->item(i); + item->setHidden(false); + } + } break; + } +} + +void EventEditorWidget::eventListItemChanged(QListWidgetItem* item) { + quint64 newState = level->eventState ^ (1ULL << item->data(Qt::UserRole).toInt()); + undoStack->push(new EditorCommand::SetValue(&level->eventState, newState, tr("Changed Area Event Flags"))); +} + +void EventEditorWidget::filterChanged(int newFilter) { + this->filter = newFilter; + updateFilter(); +} diff --git a/leveleditor/eventeditorwidget.h b/leveleditor/eventeditorwidget.h new file mode 100644 index 00000000..7cecc720 --- /dev/null +++ b/leveleditor/eventeditorwidget.h @@ -0,0 +1,36 @@ +#ifndef EVENTEDITORWIDGET_H +#define EVENTEDITORWIDGET_H + +#include +#include +#include +#include + +#include "level.h" + +class EventEditorWidget : public QWidget +{ + Q_OBJECT +public: + EventEditorWidget(Level *level, QUndoStack *undoStack); + + void updateEditor(); + +private: + void updateEventStates(); + void updateFilter(); + + QListWidget *eventsList; + QComboBox *viewFilter; + + Level *level; + QUndoStack *undoStack; + + int filter = 0; + +private slots: + void eventListItemChanged(QListWidgetItem *item); + void filterChanged(int filter); +}; + +#endif // EVENTEDITORWIDGET_H diff --git a/leveleditor/layermask.h b/leveleditor/layermask.h new file mode 100644 index 00000000..daa91377 --- /dev/null +++ b/leveleditor/layermask.h @@ -0,0 +1,15 @@ +#ifndef LAYERMASK_H +#define LAYERMASK_H + +#include "qtypes.h" + +enum LAYER_MASK : quint8 +{ + NONE = 0x00, + LAYER_ONE = 0x01, + LAYER_TWO = 0x02, + LAYER_THREE = 0x04, + ALL = 0x07 +}; + +#endif // LAYERMASK_H diff --git a/leveleditorwindow.cpp b/leveleditor/leveleditorwindow.cpp similarity index 56% rename from leveleditorwindow.cpp rename to leveleditor/leveleditorwindow.cpp index 220cb0d2..027df364 100644 --- a/leveleditorwindow.cpp +++ b/leveleditor/leveleditorwindow.cpp @@ -18,6 +18,7 @@ #include "is.h" #include "settingsmanager.h" +#include "settingsdialog.h" #include #include @@ -34,8 +35,7 @@ #endif LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : - WindowBase(lvlMgr->getParent()), - ui(new Ui::LevelEditorWindow) + WindowBase(lvlMgr->getParent()), ui(new Ui::LevelEditorWindow) { this->lvlMgr = lvlMgr; this->settings = SettingsManager::getInstance(); @@ -48,11 +48,10 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : areaSelector = new QComboBox(this); ui->toolBar->insertWidget(ui->actionAddArea, areaSelector); - connect(areaSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(handleAreaIndexChange(int))); + connect(areaSelector, &QComboBox::currentIndexChanged, this, &LevelEditorWindow::handleAreaIndexChange); - editStatus = new QLabel(this); - ui->statusbar->addWidget(editStatus); - //connect(editStatus, SIGNAL(updateLevelLabel(QString)), editStatus, SLOT(setText(QString))); + statusLabel = new QLabel(this); + ui->statusbar->addWidget(statusLabel); // Load UI Icons QString basePath(settings->dataPath("icons/")); @@ -78,16 +77,29 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : ui->actionRenderCameraLimits->setIcon(QIcon(basePath + "render_camera_limits.png")); ui->actionAddArea->setIcon(QIcon(basePath + "add.png")); ui->actionDeleteCurrentArea->setIcon(QIcon(basePath + "remove.png")); - ui->actionSetBackgroundColor->setIcon(QIcon(basePath + "colors.png")); - ui->actionResetBackgroundColor->setIcon(QIcon(basePath + "delete_colors.png")); + + connect(ui->actionShowPreferences, &QAction::triggered, this, &LevelEditorWindow::showPreferencesDialog); + ui->actionToggleLayer1->setIcon(QIcon(basePath + "layer1.png")); + connect(ui->actionToggleLayer1, &QAction::toggled, this, &LevelEditorWindow::toggleLayer); + ui->actionToggleLayer2->setIcon(QIcon(basePath + "layer2.png")); + connect(ui->actionToggleLayer2, &QAction::toggled, this, &LevelEditorWindow::toggleLayer); + ui->actionToggleSprites->setIcon(QIcon(basePath + "sprite.png")); + connect(ui->actionToggleSprites, &QAction::toggled, this, &LevelEditorWindow::toggleSprites); + + ui->actionToggleEntrances->setIcon(QIcon(basePath + "entrance.png")); + connect(ui->actionToggleEntrances, &QAction::toggled, this, &LevelEditorWindow::toggleEntrances); + ui->actionTogglePaths->setIcon(QIcon(basePath + "path.png")); + connect(ui->actionTogglePaths, &QAction::toggled, this, &LevelEditorWindow::togglePaths); + ui->actionToggleLocations->setIcon(QIcon(basePath + "location.png")); + connect(ui->actionToggleLocations, &QAction::toggled, this, &LevelEditorWindow::toggleLocations); + ui->actionToggle3DOverlay->setIcon(QIcon(basePath + "3D.png")); ui->actionToggle2DTile->setIcon(QIcon(basePath + "2D.png")); - ui->actionToggleEntrances->setIcon(QIcon(basePath + "entrance.png")); // Set Shortcuts QList deleteShortcuts; @@ -98,7 +110,7 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : toolboxDock->setObjectName("toolboxDock"); toolboxDock->setWindowTitle(tr("Toolbox")); toolboxTabs = new QTabWidget(this); - connect(toolboxTabs, SIGNAL(currentChanged(int)), this, SLOT(toolboxTabsCurrentChanged(int))); + connect(toolboxTabs, &QTabWidget::currentChanged, this, &LevelEditorWindow::toolboxTabsCurrentChanged); toolboxDock->setWidget(toolboxTabs); minimapDock = new QDockWidget(this); @@ -108,10 +120,42 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : addDockWidget(Qt::LeftDockWidgetArea, toolboxDock); addDockWidget(Qt::LeftDockWidgetArea, minimapDock); + // Undo/Redo + undoStack = new QUndoStack(this); + connect(undoStack, &QUndoStack::indexChanged, this, &LevelEditorWindow::historyStateChanged); + + actionUndo = undoStack->createUndoAction(this, tr("&Undo")); + actionUndo->setIcon(QIcon(basePath + "undo.png")); + actionUndo->setShortcuts(QKeySequence::Undo); + + actionRedo = undoStack->createRedoAction(this, tr("&Redo")); + actionRedo->setIcon(QIcon(basePath + "redo.png")); + actionRedo->setShortcuts(QKeySequence::Redo); + + // Add actions to ui + ui->toolBar->addAction(actionUndo); + ui->toolBar->addAction(actionRedo); + + // Add actions to ui + ui->menuEdit->addAction(actionUndo); + ui->menuEdit->addAction(actionRedo); + + // Create undo view + undoView = new QUndoView(undoStack); + undoView->setEmptyLabel(tr("")); + + historyDock = new QDockWidget(this); + historyDock->setObjectName("historyDock"); + historyDock->setWindowTitle(tr("History")); + historyDock->setWidget(undoView); + historyDock->setVisible(false); + addDockWidget(Qt::RightDockWidgetArea, historyDock); + restoreState(settings->get("lvleditorState").toByteArray()); updateDockedWidgetCheckboxes(); - connect(toolboxDock, SIGNAL(visibilityChanged(bool)), this, SLOT(updateDockedWidgetCheckboxes())); - connect(minimapDock, SIGNAL(visibilityChanged(bool)), this, SLOT(updateDockedWidgetCheckboxes())); + connect(toolboxDock, &QDockWidget::visibilityChanged, this, &LevelEditorWindow::updateDockedWidgetCheckboxes); + connect(minimapDock, &QDockWidget::visibilityChanged, this, &LevelEditorWindow::updateDockedWidgetCheckboxes); + connect(minimapDock, &QDockWidget::visibilityChanged, this, &LevelEditorWindow::updateDockedWidgetCheckboxes); loadArea(initialArea, false, true); @@ -120,9 +164,9 @@ LevelEditorWindow::LevelEditorWindow(LevelManager* lvlMgr, int initialArea) : ui->actionCheckerboard->setChecked(settings->get("checkerboard", false).toBool()); ui->actionRenderLiquids->setChecked(settings->get("renderLiquids", true).toBool()); ui->actionRenderCameraLimits->setChecked(settings->get("renderCameraLimits", true).toBool()); - ui->actionHideStatusbar->setChecked(settings->get("lvleditorHideStatusBar", false).toBool()); - editStatus->setText(tr("Ready!")); + loadSettings(); + setStatus(Ready); #ifdef USE_KDE_BLUR if (KWindowEffects::isEffectAvailable(KWindowEffects::BlurBehind)) @@ -158,40 +202,109 @@ void LevelEditorWindow::changeEvent(QEvent* event) QMainWindow::changeEvent(event); } +void LevelEditorWindow::showPreferencesDialog(bool show) { + SettingsDialog settingsDialog(this); + connect(&settingsDialog, &SettingsDialog::changesApplied, this, &LevelEditorWindow::loadSettings); + settingsDialog.exec(); +} + +void LevelEditorWindow::loadSettings() { + levelView->setBackgroundColor(settings->getLEWindowColor()); + undoStack->setUndoLimit(static_cast(settings->getLEUndoLimit())); + levelView->editManagerPtr()->toggleSelectAfterPlacement(settings->getLESelectOnPlace()); + ui->statusbar->setHidden(!settings->getLEShowStatusbar()); +} + +void LevelEditorWindow::historyStateChanged(int index) +{ + Q_UNUSED(index); + + setStatus(Unsaved); + + if (levelView == nullptr) { + return; + } + + levelView->update(); + updateEditors(); + + if (undoStack->index() == undoStack->count()) { + return; + } + + // Update button states + + ui->actionToggleLayer1->blockSignals(true); + ui->actionToggleLayer1->setChecked(levelView->editManagerPtr()->getLayerMask() & LAYER_MASK::LAYER_ONE); + ui->actionToggleLayer1->blockSignals(false); + + ui->actionToggleLayer2->blockSignals(true); + ui->actionToggleLayer2->setChecked(levelView->editManagerPtr()->getLayerMask() & LAYER_MASK::LAYER_TWO); + ui->actionToggleLayer2->blockSignals(false); + + ui->actionToggleSprites->blockSignals(true); + ui->actionToggleSprites->setChecked(levelView->editManagerPtr()->spriteInteractionEnabled()); + ui->actionToggleSprites->blockSignals(false); + + ui->actionToggleEntrances->blockSignals(true); + ui->actionToggleEntrances->setChecked(levelView->editManagerPtr()->entranceInteractionEnabled()); + ui->actionToggleEntrances->blockSignals(false); + + ui->actionTogglePaths->blockSignals(true); + ui->actionTogglePaths->setChecked(levelView->editManagerPtr()->pathInteractionEnabled()); + ui->actionTogglePaths->blockSignals(false); + + ui->actionToggleLocations->blockSignals(true); + ui->actionToggleLocations->setChecked(levelView->editManagerPtr()->locationInteractionEnabled()); + ui->actionToggleLocations->blockSignals(false); + + levelView->editManagerPtr()->clearSelection(); + deselect(); + levelView->update(); +} + // Actions -void LevelEditorWindow::on_actionToggleLayer1_toggled(bool toggle) +void LevelEditorWindow::toggleLayer(bool toggle) { - if (toggle) layerMask |= 0x1; - else layerMask &= ~0x1; - levelView->setLayerMask(layerMask); - update(); + LAYER_MASK mask = LAYER_MASK::NONE; + + QAction *action = qobject_cast(sender()); + if (action == ui->actionToggleLayer1) + { + mask = LAYER_MASK::LAYER_ONE; + } + else if (action == ui->actionToggleLayer2) + { + mask = LAYER_MASK::LAYER_TWO; + } + else + { + qDebug() << "toggleLayer: Unknown Sender"; + return; + } + + levelView->editManagerPtr()->setLayerMask(mask, toggle); } -void LevelEditorWindow::on_actionToggleLayer2_toggled(bool toggle) +void LevelEditorWindow::toggleSprites(bool toggle) { - if (toggle) layerMask |= 0x2; - else layerMask &= ~0x2; - levelView->setLayerMask(layerMask); - update(); + levelView->editManagerPtr()->enableSpriteInteraction(toggle); } -void LevelEditorWindow::on_actionToggleSprites_toggled(bool toggle) +void LevelEditorWindow::toggleEntrances(bool toggle) { - levelView->toggleSprites(toggle); - update(); + levelView->editManagerPtr()->enableEntranceInteraction(toggle); } -void LevelEditorWindow::on_actionTogglePaths_toggled(bool toggle) +void LevelEditorWindow::togglePaths(bool toggle) { - levelView->togglePaths(toggle); - update(); + levelView->editManagerPtr()->enablePathInteraction(toggle); } -void LevelEditorWindow::on_actionToggleLocations_toggled(bool toggle) +void LevelEditorWindow::toggleLocations(bool toggle) { - levelView->toggleLocations(toggle); - update(); + levelView->editManagerPtr()->enableLocationInteraction(toggle); } void LevelEditorWindow::on_actionToggle3DOverlay_toggled(bool toggle) @@ -206,12 +319,6 @@ void LevelEditorWindow::on_actionToggle2DTile_toggled(bool toggle) update(); } -void LevelEditorWindow::on_actionToggleEntrances_toggled(bool toggle) -{ - levelView->toggleEntrances(toggle); - update(); -} - void LevelEditorWindow::on_actionZoom_In_triggered() { if (zoom < 4) @@ -256,47 +363,59 @@ void LevelEditorWindow::on_actionZoom_Minimum_triggered() update(); } -void LevelEditorWindow::handleEditMade() -{ - editStatus->setText(tr("Unsaved Changes")); - unsavedChanges = true; +void LevelEditorWindow::setStatus(EditorStatus newStatus) +{ + switch (newStatus) { + case EditorStatus::Ready: + status = Ready; + statusLabel->setText(tr("Ready!")); + break; + case EditorStatus::Unsaved: + status = Unsaved; + statusLabel->setText(tr("Unsaved Changes")); + break; + case EditorStatus::SaveFailed: + status = SaveFailed; + statusLabel->setText(tr("Save Failed")); + break; + case EditorStatus::ChangesSaved: + status = ChangesSaved; + statusLabel->setText(tr("Changes Saved")); + default: + break; + } } void LevelEditorWindow::on_actionSave_triggered() { qint8 res = levelView->saveLevel(); - if (res != 0) - editStatus->setText(tr("Save Failed")); - else - { - editStatus->setText(tr("Changes Saved")); - unsavedChanges = false; + if (res != 0) { + setStatus(SaveFailed); + } + else { + setStatus(ChangesSaved); } } void LevelEditorWindow::on_actionCopy_triggered() { levelView->copy(); - emit handleEditMade(); } void LevelEditorWindow::on_actionPaste_triggered() { spriteEditor->spriteIdsPtr()->deselect(); levelView->paste(); - emit handleEditMade(); } void LevelEditorWindow::on_actionCut_triggered() { levelView->cut(); - emit handleEditMade(); } void LevelEditorWindow::on_actionDelete_triggered() { levelView->deleteSel(); - emit handleEditMade(); } void LevelEditorWindow::on_actionSelectAll_triggered() @@ -307,25 +426,21 @@ void LevelEditorWindow::on_actionSelectAll_triggered() void LevelEditorWindow::on_actionRaise_triggered() { levelView->raise(); - emit handleEditMade(); } void LevelEditorWindow::on_actionLower_triggered() { levelView->lower(); - emit handleEditMade(); } void LevelEditorWindow::on_actionRaiseLayer_triggered() { levelView->raiseLayer(); - emit handleEditMade(); } void LevelEditorWindow::on_actionLowerLayer_triggered() { levelView->lowerLayer(); - emit handleEditMade(); } void LevelEditorWindow::on_actionFullscreen_toggled(bool toggle) @@ -368,17 +483,11 @@ void LevelEditorWindow::on_actionRenderCameraLimits_toggled(bool toggle) void LevelEditorWindow::setSelSprite(int spriteId) { - levelView->objEditionModePtr()->setDrawType(1); - levelView->objEditionModePtr()->setSprite(spriteId); -} - -void LevelEditorWindow::on_actionSelectAfterPlacement_toggled(bool toggle) -{ - levelView->objEditionModePtr()->toggleSelectAfterPlacement(toggle); - settings->set("SelectAfterPlacement", toggle); + levelView->editManagerPtr()->setDrawType(ObjectType::SPRITE); + levelView->editManagerPtr()->setSprite(spriteId); } -void LevelEditorWindow::setObjectEdition(Object* obj) +void LevelEditorWindow::handleSelectionChanged(Object* obj) { deselect(); @@ -422,6 +531,10 @@ void LevelEditorWindow::setObjectEdition(Object* obj) void LevelEditorWindow::deselect() { + if (!editorsLoaded()) { + return; + } + spriteEditor->spriteDataEditorPtr()->deselect(); entranceEditor->deselect(); zoneEditor->deselect(); @@ -433,67 +546,107 @@ void LevelEditorWindow::deselect() void LevelEditorWindow::updateEditors() { - //spriteEditor->spriteDataEditorPtr()->updateEditor(); + if (!editorsLoaded()) { + return; + } + + tilesetPalette->updateEditor(); + areaEditor->updateEditor(); entranceEditor->updateEditor(); zoneEditor->updateEditor(); locationEditor->updateEditor(); pathEditor->updateEditor(); progPathEditor->updateEditor(); spriteEditor->spriteIdsPtr()->updateEditor(); +// spriteEditor->spriteDataEditorPtr()->updateEditor(); +} + +bool LevelEditorWindow::editorsLoaded() +{ + return (entranceEditor != nullptr && + zoneEditor != nullptr && + locationEditor != nullptr && + pathEditor != nullptr && + progPathEditor != nullptr && + spriteEditor != nullptr); } void LevelEditorWindow::toolboxTabsCurrentChanged(int index) { - if (index == 0) - levelView->objEditionModePtr()->setDrawType(-1); - else - { - levelView->objEditionModePtr()->setDrawType(index-1); + switch (index) { + case 0: + levelView->editManagerPtr()->setDrawType(ObjectType::INVALID); + break; + case 1: + levelView->editManagerPtr()->setDrawType(ObjectType::BGDATOBJECT); + break; + case 2: + levelView->editManagerPtr()->setDrawType(ObjectType::SPRITE); + break; + case 3: + levelView->editManagerPtr()->setDrawType(ObjectType::ENTRANCE); + break; + case 4: + levelView->editManagerPtr()->setDrawType(ObjectType::ZONE); + break; + case 5: + levelView->editManagerPtr()->setDrawType(ObjectType::LOCATION); + break; + case 6: + levelView->editManagerPtr()->setDrawType(ObjectType::PATHNODE); + break; + case 7: + levelView->editManagerPtr()->setDrawType(ObjectType::PROGRESSPATHNODE); + break; + default: + break; } } -void LevelEditorWindow::on_actionAddArea_triggered() +const int LevelEditorWindow::showSaveDialog() { - bool ignore = false; - if (unsavedChanges) - { - QMessageBox message(this); - message.setWindowTitle(tr("Unsaved Changes")); - message.setText(tr("Do you want to save your changes?")); - message.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + QMessageBox message(this); + message.setWindowTitle(tr("Unsaved Changes")); + message.setText(tr("Do you want to save your changes?")); + message.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); - QSpacerItem* spacer = new QSpacerItem(400, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - QGridLayout* layout = (QGridLayout*)message.layout(); - layout->addItem(spacer, layout->rowCount(), 0, 1, layout->columnCount()); + QSpacerItem* spacer = new QSpacerItem(400, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); + QGridLayout* layout = qobject_cast(message.layout()); + layout->addItem(spacer, layout->rowCount(), 0, 1, layout->columnCount()); - switch (message.exec()) - { - case QMessageBox::Save: - levelView->saveLevel(); - unsavedChanges = false; - editStatus->setText(tr("Changes Saved")); - break; - case QMessageBox::Discard: - unsavedChanges = false; - editStatus->setText(""); - break; - case QMessageBox::Cancel: - ignore = true; - break; - } - } + int exitCode = message.exec(); - if (!ignore) + switch (exitCode) { - if (lvlMgr->getAreaCount() >= 4) + case QMessageBox::Save: + levelView->saveLevel(); + setStatus(ChangesSaved); + break; + case QMessageBox::Discard: + setStatus(Ready); + break; + } + + return exitCode; +} + +void LevelEditorWindow::on_actionAddArea_triggered() +{ + if (status == EditorStatus::Unsaved || status == EditorStatus::SaveFailed) { + int exitCode = showSaveDialog(); + + if (exitCode != QMessageBox::Cancel) { - QMessageBox::information(this, "CoinKiller", tr("Due to limitations there can only be a maximum of 4 areas in a level."), QMessageBox::Ok); - return; + if (lvlMgr->getAreaCount() >= 4) + { + QMessageBox::information(this, "CoinKiller", tr("Due to limitations there can only be a maximum of 4 areas in a level."), QMessageBox::Ok); + return; + } + + int seekArea = lvlMgr->addArea(lvlMgr->getAreaCount()); + loadArea(seekArea); + updateAreaSelector(seekArea); } - - int seekArea = lvlMgr->addArea(lvlMgr->getAreaCount()); - loadArea(seekArea); - updateAreaSelector(seekArea); } } @@ -507,7 +660,8 @@ void LevelEditorWindow::on_actionDeleteCurrentArea_triggered() QMessageBox warning; warning.setWindowTitle("CoinKiller"); - warning.setText(tr("Are you sure you want to delete this area?\n\nThe level will automatically save afterwards and therefore the deletion of this area cannot be undone afterwards.")); + warning.setText(tr("Are you sure you want to delete this area?\n\n" + "The level will automatically save afterwards and therefore the deletion of this area cannot be undone afterwards.")); warning.setStandardButtons(QMessageBox::Yes); warning.addButton(QMessageBox::No); warning.setDefaultButton(QMessageBox::No); @@ -553,16 +707,18 @@ void LevelEditorWindow::loadArea(int id, bool closeLevel, bool init) delete levelView; delete miniMap; + + undoStack->blockSignals(true); } level = lvlMgr->openArea(id); - levelView = new LevelView(this, level); + levelView = new LevelView(this, level, undoStack); ui->levelViewArea->setWidget(levelView); levelView->setMinimumSize(4096*20, 4096*20); levelView->setMaximumSize(4096*20, 4096*20); - layerMask = 0x7; + levelView->editManagerPtr()->setLayerMask(LAYER_MASK::ALL, true); ui->actionToggleLayer1->setChecked(true); ui->actionToggleLayer2->setChecked(true); ui->actionToggleSprites->setChecked(true); @@ -571,82 +727,63 @@ void LevelEditorWindow::loadArea(int id, bool closeLevel, bool init) ui->actionToggle2DTile->setChecked(true); ui->actionToggle3DOverlay->setChecked(true); ui->actionToggleEntrances->setChecked(true); - ui->actionSelectAfterPlacement->setChecked(settings->get("SelectAfterPlacement").toBool()); - levelView->setLayerMask(layerMask); + levelView->toggleGrid(ui->actionGrid->isChecked()); levelView->toggleCheckerboard(ui->actionCheckerboard->isChecked()); levelView->toggleRenderLiquids(ui->actionRenderLiquids->isChecked()); levelView->toggleRenderCameraLimits(ui->actionRenderCameraLimits->isChecked()); - levelView->setBackgroundColor(settings->getColor("lewColor", QColor(119,136,153))); #ifdef USE_KDE_BLUR setBlurStylesheet(); #endif - levelView->toggleSprites(ui->actionToggleSprites->isChecked()); - levelView->togglePaths(ui->actionTogglePaths->isChecked()); - levelView->toggleLocations(ui->actionToggleLocations->isChecked()); - levelView->toggleEntrances(ui->actionToggleEntrances->isChecked()); + levelView->editManagerPtr()->enableSpriteInteraction(ui->actionToggleSprites->isChecked()); + levelView->editManagerPtr()->enableEntranceInteraction(ui->actionToggleEntrances->isChecked()); + levelView->editManagerPtr()->enablePathInteraction(ui->actionTogglePaths->isChecked()); + levelView->editManagerPtr()->enableLocationInteraction(ui->actionToggleLocations->isChecked()); zoom = 1.0; QString basePath(settings->dataPath("icons/")); // Setup Area Editor - areaEditor = new AreaEditorWidget(level, lvlMgr->getGame()); - connect(areaEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(areaEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + areaEditor = new AreaEditorWidget(level, lvlMgr->getGame(), undoStack); // Setup Tileset Picker - tilesetPalette = new TilesetPalette(level, levelView->objEditionModePtr(), lvlMgr->getGame()); - connect(tilesetPalette, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(tilesetPalette, SIGNAL(editMade()), this, SLOT(handleEditMade())); + tilesetPalette = new TilesetPalette(level, levelView->editManagerPtr(), lvlMgr->getGame(), undoStack); // Setup Sprite Picker - spriteEditor = new SpriteEditorWidget(&level->sprites); - connect(spriteEditor->spriteDataEditorPtr(), SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(spriteEditor, SIGNAL(currentSpriteChanged(int)), this, SLOT(setSelSprite(int))); - connect(spriteEditor, SIGNAL(selectedSpriteChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(spriteEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(spriteEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + spriteEditor = new SpriteEditorWidget(&level->sprites, undoStack); + connect(spriteEditor, &SpriteEditorWidget::currentSpriteChanged, this, &LevelEditorWindow::setSelSprite); + connect(spriteEditor, &SpriteEditorWidget::selectedSpriteChanged, levelView, &LevelView::selectObj); // Setup Entrance Editor - entranceEditor = new EntranceEditorWidget(&level->entrances); - connect(entranceEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(entranceEditor, SIGNAL(selectedEntrChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(entranceEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + entranceEditor = new EntranceEditorWidget(&level->entrances, undoStack); + connect(entranceEditor, &EntranceEditorWidget::selectedEntrChanged, levelView, &LevelView::selectObj); // Setup Zone Editor - zoneEditor = new ZoneEditorWidget(&level->zones, &level->backgrounds, &level->boundings); - connect(zoneEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(zoneEditor, SIGNAL(selectedZoneChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(zoneEditor, SIGNAL(selectZoneContents(Zone*)), levelView, SLOT(selectZoneContents(Zone*))); - connect(zoneEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); - connect(zoneEditor, SIGNAL(screenshot(QRect)), levelView, SLOT(screenshot(QRect))); + zoneEditor = new ZoneEditorWidget(&level->zones, &level->backgrounds, &level->boundings, undoStack, level); + connect(zoneEditor, &ZoneEditorWidget::selectedZoneChanged, levelView, &LevelView::selectObj); + connect(zoneEditor, &ZoneEditorWidget::selectZoneContents, levelView, &LevelView::selectZoneContents); + connect(zoneEditor, &ZoneEditorWidget::screenshot, levelView, &LevelView::screenshot); // Setup Location Editor - locationEditor = new LocationEditorWidget(&level->locations); - connect(locationEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(locationEditor, SIGNAL(selectedLocChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(locationEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + locationEditor = new LocationEditorWidget(&level->locations, undoStack); + connect(locationEditor, &LocationEditorWidget::selectedLocChanged, levelView, &LevelView::selectObj); // Setup Path Editor - pathEditor = new PathEditorWidget(&level->paths); - connect(pathEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(pathEditor, SIGNAL(selectedPathChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(pathEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + pathEditor = new PathEditorWidget(&level->paths, undoStack); + connect(pathEditor, &PathEditorWidget::selectedPathChanged, levelView, &LevelView::selectObj); // Setup Progress Path Editor - progPathEditor = new ProgressPathEditorWidget(&level->progressPaths); - connect(progPathEditor, SIGNAL(updateLevelView()), levelView, SLOT(update())); - connect(progPathEditor, SIGNAL(selectedProgPathChanged(Object*)), levelView, SLOT(selectObj(Object*))); - connect(progPathEditor, SIGNAL(editMade()), this, SLOT(handleEditMade())); + progPathEditor = new ProgressPathEditorWidget(&level->progressPaths, undoStack); + connect(progPathEditor, &ProgressPathEditorWidget::selectedProgPathChanged, levelView, &LevelView::selectObj); - connect(levelView, SIGNAL(scrollTo(int,int)), this, SLOT(scrollTo(int,int))); - connect(levelView->editionModePtr(), SIGNAL(selectdObjectChanged(Object*)), this, SLOT(setObjectEdition(Object*))); - connect(levelView->editionModePtr(), SIGNAL(deselected()), this, SLOT(deselect())); - connect(levelView->editionModePtr(), SIGNAL(updateEditors()), this, SLOT(updateEditors())); - connect(levelView->editionModePtr(), SIGNAL(editMade()), this, SLOT(handleEditMade())); + // Setup Level View + connect(levelView, &LevelView::scrollTo, this, &LevelEditorWindow::scrollTo); + connect(levelView->editManagerPtr(), &EditManager::selectdObjectChanged, this, &LevelEditorWindow::handleSelectionChanged); + connect(levelView->editManagerPtr(), &EditManager::deselected, this, &LevelEditorWindow::deselect); + connect(levelView->editManagerPtr(), &EditManager::updateEditors, this, &LevelEditorWindow::updateEditors); toolboxTabs->setUsesScrollButtons(true); toolboxTabs->addTab(areaEditor, QIcon(basePath + "settings.png"), ""); @@ -667,15 +804,20 @@ void LevelEditorWindow::loadArea(int id, bool closeLevel, bool init) toolboxTabs->setTabToolTip(7, "Progress Paths"); miniMap = new LevelMiniMap(this, level); - connect(levelView, SIGNAL(updateMinimap(QRect)), miniMap, SLOT(update_(QRect))); - connect(levelView, SIGNAL(updateMinimapBounds()), miniMap, SLOT(updateBounds())); - connect(miniMap, SIGNAL(scrollTo(int,int)), this, SLOT(scrollTo(int,int))); - //ui->miniMap->setWidget(miniMap); + connect(levelView, &LevelView::updateMinimap, miniMap, &LevelMiniMap::update_); + connect(levelView, &LevelView::updateMinimapBounds, miniMap, &LevelMiniMap::updateBounds); + connect(miniMap, &LevelMiniMap::scrollTo, this, &LevelEditorWindow::scrollTo); minimapDock->setWidget(miniMap); update(); toolboxTabs->blockSignals(false); + + undoStack->clear(); + undoStack->blockSignals(false); + + loadSettings(); + setStatus(Ready); } void LevelEditorWindow::updateAreaSelector(int index) @@ -692,7 +834,7 @@ void LevelEditorWindow::updateAreaSelector(int index) for (int i = 0; i < areaCount; i++) areaStrings << tr("Area %2").arg(i+1); - QStringListModel *model = new QStringListModel(); + QStringListModel *model = new QStringListModel(this); model->setStringList(areaStrings); areaSelector->setModel(model); @@ -708,64 +850,33 @@ void LevelEditorWindow::updateAreaSelector(int index) void LevelEditorWindow::handleAreaIndexChange(int index) { - bool ignore = false; + if (status == EditorStatus::Unsaved || status == EditorStatus::SaveFailed) { + int exitCode = showSaveDialog(); - if (unsavedChanges) - { - QMessageBox message(this); - message.setWindowTitle(tr("Unsaved Changes")); - message.setText(tr("Do you want to save your changes?")); - message.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); - - QSpacerItem* spacer = new QSpacerItem(400, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - QGridLayout* layout = (QGridLayout*)message.layout(); - layout->addItem(spacer, layout->rowCount(), 0, 1, layout->columnCount()); - - switch (message.exec()) - { - case QMessageBox::Save: - levelView->saveLevel(); - unsavedChanges = false; - editStatus->setText(tr("Changes Saved")); - break; - case QMessageBox::Discard: - unsavedChanges = false; - editStatus->setText(tr("Ready!")); - break; - case QMessageBox::Cancel: - ignore = true; - break; - } + if (exitCode == QMessageBox::Cancel) { + areaSelector->blockSignals(true); + areaSelector->setCurrentIndex(level->getAreaID()-1); + areaSelector->blockSignals(false); + return; + } } - if (!ignore) - { - index++; + index++; - if (lvlMgr->areaIsOpen(index)) - { - updateAreaSelector(level->getAreaID()); - QMessageBox::information(this, "CoinKiller", tr("Area %1 cannot be opened because it is already opened in another editor window.").arg(index), QMessageBox::Ok); - return; - } + if (lvlMgr->areaIsOpen(index)) { + updateAreaSelector(level->getAreaID()); + QMessageBox::information(this, "CoinKiller", tr("Area %1 cannot be opened because it is already opened in another editor window.").arg(index), QMessageBox::Ok); + return; + } - if (QApplication::queryKeyboardModifiers() &= Qt::ControlModifier) - { - updateAreaSelector(level->getAreaID()); - lvlMgr->openAreaEditor(index); - } - else - { - loadArea(index); - updateAreaSelector(); - } - } - else - { - areaSelector->blockSignals(true); - areaSelector->setCurrentIndex(level->getAreaID()-1); - areaSelector->blockSignals(false); - } + if (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) { + updateAreaSelector(level->getAreaID()); + lvlMgr->openAreaEditor(index); + } + else { + loadArea(index); + updateAreaSelector(); + } } void LevelEditorWindow::handleMgrUpdate() @@ -781,69 +892,20 @@ void LevelEditorWindow::scrollTo(int x, int y) ui->levelViewArea->verticalScrollBar()->setValue(y*zoom); } -void LevelEditorWindow::on_actionSetBackgroundColor_triggered() -{ - QColorDialog::ColorDialogOptions options = QColorDialog::DontUseNativeDialog; -#ifdef USE_KDE_BLUR - options |= QColorDialog::ShowAlphaChannel; -#endif - - QColor bgColor = QColorDialog::getColor(settings->getColor("lewColor", QColor(119,136,153)), this, tr("Select Background Color"), options); - if(bgColor.isValid()) - { - levelView->setBackgroundColor(bgColor); - settings->setColor("lewColor", bgColor); - } -} - -void LevelEditorWindow::on_actionResetBackgroundColor_triggered() -{ - QMessageBox::StandardButton reset; - reset = QMessageBox::question(this, "CoinKiller", tr("Are you sure you wish to reset the background color?"), QMessageBox::Cancel|QMessageBox::Ok); - if(reset == QMessageBox::Ok) - { - levelView->setBackgroundColor(QColor(119,136,153)); - settings->setColor("lewColor", QColor(119,136,153)); - } -} - -void LevelEditorWindow::on_actionHideStatusbar_toggled(bool hide) -{ - settings->set("lvleditorHideStatusBar", hide); - ui->statusbar->setHidden(hide); -} - void LevelEditorWindow::closeEvent(QCloseEvent *event) { - if (unsavedChanges) - { - QMessageBox message(this); - message.setWindowTitle(tr("Unsaved Changes")); - message.setText(tr("Do you want to save your changes?")); - message.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard); - - QSpacerItem* spacer = new QSpacerItem(400, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - QGridLayout* layout = (QGridLayout*)message.layout(); - layout->addItem(spacer, layout->rowCount(), 0, 1, layout->columnCount()); + if (status == EditorStatus::Unsaved || status == EditorStatus::SaveFailed) { + int exitCode = showSaveDialog(); - switch (message.exec()) - { - case QMessageBox::Save: - levelView->saveLevel(); - event->accept(); - break; - case QMessageBox::Cancel: + if (exitCode == QMessageBox::Cancel) { event->ignore(); - break; - case QMessageBox::Discard: + } else { event->accept(); - break; } } - else event->accept(); - if (event->isAccepted()) - { + if (event->isAccepted()) { + undoStack->clear(); settings->set("lvleditorState", saveState()); } } @@ -858,10 +920,16 @@ void LevelEditorWindow::on_actionShowMinimap_toggled(bool checked) minimapDock->setHidden(!checked); } +void LevelEditorWindow::on_actionShowHistory_toggled(bool checked) +{ + historyDock->setHidden(!checked); +} + void LevelEditorWindow::updateDockedWidgetCheckboxes() { ui->actionShowToolbox->setChecked(!toolboxDock->isHidden()); ui->actionShowMinimap->setChecked(!minimapDock->isHidden()); + ui->actionShowHistory->setChecked(!historyDock->isHidden()); } #ifdef USE_KDE_BLUR diff --git a/leveleditorwindow.h b/leveleditor/leveleditorwindow.h similarity index 72% rename from leveleditorwindow.h rename to leveleditor/leveleditorwindow.h index ae0ace72..ffa83ecc 100644 --- a/leveleditorwindow.h +++ b/leveleditor/leveleditorwindow.h @@ -18,8 +18,10 @@ #include #include #include +#include +#include -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "levelview.h" #include "levelminimap.h" #include "ctpk.h" @@ -36,6 +38,7 @@ #include "eventeditorwidget.h" #include "settingsmanager.h" #include "windowbase.h" +#include "layermask.h" namespace Ui { class LevelEditorWindow; @@ -57,22 +60,21 @@ class LevelEditorWindow : public WindowBase #endif public slots: - void setObjectEdition(Object* obj); + void handleSelectionChanged(Object* obj); void deselect(); void updateEditors(); void scrollTo(int x, int y); - void handleEditMade(); private slots: - void on_actionToggleLayer1_toggled(bool arg1); + void toggleLayer(bool toggle); - void on_actionToggleLayer2_toggled(bool arg1); + void toggleSprites(bool toggle); - void on_actionToggleSprites_toggled(bool arg1); + void toggleEntrances(bool toggle); - void on_actionTogglePaths_toggled(bool arg1); + void togglePaths(bool toggle); - void on_actionToggleLocations_toggled(bool arg1); + void toggleLocations(bool toggle); void on_actionZoom_In_triggered(); @@ -126,25 +128,23 @@ private slots: void on_actionSelectAll_triggered(); - void on_actionSetBackgroundColor_triggered(); - - void on_actionResetBackgroundColor_triggered(); - - void on_actionSelectAfterPlacement_toggled(bool arg1); - - void on_actionHideStatusbar_toggled(bool hide); - void on_actionShowMinimap_toggled(bool checked); void on_actionShowToolbox_toggled(bool checked); + void on_actionShowHistory_toggled(bool checked); + void updateDockedWidgetCheckboxes(); void on_actionToggle3DOverlay_toggled(bool arg1); void on_actionToggle2DTile_toggled(bool arg1); - void on_actionToggleEntrances_toggled(bool arg1); + void historyStateChanged(int index); + + void showPreferencesDialog(bool show); + + void loadSettings(); private: Ui::LevelEditorWindow *ui; @@ -154,35 +154,44 @@ private slots: Level* level; Tileset* tileset; - LevelView* levelView; + LevelView* levelView = nullptr; LevelMiniMap* miniMap; - AreaEditorWidget* areaEditor; - TilesetPalette* tilesetPalette; - SpriteEditorWidget* spriteEditor; - EntranceEditorWidget* entranceEditor; - ZoneEditorWidget* zoneEditor; - LocationEditorWidget* locationEditor; - PathEditorWidget* pathEditor; - ProgressPathEditorWidget* progPathEditor; - SpriteIdWidget* spriteIds; - EventEditorWidget* eventEditor; + AreaEditorWidget* areaEditor = nullptr; + TilesetPalette* tilesetPalette = nullptr; + SpriteEditorWidget* spriteEditor = nullptr; + EntranceEditorWidget* entranceEditor = nullptr; + ZoneEditorWidget* zoneEditor = nullptr; + LocationEditorWidget* locationEditor = nullptr; + PathEditorWidget* pathEditor = nullptr; + ProgressPathEditorWidget* progPathEditor = nullptr; + SpriteIdWidget* spriteIds = nullptr; + EventEditorWidget* eventEditor = nullptr; QComboBox* areaSelector; - QLabel* editStatus; + QLabel* statusLabel; + + enum EditorStatus { + Ready, + Unsaved, + SaveFailed, + ChangesSaved + }; + + EditorStatus status; + void setStatus(EditorStatus newStatus); void changeEvent(QEvent* event); void updateAreaSelector(int index = -1); - quint8 layerMask; float zoom; void loadArea(int id, bool closeLevel = true, bool init = false); bool closeLvlOnClose = true; - bool unsavedChanges = false; + bool editorsLoaded(); #ifdef USE_KDE_BLUR void setBlurStylesheet(); @@ -192,7 +201,15 @@ private slots: QTabWidget* toolboxTabs; QDockWidget* minimapDock; + QDockWidget* historyDock; + + QUndoStack* undoStack; + QUndoView* undoView; + + QAction* actionUndo; + QAction* actionRedo; + const int showSaveDialog(); }; #endif // LEVELEDITORWINDOW_H diff --git a/leveleditorwindow.ui b/leveleditor/leveleditorwindow.ui similarity index 92% rename from leveleditorwindow.ui rename to leveleditor/leveleditorwindow.ui index 1cb7a84f..45412336 100644 --- a/leveleditorwindow.ui +++ b/leveleditor/leveleditorwindow.ui @@ -47,7 +47,7 @@ 0 0 1278 - 634 + 624 @@ -69,6 +69,8 @@ File + + @@ -111,27 +113,18 @@ - - - Settings - - - - - - Window + - @@ -442,22 +435,6 @@ Checkerboard - - - Set Background Color - - - Set Background Color - - - - - Reset Background Color - - - Reset Background Color - - true @@ -491,28 +468,6 @@ Render Camera Limits - - - true - - - Select Objects When Placed - - - Select Objects When Placed - - - - - true - - - Hide Statusbar - - - Hide Statusbar - - true @@ -579,6 +534,22 @@ Toggle Entrances + + + true + + + Show History + + + Show History + + + + + Preferences + + diff --git a/levelminimap.cpp b/leveleditor/levelminimap.cpp similarity index 100% rename from levelminimap.cpp rename to leveleditor/levelminimap.cpp diff --git a/levelminimap.h b/leveleditor/levelminimap.h similarity index 100% rename from levelminimap.h rename to leveleditor/levelminimap.h diff --git a/levelview.cpp b/leveleditor/levelview.cpp similarity index 87% rename from levelview.cpp rename to leveleditor/levelview.cpp index f05c2166..bcab5018 100644 --- a/levelview.cpp +++ b/leveleditor/levelview.cpp @@ -33,27 +33,21 @@ #include -LevelView::LevelView(QWidget *parent, Level* level) : QWidget(parent) +LevelView::LevelView(QWidget *parent, Level *level, QUndoStack *undoStack) : + QWidget(parent), level(level), undoStack(undoStack) { - this->level = level; - - layerMask = 0x7; // failsafe - setMouseTracking(true); - setEditonMode(EditMode_ObjectsMode, true); + editManager = new EditManager(level, undoStack); + connect(editManager, SIGNAL(updateLevelView()), this, SLOT(update())); zoom = 1; grid = false; checkerboard = false; renderLiquids = false; renderCameraLimits = false; - renderSprites = true; - renderPaths = true; - renderLocations = true; render2DTile = true; render3DOverlay = true; - renderEntrances = true; #ifdef USE_KDE_BLUR setBackgroundColor(QColor(0,0,0,0)); @@ -62,8 +56,7 @@ LevelView::LevelView(QWidget *parent, Level* level) : QWidget(parent) LevelView::~LevelView() { - mode->deactivate(); - delete objectEditionMode; + delete editManager; } void LevelView::paintEvent(QPaintEvent* evt) @@ -145,7 +138,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti // Render Tiles for (int l = 1; l >= 0; l--) { - if (!(layerMask & (1<getLayerMask() & (1<locationInteractionEnabled()) { for (int i = 0; i < level->locations.size(); i++) { @@ -200,7 +193,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti } } - if (renderSprites) + if (editManager->spriteInteractionEnabled()) { // Render Liquids if (renderLiquids) @@ -341,10 +334,10 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti // Render Camera Limit Boundries if (renderCameraLimits) { - QList leftCamLimits = level->getLeftCamLimits(); - QList rightCamLimits = level->getRightCamLimits(); - QList topCamLimits = level->getTopCamLimits(); - QList bottomCamLimits = level->getBottomCamLimits(); + QList leftCamLimits = level->leftCamLimits; + QList rightCamLimits = level->rightCamLimits; + QList topCamLimits = level->topCamLimits; + QList bottomCamLimits = level->bottomCamLimits; foreach (Sprite* left, leftCamLimits) { @@ -404,7 +397,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti bool isRight = false; int xRenderOffset = 0; foreach (Sprite* bottom, bottomCamLimits) - { + { if (bottom->getx() != top->getx()) continue; @@ -445,7 +438,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti } // Render Entrances - if (renderEntrances) + if (editManager->entranceInteractionEnabled()) { for (int i = 0; i < level->entrances.size(); i++) { @@ -461,7 +454,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti } } // Render Paths - if (renderPaths) + if (editManager->pathInteractionEnabled()) { for (int i = 0; i < level->paths.size(); i++) { @@ -584,7 +577,7 @@ void LevelView::paint(QPainter& painter, QRect rect, float zoomLvl, bool selecti // Render Edition Mode Stuff if (selections) - mode->render(&painter); + editManager->render(&painter); // Render Grid if (grid) @@ -658,11 +651,11 @@ void LevelView::mousePressEvent(QMouseEvent* evt) dragY = evt->position().y(); } - if (mode != NULL) + if (editManager != NULL) { if (evt->buttons() == Qt::LeftButton || evt->buttons() == Qt::RightButton) - mode->mouseDown(evt->position().x()/zoom, evt->position().y()/zoom, evt->buttons(), evt->modifiers(), drawrect); - setCursor(QCursor(mode->getActualCursor())); + editManager->mouseDown(evt->position().x()/zoom, evt->position().y()/zoom, evt->buttons(), evt->modifiers(), drawrect); + setCursor(QCursor(editManager->getActualCursor())); } update(); @@ -671,7 +664,7 @@ void LevelView::mousePressEvent(QMouseEvent* evt) void LevelView::mouseMoveEvent(QMouseEvent* evt) -{ +{ if (evt->buttons() & Qt::MiddleButton) { int x = evt->position().x(); @@ -680,42 +673,29 @@ void LevelView::mouseMoveEvent(QMouseEvent* evt) emit scrollTo((visibleRegion().boundingRect().x() - x + dragX)/zoom, (visibleRegion().boundingRect().y() - y + dragY)/zoom); } - if (mode != NULL) + if (editManager != nullptr) { int x = evt->position().x()/zoom; int y = evt->position().y()/zoom; if (evt->buttons() == Qt::LeftButton || evt->buttons() == Qt::RightButton) { - mode->mouseDrag(x, y, evt->modifiers(), drawrect); + editManager->mouseDrag(x, y, evt->modifiers(), drawrect); } else - mode->mouseMove(x, y); - } - setCursor(QCursor(mode->getActualCursor())); - update(); - - /*QString ret; - - foreach (Sprite* spr, level->sprites) - { - QRect spriteRect = QRect(spr->getx()+spr->getOffsetX(), spr->gety()+spr->getOffsetY(), spr->getwidth(), spr->getheight()); - QRect mouseRect = QRect(evt->x(), evt->y(), 20, 20); - - ret = "(" + QString::number(evt->x()) + ", " + QString::number(evt->y()) + ")"; - - emit updateLevelLabel(ret); - //if (spriteRect.intersects(mouseRect)) + editManager->mouseMove(x, y); - }*/ + setCursor(QCursor(editManager->getActualCursor())); + } + update(); emit updateMinimapBounds(); } void LevelView::mouseReleaseEvent(QMouseEvent *evt) { - mode->mouseUp(evt->position().x()/zoom, evt->position().y()/zoom); - setCursor(QCursor(mode->getActualCursor())); + editManager->mouseUp(evt->position().x()/zoom, evt->position().y()/zoom); + setCursor(QCursor(editManager->getActualCursor())); update(); } @@ -734,42 +714,7 @@ void LevelView::keyPressEvent(QKeyEvent* evt) return; } - mode->keyPress(evt); -} - -void LevelView::setLayerMask(quint8 mask) -{ - layerMask = mask; - editionModePtr()->setLayerMask(layerMask); - update(); -} - -void LevelView::toggleSprites(bool toggle) -{ - renderSprites = toggle; - editionModePtr()->toggleSprites(toggle); - update(); -} - -void LevelView::togglePaths(bool toggle) -{ - renderPaths = toggle; - editionModePtr()->togglePaths(toggle); - update(); -} - -void LevelView::toggleLocations(bool toggle) -{ - renderLocations = toggle; - editionModePtr()->toggleLocations(toggle); - update(); -} - -void LevelView::toggleEntrances(bool toggle) -{ - renderEntrances = toggle; - editionModePtr()->toggleEntrances(toggle); - update(); + editManager->keyPress(evt); } qint8 LevelView::saveLevel() @@ -779,7 +724,7 @@ qint8 LevelView::saveLevel() void LevelView::copy() { - editionModePtr()->copy(); + editManager->copy(); } void LevelView::paste() @@ -789,59 +734,59 @@ void LevelView::paste() int w = visibleRegion().boundingRect().width()/zoom; int h = visibleRegion().boundingRect().height()/zoom; - editionModePtr()->paste(x, y, w, h); + editManager->paste(x, y, w, h); update(); emit updateMinimapBounds(); } void LevelView::raise() { - objEditionModePtr()->raise(); + editManager->raise(); update(); } void LevelView::lower() { - objEditionModePtr()->lower(); + editManager->lower(); update(); } void LevelView::raiseLayer() { - objEditionModePtr()->raiseLayer(); + editManager->raiseLayer(); update(); } void LevelView::lowerLayer() { - objEditionModePtr()->lowerLayer(); + editManager->lowerLayer(); update(); } void LevelView::cut() { - editionModePtr()->cut(); + editManager->cut(); update(); emit updateMinimapBounds(); } void LevelView::selectAll() { - editionModePtr()->selectAll(); + editManager->selectAll(); update(); } void LevelView::deleteSel() { - mode->deleteSelection(); - setCursor(QCursor(mode->getActualCursor())); + editManager->deleteSelection(); + setCursor(QCursor(editManager->getActualCursor())); update(); emit updateMinimapBounds(); } void LevelView::selectObj(Object *obj) { - mode->select(obj); + editManager->select(obj); int x = obj->getx()+obj->getOffsetX(); int y = obj->gety()+obj->getOffsetY(); @@ -862,31 +807,6 @@ void LevelView::selectObj(Object *obj) void LevelView::selectZoneContents(Zone* zone) { - if (is(mode)) - { - objectEditionMode->selectZoneContents(zone); - update(); - } -} - -void LevelView::setEditonMode(EditMode newMode, bool init) -{ - if (init) - { - objectEditionMode = new ObjectsEditonMode(level); - connect(objectEditionMode, SIGNAL(updateLevelView()), this, SLOT(update())); - } - else - mode->deactivate(); - - switch (newMode) - { - case EditMode_ObjectsMode: - default: - mode = objectEditionMode; - break; - } - - mode->activate(); + editManager->selectZoneContents(zone); update(); } diff --git a/levelview.h b/leveleditor/levelview.h similarity index 81% rename from levelview.h rename to leveleditor/levelview.h index 4bcb6053..82e09a6c 100644 --- a/levelview.h +++ b/leveleditor/levelview.h @@ -21,20 +21,20 @@ #include #include #include +#include -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "level.h" #include "tileset.h" -#include "objectseditionmode.h" +#include "editmanager.h" class LevelView : public QWidget { Q_OBJECT public: - explicit LevelView(QWidget *parent, Level* level); + explicit LevelView(QWidget *parent, Level *level, QUndoStack *undoStack); ~LevelView(); - void setLayerMask(quint8 mask); void setZoom(float zoom) { this->zoom = zoom; setMinimumSize(4096*20*zoom, 4096*20*zoom); setMaximumSize(4096*20*zoom, 4096*20*zoom); update(); } void toggleGrid(bool toggle) { grid = toggle; update(); } void toggleCheckerboard(bool toggle) { checkerboard = toggle; update(); } @@ -42,10 +42,7 @@ class LevelView : public QWidget void toggleRenderCameraLimits(bool toggle) { renderCameraLimits = toggle; update(); } void toggle3DOverlay(bool toggle) { render3DOverlay = toggle; update(); } void toggle2DTile(bool toggle) { render2DTile = toggle; update(); } - void toggleSprites(bool toggle); - void togglePaths(bool toggle); - void toggleLocations(bool toggle); - void toggleEntrances(bool toggle); + qint8 saveLevel(); void copy(); void paste(); @@ -58,10 +55,7 @@ class LevelView : public QWidget void lowerLayer(); void setBackgroundColor(QColor bgcolor) {backgroundColor = bgcolor; update(); } - void setEditonMode(EditMode newMode, bool init = false); - - EditionMode* editionModePtr() { return mode; } - ObjectsEditonMode* objEditionModePtr() { return objectEditionMode; } + EditManager* editManagerPtr() { return editManager; } signals: void scrollTo(int x, int y); @@ -88,27 +82,22 @@ public slots: Level* level; + QUndoStack *undoStack; + QRect drawrect; float zoom; int dragX; int dragY; - ObjectsEditonMode* objectEditionMode; - EditionMode* mode; + EditManager* editManager; bool grid; bool checkerboard; bool renderLiquids; bool renderCameraLimits; - bool renderSprites; - bool renderPaths; - bool renderLocations; bool render2DTile; bool render3DOverlay; - bool renderEntrances; - - quint8 layerMask; // determines which tiles are already occupied TileGrid tileGrid; diff --git a/locationeditorwidget.cpp b/leveleditor/locationeditorwidget.cpp similarity index 81% rename from locationeditorwidget.cpp rename to leveleditor/locationeditorwidget.cpp index c25ad63b..0c375b41 100644 --- a/locationeditorwidget.cpp +++ b/leveleditor/locationeditorwidget.cpp @@ -4,15 +4,18 @@ #include #include -LocationEditorWidget::LocationEditorWidget(QList *locations) -{ - this->locations = locations; +#include "commands/locationcommands.h" + +LocationEditorWidget::LocationEditorWidget(QList *locations, QUndoStack *undoStack, QWidget *parent) : + QWidget(parent), + locations(locations), + undoStack(undoStack) { QVBoxLayout* layout = new QVBoxLayout(); setLayout(layout); locationList = new QListWidget(); - connect(locationList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleLocationListIndexChange(QListWidgetItem*))); + connect(locationList, &QListWidget::itemClicked, this, &LocationEditorWidget::handleLocationListIndexChange); layout->addWidget(locationList); edits = new QWidget(); @@ -23,7 +26,7 @@ LocationEditorWidget::LocationEditorWidget(QList *locations) subLayout->addWidget(new QLabel(tr("ID:")), 0, 0, 1, 1, Qt::AlignRight); id = new QSpinBox(); id->setRange(0, 255); - connect(id, SIGNAL(valueChanged(int)), this, SLOT(handleIDChange(int))); + connect(id, &QSpinBox::valueChanged, this, &LocationEditorWidget::handleIDChange); subLayout->addWidget(id, 0, 1); layout->addWidget(edits); @@ -78,13 +81,11 @@ void LocationEditorWidget::updateEditor() updateList(); } -void LocationEditorWidget::handleIDChange(int idVal) +void LocationEditorWidget::handleIDChange(int id) { if (!handleChanges) return; - editLocation->setId(idVal); + undoStack->push(new Commands::LocationCmd::SetId(editLocation, id)); updateList(); - emit updateLevelView(); - emit editMade(); } void LocationEditorWidget::handleLocationListIndexChange(QListWidgetItem *item) diff --git a/locationeditorwidget.h b/leveleditor/locationeditorwidget.h similarity index 82% rename from locationeditorwidget.h rename to leveleditor/locationeditorwidget.h index 8761e427..9b780569 100644 --- a/locationeditorwidget.h +++ b/leveleditor/locationeditorwidget.h @@ -6,20 +6,19 @@ #include #include #include +#include class LocationEditorWidget : public QWidget { Q_OBJECT public: - LocationEditorWidget(QList *locations); + LocationEditorWidget(QList *locations, QUndoStack *undoStack, QWidget *parent = nullptr); void deselect(); void select(Location *loc); void updateEditor(); signals: - void updateLevelView(); void selectedLocChanged(Object* loc); - void editMade(); private slots: void handleLocationListIndexChange(QListWidgetItem *item); @@ -37,6 +36,8 @@ private slots: Location* editLocation; bool editingALocation = false; bool handleChanges = true; + + QUndoStack *undoStack; }; #endif // LOCATIONEDITORWIDGET_H diff --git a/patheditorwidget.cpp b/leveleditor/patheditorwidget.cpp similarity index 67% rename from patheditorwidget.cpp rename to leveleditor/patheditorwidget.cpp index 09b44208..dfc8e917 100644 --- a/patheditorwidget.cpp +++ b/leveleditor/patheditorwidget.cpp @@ -3,9 +3,13 @@ #include #include -PathEditorWidget::PathEditorWidget(QList *paths) -{ - this->paths = paths; +#include "commands/pathcommands.h" +#include "commands/pathnodecommands.h" + +PathEditorWidget::PathEditorWidget(QList *paths, QUndoStack *undoStack, QWidget *parent) : + QWidget(parent), + paths(paths), + undoStack(undoStack) { QVBoxLayout* layout = new QVBoxLayout(); @@ -82,20 +86,19 @@ PathEditorWidget::PathEditorWidget(QList *paths) layout->addWidget(edits); setLayout(layout); - connect(pathList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handlePathListIndexChanged(QListWidgetItem*))); - connect(id, SIGNAL(valueChanged(int)), this, SLOT(handleIDChanged(int))); - connect(loop, SIGNAL(stateChanged(int)), this, SLOT(handleLoopChanged())); - connect(speed, SIGNAL(valueChanged(double)), this, SLOT(handleSpeedChanged(double))); - connect(acceleration, SIGNAL(valueChanged(double)), this, SLOT(handleAccelChanged(double))); - connect(delay, SIGNAL(valueChanged(int)), this, SLOT(handleDelayChanged(int))); + connect(pathList, &QListWidget::itemClicked, this, &PathEditorWidget::handlePathListIndexChanged); + connect(id, &QSpinBox::valueChanged, this, &PathEditorWidget::handleIDChanged); + connect(loop, &QCheckBox::stateChanged, this, &PathEditorWidget::handleLoopChanged); + connect(speed, &QDoubleSpinBox::valueChanged, this, &PathEditorWidget::handleSpeedChanged); + connect(acceleration, &QDoubleSpinBox::valueChanged, this, &PathEditorWidget::handleAccelChanged); + connect(delay, &QSpinBox::valueChanged, this, &PathEditorWidget::handleDelayChanged); - connect(rotation, SIGNAL(valueChanged(int)), this, SLOT(handleRotationChanged(int))); - connect(variableField, SIGNAL(valueChanged(int)), this, SLOT(handleVariableFieldChanged(int))); - connect(nextPathID, SIGNAL(valueChanged(int)), this, SLOT(handleNextPathIDChanged(int))); - connect(nodeID, SIGNAL(valueChanged(int)), this, SLOT(handleNodeIDChanged(int))); + connect(rotation, &QSpinBox::valueChanged, this, &PathEditorWidget::handleRotationChanged); + connect(variableField, &QSpinBox::valueChanged, this, &PathEditorWidget::handleVariableFieldChanged); + connect(nextPathID, &QSpinBox::valueChanged, this, &PathEditorWidget::handleNextPathIDChanged); + connect(nodeID, &QSpinBox::valueChanged, this, &PathEditorWidget::handleNodeIDChanged); - updateList(); - updateInfo(); + updateEditor(); } void PathEditorWidget::updateEditor() @@ -112,7 +115,7 @@ void PathEditorWidget::updateList() foreach (Path* path, *paths) { QListWidgetItem* pathItem = new QListWidgetItem(); - pathItem->setText(tr("Path %1: %n Node(s)", 0, path->getNumberOfNodes()).arg(path->getid())); + pathItem->setText(tr("Path %1: %n Node(s)", nullptr, path->getNumberOfNodes()).arg(path->getid())); pathList->addItem(pathItem); } pathList->setCurrentIndex(index); @@ -152,7 +155,7 @@ void PathEditorWidget::select(PathNode* node) editingAPath = true; updateInfo(); handleChanges = false; - pathList->setCurrentRow(paths->indexOf(editPath)); + pathList->setCurrentRow(static_cast(paths->indexOf(editPath))); handleChanges = true; } @@ -173,80 +176,70 @@ void PathEditorWidget::handlePathListIndexChanged(QListWidgetItem *item) emit selectedPathChanged(editPath->getNode(0)); } -void PathEditorWidget::handleIDChanged(int idVal) +void PathEditorWidget::handleIDChanged(int id) { if (!handleChanges) return; - editPath->setId(idVal); + undoStack->push(new Commands::PathCmd::SetId(editPath, id)); updateList(); - emit updateLevelView(); - emit editMade(); } void PathEditorWidget::handleLoopChanged() { if (!handleChanges) return; - if (loop->isChecked()) - editPath->setLoop(2); - else - editPath->setLoop(0); - - emit updateLevelView(); - emit editMade(); + if (loop->isChecked()) { + undoStack->push(new Commands::PathCmd::SetLoop(editPath, 2)); + } else { + undoStack->push(new Commands::PathCmd::SetLoop(editPath, 0)); + } } -void PathEditorWidget::handleSpeedChanged(double speedVal) +void PathEditorWidget::handleSpeedChanged(double speed) { if (!handleChanges) return; - editNode->setSpeed((float)speedVal); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetSpeed(editNode, static_cast(speed))); } -void PathEditorWidget::handleAccelChanged(double accelVal) +void PathEditorWidget::handleAccelChanged(double accel) { if (!handleChanges) return; - editNode->setAccel((float)accelVal); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetAccel(editNode, static_cast(accel))); } -void PathEditorWidget::handleDelayChanged(int delayVal) +void PathEditorWidget::handleDelayChanged(int delay) { if (!handleChanges) return; - editNode->setDelay(delayVal); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetDelay(editNode, delay)); } -void PathEditorWidget::handleRotationChanged(int rotationVal) +void PathEditorWidget::handleRotationChanged(int rotation) { if (!handleChanges) return; - editNode->setRotation(rotationVal); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetRotation(editNode, static_cast(rotation))); } -void PathEditorWidget::handleVariableFieldChanged(int flagVal) +void PathEditorWidget::handleVariableFieldChanged(int value) { if (!handleChanges) return; - editNode->setVariableField(flagVal); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetVariableField(editNode, value)); } void PathEditorWidget::handleNextPathIDChanged(int nextPathID) { if (!handleChanges) return; - editNode->setNextPathID(nextPathID); - emit editMade(); + undoStack->push(new Commands::PathNodeCmd::SetNextPathID(editNode, nextPathID)); } void PathEditorWidget::handleNodeIDChanged(int nodeID) { if (!handleChanges) return; - if (nodeID >= editPath->getNumberOfNodes()) - { + + if (nodeID >= editPath->getNumberOfNodes()) { + this->nodeID->blockSignals(true); this->nodeID->setValue(editPath->getIndexOfNode(editNode)); + this->nodeID->blockSignals(false); return; } - editPath->swapNodes(editPath->getIndexOfNode(editNode), nodeID); - emit updateLevelView(); - emit updateInfo(); - emit editMade(); + undoStack->push(new Commands::PathCmd::SwapNodes(editPath, editPath->getIndexOfNode(editNode), nodeID)); + updateInfo(); } diff --git a/patheditorwidget.h b/leveleditor/patheditorwidget.h similarity index 90% rename from patheditorwidget.h rename to leveleditor/patheditorwidget.h index 733a1a32..82894fe5 100644 --- a/patheditorwidget.h +++ b/leveleditor/patheditorwidget.h @@ -10,22 +10,19 @@ #include #include #include +#include class PathEditorWidget : public QWidget { Q_OBJECT public: - PathEditorWidget(QList *paths); + PathEditorWidget(QList *paths, QUndoStack *undoStack, QWidget *parent = nullptr); void deselect(); void select(PathNode* node); void updateEditor(); signals: - void updateLevelView(); void selectedPathChanged(Object* pPath); - void editMade(); - -public slots: private: Path* editPath; @@ -50,6 +47,7 @@ public slots: QSpinBox* nodeID; + QUndoStack *undoStack; void updateList(); void updateInfo(); diff --git a/progresspatheditorwidget.cpp b/leveleditor/progresspatheditorwidget.cpp similarity index 72% rename from progresspatheditorwidget.cpp rename to leveleditor/progresspatheditorwidget.cpp index b4e07983..bedc000e 100644 --- a/progresspatheditorwidget.cpp +++ b/leveleditor/progresspatheditorwidget.cpp @@ -2,9 +2,12 @@ #include -ProgressPathEditorWidget::ProgressPathEditorWidget(QList *paths) -{ - this->paths = paths; +#include "commands/progresspathcommands.h" + +ProgressPathEditorWidget::ProgressPathEditorWidget(QList *paths, QUndoStack *undoStack, QWidget *parent) : + QWidget(parent), + paths(paths), + undoStack(undoStack) { QVBoxLayout* layout = new QVBoxLayout(); @@ -28,9 +31,9 @@ ProgressPathEditorWidget::ProgressPathEditorWidget(QList *paths) layout->addWidget(edits); setLayout(layout); - connect(pathList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handlePathListIndexChanged(QListWidgetItem*))); - connect(id, SIGNAL(valueChanged(int)), this, SLOT(handleIDChanged(int))); - connect(alternatePathFlag, SIGNAL(toggled(bool)), this, SLOT(handleAlternetePathFlagChanged(bool))); + connect(pathList, &QListWidget::itemClicked, this, &ProgressPathEditorWidget::handlePathListIndexChanged); + connect(id, &QSpinBox::valueChanged, this, &ProgressPathEditorWidget::handleIDChanged); + connect(alternatePathFlag, &QAbstractButton::toggled, this, &ProgressPathEditorWidget::handleAlternetePathFlagChanged); updateList(); updateInfo(); @@ -50,7 +53,7 @@ void ProgressPathEditorWidget::updateList() foreach (ProgressPath* path, *paths) { QListWidgetItem* pathItem = new QListWidgetItem(); - pathItem->setText(tr("Progress Path %1: %n Node(s)", 0, path->getNumberOfNodes()).arg(path->getid())); + pathItem->setText(tr("Progress Path %1: %n Node(s)", nullptr, path->getNumberOfNodes()).arg(path->getid())); pathList->addItem(pathItem); } pathList->setCurrentIndex(index); @@ -77,7 +80,7 @@ void ProgressPathEditorWidget::select(ProgressPathNode* node) editingAPath = true; updateInfo(); handleChanges = false; - pathList->setCurrentRow(paths->indexOf(editPath)); + pathList->setCurrentRow(static_cast(paths->indexOf(editPath))); handleChanges = true; } @@ -97,18 +100,15 @@ void ProgressPathEditorWidget::handlePathListIndexChanged(QListWidgetItem *item) emit selectedProgPathChanged(editPath->getNode(0)); } -void ProgressPathEditorWidget::handleIDChanged(int idVal) +void ProgressPathEditorWidget::handleIDChanged(int id) { if (!handleChanges) return; - editPath->setId(idVal); + undoStack->push(new Commands::ProgressPathCmd::SetId(editPath, id)); updateList(); - emit updateLevelView(); - emit editMade(); } -void ProgressPathEditorWidget::handleAlternetePathFlagChanged(bool apfVal) +void ProgressPathEditorWidget::handleAlternetePathFlagChanged(bool flag) { if (!handleChanges) return; - editPath->setAlternatePathFlag(apfVal); - emit editMade(); + undoStack->push(new Commands::ProgressPathCmd::SetAltPathFlag(editPath, flag)); } diff --git a/progresspatheditorwidget.h b/leveleditor/progresspatheditorwidget.h similarity index 85% rename from progresspatheditorwidget.h rename to leveleditor/progresspatheditorwidget.h index 480f80cd..90ba9c54 100644 --- a/progresspatheditorwidget.h +++ b/leveleditor/progresspatheditorwidget.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "objects.h" @@ -15,15 +16,13 @@ class ProgressPathEditorWidget : public QWidget { Q_OBJECT public: - ProgressPathEditorWidget(QList *paths); + ProgressPathEditorWidget(QList *paths, QUndoStack *undoStack, QWidget *parent = nullptr); void deselect(); void select(ProgressPathNode* node); void updateEditor(); signals: - void updateLevelView(); void selectedProgPathChanged(Object* pPath); - void editMade(); public slots: @@ -39,6 +38,8 @@ public slots: QSpinBox* id; QCheckBox* alternatePathFlag; + QUndoStack *undoStack; + void updateList(); void updateInfo(); diff --git a/leveleditor/settingsdialog.cpp b/leveleditor/settingsdialog.cpp new file mode 100644 index 00000000..90d41399 --- /dev/null +++ b/leveleditor/settingsdialog.cpp @@ -0,0 +1,108 @@ +#include "settingsdialog.h" +#include "ui_settingsdialog.h" +#include "settingsmanager.h" + +#include + +SettingsDialog::SettingsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SettingsDialog) { + ui->setupUi(this); + loadSettings(); + + connect(ui->backgroundColorPickerButton, &QPushButton::clicked, this, &SettingsDialog::changeBackgroundColor); + connect(ui->undoLimitSpinBox, &QSpinBox::valueChanged, this, &SettingsDialog::changeUndoLimit); + connect(ui->selectOnPlacedCheckBox, &QCheckBox::clicked, this, &SettingsDialog::changeSelectOnPlaced); + connect(ui->showStatusBarCheckBox, &QCheckBox::clicked, this, &SettingsDialog::changeShowStatusbar); + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &SettingsDialog::handleButtonClicked); +} + +SettingsDialog::~SettingsDialog() { + delete ui; +} + +void SettingsDialog::loadSettings() { + backgroundColor = SettingsManager::getInstance()->getLEWindowColor(); + updateColorPickerButton(backgroundColor); + + undoLimit = SettingsManager::getInstance()->getLEUndoLimit(); + ui->undoLimitSpinBox->setValue(static_cast(undoLimit)); + + selectOnPlaced = SettingsManager::getInstance()->getLESelectOnPlace(); + ui->selectOnPlacedCheckBox->setChecked(selectOnPlaced); + + showStatusbar = SettingsManager::getInstance()->getLEShowStatusbar(); + ui->showStatusBarCheckBox->setChecked(showStatusbar); +} + +void SettingsDialog::restoreDefaults() { + backgroundColor = SettingsManager::LE_WINDOW_COLOR_DEFAULT; + updateColorPickerButton(backgroundColor); + + undoLimit = SettingsManager::LE_UNDO_LIMIT_DEFAULT; + ui->undoLimitSpinBox->setValue(static_cast(undoLimit)); + + selectOnPlaced = SettingsManager::LE_SELECT_ON_PLACE_DEFAULT; + ui->selectOnPlacedCheckBox->setChecked(selectOnPlaced); + + showStatusbar = SettingsManager::LE_SHOW_STATUSBAR_DEFAULT; + ui->showStatusBarCheckBox->setChecked(showStatusbar); +} + +void SettingsDialog::applyChanges() { + SettingsManager::getInstance()->setLEWindowColor(backgroundColor); + SettingsManager::getInstance()->setLEUndoLimit(undoLimit); + SettingsManager::getInstance()->setLESelectOnPlace(selectOnPlaced); + SettingsManager::getInstance()->setLEShowStatusbar(showStatusbar); + + emit changesApplied(); +} + +void SettingsDialog::handleButtonClicked(QAbstractButton *button) { + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) { + restoreDefaults(); + } + + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { + applyChanges(); + } + + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { + applyChanges(); + accept(); + } +} + +void SettingsDialog::changeBackgroundColor() { + + QColorDialog::ColorDialogOptions options = QColorDialog::DontUseNativeDialog; + +#ifdef USE_KDE_BLUR + options |= QColorDialog::ShowAlphaChannel; +#endif + + QColor newColor = QColorDialog::getColor(backgroundColor, this, tr("Select Background Color"), options); + if(newColor.isValid()) { + backgroundColor = newColor; + updateColorPickerButton(newColor); + } +} + +void SettingsDialog::changeUndoLimit() { + undoLimit = ui->undoLimitSpinBox->value(); +} + +void SettingsDialog::changeSelectOnPlaced() { + selectOnPlaced = ui->selectOnPlacedCheckBox->isChecked(); +} + +void SettingsDialog::changeShowStatusbar() { + showStatusbar = ui->showStatusBarCheckBox->isChecked(); +} + +void SettingsDialog::updateColorPickerButton(QColor color) { + const QString buttonStyle("QPushButton { border: none; background-color : %1;}"); + ui->backgroundColorPickerButton->setStyleSheet(buttonStyle.arg(color.name())); + ui->backgroundColorPickerButton->setAutoFillBackground(true); + ui->backgroundColorPickerButton->setFlat(true); +} diff --git a/leveleditor/settingsdialog.h b/leveleditor/settingsdialog.h new file mode 100644 index 00000000..6d87ce1e --- /dev/null +++ b/leveleditor/settingsdialog.h @@ -0,0 +1,43 @@ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include +#include + +namespace Ui { +class SettingsDialog; +} + +class SettingsDialog : public QDialog { + Q_OBJECT + +public: + explicit SettingsDialog(QWidget *parent = nullptr); + ~SettingsDialog() override; + +signals: + void changesApplied(); + +private slots: + void changeBackgroundColor(); + void changeUndoLimit(); + void changeSelectOnPlaced(); + void changeShowStatusbar(); + void handleButtonClicked(QAbstractButton *button); + +private: + Ui::SettingsDialog *ui; + + void loadSettings(); + void restoreDefaults(); + void applyChanges(); + + void updateColorPickerButton(QColor color); + + QColor backgroundColor; + quint32 undoLimit; + bool selectOnPlaced; + bool showStatusbar; +}; + +#endif // SETTINGSDIALOG_H diff --git a/leveleditor/settingsdialog.ui b/leveleditor/settingsdialog.ui new file mode 100644 index 00000000..c2a89c2f --- /dev/null +++ b/leveleditor/settingsdialog.ui @@ -0,0 +1,189 @@ + + + SettingsDialog + + + + 0 + 0 + 423 + 317 + + + + CoinKiller - Level Editor Settings + + + + + + + 0 + 0 + + + + Preferences + + + + + + + + + + + 0 + 0 + + + + Undo Steps: + + + + + + + 2000 + + + + + + + + + Qt::Horizontal + + + + + + + + + Background Color: + + + + + + + false + + + border: none; +background-color: rgb(119, 136, 153); + + + + + + + false + + + true + + + + + + + + + Qt::Horizontal + + + + + + + Show Statusbar + + + + + + + Select objects after placement + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + false + + + + + + + + + buttonBox + accepted() + SettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/spriteeditorwidget.cpp b/leveleditor/spriteeditorwidget.cpp similarity index 75% rename from spriteeditorwidget.cpp rename to leveleditor/spriteeditorwidget.cpp index dec9bb3d..55d8e7e5 100644 --- a/spriteeditorwidget.cpp +++ b/leveleditor/spriteeditorwidget.cpp @@ -1,5 +1,4 @@ #include "spriteeditorwidget.h" -#include "unitsconvert.h" #include "settingsmanager.h" #include @@ -8,7 +7,10 @@ #include #include -SpriteEditorWidget::SpriteEditorWidget(QList *sprites) +#include "commands/spritecommands.h" + +SpriteEditorWidget::SpriteEditorWidget(QList *sprites, QUndoStack *undoStack, QWidget *parent) : + QSplitter(parent) { QWidget* addSpriteView = new QWidget; QTabWidget* tabs = new QTabWidget; @@ -16,12 +18,12 @@ SpriteEditorWidget::SpriteEditorWidget(QList *sprites) QLabel* viewLabel = new QLabel(tr("View:")); viewLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); viewComboBox = new QComboBox(); - connect(viewComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setView(int))); + connect(viewComboBox, &QComboBox::currentIndexChanged, this, &SpriteEditorWidget::setView); QLabel* searchLabel = new QLabel(tr("Search:")); searchLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); searchEdit = new QLineEdit(); - connect(searchEdit, SIGNAL(textEdited(QString)), this, SLOT(search(QString))); + connect(searchEdit, &QLineEdit::textEdited, this, &SpriteEditorWidget::search); spriteTree = new QTreeWidget(); spriteTree->setColumnCount(1); @@ -42,12 +44,12 @@ SpriteEditorWidget::SpriteEditorWidget(QList *sprites) tabs->addTab(addSpriteView, tr("Add")); QStringList viewNames = getViewNames(); - viewComboBox->setModel(new QStringListModel(viewNames)); + viewComboBox->setModel(new QStringListModel(viewNames, this)); spriteIds = new SpriteIdWidget(sprites); tabs->addTab(spriteIds, tr("In Level")); - editor = new SpriteDataEditorWidget(&spriteData); + editor = new SpriteDataEditorWidget(&spriteData, undoStack); this->addWidget(tabs); this->addWidget(editor); @@ -56,11 +58,9 @@ SpriteEditorWidget::SpriteEditorWidget(QList *sprites) this->setCollapsible(1, false); this->restoreState(SettingsManager::getInstance()->get("SpriteEditorSplitter").toByteArray()); - connect(spriteTree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(handleIndexChange(QTreeWidgetItem*))); - connect(editor, SIGNAL(editMade()), this, SLOT(handleEditDetected())); - connect(spriteIds, SIGNAL(selectedSpriteChanged(Object*)), this, SLOT(handleSelectedSpriteChanged(Object*))); - connect(spriteIds, SIGNAL(updateLevelView()), this, SLOT(handleUpdateLevelView())); - connect(this, SIGNAL(splitterMoved(int,int)), this, SLOT(handleSplitterMoved())); + connect(spriteTree, &QTreeWidget::currentItemChanged, this, &SpriteEditorWidget::handleIndexChange); + connect(spriteIds, &SpriteIdWidget::selectedSpriteChanged, this, &SpriteEditorWidget::handleSelectedSpriteChanged); + connect(this, &SpriteEditorWidget::splitterMoved, this, &SpriteEditorWidget::handleSplitterMoved); } void SpriteEditorWidget::handleSplitterMoved() @@ -125,7 +125,7 @@ void SpriteEditorWidget::changeEvent(QEvent* event) viewComboBox->setCurrentIndex(currentView); } - QWidget::changeEvent(event); + QSplitter::changeEvent(event); } void SpriteEditorWidget::setView(int view) @@ -168,19 +168,13 @@ void SpriteEditorWidget::handleIndexChange(QTreeWidgetItem *item) { int data = item->data(0, Qt::UserRole).toInt(); - emit(currentSpriteChanged(data)); + emit currentSpriteChanged(data); editor->updateEditor(); - emit editMade(); } void SpriteEditorWidget::select(Sprite *sprite) { - emit(currentSpriteChanged(sprite->getid())); -} - -void SpriteEditorWidget::handleEditDetected() -{ - emit editMade(); + emit currentSpriteChanged(sprite->getid()); } void SpriteEditorWidget::handleSelectedSpriteChanged(Object* obj) @@ -193,15 +187,10 @@ void SpriteEditorWidget::handleSelectedSpriteChanged(Object* obj) } } -void SpriteEditorWidget::handleUpdateLevelView() -{ - emit updateLevelView(); -} -SpriteDataEditorWidget::SpriteDataEditorWidget(SpriteData *spriteData) +SpriteDataEditorWidget::SpriteDataEditorWidget(SpriteData *spriteData, QUndoStack *undoStack, QWidget *parent) : + QScrollArea(parent), spriteData(spriteData), undoStack(undoStack) { - this->spriteData = spriteData; - layout = new QGridLayout(); this->setWidgetResizable(true); @@ -221,13 +210,13 @@ SpriteDataEditorWidget::SpriteDataEditorWidget(SpriteData *spriteData) spriteNotesButton->setMaximumHeight(20); spriteNotesButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); layout->addWidget(spriteNotesButton, 0, 1, 1, 1, Qt::AlignRight); - connect(spriteNotesButton, SIGNAL (pressed()),this, SLOT (handleShowNotes())); + connect(spriteNotesButton, &QAbstractButton::pressed, this, &SpriteDataEditorWidget::handleShowNotes); rawSpriteData = new QLineEdit(); rawSpriteData->setInputMask("HHHH HHHH HHHH HHHH HHHH HHHH"); layout->addWidget(new QLabel(tr("Raw Sprite Data:")), 1, 0, 1, 1, Qt::AlignRight); layout->addWidget(rawSpriteData, 1, 1); - connect(rawSpriteData, SIGNAL(textEdited(QString)), this, SLOT(handleRawSpriteDataChange(QString))); + connect(rawSpriteData, &QLineEdit::textEdited, this, &SpriteDataEditorWidget::handleRawSpriteDataChange); splitterLine = new HorLine(); @@ -236,7 +225,7 @@ SpriteDataEditorWidget::SpriteDataEditorWidget(SpriteData *spriteData) QStringList layerNames; layerNames << tr("Layer 1") << tr("Layer 2"); layerComboBox->addItems(layerNames); - connect(layerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(handleLayerChanged(int))); + connect(layerComboBox, &QComboBox::currentIndexChanged, this, &SpriteDataEditorWidget::handleLayerChanged); setHidden(true); } @@ -273,44 +262,42 @@ void SpriteDataEditorWidget::select(Sprite *sprite) if (field->type == Field::List) { - SpriteListFieldWidget* fieldWidget = new SpriteListFieldWidget(sprite, field); + SpriteListFieldWidget* fieldWidget = new SpriteListFieldWidget(sprite, field, undoStack); layout->addWidget(fieldWidget, i+2, 1); listFieldWidgets.append(fieldWidget); - connect(fieldWidget, SIGNAL(updateHex()), this, SLOT(updateRawSpriteData())); - connect(fieldWidget, SIGNAL(updateFields()), this, SLOT(updateFields())); - connect(fieldWidget, SIGNAL (editMade()), this, SLOT(handleEditDetected())); + connect(fieldWidget, &SpriteListFieldWidget::updateHex, this, &SpriteDataEditorWidget::updateRawSpriteData); + connect(fieldWidget, &SpriteListFieldWidget::updateFields, this, &SpriteDataEditorWidget::updateFields); } else if (field->type == Field::Checkbox) { - SpriteCheckboxFieldWidget* fieldWidget = new SpriteCheckboxFieldWidget(sprite, field); + SpriteCheckboxFieldWidget* fieldWidget = new SpriteCheckboxFieldWidget(sprite, field, undoStack); layout->addWidget(fieldWidget, i+2, 1); checkboxFieldWidgets.append(fieldWidget); - connect(fieldWidget, SIGNAL(updateHex()), this, SLOT(updateRawSpriteData())); - connect(fieldWidget, SIGNAL(updateFields()), this, SLOT(updateFields())); - connect(fieldWidget, SIGNAL (editMade()), this, SLOT(handleEditDetected())); + connect(fieldWidget, &SpriteCheckboxFieldWidget::updateHex, this, &SpriteDataEditorWidget::updateRawSpriteData); + connect(fieldWidget, &SpriteCheckboxFieldWidget::updateFields, this, &SpriteDataEditorWidget::updateFields); } else if (field->type == Field::Value) { - SpriteValueFieldWidget* fieldWidget = new SpriteValueFieldWidget(sprite, field); + SpriteValueFieldWidget* fieldWidget = new SpriteValueFieldWidget(sprite, field, undoStack); layout->addWidget(fieldWidget, i+2, 1); valueFieldWidgets.append(fieldWidget); - connect(fieldWidget, SIGNAL(updateHex()), this, SLOT(updateRawSpriteData())); - connect(fieldWidget, SIGNAL(updateFields()), this, SLOT(updateFields())); - connect(fieldWidget, SIGNAL (editMade()), this, SLOT(handleEditDetected())); + connect(fieldWidget, &SpriteValueFieldWidget::updateHex, this, &SpriteDataEditorWidget::updateRawSpriteData); + connect(fieldWidget, &SpriteValueFieldWidget::updateFields, this, &SpriteDataEditorWidget::updateFields); } else if (field->type == Field::Bitfield) { - SpriteBitFieldWidget* fieldWidget = new SpriteBitFieldWidget(sprite, field); + SpriteBitFieldWidget* fieldWidget = new SpriteBitFieldWidget(sprite, field, undoStack); layout->addWidget(fieldWidget, i+2, 1); bitFieldWidgets.append(fieldWidget); - connect(fieldWidget, SIGNAL(updateHex()), this, SLOT(updateRawSpriteData())); - connect(fieldWidget, SIGNAL(updateFields()), this, SLOT(updateFields())); - connect(fieldWidget, SIGNAL (editMade()), this, SLOT(handleEditDetected())); + connect(fieldWidget, &SpriteBitFieldWidget::updateHex, this, &SpriteDataEditorWidget::updateRawSpriteData); + connect(fieldWidget, &SpriteBitFieldWidget::updateFields, this, &SpriteDataEditorWidget::updateFields); } } // TODO: Only show layer combo box for sprites that use the layer setting + layerComboBox->blockSignals(true); layerComboBox->setCurrentIndex(editSprite->getLayer()); + layerComboBox->blockSignals(false); int fieldCount = def.getFieldCount(); layout->addWidget(splitterLine, fieldCount+2, 0, 1, 2); @@ -347,33 +334,26 @@ void SpriteDataEditorWidget::updateRawSpriteData() QString rawSpriteDataStr; for (int i = 0; i < 12; i++) rawSpriteDataStr.append(QString("%1").arg(editSprite->getByte(i), 2, 16, QChar('0'))); rawSpriteData->setText(rawSpriteDataStr); - emit updateLevelView(); } void SpriteDataEditorWidget::handleRawSpriteDataChange(QString text) { QString bytes = text.remove(" "); - for (int i = 0; i < 12; i++) - editSprite->setByte(i, (quint8)bytes.mid(i*2, 2).toUInt(0, 16)); - - editSprite->setRect(); + undoStack->beginMacro("Edit Raw Spritedata"); + for (int i = 0; i < 12; i++) { + undoStack->push(new Commands::SpriteCmd::SetByte(editSprite, i, (quint8)bytes.mid(i*2, 2).toUInt(nullptr, 16))); + } + undoStack->endMacro(); updateFields(); - - emit updateLevelView(); - emit editMade(); -} - -void SpriteDataEditorWidget::handleEditDetected() -{ - emit editMade(); } void SpriteDataEditorWidget::handleShowNotes() { QString name = spriteName->text(); - name.remove(QRegularExpression("<[^>]*>")); + QRegularExpression re("<[^>]*>"); + name.remove(re); QMessageBox notes; notes.setWindowTitle(name); @@ -395,7 +375,7 @@ void SpriteDataEditorWidget::handleShowNotes() void SpriteDataEditorWidget::handleLayerChanged(int layer) { - editSprite->setLayer(layer); + undoStack->push(new Commands::SpriteCmd::SetLayer(editSprite, layer)); } void SpriteDataEditorWidget::updateEditor() @@ -418,25 +398,26 @@ void SpriteDataEditorWidget::reloadFields() layout->removeWidget(splitterLine); layout->removeWidget(layerComboBox); layout->removeWidget(layerLabel); - select(editSprite); } // Field Widgets -SpriteValueFieldWidget::SpriteValueFieldWidget(Sprite *sprite, Field *field) -{ - this->sprite = sprite; - this->field = field; +SpriteValueFieldWidget::SpriteValueFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent) : + QSpinBox(parent), + sprite(sprite), + field(field), + undoStack(undoStack) { this->setToolTip(field->comment); - if (field->posType == Field::Bits) + if (field->posType == Field::Bits) { setRange(0, (1 << (field->endPos - field->startPos + 1)) - 1); - else + } else { setRange(0, (1 << ((field->endPos - field->startPos + 1) * 4)) - 1); + } updateValue(); - connect(this, SIGNAL(valueChanged(int)), this, SLOT(handleValueChange(int))); + connect(this, &QSpinBox::valueChanged, this, &SpriteValueFieldWidget::handleValueChange); } void SpriteValueFieldWidget::updateValue() @@ -455,27 +436,25 @@ void SpriteValueFieldWidget::handleValueChange(int value) { if (!handleValueChanges) return; - if (field->posType == Field::Bits) - sprite->setBits(value, field->startPos, field->endPos); - else - sprite->setNybbleData(value, field->startPos, field->endPos); + if (field->posType == Field::Bits) { + undoStack->push(new Commands::SpriteCmd::SetBits(sprite, value, field->startPos, field->endPos)); + } else { + undoStack->push(new Commands::SpriteCmd::SetNybbleData(sprite, value, field->startPos, field->endPos)); + } - sprite->setRect(); emit updateHex(); emit updateFields(); - emit editMade(); } -SpriteCheckboxFieldWidget::SpriteCheckboxFieldWidget(Sprite *sprite, Field *field) +SpriteCheckboxFieldWidget::SpriteCheckboxFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent) : + QCheckBox(parent), sprite(sprite), field(field), undoStack(undoStack) { - this->sprite = sprite; - this->field = field; this->setToolTip(field->comment); setText(field->title); updateValue(); - connect(this, SIGNAL(toggled(bool)), this, SLOT(handleValueChange(bool))); + connect(this, &QAbstractButton::toggled, this, &SpriteCheckboxFieldWidget::handleValueChange); } void SpriteCheckboxFieldWidget::updateValue() @@ -492,30 +471,31 @@ void SpriteCheckboxFieldWidget::updateValue() void SpriteCheckboxFieldWidget::handleValueChange(bool checked) { - if (!handleValueChanges) return; - - if (field->posType == Field::Bits) - { - sprite->setBits(checked, field->startPos, field->endPos); + if (!handleValueChanges) { + return; } - else - { + + if (field->posType == Field::Bits) { + undoStack->push(new Commands::SpriteCmd::SetBits(sprite, checked, field->startPos, field->endPos)); + } else { quint8 newData = sprite->getNybbleData(field->startPos, field->endPos) & (~field->mask); - if (checked) newData |= field->mask; - sprite->setNybbleData((int)newData, field->startPos, field->endPos); + if (checked) { + newData |= field->mask; + } + undoStack->push(new Commands::SpriteCmd::SetNybbleData(sprite, newData, field->startPos, field->endPos)); } - sprite->setRect(); emit updateHex(); emit updateFields(); - emit editMade(); } -SpriteListFieldWidget::SpriteListFieldWidget(Sprite *sprite, Field *field) -{ - this->sprite = sprite; - this->field = field; +SpriteListFieldWidget::SpriteListFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent) : + QComboBox(parent), + sprite(sprite), + field(field), + undoStack(undoStack) { + this->setToolTip(field->comment); for (int i = 0; i < field->listEntries.count(); i++) @@ -525,7 +505,7 @@ SpriteListFieldWidget::SpriteListFieldWidget(Sprite *sprite, Field *field) } updateValue(); - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(handleIndexChange(int))); + connect(this, &QComboBox::currentIndexChanged, this, &SpriteListFieldWidget::handleIndexChange); } void SpriteListFieldWidget::updateValue() @@ -556,24 +536,27 @@ void SpriteListFieldWidget::updateValue() void SpriteListFieldWidget::handleIndexChange(int index) { - if (!handleValueChanges) return; + if (!handleValueChanges) { + return; + } - if (field->posType == Field::Bits) - sprite->setBits(itemData(index).toInt(), field->startPos, field->endPos); - else - sprite->setNybbleData(itemData(index).toInt(), field->startPos, field->endPos); + if (field->posType == Field::Bits) { + undoStack->push(new Commands::SpriteCmd::SetBits(sprite, itemData(index).toInt(), field->startPos, field->endPos)); + } else { + undoStack->push(new Commands::SpriteCmd::SetNybbleData(sprite, itemData(index).toInt(), field->startPos, field->endPos)); + } - sprite->setRect(); emit updateHex(); emit updateFields(); - emit editMade(); } -SpriteBitFieldWidget::SpriteBitFieldWidget(Sprite *sprite, Field *field) -{ - this->sprite = sprite; - this->field = field; +SpriteBitFieldWidget::SpriteBitFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent) : + QFrame(parent), + sprite(sprite), + field(field), + undoStack(undoStack) { + this->setToolTip(field->comment); this->setFrameShape(QFrame::StyledPanel); @@ -597,7 +580,7 @@ SpriteBitFieldWidget::SpriteBitFieldWidget(Sprite *sprite, Field *field) QCheckBox* checkbox = new QCheckBox(); layout->addWidget(checkbox, length - i/4, 4 - j); checkboxWidgets.append(checkbox); - connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(handleValueChange())); + connect(checkbox, &QAbstractButton::toggled, this, &SpriteBitFieldWidget::handleValueChange); i++; } } @@ -629,27 +612,27 @@ void SpriteBitFieldWidget::updateValue() void SpriteBitFieldWidget::handleValueChange() { - if (!handleValueChanges) return; + if (!handleValueChanges) { + return; + } QCheckBox* checkbox = qobject_cast(sender()); int bit = checkboxWidgets.indexOf(checkbox); - if (field->posType == Field::Bits) - { + if (bit < 0) { + return; + } + + if (field->posType == Field::Bits) { int value = sprite->getBits(field->startPos, field->endPos); value ^= 1 << bit; - sprite->setBits(value, field->startPos, field->endPos); - - } - else - { + undoStack->push(new Commands::SpriteCmd::SetBits(sprite, value, field->startPos, field->endPos)); + } else { int value = sprite->getNybbleData(field->startPos, field->endPos); value ^= 1 << bit; - sprite->setNybbleData(value, field->startPos, field->endPos); + undoStack->push(new Commands::SpriteCmd::SetNybbleData(sprite, value, field->startPos, field->endPos)); } - sprite->setRect(); emit updateHex(); emit updateFields(); - emit editMade(); } diff --git a/spriteeditorwidget.h b/leveleditor/spriteeditorwidget.h similarity index 76% rename from spriteeditorwidget.h rename to leveleditor/spriteeditorwidget.h index b56072bf..73d41bcb 100644 --- a/spriteeditorwidget.h +++ b/leveleditor/spriteeditorwidget.h @@ -2,7 +2,7 @@ #define SPRITESEDITOR_H #include "spritedata.h" -#include "level.h" +#include "objects.h" #include "spriteidswidget.h" #include @@ -17,23 +17,26 @@ #include #include #include +#include class SpriteValueFieldWidget : public QSpinBox { Q_OBJECT public: - SpriteValueFieldWidget(Sprite* sprite, Field* field); + SpriteValueFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent = nullptr); void updateValue(); + private slots: void handleValueChange(int value); + signals: void updateHex(); void updateFields(); - void editMade(); private: Sprite* sprite; Field* field; + QUndoStack *undoStack; bool handleValueChanges; }; @@ -41,18 +44,18 @@ class SpriteCheckboxFieldWidget : public QCheckBox { Q_OBJECT public: - SpriteCheckboxFieldWidget(Sprite* sprite, Field* field); + SpriteCheckboxFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent = nullptr); void updateValue(); private slots: void handleValueChange(bool checked); signals: void updateHex(); void updateFields(); - void editMade(); private: - Sprite* sprite; - Field* field; + Sprite *sprite; + Field *field; + QUndoStack *undoStack; bool handleValueChanges; }; @@ -60,18 +63,18 @@ class SpriteListFieldWidget : public QComboBox { Q_OBJECT public: - SpriteListFieldWidget(Sprite* sprite, Field* field); + SpriteListFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent = nullptr); void updateValue(); private slots: void handleIndexChange(int index); signals: void updateHex(); void updateFields(); - void editMade(); private: - Sprite* sprite; - Field* field; + Sprite *sprite; + Field *field; + QUndoStack *undoStack; bool handleValueChanges; }; @@ -79,31 +82,29 @@ class SpriteBitFieldWidget : public QFrame { Q_OBJECT public: - SpriteBitFieldWidget(Sprite* sprite, Field* field); + SpriteBitFieldWidget(Sprite *sprite, Field *field, QUndoStack *undoStack, QWidget *parent = nullptr); void updateValue(); private slots: void handleValueChange(); signals: void updateHex(); void updateFields(); - void editMade(); private: - QGridLayout* layout; - - Sprite* sprite; - Field* field; - bool handleValueChanges; - + QGridLayout *layout; QList checkboxWidgets; + Sprite *sprite; + Field *field; + QUndoStack *undoStack; + bool handleValueChanges; }; class SpriteDataEditorWidget : public QScrollArea { Q_OBJECT public: - SpriteDataEditorWidget(SpriteData* spriteData); + SpriteDataEditorWidget(SpriteData* spriteData, QUndoStack *undoStack, QWidget *parent = nullptr); void select(Sprite* sprite); void deselect(); void updateEditor(); @@ -112,14 +113,9 @@ private slots: void handleRawSpriteDataChange(QString text); void updateRawSpriteData(); void updateFields(); - void handleEditDetected(); void handleShowNotes(); void handleLayerChanged(int); -signals: - void updateLevelView(); - void editMade(); - private: QGridLayout* layout; QLineEdit* rawSpriteData; @@ -146,13 +142,15 @@ private slots: void addField(Field* field, int pos); void reloadFields(); + + QUndoStack *undoStack; }; class SpriteEditorWidget : public QSplitter { Q_OBJECT public: - SpriteEditorWidget(QList *sprites); + SpriteEditorWidget(QList *sprites, QUndoStack *undoStack, QWidget *parent = nullptr); void select(Sprite* sprite); SpriteDataEditorWidget* spriteDataEditorPtr() { return editor; } SpriteIdWidget* spriteIdsPtr() { return spriteIds; } @@ -160,18 +158,14 @@ class SpriteEditorWidget : public QSplitter signals: void currentSpriteChanged(int); void selectedSpriteChanged(Object*); - void editMade(); - void updateLevelView(); public slots: void setView(int view); void search(QString text); void handleSelectedSpriteChanged(Object* obj); - void handleUpdateLevelView(); private slots: void handleIndexChange(QTreeWidgetItem *item); - void handleEditDetected(); void handleSplitterMoved(); private: @@ -183,7 +177,7 @@ private slots: SpriteDataEditorWidget* editor; - void changeEvent(QEvent* event); + void changeEvent(QEvent* event) override; QStringList getViewNames(); }; diff --git a/spriteidswidget.cpp b/leveleditor/spriteidswidget.cpp similarity index 100% rename from spriteidswidget.cpp rename to leveleditor/spriteidswidget.cpp diff --git a/spriteidswidget.h b/leveleditor/spriteidswidget.h similarity index 100% rename from spriteidswidget.h rename to leveleditor/spriteidswidget.h diff --git a/leveleditor/tilesetpalette.cpp b/leveleditor/tilesetpalette.cpp new file mode 100644 index 00000000..3cf89c99 --- /dev/null +++ b/leveleditor/tilesetpalette.cpp @@ -0,0 +1,243 @@ +#include "tilesetpalette.h" + +#include +#include +#include +#include +#include +#include + +#include "commands/levelcommands.h" + +TilesetPalette::TilesetPalette(Level* level, EditManager* editManager, Game* game, QUndoStack *undoStack, QWidget *parent) : + QWidget(parent), + level(level), + editManager(editManager), + game(game), + undoStack(undoStack) { + + QVBoxLayout* layout = new QVBoxLayout(); + this->setLayout(layout); + + QHBoxLayout* topLayout = new QHBoxLayout(); + layout->addLayout(topLayout); + + QLabel* label = new QLabel(tr("Paint on:")); + label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + topLayout->addWidget(label); + + QRadioButton* layer1RadioBtn = new QRadioButton(tr("Layer 1")); + layer1RadioBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + layer1RadioBtn->setChecked(true); + topLayout->addWidget(layer1RadioBtn); + + QRadioButton* layer2RadioBtn = new QRadioButton(tr("Layer 2")); + layer2RadioBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + topLayout->addWidget(layer2RadioBtn); + + topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred)); + + tabWidget = new QTabWidget(); + layout->addWidget(tabWidget); + + // Setup Tileset Selector + for (int tsSlot = 0; tsSlot < 4; tsSlot++) { + QComboBox* tsPicker = new QComboBox(); + tilesetPickers.insert(tsSlot, tsPicker); + QStandardItemModel* model = game->getTilesetModel(tsSlot, true); + model->setParent(this); + + model->sort(0, Qt::AscendingOrder); + + for (int pickerIndex = 0; pickerIndex < model->rowCount(); pickerIndex++) { + // Tileset Name + QModelIndex tsNameIndex = model->index(pickerIndex, 0); + QString tilesetName = tsNameIndex.data().toString(); + + tsPicker->addItem(tilesetName); + + // File Name + QModelIndex fileNameIndex = model->index(pickerIndex, 1); + QString fileName = fileNameIndex.data().toString(); + + tsPicker->setItemData(pickerIndex, fileName, Qt::UserRole); + + if (level->tilesets[tsSlot]) { + QString selectedTs = level->tilesets[tsSlot]->getName(); + + if (selectedTs == fileName) { + tsPicker->setCurrentIndex(pickerIndex); + } + } + } + + connect(tsPicker, &QComboBox::currentIndexChanged, this, &TilesetPalette::tilesetPickerChosen); + + QWidget* tabPage = new QWidget; + QGridLayout* tabLayout = new QGridLayout; + + QLabel* tilesetLabel = new QLabel(tr("Tileset:")); + tilesetLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + tabLayout->addWidget(tilesetLabel, 0, 0, 1, 1); + tabLayout->addWidget(tsPicker, 0, 1); + + tabPage->setLayout(tabLayout); + + objectLists.insert(tsSlot, new QListView()); + tabLayout->addWidget(objectLists[tsSlot], 1, 0, 1, 2); + + QString title; + if (tsSlot == 0) title = tr("Standard"); + else if (tsSlot == 1) title = tr("Stage"); + else if (tsSlot == 2) title = tr("Background"); + else if (tsSlot == 3) title = tr("Interactive"); + + tabWidget->addTab(tabPage, title); + + objectLists[tsSlot]->setFlow(QListView::LeftToRight); + objectLists[tsSlot]->setLayoutMode(QListView::SinglePass); + objectLists[tsSlot]->setMovement(QListView::Static); + objectLists[tsSlot]->setResizeMode(QListView::Adjust); + objectLists[tsSlot]->setWrapping(true); + objectLists[tsSlot]->setIconSize(QSize(400, 400)); + objectLists[tsSlot]->setVerticalScrollMode(QListView::ScrollPerPixel); + objectLists[tsSlot]->setEditTriggers(QAbstractItemView::NoEditTriggers); + loadTileset(tsSlot); + + connect(objectLists[tsSlot], &QListView::clicked, this, &TilesetPalette::objectsListViewClicked); + connect(objectLists[tsSlot], &QListView::entered, this, &TilesetPalette::objectsListViewClicked); + } + + connect(layer1RadioBtn, &QRadioButton::toggled, this, &TilesetPalette::layerToggled); + +} + +void TilesetPalette::updateEditor() +{ + reloadTilesets(); + updateTilesetPickerIndex(); +} + +void TilesetPalette::updateTilesetPickerIndex() +{ + for (int tsSlot = 0; tsSlot < 4; tsSlot++) { + + QComboBox *tsPicker = tilesetPickers[tsSlot]; + tsPicker->blockSignals(true); + + if (!level->tilesets[tsSlot]) { + tsPicker->setCurrentIndex(0); + tsPicker->blockSignals(false); + continue; + } + + QString selectedTs = level->tilesets[tsSlot]->getName(); + + for (int pickerIndex = 0; pickerIndex < tsPicker->model()->rowCount(); pickerIndex++) { + QString fileName = tsPicker->itemData(pickerIndex).toString(); + + if (selectedTs == fileName) { + tsPicker->setCurrentIndex(pickerIndex); + break; + } + } + tsPicker->blockSignals(false); + } +} + +void TilesetPalette::reloadTilesets() +{ + for (int i = 0; i < 4; i++) loadTileset(i); +} + +void TilesetPalette::loadTileset(int tilesetNbr) +{ + if (!level->tilesets[tilesetNbr]) + { + objectLists[tilesetNbr]->setEnabled(false); + objectLists[tilesetNbr]->setModel(new QStandardItemModel(this)); + return; + } + objectLists[tilesetNbr]->setEnabled(true); + + QStandardItemModel* objectsModel = new QStandardItemModel(this); + + for (int i = 0; i < level->tilesets[tilesetNbr]->getNumObjects(); i++) + { + ObjectDef* obj = level->tilesets[tilesetNbr]->getObjectDef(i); + QPixmap objPixmap(obj->width*20, obj->height*20); + objPixmap.fill(Qt::transparent); + + QPainter p(&objPixmap); + TileGrid tileGrid; + tileGrid.clear(); + tileGrid[0xFFFFFFFF] = 1; + level->tilesets[tilesetNbr]->Render2DTiles(true); + level->tilesets[tilesetNbr]->Render3DOverlay(true); + level->tilesets[tilesetNbr]->drawObject(p, tileGrid, i, 0, 0, obj->width, obj->height, 1); + p.end(); + QStandardItem *objItem = new QStandardItem(); + objItem->setIcon(QIcon(objPixmap)); + objItem->setToolTip(tr("Object: %1").arg(i)); + objectsModel->appendRow(objItem); + } + + objectLists[tilesetNbr]->setModel(objectsModel); +} + +void TilesetPalette::objectsListViewClicked(const QModelIndex &index) +{ + QListView *listView = qobject_cast(QObject::sender()); + int tilsetId = objectLists.indexOf(listView); + + updatePalettes(tilsetId); + editManager->setDrawType(ObjectType::BGDATOBJECT); + editManager->setObject(index.row(), tilsetId); +} + +void TilesetPalette::updatePalettes(int actualPal) +{ + for (int i = 0; i < 4; i++) + { + if (i == actualPal) continue; + objectLists[i]->clearSelection(); + } +} + +void TilesetPalette::layerToggled(bool checked) +{ + editManager->setLayer(!checked); +} + +void TilesetPalette::select(BgdatObject *obj) +{ + int tsid = obj->getTsID(); + tabWidget->setCurrentIndex(tsid); + objectLists[tsid]->setCurrentIndex(objectLists[tsid]->model()->index(obj->getObjID(), 0)); + + updatePalettes(tsid); + editManager->setDrawType(ObjectType::BGDATOBJECT); + editManager->setObject(obj->getObjID(), obj->getTsID()); +} + +void TilesetPalette::tilesetPickerChosen(int index) +{ + QComboBox* tsNameCombobox = qobject_cast(sender()); + + QString tsName = tsNameCombobox->itemData(index).toString(); + int tsId = tabWidget->currentIndex(); + + Tileset *newTs; + + if (tsName == "") { + newTs = nullptr; + } else { + newTs = game->getTileset(tsName); + } + + undoStack->push(new Commands::LevelCmd::SetTileset(level, tsId, newTs)); + + + reloadTilesets(); +} diff --git a/leveleditor/tilesetpalette.h b/leveleditor/tilesetpalette.h new file mode 100644 index 00000000..46c38ce9 --- /dev/null +++ b/leveleditor/tilesetpalette.h @@ -0,0 +1,45 @@ +#ifndef TILESETPALETTE_H +#define TILESETPALETTE_H + +#include "level.h" +#include "game.h" +#include "editmanager.h" + +#include +#include +#include +#include +#include + +class TilesetPalette : public QWidget +{ + Q_OBJECT +public: + explicit TilesetPalette(Level* level, EditManager *editManager, Game *game, QUndoStack *undoStack, QWidget *parent = nullptr); + void select(BgdatObject* obj); + void updateEditor(); + +private slots: + void objectsListViewClicked(const QModelIndex &index); + void layerToggled(bool state); + void tilesetPickerChosen(int index); + +private: + Level *level; + EditManager *editManager; + Game *game; + QUndoStack *undoStack; + + QTabWidget *tabWidget; + QList tilesetPickers; + QList objectLists; + + void loadTileset(int tilesetNbr); + void updatePalettes(int actualPal); + void updateTilesetPickerIndex(); + + void reloadTilesets(); + +}; + +#endif // TILESETPALETTE_H diff --git a/zoneeditorwidget.cpp b/leveleditor/zoneeditorwidget.cpp similarity index 74% rename from zoneeditorwidget.cpp rename to leveleditor/zoneeditorwidget.cpp index 5d020f23..4a730b2a 100644 --- a/zoneeditorwidget.cpp +++ b/leveleditor/zoneeditorwidget.cpp @@ -1,5 +1,6 @@ #include "zoneeditorwidget.h" #include "unitsconvert.h" +#include "settingsmanager.h" #include #include @@ -10,26 +11,39 @@ #include #include -ZoneEditorWidget::ZoneEditorWidget(QList *zones, QList *bgs, QList *bounds) -{ - this->zones = zones; - this->zoneBoundings = bounds; - this->zoneBgs = bgs; - - multiplayerTrackings.insert(0, tr("Horizontal")); - multiplayerTrackings.insert(6, tr("Vertical")); - +#include "commands/zonecommands.h" +#include "commands/zonebgcommands.h" +#include "commands/zoneboundingcommands.h" +#include "commands/levelcommands.h" + +ZoneEditorWidget::ZoneEditorWidget(QList *zones, QList *bgs, QList *bounds, QUndoStack *undoStack, Level *level, QWidget *parent) : + QWidget(parent), + zones(zones), + zoneBoundings(bounds), + zoneBgs(bgs), + undoStack(undoStack), + level(level) { + + multiplayerTrackings.insert(0, tr("Right and Down")); + multiplayerTrackings.insert(1, tr("Right and Up")); + multiplayerTrackings.insert(2, tr("Left and Down")); + multiplayerTrackings.insert(3, tr("Left and Up")); + multiplayerTrackings.insert(4, tr("Down and Right")); + multiplayerTrackings.insert(5, tr("Down and Left")); + multiplayerTrackings.insert(6, tr("Up and Right")); + multiplayerTrackings.insert(7, tr("Up and Left")); + multiplayerTrackings.insert(8, tr("Right and Right")); loadMusicIDs(); zoneList = new QListWidget(); zoneList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(zoneList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleZoneListIndexChange(QListWidgetItem*))); + connect(zoneList, &QListWidget::itemClicked, this, &ZoneEditorWidget::handleZoneListIndexChange); selectContentsBtn = new QPushButton(tr("Select Contents"), this); - connect(selectContentsBtn, SIGNAL(clicked(bool)), this, SLOT(handleSelectContentsClicked())); + connect(selectContentsBtn, &QAbstractButton::clicked, this, &ZoneEditorWidget::handleSelectContentsClicked); screenshotBtn = new QPushButton(tr("Screenshot Zone"), this); - connect(screenshotBtn, SIGNAL(clicked(bool)), this, SLOT(handleScreenshotClicked())); + connect(screenshotBtn, &QAbstractButton::clicked, this, &ZoneEditorWidget::handleScreenshotClicked); settingsGroup = new QGroupBox(); QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); @@ -38,24 +52,27 @@ ZoneEditorWidget::ZoneEditorWidget(QList *zones, QList * id = new QSpinBox(); id->setRange(0, 255); - connect(id, SIGNAL(valueChanged(int)), this, SLOT(handleIDChange(int))); + connect(id, &QSpinBox::valueChanged, this, &ZoneEditorWidget::handleIDChange); multiplayerTracking = new QComboBox(); multiplayerTracking->addItems(multiplayerTrackings.values()); - connect(multiplayerTracking, SIGNAL(currentTextChanged(QString)), this, SLOT(handleMultiPlayerTrackingChange(QString))); + connect(multiplayerTracking, &QComboBox::currentTextChanged, this, &ZoneEditorWidget::handleMultiPlayerTrackingChange); progPathId = new QSpinBox(); progPathId->setRange(0, 255); - connect(progPathId, SIGNAL(valueChanged(int)), this, SLOT(handleProgPathIDChange(int))); + connect(progPathId, &QSpinBox::valueChanged, this, &ZoneEditorWidget::handleProgPathIDChange); musicId = new QComboBox(); - for (QPair i : musicIds.values()) musicId->addItem(i.second); + for (auto iter = musicIds.begin(), end = musicIds.end(); iter != end; iter++) { + musicId->addItem(iter->second); + } + musicId->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon); - connect(musicId, SIGNAL(currentTextChanged(QString)), this, SLOT(handleMusicIDChange(QString))); + connect(musicId, &QComboBox::currentTextChanged, this, &ZoneEditorWidget::handleMusicIDChange); unk1 = new QSpinBox(); unk1->setRange(0, 255); - connect(unk1, SIGNAL(valueChanged(int)), this, SLOT(handleUnk1Change(int))); + connect(unk1, &QSpinBox::valueChanged, this, &ZoneEditorWidget::handleUnk1Change); boundingId = new QSpinBox(); boundingId->setRange(0, 255); @@ -68,18 +85,16 @@ ZoneEditorWidget::ZoneEditorWidget(QList *zones, QList * backgroundId->setEnabled(false); editBounding = new QPushButton(tr("Open Bounding Editor"), this); - connect(editBounding, SIGNAL(clicked(bool)), this, SLOT(handleEditBoundingClicked())); + connect(editBounding, &QPushButton::clicked, this, &ZoneEditorWidget::handleEditBoundingClicked); editBackground = new QPushButton(tr("Open Background Editor"), this); - connect(editBackground, SIGNAL(clicked(bool)), this, SLOT(handleEditBackgroundClicked())); + connect(editBackground, &QAbstractButton::clicked, this, &ZoneEditorWidget::handleEditBackgroundClicked); - boundingWidget = new ZoneBoundingWidget(bounds); - connect(boundingWidget, SIGNAL(editMade()), this, SLOT(handleEditMade())); - connect(boundingWidget, SIGNAL(selectedBoundingChanged(int)), this, SLOT(handleBoundingIDChange(int))); + boundingWidget = new ZoneBoundingWidget(bounds, undoStack, level); + connect(boundingWidget, &ZoneBoundingWidget::selectedBoundingChanged, this, &ZoneEditorWidget::handleBoundingIDChange); - backgroundWidget = new ZoneBackgroundWidget(bgs); - connect(backgroundWidget, SIGNAL(editMade()), this, SLOT(handleEditMade())); - connect(backgroundWidget, SIGNAL(selectedBackgroundChanged(int)), this, SLOT(handleBackgroundIDChange(int))); + backgroundWidget = new ZoneBackgroundWidget(bgs, undoStack, level); + connect(backgroundWidget, &ZoneBackgroundWidget::selectedBackgroundChanged, this, &ZoneEditorWidget::handleBackgroundIDChange); QVBoxLayout* layout = new QVBoxLayout(); setLayout(layout); @@ -141,7 +156,9 @@ void ZoneEditorWidget::changeEvent(QEvent* event) if (event->type() == QEvent::LanguageChange) { loadMusicIDs(); - for (QPair i : musicIds.values()) musicId->addItem(i.second); + for (auto iter = musicIds.begin(), end = musicIds.end(); iter != end; iter++) { + musicId->addItem(iter->second); + } updateEditor(); } @@ -160,7 +177,7 @@ void ZoneEditorWidget::select(Zone *zone) editZone = zone; editingAZone = true; updateInfo(); - zoneList->setCurrentRow(zones->indexOf(zone)); + zoneList->setCurrentRow(static_cast(zones->indexOf(zone))); } void ZoneEditorWidget::updateEditor() @@ -192,8 +209,8 @@ void ZoneEditorWidget::loadMusicIDs() file.close(); } -BgPreview::BgPreview() -{ +BgPreview::BgPreview(QWidget *parent) : + QLabel(parent) { bg = QPixmap(400,240); bg.fill(Qt::black); setMinimumWidth(100); @@ -240,9 +257,11 @@ void ZoneEditorWidget::updateInfo() handleChanges = false; id->setValue(editZone->getid()); - for (QPair i : musicIds.values()) - if (i.first == editZone->getMusicId()) - musicId->setCurrentText((i.second)); + for (auto iter = musicIds.begin(), end = musicIds.end(); iter != end; iter++) { + if (iter->first == editZone->getMusicId()) { + musicId->setCurrentText((iter->second)); + } + } multiplayerTracking->setCurrentText(multiplayerTrackings.value(editZone->getMultiplayerTracking())); progPathId->setValue(editZone->getProgPathId()); @@ -262,46 +281,44 @@ void ZoneEditorWidget::handleZoneListIndexChange(QListWidgetItem *item) emit selectedZoneChanged(editZone); } -void ZoneEditorWidget::handleIDChange(int idVal) +void ZoneEditorWidget::handleIDChange(int id) { if (!handleChanges) return; - editZone->setID(idVal); + undoStack->push(new Commands::ZoneCmd::SetId(editZone, id)); updateList(); - emit updateLevelView(); - emit editMade(); } -void ZoneEditorWidget::handleProgPathIDChange(int ppIDVal) +void ZoneEditorWidget::handleProgPathIDChange(int progPathId) { if (!handleChanges) return; - editZone->setProgPathId(ppIDVal); - emit editMade(); + undoStack->push(new Commands::ZoneCmd::SetProgPathId(editZone, progPathId)); } void ZoneEditorWidget::handleMusicIDChange(QString text) { if (!handleChanges) return; - int m_id = 0; - for (QPair i : musicIds.values()) - if (i.second == text) m_id = i.first; + int musicId = 0; + for (auto iter = musicIds.begin(), end = musicIds.end(); iter != end; iter++) { + if (iter->second == text) { + musicId = iter->first; + break; + } + } - editZone->setMusicID(quint8(m_id)); - emit editMade(); + undoStack->push(new Commands::ZoneCmd::SetMusicId(editZone, musicId)); } void ZoneEditorWidget::handleMultiPlayerTrackingChange(QString text) { if (!handleChanges) return; - editZone->setMultiplayerTracking(multiplayerTrackings.key(text, 0)); - emit editMade(); + undoStack->push(new Commands::ZoneCmd::SetMultiplayerTracking(editZone, multiplayerTrackings.key(text, 0))); } void ZoneEditorWidget::handleUnk1Change(int unk1) { if (!handleChanges) return; - editZone->setUnk1(unk1); - emit editMade(); + undoStack->push(new Commands::ZoneCmd::SetUnk1(editZone, unk1)); } void ZoneEditorWidget::handleSelectContentsClicked() @@ -319,25 +336,14 @@ void ZoneEditorWidget::handleScreenshotClicked() void ZoneEditorWidget::handleBoundingIDChange(int val) { if (!handleChanges) return; - - - editZone->setBoundingId(val); - emit updateLevelView(); - emit editMade(); - - boundingId->setValue(val); + undoStack->push(new Commands::ZoneCmd::SetBoundingId(editZone, val)); } void ZoneEditorWidget::handleBackgroundIDChange(int val) { if (!handleChanges) return; - - editZone->setBackgroundId(val); + undoStack->push(new Commands::ZoneCmd::SetBackgroundId(editZone, val)); updateList(); - emit updateLevelView(); - emit editMade(); - - backgroundId->setValue(val); } void ZoneEditorWidget::handleEditBoundingClicked() @@ -356,39 +362,36 @@ void ZoneEditorWidget::handleEditBackgroundClicked() backgroundWidget->exec(); } -void ZoneEditorWidget::handleEditMade() -{ - emit editMade(); -} // Zone Background Widget - -ZoneBackgroundWidget::ZoneBackgroundWidget(QList *backgrounds) -{ - this->zoneBgs = backgrounds; +ZoneBackgroundWidget::ZoneBackgroundWidget(QList *backgrounds, QUndoStack *undoStack, Level *level, QWidget *parent) : + QDialog(parent), + zoneBgs(backgrounds), + undoStack(undoStack), + level(level) { backgroundList = new QListWidget(); backgroundList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(backgroundList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleBackgroundListIndexChange(QListWidgetItem*))); - connect(backgroundList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(handleBackgroundListDoubleClick(QListWidgetItem*))); + connect(backgroundList, &QListWidget::itemClicked, this, &ZoneBackgroundWidget::handleBackgroundListIndexChange); + connect(backgroundList, &QListWidget::itemDoubleClicked, this, &ZoneBackgroundWidget::handleBackgroundListDoubleClick); addBackgroundBtn = new QPushButton(tr("Add Background"), this); - connect(addBackgroundBtn, SIGNAL(clicked(bool)), this, SLOT(handleAddBackgroundClicked())); + connect(addBackgroundBtn, &QAbstractButton::clicked, this, &ZoneBackgroundWidget::handleAddBackgroundClicked); removeBackgroundBtn = new QPushButton(tr("Remove Background"), this); - connect(removeBackgroundBtn, SIGNAL(clicked(bool)), this, SLOT(handleRemoveBackgroundClicked())); + connect(removeBackgroundBtn, &QAbstractButton::clicked, this, &ZoneBackgroundWidget::handleRemoveBackgroundClicked); backgroundId = new QSpinBox(); backgroundId->setRange(0, 255); - connect(backgroundId, SIGNAL(valueChanged(int)), this, SLOT(handleBackgroundIDChanged(int))); + connect(backgroundId, &QSpinBox::valueChanged, this, &ZoneBackgroundWidget::handleBackgroundIDChanged); xPos = new QSpinBox(); xPos->setRange(-32768, 32767); - connect(xPos, SIGNAL(valueChanged(int)), this, SLOT(handleXPosChanged(int))); + connect(xPos, &QSpinBox::valueChanged, this, &ZoneBackgroundWidget::handleXPosChanged); yPos = new QSpinBox(); yPos->setRange(-32768, 32767); - connect(yPos, SIGNAL(valueChanged(int)), this, SLOT(handleYPosChanged(int))); + connect(yPos, &QSpinBox::valueChanged, this, &ZoneBackgroundWidget::handleYPosChanged); parallaxMode = new QComboBox(); parallaxMode->addItem(tr("Y Offset Off, All Parallax On")); @@ -396,12 +399,12 @@ ZoneBackgroundWidget::ZoneBackgroundWidget(QList *backgrounds) parallaxMode->addItem(tr("Y Offset On, All Parallax Off")); parallaxMode->addItem(tr("Y Offset On, Y Parallax Off")); parallaxMode->addItem(tr("Y Offset On, X Parallax Off")); - connect(parallaxMode, SIGNAL(currentIndexChanged(int)), this, SLOT(handleParallaxModeChange(int))); + connect(parallaxMode, &QComboBox::currentIndexChanged, this, &ZoneBackgroundWidget::handleParallaxModeChange); background = new QComboBox(); background->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon); loadBackgrounds(); - connect(background, SIGNAL(currentTextChanged(QString)), this, SLOT(handleBackgroundChange(QString))); + connect(background, &QComboBox::currentTextChanged, this, &ZoneBackgroundWidget::handleBackgroundChange); backgroundPreview = new BgPreview(); @@ -526,39 +529,34 @@ void ZoneBackgroundWidget::updateBgPreview() void ZoneBackgroundWidget::handleParallaxModeChange(int val) { if (!handleChanges) return; - editBg->setParallaxMode(val); - emit editMade(); + undoStack->push(new Commands::ZoneBgCmd::SetParallaxMode(editBg, val)); } void ZoneBackgroundWidget::handleXPosChanged(int val) { if (!handleChanges) return; - editBg->setXPos(val); - emit editMade(); + undoStack->push(new Commands::ZoneBgCmd::SetXPos(editBg, static_cast(val))); } void ZoneBackgroundWidget::handleYPosChanged(int val) { if (!handleChanges) return; - editBg->setYPos(val); - emit editMade(); + undoStack->push(new Commands::ZoneBgCmd::SetYPos(editBg, static_cast(val))); } void ZoneBackgroundWidget::handleBackgroundIDChanged(int val) { if (!handleChanges) return; - editBg->setId(val); + undoStack->push(new Commands::ZoneBgCmd::SetId(editBg, val)); updateList(); updateInfo(); - emit editMade(); } void ZoneBackgroundWidget::handleBackgroundChange(QString text) { if (!handleChanges) return; - editBg->setName(backgrounds.key(text, "Nohara")); + undoStack->push(new Commands::ZoneBgCmd::SetName(editBg, backgrounds.key(text, "Nohara"))); updateBgPreview(); - emit editMade(); } void ZoneBackgroundWidget::handleAddBackgroundClicked() @@ -577,11 +575,9 @@ void ZoneBackgroundWidget::handleAddBackgroundClicked() } ZoneBackground* bg = new ZoneBackground(id, 0, 0, "Nohara", 0); + undoStack->push(new Commands::LevelCmd::InsertZoneBackground(level, bg)); - zoneBgs->append(bg); updateList(); - - emit editMade(); } void ZoneBackgroundWidget::handleRemoveBackgroundClicked() @@ -591,15 +587,12 @@ void ZoneBackgroundWidget::handleRemoveBackgroundClicked() if (!handleChanges) return; - zoneBgs->removeOne(editBg); + undoStack->push(new Commands::LevelCmd::DeleteZoneBackground(level, editBg)); editingABg = false; settingsGroup->setDisabled(true); - delete editBg; - updateList(); - emit editMade(); } void ZoneBackgroundWidget::handleBackgroundListDoubleClick(QListWidgetItem *item) @@ -616,46 +609,44 @@ void ZoneBackgroundWidget::setSelectedIndex(int index) if (items.isEmpty()) return; - else - { - backgroundList->setCurrentIndex(backgroundList->indexFromItem(items.at(0))); - backgroundList->setFocus(); - editBg = zoneBgs->at(backgroundList->row(items.at(0))); - editingABg = true; - updateInfo(); - settingsGroup->setEnabled(true); - } + backgroundList->setCurrentIndex(backgroundList->indexFromItem(items.at(0))); + backgroundList->setFocus(); + editBg = zoneBgs->at(backgroundList->row(items.at(0))); + editingABg = true; + updateInfo(); + settingsGroup->setEnabled(true); } // Zone Bounding Widget - -ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings) -{ - this->zoneBoundings = boundings; +ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings, QUndoStack *undoStack, Level *level, QWidget *parent) : + QDialog(parent), + zoneBoundings(boundings), + undoStack(undoStack), + level(level) { boundingList = new QListWidget(); boundingList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(boundingList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleBoundingListIndexChange(QListWidgetItem*))); - connect(boundingList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(handleBoundingListDoubleClick(QListWidgetItem*))); + connect(boundingList, &QListWidget::itemClicked, this, &ZoneBoundingWidget::handleBoundingListIndexChange); + connect(boundingList, &QListWidget::itemDoubleClicked, this, &ZoneBoundingWidget::handleBoundingListDoubleClick); addBoundingBtn = new QPushButton(tr("Add Bounding"), this); - connect(addBoundingBtn, SIGNAL(clicked(bool)), this, SLOT(handleAddBoundingClicked())); + connect(addBoundingBtn, &QAbstractButton::clicked, this, &ZoneBoundingWidget::handleAddBoundingClicked); removeBoundingBtn = new QPushButton(tr("Remove Bounding"), this); - connect(removeBoundingBtn, SIGNAL(clicked(bool)), this, SLOT(handleRemoveBoundingClicked())); + connect(removeBoundingBtn, &QAbstractButton::clicked, this, &ZoneBoundingWidget::handleRemoveBoundingClicked); unlimitedScrolling = new QCheckBox(tr("Unlimited")); - connect(unlimitedScrolling, SIGNAL(toggled(bool)), this, SLOT(handleUnlimitedScrollingChange(bool))); + connect(unlimitedScrolling, &QAbstractButton::toggled, this, &ZoneBoundingWidget::handleUnlimitedScrollingChange); boundingId = new QSpinBox(); boundingId->setRange(0, 255); - connect(boundingId, SIGNAL(valueChanged(int)), this, SLOT(handleBoundingIdChange(int))); + connect(boundingId, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handleBoundingIdChange); vertScrollingDistance = new QSpinBox(); vertScrollingDistance->setRange(0, 65535); - connect(vertScrollingDistance, SIGNAL(valueChanged(int)), this, SLOT(handleVertScrollingDistanceChange(int))); + connect(vertScrollingDistance, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handleVertScrollingDistanceChange); primaryUpperBound = new QSpinBox(); primaryUpperBound->setRange(-2147483648, 2147483647); @@ -663,7 +654,7 @@ ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings) "This is used to determine how close the player has to be to the top of the screen before the camera scrolls up.\n" "Negative values require the player to be closer to the top of the screen, positive values require the player to be further away.\n" "A value of 0 requires the player to be >5 tiles away from the top before the camera will move.")); - connect(primaryUpperBound, SIGNAL(valueChanged(int)), this, SLOT(handlePrimaryUpperBoundChange(int))); + connect(primaryUpperBound, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handlePrimaryUpperBoundChange); primaryLowerBound = new QSpinBox(); primaryLowerBound->setRange(-2147483648, 2147483647); @@ -671,7 +662,7 @@ ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings) "This is used to determine how close the player has to be to the bottom of the screen before the camera scrolls down.\n" "Positive values require the player to be closer to the bottom of the screen, negative values require the player to be further away.\n" "A value of 0 requires the player to be >5 tiles away from the bottom before the camera will move.")); - connect(primaryLowerBound, SIGNAL(valueChanged(int)), this, SLOT(handlePrimaryLowerBoundChange(int))); + connect(primaryLowerBound, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handlePrimaryLowerBoundChange); secondaryUpperBound = new QSpinBox(); secondaryUpperBound->setRange(-2147483648, 2147483647); @@ -679,7 +670,7 @@ ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings) "This is used to determine how close the player has to be to the top of the screen before the camera scrolls up.\n" "Negative values require the player to be closer to the top of the screen, positive values require the player to be further away.\n" "A value of 0 requires the player to be >5 tiles away from the top before the camera will move.")); - connect(secondaryUpperBound, SIGNAL(valueChanged(int)), this, SLOT(handleSecondaryUpperBoundChange(int))); + connect(secondaryUpperBound, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handleSecondaryUpperBoundChange); secondaryLowerBound = new QSpinBox(); secondaryLowerBound->setRange(-2147483648, 2147483647); @@ -687,7 +678,7 @@ ZoneBoundingWidget::ZoneBoundingWidget(QList *boundings) "This is used to determine how close the player has to be to the bottom of the screen before the camera scrolls down.\n" "Positive values require the player to be closer to the bottom of the screen, negative values require the player to be further away.\n" "A value of 0 requires the player to be >5 tiles away from the bottom before the camera will move.")); - connect(secondaryLowerBound, SIGNAL(valueChanged(int)), this, SLOT(handleSecondaryLowerBoundChange(int))); + connect(secondaryLowerBound, &QSpinBox::valueChanged, this, &ZoneBoundingWidget::handleSecondaryLowerBoundChange); QVBoxLayout* layout = new QVBoxLayout(); setLayout(layout); @@ -797,58 +788,51 @@ void ZoneBoundingWidget::handleBoundingListDoubleClick(QListWidgetItem *item) void ZoneBoundingWidget::handleUnlimitedScrollingChange(bool val) { if (!handleChanges) return; - editBounding->setUpScrolling(val? 0x0F : 0x00); + undoStack->push(new Commands::ZoneBoundingCmd::SetUpScrolling(editBounding, val? 0x0F : 0x00)); if (val) vertScrollingDistance->setEnabled(false); else vertScrollingDistance->setEnabled(true); - - emit editMade(); } void ZoneBoundingWidget::handleVertScrollingDistanceChange(int val) { if (!handleChanges) return; - editBounding->setUpScrolling(val); - emit editMade(); + undoStack->push(new Commands::ZoneBoundingCmd::SetUpScrolling(editBounding, val)); } void ZoneBoundingWidget::handlePrimaryUpperBoundChange(int val) { if (!handleChanges) return; - editBounding->setPrimaryUpperBound(val); - emit editMade(); + undoStack->push(new Commands::ZoneBoundingCmd::SetPrimaryUpperBound(editBounding, val)); + } void ZoneBoundingWidget::handlePrimaryLowerBoundChange(int val) { if (!handleChanges) return; - editBounding->setPrimaryLowerBound(val); - emit editMade(); + undoStack->push(new Commands::ZoneBoundingCmd::SetPrimaryLowerBound(editBounding, val)); } void ZoneBoundingWidget::handleSecondaryUpperBoundChange(int val) { if (!handleChanges) return; - editBounding->setSecondaryUpperBound(val); - emit editMade(); + undoStack->push(new Commands::ZoneBoundingCmd::SetSecondaryUpperBound(editBounding, val)); } void ZoneBoundingWidget::handleSecondaryLowerBoundChange(int val) { if (!handleChanges) return; - editBounding->setSecondaryLowerBound(val); - emit editMade(); + undoStack->push(new Commands::ZoneBoundingCmd::SetSecondaryLowerBound(editBounding, val)); } void ZoneBoundingWidget::handleBoundingIdChange(int val) { if (!handleChanges) return; - editBounding->setId(val); + undoStack->push(new Commands::ZoneBoundingCmd::SetId(editBounding, val)); updateList(); updateInfo(); - emit editMade(); } void ZoneBoundingWidget::handleAddBoundingClicked() @@ -867,11 +851,8 @@ void ZoneBoundingWidget::handleAddBoundingClicked() } ZoneBounding* bounding = new ZoneBounding(id, 0, 0, 0, 0, 0); - - zoneBoundings->append(bounding); + undoStack->push(new Commands::LevelCmd::InsertZoneBounding(level, bounding)); updateList(); - - emit editMade(); } void ZoneBoundingWidget::handleRemoveBoundingClicked() @@ -881,15 +862,12 @@ void ZoneBoundingWidget::handleRemoveBoundingClicked() if (!handleChanges) return; - zoneBoundings->removeOne(editBounding); + undoStack->push(new Commands::LevelCmd::DeleteZoneBounding(level, editBounding)); editingABounding = false; settingsGroup->setDisabled(true); - delete editBounding; - updateList(); - emit editMade(); } void ZoneBoundingWidget::setSelectedIndex(int index) diff --git a/zoneeditorwidget.h b/leveleditor/zoneeditorwidget.h similarity index 86% rename from zoneeditorwidget.h rename to leveleditor/zoneeditorwidget.h index 601d8572..9ca660ad 100644 --- a/zoneeditorwidget.h +++ b/leveleditor/zoneeditorwidget.h @@ -2,7 +2,7 @@ #define ZONEEDITORWIDGET_H #include "objects.h" -#include "settingsmanager.h" +#include "level.h" #include #include @@ -16,13 +16,14 @@ #include #include #include +#include class BgPreview : public QLabel { Q_OBJECT public: - BgPreview(); - void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; + BgPreview(QWidget *parent = nullptr); + void resizeEvent(QResizeEvent *) override; void setBg(QPixmap bg); private: QPixmap bg; @@ -32,12 +33,11 @@ class ZoneBackgroundWidget : public QDialog { Q_OBJECT public: - ZoneBackgroundWidget(QList *backgrounds); + ZoneBackgroundWidget(QList *backgrounds, QUndoStack *undoStack, Level *level, QWidget *parent = nullptr); void updateWidget(); void setSelectedIndex(int index); signals: - void editMade(); void selectedBackgroundChanged(int val); private: @@ -68,6 +68,9 @@ class ZoneBackgroundWidget : public QDialog bool editingABg = false; bool handleChanges = true; + QUndoStack *undoStack; + Level *level; + private slots: void handleBackgroundListIndexChange(QListWidgetItem* item); void handleBackgroundListDoubleClick(QListWidgetItem* item); @@ -84,12 +87,11 @@ class ZoneBoundingWidget : public QDialog { Q_OBJECT public: - ZoneBoundingWidget(QList *boundings); + ZoneBoundingWidget(QList *boundings, QUndoStack *undoStack, Level *level, QWidget *parent = nullptr); void updateWidget(); void setSelectedIndex(int index); signals: - void editMade(); void selectedBoundingChanged(int val); private: @@ -116,6 +118,9 @@ class ZoneBoundingWidget : public QDialog bool editingABounding = false; bool handleChanges = true; + QUndoStack *undoStack; + Level *level; + private slots: void handleBoundingListIndexChange(QListWidgetItem* item); void handleBoundingListDoubleClick(QListWidgetItem* item); @@ -134,17 +139,15 @@ class ZoneEditorWidget : public QWidget { Q_OBJECT public: - ZoneEditorWidget(QList *zones, QList *bgs, QList *bounds); - ~ZoneEditorWidget(); + ZoneEditorWidget(QList *zones, QList *bgs, QList *bounds, QUndoStack *undoStack, Level *level, QWidget *parent = nullptr); + ~ZoneEditorWidget() override; void deselect(); void select(Zone* zone); void updateEditor(); signals: - void updateLevelView(); void selectedZoneChanged(Object* zone); void selectZoneContents(Zone* zone); - void editMade(); void screenshot(QRect); private: @@ -176,7 +179,7 @@ class ZoneEditorWidget : public QWidget QList *zoneBgs; Zone* editZone; - void changeEvent(QEvent* event); + void changeEvent(QEvent* event) override; void loadMusicIDs(); @@ -186,6 +189,9 @@ class ZoneEditorWidget : public QWidget bool editingAZone = false; bool handleChanges = true; + QUndoStack *undoStack; + Level *level; + private slots: void handleZoneListIndexChange(QListWidgetItem* item); void handleIDChange(int idVal); @@ -199,7 +205,6 @@ private slots: void handleBackgroundIDChange(int val); void handleEditBoundingClicked(); void handleEditBackgroundClicked(); - void handleEditMade(); }; #endif // ZONEEDITORWIDGET_H diff --git a/levelmanager.cpp b/levelmanager.cpp index b12e8295..eb574e60 100644 --- a/levelmanager.cpp +++ b/levelmanager.cpp @@ -1,5 +1,5 @@ #include "levelmanager.h" -#include "leveleditorwindow.h" +#include "leveleditor/leveleditorwindow.h" #include "game.h" #include "settingsmanager.h" diff --git a/mainwindow.cpp b/mainwindow.cpp index c94ce39d..6fcd10a4 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -30,12 +30,11 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "imagecache.h" -#include "leveleditorwindow.h" -#include "tileseteditorwindow.h" +#include "tileseteditor/tileseteditorwindow.h" #include "sarcexplorerwindow.h" #include "newtilesetdialog.h" #include "newleveldialog.h" @@ -121,8 +120,12 @@ void MainWindow::changeEvent(QEvent* event) if (gameLoaded) { - ui->levelList->setModel(game->getCourseModel()); - ui->tilesetView->setModel(game->getTilesetModel()); + QStandardItemModel *courseModel = game->getCourseModel(); + courseModel->setParent(this); + ui->levelList->setModel(courseModel); + QStandardItemModel *tilesetModel = game->getTilesetModel(); + tilesetModel->setParent(this); + ui->tilesetView->setModel(tilesetModel); } } @@ -164,10 +167,14 @@ void MainWindow::loadGame(const QString& path) setGameLoaded(true); statusLabel->setText(tr("Loaded: %1").arg(path)); - ui->levelList->setModel(game->getCourseModel()); + QStandardItemModel *courseModel = game->getCourseModel(); + courseModel->setParent(this); + ui->levelList->setModel(courseModel); ui->tilesetView->setHeaderHidden(false); - ui->tilesetView->setModel(game->getTilesetModel()); + QStandardItemModel *tilesetModel = game->getTilesetModel(); + tilesetModel->setParent(this); + ui->tilesetView->setModel(tilesetModel); ui->tilesetView->setColumnWidth(0, 200); } @@ -357,8 +364,9 @@ void MainWindow::on_addLevelBtn_clicked() blankLvl.copy(settings->getLastRomFSPath() + "/Course/" + nld.getName() + ".sarc"); - ui->levelList->setModel(game->getCourseModel()); -} + QStandardItemModel *courseModel = game->getCourseModel(); + courseModel->setParent(this); + ui->levelList->setModel(courseModel);} void MainWindow::on_removeLevelBtn_clicked() { @@ -371,7 +379,9 @@ void MainWindow::on_removeLevelBtn_clicked() return; game->fs->deleteFile("/Course/" + selLvlName); - ui->levelList->setModel(game->getCourseModel()); + QStandardItemModel *courseModel = game->getCourseModel(); + courseModel->setParent(this); + ui->levelList->setModel(courseModel); ui->removeLevelBtn->setDisabled(true); } @@ -412,7 +422,9 @@ void MainWindow::on_addTilesetBtn_clicked() ts.setInternalName(ntd.getName()); ts.save(); - ui->tilesetView->setModel(game->getTilesetModel()); + QStandardItemModel *tilesetModel = game->getTilesetModel(); + tilesetModel->setParent(this); + ui->tilesetView->setModel(tilesetModel); } void MainWindow::on_removeTilesetBtn_clicked() @@ -429,7 +441,9 @@ void MainWindow::on_removeTilesetBtn_clicked() return; game->fs->deleteFile("/Unit/" + selTsName + ".sarc"); - ui->tilesetView->setModel(game->getTilesetModel()); + QStandardItemModel *tilesetModel = game->getTilesetModel(); + tilesetModel->setParent(this); + ui->tilesetView->setModel(tilesetModel); ui->removeTilesetBtn->setDisabled(true); } diff --git a/objectrenderer.cpp b/objectrenderer.cpp index 952e09ec..9bf962e0 100644 --- a/objectrenderer.cpp +++ b/objectrenderer.cpp @@ -790,6 +790,7 @@ SpriteRenderer::SpriteRenderer(const Sprite *spr, Tileset *tilesets[]) void SpriteRenderer::render(QPainter *painter, QRect *drawrect) { ret->render(painter, drawrect); + delete ret; } NormalImageRenderer::NormalImageRenderer(const Object *obj, QString filename) diff --git a/objectrenderer.h b/objectrenderer.h index cd78a339..06b3e105 100644 --- a/objectrenderer.h +++ b/objectrenderer.h @@ -128,6 +128,7 @@ class WhompRenderer: public SpriteRenderer { public: WhompRenderer(const Sprite *spr); + ~WhompRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -213,6 +214,7 @@ class MovementSpriteRenderer: public SpriteRenderer { public: MovementSpriteRenderer(const Sprite *spr, QString fileName); + ~MovementSpriteRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -231,6 +233,7 @@ class FourBurnerRenderer: public SpriteRenderer { public: FourBurnerRenderer(const Sprite *spr); + ~FourBurnerRenderer() { delete up; delete down; delete left; delete right; delete center; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *up; @@ -245,6 +248,7 @@ class FuzzyRenderer: public SpriteRenderer { public: FuzzyRenderer(const Sprite *spr); + ~FuzzyRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -255,6 +259,7 @@ class RotationSpriteRenderer: public SpriteRenderer { public: RotationSpriteRenderer(const Sprite *spr, QString fileName); + ~RotationSpriteRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -265,6 +270,7 @@ class RedCoinRenderer: public SpriteRenderer { public: RedCoinRenderer(const Sprite *spr, QString filename); + ~RedCoinRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: QString filename; @@ -286,6 +292,7 @@ class FireBarRenderer: public SpriteRenderer { public: FireBarRenderer(const Sprite *spr); + ~FireBarRenderer() { delete radius; } void render(QPainter *painter, QRect *drawrect); protected: CircleRenderer *radius; @@ -296,6 +303,7 @@ class FlagRenderer: public SpriteRenderer { public: FlagRenderer(const Sprite *spr); + ~FlagRenderer() { delete rect; } void render(QPainter *painter, QRect *drawrect); private: RoundedRectRenderer *rect; @@ -324,6 +332,7 @@ class BlooperRenderer: public SpriteRenderer { public: BlooperRenderer(const Sprite *spr); + ~BlooperRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -334,6 +343,7 @@ class GoalRenderer: public SpriteRenderer { public: GoalRenderer(const Sprite *spr); + ~GoalRenderer() { delete pole; delete fort; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *pole; @@ -345,6 +355,7 @@ class PathContFenceRenderer: public SpriteRenderer { public: PathContFenceRenderer(const Sprite *spr); + ~PathContFenceRenderer() { delete rect; } void render(QPainter *painter, QRect *drawrect); protected: RoundedRectRenderer *rect; @@ -355,6 +366,7 @@ class SignboardRenderer: public SpriteRenderer { public: SignboardRenderer(const Sprite *spr); + ~SignboardRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -365,6 +377,7 @@ class FloatingBoxRenderer: public SpriteRenderer { public: FloatingBoxRenderer(const Sprite *spr); + FloatingBoxRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -391,6 +404,7 @@ class BulletBillRenderer: public SpriteRenderer { public: BulletBillRenderer(const Sprite *spr); + ~BulletBillRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -401,6 +415,7 @@ class BanzaiBillRenderer: public SpriteRenderer { public: BanzaiBillRenderer(const Sprite *spr); + ~BanzaiBillRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -427,6 +442,7 @@ class BouncyMushroomRenderer: public SpriteRenderer { public: BouncyMushroomRenderer(const Sprite *spr); + ~BouncyMushroomRenderer() { delete img; } void render(QPainter* painter, QRect* drawrect); protected: NormalImageRenderer *img; @@ -447,6 +463,7 @@ class BowserFlameRenderer: public SpriteRenderer { public: BowserFlameRenderer(const Sprite *spr); + ~BowserFlameRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -468,6 +485,7 @@ class RuinsRickRenderer: public SpriteRenderer { public: RuinsRickRenderer(const Sprite *spr); + ~RuinsRickRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -478,6 +496,7 @@ class GoombaRenderer: public SpriteRenderer { public: GoombaRenderer(const Sprite *spr); + ~GoombaRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -488,6 +507,7 @@ class BoneGoombaRenderer: public SpriteRenderer { public: BoneGoombaRenderer(const Sprite *spr); + ~BoneGoombaRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -498,6 +518,7 @@ class GoombaTowerRenderer: public SpriteRenderer { public: GoombaTowerRenderer(const Sprite *spr); + ~GoombaTowerRenderer() { delete top; qDeleteAll(middle); delete bottom; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *top; @@ -526,6 +547,7 @@ class ThreePlatRickRenderer: public SpriteRenderer { public: ThreePlatRickRenderer(const Sprite *spr); + ~ThreePlatRickRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -552,6 +574,7 @@ class FourPlatRickRenderer: public SpriteRenderer { public: FourPlatRickRenderer(const Sprite *spr); + FourPlatRickRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -577,6 +600,7 @@ class BuzzyBeetleRenderer: public SpriteRenderer { public: BuzzyBeetleRenderer(const Sprite *spr); + ~BuzzyBeetleRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -587,6 +611,7 @@ class SpikeTopRenderer: public SpriteRenderer { public: SpikeTopRenderer(const Sprite *spr); + ~SpikeTopRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -612,6 +637,7 @@ class ClimbKoopaHorRenderer: public SpriteRenderer { public: ClimbKoopaHorRenderer(const Sprite *spr); + ~ClimbKoopaHorRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -622,6 +648,7 @@ class ClimbKoopaVertRenderer: public SpriteRenderer { public: ClimbKoopaVertRenderer(const Sprite *spr); + ~ClimbKoopaVertRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -632,6 +659,7 @@ class KoopaTroopaRenderer: public SpriteRenderer { public: KoopaTroopaRenderer(const Sprite *spr); + ~KoopaTroopaRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -642,6 +670,7 @@ class PlantRenderer: public SpriteRenderer { public: PlantRenderer(const Sprite *spr, QString filename); + ~PlantRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: QString filename; @@ -653,6 +682,7 @@ class KoopaParatroopaRenderer: public SpriteRenderer { public: KoopaParatroopaRenderer(const Sprite *spr); + ~KoopaParatroopaRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -684,6 +714,7 @@ class CheepCheepRenderer: public SpriteRenderer { public: CheepCheepRenderer(const Sprite *spr); + ~CheepCheepRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -694,6 +725,7 @@ class BigCheepRenderer: public SpriteRenderer { public: BigCheepRenderer(const Sprite *spr); + ~BigCheepRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -704,6 +736,7 @@ class JumpingCheepRenderer: public SpriteRenderer { public: JumpingCheepRenderer(const Sprite *spr); + ~JumpingCheepRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -714,6 +747,7 @@ class SpinyCheepRenderer: public SpriteRenderer { public: SpinyCheepRenderer(const Sprite *spr); + ~SpinyCheepRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -766,6 +800,7 @@ class SwitchRenderer: public SpriteRenderer { public: SwitchRenderer(const Sprite *spr, QString filename); + ~SwitchRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: QString filename; @@ -788,9 +823,8 @@ class BigBooRenderer: public SpriteRenderer { public: BigBooRenderer(const Sprite *spr); + ~BigBooRenderer() {} void render(QPainter *painter, QRect *drawrect); -protected: - NormalImageRenderer *img; }; // Sprite 186/199/230: Paratroopa/CheepCheep/Peepa Circle @@ -798,6 +832,7 @@ class CoinCircleRenderer: public SpriteRenderer { public: CoinCircleRenderer(const Sprite *spr, Tileset* tileset); + ~CoinCircleRenderer() { delete circle; } void render(QPainter *painter, QRect *drawrect); protected: CircleRenderer *circle; @@ -809,6 +844,7 @@ class BoohemothRenderer: public SpriteRenderer { public: BoohemothRenderer(const Sprite *spr); + ~BoohemothRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -819,6 +855,7 @@ class SpinyRenderer: public SpriteRenderer { public: SpinyRenderer(const Sprite *spr); + ~SpinyRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -829,6 +866,7 @@ class CeilingSpinyRenderer: public SpriteRenderer { public: CeilingSpinyRenderer(const Sprite *spr); + ~CeilingSpinyRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -840,8 +878,6 @@ class SwingingVineRenderer: public SpriteRenderer public: SwingingVineRenderer(const Sprite *spr); void render(QPainter *painter, QRect *drawrect); -protected: - NormalImageRenderer* img; }; // Sprite 240: Urchin @@ -849,6 +885,7 @@ class UrchinRenderer: public SpriteRenderer { public: UrchinRenderer(const Sprite *spr); + ~UrchinRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -859,6 +896,7 @@ class RotatingUrchinRenderer: public SpriteRenderer { public: RotatingUrchinRenderer(const Sprite *spr); + ~RotatingUrchinRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -869,6 +907,7 @@ class GhostWallRenderer: public SpriteRenderer { public: GhostWallRenderer(const Sprite *spr); + ~GhostWallRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -879,6 +918,7 @@ class ChainChompRenderer: public SpriteRenderer { public: ChainChompRenderer(const Sprite *spr); + ~ChainChompRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -996,6 +1036,7 @@ class EventRecLiftRenderer: public SpriteRenderer { public: EventRecLiftRenderer(const Sprite *spr, QString path); + ~EventRecLiftRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -1014,6 +1055,7 @@ class BounceMushCastleRenderer: public SpriteRenderer { public: BounceMushCastleRenderer(const Sprite *spr); + ~BounceMushCastleRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -1024,6 +1066,7 @@ class IceLiftRenderer: public SpriteRenderer { public: IceLiftRenderer(const Sprite *spr); + ~IceLiftRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer* img; @@ -1034,6 +1077,7 @@ class CoinMeteorRenderer: public SpriteRenderer { public: CoinMeteorRenderer(const Sprite *spr); + ~CoinMeteorRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -1044,6 +1088,7 @@ class UnderwaterRecLiftRenderer: public SpriteRenderer { public: UnderwaterRecLiftRenderer(const Sprite *spr); + ~UnderwaterRecLiftRenderer() { delete img; } void render(QPainter *painter, QRect *drawrect); protected: NormalImageRenderer *img; @@ -1061,6 +1106,7 @@ class EntranceRenderer : public ObjectRenderer { public: EntranceRenderer(const Entrance *entrance); + ~EntranceRenderer() { delete rect; } void render(QPainter *painter, QRect *drawrect); private: RoundedRectRenderer *rect; diff --git a/objects.cpp b/objects.cpp index 4d2fdc0c..2423f2de 100644 --- a/objects.cpp +++ b/objects.cpp @@ -100,7 +100,6 @@ BgdatObject::BgdatObject(BgdatObject *obj) layer = obj->getLayer(); } -qint32 BgdatObject::getType() const { return 0; } qint32 BgdatObject::getid() const { return id; } qint32 BgdatObject::getLayer() const { return layer; } @@ -109,11 +108,21 @@ void BgdatObject::setTsID(qint32 tsID) id = (id & 0xFFF) | (tsID << 12); } +qint32 BgdatObject::getTsID() const +{ + return (id >> 12) & 0x3; +} + void BgdatObject::setObjID(qint32 objID) { id = (id & 0xF000) | objID; } +qint32 BgdatObject::getObjID() const +{ + return id & 0x0FFF; +} + // Format: 0:ID:Layer:X:Y:Width:Height QString BgdatObject::toString(qint32 xOffset, qint32 yOffset) const { return QString("0:%1:%2:%3:%4:%5:%6").arg(id).arg(layer).arg(x+xOffset).arg(y+yOffset).arg(width).arg(height); } @@ -2885,7 +2894,6 @@ void Sprite::setRect() } } -qint32 Sprite::getType() const { return 1; } qint16 Sprite::getid() const { return id; } quint8 Sprite::getByte(qint32 id) const { return spriteData[id]; } @@ -3144,7 +3152,6 @@ Location::Location(Location *loc) id = loc->getid(); } -qint32 Location::getType() const { return 4; } qint32 Location::getid() const { return id; } // Format: 4:ID:X:Y:Width:Height @@ -3230,6 +3237,22 @@ PathNode::PathNode(qint32 x, qint32 y, float speed, float accel, quint16 delay, this->offsety = -10; } +PathNode::PathNode(qint32 x, qint32 y, Path* parentPath) +{ + this->x = x; + this->y = y; + this->speed = 0; + this->accel = 0; + this->delay = 0; + this->rotation = 0; + this->variableField = 0; + this->nextPathID = 0; + this->parentPath = parentPath; + + this->offsetx = -10; + this->offsety = -10; +} + PathNode::PathNode(PathNode *node, Path* parentPath) { x = node->getx(); diff --git a/objects.h b/objects.h index 26cc99b6..23fff80f 100644 --- a/objects.h +++ b/objects.h @@ -22,6 +22,18 @@ #include #include +enum ObjectType +{ + INVALID, + BGDATOBJECT, + SPRITE, + ENTRANCE, + ZONE, + LOCATION, + PATHNODE, + PROGRESSPATHNODE +}; + // Obj Baseclass class Object { @@ -32,7 +44,7 @@ class Object void increasePosition(qint32 deltax, qint32 deltay, qint32 snap = 0); void resize(qint32 width, qint32 height); void increaseSize(qint32 deltax, qint32 deltay, qint32 snap = 0); - virtual qint32 getType() const { return -1; } + virtual ObjectType getType() const { return ObjectType::INVALID; } virtual bool isResizable() const { return false; } virtual bool doRender(QRect r) { return r.intersects(QRect(x + offsetx, y + offsety, width, height)); } qint32 getx() const { return x; } @@ -45,15 +57,6 @@ class Object bool clickDetection(QRect rect); virtual QString toString(qint32 xOffset, qint32 yOffset) const; - // First Number: - // -1: Invalid - // 0: BgdatObject - // 1: Sprite - // 2: Entrance - // 3: Zone - // 4: Location - // 5: Path - // 6: Progress Path protected: qint32 x, y; @@ -70,11 +73,13 @@ class BgdatObject: public Object BgdatObject() {} BgdatObject(BgdatObject* obj); BgdatObject(qint32 x, qint32 y, qint32 width, qint32 height, qint32 id, qint32 layer); - qint32 getType() const; + ObjectType getType() const { return ObjectType::BGDATOBJECT; } bool isResizable() const { return true; } qint32 getid() const; void setTsID(qint32 tsID); + qint32 getTsID() const; void setObjID(qint32 objID); + qint32 getObjID() const; qint32 getLayer() const; QString toString(qint32 xOffset, qint32 yOffset) const; void setLayer(qint32 layer) { this->layer = layer; } @@ -89,9 +94,10 @@ class Sprite: public Object { public: Sprite() {} + ~Sprite() { delete selectionRects; } Sprite(Sprite* spr); Sprite(qint32 x, qint32 y, qint16 id); - qint32 getType() const; + ObjectType getType() const { return ObjectType::SPRITE; } bool isResizable() const { return false; } virtual bool doRender(QRect r) { return r.intersects(QRect(x + offsetx + renderOffsetX, y + offsety + renderOffsetY, width + renderOffsetW, height + renderOffsetH)); } qint16 getid() const; @@ -135,7 +141,7 @@ class Entrance: public Object Entrance() {} Entrance(Entrance* entr); Entrance(qint32 x, qint32 y, qint16 cameraX, qint16 cameraY, quint8 id, quint8 destArea, quint8 destEntr, quint8 entrType, quint16 settings, quint8 unk1, quint8 unk2); - qint32 getType() const { return 2; } + ObjectType getType() const { return ObjectType::ENTRANCE; } bool isResizable() const { return false; } QString toString(qint32 xOffset, qint32 yOffset) const; quint8 getid() const { return id; } @@ -214,14 +220,14 @@ class ZoneBackground void setYPos(qint16 yPos) { this->yPos = yPos; } void setXPos(qint16 xPos) { this->xPos = xPos; } void setName(QString name) { this->name = name; } - void setParallaxMode(qint8 parallaxMode) { this->parallaxMode = parallaxMode; } + void setParallaxMode(quint8 parallaxMode) { this->parallaxMode = parallaxMode; } protected: quint16 id = 0; qint16 yPos = 0; qint16 xPos = 0; QString name = "Nohara"; - qint8 parallaxMode = 0; + quint8 parallaxMode = 0; }; class Zone: public Object @@ -232,7 +238,7 @@ class Zone: public Object Zone(qint32 x, qint32 y, qint32 width, qint32 height, quint8 id, quint8 progPathId, quint8 musicId, quint8 multiplayerTracking, quint16 unk1, quint8 boundingId, quint8 backgroundId); bool clickDetection(qint32 xcheck, qint32 ycheck); bool clickDetection(QRect rect); - qint32 getType() const { return 3; } + ObjectType getType() const { return ObjectType::ZONE; } bool isResizable() const { return true; } QString toString(qint32 xOffset, qint32 yOffset) const; quint16 getUnk1() const { return unk1; } @@ -268,7 +274,7 @@ class Location: public Object Location() {} Location(Location* loc); Location(qint32 x, qint32 y, qint32 width, qint32 height, qint32 id); - qint32 getType() const; + ObjectType getType() const { return ObjectType::LOCATION; } bool isResizable() const { return true; } qint32 getid() const; void setId(quint8 id) { this->id = id; } @@ -285,8 +291,9 @@ class PathNode: public Object public: PathNode() {} PathNode(PathNode* node, Path* parentPath); + PathNode(qint32 x, qint32 y, Path *parentPath); PathNode(qint32 x, qint32 y, float speed, float accel, quint16 delay, qint16 rotation, quint8 variableField, quint8 nextPathID, Path *parentPath); - qint32 getType() const { return 5; } + ObjectType getType() const { return ObjectType::PATHNODE; } bool isResizable() const { return false; } float getSpeed() const { return speed; } float getAccel() const { return accel; } @@ -320,7 +327,7 @@ class Path public: Path() {} Path(Path* path); - ~Path() { foreach (PathNode* node, nodes) delete node; } + ~Path() { qDeleteAll(nodes); } Path(quint16 id, quint16 loop); void insertNode(PathNode* node, qint32 index = -1); void removeNode(PathNode* node); @@ -333,7 +340,7 @@ class Path void setId(qint32 id) { this->id = id; } void setLoop(qint32 loop) {this->loop = loop; } QString toString(qint32 xOffset, qint32 yOffset); - void swapNodes(qint32 node1, quint32 node2) { nodes.swapItemsAt(node1, node2); } + void swapNodes(qsizetype node1, qsizetype node2) { nodes.swapItemsAt(node1, node2); } protected: quint16 id; @@ -350,7 +357,7 @@ class ProgressPathNode: public Object ProgressPathNode() {} ProgressPathNode(ProgressPathNode* node, ProgressPath* parentPath); ProgressPathNode(qint32 x, qint32 y, ProgressPath* parentPath); - qint32 getType() const { return 6; } + ObjectType getType() const { return ObjectType::PROGRESSPATHNODE; } bool isResizable() const { return false; } ProgressPath* getParentPath() const { return parentPath; } QString toString(qint32 xOffset, qint32 yOffset) const; @@ -365,7 +372,7 @@ class ProgressPath public: ProgressPath() {} ProgressPath(ProgressPath* path); - ~ProgressPath() { foreach (ProgressPathNode* node, nodes) delete node; } + ~ProgressPath() { qDeleteAll(nodes); } ProgressPath(quint16 id, quint8 alternatePathFlag); void insertNode(ProgressPathNode* node, qint32 index = -1); void removeNode(ProgressPathNode* node); @@ -376,7 +383,7 @@ class ProgressPath ProgressPathNode* getNode(qint32 id) const { return nodes[id]; } qint32 getIndexOfNode(ProgressPathNode* node) { return nodes.indexOf(node); } void setId(qint32 id) { this->id = id; } - void setAlternatePathFlag(bool flag) { this->alternatePathFlag = flag; } + void setAlternatePathFlag(quint8 flag) { this->alternatePathFlag = flag; } QString toString(qint32 xOffset, qint32 yOffset); protected: quint16 id; diff --git a/English.ts b/resource/translations/English.ts similarity index 100% rename from English.ts rename to resource/translations/English.ts diff --git a/German.ts b/resource/translations/German.ts similarity index 100% rename from German.ts rename to resource/translations/German.ts diff --git a/Italian.ts b/resource/translations/Italian.ts similarity index 100% rename from Italian.ts rename to resource/translations/Italian.ts diff --git a/sarcexplorerwindow.h b/sarcexplorerwindow.h index 2605fadf..959de3e2 100644 --- a/sarcexplorerwindow.h +++ b/sarcexplorerwindow.h @@ -6,7 +6,7 @@ #include #include -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "settingsmanager.h" #include "windowbase.h" diff --git a/settingsmanager.cpp b/settingsmanager.cpp index 07740cbd..f0e3ca3d 100644 --- a/settingsmanager.cpp +++ b/settingsmanager.cpp @@ -27,68 +27,63 @@ #include #include -SettingsManager* SettingsManager::instance = NULL; +SettingsManager* SettingsManager::instance = nullptr; -SettingsManager* SettingsManager::init(QWidget* parentWidget) -{ +SettingsManager* SettingsManager::init(QWidget* parentWidget) { QCoreApplication::setOrganizationName("Blarg City"); QCoreApplication::setApplicationName("CoinKiller"); - if (instance != NULL) - throw new std::runtime_error("SettingsManager already inited."); + if (instance != nullptr) { + throw std::runtime_error("SettingsManager already inited."); + } instance = new SettingsManager(parentWidget); return instance; } -SettingsManager* SettingsManager::getInstance() -{ - if (instance == NULL) - throw new std::runtime_error("SettingsManager not inited."); +SettingsManager* SettingsManager::getInstance() { + if (instance == nullptr) { + throw std::runtime_error("SettingsManager not inited."); + } return instance; } -SettingsManager::SettingsManager(QWidget* parentWidget) -{ - this->parentWidget = parentWidget; +SettingsManager::SettingsManager(QWidget *parent) : + QObject(parent) { QFileInfo localDataDir(QCoreApplication::applicationDirPath() + "/coinkiller_data"); - if (localDataDir.isDir() && localDataDir.isReadable()) + if (localDataDir.isDir() && localDataDir.isReadable()) { dataBasePath = localDataDir.absoluteFilePath(); - else - { + } else { dataBasePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/coinkiller_data"; QDir().mkpath(dataBasePath); } } -SettingsManager::~SettingsManager() -{ +SettingsManager::~SettingsManager() { } -QString SettingsManager::dataPath(const QString& path) -{ +QString SettingsManager::dataPath(const QString& path) { return QString("%1/%2").arg(dataBasePath).arg(path); } -void SettingsManager::loadTranslations() -{ +void SettingsManager::loadTranslations() { QString language = settings.value("Language", "English").toString(); loadTranslations(language); } -void SettingsManager::loadTranslations(QString languageName) -{ +void SettingsManager::loadTranslations(QString languageName) { QString file = dataPath("languages/"+languageName+"/"+languageName); bool loaded = translator.load(file); - if (loaded) + if (loaded) { qApp->installTranslator(&translator); - else + } else { qApp->removeTranslator(&translator); + } QStringList translateFiles; @@ -101,18 +96,17 @@ void SettingsManager::loadTranslations(QString languageName) << "tilebehaviors.xml" << "tilesetnames.txt"; - foreach (QString transFile, translateFiles) - { + foreach (QString transFile, translateFiles) { QString path = dataPath("languages/"+languageName+"/"+transFile); - if(!QFile(path).exists()) + if(!QFile(path).exists()) { path = dataPath(transFile); + } translatedFiles.insert(transFile, path); } } -void SettingsManager::setupLanguageSelector(QListWidget* selector) -{ +void SettingsManager::setupLanguageSelector(QListWidget* selector) { selector->blockSignals(true); selector->clear(); @@ -120,50 +114,77 @@ void SettingsManager::setupLanguageSelector(QListWidget* selector) translationsFolder.setFilter(QDir::NoDotAndDotDot | QDir::Dirs); QDirIterator directories(translationsFolder, QDirIterator::NoIteratorFlags); - while(directories.hasNext()) - { + while(directories.hasNext()) { directories.next(); QListWidgetItem* item = new QListWidgetItem(directories.fileName()); selector->addItem(item); - if (directories.fileName() == settings.value("Language", "English").toString()) + if (directories.fileName() == settings.value("Language", "English").toString()) { selector->setCurrentItem(item); + } } - connect(selector, SIGNAL(currentTextChanged(QString)), this, SLOT(setLanguage(QString))); + connect(selector, &QListWidget::currentTextChanged, this, &SettingsManager::setLanguage); selector->blockSignals(false); } -QString SettingsManager::getFilePath(QString file) -{ +QString SettingsManager::getFilePath(QString file) { return translatedFiles.value(file); } -void SettingsManager::setLanguage(QString language) -{ +void SettingsManager::setLanguage(QString language) { settings.setValue("Language", language); loadTranslations(language); } -QVariant SettingsManager::get(const QString &key, const QVariant &defaultValue) -{ +QVariant SettingsManager::get(const QString &key, const QVariant &defaultValue) { return settings.value(key, defaultValue); } -void SettingsManager::set(const QString &key, const QVariant &value) -{ +void SettingsManager::set(const QString &key, const QVariant &value) { settings.setValue(key, value); } -QColor SettingsManager::getColor(const QString &key, const QColor &defaultColor) -{ +QColor SettingsManager::getColor(const QString &key, const QColor &defaultColor) { return QColor::fromRgba(settings.value(key, defaultColor.rgba()).toUInt()); } -void SettingsManager::setColor(const QString &key, const QColor &color) -{ +void SettingsManager::setColor(const QString &key, const QColor &color) { settings.setValue(key, color.rgba()); } + +// Level Editor settings +QColor SettingsManager::getLEWindowColor() { + return QColor::fromRgba(settings.value("LE_WINDOW_COLOR", LE_WINDOW_COLOR_DEFAULT.rgba()).toUInt()); +} + +void SettingsManager::setLEWindowColor(const QColor &color) { + settings.setValue("LE_WINDOW_COLOR", color.rgba()); +} + +quint32 SettingsManager::getLEUndoLimit() { + return settings.value("LE_UNDO_LIMIT", LE_UNDO_LIMIT_DEFAULT).toUInt(); +} + +void SettingsManager::setLEUndoLimit(const quint32 &value) { + settings.setValue("LE_UNDO_LIMIT", value); +} + +bool SettingsManager::getLESelectOnPlace() { + return settings.value("LE_SELECT_ON_PLACE", LE_SELECT_ON_PLACE_DEFAULT).toBool(); +} + +void SettingsManager::setLESelectOnPlace(const bool &value) { + settings.setValue("LE_SELECT_ON_PLACE", value); +} + +bool SettingsManager::getLEShowStatusbar() { + return settings.value("LE_SHOW_STATUSBAR", LE_SHOW_STATUSBAR_DEFAULT).toBool(); +} + +void SettingsManager::setLEShowStatusbar(const bool &value) { + settings.setValue("LE_SHOW_STATUSBAR", value); +} diff --git a/settingsmanager.h b/settingsmanager.h index 43d32dac..60e0bdb8 100644 --- a/settingsmanager.h +++ b/settingsmanager.h @@ -29,9 +29,9 @@ class SettingsManager : public QObject { Q_OBJECT public: - static SettingsManager* init(QWidget* parentWidget); + static SettingsManager* init(QWidget *parent = nullptr); static SettingsManager* getInstance(); - ~SettingsManager(); + ~SettingsManager() override; QString dataPath(const QString& path = ""); @@ -55,6 +55,24 @@ class SettingsManager : public QObject QColor getColor(const QString &key, const QColor &defaultColor = Qt::white); void setColor(const QString &key, const QColor &color); + QColor getLEWindowColor(); + void setLEWindowColor(const QColor &color); + + quint32 getLEUndoLimit(); + void setLEUndoLimit(const quint32 &value); + + bool getLESelectOnPlace(); + void setLESelectOnPlace(const bool &value); + + bool getLEShowStatusbar(); + void setLEShowStatusbar(const bool &value); + + // Defaults - Level Editor + static constexpr QColor LE_WINDOW_COLOR_DEFAULT = QColor(119, 136, 153); + static constexpr int LE_UNDO_LIMIT_DEFAULT = 200; + static constexpr bool LE_SELECT_ON_PLACE_DEFAULT = true; + static constexpr bool LE_SHOW_STATUSBAR_DEFAULT = true; + protected: SettingsManager(QWidget* parentWidget); diff --git a/tileset.cpp b/tileset.cpp index c79f6ebf..14f6e848 100644 --- a/tileset.cpp +++ b/tileset.cpp @@ -103,6 +103,7 @@ Tileset::Tileset(Game *game, QString name) if (b == 0xFE) // start new row { obj->rows.append(*row); + delete row; row = new ObjectRow(); row->slopeFlags = 0; @@ -224,6 +225,7 @@ Tileset::~Tileset() { delete ctpk; delete archive; + qDeleteAll(objectDefs); } diff --git a/tileset.h b/tileset.h index 2647ef2b..f33133b1 100644 --- a/tileset.h +++ b/tileset.h @@ -18,7 +18,7 @@ #ifndef TILESET_H #define TILESET_H -#include "filesystem.h" +#include "filesystem/filesystem.h" #include "ctpk.h" #include diff --git a/tileseteditorwidgets.cpp b/tileseteditor/tileseteditorwidgets.cpp similarity index 100% rename from tileseteditorwidgets.cpp rename to tileseteditor/tileseteditorwidgets.cpp diff --git a/tileseteditorwidgets.h b/tileseteditor/tileseteditorwidgets.h similarity index 100% rename from tileseteditorwidgets.h rename to tileseteditor/tileseteditorwidgets.h diff --git a/tileseteditorwindow.cpp b/tileseteditor/tileseteditorwindow.cpp similarity index 100% rename from tileseteditorwindow.cpp rename to tileseteditor/tileseteditorwindow.cpp diff --git a/tileseteditorwindow.h b/tileseteditor/tileseteditorwindow.h similarity index 100% rename from tileseteditorwindow.h rename to tileseteditor/tileseteditorwindow.h diff --git a/tileseteditorwindow.ui b/tileseteditor/tileseteditorwindow.ui similarity index 100% rename from tileseteditorwindow.ui rename to tileseteditor/tileseteditorwindow.ui diff --git a/tilesetpalette.cpp b/tilesetpalette.cpp deleted file mode 100644 index 56f933ea..00000000 --- a/tilesetpalette.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "tilesetpalette.h" - -#include -#include -#include -#include -#include -#include - -TilesetPalette::TilesetPalette(Level* level, ObjectsEditonMode* objEditionMode, Game* game) -{ - this->level = level; - this->game = game; - this->objEditionMode = objEditionMode; - - QVBoxLayout* layout = new QVBoxLayout(); - this->setLayout(layout); - - QHBoxLayout* topLayout = new QHBoxLayout(); - layout->addLayout(topLayout); - - QLabel* label = new QLabel(tr("Paint on:")); - label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - topLayout->addWidget(label); - - QRadioButton* layer1RadioBtn = new QRadioButton(tr("Layer 1")); - layer1RadioBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - layer1RadioBtn->setChecked(true); - topLayout->addWidget(layer1RadioBtn); - - QRadioButton* layer2RadioBtn = new QRadioButton(tr("Layer 2")); - layer2RadioBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - topLayout->addWidget(layer2RadioBtn); - - topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred)); - - tabWidget = new QTabWidget(); - layout->addWidget(tabWidget); - - // Setup Tileset Selector - for (int i = 0; i < 4; i++) - { - QComboBox* tsNameCombobox = new QComboBox(); - QStandardItemModel* model = game->getTilesetModel(i, true); - - model->sort(0, Qt::AscendingOrder); - - for (int j = 0; j < model->rowCount(); j++) - { - // Tileset Name - QModelIndex tsNameIndex = model->index(j, 0); - QString tilesetName = tsNameIndex.data().toString(); - - tsNameCombobox->addItem(tilesetName); - - // File Name - QModelIndex fileNameIndex = model->index(j, 1); - QString fileName = fileNameIndex.data().toString(); - - tsNameCombobox->setItemData(j, fileName, Qt::UserRole); - - if (level->tilesets[i]) - { - QString selectedTs = level->tilesets[i]->getName(); - - if (selectedTs == fileName) - tsNameCombobox->setCurrentIndex(j); - } - } - - connect(tsNameCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(handleTilesetChange(int))); - - QWidget* tabPage = new QWidget; - QGridLayout* tabLayout = new QGridLayout; - - QLabel* tilesetLabel = new QLabel(tr("Tileset:")); - tilesetLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - - tabLayout->addWidget(tilesetLabel, 0, 0, 1, 1); - tabLayout->addWidget(tsNameCombobox, 0, 1); - - tabPage->setLayout(tabLayout); - - objectLists[i] = new QListView(); - tabLayout->addWidget(objectLists[i], 1, 0, 1, 2); - - QString title; - if (i == 0) title = tr("Standard"); - else if (i == 1) title = tr("Stage"); - else if (i == 2) title = tr("Background"); - else if (i == 3) title = tr("Interactive"); - - tabWidget->addTab(tabPage, title); - - objectLists[i]->setFlow(QListView::LeftToRight); - objectLists[i]->setLayoutMode(QListView::SinglePass); - objectLists[i]->setMovement(QListView::Static); - objectLists[i]->setResizeMode(QListView::Adjust); - objectLists[i]->setWrapping(true); - objectLists[i]->setIconSize(QSize(400,400)); - objectLists[i]->setVerticalScrollMode(QListView::ScrollPerPixel); - objectLists[i]->setEditTriggers(QAbstractItemView::NoEditTriggers); - loadTileset(i); - } - - connect(objectLists[0], SIGNAL(clicked(QModelIndex)), this, SLOT(on_objectsListView0_clicked(QModelIndex))); - connect(objectLists[1], SIGNAL(clicked(QModelIndex)), this, SLOT(on_objectsListView1_clicked(QModelIndex))); - connect(objectLists[2], SIGNAL(clicked(QModelIndex)), this, SLOT(on_objectsListView2_clicked(QModelIndex))); - connect(objectLists[3], SIGNAL(clicked(QModelIndex)), this, SLOT(on_objectsListView3_clicked(QModelIndex))); - connect(objectLists[0], SIGNAL(entered(QModelIndex)), this, SLOT(on_objectsListView0_clicked(QModelIndex))); - connect(objectLists[1], SIGNAL(entered(QModelIndex)), this, SLOT(on_objectsListView1_clicked(QModelIndex))); - connect(objectLists[2], SIGNAL(entered(QModelIndex)), this, SLOT(on_objectsListView2_clicked(QModelIndex))); - connect(objectLists[3], SIGNAL(entered(QModelIndex)), this, SLOT(on_objectsListView3_clicked(QModelIndex))); - connect(layer1RadioBtn, SIGNAL(toggled(bool)), SLOT(on_layerRadioButton_toggled(bool))); -} - -void TilesetPalette::reloadTilesets() -{ - for (int i = 0; i < 4; i++) loadTileset(i); -} - -void TilesetPalette::loadTileset(int tilesetNbr) -{ - if (!level->tilesets[tilesetNbr]) - { - objectLists[tilesetNbr]->setEnabled(false); - objectLists[tilesetNbr]->setModel(new QStandardItemModel()); - return; - } - objectLists[tilesetNbr]->setEnabled(true); - - QStandardItemModel* objectsModel = new QStandardItemModel(this); - - for (int i = 0; i < level->tilesets[tilesetNbr]->getNumObjects(); i++) - { - ObjectDef* obj = level->tilesets[tilesetNbr]->getObjectDef(i); - QPixmap objPixmap(obj->width*20, obj->height*20); - objPixmap.fill(Qt::transparent); - - QPainter p(&objPixmap); - TileGrid tileGrid; - tileGrid.clear(); - tileGrid[0xFFFFFFFF] = 1; - level->tilesets[tilesetNbr]->Render2DTiles(true); - level->tilesets[tilesetNbr]->Render3DOverlay(true); - level->tilesets[tilesetNbr]->drawObject(p, tileGrid, i, 0, 0, obj->width, obj->height, 1); - p.end(); - QStandardItem *objItem = new QStandardItem(); - objItem->setIcon(QIcon(objPixmap)); - objItem->setToolTip(tr("Object: %1").arg(i)); - objectsModel->appendRow(objItem); - } - - objectLists[tilesetNbr]->setModel(objectsModel); -} - -void TilesetPalette::on_objectsListView0_clicked(const QModelIndex &index) -{ - updatePalettes(0); - objEditionMode->setDrawType(0); - objEditionMode->setObject(index.row(), 0); -} - -void TilesetPalette::on_objectsListView1_clicked(const QModelIndex &index) -{ - updatePalettes(1); - objEditionMode->setDrawType(0); - objEditionMode->setObject(index.row(), 1); -} - -void TilesetPalette::on_objectsListView2_clicked(const QModelIndex &index) -{ - updatePalettes(2); - objEditionMode->setDrawType(0); - objEditionMode->setObject(index.row(), 2); -} - -void TilesetPalette::on_objectsListView3_clicked(const QModelIndex &index) -{ - updatePalettes(3); - objEditionMode->setDrawType(0); - objEditionMode->setObject(index.row(), 3); -} - -void TilesetPalette::updatePalettes(int actualPal) -{ - for (int i = 0; i < 4; i++) - { - if (i == actualPal) continue; - objectLists[i]->clearSelection(); - } -} - -void TilesetPalette::on_layerRadioButton_toggled(bool checked) -{ - objEditionMode->setLayer(!checked); -} - -void TilesetPalette::select(BgdatObject *obj) -{ - int tsid = (obj->getid() >> 12) & 0x3; - tabWidget->setCurrentIndex(tsid); - objectLists[tsid]->setCurrentIndex(objectLists[tsid]->model()->index(obj->getid()&0x0FFF, 0)); - - updatePalettes(tsid); - objEditionMode->setDrawType(0); - objEditionMode->setObject(obj->getid()&0x0FFF, (obj->getid() >> 12) & 0x3); -} - -void TilesetPalette::handleTilesetChange(int index) -{ - QComboBox* tsNameCombobox = qobject_cast(sender()); - - QString tsName = tsNameCombobox->itemData(index).toString(); - int tsId = tabWidget->currentIndex(); - - delete level->tilesets[tsId]; - - if (tsName == "") - level->tilesets[tsId] = NULL; - else - level->tilesets[tsId] = game->getTileset(tsName); - - emit updateLevelView(); - emit editMade(); - reloadTilesets(); -} diff --git a/tilesetpalette.h b/tilesetpalette.h deleted file mode 100644 index 2e7044ba..00000000 --- a/tilesetpalette.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef TILESETPALETTE_H -#define TILESETPALETTE_H - -#include "level.h" -#include "game.h" -#include "objectseditionmode.h" - -#include -#include -#include -#include - -class TilesetPalette : public QWidget -{ - Q_OBJECT -public: - explicit TilesetPalette(Level* level, ObjectsEditonMode *objEditionMode, Game *game); - void select(BgdatObject* obj); - -signals: - void updateLevelView(); - void editMade(); - -private slots: - void on_objectsListView0_clicked(const QModelIndex &index); - void on_objectsListView1_clicked(const QModelIndex &index); - void on_objectsListView2_clicked(const QModelIndex &index); - void on_objectsListView3_clicked(const QModelIndex &index); - void on_layerRadioButton_toggled(bool checked); - - void handleTilesetChange(int index); - -private: - Level* level; - Game* game; - ObjectsEditonMode* objEditionMode; - - QTabWidget* tabWidget; - QListView* objectLists[4]; - - void loadTileset(int tilesetNbr); - void updatePalettes(int actualPal); - - void reloadTilesets(); -}; - -#endif // TILESETPALETTE_H diff --git a/unitsconvert.cpp b/unitsconvert.cpp index b63e7cf0..6b1d9bf6 100644 --- a/unitsconvert.cpp +++ b/unitsconvert.cpp @@ -16,6 +16,7 @@ */ #include "unitsconvert.h" +#include "objects.h" int sign(int nbr) { @@ -31,7 +32,7 @@ int toNext16Compatible(int nbr) { return to20(to16(nbr)); } int typeRound(int nbr, int type) { - if (type == 0) + if (type == ObjectType::BGDATOBJECT) return toNext20(nbr-10); else return toNext16Compatible(nbr);