diff --git a/src/scenario/town.cpp b/src/scenario/town.cpp index 7d22d539..92d20e98 100644 --- a/src/scenario/town.cpp +++ b/src/scenario/town.cpp @@ -276,4 +276,15 @@ bool cTown::any_preset_items() const { if(item.code >= 0) return true; } return false; +} + +bool cTown::cItem::operator==(const cTown::cItem& other) { + CHECK_EQ(other, loc); + CHECK_EQ(other, code); + CHECK_EQ(other, ability); + CHECK_EQ(other, charges); + CHECK_EQ(other, always_there); + CHECK_EQ(other, property); + CHECK_EQ(other, contained); + return true; } \ No newline at end of file diff --git a/src/scenario/town.hpp b/src/scenario/town.hpp index 1811a0b0..6c42f744 100644 --- a/src/scenario/town.hpp +++ b/src/scenario/town.hpp @@ -59,6 +59,9 @@ public: eEnchant ability; int charges = -1; bool always_there = false, property = false, contained = false; + // For detecting actual changes to town items in the editor + bool operator==(const cItem& other); + bool operator!=(const cItem& other) { return !(*this == other); } void import_legacy(legacy::preset_item_type old); cItem(); diff --git a/src/scenedit/scen.actions.cpp b/src/scenedit/scen.actions.cpp index d1579145..55d1d94a 100644 --- a/src/scenedit/scen.actions.cpp +++ b/src/scenedit/scen.actions.cpp @@ -856,11 +856,17 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) { } break; case MODE_EDIT_ITEM: - for(short x = 0; x < town->preset_items.size(); x++) - if((spot_hit.x == town->preset_items[x].loc.x) && - (spot_hit.y == town->preset_items[x].loc.y) && (town->preset_items[x].code >= 0)) { + for(short x = 0; x < town->preset_items.size(); x++){ + cTown::cItem old_item = town->preset_items[x]; + if((spot_hit.x == old_item.loc.x) && + (spot_hit.y == old_item.loc.y) && (old_item.code >= 0)) { edit_placed_item(x); + if(town->preset_items[x] != old_item){ + undo_list.add(action_ptr(new aEditPlacedItem(x, old_item, town->preset_items[x]))); + update_edit_menu(); + } } + } overall_mode = MODE_DRAWING; break; case MODE_PASTE: diff --git a/src/scenedit/scen.undo.cpp b/src/scenedit/scen.undo.cpp index 4adf061c..305d5cb9 100644 --- a/src/scenedit/scen.undo.cpp +++ b/src/scenedit/scen.undo.cpp @@ -309,4 +309,14 @@ bool aClearProperty::redo_me() { item.property = false; } return true; +} + +bool aEditPlacedItem::undo_me() { + town->preset_items[which] = old_item; + return true; +} + +bool aEditPlacedItem::redo_me() { + town->preset_items[which] = new_item; + return true; } \ No newline at end of file diff --git a/src/scenedit/scen.undo.hpp b/src/scenedit/scen.undo.hpp index 49bbf56e..49ffddff 100644 --- a/src/scenedit/scen.undo.hpp +++ b/src/scenedit/scen.undo.hpp @@ -95,6 +95,19 @@ public: aPlaceEraseItem(std::string name, bool place, size_t index, cTown::cItem item); }; +/// Action which edits an item in a town +class aEditPlacedItem : public cTerrainAction { + size_t which; + cTown::cItem old_item; + cTown::cItem new_item; + bool undo_me() override; + bool redo_me() override; +public: + aEditPlacedItem(size_t which, cTown::cItem old_item, cTown::cItem new_item) : + cTerrainAction("Edit Placed Item", new_item.loc), + which(which), old_item(old_item), new_item(new_item) {} +}; + /// Action which places or erases creature(s) in a town class aPlaceEraseCreature : public cTerrainAction { bool placed;