scenedit undo/redo infrastructure

This commit is contained in:
2025-05-31 12:01:08 -05:00
parent 79cd86f7dc
commit b6fb93f199
8 changed files with 163 additions and 32 deletions

View File

@@ -12,6 +12,7 @@ scened_sources = Split("""
scen.main.cpp
scen.sdfpicker.cpp
scen.townout.cpp
scen.undo.cpp
../view_dialogs.cpp
../fileio/fileio_party.cpp
../damage.cpp

View File

@@ -20,6 +20,7 @@
#include "scen.keydlgs.hpp"
#include "scen.townout.hpp"
#include "scen.menus.hpp"
#include "scen.undo.hpp"
#include "mathutil.hpp"
#include "fileio/fileio.hpp"
#include "tools/keymods.hpp"
@@ -710,6 +711,7 @@ static bool handle_rb_action(location the_point, bool option_hit) {
static bool handle_terrain_action(location the_point, bool ctrl_hit) {
cArea* cur_area = get_current_area();
std::shared_ptr<cAction> undo_action = nullptr;
if(mouse_spot.x >= 0 && mouse_spot.y >= 0) {
if(cur_viewing_mode == 0) {
spot_hit.x = cen_x + mouse_spot.x - 4;
@@ -1090,6 +1092,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
auto& specials = cur_area->special_locs;
for(short x = 0; x < specials.size(); x++)
if(specials[x] == spot_hit && specials[x].spec >= 0) {
spec_loc_t for_redo = specials[x];
specials[x] = {-1,-1};
specials[x].spec = -1;
if(x == specials.size() - 1) {
@@ -1098,6 +1101,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
specials.pop_back();
} while(!specials.empty() && specials.back().spec < 0);
}
undo_action.reset(new aEraseSpecial(for_redo));
break;
}
overall_mode = MODE_DRAWING;
@@ -1204,6 +1208,11 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
if((overall_mode == MODE_DRAWING) && (old_mode != MODE_DRAWING))
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name);
draw_terrain();
if(undo_action != nullptr){
undo_list.add(undo_action);
update_edit_menu();
}
return true;
}
bool need_redraw = false;

View File

@@ -48,13 +48,3 @@ bool monst_on_space(location loc,short m_num);
void place_edit_special(location loc);
void set_special(location spot_hit);
bool save_check(std::string which_dlog, bool allow_no = true);
/// Represents the action of adding a new town to the end of the list
class aNewTown : public cAction {
class cTown* theTown;
bool undo_me() override;
bool redo_me() override;
public:
aNewTown(class cTown* t);
~aNewTown();
};

View File

@@ -17,6 +17,7 @@
#include "scen.sdfpicker.hpp"
#include "scen.fileio.hpp"
#include "scen.core.hpp"
#include "scen.undo.hpp"
#include "mathutil.hpp"
#include "dialogxml/widgets/button.hpp"
#include "dialogxml/widgets/field.hpp"
@@ -1642,27 +1643,6 @@ void set_current_out(location out_sec, bool continuous_shift, bool first_restore
set_up_main_screen();
}
aNewTown::aNewTown(cTown* t)
: cAction("add town")
, theTown(t)
{}
bool aNewTown::undo_me() {
scenario.towns.resize(scenario.towns.size() - 1);
set_current_town(scenario.towns.size() - 1);
return true;
}
bool aNewTown::redo_me() {
scenario.towns.push_back(theTown);
set_current_town(scenario.towns.size() - 1);
return true;
}
aNewTown::~aNewTown() {
if(!isDone()) delete theTown;
}
bool new_town() {
ter_num_t preset = 0;
cChoiceDlog new_dlg("new-town", {"okay", "cancel"});

View File

@@ -0,0 +1,93 @@
#include "scen.undo.hpp"
#include "scenario/scenario.hpp"
#include "scenario/area.hpp"
extern bool editing_town;
extern short cur_town;
extern short cur_town;
extern location cur_out;
extern short cen_x;
extern short cen_y;
extern cScenario scenario;
extern cArea* get_current_area();
extern void start_town_edit();
extern void start_out_edit();
extern void redraw_screen();
cTerrainAction::cTerrainAction(std::string name, short town_num, location where) : cAction(name) {
area.is_town = true;
area.town_num = town_num;
area.where = where;
}
cTerrainAction::cTerrainAction(std::string name, location out_sec, location where) : cAction(name) {
area.is_town = false;
area.out_sec = out_sec;
area.where = where;
}
cTerrainAction::cTerrainAction(std::string name, location where) : cAction(name) {
area.is_town = editing_town;
// One of these two will be ignored
area.town_num = cur_town;
area.out_sec = cur_out;
area.where = where;
}
void cTerrainAction::showChangeSite() {
if(area.is_town){
cur_town = area.town_num;
}else{
cur_out = area.out_sec;
}
editing_town = area.is_town;
// TODO this isn't working and I don't know why:
cen_x = area.where.x;
cen_y = area.where.y;
redraw_screen();
}
void cTerrainAction::undo() {
showChangeSite();
cAction::undo();
}
void cTerrainAction::redo() {
showChangeSite();
cAction::redo();
}
// Undo/Redo implementations for actions:
bool aEraseSpecial::undo_me() {
cArea* cur_area = get_current_area();
auto& specials = cur_area->special_locs;
specials.push_back(for_redo);
return true;
}
bool aEraseSpecial::redo_me() {
cArea* cur_area = get_current_area();
auto& specials = cur_area->special_locs;
specials.pop_back();
return true;
}
aNewTown::aNewTown(cTown* t)
: cAction("Add Town")
, theTown(t)
{}
bool aNewTown::undo_me() {
scenario.towns.resize(scenario.towns.size() - 1);
cur_town = min(cur_town, scenario.towns.size() - 1);
return true;
}
bool aNewTown::redo_me() {
scenario.towns.push_back(theTown);
return true;
}
aNewTown::~aNewTown() {
if(!isDone()) delete theTown;
}

View File

@@ -0,0 +1,51 @@
#ifndef BoE_scen_undo_h
#define BoE_scen_undo_h
#include "location.hpp"
#include "tools/undo.hpp"
struct area_ref_t {
bool is_town;
// Can't just make the next two a union for compiler reasons.
short town_num;
location out_sec;
location where;
};
// Action that modified town or outdoor terrain, so we should show the modified area when undoing or redoing
class cTerrainAction : public cAction {
public:
cTerrainAction(std::string name, short town_num, location where);
cTerrainAction(std::string name, location out_sec, location where);
cTerrainAction(std::string name, location where);
void undo();
void redo();
bool undo_me() = 0;
bool redo_me() = 0;
private:
/// Show where the change happened
void showChangeSite();
area_ref_t area;
};
/// Represents the action of adding a new town to the end of the list
class aNewTown : public cAction {
class cTown* theTown;
bool undo_me() override;
bool redo_me() override;
public:
aNewTown(class cTown* t);
~aNewTown();
};
class aEraseSpecial : public cTerrainAction {
public:
aEraseSpecial(spec_loc_t special) : cTerrainAction("Erase Special Encounter", special), for_redo(special) {}
bool undo_me() override;
bool redo_me() override;
private:
spec_loc_t for_redo;
bool editing_town;
};
#endif