Major updates

This commit is contained in:
Michael 2023-10-13 11:56:54 -04:00
parent 57fafad066
commit 2569d101da
3 changed files with 101 additions and 35 deletions

View File

@ -1,18 +1,18 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [core] example - Gamepad information * raylib [core] example - Gamepad information
* *
* NOTE: This example requires a Gamepad connected to the system * NOTE: This example requires a Gamepad connected to the system
* Check raylib.h for buttons configuration * Check raylib.h for buttons configuration
* *
* Example originally created with raylib 4.6, last time updated with raylib 4.6 * Example originally created with raylib 4.6, last time updated with raylib 4.6
* *
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software * BSD-like license that allows static linking with closed source software
* *
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) * Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
* *
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
@ -26,14 +26,14 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad information"); InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad information");
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
int y = 10; int y = 10;
@ -41,12 +41,24 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
for (int i = 0; i < 4; i++) // by default rcore.h has a MAX_GAMEPADS of 4 so mimmic that here. for (int i = 0; i < 4; i++) // by default rcore.h has a MAX_GAMEPADS of 4 so mimmic that here.
{ {
if (IsGamepadAvailable(i)) if (IsGamepadAvailable(i))
{ {
DrawText(TextFormat("Gamepad:\n\tName: %s\n\tAxes: %d", GetGamepadName(i), GetGamepadAxisCount(i)), 10, y, 20, BLACK); DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 20, BLACK);
y += 40; y += 30;
DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 20, BLACK);
y += 30;
for (int axis = 0; axis < GetGamepadAxisCount(i); axis++)
{
DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 20, BLACK);
y += 30;
}
for (int button = 0; button < 32; button++)
{
DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonPressed(i, button)), 10, y, 20, BLACK);
y += 30;
}
} }
} }
@ -55,6 +67,6 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
} }

View File

@ -1339,7 +1339,7 @@ void PollInputEvents(void)
// Reset last gamepad button/axis registered state // Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
CORE.Input.Gamepad.axisCount = 0; //CORE.Input.Gamepad.axisCount = 0;
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback) // Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
// Register previous keys states // Register previous keys states
@ -1439,7 +1439,7 @@ void PollInputEvents(void)
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f); CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f); CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);
CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST + 1; CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
} }
} }

View File

