Check in current state
This commit is contained in:
parent
cbef73c5cb
commit
cddb0fa969
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -75,6 +75,9 @@ xcschememanagement.plist
|
||||||
xcuserdata/
|
xcuserdata/
|
||||||
DerivedData/
|
DerivedData/
|
||||||
|
|
||||||
|
# VSCode project
|
||||||
|
.vscode
|
||||||
|
|
||||||
# Jetbrains project
|
# Jetbrains project
|
||||||
.idea/
|
.idea/
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
|
|
|
||||||
621
src/rcore.c
621
src/rcore.c
|
|
@ -99,6 +99,7 @@
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#include "raylib.h" // Declares module functions
|
#include "raylib.h" // Declares module functions
|
||||||
|
#include "rcore.h"
|
||||||
|
|
||||||
// Check if config flags have been externally provided on compilation line
|
// Check if config flags have been externally provided on compilation line
|
||||||
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
||||||
|
|
@ -243,265 +244,12 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
|
||||||
//#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...)
|
|
||||||
#include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others
|
|
||||||
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
|
|
||||||
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
|
|
||||||
|
|
||||||
#include <EGL/egl.h> // Native platform windowing system interface
|
|
||||||
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
|
||||||
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
|
||||||
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
|
||||||
#include <pthread.h> // POSIX threads management (inputs reading)
|
|
||||||
#include <dirent.h> // POSIX directory browsing
|
|
||||||
|
|
||||||
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
|
||||||
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
|
||||||
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
|
|
||||||
#include <linux/joystick.h> // Linux: Joystick support library
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
#include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM)
|
|
||||||
#include <xf86drm.h> // Direct Rendering Manager user-level library interface
|
|
||||||
#include <xf86drmMode.h> // Direct Rendering Manager mode setting (KMS) interface
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "EGL/egl.h" // Native platform windowing system interface
|
|
||||||
#include "EGL/eglext.h" // EGL extensions
|
|
||||||
//#include "GLES2/gl2.h" // OpenGL ES 2.0 library (not required in this module, only in rlgl)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
|
||||||
#define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL)
|
|
||||||
//#define GLFW_INCLUDE_ES3 // GLFW3: Enable OpenGL ES 3.0 (transalted to WebGL2?)
|
|
||||||
#include "GLFW/glfw3.h" // GLFW3: Windows, OpenGL context and Input management
|
|
||||||
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
|
||||||
|
|
||||||
#include <emscripten/emscripten.h> // Emscripten functionality for C
|
|
||||||
#include <emscripten/html5.h> // Emscripten HTML5 library
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
|
||||||
|
|
||||||
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
|
|
||||||
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_FILEPATH_CAPACITY
|
|
||||||
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_FILEPATH_LENGTH
|
|
||||||
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_KEYBOARD_KEYS
|
|
||||||
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_MOUSE_BUTTONS
|
|
||||||
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_GAMEPADS
|
|
||||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_GAMEPAD_AXIS
|
|
||||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_GAMEPAD_BUTTONS
|
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_TOUCH_POINTS
|
|
||||||
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_KEY_PRESSED_QUEUE
|
|
||||||
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_CHAR_PRESSED_QUEUE
|
|
||||||
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_DECOMPRESSION_SIZE
|
|
||||||
#define MAX_DECOMPRESSION_SIZE 64 // Maximum size allocated for decompression in MB
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Flags operation macros
|
|
||||||
#define FLAG_SET(n, f) ((n) |= (f))
|
|
||||||
#define FLAG_CLEAR(n, f) ((n) &= ~(f))
|
|
||||||
#define FLAG_TOGGLE(n, f) ((n) ^= (f))
|
|
||||||
#define FLAG_CHECK(n, f) ((n) & (f))
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
typedef struct {
|
|
||||||
pthread_t threadId; // Event reading thread id
|
|
||||||
int fd; // File descriptor to the device it is assigned to
|
|
||||||
int eventNum; // Number of 'event<N>' device
|
|
||||||
Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
|
|
||||||
int touchSlot; // Hold the touch slot number of the currently being sent multitouch block
|
|
||||||
bool isMouse; // True if device supports relative X Y movements
|
|
||||||
bool isTouch; // True if device supports absolute X Y movements and has BTN_TOUCH
|
|
||||||
bool isMultitouch; // True if device supports multiple absolute movevents and has BTN_TOUCH
|
|
||||||
bool isKeyboard; // True if device has letter keycodes
|
|
||||||
bool isGamepad; // True if device has gamepad buttons
|
|
||||||
} InputEventWorker;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct { int x; int y; } Point;
|
|
||||||
typedef struct { unsigned int width; unsigned int height; } Size;
|
|
||||||
|
|
||||||
// Core global state context data
|
|
||||||
typedef struct CoreData {
|
|
||||||
struct {
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
GLFWwindow *handle; // GLFW window handle (graphic device)
|
|
||||||
#endif
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
int fd; // File descriptor for /dev/dri/...
|
|
||||||
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
|
|
||||||
drmModeCrtc *crtc; // CRT Controller
|
|
||||||
int modeIndex; // Index of the used mode of connector->modes
|
|
||||||
struct gbm_device *gbmDevice; // GBM device
|
|
||||||
struct gbm_surface *gbmSurface; // GBM surface
|
|
||||||
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
|
|
||||||
uint32_t prevFB; // Previous GBM framebufer (during frame swapping)
|
|
||||||
#endif // PLATFORM_DRM
|
|
||||||
EGLDisplay device; // Native display device (physical screen connection)
|
|
||||||
EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
|
|
||||||
EGLContext context; // Graphic context, mode in which drawing can be done
|
|
||||||
EGLConfig config; // Graphic config
|
|
||||||
#endif
|
|
||||||
const char *title; // Window text title const pointer
|
|
||||||
unsigned int flags; // Configuration flags (bit based), keeps window state
|
|
||||||
bool ready; // Check if window has been initialized successfully
|
|
||||||
bool fullscreen; // Check if fullscreen mode is enabled
|
|
||||||
bool shouldClose; // Check if window set for closing
|
|
||||||
bool resizedLastFrame; // Check if window has been resized last frame
|
|
||||||
bool eventWaiting; // Wait for events before ending frame
|
|
||||||
|
|
||||||
Point position; // Window position (required on fullscreen toggle)
|
|
||||||
Point previousPosition; // Window previous position (required on borderless windowed toggle)
|
|
||||||
Size display; // Display width and height (monitor, device-screen, LCD, ...)
|
|
||||||
Size screen; // Screen width and height (used render area)
|
|
||||||
Size previousScreen; // Screen previous width and height (required on borderless windowed toggle)
|
|
||||||
Size currentFbo; // Current render width and height (depends on active fbo)
|
|
||||||
Size render; // Framebuffer width and height (render area, including black bars if required)
|
|
||||||
Point renderOffset; // Offset from render area (must be divided by 2)
|
|
||||||
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
|
||||||
|
|
||||||
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
|
||||||
unsigned int dropFileCount; // Count dropped files strings
|
|
||||||
|
|
||||||
} Window;
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
|
||||||
struct {
|
|
||||||
bool appEnabled; // Flag to detect if app is active ** = true
|
|
||||||
struct android_app *app; // Android activity
|
|
||||||
struct android_poll_source *source; // Android events polling source
|
|
||||||
bool contextRebindRequired; // Used to know context rebind required
|
|
||||||
} Android;
|
|
||||||
#endif
|
|
||||||
struct {
|
|
||||||
const char *basePath; // Base path for data storage
|
|
||||||
} Storage;
|
|
||||||
struct {
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
|
||||||
#endif
|
|
||||||
struct {
|
|
||||||
int exitKey; // Default exit key
|
|
||||||
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
|
||||||
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
|
||||||
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
|
|
||||||
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
|
|
||||||
|
|
||||||
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
|
||||||
int keyPressedQueueCount; // Input keys queue count
|
|
||||||
|
|
||||||
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
|
|
||||||
int charPressedQueueCount; // Input characters queue count
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
int defaultMode; // Default keyboard mode
|
|
||||||
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
|
||||||
bool evtMode; // Keyboard in event mode
|
|
||||||
#endif
|
|
||||||
int defaultFileFlags; // Default IO file flags
|
|
||||||
struct termios defaultSettings; // Default keyboard settings
|
|
||||||
int fd; // File descriptor for the evdev keyboard
|
|
||||||
#endif
|
|
||||||
} Keyboard;
|
|
||||||
struct {
|
|
||||||
Vector2 offset; // Mouse offset
|
|
||||||
Vector2 scale; // Mouse scaling
|
|
||||||
Vector2 currentPosition; // Mouse position on screen
|
|
||||||
Vector2 previousPosition; // Previous mouse position
|
|
||||||
|
|
||||||
int cursor; // Tracks current mouse cursor
|
|
||||||
bool cursorHidden; // Track if cursor is hidden
|
|
||||||
bool cursorOnScreen; // Tracks if cursor is inside client area
|
|
||||||
|
|
||||||
char currentButtonState[MAX_MOUSE_BUTTONS]; // Registers current mouse button state
|
|
||||||
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
|
|
||||||
Vector2 currentWheelMove; // Registers current mouse wheel variation
|
|
||||||
Vector2 previousWheelMove; // Registers previous mouse wheel variation
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
Vector2 eventWheelMove; // Registers the event mouse wheel variation
|
|
||||||
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
|
|
||||||
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
|
|
||||||
#endif
|
|
||||||
} Mouse;
|
|
||||||
struct {
|
|
||||||
int pointCount; // Number of touch points active
|
|
||||||
int pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
|
||||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
|
||||||
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
|
||||||
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
|
||||||
} Touch;
|
|
||||||
struct {
|
|
||||||
int lastButtonPressed; // Register last gamepad button pressed
|
|
||||||
int axisCount; // Register number of available gamepad axis
|
|
||||||
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
|
|
||||||
char name[MAX_GAMEPADS][64]; // Gamepad name holder
|
|
||||||
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
|
||||||
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
|
||||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
pthread_t threadId; // Gamepad reading thread id
|
|
||||||
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
|
|
||||||
#endif
|
|
||||||
} Gamepad;
|
|
||||||
} Input;
|
|
||||||
struct {
|
|
||||||
double current; // Current time measure
|
|
||||||
double previous; // Previous time measure
|
|
||||||
double update; // Time measure for frame update
|
|
||||||
double draw; // Time measure for frame draw
|
|
||||||
double frame; // Time measure for one frame
|
|
||||||
double target; // Desired time for one frame, if 0 not applied
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
|
||||||
unsigned long long int base; // Base time measure for hi-res timer
|
|
||||||
#endif
|
|
||||||
unsigned int frameCounter; // Frame counter
|
|
||||||
} Time;
|
|
||||||
} CoreData;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings
|
RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings
|
||||||
|
|
||||||
static CoreData CORE = { 0 }; // Global CORE state context
|
CoreData CORE = { 0 }; // Global CORE state context
|
||||||
|
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
||||||
static int screenshotCounter = 0; // Screenshots counter
|
static int screenshotCounter = 0; // Screenshots counter
|
||||||
|
|
@ -644,16 +392,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd);
|
||||||
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs
|
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
|
||||||
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
|
||||||
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
|
||||||
|
|
||||||
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
|
||||||
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
#if defined(PLATFORM_DRM)
|
||||||
static void InitKeyboard(void); // Initialize raw keyboard system
|
static void InitKeyboard(void); // Initialize raw keyboard system
|
||||||
static void RestoreKeyboard(void); // Restore keyboard system
|
static void RestoreKeyboard(void); // Restore keyboard system
|
||||||
|
|
@ -731,221 +469,6 @@ struct android_app *GetAndroidApp(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initialize window and OpenGL context
|
|
||||||
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
|
||||||
void InitWindow(int width, int height, const char *title)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
|
||||||
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
|
||||||
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
||||||
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
|
||||||
#endif
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXTURES)
|
|
||||||
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
|
||||||
#endif
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT)
|
|
||||||
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
|
||||||
#endif
|
|
||||||
#if defined(SUPPORT_MODULE_RMODELS)
|
|
||||||
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
|
||||||
#endif
|
|
||||||
#if defined(SUPPORT_MODULE_RAUDIO)
|
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
|
||||||
|
|
||||||
// Initialize global input state
|
|
||||||
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
|
||||||
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
|
||||||
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
|
||||||
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
|
||||||
#if defined(SUPPORT_EVENTS_WAITING)
|
|
||||||
CORE.Window.eventWaiting = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
|
||||||
CORE.Window.screen.width = width;
|
|
||||||
CORE.Window.screen.height = height;
|
|
||||||
CORE.Window.currentFbo.width = width;
|
|
||||||
CORE.Window.currentFbo.height = height;
|
|
||||||
|
|
||||||
// Set desired windows flags before initializing anything
|
|
||||||
ANativeActivity_setWindowFlags(CORE.Android.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
|
||||||
|
|
||||||
int orientation = AConfiguration_getOrientation(CORE.Android.app->config);
|
|
||||||
|
|
||||||
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
|
||||||
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
|
||||||
|
|
||||||
// TODO: Automatic orientation doesn't seem to work
|
|
||||||
if (width <= height)
|
|
||||||
{
|
|
||||||
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
|
||||||
}
|
|
||||||
|
|
||||||
//AConfiguration_getDensity(CORE.Android.app->config);
|
|
||||||
//AConfiguration_getKeyboard(CORE.Android.app->config);
|
|
||||||
//AConfiguration_getScreenSize(CORE.Android.app->config);
|
|
||||||
//AConfiguration_getScreenLong(CORE.Android.app->config);
|
|
||||||
|
|
||||||
// Initialize App command system
|
|
||||||
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
|
||||||
CORE.Android.app->onAppCmd = AndroidCommandCallback;
|
|
||||||
|
|
||||||
// Initialize input events system
|
|
||||||
CORE.Android.app->onInputEvent = AndroidInputCallback;
|
|
||||||
|
|
||||||
// Initialize assets manager
|
|
||||||
InitAssetManager(CORE.Android.app->activity->assetManager, CORE.Android.app->activity->internalDataPath);
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = CORE.Android.app->activity->internalDataPath;
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "ANDROID: App initialized successfully");
|
|
||||||
|
|
||||||
// Android ALooper_pollAll() variables
|
|
||||||
int pollResult = 0;
|
|
||||||
int pollEvents = 0;
|
|
||||||
|
|
||||||
// Wait for window to be initialized (display and context)
|
|
||||||
while (!CORE.Window.ready)
|
|
||||||
{
|
|
||||||
// Process events loop
|
|
||||||
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
|
|
||||||
{
|
|
||||||
// Process this event
|
|
||||||
if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
|
|
||||||
|
|
||||||
// NOTE: Never close window, native activity is controlled by the system!
|
|
||||||
//if (CORE.Android.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_DRM)
|
|
||||||
// Initialize graphics device (display device and OpenGL context)
|
|
||||||
// NOTE: returns true if window and graphic device has been initialized successfully
|
|
||||||
CORE.Window.ready = InitGraphicsDevice(width, height);
|
|
||||||
|
|
||||||
// If graphic device is no properly initialized, we end program
|
|
||||||
if (!CORE.Window.ready)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_FATAL, "Failed to initialize Graphic Device");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
|
||||||
|
|
||||||
// Initialize hi-res timer
|
|
||||||
InitTimer();
|
|
||||||
|
|
||||||
// Initialize random seed
|
|
||||||
srand((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
// Initialize base path for storage
|
|
||||||
CORE.Storage.basePath = GetWorkingDirectory();
|
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
||||||
// Load default font
|
|
||||||
// WARNING: External function: Module required: rtext
|
|
||||||
LoadFontDefault();
|
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
||||||
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
|
||||||
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
|
||||||
Rectangle rec = GetFontDefault().recs[95];
|
|
||||||
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
|
||||||
{
|
|
||||||
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
|
||||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
|
||||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
||||||
// Set default texture and rectangle to be used for shapes drawing
|
|
||||||
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
|
||||||
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
|
||||||
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
|
||||||
{
|
|
||||||
// Set default font texture filter for HighDPI (blurry)
|
|
||||||
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
|
||||||
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
|
||||||
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
|
||||||
// Initialize raw input system
|
|
||||||
InitEvdevInput(); // Evdev inputs initialization
|
|
||||||
InitGamepad(); // Gamepad init
|
|
||||||
InitKeyboard(); // Keyboard init (stdin)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
|
||||||
// Setup callback functions for the DOM events
|
|
||||||
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
|
||||||
|
|
||||||
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
|
||||||
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
|
||||||
//emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
||||||
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
|
||||||
//emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
||||||
// Trigger this once to get initial window sizing
|
|
||||||
//EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
|
||||||
|
|
||||||
// Support keyboard events -> Not used, GLFW.JS takes care of that
|
|
||||||
//emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
||||||
//emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
||||||
|
|
||||||
// Support mouse events
|
|
||||||
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
|
|
||||||
|
|
||||||
// Support touch events
|
|
||||||
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
|
||||||
|
|
||||||
// Support gamepad events (not provided by GLFW3 on emscripten)
|
|
||||||
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
|
||||||
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
|
||||||
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
|
|
||||||
CORE.Time.frameCounter = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // PLATFORM_DESKTOP || PLATFORM_WEB || PLATFORM_DRM
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close window and unload OpenGL context
|
// Close window and unload OpenGL context
|
||||||
void CloseWindow(void)
|
void CloseWindow(void)
|
||||||
{
|
{
|
||||||
|
|
@ -6150,146 +5673,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
|
||||||
// Register fullscreen change events
|
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
|
||||||
{
|
|
||||||
// TODO: Implement EmscriptenFullscreenChangeCallback()?
|
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register window resize event
|
|
||||||
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
|
||||||
{
|
|
||||||
// TODO: Implement EmscriptenWindowResizedCallback()?
|
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
|
||||||
}
|
|
||||||
|
|
||||||
EM_JS(int, GetCanvasWidth, (), { return canvas.clientWidth; });
|
|
||||||
EM_JS(int, GetCanvasHeight, (), { return canvas.clientHeight; });
|
|
||||||
|
|
||||||
// Register DOM element resize event
|
|
||||||
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
|
||||||
{
|
|
||||||
// Don't resize non-resizeable windows
|
|
||||||
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) return 1;
|
|
||||||
|
|
||||||
// This event is called whenever the window changes sizes,
|
|
||||||
// so the size of the canvas object is explicitly retrieved below
|
|
||||||
int width = GetCanvasWidth();
|
|
||||||
int height = GetCanvasHeight();
|
|
||||||
emscripten_set_canvas_element_size("#canvas",width,height);
|
|
||||||
|
|
||||||
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
|
||||||
|
|
||||||
CORE.Window.currentFbo.width = width;
|
|
||||||
CORE.Window.currentFbo.height = height;
|
|
||||||
CORE.Window.resizedLastFrame = true;
|
|
||||||
|
|
||||||
if (IsWindowFullscreen()) return 1;
|
|
||||||
|
|
||||||
// Set current screen size
|
|
||||||
CORE.Window.screen.width = width;
|
|
||||||
CORE.Window.screen.height = height;
|
|
||||||
|
|
||||||
// NOTE: Postprocessing texture is not scaled to new size
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register mouse input events
|
|
||||||
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
|
||||||
{
|
|
||||||
// This is only for registering mouse click events with emscripten and doesn't need to do anything
|
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register connected/disconnected gamepads events
|
|
||||||
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
TRACELOGD("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"",
|
|
||||||
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
|
||||||
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
|
|
||||||
|
|
||||||
for (int i = 0; i < gamepadEvent->numAxes; ++i) TRACELOGD("Axis %d: %g", i, gamepadEvent->axis[i]);
|
|
||||||
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
|
||||||
{
|
|
||||||
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
|
||||||
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index],"%s",gamepadEvent->id);
|
|
||||||
}
|
|
||||||
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register touch input events
|
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
|
||||||
{
|
|
||||||
// Register touch points count
|
|
||||||
CORE.Input.Touch.pointCount = touchEvent->numTouches;
|
|
||||||
|
|
||||||
double canvasWidth = 0.0;
|
|
||||||
double canvasHeight = 0.0;
|
|
||||||
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
|
||||||
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
|
||||||
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
|
||||||
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
|
||||||
|
|
||||||
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
|
||||||
{
|
|
||||||
// Register touch points id
|
|
||||||
CORE.Input.Touch.pointId[i] = touchEvent->touches[i].identifier;
|
|
||||||
|
|
||||||
// Register touch points position
|
|
||||||
CORE.Input.Touch.position[i] = (Vector2){ touchEvent->touches[i].targetX, touchEvent->touches[i].targetY };
|
|
||||||
|
|
||||||
// Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
|
|
||||||
CORE.Input.Touch.position[i].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
|
||||||
CORE.Input.Touch.position[i].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
|
||||||
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) CORE.Input.Touch.currentTouchState[i] = 1;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_WEB
|
|
||||||
GestureEvent gestureEvent = { 0 };
|
|
||||||
|
|
||||||
gestureEvent.pointCount = CORE.Input.Touch.pointCount;
|
|
||||||
|
|
||||||
// Register touch actions
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_ACTION_DOWN;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_ACTION_UP;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_ACTION_MOVE;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL) gestureEvent.touchAction = TOUCH_ACTION_CANCEL;
|
|
||||||
|
|
||||||
for (int i = 0; (i < gestureEvent.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
|
||||||
{
|
|
||||||
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
|
||||||
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
|
||||||
|
|
||||||
// Normalize gestureEvent.position[i]
|
|
||||||
gestureEvent.position[i].x /= (float)GetScreenWidth();
|
|
||||||
gestureEvent.position[i].y /= (float)GetScreenHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gesture data is sent to gestures system for processing
|
|
||||||
ProcessGestureEvent(gestureEvent);
|
|
||||||
|
|
||||||
// Reset the pointCount for web, if it was the last Touch End event
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHEND && CORE.Input.Touch.pointCount == 1) CORE.Input.Touch.pointCount = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
#if defined(PLATFORM_DRM)
|
||||||
// Initialize Keyboard system (using standard input)
|
// Initialize Keyboard system (using standard input)
|
||||||
static void InitKeyboard(void)
|
static void InitKeyboard(void)
|
||||||
|
|
|
||||||
221
src/rcore.h
Normal file
221
src/rcore.h
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
#ifndef RCORE_H
|
||||||
|
#define RCORE_H
|
||||||
|
|
||||||
|
// PROVIDE A HEADER TO BE USED BY ALL THE rcore_* IMPLEMENTATIONS.
|
||||||
|
/*
|
||||||
|
|
||||||
|
Status:
|
||||||
|
InitWindow: DRM,
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
||||||
|
|
||||||
|
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
|
||||||
|
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_FILEPATH_CAPACITY
|
||||||
|
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_FILEPATH_LENGTH
|
||||||
|
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_KEYBOARD_KEYS
|
||||||
|
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_MOUSE_BUTTONS
|
||||||
|
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_GAMEPADS
|
||||||
|
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_GAMEPAD_AXIS
|
||||||
|
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_GAMEPAD_BUTTONS
|
||||||
|
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_TOUCH_POINTS
|
||||||
|
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_KEY_PRESSED_QUEUE
|
||||||
|
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_CHAR_PRESSED_QUEUE
|
||||||
|
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_DECOMPRESSION_SIZE
|
||||||
|
#define MAX_DECOMPRESSION_SIZE 64 // Maximum size allocated for decompression in MB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Flags operation macros
|
||||||
|
#define FLAG_SET(n, f) ((n) |= (f))
|
||||||
|
#define FLAG_CLEAR(n, f) ((n) &= ~(f))
|
||||||
|
#define FLAG_TOGGLE(n, f) ((n) ^= (f))
|
||||||
|
#define FLAG_CHECK(n, f) ((n) & (f))
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct { int x; int y; } Point;
|
||||||
|
typedef struct { unsigned int width; unsigned int height; } Size;
|
||||||
|
|
||||||
|
|
||||||
|
// Core global state context data
|
||||||
|
typedef struct CoreData {
|
||||||
|
struct {
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
|
GLFWwindow *handle; // GLFW window handle (graphic device)
|
||||||
|
#endif
|
||||||
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
int fd; // File descriptor for /dev/dri/...
|
||||||
|
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
|
||||||
|
drmModeCrtc *crtc; // CRT Controller
|
||||||
|
int modeIndex; // Index of the used mode of connector->modes
|
||||||
|
struct gbm_device *gbmDevice; // GBM device
|
||||||
|
struct gbm_surface *gbmSurface; // GBM surface
|
||||||
|
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
|
||||||
|
uint32_t prevFB; // Previous GBM framebufer (during frame swapping)
|
||||||
|
#endif // PLATFORM_DRM
|
||||||
|
EGLDisplay device; // Native display device (physical screen connection)
|
||||||
|
EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
|
||||||
|
EGLContext context; // Graphic context, mode in which drawing can be done
|
||||||
|
EGLConfig config; // Graphic config
|
||||||
|
#endif
|
||||||
|
const char *title; // Window text title const pointer
|
||||||
|
unsigned int flags; // Configuration flags (bit based), keeps window state
|
||||||
|
bool ready; // Check if window has been initialized successfully
|
||||||
|
bool fullscreen; // Check if fullscreen mode is enabled
|
||||||
|
bool shouldClose; // Check if window set for closing
|
||||||
|
bool resizedLastFrame; // Check if window has been resized last frame
|
||||||
|
bool eventWaiting; // Wait for events before ending frame
|
||||||
|
|
||||||
|
Point position; // Window position (required on fullscreen toggle)
|
||||||
|
Point previousPosition; // Window previous position (required on borderless windowed toggle)
|
||||||
|
Size display; // Display width and height (monitor, device-screen, LCD, ...)
|
||||||
|
Size screen; // Screen width and height (used render area)
|
||||||
|
Size previousScreen; // Screen previous width and height (required on borderless windowed toggle)
|
||||||
|
Size currentFbo; // Current render width and height (depends on active fbo)
|
||||||
|
Size render; // Framebuffer width and height (render area, including black bars if required)
|
||||||
|
Point renderOffset; // Offset from render area (must be divided by 2)
|
||||||
|
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
||||||
|
|
||||||
|
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
||||||
|
unsigned int dropFileCount; // Count dropped files strings
|
||||||
|
|
||||||
|
} Window;
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
struct {
|
||||||
|
bool appEnabled; // Flag to detect if app is active ** = true
|
||||||
|
struct android_app *app; // Android activity
|
||||||
|
struct android_poll_source *source; // Android events polling source
|
||||||
|
bool contextRebindRequired; // Used to know context rebind required
|
||||||
|
} Android;
|
||||||
|
#endif
|
||||||
|
struct {
|
||||||
|
const char *basePath; // Base path for data storage
|
||||||
|
} Storage;
|
||||||
|
struct {
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
||||||
|
#endif
|
||||||
|
struct {
|
||||||
|
int exitKey; // Default exit key
|
||||||
|
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
||||||
|
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
||||||
|
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
|
||||||
|
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
|
||||||
|
|
||||||
|
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
||||||
|
int keyPressedQueueCount; // Input keys queue count
|
||||||
|
|
||||||
|
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
|
||||||
|
int charPressedQueueCount; // Input characters queue count
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
int defaultMode; // Default keyboard mode
|
||||||
|
#if defined(SUPPORT_SSH_KEYBOARD_RPI)
|
||||||
|
bool evtMode; // Keyboard in event mode
|
||||||
|
#endif
|
||||||
|
int defaultFileFlags; // Default IO file flags
|
||||||
|
struct termios defaultSettings; // Default keyboard settings
|
||||||
|
int fd; // File descriptor for the evdev keyboard
|
||||||
|
#endif
|
||||||
|
} Keyboard;
|
||||||
|
struct {
|
||||||
|
Vector2 offset; // Mouse offset
|
||||||
|
Vector2 scale; // Mouse scaling
|
||||||
|
Vector2 currentPosition; // Mouse position on screen
|
||||||
|
Vector2 previousPosition; // Previous mouse position
|
||||||
|
|
||||||
|
int cursor; // Tracks current mouse cursor
|
||||||
|
bool cursorHidden; // Track if cursor is hidden
|
||||||
|
bool cursorOnScreen; // Tracks if cursor is inside client area
|
||||||
|
|
||||||
|
char currentButtonState[MAX_MOUSE_BUTTONS]; // Registers current mouse button state
|
||||||
|
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
|
||||||
|
Vector2 currentWheelMove; // Registers current mouse wheel variation
|
||||||
|
Vector2 previousWheelMove; // Registers previous mouse wheel variation
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
Vector2 eventWheelMove; // Registers the event mouse wheel variation
|
||||||
|
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
|
||||||
|
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
|
||||||
|
#endif
|
||||||
|
} Mouse;
|
||||||
|
struct {
|
||||||
|
int pointCount; // Number of touch points active
|
||||||
|
int pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
||||||
|
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||||
|
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
||||||
|
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
||||||
|
} Touch;
|
||||||
|
struct {
|
||||||
|
int lastButtonPressed; // Register last gamepad button pressed
|
||||||
|
int axisCount; // Register number of available gamepad axis
|
||||||
|
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
|
||||||
|
char name[MAX_GAMEPADS][64]; // Gamepad name holder
|
||||||
|
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||||
|
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||||
|
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||||
|
#if defined(PLATFORM_DRM)
|
||||||
|
pthread_t threadId; // Gamepad reading thread id
|
||||||
|
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||||
|
#endif
|
||||||
|
} Gamepad;
|
||||||
|
} Input;
|
||||||
|
struct {
|
||||||
|
double current; // Current time measure
|
||||||
|
double previous; // Previous time measure
|
||||||
|
double update; // Time measure for frame update
|
||||||
|
double draw; // Time measure for frame draw
|
||||||
|
double frame; // Time measure for one frame
|
||||||
|
double target; // Desired time for one frame, if 0 not applied
|
||||||
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
||||||
|
unsigned long long int base; // Base time measure for hi-res timer
|
||||||
|
#endif
|
||||||
|
unsigned int frameCounter; // Frame counter
|
||||||
|
} Time;
|
||||||
|
} CoreData;
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern CoreData CORE;
|
||||||
|
|
||||||
|
#endif
|
||||||
123
src/rcore_android.c
Normal file
123
src/rcore_android.c
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "rcore.h"
|
||||||
|
|
||||||
|
//#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...)
|
||||||
|
#include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others
|
||||||
|
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
|
||||||
|
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
|
||||||
|
|
||||||
|
#include <EGL/egl.h> // Native platform windowing system interface
|
||||||
|
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
|
||||||
|
|
||||||
|
// Initialize window and OpenGL context
|
||||||
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
|
void InitWindow(int width, int height, const char *title)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
||||||
|
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
||||||
|
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT)
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RMODELS)
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RAUDIO)
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
|
// Initialize global input state
|
||||||
|
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
||||||
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
#if defined(SUPPORT_EVENTS_WAITING)
|
||||||
|
CORE.Window.eventWaiting = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
CORE.Window.currentFbo.width = width;
|
||||||
|
CORE.Window.currentFbo.height = height;
|
||||||
|
|
||||||
|
// Set desired windows flags before initializing anything
|
||||||
|
ANativeActivity_setWindowFlags(CORE.Android.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
||||||
|
|
||||||
|
int orientation = AConfiguration_getOrientation(CORE.Android.app->config);
|
||||||
|
|
||||||
|
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as portrait");
|
||||||
|
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TRACELOG(LOG_INFO, "ANDROID: Window orientation set as landscape");
|
||||||
|
|
||||||
|
// TODO: Automatic orientation doesn't seem to work
|
||||||
|
if (width <= height)
|
||||||
|
{
|
||||||
|
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_PORT);
|
||||||
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to portrait");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_LAND);
|
||||||
|
TRACELOG(LOG_WARNING, "ANDROID: Window orientation changed to landscape");
|
||||||
|
}
|
||||||
|
|
||||||
|
//AConfiguration_getDensity(CORE.Android.app->config);
|
||||||
|
//AConfiguration_getKeyboard(CORE.Android.app->config);
|
||||||
|
//AConfiguration_getScreenSize(CORE.Android.app->config);
|
||||||
|
//AConfiguration_getScreenLong(CORE.Android.app->config);
|
||||||
|
|
||||||
|
// Initialize App command system
|
||||||
|
// NOTE: On APP_CMD_INIT_WINDOW -> InitGraphicsDevice(), InitTimer(), LoadFontDefault()...
|
||||||
|
CORE.Android.app->onAppCmd = AndroidCommandCallback;
|
||||||
|
|
||||||
|
// Initialize input events system
|
||||||
|
CORE.Android.app->onInputEvent = AndroidInputCallback;
|
||||||
|
|
||||||
|
// Initialize assets manager
|
||||||
|
InitAssetManager(CORE.Android.app->activity->assetManager, CORE.Android.app->activity->internalDataPath);
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = CORE.Android.app->activity->internalDataPath;
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "ANDROID: App initialized successfully");
|
||||||
|
|
||||||
|
// Android ALooper_pollAll() variables
|
||||||
|
int pollResult = 0;
|
||||||
|
int pollEvents = 0;
|
||||||
|
|
||||||
|
// Wait for window to be initialized (display and context)
|
||||||
|
while (!CORE.Window.ready)
|
||||||
|
{
|
||||||
|
// Process events loop
|
||||||
|
while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
|
||||||
|
{
|
||||||
|
// Process this event
|
||||||
|
if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
|
||||||
|
|
||||||
|
// NOTE: Never close window, native activity is controlled by the system!
|
||||||
|
//if (CORE.Android.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
src/rcore_desktop.c
Normal file
114
src/rcore_desktop.c
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "rcore.h"
|
||||||
|
|
||||||
|
// Initialize window and OpenGL context
|
||||||
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
|
void InitWindow(int width, int height, const char *title)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
||||||
|
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
||||||
|
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT)
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RMODELS)
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RAUDIO)
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
|
// Initialize global input state
|
||||||
|
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
||||||
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
#if defined(SUPPORT_EVENTS_WAITING)
|
||||||
|
CORE.Window.eventWaiting = true;
|
||||||
|
#endif
|
||||||
|
// Initialize graphics device (display device and OpenGL context)
|
||||||
|
// NOTE: returns true if window and graphic device has been initialized successfully
|
||||||
|
CORE.Window.ready = InitGraphicsDevice(width, height);
|
||||||
|
|
||||||
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_FATAL, "Failed to initialize Graphic Device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
||||||
|
|
||||||
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
// Load default font
|
||||||
|
// WARNING: External function: Module required: rtext
|
||||||
|
LoadFontDefault();
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
||||||
|
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
||||||
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||||
|
{
|
||||||
|
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set default texture and rectangle to be used for shapes drawing
|
||||||
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
|
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
|
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||||
|
{
|
||||||
|
// Set default font texture filter for HighDPI (blurry)
|
||||||
|
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
|
||||||
|
CORE.Time.frameCounter = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
154
src/rcore_drm.c
Normal file
154
src/rcore_drm.c
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "rcore.h"
|
||||||
|
|
||||||
|
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
||||||
|
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
||||||
|
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
||||||
|
#include <pthread.h> // POSIX threads management (inputs reading)
|
||||||
|
#include <dirent.h> // POSIX directory browsing
|
||||||
|
|
||||||
|
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
||||||
|
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
||||||
|
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
|
||||||
|
#include <linux/joystick.h> // Linux: Joystick support library
|
||||||
|
|
||||||
|
#include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM)
|
||||||
|
#include <xf86drm.h> // Direct Rendering Manager user-level library interface
|
||||||
|
#include <xf86drmMode.h> // Direct Rendering Manager mode setting (KMS) interface
|
||||||
|
|
||||||
|
#include "EGL/egl.h" // Native platform windowing system interface
|
||||||
|
#include "EGL/eglext.h" // EGL extensions
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_t threadId; // Event reading thread id
|
||||||
|
int fd; // File descriptor to the device it is assigned to
|
||||||
|
int eventNum; // Number of 'event<N>' device
|
||||||
|
Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
|
||||||
|
int touchSlot; // Hold the touch slot number of the currently being sent multitouch block
|
||||||
|
bool isMouse; // True if device supports relative X Y movements
|
||||||
|
bool isTouch; // True if device supports absolute X Y movements and has BTN_TOUCH
|
||||||
|
bool isMultitouch; // True if device supports multiple absolute movevents and has BTN_TOUCH
|
||||||
|
bool isKeyboard; // True if device has letter keycodes
|
||||||
|
bool isGamepad; // True if device has gamepad buttons
|
||||||
|
} InputEventWorker;
|
||||||
|
|
||||||
|
// Initialize window and OpenGL context
|
||||||
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
|
void InitWindow(int width, int height, const char *title)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
||||||
|
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
||||||
|
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT)
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RMODELS)
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RAUDIO)
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((title != NULL) && (title[0] != 0))
|
||||||
|
CORE.Window.title = title;
|
||||||
|
|
||||||
|
// Initialize global input state
|
||||||
|
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
||||||
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
|
CORE.Input.Mouse.scale = (Vector2){1.0f, 1.0f};
|
||||||
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
#if defined(SUPPORT_EVENTS_WAITING)
|
||||||
|
CORE.Window.eventWaiting = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize graphics device (display device and OpenGL context)
|
||||||
|
// NOTE: returns true if window and graphic device has been initialized successfully
|
||||||
|
CORE.Window.ready = InitGraphicsDevice(width, height);
|
||||||
|
|
||||||
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_FATAL, "Failed to initialize Graphic Device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);
|
||||||
|
|
||||||
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
// Load default font
|
||||||
|
// WARNING: External function: Module required: rtext
|
||||||
|
LoadFontDefault();
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
||||||
|
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
||||||
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||||
|
{
|
||||||
|
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){rec.x + 2, rec.y + 2, 1, 1});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set default texture and rectangle to be used for shapes drawing
|
||||||
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
|
Texture2D texture = {rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8};
|
||||||
|
SetShapesTexture(texture, (Rectangle){0.0f, 0.0f, 1.0f, 1.0f}); // WARNING: Module required: rshapes
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||||
|
{
|
||||||
|
// Set default font texture filter for HighDPI (blurry)
|
||||||
|
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize raw input system
|
||||||
|
InitEvdevInput(); // Evdev inputs initialization
|
||||||
|
InitGamepad(); // Gamepad init
|
||||||
|
InitKeyboard(); // Keyboard init (stdin)
|
||||||
|
|
||||||
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
|
||||||
|
CORE.Time.frameCounter = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
296
src/rcore_web.c
Normal file
296
src/rcore_web.c
Normal file
|
|
@ -0,0 +1,296 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "rcore.h"
|
||||||
|
|
||||||
|
#define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL)
|
||||||
|
//#define GLFW_INCLUDE_ES3 // GLFW3: Enable OpenGL ES 3.0 (transalted to WebGL2?)
|
||||||
|
#include "GLFW/glfw3.h" // GLFW3: Windows, OpenGL context and Input management
|
||||||
|
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
||||||
|
|
||||||
|
#include <emscripten/emscripten.h> // Emscripten functionality for C
|
||||||
|
#include <emscripten/html5.h> // Emscripten HTML5 library
|
||||||
|
|
||||||
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
||||||
|
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
|
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
|
|
||||||
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
||||||
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
||||||
|
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
||||||
|
|
||||||
|
// Initialize window and OpenGL context
|
||||||
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
|
void InitWindow(int width, int height, const char *title)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
||||||
|
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
||||||
|
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT)
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RMODELS)
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RAUDIO)
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
||||||
|
|
||||||
|
// Initialize global input state
|
||||||
|
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
||||||
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
||||||
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
||||||
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
||||||
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
#if defined(SUPPORT_EVENTS_WAITING)
|
||||||
|
CORE.Window.eventWaiting = true;
|
||||||
|
#endif
|
||||||
|
// Initialize graphics device (display device and OpenGL context)
|
||||||
|
// NOTE: returns true if window and graphic device has been initialized successfully
|
||||||
|
CORE.Window.ready = InitGraphicsDevice(width, height);
|
||||||
|
|
||||||
|
// If graphic device is no properly initialized, we end program
|
||||||
|
if (!CORE.Window.ready)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_FATAL, "Failed to initialize Graphic Device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2);
|
||||||
|
|
||||||
|
// Initialize hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
|
// Initialize base path for storage
|
||||||
|
CORE.Storage.basePath = GetWorkingDirectory();
|
||||||
|
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
// Load default font
|
||||||
|
// WARNING: External function: Module required: rtext
|
||||||
|
LoadFontDefault();
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
||||||
|
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
||||||
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||||
|
{
|
||||||
|
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set default texture and rectangle to be used for shapes drawing
|
||||||
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
|
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
|
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||||
|
{
|
||||||
|
// Set default font texture filter for HighDPI (blurry)
|
||||||
|
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Setup callback functions for the DOM events
|
||||||
|
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
||||||
|
|
||||||
|
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
||||||
|
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
||||||
|
//emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
|
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
||||||
|
//emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
|
// Trigger this once to get initial window sizing
|
||||||
|
//EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
||||||
|
|
||||||
|
// Support keyboard events -> Not used, GLFW.JS takes care of that
|
||||||
|
//emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||||
|
//emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||||
|
|
||||||
|
// Support mouse events
|
||||||
|
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
|
||||||
|
|
||||||
|
// Support touch events
|
||||||
|
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback);
|
||||||
|
|
||||||
|
// Support gamepad events (not provided by GLFW3 on emscripten)
|
||||||
|
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
|
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
|
|
||||||
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
||||||
|
events = (AutomationEvent *)RL_CALLOC(MAX_CODE_AUTOMATION_EVENTS, sizeof(AutomationEvent));
|
||||||
|
CORE.Time.frameCounter = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register fullscreen change events
|
||||||
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
||||||
|
{
|
||||||
|
// TODO: Implement EmscriptenFullscreenChangeCallback()?
|
||||||
|
|
||||||
|
return 1; // The event was consumed by the callback handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register window resize event
|
||||||
|
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
||||||
|
{
|
||||||
|
// TODO: Implement EmscriptenWindowResizedCallback()?
|
||||||
|
|
||||||
|
return 1; // The event was consumed by the callback handler
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_JS(int, GetCanvasWidth, (), { return canvas.clientWidth; });
|
||||||
|
EM_JS(int, GetCanvasHeight, (), { return canvas.clientHeight; });
|
||||||
|
|
||||||
|
// Register DOM element resize event
|
||||||
|
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
||||||
|
{
|
||||||
|
// Don't resize non-resizeable windows
|
||||||
|
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) return 1;
|
||||||
|
|
||||||
|
// This event is called whenever the window changes sizes,
|
||||||
|
// so the size of the canvas object is explicitly retrieved below
|
||||||
|
int width = GetCanvasWidth();
|
||||||
|
int height = GetCanvasHeight();
|
||||||
|
emscripten_set_canvas_element_size("#canvas",width,height);
|
||||||
|
|
||||||
|
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
||||||
|
|
||||||
|
CORE.Window.currentFbo.width = width;
|
||||||
|
CORE.Window.currentFbo.height = height;
|
||||||
|
CORE.Window.resizedLastFrame = true;
|
||||||
|
|
||||||
|
if (IsWindowFullscreen()) return 1;
|
||||||
|
|
||||||
|
// Set current screen size
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
|
|
||||||
|
// NOTE: Postprocessing texture is not scaled to new size
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register mouse input events
|
||||||
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
||||||
|
{
|
||||||
|
// This is only for registering mouse click events with emscripten and doesn't need to do anything
|
||||||
|
|
||||||
|
return 1; // The event was consumed by the callback handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register connected/disconnected gamepads events
|
||||||
|
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TRACELOGD("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"",
|
||||||
|
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
||||||
|
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
|
||||||
|
|
||||||
|
for (int i = 0; i < gamepadEvent->numAxes; ++i) TRACELOGD("Axis %d: %g", i, gamepadEvent->axis[i]);
|
||||||
|
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
||||||
|
{
|
||||||
|
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
||||||
|
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index],"%s",gamepadEvent->id);
|
||||||
|
}
|
||||||
|
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
||||||
|
|
||||||
|
return 1; // The event was consumed by the callback handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register touch input events
|
||||||
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
||||||
|
{
|
||||||
|
// Register touch points count
|
||||||
|
CORE.Input.Touch.pointCount = touchEvent->numTouches;
|
||||||
|
|
||||||
|
double canvasWidth = 0.0;
|
||||||
|
double canvasHeight = 0.0;
|
||||||
|
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
||||||
|
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
||||||
|
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
|
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
|
|
||||||
|
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
|
{
|
||||||
|
// Register touch points id
|
||||||
|
CORE.Input.Touch.pointId[i] = touchEvent->touches[i].identifier;
|
||||||
|
|
||||||
|
// Register touch points position
|
||||||
|
CORE.Input.Touch.position[i] = (Vector2){ touchEvent->touches[i].targetX, touchEvent->touches[i].targetY };
|
||||||
|
|
||||||
|
// Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
|
||||||
|
CORE.Input.Touch.position[i].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
||||||
|
CORE.Input.Touch.position[i].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
||||||
|
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) CORE.Input.Touch.currentTouchState[i] = 1;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_WEB
|
||||||
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
|
gestureEvent.pointCount = CORE.Input.Touch.pointCount;
|
||||||
|
|
||||||
|
// Register touch actions
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_ACTION_DOWN;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_ACTION_UP;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_ACTION_MOVE;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL) gestureEvent.touchAction = TOUCH_ACTION_CANCEL;
|
||||||
|
|
||||||
|
for (int i = 0; (i < gestureEvent.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
|
{
|
||||||
|
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
||||||
|
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
||||||
|
|
||||||
|
// Normalize gestureEvent.position[i]
|
||||||
|
gestureEvent.position[i].x /= (float)GetScreenWidth();
|
||||||
|
gestureEvent.position[i].y /= (float)GetScreenHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gesture data is sent to gestures system for processing
|
||||||
|
ProcessGestureEvent(gestureEvent);
|
||||||
|
|
||||||
|
// Reset the pointCount for web, if it was the last Touch End event
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHEND && CORE.Input.Touch.pointCount == 1) CORE.Input.Touch.pointCount = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1; // The event was consumed by the callback handler
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user