diff --git a/src/scenario/scenario.hpp b/src/scenario/scenario.hpp index 5b008cc0..931be387 100644 --- a/src/scenario/scenario.hpp +++ b/src/scenario/scenario.hpp @@ -182,4 +182,53 @@ public: std::istream& operator>> (std::istream& in, eContentRating& rating); 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 +// if that's worth it. +struct scenario_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 { + CHECK_EQ(other, difficulty); + CHECK_EQ(other, rating); + CHECK_EQ(other, scen_name); + for(short i = 0; i < 3; i++) + if(this->ver[i] != other.ver[i]) return false; + for(short i = 0; i < 2; i++) + if(this->teaser_text[i] != other.teaser_text[i]) return false; + for(short i = 0; i < 2; i++) + if(this->contact_info[i] != other.contact_info[i]) return false; + return true; + } + bool operator!=(const scenario_details_t& other) const { return !(*this == other); } +}; + +inline scenario_details_t details_from_scen(cScenario& scen) { + return { + scen.difficulty, + scen.rating, + scen.scen_name, + scen.format.ver[0],scen.format.ver[1],scen.format.ver[2], + scen.teaser_text[0],scen.teaser_text[1], + scen.contact_info[0],scen.contact_info[1], + }; +} + +inline void scen_set_details(cScenario& scen, scenario_details_t details) { + scen.difficulty = details.difficulty; + scen.rating = details.rating; + scen.scen_name = details.scen_name; + for(short i = 0; i < 3; i++) + scen.format.ver[i] = details.ver[i]; + for(short i = 0; i < 2; i++) + scen.teaser_text[i] = details.teaser_text[i]; + for(short i = 0; i < 2; i++) + scen.contact_info[i] = details.contact_info[i]; +} + #endif diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp index 7d0bcaae..6ee52fc9 100644 --- a/src/scenedit/scen.core.cpp +++ b/src/scenedit/scen.core.cpp @@ -3061,25 +3061,35 @@ 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; + { cLedGroup& difficulty = dynamic_cast(me["difficulty"]); - scenario.difficulty = difficulty.getSelected()[3] - '1'; + new_details.difficulty = difficulty.getSelected()[3] - '1'; }{ cLedGroup& rating = dynamic_cast(me["rating"]); switch(rating.getSelected()[4]) { - case '1': scenario.rating = eContentRating::G; break; - case '2': scenario.rating = eContentRating::PG; break; - case '3': scenario.rating = eContentRating::R; break; - case '4': scenario.rating = eContentRating::NC17; break; + case '1': new_details.rating = eContentRating::G; break; + case '2': new_details.rating = eContentRating::PG; break; + case '3': new_details.rating = eContentRating::R; break; + case '4': new_details.rating = eContentRating::NC17; break; } } - scenario.scen_name = me["title"].getText(); + new_details.scen_name = me["title"].getText(); for(short i = 0; i < 3; i++) - scenario.format.ver[i] = me["ver" + std::to_string(i + 1)].getTextAsNum(); - scenario.teaser_text[0] = me["teaser1"].getText(); - scenario.teaser_text[1] = me["teaser2"].getText(); - scenario.contact_info[0] = me["author"].getText(); - scenario.contact_info[1] = me["contact"].getText(); + new_details.ver[i] = me["ver" + std::to_string(i + 1)].getTextAsNum(); + new_details.teaser_text[0] = me["teaser1"].getText(); + new_details.teaser_text[1] = me["teaser2"].getText(); + new_details.contact_info[0] = me["author"].getText(); + new_details.contact_info[1] = me["contact"].getText(); + + if(new_details != old_details){ + scen_set_details(scenario, new_details); + undo_list.add(action_ptr(new aEditScenarioDetails(old_details, new_details))); + update_edit_menu(); + } + return true; } diff --git a/src/scenedit/scen.undo.cpp b/src/scenedit/scen.undo.cpp index 19589996..6969acb6 100644 --- a/src/scenedit/scen.undo.cpp +++ b/src/scenedit/scen.undo.cpp @@ -858,4 +858,14 @@ bool aReplaceSound::undo_me() { bool aReplaceSound::redo_me() { ResMgr::sounds.free(sound_to_fname(index)); return new_sound.saveToFile(get_snd_path(index).string()); +} + +bool aEditScenarioDetails::undo_me() { + scen_set_details(scenario, old_details); + return true; +} + +bool aEditScenarioDetails::redo_me() { + scen_set_details(scenario, new_details); + return true; } \ No newline at end of file diff --git a/src/scenedit/scen.undo.hpp b/src/scenedit/scen.undo.hpp index 26028980..e01fac16 100644 --- a/src/scenedit/scen.undo.hpp +++ b/src/scenedit/scen.undo.hpp @@ -512,4 +512,14 @@ public: index(index), old_sound(old_sound), new_sound(new_sound) {} }; +class aEditScenarioDetails : public cAction { + scenario_details_t old_details; + scenario_details_t new_details; + bool undo_me() override; + bool redo_me() override; +public: + aEditScenarioDetails(scenario_details_t old_details, scenario_details_t new_details) : + cAction("Edit Scenario Details"), old_details(old_details), new_details(new_details) {} +}; + #endif \ No newline at end of file