editor/action/mouse/mouse_action.cpp

Go to the documentation of this file.
00001 /* $Id: mouse_action.cpp 53695 2012-03-30 15:42:21Z fendrin $ */
00002 /*
00003    Copyright (C) 2008 - 2012 by Tomasz Sniatowski <kailoran@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 #define GETTEXT_DOMAIN "wesnoth-editor"
00016 
00017 #include "editor/action/action.hpp"
00018 #include "editor/toolkit/brush.hpp"
00019 #include "../../editor_display.hpp"
00020 #include "mouse_action.hpp"
00021 
00022 #include "construct_dialog.hpp"
00023 #include "gettext.hpp"
00024 #include "gui/dialogs/editor_set_starting_position.hpp"
00025 #include "editor/palette/terrain_palettes.hpp"
00026 
00027 namespace editor {
00028 
00029 bool mouse_action::has_context_menu() const
00030 {
00031     return false;
00032 }
00033 
00034 void mouse_action::move(editor_display& disp, const map_location& hex)
00035 {
00036     if (hex != previous_move_hex_) {
00037         update_brush_highlights(disp, hex);
00038         previous_move_hex_ = hex;
00039     }
00040 }
00041 
00042 void mouse_action::update_brush_highlights(editor_display& disp, const map_location& hex)
00043 {
00044     disp.set_brush_locs(affected_hexes(disp, hex));
00045 }
00046 
00047 std::set<map_location> mouse_action::affected_hexes(
00048         editor_display& /*disp*/, const map_location& hex)
00049 {
00050     std::set<map_location> res;
00051     res.insert(hex);
00052     return res;
00053 }
00054 
00055 editor_action* mouse_action::drag_left(editor_display& /*disp*/,
00056         int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
00057 {
00058     return NULL;
00059 }
00060 
00061 editor_action* mouse_action::drag_right(editor_display& /*disp*/,
00062         int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
00063 {
00064     return NULL;
00065 }
00066 
00067 editor_action* mouse_action::drag_end(
00068         editor_display& /*disp*/, int /*x*/, int /*y*/)
00069 {
00070     return NULL;
00071 }
00072 
00073 editor_action* mouse_action::up_right(
00074         editor_display& /*disp*/, int /*x*/, int /*y*/)
00075 {
00076     return NULL;
00077 }
00078 
00079 editor_action* mouse_action::up_left(
00080         editor_display& /*disp*/, int /*x*/, int /*y*/)
00081 {
00082     return NULL;
00083 }
00084 
00085 editor_action* mouse_action::key_event(
00086     editor_display& disp, const SDL_Event& event)
00087 {
00088     if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) {
00089         int side = event.key.keysym.sym - '0';
00090         if (side >= 1 && side <= gamemap::MAX_PLAYERS) {
00091             map_location pos = disp.get_map().starting_position(side);
00092             if (pos.valid()) {
00093                 disp.scroll_to_tile(pos, display::WARP);
00094             }
00095         }
00096         return NULL;
00097     }
00098     if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) {
00099         return NULL;
00100     }
00101     editor_action* a = NULL;
00102     if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9'))
00103     || event.key.keysym.sym == SDLK_DELETE) {
00104         int res = event.key.keysym.sym - '0';
00105         if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0;
00106         int player_starting_at_hex = disp.map().is_starting_position(previous_move_hex_) + 1;
00107         if (res == 0 && player_starting_at_hex != -1) {
00108             a = new editor_action_starting_position(map_location(), player_starting_at_hex);
00109         } else if (res > 0 && res != player_starting_at_hex) {
00110             a = new editor_action_starting_position(previous_move_hex_, res);
00111         }
00112     }
00113     return a;
00114 }
00115 
00116 void mouse_action::set_mouse_overlay(editor_display& disp)
00117 {
00118     disp.set_mouseover_hex_overlay(NULL);
00119 }
00120 
00121 bool mouse_action::has_alt_modifier() const
00122 {
00123     return key_[SDLK_RALT] || key_[SDLK_LALT];
00124 }
00125 
00126 bool mouse_action::has_shift_modifier() const
00127 {
00128     return key_[SDLK_RSHIFT] || key_[SDLK_LSHIFT];
00129 }
00130 
00131 bool mouse_action::has_ctrl_modifier() const
00132 {
00133 #ifdef __APPLE__
00134     return key_[SDLK_RMETA] || key_[SDLK_LMETA];
00135 #else
00136     return key_[SDLK_RCTRL] || key_[SDLK_LCTRL];
00137 #endif
00138 }
00139 
00140 void mouse_action::set_terrain_mouse_overlay(editor_display& disp, t_translation::t_terrain fg,
00141         t_translation::t_terrain bg)
00142 {
00143     surface image_fg(image::get_image("terrain/"
00144         + disp.get_map().get_terrain_info(fg).editor_image() + ".png"));
00145     surface image_bg(image::get_image("terrain/"
00146         + disp.get_map().get_terrain_info(bg).editor_image() + ".png"));
00147 
00148     if (image_fg == NULL || image_bg == NULL) {
00149         ERR_ED << "Missing terrain icon\n";
00150         disp.set_mouseover_hex_overlay(NULL);
00151         return;
00152     }
00153 
00154     // Create a transparent surface of the right size.
00155     surface image = create_compatible_surface(image_fg, image_fg->w, image_fg->h);
00156     sdl_fill_rect(image,NULL,SDL_MapRGBA(image->format,0,0,0, 0));
00157 
00158     // For efficiency the size of the tile is cached.
00159     // We assume all tiles are of the same size.
00160     // The zoom factor can change, so it's not cached.
00161     // NOTE: when zooming and not moving the mouse, there are glitches.
00162     // Since the optimal alpha factor is unknown, it has to be calculated
00163     // on the fly, and caching the surfaces makes no sense yet.
00164     static const Uint8 alpha = 196;
00165     static const int size = image_fg->w;
00166     static const int half_size = size / 2;
00167     static const int quarter_size = size / 4;
00168     static const int offset = 2;
00169     static const int new_size = half_size - 2;
00170     const int zoom = static_cast<int>(size * disp.get_zoom_factor());
00171 
00172     // Blit left side
00173     image_fg = scale_surface(image_fg, new_size, new_size);
00174     SDL_Rect rcDestLeft = create_rect(offset, quarter_size, 0, 0);
00175     sdl_blit ( image_fg, NULL, image, &rcDestLeft );
00176 
00177     // Blit left side
00178     image_bg = scale_surface(image_bg, new_size, new_size);
00179     SDL_Rect rcDestRight = create_rect(half_size, quarter_size, 0, 0);
00180     sdl_blit ( image_bg, NULL, image, &rcDestRight );
00181 
00182     //apply mask so the overlay is contained within the mouseover hex
00183     image = mask_surface(image, image::get_hexmask());
00184 
00185     // Add the alpha factor and scale the image
00186     image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);
00187 
00188     // Set as mouseover
00189     disp.set_mouseover_hex_overlay(image);
00190 }
00191 
00192 std::set<map_location> brush_drag_mouse_action::affected_hexes(
00193     editor_display& /*disp*/, const map_location& hex)
00194 {
00195     return get_brush().project(hex);
00196 }
00197 
00198 editor_action* brush_drag_mouse_action::click_left(editor_display& disp, int x, int y)
00199 {
00200     map_location hex = disp.hex_clicked_on(x, y);
00201     previous_drag_hex_ = hex;
00202     return click_perform_left(disp, affected_hexes(disp, hex));
00203 }
00204 
00205 editor_action* brush_drag_mouse_action::click_right(editor_display& disp, int x, int y)
00206 {
00207     map_location hex = disp.hex_clicked_on(x, y);
00208     previous_drag_hex_ = hex;
00209     return click_perform_right(disp, affected_hexes(disp, hex));
00210 }
00211 
00212 editor_action* brush_drag_mouse_action::drag_left(editor_display& disp,
00213         int x, int y, bool& partial, editor_action* last_undo)
00214 {
00215     return drag_generic<&brush_drag_mouse_action::click_perform_left>(disp, x, y, partial, last_undo);
00216 }
00217 
00218 editor_action* brush_drag_mouse_action::drag_right(editor_display& disp,
00219         int x, int y, bool& partial, editor_action* last_undo)
00220 {
00221     return drag_generic<&brush_drag_mouse_action::click_perform_right>(disp, x, y, partial, last_undo);
00222 }
00223 
00224 editor_action* brush_drag_mouse_action::drag_end(
00225         editor_display& /*disp*/, int /*x*/, int /*y*/)
00226 {
00227     return NULL;
00228 }
00229 
00230 template <editor_action* (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<map_location>&)>
00231 editor_action* brush_drag_mouse_action::drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo)
00232 {
00233     map_location hex = disp.hex_clicked_on(x, y);
00234     move(disp, hex);
00235     if (hex != previous_drag_hex_) {
00236         std::set<map_location> current_step_locs = affected_hexes(disp, hex);
00237         editor_action_extendable* last_undo_x = dynamic_cast<editor_action_extendable*>(last_undo);
00238         LOG_ED << "Last undo is " << last_undo << " and as x " << last_undo_x << "\n";
00239         partial = true;
00240         editor_action* a = (this->*perform_func)(disp, affected_hexes(disp, hex));
00241         previous_drag_hex_ = hex;
00242         return a;
00243     } else {
00244         return NULL;
00245     }
00246 }
00247 
00248 const brush& brush_drag_mouse_action::get_brush()
00249 {
00250     assert(brush_);
00251     assert(*brush_);
00252     return **brush_;
00253 }
00254 
00255 
00256 editor_action* mouse_action_paint::click_left(editor_display& disp, int x, int y)
00257 {
00258     if (has_ctrl_modifier()) {
00259         map_location hex = disp.hex_clicked_on(x, y);
00260         set_selected_fg_terrain(disp.map().get_terrain(hex));
00261         return NULL;
00262     } else {
00263         return brush_drag_mouse_action::click_left(disp, x, y);
00264     }
00265 }
00266 
00267 editor_action* mouse_action_paint::click_right(editor_display& disp, int x, int y)
00268 {
00269     if (has_ctrl_modifier()) {
00270         map_location hex = disp.hex_clicked_on(x, y);
00271         set_selected_bg_terrain(disp.map().get_terrain(hex));
00272         return NULL;
00273     } else {
00274         return brush_drag_mouse_action::click_right(disp, x, y);
00275     }
00276 }
00277 
00278 editor_action* mouse_action_paint::click_perform_left(
00279         editor_display& /*disp*/, const std::set<map_location>& hexes)
00280 {
00281     if (has_ctrl_modifier()) return NULL;
00282     return new editor_action_chain(new editor_action_paint_area(
00283             hexes, terrain_palette_.selected_fg_item(), has_shift_modifier()));
00284 }
00285 
00286 editor_action* mouse_action_paint::click_perform_right(
00287         editor_display& /*disp*/, const std::set<map_location>& hexes)
00288 {
00289     if (has_ctrl_modifier()) return NULL;
00290     return new editor_action_chain(new editor_action_paint_area(
00291             hexes, terrain_palette_.selected_bg_item(), has_shift_modifier()));
00292 }
00293 
00294 void mouse_action_paint::set_mouse_overlay(editor_display& disp)
00295 {
00296     set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
00297             terrain_palette_.selected_bg_item());
00298 }
00299 
00300 
00301 std::set<map_location> mouse_action_select::affected_hexes(
00302     editor_display& disp, const map_location& hex)
00303 {
00304     if (has_shift_modifier()) {
00305         return disp.map().get_contiguous_terrain_tiles(hex);
00306     } else {
00307         return brush_drag_mouse_action::affected_hexes(disp, hex);
00308     }
00309 }
00310 
00311 editor_action* mouse_action_select::key_event(
00312         editor_display& disp, const SDL_Event& event)
00313 {
00314     editor_action* ret = mouse_action::key_event(disp, event);
00315     update_brush_highlights(disp, previous_move_hex_);
00316     return ret;
00317 }
00318 
00319 editor_action* mouse_action_select::click_perform_left(
00320         editor_display& /*disp*/, const std::set<map_location>& hexes)
00321 {
00322     return new editor_action_chain(new editor_action_select(hexes));
00323 }
00324 
00325 editor_action* mouse_action_select::click_perform_right(
00326         editor_display& /*disp*/, const std::set<map_location>& hexes)
00327 {
00328     return new editor_action_chain(new editor_action_deselect(hexes));
00329 }
00330 
00331 void mouse_action_select::set_mouse_overlay(editor_display& disp)
00332 {
00333     surface image;
00334     if (has_shift_modifier()) {
00335         image = image::get_image("editor/tool-overlay-select-wand.png");
00336     } else {
00337         image = image::get_image("editor/tool-overlay-select-brush.png");
00338     }
00339     Uint8 alpha = 196;
00340     int size = image->w;
00341     int zoom = static_cast<int>(size * disp.get_zoom_factor());
00342 
00343     // Add the alpha factor and scale the image
00344     image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);
00345     disp.set_mouseover_hex_overlay(image);
00346 }
00347 
00348 
00349 bool mouse_action_paste::has_context_menu() const
00350 {
00351     return true;
00352 }
00353 
00354 std::set<map_location> mouse_action_paste::affected_hexes(
00355     editor_display& /*disp*/, const map_location& hex)
00356 {
00357     return paste_.get_offset_area(hex);
00358 }
00359 
00360 editor_action* mouse_action_paste::click_left(editor_display& disp, int x, int y)
00361 {
00362     map_location hex = disp.hex_clicked_on(x, y);
00363     editor_action_paste* a = new editor_action_paste(paste_, hex);
00364     return a;
00365 }
00366 
00367 editor_action* mouse_action_paste::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
00368 {
00369     return NULL;
00370 }
00371 
00372 void mouse_action_paste::set_mouse_overlay(editor_display& disp)
00373 {
00374     disp.set_mouseover_hex_overlay(NULL); //TODO
00375 }
00376 
00377 std::set<map_location> mouse_action_fill::affected_hexes(
00378     editor_display& disp, const map_location& hex)
00379 {
00380     return disp.map().get_contiguous_terrain_tiles(hex);
00381 }
00382 
00383 editor_action* mouse_action_fill::click_left(editor_display& disp, int x, int y)
00384 {
00385     map_location hex = disp.hex_clicked_on(x, y);
00386     if (has_ctrl_modifier()) {
00387         set_selected_fg_terrain(disp.map().get_terrain(hex));
00388         return NULL;
00389     } else {
00390         //TODO only take the base terrain into account when searching for contiguous terrain when painting base only
00391         //or use a different key modifier for that
00392         editor_action_fill* a = new editor_action_fill(hex, terrain_palette_.selected_fg_item(),
00393                 has_shift_modifier());
00394         return a;
00395     }
00396 }
00397 
00398 editor_action* mouse_action_fill::click_right(editor_display& disp, int x, int y)
00399 {
00400     map_location hex = disp.hex_clicked_on(x, y);
00401     if (has_ctrl_modifier()) {
00402         set_selected_bg_terrain(disp.map().get_terrain(hex));
00403         return NULL;
00404     } else {
00405         //TODO only take the base terrain into account when searching for contiguous terrain when painting base only
00406         //or use a different key modifier for that
00407         editor_action_fill* a = new editor_action_fill(hex, terrain_palette_.selected_bg_item(),
00408                 has_shift_modifier());
00409         return a;
00410     }
00411 }
00412 
00413 void mouse_action_fill::set_mouse_overlay(editor_display& disp)
00414 {
00415     set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
00416             terrain_palette_.selected_bg_item());
00417 }
00418 
00419 editor_action* mouse_action_starting_position::up_left(editor_display& disp, int x, int y)
00420 {
00421     if (!click_) return NULL;
00422     click_ = false;
00423     map_location hex = disp.hex_clicked_on(x, y);
00424     if (!disp.map().on_board(hex)) {
00425         return NULL;
00426     }
00427 
00428     const unsigned player_starting_at_hex =
00429         static_cast<unsigned>(disp.map().is_starting_position(hex) + 1); // 1st player = 1
00430 
00431     std::vector<map_location> starting_positions;
00432 
00433     for(int i = 1; i <= gamemap::MAX_PLAYERS; ++i) {
00434         starting_positions.push_back(disp.map().starting_position(i));
00435     }
00436 
00437     gui2::teditor_set_starting_position dlg(
00438         player_starting_at_hex, gamemap::MAX_PLAYERS, starting_positions);
00439     dlg.show(disp.video());
00440 
00441     unsigned new_player_at_hex = dlg.result(); // 1st player = 1
00442     editor_action* a = NULL;
00443 
00444     if(new_player_at_hex != player_starting_at_hex) {
00445         if(!new_player_at_hex) {
00446             // Erase current starting position
00447             a = new editor_action_starting_position(map_location(), player_starting_at_hex);
00448         } else {
00449             // Set a starting position
00450             a = new editor_action_starting_position(hex, new_player_at_hex);
00451         }
00452     }
00453 
00454     update_brush_highlights(disp, hex);
00455 
00456     return a;
00457 }
00458 
00459 editor_action* mouse_action_starting_position::click_left(editor_display& /*disp*/, int /*x*/, int /*y*/)
00460 {
00461     click_ = true;
00462     return NULL;
00463 }
00464 
00465 editor_action* mouse_action_starting_position::up_right(editor_display& disp, int x, int y)
00466 {
00467     map_location hex = disp.hex_clicked_on(x, y);
00468     int player_starting_at_hex = disp.map().is_starting_position(hex) + 1;
00469     if (player_starting_at_hex != -1) {
00470         return new editor_action_starting_position(map_location(), player_starting_at_hex);
00471     } else {
00472         return NULL;
00473     }
00474 }
00475 
00476 editor_action* mouse_action_starting_position::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
00477 {
00478     return NULL;
00479 }
00480 
00481 void mouse_action_starting_position::set_mouse_overlay(editor_display& disp)
00482 {
00483     surface image = image::get_image("editor/tool-overlay-starting-position.png");
00484     Uint8 alpha = 196;
00485     int size = image->w;
00486     int zoom = static_cast<int>(size * disp.get_zoom_factor());
00487 
00488     // Add the alpha factor and scale the image
00489     image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);
00490     disp.set_mouseover_hex_overlay(image);
00491 }
00492 
00493 
00494 } //end namespace editor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:49 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs