Make basic placing/erasing items undoable
This commit is contained in:
@@ -712,12 +712,18 @@ static bool handle_rb_action(location the_point, bool option_hit) {
|
||||
stroke_ter_changes_t current_stroke_changes;
|
||||
std::string current_stroke_type;
|
||||
|
||||
item_changes_t current_items_placed;
|
||||
|
||||
void commit_stroke() {
|
||||
if(!current_stroke_changes.empty()){
|
||||
undo_list.add(action_ptr(new aDrawTerrain("Draw Terrain (" + current_stroke_type + ")", current_stroke_changes)));
|
||||
update_edit_menu();
|
||||
current_stroke_changes.clear();
|
||||
current_stroke_type = "";
|
||||
}else if(!current_items_placed.empty()){
|
||||
undo_list.add(action_ptr(new aPlaceEraseItem(current_items_placed.size() > 1 ? "Place Items" : "Place Item", true, current_items_placed)));
|
||||
update_edit_menu();
|
||||
current_items_placed.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,16 +902,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
|
||||
// If we just placed this item there, forget it
|
||||
if(!mouse_button_held || last_placement != spot_hit) {
|
||||
mouse_button_held = true;
|
||||
auto iter = std::find_if(town->preset_items.begin(), town->preset_items.end(), [](const cTown::cItem& item) {
|
||||
return item.code < 0;
|
||||
});
|
||||
if(iter != town->preset_items.end()) {
|
||||
*iter = {spot_hit, mode_count, scenario.scen_items[mode_count]};
|
||||
if(container_there(spot_hit)) iter->contained = true;
|
||||
} else {
|
||||
town->preset_items.push_back({spot_hit, mode_count, scenario.scen_items[mode_count]});
|
||||
if(container_there(spot_hit)) town->preset_items.back().contained = true;
|
||||
}
|
||||
place_item(spot_hit, mode_count, false, false, 100, current_items_placed);
|
||||
last_placement = spot_hit;
|
||||
}
|
||||
break;
|
||||
@@ -1154,11 +1151,12 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
|
||||
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)) {
|
||||
|
||||
undo_list.add(action_ptr(new aPlaceEraseItem("Erase Item", false, x, town->preset_items[x])));
|
||||
update_edit_menu();
|
||||
town->preset_items[x].code = -1;
|
||||
break;
|
||||
}
|
||||
while(!town->preset_items.empty() && town->preset_items.back().code == -1)
|
||||
town->preset_items.pop_back();
|
||||
overall_mode = MODE_DRAWING;
|
||||
break;
|
||||
case MODE_SET_TOWN_START:
|
||||
@@ -2444,7 +2442,7 @@ void adjust_space(location l, stroke_ter_changes_t& stroke_changes) {
|
||||
}
|
||||
}
|
||||
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds) {
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds,std::map<size_t,cTown::cItem>& items_placed) {
|
||||
// odds 0 - 100, with 100 always
|
||||
if((which_item < 0) || (which_item >= scenario.scen_items.size()))
|
||||
return true;
|
||||
@@ -2462,6 +2460,8 @@ bool place_item(location spot_hit,short which_item,bool property,bool always,sho
|
||||
town->preset_items[x].contained = container_there(spot_hit);
|
||||
town->preset_items[x].property = property;
|
||||
town->preset_items[x].always_there = always;
|
||||
items_placed[x] = town->preset_items[x];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2471,6 +2471,7 @@ bool place_item(location spot_hit,short which_item,bool property,bool always,sho
|
||||
|
||||
void place_items_in_town() {
|
||||
location l;
|
||||
std::map<size_t, cTown::cItem> items_placed;
|
||||
for(short i = 0; i < town->max_dim; i++)
|
||||
for(short j = 0; j < town->max_dim; j++) {
|
||||
l.x = i;
|
||||
@@ -2481,7 +2482,7 @@ void place_items_in_town() {
|
||||
for(short x = 0; x < 10; x++)
|
||||
place_item(l,scenario.storage_shortcuts[k].item_num[x],
|
||||
scenario.storage_shortcuts[k].property,false,
|
||||
scenario.storage_shortcuts[k].item_odds[x]);
|
||||
scenario.storage_shortcuts[k].item_odds[x],items_placed);
|
||||
}
|
||||
}
|
||||
draw_terrain();
|
||||
|
@@ -28,7 +28,7 @@ void adjust_space(location l,stroke_ter_changes_t& stroke_changes);
|
||||
void commit_stroke();
|
||||
bool is_lava(short x,short y);
|
||||
ter_num_t coord_to_ter(short x,short y);
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds);
|
||||
bool place_item(location spot_hit,short which_item,bool property,bool always,short odds,std::map<size_t,cTown::cItem>& items_placed);
|
||||
void place_items_in_town();
|
||||
void set_up_start_screen();
|
||||
void set_up_main_screen();
|
||||
|
@@ -16,17 +16,17 @@ extern void start_out_edit();
|
||||
extern void redraw_screen();
|
||||
extern void set_current_town(int,bool first_restore = false);
|
||||
|
||||
cTerrainAction::cTerrainAction(std::string name, short town_num, location where) : cAction(name) {
|
||||
cTerrainAction::cTerrainAction(std::string name, short town_num, location where, bool reversed) : cAction(name, reversed) {
|
||||
area.is_town = true;
|
||||
area.town_num = town_num;
|
||||
area.where = where;
|
||||
}
|
||||
cTerrainAction::cTerrainAction(std::string name, location out_sec, location where) : cAction(name) {
|
||||
cTerrainAction::cTerrainAction(std::string name, location out_sec, location where, bool reversed) : cAction(name, reversed) {
|
||||
area.is_town = false;
|
||||
area.out_sec = out_sec;
|
||||
area.where = where;
|
||||
}
|
||||
cTerrainAction::cTerrainAction(std::string name, location where) : cAction(name) {
|
||||
cTerrainAction::cTerrainAction(std::string name, location where, bool reversed) : cAction(name, reversed) {
|
||||
area.is_town = editing_town;
|
||||
// One of these two will be ignored
|
||||
area.town_num = cur_town;
|
||||
@@ -108,3 +108,29 @@ bool aDrawTerrain::redo_me() {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
aPlaceEraseItem::aPlaceEraseItem(std::string name, bool place, size_t index, cTown::cItem item)
|
||||
: cTerrainAction(name, item.loc, !place)
|
||||
, items({{index, item}})
|
||||
{}
|
||||
|
||||
aPlaceEraseItem::aPlaceEraseItem(std::string name, bool place, item_changes_t items)
|
||||
: cTerrainAction(name, items.begin()->second.loc, !place)
|
||||
, items(items)
|
||||
{}
|
||||
|
||||
bool aPlaceEraseItem::undo_me() {
|
||||
auto& town_items = scenario.towns[cur_town]->preset_items;
|
||||
for(auto change : items){
|
||||
town_items[change.first].code = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aPlaceEraseItem::redo_me() {
|
||||
auto& town_items = scenario.towns[cur_town]->preset_items;
|
||||
for(auto change : items){
|
||||
town_items[change.first] = change.second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "location.hpp"
|
||||
#include "tools/undo.hpp"
|
||||
#include "scenario/town.hpp"
|
||||
|
||||
struct area_ref_t {
|
||||
bool is_town;
|
||||
@@ -18,13 +19,14 @@ struct ter_change_t {
|
||||
};
|
||||
|
||||
typedef std::map<location,ter_change_t,loc_compare> stroke_ter_changes_t;
|
||||
typedef std::map<size_t, cTown::cItem> item_changes_t;
|
||||
|
||||
// Action that modified something in 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);
|
||||
cTerrainAction(std::string name, short town_num, location where, bool reversed = false);
|
||||
cTerrainAction(std::string name, location out_sec, location where, bool reversed = false);
|
||||
cTerrainAction(std::string name, location where, bool reversed = false);
|
||||
void undo();
|
||||
void redo();
|
||||
bool undo_me() = 0;
|
||||
@@ -58,6 +60,17 @@ private:
|
||||
const stroke_ter_changes_t changes;
|
||||
};
|
||||
|
||||
/// Action which places or erases item(s) in a town
|
||||
class aPlaceEraseItem : public cTerrainAction {
|
||||
bool placed;
|
||||
item_changes_t items;
|
||||
bool undo_me() override;
|
||||
bool redo_me() override;
|
||||
public:
|
||||
aPlaceEraseItem(std::string name, bool place, item_changes_t items);
|
||||
aPlaceEraseItem(std::string name, bool place, size_t index, cTown::cItem item);
|
||||
};
|
||||
|
||||
/// Action which adds a new town to the end of the list, or deletes the last one
|
||||
class aCreateDeleteTown : public cAction {
|
||||
bool created;
|
||||
|
Reference in New Issue
Block a user