editor2: wire in flip actions, smarter after-action refreshing,

...mouse action tweaks (do less work on mouse move within same
hex). Not guaranteed to be 100% stable at the moment, editor_map needs
a slight overhaul.
This commit is contained in:
Tomasz Śniatowski 2008-07-30 00:21:57 +01:00
parent 318cd685c9
commit e68301c3f7
14 changed files with 143 additions and 47 deletions

View file

@ -140,7 +140,7 @@
id=menu-editor-map
title= _ "Map"
image=lite
items=editor-map-resize,editor-map-rotate,editor-map-flip,editor-map-generate,editor-refresh,editor-update-transitions,editor-auto-update-transitions
items=editor-map-resize,editor-map-rotate,editor-map-flip-x,editor-map-flip-y,editor-map-generate,editor-refresh,editor-update-transitions,editor-auto-update-transitions
rect="+2,=,+100,="
xanchor=fixed
yanchor=fixed

View file

@ -70,12 +70,14 @@ void draw_terrain(editor_map& map, t_translation::t_terrain terrain,
} else {
map.set_terrain(loc, terrain);
}
map.add_changed_location(loc);
}
}
}
void editor_action_whole_map::perform_without_undo(editor_map& m) const {
m = m_;
void editor_action_whole_map::perform_without_undo(editor_map& map) const {
map = m_;
map.set_needs_reload();
}
editor_action_chain::~editor_action_chain()
@ -84,18 +86,18 @@ editor_action_chain::~editor_action_chain()
delete a;
}
}
editor_action_chain* editor_action_chain::perform(editor_map& m) const {
editor_action_chain* editor_action_chain::perform(editor_map& map) const {
std::vector<editor_action*> undo;
foreach (editor_action* a, actions_) {
undo.push_back(a->perform(m));
undo.push_back(a->perform(map));
}
std::reverse(undo.begin(), undo.end());
return new editor_action_chain(undo);
}
void editor_action_chain::perform_without_undo(editor_map& m) const
void editor_action_chain::perform_without_undo(editor_map& map) const
{
foreach (editor_action* a, actions_) {
a->perform_without_undo(m);
a->perform_without_undo(map);
}
}
@ -114,6 +116,8 @@ editor_action_paste* editor_action_paste::perform(editor_map& map) const
void editor_action_paste::perform_without_undo(editor_map& map) const
{
paste_.paste_into(map, loc_);
map.add_changed_location(paste_.get_offset_area(loc_));
map.set_needs_terrain_rebuild();
}
editor_action_paint_hex* editor_action_paint_hex::perform(editor_map& map) const
@ -125,6 +129,7 @@ editor_action_paint_hex* editor_action_paint_hex::perform(editor_map& map) const
void editor_action_paint_hex::perform_without_undo(editor_map& map) const
{
draw_terrain(map, t_, loc_);
map.set_needs_terrain_rebuild();
}
editor_action_paste* editor_action_paint_area::perform(editor_map& map) const
@ -137,6 +142,8 @@ editor_action_paste* editor_action_paint_area::perform(editor_map& map) const
void editor_action_paint_area::perform_without_undo(editor_map& map) const
{
draw_terrain(map, t_, area_);
map.add_changed_location(area_);
map.set_needs_terrain_rebuild();
}
editor_action_paint_area* editor_action_fill::perform(editor_map& map) const
@ -144,12 +151,14 @@ editor_action_paint_area* editor_action_fill::perform(editor_map& map) const
std::set<gamemap::location> to_fill = map.get_contigious_terrain_tiles(loc_);
editor_action_paint_area* undo = new editor_action_paint_area(to_fill, map.get_terrain(loc_));
draw_terrain(map, t_, to_fill);
map.set_needs_terrain_rebuild();
return undo;
}
void editor_action_fill::perform_without_undo(editor_map& map) const
{
std::set<gamemap::location> to_fill = map.get_contigious_terrain_tiles(loc_);
draw_terrain(map, t_, to_fill);
map.set_needs_terrain_rebuild();
}
editor_action_select_xor* editor_action_select_xor::perform(editor_map& map) const
@ -157,6 +166,7 @@ editor_action_select_xor* editor_action_select_xor::perform(editor_map& map) con
perform_without_undo(map);
return new editor_action_select_xor(area_);
}
void editor_action_select_xor::perform_without_undo(editor_map& map) const
{
foreach (const gamemap::location& loc, area_) {
@ -165,6 +175,7 @@ void editor_action_select_xor::perform_without_undo(editor_map& map) const
} else {
map.add_to_selection(loc);
}
map.add_changed_location(loc);
}
}
@ -174,6 +185,7 @@ editor_action_select_xor* editor_action_select::perform(editor_map& map) const
foreach (const gamemap::location& loc, area_) {
if (!map.in_selection(loc)) {
undo_locs.insert(loc);
map.add_changed_location(loc);
}
}
perform_without_undo(map);
@ -183,6 +195,7 @@ void editor_action_select::perform_without_undo(editor_map& map) const
{
foreach (const gamemap::location& loc, area_) {
map.add_to_selection(loc);
map.add_changed_location(loc);
}
}
@ -192,6 +205,7 @@ editor_action_select_xor* editor_action_deselect::perform(editor_map& map) const
foreach (const gamemap::location& loc, area_) {
if (map.in_selection(loc)) {
undo_locs.insert(loc);
map.add_changed_location(loc);
}
}
perform_without_undo(map);
@ -201,12 +215,14 @@ void editor_action_deselect::perform_without_undo(editor_map& map) const
{
foreach (const gamemap::location& loc, area_) {
map.remove_from_selection(loc);
map.add_changed_location(loc);
}
}
void editor_action_resize_map::perform_without_undo(editor_map& map) const
{
map.resize(x_size_, y_size_, x_offset_, y_offset_);
map.set_needs_reload();
}
void editor_action_rotate_map::perform_without_undo(editor_map& /*map*/) const
@ -217,10 +233,13 @@ void editor_action_rotate_map::perform_without_undo(editor_map& /*map*/) const
void editor_action_flip_x::perform_without_undo(editor_map& map) const
{
map.flip_x();
map.set_needs_reload();
}
void editor_action_flip_y::perform_without_undo(editor_map& map) const
{
map.flip_y();
map.set_needs_reload();
}
editor_action_paste* editor_action_plot_route::perform(editor_map& /*map*/) const

