VEX Engine
Retro looking game engine made in vulkan mostly because i wanted to understand it better.
Loading...
Searching...
No Matches
InputSystem.cpp
2#include <SDL3/SDL.h>
3#include <unordered_map>
4#include "SDL3/SDL_mouse.h"
6
7
8namespace vex {
9
10 InputSystem::InputSystem(vex::Registry &registry, SDL_Window *window)
11 : m_registry(registry), m_window(window), m_inputMode(InputMode::Game)
12 {
13 setInputMode(InputMode::Game);
14
15 if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD))
16 {
17 log(LogLevel::ERROR, "Could not initialize gamepad subsystem: %s", SDL_GetError());
18 }
19 }
20
22 m_inputMode = mode;
23 if (mode == InputMode::Game) {
24 SDL_SetWindowRelativeMouseMode(m_window, true);
25 SDL_HideCursor();
26 } else {
27 SDL_SetWindowRelativeMouseMode(m_window, false);
28 SDL_ShowCursor();
29 }
30 }
31
32 void InputSystem::processEvent(const SDL_Event &event, float deltaTime) {
33 if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_KEY_UP) {
34 bool isPressed = (event.type == SDL_EVENT_KEY_DOWN);
35 SDL_Scancode scancode = event.key.scancode;
36
37 auto& keyState = keyStates[scancode];
38 bool wasPressed = keyState.isPressed;
39
40 keyState.isPressed = isPressed;
41 if (isPressed && !wasPressed) {
42 keyState.wasProcessedAsPressed = false;
43 }
44
45 vex::View<InputComponent>(m_registry).each([&, this, scancode, isPressed, wasPressed](vex::Entity entity, InputComponent& inputComp) {
46 for (const auto& binding : inputComp.bindings) {
47 if (binding.scancode == scancode) {
48 if (isPressed && binding.state == InputActionState::Pressed && !wasPressed && !keyStates[scancode].wasProcessedAsPressed) {
49 binding.action(deltaTime);
50 keyStates[scancode].wasProcessedAsPressed = true;
51 } else if (!isPressed && binding.state == InputActionState::Released) {
52 binding.action(deltaTime);
53 } else if (!isPressed && binding.state == InputActionState::Held) {
54 binding.action(0.0f);
55 }
56 }
57 }
58 });
59 } else if (event.type == SDL_EVENT_MOUSE_MOTION && m_inputMode != InputMode::UI) {
60 vex::View<InputComponent>(m_registry).each([&, this](vex::Entity entity, InputComponent& inputComp) {
61 for (const auto& binding : inputComp.mouseAxisBindings) {
62 float delta = (binding.axis == MouseAxis::X) ? event.motion.xrel : event.motion.yrel;
63 binding.action(delta);
64 }
65 });
66 } else if (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event.type == SDL_EVENT_GAMEPAD_BUTTON_UP) {
67 bool isPressed = (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
68 SDL_GamepadButton button = (SDL_GamepadButton)event.gbutton.button;
69
70 gamepadButtonStates[button].isPressed = isPressed;
71
72 vex::View<InputComponent>(m_registry).each([&, this, button, isPressed, deltaTime](vex::Entity entity, InputComponent& inputComp) {
73 for (const auto& binding : inputComp.gamepadButtonBindings) {
74 if (binding.button == button) {
75 if (isPressed && binding.state == InputActionState::Pressed) {
76 binding.action(deltaTime);
77 } else if (!isPressed && binding.state == InputActionState::Released) {
78 binding.action(deltaTime);
79 }
80 }
81 }
82 });
83 } else if (event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
84 float normalizedValue = event.gaxis.value / 32767.0f;
85 gamepadAxisStates[(SDL_GamepadAxis)event.gaxis.axis] = normalizedValue;
86 }
87 }
88
89 void InputSystem::update(float deltaTime) {
90 vex::View<InputComponent>(m_registry).each([&, this, deltaTime](vex::Entity entity, InputComponent& inputComp) {
91 for (const auto& binding : inputComp.gamepadAxisBindings) {
92 float currentValue = gamepadAxisStates[binding.axis];
93 binding.action(currentValue);
94 }
95 for (const auto& binding : inputComp.gamepadButtonBindings) {
96 if (binding.state == InputActionState::Held && gamepadButtonStates[binding.button].isPressed) {
97 binding.action(deltaTime);
98 }
99 }
100 for (const auto& binding : inputComp.bindings) {
101 if (binding.state == InputActionState::Held && keyStates[binding.scancode].isPressed) {
102 binding.action(deltaTime);
103 }
104 }
105 });
106 }
107}
Component you add to your GameObject to handle input, eg. add input bindings and mouse axis bindings.
This file defines InputSystem class.
void setInputMode(InputMode mode)
Sets the input processing mode.
void update(float deltaTime)
Per-frame update for continuous input states.
InputSystem(vex::Registry &registry, SDL_Window *window)
Constructor for InputSystem.
void processEvent(const SDL_Event &event, float deltaTime)
Processes raw SDL events and maps them to Game Component actions.
Central registry for managing entities and their components in the ECS system.
Definition Registry.hpp:29
Provides iteration over entities that have all specified component types.
Definition View.hpp:17
void each(Func func)
Iterates over all entities with the specified component types.
Definition View.hpp:40
uint32_t Entity
Type alias representing a unique entity identifier in the ECS system.
Definition Types.hpp:11
InputMode
Enum representing different input modes.
void VEX_EXPORT log(const char *fmt,...)
Logs a formatted message.
Component you add to your GameObject to handle input, eg. add input bindings and mouse axis bindings.