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