#include "input_unified.h" namespace fn::input { namespace { constexpr float STICK_DEADZONE = 0.15f; constexpr float STICK_MAX = 32767.0f; float normalize_axis(int16_t v) { float f = (float)v / STICK_MAX; if (f > 1.0f) f = 1.0f; if (f < -1.0f) f = -1.0f; if (f > -STICK_DEADZONE && f < STICK_DEADZONE) return 0.0f; return f; } // Set logical button + rising-edge flag if transitioning false->true. void set_btn(bool& held, bool& pressed, bool down) { if (down && !held) pressed = true; held = down; } void apply_key(InputState& s, SDL_Keycode key, bool down) { switch (key) { case SDLK_A: case SDLK_LEFT: set_btn(s.left, s.left_pressed, down); break; case SDLK_D: case SDLK_RIGHT: set_btn(s.right, s.right_pressed, down); break; case SDLK_W: case SDLK_UP: set_btn(s.up, s.up_pressed, down); break; case SDLK_S: case SDLK_DOWN: set_btn(s.down, s.down_pressed, down); break; case SDLK_SPACE: set_btn(s.action_a, s.a_pressed, down); break; case SDLK_RETURN: set_btn(s.start, s.start_pressed, down); break; case SDLK_ESCAPE: set_btn(s.back, s.back_pressed, down); break; default: break; } } void apply_gpad_button(InputState& s, Uint8 button, bool down) { switch (button) { case SDL_GAMEPAD_BUTTON_DPAD_LEFT: set_btn(s.left, s.left_pressed, down); break; case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: set_btn(s.right, s.right_pressed, down); break; case SDL_GAMEPAD_BUTTON_DPAD_UP: set_btn(s.up, s.up_pressed, down); break; case SDL_GAMEPAD_BUTTON_DPAD_DOWN: set_btn(s.down, s.down_pressed, down); break; case SDL_GAMEPAD_BUTTON_SOUTH: set_btn(s.action_a, s.a_pressed, down); break; case SDL_GAMEPAD_BUTTON_EAST: set_btn(s.action_b, s.b_pressed, down); break; case SDL_GAMEPAD_BUTTON_WEST: set_btn(s.action_x, s.x_pressed, down); break; case SDL_GAMEPAD_BUTTON_NORTH: set_btn(s.action_y, s.y_pressed, down); break; case SDL_GAMEPAD_BUTTON_START: set_btn(s.start, s.start_pressed, down); break; case SDL_GAMEPAD_BUTTON_BACK: set_btn(s.back, s.back_pressed, down); break; default: break; } } int find_touch_slot(InputState& s, int id) { for (int i = 0; i < s.touch_count; ++i) { if (s.touches[i].id == id) return i; } return -1; } } // namespace void input_begin_frame(InputState& s) { s.left_pressed = s.right_pressed = s.up_pressed = s.down_pressed = false; s.a_pressed = s.b_pressed = s.x_pressed = s.y_pressed = false; s.start_pressed = s.back_pressed = false; s.m_left_pressed = s.m_right_pressed = false; } void input_process_event(InputState& s, const SDL_Event* e) { if (!e) return; switch (e->type) { case SDL_EVENT_KEY_DOWN: if (!e->key.repeat) apply_key(s, e->key.key, true); break; case SDL_EVENT_KEY_UP: apply_key(s, e->key.key, false); break; case SDL_EVENT_MOUSE_MOTION: s.mx = e->motion.x; s.my = e->motion.y; break; case SDL_EVENT_MOUSE_BUTTON_DOWN: if (e->button.button == SDL_BUTTON_LEFT) set_btn(s.m_left, s.m_left_pressed, true); if (e->button.button == SDL_BUTTON_RIGHT) set_btn(s.m_right, s.m_right_pressed, true); break; case SDL_EVENT_MOUSE_BUTTON_UP: if (e->button.button == SDL_BUTTON_LEFT) set_btn(s.m_left, s.m_left_pressed, false); if (e->button.button == SDL_BUTTON_RIGHT) set_btn(s.m_right, s.m_right_pressed, false); break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: apply_gpad_button(s, e->gbutton.button, true); break; case SDL_EVENT_GAMEPAD_BUTTON_UP: apply_gpad_button(s, e->gbutton.button, false); break; case SDL_EVENT_GAMEPAD_AXIS_MOTION: { float v = normalize_axis(e->gaxis.value); switch (e->gaxis.axis) { case SDL_GAMEPAD_AXIS_LEFTX: s.lx = v; break; case SDL_GAMEPAD_AXIS_LEFTY: s.ly = v; break; case SDL_GAMEPAD_AXIS_RIGHTX: s.rx = v; break; case SDL_GAMEPAD_AXIS_RIGHTY: s.ry = v; break; default: break; } break; } case SDL_EVENT_GAMEPAD_ADDED: SDL_OpenGamepad(e->gdevice.which); break; case SDL_EVENT_FINGER_DOWN: { if (s.touch_count < 8) { auto& t = s.touches[s.touch_count++]; t.id = (int)e->tfinger.fingerID; t.x = e->tfinger.x; t.y = e->tfinger.y; t.pressed = true; } break; } case SDL_EVENT_FINGER_MOTION: { int idx = find_touch_slot(s, (int)e->tfinger.fingerID); if (idx >= 0) { s.touches[idx].x = e->tfinger.x; s.touches[idx].y = e->tfinger.y; } break; } case SDL_EVENT_FINGER_UP: { int idx = find_touch_slot(s, (int)e->tfinger.fingerID); if (idx >= 0) { // compact array for (int i = idx; i < s.touch_count - 1; ++i) { s.touches[i] = s.touches[i + 1]; } s.touch_count--; s.touches[s.touch_count] = {}; } break; } default: break; } } } // namespace fn::input