editor2: followup to 2008-08-20T21:14:42Z!kailoran@gmail.com:
...fix issues with click-drag undo in paint and select operations (separate fixes). Get rid of editor_action_select_xor. Some doc comments that got caught in the way.
This commit is contained in:
parent
4eae029023
commit
3335b9c4a3
6 changed files with 107 additions and 50 deletions
|
@ -96,6 +96,7 @@ void editor_action_area::extend(const editor_map& map, const std::set<gamemap::l
|
|||
|
||||
void editor_action_paste::extend(const editor_map& map, const std::set<gamemap::location>& locs)
|
||||
{
|
||||
LOG_ED << "Area extend\n";
|
||||
paste_.add_tiles(map, locs);
|
||||
}
|
||||
editor_action_paste* editor_action_paste::perform(map_context& mc) const
|
||||
|
@ -184,24 +185,17 @@ void editor_action_starting_position::perform_without_undo(map_context& mc) cons
|
|||
mc.set_needs_labels_reset();
|
||||
}
|
||||
|
||||
editor_action_select_xor* editor_action_select_xor::perform(map_context& mc) const
|
||||
void editor_action_select::extend(const editor_map& map, const std::set<gamemap::location>& locs)
|
||||
{
|
||||
perform_without_undo(mc);
|
||||
return new editor_action_select_xor(area_);
|
||||
}
|
||||
void editor_action_select_xor::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
foreach (const gamemap::location& loc, area_) {
|
||||
if (mc.get_map().in_selection(loc)) {
|
||||
mc.get_map().remove_from_selection(loc);
|
||||
} else {
|
||||
mc.get_map().add_to_selection(loc);
|
||||
foreach (const gamemap::location& loc, locs) {
|
||||
LOG_ED << "Checking " << loc << "\n";
|
||||
if (map.in_selection(loc)) {
|
||||
LOG_ED << "Extending by " << loc << "\n";
|
||||
area_.insert(loc);
|
||||
}
|
||||
mc.add_changed_location(loc);
|
||||
}
|
||||
}
|
||||
|
||||
editor_action_select_xor* editor_action_select::perform(map_context& mc) const
|
||||
editor_action* editor_action_select::perform(map_context& mc) const
|
||||
{
|
||||
std::set<gamemap::location> undo_locs;
|
||||
foreach (const gamemap::location& loc, area_) {
|
||||
|
@ -211,7 +205,7 @@ editor_action_select_xor* editor_action_select::perform(map_context& mc) const
|
|||
}
|
||||
}
|
||||
perform_without_undo(mc);
|
||||
return new editor_action_select_xor(undo_locs);
|
||||
return new editor_action_deselect(undo_locs);
|
||||
}
|
||||
void editor_action_select::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
|
@ -221,7 +215,17 @@ void editor_action_select::perform_without_undo(map_context& mc) const
|
|||
}
|
||||
}
|
||||
|
||||
editor_action_select_xor* editor_action_deselect::perform(map_context& mc) const
|
||||
void editor_action_deselect::extend(const editor_map& map, const std::set<gamemap::location>& locs)
|
||||
{
|
||||
foreach (const gamemap::location& loc, locs) {
|
||||
LOG_ED << "Checking " << loc << "\n";
|
||||
if (!map.in_selection(loc)) {
|
||||
LOG_ED << "Extending by " << loc << "\n";
|
||||
area_.insert(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
editor_action* editor_action_deselect::perform(map_context& mc) const
|
||||
{
|
||||
std::set<gamemap::location> undo_locs;
|
||||
foreach (const gamemap::location& loc, area_) {
|
||||
|
@ -231,7 +235,7 @@ editor_action_select_xor* editor_action_deselect::perform(map_context& mc) const
|
|||
}
|
||||
}
|
||||
perform_without_undo(mc);
|
||||
return new editor_action_select_xor(undo_locs);
|
||||
return new editor_action_select(undo_locs);
|
||||
}
|
||||
void editor_action_deselect::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
|
@ -241,7 +245,7 @@ void editor_action_deselect::perform_without_undo(map_context& mc) const
|
|||
}
|
||||
}
|
||||
|
||||
editor_action_select_xor* editor_action_select_all::perform(map_context& mc) const
|
||||
editor_action_deselect* editor_action_select_all::perform(map_context& mc) const
|
||||
{
|
||||
|
||||
std::set<gamemap::location> current = mc.get_map().selection();
|
||||
|
@ -252,7 +256,7 @@ editor_action_select_xor* editor_action_select_all::perform(map_context& mc) con
|
|||
current.begin(), current.end(),
|
||||
std::inserter(undo_locs, undo_locs.begin()));
|
||||
mc.set_everything_changed();
|
||||
return new editor_action_select_xor(undo_locs);
|
||||
return new editor_action_deselect(undo_locs);
|
||||
}
|
||||
void editor_action_select_all::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
|
@ -260,13 +264,13 @@ void editor_action_select_all::perform_without_undo(map_context& mc) const
|
|||
mc.set_everything_changed();
|
||||
}
|
||||
|
||||
editor_action_select_xor* editor_action_select_none::perform(map_context& mc) const
|
||||
editor_action_select* editor_action_select_none::perform(map_context& mc) const
|
||||
{
|
||||
|
||||
std::set<gamemap::location> current = mc.get_map().selection();
|
||||
mc.get_map().clear_selection();
|
||||
mc.set_everything_changed();
|
||||
return new editor_action_select_xor(current);
|
||||
return new editor_action_select(current);
|
||||
}
|
||||
void editor_action_select_none::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
|
|
|
@ -44,12 +44,24 @@ class editor_action_whole_map : public editor_action
|
|||
editor_map m_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for actions that:
|
||||
* 1) operate on an area
|
||||
* 2) can be used as undo for a click-drag operation
|
||||
* 3) can be extended so one undo action undos several actual drag actions
|
||||
*/
|
||||
class editor_action_extendable : public editor_action
|
||||
{
|
||||
public:
|
||||
editor_action_extendable()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* The crux of the extendable contract. This member function must be
|
||||
* implemented so that the undo behaviour is consistent, exactly the
|
||||
* same as would be with separate undo actions for every part of
|
||||
* the drag.
|
||||
*/
|
||||
virtual void extend(const editor_map& map, const std::set<gamemap::location>& locs) = 0;
|
||||
};
|
||||
|
||||
|
@ -209,20 +221,6 @@ class editor_action_starting_position : public editor_action_location
|
|||
int player_;
|
||||
};
|
||||
|
||||
/**
|
||||
* "xor" select action, used as undo in select/deselect
|
||||
*/
|
||||
class editor_action_select_xor : public editor_action_area
|
||||
{
|
||||
public:
|
||||
editor_action_select_xor(const std::set<gamemap::location>& area)
|
||||
: editor_action_area(area)
|
||||
{
|
||||
}
|
||||
editor_action_select_xor* perform(map_context& mc) const;
|
||||
void perform_without_undo(map_context& mc) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the given locations
|
||||
*/
|
||||
|
@ -233,7 +231,8 @@ class editor_action_select : public editor_action_area
|
|||
: editor_action_area(area)
|
||||
{
|
||||
}
|
||||
editor_action_select_xor* perform(map_context& mc) const;
|
||||
void extend(const editor_map& map, const std::set<gamemap::location>& locs);
|
||||
editor_action* perform(map_context& mc) const;
|
||||
void perform_without_undo(map_context& mc) const;
|
||||
};
|
||||
|
||||
|
@ -247,7 +246,8 @@ class editor_action_deselect : public editor_action_area
|
|||
: editor_action_area(area)
|
||||
{
|
||||
}
|
||||
editor_action_select_xor* perform(map_context& mc) const;
|
||||
void extend(const editor_map& map, const std::set<gamemap::location>& locs);
|
||||
editor_action* perform(map_context& mc) const;
|
||||
void perform_without_undo(map_context& mc) const;
|
||||
};
|
||||
|
||||
|
@ -260,7 +260,7 @@ class editor_action_select_all : public editor_action
|
|||
editor_action_select_all()
|
||||
{
|
||||
}
|
||||
editor_action_select_xor* perform(map_context& mc) const;
|
||||
editor_action_deselect* perform(map_context& mc) const;
|
||||
void perform_without_undo(map_context& mc) const;
|
||||
};
|
||||
|
||||
|
@ -273,7 +273,7 @@ class editor_action_select_none : public editor_action
|
|||
editor_action_select_none()
|
||||
{
|
||||
}
|
||||
editor_action_select_xor* perform(map_context& mc) const;
|
||||
editor_action_select* perform(map_context& mc) const;
|
||||
void perform_without_undo(map_context& mc) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,10 +34,21 @@ namespace editor2 {
|
|||
class map_context : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* A map context can only by created from an existing map
|
||||
*/
|
||||
map_context(const editor_map& map);
|
||||
|
||||
~map_context();
|
||||
|
||||
/**
|
||||
* Map accesor
|
||||
*/
|
||||
editor_map& get_map() { return map_; };
|
||||
|
||||
/**
|
||||
* Map accesor - const version
|
||||
*/
|
||||
const editor_map& get_map() const { return map_; }
|
||||
|
||||
/**
|
||||
|
@ -54,13 +65,35 @@ public:
|
|||
void draw_terrain(t_translation::t_terrain terrain, const std::set<gamemap::location>& locs,
|
||||
bool one_layer_only = false);
|
||||
|
||||
/**
|
||||
* Getter for the reload flag. Reload is the highest level of required refreshing,
|
||||
* set when the map size has changed or the map was reassigned.
|
||||
*/
|
||||
bool needs_reload() const { return needs_reload_; }
|
||||
|
||||
/**
|
||||
* Setter for the reload flag
|
||||
*/
|
||||
void set_needs_reload(bool value=true) { needs_reload_ = value; }
|
||||
|
||||
/**
|
||||
* Getter for the terrain rebuild flag. Set whenever any terrain has changed.
|
||||
*/
|
||||
bool needs_terrain_rebuild() const { return needs_terrain_rebuild_; }
|
||||
|
||||
/**
|
||||
* Setter for the terrain rebuild flag
|
||||
*/
|
||||
void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
|
||||
|
||||
/**
|
||||
* Getter fo the labels reset flag. Set when the labels need to be refreshed.
|
||||
*/
|
||||
bool needs_labels_reset() const { return needs_labels_reset_; }
|
||||
|
||||
/**
|
||||
* Setter for the labels reset flag
|
||||
*/
|
||||
void set_needs_labels_reset(bool value=true) { needs_labels_reset_ = value; }
|
||||
|
||||
const std::set<gamemap::location> changed_locations() const { return changed_locations_; }
|
||||
|
@ -78,6 +111,10 @@ public:
|
|||
|
||||
void set_filename(const std::string& fn) { filename_ = fn; }
|
||||
|
||||
/**
|
||||
* Saves the map under the current filename. Filename must be valid.
|
||||
* May throw an exception on failure.
|
||||
*/
|
||||
bool save();
|
||||
|
||||
/**
|
||||
|
@ -87,6 +124,11 @@ public:
|
|||
*/
|
||||
void perform_action(const editor_action& action);
|
||||
|
||||
/**
|
||||
* Performs a partial action, assumes that the top undo action has been modified to
|
||||
* maintain coherent state of the undo stacks, and so a new undo action is not
|
||||
* created.
|
||||
*/
|
||||
void perform_partial_action(const editor_action& action);
|
||||
|
||||
/** @return whether the map was modified since the last save */
|
||||
|
|
|
@ -31,7 +31,10 @@ map_fragment::map_fragment(const gamemap& map, const std::set<gamemap::location>
|
|||
|
||||
void map_fragment::add_tile(const gamemap& map, const gamemap::location& loc)
|
||||
{
|
||||
items_.push_back(tile_info(map, loc));
|
||||
if (area_.find(loc) == area_.end()) {
|
||||
items_.push_back(tile_info(map, loc));
|
||||
area_.insert(loc);
|
||||
}
|
||||
}
|
||||
|
||||
void map_fragment::add_tiles(const gamemap& map, const std::set<gamemap::location>& locs)
|
||||
|
@ -43,11 +46,7 @@ void map_fragment::add_tiles(const gamemap& map, const std::set<gamemap::locatio
|
|||
|
||||
std::set<gamemap::location> map_fragment::get_area() const
|
||||
{
|
||||
std::set<gamemap::location> result;
|
||||
foreach (const tile_info& i, items_) {
|
||||
result.insert(i.offset);
|
||||
}
|
||||
return result;
|
||||
return area_;
|
||||
}
|
||||
|
||||
std::set<gamemap::location> map_fragment::get_offset_area(const gamemap::location& loc) const
|
||||
|
@ -113,6 +112,7 @@ void map_fragment::center_by_mass()
|
|||
|
||||
void map_fragment::rotate_60_cw()
|
||||
{
|
||||
area_.clear();
|
||||
foreach (tile_info& ti, items_) {
|
||||
gamemap::location l(0,0);
|
||||
int x = ti.offset.x;
|
||||
|
@ -123,6 +123,7 @@ void map_fragment::rotate_60_cw()
|
|||
l = l.get_direction(gamemap::location::SOUTH_EAST, (x-is_odd(x))/2 );
|
||||
l = l.get_direction(gamemap::location::SOUTH_WEST, y);
|
||||
ti.offset = l;
|
||||
area_.insert(l);
|
||||
}
|
||||
if (get_area().size() != items_.size()) {
|
||||
throw editor_exception("Map fragment rotation resulted in duplicate entries");
|
||||
|
@ -131,6 +132,7 @@ void map_fragment::rotate_60_cw()
|
|||
|
||||
void map_fragment::rotate_60_ccw()
|
||||
{
|
||||
area_.clear();
|
||||
foreach (tile_info& ti, items_) {
|
||||
gamemap::location l(0,0);
|
||||
int x = ti.offset.x;
|
||||
|
@ -141,6 +143,7 @@ void map_fragment::rotate_60_ccw()
|
|||
l = l.get_direction(gamemap::location::NORTH_EAST, (x+is_odd(x))/2 );
|
||||
l = l.get_direction(gamemap::location::SOUTH_EAST, y);
|
||||
ti.offset = l;
|
||||
area_.insert(l);
|
||||
}
|
||||
if (get_area().size() != items_.size()) {
|
||||
throw editor_exception("Map fragment rotation resulted in duplicate entries");
|
||||
|
|
|
@ -127,8 +127,13 @@ class map_fragment
|
|||
* Rotate the map fragment 60 degrees counter-clockwise around (0,0)
|
||||
*/
|
||||
void rotate_60_ccw();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The data of this map_fragment
|
||||
*/
|
||||
std::vector<tile_info> items_;
|
||||
std::set<gamemap::location> area_;
|
||||
};
|
||||
|
||||
} //end namespace editor2
|
||||
|
|
|
@ -177,9 +177,6 @@ public:
|
|||
editor_action* drag_end(editor_display& disp, int x, int y);
|
||||
|
||||
protected:
|
||||
template <editor_action_extendable* (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<gamemap::location>&)>
|
||||
editor_action* drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
|
||||
|
||||
/** Brush accessor */
|
||||
const brush& get_brush();
|
||||
|
||||
|
@ -189,9 +186,15 @@ protected:
|
|||
*/
|
||||
gamemap::location previous_drag_hex_;
|
||||
|
||||
editor_action* foo(editor_display&, const std::set<gamemap::location>&) {return NULL;}
|
||||
editor_action* bar(editor_display&, const std::set<gamemap::location>&) {return NULL;}
|
||||
private:
|
||||
/**
|
||||
* Template helper gathering actions common for both drag_right and drag_left.
|
||||
* The drags differ only in the worker function called, which should be
|
||||
* passed as the template parameter. This exists only to avoid copy-pasting code.
|
||||
*/
|
||||
template <editor_action_extendable* (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<gamemap::location>&)>
|
||||
editor_action* drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
|
||||
|
||||
/**
|
||||
* Current brush handle. Currently a pointer-to-pointer with full constness.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue