ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
action.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <unordered_map>
5#include <vector>
6
7namespace {
8
9struct ActionData {
10 std::vector<asw::input::ActionBinding> bindings;
11
12 bool pressed { false };
13 bool released { false };
14 bool down { false };
15 float strength { 0.0F };
16
18 bool prev_down { false };
19};
20
21std::unordered_map<std::string, ActionData> action_map;
22
23// ---------------------------------------------------------------------------
24// Per-binding query helpers
25// ---------------------------------------------------------------------------
26
28bool binding_is_down(const asw::input::ActionBinding& binding, float& out_strength)
29{
30 return std::visit(
31 [&out_strength](const auto& b) -> bool {
32 using T = std::decay_t<decltype(b)>;
33
34 if constexpr (std::is_same_v<T, asw::input::KeyBinding>) {
35 if (asw::input::get_key(b.key)) {
36 out_strength = std::max(out_strength, 1.0F);
37 return true;
38 }
39 return false;
40
41 } else if constexpr (std::is_same_v<T, asw::input::MouseButtonBinding>) {
42 if (asw::input::get_mouse_button(b.button)) {
43 out_strength = std::max(out_strength, 1.0F);
44 return true;
45 }
46 return false;
47
48 } else if constexpr (std::is_same_v<T, asw::input::ControllerButtonBinding>) {
49 if (asw::input::get_controller_button(b.controller_index, b.button)) {
50 out_strength = std::max(out_strength, 1.0F);
51 return true;
52 }
53 return false;
54
55 } else if constexpr (std::is_same_v<T, asw::input::ControllerAxisBinding>) {
56 const float val = asw::input::get_controller_axis(b.controller_index, b.axis);
57 const float effective = b.positive_direction ? val : -val;
58 if (effective >= b.threshold) {
59 out_strength = std::max(out_strength, effective);
60 return true;
61 }
62
63 return false;
64 }
65
66 return false;
67 },
68 binding);
69}
70
74{
75 return std::visit(
76 [](const auto& b) -> bool {
77 using T = std::decay_t<decltype(b)>;
78
79 if constexpr (std::is_same_v<T, asw::input::KeyBinding>) {
80 return asw::input::get_key_down(b.key);
81
82 } else if constexpr (std::is_same_v<T, asw::input::MouseButtonBinding>) {
83 return asw::input::get_mouse_button_down(b.button);
84
85 } else if constexpr (std::is_same_v<T, asw::input::ControllerButtonBinding>) {
86 return asw::input::get_controller_button_down(b.controller_index, b.button);
87
88 } else {
89 // ControllerAxisBinding: transition handled by prev_down in update_actions.
90 return false;
91 }
92 },
93 binding);
94}
95
98{
99 return std::visit(
100 [](const auto& b) -> bool {
101 using T = std::decay_t<decltype(b)>;
102
103 if constexpr (std::is_same_v<T, asw::input::KeyBinding>) {
104 return asw::input::get_key_up(b.key);
105
106 } else if constexpr (std::is_same_v<T, asw::input::MouseButtonBinding>) {
107 return asw::input::get_mouse_button_up(b.button);
108
109 } else if constexpr (std::is_same_v<T, asw::input::ControllerButtonBinding>) {
110 return asw::input::get_controller_button_up(b.controller_index, b.button);
111
112 } else {
113 // ControllerAxisBinding: transition handled by prev_down in update_actions.
114 return false;
115 }
116 },
117 binding);
118}
119
120} // namespace
121
122// ---------------------------------------------------------------------------
123// Public API
124// ---------------------------------------------------------------------------
125
126void asw::input::bind_action(std::string_view name, asw::input::ActionBinding binding)
127{
128 action_map[std::string(name)].bindings.push_back(binding);
129}
130
131void asw::input::unbind_action(std::string_view name)
132{
133 action_map.erase(std::string(name));
134}
135
137{
138 action_map.clear();
139}
140
141bool asw::input::get_action_down(std::string_view name)
142{
143 auto it = action_map.find(std::string(name));
144 return it != action_map.end() && it->second.pressed;
145}
146
147bool asw::input::get_action_up(std::string_view name)
148{
149 auto it = action_map.find(std::string(name));
150 return it != action_map.end() && it->second.released;
151}
152
153bool asw::input::get_action(std::string_view name)
154{
155 auto it = action_map.find(std::string(name));
156 return it != action_map.end() && it->second.down;
157}
158
159float asw::input::get_action_strength(std::string_view name)
160{
161 auto it = action_map.find(std::string(name));
162 return it != action_map.end() ? it->second.strength : 0.0F;
163}
164
166{
167 for (auto& [name, action] : action_map) {
168 bool any_down = false;
169 bool any_pressed = false;
170 bool any_released = false;
171 float max_strength = 0.0F;
172
173 for (const auto& binding : action.bindings) {
174 any_down |= binding_is_down(binding, max_strength);
175 any_pressed |= binding_is_pressed(binding);
176 any_released |= binding_is_released(binding);
177 }
178
179 // Derive press / release transitions for axis bindings (and as a
180 // fallback for any binding that doesn't supply its own signals).
181 if (any_down && !action.prev_down) {
182 any_pressed = true;
183 }
184 if (!any_down && action.prev_down) {
185 any_released = true;
186 }
187
188 action.pressed = any_pressed;
189 action.released = any_released;
190 action.down = any_down;
191 action.strength = max_strength;
192 action.prev_down = any_down;
193 }
194}
Action binding system for the ASW library.
bool binding_is_pressed(const asw::input::ActionBinding &binding)
Definition action.cpp:73
std::unordered_map< std::string, ActionData > action_map
Definition action.cpp:21
bool binding_is_down(const asw::input::ActionBinding &binding, float &out_strength)
Returns true if the binding is currently active, and updates out_strength.
Definition action.cpp:28
bool binding_is_released(const asw::input::ActionBinding &binding)
Returns true if the binding was released this frame (digital sources only).
Definition action.cpp:97
bool get_controller_button_up(uint32_t index, asw::input::ControllerButton button)
Check if a controller button was released since the last update.
Definition input.cpp:184
bool get_controller_button_down(uint32_t index, asw::input::ControllerButton button)
Check if a controller button was pressed since the last update.
Definition input.cpp:175
bool get_key(asw::input::Key key)
Check if a key is down.
Definition input.cpp:148
bool get_action_down(std::string_view name)
Check if an action was triggered (first pressed) this frame.
Definition action.cpp:141
void bind_action(std::string_view name, ActionBinding binding)
Register a binding for a named action.
Definition action.cpp:126
bool get_controller_button(uint32_t index, asw::input::ControllerButton button)
Check if a controller button is down.
Definition input.cpp:166
bool get_key_up(asw::input::Key key)
Check if a key was released since the last update.
Definition input.cpp:158
bool get_key_down(asw::input::Key key)
Check if a key was pressed since the last update.
Definition input.cpp:153
bool get_mouse_button(asw::input::MouseButton button)
Check if a mouse button is down.
Definition input.cpp:115
void clear_actions()
Remove all registered actions and their bindings.
Definition action.cpp:136
void update_actions()
Update cached action states from current raw input.
Definition action.cpp:165
float get_controller_axis(uint32_t index, asw::input::ControllerAxis axis)
Get the value of a controller axis.
Definition input.cpp:193
bool get_action(std::string_view name)
Check if an action is currently held down.
Definition action.cpp:153
float get_action_strength(std::string_view name)
Get the analogue strength of an action (0.0 – 1.0).
Definition action.cpp:159
bool get_mouse_button_up(asw::input::MouseButton button)
Check if a mouse button was released since the last update.
Definition input.cpp:125
bool get_mouse_button_down(asw::input::MouseButton button)
Check if a mouse button was pressed since the last update.
Definition input.cpp:120
void unbind_action(std::string_view name)
Remove all bindings for a named action.
Definition action.cpp:131
std::variant< KeyBinding, MouseButtonBinding, ControllerButtonBinding, ControllerAxisBinding > ActionBinding
A single input binding — keyboard, mouse button, controller button, or controller axis.
Definition action.h:60
bool get_action_up(std::string_view name)
Check if an action was released this frame.
Definition action.cpp:147
std::vector< asw::input::ActionBinding > bindings
Definition action.cpp:10