diff --git a/main.c b/main.c index 3e92518..de4f1e5 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,7 @@ static const Uint32 FONT_ID = 0; typedef struct app_state { SDL_Window *window; + SDL_Gamepad *gamepad; Clay_SDL3RendererData rendererData; ClayVideoDemo_Data demoData; ecs_world_t *world; @@ -45,7 +46,10 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { (void) argc; (void) argv; - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD)) { + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "0"); + + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD | SDL_INIT_JOYSTICK | SDL_INIT_SENSOR | SDL_INIT_HAPTIC)) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to initialize SDL: %s", SDL_GetError()); return SDL_APP_FAILURE; } @@ -116,7 +120,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { ECS_IMPORT(world, FlecsScript); ecs_singleton_set(world, EcsRest, {0}); // Creates REST server on default port (27750) state->world = world; - + *appstate = state; return SDL_APP_CONTINUE; } @@ -124,29 +128,39 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { AppState *state = appstate; SDL_AppResult ret_val = SDL_APP_CONTINUE; + SDL_UpdateGamepads(); switch (event->type) { - case SDL_EVENT_QUIT: + case SDL_EVENT_QUIT: { ret_val = SDL_APP_SUCCESS; break; - case SDL_EVENT_WINDOW_RESIZED: + } + case SDL_EVENT_WINDOW_RESIZED: { Clay_SetLayoutDimensions((Clay_Dimensions) { (float) event->window.data1, (float) event->window.data2 }); break; - case SDL_EVENT_MOUSE_MOTION: + } + case SDL_EVENT_MOUSE_MOTION: { Clay_SetPointerState((Clay_Vector2) { event->motion.x, event->motion.y }, event->motion.state & SDL_BUTTON_LMASK); break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: + } + case SDL_EVENT_MOUSE_BUTTON_DOWN: { Clay_SetPointerState((Clay_Vector2) { event->button.x, event->button.y }, event->button.button == SDL_BUTTON_LEFT); break; - case SDL_EVENT_MOUSE_WHEEL: + } + case SDL_EVENT_MOUSE_WHEEL: { Clay_UpdateScrollContainers(true, (Clay_Vector2) { event->wheel.x, event->wheel.y }, 0.01f); break; - case SDL_EVENT_KEY_DOWN: - if (event->key.repeat) { + } + case SDL_EVENT_KEY_DOWN: { + SDL_KeyboardEvent kb_event = event->key; + SDL_Keycode keycode = kb_event.key; + SDL_Scancode scancode = kb_event.scancode; + bool repeat = kb_event.repeat; + if (repeat) { break; } - SDL_Log("Pressed key: %s\n", SDL_GetKeyName(event->key.key)); - switch (event->key.scancode) { + SDL_Log("Pressed key: %s\n", SDL_GetKeyName(keycode)); + switch (scancode) { case SDL_SCANCODE_LCTRL: { ecs_world_t *world = state->world; ecs_entity_t e = ecs_entity(world, { .name = "Lily" }); @@ -166,9 +180,13 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { } } break; - case SDL_EVENT_KEY_UP: - SDL_Log("Released key: %s\n", SDL_GetKeyName(event->key.key)); - switch (event->key.scancode) { + } + case SDL_EVENT_KEY_UP: { + SDL_KeyboardEvent kb_event = event->key; + SDL_Keycode keycode = kb_event.key; + SDL_Scancode scancode = kb_event.scancode; + SDL_Log("Released key: %s\n", SDL_GetKeyName(keycode)); + switch (scancode) { case SDL_SCANCODE_LCTRL: { ecs_world_t *world = state->world; ecs_entity_t e = ecs_lookup(world, "Lily"); @@ -179,8 +197,50 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { } } break; - default: + } + case SDL_EVENT_GAMEPAD_ADDED: { + SDL_GamepadDeviceEvent device_event = event->gdevice; + SDL_JoystickID joystick_id = device_event.which; + SDL_Log("Gamepad ID %d added", joystick_id); + state->gamepad = SDL_OpenGamepad(joystick_id); // TODO: store multiple gamepads in state + if (!state->gamepad) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to open gamepad: %s", SDL_GetError()); + } break; + } + case SDL_EVENT_GAMEPAD_REMOVED: { + SDL_GamepadDeviceEvent device_event = event->gdevice; + SDL_JoystickID joystick_id = device_event.which; + SDL_Log("Gamepad ID %d removed", joystick_id); + break; + } + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { + SDL_GamepadButtonEvent button_event = event->gbutton; + SDL_GamepadButton button = button_event.button; + SDL_Log("Gamepad button down: %s", SDL_GetGamepadStringForButton(button)); + if (state->gamepad) { + if (!SDL_RumbleGamepad(state->gamepad, 0xFFFF, 0xFFFF, 1000)) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to rumble gamepad: %s", SDL_GetError()); + } + } + break; + } + case SDL_EVENT_GAMEPAD_BUTTON_UP: { + SDL_GamepadButtonEvent button_event = event->gbutton; + SDL_GamepadButton button = button_event.button; + SDL_Log("Gamepad button up: %s", SDL_GetGamepadStringForButton(button)); + break; + } + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { + SDL_GamepadAxisEvent axis_event = event->gaxis; + SDL_GamepadAxis axis = axis_event.axis; + Sint16 val = axis_event.value; + SDL_Log("Gamepad axis motion: %s - %d", SDL_GetGamepadStringForAxis(axis), val); + break; + } + default: { + break; + } } return ret_val;