| @ -0,0 +1,789 @@ | |||||
| /********************************************************************************************** | |||||
| * | |||||
| * rcore_<platform> - Functions to manage window, graphics device and inputs | |||||
| * | |||||
| * PLATFORM: <PLATFORM> | |||||
| * - TODO: Define the target platform for the core | |||||
| * | |||||
| * LIMITATIONS: | |||||
| * - Limitation 01 | |||||
| * - Limitation 02 | |||||
| * | |||||
| * POSSIBLE IMPROVEMENTS: | |||||
| * - Improvement 01 | |||||
| * - Improvement 02 | |||||
| * | |||||
| * ADDITIONAL NOTES: | |||||
| * - TRACELOG() function is located in raylib [utils] module | |||||
| * | |||||
| * CONFIGURATION: | |||||
| * #define RCORE_CUSTOM_FLAG | |||||
| * Custom flag for rcore on PLATFORM_<platform> -not used- | |||||
| * | |||||
| * DEPENDENCIES: | |||||
| * - Dependency 01 | |||||
| * - Dependency 02 | |||||
| * | |||||
| * | |||||
| * LICENSE: zlib/libpng | |||||
| * | |||||
| * Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) and contributors | |||||
| * | |||||
| * This software is provided "as-is", without any express or implied warranty. In no event | |||||
| * will the authors be held liable for any damages arising from the use of this software. | |||||
| * | |||||
| * Permission is granted to anyone to use this software for any purpose, including commercial | |||||
| * applications, and to alter it and redistribute it freely, subject to the following restrictions: | |||||
| * | |||||
| * 1. The origin of this software must not be misrepresented; you must not claim that you | |||||
| * wrote the original software. If you use this software in a product, an acknowledgment | |||||
| * in the product documentation would be appreciated but is not required. | |||||
| * | |||||
| * 2. Altered source versions must be plainly marked as such, and must not be misrepresented | |||||
| * as being the original software. | |||||
| * | |||||
| * 3. This notice may not be removed or altered from any source distribution. | |||||
| * | |||||
| **********************************************************************************************/ | |||||
| #include "rcore.h" | |||||
| // TODO: Include the platform specific libraries | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Types and Structures Definition | |||||
| //---------------------------------------------------------------------------------- | |||||
| typedef struct { | |||||
| // TODO: Define the platform specific variables required | |||||
| // Display data | |||||
| 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 | |||||
| } PlatformData; | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Global Variables Definition | |||||
| //---------------------------------------------------------------------------------- | |||||
| extern CoreData CORE; // Global CORE state context | |||||
| static PlatformData platform = { 0 }; // Platform specific data | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Internal Functions Declaration | |||||
| //---------------------------------------------------------------------------------- | |||||
| static bool InitGraphicsDevice(int width, int height); // Initialize graphics device | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Functions Declaration | |||||
| //---------------------------------------------------------------------------------- | |||||
| // NOTE: Functions declaration is provided by raylib.h | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Functions Definition: Window and Graphics Device | |||||
| //---------------------------------------------------------------------------------- | |||||
| // 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 | |||||
| // NOTE: Keep internal pointer to input title string (no copy) | |||||
| 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 | |||||
| CORE.Window.eventWaiting = false; | |||||
| CORE.Window.screen.width = width; | |||||
| CORE.Window.screen.height = height; | |||||
| CORE.Window.currentFbo.width = width; | |||||
| CORE.Window.currentFbo.height = height; | |||||
| // TODO: Initialize window/display system | |||||
| // TODO: Initialize input events system | |||||
| // TODO: Initialize assets manager | |||||
| // TODO: Initialize base path for storage | |||||
| //CORE.Storage.basePath = platform.app->activity->internalDataPath; | |||||
| TRACELOG(LOG_INFO, "PLATFORM: Application initialized successfully"); | |||||
| } | |||||
| // Close window and unload OpenGL context | |||||
| void CloseWindow(void) | |||||
| { | |||||
| #if defined(SUPPORT_GIF_RECORDING) | |||||
| if (gifRecording) | |||||
| { | |||||
| MsfGifResult result = msf_gif_end(&gifState); | |||||
| msf_gif_free(result); | |||||
| gifRecording = false; | |||||
| } | |||||
| #endif | |||||
| #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) | |||||
| UnloadFontDefault(); // WARNING: Module required: rtext | |||||
| #endif | |||||
| rlglClose(); // De-init rlgl | |||||
| #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) | |||||
| timeEndPeriod(1); // Restore time period | |||||
| #endif | |||||
| // TODO: Close surface, context and display | |||||
| #if defined(SUPPORT_EVENTS_AUTOMATION) | |||||
| RL_FREE(events); | |||||
| #endif | |||||
| CORE.Window.ready = false; | |||||
| TRACELOG(LOG_INFO, "Window closed successfully"); | |||||
| } | |||||
| // Check if application should close | |||||
| bool WindowShouldClose(void) | |||||
| { | |||||
| if (CORE.Window.ready) return CORE.Window.shouldClose; | |||||
| else return true; | |||||
| } | |||||
| // Check if window is currently hidden | |||||
| bool IsWindowHidden(void) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| // Check if window has been minimized | |||||
| bool IsWindowMinimized(void) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| // Check if window has been maximized | |||||
| bool IsWindowMaximized(void) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| // Check if window has the focus | |||||
| bool IsWindowFocused(void) | |||||
| { | |||||
| return platform.appEnabled; | |||||
| } | |||||
| // Check if window has been resizedLastFrame | |||||
| bool IsWindowResized(void) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| // Toggle fullscreen mode | |||||
| void ToggleFullscreen(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "ToggleFullscreen() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window state: maximized, if resizable | |||||
| void MaximizeWindow(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "MaximizeWindow() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window state: minimized | |||||
| void MinimizeWindow(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "MinimizeWindow() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window state: not minimized/maximized | |||||
| void RestoreWindow(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "RestoreWindow() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Toggle borderless windowed mode | |||||
| void ToggleBorderlessWindowed(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window configuration state using flags | |||||
| void SetWindowState(unsigned int flags) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowState() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Clear window configuration state flags | |||||
| void ClearWindowState(unsigned int flags) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "ClearWindowState() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set icon for window | |||||
| void SetWindowIcon(Image image) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowIcon() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set icon for window | |||||
| void SetWindowIcons(Image *images, int count) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowIcons() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set title for window | |||||
| void SetWindowTitle(const char *title) | |||||
| { | |||||
| CORE.Window.title = title; | |||||
| } | |||||
| // Set window position on screen (windowed mode) | |||||
| void SetWindowPosition(int x, int y) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowPosition() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set monitor for the current window | |||||
| void SetWindowMonitor(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowMonitor() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) | |||||
| void SetWindowMinSize(int width, int height) | |||||
| { | |||||
| CORE.Window.windowMin.width = width; | |||||
| CORE.Window.windowMin.height = height; | |||||
| } | |||||
| // Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) | |||||
| void SetWindowMaxSize(int width, int height) | |||||
| { | |||||
| CORE.Window.windowMax.width = width; | |||||
| CORE.Window.windowMax.height = height; | |||||
| } | |||||
| // Set window dimensions | |||||
| void SetWindowSize(int width, int height) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowSize() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window opacity, value opacity is between 0.0 and 1.0 | |||||
| void SetWindowOpacity(float opacity) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Set window focused | |||||
| void SetWindowFocused(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetWindowFocused() not available on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Get native window handle | |||||
| void *GetWindowHandle(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetWindowHandle() not implemented on PLATFORM_CUSTOM"); | |||||
| return NULL; | |||||
| } | |||||
| // Get number of monitors | |||||
| int GetMonitorCount(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorCount() not implemented on PLATFORM_CUSTOM"); | |||||
| return 1; | |||||
| } | |||||
| // Get number of monitors | |||||
| int GetCurrentMonitor(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get selected monitor position | |||||
| Vector2 GetMonitorPosition(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorPosition() not implemented on PLATFORM_CUSTOM"); | |||||
| return (Vector2){ 0, 0 }; | |||||
| } | |||||
| // Get selected monitor width (currently used by monitor) | |||||
| int GetMonitorWidth(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorWidth() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get selected monitor height (currently used by monitor) | |||||
| int GetMonitorHeight(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorHeight() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get selected monitor physical width in millimetres | |||||
| int GetMonitorPhysicalWidth(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get selected monitor physical height in millimetres | |||||
| int GetMonitorPhysicalHeight(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get selected monitor refresh rate | |||||
| int GetMonitorRefreshRate(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get the human-readable, UTF-8 encoded name of the selected monitor | |||||
| const char *GetMonitorName(int monitor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMonitorName() not implemented on PLATFORM_CUSTOM"); | |||||
| return ""; | |||||
| } | |||||
| // Get window position XY on monitor | |||||
| Vector2 GetWindowPosition(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetWindowPosition() not implemented on PLATFORM_CUSTOM"); | |||||
| return (Vector2){ 0, 0 }; | |||||
| } | |||||
| // Get window scale DPI factor for current monitor | |||||
| Vector2 GetWindowScaleDPI(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on PLATFORM_CUSTOM"); | |||||
| return (Vector2){ 1.0f, 1.0f }; | |||||
| } | |||||
| // Set clipboard text content | |||||
| void SetClipboardText(const char *text) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetClipboardText() not implemented on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Get clipboard text content | |||||
| // NOTE: returned string is allocated and freed by GLFW | |||||
| const char *GetClipboardText(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetClipboardText() not implemented on PLATFORM_CUSTOM"); | |||||
| return NULL; | |||||
| } | |||||
| // Show mouse cursor | |||||
| void ShowCursor(void) | |||||
| { | |||||
| CORE.Input.Mouse.cursorHidden = false; | |||||
| } | |||||
| // Hides mouse cursor | |||||
| void HideCursor(void) | |||||
| { | |||||
| CORE.Input.Mouse.cursorHidden = true; | |||||
| } | |||||
| // Enables cursor (unlock cursor) | |||||
| void EnableCursor(void) | |||||
| { | |||||
| // Set cursor position in the middle | |||||
| SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); | |||||
| CORE.Input.Mouse.cursorHidden = false; | |||||
| } | |||||
| // Disables cursor (lock cursor) | |||||
| void DisableCursor(void) | |||||
| { | |||||
| // Set cursor position in the middle | |||||
| SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); | |||||
| CORE.Input.Mouse.cursorHidden = true; | |||||
| } | |||||
| // Swap back buffer with front buffer (screen drawing) | |||||
| void SwapScreenBuffer(void) | |||||
| { | |||||
| eglSwapBuffers(platform.device, platform.surface); | |||||
| } | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Functions Definition: Misc | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Get elapsed time measure in seconds since InitTimer() | |||||
| double GetTime(void) | |||||
| { | |||||
| double time = 0.0; | |||||
| struct timespec ts = { 0 }; | |||||
| clock_gettime(CLOCK_MONOTONIC, &ts); | |||||
| unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; | |||||
| time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() | |||||
| return time; | |||||
| } | |||||
| // Open URL with default system browser (if available) | |||||
| // NOTE: This function is only safe to use if you control the URL given. | |||||
| // A user could craft a malicious string performing another action. | |||||
| // Only call this function yourself not with user input or make sure to check the string yourself. | |||||
| // Ref: https://github.com/raysan5/raylib/issues/686 | |||||
| void OpenURL(const char *url) | |||||
| { | |||||
| // Security check to (partially) avoid malicious code on PLATFORM_CUSTOM | |||||
| if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); | |||||
| else | |||||
| { | |||||
| JNIEnv *env = NULL; | |||||
| JavaVM *vm = platform.app->activity->vm; | |||||
| (*vm)->AttachCurrentThread(vm, &env, NULL); | |||||
| jstring urlString = (*env)->NewStringUTF(env, url); | |||||
| jclass uriClass = (*env)->FindClass(env, "android/net/Uri"); | |||||
| jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;"); | |||||
| jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, urlString); | |||||
| jclass intentClass = (*env)->FindClass(env, "android/content/Intent"); | |||||
| jfieldID actionViewId = (*env)->GetStaticFieldID(env, intentClass, "ACTION_VIEW", "Ljava/lang/String;"); | |||||
| jobject actionView = (*env)->GetStaticObjectField(env, intentClass, actionViewId); | |||||
| jmethodID newIntent = (*env)->GetMethodID(env, intentClass, "<init>", "(Ljava/lang/String;Landroid/net/Uri;)V"); | |||||
| jobject intent = (*env)->AllocObject(env, intentClass); | |||||
| (*env)->CallVoidMethod(env, intent, newIntent, actionView, uri); | |||||
| jclass activityClass = (*env)->FindClass(env, "android/app/Activity"); | |||||
| jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V"); | |||||
| (*env)->CallVoidMethod(env, platform.app->activity->clazz, startActivity, intent); | |||||
| (*vm)->DetachCurrentThread(vm); | |||||
| } | |||||
| } | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Functions Definition: Inputs | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Set a custom key to exit program | |||||
| void SetExitKey(int key) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetExitKey() not implemented on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Get gamepad internal name id | |||||
| const char *GetGamepadName(int gamepad) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetGamepadName() not implemented on PLATFORM_CUSTOM"); | |||||
| return NULL; | |||||
| } | |||||
| // Get gamepad axis count | |||||
| int GetGamepadAxisCount(int gamepad) | |||||
| { | |||||
| return CORE.Input.Gamepad.axisCount; | |||||
| } | |||||
| // Set internal gamepad mappings | |||||
| int SetGamepadMappings(const char *mappings) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0; | |||||
| } | |||||
| // Get mouse position X | |||||
| int GetMouseX(void) | |||||
| { | |||||
| return (int)CORE.Input.Touch.position[0].x; | |||||
| } | |||||
| // Get mouse position Y | |||||
| int GetMouseY(void) | |||||
| { | |||||
| return (int)CORE.Input.Touch.position[0].y; | |||||
| } | |||||
| // Get mouse position XY | |||||
| Vector2 GetMousePosition(void) | |||||
| { | |||||
| return GetTouchPosition(0); | |||||
| } | |||||
| // Set mouse position XY | |||||
| void SetMousePosition(int x, int y) | |||||
| { | |||||
| CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; | |||||
| CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; | |||||
| } | |||||
| // Get mouse wheel movement Y | |||||
| float GetMouseWheelMove(void) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "GetMouseWheelMove() not implemented on PLATFORM_CUSTOM"); | |||||
| return 0.0f; | |||||
| } | |||||
| // Set mouse cursor | |||||
| void SetMouseCursor(int cursor) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on PLATFORM_CUSTOM"); | |||||
| } | |||||
| // Get touch position X for touch point 0 (relative to screen size) | |||||
| int GetTouchX(void) | |||||
| { | |||||
| return (int)CORE.Input.Touch.position[0].x; | |||||
| } | |||||
| // Get touch position Y for touch point 0 (relative to screen size) | |||||
| int GetTouchY(void) | |||||
| { | |||||
| return (int)CORE.Input.Touch.position[0].y; | |||||
| } | |||||
| // Get touch position XY for a touch point index (relative to screen size) | |||||
| // TODO: Touch position should be scaled depending on display size and render size | |||||
| Vector2 GetTouchPosition(int index) | |||||
| { | |||||
| Vector2 position = { -1.0f, -1.0f }; | |||||
| if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index]; | |||||
| else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); | |||||
| return position; | |||||
| } | |||||
| // Register all input events | |||||
| void PollInputEvents(void) | |||||
| { | |||||
| #if defined(SUPPORT_GESTURES_SYSTEM) | |||||
| // NOTE: Gestures update must be called every frame to reset gestures correctly | |||||
| // because ProcessGestureEvent() is just called on an event, not every frame | |||||
| UpdateGestures(); | |||||
| #endif | |||||
| // Reset keys/chars pressed registered | |||||
| CORE.Input.Keyboard.keyPressedQueueCount = 0; | |||||
| CORE.Input.Keyboard.charPressedQueueCount = 0; | |||||
| // Reset key repeats | |||||
| for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; | |||||
| // Reset last gamepad button/axis registered state | |||||
| CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN | |||||
| CORE.Input.Gamepad.axisCount = 0; | |||||
| // Register previous touch states | |||||
| for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; | |||||
| // Reset touch positions | |||||
| // TODO: It resets on PLATFORM_CUSTOM the mouse position and not filled again until a move-event, | |||||
| // so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed! | |||||
| //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; | |||||
| // Register previous keys states | |||||
| // NOTE: Android supports up to 260 keys | |||||
| for (int i = 0; i < 260; i++) | |||||
| { | |||||
| CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; | |||||
| CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; | |||||
| } | |||||
| // TODO: Poll input events for current plaform | |||||
| } | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Module Internal Functions Definition | |||||
| //---------------------------------------------------------------------------------- | |||||
| // Initialize display device and framebuffer | |||||
| // NOTE: width and height represent the screen (framebuffer) desired size, not actual display size | |||||
| // If width or height are 0, default display size will be used for framebuffer size | |||||
| // NOTE: returns false in case graphic device could not be created | |||||
| static bool InitGraphicsDevice(int width, int height) | |||||
| { | |||||
| CORE.Window.screen.width = width; // User desired width | |||||
| CORE.Window.screen.height = height; // User desired height | |||||
| CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default | |||||
| // Set the screen minimum and maximum default values to 0 | |||||
| CORE.Window.screenMin.width = 0; | |||||
| CORE.Window.screenMin.height = 0; | |||||
| CORE.Window.screenMax.width = 0; | |||||
| CORE.Window.screenMax.height = 0; | |||||
| // NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars... | |||||
| // ...in top-down or left-right to match display aspect ratio (no weird scaling) | |||||
| CORE.Window.fullscreen = true; | |||||
| CORE.Window.flags |= FLAG_FULLSCREEN_MODE; | |||||
| EGLint samples = 0; | |||||
| EGLint sampleBuffer = 0; | |||||
| if (CORE.Window.flags & FLAG_MSAA_4X_HINT) | |||||
| { | |||||
| samples = 4; | |||||
| sampleBuffer = 1; | |||||
| TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4"); | |||||
| } | |||||
| const EGLint framebufferAttribs[] = | |||||
| { | |||||
| EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support | |||||
| EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5) | |||||
| EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6) | |||||
| EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5) | |||||
| //EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI) | |||||
| EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!) | |||||
| //EGL_STENCIL_SIZE, 8, // Stencil buffer size | |||||
| EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA | |||||
| EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs) | |||||
| EGL_NONE | |||||
| }; | |||||
| const EGLint contextAttribs[] = | |||||
| { | |||||
| EGL_CONTEXT_CLIENT_VERSION, 2, | |||||
| EGL_NONE | |||||
| }; | |||||
| EGLint numConfigs = 0; | |||||
| // Get an EGL device connection | |||||
| platform.device = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |||||
| if (platform.device == EGL_NO_DISPLAY) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); | |||||
| return false; | |||||
| } | |||||
| // Initialize the EGL device connection | |||||
| if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE) | |||||
| { | |||||
| // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. | |||||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device"); | |||||
| return false; | |||||
| } | |||||
| // Get an appropriate EGL framebuffer configuration | |||||
| eglChooseConfig(platform.device, framebufferAttribs, &platform.config, 1, &numConfigs); | |||||
| // Set rendering API | |||||
| eglBindAPI(EGL_OPENGL_ES_API); | |||||
| // Create an EGL rendering context | |||||
| platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs); | |||||
| if (platform.context == EGL_NO_CONTEXT) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context"); | |||||
| return false; | |||||
| } | |||||
| // Create an EGL window surface | |||||
| //--------------------------------------------------------------------------------- | |||||
| EGLint displayFormat = 0; | |||||
| // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry() | |||||
| // As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID | |||||
| eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat); | |||||
| // At this point we need to manage render size vs screen size | |||||
| // NOTE: This function use and modify global module variables: | |||||
| // -> CORE.Window.screen.width/CORE.Window.screen.height | |||||
| // -> CORE.Window.render.width/CORE.Window.render.height | |||||
| // -> CORE.Window.screenScale | |||||
| SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); | |||||
| ANativeWindow_setBuffersGeometry(platform.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat); | |||||
| //ANativeWindow_setBuffersGeometry(platform.app->window, 0, 0, displayFormat); // Force use of native display size | |||||
| platform.surface = eglCreateWindowSurface(platform.device, platform.config, platform.app->window, NULL); | |||||
| // There must be at least one frame displayed before the buffers are swapped | |||||
| //eglSwapInterval(platform.device, 1); | |||||
| if (eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context) == EGL_FALSE) | |||||
| { | |||||
| TRACELOG(LOG_WARNING, "DISPLAY: Failed to attach EGL rendering context to EGL surface"); | |||||
| return false; | |||||
| } | |||||
| else | |||||
| { | |||||
| CORE.Window.render.width = CORE.Window.screen.width; | |||||
| CORE.Window.render.height = CORE.Window.screen.height; | |||||
| CORE.Window.currentFbo.width = CORE.Window.render.width; | |||||
| CORE.Window.currentFbo.height = CORE.Window.render.height; | |||||
| TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); | |||||
| TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); | |||||
| TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); | |||||
| TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); | |||||
| TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); | |||||
| } | |||||
| // Load OpenGL extensions | |||||
| // NOTE: GL procedures address loader is required to load extensions | |||||
| rlLoadExtensions(eglGetProcAddress); | |||||
| // Initialize OpenGL context (states and resources) | |||||
| // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl | |||||
| rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); | |||||
| // Setup default viewport | |||||
| // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height | |||||
| SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); | |||||
| CORE.Window.ready = true; | |||||
| if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow(); | |||||
| return true; | |||||
| } | |||||
| // EOF | |||||