The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
mouse_action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2017 by Tomasz Sniatowski <kailoran@gmail.com>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 #define GETTEXT_DOMAIN "wesnoth-editor"
15 
16 #include "editor/action/action.hpp"
17 #include "editor/toolkit/brush.hpp"
20 
21 #include "gettext.hpp"
24 
25 namespace editor {
26 
28 {
29  return false;
30 }
31 
33 {
34  if (hex != previous_move_hex_) {
35  update_brush_highlights(disp, hex);
36  previous_move_hex_ = hex;
37  }
38 }
39 
41 {
42  disp.set_brush_locs(affected_hexes(disp, hex));
43 }
44 
45 std::set<map_location> mouse_action::affected_hexes(
46  editor_display& /*disp*/, const map_location& hex)
47 {
48  std::set<map_location> res;
49  res.insert(hex);
50  return res;
51 }
52 
54  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
55 {
56  return nullptr;
57 }
58 
60  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
61 {
62  return nullptr;
63 }
64 
66  editor_display& /*disp*/, int /*x*/, int /*y*/)
67 {
68  return nullptr;
69 }
70 
72  editor_display& /*disp*/, int /*x*/, int /*y*/)
73 {
74  return nullptr;
75 }
76 
78  editor_display& /*disp*/, int /*x*/, int /*y*/)
79 {
80  return nullptr;
81 }
82 
84  editor_display& /*disp*/, int /*x*/, int /*y*/)
85 {
86  return nullptr;
87 }
88 
90  editor_display& disp, const SDL_Event& event)
91 {
92  if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) {
93  int side = event.key.keysym.sym - '0';
94  if (side >= 1 && side <= gamemap::MAX_PLAYERS) {
95  map_location pos = disp.get_map().starting_position(side);
96  if (pos.valid()) {
97  disp.scroll_to_tile(pos, display::WARP);
98  }
99  }
100  return nullptr;
101  }
102  if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) {
103  return nullptr;
104  }
105  editor_action* a = nullptr;
106  if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9'))
107  || event.key.keysym.sym == SDLK_DELETE) {
108  int res = event.key.keysym.sym - '0';
109  if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0;
110  const std::string* old_id = disp.map().is_starting_position(previous_move_hex_);
111  if (res == 0 && old_id != nullptr) {
112  a = new editor_action_starting_position(map_location(), *old_id);
113  } else if (res > 0 && (old_id == nullptr || *old_id == std::to_string(res))) {
114  a = new editor_action_starting_position(previous_move_hex_, std::to_string(res));
115  }
116  }
117  return a;
118 }
119 
121 {
122  disp.set_mouseover_hex_overlay(nullptr);
123 }
124 
126 {
127  return key_[SDLK_RALT] || key_[SDLK_LALT];
128 }
129 
131 {
132  return key_[SDLK_RSHIFT] || key_[SDLK_LSHIFT];
133 }
134 
136 {
137 #ifdef __APPLE__
138  return key_[SDLK_RGUI] || key_[SDLK_LGUI];
139 #else
140  return key_[SDLK_RCTRL] || key_[SDLK_LCTRL];
141 #endif
142 }
143 
145  const t_translation::terrain_code & bg)
146 {
149 
150  if (image_fg == nullptr || image_bg == nullptr) {
151  ERR_ED << "Missing terrain icon" << std::endl;
152  disp.set_mouseover_hex_overlay(nullptr);
153  return;
154  }
155 
156  // Create a transparent surface of the right size.
157  surface image = create_neutral_surface(image_fg->w, image_fg->h);
158 
159  // For efficiency the size of the tile is cached.
160  // We assume all tiles are of the same size.
161  // The zoom factor can change, so it's not cached.
162  // NOTE: when zooming and not moving the mouse, there are glitches.
163  // Since the optimal alpha factor is unknown, it has to be calculated
164  // on the fly, and caching the surfaces makes no sense yet.
165  static const fixed_t alpha = 196;
166  static const int size = image_fg->w;
167  static const int half_size = size / 2;
168  static const int quarter_size = size / 4;
169  static const int offset = 2;
170  static const int new_size = half_size - 2;
171 
172  // Blit left side
173  image_fg = scale_surface(image_fg, new_size, new_size);
174  SDL_Rect rcDestLeft {offset, quarter_size, 0, 0};
175  sdl_blit( image_fg, nullptr, image, &rcDestLeft );
176 
177  // Blit right side
178  image_bg = scale_surface(image_bg, new_size, new_size);
179  SDL_Rect rcDestRight {half_size, quarter_size, 0, 0};
180  sdl_blit( image_bg, nullptr, image, &rcDestRight );
181 
182  //apply mask so the overlay is contained within the mouseover hex
183  image = mask_surface(image, image::get_hexmask());
184 
185  // Add the alpha factor
186  adjust_surface_alpha(image, alpha);
187 
188  // scale the image
189  const unsigned int zoom = disp.hex_size();
190  if (zoom != game_config::tile_size) {
191  image = scale_surface(image, zoom, zoom);
192  }
193 
194  // Set as mouseover
195  disp.set_mouseover_hex_overlay(image);
196 }
197 
199  editor_display& /*disp*/, const map_location& hex)
200 {
201  return get_brush().project(hex);
202 }
203 
205 {
206  map_location hex = disp.hex_clicked_on(x, y);
207  previous_drag_hex_ = hex;
208  return click_perform_left(disp, affected_hexes(disp, hex));
209 }
210 
212 {
213  map_location hex = disp.hex_clicked_on(x, y);
214  previous_drag_hex_ = hex;
215  return click_perform_right(disp, affected_hexes(disp, hex));
216 }
217 
219  int x, int y, bool& partial, editor_action* last_undo)
220 {
221  return drag_generic<&brush_drag_mouse_action::click_perform_left>(disp, x, y, partial, last_undo);
222 }
223 
225  int x, int y, bool& partial, editor_action* last_undo)
226 {
227  return drag_generic<&brush_drag_mouse_action::click_perform_right>(disp, x, y, partial, last_undo);
228 }
229 
231  editor_display& /*disp*/, int /*x*/, int /*y*/)
232 {
233  return nullptr;
234 }
235 
236 template <editor_action* (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<map_location>&)>
238 {
239  map_location hex = disp.hex_clicked_on(x, y);
240  move(disp, hex);
241  if (hex != previous_drag_hex_) {
242  editor_action_extendable* last_undo_x = dynamic_cast<editor_action_extendable*>(last_undo);
243  LOG_ED << "Last undo is " << last_undo << " and as x " << last_undo_x << "\n";
244  partial = true;
245  editor_action* a = (this->*perform_func)(disp, affected_hexes(disp, hex));
246  previous_drag_hex_ = hex;
247  return a;
248  } else {
249  return nullptr;
250  }
251 }
252 
254 {
255  assert(brush_);
256  assert(*brush_);
257  return **brush_;
258 }
259 
260 
262 {
263  if (has_ctrl_modifier()) {
264  map_location hex = disp.hex_clicked_on(x, y);
266  return nullptr;
267  } else {
268  return brush_drag_mouse_action::click_left(disp, x, y);
269  }
270 }
271 
273 {
274  if (has_ctrl_modifier()) {
275  map_location hex = disp.hex_clicked_on(x, y);
277  return nullptr;
278  } else {
279  return brush_drag_mouse_action::click_right(disp, x, y);
280  }
281 }
282 
284  editor_display& /*disp*/, const std::set<map_location>& hexes)
285 {
286  if (has_ctrl_modifier()) return nullptr;
289 }
290 
292  editor_display& /*disp*/, const std::set<map_location>& hexes)
293 {
294  if (has_ctrl_modifier()) return nullptr;
297 }
298 
300 {
303 }
304 
305 
306 
307 
308 
310 {
311  return true;
312 }
313 
314 std::set<map_location> mouse_action_paste::affected_hexes(
315  editor_display& /*disp*/, const map_location& hex)
316 {
317  return paste_.get_offset_area(hex);
318 }
319 
321 {
322  map_location hex = disp.hex_clicked_on(x, y);
324  return a;
325 }
326 
328 {
329  return nullptr;
330 }
331 
333 {
334  surface image60 = image::get_image("icons/action/editor-paste_60.png");
335 
336  //TODO avoid hardcoded hex field size
338 
339  SDL_Rect r {6, 6, 0, 0};
340  sdl_blit(image60, nullptr, image, &r);
341 
342  uint8_t alpha = 196;
343  int size = image->w;
344  int zoom = static_cast<int>(size * disp.get_zoom_factor());
345 
346  // Add the alpha factor and scale the image
347  adjust_surface_alpha(image, alpha);
348  image = scale_surface(image, zoom, zoom);
349  disp.set_mouseover_hex_overlay(image);
350 }
351 
352 std::set<map_location> mouse_action_fill::affected_hexes(
353  editor_display& disp, const map_location& hex)
354 {
355  return disp.map().get_contiguous_terrain_tiles(hex);
356 }
357 
359 {
360  map_location hex = disp.hex_clicked_on(x, y);
361  if (has_ctrl_modifier()) {
363  return nullptr;
364  } else {
365  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
366  //or use a different key modifier for that
369  return a;
370  }
371 }
372 
374 {
375  map_location hex = disp.hex_clicked_on(x, y);
376  if (has_ctrl_modifier()) {
378  return nullptr;
379  } else {
380  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
381  //or use a different key modifier for that
384  return a;
385  }
386 }
387 
389 {
392 }
393 
395 {
396  if (!click_) return nullptr;
397  click_ = false;
398  map_location hex = disp.hex_clicked_on(x, y);
399  if (!disp.map().on_board(hex)) {
400  return nullptr;
401  }
402  auto player_starting_at_hex = disp.map().is_starting_position(hex);
403 
404  if (has_ctrl_modifier()) {
405  if (player_starting_at_hex) {
406  location_palette_.add_item(*player_starting_at_hex);
407  }
408  return nullptr;
409  }
410 
411  std::string new_player_at_hex = location_palette_.selected_item();
412  editor_action* a = nullptr;
413 
414  if(!player_starting_at_hex || new_player_at_hex != *player_starting_at_hex) {
415  // Set a starting position
416  a = new editor_action_starting_position(hex, new_player_at_hex);
417  }
418  else {
419  // Erase current starting position
420  a = new editor_action_starting_position(map_location(), *player_starting_at_hex);
421  }
422 
423  update_brush_highlights(disp, hex);
424 
425  return a;
426 }
427 
429 {
430  click_ = true;
431  return nullptr;
432 }
433 
435 {
436  map_location hex = disp.hex_clicked_on(x, y);
437  auto player_starting_at_hex = disp.map().is_starting_position(hex);
438  if (player_starting_at_hex != nullptr) {
439  return new editor_action_starting_position(map_location(), *player_starting_at_hex);
440  } else {
441  return nullptr;
442  }
443 }
444 
446 {
447  return nullptr;
448 }
449 
451 {
452  surface image60 = image::get_image("icons/action/editor-tool-starting-position_60.png");
453 
454  //TODO avoid hardcoded hex field size
456 
457  SDL_Rect r {6, 6, 0, 0};
458  sdl_blit(image60, nullptr, image, &r);
459 
460  uint8_t alpha = 196;
461  int size = image->w;
462  int zoom = static_cast<int>(size * disp.get_zoom_factor());
463 
464  // Add the alpha factor and scale the image
465  adjust_surface_alpha(image, alpha);
466  image = scale_surface(image, zoom, zoom);
467  disp.set_mouseover_hex_overlay(image);
468 }
469 
470 
471 } //end namespace editor
editor_action * drag_end(editor_display &disp, int x, int y)
End of dragging.
editor_action * click_left(editor_display &disp, int x, int y)
A click, possibly the beginning of a drag.
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:926
terrain_palette & terrain_palette_
virtual void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
virtual editor_action * click_perform_left(editor_display &disp, const std::set< map_location > &hexes)=0
The actual action function which is called by click() and drag().
surface create_neutral_surface(int w, int h)
Definition: utils.cpp:84
bool has_shift_modifier() const
virtual void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
const CKey & key_
Key presses, used for modifiers (alt, shift) in some operations.
std::vector< char_t > string
editor_action * click_perform_right(editor_display &disp, const std::set< map_location > &hexes) override
Create an appropriate editor_action and return it.
editor_action * click_right(editor_display &disp, int x, int y)
A click, possibly the beginning of a drag.
virtual bool has_context_menu() const
const brush & get_brush()
Brush accessor.
map_location previous_move_hex_
The hex previously used in move operations.
const brush *const *const brush_
Current brush handle.
#define a
void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this action.
void set_brush_locs(const std::set< map_location > &hexes)
const t_translation::terrain_code & selected_fg_item() const
#define LOG_ED
editor_action * up_left(editor_display &disp, int x, int y)
Left click displays a player-number-selector dialog and then creates an action or returns nullptr if ...
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:55
const map_location hex_clicked_on(int x, int y) const
given x,y co-ordinates of an onscreen pixel, will return the location of the hex that this pixel corr...
Definition: display.cpp:589
Paste a map fragment into the map.
Definition: action.hpp:255
void set_terrain_mouse_overlay(editor_display &disp, const t_translation::terrain_code &fg, const t_translation::terrain_code &bg)
Helper function for derived classes that need a active-terrain mouse overlay.
double get_zoom_factor() const
Returns the current zoom factor.
Definition: display.hpp:257
Container action wrapping several actions into one.
Definition: action.hpp:90
virtual editor_action * drag_left(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
Definition: utils.cpp:274
bool has_ctrl_modifier() const
Set starting position action.
Definition: action.hpp:340
editor_action * click_left(editor_display &disp, int x, int y) override
Return a paste with offset action.
std::set< map_location > get_contiguous_terrain_tiles(const map_location &start) const
Get a contiguous set of tiles having the same terrain as the starting location.
Definition: editor_map.cpp:116
const std::string & selected_item() const
Return the currently selected item.
map_location previous_drag_hex_
The previous hex dragged into.
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:301
void select_bg_item(const t_translation::terrain_code &terrain)
surface mask_surface(const surface &surf, const surface &mask, bool *empty_result, const std::string &filename)
Applies a mask on a surface.
Definition: utils.cpp:1221
virtual editor_action * up_left(editor_display &disp, int x, int y)
void adjust_surface_alpha(surface &surf, fixed_t amount)
Definition: utils.cpp:1174
virtual editor_action * key_event(editor_display &disp, const SDL_Event &e)
Function called by the controller on a key event for the current mouse action.
const map_fragment & paste_
Reference to the buffer used for pasting (e.g.
std::set< map_location > get_offset_area(const map_location &offset) const
Get the area covered by this map fragment, shifted by an offset.
map_location starting_position(int side) const
Definition: map.cpp:323
bool valid() const
Definition: location.hpp:72
virtual editor_action * drag_right(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
const std::string & editor_image() const
Definition: terrain.hpp:32
editor_action * click_left(editor_display &disp, int x, int y)
Left / right click fills with the respective terrain.
editor_action * up_right(editor_display &disp, int x, int y)
Right click only erases the starting position if there is one.
Editor action classes.
void update_brush_highlights(editor_display &disp, const map_location &hex)
Unconditionally update the brush highlights for the current tool when hex is the center location...
The brush class represents a single brush – a set of relative locations around a "hotspot"...
Definition: brush.hpp:25
editor_action * click_left(editor_display &disp, int x, int y)
Calls click_perform_left()
virtual editor_action * up_right(editor_display &disp, int x, int y)
void set_mouseover_hex_overlay(const surface &image)
mouseover_hex_overlay_ require a prerendered surface and is drawn underneath the mouse's location ...
Definition: display.hpp:437
Manage the empty-palette in the editor.
Definition: action.cpp:29
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
void select_fg_item(const t_translation::terrain_code &terrain)
editor_action * click_right(editor_display &disp, int x, int y) override
Handle terrain sampling before calling generic handler.
int32_t fixed_t
Definition: math.hpp:313
Paint the same terrain on a number of locations on the map.
Definition: action.hpp:284
terrain_palette & terrain_palette_
Encapsulates the map of the game.
Definition: location.hpp:40
virtual bool has_context_menu() const override
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
void add_item(const std::string &id)
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
Definition: display.cpp:2199
virtual void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this action.
bool has_alt_modifier() const
Base class for all editor actions.
Definition: action_base.hpp:40
surface get_hexmask()
function to get the standard hex mask
Definition: image.cpp:1062
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex)
Tiles that will be painted to, possibly use modifier keys here.
editor_action * drag_right(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Calls click_perform for every new hex the mouse is dragged into.
Base class for actions that: 1) operate on an area 2) can be used as undo for a click-drag operation ...
Definition: action.hpp:63
editor_action * drag_generic(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Template helper gathering actions common for both drag_right and drag_left.
virtual void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:369
editor_action * click_left(editor_display &disp, int x, int y) override
Handle terrain sampling before calling generic handler.
editor_action * drag_left(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Calls click_perform() for every new hex the mouse is dragged into.
const gamemap & get_map() const
Definition: display.hpp:92
virtual editor_action * drag_end_left(editor_display &disp, int x, int y)
The end of dragging.
unsigned int tile_size
Definition: game_config.cpp:84
editor_action * click_right(editor_display &disp, int x, int y)
Left / right click fills with the respective terrain.
virtual void move(editor_display &disp, const map_location &hex)
Mouse move (not a drag).
#define ERR_ED
this module manages the cache of images.
Definition: image.cpp:109
const std::string * is_starting_position(const map_location &loc) const
returns the side number of the side starting at position loc, 0 if no such side exists.
Definition: map.cpp:341
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex) override
Show an outline of where the paste will go.
editor_action * click_right(editor_display &disp, int x, int y)
Calls click_perform_right()
editor_action * click_perform_left(editor_display &disp, const std::set< map_location > &hexes) override
Create an appropriate editor_action and return it.
virtual std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex)
Locations that would be affected by a click, used by move to update highlights.
editor_action * click_right(editor_display &disp, int x, int y) override
Right click does nothing for now.
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:33
virtual editor_action * click_perform_right(editor_display &disp, const std::set< map_location > &hexes)=0
The actual action function which is called by click() and drag().
int hex_size() const
Function which returns the size of a hex in pixels (from top tip to bottom tip or left edge to right ...
Definition: display.hpp:254
const t_translation::terrain_code & selected_bg_item() const
virtual editor_action * drag_end_right(editor_display &disp, int x, int y)
const editor_map & map() const
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex)
The affected hexes of a brush action are the result of projecting the current brush on the mouseover ...
std::set< map_location > project(const map_location &hotspot) const
Get a set of locations affected (i.e.
Definition: brush.cpp:95