View file

@ -234,6 +234,7 @@ class editor_action_flip_y : public editor_action
{
}
void perform_without_undo(editor_map& map) const;
bool require_map_reload() { return true; }
};
//plot a route between two points

View file

@ -26,8 +26,10 @@
#define EDITOR2_ACTION_BASE_HPP_INCLUDED
#include "editor_common.hpp"
#include <string>
namespace editor2 {
//base class (interface) for editor actions.

View file

@ -138,7 +138,10 @@ bool editor_controller::confirm_discard()
void editor_controller::load_map_dialog()
{
if (!confirm_discard()) return;
std::string fn = map_.get_filename().empty() ? get_dir(get_dir(get_user_data_dir() + "/editor") + "/maps") : filename_;
std::string fn = map_.get_filename();
if (fn.empty()) {
fn = get_dir(get_dir(get_user_data_dir() + "/editor") + "/maps");
}
int res = dialogs::show_file_chooser_dialog(gui(), fn, _("Choose a Map to Load"));
if (res == 0) {
load_map(fn);
@ -254,6 +257,15 @@ void editor_controller::set_map(const editor_map& map)
refresh_all();
}
void editor_controller::reload_map()
{
map_.clear_starting_position_labels(gui());
gui().reload_map();
map_.set_starting_position_labels(gui());
refresh_all();
}
bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int /*index*/) const
{
using namespace hotkey; //reduce hotkey:: clutter
@ -303,7 +315,8 @@ bool editor_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int
case HOTKEY_EDITOR_SELECT_ALL:
case HOTKEY_EDITOR_MAP_RESIZE:
case HOTKEY_EDITOR_MAP_ROTATE:
case HOTKEY_EDITOR_MAP_FLIP:
case HOTKEY_EDITOR_MAP_FLIP_X:
case HOTKEY_EDITOR_MAP_FLIP_Y:
case HOTKEY_EDITOR_MAP_GENERATE:
case HOTKEY_EDITOR_REFRESH:
case HOTKEY_EDITOR_UPDATE_TRANSITIONS:
@ -357,6 +370,19 @@ bool editor_controller::execute_command(hotkey::HOTKEY_COMMAND command, int inde
case HOTKEY_EDITOR_CUT:
cut_selection();
return true;
case HOTKEY_EDITOR_MAP_FLIP_X: {
editor_action_flip_x fx;
map_.perform_action(fx);
refresh_after_action();
return true;
}
case HOTKEY_EDITOR_MAP_FLIP_Y: {
LOG_ED << "FlipYhk\n";
editor_action_flip_y fy;
map_.perform_action(fy);
refresh_after_action();
return true;
}
case HOTKEY_EDITOR_MAP_LOAD:
load_map_dialog();
return true;
@ -470,7 +496,7 @@ void editor_controller::cut_selection()
copy_selection();
editor_action_paint_area a(map_.selection(), background_terrain_);
map_.perform_action(a);
refresh_after_action(a);
refresh_after_action();
}
void editor_controller::hotkey_set_mouse_action(hotkey::HOTKEY_COMMAND command)
@ -511,10 +537,24 @@ mouse_action* editor_controller::get_mouse_action()
}
void editor_controller::refresh_after_action(const editor_action& /*action*/)
void editor_controller::refresh_after_action()
{
//TODO rebuild and ivalidate only what's really needed
refresh_all();
if (map_.needs_reload()) {
reload_map();
map_.set_needs_reload(false);
map_.set_needs_terrain_rebuild(false);
map_.clear_changed_locations();
} else if (map_.needs_terrain_rebuild()) {
gui().rebuild_all();
gui().invalidate_all();
map_.set_needs_terrain_rebuild(false);
map_.clear_changed_locations();
} else {
gui().invalidate(map_.changed_locations());
map_.clear_changed_locations();
}
gui().recalculate_minimap();
}
void editor_controller::refresh_all()
@ -526,18 +566,20 @@ void editor_controller::refresh_all()
gui().rebuild_all();
gui().invalidate_all();
gui().recalculate_minimap();
map_.set_needs_terrain_rebuild(false);
map_.clear_changed_locations();
}
void editor_controller::undo()
{
map_.undo();
refresh_all();
refresh_after_action();
}
void editor_controller::redo()
{
map_.redo();
refresh_all();
refresh_after_action();
}
void editor_controller::mouse_motion(int x, int y, const bool browse, bool update)
@ -560,7 +602,7 @@ void editor_controller::mouse_motion(int x, int y, const bool browse, bool updat
} else {
map_.perform_action(*a);
}
refresh_after_action(*a);
refresh_after_action();
delete a;
}
} else {
@ -585,7 +627,7 @@ bool editor_controller::left_click(int x, int y, const bool browse)
editor_action* a = get_mouse_action()->click(*gui_, x, y);
if (a != NULL) {
map_.perform_action(*a);
refresh_after_action(*a);
refresh_after_action();
delete a;
}
return true;
@ -601,7 +643,7 @@ void editor_controller::left_drag_end(int x, int y, const bool browse)
editor_action* a = get_mouse_action()->drag_end(*gui_, x, y);
if (a != NULL) {
map_.perform_action(*a);
refresh_after_action(*a);
refresh_after_action();
delete a;
}
} else {

View file

@ -68,6 +68,7 @@ class editor_controller : public controller_base,
void new_map(int width, int height, t_translation::t_terrain fill);
void load_map(const std::string& filename);
void set_map(const editor_map& map);
void reload_map();
bool can_execute_command(hotkey::HOTKEY_COMMAND, int index = -1) const;
hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command) const;
@ -101,7 +102,7 @@ class editor_controller : public controller_base,
/** init the display object and general set-up */
void init(CVideo& video);
void refresh_after_action(const editor_action& action);
void refresh_after_action();
void refresh_all();
@ -118,8 +119,6 @@ class editor_controller : public controller_base,
/** The current map object */
editor_map map_;
std::string filename_;
/** The display object used and owned by the editor. */
editor_display* gui_;

