editor2: drag actions create one large undo action...

...instead of one undo per new hex the mouse is moved on
This commit is contained in:
Tomasz Śniatowski 2008-08-20 22:14:42 +01:00
parent 9323a46652
commit 24d96251e3
6 changed files with 118 additions and 45 deletions

View file

@ -85,18 +85,30 @@ bool editor_action_area::add_location(const gamemap::location& loc)
{
return area_.insert(loc).second;
}
void editor_action_area::add_locations(const std::set<gamemap::location>& locs)
{
area_.insert(locs.begin(), locs.end());
}
void editor_action_area::extend(const editor_map& map, const std::set<gamemap::location>& locs)
{
area_.insert(locs.begin(), locs.end());
}
void editor_action_paste::extend(const editor_map& map, const std::set<gamemap::location>& locs)
{
paste_.add_tiles(map, locs);
}
editor_action_paste* editor_action_paste::perform(map_context& mc) const
{
map_fragment mf(mc.get_map(), paste_.get_offset_area(loc_));
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(gamemap::location(0,0), mf));
map_fragment mf(mc.get_map(), paste_.get_offset_area(offset_));
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(mf));
perform_without_undo(mc);
return undo.release();
}
void editor_action_paste::perform_without_undo(map_context& mc) const
{
paste_.paste_into(mc.get_map(), loc_);
mc.add_changed_location(paste_.get_offset_area(loc_));
paste_.paste_into(mc.get_map(), offset_);
mc.add_changed_location(paste_.get_offset_area(offset_));
mc.set_needs_terrain_rebuild();
}
@ -115,7 +127,7 @@ void editor_action_paint_hex::perform_without_undo(map_context& mc) const
editor_action_paste* editor_action_paint_area::perform(map_context& mc) const
{
map_fragment mf(mc.get_map(), area_);
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(gamemap::location(0,0), mf));
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(mf));
perform_without_undo(mc);
return undo.release();
}
@ -309,7 +321,7 @@ void editor_action_plot_route::perform_without_undo(map_context& /*mc*/) const
editor_action_paste* editor_action_shuffle_area::perform(map_context& mc) const
{
map_fragment mf(mc.get_map(), area_);
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(gamemap::location(0,0), mf));
std::auto_ptr<editor_action_paste> undo(new editor_action_paste(mf));
perform_without_undo(mc);
return undo.release();
}

View file

@ -44,6 +44,15 @@ class editor_action_whole_map : public editor_action
editor_map m_;
};
class editor_action_extendable : public editor_action
{
public:
editor_action_extendable()
{
}
virtual void extend(const editor_map& map, const std::set<gamemap::location>& locs) = 0;
};
/**
* Container action wrapping several actions into one.
* The actions are performed in the order they are added,.
@ -101,7 +110,7 @@ class editor_action_location_terrain : public editor_action_location
/**
* Base class for area-affecting actions
*/
class editor_action_area : public editor_action
class editor_action_area : public editor_action_extendable
{
public:
editor_action_area(const std::set<gamemap::location>& area)
@ -109,6 +118,8 @@ class editor_action_area : public editor_action
{
}
bool add_location(const gamemap::location& loc);
void add_locations(const std::set<gamemap::location>& locs);
void extend(const editor_map& map, const std::set<gamemap::location>& locs);
protected:
std::set<gamemap::location> area_;
};
@ -116,16 +127,18 @@ class editor_action_area : public editor_action
/**
* Paste a map fragment into the map. No offset is used.
*/
class editor_action_paste : public editor_action_location
class editor_action_paste : public editor_action_extendable
{
public:
editor_action_paste(const gamemap::location& loc, const map_fragment& paste)
: editor_action_location(loc), paste_(paste)
editor_action_paste(const map_fragment& paste, const gamemap::location& offset = gamemap::location(0,0))
: offset_(offset), paste_(paste)
{
}
editor_action_paste* perform(map_context& mc) const;
void perform_without_undo(map_context& mc) const;
void extend(const editor_map& map, const std::set<gamemap::location>& locs);
protected:
gamemap::location offset_;
map_fragment paste_;
};

View file

