From cc5310791801e65c5908024252a47f1e1f61fcee Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 26 Jun 2024 22:40:11 +1000 Subject: [PATCH] SDL: Untested controller support --- Makefile | 13 +++-- src/{Window_SDL.c => Window_SDL2.c} | 73 +++++++++++++++++++++++-- src/Window_SDL3.c | 82 ++++++++++++++++++++++++++--- 3 files changed, 153 insertions(+), 15 deletions(-) rename src/{Window_SDL.c => Window_SDL2.c} (79%) diff --git a/Makefile b/Makefile index 8147f1821..a80ef2dfe 100644 --- a/Makefile +++ b/Makefile @@ -209,7 +209,7 @@ clean: $(ENAME): $(BUILD_DIR) $(OBJECTS) - $(CC) $(LDFLAGS) -o $@$(OEXT) $(OBJECTS) $(LIBS) + $(CC) $(LDFLAGS) -o $@$(OEXT) $(OBJECTS) $(EXTRALIBS) $(LIBS) $(BUILD_DIR): mkdir -p $(BUILD_DIR) @@ -222,18 +222,21 @@ DEPFILES := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.d, $(C_SOURCES)) $(DEPFILES): $(C_OBJECTS): $(BUILD_DIR)/%.o : $(SOURCE_DIR)/%.c $(BUILD_DIR)/%.d - $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) $(EXTRAFLAGS) $(DEPFLAGS) -c $< -o $@ include $(wildcard $(DEPFILES)) # === Compiling WITHOUT dependency tracking === else $(C_OBJECTS): $(BUILD_DIR)/%.o : $(SOURCE_DIR)/%.c - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) $(EXTRAFLAGS) -c $< -o $@ endif # === Platform specific file compiling === $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.m - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) $(EXTRAFLAGS) -c $< -o $@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) $(EXTRAFLAGS) -c $< -o $@ + +# EXTRAFLAGS and EXTRALIBS are not defined in the makefile intentionally - +# define them on the command line as a simple way of adding CFLAGS/LIBS diff --git a/src/Window_SDL.c b/src/Window_SDL2.c similarity index 79% rename from src/Window_SDL.c rename to src/Window_SDL2.c index 5746910aa..04e7a551f 100644 --- a/src/Window_SDL.c +++ b/src/Window_SDL2.c @@ -52,7 +52,7 @@ static void Window_SDLFail(const char* place) { } void Window_PreInit(void) { - SDL_Init(SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER); } void Window_Init(void) { @@ -462,8 +462,75 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } -void Gamepads_Init(void) { } -void Gamepads_Process(float delta) { } + +/*########################################################################################################################* +*--------------------------------------------------------Gamepads---------------------------------------------------------* +*#########################################################################################################################*/ +#include "ExtMath.h" +static SDL_GameController* controllers[INPUT_MAX_GAMEPADS]; + +static void LoadControllers(void) { + for (int i = 0, port = 0; i < SDL_NumJoysticks() && port < INPUT_MAX_GAMEPADS; i++) + { + if (!SDL_IsGameController(i)) continue; + Input.Sources |= INPUT_SOURCE_GAMEPAD; + + controllers[port] = SDL_GameControllerOpen(i); + port++; + } +} + +void Gamepads_Init(void) { + LoadControllers(); +} + +static void ProcessGamepadButtons(int port) { + SDL_GameController* gp = controllers[port]; + + Gamepad_SetButton(port, CCPAD_A, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_A)); + Gamepad_SetButton(port, CCPAD_B, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_B)); + Gamepad_SetButton(port, CCPAD_X, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_X)); + Gamepad_SetButton(port, CCPAD_Y, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_Y)); + + Gamepad_SetButton(port, CCPAD_ZL, SDL_GameControllerGetAxis( gp, SDL_CONTROLLER_AXIS_TRIGGERLEFT ) > 8000); + Gamepad_SetButton(port, CCPAD_ZR, SDL_GameControllerGetAxis( gp, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 8000); + Gamepad_SetButton(port, CCPAD_L, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)); + Gamepad_SetButton(port, CCPAD_R, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)); + + Gamepad_SetButton(port, CCPAD_SELECT, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_GUIDE)); + Gamepad_SetButton(port, CCPAD_START, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_START)); + Gamepad_SetButton(port, CCPAD_LSTICK, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_LEFTSTICK)); + Gamepad_SetButton(port, CCPAD_RSTICK, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_RIGHTSTICK)); + + Gamepad_SetButton(port, CCPAD_UP, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_DPAD_UP)); + Gamepad_SetButton(port, CCPAD_DOWN, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_DPAD_DOWN)); + Gamepad_SetButton(port, CCPAD_LEFT, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_DPAD_LEFT)); + Gamepad_SetButton(port, CCPAD_RIGHT, SDL_GameControllerGetButton(gp, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)); +} + +#define PAD_AXIS_SCALE 32768.0f +static void ProcessJoystick(int port, int axis, float delta) { + SDL_GameController* gp = controllers[port]; + int x = SDL_GameControllerGetAxis(gp, axis == PAD_AXIS_LEFT ? SDL_CONTROLLER_AXIS_LEFTX : SDL_CONTROLLER_AXIS_RIGHTX); + int y = SDL_GameControllerGetAxis(gp, axis == PAD_AXIS_LEFT ? SDL_CONTROLLER_AXIS_LEFTY : SDL_CONTROLLER_AXIS_RIGHTY); + + // May not be exactly 0 on actual hardware + if (Math_AbsI(x) <= 1024) x = 0; + if (Math_AbsI(y) <= 1024) y = 0; + + Gamepad_SetAxis(port, axis, x / PAD_AXIS_SCALE, -y / PAD_AXIS_SCALE, delta); +} + +void Gamepads_Process(float delta) { + for (int port = 0; port < INPUT_MAX_GAMEPADS; port++) + { + if (!controllers[port]) continue; + + ProcessGamepadButtons(port); + ProcessJoystick(port, PAD_AXIS_LEFT, delta); + ProcessJoystick(port, PAD_AXIS_RIGHT, delta); + } +} /*########################################################################################################################* diff --git a/src/Window_SDL3.c b/src/Window_SDL3.c index e297444e7..2c37b6119 100644 --- a/src/Window_SDL3.c +++ b/src/Window_SDL3.c @@ -25,7 +25,7 @@ static void Window_SDLFail(const char* place) { } void Window_PreInit(void) { - SDL_Init(SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD); #ifdef CC_BUILD_FLATPAK SDL_SetHint(SDL_HINT_APP_ID, "net.classicube.flatpak.client"); #endif @@ -52,7 +52,7 @@ void Window_Free(void) { } #include "../misc/sdl/CCIcon_SDL.h" static void ApplyIcon(void) { - SDL_Surface* surface = SDL_CreateSurfaceFrom(CCIcon_Data, CCIcon_Width, CCIcon_Height, + SDL_Surface* surface = SDL_CreateSurfaceFrom((void*)CCIcon_Data, CCIcon_Width, CCIcon_Height, CCIcon_Pitch, SDL_PIXELFORMAT_BGRA8888); SDL_SetWindowIcon(win_handle, surface); } @@ -320,9 +320,6 @@ void Window_ProcessEvents(float delta) { } } -void Gamepads_Init(void) { } -void Gamepads_Process(float delta) { } - static void Cursor_GetRawPos(int* x, int* y) { float xPos, yPos; SDL_GetMouseState(&xPos, &yPos); @@ -478,11 +475,11 @@ void Window_FreeFramebuffer(struct Bitmap* bmp) { /* TODO: Do we still need to unlock it though? */ } -void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { SDL_StartTextInput(); } +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { SDL_StartTextInput(win_handle); } void OnscreenKeyboard_SetText(const cc_string* text) { } void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } void OnscreenKeyboard_Draw3D(void) { } -void OnscreenKeyboard_Close(void) { SDL_StopTextInput(); } +void OnscreenKeyboard_Close(void) { SDL_StopTextInput(win_handle); } void Window_EnableRawMouse(void) { RegrabMouse(); @@ -498,6 +495,77 @@ void Window_DisableRawMouse(void) { } +/*########################################################################################################################* +*--------------------------------------------------------Gamepads---------------------------------------------------------* +*#########################################################################################################################*/ +#include "ExtMath.h" +static SDL_Gamepad* controllers[INPUT_MAX_GAMEPADS]; + +static void LoadControllers(void) { + int count = 0; + SDL_JoystickID* joysticks = SDL_GetGamepads(&count); + + for (int i = 0; i < count && i < INPUT_MAX_GAMEPADS; i++) + { + Input.Sources |= INPUT_SOURCE_GAMEPAD; + controllers[i] = SDL_OpenGamepad(joysticks[i]); + } + SDL_free(joysticks); +} + +void Gamepads_Init(void) { + LoadControllers(); +} + +static void ProcessGamepadButtons(int port) { + SDL_Gamepad* gp = controllers[port]; + + Gamepad_SetButton(port, CCPAD_A, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_SOUTH)); + Gamepad_SetButton(port, CCPAD_B, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_EAST)); + Gamepad_SetButton(port, CCPAD_X, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_WEST)); + Gamepad_SetButton(port, CCPAD_Y, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_NORTH)); + + Gamepad_SetButton(port, CCPAD_ZL, SDL_GetGamepadAxis( gp, SDL_GAMEPAD_AXIS_LEFT_TRIGGER ) > 8000); + Gamepad_SetButton(port, CCPAD_ZR, SDL_GetGamepadAxis( gp, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) > 8000); + Gamepad_SetButton(port, CCPAD_L, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)); + Gamepad_SetButton(port, CCPAD_R, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)); + + Gamepad_SetButton(port, CCPAD_SELECT, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_GUIDE)); + Gamepad_SetButton(port, CCPAD_START, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_START)); + Gamepad_SetButton(port, CCPAD_LSTICK, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_LEFT_STICK)); + Gamepad_SetButton(port, CCPAD_RSTICK, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_RIGHT_STICK)); + + Gamepad_SetButton(port, CCPAD_UP, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_DPAD_UP)); + Gamepad_SetButton(port, CCPAD_DOWN, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_DPAD_DOWN)); + Gamepad_SetButton(port, CCPAD_LEFT, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_DPAD_LEFT)); + Gamepad_SetButton(port, CCPAD_RIGHT, SDL_GetGamepadButton(gp, SDL_GAMEPAD_BUTTON_DPAD_RIGHT)); +} + +#define PAD_AXIS_SCALE 32768.0f +static void ProcessJoystick(int port, int axis, float delta) { + SDL_Gamepad* gp = controllers[port]; + int x = SDL_GetGamepadAxis(gp, axis == PAD_AXIS_LEFT ? SDL_GAMEPAD_AXIS_LEFTX : SDL_GAMEPAD_AXIS_RIGHTX); + int y = SDL_GetGamepadAxis(gp, axis == PAD_AXIS_LEFT ? SDL_GAMEPAD_AXIS_LEFTY : SDL_GAMEPAD_AXIS_RIGHTY); + + // May not be exactly 0 on actual hardware + if (Math_AbsI(x) <= 1024) x = 0; + if (Math_AbsI(y) <= 1024) y = 0; + + Gamepad_SetAxis(port, axis, x / PAD_AXIS_SCALE, -y / PAD_AXIS_SCALE, delta); +} + +void Gamepads_Process(float delta) { + for (int port = 0; port < INPUT_MAX_GAMEPADS; port++) + { + if (!controllers[port]) continue; + + ProcessGamepadButtons(port); + ProcessJoystick(port, PAD_AXIS_LEFT, delta); + ProcessJoystick(port, PAD_AXIS_RIGHT, delta); + } +} + + /*########################################################################################################################* *-----------------------------------------------------OpenGL context------------------------------------------------------* *#########################################################################################################################*/