#pragma once #ifndef CATA_SRC_INPUT_H #define CATA_SRC_INPUT_H #include #include #include #include #include #include #if defined(__ANDROID__) #include #include #endif #include "point.h" #include "translations.h" enum action_id : int; class hotkey_queue; namespace cata { template class optional; } // namespace cata namespace catacurses { class window; } // namespace catacurses // Curses key constants static constexpr int KEY_ESCAPE = 27; static constexpr int KEY_MIN = 0x101; /* minimum extended key value */ //<---------not used static constexpr int KEY_BREAK = 0x101; /* break key */ //<---------not used static constexpr int KEY_DOWN = 0x102; /* down arrow */ static constexpr int KEY_UP = 0x103; /* up arrow */ static constexpr int KEY_LEFT = 0x104; /* left arrow */ static constexpr int KEY_RIGHT = 0x105; /* right arrow*/ static constexpr int KEY_HOME = 0x106; /* home key */ //<---------not used static constexpr int KEY_BACKSPACE = 0x107; /* Backspace */ //<---------not used static constexpr int KEY_DC = 0x151; /* Delete Character */ static constexpr int KEY_F0 = 0x108; inline constexpr int KEY_F( const int n ) { return KEY_F0 + n; /* F1, F2, etc*/ } static constexpr int F_KEY_NUM_BEG = 0; static constexpr int F_KEY_NUM_END = 63; inline constexpr int F_KEY_NUM( const int key ) { return key - KEY_F0; } inline constexpr bool IS_F_KEY( const int key ) { return key >= KEY_F( F_KEY_NUM_BEG ) && key <= KEY_F( F_KEY_NUM_END ); } /** @return true if the given character is in the range of basic ASCII control characters */ inline constexpr bool IS_CTRL_CHAR( const int key ) { // https://en.wikipedia.org/wiki/C0_and_C1_control_codes#Basic_ASCII_control_codes return key >= 0 && key < ' '; } /** @return true if the given character is an ASCII control char but should not be rendered with "CTRL+" */ inline constexpr bool IS_NAMED_CTRL_CHAR( const int key ) { return key == '\t' || key == '\n' || key == KEY_ESCAPE || key == KEY_BACKSPACE; } inline constexpr int KEY_NUM( const int n ) { return 0x30 + n; /* Numbers 0, 1, ..., 9 */ } static constexpr int KEY_NPAGE = 0x152; /* page down */ static constexpr int KEY_PPAGE = 0x153; /* page up */ static constexpr int KEY_ENTER = 0x157; /* enter */ static constexpr int KEY_BTAB = 0x161; /* back-tab = shift + tab */ static constexpr int KEY_END = 0x168; /* End */ // Platform independent key code (though largely based on SDL key code) // // These and other code related to keyboard_code event should NOT be guarded with // platform macros, since they are required to load and save keyboard_code events, // which should always be done regardless whether the platform supports it, otherwise // custom keybindings might be lost when someone switches e.g. from tiles to curses // and save the keybindings, and switches back to tiles later. namespace keycode { enum : int { backspace = 0x08, tab = 0x09, return_ = 0x0D, escape = 0x1B, space = 0x20, f1 = 0x4000003A, f2 = 0x4000003B, f3 = 0x4000003C, f4 = 0x4000003D, f5 = 0x4000003E, f6 = 0x4000003F, f7 = 0x40000040, f8 = 0x40000041, f9 = 0x40000042, f10 = 0x40000043, f11 = 0x40000044, f12 = 0x40000045, home = 0x4000004A, ppage = 0x4000004B, end = 0x4000004D, npage = 0x4000004E, right = 0x4000004F, left = 0x40000050, down = 0x40000051, up = 0x40000052, kp_divide = 0x40000054, kp_multiply = 0x40000055, kp_minus = 0x40000056, kp_plus = 0x40000057, kp_enter = 0x40000058, kp_1 = 0x40000059, kp_2 = 0x4000005A, kp_3 = 0x4000005B, kp_4 = 0x4000005C, kp_5 = 0x4000005D, kp_6 = 0x4000005E, kp_7 = 0x4000005F, kp_8 = 0x40000060, kp_9 = 0x40000061, kp_0 = 0x40000062, kp_period = 0x40000063, f13 = 0x40000068, f14 = 0x40000069, f15 = 0x4000006A, f16 = 0x4000006B, f17 = 0x4000006C, f18 = 0x4000006D, f19 = 0x4000006E, f20 = 0x4000006F, f21 = 0x40000070, f22 = 0x40000071, f23 = 0x40000072, f24 = 0x40000073, }; } // namespace keycode static constexpr int LEGEND_HEIGHT = 11; static constexpr int BORDER_SPACE = 2; bool is_mouse_enabled(); bool is_keycode_mode_supported(); std::string get_input_string_from_file( const std::string &fname = "input.txt" ); enum mouse_buttons { MOUSE_BUTTON_LEFT = 1, MOUSE_BUTTON_RIGHT, SCROLLWHEEL_UP, SCROLLWHEEL_DOWN, MOUSE_MOVE }; enum class input_event_t : int { error, timeout, // used on platforms with only character/text input, such as curses keyboard_char, // used on platforms with raw keycode input, such as non-android sdl keyboard_code, gamepad, mouse }; enum class keymod_t { ctrl, alt, shift, }; /** * An instance of an input, like a keypress etc. * * Gamepad, mouse and keyboard keypresses will be represented as `int`. * Whether a gamepad, mouse or keyboard was used can be checked using the * `type` member. * */ struct input_event { input_event_t type; std::set modifiers; // Keys that need to be held down for // this event to be activated. std::vector sequence; // The sequence of key or mouse events that // triggers this event. For single-key // events, simply make this of size 1. point mouse_pos; // Mouse click co-ordinates, if applicable // Actually entered text (if any), UTF-8 encoded, might be empty if // the input is not UTF-8 or not even text. std::string text; std::string edit; bool edit_refresh; #if defined(__ANDROID__) // Used exclusively by the quick shortcuts to determine how stale a shortcut is int shortcut_last_used_action_counter = 0; #endif input_event() : edit_refresh( false ) { type = input_event_t::error; } input_event( int s, input_event_t t ) : type( t ), edit_refresh( false ) { sequence.push_back( s ); } input_event( const std::set &mod, int s, input_event_t t ); int get_first_input() const; void add_input( const int input ) { sequence.push_back( input ); } bool operator==( const input_event &other ) const { return type == other.type && modifiers == other.modifiers && sequence == other.sequence; } bool operator!=( const input_event &other ) const; std::string long_description() const; std::string short_description() const; /** * Lexicographical order considering input event type, * modifiers, and key code sequence. */ static bool compare_type_mod_code( const input_event &lhs, const input_event &rhs ); }; /** * A set of attributes for an action */ struct action_attributes { action_attributes() : is_user_created( false ) {} bool is_user_created; translation name; std::vector input_events; }; // Definitions for joystick/gamepad. // On the joystick there's a maximum of 256 key states. // So for joy axis events, we simply use a number larger // than that. constexpr int JOY_0 = 0; constexpr int JOY_1 = 1; constexpr int JOY_2 = 2; constexpr int JOY_3 = 3; constexpr int JOY_4 = 4; constexpr int JOY_5 = 5; constexpr int JOY_6 = 6; constexpr int JOY_7 = 7; constexpr int JOY_8 = 8; constexpr int JOY_9 = 9; constexpr int JOY_10 = 10; constexpr int JOY_11 = 11; constexpr int JOY_12 = 12; constexpr int JOY_13 = 13; constexpr int JOY_14 = 14; constexpr int JOY_15 = 15; constexpr int JOY_16 = 16; constexpr int JOY_17 = 17; constexpr int JOY_18 = 18; constexpr int JOY_19 = 19; constexpr int JOY_20 = 20; constexpr int JOY_21 = 21; constexpr int JOY_22 = 22; constexpr int JOY_23 = 23; constexpr int JOY_24 = 24; constexpr int JOY_25 = 25; constexpr int JOY_26 = 26; constexpr int JOY_27 = 27; constexpr int JOY_28 = 28; constexpr int JOY_29 = 29; constexpr int JOY_30 = 30; constexpr int JOY_LEFT = 256 + 1; constexpr int JOY_RIGHT = 256 + 2; constexpr int JOY_UP = 256 + 3; constexpr int JOY_DOWN = 256 + 4; constexpr int JOY_RIGHTUP = 256 + 5; constexpr int JOY_RIGHTDOWN = 256 + 6; constexpr int JOY_LEFTUP = 256 + 7; constexpr int JOY_LEFTDOWN = 256 + 8; enum class keyboard_mode { // Accept character input and text input. Input in this mode // may be manipulated by the system via IMEs or dead keys. keychar, // Accept raw key code input. Text input is not available in this // mode. All keyboard events are directly fed to the program // in this mode, bypassing IMEs and dead keys. Only supported on // some platforms, such as non-android SDL. On other platforms // this falls back to `keychar` automatically. keycode, }; /** * Manages the translation from action IDs to associated input. * * Planned methods of input: * 1. Single key press: a * 2. Multi-key combination: `a * 3. Gamepad button: A */ class input_manager { public: // TODO: rewrite this to have several alternative input events for the same action /** * Get the input events associated with an action ID in a given context. * * @param action_descriptor The action ID to get the input events for. * @param context The context in which to get the input events. Defaults to "default". * @param overwrites_default If this is non-NULL, this will be used as return parameter and will be set to true if the default * keybinding is overridden by something else in the given context. */ const std::vector &get_input_for_action( const std::string &action_descriptor, const std::string &context = "default", bool *overwrites_default = nullptr ); /** * Return first char associated with an action ID in a given context. */ int get_first_char_for_action( const std::string &action_descriptor, const std::string &context = "default" ); /** * Initializes the input manager, aka loads the input mapping configuration JSON. */ void init(); /** * Opposite of @ref init, save the data that has been loaded by @ref init, * and possibly been modified. */ void save(); /** * Return the previously pressed key, or 0 if there is no previous input * or the previous input wasn't a key. */ int get_previously_pressed_key() const; /** * Get the keycode associated with the given key name. */ int get_keycode( input_event_t inp_type, const std::string &name ) const; /** * Get the key name associated with the given keyboard keycode. * * @param ch Character code. * @param inp_type Whether the keycode is a gamepad or a keyboard code. * @param portable If true, return a language independent and portable name * of the key. This acts as the inverse to get_keyname: * get_keyname(get_keycode(a), , true) == a */ std::string get_keyname( int ch, input_event_t inp_type, bool portable = false ) const; /** * curses getch() replacement. * * Defined in the respective platform wrapper, e.g. sdlcurse.cpp */ input_event get_input_event( keyboard_mode preferred_keyboard_mode = keyboard_mode::keycode ); /** * Resize & refresh if necessary, process all pending window events, and ignore keypresses */ void pump_events(); /** * Wait until the user presses a key. Mouse and similar input is ignored, * only input events from the keyboard are considered. */ void wait_for_any_key(); /** * Sets global input polling timeout as appropriate for the current interface system. * Use `input_context::(re)set_timeout()` when possible so timeout will be properly * reset when entering a new input context. */ void set_timeout( int delay ); void reset_timeout() { set_timeout( -1 ); } int get_timeout() const { return input_timeout; } static keyboard_mode actual_keyboard_mode( keyboard_mode preferred_keyboard_mode ); private: friend class input_context; using t_input_event_list = std::vector; using t_actions = std::map; using t_action_contexts = std::map; t_action_contexts action_contexts; using t_key_to_name_map = std::map; t_key_to_name_map keyboard_char_keycode_to_keyname; t_key_to_name_map keyboard_code_keycode_to_keyname; t_key_to_name_map gamepad_keycode_to_keyname; t_key_to_name_map mouse_keycode_to_keyname; using t_name_to_key_map = std::map; t_name_to_key_map keyboard_char_keyname_to_keycode; t_name_to_key_map keyboard_code_keyname_to_keycode; t_name_to_key_map gamepad_keyname_to_keycode; t_name_to_key_map mouse_keyname_to_keycode; // See @ref get_previously_pressed_key int previously_pressed_key; // Maps the key names we see in keybindings.json and in-game to // the keycode integers. void init_keycode_mapping(); void add_keyboard_char_keycode_pair( int ch, const std::string &name ); void add_keyboard_code_keycode_pair( int ch, const std::string &name ); void add_gamepad_keycode_pair( int ch, const std::string &name ); void add_mouse_keycode_pair( int ch, const std::string &name ); /** * Load keybindings from a json file, override existing bindings. * Throws std::string on errors */ void load( const std::string &file_name, bool is_user_preferences ); int input_timeout; t_input_event_list &get_or_create_event_list( const std::string &action_descriptor, const std::string &context ); void remove_input_for_action( const std::string &action_descriptor, const std::string &context ); void add_input_for_action( const std::string &action_descriptor, const std::string &context, const input_event &event ); /** * Get the attributes of the action associated with an action ID by * searching the given context and the default context. * * @param action_id The action ID of the action to find. * @param context The context in which to get the action. If not found, * the "default" context will additionally be checked. * Defaults to "default". * @param overwrites_default If this is non-NULL, this will be used as a * return parameter. It will be set to true if * the found action was not in the default * context. It will be set to false if the found * action was in the default context. */ const action_attributes &get_action_attributes( const std::string &action_id, const std::string &context = "default", bool *overwrites_default = nullptr ); /** * Get a value to be used as the default name for a newly created action. * This name should be used as a fallback in cases where it is necessary * to create a new action. * * @param action_id The action ID of the action. * * @return If the action ID exists in the default context, the name of * that action's name is returned. Otherwise, no_translation( action_id ) is * returned. */ translation get_default_action_name( const std::string &action_id ) const; }; // Singleton for our input manager. extern input_manager inp_mngr; /** * Represents a context in which a set of actions can be performed. * * This class is responsible for registering possible actions * (traditionally keypresses), handling input, and yielding the correct * action string descriptors for given input. * * This turns this class into an abstraction method between actual * input(keyboard, gamepad etc.) and game. */ class input_context { public: #if defined(__ANDROID__) // Whatever's on top is our current input context. static std::list input_context_stack; #endif input_context() : registered_any_input( false ), category( "default" ), coordinate_input_received( false ), handling_coordinate_input( false ) { #if defined(__ANDROID__) input_context_stack.push_back( this ); allow_text_entry = false; #endif } // TODO: consider making the curses WINDOW an argument to the constructor, so that mouse input // outside that window can be ignored explicit input_context( const std::string &category, const keyboard_mode preferred_keyboard_mode = keyboard_mode::keycode ) : registered_any_input( false ), category( category ), coordinate_input_received( false ), handling_coordinate_input( false ), preferred_keyboard_mode( preferred_keyboard_mode ) { #if defined(__ANDROID__) input_context_stack.push_back( this ); allow_text_entry = false; #endif } #if defined(__ANDROID__) virtual ~input_context() { input_context_stack.remove( this ); } // HACK: hack to allow creating manual keybindings for getch() instances, uilists etc. that don't use an input_context outside of the Android version struct manual_key { manual_key( int _key, const std::string &_text ) : key( _key ), text( _text ) {} int key; std::string text; bool operator==( const manual_key &other ) const { return key == other.key && text == other.text; } }; std::vector registered_manual_keys; // If true, prevent virtual keyboard from dismissing after a key press while this input context is active. // NOTE: This won't auto-bring up the virtual keyboard, for that use sdltiles.cpp is_string_input() bool allow_text_entry; void register_manual_key( manual_key mk ); void register_manual_key( int key, const std::string text = "" ); std::string get_action_name_for_manual_key( int key ) { for( const auto &manual_key : registered_manual_keys ) { if( manual_key.key == key ) { return manual_key.text; } } return std::string(); } std::vector &get_registered_manual_keys() { return registered_manual_keys; } std::string &get_category() { return category; } std::vector &get_registered_actions() { return registered_actions; } bool is_action_registered( const std::string &action_descriptor ) const { return std::find( registered_actions.begin(), registered_actions.end(), action_descriptor ) != registered_actions.end(); } input_context &operator=( const input_context &other ) { registered_actions = other.registered_actions; registered_manual_keys = other.registered_manual_keys; allow_text_entry = other.allow_text_entry; registered_any_input = other.registered_any_input; category = other.category; coordinate = other.coordinate; coordinate_input_received = other.coordinate_input_received; handling_coordinate_input = other.handling_coordinate_input; next_action = other.next_action; iso_mode = other.iso_mode; action_name_overrides = other.action_name_overrides; timeout = other.timeout; return *this; } bool operator==( const input_context &other ) const { return category == other.category && registered_actions == other.registered_actions && registered_manual_keys == other.registered_manual_keys && allow_text_entry == other.allow_text_entry && registered_any_input == other.registered_any_input && coordinate == other.coordinate && coordinate_input_received == other.coordinate_input_received && handling_coordinate_input == other.handling_coordinate_input && next_action == other.next_action && iso_mode == other.iso_mode && action_name_overrides == other.action_name_overrides && timeout == other.timeout; } bool operator!=( const input_context &other ) const { return !( *this == other ); } #endif /** * Register an action with this input context. * * Only registered actions will be returned by `handle_input()`, it's * thus possible to have multiple actions associated with the same keypress, * as long as they don't ever occur in the same input context. * * If `action_descriptor` is the special "ANY_INPUT", instead of ignoring * unregistered keys, those keys will all be linked to this "ANY_INPUT" * action. * * If `action_descriptor` is the special "COORDINATE", coordinate input will be processed * and the specified coordinates can be retrieved using `get_coordinates()`. Currently the * only form of coordinate input is mouse input(you can directly click coordinates on * the screen). * * @param action_descriptor String of action id. */ void register_action( const std::string &action_descriptor ); /** * Same as other @ref register_action function but allows a context specific * action name. The given name is displayed instead of the name taken from * the @ref input_manager. * * @param action_descriptor String of action id. * @param name Name of the action, displayed to the user. If empty use the * name reported by the input_manager. */ void register_action( const std::string &action_descriptor, const translation &name ); /** * Get the set of available single character keyboard keys that do not * conflict with any registered hotkeys. The result will only include * characters from the requested_keys parameter that have no conflicts * i.e. the set difference requested_keys - conflicts. * * @param requested_keys The set of single character hotkeys to * potentially use. Defaults to all printable ascii. * * @return Returns the set of non-conflicting, single character keyboard * keys suitable for use as hotkeys. */ std::string get_available_single_char_hotkeys( std::string requested_keys = "abcdefghijkpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=:;'\",./<>?!@#$%^&*()_+[]\\{}|`~" ); using input_event_filter = std::function; // Helper functions to be used as @ref input_event_filter static bool disallow_lower_case_or_non_modified_letters( const input_event &evt ); static bool allow_all_keys( const input_event &evt ); /** * Get a description text for the key/other input method associated * with the given action. If there are multiple bound keys, no more * than max_limit will be described in the result. In addition, only * keys satisfying evt_filter will be described. * * @param action_descriptor The action descriptor for which to return * a description of the bound keys. * * @param max_limit No more than max_limit bound keys will be * described in the returned description. A value of * 0 indicates no limit. * * @param evt_filter Only keys satisfying this function will be * described. */ std::string get_desc( const std::string &action_descriptor, unsigned int max_limit = 0, const input_event_filter &evt_filter = allow_all_keys ) const; /** * Get a description based on `text`. If a bound key for `action_descriptor` * satisfying `evt_filter` is contained in `text`, surround the key with * brackets and change the case if necessary (e.g. "(Y)es"). Otherwise * prefix `text` with description of the first bound key satisfying * `evt_filter`, surrounded in square brackets (e.g "[RETURN] Yes"). * * @param action_descriptor The action descriptor for which to return * a description of the bound keys. * * @param text The base text for action description * * @param evt_filter Only keys satisfying this function will be considered * @param inline_fmt Action description format when a key is found in the * text (for example "(a)ctive") * @param separate_fmt Action description format when a key is not found * in the text (for example "[X] active" or "[N/A] active") */ std::string get_desc( const std::string &action_descriptor, const std::string &text, const input_event_filter &evt_filter, const translation &inline_fmt, const translation &separate_fmt ) const; std::string get_desc( const std::string &action_descriptor, const std::string &text, const input_event_filter &evt_filter = allow_all_keys ) const; /** * Equivalent to get_desc( act, get_action_name( act ), filter ) **/ std::string describe_key_and_name( const std::string &action_descriptor, const input_event_filter &evt_filter = allow_all_keys ) const; /** * Handles input and returns the next action in the queue. * * This internally calls getch() or whatever other input method * is available(e.g. gamepad). * * If the action is mouse input, returns "MOUSE". * * @return One of the input actions formerly registered with * `register_action()`, or "ERROR" if an error happened. * */ const std::string &handle_input(); const std::string &handle_input( int timeout ); /** * Convert a direction action (UP, DOWN etc) to a delta vector. * * @return If the action is a movement action (UP, DOWN, ...), * the delta vector associated with it. Otherwise returns an empty value. * The returned vector will always have a z component of 0. */ cata::optional get_direction( const std::string &action ) const; /** * Get the coordinates associated with the last mouse click (if any). * * TODO: This right now is more or less specific to the map window, * and returns the absolute map coordinate. * Eventually this should be made more flexible. */ cata::optional get_coordinates( const catacurses::window &capture_win_ ); // Below here are shortcuts for registering common key combinations. void register_directions(); void register_updown(); void register_leftright(); void register_cardinal(); /** * Displays the possible actions in the current context and their * keybindings. * @param permit_execute_action If `true` the function allows the user to specify an action to execute * @returns action_id of any action the user specified to execute, or ACTION_NULL if none */ action_id display_menu( bool permit_execute_action = false ); /** * Temporary method to retrieve the raw input received, so that input_contexts * can be used in screens where not all possible actions have been defined in * keybindings.json yet. */ input_event get_raw_input(); /** * Get coordinate of text level from mouse input, difference between this and get_coordinates is that one is getting pixel level coordinate. */ cata::optional get_coordinates_text( const catacurses::window &capture_win ) const; /** * Get the human-readable name for an action. */ std::string get_action_name( const std::string &action_id ) const; /* For the future, something like this might be nice: * const std::string register_action(const std::string& action_descriptor, x, y, width, height); * (x, y, width, height) would describe an area on the visible window that, if clicked, triggers the action. */ // (Press X (or Y)|Try) to Z std::string press_x( const std::string &action_id ) const; std::string press_x( const std::string &action_id, const std::string &key_bound, const std::string &key_unbound ) const; std::string press_x( const std::string &action_id, const std::string &key_bound_pre, const std::string &key_bound_suf, const std::string &key_unbound ) const; /** * Keys (and only keys, other input types are not included) that * trigger the given action. * @param action_descriptor The action descriptor for which to get the bound keys. * @param maximum_modifier_count Maximum number of modifiers allowed for * the returned action. <0 means any number is allowed. * @param restrict_to_printable If `true` the function returns the bound * keys only if they are printable (space counts as non-printable * here). If `false`, all keys (whether they are printable or not) * are returned. * @returns All keys bound to the given action descriptor. */ std::vector keys_bound_to( const std::string &action_descriptor, int maximum_modifier_count = -1, bool restrict_to_printable = true ) const; /** * Get/Set edittext to display IME unspecified string. */ void set_edittext( const std::string &s ); std::string get_edittext(); void set_iso( bool mode = true ); /** * Sets input polling timeout as appropriate for the current interface system. * Use this method to set timeouts when using input_context, rather than calling * the old timeout() method or using input_manager::(re)set_timeout, as using * this method will cause input_event_t::timeout events to be generated correctly, * and will reset timeout correctly when a new input context is entered. */ void set_timeout( int val ); void reset_timeout(); input_event first_unassigned_hotkey( const hotkey_queue &queue ) const; input_event next_unassigned_hotkey( const hotkey_queue &queue, const input_event &prev ) const; private: std::vector registered_actions; std::string edittext; public: const std::string &input_to_action( const input_event &inp ) const; bool is_event_type_enabled( input_event_t type ) const; private: bool registered_any_input; std::string category; // The input category this context uses. point coordinate; bool coordinate_input_received; bool handling_coordinate_input; input_event next_action; bool iso_mode = false; // should this context follow the game's isometric settings? int timeout = -1; keyboard_mode preferred_keyboard_mode = keyboard_mode::keycode; /** * When registering for actions within an input_context, callers can * specify a custom action name that will override the action's normal * name. This map stores those overrides. The key is the action ID and the * value is the user-visible name. */ std::map action_name_overrides; /** * Returns whether action uses the specified input */ bool action_uses_input( const std::string &action_id, const input_event &event ) const; /** * Return a user presentable list of actions that conflict with the * proposed keybinding. Returns an empty string if nothing conflicts. */ std::string get_conflicts( const input_event &event ) const; /** * Clear an input_event from all conflicting keybindings that are * registered by this input_context. * * @param event The input event to be cleared from conflicting * keybindings. */ void clear_conflicting_keybindings( const input_event &event ); /** * Filter a vector of strings by a phrase, returning only strings that contain the phrase. * * @param strings The vector of strings to filter * @param phrase The phrase to search within each of the given strings * @return A vector of the filtered strings */ std::vector filter_strings_by_phrase( const std::vector &strings, const std::string &phrase ) const; }; /** * Check whether a gamepad is plugged in/available. * * Always false in non-SDL versions. */ bool gamepad_available(); // rotate a delta direction clockwise void rotate_direction_cw( int &dx, int &dy ); class hotkey_queue { public: // ctxt is only used for determining hotkey input type // use input_context::first_unassigned_hotkey() instead to skip assigned actions input_event first( const input_context &ctxt ) const; // use input_context::next_unassigned_hotkey() instead to skip assigned actions input_event next( const input_event &prev ) const; /** * In keychar mode: * a-z, A-Z * In keycode mode: * a-z, shift a-z */ static const hotkey_queue &alphabets(); /** * In keychar mode: * 1-0, a-z, A-Z * In keycode mode: * 1-0, a-z, shift 1-0, shift a-z */ static const hotkey_queue &alpha_digits(); private: std::vector codes_keychar; std::vector codes_keycode; std::vector> modifiers_keycode; }; #endif // CATA_SRC_INPUT_H