View file

@ -16,6 +16,8 @@
#include "editor_common.hpp"
#include "editor_controller.hpp"
#include "../hotkeys.hpp"
namespace editor2 {
EXIT_STATUS start(config& game_conf, CVideo& video)

View file

@ -15,11 +15,8 @@
#ifndef EDITOR2_EDITOR_MAIN_H_INCLUDED
#define EDITOR2_EDITOR_MAIN_H_INCLUDED
#include "display.hpp"
#include "config.hpp"
#include "filesystem.hpp"
#include "game_preferences.hpp"
#include "gamestatus.hpp"
class config;
class CVideo;
namespace editor2 {

View file

@ -30,14 +30,15 @@ namespace editor2 {
const int editor_map::max_action_stack_size_ = 100;
editor_map::editor_map(const config& terrain_cfg, const std::string& data)
: gamemap(terrain_cfg, data), filename_(), actions_since_save_(0)
: gamemap(terrain_cfg, data), filename_(), actions_since_save_(0),
needs_reload_(false), needs_terrain_rebuild_(false)
{
}
editor_map::editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler)
: gamemap(terrain_cfg, gamemap::default_map_header + t_translation::write_game_map(
t_translation::t_map(width, t_translation::t_list(height, filler))))
, filename_(), actions_since_save_(0)
, filename_(), actions_since_save_(0), needs_reload_(false), needs_terrain_rebuild_(false)
{
}
@ -70,22 +71,29 @@ std::set<gamemap::location> editor_map::get_contigious_terrain_tiles(const gamem
return result;
}
void editor_map::clear_starting_position_labels(display& disp) const
void editor_map::add_changed_location(const std::set<gamemap::location>& locs)
{
foreach (const gamemap::location& loc, startingPositions_) {
if (loc.valid()) {
disp.labels().set_label(loc, "");
}
foreach (const gamemap::location& loc, locs) {
changed_locations_.insert(loc);
}
}
void editor_map::clear_starting_position_labels(display& disp)
{
foreach (const gamemap::location& loc, starting_position_label_locs_) {
disp.labels().set_label(loc, "");
}
starting_position_label_locs_.clear();
}
void editor_map::set_starting_position_labels(display& disp) const
void editor_map::set_starting_position_labels(display& disp)
{
std::string label = _("Player");
label += " ";
for (int i = 1; i <= gamemap::MAX_PLAYERS; i++) {
if (startingPositions_[i].valid()) {
disp.labels().set_label(startingPositions_[i], label + lexical_cast<std::string>(i));
starting_position_label_locs_.insert(startingPositions_[i]);
}
}
}
@ -95,7 +103,6 @@ bool editor_map::save()
std::string data = write();
write_file(get_filename(), data);
actions_since_save_ = 0;
return true;
}
@ -280,6 +287,7 @@ void editor_map::resize(int width, int height, int x_offset, int y_offset,
void editor_map::flip_x()
{
LOG_ED << "FlipX\n";
// Due to the hexes we need some mirror tricks when mirroring over the
// X axis. We resize the map and fill it. The odd columns will be extended
// with the data in row 0 the even columns are extended with the data in
@ -301,13 +309,13 @@ void editor_map::flip_x()
swap_starting_position(x, y1, x, y2);
std::swap(tiles_[x][y1], tiles_[x][y2]);
}
}
}
}
void editor_map::flip_y()
{
LOG_ED << "FlipY\n";
// Flipping on the Y axis requires no resize,
// so the code is much simpler.
const size_t middle = (tiles_.size() / 2);

View file

@ -35,11 +35,11 @@ class editor_map : public gamemap
public:
editor_map(const config& terrain_cfg, const std::string& data);
editor_map(const config& terrain_cfg, size_t width, size_t height, t_translation::t_terrain filler);
~editor_map();
/**
* Get a contigious set of tiles having the same terrain as the starting location.
* Useful for flood fill or magic wand selection
@ -47,9 +47,20 @@ public:
*/
std::set<gamemap::location> get_contigious_terrain_tiles(const gamemap::location& start) const;
void clear_starting_position_labels(display& disp) const;
bool needs_reload() const { return needs_reload_; }
void set_needs_reload(bool value=true) { needs_reload_ = value; }
void set_starting_position_labels(display& disp) const;
bool needs_terrain_rebuild() const { return needs_terrain_rebuild_; }
void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
const std::set<gamemap::location> changed_locations() const { return changed_locations_; }
void clear_changed_locations() { changed_locations_.clear(); }
void add_changed_location(const gamemap::location& loc) { changed_locations_.insert(loc); }
void add_changed_location(const std::set<gamemap::location>& locs);
void clear_starting_position_labels(display& disp);
void set_starting_position_labels(display& disp);
/**
* @return true when the location is part of the selection, false otherwise
@ -199,10 +210,15 @@ protected:
* Number of actions performed since the map was saved. Zero means the map was not modified.
*/
int actions_since_save_;
std::set<gamemap::location> starting_position_label_locs_;
bool needs_reload_;
bool needs_terrain_rebuild_;
std::set<gamemap::location> changed_locations_;
};
} //end namespace editor2
#endif

