diff --git a/src/main.zig b/src/main.zig index 7662f2d..8141333 100644 --- a/src/main.zig +++ b/src/main.zig @@ -127,6 +127,36 @@ pub fn main() !void { } defer seizer.backend.glfw.c.glfwTerminate(); + // update joystick to gamepad mappings + update_gamepad_mappings_file: { + const sdl_controller_config_filepath = std.process.getEnvVarOwned(gpa.allocator(), "SDL_GAMECONTROLLERCONFIG_FILE") catch break :update_gamepad_mappings_file; + defer gpa.allocator().free(sdl_controller_config_filepath); + + const controller_config_data = std.fs.cwd().readFileAllocOptions( + gpa.allocator(), + sdl_controller_config_filepath, + 512 * 1024 * 1024, + null, + @alignOf(u8), + 0, + ) catch break :update_gamepad_mappings_file; + defer gpa.allocator().free(controller_config_data); + + if (seizer.backend.glfw.c.glfwUpdateGamepadMappings(controller_config_data) == 0) { + std.log.warn("Failed to update gamepad mappings from file", .{}); + } + } + update_gamepad_mappings: { + const sdl_controller_config = std.process.getEnvVarOwned(gpa.allocator(), "SDL_GAMECONTROLLERCONFIG") catch break :update_gamepad_mappings; + defer gpa.allocator().free(sdl_controller_config); + + const sdl_controller_configz = gpa.allocator().dupeZ(u8, sdl_controller_config) catch break :update_gamepad_mappings; + + if (seizer.backend.glfw.c.glfwUpdateGamepadMappings(sdl_controller_configz) == 0) { + std.log.warn("Failed to update gamepad mappings from environment variable", .{}); + } + } + seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_OPENGL_DEBUG_CONTEXT, seizer.backend.glfw.c.GLFW_TRUE); seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_CLIENT_API, seizer.backend.glfw.c.GLFW_OPENGL_ES_API); seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -184,6 +214,12 @@ pub fn main() !void { // TODO: Restore hovered_action when undoing var hovered_action: ?Action = null; + if (seizer.backend.glfw.c.glfwJoystickIsGamepad(seizer.backend.glfw.c.GLFW_JOYSTICK_1) != 0) { + std.log.info("detected gamepad = \"{?s}\" {?s}", .{ seizer.backend.glfw.c.glfwGetGamepadName(seizer.backend.glfw.c.GLFW_JOYSTICK_1), seizer.backend.glfw.c.glfwGetJoystickGUID(seizer.backend.glfw.c.GLFW_JOYSTICK_1) }); + } else if (seizer.backend.glfw.c.glfwJoystickPresent(seizer.backend.glfw.c.GLFW_JOYSTICK_1) != 0) { + std.log.info("detected joystick = \"{?s}\" {?s}", .{ seizer.backend.glfw.c.glfwGetJoystickName(seizer.backend.glfw.c.GLFW_JOYSTICK_1), seizer.backend.glfw.c.glfwGetJoystickGUID(seizer.backend.glfw.c.GLFW_JOYSTICK_1) }); + } + while (seizer.backend.glfw.c.glfwWindowShouldClose(window) != seizer.backend.glfw.c.GLFW_TRUE) { input_state = .{ .left = false, @@ -195,6 +231,36 @@ pub fn main() !void { }; seizer.backend.glfw.c.glfwPollEvents(); + if (seizer.backend.glfw.c.glfwJoystickIsGamepad(seizer.backend.glfw.c.GLFW_JOYSTICK_1) != 0) { + var gamepad_state: seizer.backend.glfw.c.GLFWgamepadstate = undefined; + if (seizer.backend.glfw.c.glfwGetGamepadState(seizer.backend.glfw.c.GLFW_JOYSTICK_1, &gamepad_state) != 0) { + input_state.left = input_state.left or gamepad_state.buttons[seizer.backend.glfw.c.GLFW_GAMEPAD_BUTTON_DPAD_LEFT] != 0; + input_state.right = input_state.right or gamepad_state.buttons[seizer.backend.glfw.c.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] != 0; + input_state.up = input_state.up or gamepad_state.buttons[seizer.backend.glfw.c.GLFW_GAMEPAD_BUTTON_DPAD_UP] != 0; + input_state.down = input_state.down or gamepad_state.buttons[seizer.backend.glfw.c.GLFW_GAMEPAD_BUTTON_DPAD_DOWN] != 0; + } + } else if (seizer.backend.glfw.c.glfwJoystickPresent(seizer.backend.glfw.c.GLFW_JOYSTICK_1) != 0) { + var hats_count: c_int = undefined; + const hats_ptr = seizer.backend.glfw.c.glfwGetJoystickHats(seizer.backend.glfw.c.GLFW_JOYSTICK_1, &hats_count); + const hats = hats_ptr[0..@intCast(hats_count)]; + + const HAT_UP = seizer.backend.glfw.c.GLFW_HAT_UP; + const HAT_RIGHT = seizer.backend.glfw.c.GLFW_HAT_RIGHT; + const HAT_DOWN = seizer.backend.glfw.c.GLFW_HAT_DOWN; + const HAT_LEFT = seizer.backend.glfw.c.GLFW_HAT_LEFT; + + input_state.left = input_state.left or hats[0] & HAT_LEFT != 0; + input_state.right = input_state.right or hats[0] & HAT_RIGHT != 0; + input_state.up = input_state.up or hats[0] & HAT_UP != 0; + input_state.down = input_state.down or hats[0] & HAT_DOWN != 0; + + var buttons_count: c_int = undefined; + const buttons_ptr = seizer.backend.glfw.c.glfwGetJoystickButtons(seizer.backend.glfw.c.GLFW_JOYSTICK_1, &buttons_count); + const buttons = buttons_ptr[0..@intCast(buttons_count)]; + input_state.action = input_state.action or buttons[0] != 0; + input_state.undo = input_state.undo or buttons[1] != 0; + } + var request_command: ?[]const u8 = null; defer if (request_command) |command| gpa.allocator().free(command);