feat(kotlin-compose): design system + 33 components + gallery_kt + e2e android emulator + scaffolder fixes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user