The Battle for Wesnoth  1.17.0-dev
mouse_action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
3  by Tomasz Sniatowski <kailoran@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-editor"
17 
18 #include "editor/action/action.hpp"
19 #include "editor/toolkit/brush.hpp"
22 
23 #include "gettext.hpp"
25 
26 namespace editor {
27 
29 {
30  return false;
31 }
32 
34 {
35  if (hex != previous_move_hex_) {
36  update_brush_highlights(disp, hex);
37  previous_move_hex_ = hex;
38  }
39 }
40 
42 {
43  disp.set_brush_locs(affected_hexes(disp, hex));
44 }
45 
46 std::set<map_location> mouse_action::affected_hexes(
47  editor_display& /*disp*/, const map_location& hex)
48 {
49  std::set<map_location> res;
50  res.insert(hex);
51  return res;
52 }
53 
54 std::unique_ptr<editor_action> mouse_action::drag_left(editor_display& /*disp*/,
55  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
56 {
57  return nullptr;
58 }
59 
60 std::unique_ptr<editor_action> mouse_action::drag_right(editor_display& /*disp*/,
61  int /*x*/, int /*y*/, bool& /*partial*/, editor_action* /*last_undo*/)
62 {
63  return nullptr;
64 }
65 
66 std::unique_ptr<editor_action> mouse_action::drag_end_left(
67  editor_display& /*disp*/, int /*x*/, int /*y*/)
68 {
69  return nullptr;
70 }
71 
72 std::unique_ptr<editor_action> mouse_action::drag_end_right(
73  editor_display& /*disp*/, int /*x*/, int /*y*/)
74 {
75  return nullptr;
76 }
77 
78 std::unique_ptr<editor_action> mouse_action::up_right(
79  editor_display& /*disp*/, int /*x*/, int /*y*/)
80 {
81  return nullptr;
82 }
83 
84 std::unique_ptr<editor_action> mouse_action::up_left(
85  editor_display& /*disp*/, int /*x*/, int /*y*/)
86 {
87  return nullptr;
88 }
89 
90 std::unique_ptr<editor_action> mouse_action::key_event(
91  editor_display& disp, const SDL_Event& event)
92 {
93  if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) {
94  int side = event.key.keysym.sym - '0';
95  if (side >= 1 && side <= gamemap::MAX_PLAYERS) {
96  map_location pos = disp.get_map().starting_position(side);
97  if (pos.valid()) {
98  disp.scroll_to_tile(pos, display::WARP);
99  }
100  }
101  return nullptr;
102  }
103  if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) {
104  return nullptr;
105  }
106  std::unique_ptr<editor_action> a;
107  if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9'))
108  || event.key.keysym.sym == SDLK_DELETE) {
109  int res = event.key.keysym.sym - '0';
110  if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0;
111  const std::string* old_id = disp.map().is_special_location(previous_move_hex_);
112  if (res == 0 && old_id != nullptr) {
113  a = std::make_unique<editor_action_starting_position>(map_location(), *old_id);
114  } else if (res > 0 && (old_id == nullptr || *old_id == std::to_string(res))) {
115  a = std::make_unique<editor_action_starting_position>(previous_move_hex_, std::to_string(res));
116  }
117  }
118  return a;
119 }
120 
122 {
123  disp.set_mouseover_hex_overlay(nullptr);
124 }
125 
127 {
128  return key_[SDLK_RALT] || key_[SDLK_LALT];
129 }
130 
132 {
133  return key_[SDLK_RSHIFT] || key_[SDLK_LSHIFT];
134 }
135 
137 {
138 #ifdef __APPLE__
139  return key_[SDLK_RGUI] || key_[SDLK_LGUI];
140 #else
141  return key_[SDLK_RCTRL] || key_[SDLK_LCTRL];
142 #endif
143 }
144 
146  const t_translation::terrain_code & bg)
147 {
150 
151  if (image_fg == nullptr || image_bg == nullptr) {
152  ERR_ED << "Missing terrain icon" << std::endl;
153  disp.set_mouseover_hex_overlay(nullptr);
154  return;
155  }
156 
157  // Create a transparent surface of the right size.
158  surface image(image_fg->w, image_fg->h);
159 
160  // For efficiency the size of the tile is cached.
161  // We assume all tiles are of the same size.
162  // The zoom factor can change, so it's not cached.
163  // NOTE: when zooming and not moving the mouse, there are glitches.
164  // Since the optimal alpha factor is unknown, it has to be calculated
165  // on the fly, and caching the surfaces makes no sense yet.
166  static const fixed_t alpha = 196;
167  static const int size = image_fg->w;
168  static const int half_size = size / 2;
169  static const int quarter_size = size / 4;
170  static const int offset = 2;
171  static const int new_size = half_size - 2;
172 
173  // Blit left side
174  image_fg = scale_surface(image_fg, new_size, new_size);
175  SDL_Rect rcDestLeft {offset, quarter_size, 0, 0};
176  sdl_blit( image_fg, nullptr, image, &rcDestLeft );
177 
178  // Blit right side
179  image_bg = scale_surface(image_bg, new_size, new_size);
180  SDL_Rect rcDestRight {half_size, quarter_size, 0, 0};
181  sdl_blit( image_bg, nullptr, image, &rcDestRight );
182 
183  //apply mask so the overlay is contained within the mouseover hex
184  image = mask_surface(image, image::get_hexmask());
185 
186  // Add the alpha factor
187  adjust_surface_alpha(image, alpha);
188 
189  // scale the image
190  const unsigned int zoom = disp.hex_size();
191  if (zoom != game_config::tile_size) {
192  image = scale_surface(image, zoom, zoom);
193  }
194 
195  // Set as mouseover
196  disp.set_mouseover_hex_overlay(image);
197 }
198 
200  editor_display& /*disp*/, const map_location& hex)
201 {
202  return get_brush().project(hex);
203 }
204 
205 std::unique_ptr<editor_action> brush_drag_mouse_action::click_left(editor_display& disp, int x, int y)
206 {
207  map_location hex = disp.hex_clicked_on(x, y);
208  previous_drag_hex_ = hex;
209  return click_perform_left(disp, affected_hexes(disp, hex));
210 }
211 
212 std::unique_ptr<editor_action> brush_drag_mouse_action::click_right(editor_display& disp, int x, int y)
213 {
214  map_location hex = disp.hex_clicked_on(x, y);
215  previous_drag_hex_ = hex;
216  return click_perform_right(disp, affected_hexes(disp, hex));
217 }
218 
219 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_left(editor_display& disp,
220  int x, int y, bool& partial, editor_action* last_undo)
221 {
222  return drag_generic<&brush_drag_mouse_action::click_perform_left>(disp, x, y, partial, last_undo);
223 }
224 
225 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_right(editor_display& disp,
226  int x, int y, bool& partial, editor_action* last_undo)
227 {
228  return drag_generic<&brush_drag_mouse_action::click_perform_right>(disp, x, y, partial, last_undo);
229 }
230 
231 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_end(
232  editor_display& /*disp*/, int /*x*/, int /*y*/)
233 {
234  return nullptr;
235 }
236 
237 template <std::unique_ptr<editor_action> (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<map_location>&)>
238 std::unique_ptr<editor_action> brush_drag_mouse_action::drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo)
239 {
240  map_location hex = disp.hex_clicked_on(x, y);
241  move(disp, hex);
242  if (hex != previous_drag_hex_) {
243  editor_action_extendable* last_undo_x = dynamic_cast<editor_action_extendable*>(last_undo);
244  LOG_ED << "Last undo is " << last_undo << " and as x " << last_undo_x << "\n";
245  partial = true;
246  auto a = (this->*perform_func)(disp, affected_hexes(disp, hex));
247  previous_drag_hex_ = hex;
248  return a;
249  } else {
250  return nullptr;
251  }
252 }
253 
255 {
256  assert(brush_);
257  assert(*brush_);
258  return **brush_;
259 }
260 
261 
262 std::unique_ptr<editor_action> mouse_action_paint::click_left(editor_display& disp, int x, int y)
263 {
264  if (has_ctrl_modifier()) {
265  map_location hex = disp.hex_clicked_on(x, y);
266  terrain_palette_.select_fg_item(disp.map().get_terrain(hex));
267  return nullptr;
268  } else {
269  return brush_drag_mouse_action::click_left(disp, x, y);
270  }
271 }
272 
273 std::unique_ptr<editor_action> mouse_action_paint::click_right(editor_display& disp, int x, int y)
274 {
275  if (has_ctrl_modifier()) {
276  map_location hex = disp.hex_clicked_on(x, y);
277  terrain_palette_.select_bg_item(disp.map().get_terrain(hex));
278  return nullptr;
279  } else {
280  return brush_drag_mouse_action::click_right(disp, x, y);
281  }
282 }
283 
284 std::unique_ptr<editor_action> mouse_action_paint::click_perform_left(
285  editor_display& /*disp*/, const std::set<map_location>& hexes)
286 {
287  if (has_ctrl_modifier()) return nullptr;
288  // \todo why is this a chain and not an individual action? I guess that mouse drags were meant
289  // to be optimised with one undo for multiple hexes, but it seems that was never added.
290  auto chain = std::make_unique<editor_action_chain>();
291  chain->append_action(std::make_unique<editor_action_paint_area>(
292  hexes, terrain_palette_.selected_fg_item(), has_shift_modifier()));
293  return chain;
294 }
295 
296 std::unique_ptr<editor_action> mouse_action_paint::click_perform_right(
297  editor_display& /*disp*/, const std::set<map_location>& hexes)
298 {
299  if (has_ctrl_modifier()) return nullptr;
300  // \todo why is this a chain and not an individual action?
301  auto chain = std::make_unique<editor_action_chain>();
302  chain->append_action(std::make_unique<editor_action_paint_area>(
303  hexes, terrain_palette_.selected_bg_item(), has_shift_modifier()));
304  return chain;
305 }
306 
308 {
309  set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
310  terrain_palette_.selected_bg_item());
311 }
312 
313 
314 
315 
316 
318 {
319  return true;
320 }
321 
322 std::set<map_location> mouse_action_paste::affected_hexes(
323  editor_display& /*disp*/, const map_location& hex)
324 {
325  return paste_.get_offset_area(hex);
326 }
327 
328 std::unique_ptr<editor_action> mouse_action_paste::click_left(editor_display& disp, int x, int y)
329 {
330  map_location hex = disp.hex_clicked_on(x, y);
331  return std::make_unique<editor_action_paste>(paste_, hex);
332 }
333 
334 std::unique_ptr<editor_action> mouse_action_paste::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
335 {
336  return nullptr;
337 }
338 
340 {
341  surface image60 = image::get_image("icons/action/editor-paste_60.png");
342 
343  //TODO avoid hardcoded hex field size
344  surface image(72,72);
345 
346  SDL_Rect r {6, 6, 0, 0};
347  sdl_blit(image60, nullptr, image, &r);
348 
349  uint8_t alpha = 196;
350  int size = image->w;
351  int zoom = static_cast<int>(size * disp.get_zoom_factor());
352 
353  // Add the alpha factor and scale the image
354  adjust_surface_alpha(image, alpha);
355  image = scale_surface(image, zoom, zoom);
356  disp.set_mouseover_hex_overlay(image);
357 }
358 
359 std::set<map_location> mouse_action_fill::affected_hexes(
360  editor_display& disp, const map_location& hex)
361 {
362  return disp.map().get_contiguous_terrain_tiles(hex);
363 }
364 
365 std::unique_ptr<editor_action> mouse_action_fill::click_left(editor_display& disp, int x, int y)
366 {
367  map_location hex = disp.hex_clicked_on(x, y);
368  if (has_ctrl_modifier()) {
369  terrain_palette_.select_fg_item(disp.map().get_terrain(hex));
370  return nullptr;
371  } else {
372  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
373  //or use a different key modifier for that
374  return std::make_unique<editor_action_fill>(hex, terrain_palette_.selected_fg_item(),
376  }
377 }
378 
379 std::unique_ptr<editor_action> mouse_action_fill::click_right(editor_display& disp, int x, int y)
380 {
381  map_location hex = disp.hex_clicked_on(x, y);
382  if (has_ctrl_modifier()) {
383  terrain_palette_.select_bg_item(disp.map().get_terrain(hex));
384  return nullptr;
385  } else {
386  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
387  //or use a different key modifier for that
388  return std::make_unique<editor_action_fill>(hex, terrain_palette_.selected_bg_item(),
390  }
391 }
392 
394 {
395  set_terrain_mouse_overlay(disp, terrain_palette_.selected_fg_item(),
396  terrain_palette_.selected_bg_item());
397 }
398 
399 std::unique_ptr<editor_action> mouse_action_starting_position::up_left(editor_display& disp, int x, int y)
400 {
401  if (!click_) return nullptr;
402  click_ = false;
403  map_location hex = disp.hex_clicked_on(x, y);
404  if (!disp.map().on_board(hex)) {
405  return nullptr;
406  }
407  auto player_starting_at_hex = disp.map().is_special_location(hex);
408 
409  if (has_ctrl_modifier()) {
410  if (player_starting_at_hex) {
411  location_palette_.add_item(*player_starting_at_hex);
412  }
413  return nullptr;
414  }
415 
416  std::string new_player_at_hex = location_palette_.selected_item();
417  std::unique_ptr<editor_action> a;
418 
419  if(!player_starting_at_hex || new_player_at_hex != *player_starting_at_hex) {
420  // Set a starting position
421  a = std::make_unique<editor_action_starting_position>(hex, new_player_at_hex);
422  }
423  else {
424  // Erase current starting position
425  a = std::make_unique<editor_action_starting_position>(map_location(), *player_starting_at_hex);
426  }
427 
428  update_brush_highlights(disp, hex);
429 
430  return a;
431 }
432 
433 std::unique_ptr<editor_action> mouse_action_starting_position::click_left(editor_display& /*disp*/, int /*x*/, int /*y*/)
434 {
435  click_ = true;
436  return nullptr;
437 }
438 
439 std::unique_ptr<editor_action> mouse_action_starting_position::up_right(editor_display& disp, int x, int y)
440 {
441  map_location hex = disp.hex_clicked_on(x, y);
442  auto player_starting_at_hex = disp.map().is_special_location(hex);
443  if (player_starting_at_hex != nullptr) {
444  return std::make_unique<editor_action_starting_position>(map_location(), *player_starting_at_hex);
445  } else {
446  return nullptr;
447  }
448 }
449 
450 std::unique_ptr<editor_action> mouse_action_starting_position::click_right(editor_display& /*disp*/, int /*x*/, int /*y*/)
451 {
452  return nullptr;
453 }
454 
456 {
457  surface image60 = image::get_image("icons/action/editor-tool-starting-position_60.png");
458 
459  //TODO avoid hardcoded hex field size
460  surface image(72,72);
461 
462  SDL_Rect r {6, 6, 0, 0};
463  sdl_blit(image60, nullptr, image, &r);
464 
465  uint8_t alpha = 196;
466  int size = image->w;
467  int zoom = static_cast<int>(size * disp.get_zoom_factor());
468 
469  // Add the alpha factor and scale the image
470  adjust_surface_alpha(image, alpha);
471  image = scale_surface(image, zoom, zoom);
472  disp.set_mouseover_hex_overlay(image);
473 }
474 
475 
476 } //end namespace editor
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
Definition: picture.cpp:816
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:260
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:357
map_location starting_position(int side) const
Definition: map.cpp:324
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:599
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:263
#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:50
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
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:197
const std::string & editor_image() const
Definition: terrain.hpp:47
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:45
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:1134
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
void adjust_surface_alpha(surface &surf, fixed_t amount)
Definition: utils.cpp:1087
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:302
virtual void set_mouse_overlay(editor_display &disp) override
Set the mouse overlay for this action.
bool valid() const
Definition: location.hpp:89
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:115
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:26
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:448
Manage the empty-palette in the editor.
Definition: action.cpp:30
int32_t fixed_t
Definition: math.hpp:313
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:38
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:2203
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:41
surface get_hexmask()
Retrieves the standard hexagonal tile mask.
Definition: picture.cpp:941
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:60
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:385
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:96
unsigned int tile_size
Definition: game_config.cpp:69
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:32
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