@ -85,6 +85,11 @@
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef struct {
int min;
int max;
} GamepadAxisRange;
typedef struct { typedef struct {
pthread_t threadId; // Event reading thread id pthread_t threadId; // Event reading thread id
@ -131,8 +136,12 @@ typedef struct {
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
// Gamepad data // Gamepad data
pthread_t gamepadThreadId; // Gamepad reading thread id pthread_t gamepadThreadId; // Gamepad reading thread id
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
struct input_absinfo gamepadAxisFeatures[MAX_GAMEPADS][ABS_MAX]; // Store the features of each axis for each gamepad.
int gamepadActiveAxes[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Map axis ID to actual axis, e.g. the first axis found will be axis 0 as far as raylib is concerned but might actually be ABS_HAT0X (16) for some gamepads.
int gamepadButtonCount[MAX_GAMEPADS]; // Store the number of active buttons found, up to MAX_GAMEPAD_BUTTONS
int gamepadActiveButtons[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Map button ID to actual key. e.g. the first key on a joystick might be KEY_A or KEY_X.
} PlatformData; } PlatformData;
@ -1479,7 +1488,7 @@ static void InitDrmInput(void)
// Devices are in the format: // Devices are in the format:
// /dev/input/by-id/usb-Name_of_Device-[event-joystick|event-kbd|event-mouse] // /dev/input/by-id/usb-Name_of_Device-[event-joystick|event-kbd|event-mouse]
int len = strlen("event-joystick"); int len = strlen("event-joystick");
if (strncmp("event-joystick", entity->d_name + (strlen(entity->d_name)-len), len) == 0) if (strncmp("event-joystick", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-joystick"
{ {
TraceLog(LOG_INFO, TextFormat("Device %s is an event joystick", entity->d_name)); TraceLog(LOG_INFO, TextFormat("Device %s is an event joystick", entity->d_name));
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
@ -1493,13 +1502,13 @@ static void InitDrmInput(void)
} }
len = strlen("event-kbd"); len = strlen("event-kbd");
if (strncmp("event-kbd", entity->d_name + (strlen(entity->d_name)-len), len) == 0) if (strncmp("event-kbd", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-kbd"
{ {
TraceLog(LOG_INFO, TextFormat("Device %s is an event keyboard", entity->d_name)); TraceLog(LOG_INFO, TextFormat("Device %s is an event keyboard", entity->d_name));
} }
len = strlen("event-mouse"); len = strlen("event-mouse");
if (strncmp("event-mouse", entity->d_name + (strlen(entity->d_name)-len), len) == 0) if (strncmp("event-mouse", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-mouse"
{ {
TraceLog(LOG_INFO, TextFormat("Device %s is an event mouse", entity->d_name)); TraceLog(LOG_INFO, TextFormat("Device %s is an event mouse", entity->d_name));
} }
@ -1516,18 +1525,36 @@ static void InitDrmJoystick(int index, const char *path)
int result = (platform.gamepadStreamFd[index] = open(path, O_RDONLY | O_NONBLOCK)); int result = (platform.gamepadStreamFd[index] = open(path, O_RDONLY | O_NONBLOCK));
printf("Result of file open: %d\n", result); printf("Result of file open: %d\n", result);
// Get the name of the device.
ioctl(platform.gamepadStreamFd[index], EVIOCGNAME(64), &CORE.Input.Gamepad.name[index]);
// Get the bits describing the buttons of the device.
unsigned long key_bits[KEY_MAX / 8 + 1] = {0};
ioctl(platform.gamepadStreamFd[index], EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits);
// Count the buttons present and map a game button id (0-32) to the key code of the physical button.
for (int key = 0; key < KEY_MAX; key++)
{
if (MI_IS_BIT_SET(key_bits, key) && platform.gamepadButtonCount[index] < MAX_GAMEPAD_BUTTONS)
{
platform.gamepadActiveButtons[index][platform.gamepadButtonCount[index]++] = key;
}
}
// Get the bits describing the absolute axes of the device. // Get the bits describing the absolute axes of the device.
unsigned long abs_bits[ABS_MAX / 8 + 1] = {0}; unsigned long abs_bits[ABS_MAX / 8 + 1] = {0};
ioctl(platform.gamepadStreamFd[index], EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits); ioctl(platform.gamepadStreamFd[index], EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits);
ioctl(platform.gamepadStreamFd[index], EVIOCGNAME(64), &CORE.Input.Gamepad.name[index]);
// Count the axes present on the device. // Count the axes present on the device and read their features.
CORE.Input.Gamepad.axisCount[index] = 0; CORE.Input.Gamepad.axisCount[index] = 0;
for (int axis = 0; axis < ABS_MAX; axis++) for (int axis = 0; axis < ABS_MAX; axis++)
{ {
if (MI_IS_BIT_SET(abs_bits, axis)) { // axis may be any number between 0x00 and 0x3f, and it is common for the first axis to be 0x10 (ABS_HAT0X). This maps the active axes to a range of IDs between 0 and MAX_GAMEPAD_AXIS
if (MI_IS_BIT_SET(abs_bits, axis) && CORE.Input.Gamepad.axisCount < MAX_GAMEPAD_AXIS)
{
platform.gamepadActiveAxes[index][CORE.Input.Gamepad.axisCount[index]++] = axis;
TraceLog(LOG_INFO, TextFormat("Gamepad %d has axis %d", index, axis)); TraceLog(LOG_INFO, TextFormat("Gamepad %d has axis %d", index, axis));
CORE.Input.Gamepad.axisCount[index]++; ioctl(platform.gamepadStreamFd[index], EVIOCGABS(axis), &platform.gamepadAxisFeatures[index][axis]);
} }
} }
@ -1550,7 +1577,32 @@ static void PollDrmJoystickEvents()
switch(ev.type) switch(ev.type)
{ {
case EV_KEY: case EV_KEY:
printf("Key %d = %d", ev.code, ev.value); if (ev.code < MAX_GAMEPAD_BUTTONS)
{
CORE.Input.Gamepad.currentButtonState[i][ev.code] = ev.value;
for (int lookupButton = 0; lookupButton < MAX_GAMEPAD_BUTTONS; lookupButton++)
{
if (platform.gamepadActiveButtons[i][lookupButton] == ev.code)
{
CORE.Input.Gamepad.currentButtonState[i][lookupButton] = ev.value;
break;
}
}
}
break;
case EV_ABS:
if (ev.code < MAX_GAMEPAD_AXIS)
{
struct input_absinfo f = platform.gamepadAxisFeatures[i][ev.code];
for (int lookupAxis = 0; lookupAxis < MAX_GAMEPAD_AXIS; lookupAxis++)
{
if (platform.gamepadActiveAxes[i][lookupAxis] == ev.code)
{
CORE.Input.Gamepad.axisState[i][lookupAxis] = ((float)ev.value - ((f.maximum - f.minimum) / 2.0f)) / (float)(f.maximum - f.minimum);
break;
}
}
}
break; break;
} }
} }
@ -2086,6 +2138,7 @@ static void *EventThread(void *arg)
// } // }
// } // }
/*
// Process Gamepad (/dev/input/js0) // Process Gamepad (/dev/input/js0)
static void *GamepadThread(void *arg) static void *GamepadThread(void *arg)
{ {
@ -2142,6 +2195,7 @@ static void *GamepadThread(void *arg)
return NULL; return NULL;
} }
*/
// Search matching DRM mode in connector's mode list // Search matching DRM mode in connector's mode list
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode) static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)