@ -26,9 +26,7 @@ map_fragment::map_fragment()
map_fragment::map_fragment(const gamemap& map, const std::set<gamemap::location>& area)
{
foreach (const gamemap::location& loc, area) {
add_tile(map, loc);
}
add_tiles(map, area);
}
void map_fragment::add_tile(const gamemap& map, const gamemap::location& loc)
@ -36,6 +34,13 @@ void map_fragment::add_tile(const gamemap& map, const gamemap::location& loc)
items_.push_back(tile_info(map, loc));
}
void map_fragment::add_tiles(const gamemap& map, const std::set<gamemap::location>& locs)
{
foreach (const gamemap::location& loc, locs) {
add_tile(map, loc);
}
}
std::set<gamemap::location> map_fragment::get_area() const
{
std::set<gamemap::location> result;

View file

@ -63,6 +63,11 @@ class map_fragment
*/
void add_tile(const gamemap& map, const gamemap::location& loc);
/**
* Add many locations and pull their info from the map.
*/
void add_tiles(const gamemap& map, const std::set<gamemap::location>& loc);
/**
* Get the tile_info vector.
*/

View file

@ -25,6 +25,31 @@
namespace editor2 {
class A
{
void doA(int);
void doStuffThenA(int);
template<void (A::*foo)(int)>
void doStuffThenFoo(int);
};
void A::doA(int)
{
}
void A::doStuffThenA(int a)
{
doStuffThenFoo<&A::doA>(a);
}
template<void (A::*foo)(int)>
void A::doStuffThenFoo(int a)
{
//doStuff
(this->*foo)(a);
}
void mouse_action::move(editor_display& disp, const gamemap::location& hex)
{
if (hex != previous_move_hex_) {
@ -126,32 +151,16 @@ editor_action* brush_drag_mouse_action::click_right(editor_display& disp, int x,
}
editor_action* brush_drag_mouse_action::drag_left(editor_display& disp,
int x, int y, bool& /*partial*/, editor_action* /*last_undo*/)
int x, int y, bool& partial, editor_action* last_undo)
{
gamemap::location hex = disp.hex_clicked_on(x, y);
move(disp, hex);
if (hex != previous_drag_hex_) {
editor_action* a = click_perform_left(disp, affected_hexes(disp, hex));
previous_drag_hex_ = hex;
return a;
} else {
return NULL;
}
return drag_generic<&brush_drag_mouse_action::click_perform_left>(disp, x, y, partial, last_undo);
}
editor_action* brush_drag_mouse_action::drag_right(editor_display& disp,
int x, int y, bool& /*partial*/, editor_action* /*last_undo*/)
int x, int y, bool& partial, editor_action* last_undo)
{
gamemap::location hex = disp.hex_clicked_on(x, y);
move(disp, hex);
if (hex != previous_drag_hex_) {
editor_action* a = click_perform_right(disp, affected_hexes(disp, hex));
previous_drag_hex_ = hex;
return a;
} else {
return NULL;
}
}
return drag_generic<&brush_drag_mouse_action::click_perform_right>(disp, x, y, partial, last_undo);
}
editor_action* brush_drag_mouse_action::drag_end(
editor_display& /*disp*/, int /*x*/, int /*y*/)
@ -159,6 +168,29 @@ editor_action* brush_drag_mouse_action::drag_end(
return NULL;
}
template <editor_action_extendable* (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<gamemap::location>&)>
editor_action* brush_drag_mouse_action::drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo)
{
gamemap::location hex = disp.hex_clicked_on(x, y);
move(disp, hex);
if (hex != previous_drag_hex_) {
std::set<gamemap::location> current_step_locs = affected_hexes(disp, hex);
editor_action_extendable* last_undo_x = dynamic_cast<editor_action_extendable*>(last_undo);
LOG_ED << "Last undo is " << last_undo << " and as x " << last_undo_x << "\n";
if (last_undo_x != NULL) {
last_undo_x->extend(disp.map(), current_step_locs);
partial = true;
} else {
WRN_ED << "last undo in drag was not an editor_action_extendable\n";
}
editor_action* a = (this->*perform_func)(disp, affected_hexes(disp, hex));
previous_drag_hex_ = hex;
return a;
} else {
return NULL;
}
}
const brush& brush_drag_mouse_action::get_brush()
{
assert(brush_);
@ -167,13 +199,13 @@ const brush& brush_drag_mouse_action::get_brush()
}
editor_action* mouse_action_paint::click_perform_left(
editor_action_extendable* mouse_action_paint::click_perform_left(
editor_display& /*disp*/, const std::set<gamemap::location>& hexes)
{
return new editor_action_paint_area(hexes, terrain_left_, has_alt_modifier());
}
editor_action* mouse_action_paint::click_perform_right(
editor_action_extendable* mouse_action_paint::click_perform_right(
editor_display& /*disp*/, const std::set<gamemap::location>& hexes)
{
return new editor_action_paint_area(hexes, terrain_right_, has_alt_modifier());
@ -198,13 +230,13 @@ editor_action* mouse_action_select::key_event(
return ret;
}
editor_action* mouse_action_select::click_perform_left(
editor_action_extendable* mouse_action_select::click_perform_left(
editor_display& /*disp*/, const std::set<gamemap::location>& hexes)
{
return new editor_action_select(hexes);
}
editor_action* mouse_action_select::click_perform_right(
editor_action_extendable* mouse_action_select::click_perform_right(
editor_display& /*disp*/, const std::set<gamemap::location>& hexes)
{
return new editor_action_deselect(hexes);
@ -220,7 +252,7 @@ std::set<gamemap::location> mouse_action_paste::affected_hexes(
editor_action* mouse_action_paste::click_left(editor_display& disp, int x, int y)
{
gamemap::location hex = disp.hex_clicked_on(x, y);
editor_action_paste* a = new editor_action_paste(hex, paste_);
editor_action_paste* a = new editor_action_paste(paste_, hex);
return a;
}

View file

@ -141,12 +141,12 @@ public:
/**
* The actual action function which is called by click() and drag(). Derived classes override this instead of click() and drag().
*/
virtual editor_action* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes) = 0;
virtual editor_action_extendable* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes) = 0;
/**
* The actual action function which is called by click() and drag(). Derived classes override this instead of click() and drag().
*/
virtual editor_action* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes) = 0;
virtual editor_action_extendable* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes) = 0;
/**
* Calls click_perform_left()
@ -177,6 +177,9 @@ 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();
@ -185,6 +188,9 @@ protected:
* @todo keep a set of all "visited" locations to reduce action count in long drags that hit the same hexes multiple times?
*/
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:
/**
* Current brush handle. Currently a pointer-to-pointer with full constness.
@ -210,12 +216,12 @@ public:
/**
* Create an appropriate editor_action and return it
*/
editor_action* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes);
editor_action_extendable* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes);
/**
* Create an appropriate editor_action and return it
*/
editor_action* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes);
editor_action_extendable* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes);
bool uses_terrains() const { return true; }
protected:
@ -247,12 +253,12 @@ public:
/**
* Left click/drag selects
*/
editor_action* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes);
editor_action_extendable* click_perform_left(editor_display& disp, const std::set<gamemap::location>& hexes);
/**
* Right click/drag deselects
*/
editor_action* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes);
editor_action_extendable* click_perform_right(editor_display& disp, const std::set<gamemap::location>& hexes);
};
/**