Drag and drop of selections added.
This commit is contained in:
parent
e95536ac51
commit
ebd6d32ad4
2 changed files with 148 additions and 42 deletions
|
@ -76,9 +76,8 @@ map_editor::map_editor(display &gui, gamemap &map, config &theme, config &game_c
|
|||
: gui_(gui), map_(map), tup_(gui, "", gui::button::TYPE_PRESS, "uparrow-button"),
|
||||
tdown_(gui, "", gui::button::TYPE_PRESS, "downarrow-button"), abort_(DONT_ABORT),
|
||||
num_operations_since_save_(0), theme_(theme), game_config_(game_config),
|
||||
draw_terrain_(false), map_dirty_(false),
|
||||
palette_(gui, size_specs_, map), brush_(gui, size_specs_), add_selection_(false) {
|
||||
|
||||
map_dirty_(false), palette_(gui, size_specs_, map), brush_(gui, size_specs_),
|
||||
l_button_func_(NONE) {
|
||||
|
||||
// Set size specs.
|
||||
adjust_sizes(gui_, size_specs_, palette_.num_terrains());
|
||||
|
@ -135,34 +134,45 @@ void map_editor::handle_mouse_button_event(const SDL_MouseButtonEvent &event,
|
|||
show_menu(m->items(), mousex, mousey + 1, true);
|
||||
}
|
||||
if (button == SDL_BUTTON_LEFT) {
|
||||
if (key_[SDLK_LSHIFT] || key_[SDLK_RSHIFT]) {
|
||||
// Set a boolean to indicate wether to add or remove selected hexes.
|
||||
if (selected_hexes_.find(gui_.hex_clicked_on(mousex, mousey))
|
||||
== selected_hexes_.end()) {
|
||||
add_selection_ = true;
|
||||
gamemap::location hex_clicked = gui_.hex_clicked_on(mousex, mousey);
|
||||
if (map_.on_board(hex_clicked)) {
|
||||
if (key_[SDLK_LSHIFT] || key_[SDLK_RSHIFT]) {
|
||||
if (selected_hexes_.find(hex_clicked)
|
||||
== selected_hexes_.end()) {
|
||||
l_button_func_ = ADD_SELECTION;
|
||||
}
|
||||
else {
|
||||
l_button_func_ = REMOVE_SELECTION;
|
||||
}
|
||||
}
|
||||
else if (selected_hexes_.find(hex_clicked) != selected_hexes_.end()) {
|
||||
l_button_func_ = MOVE_SELECTION;
|
||||
selection_move_start_ = hex_clicked;
|
||||
}
|
||||
else if (!selected_hexes_.empty()) {
|
||||
// If hexes are selected, clear them and do not draw
|
||||
// anything.
|
||||
selected_hexes_.clear();
|
||||
gui_.clear_highlighted_locs();
|
||||
update_mouse_over_hexes(hex_clicked);
|
||||
}
|
||||
else {
|
||||
add_selection_ = false;
|
||||
l_button_func_ = DRAW_TERRAIN;
|
||||
}
|
||||
}
|
||||
else if (!selected_hexes_.empty()
|
||||
&& map_.on_board(gui_.hex_clicked_on(mousex, mousey))
|
||||
&& !(key_[SDLK_LSHIFT] || key_[SDLK_RSHIFT])) {
|
||||
// If hexes are selected, clear them and do not draw
|
||||
// anything.
|
||||
selected_hexes_.clear();
|
||||
gui_.clear_highlighted_locs();
|
||||
update_mouse_over_hexes(gui_.hex_clicked_on(mousex, mousey));
|
||||
}
|
||||
else {
|
||||
draw_terrain_ = true;
|
||||
palette_.left_mouse_click(mousex, mousey);
|
||||
brush_.left_mouse_click(mousex, mousey);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event.type == SDL_MOUSEBUTTONUP) {
|
||||
draw_terrain_ = false;
|
||||
// If we miss the mouse up event we need to perform the actual
|
||||
// movement if we are in the progress of moving a selection.
|
||||
if (l_button_func_ == MOVE_SELECTION) {
|
||||
perform_selection_move();
|
||||
}
|
||||
l_button_func_ = NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,24 +286,29 @@ void map_editor::edit_copy() {
|
|||
|
||||
void map_editor::edit_paste() {
|
||||
map_undo_action undo_action;
|
||||
std::vector<gamemap::location> filled;
|
||||
std::set<gamemap::location> filled;
|
||||
gamemap::location start_hex = selected_hex_;
|
||||
// The x coordinate may need to be adjusted because the same
|
||||
// representation of the hexes may not look the same on the map, and
|
||||
// we want to make sure it looks the same when pasted.
|
||||
start_hex.x = start_hex.x % 2 == clipboard_offset_loc_.x % 2 ? start_hex.x : start_hex.x - 1;
|
||||
gui_.clear_highlighted_locs();
|
||||
for (std::vector<clipboard_item>::const_iterator it = clipboard_.begin();
|
||||
it != clipboard_.end(); it++) {
|
||||
const gamemap::location target =
|
||||
gamemap::location(start_hex.x + (*it).x_offset,
|
||||
start_hex.y + (*it).y_offset);
|
||||
gamemap::location l(clipboard_offset_loc_.x + (*it).x_offset,
|
||||
clipboard_offset_loc_.y + (*it).y_offset);
|
||||
const int x_offset = start_hex.x - clipboard_offset_loc_.x;
|
||||
const int y_offset = start_hex.y - clipboard_offset_loc_.y;
|
||||
gamemap::location target = get_hex_with_offset(l, x_offset, y_offset);
|
||||
/*gamemap::location target(start_hex.x + (*it).x_offset, start_hex.y + (*it).y_offset);
|
||||
if (is_odd(clipboard_offset_loc_.x - start_hex.x) && is_odd(target.x - start_hex.x) ) {
|
||||
target.y--;
|
||||
}*/
|
||||
if (map_.on_board(target)) {
|
||||
undo_action.add(map_.get_terrain(target), (*it).terrain, target);
|
||||
map_.set_terrain(target, (*it).terrain);
|
||||
filled.push_back(target);
|
||||
filled.insert(target);
|
||||
gui_.add_highlighted_loc(target);
|
||||
}
|
||||
}
|
||||
invalidate_all_and_adjacent(filled);
|
||||
selected_hexes_ = filled;
|
||||
add_undo_action(undo_action);
|
||||
}
|
||||
|
||||
|
@ -365,6 +380,9 @@ void map_editor::add_undo_action(const map_undo_action &action) {
|
|||
void map_editor::undo() {
|
||||
if(!undo_stack_.empty()) {
|
||||
--num_operations_since_save_;
|
||||
// Clear the selected hexes to avoid some weirdness from occuring.
|
||||
selected_hexes_.clear();
|
||||
gui_.clear_highlighted_locs();
|
||||
map_undo_action action = undo_stack_.back();
|
||||
std::vector<gamemap::location> to_invalidate;
|
||||
for(std::map<gamemap::location,gamemap::TERRAIN>::const_iterator it = action.undo_terrains().begin();
|
||||
|
@ -383,9 +401,13 @@ void map_editor::undo() {
|
|||
void map_editor::redo() {
|
||||
if(!redo_stack_.empty()) {
|
||||
++num_operations_since_save_;
|
||||
// Clear the selected hexes to avoid some weirdness from occuring.
|
||||
selected_hexes_.clear();
|
||||
gui_.clear_highlighted_locs();
|
||||
map_undo_action action = redo_stack_.back();
|
||||
std::vector<gamemap::location> to_invalidate;
|
||||
for(std::map<gamemap::location,gamemap::TERRAIN>::const_iterator it = action.redo_terrains().begin();
|
||||
for(std::map<gamemap::location,gamemap::TERRAIN>::const_iterator it =
|
||||
action.redo_terrains().begin();
|
||||
it != action.redo_terrains().end(); ++it) {
|
||||
map_.set_terrain(it->first, it->second);
|
||||
to_invalidate.push_back(it->first);
|
||||
|
@ -424,11 +446,20 @@ void map_editor::set_file_to_save_as(const std::string filename) {
|
|||
filename_ = filename;
|
||||
}
|
||||
|
||||
gamemap::location map_editor::get_hex_with_offset(const gamemap::location loc,
|
||||
const int x_offset, const int y_offset) {
|
||||
gamemap::location new_loc(loc.x + x_offset, loc.y + y_offset);
|
||||
if (new_loc.x % 2 != loc.x % 2 && is_odd(new_loc.x)) {
|
||||
new_loc.y--;
|
||||
}
|
||||
return new_loc;
|
||||
}
|
||||
|
||||
void map_editor::left_button_down(const int mousex, const int mousey) {
|
||||
const gamemap::location& loc = gui_.minimap_location_on(mousex,mousey);
|
||||
const gamemap::location& minimap_loc = gui_.minimap_location_on(mousex,mousey);
|
||||
const gamemap::location hex = gui_.hex_clicked_on(mousex, mousey);
|
||||
if (loc.valid()) {
|
||||
gui_.scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
if (minimap_loc.valid()) {
|
||||
gui_.scroll_to_tile(minimap_loc.x,minimap_loc.y,display::WARP,false);
|
||||
}
|
||||
else if (key_[SDLK_RSHIFT] || key_[SDLK_LSHIFT]) {
|
||||
if (key_[SDLK_RALT] || key_[SDLK_LALT]) {
|
||||
|
@ -437,7 +468,7 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
|
|||
selected = get_component(map_, selected_hex_);
|
||||
for (std::set<gamemap::location>::const_iterator it = selected.begin();
|
||||
it != selected.end(); it++) {
|
||||
if (add_selection_) {
|
||||
if (l_button_func_ == ADD_SELECTION) {
|
||||
gui_.add_highlighted_loc(*it);
|
||||
selected_hexes_.insert(*it);
|
||||
}
|
||||
|
@ -454,7 +485,7 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
|
|||
selected = get_tiles(map_, hex, brush_.selected_brush_size());
|
||||
for (std::vector<gamemap::location>::const_iterator it = selected.begin();
|
||||
it != selected.end(); it++) {
|
||||
if (add_selection_) {
|
||||
if (l_button_func_ == ADD_SELECTION) {
|
||||
gui_.add_highlighted_loc(*it);
|
||||
selected_hexes_.insert(*it);
|
||||
}
|
||||
|
@ -468,7 +499,7 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
|
|||
}
|
||||
// If the left mouse button is down and we beforhand have registred
|
||||
// a mouse down event, draw terrain at the current location.
|
||||
else if (draw_terrain_) {
|
||||
else if (l_button_func_ == DRAW_TERRAIN) {
|
||||
if(map_.on_board(hex)) {
|
||||
const gamemap::TERRAIN terrain = map_[hex.x][hex.y];
|
||||
if(key_[SDLK_RCTRL] || key_[SDLK_LCTRL]) {
|
||||
|
@ -505,6 +536,53 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (l_button_func_ == MOVE_SELECTION) {
|
||||
const int x_diff = hex.x - selection_move_start_.x;
|
||||
const int y_diff = hex.y - selection_move_start_.y;
|
||||
// No other selections should be active when doing this.
|
||||
gui_.clear_highlighted_locs();
|
||||
for (std::set<gamemap::location>::const_iterator it = selected_hexes_.begin();
|
||||
it != selected_hexes_.end(); it++) {
|
||||
const gamemap::location hl_loc =
|
||||
get_hex_with_offset(*it, x_diff, y_diff);
|
||||
if (map_.on_board(hl_loc)) {
|
||||
gui_.add_highlighted_loc(hl_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_editor::perform_selection_move() {
|
||||
map_undo_action undo_action;
|
||||
const int x_diff = selected_hex_.x - selection_move_start_.x;
|
||||
const int y_diff = selected_hex_.y - selection_move_start_.y;
|
||||
gui_.clear_highlighted_locs();
|
||||
std::set<gamemap::location> new_selection;
|
||||
// Transfer the terrain to the new position.
|
||||
for (std::set<gamemap::location>::const_iterator it = selected_hexes_.begin();
|
||||
it != selected_hexes_.end(); it++) {
|
||||
const gamemap::location hl_loc =
|
||||
get_hex_with_offset(*it, x_diff, y_diff);
|
||||
if (map_.on_board(hl_loc)) {
|
||||
undo_action.add(map_.get_terrain(hl_loc), map_.get_terrain(*it), hl_loc);
|
||||
gui_.add_highlighted_loc(hl_loc);
|
||||
map_.set_terrain(hl_loc, map_.get_terrain(*it));
|
||||
new_selection.insert(hl_loc);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the selection with the selected terrain.
|
||||
for (std::set<gamemap::location>::const_iterator it = selected_hexes_.begin();
|
||||
it != selected_hexes_.end(); it++) {
|
||||
if (map_.on_board(*it) && new_selection.find(*it) == new_selection.end()) {
|
||||
undo_action.add(map_.get_terrain(*it), palette_.selected_terrain(), *it);
|
||||
map_.set_terrain(*it, palette_.selected_terrain());
|
||||
}
|
||||
}
|
||||
invalidate_all_and_adjacent(selected_hexes_);
|
||||
selected_hexes_ = new_selection;
|
||||
invalidate_all_and_adjacent(selected_hexes_);
|
||||
add_undo_action(undo_action);
|
||||
}
|
||||
|
||||
void map_editor::draw_terrain(const gamemap::TERRAIN terrain,
|
||||
|
@ -580,12 +658,12 @@ void map_editor::middle_button_down(const int mousex, const int mousey) {
|
|||
|
||||
|
||||
bool map_editor::confirm_exit_and_save() {
|
||||
if (gui::show_dialog(gui_, NULL, "",
|
||||
if (gui::show_dialog(gui_, NULL, "Exit?",
|
||||
"Do you want to exit the map editor?", gui::YES_NO) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (changed_since_save() &&
|
||||
gui::show_dialog(gui_, NULL, "",
|
||||
gui::show_dialog(gui_, NULL, "Save?",
|
||||
"Do you want to save the map before exiting?", gui::YES_NO) == 0) {
|
||||
if (!save_map("", false)) {
|
||||
return false;
|
||||
|
@ -718,8 +796,10 @@ void map_editor::main_loop() {
|
|||
const bool m_button_down = mouse_flags & SDL_BUTTON_MMASK;
|
||||
|
||||
const gamemap::location cur_hex = gui_.hex_clicked_on(mousex,mousey);
|
||||
if (cur_hex != selected_hex_
|
||||
|| last_brush_size != brush_.selected_brush_size()) {
|
||||
if (cur_hex != selected_hex_) {
|
||||
mouse_moved_ = true;
|
||||
}
|
||||
if (mouse_moved_ || last_brush_size != brush_.selected_brush_size()) {
|
||||
// The mouse have moved or the brush size has changed,
|
||||
// adjust the hexes the mouse is over.
|
||||
update_mouse_over_hexes(cur_hex);
|
||||
|
@ -750,6 +830,14 @@ void map_editor::main_loop() {
|
|||
if (l_button_down) {
|
||||
left_button_down(mousex, mousey);
|
||||
}
|
||||
else {
|
||||
if (l_button_func_ == MOVE_SELECTION) {
|
||||
// When it is detected that the mouse is no longer down
|
||||
// and we are in the progress of moving a selection,
|
||||
// perform the movement.
|
||||
perform_selection_move();
|
||||
}
|
||||
}
|
||||
if (r_button_down) {
|
||||
right_button_down(mousex, mousey);
|
||||
}
|
||||
|
@ -787,6 +875,7 @@ void map_editor::main_loop() {
|
|||
set_abort(DONT_ABORT);
|
||||
}
|
||||
}
|
||||
mouse_moved_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,15 @@ private:
|
|||
/// Insert the currently selected locations in the clipboard.
|
||||
void insert_selection_in_clipboard();
|
||||
|
||||
/// Return the hex with the given offset from loc. Make calculations
|
||||
/// so the result with have the same _appearance_ as when the offset
|
||||
/// was calculated ,not the same representation.
|
||||
gamemap::location get_hex_with_offset(const gamemap::location loc,
|
||||
const int x_offset, const int y_offset);
|
||||
|
||||
/// Commit the movement of a selection.
|
||||
void perform_selection_move();
|
||||
|
||||
struct clipboard_item {
|
||||
clipboard_item(int xo, int yo, gamemap::TERRAIN t) :
|
||||
x_offset(xo), y_offset(yo), terrain(t) {}
|
||||
|
@ -214,6 +223,10 @@ private:
|
|||
gamemap::TERRAIN terrain;
|
||||
};
|
||||
|
||||
/// What to perform while the left button is held down.
|
||||
enum LEFT_BUTTON_FUNC {DRAW_TERRAIN, ADD_SELECTION, REMOVE_SELECTION,
|
||||
MOVE_SELECTION, NONE};
|
||||
|
||||
display &gui_;
|
||||
gamemap &map_;
|
||||
gui::button tup_, tdown_;
|
||||
|
@ -228,7 +241,6 @@ private:
|
|||
size_specs size_specs_;
|
||||
config &theme_;
|
||||
config &game_config_;
|
||||
bool draw_terrain_;
|
||||
CKey key_;
|
||||
gamemap::location selected_hex_;
|
||||
// When map_dirty_ is true, schedule redraw of the minimap and
|
||||
|
@ -240,9 +252,14 @@ private:
|
|||
std::vector<gamemap::location> starting_positions_;
|
||||
std::set<gamemap::location> mouse_over_hexes_;
|
||||
std::set<gamemap::location> selected_hexes_;
|
||||
bool add_selection_;
|
||||
std::vector<clipboard_item> clipboard_;
|
||||
gamemap::location clipboard_offset_loc_;
|
||||
LEFT_BUTTON_FUNC l_button_func_;
|
||||
gamemap::location selection_move_start_;
|
||||
// mouse_moved_ will be true if the mouse have moved between two
|
||||
// cycles.
|
||||
bool mouse_moved_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue