undo/redo for replacing custom sheet

This commit is contained in:
2025-06-18 10:46:48 -05:00
parent 403a742375
commit 14014382b3
3 changed files with 72 additions and 4 deletions

View File

@@ -3632,6 +3632,10 @@ extern fs::path tempDir;
extern std::string scenario_temp_dir_name;
void edit_custom_sheets() {
// Creating and deleting graphics sheets happens immediately. Replacing graphics sheets, all actions
// are committed when you hit okay.
std::vector<action_ptr> deferred_actions;
int max_pic = -1;
std::vector<int> all_pics;
fs::path pic_dir = tempDir/scenario_temp_dir_name/"graphics";
@@ -3706,26 +3710,34 @@ void edit_custom_sheets() {
set_clipboard_img(sheets[cur]);
return true;
});
pic_dlg["paste"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog& me, std::string, eKeyMod) -> bool {
pic_dlg["paste"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir,&deferred_actions](cDialog& me, std::string, eKeyMod) -> bool {
auto img = get_clipboard_img();
if(img == nullptr) {
beep();
return true;
}
sf::Image new_image = *img;
if(cur >= spec_scen_g.numSheets) {
std::string resName = "sheet" + std::to_string(all_pics[cur]);
fs::path toPath = pic_dir/(resName + ".png");
sf::Image image_for_undo;
image_for_undo.loadFromFile(toPath.string());
deferred_actions.push_back(action_ptr(new aReplaceGraphicsSheet("Paste Graphics Sheet", all_pics[cur], image_for_undo, new_image)));
img->saveToFile(toPath.string().c_str());
ResMgr::graphics.free(resName);
set_dlg_custom_sheet(me, all_pics[cur]);
return true;
}
deferred_actions.push_back(action_ptr(new aReplaceGraphicsSheet("Paste Graphics Sheet", cur, sheets[cur], new_image)));
sheets[cur] = *img;
spec_scen_g.replace_sheet(cur, *img);
set_dlg_custom_sheet(me, all_pics[cur]);
return true;
});
pic_dlg["open"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog& me, std::string, eKeyMod) -> bool {
pic_dlg["open"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir,&deferred_actions](cDialog& me, std::string, eKeyMod) -> bool {
fs::path fpath = nav_get_rsrc({"png", "bmp", "jpg", "jpeg", "gif", "psd"});
if(fpath.empty()) return true;
sf::Image img;
@@ -3736,11 +3748,18 @@ void edit_custom_sheets() {
if(cur >= spec_scen_g.numSheets) {
std::string resName = "sheet" + std::to_string(all_pics[cur]);
fs::path toPath = pic_dir/(resName + ".png");
sf::Image image_for_undo;
image_for_undo.loadFromFile(toPath.string());
deferred_actions.push_back(action_ptr(new aReplaceGraphicsSheet("Import Graphics Sheet", all_pics[cur], image_for_undo, img)));
img.saveToFile(toPath.string().c_str());
ResMgr::graphics.free(resName);
set_dlg_custom_sheet(me, all_pics[cur]);
return true;
}
deferred_actions.push_back(action_ptr(new aReplaceGraphicsSheet("Import Graphics Sheet", all_pics[cur], sheets[cur], img)));
sheets[cur] = img;
spec_scen_g.replace_sheet(cur, img);
set_dlg_custom_sheet(me, all_pics[cur]);
@@ -3835,7 +3854,10 @@ void edit_custom_sheets() {
all_pics.erase(all_pics.begin() + cur);
}
if(fs::exists(fpath)) fs::remove(fpath);
// We'll update the edit menu after this dialog closes
undo_list.add(action_ptr(new aDeleteGraphicsSheet(which_pic, moved, image_for_undo)));
if(all_pics.size() == 1) {
me["left"].hide();
me["right"].hide();
@@ -3871,8 +3893,14 @@ void edit_custom_sheets() {
shut_down_menus(5); // So that cmd+O, cmd+N, cmd+S can work
pic_dlg.run();
// Commit undo actions for the cancelable operations
if(pic_dlg.accepted()){
for(action_ptr action : deferred_actions){
undo_list.add(action);
}
}
// Now, we need to restore the sheets if they pressed cancel
if(!pic_dlg.accepted()) {
else{
for(auto p : sheetsSave) {
spec_scen_g.replace_sheet(p.first, p.second);
}

View File

@@ -806,4 +806,32 @@ bool aDeleteGraphicsSheet::redo_me() {
if(fs::exists(sheetPath)) fs::remove(sheetPath);
return true;
}
}
bool aReplaceGraphicsSheet::undo_me() {
if(index >= spec_scen_g.numSheets) {
std::string resName = "sheet" + std::to_string(index);
fs::path toPath = get_pic_dir()/(resName + ".png");
old_image.saveToFile(toPath.string().c_str());
ResMgr::graphics.free(resName);
}else{
spec_scen_g.replace_sheet(index, old_image);
}
return true;
}
bool aReplaceGraphicsSheet::redo_me() {
if(index >= spec_scen_g.numSheets) {
std::string resName = "sheet" + std::to_string(index);
fs::path toPath = get_pic_dir()/(resName + ".png");
new_image.saveToFile(toPath.string().c_str());
ResMgr::graphics.free(resName);
}else{
spec_scen_g.replace_sheet(index, new_image);
}
return true;
}

View File

@@ -475,4 +475,16 @@ public:
cAction("Delete Custom Graphics Sheet"), index(index), image(image), move_others(move_others) {}
};
/// Action that changes a custom graphics sheet
class aReplaceGraphicsSheet : public cAction {
size_t index;
sf::Image old_image;
sf::Image new_image;
bool undo_me() override;
bool redo_me() override;
public:
aReplaceGraphicsSheet(std::string name, size_t index, sf::Image old_image, sf::Image new_image) :
cAction(name), index(index), old_image(old_image), new_image(new_image) {}
};
#endif