The Battle for Wesnoth  1.19.13+dev
command_executor.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
3  by David White <dave@whitevine.net>
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 
17 #include "hotkey/hotkey_item.hpp"
18 
19 #include "gui/gui.hpp"
22 #include "gui/dialogs/message.hpp"
25 #include "gui/widgets/retval.hpp"
26 #include "filesystem.hpp"
27 #include "gettext.hpp"
28 #include "log.hpp"
30 #include "display.hpp"
31 #include "quit_confirmation.hpp"
32 #include "sdl/surface.hpp"
33 #include "../resources.hpp"
34 #include "../playmp_controller.hpp"
35 #include "sdl/input.hpp" // get_mouse_state
36 #include "video.hpp" // toggle_fullscreen
37 
38 #include <ios>
39 #include <set>
40 
41 static lg::log_domain log_config("config");
42 static lg::log_domain log_hotkey("hotkey");
43 #define ERR_G LOG_STREAM(err, lg::general())
44 #define WRN_G LOG_STREAM(warn, lg::general())
45 #define LOG_G LOG_STREAM(info, lg::general())
46 #define DBG_G LOG_STREAM(debug, lg::general())
47 #define ERR_CF LOG_STREAM(err, log_config)
48 #define LOG_HK LOG_STREAM(info, log_hotkey)
49 
50 namespace {
51 
52 void make_screenshot(const std::string& name, bool map_screenshot)
53 {
54  surface screenshot = display::get_singleton()->screenshot(map_screenshot);
55  if(screenshot) {
56  std::string filename = filesystem::get_screenshot_dir() + "/" + name + "_";
58  gui2::dialogs::screenshot_notification::display(filename, screenshot);
59  }
60 }
61 }
62 namespace hotkey {
63 
64 static void event_queue(const SDL_Event& event, command_executor* executor);
65 
66 bool command_executor::do_execute_command(const hotkey::ui_command& cmd, bool press, bool release)
67 {
68  // hotkey release handling
69  if (release) {
70  switch(cmd.hotkey_command) {
71  // release a scroll key, un-apply scrolling in the given direction
72  case HOTKEY_SCROLL_UP:
73  scroll_up(false);
74  break;
75  case HOTKEY_SCROLL_DOWN:
76  scroll_down(false);
77  break;
78  case HOTKEY_SCROLL_LEFT:
79  scroll_left(false);
80  break;
82  scroll_right(false);
83  break;
84  default:
85  return false; // nothing else handles a hotkey release
86  }
87 
88  return true;
89  }
90 
91  // handling of hotkeys which activate even on hold events
92  switch(cmd.hotkey_command) {
95  return true;
96  case HOTKEY_SCROLL_UP:
97  scroll_up(true);
98  return true;
99  case HOTKEY_SCROLL_DOWN:
100  scroll_down(true);
101  return true;
102  case HOTKEY_SCROLL_LEFT:
103  scroll_left(true);
104  return true;
105  case HOTKEY_SCROLL_RIGHT:
106  scroll_right(true);
107  return true;
108  default:
109  break;
110  }
111 
112  if(!press) {
113  return false; // nothing else handles hotkey hold events
114  }
115 
116  // hotkey press handling
117  switch(cmd.hotkey_command) {
118  case HOTKEY_CYCLE_UNITS:
119  cycle_units();
120  break;
123  break;
124  case HOTKEY_ENDTURN:
125  end_turn();
126  break;
129  break;
131  end_unit_turn();
132  break;
133  case HOTKEY_LEADER:
134  goto_leader();
135  break;
136  case HOTKEY_UNDO:
137  undo();
138  break;
139  case HOTKEY_REDO:
140  redo();
141  break;
144  break;
147  break;
148  case HOTKEY_RENAME_UNIT:
149  rename_unit();
150  break;
151  case HOTKEY_SAVE_GAME:
152  save_game();
153  break;
154  case HOTKEY_SAVE_REPLAY:
155  save_replay();
156  break;
157  case HOTKEY_SAVE_MAP:
158  save_map();
159  break;
160  case HOTKEY_LOAD_GAME:
161  load_game();
162  break;
164  toggle_ellipses();
165  break;
166  case HOTKEY_TOGGLE_GRID:
167  toggle_grid();
168  break;
169  case HOTKEY_STATUS_TABLE:
170  status_table();
171  break;
172  case HOTKEY_RECALL:
173  recall();
174  break;
176  label_settings();
177  break;
178  case HOTKEY_RECRUIT:
179  recruit();
180  break;
181  case HOTKEY_SPEAK:
182  speak();
183  break;
184  case HOTKEY_SPEAK_ALLY:
185  whisper();
186  break;
187  case HOTKEY_SPEAK_ALL:
188  shout();
189  break;
190  case HOTKEY_CREATE_UNIT:
191  create_unit();
192  break;
193  case HOTKEY_CHANGE_SIDE:
194  change_side();
195  break;
196  case HOTKEY_KILL_UNIT:
197  kill_unit();
198  break;
200  select_teleport();
201  break;
202  case HOTKEY_PREFERENCES:
203  preferences();
204  break;
205  case HOTKEY_OBJECTIVES:
206  objectives();
207  break;
208  case HOTKEY_UNIT_LIST:
209  unit_list();
210  break;
211  case HOTKEY_STATISTICS:
212  show_statistics();
213  break;
214  case HOTKEY_STOP_NETWORK:
215  stop_network();
216  break;
218  start_network();
219  break;
221  label_terrain(true);
222  break;
224  label_terrain(false);
225  break;
226  case HOTKEY_CLEAR_LABELS:
227  clear_labels();
228  break;
230  show_enemy_moves(false);
231  break;
233  show_enemy_moves(true);
234  break;
235  case HOTKEY_DELAY_SHROUD:
237  break;
240  break;
242  continue_move();
243  break;
244  case HOTKEY_SEARCH:
245  search();
246  break;
247  case HOTKEY_HELP:
248  show_help();
249  break;
251  // although HOTKEY_HELP uses a virtual call to allow context-specific help, this one is already a specific topic
252  help::show_help("saveload");
253  break;
254  case HOTKEY_CHAT_LOG:
255  show_chat_log();
256  break;
257  case HOTKEY_USER_CMD:
258  user_command();
259  break;
260  case HOTKEY_CUSTOM_CMD:
261  custom_command();
262  break;
263  case HOTKEY_AI_FORMULA:
264  ai_formula();
265  break;
266  case HOTKEY_CLEAR_MSG:
267  clear_messages();
268  break;
269  case HOTKEY_LANGUAGE:
270  change_language();
271  break;
272  case HOTKEY_REPLAY_PLAY:
273  play_replay();
274  break;
275  case HOTKEY_REPLAY_RESET:
276  reset_replay();
277  break;
278  case HOTKEY_REPLAY_STOP:
279  stop_replay();
280  break;
283  break;
286  break;
289  break;
292  break;
295  break;
298  break;
301  break;
302  case HOTKEY_REPLAY_EXIT:
303  replay_exit();
304  break;
305  case HOTKEY_WB_TOGGLE:
307  break;
310  break;
313  break;
316  break;
319  break;
322  break;
325  break;
326  case HOTKEY_SELECT_HEX:
327  select_hex();
328  break;
329  case HOTKEY_DESELECT_HEX:
330  deselect_hex();
331  break;
332  case HOTKEY_MOVE_ACTION:
333  move_action();
334  break;
337  break;
338  case HOTKEY_TOUCH_HEX:
339  touch_hex();
340  break;
341  case HOTKEY_ACCELERATED:
343  break;
344  case LUA_CONSOLE:
345  lua_console();
346  break;
347  case HOTKEY_ZOOM_IN:
348  zoom_in();
349  break;
350  case HOTKEY_ZOOM_OUT:
351  zoom_out();
352  break;
353  case HOTKEY_ZOOM_DEFAULT:
354  zoom_default();
355  break;
357  map_screenshot();
358  break;
361  break;
362  case HOTKEY_QUIT_GAME:
363  gui2::switch_theme(prefs::get().gui2_theme());
365  break;
366  case HOTKEY_SURRENDER:
367  surrender_game();
368  break;
370  prefs::get().set_minimap_draw_terrain(!prefs::get().minimap_draw_terrain());
372  break;
374  prefs::get().set_minimap_terrain_coding(!prefs::get().minimap_terrain_coding());
376  break;
378  prefs::get().set_minimap_movement_coding(!prefs::get().minimap_movement_coding());
380  break;
382  prefs::get().set_minimap_draw_units(!prefs::get().minimap_draw_units());
384  break;
386  prefs::get().set_minimap_draw_villages(!prefs::get().minimap_draw_villages());
388  break;
389  case HOTKEY_ACHIEVEMENTS:
390  {
392  ach.show();
393  }
394  break;
395  default:
396  return false;
397  }
398  return true;
399 }
400 
402  if(gui2::show_message(_("Surrender"), _("Do you really want to surrender the game?"), gui2::dialogs::message::yes_no_buttons) != gui2::retval::CANCEL) {
404  if(pmc && !pmc->is_linger_mode() && !pmc->is_observer()) {
406  }
407  }
408 }
409 
410 void command_executor::show_menu(const std::vector<config>& items_arg, const point& menu_loc, bool /*context_menu*/)
411 {
412  if(items_arg.empty()) {
413  return;
414  }
415 
416  // FIXME: take the argument by value
417  std::vector<config> items = items_arg;
418  for(std::size_t i = 0; i < items.size(); ++i) {
419  populate_menu_item_info(items[i], i);
420  }
421 
422  const auto do_command = [&](int selected_item) {
423  std::string id = items[selected_item]["id"].str();
424  do_execute_command(hotkey::ui_command(id, selected_item));
426  };
427 
428  int res = -1;
429  point selection_pos;
430  {
431  rect pos(menu_loc, {1,1});
432  gui2::dialogs::drop_down_menu mmenu(pos, items, -1, true, keep_menu_open());
433 
434  // Transitional API. Remove once the game UI is using GUI2.
435  // Callback will only fire if keep_menu_open is false
436  mmenu.set_legacy_menu_mode(true);
437  mmenu.set_legacy_toggle_callback(do_command);
438 
439  if(mmenu.show()) {
440  res = mmenu.selected_item();
441  if(res >= 0) {
442  // Get selection coordinates for a potential submenu below
443  // And compensate for borders
444  selection_pos = mmenu.selected_item_pos() - point{1, 1};
445  }
446  }
447  } // This will kill the dialog.
448 
449  if(res < 0 || std::size_t(res) >= items.size()) {
450  return;
451  }
452 
453  if(const theme::menu* submenu = display::get_singleton()->get_theme().get_menu_item(items[res]["id"])) {
454  show_menu(submenu->items(), selection_pos, submenu->is_context());
455  } else {
456  do_command(res);
457  }
458 }
459 
460 void command_executor::execute_action(const std::vector<std::string>& items_arg)
461 {
462  for(const std::string& item : items_arg) {
463  auto cmd = hotkey::ui_command(item);
464  if(can_execute_command(cmd)) {
465  do_execute_command(cmd);
467  }
468  }
469 }
470 
472 {
473  const std::string& command = item["id"];
474 
475  // FIXME: better integrate this with GUI2
476  const std::string default_image = "icons/action/" + command + "_25.png";
477  const std::string pressed_image = "icons/action/" + command + "_25-pressed.png";
478 
479  auto cmd = hotkey::ui_command(command, index);
481 
482  // An image set, if present, takes precedence over toggle buttons to represent
483  // an item's state. See the editor's terrain category dropdown for an example.
484  if(filesystem::file_exists(game_config::path + "/images/" + default_image)) {
485  switch(state) {
486  case action_state::on:
488  item["icon"] = pressed_image + "~CROP(3,3,18,18)";
489  return;
490  default:
491  item["icon"] = default_image + "~CROP(3,3,18,18)";
492  return;
493  }
494  }
495 
496  switch(state) {
497  case action_state::on:
498  item["checkbox"] = true;
499  break;
500  case action_state::off:
501  item["checkbox"] = false;
502  break;
504  item["radio"] = true;
505  break;
507  item["radio"] = false;
508  break;
510  // Do nothing
511  break;
512  }
513 }
514 
516 {
517  const std::string& item_id = item["id"];
518  const auto& hk = hotkey::get_hotkey_command(item_id);
520 
521  // Submenu
522  if(const theme::menu* menu = theme.get_menu_item(item_id)) {
523  item["icon"] = "icons/arrows/short_arrow_right_25.png~CROP(3,3,18,18)"; // TODO: should not be hardcoded
524  item["label"] = menu->title();
525  return;
526  }
527 
528  // Populate icons and enable toggle buttons
530 
531  if(hk.command != hotkey::HOTKEY_NULL) {
532  item["details"] = hotkey::get_names(item_id);
533 
534  switch(hk.command) {
535  case hotkey::HOTKEY_WML:
536  break; // Labels are handled by the menu item manager
537 
539  if(const theme::action* b = theme.get_action_item("button-endturn")) {
540  item["label"] = b->title();
541  break;
542  }
543  [[fallthrough]];
544 
545  default:
546  item["label"] = hk.description;
547  break;
548  }
549  }
550 }
551 
552 void mbutton_event(const SDL_Event& event, command_executor* executor)
553 {
554  event_queue(event, executor);
555 
556  /* Run mouse events immediately.
557 
558  This is necessary because the sidebar doesn't allow set_button_state() to be called after a
559  button has received the mouse press event but before it has received the mouse release event.
560  When https://github.com/wesnoth/wesnoth/pull/2872 delayed the processing of input events,
561  set_button_state() ended up being called at such a time. However, if we run the event handlers
562  now, the button (if any) hasn't received the press event yet and we can call set_button_state()
563  safely.
564 
565  See https://github.com/wesnoth/wesnoth/issues/2884 */
566 
567  run_events(executor);
568 }
569 
570 void jbutton_event(const SDL_Event& event, command_executor* executor)
571 {
572  event_queue(event, executor);
573 }
574 
575 void jhat_event(const SDL_Event& event, command_executor* executor)
576 {
577  event_queue(event, executor);
578 }
579 
580 void key_event(const SDL_Event& event, command_executor* executor)
581 {
582  if (!executor) return;
583  event_queue(event,executor);
584 }
585 
586 void keyup_event(const SDL_Event&, command_executor* executor)
587 {
588  if(!executor) return;
589  executor->handle_keyup();
590 }
591 
593 {
594  if(!executor) return;
595  bool commands_ran = executor->run_queued_commands();
596  if(commands_ran) {
597  executor->set_button_state();
598  }
599 }
600 
601 static void event_queue(const SDL_Event& event, command_executor* executor)
602 {
603  if (!executor) return;
604  executor->queue_command(event);
605  executor->set_button_state();
606 }
607 
608 void command_executor::queue_command(const SDL_Event& event, int index)
609 {
610  LOG_HK << "event 0x" << std::hex << event.type << std::dec;
611  if(event.type == SDL_TEXTINPUT) {
612  LOG_HK << "SDL_TEXTINPUT \"" << event.text.text << "\"";
613  }
614 
615  const hotkey_ptr hk = get_hotkey(event);
616  if(!hk->active() || hk->is_disabled()) {
617  return;
618  }
619 
620  const hotkey_command& command = hotkey::get_hotkey_command(hk->get_command());
621  bool keypress = (event.type == SDL_KEYDOWN || event.type == SDL_TEXTINPUT) &&
623  bool press = keypress ||
624  (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_FINGERDOWN);
625  bool release = event.type == SDL_KEYUP;
626  if(press) {
627  LOG_HK << "sending press event (keypress = " <<
628  std::boolalpha << keypress << std::noboolalpha << ")";
629  }
630  if(keypress) {
631  press_event_sent_ = true;
632  }
633 
634  command_queue_.emplace_back(command, index, press, release);
635 }
636 
638 {
639  auto ui_cmd = hotkey::ui_command(*command.command, command.index);
640  if (!can_execute_command(ui_cmd)
641  || do_execute_command(ui_cmd, command.press, command.release)) {
642  return;
643  }
644 
645  if (!command.press) {
646  return; // none of the commands here respond to a key release
647  }
648 
649  switch(command.command->command) {
650  case HOTKEY_FULLSCREEN:
652  break;
653  case HOTKEY_SCREENSHOT:
654  make_screenshot(_("Screenshot"), false);
655  break;
656  case HOTKEY_ANIMATE_MAP:
657  prefs::get().set_animate_map(!prefs::get().animate_map());
658  break;
659  case HOTKEY_MOUSE_SCROLL:
660  prefs::get().set_mouse_scrolling(!prefs::get().mouse_scrolling());
661  break;
662  case HOTKEY_MUTE:
663  {
664  // look if both is not playing
665  static struct before_muted_s
666  {
667  bool playing_sound,playing_music;
668  before_muted_s() : playing_sound(false),playing_music(false){}
669  } before_muted;
670  if (prefs::get().music_on() || prefs::get().sound())
671  {
672  // then remember settings and mute both
673  before_muted.playing_sound = prefs::get().sound();
674  before_muted.playing_music = prefs::get().music_on();
675  prefs::get().set_sound(false);
676  prefs::get().set_music(false);
677  }
678  else
679  {
680  // then set settings before mute
681  prefs::get().set_sound(before_muted.playing_sound);
682  prefs::get().set_music(before_muted.playing_music);
683  }
684  }
685  break;
686  default:
687  DBG_G << "command_executor: unknown command number " << command.command->command << ", ignoring.";
688  break;
689  }
690 }
691 
693 {
694  display& disp = get_display();
695  for (const theme::menu& menu : disp.get_theme().menus()) {
696 
697  std::shared_ptr<gui::button> button = disp.find_menu_button(menu.get_id());
698  if (!button) continue;
699  bool enabled = false;
700  for (const auto& command : menu.items()) {
701 
702  ui_command command_obj = ui_command(command["id"].str());
703  bool can_execute = can_execute_command(command_obj);
704  if (can_execute) {
705  enabled = true;
706  break;
707  }
708  }
709  button->enable(enabled);
710  }
711 
712  for (const theme::action& action : disp.get_theme().actions()) {
713 
714  std::shared_ptr<gui::button> button = disp.find_action_button(action.get_id());
715  if (!button) continue;
716  bool enabled = false;
717  int i = 0;
718  for (const std::string& command : action.items()) {
719 
720  ui_command command_obj = ui_command(command);
721  std::string tooltip = action.tooltip(i);
722  if (filesystem::file_exists(game_config::path + "/images/icons/action/" + command + "_25.png" ))
723  button->set_overlay("icons/action/" + command);
724  if (!tooltip.empty())
725  button->set_tooltip_string(tooltip);
726 
727  bool can_execute = can_execute_command(command_obj);
728  i++;
729  if (!can_execute) continue;
730  enabled = true;
731 
732  action_state state = get_action_state(command_obj);
733  switch (state) {
735  case action_state::on:
736  button->set_check(true);
737  break;
738  case action_state::off:
740  button->set_check(false);
741  break;
743  break;
744  default:
745  break;
746  }
747 
748  break;
749  }
750  button->enable(enabled);
751  }
752 }
753 
754 // Removes duplicate commands caused by both SDL_KEYDOWN and SDL_TEXTINPUT triggering hotkeys.
755 // See https://github.com/wesnoth/wesnoth/issues/1736
756 std::vector<command_executor::queued_command> command_executor::filter_command_queue()
757 {
758  std::vector<queued_command> filtered_commands;
759 
760  /** A command plus "key released" flag. Otherwise, we will filter out key releases that are preceded by a keypress. */
761  using command_with_keyrelease = std::pair<const hotkey_command*, bool>;
762  std::set<command_with_keyrelease> seen_commands;
763 
764  for(const queued_command& cmd : command_queue_) {
765  command_with_keyrelease command_key(cmd.command, cmd.release);
766  if(seen_commands.find(command_key) == seen_commands.end()) {
767  seen_commands.insert(command_key);
768  filtered_commands.push_back(cmd);
769  }
770  }
771 
772  command_queue_.clear();
773 
774  return filtered_commands;
775 }
776 
778 {
779  std::vector<queued_command> commands = filter_command_queue();
780  for(const queued_command& cmd : commands) {
782  }
783 
784  return !commands.empty();
785 }
786 
788 {
790 }
791 
793 {
795 }
796 
798 {
799  if (get_display().in_game()) {
801  } else {
803  }
804 }
805 
807 {
809 }
810 
812 {
813  if(!get_display().view_locked()) {
814  get_display().set_zoom(true);
815  }
816 }
817 
819 {
820  if(!get_display().view_locked()) {
821  get_display().set_zoom(false);
822  }
823 }
824 
826 {
827  if(!get_display().view_locked()) {
829  }
830 }
831 
833 {
834  make_screenshot(_("Map-Screenshot"), true);
835 }
836 }
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:88
void recalculate_minimap()
Schedule the minimap for recalculation.
Definition: display.cpp:1455
std::shared_ptr< gui::button > find_action_button(const std::string &id)
Retrieves a pointer to a theme UI button.
Definition: display.cpp:759
std::shared_ptr< gui::button > find_menu_button(const std::string &id)
Definition: display.cpp:769
bool set_zoom(bool increase)
Zooms the display in (true) or out (false).
Definition: display.cpp:1682
surface screenshot(bool map_screenshot=false)
Capture a (map-)screenshot into a surface.
Definition: display.cpp:714
theme & get_theme()
Definition: display.hpp:381
void toggle_default_zoom()
Sets the zoom amount to the default.
Definition: display.cpp:1750
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:102
std::size_t viewing_team_index() const
The viewing team is the team currently viewing the game.
Definition: display.hpp:117
Used by the menu_button widget.
static void display(lua_kernel_base *lk)
Display a new console, using given video and lua kernel.
@ yes_no_buttons
Shows a yes and no button.
Definition: message.hpp:81
bool show(const unsigned auto_close_time=0)
Shows the window.
virtual display & get_display()=0
virtual void scroll_right(bool)
virtual void show_menu(const std::vector< config > &items_arg, const point &menu_loc, bool context_menu)
virtual void replay_skip_animation()
virtual void scroll_up(bool)
virtual void scroll_left(bool)
virtual void whiteboard_execute_all_actions()
virtual bool do_execute_command(const hotkey::ui_command &command, bool press=true, bool release=false)
virtual void whiteboard_execute_action()
virtual void show_enemy_moves(bool)
std::vector< queued_command > command_queue_
virtual void toggle_shroud_updates()
virtual void whiteboard_bump_down_action()
void execute_command_wrap(const queued_command &command)
void execute_action(const std::vector< std::string > &items_arg)
virtual action_state get_action_state(const hotkey::ui_command &) const
virtual void whiteboard_delete_action()
virtual bool keep_menu_open() const
If true, the menu will remain open after an item has been selected.
virtual void replay_show_everything()
virtual void toggle_accelerated_speed()
virtual void whiteboard_suppose_dead()
void populate_menu_item_info(config &item, int index) const
virtual void scroll_down(bool)
virtual void label_terrain(bool)
virtual void whiteboard_bump_up_action()
virtual void unit_hold_position()
virtual void terrain_description()
virtual void recalculate_minimap()
virtual bool can_execute_command(const hotkey::ui_command &command) const =0
std::vector< queued_command > filter_command_queue()
void queue_command(const SDL_Event &event, int index=-1)
void populate_menu_controls(config &item, int index) const
bool is_linger_mode() const
bool is_observer() const
void surrender(int side_number)
bool set_music(bool ison)
static prefs & get()
bool sound()
bool set_sound(bool ison)
bool music_on()
static void quit_to_desktop()
static void quit_to_title()
Definition: theme.hpp:43
const action * get_action_item(const std::string &key) const
Definition: theme.cpp:924
const menu * get_menu_item(const std::string &key) const
Definition: theme.cpp:915
const std::vector< action > & actions() const
Definition: theme.hpp:258
const std::vector< menu > & menus() const
Definition: theme.hpp:256
#define LOG_HK
static lg::log_domain log_hotkey("hotkey")
#define DBG_G
static lg::log_domain log_config("config")
map_display and display: classes which take care of displaying the map and game-data on the screen.
Declarations for File-IO.
std::size_t i
Definition: function.cpp:1032
static std::string _(const char *str)
Definition: gettext.hpp:97
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
Definition: manager.cpp:203
Contains functions for cleanly handling SDL input.
Standard logging facilities (interface).
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:341
std::string get_screenshot_dir()
std::string get_next_filename(const std::string &name, const std::string &extension)
Get the next free filename using "name + number (3 digits) + extension" maximum 1000 files then start...
Definition: filesystem.cpp:601
std::string path
Definition: filesystem.cpp:106
static bool sound()
static bool music_on()
void switch_theme(const std::string &theme_id)
Set and activate the given gui2 theme.
Definition: gui.cpp:153
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:148
@ CANCEL
Dialog was closed with the CANCEL button.
Definition: retval.hpp:38
void show_help(const std::string &show_topic)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:139
Keyboard shortcuts for game actions.
void jhat_event(const SDL_Event &event, command_executor *executor)
void key_event(const SDL_Event &event, command_executor *executor)
void mbutton_event(const SDL_Event &event, command_executor *executor)
static void event_queue(const SDL_Event &event, command_executor *executor)
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
std::shared_ptr< class hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:27
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
void run_events(command_executor *executor)
void jbutton_event(const SDL_Event &event, command_executor *executor)
const hotkey_command & get_hotkey_command(std::string_view command)
Returns the hotkey_command with the given id.
void keyup_event(const SDL_Event &, command_executor *executor)
@ HOTKEY_MINIMAP_DRAW_VILLAGES
@ HOTKEY_FULLSCREEN
@ HOTKEY_OBJECTIVES
@ HOTKEY_ANIMATE_MAP
@ HOTKEY_SCREENSHOT
@ HOTKEY_TELEPORT_UNIT
@ HOTKEY_SPEAK_ALLY
@ HOTKEY_ACCELERATED
@ HOTKEY_MOUSE_SCROLL
@ HOTKEY_TERRAIN_DESCRIPTION
@ HOTKEY_END_UNIT_TURN
@ HOTKEY_LABEL_SETTINGS
@ HOTKEY_WB_EXECUTE_ALL_ACTIONS
@ HOTKEY_WB_SUPPOSE_DEAD
@ HOTKEY_HELP_ABOUT_SAVELOAD
@ HOTKEY_REPLAY_PLAY
@ HOTKEY_SCROLL_LEFT
@ HOTKEY_SAVE_GAME
@ HOTKEY_SPEAK_ALL
@ HOTKEY_SHOW_ENEMY_MOVES
@ HOTKEY_ACHIEVEMENTS
@ HOTKEY_DESELECT_HEX
@ HOTKEY_UNIT_DESCRIPTION
@ HOTKEY_UPDATE_SHROUD
@ HOTKEY_REPEAT_RECRUIT
@ HOTKEY_REPLAY_STOP
@ HOTKEY_KILL_UNIT
@ HOTKEY_SCROLL_RIGHT
@ HOTKEY_SAVE_REPLAY
@ HOTKEY_LABEL_TEAM_TERRAIN
@ HOTKEY_UNIT_HOLD_POSITION
@ HOTKEY_REPLAY_NEXT_TURN
@ HOTKEY_TOGGLE_GRID
@ HOTKEY_SURRENDER
@ HOTKEY_SELECT_AND_ACTION
@ HOTKEY_CLEAR_MSG
@ HOTKEY_REPLAY_SHOW_EVERYTHING
@ HOTKEY_REPLAY_SHOW_TEAM1
@ HOTKEY_MINIMAP_DRAW_TERRAIN
@ HOTKEY_LABEL_TERRAIN
@ HOTKEY_CUSTOM_CMD
@ HOTKEY_STOP_NETWORK
@ HOTKEY_MAP_SCREENSHOT
@ HOTKEY_CLEAR_LABELS
@ HOTKEY_CONTINUE_MOVE
@ HOTKEY_BEST_ENEMY_MOVES
@ HOTKEY_QUIT_TO_DESKTOP
@ HOTKEY_TOGGLE_ELLIPSES
@ HOTKEY_RENAME_UNIT
@ HOTKEY_MINIMAP_CODING_TERRAIN
@ HOTKEY_LOAD_GAME
@ HOTKEY_WB_EXECUTE_ACTION
@ HOTKEY_MINIMAP_DRAW_UNITS
@ HOTKEY_CHANGE_SIDE
@ HOTKEY_CYCLE_UNITS
@ HOTKEY_DELAY_SHROUD
@ HOTKEY_WB_BUMP_UP_ACTION
@ HOTKEY_CREATE_UNIT
@ HOTKEY_REPLAY_EXIT
@ HOTKEY_PREFERENCES
@ HOTKEY_STATUS_TABLE
@ HOTKEY_REPLAY_NEXT_SIDE
@ HOTKEY_MOVE_ACTION
@ HOTKEY_REPLAY_NEXT_MOVE
@ HOTKEY_REPLAY_RESET
@ HOTKEY_TOUCH_HEX
@ HOTKEY_START_NETWORK
@ HOTKEY_WB_TOGGLE
@ HOTKEY_STATISTICS
@ HOTKEY_UNIT_LIST
@ HOTKEY_SCROLL_DOWN
@ HOTKEY_REPLAY_SKIP_ANIMATION
@ HOTKEY_ZOOM_DEFAULT
@ HOTKEY_WB_BUMP_DOWN_ACTION
@ HOTKEY_SCROLL_UP
@ HOTKEY_SELECT_HEX
@ HOTKEY_QUIT_GAME
@ HOTKEY_AI_FORMULA
@ HOTKEY_REPLAY_SHOW_EACH
@ HOTKEY_CYCLE_BACK_UNITS
@ HOTKEY_WB_DELETE_ACTION
@ HOTKEY_MINIMAP_CODING_UNIT
play_controller * controller
Definition: resources.cpp:21
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
void toggle_fullscreen()
Toggle fullscreen mode.
Definition: video.cpp:825
std::string filename
Filename.
Stores all information related to functions that can be bound to hotkeys.
HOTKEY_COMMAND command
The command associated with this hotkey.
Used as the main parameter for can_execute_command/do_execute_command These functions are used to exe...
hotkey::HOTKEY_COMMAND hotkey_command
The hotkey::HOTKEY_COMMAND associated with this action, HOTKEY_NULL for actions that don't allow hotk...
Holds a 2D point.
Definition: point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49
#define b