Redesigned RPI input system -IN PROGRESS-
This commit is contained in:
parent
afd2ffb74a
commit
8aab52aeda
5 changed files with 289 additions and 186 deletions
|
@ -21,6 +21,7 @@ int main()
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input");
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input");
|
||||||
|
|
||||||
Vector2 ballPosition = { -100.0f, -100.0f };
|
Vector2 ballPosition = { -100.0f, -100.0f };
|
||||||
|
Color ballColor = DARKBLUE;
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
|
@ -30,10 +31,11 @@ int main()
|
||||||
{
|
{
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
|
||||||
{
|
|
||||||
ballPosition = GetMousePosition();
|
ballPosition = GetMousePosition();
|
||||||
}
|
|
||||||
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ballColor = MAROON;
|
||||||
|
else if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) ballColor = LIME;
|
||||||
|
else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) ballColor = DARKBLUE;
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
@ -42,9 +44,9 @@ int main()
|
||||||
|
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
DrawCircleV(ballPosition, 40, GOLD);
|
DrawCircleV(ballPosition, 40, ballColor);
|
||||||
|
|
||||||
DrawText("mouse click to draw the ball", 10, 10, 20, DARKGRAY);
|
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
@ -227,10 +227,10 @@ core_mouse_wheel: core_mouse_wheel.c
|
||||||
|
|
||||||
# compile [core] example - gamepad input
|
# compile [core] example - gamepad input
|
||||||
core_input_gamepad: core_input_gamepad.c
|
core_input_gamepad: core_input_gamepad.c
|
||||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI))
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
||||||
else
|
else
|
||||||
@echo core_input_gamepad: Only supported on desktop platform
|
@echo core_input_gamepad: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# compile [core] example - generate random values
|
# compile [core] example - generate random values
|
||||||
|
@ -246,15 +246,15 @@ core_drop_files: core_drop_files.c
|
||||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
||||||
else
|
else
|
||||||
@echo core_drop_files: Only supported on desktop platform
|
@echo core_drop_files: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB or PLATFORM_RPI
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# compile [core] example - storage values
|
# compile [core] example - storage values
|
||||||
core_storage_values: core_storage_values.c
|
core_storage_values: core_storage_values.c
|
||||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI))
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
|
||||||
else
|
else
|
||||||
@echo core_storage_values: Only supported on desktop platform
|
@echo core_storage_values: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# compile [core] example - gestures detection
|
# compile [core] example - gestures detection
|
||||||
|
|
423
src/core.c
423
src/core.c
|
@ -103,10 +103,15 @@
|
||||||
#include "EGL/eglext.h" // Khronos EGL library - Extensions
|
#include "EGL/eglext.h" // Khronos EGL library - Extensions
|
||||||
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
|
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
|
||||||
|
|
||||||
#define DEFAULT_KEYBOARD_DEV "/dev/input/event0" // Not used, keyboard inputs are read raw from stdin
|
// Old device inputs system
|
||||||
#define DEFAULT_MOUSE_DEV "/dev/input/event1"
|
#define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input
|
||||||
//#define DEFAULT_MOUSE_DEV "/dev/input/mouse0"
|
#define DEFAULT_MOUSE_DEV "/dev/input/mouse0"
|
||||||
#define DEFAULT_GAMEPAD_DEV "/dev/input/js0"
|
#define DEFAULT_GAMEPAD_DEV "/dev/input/js0"
|
||||||
|
|
||||||
|
// New device input events (evdev) (must be detected)
|
||||||
|
//#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN"
|
||||||
|
//#define DEFAULT_MOUSE_DEV "/dev/input/eventN"
|
||||||
|
//#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
|
@ -142,16 +147,11 @@ static int currentButtonState[128] = { 1 }; // Required to check if button p
|
||||||
#elif defined(PLATFORM_RPI)
|
#elif defined(PLATFORM_RPI)
|
||||||
static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device)
|
static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device)
|
||||||
|
|
||||||
// Input variables (mouse/keyboard)
|
// Keyboard input variables
|
||||||
static int mouseStream = -1; // Mouse device file descriptor
|
|
||||||
static bool mouseReady = false; // Flag to know if mouse is ready
|
|
||||||
pthread_t mouseThreadId; // Mouse reading thread id
|
|
||||||
|
|
||||||
// NOTE: For keyboard we will use the standard input (but reconfigured...)
|
// NOTE: For keyboard we will use the standard input (but reconfigured...)
|
||||||
|
static struct termios defaultKeyboardSettings; // Used to store default keyboard settings
|
||||||
static int defaultKeyboardMode; // Used to store default keyboard mode
|
static int defaultKeyboardMode; // Used to store default keyboard mode
|
||||||
static struct termios defaultKeyboardSettings; // Used to staore default keyboard settings
|
static int keyboardMode = 0; // Register Keyboard mode: 1 - KEYCODES, 2 - ASCII
|
||||||
|
|
||||||
static int keyboardMode = 0; // Keyboard mode: 1 - KEYCODES, 2 - ASCII
|
|
||||||
|
|
||||||
// This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256)
|
// This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256)
|
||||||
const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68,
|
const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68,
|
||||||
|
@ -159,7 +159,15 @@ const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
||||||
297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1,
|
297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1,
|
||||||
346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
||||||
|
|
||||||
|
// Mouse input variables
|
||||||
|
static int mouseStream = -1; // Mouse device file descriptor
|
||||||
|
static bool mouseReady = false; // Flag to know if mouse is ready
|
||||||
|
pthread_t mouseThreadId; // Mouse reading thread id
|
||||||
|
|
||||||
|
// Gamepad input variables
|
||||||
static int gamepadStream = -1; // Gamepad device file descriptor
|
static int gamepadStream = -1; // Gamepad device file descriptor
|
||||||
|
static bool gamepadReady = false; // Flag to know if gamepad is ready
|
||||||
|
pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||||
|
@ -244,11 +252,13 @@ static void LogoAnimation(void); // Plays raylib logo app
|
||||||
static void SetupFramebufferSize(int displayWidth, int displayHeight);
|
static void SetupFramebufferSize(int displayWidth, int displayHeight);
|
||||||
|
|
||||||
#if defined(PLATFORM_RPI)
|
#if defined(PLATFORM_RPI)
|
||||||
|
static void InitKeyboard(void); // Init raw keyboard system (standard input reading)
|
||||||
|
static void ProcessKeyboard(void); // Process keyboard events
|
||||||
|
static void RestoreKeyboard(void); // Restore keyboard system
|
||||||
static void InitMouse(void); // Mouse initialization (including mouse thread)
|
static void InitMouse(void); // Mouse initialization (including mouse thread)
|
||||||
static void *MouseThread(void *arg); // Mouse reading thread
|
static void *MouseThread(void *arg); // Mouse reading thread
|
||||||
static void InitKeyboard(void); // Init raw keyboard system (standard input reading)
|
|
||||||
static void RestoreKeyboard(void); // Restore keyboard system
|
|
||||||
static void InitGamepad(void); // Init raw gamepad input
|
static void InitGamepad(void); // Init raw gamepad input
|
||||||
|
static void *GamepadThread(void *arg); // Mouse reading thread
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
|
@ -1128,18 +1138,21 @@ bool IsCursorHidden()
|
||||||
{
|
{
|
||||||
return cursorHidden;
|
return cursorHidden;
|
||||||
}
|
}
|
||||||
#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
|
||||||
|
|
||||||
// TODO: Enable gamepad usage on Rapsberry Pi
|
// NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB)
|
||||||
// NOTE: emscripten not implemented
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
// Detect if a gamepad is available
|
// Detect if a gamepad is available
|
||||||
bool IsGamepadAvailable(int gamepad)
|
bool IsGamepadAvailable(int gamepad)
|
||||||
{
|
{
|
||||||
int result = glfwJoystickPresent(gamepad);
|
bool result = false;
|
||||||
|
|
||||||
if (result == 1) return true;
|
#if defined(PLATFORM_RPI)
|
||||||
else return false;
|
if (gamepadReady && (gamepad == 0)) result = true;
|
||||||
|
#else
|
||||||
|
if (glfwJoystickPresent(gamepad) == 1) result = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return axis movement vector for a gamepad
|
// Return axis movement vector for a gamepad
|
||||||
|
@ -1148,9 +1161,13 @@ Vector2 GetGamepadMovement(int gamepad)
|
||||||
Vector2 vec = { 0, 0 };
|
Vector2 vec = { 0, 0 };
|
||||||
|
|
||||||
const float *axes;
|
const float *axes;
|
||||||
int axisCount;
|
int axisCount = 0;
|
||||||
|
|
||||||
|
#if defined(PLATFORM_RPI)
|
||||||
|
// TODO: Get gamepad axis information
|
||||||
|
#else
|
||||||
axes = glfwGetJoystickAxes(gamepad, &axisCount);
|
axes = glfwGetJoystickAxes(gamepad, &axisCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (axisCount >= 2)
|
if (axisCount >= 2)
|
||||||
{
|
{
|
||||||
|
@ -1184,16 +1201,20 @@ bool IsGamepadButtonPressed(int gamepad, int button)
|
||||||
// Detect if a gamepad button is being pressed
|
// Detect if a gamepad button is being pressed
|
||||||
bool IsGamepadButtonDown(int gamepad, int button)
|
bool IsGamepadButtonDown(int gamepad, int button)
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
const unsigned char *buttons;
|
const unsigned char *buttons;
|
||||||
int buttonsCount;
|
int buttonsCount;
|
||||||
|
|
||||||
|
#if defined(PLATFORM_RPI)
|
||||||
|
// TODO: Get gamepad buttons information
|
||||||
|
#else
|
||||||
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
||||||
|
|
||||||
if ((buttons != NULL) && (buttons[button] == GLFW_PRESS))
|
if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true;
|
||||||
{
|
else result = false;
|
||||||
return true;
|
#endif
|
||||||
}
|
|
||||||
else return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if a gamepad button has NOT been pressed once
|
// Detect if a gamepad button has NOT been pressed once
|
||||||
|
@ -1216,19 +1237,23 @@ bool IsGamepadButtonReleased(int gamepad, int button)
|
||||||
// Detect if a mouse button is NOT being pressed
|
// Detect if a mouse button is NOT being pressed
|
||||||
bool IsGamepadButtonUp(int gamepad, int button)
|
bool IsGamepadButtonUp(int gamepad, int button)
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
const unsigned char *buttons;
|
const unsigned char *buttons;
|
||||||
int buttonsCount;
|
int buttonsCount;
|
||||||
|
|
||||||
|
#if defined(PLATFORM_RPI)
|
||||||
|
// TODO: Get gamepad buttons information
|
||||||
|
#else
|
||||||
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
||||||
|
|
||||||
if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE))
|
if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true;
|
||||||
{
|
else result = false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||||
|
|
||||||
// Returns touch position X
|
// Returns touch position X
|
||||||
int GetTouchX(void)
|
int GetTouchX(void)
|
||||||
{
|
{
|
||||||
|
@ -2157,7 +2182,68 @@ static void PollInputEvents(void)
|
||||||
|
|
||||||
// NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin,
|
// NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin,
|
||||||
// we use method 2 (stdin) but maybe in a future we should change to method 1...
|
// we use method 2 (stdin) but maybe in a future we should change to method 1...
|
||||||
|
ProcessKeyboard();
|
||||||
|
|
||||||
|
// NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread()
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PLATFORM_RPI)
|
||||||
|
// Initialize Keyboard system (using standard input)
|
||||||
|
static void InitKeyboard(void)
|
||||||
|
{
|
||||||
|
// NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor
|
||||||
|
|
||||||
|
// Make stdin non-blocking (not enough, need to configure to non-canonical mode)
|
||||||
|
int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified
|
||||||
|
|
||||||
|
// Save terminal keyboard settings and reconfigure terminal with new settings
|
||||||
|
struct termios keyboardNewSettings;
|
||||||
|
tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings
|
||||||
|
keyboardNewSettings = defaultKeyboardSettings;
|
||||||
|
|
||||||
|
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing
|
||||||
|
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
|
||||||
|
keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG);
|
||||||
|
//keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF);
|
||||||
|
keyboardNewSettings.c_cc[VMIN] = 1;
|
||||||
|
keyboardNewSettings.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
// Set new keyboard settings (change occurs immediately)
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings);
|
||||||
|
|
||||||
|
// NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY???
|
||||||
|
|
||||||
|
// Save old keyboard mode to restore it at the end
|
||||||
|
if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0)
|
||||||
|
{
|
||||||
|
// NOTE: It could mean we are using a remote keyboard through ssh!
|
||||||
|
TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)");
|
||||||
|
|
||||||
|
keyboardMode = 2; // ASCII
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We reconfigure keyboard mode to get:
|
||||||
|
// - scancodes (K_RAW)
|
||||||
|
// - keycodes (K_MEDIUMRAW)
|
||||||
|
// - ASCII chars (K_XLATE)
|
||||||
|
// - UNICODE chars (K_UNICODE)
|
||||||
|
ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
|
||||||
|
|
||||||
|
//http://lct.sourceforge.net/lct/x60.html
|
||||||
|
|
||||||
|
keyboardMode = 2; // keycodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register keyboard restore when program finishes
|
||||||
|
atexit(RestoreKeyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ProcessKeyboard(void)
|
||||||
|
{
|
||||||
// Keyboard input polling (fill keys[256] array with status)
|
// Keyboard input polling (fill keys[256] array with status)
|
||||||
int numKeysBuffer = 0; // Keys available on buffer
|
int numKeysBuffer = 0; // Keys available on buffer
|
||||||
char keysBuffer[32]; // Max keys to be read at a time
|
char keysBuffer[32]; // Max keys to be read at a time
|
||||||
|
@ -2242,45 +2328,18 @@ static void PollInputEvents(void)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Gamepad support (use events, easy!)
|
|
||||||
/*
|
|
||||||
struct js_event gamepadEvent;
|
|
||||||
|
|
||||||
read(gamepadStream, &gamepadEvent, sizeof(struct js_event));
|
|
||||||
|
|
||||||
if (gamepadEvent.type == JS_EVENT_BUTTON)
|
|
||||||
{
|
|
||||||
switch (gamepadEvent.number)
|
|
||||||
{
|
|
||||||
case 0: // 1st Axis X
|
|
||||||
case 1: // 1st Axis Y
|
|
||||||
case 2: // 2st Axis X
|
|
||||||
case 3: // 2st Axis Y
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
if (gamepadEvent.value == 1) // Button pressed, 0 release
|
|
||||||
|
|
||||||
} break;
|
|
||||||
// Buttons is similar, variable for every joystick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (gamepadEvent.type == JS_EVENT_AXIS)
|
|
||||||
{
|
|
||||||
switch (gamepadEvent.number)
|
|
||||||
{
|
|
||||||
case 0: // 1st Axis X
|
|
||||||
case 1: // 1st Axis Y
|
|
||||||
case 2: // 2st Axis X
|
|
||||||
case 3: // 2st Axis Y
|
|
||||||
// Buttons is similar, variable for every joystick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PLATFORM_RPI)
|
// Restore default keyboard input
|
||||||
|
static void RestoreKeyboard(void)
|
||||||
|
{
|
||||||
|
// Reset to default keyboard settings
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings);
|
||||||
|
|
||||||
|
// Reconfigure keyboard to default mode
|
||||||
|
ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode);
|
||||||
|
}
|
||||||
|
|
||||||
// Mouse initialization (including mouse thread)
|
// Mouse initialization (including mouse thread)
|
||||||
static void InitMouse(void)
|
static void InitMouse(void)
|
||||||
{
|
{
|
||||||
|
@ -2305,118 +2364,156 @@ static void InitMouse(void)
|
||||||
// if too much time passes between reads, queue gets full and new events override older ones...
|
// if too much time passes between reads, queue gets full and new events override older ones...
|
||||||
static void *MouseThread(void *arg)
|
static void *MouseThread(void *arg)
|
||||||
{
|
{
|
||||||
struct input_event mouseEvent;
|
const unsigned char XSIGN = 1<<4, YSIGN = 1<<5;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buttons;
|
||||||
|
char dx, dy;
|
||||||
|
} MouseEvent;
|
||||||
|
|
||||||
|
MouseEvent mouse;
|
||||||
|
|
||||||
|
int mouseRelX = 0;
|
||||||
|
int mouseRelY = 0;
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
// NOTE: read() will return -1 if the events queue is empty
|
if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent))
|
||||||
read(mouseStream, &mouseEvent, sizeof(struct input_event));
|
|
||||||
|
|
||||||
// Check event types
|
|
||||||
if (mouseEvent.type == EV_REL) // Relative motion event
|
|
||||||
{
|
{
|
||||||
if (mouseEvent.code == REL_X)
|
if ((mouse.buttons & 0x08) == 0) break; // This bit should always be set
|
||||||
{
|
|
||||||
mousePosition.x += (float)mouseEvent.value;
|
// Check Left button pressed
|
||||||
|
if ((mouse.buttons & 0x01) > 0) currentMouseState[0] = 1;
|
||||||
|
else currentMouseState[0] = 0;
|
||||||
|
|
||||||
|
// Check Right button pressed
|
||||||
|
if ((mouse.buttons & 0x02) > 0) currentMouseState[1] = 1;
|
||||||
|
else currentMouseState[1] = 0;
|
||||||
|
|
||||||
|
// Check Middle button pressed
|
||||||
|
if ((mouse.buttons & 0x04) > 0) currentMouseState[2] = 1;
|
||||||
|
else currentMouseState[2] = 0;
|
||||||
|
|
||||||
|
mouseRelX = (int)mouse.dx;
|
||||||
|
mouseRelY = (int)mouse.dy;
|
||||||
|
|
||||||
|
if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX);
|
||||||
|
if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY);
|
||||||
|
|
||||||
|
mousePosition.x += (float)mouseRelX;
|
||||||
|
mousePosition.y -= (float)mouseRelY;
|
||||||
|
|
||||||
// Screen limits X check
|
|
||||||
if (mousePosition.x < 0) mousePosition.x = 0;
|
if (mousePosition.x < 0) mousePosition.x = 0;
|
||||||
if (mousePosition.x > screenWidth) mousePosition.x = screenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouseEvent.code == REL_Y)
|
|
||||||
{
|
|
||||||
mousePosition.y += (float)mouseEvent.value;
|
|
||||||
|
|
||||||
// Screen limits Y check
|
|
||||||
if (mousePosition.y < 0) mousePosition.y = 0;
|
if (mousePosition.y < 0) mousePosition.y = 0;
|
||||||
|
|
||||||
|
if (mousePosition.x > screenWidth) mousePosition.x = screenWidth;
|
||||||
if (mousePosition.y > screenHeight) mousePosition.y = screenHeight;
|
if (mousePosition.y > screenHeight) mousePosition.y = screenHeight;
|
||||||
}
|
}
|
||||||
|
//else read(mouseStream, &mouse, 1); // Try to sync up again
|
||||||
if (mouseEvent.code == REL_WHEEL)
|
|
||||||
{
|
|
||||||
// mouseEvent.value give 1 or -1 (direction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mouseEvent.type == EV_KEY) // Mouse button event
|
|
||||||
{
|
|
||||||
if (mouseEvent.code == BTN_LEFT) currentMouseState[0] = mouseEvent.value;
|
|
||||||
if (mouseEvent.code == BTN_RIGHT) currentMouseState[1] = mouseEvent.value;
|
|
||||||
if (mouseEvent.code == BTN_MIDDLE) currentMouseState[2] = mouseEvent.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize Keyboard system (using standard input)
|
|
||||||
static void InitKeyboard(void)
|
|
||||||
{
|
|
||||||
// NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor
|
|
||||||
|
|
||||||
// Make stdin non-blocking (not enough, need to configure to non-canonical mode)
|
|
||||||
int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags
|
|
||||||
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified
|
|
||||||
|
|
||||||
// Save terminal keyboard settings and reconfigure terminal with new settings
|
|
||||||
struct termios keyboardNewSettings;
|
|
||||||
tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings
|
|
||||||
keyboardNewSettings = defaultKeyboardSettings;
|
|
||||||
|
|
||||||
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing
|
|
||||||
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
|
|
||||||
keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG);
|
|
||||||
//keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF);
|
|
||||||
keyboardNewSettings.c_cc[VMIN] = 1;
|
|
||||||
keyboardNewSettings.c_cc[VTIME] = 0;
|
|
||||||
|
|
||||||
// Set new keyboard settings (change occurs immediately)
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings);
|
|
||||||
|
|
||||||
// NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY???
|
|
||||||
|
|
||||||
// Save old keyboard mode to restore it at the end
|
|
||||||
if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0)
|
|
||||||
{
|
|
||||||
// NOTE: It could mean we are using a remote keyboard through ssh!
|
|
||||||
TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)");
|
|
||||||
|
|
||||||
keyboardMode = 2; // ASCII
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We reconfigure keyboard mode to get:
|
|
||||||
// - scancodes (K_RAW)
|
|
||||||
// - keycodes (K_MEDIUMRAW)
|
|
||||||
// - ASCII chars (K_XLATE)
|
|
||||||
// - UNICODE chars (K_UNICODE)
|
|
||||||
ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW);
|
|
||||||
|
|
||||||
//http://lct.sourceforge.net/lct/x60.html
|
|
||||||
|
|
||||||
keyboardMode = 1; // keycodes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register keyboard restore when program finishes
|
|
||||||
atexit(RestoreKeyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore default keyboard input
|
|
||||||
static void RestoreKeyboard(void)
|
|
||||||
{
|
|
||||||
// Reset to default keyboard settings
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings);
|
|
||||||
|
|
||||||
// Reconfigure keyboard to default mode
|
|
||||||
ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init gamepad system
|
// Init gamepad system
|
||||||
static void InitGamepad(void)
|
static void InitGamepad(void)
|
||||||
{
|
{
|
||||||
// TODO: Add Gamepad support
|
if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0)
|
||||||
if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available");
|
{
|
||||||
|
TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gamepadReady = true;
|
||||||
|
|
||||||
|
int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL);
|
||||||
|
|
||||||
|
if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread");
|
||||||
else TraceLog(INFO, "Gamepad device initialized successfully");
|
else TraceLog(INFO, "Gamepad device initialized successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Gamepad (/dev/input/js0)
|
||||||
|
static void *GamepadThread(void *arg)
|
||||||
|
{
|
||||||
|
#define JS_EVENT_BUTTON 0x01 // Button pressed/released
|
||||||
|
#define JS_EVENT_AXIS 0x02 // Joystick axis moved
|
||||||
|
#define JS_EVENT_INIT 0x80 // Initial state of device
|
||||||
|
|
||||||
|
struct js_event {
|
||||||
|
unsigned int time; // event timestamp in milliseconds
|
||||||
|
short value; // event value
|
||||||
|
unsigned char type; // event type
|
||||||
|
unsigned char number; // event axis/button number
|
||||||
|
};
|
||||||
|
|
||||||
|
// These values are sensible on Logitech Dual Action Rumble and Xbox360 controller
|
||||||
|
const int joystickAxisX = 0;
|
||||||
|
const int joystickAxisY = 1;
|
||||||
|
|
||||||
|
// Read gamepad event
|
||||||
|
struct js_event gamepadEvent;
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
int buttons[11];
|
||||||
|
int stickX;
|
||||||
|
int stickY;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (read(gamepadStream, &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
|
||||||
|
{
|
||||||
|
gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events
|
||||||
|
|
||||||
|
// Process gamepad events by type
|
||||||
|
if (gamepadEvent.type == JS_EVENT_BUTTON)
|
||||||
|
{
|
||||||
|
if (gamepadEvent.number < 11)
|
||||||
|
{
|
||||||
|
switch (gamepadEvent.value)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1: buttons[gamepadEvent.number] = gamepadEvent.value; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
switch (gamepadEvent.number)
|
||||||
|
{
|
||||||
|
case 0: // 1st Axis X
|
||||||
|
case 1: // 1st Axis Y
|
||||||
|
case 2: // 2st Axis X
|
||||||
|
case 3: // 2st Axis Y
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (gamepadEvent.value == 1) // Button pressed, 0 release
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
// Buttons is similar, variable for every joystick
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else if (gamepadEvent.type == JS_EVENT_AXIS)
|
||||||
|
{
|
||||||
|
if (gamepadEvent.number == joystickAxisX) stickX = gamepadEvent.value;
|
||||||
|
if (gamepadEvent.number == joystickAxisY) stickY = gamepadEvent.value;
|
||||||
|
/*
|
||||||
|
switch (gamepadEvent.number)
|
||||||
|
{
|
||||||
|
case 0: // 1st Axis X
|
||||||
|
case 1: // 1st Axis Y
|
||||||
|
case 2: // 2st Axis X
|
||||||
|
case 3: // 2st Axis Y
|
||||||
|
// Buttons is similar, variable for every joystick
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else read(gamepadStream, &gamepadEvent, 1); // Try to sync up again
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,13 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# define all object files required
|
# define all object files required
|
||||||
OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
|
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
|
OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
|
||||||
|
else
|
||||||
|
#GLAD only required on desktop platform
|
||||||
|
OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o stb_vorbis.o utils.o camera.o gestures.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# typing 'make' will invoke the first target entry in the file,
|
# typing 'make' will invoke the first target entry in the file,
|
||||||
# in this case, the 'default' target entry is raylib
|
# in this case, the 'default' target entry is raylib
|
||||||
|
|
|
@ -583,9 +583,7 @@ void HideCursor(void); // Hides cursor
|
||||||
void EnableCursor(void); // Enables cursor
|
void EnableCursor(void); // Enables cursor
|
||||||
void DisableCursor(void); // Disables cursor
|
void DisableCursor(void); // Disables cursor
|
||||||
bool IsCursorHidden(void); // Returns true if cursor is not visible
|
bool IsCursorHidden(void); // Returns true if cursor is not visible
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
|
bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
|
||||||
Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad
|
Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad
|
||||||
bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
|
bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue