The Battle for Wesnoth  1.15.12+dev
mouse_action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Tomasz Sniatowski <kailoran@gmail.com>
3  Part of the Battle for Wesnoth Project https://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"
23 
24 namespace editor {
25 
27 {
28  return false;
29 }
30 
32 {
33  if (hex != previous_move_hex_) {
34  update_brush_highlights(disp, hex);
35  previous_move_hex_ = hex;
36  }
37 }
38 
40 {
41  disp.set_brush_locs(affected_hexes(disp, hex));
42 }
43 
44 std::set<map_location> mouse_action::affected_hexes(
45  editor_display& /*disp*/, const map_location& hex)
46 {
47  std::set<map_location> res;
48  res.insert(hex);
49  return res;
50 }
51 
52 std::unique_ptr<editor_action> mouse_action::drag_left(editor_display& /*disp*/,
53  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
54 {
55  return nullptr;
56 }
57 
58 std::unique_ptr<editor_action> mouse_action::drag_right(editor_display& /*disp*/,
59  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
60 {
61  return nullptr;
62 }
63 
64 std::unique_ptr<editor_action> mouse_action::drag_end_left(
65  editor_display& /*disp*/, int /*x*/, int /*y*/)
66 {
67  return nullptr;
68 }
69 
70 std::unique_ptr<editor_action> mouse_action::drag_end_right(
71  editor_display& /*disp*/, int /*x*/, int /*y*/)
72 {
73  return nullptr;
74 }
75 
76 std::unique_ptr<editor_action> mouse_action::up_right(
77  editor_display& /*disp*/, int /*x*/, int /*y*/)
78 {
79  return nullptr;
80 }
81 
82 std::unique_ptr<editor_action> mouse_action::up_left(
83  editor_display& /*disp*/, int /*x*/, int /*y*/)
84 {
85  return nullptr;
86 }
87 
88 std::unique_ptr<editor_action> mouse_action::key_event(
89  editor_display& disp, const SDL_Event& event)
90 {
91  if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) {
92  int side = event.key.keysym.sym - '0';
93  if (side >= 1 && side <= gamemap::MAX_PLAYERS) {
94  map_location pos = disp.get_map().starting_position(side);
95  if (pos.valid()) {
96  disp.scroll_to_tile(pos, display::WARP);
97  }
98  }
99  return nullptr;
100  }
101  if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) {
102  return nullptr;
103  }
104  std::unique_ptr<editor_action> a;
105  if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9'))
106  || event.key.keysym.sym == SDLK_DELETE) {
107  int res = event.key.keysym.sym - '0';
108  if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0;
109  const std::string* old_id = disp.map().is_special_location(previous_move_hex_);
110  if (res == 0 && old_id != nullptr) {
111  a = std::make_unique<editor_action_starting_position>(map_location(), *old_id);
112  } else if (res > 0 && (old_id == nullptr || *old_id == std::to_string(res))) {
113  a = std::make_unique<editor_action_starting_position>(previous_move_hex_, std::to_string(res));
114  }
115  }
116  return a;
117 }
118 
120 {
121  disp.set_mouseover_hex_overlay(nullptr);
122 }
123 
125 {
126  return key_[SDLK_RALT] || key_[SDLK_LALT];
127 }
128 
130 {
131  return key_[SDLK_RSHIFT] || key_[SDLK_LSHIFT];
132 }
133 
135 {
136 #ifdef __APPLE__
137  return key_[SDLK_RGUI] || key_[SDLK_LGUI];
138 #else
139  return key_[SDLK_RCTRL] || key_[SDLK_LCTRL];
140 #endif
141 }
142 
144  const t_translation::terrain_code & bg)
145 {
148 
149  if (image_fg == nullptr || image_bg == nullptr) {
150  ERR_ED << "Missing terrain icon" << std::endl;
151  disp.set_mouseover_hex_overlay(nullptr);
152  return;
153  }
154 
155  // Create a transparent surface of the right size.
156  surface image(image_fg->w, image_fg->h);
157 
158  // For efficiency the size of the tile is cached.
159  // We assume all tiles are of the same size.
160  // The zoom factor can change, so it's not cached.
161  // NOTE: when zooming and not moving the mouse, there are glitches.
162  // Since the optimal alpha factor is unknown, it has to be calculated
163  // on the fly, and caching the surfaces makes no sense yet.
164  static const fixed_t alpha = 196;
165  static const int size = image_fg->w;
166  static const int half_size = size / 2;
167  static const int quarter_size = size / 4;
168  static const int offset = 2;
169  static const int new_size = half_size - 2;
170 
171  // Blit left side
172  image_fg = scale_surface(image_fg, new_size, new_size);
173  SDL_Rect rcDestLeft {offset, quarter_size, 0, 0};
174  sdl_blit( image_fg, nullptr, image, &rcDestLeft );
175 
176  // Blit right side
177  image_bg = scale_surface(image_bg, new_size, new_size);
178  SDL_Rect rcDestRight {half_size, quarter_size, 0, 0};
179  sdl_blit( image_bg, nullptr, image, &rcDestRight );
180 
181  //apply mask so the overlay is contained within the mouseover hex
182  image = mask_surface(image, image::get_hexmask());
183 
184  // Add the alpha factor
185  adjust_surface_alpha(image, alpha);
186 
187  // scale the image
188  const unsigned int zoom = disp.hex_size();
189  if (zoom != game_config::tile_size) {
190  image = scale_surface(image, zoom, zoom);
191  }
192 
193  // Set as mouseover
194  disp.set_mouseover_hex_overlay(image);
195 }
196 
198  editor_display& /*disp*/, const map_location& hex)
199 {
200  return get_brush().project(hex);
201 }
202 
203 std::unique_ptr<editor_action> brush_drag_mouse_action::click_left(editor_display& disp, int x, int y)
204 {
205  map_location hex = disp.hex_clicked_on(x, y);
206  previous_drag_hex_ = hex;
207  return click_perform_left(disp, affected_hexes(disp, hex));
208 }
209 
210 std::unique_ptr<editor_action> brush_drag_mouse_action::click_right(editor_display& disp, int x, int y)
211 {
212  map_location hex = disp.hex_clicked_on(x, y);
213  previous_drag_hex_ = hex;
214  return click_perform_right(disp, affected_hexes(disp, hex));
215 }
216 
217 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_left(editor_display& disp,
218  int x, int y, bool& partial, editor_action* last_undo)
219 {
220  return drag_generic<&brush_drag_mouse_action::click_perform_left>(disp, x, y, partial, last_undo);
221 }
222 
223 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_right(editor_display& disp,
224  int x, int y, bool& partial, editor_action* last_undo)
225 {
226  return drag_generic<&brush_drag_mouse_action::click_perform_right>(disp, x, y, partial, last_undo);
227 }
228 
229 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_end(
230  editor_display& /*disp*/, int /*x*/, int /*y*/)
231 {
232  return nullptr;
233 }
234 
235 template <std::unique_ptr<editor_action> (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<map_location>&)>
236 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo)
237 {
238  map_location hex = disp.hex_clicked_on(x, y);
239  move(disp, hex);
240  if (hex != previous_drag_hex_) {
241  editor_action_extendable* last_undo_x = dynamic_cast<editor_action_extendable*>(last_undo);
242  LOG_ED << "Last undo is " << last_undo << " and as x " << last_undo_x << "\n";
243  partial = true;
244  auto a = (this->*perform_func)(disp, affected_hexes(disp, hex));
245  previous_drag_hex_ = hex;
246  return a;
247  } else {
248  return nullptr;
249  }
250 }
251 
253 {
254  assert(brush_);
255  assert(*brush_);
256  return **brush_;
257 }
258 
259 
260 std::unique_ptr<editor_action> mouse_action_paint::click_left(editor_display& disp, int x, int y)
261 {
262  if (has_ctrl_modifier()) {
263  map_location hex = disp.hex_clicked_on(x, y);
264  terrain_palette_.select_fg_item(disp.map().get_terrain(hex));
265  return nullptr;
266  } else {
267  return brush_drag_mouse_action::click_left(disp, x, y);
268  }
269 }
270 
271 std::unique_ptr<editor_action> mouse_action_paint::click_right(editor_display& disp, int x, int y)
272 {
273  if (has_ctrl_modifier()) {
274  map_location hex = disp.hex_clicked_on(x, y);
275  terrain_palette_.select_bg_item(disp.map().get_terrain(hex));
276  return nullptr;
277  } else {
278  return brush_drag_mouse_action::click_right(disp, x, y);
279  }
280 }
281 
282 std::unique_ptr<editor_action> mouse_action_paint::click_perform_left(
283  editor_display& /*disp*/, const std::set<map_location>& hexes)
284 {
285  if (has_ctrl_modifier()) return nullptr;
286  // \todo why is this a chain and not an individual action? I guess that mouse drags were meant
287  // to be optimised with one undo for multiple hexes, but it seems that was never added.
288  auto chain = std::make_unique<editor_action_chain>();
289  chain->append_action(std::make_unique<editor_action_paint_area>(
290  hexes, terrain_palette_.selected_fg_item(), has_shift_modifier()));
291  return chain;
292 }
293 
294 std::unique_ptr<editor_action> mouse_action_paint::click_perform_right(
295  editor_display& /*disp*/, const std::set<map_location>& hexes)
296 {
297  if (has_ctrl_modifier()) return nullptr;
298  // \todo why is this a chain and not an individual action?
299  auto chain = std::make_unique<editor_action_chain>();
300  chain->append_action(std::make_unique<editor_action_paint_area>(
301  hexes, terrain_palette_.selected_bg_item(), has_shift_modifier()));
302  return chain;
303 }
304 
306 {
307  set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
308  terrain_palette_.selected_bg_item());
309 }
310 
311 
312 
313 
314 
316 {
317  return true;
318 }
319 
320 std::set<map_location> mouse_action_paste::affected_hexes(
321  editor_display& /*disp*/, const map_location& hex)
322 {
323  return paste_.get_offset_area(hex);
324 }
325 
326 std::unique_ptr<editor_action> mouse_action_paste::click_left(editor_display& disp, int x, int y)
327 {
328  map_location hex = disp.hex_clicked_on(x, y);
329  return std::make_unique<editor_action_paste>(paste_, hex);
330 }
331 
332 std::unique_ptr<editor_action> mouse_action_paste::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
333 {
334  return nullptr;
335 }
336 
338 {
339  surface image60 = image::get_image("icons/action/editor-paste_60.png");
340 
341  //TODO avoid hardcoded hex field size
342  surface image(72,72);
343 
344  SDL_Rect r {6, 6, 0, 0};
345  sdl_blit(image60, nullptr, image, &r);
346 
347  uint8_t alpha = 196;
348  int size = image->w;
349  int zoom = static_cast<int>(size * disp.get_zoom_factor());
350 
351  // Add the alpha factor and scale the image
352  adjust_surface_alpha(image, alpha);
353  image = scale_surface(image, zoom, zoom);
354  disp.set_mouseover_hex_overlay(image);
355 }
356 
357 std::set<map_location> mouse_action_fill::affected_hexes(
358  editor_display& disp, const map_location& hex)
359 {
360  return disp.map().get_contiguous_terrain_tiles(hex);
361 }
362 
363 std::unique_ptr<editor_action> mouse_action_fill::click_left(editor_display& disp, int x, int y)
364 {
365  map_location hex = disp.hex_clicked_on(x, y);
366  if (has_ctrl_modifier()) {
367  terrain_palette_.select_fg_item(disp.map().get_terrain(hex));
368  return nullptr;
369  } else {
370  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
371  //or use a different key modifier for that
372  return std::make_unique<editor_action_fill>(hex, terrain_palette_.selected_fg_item(),
374  }
375 }
376 
377 std::unique_ptr<editor_action> mouse_action_fill::click_right(editor_display& disp, int x, int y)
378 {
379  map_location hex = disp.hex_clicked_on(x, y);
380  if (has_ctrl_modifier()) {
381  terrain_palette_.select_bg_item(disp.map().get_terrain(hex));
382  return nullptr;
383  } else {
384  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
385  //or use a different key modifier for that
386  return std::make_unique<editor_action_fill>(hex, terrain_palette_.selected_bg_item(),
388  }
389 }
390 
392 {
393  set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
394  terrain_palette_.selected_bg_item());
395 }
396 
397 std::unique_ptr<editor_action> mouse_action_starting_position::up_left(editor_display& disp, int x, int y)
398 {
399  if (!click_) return nullptr;
400  click_ = false;
401  map_location hex = disp.hex_clicked_on(x, y);
402  if (!disp.map().on_board(hex)) {
403  return nullptr;
404  }
405  auto player_starting_at_hex = disp.map().is_special_location(hex);
406 
407  if (has_ctrl_modifier()) {
408  if (player_starting_at_hex) {
409  location_palette_.add_item(*player_starting_at_hex);
410  }
411  return nullptr;
412  }
413 
414  std::string new_player_at_hex = location_palette_.selected_item();
415  std::unique_ptr<editor_action> a;
416 
417  if(!player_starting_at_hex || new_player_at_hex != *player_starting_at_hex) {
418  // Set a starting position
419  a = std::make_unique<editor_action_starting_position>(hex, new_player_at_hex);
420  }
421  else {
422  // Erase current starting position
423  a = std::make_unique<editor_action_starting_position>(map_location(), *player_starting_at_hex);
424  }
425 
426  update_brush_highlights(disp, hex);
427 
428  return a;
429 }
430 
431 std::unique_ptr<editor_action> mouse_action_starting_position::click_left(editor_display& /*disp*/, int /*x*/, int /*y*/)
432 {
433  click_ = true;
434  return nullptr;
435 }
436 
437 std::unique_ptr<editor_action> mouse_action_starting_position::up_right(editor_display& disp, int x, int y)
438 {
439  map_location hex = disp.hex_clicked_on(x, y);
440  auto player_starting_at_hex = disp.map().is_special_location(hex);
441  if (player_starting_at_hex != nullptr) {
442  return std::make_unique<editor_action_starting_position>(map_location(), *player_starting_at_hex);
443  } else {
444  return nullptr;
445  }
446 }
447 
448 std::unique_ptr<editor_action> mouse_action_starting_position::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
449 {
450  return nullptr;
451 }
452 
454 {
455  surface image60 = image::get_image("icons/action/editor-tool-starting-position_60.png");
456 
457  //TODO avoid hardcoded hex field size
458  surface image(72,72);
459 
460  SDL_Rect r {6, 6, 0, 0};
461  sdl_blit(image60, nullptr, image, &r);
462 
463  uint8_t alpha = 196;
464  int size = image->w;
465  int zoom = static_cast<int>(size * disp.get_zoom_factor());
466 
467  // Add the alpha factor and scale the image
468  adjust_surface_alpha(image, alpha);
469  image = scale_surface(image, zoom, zoom);
470  disp.set_mouseover_hex_overlay(image);
471 }
472 
473 
474 } //end namespace editor
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
Definition: picture.cpp:815
const editor_map & map() const
virtual std::unique_ptr< editor_action > drag_end_left(editor_display &disp, int x, int y)
The end of dragging.
std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y) override
Right click does nothing for now.
const CKey & key_
Key presses, used for modifiers (alt, shift) in some operations.
std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y) override
Return a paste with offset action.
const brush & get_brush()
Brush accessor.
map_location previous_move_hex_
The hex previously used in move operations.
static int hex_size()
Function which returns the size of a hex in pixels (from top tip to bottom tip or left edge to right ...
Definition: display.hpp:257
const std::string * is_special_location(const map_location &loc) const
returns the name of the special location at position loc, null if no such location exists...
Definition: map.cpp:352
map_location starting_position(int side) const
Definition: map.cpp:319
std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y) override
Handle terrain sampling before calling generic handler.
std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y) override
Left / right click fills with the respective terrain.
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:596
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:260
#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)
#define LOG_ED
std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y) override
A click, possibly the beginning of a drag.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:97
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.
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:196
const std::string & editor_image() const
Definition: terrain.hpp:46
std::unique_ptr< editor_action > up_right(editor_display &disp, int x, int y) override
Right click only erases the starting position if there is one.
virtual std::unique_ptr< editor_action > up_right(editor_display &disp, int x, int y)
std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y) override
Handle terrain sampling before calling generic handler.
virtual std::unique_ptr< editor_action > drag_end_right(editor_display &disp, int x, int y)
static const int MAX_PLAYERS
Maximum number of players supported.
Definition: map.hpp:44
std::unique_ptr< 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.
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:1133
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
void adjust_surface_alpha(surface &surf, fixed_t amount)
Definition: utils.cpp:1086
virtual std::unique_ptr< 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.
virtual bool has_context_menu() const
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:297
virtual void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this action.
bool valid() const
Definition: location.hpp:88
bool has_shift_modifier() const
virtual void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this 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:113
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
void set_mouseover_hex_overlay(const surface &image)
mouseover_hex_overlay_ require a prerendered surface and is drawn underneath the mouse&#39;s location ...
Definition: display.hpp:445
Manage the empty-palette in the editor.
Definition: action.cpp:29
int32_t fixed_t
Definition: math.hpp:312
std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y) override
A click, possibly the beginning of a drag.
Encapsulates the map of the game.
Definition: location.hpp:37
virtual bool has_context_menu() const override
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex) override
Tiles that will be painted to, possibly use modifier keys here.
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:2191
virtual void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this action.
Base class for all editor actions.
Definition: action_base.hpp:40
surface get_hexmask()
Retrieves the standard hexagonal tile mask.
Definition: picture.cpp:940
std::unique_ptr< 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.
std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y) override
Left / right click fills with the respective terrain.
Base class for actions that: 1) operate on an area 2) can be used as undo for a click-drag operation ...
Definition: action.hpp:59
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:380
std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y)
Calls click_perform_left()
virtual std::unique_ptr< editor_action > up_left(editor_display &disp, int x, int y)
virtual void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
std::unique_ptr< editor_action > up_left(editor_display &disp, int x, int y) override
Left click displays a player-number-selector dialog and then creates an action or returns nullptr if ...
const gamemap & get_map() const
Definition: display.hpp:94
unsigned int tile_size
Definition: game_config.cpp:67
virtual void move(editor_display &disp, const map_location &hex)
Mouse move (not a drag).
#define ERR_ED
std::unique_ptr< editor_action > click_perform_right(editor_display &disp, const std::set< map_location > &hexes) override
Create an appropriate editor_action and return it.
Functions to load and save images from/to disk.
bool has_ctrl_modifier() const
virtual std::unique_ptr< editor_action > drag_left(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex) override
Show an outline of where the paste will go.
std::unique_ptr< editor_action > click_perform_left(editor_display &disp, const std::set< map_location > &hexes) override
Create an appropriate editor_action and return it.
std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y)
Calls click_perform_right()
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.
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:31
std::unique_ptr< 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.
virtual std::unique_ptr< editor_action > drag_right(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
std::unique_ptr< editor_action > drag_end(editor_display &disp, int x, int y)
End of dragging.
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 ...
bool has_alt_modifier() const