The Battle for Wesnoth  1.13.4+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 - 2016 by Tomasz Sniatowski <[email protected]>
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"
19 #include "mouse_action.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) {
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_RMETA] || key_[SDLK_LMETA];
139 #else
140  return key_[SDLK_RCTRL] || key_[SDLK_LCTRL];
141 #endif
142 }
143 
145  const t_translation::t_terrain & 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 = sdl::create_rect(offset, quarter_size, 0, 0);
175  blit_surface ( 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 = sdl::create_rect(half_size, quarter_size, 0, 0);
180  blit_surface ( 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  image = adjust_surface_alpha(image, alpha);
187 
188  // scale the image
189  const 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 = sdl::create_rect(6, 6, 0, 0);
340  blit_surface(image60, nullptr, image, &r);
341 
342  Uint8 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  image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);
348  disp.set_mouseover_hex_overlay(image);
349 }
350 
351 std::set<map_location> mouse_action_fill::affected_hexes(
352  editor_display& disp, const map_location& hex)
353 {
354  return disp.map().get_contiguous_terrain_tiles(hex);
355 }
356 
358 {
359  map_location hex = disp.hex_clicked_on(x, y);
360  if (has_ctrl_modifier()) {
362  return nullptr;
363  } else {
364  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
365  //or use a different key modifier for that
368  return a;
369  }
370 }
371 
373 {
374  map_location hex = disp.hex_clicked_on(x, y);
375  if (has_ctrl_modifier()) {
377  return nullptr;
378  } else {
379  /** @todo only take the base terrain into account when searching for contiguous terrain when painting base only */
380  //or use a different key modifier for that
383  return a;
384  }
385 }
386 
388 {
391 }
392 
394 {
395  if (!click_) return nullptr;
396  click_ = false;
397  map_location hex = disp.hex_clicked_on(x, y);
398  if (!disp.map().on_board(hex)) {
399  return nullptr;
400  }
401  auto player_starting_at_hex = disp.map().is_starting_position(hex);
402 
403  if (has_ctrl_modifier()) {
404  if (player_starting_at_hex) {
405  location_palette_.add_item(*player_starting_at_hex);
406  }
407  return nullptr;
408  }
409 
410  std::string new_player_at_hex = location_palette_.selected_item();
411  editor_action* a = nullptr;
412 
413  if(!player_starting_at_hex || new_player_at_hex != *player_starting_at_hex) {
414  // Set a starting position
415  a = new editor_action_starting_position(hex, new_player_at_hex);
416  }
417  else {
418  // Erase current starting position
419  a = new editor_action_starting_position(map_location(), *player_starting_at_hex);
420  }
421 
422  update_brush_highlights(disp, hex);
423 
424  return a;
425 }
426 
428 {
429  click_ = true;
430  return nullptr;
431 }
432 
434 {
435  map_location hex = disp.hex_clicked_on(x, y);
436  auto player_starting_at_hex = disp.map().is_starting_position(hex);
437  if (player_starting_at_hex != nullptr) {
438  return new editor_action_starting_position(map_location(), *player_starting_at_hex);
439  } else {
440  return nullptr;
441  }
442 }
443 
445 {
446  return nullptr;
447 }
448 
450 {
451  surface image60 = image::get_image("icons/action/editor-tool-starting-position_60.png");
452 
453  //TODO avoid hardcoded hex field size
455 
456  SDL_Rect r = sdl::create_rect(6, 6, 0, 0);
457  blit_surface(image60, nullptr, image, &r);
458 
459  Uint8 alpha = 196;
460  int size = image->w;
461  int zoom = static_cast<int>(size * disp.get_zoom_factor());
462 
463  // Add the alpha factor and scale the image
464  image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);
465  disp.set_mouseover_hex_overlay(image);
466 }
467 
468 
469 } //end namespace editor
#define SDLK_RMETA
Definition: compat.hpp:34
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:878
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:150
void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
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.
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.
const t_translation::t_terrain & selected_bg_item() const
map_location previous_move_hex_
The hex previously used in move operations.
const brush *const *const brush_
Current brush handle.
int pos
Definition: formula.cpp:800
editor_action * click_perform_right(editor_display &disp, const std::set< map_location > &hexes)
Create an appropriate editor_action and return it.
Sint32 fixed_t
Definition: drawer.hpp:40
void set_brush_locs(const std::set< map_location > &hexes)
editor_action * click_right(editor_display &disp, int x, int y)
Right click does nothing for now.
virtual void set_mouse_overlay(editor_display &disp)
Set the mouse overlay for this action.
#define LOG_ED
void set_terrain_mouse_overlay(editor_display &disp, const t_translation::t_terrain &fg, const t_translation::t_terrain &bg)
Helper function for derived classes that need a active-terrain mouse overlay.
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 ...
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:577
Paste a map fragment into the map.
Definition: action.hpp:224
double get_zoom_factor() const
Returns the current zoom factor.
Definition: display.hpp:269
Container action wrapping several actions into one.
Definition: action.hpp:79
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
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)
Definition: utils.cpp:443
bool has_ctrl_modifier() const
Set starting position action.
Definition: action.hpp:283
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:126
const t_translation::t_terrain & selected_fg_item() const
void blit_surface(const surface &surf, const SDL_Rect *srcrect, surface &dst, const SDL_Rect *dstrect)
Replacement for sdl_blit.
Definition: utils.cpp:2185
const std::string & selected_item() const
Return the currently selected item.
map_location previous_drag_hex_
The previous hex dragged into.
GLintptr offset
Definition: glew.h:1650
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:1279
editor_action * click_left(editor_display &disp, int x, int y)
Handle terrain sampling before calling generic handler.
virtual editor_action * up_left(editor_display &disp, int x, int y)
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:421
editor_action * click_perform_left(editor_display &disp, const std::set< map_location > &hexes)
Create an appropriate editor_action and return it.
bool valid() const
Definition: location.hpp:69
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
surface adjust_surface_alpha(const surface &surf, fixed_t amount, bool optimize)
Definition: utils.cpp:1202
editor_action * click_left(editor_display &disp, int x, int y)
Left / right click fills with the respective terrain.
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
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...
GLclampf GLclampf GLclampf alpha
Definition: glew.h:1488
The brush class represents a single brush – a set of relative locations around a "hotspot"...
Definition: brush.hpp:26
editor_action * click_left(editor_display &disp, int x, int y)
Calls click_perform_left()
std::set< map_location > affected_hexes(editor_display &disp, const map_location &hex)
Show an outline of where the paste will go.
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:458
Manage the empty-palette in the editor.
Definition: action.cpp:28
Paint the same terrain on a number of locations on the map.
Definition: action.hpp:244
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
terrain_palette & terrain_palette_
Encapsulates the map of the game.
Definition: location.hpp:38
const terrain_type & get_terrain_info(const t_translation::t_terrain &terrain) const
Definition: map.cpp:100
GLuint res
Definition: glew.h:9258
void select_fg_item(const t_translation::t_terrain &terrain)
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:2434
bool has_alt_modifier() const
#define SDLK_LMETA
Definition: compat.hpp:33
Base class for all editor actions.
Definition: action_base.hpp:41
surface get_hexmask()
function to get the standard hex mask
Definition: image.cpp:1115
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.
void select_bg_item(const t_translation::t_terrain &terrain)
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
editor_action * click_right(editor_display &disp, int x, int y)
Handle terrain sampling before calling generic handler.
Base class for actions that: 1) operate on an area 2) can be used as undo for a click-drag operation ...
Definition: action.hpp:58
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
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.
t_translation::t_terrain get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:341
SDL_Rect create_rect(const int x, const int y, const int w, const int h)
Creates an empty SDL_Rect.
Definition: rect.cpp:28
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:467
editor_action * click_left(editor_display &disp, int x, int y)
Return a paste with offset action.
GLsizeiptr size
Definition: glew.h:1649
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
cl_event event
Definition: glew.h:3070
virtual editor_action * drag_end_left(editor_display &disp, int x, int y)
The end of dragging.
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:75
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:439
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.
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:266
GLsizei const GLcharARB ** string
Definition: glew.h:4503
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