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;
|
stroke_ter_changes_t current_stroke_changes;
|
||||||
std::string current_stroke_type;
|
std::string current_stroke_type;
|
||||||
|
|
||||||
|
item_changes_t current_items_placed;
|
||||||
|
|
||||||
void commit_stroke() {
|
void commit_stroke() {
|
||||||
if(!current_stroke_changes.empty()){
|
if(!current_stroke_changes.empty()){
|
||||||
undo_list.add(action_ptr(new aDrawTerrain("Draw Terrain (" + current_stroke_type + ")", current_stroke_changes)));
|
undo_list.add(action_ptr(new aDrawTerrain("Draw Terrain (" + current_stroke_type + ")", current_stroke_changes)));
|
||||||
update_edit_menu();
|
update_edit_menu();
|
||||||
current_stroke_changes.clear();
|
current_stroke_changes.clear();
|
||||||
current_stroke_type = "";
|
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 we just placed this item there, forget it
|
||||||
if(!mouse_button_held || last_placement != spot_hit) {
|
if(!mouse_button_held || last_placement != spot_hit) {
|
||||||
mouse_button_held = true;
|
mouse_button_held = true;
|
||||||
auto iter = std::find_if(town->preset_items.begin(), town->preset_items.end(), [](const cTown::cItem& item) {
|
place_item(spot_hit, mode_count, false, false, 100, current_items_placed);
|
||||||
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;
|
|
||||||
}
|
|
||||||
last_placement = spot_hit;
|
last_placement = spot_hit;
|
||||||
}
|
}
|
||||||
break;
|
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++)
|
for(short x = 0; x < town->preset_items.size(); x++)
|
||||||
if((spot_hit.x == town->preset_items[x].loc.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)) {
|
(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;
|
town->preset_items[x].code = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while(!town->preset_items.empty() && town->preset_items.back().code == -1)
|
|
||||||
town->preset_items.pop_back();
|
|
||||||
overall_mode = MODE_DRAWING;
|
overall_mode = MODE_DRAWING;
|
||||||
break;
|
break;
|
||||||
case MODE_SET_TOWN_START:
|
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
|
// odds 0 - 100, with 100 always
|
||||||
if((which_item < 0) || (which_item >= scenario.scen_items.size()))
|
if((which_item < 0) || (which_item >= scenario.scen_items.size()))
|
||||||
return true;
|
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].contained = container_there(spot_hit);
|
||||||
town->preset_items[x].property = property;
|
town->preset_items[x].property = property;
|
||||||
town->preset_items[x].always_there = always;
|
town->preset_items[x].always_there = always;
|
||||||
|
items_placed[x] = town->preset_items[x];
|
||||||
|
|
||||||
return true;
|
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() {
|
void place_items_in_town() {
|
||||||
location l;
|
location l;
|
||||||
|
std::map<size_t, cTown::cItem> items_placed;
|
||||||
for(short i = 0; i < town->max_dim; i++)
|
for(short i = 0; i < town->max_dim; i++)
|
||||||
for(short j = 0; j < town->max_dim; j++) {
|
for(short j = 0; j < town->max_dim; j++) {
|
||||||
l.x = i;
|
l.x = i;
|
||||||
@@ -2481,7 +2482,7 @@ void place_items_in_town() {
|
|||||||
for(short x = 0; x < 10; x++)
|
for(short x = 0; x < 10; x++)
|
||||||
place_item(l,scenario.storage_shortcuts[k].item_num[x],
|
place_item(l,scenario.storage_shortcuts[k].item_num[x],
|
||||||
scenario.storage_shortcuts[k].property,false,
|
scenario.storage_shortcuts[k].property,false,
|
||||||
scenario.storage_shortcuts[k].item_odds[x]);
|
scenario.storage_shortcuts[k].item_odds[x],items_placed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
draw_terrain();
|
draw_terrain();
|
||||||
|
@@ -28,7 +28,7 @@ void adjust_space(location l,stroke_ter_changes_t& stroke_changes);
|
|||||||
void commit_stroke();
|
void commit_stroke();
|
||||||
bool is_lava(short x,short y);
|
bool is_lava(short x,short y);
|
||||||
ter_num_t coord_to_ter(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 place_items_in_town();
|
||||||
void set_up_start_screen();
|
void set_up_start_screen();
|
||||||
void set_up_main_screen();
|
void set_up_main_screen();
|
||||||
|
@@ -16,17 +16,17 @@ extern void start_out_edit();
|
|||||||
extern void redraw_screen();
|
extern void redraw_screen();
|
||||||
extern void set_current_town(int,bool first_restore = false);
|
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.is_town = true;
|
||||||
area.town_num = town_num;
|
area.town_num = town_num;
|
||||||
area.where = where;
|
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.is_town = false;
|
||||||
area.out_sec = out_sec;
|
area.out_sec = out_sec;
|
||||||
area.where = where;
|
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;
|
area.is_town = editing_town;
|
||||||
// One of these two will be ignored
|
// One of these two will be ignored
|
||||||
area.town_num = cur_town;
|
area.town_num = cur_town;
|
||||||
@@ -108,3 +108,29 @@ bool aDrawTerrain::redo_me() {
|
|||||||
}
|
}
|
||||||
return true;
|
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 "location.hpp"
|
||||||
#include "tools/undo.hpp"
|
#include "tools/undo.hpp"
|
||||||
|
#include "scenario/town.hpp"
|
||||||
|
|
||||||
struct area_ref_t {
|
struct area_ref_t {
|
||||||
bool is_town;
|
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<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
|
// Action that modified something in town or outdoor terrain, so we should show the modified area when undoing or redoing
|
||||||
class cTerrainAction : public cAction {
|
class cTerrainAction : public cAction {
|
||||||
public:
|
public:
|
||||||
cTerrainAction(std::string name, short town_num, location where);
|
cTerrainAction(std::string name, short town_num, location where, bool reversed = false);
|
||||||
cTerrainAction(std::string name, location out_sec, location where);
|
cTerrainAction(std::string name, location out_sec, location where, bool reversed = false);
|
||||||
cTerrainAction(std::string name, location where);
|
cTerrainAction(std::string name, location where, bool reversed = false);
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
bool undo_me() = 0;
|
bool undo_me() = 0;
|
||||||
@@ -58,6 +60,17 @@ private:
|
|||||||
const stroke_ter_changes_t changes;
|
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
|
/// Action which adds a new town to the end of the list, or deletes the last one
|
||||||
class aCreateDeleteTown : public cAction {
|
class aCreateDeleteTown : public cAction {
|
||||||
bool created;
|
bool created;
|
||||||
|
Reference in New Issue
Block a user