The Battle for Wesnoth  1.17.12+dev
mouse_action.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2022
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 #pragma once
17 
20 #include "theme.hpp"
25 
26 class CKey;
27 
28 namespace editor {
29 
30 /**
31  * A mouse action receives events from the controller, and responds to them by creating
32  * an appropriate editor_action object. Mouse actions may store some temporary data
33  * such as the last clicked hex for better handling of click-drag. They should *not* modify
34  * the map or trigger refreshes, but may set brush locations and similar overlays that
35  * should be visible around the mouse cursor, hence the display references are not const.
36  */
38 {
39 public:
42  , key_(key)
43  , toolbar_button_(nullptr)
44  , palette_(palette)
45  {
46  }
47 
48  virtual ~mouse_action() {}
49 
50  virtual bool has_context_menu() const;
51 
52  /**
53  * Mouse move (not a drag). Never changes anything (other than temporary highlights and similar)
54  */
55  virtual void move(editor_display& disp, const map_location& hex);
56 
57  /**
58  * Unconditionally update the brush highlights for the current tool when hex is the center location
59  */
60  void update_brush_highlights(editor_display& disp, const map_location& hex);
61 
62  /**
63  * Locations that would be affected by a click, used by move to update highlights. Defaults to highlight the mouseover hex.
64  * Maybe also used for actually performing the action in click() or drag().
65  */
66  virtual std::set<map_location> affected_hexes(editor_display& disp, const map_location& hex);
67 
68  /**
69  * A click, possibly the beginning of a drag. Must be overridden.
70  */
71  virtual std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y) = 0;
72 
73  /**
74  * A click, possibly the beginning of a drag. Must be overridden.
75  */
76  virtual std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y) = 0;
77 
78  /**
79  * Drag operation. A click should have occurred earlier. Defaults to no action.
80  */
81  virtual std::unique_ptr<editor_action> drag_left(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
82 
83  /**
84  * Drag operation. A click should have occurred earlier. Defaults to no action.
85  */
86  virtual std::unique_ptr<editor_action> drag_right(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
87 
88  /**
89  * The end of dragging. Defaults to no action.
90  */
91  virtual std::unique_ptr<editor_action> drag_end_left(editor_display& disp, int x, int y);
92 
93  virtual std::unique_ptr<editor_action> drag_end_right(editor_display& disp, int x, int y);
94 
95  virtual std::unique_ptr<editor_action> up_left(editor_display& disp, int x, int y);
96 
97  virtual std::unique_ptr<editor_action> up_right(editor_display& disp, int x, int y);
98 
99  /**
100  * Function called by the controller on a key event for the current mouse action.
101  * Defaults to starting position processing.
102  */
103  virtual std::unique_ptr<editor_action> key_event(editor_display& disp, const SDL_Event& e);
104 
105  /**
106  * Helper variable setter - pointer to a toolbar menu/button used for highlighting
107  * the current action. Should always be nullptr or point to a valid menu.
108  */
109  void set_toolbar_button(const theme::menu* value) { toolbar_button_ = value; }
110 
111  /**
112  * Getter for the (possibly nullptr) associated menu/button.
113  */
114  const theme::menu* toolbar_button() const { return toolbar_button_; }
115 
116  /**
117  * Getter for the associated palette.
118  */
120 
121  /** Whether we need the brush bar, is used to grey it out.*/
122  virtual bool supports_brushes() const { return false; }
123 
124  /**
125  * Set the mouse overlay for this action. Defaults to an empty overlay.
126  */
127  virtual void set_mouse_overlay(editor_display& disp);
128 
129 
130 protected:
131  bool has_alt_modifier() const;
132  bool has_shift_modifier() const;
133  bool has_ctrl_modifier() const;
134 
135  /**
136  * Helper function for derived classes that need a active-terrain mouse overlay
137  */
139  const t_translation::terrain_code & fg,
140  const t_translation::terrain_code & bg);
141 
142  /**
143  * The hex previously used in move operations
144  */
146 
147  /**
148  * Key presses, used for modifiers (alt, shift) in some operations
149  */
150  const CKey& key_;
151 
152 private:
153  /**
154  * Pointer to an associated menu/button, if such exists
155  */
157 
158  /**
159  * Pointer to an associated palette, if such exists
160  */
162 };
163 
164 /**
165  * A brush-drag mouse action base class which adds brush and drag processing to a basic mouse action
166  */
168 {
169 public:
170  brush_drag_mouse_action(common_palette& palette, const brush* const * const brush, const CKey& key)
171  : mouse_action(palette, key)
172  , previous_drag_hex_()
173  , brush_(brush)
174  {
175  }
176 
177  /**
178  * The affected hexes of a brush action are the result of projecting the current brush on the mouseover hex
179  */
180  std::set<map_location> affected_hexes(editor_display& disp, const map_location& hex);
181 
182  /**
183  * The actual action function which is called by click() and drag(). Derived classes override this instead of click() and drag().
184  */
185  virtual std::unique_ptr<editor_action> click_perform_left(editor_display& disp, const std::set<map_location>& hexes) = 0;
186 
187  /**
188  * The actual action function which is called by click() and drag(). Derived classes override this instead of click() and drag().
189  */
190  virtual std::unique_ptr<editor_action> click_perform_right(editor_display& disp, const std::set<map_location>& hexes) = 0;
191 
192  /**
193  * Calls click_perform_left()
194  */
195  std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y);
196 
197  /**
198  * Calls click_perform_right()
199  */
200  std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y);
201 
202  /**
203  * Calls click_perform() for every new hex the mouse is dragged into.
204  * @todo partial actions support and merging of many drag actions into one
205  */
206  std::unique_ptr<editor_action> drag_left(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
207 
208  /**
209  * Calls click_perform for every new hex the mouse is dragged into.
210  * @todo partial actions support and merging of many drag actions into one
211  */
212  std::unique_ptr<editor_action> drag_right(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
213 
214  /**
215  * End of dragging.
216  * @todo partial actions (the entire drag should end up as one action)
217  */
218  std::unique_ptr<editor_action> drag_end(editor_display& disp, int x, int y);
219 
220 protected:
221  /** Brush accessor */
222  const brush& get_brush();
223 
224  /**
225  * The previous hex dragged into.
226  * @todo keep a set of all "visited" locations to reduce action count in long drags that hit the same hexes multiple times?
227  */
229 
230 private:
231  /**
232  * Template helper gathering actions common for both drag_right and drag_left.
233  * The drags differ only in the worker function called, which should be
234  * passed as the template parameter. This exists only to avoid copy-pasting code.
235  */
236  template <std::unique_ptr<editor_action> (brush_drag_mouse_action::*perform_func)(editor_display&, const std::set<map_location>&)>
237  std::unique_ptr<editor_action> drag_generic(editor_display& disp, int x, int y, bool& partial, editor_action* last_undo);
238 
239  /**
240  * Current brush handle. Currently a pointer-to-pointer with full constness.
241  * The mouse action does not modify the brush, does not modify the pointer
242  * to the current brush, and we allow setting this pointr only once, hence
243  * the three "consts".
244  */
245  const brush* const * const brush_;
246 };
247 
248 /**
249  * Brush paint mouse action. Uses keyboard modifiers for one-layer painting.
250  */
252 {
253 public:
255  const brush* const * const brush, const CKey& key, terrain_palette& palette)
256  : brush_drag_mouse_action(palette, brush, key)
257  , terrain_palette_(palette)
258  {
259  }
260 
261  /**
262  * Handle terrain sampling before calling generic handler
263  */
264  std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y) override;
265 
266  /**
267  * Handle terrain sampling before calling generic handler
268  */
269  std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y) override;
270 
271  /**
272  * Create an appropriate editor_action and return it
273  */
274  std::unique_ptr<editor_action> click_perform_left(editor_display& disp, const std::set<map_location>& hexes) override;
275 
276  /**
277  * Create an appropriate editor_action and return it
278  */
279  std::unique_ptr<editor_action> click_perform_right(editor_display& disp, const std::set<map_location>& hexes) override;
280 
281  void set_mouse_overlay(editor_display& disp) override;
282 
283  virtual bool supports_brushes() const override { return true; }
284 
285 protected:
286 
288 
289 };
290 
291 
292 
293 /**
294  * Paste action. No dragging capabilities.
295  */
297 {
298 public:
300  : mouse_action(palette, key), paste_(paste)
301  {
302  }
303 
304  virtual bool has_context_menu() const override;
305 
306  /**
307  * Show an outline of where the paste will go
308  */
309  std::set<map_location> affected_hexes(editor_display& disp, const map_location& hex) override;
310 
311  /**
312  * Return a paste with offset action
313  */
314  std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y) override;
315 
316  /**
317  * Right click does nothing for now
318  */
319  std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y) override;
320 
321  virtual void set_mouse_overlay(editor_display& disp) override;
322 
323 protected:
324  /**
325  * Reference to the buffer used for pasting (e.g. the clipboard)
326  */
328 };
329 
330 /**
331  * Fill action. No dragging capabilities. Uses keyboard modifiers for one-layer painting.
332  */
334 {
335 public:
338  : mouse_action(terrain_palette, key)
339  , terrain_palette_(terrain_palette)
340  {
341  }
342 
343  /**
344  * Tiles that will be painted to, possibly use modifier keys here
345  */
346  std::set<map_location> affected_hexes(editor_display& disp, const map_location& hex) override;
347 
348  /**
349  * Left / right click fills with the respective terrain
350  */
351  std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y) override;
352 
353  /**
354  * Left / right click fills with the respective terrain
355  */
356  std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y) override;
357 
358  virtual void set_mouse_overlay(editor_display& disp) override;
359 
360 protected:
362 };
363 
364 /**
365  * Set starting position action.
366  */
368 {
369 public:
371  : mouse_action(palette, key), click_(false), location_palette_(palette)
372  {
373  }
374 
375  /**
376  * Left click displays a player-number-selector dialog and then creates an action
377  * or returns nullptr if cancel was pressed or there would be no change.
378  * Do this on mouse up to avoid drag issue.
379  */
380  std::unique_ptr<editor_action> up_left(editor_display& disp, int x, int y) override;
381 
382  std::unique_ptr<editor_action> click_left(editor_display& disp, int x, int y) override;
383  /**
384  * Right click only erases the starting position if there is one.
385  * Do this on mouse up to avoid drag issue,
386  */
387  std::unique_ptr<editor_action> up_right(editor_display& disp, int x, int y) override;
388 
389  std::unique_ptr<editor_action> click_right(editor_display& disp, int x, int y) override;
390 
391  virtual void set_mouse_overlay(editor_display& disp) override;
392 
393 private:
394  bool click_;
396 };
397 
398 
399 
400 } //end namespace editor
Brush paint mouse action.
terrain_palette & terrain_palette_
virtual std::unique_ptr< editor_action > drag_end_left(editor_display &disp, int x, int y)
The end of dragging.
const CKey & key_
Key presses, used for modifiers (alt, shift) in some operations.
A map fragment – a collection of locations and information abut them.
map_location previous_move_hex_
The hex previously used in move operations.
virtual std::unique_ptr< editor_action > click_right(editor_display &disp, int x, int y)=0
A click, possibly the beginning of a drag.
const brush *const *const brush_
Current brush handle.
std::vector< color_t > palette(const color_range &cr)
Creates a reference color palette from a color range.
Definition: color_range.cpp:85
mouse_action_fill(const CKey &key, terrain_palette &terrain_palette)
Palette where the terrain to be drawn can be selected.
common_palette & palette_
Pointer to an associated palette, if such exists.
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
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.
Base class for editor actions.
List of starting locations and location ids.
virtual std::unique_ptr< editor_action > up_right(editor_display &disp, int x, int y)
virtual std::unique_ptr< editor_action > drag_end_right(editor_display &disp, int x, int y)
mouse_action_paste(const map_fragment &paste, const CKey &key, common_palette &palette)
A brush-drag mouse action base class which adds brush and drag processing to a basic mouse action...
map_location previous_drag_hex_
The previous hex dragged into.
const map_fragment & paste_
Reference to the buffer used for pasting (e.g.
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.
brush_drag_mouse_action(common_palette &palette, const brush *const *const brush, const CKey &key)
mouse_action_starting_position(const CKey &key, location_palette &palette)
virtual bool has_context_menu() const
common_palette & get_palette()
Getter for the associated palette.
bool has_shift_modifier() const
mouse_action_paint(const brush *const *const brush, const CKey &key, terrain_palette &palette)
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
Manage the empty-palette in the editor.
Definition: action.cpp:30
virtual bool supports_brushes() const
Whether we need the brush bar, is used to grey it out.
terrain_palette & terrain_palette_
Encapsulates the map of the game.
Definition: location.hpp:38
virtual bool supports_brushes() const override
Whether we need the brush bar, is used to grey it out.
void set_toolbar_button(const theme::menu *value)
Helper variable setter - pointer to a toolbar menu/button used for highlighting the current action...
Base class for all editor actions.
Definition: action_base.hpp:41
Definitions related to theme-support.
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.
const theme::menu * toolbar_button() const
Getter for the (possibly nullptr) associated menu/button.
const theme::menu * toolbar_button_
Pointer to an associated menu/button, if such exists.
virtual void move(editor_display &disp, const map_location &hex)
Mouse move (not a drag).
virtual std::unique_ptr< editor_action > click_left(editor_display &disp, int x, int y)=0
A click, possibly the beginning of a drag.
Set starting position action.
bool has_ctrl_modifier() const
mouse_action(common_palette &palette, const CKey &key)
virtual std::unique_ptr< editor_action > drag_left(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
#define e
A mouse action receives events from the controller, and responds to them by creating an appropriate e...
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.
There are still moves and/or attacks possible, but the unit doesn&#39;t fit in the "unmoved" status...
Class that keeps track of all the keys on the keyboard.
Definition: key.hpp:28
virtual std::unique_ptr< editor_action > drag_right(editor_display &disp, int x, int y, bool &partial, editor_action *last_undo)
Drag operation.
bool has_alt_modifier() const