undo/redo for editing intro text/picture

This commit is contained in:
2025-06-19 10:22:11 -05:00
parent f7d145db70
commit e04e261afa
5 changed files with 72 additions and 15 deletions

View File

@@ -184,16 +184,16 @@ std::ostream& operator<< (std::ostream& out, eContentRating rating);
// Store a version the scenario details for undo history.
// This could be made a struct that cScenario contains, and that would eliminate the next 2 functions, but it would
// require changing every reference to these detail values in the game code, making them more verbose. I don't know
// require changing every reference to these detail values in the game and fileio code, making them more verbose. I don't know
// if that's worth it.
struct scenario_details_t {
struct scen_details_t {
unsigned short difficulty;
eContentRating rating;
std::string scen_name;
unsigned char ver[3];
std::string teaser_text[2];
std::string contact_info[2];
bool operator==(const scenario_details_t& other) const {
bool operator==(const scen_details_t& other) const {
CHECK_EQ(other, difficulty);
CHECK_EQ(other, rating);
CHECK_EQ(other, scen_name);
@@ -205,10 +205,10 @@ struct scenario_details_t {
if(this->contact_info[i] != other.contact_info[i]) return false;
return true;
}
bool operator!=(const scenario_details_t& other) const { return !(*this == other); }
bool operator!=(const scen_details_t& other) const { return !(*this == other); }
};
inline scenario_details_t details_from_scen(cScenario& scen) {
inline scen_details_t details_from_scen(cScenario& scen) {
return {
scen.difficulty,
scen.rating,
@@ -219,7 +219,7 @@ inline scenario_details_t details_from_scen(cScenario& scen) {
};
}
inline void scen_set_details(cScenario& scen, scenario_details_t details) {
inline void scen_set_details(cScenario& scen, scen_details_t details) {
scen.difficulty = details.difficulty;
scen.rating = details.rating;
scen.scen_name = details.scen_name;
@@ -231,4 +231,30 @@ inline void scen_set_details(cScenario& scen, scenario_details_t details) {
scen.contact_info[i] = details.contact_info[i];
}
// Store a version the scenario intro text/icon# for undo history.
// This could be made a struct that cScenario contains, and that would eliminate the next 2 functions, but it would
// require changing every reference to these detail values in the game and fileio code, making them more verbose. I don't know
// if that's worth it.
struct scen_intro_t {
unsigned short intro_pic;
std::array<std::string, 6> intro_strs;
bool operator==(const scen_intro_t& other) const {
CHECK_EQ(other, intro_pic);
for(int i = 0; i < intro_strs.size(); ++i){
if(intro_strs[i] != other.intro_strs[i]) return false;
}
return true;
}
bool operator!=(const scen_intro_t& other) const { return !(*this == other); }
};
inline scen_intro_t intro_from_scen(cScenario& scen) {
return { scen.intro_pic, scen.intro_strs };
}
inline void scen_set_intro(cScenario& scen, scen_intro_t details) {
scen.intro_pic = details.intro_pic;
scen.intro_strs = details.intro_strs;
}
#endif

View File

@@ -3061,8 +3061,8 @@ void edit_item_placement() {
static bool save_scen_details(cDialog& me, std::string, eKeyMod) {
if(!me.toast(true)) return true;
scenario_details_t old_details = details_from_scen(scenario);
scenario_details_t new_details;
scen_details_t old_details = details_from_scen(scenario);
scen_details_t new_details;
{
cLedGroup& difficulty = dynamic_cast<cLedGroup&>(me["difficulty"]);

View File

@@ -38,6 +38,8 @@ extern ter_num_t template_terrain[64][64];
extern cScenario scenario;
extern cOutdoors* current_terrain;
extern cCustomGraphics spec_scen_g;
extern cUndoList undo_list;
extern void update_edit_menu();
std::vector<pic_num_t> field_pics = {0,3,5,6,7,8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31,4};
std::vector<pic_num_t> static_boom_pics = {0,1,2,3,4,5};
@@ -1691,14 +1693,23 @@ short edit_special_num(short mode,short what_start) {
static bool edit_scen_intro_event_filter(cDialog& me, std::string item_hit, eKeyMod) {
if(item_hit == "okay") {
scenario.intro_pic = me["picnum"].getTextAsNum();
if(scenario.intro_pic > 29) {
scen_intro_t old_intro = intro_from_scen(scenario);
scen_intro_t new_intro;
new_intro.intro_pic = me["picnum"].getTextAsNum();
if(new_intro.intro_pic > 29) {
showError("Intro picture number is out of range.","",&me);
return true;
}
for(short i = 0; i < scenario.intro_strs.size(); i++) {
for(short i = 0; i < new_intro.intro_strs.size(); i++) {
std::string id = "str" + std::to_string(i + 1);
scenario.intro_strs[i] = me[id].getText();
new_intro.intro_strs[i] = me[id].getText();
}
if(new_intro != old_intro){
scen_set_intro(scenario, new_intro);
undo_list.add(action_ptr(new aEditIntro(old_intro, new_intro)));
update_edit_menu();
}
me.toast(true);
} else if(item_hit == "cancel") {

View File

@@ -868,4 +868,14 @@ bool aEditScenarioDetails::undo_me() {
bool aEditScenarioDetails::redo_me() {
scen_set_details(scenario, new_details);
return true;
}
bool aEditIntro::undo_me() {
scen_set_intro(scenario, old_intro);
return true;
}
bool aEditIntro::redo_me() {
scen_set_intro(scenario, new_intro);
return true;
}

View File

@@ -513,13 +513,23 @@ public:
};
class aEditScenarioDetails : public cAction {
scenario_details_t old_details;
scenario_details_t new_details;
scen_details_t old_details;
scen_details_t new_details;
bool undo_me() override;
bool redo_me() override;
public:
aEditScenarioDetails(scenario_details_t old_details, scenario_details_t new_details) :
aEditScenarioDetails(scen_details_t old_details, scen_details_t new_details) :
cAction("Edit Scenario Details"), old_details(old_details), new_details(new_details) {}
};
class aEditIntro : public cAction {
scen_intro_t old_intro;
scen_intro_t new_intro;
bool undo_me() override;
bool redo_me() override;
public:
aEditIntro(scen_intro_t old_intro, scen_intro_t new_intro) :
cAction("Edit Scenario Intro/Picture"), old_intro(old_intro), new_intro(new_intro) {}
};
#endif