raylib-cpp
C++ object-oriented wrapper library for raylib.
Loading...
Searching...
No Matches
BufferedRaylib.hpp
1
6#include "raylib.h"
7#include "../FastSignals/libfastsignals/include/signal.h"
8
9#include <set>
10#include <string>
11#include <string_view>
12#include <map>
13#include <array>
14#include <concepts>
15
16namespace raylib {
17
18 template<typename F>
19 struct Delegate {};
20
21 template<typename Ret, typename... Args>
22 struct Delegate<Ret(Args...)>: public is::signals::signal<Ret(Args...)> {
23 using callback_type = typename is::signals::signal<Ret(Args...)>::slot_type;
24
25 Delegate& operator+=(callback_type callback) { this->connect(callback); return *this; }
26
27 void set(callback_type callback) {
28 this->disconnect_all_slots();
29 this->connect(callback);
30 }
31 Delegate& operator=(callback_type callback) { set(callback); return *this; }
32 };
33
37 struct Button {
38 // Enumerates different button types.
39 enum class Type {
40 Invalid = 0,
41 Keyboard,
42 Mouse,
44 } type;
45
46 // Union to store different types of button configurations (raylib enums).
47 // NOTE: it is recommended to not directly manipulate buttons but to instead use one of the following factory functions
48 union {
49 KeyboardKey keyboard;
50 MouseButton mouse;
51 struct {
52 int id;
53 GamepadButton button;
54 } gamepad;
55 };
56
62 bool operator<(const Button& o) const;
63
69 static bool IsPressed(const Button& button);
70
76 static uint8_t IsSetPressed(const std::set<Button>& buttons);
77
78 // Static helper functions to create Button objects for different input types.
85 static Button key(KeyboardKey key) { return { Type::Keyboard, key}; }
86
93 static Button btn(MouseButton button) { return { Type::Mouse, {.mouse = button}}; }
101 static Button mouse_button(MouseButton button) { return btn(button); }
102
110 static Button pad(GamepadButton button, int gamepad = 0) { return { Type::Keyboard, {.gamepad = {gamepad, button}}}; }
119 static Button joy(GamepadButton button, int gamepad = 0) { return pad(button, gamepad); }
128 static Button gamepad_button(GamepadButton button, int gamepad = 0) { return pad(button, gamepad); }
129 };
130
131 // Typedef for a set of buttons.
132 using ButtonSet = std::set<Button>;
133
137 struct Action {
138 // Enumerates different action types.
139 enum class Type {
140 Invalid = 0,
141 Button,
142 Axis,
143 Vector,
144 MultiButton
145 } type;
146
150 struct Gamepad {
151 int id;
152 GamepadAxis axis;
153 };
154
160 template<size_t N>
162 enum Direction {
163 Up, Down, Left, Right,
164 UpLeft, UpRight, DownLeft, DownRight
165 };
166 std::array<ButtonSet, N> directions;
167 std::array<uint8_t, N> lasts;
168 bool normalize = true; // When true the maximum value returned for a given axis is 1, if false the value of each direction will be the sum of the buttons pressed pointing one direction minus the sum of the pressed buttons pointing the other direction
169 };
170
171 // Union to store different types of action data.
172 // NOTE: It is recommended that you don't try to mess with these values yourself, instead use one of the factory functions below
173 // NOTE: Every inner type has a variable called last_state which holds the state as of the last time this action was pumped!
174 // Can be quired externally if nessicary... but ensure that you are accessing data of the correct type!
175 union Data {
176 struct Button {
177 ButtonSet* buttons;
178 bool combo = false; // When true all buttons in the set must be pressed for the action to trigger
179 uint8_t last_state = 0; // TODO: can we add a function to access the last state?
180 } button;
181
182 struct Axis {
183 enum class Type {
184 Invalid = 0,
185 Gamepad,
186 MouseWheel
187 } type;
188
189 Gamepad gamepad;
190 float last_state = 0;
191 } axis;
192
193 struct Vector {
194 enum class Type {
195 Invalid = 0,
196 MouseWheel,
197 MousePosition,
198 // MouseDelta,
199 GamepadAxes,
200 } type;
201
202 struct GamepadAxes{
203 Gamepad horizontal;
204 Gamepad vertical;
205 } gamepad;
206 Vector2 last_state = { 0, 0 };
207 } vector;
208
209 struct MultiButton {
210 enum class Type {
211 Invalid = 0,
212 ButtonPair,
213 QuadButtons,
214 } type;
215
216 MultiButtonData<4>* quadButtons;
217 Vector2 last_state;
218 } multi;
219 } data;
220
221 // Callback invoked when the action is triggered
222 Delegate<void(const std::string_view name, Vector2 state, Vector2 delta)> callback;
223
224 // Constructors and destructor for the Action class.
225 Action() : type(Type::Invalid), data({.button = {}}) {}
226 ~Action() {
227 if(type == Type::Button && data.button.buttons) delete data.button.buttons;
228 else if(type == Type::MultiButton && data.multi.quadButtons) delete data.multi.quadButtons;
229 }
230 Action(Type t, Data d = {.button = {nullptr, false, 0}}) : type(t), data(d) {}
231 Action(const Action&) = delete;
232 Action(Action&& o) : Action() { *this = std::move(o); }
233 Action& operator=(const Action&) = delete;
234 Action& operator=(Action&& o);
235
236 // Member functions to add and set callback functions for the action (vector overloads).
237 Action& AddVectorCallbackNamed(is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type callback) {
238 this->callback.connect(callback);
239 return *this;
240 }
241 Action& SetVectorCallbackNamed(is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type callback) {
242 this->callback.disconnect_all_slots();
243 return AddVectorCallbackNamed(callback);
244 }
245 Action& AddVectorCallback(is::signals::signal<void(Vector2 state, Vector2 delta)>::slot_type callback) {
246 return AddVectorCallbackNamed((is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
247 [callback = std::move(callback)](const std::string_view name, Vector2 state, Vector2 delta){
248 callback(state, delta);
249 });
250 }
251 Action& SetVectorCallback(is::signals::signal<void(Vector2 state, Vector2 delta)>::slot_type callback) {
252 return SetVectorCallbackNamed((is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
253 [callback = std::move(callback)](const std::string_view name, Vector2 state, Vector2 delta){
254 callback(state, delta);
255 });
256 }
257
258 // Member functions to add and set callback functions for the action (float overloads).
259 Action& AddFloatCallbackNamed(is::signals::signal<void(const std::string_view name, float state, float delta)>::slot_type callback) {
260 return AddVectorCallbackNamed(
261 (is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
262 [callback](const std::string_view name, Vector2 state, Vector2 delta) {
263 callback(name, state.x, delta.x);
264 });
265 }
266 Action& SetFloatCallbackNamed(is::signals::signal<void(const std::string_view name, float state, float delta)>::slot_type callback) {
267 this->callback.disconnect_all_slots();
268 return AddFloatCallbackNamed(callback);
269 }
270 Action& AddFloatCallback(is::signals::signal<void(float state, float delta)>::slot_type callback) {
271 return AddFloatCallbackNamed([callback = std::move(callback)](const std::string_view name, float state, float delta){
272 callback(state, delta);
273 });
274 }
275 Action& SetFloatCallback(is::signals::signal<void(float state, float delta)>::slot_type callback) {
276 return SetFloatCallbackNamed([callback = std::move(callback)](const std::string_view name, float state, float delta){
277 callback(state, delta);
278 });
279 }
280
281 // Aliases for backwards compatibility
282 Action& AddCallbackNamed(is::signals::signal<void(const std::string_view name, float state, float delta)>::slot_type callback) {
283 return AddFloatCallbackNamed(callback);
284 }
285 Action& SetCallbackNamed(is::signals::signal<void(const std::string_view name, float state, float delta)>::slot_type callback) {
286 return SetFloatCallbackNamed(callback);
287 }
288 Action& AddCallback(is::signals::signal<void(float state, float delta)>::slot_type callback) {
289 return AddFloatCallback(callback);
290 }
291 Action& SetCallback(is::signals::signal<void(float state, float delta)>::slot_type callback) {
292 return SetFloatCallback(callback);
293 }
294
295 // Member functions to add and set callback functions for the action (button pressed overloads).
296 Action& AddPressedCallbackNamed(is::signals::signal<void(const std::string_view name)>::slot_type callback) {
297 return AddVectorCallbackNamed(
298 (is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
299 [callback](const std::string_view name, Vector2 state, Vector2 delta) {
300 if(state.x) callback(name);
301 });
302 }
303 Action& SetPressedCallbackNamed(is::signals::signal<void(const std::string_view name)>::slot_type callback) {
304 this->callback.disconnect_all_slots();
305 return AddPressedCallbackNamed(callback);
306 }
307 Action& AddPressedCallback(is::signals::signal<void()>::slot_type callback) {
308 return AddVectorCallbackNamed(
309 (is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
310 [callback](const std::string_view name, Vector2 state, Vector2 delta) {
311 if(state.x) callback();
312 });
313 }
314 Action& SetPressedCallback(is::signals::signal<void()>::slot_type callback) {
315 this->callback.disconnect_all_slots();
316 return AddPressedCallback(callback);
317 }
318 // Member functions to add and set callback functions for the action (button released overloads).
319 Action& AddReleasedCallbackNamed(is::signals::signal<void(const std::string_view name)>::slot_type callback) {
320 return AddVectorCallbackNamed(
321 (is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
322 [callback](const std::string_view name, Vector2 state, Vector2 delta) {
323 if(!state.x) callback(name);
324 });
325 }
326 Action& SetReleasedCallbackNamed(is::signals::signal<void(const std::string_view name)>::slot_type callback) {
327 this->callback.disconnect_all_slots();
328 return AddReleasedCallbackNamed(callback);
329 }
330 Action& AddReleasedCallback(is::signals::signal<void()>::slot_type callback) {
331 return AddVectorCallbackNamed(
332 (is::signals::signal<void(const std::string_view name, Vector2 state, Vector2 delta)>::slot_type)
333 [callback](const std::string_view name, Vector2 state, Vector2 delta) {
334 if(!state.x) callback();
335 });
336 }
337 Action& SetReleasedCallback(is::signals::signal<void()>::slot_type callback) {
338 this->callback.disconnect_all_slots();
339 return AddReleasedCallback(callback);
340 }
341
351 static Action button(Button button, bool combo = false) { return Action{Action::Type::Button, Action::Data{ .button = {new ButtonSet{button}, combo}}}; }
352
362 static Action key(KeyboardKey key, bool combo = false) { return button({ Button::Type::Keyboard, key}, combo); }
363
373 static Action mouse_button(MouseButton b, bool combo = false) { return button({ Button::Type::Mouse, {.mouse = b}}, combo); }
374
385 static Action pad(GamepadButton b, int gamepad = 0, bool combo = false) { return button({ Button::Type::Keyboard, {.gamepad = {gamepad, b}}}, combo); }
386
398 static Action joy(GamepadButton b, int gamepad = 0, bool combo = false) { return pad(b, gamepad, combo); }
399
411 static Action gamepad_button(GamepadButton b, int gamepad = 0, bool combo = false) { return pad(b, gamepad, combo); }
412
423 static Action button_set(ButtonSet buttons = {}, bool combo = false) { return Action{Action::Type::Button, Action::Data{ .button = { new ButtonSet(buttons), combo }}}; }
424
433 static Action gamepad_axis(GamepadAxis axis = GAMEPAD_AXIS_LEFT_X, int gamepad = 0) {
434 return {Action::Type::Axis, {.axis = {Data::Axis::Type::Gamepad, {gamepad, axis}}}};
435 }
436
444 return {Action::Type::Axis, {.axis = { Data::Axis::Type::MouseWheel }}};
445 }
446
457 static Action button_axis(ButtonSet positive, ButtonSet negative, bool normalize = true) {
458 Action out{Action::Type::MultiButton};
459 out.data.multi.type = Data::MultiButton::Type::ButtonPair;
460 out.data.multi.quadButtons = new MultiButtonData<4>{{ positive, negative }, {}, normalize};
461 return out;
462 }
463
474 static Action button_pair(ButtonSet left, ButtonSet right, bool normalize = true) {
475 return button_axis(left, right, normalize);
476 }
477
485 return {Action::Type::Vector, {.vector = { Data::Vector::Type::MouseWheel }}};
486 }
487
495 return {Action::Type::Vector, {.vector = { Data::Vector::Type::MousePosition }}};
496 }
497
508 static Action gamepad_axes(GamepadAxis horizontal = GAMEPAD_AXIS_LEFT_X, GamepadAxis vertical = GAMEPAD_AXIS_LEFT_Y, int gamepadHorizontal = 0, int gamepadVertical = -1);
509
524 static Action quad(ButtonSet up, ButtonSet down, ButtonSet left, ButtonSet right, bool normalized = true) {
525 Action out{Action::Type::MultiButton};
526 out.data.multi.type = Data::MultiButton::Type::QuadButtons;
527 out.data.multi.quadButtons = new MultiButtonData<4>{{ up, down, left, right }, {}, normalized};
528 return out;
529 }
530
545 static Action wasd(
546 ButtonSet up = {Button::key(KEY_W), Button::key(KEY_UP)},
547 ButtonSet left = {Button::key(KEY_A), Button::key(KEY_LEFT)},
548 ButtonSet down = {Button::key(KEY_S), Button::key(KEY_DOWN)},
549 ButtonSet right = {Button::key(KEY_D), Button::key(KEY_RIGHT)},
550 bool normalized = true
551 ) { return quad(up, down, left, right, normalized); }
552
553
561 Action&& Move() { return std::move(*this); }
562 Action&& move() { return std::move(*this); }
563
570 void PollEvents(std::string_view name);
571
572 protected:
573 friend struct BufferedInput;
574
575 // Functions which get called by BufferedInput to process actions
576 void PumpButton(std::string_view name);
577 void PumpAxis(std::string_view name);
578 void PumpVector(std::string_view name);
579 void PumpMultiButton(std::string_view name);
580 };
581
582
587 // Map associating names with actions
588 std::map<std::string, Action> actions;
589
590 // Access to the action map via the input object itself
591 Action& operator[](const std::string& key) {
592 return actions[key];
593 }
594
595 // Function which updates the state of all actions in the `actions` map.
596 void PollEvents(bool whileUnfocused = false);
597 };
598
599}
Input-related functions: gamepads.
Definition: Gamepad.hpp:14
All raylib-cpp classes and functions appear in the raylib namespace.
Definition: AudioDevice.hpp:8
struct combining a gamepad and axis enum and id together
Struct holding configuration data for multibutton actions.
Represents various input action types, such as buttons, axes (controller trigger, mouse wheel),...
static Action button(Button button, bool combo=false)
Action that is invoked whenever the abstract button is pressed.
static Action gamepad_button(GamepadButton b, int gamepad=0, bool combo=false)
Action that is invoked whenever the gamepad button is pressed.
static Action key(KeyboardKey key, bool combo=false)
Action that is invoked whenever the keyboard key is pressed.
Action && Move()
Helper function which moves the action, equivalent to calling std::move but can be chained for conven...
static Action pad(GamepadButton b, int gamepad=0, bool combo=false)
Action that is invoked whenever the gamepad button is pressed.
static Action quad(ButtonSet up, ButtonSet down, ButtonSet left, ButtonSet right, bool normalized=true)
Action that combines button sets pointing in 4 cardinal directions into a vector which represents the...
static Action mouse_wheel()
Action that is invoked whenever the mouse wheel is adjusted.
void PollEvents(std::string_view name)
Function which updates the state of the action and invokes the callback if a change occured.
static Action gamepad_axis(GamepadAxis axis=GAMEPAD_AXIS_LEFT_X, int gamepad=0)
Action that is invoked whenever the gamepad axis (usually triggers) is de/pressed.
static Action joy(GamepadButton b, int gamepad=0, bool combo=false)
Action that is invoked whenever the gamepad button is pressed.
static Action button_pair(ButtonSet left, ButtonSet right, bool normalize=true)
Action that combines button sets pointing in 2 opposing directions into a signed value which represen...
static Action gamepad_axes(GamepadAxis horizontal=GAMEPAD_AXIS_LEFT_X, GamepadAxis vertical=GAMEPAD_AXIS_LEFT_Y, int gamepadHorizontal=0, int gamepadVertical=-1)
Action that merges two seperate gamepad axis into a single vector.
static Action button_axis(ButtonSet positive, ButtonSet negative, bool normalize=true)
Action that combines button sets pointing in 2 opposing directions into a signed value which represen...
static Action mouse_wheel_vector()
Action that is invoked whenever the mouse wheel is adjusted (also supports wheels that can tilt side ...
static Action mouse_button(MouseButton b, bool combo=false)
Action that is invoked whenever the mouse button is pressed.
static Action wasd(ButtonSet up={Button::key(KEY_W), Button::key(KEY_UP)}, ButtonSet left={Button::key(KEY_A), Button::key(KEY_LEFT)}, ButtonSet down={Button::key(KEY_S), Button::key(KEY_DOWN)}, ButtonSet right={Button::key(KEY_D), Button::key(KEY_RIGHT)}, bool normalized=true)
Action that combines button sets pointing in 4 cardinal directions into a vector which represents the...
static Action mouse_position()
Action that is invoked whenever the mouse moves.
static Action button_set(ButtonSet buttons={}, bool combo=false)
Action that is invoked whenever the one of the collection of buttons are pressed.
InputManager which is responsible for a map of actions and updating their values.
Represents various input button types, including keyboard keys, mouse buttons, and gamepad buttons.
static bool IsPressed(const Button &button)
Checks if the specified button is currently pressed.
static Button joy(GamepadButton button, int gamepad=0)
Creates a button associated with a gamepad buttion.
static Button gamepad_button(GamepadButton button, int gamepad=0)
Creates a button associated with a gamepad buttion.
bool operator<(const Button &o) const
Overloaded less-than operator for comparing buttons.
static Button pad(GamepadButton button, int gamepad=0)
Creates a button associated with a gamepad buttion.
static uint8_t IsSetPressed(const std::set< Button > &buttons)
Checks if a set of buttons is pressed.
static Button key(KeyboardKey key)
Creates a button associated with a keyboard key.
static Button mouse_button(MouseButton button)
Creates a button associated with a mouse buttion.
static Button btn(MouseButton button)
Creates a button associated with a mouse buttion.