View file

@ -40,13 +40,17 @@ editor_action* mouse_action::drag_end(editor_display& disp, int x, int y)
void brush_drag_mouse_action::move(editor_display& disp, int x, int y)
{
disp.set_brush_locs(get_brush().project(disp.hex_clicked_on(x,y)));
gamemap::location hex = disp.hex_clicked_on(x, y);
if (hex != previous_move_hex_) {
disp.set_brush_locs(get_brush().project(disp.hex_clicked_on(x,y)));
previous_move_hex_ = hex;
}
}
editor_action* brush_drag_mouse_action::click(editor_display& disp, int x, int y)
{
gamemap::location hex = disp.hex_clicked_on(x, y);
previous_hex_ = hex;
previous_drag_hex_ = hex;
return click_perform(disp, hex);
}
@ -54,8 +58,10 @@ editor_action* brush_drag_mouse_action::drag(editor_display& disp, int x, int y,
{
move(disp, x, y);
gamemap::location hex = disp.hex_clicked_on(x, y);
if (hex != previous_hex_) {
return click_perform(disp, hex);
if (hex != previous_drag_hex_) {
editor_action* a = click_perform(disp, hex);
previous_drag_hex_ = hex;
return a;
} else {
return NULL;
}

View file

@ -56,7 +56,7 @@ public:
virtual editor_action* drag_end(editor_display& disp, int x, int y);
protected:
gamemap::location previous_hex_;
gamemap::location previous_move_hex_;
};
class brush_drag_mouse_action : public mouse_action
@ -73,6 +73,7 @@ public:
editor_action* drag_end(editor_display& disp, int x, int y);
protected:
const brush& get_brush();
gamemap::location previous_drag_hex_;
private:
const brush* const * const brush_;
};

View file

@ -164,8 +164,10 @@ const struct {
N_("Resize Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_ROTATE, "editor-map-rotate",
N_("Rotate Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_FLIP, "editor-map-flip",
N_("Flip Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_FLIP_X, "editor-map-flip-x",
N_("Flip Map along X axis"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_FLIP_Y, "editor-map-flip-y",
N_("Flip Map along Y axis"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_MAP_GENERATE, "editor-map-generate",
N_("Generate Map"), false, hotkey::SCOPE_EDITOR },
{ hotkey::HOTKEY_EDITOR_REFRESH, "editor-refresh",

View file

@ -82,7 +82,8 @@ enum HOTKEY_COMMAND {
HOTKEY_EDITOR_SELECT_ALL,
HOTKEY_EDITOR_SELECTION_ROTATE, HOTKEY_EDITOR_SELECTION_FLIP,
HOTKEY_EDITOR_SELECTION_GENERATE, HOTKEY_EDITOR_SELECTION_RANDOMIZE,
HOTKEY_EDITOR_MAP_RESIZE, HOTKEY_EDITOR_MAP_ROTATE, HOTKEY_EDITOR_MAP_FLIP,
HOTKEY_EDITOR_MAP_RESIZE, HOTKEY_EDITOR_MAP_ROTATE,
HOTKEY_EDITOR_MAP_FLIP_X, HOTKEY_EDITOR_MAP_FLIP_Y,
HOTKEY_EDITOR_MAP_GENERATE,
HOTKEY_EDITOR_REFRESH, HOTKEY_EDITOR_UPDATE_TRANSITIONS,
HOTKEY_EDITOR_AUTO_UPDATE_TRANSITIONS,