GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 94.4% 17 / 0 / 18
Functions: 100.0% 6 / 0 / 6
Branches: 87.5% 7 / 0 / 8

include/DetourModKit/input_codes.hpp
Line Branch Exec Source
1 #ifndef DETOURMODKIT_INPUT_CODES_HPP
2 #define DETOURMODKIT_INPUT_CODES_HPP
3
4 /**
5 * @file input_codes.hpp
6 * @brief Unified input code types for keyboard, mouse, and gamepad inputs.
7 * @details Provides a tagged InputCode type that identifies both the device source
8 * and button/key code, along with named key resolution for human-readable
9 * configuration strings. Gamepad codes correspond to XInput button masks.
10 */
11
12 #include <cstdint>
13 #include <functional>
14 #include <optional>
15 #include <string>
16 #include <string_view>
17
18 namespace DetourModKit
19 {
20 /**
21 * @enum InputSource
22 * @brief Identifies the device type for an input code.
23 */
24 enum class InputSource : uint8_t
25 {
26 Keyboard,
27 Mouse,
28 Gamepad
29 };
30
31 /**
32 * @brief Converts an InputSource enum to its string representation.
33 * @param source The InputSource enum value.
34 * @return std::string_view String representation of the source.
35 */
36 3 constexpr std::string_view input_source_to_string(InputSource source)
37 {
38
3/4
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 2 → 5 taken 1 time.
✗ Branch 2 → 6 not taken.
3 switch (source)
39 {
40 1 case InputSource::Keyboard:
41 1 return "Keyboard";
42 1 case InputSource::Mouse:
43 1 return "Mouse";
44 1 case InputSource::Gamepad:
45 1 return "Gamepad";
46 }
47 return "Unknown";
48 }
49
50 /**
51 * @struct InputCode
52 * @brief A tagged input identifier combining a device source and a button/key code.
53 * @details For Keyboard and Mouse sources, the code is a Windows Virtual Key code
54 * (usable with GetAsyncKeyState). For Gamepad, the code is an XInput
55 * button bitmask or a synthetic trigger identifier (see GamepadCode).
56 */
57 struct InputCode
58 {
59 124 InputSource source = InputSource::Keyboard;
60 96 int code = 0;
61
62
4/4
✓ Branch 2 → 3 taken 28 times.
✓ Branch 2 → 4 taken 96 times.
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 91 times.
124 constexpr bool operator==(const InputCode &) const noexcept = default;
63 };
64
65 /**
66 * @brief Hash functor for InputCode, enabling use in unordered containers.
67 */
68 struct InputCodeHash
69 {
70 17 std::size_t operator()(const InputCode &ic) const noexcept
71 {
72 17 return std::hash<int>{}(ic.code) ^
73 17 (std::hash<uint8_t>{}(static_cast<uint8_t>(ic.source)) << 16);
74 }
75 };
76
77 /**
78 * @brief Creates a keyboard InputCode from a Windows Virtual Key code.
79 * @param vk The VK code (e.g., 0x41 for 'A').
80 * @return InputCode Tagged as Keyboard.
81 */
82 75 constexpr InputCode keyboard_key(int vk) noexcept { return {InputSource::Keyboard, vk}; }
83
84 /**
85 * @brief Creates a mouse InputCode from a Windows Virtual Key code.
86 * @param vk The VK code (e.g., 0x01 for VK_LBUTTON).
87 * @return InputCode Tagged as Mouse.
88 */
89 6 constexpr InputCode mouse_button(int vk) noexcept { return {InputSource::Mouse, vk}; }
90
91 /**
92 * @brief Creates a gamepad InputCode from an XInput button code.
93 * @param code The XInput button mask or synthetic trigger code (see GamepadCode).
94 * @return InputCode Tagged as Gamepad.
95 */
96 25 constexpr InputCode gamepad_button(int code) noexcept { return {InputSource::Gamepad, code}; }
97
98 /**
99 * @namespace GamepadCode
100 * @brief XInput-compatible gamepad button codes and synthetic analog identifiers.
101 * @details Digital button codes match XInput XINPUT_GAMEPAD_* bitmask values.
102 * LeftTrigger/RightTrigger and thumbstick direction codes are synthetic
103 * identifiers for analog inputs treated as digital with configurable
104 * deadzone thresholds.
105 */
106 namespace GamepadCode
107 {
108 inline constexpr int DpadUp = 0x0001;
109 inline constexpr int DpadDown = 0x0002;
110 inline constexpr int DpadLeft = 0x0004;
111 inline constexpr int DpadRight = 0x0008;
112 inline constexpr int Start = 0x0010;
113 inline constexpr int Back = 0x0020;
114 inline constexpr int LeftStick = 0x0040;
115 inline constexpr int RightStick = 0x0080;
116 inline constexpr int LeftBumper = 0x0100;
117 inline constexpr int RightBumper = 0x0200;
118 inline constexpr int A = 0x1000;
119 inline constexpr int B = 0x2000;
120 inline constexpr int X = 0x4000;
121 inline constexpr int Y = 0x8000;
122
123 /// Synthetic codes for analog triggers treated as digital inputs.
124 inline constexpr int LeftTrigger = 0x10000;
125 inline constexpr int RightTrigger = 0x10001;
126
127 /// Synthetic codes for thumbstick axes treated as digital inputs.
128 /// Each direction fires when the axis exceeds the stick deadzone threshold.
129 inline constexpr int LeftStickUp = 0x10002;
130 inline constexpr int LeftStickDown = 0x10003;
131 inline constexpr int LeftStickLeft = 0x10004;
132 inline constexpr int LeftStickRight = 0x10005;
133 inline constexpr int RightStickUp = 0x10006;
134 inline constexpr int RightStickDown = 0x10007;
135 inline constexpr int RightStickLeft = 0x10008;
136 inline constexpr int RightStickRight = 0x10009;
137
138 /// Default analog trigger threshold (0-255 range, values above are "pressed").
139 inline constexpr int TriggerThreshold = 30;
140
141 /// Default thumbstick deadzone threshold (0-32767 range).
142 /// Matches XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE (7849).
143 inline constexpr int StickThreshold = 7849;
144 } // namespace GamepadCode
145
146 /**
147 * @brief Attempts to resolve a human-readable name to an InputCode.
148 * @details Performs case-insensitive matching against a built-in table of known
149 * key, mouse button, and gamepad button names.
150 *
151 * Recognized name formats:
152 * - Keyboard: "A"-"Z", "0"-"9", "F1"-"F24", "Ctrl", "Shift", "Alt",
153 * "Space", "Enter", "Escape", "Tab", "Backspace", etc.
154 * - Mouse: "Mouse1" (left) through "Mouse5" (XButton2)
155 * - Gamepad: "Gamepad_A", "Gamepad_B", "Gamepad_LB", "Gamepad_LT", etc.
156 *
157 * @param name The input name to resolve.
158 * @return std::optional<InputCode> The resolved code, or std::nullopt if unrecognized.
159 */
160 std::optional<InputCode> parse_input_name(std::string_view name);
161
162 /**
163 * @brief Returns a human-readable name for an InputCode, if one exists.
164 * @param code The input code to look up.
165 * @return std::string_view The canonical name, or an empty view if not in the table.
166 */
167 std::string_view input_code_to_name(const InputCode &code);
168
169 /**
170 * @brief Formats an InputCode as a human-readable string.
171 * @details Returns the canonical name if the code is in the lookup table,
172 * otherwise falls back to a hexadecimal representation (e.g., "0x72").
173 * @param code The input code to format.
174 * @return std::string Formatted string.
175 */
176 std::string format_input_code(const InputCode &code);
177
178 } // namespace DetourModKit
179
180 #endif // DETOURMODKIT_INPUT_CODES_HPP
181