From 35a9257d20eb2b33866215cde5823bce83f8821f Mon Sep 17 00:00:00 2001 From: Michael Kearns <1312115+mobiuscog@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:00:06 +0000 Subject: [PATCH 01/39] Update BINDINGS.md for official V language binding change (#4691) The bindings from @EmmaTheMartian were moved to official status, so the link is updated. The name was normalized to be consistent with other 'vendored' names in other languages. --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 3bc235b76..860151b21 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -76,7 +76,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT | | [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | | [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib | -| [raylib-for-v](https://github.com/EmmaTheMartian/raylib-for-v) | 5.5 | [V](https://vlang.io) | MIT/Unlicense | +| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense | | [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib | | [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **5.0** | [Vala](https://vala.dev) | Zlib | | [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC | From 5c1cce28a7fefbb184dc4bc922325a46e047f7dd Mon Sep 17 00:00:00 2001 From: Eike Decker Date: Thu, 16 Jan 2025 00:32:58 +0100 Subject: [PATCH 02/39] Using Module provided canvas id for event binding (#4690) This change is replacing the hardcoded "#canvas" element references in rcore_web to allow using canvas elements that use different names (which is necessary when using multiple canvas elements on one page). Also adding a cursor hiding example to mouse example. --- examples/core/core_input_mouse.c | 23 +++++++++++++++-- src/platforms/rcore_web.c | 44 ++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c index e6a3e15dc..e4c6f20ee 100644 --- a/examples/core/core_input_mouse.c +++ b/examples/core/core_input_mouse.c @@ -2,12 +2,12 @@ * * raylib [core] example - Mouse input * -* Example originally created with raylib 1.0, last time updated with raylib 4.0 +* Example originally created with raylib 1.0, last time updated with raylib 5.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -27,6 +27,7 @@ int main(void) Vector2 ballPosition = { -100.0f, -100.0f }; Color ballColor = DARKBLUE; + int isCursorHidden = 0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- @@ -36,6 +37,20 @@ int main(void) { // Update //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_H)) + { + if (isCursorHidden == 0) + { + HideCursor(); + isCursorHidden = 1; + } + else + { + ShowCursor(); + isCursorHidden = 0; + } + } + ballPosition = GetMousePosition(); if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) ballColor = MAROON; @@ -56,6 +71,10 @@ int main(void) DrawCircleV(ballPosition, 40, ballColor); DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); + DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY); + + if (isCursorHidden == 1) DrawText("CURSOR HIDDEN", 20, 60, 20, RED); + else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 78fd46f50..4faf5b87f 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -142,6 +142,8 @@ static EM_BOOL EmscriptenPointerlockCallback(int eventType, const EmscriptenPoin static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); +static const char *GetCanvasId(void); + //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- @@ -824,7 +826,7 @@ void ShowCursor(void) { if (CORE.Input.Mouse.cursorHidden) { - EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, cursorLUT[CORE.Input.Mouse.cursor]); + EM_ASM( { Module.canvas.style.cursor = UTF8ToString($0); }, cursorLUT[CORE.Input.Mouse.cursor]); CORE.Input.Mouse.cursorHidden = false; } @@ -835,7 +837,7 @@ void HideCursor(void) { if (!CORE.Input.Mouse.cursorHidden) { - EM_ASM(document.getElementById('canvas').style.cursor = 'none';); + EM_ASM(Module.canvas.style.cursor = 'none';); CORE.Input.Mouse.cursorHidden = true; } @@ -856,7 +858,7 @@ void EnableCursor(void) void DisableCursor(void) { // TODO: figure out how not to hard code the canvas ID here. - emscripten_request_pointerlock("#canvas", 1); + emscripten_request_pointerlock(GetCanvasId(), 1); // Set cursor position in the middle SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); @@ -1355,25 +1357,25 @@ int InitPlatform(void) // emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback); // Support mouse events - emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback); + emscripten_set_click_callback(GetCanvasId(), NULL, 1, EmscriptenMouseCallback); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenPointerlockCallback); // Following the mouse delta when the mouse is locked - emscripten_set_mousemove_callback("#canvas", NULL, 1, EmscriptenMouseMoveCallback); + emscripten_set_mousemove_callback(GetCanvasId(), NULL, 1, EmscriptenMouseMoveCallback); // 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); + emscripten_set_touchstart_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchend_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchmove_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchcancel_callback(GetCanvasId(), 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); // Support focus events - emscripten_set_blur_callback("#canvas", platform.handle, 1, EmscriptenFocusCallback); - emscripten_set_focus_callback("#canvas", platform.handle, 1, EmscriptenFocusCallback); + emscripten_set_blur_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback); + emscripten_set_focus_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback); //---------------------------------------------------------------------------- // Initialize timing system @@ -1674,7 +1676,7 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent * if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height; else if ((height > (int)CORE.Window.screenMax.height) && (CORE.Window.screenMax.height > 0)) height = CORE.Window.screenMax.height; - emscripten_set_canvas_element_size("#canvas", width, height); + emscripten_set_canvas_element_size(GetCanvasId(), width, height); SetupViewport(width, height); // Reset viewport and projection matrix for new size @@ -1760,7 +1762,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent // 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); + emscripten_get_element_css_size(GetCanvasId(), &canvasWidth, &canvasHeight); for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++) { @@ -1835,4 +1837,20 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent return 1; // The event was consumed by the callback handler } +// obtaining the canvas id provided by the module configuration +EM_JS(char*, GetCanvasIdJs, (), { + var canvasId = "#" + Module.canvas.id; + var lengthBytes = lengthBytesUTF8(canvasId) + 1; + var stringOnWasmHeap = _malloc(lengthBytes); + stringToUTF8(canvasId, stringOnWasmHeap, lengthBytes); + return stringOnWasmHeap; +}); + +static const char *GetCanvasId(void) +{ + static char *canvasId = NULL; + if (canvasId == NULL) canvasId = GetCanvasIdJs(); + return canvasId; +} + // EOF From 6bf40eee4f5bb86e676abd0635f7c9b9aefe3fee Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Wed, 15 Jan 2025 18:34:27 -0500 Subject: [PATCH 03/39] Update to RGFW 1.5 (#4688) * add PLATFORM_WEB_RGFW * fix some bugs * fix web_rgfw gamepad * send fake screensize * fix gamepad bugs (linux) | add L3 + R3 (gamepad) * fix? * update RGFW (again) * update raylib (merge) * fix xinput stuff * delete makefile added by mistake * update RGFW * update RGFW (rename joystick to gamepad to avoid misunderstandings * update RGFW (fix X11 bug) * update RGFW * use RL_MALLOC for RGFW * update RGFW (fixes xdnd bug) * fix some formating * Update RGFW * update RGFW * undo change * undo change * undo change * undo change * have .scroll be 0 by default * update RGFW * update RGFW * update RGFW * fix year * fix wasm key event bug --- src/external/RGFW.h | 12894 ++++++++++++++------------- src/platforms/rcore_desktop_rgfw.c | 151 +- 2 files changed, 6794 insertions(+), 6251 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 317d00c7a..d4ec7d77f 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -1,5 +1,8 @@ /* -* Copyright (C) 2023-24 ColleagueRiley +* +* RGFW 1.5.1-dev +* +* Copyright (C) 2022-25 ColleagueRiley * * libpng license * @@ -29,8 +32,7 @@ /* #define RGFW_IMPLEMENTATION - (required) makes it so the source code is included - #define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found - #define RGFW_DEBUG - (optional) makes it so RGFW prints debug messages + #define RGFW_DEBUG - (optional) makes it so RGFW prints debug messages anderrors when they're found #define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl) #define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format) #define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api) @@ -43,32 +45,38 @@ #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX) #define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress) - #define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically (using GetProcAddress) - #define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS - #define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime + #define RGFW_WAYLAND (optional) (unix only) if Wayland should be used. (This can be used with X11) + #define RGFW_NO_X11 (optional) (unix only) if X11 should be used (with Wayland). + #define RGFW_NO_LOAD_WGL (optional) (windows only) if WGL should be loaded dynamically during runtime #define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor #define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) Use XCursor, but don't link it in code, (you'll have to link it with -lXcursor) + #define RGFW_NO_LOAD_WINMM (optional) (windows only) Use winmm (timeBeginPeriod), but don't link it in code, (you'll have to link it with -lwinmm) + #define RGFW_NO_WINMM (optional) (windows only) don't use winmm + #define RGFW_NO_IOKIT (optional) (macOS) don't use IOKit + #define RGFW_NO_UNIX_CLOCK (optional) (unux) don't link unix clock functions + #define RGFW_NO_DWM (windows only) - Do not use or linj dwmapi + #define RGFW_USE_XDL (optional) (X11) use X11 in RGFW (must include XDL.h along with RGFW) (XLib Dynamic Loader) #define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included) #define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data) - #define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used - #define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used - #define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used + #define RGFW_alloc(userptr, size) x - choose what default function to use to allocate, by default the standard malloc is used + #define RGFW_free(userptr, ptr) x - choose what default function to use to allocated memory, by default the standard free is used + #define RGFW_USERPTR x - choose the default userptr sent to the malloc call, (NULL by default) - #define RGFW_EXPORT - Use when building RGFW + #define RGFW_EXPORT - Use when building RGFW #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header) - - #define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc)) + + #define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc)) */ /* Example to get you started : -linux : gcc main.c -lX11 -lXrandr -lGL -lm -windows : gcc main.c -lopengl32 -lwinmm -lshell32 -lgdi32 -macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo +linux : gcc main.c -lX11 -lXrandr -lGL +windows : gcc main.c -lopengl32 -lgdi32 +macos : gcc main.c -framework Cocoa -framework OpenGL -framework IOKit #define RGFW_IMPLEMENTATION #include "RGFW.h" @@ -76,18 +84,18 @@ macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -fr u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; int main() { - RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); + RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(100, 100, 500, 500), (u64)0); RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); for (;;) { RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag - if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) + if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_escape)) break; RGFW_window_swapBuffers(win); - glClearColor(0xFF, 0XFF, 0xFF, 0xFF); + glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT); } @@ -102,8 +110,8 @@ int main() { #define RGFW_IMPLEMENTATION #include "RGFW.h" - You may also want to add - `#define RGFW_EXPORT` when compiling and + You may also want to add + `#define RGFW_EXPORT` when compiling and `#define RGFW_IMPORT`when linking RGFW on it's own: this reduces inline functions and prevents bloat in the object file @@ -114,39 +122,34 @@ int main() { after you compile the library into an object file, you can also turn the object file into an static or shared library (commands ar and gcc can be replaced with whatever equivalent your system uses) + static : ar rcs RGFW.a RGFW.o shared : windows: - gcc -shared RGFW.o -lwinmm -lopengl32 -lshell32 -lgdi32 -o RGFW.dll + gcc -shared RGFW.o -lopengl32 -lgdi32 -o RGFW.dll linux: gcc -shared RGFW.o -lX11 -lGL -lXrandr -o RGFW.so macos: - gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo + gcc -shared RGFW.o -framework Cocoa -framework OpenGL -framework IOKit */ /* Credits : - EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing + EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing stb - This project is heavily inspired by the stb single header files GLFW: certain parts of winapi and X11 are very poorly documented, - GLFW's source code was referenced and used throughout the project (used code is marked in some way), - this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well) - - GLFW Copyright, https::/github.com/GLFW/GLFW - - Copyright (c) 2002-2006 Marcus Geelnard - Copyright (c) 2006-2019 Camilla Löwy - + GLFW's source code was referenced and used throughout the project. + contributors : (feel free to put yourself here if you contribute) krisvers -> code review EimaMei (SaCode) -> code review Code-Nycticebus -> bug fixes - Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs + Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs AICDG (@THISISAGOODNAME) -> vulkan support (example) @Easymode -> support, testing/debugging, bug fixes and reviews Joshua Rowe (omnisci3nce) - bug fix, review (macOS) @@ -163,17 +166,38 @@ int main() { #pragma comment(lib, "user32") #endif -#ifndef RGFW_MALLOC +#ifndef RGFW_UNUSED + #define RGFW_UNUSED(x) (void)(x) +#endif + +#ifndef RGFW_USERPTR + #define RGFW_USERPTR NULL +#endif + +#ifndef RGFW_ROUND +#define RGFW_ROUND(x) (int)((x) >= 0 ? (x) + 0.5f : (x) - 0.5f) +#endif + +#ifndef RGFW_ALLOC #include #ifndef __USE_POSIX199309 #define __USE_POSIX199309 #endif - #include - #define RGFW_MALLOC malloc - #define RGFW_CALLOC calloc - #define RGFW_FREE free + #define RGFW_ALLOC(userptr, size) (RGFW_UNUSED(userptr),malloc(size)) + #define RGFW_FREE(userptr, ptr) (RGFW_UNUSED(userptr),free(ptr)) +#endif + +#ifndef RGFW_MEMCPY + #include + + #define RGFW_MEMCPY(dist, src, len) memcpy(dist, src, len) + #define RGFW_STRNCMP(s1, s2, max) strncmp(s1, s2, max) + //required for X11 + #define RGFW_STRTOL(str, endptr, base) strtol(str, endptr, base) +#else +#undef _INC_STRING #endif #if !_MSC_VER @@ -197,7 +221,7 @@ int main() { #if defined(RGFW_EXPORT) #define RGFWDEF __declspec(dllexport) - #else + #else #define RGFWDEF __declspec(dllimport) #endif #else @@ -205,7 +229,7 @@ int main() { #define RGFWDEF __attribute__((visibility("default"))) #endif #endif -#endif +#endif #ifndef RGFWDEF #define RGFWDEF inline @@ -215,11 +239,12 @@ int main() { #define RGFW_ENUM(type, name) type name; enum #endif -#ifndef RGFW_UNUSED - #define RGFW_UNUSED(x) (void)(x); -#endif #if defined(__cplusplus) && !defined(__EMSCRIPTEN__) + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wnullability-completeness" + #endif extern "C" { #endif @@ -240,6 +265,7 @@ int main() { typedef signed long long i64; #else /* use stdint standard types instead of c ""standard"" types */ #include + #include typedef uint8_t u8; typedef int8_t i8; @@ -250,11 +276,13 @@ int main() { typedef uint64_t u64; typedef int64_t i64; #endif + #define u8 u8 #endif #if !defined(b8) /* RGFW bool type */ typedef u8 b8; typedef u32 b32; + #define b8 b8 #endif #define RGFW_TRUE (!(0)) @@ -282,14 +310,14 @@ int main() { #endif #endif -#if defined(RGFW_X11) && defined(__APPLE__) +#if defined(RGFW_X11) && defined(__APPLE__) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS_X11 + #define RGFW_UNIX #undef __APPLE__ #endif -#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */ +#if defined(_WIN32) && !defined(RGFW_UNIX) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) /* (if you're using X11 on windows some how) */ #define RGFW_WINDOWS - /* make sure the correct architecture is defined */ #if defined(_WIN64) #define _AMD64_ @@ -310,6 +338,7 @@ int main() { #endif #if defined(RGFW_DIRECTX) + #define OEMRESOURCE #include #include #include @@ -321,18 +350,22 @@ int main() { #endif #elif defined(RGFW_WAYLAND) - #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL)) + #define RGFW_DEBUG // wayland will be in debug mode by default for now + #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) #define RGFW_EGL #define RGFW_OPENGL + #define RGFW_UNIX #include #endif #include -#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) +#endif +#if !defined(RGFW_NO_X11) && !defined(RGFW_NO_X11) && (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS_X11 #define RGFW_X11 + #define RGFW_UNIX #include -#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) +#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS #endif @@ -347,6 +380,13 @@ int main() { #ifdef RGFW_EGL #include #elif defined(RGFW_OSMESA) + #ifdef RGFW_WINDOWS + #define OEMRESOURCE + #include + #define GLAPIENTRY APIENTRY + #define GLAPI WINGDIAPI + #endif + #ifndef __APPLE__ #include #else @@ -361,61 +401,71 @@ int main() { #include /* GLX defs, xlib.h, gl.h */ #endif -#ifndef RGFW_ALPHA - #define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */ -#endif +/*! (unix) Toggle use of wayland, this will be on by default if you use `RGFW_WAYLAND` (if you don't use RGFW_WAYLAND, you dont' expose WAYLAND functions) + this is mostly used to allow you to force the use of XWayland +*/ +RGFWDEF void RGFW_useWayland(b8 wayland); -/*! Optional arguments for making a windows */ -#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */ -#define RGFW_NO_BORDER (1L<<3) /*!< the window doesn't have border */ -#define RGFW_NO_RESIZE (1L<<4) /*!< the window cannot be resized by the user */ -#define RGFW_ALLOW_DND (1L<<5) /*!< the window supports drag and drop*/ -#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/ -#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */ -#define RGFW_CENTER (1L<<10) /*! center the window on the screen */ -#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */ -#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */ -#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */ -#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */ +/* + RGFW_allocator (optional) + you can ignore this if you use standard malloc/free +*/ +typedef void* (* RGFW_allocatorMallocfunc)(void* userdata, size_t size); +typedef void (* RGFW_allocatorFreefunc)(void* userdata, void* ptr); -#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/ -#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/ -#define RGFW_WINDOW_HIDE (1L << 16)/* the window is hidden */ +typedef struct RGFW_allocator { + void* userdata; + RGFW_allocatorMallocfunc alloc; + RGFW_allocatorFreefunc free; +} RGFW_allocator; -typedef RGFW_ENUM(u8, RGFW_event_types) { +RGFWDEF RGFW_allocator RGFW_loadAllocator(RGFW_allocator allocator); +RGFWDEF void* RGFW_alloc(size_t len); +RGFWDEF void RGFW_free(void* ptr); + +/* + regular RGFW stuff +*/ + +typedef u8 RGFW_key; + +typedef RGFW_ENUM(u8, RGFW_eventType) { /*! event codes */ - RGFW_keyPressed = 1, /* a key has been pressed */ + RGFW_eventNone = 0, /*!< no event has been sent */ + RGFW_keyPressed, /* a key has been pressed */ RGFW_keyReleased, /*!< a key has been released*/ /*! key event note the code of the key pressed is stored in - RGFW_Event.key + RGFW_event.key !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! while a string version is stored in - RGFW_Event.KeyString + RGFW_event.KeyString - RGFW_Event.lockState holds the current lockState + RGFW_event.keyMod holds the current keyMod this means if CapsLock, NumLock are active or not */ RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/ RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/ RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/ /*! mouse event note - the x and y of the mouse can be found in the vector, RGFW_Event.point + the x and y of the mouse can be found in the vector, RGFW_event.point - RGFW_Event.button holds which mouse button was pressed + RGFW_event.button holds which mouse button was pressed */ - RGFW_gpButtonPressed, /*!< a gamepad button was pressed */ - RGFW_gpButtonReleased, /*!< a gamepad button was released */ - RGFW_gpAxisMove, /*!< an axis of a gamepad was moved*/ + RGFW_gamepadConnected, /*!< a gamepad was connected */ + RGFW_gamepadDisconnected, /*!< a gamepad was disconnected */ + RGFW_gamepadButtonPressed, /*!< a gamepad button was pressed */ + RGFW_gamepadButtonReleased, /*!< a gamepad button was released */ + RGFW_gamepadAxisMove, /*!< an axis of a gamepad was moved*/ /*! gamepad event note - RGFW_Event.gamepad holds which gamepad was altered, if any - RGFW_Event.button holds which gamepad button was pressed + RGFW_event.gamepad holds which gamepad was altered, if any + RGFW_event.button holds which gamepad button was pressed - RGFW_Event.axis holds the data of all the axis - RGFW_Event.axisCount says how many axis there are + RGFW_event.axis holds the data of all the axis + RGFW_event.axisesCount says how many axis there are */ - RGFW_windowMoved, /*!< the window was moved (by the user) */ + RGFW_windowMoved, /*!< the window was moved (b the user) */ RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */ RGFW_focusIn, /*!< window is in focus now */ RGFW_focusOut, /*!< window is out of focus now */ @@ -427,25 +477,28 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { The event data is sent straight to the window structure with win->r.x, win->r.y, win->r.w and win->r.h */ - RGFW_quit, /*!< the user clicked the quit button*/ - RGFW_dnd, /*!< a file has been dropped into the window*/ - RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */ + RGFW_quit, /*!< the user clicked the quit button*/ + RGFW_DND, /*!< a file has been dropped into the window*/ + RGFW_DNDInit /*!< the start of a dnd event, when the place where the file drop is known */ /* dnd data note - The x and y coords of the drop are stored in the vector RGFW_Event.point + The x and y coords of the drop are stored in the vector RGFW_event.point - RGFW_Event.droppedFilesCount holds how many files were dropped + RGFW_event.droppedFilesCount holds how many files were dropped This is also the size of the array which stores all the dropped file string, - RGFW_Event.droppedFiles + RGFW_event.droppedFiles */ }; -/*! mouse button codes (RGFW_Event.button) */ -#define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/ -#define RGFW_mouseMiddle 2 /*!< mouse-wheel-button is pressed*/ -#define RGFW_mouseRight 3 /*!< right mouse button is pressed*/ -#define RGFW_mouseScrollUp 4 /*!< mouse wheel is scrolling up*/ -#define RGFW_mouseScrollDown 5 /*!< mouse wheel is scrolling down*/ +/*! mouse button codes (RGFW_event.button) */ +typedef RGFW_ENUM(u8, RGFW_mouseButton) { + RGFW_mouseNone = 0, /*!< no mouse button is pressed*/ + RGFW_mouseLeft, /*!< left mouse button is pressed*/ + RGFW_mouseMiddle, /*!< mouse-wheel-button is pressed*/ + RGFW_mouseRight, /*!< right mouse button is pressed*/ + RGFW_mouseScrollUp, /*!< mouse wheel is scrolling up*/ + RGFW_mouseScrollDown /*!< mouse wheel is scrolling down*/ +}; #ifndef RGFW_MAX_PATH #define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */ @@ -454,33 +507,40 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { #define RGFW_MAX_DROPS 260 /* max items you can drop at once */ #endif +#define RGFW_BIT(x) (1L << x) -/* for RGFW_Event.lockstate */ -#define RGFW_CAPSLOCK (1L << 1) -#define RGFW_NUMLOCK (1L << 2) +/* for RGFW_event.lockstate */ +typedef RGFW_ENUM(u8, RGFW_keymod) { + RGFW_modCapsLock = RGFW_BIT(0), + RGFW_modNumLock = RGFW_BIT(1), + RGFW_modControl = RGFW_BIT(2), + RGFW_modAlt = RGFW_BIT(3), + RGFW_modShift = RGFW_BIT(4), + RGFW_modSuper = RGFW_BIT(5) +}; /*! gamepad button codes (based on xbox/playstation), you may need to change these values per controller */ -#ifndef RGFW_gamepad_codes - typedef RGFW_ENUM(u8, RGFW_gamepad_codes) { - RGFW_GP_A = 0, /*!< or PS X button */ - RGFW_GP_B = 1, /*!< or PS circle button */ - RGFW_GP_Y = 2, /*!< or PS triangle button */ - RGFW_GP_X = 3, /*!< or PS square button */ - RGFW_GP_START = 9, /*!< start button */ - RGFW_GP_SELECT = 8, /*!< select button */ - RGFW_GP_HOME = 10, /*!< home button */ - RGFW_GP_UP = 13, /*!< dpad up */ - RGFW_GP_DOWN = 14, /*!< dpad down*/ - RGFW_GP_LEFT = 15, /*!< dpad left */ - RGFW_GP_RIGHT = 16, /*!< dpad right */ - RGFW_GP_L1 = 4, /*!< left bump */ - RGFW_GP_L2 = 5, /*!< left trigger*/ - RGFW_GP_R1 = 6, /*!< right bumper */ - RGFW_GP_R2 = 7, /*!< right trigger */ - RGFW_GP_L3 = 11, /* left thumb stick */ - RGFW_GP_R3 = 12 /*!< right thumb stick */ - }; -#endif +typedef RGFW_ENUM(u8, RGFW_gamepadCodes) { + RGFW_gamepadNone = 0, /*!< or PS X button */ + RGFW_gamepadA, /*!< or PS X button */ + RGFW_gamepadB, /*!< or PS circle button */ + RGFW_gamepadY, /*!< or PS triangle button */ + RGFW_gamepadX, /*!< or PS square button */ + RGFW_gamepadStart, /*!< start button */ + RGFW_gamepadSelect, /*!< select button */ + RGFW_gamepadHome, /*!< home button */ + RGFW_gamepadUp, /*!< dpad up */ + RGFW_gamepadDown, /*!< dpad down*/ + RGFW_gamepadLeft, /*!< dpad left */ + RGFW_gamepadRight, /*!< dpad right */ + RGFW_gamepadL1, /*!< left bump */ + RGFW_gamepadL2, /*!< left trigger*/ + RGFW_gamepadR1, /*!< right bumper */ + RGFW_gamepadR2, /*!< right trigger */ + RGFW_gamepadL3, /* left thumb stick */ + RGFW_gamepadR3, /*!< right thumb stick */ + RGFW_gamepadFinal +}; /*! basic vector type, if there's not already a point/vector type of choice */ #ifndef RGFW_point @@ -497,15 +557,9 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { typedef struct { u32 w, h; } RGFW_area; #endif -#ifndef __cplusplus #define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)} #define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)} #define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)} -#else -#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)} -#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)} -#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)} -#endif #ifndef RGFW_NO_MONITOR /*! structure for monitor data */ @@ -513,6 +567,7 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { char name[128]; /*!< monitor name */ RGFW_rect rect; /*!< monitor Workarea */ float scaleX, scaleY; /*!< monitor content scale*/ + float pixelRatio; /*!< pixel ratio for monitor (1.0 for regular, 2.0 for hiDPI) */ float physW, physH; /*!< monitor physical size in inches*/ } RGFW_monitor; @@ -526,11 +581,18 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); #endif -/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */ -/*! Event structure for checking/getting events */ -typedef struct RGFW_Event { - char keyName[16]; /*!< key name of event*/ +/* RGFW mouse loading */ +typedef void RGFW_mouse; +/*!< loads mouse from bitmap (similar to RGFW_window_setIcon), icon NOT resized by default*/ +RGFWDEF RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels); +/*!< frees RGFW_mouse data */ +RGFWDEF void RGFW_freeMouse(RGFW_mouse* mouse); +/* */ + +/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_event struct) */ +/*! Event structure for checking/getting events */ +typedef struct RGFW_event { /*! drag and drop data */ /* 260 max paths with a max length of 260 */ #ifdef RGFW_ALLOC_DROPFILES @@ -538,34 +600,34 @@ typedef struct RGFW_Event { #else char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/ #endif - u32 droppedFilesCount; /*!< house many files were dropped */ + size_t droppedFilesCount; /*!< house many files were dropped */ - u32 type; /*!< which event has been sent?*/ + RGFW_eventType type; /*!< which event has been sent?*/ RGFW_point point; /*!< mouse x, y of event (or drop point) */ - - u8 key; /*!< the physical key of the event, refers to where key is physically !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ + + RGFW_key key; /*!< the physical key of the event, refers to where key is physically !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ u8 keyChar; /*!< mapped key char of the event*/ b8 repeat; /*!< key press event repeated (the key is being held) */ b8 inFocus; /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ - u8 lockState; - + RGFW_keymod keyMod; + u8 button; /* !< which mouse (or gamepad) button was pressed */ double scroll; /*!< the raw mouse scroll value */ u16 gamepad; /*! which gamepad this event applies to (if applicable to any) */ u8 axisesCount; /*!< number of axises */ - + u8 whichAxis; /* which axis was effected */ RGFW_point axis[4]; /*!< x, y of axises (-100 to 100) */ u64 frameTime, frameTime2; /*!< this is used for counting the fps */ -} RGFW_Event; +} RGFW_event; /*! source data for the window (used by the APIs) */ -typedef struct RGFW_window_src { #ifdef RGFW_WINDOWS +typedef struct RGFW_window_src { HWND window; /*!< source window */ HDC hdc; /*!< source HDC */ u32 hOffset; /*!< height offset for window */ @@ -583,12 +645,15 @@ typedef struct RGFW_window_src { EGLContext EGL_context; #endif - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) HDC hdcMem; HBITMAP bitmap; #endif RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */ -#elif defined(RGFW_X11) +} RGFW_window_src; +#elif defined(RGFW_UNIX) +typedef struct RGFW_window_src { +#if defined(RGFW_X11) Display* display; /*!< source display */ Window window; /*!< source window */ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) @@ -601,33 +666,44 @@ typedef struct RGFW_window_src { EGLContext EGL_context; #endif -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - XImage* bitmap; - GC gc; -#endif -#elif defined(RGFW_WAYLAND) - struct wl_display* display; + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + XImage* bitmap; + GC gc; + #endif +#endif /* RGFW_X11 */ +#if defined(RGFW_WAYLAND) + struct wl_display* wl_display; struct wl_surface* surface; struct wl_buffer* wl_buffer; struct wl_keyboard* keyboard; + struct wl_compositor* compositor; struct xdg_surface* xdg_surface; struct xdg_toplevel* xdg_toplevel; struct zxdg_toplevel_decoration_v1* decoration; - RGFW_Event events[20]; + struct xdg_wm_base* xdg_wm_base; + struct wl_shm* shm; + struct wl_seat *seat; + u8* buffer; + + RGFW_event events[20]; i32 eventLen; size_t eventIndex; #if defined(RGFW_EGL) - struct wl_egl_window* window; + struct wl_egl_window* eglWindow; + #endif + #if defined(RGFW_EGL) && !defined(RGFW_X11) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; - #elif defined(RGFW_OSMESA) + #elif defined(RGFW_OSMESA) && !defined(RGFW_X11) OSMesaContext ctx; #endif -#elif defined(RGFW_MACOS) - u32 display; - void* displayLink; +#endif /* RGFW_WAYLAND */ +} RGFW_window_src; +#endif /* RGFW_UNIX */ +#if defined(RGFW_MACOS) +typedef struct RGFW_window_src { void* window; b8 dndPassed; #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) @@ -642,11 +718,13 @@ typedef struct RGFW_window_src { void* view; /*apple viewpoint thingy*/ -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) void* bitmap; /*!< API's bitmap for storing or managing */ void* image; #endif +} RGFW_window_src; #elif defined(RGFW_WEBASM) +typedef struct RGFW_window_src { #ifdef RGFW_WEBGPU WGPUInstance ctx; WGPUDevice device; @@ -654,27 +732,42 @@ typedef struct RGFW_window_src { #else EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx; #endif -#endif } RGFW_window_src; +#endif - +/*! Optional arguments for making a windows */ +typedef RGFW_ENUM(u32, RGFW_windowFlags) { + RGFW_windowNoInitAPI = RGFW_BIT(0), /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */ + RGFW_windowNoBorder = RGFW_BIT(1), /*!< the window doesn't have border */ + RGFW_windowNoResize = RGFW_BIT(2), /*!< the window cannot be resized by the user */ + RGFW_windowAllowDND = RGFW_BIT(3), /*!< the window supports drag and drop*/ + RGFW_windowHideMouse = RGFW_BIT(4), /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/ + RGFW_windowFullscreen = RGFW_BIT(5), /* the window is fullscreen by default or not */ + RGFW_windowTransparent = RGFW_BIT(6), /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */ + RGFW_windowCenter = RGFW_BIT(7), /*! center the window on the screen */ + RGFW_windowOpenglSoftware = RGFW_BIT(8), /*! use OpenGL software rendering */ + RGFW_windowCocoaCHDirToRes = RGFW_BIT(9), /* (cocoa only), change directory to resource folder */ + RGFW_windowScaleToMonitor = RGFW_BIT(10), /* scale the window to the screen */ + RGFW_windowHide = RGFW_BIT(11)/* the window is hidden */ +}; typedef struct RGFW_window { RGFW_window_src src; /*!< src window data */ -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */ /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */ #endif void* userPtr; /* ptr for usr data */ - - RGFW_Event event; /*!< current event */ + + RGFW_event event; /*!< current event */ RGFW_rect r; /*!< the x, y, w and h of the struct */ - + RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */ - - u32 _winArgs; /*!< windows args (for RGFW to check) */ + + u32 _flags; /*!< windows flags (for RGFW to check) */ + RGFW_allocator _mem; /*!< the allocator that was used to allocate RGFW window data, used to free it*/ } RGFW_window; /*!< Window structure for managing the window */ #if defined(RGFW_X11) || defined(RGFW_MACOS) @@ -684,14 +777,14 @@ typedef struct RGFW_window { #endif /** * @defgroup Window_management -* @{ */ +* @{ */ -/*! +/*! * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM * by default the class name will == the root window's name */ -RGFWDEF void RGFW_setClassName(char* name); +RGFWDEF void RGFW_setClassName(const char* name); /*! this has to be set before createWindow is called, else the fulscreen size is used */ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */ @@ -701,12 +794,24 @@ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resiz RGFWDEF RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ RGFW_rect rect, /* rect of window */ - u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ -); /*!< function to create a window struct */ + RGFW_windowFlags flags /* extra arguments ((u32)0 means no flags used)*/ +); /*!< function to create a window and struct */ + +RGFWDEF RGFW_window* RGFW_createWindowPtr( + const char* name, /* name of the window */ + RGFW_rect rect, /* rect of window */ + RGFW_windowFlags flags, /* extra arguments (NULL / (u32)0 means no flags used)*/ + RGFW_window* win /* ptr to the window struct you want to use */ +); /*!< function to create a window (without allocating a window struct) */ /*! get the size of the screen to an area struct */ RGFWDEF RGFW_area RGFW_getScreenSize(void); +/*! frees win->buffer (if it was allocated by RGFW) and sets the pointer to your pointer */ +RGFWDEF void RGFW_window_setBufferPtr(RGFW_window* win, u8* ptr, RGFW_area size); +/*< the new buffer is not be resized or freed (by RGFW) */ + + /*! this function checks an *individual* event (and updates window structure attributes) this means, using this function without a while loop may cause event lag @@ -715,11 +820,11 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void); while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one] - this function is optional if you choose to use event callbacks, + this function is optional if you choose to use event callbacks, although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` */ -RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ +RGFWDEF RGFW_event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ /*! for RGFW_window_eventWait and RGFW_window_checkEvents @@ -729,20 +834,20 @@ RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current if waitMS == a negative integer, the loop will not return until it gets another event */ typedef RGFW_ENUM(i32, RGFW_eventWait) { - RGFW_NEXT = -1, - RGFW_NO_WAIT = 0 + RGFW_eventWaitNext = -1, + RGFW_eventNoWait = 0 }; /*! sleep until RGFW gets an event or the timer ends (defined by OS) */ RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS); /*! - check all the events until there are none left, + check all the events until there are none left, this should only be used if you're using callbacks only */ RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS); -/*! +/*! Tell RGFW_window_eventWait to stop waiting, to be ran from another thread */ RGFWDEF void RGFW_stopCheckEvents(void); @@ -777,35 +882,35 @@ RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from /*! if the window should have a border or not (borderless) based on bool value of `border` */ RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); -/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ +/*! turn on / off dnd (RGFW_windowAllowDND stil must be passed to the window)*/ RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); #ifndef RGFW_NO_PASSTHROUGH /*!! turn on / off mouse passthrough */ RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); -#endif +#endif /*! rename window to a given string */ RGFWDEF void RGFW_window_setName(RGFW_window* win, - char* name + const char* name ); -RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ +RGFWDEF b32 RGFW_window_setIcon(RGFW_window* win, /*!< source window */ u8* icon /*!< icon bitmap */, RGFW_area a /*!< width and height of the bitmap*/, i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ ); /*!< image resized by default */ -/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/ -RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels); +/*!< sets mouse to RGFW_mouse icon (loaded from a bitmap struct) */ +RGFWDEF void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse); /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */ -RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); +RGFWDEF b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); -RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */ +RGFWDEF b32 RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */ /* Locks cursor at the center of the window - win->event.point become raw mouse movement data + win->event.point become raw mouse movement data this is useful for a 3D camera */ @@ -846,67 +951,66 @@ RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); /*! if window is maximized */ RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); -/** @} */ +/** @} */ /** * @defgroup Monitor -* @{ */ +* @{ */ #ifndef RGFW_NO_MONITOR /* scale the window to the monitor, -this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation +this is run by default if the user uses the arg `RGFW_scaleToMonitor` during window creation */ RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win); /*! get the struct of the window's monitor */ RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win); #endif -/** @} */ +/** @} */ /** * @defgroup Input -* @{ */ - -/*error handling*/ -RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */ +* @{ */ /*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ -RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ +RGFWDEF b8 RGFW_isPressed(RGFW_window* win, RGFW_key key); /*!< if key is pressed (key code)*/ -RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/ +RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, RGFW_key key); /*!< if key was pressed (checks previous state only) (key code)*/ -RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/ -RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/ +RGFWDEF b8 RGFW_isHeld(RGFW_window* win, RGFW_key key); /*!< if key is held (key code)*/ +RGFWDEF b8 RGFW_isReleased(RGFW_window* win, RGFW_key key); /*!< if key is released (key code)*/ /* if a key is pressed and then released, pretty much the same as RGFW_isReleased */ -RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/); +RGFWDEF b8 RGFW_isClicked(RGFW_window* win, RGFW_key key /*!< key code*/); /*! if a mouse button is pressed */ -RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button is held */ -RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button was released */ -RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button was pressed (checks previous state only) */ -RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); -/** @} */ +RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); +/** @} */ /** * @defgroup Clipboard -* @{ */ -RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ -RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */ +* @{ */ +typedef ptrdiff_t RGFW_ssize_t; +RGFWDEF const char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ +/*! read clipboard data or send a NULL str to just get the length of the clipboard data */ +RGFWDEF RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity); RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ -/** @} */ +/** @} */ /** - - - Event callbacks, - these are completely optional, you can use the normal + + + Event callbacks, + these are completely optional, you can use the normal RGFW_checkEvent() method if you prefer that * @defgroup Callbacks -* @{ +* @{ */ /*! RGFW_windowMoved, the window and its new rect value */ @@ -921,19 +1025,20 @@ typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status); /*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point); -/*! RGFW_dnd_init, the window, the point of the drop on the windows */ +/*! RGFW_DNDInit, the window, the point of the drop on the windows */ typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point); /*! RGFW_windowRefresh, the window that needs to be refreshed */ typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win); /*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the mapped key, the physical key, the string version, the state of mod keys, if it was a press (else it's a release) */ -typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 key, u32 mappedKey, char keyName[16], u8 lockState, b8 pressed); +typedef void (* RGFW_keyfunc)(RGFW_window* win, u8 key, char keyChar, RGFW_keymod keyMod, b8 pressed); /*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ -typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed); -/*!gp /gp, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ -typedef void (* RGFW_gpButtonfunc)(RGFW_window* win, u16 gamepad, u8 button, b8 pressed); -/*! RGFW_gpAxisMove, the window that got the event, the gamepad in question, the axis values and the amount of axises */ -typedef void (* RGFW_gpAxisfunc)(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount); - +typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, RGFW_mouseButton button, double scroll, b8 pressed); +/*!gamepad /gamepad, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +typedef void (* RGFW_gamepadButtonfunc)(RGFW_window* win, u16 gamepad, u8 button, b8 pressed); +/*! RGFW_gamepadAxisMove, the window that got the event, the gamepad in question, the axis values and the amount of axises */ +typedef void (* RGFW_gamepadAxisfunc)(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount, u8 whichAxis); +/*! RGFW_gamepadConnected/RGFW_gamepadDisconnected, the window that got the event, the gamepad in question, if the controller was connected (or disconnected if false) */ +typedef void (* RGFW_gamepadfunc)(RGFW_window* win, u16 gamepad, b8 connected); /*! RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */ #ifdef RGFW_ALLOC_DROPFILES @@ -964,58 +1069,67 @@ RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func); /*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set) */ RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); /*! set callback for a controller button (press / release ) event returns previous callback function (if it was set) */ -RGFWDEF RGFW_gpButtonfunc RGFW_setgpButtonCallback(RGFW_gpButtonfunc func); +RGFWDEF RGFW_gamepadButtonfunc RGFW_setgamepadButtonCallback(RGFW_gamepadButtonfunc func); /*! set callback for a gamepad axis mov event returns previous callback function (if it was set) */ -RGFWDEF RGFW_gpAxisfunc RGFW_setgpAxisCallback(RGFW_gpAxisfunc func); +RGFWDEF RGFW_gamepadAxisfunc RGFW_setgamepadAxisCallback(RGFW_gamepadAxisfunc func); +/*! set callback for when a controller is connected or disconnected */ +RGFWDEF RGFW_gamepadfunc RGFW_setGamepadCallback(RGFW_gamepadfunc func); -/** @} */ +/** @} */ /** * @defgroup Threads -* @{ */ +* @{ */ #ifndef RGFW_NO_THREADS - /*! threading functions*/ +/*! threading functions*/ - /*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */ - /* - I'd suggest you use sili's threading functions instead - if you're going to use sili - which is a good idea generally - */ +/*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */ +/* + I'd suggest you use sili's threading functions instead + if you're going to use sili + which is a good idea generally +*/ - #if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) - typedef void* (* RGFW_threadFunc_ptr)(void*); - #else - typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); - #endif - - RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ - RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/ - RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */ - RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ +#if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) || defined(RGFW_CUSTOM_BACKEND) + typedef void* (* RGFW_threadFunc_ptr)(void*); +#else + typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); #endif -/** @} */ +RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ +RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/ +RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */ +RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ +#endif + +/** @} */ /** * @defgroup gamepad -* @{ */ +* @{ */ + +typedef RGFW_ENUM(u8, RGFW_gamepadType) { + RGFW_gamepadMicrosoft = 0, RGFW_gamepadSony, RGFW_gamepadNintendo, RGFW_gamepadLogitech, RGFW_gamepadUnknown +}; /*! gamepad count starts at 0*/ -/*!< register gamepad to window based on a number (the number is based on when it was connected eg. /dev/js0)*/ -RGFWDEF u16 RGFW_registerGamepad(RGFW_window* win, i32 gpNumber); -RGFWDEF u16 RGFW_registerGamepadF(RGFW_window* win, char* file); +RGFWDEF u32 RGFW_isPressedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_isReleasedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_isHeldGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_wasPressedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF RGFW_point RGFW_getGamepadAxis(RGFW_window* win, u16 controller, u16 whichAxis); +RGFWDEF const char* RGFW_getGamepadName(RGFW_window* win, u16 controller); +RGFWDEF size_t RGFW_getGamepadCount(RGFW_window* win); +RGFWDEF RGFW_gamepadType RGFW_getGamepadType(RGFW_window* win, u16 controller); -RGFWDEF u32 RGFW_isPressedGP(RGFW_window* win, u16 controller, u8 button); - -/** @} */ +/** @} */ /** * @defgroup graphics_API -* @{ */ +* @{ */ /*!< make the window the current opengl drawing context NOTE: - if you want to switch the graphics context's thread, + if you want to switch the graphics context's thread, you have to run RGFW_window_makeCurrent(NULL); on the old thread then RGFW_window_makeCurrent(valid_window) on the new thread */ @@ -1033,38 +1147,39 @@ RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); /*! native API functions */ #if defined(RGFW_OPENGL) || defined(RGFW_EGL) - /*! OpenGL init hints */ - RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */ - RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */ - RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */ - RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */ +/*! OpenGL init hints */ +RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */ +RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */ +RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */ +RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */ + +/*! which profile to use for the opengl verion */ +typedef RGFW_ENUM(u8, RGFW_glProfile) { RGFW_glCore = 0, RGFW_glCompatibility }; +/*! Set OpenGL version hint (core or compatibility profile)*/ +RGFWDEF void RGFW_setGLVersion(RGFW_glProfile profile, i32 major, i32 minor); +RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); +RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */ +RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */ - /*! which profile to use for the opengl verion */ - typedef RGFW_ENUM(u8, RGFW_GL_profile) { RGFW_GL_CORE = 0, RGFW_GL_COMPATIBILITY }; - /*! Set OpenGL version hint (core or compatibility profile)*/ - RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor); - RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); - RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */ - RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */ #elif defined(RGFW_DIRECTX) - typedef struct { - IDXGIFactory* pFactory; - IDXGIAdapter* pAdapter; - ID3D11Device* pDevice; - ID3D11DeviceContext* pDeviceContext; - } RGFW_directXinfo; +typedef struct { + IDXGIFactory* pFactory; + IDXGIAdapter* pAdapter; + ID3D11Device* pDevice; + ID3D11DeviceContext* pDeviceContext; +} RGFW_directXinfo; - /* - RGFW stores a global instance of RGFW_directXinfo, - you can use this function to get a pointer the instance - */ - RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); +/* + RGFW stores a global instance of RGFW_directXinfo, + you can use this function to get a pointer the instance +*/ +RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); #endif -/** @} */ +/** @} */ /** * @defgroup Supporting -* @{ */ +* @{ */ RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */ RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */ RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */ @@ -1073,10 +1188,10 @@ RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */ key codes and mouse icon enums */ -typedef RGFW_ENUM(u8, RGFW_Key) { - RGFW_KEY_NULL = 0, - RGFW_Escape = '\033', - RGFW_Backtick = '`', +typedef RGFW_ENUM(u8, RGFW_key) { + RGFW_keyNULL = 0, + RGFW_escape = '\033', + RGFW_backtick = '`', RGFW_0 = '0', RGFW_1 = '1', RGFW_2 = '2', @@ -1088,11 +1203,11 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_8 = '8', RGFW_9 = '9', - RGFW_Minus = '-', - RGFW_Equals = '=', - RGFW_BackSpace = '\b', - RGFW_Tab = '\t', - RGFW_Space = ' ', + RGFW_minus = '-', + RGFW_equals = '=', + RGFW_backSpace = '\b', + RGFW_tab = '\t', + RGFW_space = ' ', RGFW_a = 'a', RGFW_b = 'b', @@ -1121,17 +1236,17 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_y = 'y', RGFW_z = 'z', - RGFW_Period = '.', - RGFW_Comma = ',', - RGFW_Slash = '/', - RGFW_Bracket = '{', - RGFW_CloseBracket = '}', - RGFW_Semicolon = ';', - RGFW_Apostrophe = '\'', - RGFW_BackSlash = '\\', - RGFW_Return = '\n', - - RGFW_Delete = '\177', /* 127 */ + RGFW_period = '.', + RGFW_comma = ',', + RGFW_slash = '/', + RGFW_bracket = '{', + RGFW_closeBracket = '}', + RGFW_semicolon = ';', + RGFW_apostrophe = '\'', + RGFW_backSlash = '\\', + RGFW_return = '\n', + + RGFW_delete = '\177', /* 127 */ RGFW_F1, RGFW_F2, @@ -1146,34 +1261,34 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_F11, RGFW_F12, - RGFW_CapsLock, - RGFW_ShiftL, - RGFW_ControlL, - RGFW_AltL, - RGFW_SuperL, - RGFW_ShiftR, - RGFW_ControlR, - RGFW_AltR, - RGFW_SuperR, - RGFW_Up, - RGFW_Down, - RGFW_Left, - RGFW_Right, + RGFW_capsLock, + RGFW_shiftL, + RGFW_controlL, + RGFW_altL, + RGFW_superL, + RGFW_shiftR, + RGFW_controlR, + RGFW_altR, + RGFW_superR, + RGFW_up, + RGFW_down, + RGFW_left, + RGFW_right, - RGFW_Insert, - RGFW_End, - RGFW_Home, - RGFW_PageUp, - RGFW_PageDown, + RGFW_insert, + RGFW_end, + RGFW_home, + RGFW_pageUp, + RGFW_pageDown, - RGFW_Numlock, + RGFW_numLock, RGFW_KP_Slash, - RGFW_Multiply, + RGFW_multiply, RGFW_KP_Minus, - RGFW_KP_1, - RGFW_KP_2, - RGFW_KP_3, - RGFW_KP_4, + RGFW_KP_1, + RGFW_KP_2, + RGFW_KP_3, + RGFW_KP_4, RGFW_KP_5, RGFW_KP_6, RGFW_KP_7, @@ -1182,47 +1297,101 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_KP_0, RGFW_KP_Period, RGFW_KP_Return, - - final_key + RGFW_keyLast }; +RGFWDEF u32 RGFW_apiKeyToRGFW(u32 keycode); typedef RGFW_ENUM(u8, RGFW_mouseIcons) { - RGFW_MOUSE_NORMAL = 0, - RGFW_MOUSE_ARROW, - RGFW_MOUSE_IBEAM, - RGFW_MOUSE_CROSSHAIR, - RGFW_MOUSE_POINTING_HAND, - RGFW_MOUSE_RESIZE_EW, - RGFW_MOUSE_RESIZE_NS, - RGFW_MOUSE_RESIZE_NWSE, - RGFW_MOUSE_RESIZE_NESW, - RGFW_MOUSE_RESIZE_ALL, - RGFW_MOUSE_NOT_ALLOWED, + RGFW_mouseNormal = 0, + RGFW_mouseArrow, + RGFW_mouseIbeam, + RGFW_mouseCrosshair, + RGFW_mousePointingHand, + RGFW_mouseResizeEW, + RGFW_mouseResizeNS, + RGFW_mouseResizeNWSE, + RGFW_mouseResizeNESW, + RGFW_mouseResizeAll, + RGFW_mouseNotAllowed, }; -/** @} */ +/** @} */ #endif /* RGFW_HEADER */ -#ifdef RGFW_X11 - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l +#if defined(RGFW_X11) || defined(RGFW_WAYLAND) + #define RGFW_OS_BASED_VALUE(l, w, m, h) l #elif defined(RGFW_WINDOWS) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w + #define RGFW_OS_BASED_VALUE(l, w, m, h) w #elif defined(RGFW_MACOS) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m + #define RGFW_OS_BASED_VALUE(l, w, m, h) m #elif defined(RGFW_WEBASM) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h -#elif defined(RGFW_WAYLAND) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww + #define RGFW_OS_BASED_VALUE(l, w, m, h) h #endif #ifdef RGFW_IMPLEMENTATION +b8 RGFW_useWaylandBool = 1; +#ifdef RGFW_DEBUG #include -#include -#include -#include +#endif + +#ifndef RGFW_ASSERT + #include + #define RGFW_ASSERT assert +#endif + +/* + RGFW_allocator, (optional) + you can ignore this if you use standard malloc/free +*/ + +void* RGFW_allocatorMalloc(void* userdata, size_t size) { + void* out = RGFW_ALLOC(userdata, size); RGFW_ASSERT(out != NULL); + return out; +} +void RGFW_allocatorFree(void* userdata, void* ptr) { RGFW_ASSERT(ptr != NULL); RGFW_FREE(userdata, ptr); } +RGFW_allocator RGFW_current_allocator = {RGFW_USERPTR, RGFW_allocatorMalloc, RGFW_allocatorFree}; + +RGFW_allocator RGFW_loadAllocator(RGFW_allocator allocator) { + RGFW_allocator old = RGFW_current_allocator; + RGFW_current_allocator = allocator; + return old; +} + +void* RGFW_alloc(size_t len) { return RGFW_current_allocator.alloc(RGFW_current_allocator.userdata, len); } +void RGFW_free(void* ptr) { RGFW_current_allocator.free(RGFW_current_allocator.userdata, ptr); } + + +char* RGFW_clipboard_data = NULL; +RGFW_allocator RGFW_clipboard_alloc; + +void RGFW_clipboard_switch(char* newstr) { + if (RGFW_clipboard_data != NULL) + RGFW_clipboard_alloc.free(RGFW_clipboard_alloc.userdata, RGFW_clipboard_data); + RGFW_clipboard_data = newstr; + RGFW_clipboard_alloc = RGFW_current_allocator; +} + +#define RGFW_CHECK_CLIPBOARD() \ + if (size <= 0 && RGFW_clipboard_data != NULL) \ + return (const char*)RGFW_clipboard_data; \ + else if (size <= 0) \ + return "\0"; + +const char* RGFW_readClipboard(size_t* len) { + RGFW_ssize_t size = RGFW_readClipboardPtr(NULL, 0); + RGFW_CHECK_CLIPBOARD(); + char* str = (char*)RGFW_alloc(size); + size = RGFW_readClipboardPtr(str, size); + RGFW_CHECK_CLIPBOARD(); + + if (len != NULL) *len = size; + + RGFW_clipboard_switch(str); + return (const char*)str; +} /* RGFW_IMPLEMENTATION starts with generic RGFW defines @@ -1230,165 +1399,148 @@ RGFW_IMPLEMENTATION starts with generic RGFW defines This is the start of keycode data Why not use macros instead of the numbers itself? - Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z) + Windows -> Not all scancodes keys are macros Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size MacOS -> windows and linux already don't have keycodes as macros, so there's no point */ -/* - the c++ compiler doesn't support setting up an array like, +/* + the c++ compiler doesn't support setting up an array like, we'll have to do it during runtime using a function & this messy setup */ + +#ifndef RGFW_CUSTOM_BACKEND + #ifndef __cplusplus #define RGFW_NEXT , #define RGFW_MAP -#else +#else #define RGFW_NEXT ; #define RGFW_MAP RGFW_keycodes #endif -#ifdef RGFW_WAYLAND -#include -#endif - -u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 0x15C + 1, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = { +u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 0x15C + 1, 128, DOM_VK_WIN_OEM_CLEAR + 1)] = { #ifdef __cplusplus 0 }; void RGFW_init_keys(void) { #endif - RGFW_MAP [RGFW_OS_BASED_VALUE(49, 0x029, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(49, 0x029, 50, DOM_VK_BACK_QUOTE)] = RGFW_backtick RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x00B, 29, DOM_VK_0, KEY_0)] = RGFW_0 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x002, 18, DOM_VK_1, KEY_1)] = RGFW_1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x003, 19, DOM_VK_2, KEY_2)] = RGFW_2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x004, 20, DOM_VK_3, KEY_3)] = RGFW_3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x005, 21, DOM_VK_4, KEY_4)] = RGFW_4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x006, 23, DOM_VK_5, KEY_5)] = RGFW_5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x007, 22, DOM_VK_6, KEY_6)] = RGFW_6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x008, 26, DOM_VK_7, KEY_7)] = RGFW_7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x009, 28, DOM_VK_8, KEY_8)] = RGFW_8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x00A, 25, DOM_VK_9, KEY_9)] = RGFW_9, - - RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x039, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space, - - RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x01E, 0, DOM_VK_A, KEY_A)] = RGFW_a RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x030, 11, DOM_VK_B, KEY_B)] = RGFW_b RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x02E, 8, DOM_VK_C, KEY_C)] = RGFW_c RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x020, 2, DOM_VK_D, KEY_D)] = RGFW_d RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x012, 14, DOM_VK_E, KEY_E)] = RGFW_e RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x021, 3, DOM_VK_F, KEY_F)] = RGFW_f RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x022, 5, DOM_VK_G, KEY_G)] = RGFW_g RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x023, 4, DOM_VK_H, KEY_H)] = RGFW_h RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x017, 34, DOM_VK_I, KEY_I)] = RGFW_i RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x024, 38, DOM_VK_J, KEY_J)] = RGFW_j RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x025, 40, DOM_VK_K, KEY_K)] = RGFW_k RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x026, 37, DOM_VK_L, KEY_L)] = RGFW_l RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x032, 46, DOM_VK_M, KEY_M)] = RGFW_m RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x031, 45, DOM_VK_N, KEY_N)] = RGFW_n RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x018, 31, DOM_VK_O, KEY_O)] = RGFW_o RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x019, 35, DOM_VK_P, KEY_P)] = RGFW_p RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x010, 12, DOM_VK_Q, KEY_Q)] = RGFW_q RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x013, 15, DOM_VK_R, KEY_R)] = RGFW_r RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x01F, 1, DOM_VK_S, KEY_S)] = RGFW_s RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x014, 17, DOM_VK_T, KEY_T)] = RGFW_t RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x016, 32, DOM_VK_U, KEY_U)] = RGFW_u RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x02F, 9, DOM_VK_V, KEY_V)] = RGFW_v RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x011, 13, DOM_VK_W, KEY_W)] = RGFW_w RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x02D, 7, DOM_VK_X, KEY_X)] = RGFW_x RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x015, 16, DOM_VK_Y, KEY_Y)] = RGFW_y RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x02C, 6, DOM_VK_Z, KEY_Z)] = RGFW_z, - - RGFW_MAP [RGFW_OS_BASED_VALUE(60, 0x034, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(59, 0x033, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(61, 0x035, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(34, 0x01A, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(35, 0x01B, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(47, 0x027, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(48, 0x028, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Apostrophe RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(51, 0x02B, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash, - - RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x01C, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x153, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x145, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x135, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x037, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x04A, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x04F, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x050, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x051, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x04B, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x04C, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x04D, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x047, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x048, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x049, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x052, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x053, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x11C, 77, 0, KEY_KPENTER)] = RGFW_KP_Return, - - RGFW_MAP [RGFW_OS_BASED_VALUE(20, 0x00C, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(21, 0x00D, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(22, 0x00E, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x00F, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(66, 0x03A, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x02A, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x01D, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(64, 0x038, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x15B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL, - + RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x00B, 29, DOM_VK_0)] = RGFW_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x002, 18, DOM_VK_1)] = RGFW_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x003, 19, DOM_VK_2)] = RGFW_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x004, 20, DOM_VK_3)] = RGFW_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x005, 21, DOM_VK_4)] = RGFW_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x006, 23, DOM_VK_5)] = RGFW_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x007, 22, DOM_VK_6)] = RGFW_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x008, 26, DOM_VK_7)] = RGFW_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x009, 28, DOM_VK_8)] = RGFW_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x00A, 25, DOM_VK_9)] = RGFW_9, + RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x039, 49, DOM_VK_SPACE)] = RGFW_space, + RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x01E, 0, DOM_VK_A)] = RGFW_a RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x030, 11, DOM_VK_B)] = RGFW_b RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x02E, 8, DOM_VK_C)] = RGFW_c RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x020, 2, DOM_VK_D)] = RGFW_d RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x012, 14, DOM_VK_E)] = RGFW_e RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x021, 3, DOM_VK_F)] = RGFW_f RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x022, 5, DOM_VK_G)] = RGFW_g RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x023, 4, DOM_VK_H)] = RGFW_h RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x017, 34, DOM_VK_I)] = RGFW_i RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x024, 38, DOM_VK_J)] = RGFW_j RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x025, 40, DOM_VK_K)] = RGFW_k RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x026, 37, DOM_VK_L)] = RGFW_l RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x032, 46, DOM_VK_M)] = RGFW_m RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x031, 45, DOM_VK_N)] = RGFW_n RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x018, 31, DOM_VK_O)] = RGFW_o RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x019, 35, DOM_VK_P)] = RGFW_p RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x010, 12, DOM_VK_Q)] = RGFW_q RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x013, 15, DOM_VK_R)] = RGFW_r RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x01F, 1, DOM_VK_S)] = RGFW_s RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x014, 17, DOM_VK_T)] = RGFW_t RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x016, 32, DOM_VK_U)] = RGFW_u RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x02F, 9, DOM_VK_V)] = RGFW_v RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x011, 13, DOM_VK_W)] = RGFW_w RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x02D, 7, DOM_VK_X)] = RGFW_x RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x015, 16, DOM_VK_Y)] = RGFW_y RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x02C, 6, DOM_VK_Z)] = RGFW_z, + RGFW_MAP [RGFW_OS_BASED_VALUE(60, 0x034, 47, DOM_VK_PERIOD)] = RGFW_period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(59, 0x033, 43, DOM_VK_COMMA)] = RGFW_comma RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(61, 0x035, 44, DOM_VK_SLASH)] = RGFW_slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(34, 0x01A, 33, DOM_VK_OPEN_BRACKET)] = RGFW_bracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(35, 0x01B, 30, DOM_VK_CLOSE_BRACKET)] = RGFW_closeBracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(47, 0x027, 41, DOM_VK_SEMICOLON)] = RGFW_semicolon RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(48, 0x028, 39, DOM_VK_QUOTE)] = RGFW_apostrophe RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(51, 0x02B, 42, DOM_VK_BACK_SLASH)] = RGFW_backSlash, + RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x01C, 36, DOM_VK_RETURN)] = RGFW_return RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x153, 118, DOM_VK_DELETE)] = RGFW_delete RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x145, 72, DOM_VK_NUM_LOCK)] = RGFW_numLock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x135, 82, DOM_VK_DIVIDE)] = RGFW_KP_Slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x037, 76, DOM_VK_MULTIPLY)] = RGFW_multiply RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x04A, 67, DOM_VK_SUBTRACT)] = RGFW_KP_Minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x04F, 84, DOM_VK_NUMPAD1)] = RGFW_KP_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x050, 85, DOM_VK_NUMPAD2)] = RGFW_KP_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x051, 86, DOM_VK_NUMPAD3)] = RGFW_KP_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x04B, 87, DOM_VK_NUMPAD4)] = RGFW_KP_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x04C, 88, DOM_VK_NUMPAD5)] = RGFW_KP_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x04D, 89, DOM_VK_NUMPAD6)] = RGFW_KP_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x047, 90, DOM_VK_NUMPAD7)] = RGFW_KP_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x048, 92, DOM_VK_NUMPAD8)] = RGFW_KP_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x049, 93, DOM_VK_NUMPAD9)] = RGFW_KP_9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x052, 83, DOM_VK_NUMPAD0)] = RGFW_KP_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x053, 65, DOM_VK_DECIMAL)] = RGFW_KP_Period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x11C, 77, 0)] = RGFW_KP_Return, + RGFW_MAP [RGFW_OS_BASED_VALUE(20, 0x00C, 27, DOM_VK_HYPHEN_MINUS)] = RGFW_minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(21, 0x00D, 24, DOM_VK_EQUALS)] = RGFW_equals RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(22, 0x00E, 51, DOM_VK_BACK_SPACE)] = RGFW_backSpace RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x00F, 48, DOM_VK_TAB)] = RGFW_tab RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(66, 0x03A, 57, DOM_VK_CAPS_LOCK)] = RGFW_capsLock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x02A, 56, DOM_VK_SHIFT)] = RGFW_shiftL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x01D, 59, DOM_VK_CONTROL)] = RGFW_controlL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(64, 0x038, 58, DOM_VK_ALT)] = RGFW_altL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x15B, 55, DOM_VK_WIN)] = RGFW_superL, #if !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) - RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11D, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0x15C, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR, - RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x036, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(108, 0x138, 58, 0, KEY_RIGHTALT)] = RGFW_AltR, + RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11D, 59, 0)] = RGFW_controlR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0x15C, 55, 0)] = RGFW_superR, + RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x036, 56, 0)] = RGFW_shiftR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(108, 0x138, 58, 0)] = RGFW_altR, #endif - - RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x03B, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x03C, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x03D, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x03E, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x03F, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x040, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x041, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x042, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x043, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x044, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x057, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x058, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x148, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x150, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x14B, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x14D, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x152, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x14F, 120, DOM_VK_END, KEY_END)] = RGFW_End RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(112, 0x149, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(117, 0x151, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x001, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x147, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x03B, 127, DOM_VK_F1)] = RGFW_F1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x03C, 121, DOM_VK_F2)] = RGFW_F2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x03D, 100, DOM_VK_F3)] = RGFW_F3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x03E, 119, DOM_VK_F4)] = RGFW_F4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x03F, 97, DOM_VK_F5)] = RGFW_F5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x040, 98, DOM_VK_F6)] = RGFW_F6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x041, 99, DOM_VK_F7)] = RGFW_F7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x042, 101, DOM_VK_F8)] = RGFW_F8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x043, 102, DOM_VK_F9)] = RGFW_F9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x044, 110, DOM_VK_F10)] = RGFW_F10 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x057, 104, DOM_VK_F11)] = RGFW_F11 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x058, 112, DOM_VK_F12)] = RGFW_F12 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x148, 126, DOM_VK_UP)] = RGFW_up RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x150, 125, DOM_VK_DOWN)] = RGFW_down RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x14B, 123, DOM_VK_LEFT)] = RGFW_left RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x14D, 124, DOM_VK_RIGHT)] = RGFW_right RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x152, 115, DOM_VK_INSERT)] = RGFW_insert RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x14F, 120, DOM_VK_END)] = RGFW_end RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(112, 0x149, 117, DOM_VK_PAGE_UP)] = RGFW_pageUp RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(117, 0x151, 122, DOM_VK_PAGE_DOWN)] = RGFW_pageDown RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x001, 53, DOM_VK_ESCAPE)] = RGFW_escape RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x147, 116, DOM_VK_HOME)] = RGFW_home RGFW_NEXT #ifndef __cplusplus }; -#else +#else } #endif #undef RGFW_NEXT #undef RGFW_MAP -typedef struct { - b8 current : 1; - b8 prev : 1; -} RGFW_keyState; - -RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; - -RGFWDEF u32 RGFW_apiKeyToRGFW(u32 keycode); - u32 RGFW_apiKeyToRGFW(u32 keycode) { #ifdef __cplusplus - if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) { + if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_backtick) { RGFW_init_keys(); } #endif @@ -1396,14 +1548,22 @@ u32 RGFW_apiKeyToRGFW(u32 keycode) { /* make sure the key isn't out of bounds */ if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) return 0; - + return RGFW_keycodes[keycode]; } +#endif + +typedef struct { + b8 current : 1; + b8 prev : 1; +} RGFW_keyState; + +RGFW_keyState RGFW_keyboard[RGFW_keyLast] = { {0, 0} }; RGFWDEF void RGFW_resetKey(void); void RGFW_resetKey(void) { - size_t len = final_key; /*!< last_key == length */ - + size_t len = RGFW_keyLast; /*!< last_key == length */ + size_t i; /*!< reset each previous state */ for (i = 0; i < len; i++) RGFW_keyboard[i].prev = 0; @@ -1414,19 +1574,22 @@ void RGFW_resetKey(void) { */ /* gamepad data */ -u8 RGFW_gpPressed[4][16]; /*!< if a key is currently pressed or not (per gamepad) */ +RGFW_keyState RGFW_gamepadPressed[4][18]; /*!< if a key is currently pressed or not (per gamepad) */ +RGFW_point RGFW_gamepadAxes[4][4]; /*!< if a key is currently pressed or not (per gamepad) */ -i32 RGFW_gamepads[4]; /*!< limit of 4 gamepads at a time */ -u16 RGFW_gamepadCount; /*!< the actual amount of gamepads */ +RGFW_gamepadType RGFW_gamepads_type[4]; /*!< if a key is currently pressed or not (per gamepad) */ +i32 RGFW_gamepads[4] = {0, 0, 0, 0}; /*!< limit of 4 gamepads at a time */ +char RGFW_gamepads_name[4][128]; /*!< gamepad names */ +u16 RGFW_gamepadCount = 0; /*!< the actual amount of gamepads */ -/* +/* event callback defines start here */ /* - These exist to avoid the - if (func == NULL) check + These exist to avoid the + if (func == NULL) check for (allegedly) better performance */ void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } @@ -1437,10 +1600,11 @@ void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {R void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); } -void RGFW_keyfuncEMPTY(RGFW_window* win, u32 key, u32 mappedKey, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(key); RGFW_UNUSED(mappedKey); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);} -void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} -void RGFW_gpButtonfuncEMPTY(RGFW_window* win, u16 gamepad, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } -void RGFW_gpAxisfuncEMPTY(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); } +void RGFW_keyfuncEMPTY(RGFW_window* win, RGFW_key key, char keyChar, RGFW_keymod keyMod, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(key); RGFW_UNUSED(keyChar); RGFW_UNUSED(keyMod); RGFW_UNUSED(pressed);} +void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, RGFW_mouseButton button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} +void RGFW_gamepadButtonfuncEMPTY(RGFW_window* win, u16 gamepad, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } +void RGFW_gamepadAxisfuncEMPTY(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount, u8 whichAxis){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); RGFW_UNUSED(whichAxis); } +void RGFW_gamepadfuncEMPTY(RGFW_window* win, u16 gamepad, b8 connected) {RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(connected);} #ifdef RGFW_ALLOC_DROPFILES void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} @@ -1459,22 +1623,23 @@ RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY; RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY; RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY; RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY; -RGFW_gpButtonfunc RGFW_gpButtonCallback = RGFW_gpButtonfuncEMPTY; -RGFW_gpAxisfunc RGFW_gpAxisCallback = RGFW_gpAxisfuncEMPTY; +RGFW_gamepadButtonfunc RGFW_gamepadButtonCallback = RGFW_gamepadButtonfuncEMPTY; +RGFW_gamepadAxisfunc RGFW_gamepadAxisCallback = RGFW_gamepadAxisfuncEMPTY; +RGFW_gamepadfunc RGFW_gamepadCallback = RGFW_gamepadfuncEMPTY; -void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { +void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { RGFW_window_eventWait(win, waitMS); - while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { - if (win->event.type == RGFW_quit) return; + while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { + if (win->event.type == RGFW_quit) return; } - + #ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */ RGFW_sleep(0); #endif } -RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { +RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowmovefunc prev = (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback; RGFW_windowMoveCallback = func; return prev; @@ -1531,143 +1696,168 @@ RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; return prev; } -RGFW_gpButtonfunc RGFW_setgpButtonCallback(RGFW_gpButtonfunc func) { - RGFW_gpButtonfunc prev = (RGFW_gpButtonCallback == RGFW_gpButtonfuncEMPTY) ? NULL : RGFW_gpButtonCallback; - RGFW_gpButtonCallback = func; +RGFW_gamepadButtonfunc RGFW_setgamepadButtonCallback(RGFW_gamepadButtonfunc func) { + RGFW_gamepadButtonfunc prev = (RGFW_gamepadButtonCallback == RGFW_gamepadButtonfuncEMPTY) ? NULL : RGFW_gamepadButtonCallback; + RGFW_gamepadButtonCallback = func; return prev; } -RGFW_gpAxisfunc RGFW_setgpAxisCallback(RGFW_gpAxisfunc func) { - RGFW_gpAxisfunc prev = (RGFW_gpAxisCallback == RGFW_gpAxisfuncEMPTY) ? NULL : RGFW_gpAxisCallback; - RGFW_gpAxisCallback = func; +RGFW_gamepadAxisfunc RGFW_setgamepadAxisCallback(RGFW_gamepadAxisfunc func) { + RGFW_gamepadAxisfunc prev = (RGFW_gamepadAxisCallback == RGFW_gamepadAxisfuncEMPTY) ? NULL : RGFW_gamepadAxisCallback; + RGFW_gamepadAxisCallback = func; return prev; } -/* +RGFW_gamepadfunc RGFW_setGamepadCallback(RGFW_gamepadfunc func) { + RGFW_gamepadfunc prev = (RGFW_gamepadCallback == RGFW_gamepadfuncEMPTY) ? NULL : RGFW_gamepadCallback; + RGFW_gamepadCallback = func; + return prev; +} +/* no more event call back defines */ -#define RGFW_ASSERT(check, str) {\ - if (!(check)) { \ - printf(str); \ - assert(check); \ - } \ -} - -b8 RGFW_error = 0; -b8 RGFW_Error(void) { return RGFW_error; } - #define SET_ATTRIB(a, v) { \ - assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ + RGFW_ASSERT(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ attribs[index++] = v; \ } - + +#define RGFW_NO_GPU_RENDER RGFW_BIT(20) /* don't render (using the GPU based API)*/ +#define RGFW_NO_CPU_RENDER RGFW_BIT(21) /* don't render (using the CPU based buffer rendering)*/ +#define RGFW_HOLD_MOUSE RGFW_BIT(22) /*!< hold the moues still */ +#define RGFW_MOUSE_LEFT RGFW_BIT(23) /* if mouse left the window */ +#define RGFW_WINDOW_ALLOC RGFW_BIT(24) /* if window was allocated by RGFW */ +#define RGFW_BUFFER_ALLOC RGFW_BIT(25) /* if window.buffer was allocated by RGFW */ + RGFW_area RGFW_bufferSize = {0, 0}; void RGFW_setBufferSize(RGFW_area size) { RGFW_bufferSize = size; } +RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, RGFW_windowFlags flags) { + RGFW_window* win = (RGFW_window*)RGFW_alloc(sizeof(RGFW_window)); + win->_flags |= RGFW_WINDOW_ALLOC; + return RGFW_createWindowPtr(name, rect, flags, win); +} -RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); +#if defined(RGFW_USE_XDL) && defined(RGFW_X11) + #define XDL_IMPLEMENTATION + #include "XDL.h" +#endif + +RGFWDEF void RGFW_window_basic_init(RGFW_window* win, RGFW_rect rect, RGFW_windowFlags flags); + +#if defined(RGFW_X11) || defined(RGFW_WINDOWS) +RGFW_mouse* RGFW_hiddenMouse = NULL; +#endif + +RGFW_window* RGFW_root = NULL; /* do a basic initialization for RGFW_window, this is to standard it for each OS */ -RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { - RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */ - +void RGFW_window_basic_init(RGFW_window* win, RGFW_rect rect, RGFW_windowFlags flags) { /* clear out dnd info */ #ifdef RGFW_ALLOC_DROPFILES - win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); + win->event.droppedFiles = (char**) RGFW_alloc(sizeof(char*) * RGFW_MAX_DROPS); u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); + for (i = 0; i < RGFW_MAX_DROPS; i++) { + win->event.droppedFiles[i] = (char*) RGFW_alloc(RGFW_MAX_PATH); + win->event.droppedFiles[i][0] = 0; + } #endif /* X11 requires us to have a display to get the screen size */ - #ifndef RGFW_X11 + #ifndef RGFW_X11 RGFW_area screenR = RGFW_getScreenSize(); #else win->src.display = XOpenDisplay(NULL); - assert(win->src.display != NULL); + RGFW_ASSERT(win->src.display != NULL); - Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display); + Screen* scrn = DefaultScreenOfDisplay(win->src.display); RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height); #endif - - /* rect based the requested args */ - if (args & RGFW_FULLSCREEN) + + /* rect based the requested flags */ + if (flags & RGFW_windowFullscreen) rect = RGFW_RECT(0, 0, screenR.w, screenR.h); + if (RGFW_root == NULL) { + RGFW_root = win; + } + + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + if (RGFW_hiddenMouse == NULL) { + u8 RGFW_blk[] = { 0, 0, 0, 0 }; + RGFW_hiddenMouse = RGFW_loadMouse(RGFW_blk, RGFW_AREA(1, 1), 4); + } + #endif + /* set and init the new window's data */ win->r = rect; win->event.inFocus = 1; win->event.droppedFilesCount = 0; - RGFW_gamepadCount = 0; - win->_winArgs = 0; - win->event.lockState = 0; - - return win; + win->_flags = 0; + win->event.keyMod = 0; + win->_mem.free = RGFW_current_allocator.free; } -#ifndef RGFW_NO_MONITOR -void RGFW_window_scaleToMonitor(RGFW_window* win) { - RGFW_monitor monitor = RGFW_window_getMonitor(win); - - RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleY * (float)win->r.h))); +void RGFW_window_setBufferPtr(RGFW_window* win, u8* ptr, RGFW_area size) { + RGFW_ASSERT(win); RGFW_ASSERT(ptr); + + #ifdef RGFW_BUFFER + if (win->buffer != NULL && ((win->_flags & RGFW_BUFFER_ALLOC))) { + win->_mem.free(win->_mem.userdata, win->buffer); + win->_flags ^= RGFW_BUFFER_ALLOC; + } + + RGFW_bufferSize = size; + win->buffer = ptr; + #else + RGFW_UNUSED(size); + #endif } -#endif - -RGFW_window* RGFW_root = NULL; - - -#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ -#define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */ #ifdef RGFW_MACOS RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer); RGFWDEF void* RGFW_cocoaGetLayer(void); #endif -char* RGFW_className = NULL; -void RGFW_setClassName(char* name) { +const char* RGFW_className = NULL; +void RGFW_setClassName(const char* name) { RGFW_className = name; } -void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } - RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; -b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus; +b8 RGFW_isMousePressed(RGFW_window* win, RGFW_mouseButton button) { + return RGFW_mouseButtons[button].current && (win == NULL || win->event.inFocus); } -b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus; +b8 RGFW_wasMousePressed(RGFW_window* win, RGFW_mouseButton button) { + return RGFW_mouseButtons[button].prev && (win != NULL || win->event.inFocus); } -b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { +b8 RGFW_isMouseHeld(RGFW_window* win, RGFW_mouseButton button) { return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); } -b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { - return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); +b8 RGFW_isMouseReleased(RGFW_window* win, RGFW_mouseButton button) { + return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); } -b8 RGFW_isPressed(RGFW_window* win, u8 key) { +b8 RGFW_isPressed(RGFW_window* win, RGFW_key key) { return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus); } -b8 RGFW_wasPressed(RGFW_window* win, u8 key) { +b8 RGFW_wasPressed(RGFW_window* win, RGFW_key key) { return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus); } -b8 RGFW_isHeld(RGFW_window* win, u8 key) { +b8 RGFW_isHeld(RGFW_window* win, RGFW_key key) { return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); } -b8 RGFW_isClicked(RGFW_window* win, u8 key) { +b8 RGFW_isClicked(RGFW_window* win, RGFW_key key) { return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key)); } -b8 RGFW_isReleased(RGFW_window* win, u8 key) { - return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); +b8 RGFW_isReleased(RGFW_window* win, RGFW_key key) { + return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); } #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) /* defines for directX context*/ @@ -1675,6 +1865,7 @@ b8 RGFW_isReleased(RGFW_window* win, u8 key) { RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; } #endif +#ifndef RGFW_CUSTOM_BACKEND void RGFW_window_makeCurrent(RGFW_window* win) { #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) if (win == NULL) @@ -1684,28 +1875,29 @@ void RGFW_window_makeCurrent(RGFW_window* win) { #elif defined(RGFW_OPENGL) RGFW_window_makeCurrent_OpenGL(win); #else - RGFW_UNUSED(win) + RGFW_UNUSED(win); #endif } +#endif void RGFW_window_setGPURender(RGFW_window* win, i8 set) { - if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER)) - win->_winArgs |= RGFW_NO_GPU_RENDER; - - else if (set && win->_winArgs & RGFW_NO_GPU_RENDER) - win->_winArgs ^= RGFW_NO_GPU_RENDER; + if (!set && !(win->_flags & RGFW_NO_GPU_RENDER)) + win->_flags |= RGFW_NO_GPU_RENDER; + + else if (set && win->_flags & RGFW_NO_GPU_RENDER) + win->_flags ^= RGFW_NO_GPU_RENDER; } void RGFW_window_setCPURender(RGFW_window* win, i8 set) { - if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER)) - win->_winArgs |= RGFW_NO_CPU_RENDER; + if (!set && !(win->_flags & RGFW_NO_CPU_RENDER)) + win->_flags |= RGFW_NO_CPU_RENDER; - else if (set && win->_winArgs & RGFW_NO_CPU_RENDER) - win->_winArgs ^= RGFW_NO_CPU_RENDER; + else if (set && win->_flags & RGFW_NO_CPU_RENDER) + win->_flags ^= RGFW_NO_CPU_RENDER; } void RGFW_window_maximize(RGFW_window* win) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); RGFW_area screen = RGFW_getScreenSize(); @@ -1714,37 +1906,43 @@ void RGFW_window_maximize(RGFW_window* win) { } b8 RGFW_window_shouldClose(RGFW_window* win) { - assert(win != NULL); - return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)); + RGFW_ASSERT(win != NULL); + return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_escape)); } void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); } #ifndef RGFW_NO_MONITOR - void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { - RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y)); - } +void RGFW_window_scaleToMonitor(RGFW_window* win) { + RGFW_monitor monitor = RGFW_window_getMonitor(win); + + RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleY * (float)win->r.h))); +} + +void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { + RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y)); +} #endif RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect); RGFWDEF void RGFW_releaseCursor(RGFW_window* win); void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { - if ((win->_winArgs & RGFW_HOLD_MOUSE)) + if ((win->_flags & RGFW_HOLD_MOUSE)) return; - + if (!area.w && !area.h) area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - - win->_winArgs |= RGFW_HOLD_MOUSE; + + win->_flags |= RGFW_HOLD_MOUSE; RGFW_captureCursor(win, win->r); RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); } void RGFW_window_mouseUnhold(RGFW_window* win) { - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - win->_winArgs ^= RGFW_HOLD_MOUSE; + if ((win->_flags & RGFW_HOLD_MOUSE)) { + win->_flags ^= RGFW_HOLD_MOUSE; RGFW_releaseCursor(win); } @@ -1754,7 +1952,7 @@ u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) { u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; u32 output_fps = 0; - u64 fps = round(1e+9 / deltaTime); + u64 fps = RGFW_ROUND(1e+9 / deltaTime); output_fps= fps; if (fpsCap && fps > fpsCap) { @@ -1768,132 +1966,179 @@ u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) { } win->event.frameTime = RGFW_getTimeNS(); - - if (fpsCap == 0) + + if (fpsCap == 0) return (u32) output_fps; - + deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - output_fps = round(1e+9 / deltaTime); + output_fps = RGFW_ROUND(1e+9 / deltaTime); win->event.frameTime2 = RGFW_getTimeNS(); return output_fps; } -u32 RGFW_isPressedGP(RGFW_window* win, u16 c, u8 button) { +u32 RGFW_isPressedGamepad(RGFW_window* win, u8 c, RGFW_gamepadCodes button) { RGFW_UNUSED(win); - return RGFW_gpPressed[c][button]; + return RGFW_gamepadPressed[c][button].current; +} +u32 RGFW_wasPressedGamepad(RGFW_window* win, u8 c, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return RGFW_gamepadPressed[c][button].prev; +} +u32 RGFW_isReleasedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return !RGFW_isPressedGamepad(win, controller, button) && RGFW_wasPressedGamepad(win, controller, button); +} +u32 RGFW_isHeldGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return RGFW_isPressedGamepad(win, controller, button) && RGFW_wasPressedGamepad(win, controller, button); +} + +RGFW_point RGFW_getGamepadAxis(RGFW_window* win, u16 controller, u16 whichAxis) { + RGFW_UNUSED(win); + return RGFW_gamepadAxes[controller][whichAxis]; +} +const char* RGFW_getGamepadName(RGFW_window* win, u16 controller) { + RGFW_UNUSED(win); + return (const char*)RGFW_gamepads_name[controller]; +} + +size_t RGFW_getGamepadCount(RGFW_window* win) { + RGFW_UNUSED(win); + return RGFW_gamepadCount; +} + +RGFW_gamepadType RGFW_getGamepadType(RGFW_window* win, u16 controller) { + RGFW_UNUSED(win); + return RGFW_gamepads_type[controller]; } #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - static u8 RGFW_blk[] = { 0, 0, 0, 0 }; - if (show == 0) - RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4); - else - RGFW_window_setMouseDefault(win); - } +void RGFW_window_showMouse(RGFW_window* win, i8 show) { + if (show == 0) + RGFW_window_setMouse(win, RGFW_hiddenMouse); + else + RGFW_window_setMouseDefault(win); +} #endif -RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock); -void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { - if (capital && !(win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState |= RGFW_CAPSLOCK; - else if (!capital && (win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState ^= RGFW_CAPSLOCK; - - if (numlock && !(win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState |= RGFW_NUMLOCK; - else if (!numlock && (win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState ^= RGFW_NUMLOCK; +RGFWDEF void RGFW_updateKeyMod(RGFW_window* win, RGFW_keymod mod, b8 value); +void RGFW_updateKeyMod(RGFW_window* win, RGFW_keymod mod, b8 value) { + if (value && !(win->event.keyMod & mod)) + win->event.keyMod |= mod; + else if (!value && ((win->event.keyMod & mod))) + win->event.keyMod ^= mod; +} + +RGFWDEF void RGFW_updateKeyModsPro(RGFW_window* win, b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super); +void RGFW_updateKeyModsPro(RGFW_window* win, b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super) { + RGFW_updateKeyMod(win, RGFW_modCapsLock, capital); + RGFW_updateKeyMod(win, RGFW_modNumLock, numlock); + RGFW_updateKeyMod(win, RGFW_modControl, control); + RGFW_updateKeyMod(win, RGFW_modAlt, alt); + RGFW_updateKeyMod(win, RGFW_modShift, shift); + RGFW_updateKeyMod(win, RGFW_modSuper, super); +} + +RGFWDEF void RGFW_updateKeyMods(RGFW_window* win, b8 capital, b8 numlock); +void RGFW_updateKeyMods(RGFW_window* win, b8 capital, b8 numlock) { + RGFW_updateKeyModsPro(win, capital, numlock, + RGFW_isPressed(win, RGFW_controlL) || RGFW_isPressed(win, RGFW_controlR), + RGFW_isPressed(win, RGFW_altL) || RGFW_isPressed(win, RGFW_altR), + RGFW_isPressed(win, RGFW_shiftL) || RGFW_isPressed(win, RGFW_shiftR), + RGFW_isPressed(win, RGFW_superL) || RGFW_isPressed(win, RGFW_superR)); } #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) - struct timespec; +#include +struct timespec; - int nanosleep(const struct timespec* duration, struct timespec* rem); - int clock_gettime(clockid_t clk_id, struct timespec* tp); - int setenv(const char *name, const char *value, int overwrite); +#ifndef RGFW_NO_UNIX_CLOCK +int nanosleep(const struct timespec* duration, struct timespec* rem); +int clock_gettime(clockid_t clk_id, struct timespec* tp); +#endif - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - if (allow && !(win->_winArgs & RGFW_ALLOW_DND)) - win->_winArgs |= RGFW_ALLOW_DND; +int setenv(const char *name, const char *value, int overwrite); - else if (!allow && (win->_winArgs & RGFW_ALLOW_DND)) - win->_winArgs ^= RGFW_ALLOW_DND; - } +void RGFW_window_setDND(RGFW_window* win, b8 allow) { + if (allow && !(win->_flags & RGFW_windowAllowDND)) + win->_flags |= RGFW_windowAllowDND; + + else if (!allow && (win->_flags & RGFW_windowAllowDND)) + win->_flags ^= RGFW_windowAllowDND; +} #endif /* graphics API specific code (end of generic code) - starts here + starts here */ -/* +/* OpenGL defines start here (Normal, EGL, OSMesa) */ -#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) - #ifdef RGFW_WINDOWS - #define WIN32_LEAN_AND_MEAN - #define OEMRESOURCE - #include - #endif +#if defined(RGFW_OPENGL) || defined(RGFW_EGL) - #if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER) - #include - #elif defined(__APPLE__) - #ifndef GL_SILENCE_DEPRECATION - #define GL_SILENCE_DEPRECATION - #endif - #include - #include +#ifdef RGFW_WINDOWS + #define WIN32_LEAN_AND_MEAN + #define OEMRESOURCE + #include +#endif + +#if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER) + #include +#elif defined(__APPLE__) + #ifndef GL_SILENCE_DEPRECATION + #define GL_SILENCE_DEPRECATION #endif + #include + #include +#endif /* EGL, normal OpenGL only */ -#if !defined(RGFW_OSMESA) - i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; - b8 RGFW_profile = RGFW_GL_CORE; - - #ifndef RGFW_EGL - i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; - #else - i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; - #endif +i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; +b8 RGFW_profile = RGFW_glCore; +#ifndef RGFW_EGL +i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; +#else +i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; +#endif - void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; } - void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; } - void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; } - void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; } - void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; } +void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; } +void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; } +void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; } +void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; } +void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; } - void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) { - RGFW_profile = profile; - RGFW_majorVersion = major; - RGFW_minorVersion = minor; - } +void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) { + RGFW_profile = profile; + RGFW_majorVersion = major; + RGFW_minorVersion = minor; +} /* OPENGL normal only (no EGL / OSMesa) */ -#ifndef RGFW_EGL +#if !defined(RGFW_EGL) && !defined(RGFW_CUSTOM_BACKEND) -#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0, 0) - #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0, 0) - #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0, 0) - #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0, 0) - #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0, 0) - #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0, 0) - #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0, 0) - #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0, 0) +#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0) + #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0) + #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0) + #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0) + #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0) + #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0) + #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0) + #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0) #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0, 0) - #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0, 0) - #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0, 0) - #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0, 0) - #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0, 0) - #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0, 0) - #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0, 0) + #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0) + #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0) + #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0) + #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0) + #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0) + #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0) + #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0) #endif #ifdef RGFW_WINDOWS @@ -1912,47 +2157,47 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #define WGL_TRANSPARENT_ARB 0x200A #endif - -/* The window'ing api needs to know how to render the data we (or opengl) give it - MacOS and Windows do this using a structure called a "pixel format" + +/* The window'ing api needs to know how to render the data we (or opengl) give it + MacOS and Windows do this using a structure called a "pixel format" X11 calls it a "Visual" This function returns the attributes for the format we want */ - u32* RGFW_initFormatAttribs(u32 useSoftware) { - RGFW_UNUSED(useSoftware); - static u32 attribs[] = { - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - RGFW_GL_RENDER_TYPE, - RGFW_GL_FULL_FORMAT, - #endif - RGFW_GL_ALPHA_SIZE , 8, - RGFW_GL_DEPTH_SIZE , 24, - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - RGFW_GL_DRAW, 1, - RGFW_GL_RED_SIZE , 8, - RGFW_GL_GREEN_SIZE , 8, - RGFW_GL_BLUE_SIZE , 8, - RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA, - #endif +u32* RGFW_initFormatAttribs(u32 useSoftware) { + RGFW_UNUSED(useSoftware); + static u32 attribs[] = { + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + RGFW_GL_RENDER_TYPE, + RGFW_GL_FULL_FORMAT, + #endif + RGFW_GL_ALPHA_SIZE , 8, + RGFW_GL_DEPTH_SIZE , 24, + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + RGFW_GL_DRAW, 1, + RGFW_GL_RED_SIZE , 8, + RGFW_GL_GREEN_SIZE , 8, + RGFW_GL_BLUE_SIZE , 8, + RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA, + #endif - #ifdef RGFW_X11 - GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, - #endif + #ifdef RGFW_X11 + GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, + #endif - #ifdef RGFW_MACOS - 72, - 8, 24, - #endif + #ifdef RGFW_MACOS + 72, + 8, 24, + #endif - #ifdef RGFW_WINDOWS - WGL_SUPPORT_OPENGL_ARB, 1, - WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, - WGL_COLOR_BITS_ARB, 32, - #endif + #ifdef RGFW_WINDOWS + WGL_SUPPORT_OPENGL_ARB, 1, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_COLOR_BITS_ARB, 32, + #endif - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; - size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13; + size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13; #define RGFW_GL_ADD_ATTRIB(attrib, attVal) \ if (attVal) { \ @@ -1960,27 +2205,27 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { attribs[index + 1] = attVal;\ index += 2;\ } - + RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1); - + RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL); RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO); RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS); -#ifndef RGFW_X11 + #ifndef RGFW_X11 RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES); -#endif + #endif -#ifdef RGFW_MACOS + #ifdef RGFW_MACOS if (useSoftware) { RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID); } else { attribs[index] = RGFW_GL_RENDER_TYPE; index += 1; } -#endif + #endif -#ifdef RGFW_MACOS + #ifdef RGFW_MACOS /* macOS has the surface attribs and the opengl attribs connected for some reason maybe this is to give macOS more control to limit openGL/the opengl version? */ @@ -1990,12 +2235,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) { attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200); } -#endif + #endif - RGFW_GL_ADD_ATTRIB(0, 0); + RGFW_GL_ADD_ATTRIB(0, 0); - return attribs; - } + return attribs; +} /* EGL only (no OSMesa nor normal OPENGL) */ #elif defined(RGFW_EGL) @@ -2007,7 +2252,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { PFNEGLINITIALIZEPROC eglInitializeSource; PFNEGLGETCONFIGSPROC eglGetConfigsSource; - PFNEGLCHOOSECONFIGPROC eglChooseConfigSource; + PFNEGLCHOOSECONFIgamepadROC eglChooseConfigSource; PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource; PFNEGLCREATECONTEXTPROC eglCreateContextSource; PFNEGLMAKECURRENTPROC eglMakeCurrentSource; @@ -2019,19 +2264,19 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { PFNEGLTERMINATEPROC eglTerminateSource; PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource; -#define eglInitialize eglInitializeSource -#define eglGetConfigs eglGetConfigsSource -#define eglChooseConfig eglChooseConfigSource -#define eglCreateWindowSurface eglCreateWindowSurfaceSource -#define eglCreateContext eglCreateContextSource -#define eglMakeCurrent eglMakeCurrentSource -#define eglGetDisplay eglGetDisplaySource -#define eglSwapBuffers eglSwapBuffersSource -#define eglSwapInterval eglSwapIntervalSource -#define eglBindAPI eglBindAPISource -#define eglDestroyContext eglDestroyContextSource -#define eglTerminate eglTerminateSource -#define eglDestroySurface eglDestroySurfaceSource; + #define eglInitialize eglInitializeSource + #define eglGetConfigs eglGetConfigsSource + #define eglChooseConfig eglChooseConfigSource + #define eglCreateWindowSurface eglCreateWindowSurfaceSource + #define eglCreateContext eglCreateContextSource + #define eglMakeCurrent eglMakeCurrentSource + #define eglGetDisplay eglGetDisplaySource + #define eglSwapBuffers eglSwapBuffersSource + #define eglSwapInterval eglSwapIntervalSource + #define eglBindAPI eglBindAPISource + #define eglDestroyContext eglDestroyContextSource + #define eglTerminate eglTerminateSource + #define eglDestroySurface eglDestroySurfaceSource; #endif @@ -2048,180 +2293,169 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif - void RGFW_createOpenGLContext(RGFW_window* win) { +void RGFW_createOpenGLContext(RGFW_window* win) { #if defined(RGFW_LINK_EGL) - eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize"); - eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs"); - eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig"); - eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface"); - eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext"); - eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent"); - eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay"); - eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers"); - eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval"); - eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI"); - eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext"); - eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate"); - eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface"); + eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize"); + eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs"); + eglChooseConfigSource = (PFNEGLCHOOSECONFIgamepadROC) eglGetProcAddress("eglChooseConfig"); + eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface"); + eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext"); + eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent"); + eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay"); + eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers"); + eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval"); + eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI"); + eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext"); + eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate"); + eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface"); #endif /* RGFW_LINK_EGL */ - #ifdef RGFW_WINDOWS - win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); - #elif defined(RGFW_MACOS) - win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0); - #else + #ifdef RGFW_WINDOWS + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); + #elif defined(RGFW_MACOS) + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0); + #elif defined(RGFW_WAYLAND) + if (RGFW_useWaylandBool) + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.wl_display); + else win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); - #endif - - EGLint major, minor; - - eglInitialize(win->src.EGL_display, &major, &minor); - - #ifndef EGL_OPENGL_ES1_BIT - #define EGL_OPENGL_ES1_BIT 0x1 - #endif - - EGLint egl_config[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, - #ifdef RGFW_OPENGL_ES1 - EGL_OPENGL_ES1_BIT, - #elif defined(RGFW_OPENGL_ES3) - EGL_OPENGL_ES3_BIT, - #elif defined(RGFW_OPENGL_ES2) - EGL_OPENGL_ES2_BIT, - #else - EGL_OPENGL_BIT, - #endif - EGL_NONE, EGL_NONE - }; - - EGLConfig config; - EGLint numConfigs; - eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); - - #if defined(RGFW_MACOS) - void* layer = RGFW_cocoaGetLayer(); - - RGFW_window_cocoaSetLayer(win, layer); - - win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL); - #else - win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); - #endif - - EGLint attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, - #ifdef RGFW_OPENGL_ES1 - 1, - #else - 2, - #endif - EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE - }; - - size_t index = 4; - RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL); - RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES); - - if (RGFW_DOUBLE_BUFFER) - RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER); - - if (RGFW_majorVersion) { - attribs[1] = RGFW_majorVersion; - - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion); - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion); - - if (RGFW_profile == RGFW_GL_CORE) { - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT); - } - else { - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); - } - - } - - #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3) - eglBindAPI(EGL_OPENGL_ES_API); - #else - eglBindAPI(EGL_OPENGL_API); - #endif - - win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); - - if (win->src.EGL_context == NULL) - fprintf(stderr, "failed to create an EGL opengl context\n"); - - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - } - - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); - } - - #ifdef RGFW_APPLE - void* RGFWnsglFramework = NULL; - #elif defined(RGFW_WINDOWS) - static HMODULE wglinstance = NULL; + #else + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); #endif - void* RGFW_getProcAddress(const char* procname) { - #if defined(RGFW_WINDOWS) - void* proc = (void*) GetProcAddress(wglinstance, procname); + EGLint major, minor; - if (proc) - return proc; + eglInitialize(win->src.EGL_display, &major, &minor); + + #ifndef EGL_OPENGL_ES1_BIT + #define EGL_OPENGL_ES1_BIT 0x1 + #endif + + EGLint egl_config[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + #ifdef RGFW_OPENGL_ES1 + EGL_OPENGL_ES1_BIT, + #elif defined(RGFW_OPENGL_ES3) + EGL_OPENGL_ES3_BIT, + #elif defined(RGFW_OPENGL_ES2) + EGL_OPENGL_ES2_BIT, + #else + EGL_OPENGL_BIT, #endif + EGL_NONE, EGL_NONE + }; - return (void*) eglGetProcAddress(procname); - } + EGLConfig config; + EGLint numConfigs; + eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); - void RGFW_closeEGL(RGFW_window* win) { - eglDestroySurface(win->src.EGL_display, win->src.EGL_surface); - eglDestroyContext(win->src.EGL_display, win->src.EGL_context); + #if defined(RGFW_MACOS) + void* layer = RGFW_cocoaGetLayer(); - eglTerminate(win->src.EGL_display); - } - - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - eglSwapInterval(win->src.EGL_display, swapInterval); + RGFW_window_cocoaSetLayer(win, layer); + + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL); + #elif defined(RGFW_WINDOWS) + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.hwnd, NULL); + #elif defined(RGFW_WAYLAND) + if (RGFW_useWaylandBool) + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.eglWindow, NULL); + else + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #else + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #endif + + EGLint attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, + #ifdef RGFW_OPENGL_ES1 + 1, + #else + 2, + #endif + EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE + }; + + size_t index = 4; + RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL); + RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES); + + if (RGFW_DOUBLE_BUFFER) + RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER); + + if (RGFW_majorVersion) { + attribs[1] = RGFW_majorVersion; + + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion); + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion); + + if (RGFW_profile == RGFW_glCore) { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT); + } + else { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); + } } + + #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3) + eglBindAPI(EGL_OPENGL_ES_API); + #else + eglBindAPI(EGL_OPENGL_API); + #endif + + win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); + + if (win->src.EGL_context == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "failed to create an EGL opengl context\n"); + #endif + } + eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); +} + +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); +} + +#ifdef RGFW_APPLE +void* RGFWnsglFramework = NULL; +#elif defined(RGFW_WINDOWS) +static HMODULE RGFW_wgl_dll = NULL; +#endif + +void* RGFW_getProcAddress(const char* procname) { + #if defined(RGFW_WINDOWS) + void* proc = (void*) GetProcAddress(RGFW_wgl_dll, procname); + + if (proc) + return proc; + #endif + + return (void*) eglGetProcAddress(procname); +} + +void RGFW_closeEGL(RGFW_window* win) { + eglDestroySurface(win->src.EGL_display, win->src.EGL_surface); + eglDestroyContext(win->src.EGL_display, win->src.EGL_context); + + eglTerminate(win->src.EGL_display); +} + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + eglSwapInterval(win->src.EGL_display, swapInterval); + +} + #endif /* RGFW_EGL */ -/* +/* end of RGFW_EGL defines */ - -/* OPENGL Normal / EGL defines only (no OS MESA) Ends here */ - -#elif defined(RGFW_OSMESA) /* OSmesa only */ -RGFWDEF void RGFW_OSMesa_reorganize(void); - -/* reorganize buffer for osmesa */ -void RGFW_OSMesa_reorganize(void) { - u8* row = (u8*) RGFW_MALLOC(win->r.w * 3); - - i32 half_height = win->r.h / 2; - i32 stride = win->r.w * 3; - - i32 y; - for (y = 0; y < half_height; ++y) { - i32 top_offset = y * stride; - i32 bottom_offset = (win->r.h - y - 1) * stride; - memcpy(row, win->buffer + top_offset, stride); - memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride); - memcpy(win->buffer + bottom_offset, row, stride); - } - - RGFW_FREE(row); -} -#endif /* RGFW_OSMesa */ - #endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/ /* @@ -2229,22 +2463,88 @@ This is where OS specific stuff starts */ -#if defined(RGFW_WAYLAND) || defined(RGFW_X11) +#if (defined(RGFW_WAYLAND) || defined(RGFW_X11)) && !defined(RGFW_NO_LINUX) int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */ - - - #ifdef __linux__ + #if defined(__linux__) #include #include #include + #include - RGFW_Event* RGFW_linux_updateGamepad(RGFW_window* win) { + u32 RGFW_linux_updateGamepad(RGFW_window* win) { + /* check for new gamepads */ + static const char* str[] = {"/dev/input/js0", "/dev/input/js1", "/dev/input/js2", "/dev/input/js3", "/dev/input/js4", "/dev/input/js5"}; + static u8 RGFW_rawGamepads[6]; + + for (size_t i = 0; i < 6; i++) { + size_t index = RGFW_gamepadCount; + if (RGFW_rawGamepads[i]) { + struct input_id device_info; + if (ioctl(RGFW_rawGamepads[i], EVIOCGID, &device_info) == -1) { + if (errno == ENODEV) { + RGFW_rawGamepads[i] = 0; + } + } + continue; + } + + i32 js = open(str[i], O_RDONLY); + + if (js <= 0) + break; + + if (RGFW_gamepadCount >= 4) { + close(js); + break; + } + + RGFW_rawGamepads[i] = 1; + + int axes, buttons; + if (ioctl(js, JSIOCGAXES, &axes) < 0 || ioctl(js, JSIOCGBUTTONS, &buttons) < 0) { + close(js); + continue; + } + + if (buttons <= 5 || buttons >= 30) { + close(js); + continue; + } + + RGFW_gamepadCount++; + + RGFW_gamepads[index] = js; + + ioctl(js, JSIOCGNAME(sizeof(RGFW_gamepads_name[index])), RGFW_gamepads_name[index]); + RGFW_gamepads_name[index][sizeof(RGFW_gamepads_name[index]) - 1] = 0; + + u8 j; + for (j = 0; j < 16; j++) + RGFW_gamepadPressed[index][j] = (RGFW_keyState){0, 0}; + + win->event.type = RGFW_gamepadConnected; + + RGFW_gamepads_type[index] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[index], "Microsoft") || strstr(RGFW_gamepads_name[index], "X-Box")) + RGFW_gamepads_type[index] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[index], "PlayStation") || strstr(RGFW_gamepads_name[index], "PS3") || strstr(RGFW_gamepads_name[index], "PS4") || strstr(RGFW_gamepads_name[index], "PS5")) + RGFW_gamepads_type[index] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[index], "Nintendo")) + RGFW_gamepads_type[index] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[index], "Logitech")) + RGFW_gamepads_type[index] = RGFW_gamepadLogitech; + + win->event.gamepad = index; + RGFW_gamepadCallback(win, index, 1); + return 1; + } + + /* check gamepad events */ u8 i; + for (i = 0; i < RGFW_gamepadCount; i++) { struct js_event e; - - if (RGFW_gamepads[i] == 0) continue; @@ -2254,1868 +2554,76 @@ This is where OS specific stuff starts ssize_t bytes; while ((bytes = read(RGFW_gamepads[i], &e, sizeof(e))) > 0) { switch (e.type) { - case JS_EVENT_BUTTON: - win->event.type = e.value ? RGFW_gpButtonPressed : RGFW_gpButtonReleased; - win->event.button = e.number; - RGFW_gpPressed[i][e.number + 1] = e.value; - RGFW_gpButtonCallback(win, i, e.number, e.value); - - return &win->event; - case JS_EVENT_AXIS: { - size_t axis = e.number / 2; - if (axis == 2) axis = 1; + case JS_EVENT_BUTTON: { + size_t typeIndex = 0; + if (RGFW_gamepads_type[i] == RGFW_gamepadMicrosoft) typeIndex = 1; + else if (RGFW_gamepads_type[i] == RGFW_gamepadLogitech) typeIndex = 2; - ioctl(RGFW_gamepads[i], JSIOCGAXES, &win->event.axisesCount); - win->event.axisesCount = 2; - - if (axis < 3) { - if (e.number == 0 || e.number == 3) - win->event.axis[axis].x = (e.value / 32767.0f) * 100; - else if (e.number == 1 || e.number == 4) { - win->event.axis[axis].y = (e.value / 32767.0f) * 100; - } + win->event.type = e.value ? RGFW_gamepadButtonPressed : RGFW_gamepadButtonReleased; + u8 RGFW_linux2RGFW[3][RGFW_gamepadR3 + 8] = {{ /* ps */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadY, RGFW_gamepadX, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight, + },{ /* xbox */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadSelect, RGFW_gamepadStart, + RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, 255, 255, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight + },{ /* Logitech */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight + } + }; + + win->event.button = RGFW_linux2RGFW[typeIndex][e.number]; + win->event.gamepad = i; + if (win->event.button == 255) break; + + RGFW_gamepadPressed[i][win->event.button].prev = RGFW_gamepadPressed[i][win->event.button].current; + RGFW_gamepadPressed[i][win->event.button].current = e.value; + RGFW_gamepadButtonCallback(win, i, win->event.button, e.value); + + return 1; } + case JS_EVENT_AXIS: { + size_t axis = e.number / 2; + if (axis == 2) axis = 1; - win->event.type = RGFW_gpAxisMove; - win->event.gamepad = i; - win->event.whichAxis = axis; - RGFW_gpAxisCallback(win, i, win->event.axis, win->event.axisesCount); - return &win->event; - } + ioctl(RGFW_gamepads[i], JSIOCGAXES, &win->event.axisesCount); + win->event.axisesCount = 2; + + if (axis < 3) { + if (e.number == 0 || e.number == 3) + RGFW_gamepadAxes[i][axis].x = (e.value / 32767.0f) * 100; + else if (e.number == 1 || e.number == 4) { + RGFW_gamepadAxes[i][axis].y = (e.value / 32767.0f) * 100; + } + } + + win->event.axis[axis] = RGFW_gamepadAxes[i][axis]; + win->event.type = RGFW_gamepadAxisMove; + win->event.gamepad = i; + win->event.whichAxis = axis; + RGFW_gamepadAxisCallback(win, i, win->event.axis, win->event.axisesCount, win->event.whichAxis); + return 1; + } default: break; } } - } - - return NULL; - } - - #endif -#endif - -/* - - -Start of Linux / Unix defines - - -*/ - -#ifdef RGFW_X11 -#ifndef RGFW_NO_X11_CURSOR -#include -#endif -#include - -#ifndef RGFW_NO_DPI -#include -#include -#endif - -#include -#include -#include -#include - -#include /* for converting keycode to string */ -#include /* for hiding */ -#include -#include -#include - -#include /* for data limits (mainly used in drag and drop functions) */ -#include - - -#ifdef __linux__ -#include -#endif - - u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; - /*atoms needed for drag and drop*/ - Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList; - - Atom wm_delete_window = 0; - -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int); - typedef void (*PFN_XcursorImageDestroy)(XcursorImage*); - typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*); -#endif -#ifdef RGFW_OPENGL - typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); -#endif - -#if !defined(RGFW_NO_X11_XI_PRELOAD) - typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int); - PFN_XISelectEvents XISelectEventsSrc = NULL; - #define XISelectEvents XISelectEventsSrc - - void* X11Xihandle = NULL; -#endif - -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL; - PFN_XcursorImageCreate XcursorImageCreateSrc = NULL; - PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL; - -#define XcursorImageLoadCursor XcursorImageLoadCursorSrc -#define XcursorImageCreate XcursorImageCreateSrc -#define XcursorImageDestroy XcursorImageDestroySrc - - void* X11Cursorhandle = NULL; -#endif - - u32 RGFW_windowsOpen = 0; - -#ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); } -#endif - - RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi); - void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) - RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); - - #ifdef RGFW_DEBUG - printf("RGFW INFO: createing a 4 channel %i by %i buffer\n", RGFW_bufferSize.w, RGFW_bufferSize.h); - #endif - - #ifdef RGFW_OSMESA - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - - win->src.bitmap = XCreateImage( - win->src.display, XDefaultVisual(win->src.display, vi->screen), - vi->depth, - ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, - 32, 0 - ); - - win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); - - #else - RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ - RGFW_UNUSED(vi) - #endif - } - - - - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - static Atom _MOTIF_WM_HINTS = 0; - if (_MOTIF_WM_HINTS == 0 ) - _MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False); - - struct __x11WindowHints { - unsigned long flags, functions, decorations, status; - long input_mode; - } hints; - hints.flags = (1L << 1); - hints.decorations = border; - - XChangeProperty( - win->src.display, win->src.window, - _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, - 32, PropModeReplace, (u8*)&hints, 5 - ); - } - - void RGFW_releaseCursor(RGFW_window* win) { - XUngrabPointer(win->src.display, CurrentTime); - - /* disable raw input */ - unsigned char mask[] = { 0 }; - XIEventMask em; - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - - XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); - } - - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - /* enable raw input */ - unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; - XISetMask(mask, XI_RawMotion); - - XIEventMask em; - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - - XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); - - XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2))); - } - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - if (X11Cursorhandle == NULL) { -#if defined(__CYGWIN__) - X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL); -#elif defined(__OpenBSD__) || defined(__NetBSD__) - X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL); -#else - X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL); -#endif - - XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate"); - XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy"); - XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor"); - } -#endif - -#if !defined(RGFW_NO_X11_XI_PRELOAD) - if (X11Xihandle == NULL) { -#if defined(__CYGWIN__) - X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL); -#elif defined(__OpenBSD__) || defined(__NetBSD__) - X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL); -#else - X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL); -#endif - - XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents"); - } -#endif - - XInitThreads(); /*!< init X11 threading*/ - - if (args & RGFW_OPENGL_SOFTWARE) - setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/ - -#ifdef RGFW_OPENGL - u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); - i32 fbcount; - GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount); - - i32 best_fbc = -1; - - if (fbcount == 0) { - printf("Failed to find any valid GLX visual configs\n"); - return NULL; - } - - u32 i; - for (i = 0; i < (u32)fbcount; i++) { - XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]); - if (vi == NULL) - continue; - - XFree(vi); - - i32 samp_buf, samples; - glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); - glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples); - - if ((!(args & RGFW_TRANSPARENT_WINDOW) || vi->depth == 32) && - (best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) { - best_fbc = i; - } - } - - if (best_fbc == -1) { - printf("Failed to get a valid GLX visual\n"); - return NULL; - } - - GLXFBConfig bestFbc = fbc[best_fbc]; - - /* Get a visual */ - XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc); - - XFree(fbc); -#else - XVisualInfo viNorm; - - viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display)); - - viNorm.depth = 0; - XVisualInfo* vi = &viNorm; - - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ -#endif - /* make X window attrubutes*/ - XSetWindowAttributes swa; - Colormap cmap; - - swa.colormap = cmap = XCreateColormap((Display*) win->src.display, - DefaultRootWindow(win->src.display), - vi->visual, AllocNone); - - swa.background_pixmap = None; - swa.border_pixel = 0; - swa.event_mask = event_mask; - - swa.background_pixel = 0; - - /* create the window*/ - win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h, - 0, vi->depth, InputOutput, vi->visual, - CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); - - XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0); - - #ifdef RGFW_OPENGL - XFree(vi); - #endif - - // In your .desktop app, if you set the property - // StartupWMClass=RGFW that will assoicate the launcher icon - // with your application - robrohan - - if (RGFW_className == NULL) - RGFW_className = (char*)name; - - XClassHint *hint = XAllocClassHint(); - assert(hint != NULL); - hint->res_class = (char*)RGFW_className; - hint->res_name = (char*)name; // just use the window name as the app name - XSetClassHint((Display*) win->src.display, win->src.window, hint); - XFree(hint); - - if ((args & RGFW_NO_INIT_API) == 0) { -#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ - i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; - context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; - if (RGFW_profile == RGFW_GL_CORE) - context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else - context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - - if (RGFW_majorVersion || RGFW_minorVersion) { - context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; - context_attribs[3] = RGFW_majorVersion; - context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB; - context_attribs[5] = RGFW_minorVersion; - } - - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; - glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) - glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB"); - - GLXContext ctx = NULL; - - if (RGFW_root != NULL) - ctx = RGFW_root->src.ctx; - - win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs); -#endif - if (RGFW_root == NULL) - RGFW_root = win; - - RGFW_init_buffer(win, vi); - } - - - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); - #endif - - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } - - if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ - XSizeHints sh = {0}; - sh.flags = (1L << 4) | (1L << 5); - sh.min_width = sh.max_width = win->r.w; - sh.min_height = sh.max_height = win->r.h; - - XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); - - win->_winArgs |= RGFW_NO_RESIZE; - } - - if (args & RGFW_NO_BORDER) { - RGFW_window_setBorder(win, 0); - } - - XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/ - - /* make it so the user can't close the window until the program does*/ - if (wm_delete_window == 0) - wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False); - - XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1); - - /* connect the context to the window*/ -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); -#endif - - /* set the background*/ - XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/ - - XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/ - XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/ - - if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ - win->_winArgs |= RGFW_ALLOW_DND; - - XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False); - XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False); - - /* client messages */ - XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False); - XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False); - XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False); - XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False); - XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False); - XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False); - - /* actions */ - XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False); - - XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False); - XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False); - - XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False); - const u8 version = 5; - - XChangeProperty((Display*) win->src.display, (Window) win->src.window, - XdndAware, 4, 32, - PropModeReplace, &version, 1); /*!< turns on drag and drop */ - } - - #ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) - RGFW_createOpenGLContext(win); - #endif - - RGFW_window_setMouseDefault(win); - - RGFW_windowsOpen++; - - #ifdef RGFW_DEBUG - printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); - #endif - - return win; /*return newly created window*/ - } - - RGFW_area RGFW_getScreenSize(void) { - assert(RGFW_root != NULL); - - Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display); - return RGFW_AREA(scrn->width, scrn->height); - } - - RGFW_point RGFW_getGlobalMousePoint(void) { - assert(RGFW_root != NULL); - - RGFW_point RGFWMouse; - - i32 x, y; - u32 z; - Window window1, window2; - XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z); - - return RGFWMouse; - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - assert(win != NULL); - - RGFW_point RGFWMouse; - - i32 x, y; - u32 z; - Window window1, window2; - XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z); - - return RGFWMouse; - } - - int xAxis = 0, yAxis = 0; - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - - static struct { - long source, version; - i32 format; - } xdnd; - - if (win->event.type == 0) - RGFW_resetKey(); - - if (win->event.type == RGFW_quit) { - return NULL; - } - - win->event.type = 0; - -#ifdef __linux__ - RGFW_Event* event = RGFW_linux_updateGamepad(win); - if (event != NULL) - return event; -#endif - - XPending(win->src.display); - - XEvent E; /*!< raw X11 event */ - - /* if there is no unread qued events, get a new one */ - if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) - && win->event.type != RGFW_quit - ) - XNextEvent((Display*) win->src.display, &E); - else { - return NULL; - } - - u32 i; - win->event.type = 0; - XEvent reply = { ClientMessage }; - - switch (E.type) { - case KeyPress: - case KeyRelease: { - win->event.repeat = RGFW_FALSE; - /* check if it's a real key release */ - if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/ - XEvent NE; - XPeekEvent((Display*) win->src.display, &NE); - - if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/ - win->event.repeat = RGFW_TRUE; + if (bytes == -1 && errno == ENODEV) { + RGFW_gamepadCount--; + close(RGFW_gamepads[i]); + RGFW_gamepads[i] = 0; + + win->event.type = RGFW_gamepadDisconnected; + win->event.gamepad = i; + RGFW_gamepadCallback(win, i, 0); + return 1; } - - /* set event key data */ - win->event.key = RGFW_apiKeyToRGFW(E.xkey.keycode); - - KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); - win->event.keyChar = (u8)sym; - - char* str = (char*)XKeysymToString(sym); - if (str != NULL) - strncpy(win->event.keyName, str, 16); - - win->event.keyName[15] = '\0'; - - RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); - - /* get keystate data */ - win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; - - XKeyboardState keystate; - XGetKeyboardControl((Display*) win->src.display, &keystate); - - RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); - RGFW_keyboard[win->event.key].current = (E.type == KeyPress); - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, (E.type == KeyPress)); - break; } - case ButtonPress: - case ButtonRelease: - win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match - - win->event.button = E.xbutton.button; - switch(win->event.button) { - case RGFW_mouseScrollUp: - win->event.scroll = 1; - break; - case RGFW_mouseScrollDown: - win->event.scroll = -1; - break; - default: break; - } - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - - if (win->event.repeat == RGFW_FALSE) - win->event.repeat = RGFW_isPressed(win, win->event.key); - - RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); - break; - - case MotionNotify: - win->event.point.x = E.xmotion.x; - win->event.point.y = E.xmotion.y; - - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - win->event.point.y = E.xmotion.y; - - win->event.point.x = win->event.point.x - win->_lastMousePoint.x; - win->event.point.y = win->event.point.y - win->_lastMousePoint.y; - } - - win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); - - win->event.type = RGFW_mousePosChanged; - RGFW_mousePosCallback(win, win->event.point); - break; - - case GenericEvent: { - /* MotionNotify is used for mouse events if the mouse isn't held */ - if (!(win->_winArgs & RGFW_HOLD_MOUSE)) { - XFreeEventData(win->src.display, &E.xcookie); - break; - } - - XGetEventData(win->src.display, &E.xcookie); - if (E.xcookie.evtype == XI_RawMotion) { - XIRawEvent *raw = (XIRawEvent *)E.xcookie.data; - if (raw->valuators.mask_len == 0) { - XFreeEventData(win->src.display, &E.xcookie); - break; - } - - double deltaX = 0.0f; - double deltaY = 0.0f; - - /* check if relative motion data exists where we think it does */ - if (XIMaskIsSet(raw->valuators.mask, 0) != 0) - deltaX += raw->raw_values[0]; - if (XIMaskIsSet(raw->valuators.mask, 1) != 0) - deltaY += raw->raw_values[1]; - - win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY); - - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); - - win->event.type = RGFW_mousePosChanged; - RGFW_mousePosCallback(win, win->event.point); - } - - XFreeEventData(win->src.display, &E.xcookie); - break; - } - - case Expose: - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - break; - - case ClientMessage: - /* if the client closed the window*/ - if (E.xclient.data.l[0] == (i64) wm_delete_window) { - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); - break; - } - - /* reset DND values */ - if (win->event.droppedFilesCount) { - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - - if ((win->_winArgs & RGFW_ALLOW_DND) == 0) - break; - - reply.xclient.window = xdnd.source; - reply.xclient.format = 32; - reply.xclient.data.l[0] = (long) win->src.window; - reply.xclient.data.l[1] = 0; - reply.xclient.data.l[2] = None; - - if (E.xclient.message_type == XdndEnter) { - unsigned long count; - Atom* formats; - Atom real_formats[6]; - - Bool list = E.xclient.data.l[1] & 1; - - xdnd.source = E.xclient.data.l[0]; - xdnd.version = E.xclient.data.l[1] >> 24; - - xdnd.format = None; - - if (xdnd.version > 5) - break; - - if (list) { - Atom actualType; - i32 actualFormat; - unsigned long bytesAfter; - - XGetWindowProperty((Display*) win->src.display, - xdnd.source, - XdndTypeList, - 0, - LONG_MAX, - False, - 4, - &actualType, - &actualFormat, - &count, - &bytesAfter, - (u8**) &formats); - } else { - count = 0; - - if (E.xclient.data.l[2] != None) - real_formats[count++] = E.xclient.data.l[2]; - if (E.xclient.data.l[3] != None) - real_formats[count++] = E.xclient.data.l[3]; - if (E.xclient.data.l[4] != None) - real_formats[count++] = E.xclient.data.l[4]; - - formats = real_formats; - } - - unsigned long i; - for (i = 0; i < count; i++) { - if (formats[i] == XtextUriList || formats[i] == XtextPlain) { - xdnd.format = formats[i]; - break; - } - } - - if (list) { - XFree(formats); - } - - break; - } - if (E.xclient.message_type == XdndPosition) { - const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff; - const i32 yabs = (E.xclient.data.l[2]) & 0xffff; - Window dummy; - i32 xpos, ypos; - - if (xdnd.version > 5) - break; - - XTranslateCoordinates((Display*) win->src.display, - XDefaultRootWindow((Display*) win->src.display), - (Window) win->src.window, - xabs, yabs, - &xpos, &ypos, - &dummy); - - win->event.point.x = xpos; - win->event.point.y = ypos; - - reply.xclient.window = xdnd.source; - reply.xclient.message_type = XdndStatus; - - if (xdnd.format) { - reply.xclient.data.l[1] = 1; - if (xdnd.version >= 2) - reply.xclient.data.l[4] = XdndActionCopy; - } - - XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - break; - } - - if (E.xclient.message_type != XdndDrop) - break; - - if (xdnd.version > 5) - break; - - win->event.type = RGFW_dnd_init; - - if (xdnd.format) { - Time time = CurrentTime; - - if (xdnd.version >= 1) - time = E.xclient.data.l[2]; - - XConvertSelection((Display*) win->src.display, - XdndSelection, - xdnd.format, - XdndSelection, - (Window) win->src.window, - time); - } else if (xdnd.version >= 2) { - XEvent reply = { ClientMessage }; - - XSendEvent((Display*) win->src.display, xdnd.source, - False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - } - - RGFW_dndInitCallback(win, win->event.point); - break; - case SelectionNotify: { - /* this is only for checking for xdnd drops */ - if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND)) - break; - - char* data; - unsigned long result; - - Atom actualType; - i32 actualFormat; - unsigned long bytesAfter; - - XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data); - - if (result == 0) - break; - - /* - SOURCED FROM GLFW _glfwParseUriList - Copyright (c) 2002-2006 Marcus Geelnard - Copyright (c) 2006-2019 Camilla Löwy - */ - - const char* prefix = (const char*)"file://"; - - char* line; - - win->event.droppedFilesCount = 0; - - win->event.type = RGFW_dnd; - - while ((line = strtok(data, "\r\n"))) { - char path[RGFW_MAX_PATH]; - - data = NULL; - - if (line[0] == '#') - continue; - - char* l; - for (l = line; 1; l++) { - if ((l - line) > 7) - break; - else if (*l != prefix[(l - line)]) - break; - else if (*l == '\0' && prefix[(l - line)] == '\0') { - line += 7; - while (*line != '/') - line++; - break; - } else if (*l == '\0') - break; - } - - win->event.droppedFilesCount++; - - size_t index = 0; - while (*line) { - if (line[0] == '%' && line[1] && line[2]) { - const char digits[3] = { line[1], line[2], '\0' }; - path[index] = (char) strtol(digits, NULL, 16); - line += 2; - } else - path[index] = *line; - - index++; - line++; - } - path[index] = '\0'; - strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); - } - - if (data) - XFree(data); - - if (xdnd.version >= 2) { - XEvent reply = { ClientMessage }; - reply.xclient.format = 32; - reply.xclient.message_type = XdndFinished; - reply.xclient.data.l[1] = result; - reply.xclient.data.l[2] = XdndActionCopy; - - XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - } - - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); - break; - } - case FocusIn: - win->event.inFocus = 1; - win->event.type = RGFW_focusIn; - RGFW_focusCallback(win, 1); - break; - - break; - case FocusOut: - win->event.inFocus = 0; - win->event.type = RGFW_focusOut; - RGFW_focusCallback(win, 0); - break; - - case EnterNotify: { - win->event.type = RGFW_mouseEnter; - win->event.point.x = E.xcrossing.x; - win->event.point.y = E.xcrossing.y; - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - break; - } - - case LeaveNotify: { - win->event.type = RGFW_mouseLeave; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - } - - case ConfigureNotify: { - /* detect resize */ - if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) { - win->event.type = RGFW_windowResized; - win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); - RGFW_windowResizeCallback(win, win->r); - break; - } - - /* detect move */ - if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) { - win->event.type = RGFW_windowMoved; - win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); - RGFW_windowMoveCallback(win, win->r); - break; - } - - break; - } - default: - XFlush((Display*) win->src.display); - return RGFW_window_checkEvent(win); - } - - XFlush((Display*) win->src.display); - - if (win->event.type) - return &win->event; - else - return NULL; - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); - win->r.x = v.x; - win->r.y = v.y; - - XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y); - } - - - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->r.w = a.w; - win->r.h = a.h; - - - XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h); - - if (!(win->_winArgs & RGFW_NO_RESIZE)) - return; - - XSizeHints sh = {0}; - sh.flags = (1L << 4) | (1L << 5); - sh.min_width = sh.max_width = a.w; - sh.min_height = sh.max_height = a.h; - - XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - if (a.w == 0 && a.h == 0) - return; - - XSizeHints hints; - long flags; - - XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags); - - hints.flags |= PMinSize; - - hints.min_width = a.w; - hints.min_height = a.h; - - XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints); - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - if (a.w == 0 && a.h == 0) - return; - - XSizeHints hints; - long flags; - - XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags); - - hints.flags |= PMaxSize; - - hints.max_width = a.w; - hints.max_height = a.h; - - XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints); - } - - - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); - - XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display)); - XFlush(win->src.display); - } - - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); - - XMapWindow(win->src.display, (Window) win->src.window); - XFlush(win->src.display); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - XStoreName((Display*) win->src.display, (Window) win->src.window, name); - } - - void* RGFW_libxshape = NULL; - - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - assert(win != NULL); - - #if defined(__CYGWIN__) - RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL); - #elif defined(__OpenBSD__) || defined(__NetBSD__) - RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL); - #else - RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL); - #endif - - typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); - static PFN_XShapeCombineMask XShapeCombineMask; - - typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); - static PFN_XShapeCombineRegion XShapeCombineRegion; - - if (XShapeCombineMask != NULL) - XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask"); - - if (XShapeCombineRegion != NULL) - XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask"); - - if (passthrough) { - Region region = XCreateRegion(); - XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet); - XDestroyRegion(region); - - return; - } - - XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet); - } - #endif - - /* - the majority function is sourced from GLFW - */ - - void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { - assert(win != NULL); - - i32 longCount = 2 + a.w * a.h; - - u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64)); - u64* target = X11Icon; - - *target++ = a.w; - *target++ = a.h; - - u32 i; - - for (i = 0; i < a.w * a.h; i++) { - if (channels == 3) - *target++ = ((icon[i * 3 + 0]) << 16) | - ((icon[i * 3 + 1]) << 8) | - ((icon[i * 3 + 2]) << 0) | - (0xFF << 24); - - else if (channels == 4) - *target++ = ((icon[i * 4 + 0]) << 16) | - ((icon[i * 4 + 1]) << 8) | - ((icon[i * 4 + 2]) << 0) | - ((icon[i * 4 + 3]) << 24); - } - - static Atom NET_WM_ICON = 0; - if (NET_WM_ICON == 0) - NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False); - - XChangeProperty((Display*) win->src.display, (Window) win->src.window, - NET_WM_ICON, - 6, 32, - PropModeReplace, - (u8*) X11Icon, - longCount); - - RGFW_FREE(X11Icon); - - XFlush((Display*) win->src.display); - } - - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); - -#ifndef RGFW_NO_X11_CURSOR - XcursorImage* native = XcursorImageCreate(a.w, a.h); - native->xhot = 0; - native->yhot = 0; - - u8* source = (u8*) image; - XcursorPixel* target = native->pixels; - - u32 i; - for (i = 0; i < a.w * a.h; i++, target++, source += 4) { - u8 alpha = 0xFF; - if (channels == 4) - alpha = source[3]; - - *target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0); - } - - Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native); - XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor); - - XFreeCursor((Display*) win->src.display, (Cursor) cursor); - XcursorImageDestroy(native); -#else - RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels) -#endif - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { - assert(win != NULL); - - XEvent event; - XQueryPointer(win->src.display, DefaultRootWindow(win->src.display), - &event.xbutton.root, &event.xbutton.window, - &event.xbutton.x_root, &event.xbutton.y_root, - &event.xbutton.x, &event.xbutton.y, - &event.xbutton.state); - - win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); - if (event.xbutton.x == p.x && event.xbutton.y == p.y) - return; - - XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) p.x - win->r.x, (int) p.y - win->r.y); - } - - RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) { - RGFW_UNUSED(win); - } - - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - assert(win != NULL); - - if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8))) - return; - - mouse = RGFW_mouseIconSrc[mouse]; - - Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse); - XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor); - - XFreeCursor((Display*) win->src.display, (Cursor) cursor); - } - - void RGFW_window_hide(RGFW_window* win) { - XMapWindow(win->src.display, win->src.window); - } - - void RGFW_window_show(RGFW_window* win) { - XUnmapWindow(win->src.display, win->src.window); - } - - /* - the majority function is sourced from GLFW - */ - char* RGFW_readClipboard(size_t* size) { - static Atom UTF8 = 0; - if (UTF8 == 0) - UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True); - - XEvent event; - int format; - unsigned long N, sizeN; - char* data, * s = NULL; - Atom target; - Atom CLIPBOARD = 0, XSEL_DATA = 0; - - if (CLIPBOARD == 0) { - CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0); - XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0); - } - - XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime); - XSync(RGFW_root->src.display, 0); - XNextEvent(RGFW_root->src.display, &event); - - if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0) - return NULL; - - XGetWindowProperty(event.xselection.display, event.xselection.requestor, - event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target, - &format, &sizeN, &N, (unsigned char**) &data); - - if (target == UTF8 || target == XA_STRING) { - s = (char*)RGFW_MALLOC(sizeof(char) * sizeN); - strncpy(s, data, sizeN); - s[sizeN] = '\0'; - XFree(data); - } - - XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property); - - if (s != NULL && size != NULL) - *size = sizeN; - - return s; - } - - /* - almost all of this function is sourced from GLFW - */ - void RGFW_writeClipboard(const char* text, u32 textLen) { - static Atom CLIPBOARD = 0, - UTF8_STRING = 0, - SAVE_TARGETS = 0, - TARGETS = 0, - MULTIPLE = 0, - ATOM_PAIR = 0, - CLIPBOARD_MANAGER = 0; - - if (CLIPBOARD == 0) { - CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False); - UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False); - SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False); - TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False); - MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False); - ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False); - CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False); - } - - XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime); - - XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime); - for (;;) { - XEvent event; - - XNextEvent((Display*) RGFW_root->src.display, &event); - if (event.type != SelectionRequest) { - break; - } - - const XSelectionRequestEvent* request = &event.xselectionrequest; - - XEvent reply = { SelectionNotify }; - reply.xselection.property = 0; - - if (request->target == TARGETS) { - const Atom targets[] = { TARGETS, - MULTIPLE, - UTF8_STRING, - XA_STRING }; - - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - request->property, - 4, - 32, - PropModeReplace, - (u8*) targets, - sizeof(targets) / sizeof(targets[0])); - - reply.xselection.property = request->property; - } - - if (request->target == MULTIPLE) { - Atom* targets = NULL; - - Atom actualType = 0; - int actualFormat = 0; - unsigned long count = 0, bytesAfter = 0; - - XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); - - unsigned long i; - for (i = 0; i < (u32)count; i += 2) { - if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) { - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - targets[i + 1], - targets[i], - 8, - PropModeReplace, - (u8*) text, - textLen); - XFlush(RGFW_root->src.display); - } else { - targets[i + 1] = None; - } - } - - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - request->property, - ATOM_PAIR, - 32, - PropModeReplace, - (u8*) targets, - count); - - XFlush(RGFW_root->src.display); - XFree(targets); - - reply.xselection.property = request->property; - } - - reply.xselection.display = request->display; - reply.xselection.requestor = request->requestor; - reply.xselection.selection = request->selection; - reply.xselection.target = request->target; - reply.xselection.time = request->time; - - XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply); - XFlush(RGFW_root->src.display); - } - } - - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); - - XWindowAttributes windowAttributes; - XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes); - - /* check if the window is visable */ - if (windowAttributes.map_state != IsViewable) - return 0; - - /* check if the window covers the full screen */ - return (windowAttributes.x == 0 && windowAttributes.y == 0 && - windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) && - windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display))); - } - - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); - - XWindowAttributes windowAttributes; - XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes); - - return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win)); - } - - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); - - static Atom prop = 0; - if (prop == 0) - prop = XInternAtom(win->src.display, "WM_STATE", False); - - Atom actual_type; - i32 actual_format; - unsigned long nitems, bytes_after; - unsigned char* prop_data; - - i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False, - AnyPropertyType, &actual_type, &actual_format, - &nitems, &bytes_after, &prop_data); - - if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) { - XFree(prop_data); - return 1; - } - - if (prop_data != NULL) - XFree(prop_data); - - return 0; - } - - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); - - static Atom net_wm_state = 0; - static Atom net_wm_state_maximized_horz = 0; - static Atom net_wm_state_maximized_vert = 0; - - if (net_wm_state == 0) { - net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False); - net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - } - - Atom actual_type; - i32 actual_format; - unsigned long nitems, bytes_after; - unsigned char* prop_data; - - i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False, - XA_ATOM, &actual_type, &actual_format, - &nitems, &bytes_after, &prop_data); - - if (status != Success) { - if (prop_data != NULL) - XFree(prop_data); - return 0; } - Atom* atoms = (Atom*) prop_data; - u64 i; - for (i = 0; i < nitems; ++i) { - if (atoms[i] == net_wm_state_maximized_horz || - atoms[i] == net_wm_state_maximized_vert) { - XFree(prop_data); - return 1; - } - } - - return 0; - } - - static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) { - float xdpi = 96.f, ydpi = 96.f; - -#ifndef RGFW_NO_DPI - char* rms = XResourceManagerString(display); - XrmDatabase db = NULL; - - if (rms && db) - db = XrmGetStringDatabase(rms); - - if (db == 0) { - *xscale = xdpi / 96.f; - *yscale = ydpi / 96.f; - return; - } - - XrmValue value; - char* type = NULL; - - if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0) - xdpi = ydpi = atof(value.addr); - XrmDestroyDatabase(db); -#endif - - * xscale = xdpi / 96.f; - *yscale = ydpi / 96.f; - } - - RGFW_monitor RGFW_XCreateMonitor(i32 screen) { - RGFW_monitor monitor; - - Display* display = XOpenDisplay(NULL); - - RGFW_area size = RGFW_getScreenSize(); - - monitor.rect = RGFW_RECT(0, 0, size.w, size.h); - monitor.physW = DisplayWidthMM(display, screen) / 25.4; - monitor.physH = DisplayHeightMM(display, screen) / 25.4; - - XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); - XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); - - XRRCrtcInfo* ci = NULL; - int crtc = screen; - - if (sr->ncrtc > crtc) { - ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); - } - - if (ci == NULL) { - float dpi_width = round((double)monitor.rect.w/(double)monitor.physW); - float dpi_height = round((double)monitor.rect.h/(double)monitor.physH); - - monitor.scaleX = (float) (dpi_width) / (float) 96; - monitor.scaleY = (float) (dpi_height) / (float) 96; - XRRFreeScreenResources(sr); - XCloseDisplay(display); - - #ifdef RGFW_DEBUG - printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY); - #endif - return monitor; - } - - XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]); - monitor.physW = info->mm_width / 25.4; - monitor.physH = info->mm_height / 25.4; - - monitor.rect.x = ci->x; - monitor.rect.y = ci->y; - monitor.rect.w = ci->width; - monitor.rect.h = ci->height; - - float dpi_width = round((double)monitor.rect.w/(double)monitor.physW); - float dpi_height = round((double)monitor.rect.h/(double)monitor.physH); - - monitor.scaleX = (float) (dpi_width) / (float) 96; - monitor.scaleY = (float) (dpi_height) / (float) 96; - - if (isinf(monitor.scaleX) || (monitor.scaleX > 1 && monitor.scaleX < 1.1)) - monitor.scaleX = 1; - - if (isinf(monitor.scaleY) || (monitor.scaleY > 1 && monitor.scaleY < 1.1)) - monitor.scaleY = 1; - - XRRFreeCrtcInfo(ci); - XRRFreeScreenResources(sr); - - XCloseDisplay(display); - - #ifdef RGFW_DEBUG - printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY); - #endif - - return monitor; - } - - RGFW_monitor RGFW_monitors[6]; - RGFW_monitor* RGFW_getMonitors(void) { - size_t i; - for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) - RGFW_monitors[i] = RGFW_XCreateMonitor(i); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - assert(RGFW_root != NULL); - - i32 primary = -1; - Window root = DefaultRootWindow(RGFW_root->src.display); - XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root); - - for (int i = 0; i < res->noutput; i++) { - XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]); - if (output_info->connection == RR_Connected && output_info->crtc) { - XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc); - if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) { - primary = i; - XRRFreeCrtcInfo(crtc_info); - XRRFreeOutputInfo(output_info); - break; - } - XRRFreeCrtcInfo(crtc_info); - } - XRRFreeOutputInfo(output_info); - } - - XRRFreeScreenResources(res); - - return RGFW_XCreateMonitor(primary); - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - return RGFW_XCreateMonitor(DefaultScreen(win->src.display)); - } - - #ifdef RGFW_OPENGL - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - if (win == NULL) - glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL); - else - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); - } #endif - - - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - - /* clear the window*/ - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif - RGFW_area area = RGFW_bufferSize; - -#ifndef RGFW_X11_DONT_CONVERT_BGR - win->src.bitmap->data = (char*) win->buffer; - u32 x, y; - for (y = 0; y < (u32)win->r.h; y++) { - for (x = 0; x < (u32)win->r.w; x++) { - u32 index = (y * 4 * area.w) + x * 4; - - u8 red = win->src.bitmap->data[index]; - win->src.bitmap->data[index] = win->buffer[index + 2]; - win->src.bitmap->data[index + 2] = red; - - } - } -#endif - XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h); -#endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); - #endif - } - } - - #if !defined(RGFW_EGL) - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - #if defined(RGFW_OPENGL) - ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); - #else - RGFW_UNUSED(swapInterval); - #endif - } - #endif - - - void RGFW_window_close(RGFW_window* win) { - /* ungrab pointer if it was grabbed */ - if (win->_winArgs & RGFW_HOLD_MOUSE) - XUngrabPointer(win->src.display, CurrentTime); - - assert(win != NULL); -#ifdef RGFW_EGL - RGFW_closeEGL(win); #endif -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (win->buffer != NULL) { - XDestroyImage((XImage*) win->src.bitmap); - XFreeGC(win->src.display, win->src.gc); - } -#endif - - if ((Display*) win->src.display) { -#ifdef RGFW_OPENGL - glXDestroyContext((Display*) win->src.display, win->src.ctx); -#endif - - if (win == RGFW_root) - RGFW_root = NULL; - - if ((Drawable) win->src.window) - XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/ - - XCloseDisplay((Display*) win->src.display); /*!< kill the display*/ - } - -#ifdef RGFW_ALLOC_DROPFILES - { - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); - - - RGFW_FREE(win->event.droppedFiles); - } -#endif - - RGFW_windowsOpen--; -#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) - if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) { - dlclose(X11Cursorhandle); - - X11Cursorhandle = NULL; - } -#endif -#if !defined(RGFW_NO_X11_XI_PRELOAD) - if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) { - dlclose(X11Xihandle); - - X11Xihandle = NULL; - } -#endif - - if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) { - dlclose(RGFW_libxshape); - RGFW_libxshape = NULL; - } - - if (RGFW_windowsOpen <= 0) { - if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){ - close(RGFW_eventWait_forceStop[0]); - close(RGFW_eventWait_forceStop[1]); - } - - u8 i; - for (i = 0; i < RGFW_gamepadCount; i++) - close(RGFW_gamepads[i]); - } - - /* set cleared display / window to NULL for error checking */ - win->src.display = (Display*) 0; - win->src.window = (Window) 0; - - RGFW_FREE(win); /*!< free collected window data */ - } - - -/* - End of X11 linux / unix defines -*/ - -#endif /* RGFW_X11 */ - - -/* wayland or X11 defines*/ -#if defined(RGFW_WAYLAND) || defined(RGFW_X11) -#include -#include -#include - u16 RGFW_registerGamepadF(RGFW_window* win, char* file) { - assert(win != NULL); - -#ifdef __linux__ - - i32 js = open(file, O_RDONLY); - - if (js && RGFW_gamepadCount < 4) { - RGFW_gamepadCount++; - - RGFW_gamepads[RGFW_gamepadCount - 1] = open(file, O_RDONLY); - - u8 i; - for (i = 0; i < 16; i++) - RGFW_gpPressed[RGFW_gamepadCount - 1][i] = 0; - - } - - else { -#ifdef RGFW_PRINT_ERRORS - RGFW_error = 1; - fprintf(stderr, "Error RGFW_registerGamepadF : Cannot open file %s\n", file); -#endif - } - - return RGFW_gamepadCount - 1; -#endif - } - - u16 RGFW_registerGamepad(RGFW_window* win, i32 gpNumber) { - assert(win != NULL); - -#ifdef __linux__ - char file[15]; - sprintf(file, "/dev/input/js%i", gpNumber); - - return RGFW_registerGamepadF(win, file); -#endif - } - - void RGFW_stopCheckEvents(void) { - RGFW_eventWait_forceStop[2] = 1; - while (1) { - const char byte = 0; - const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); - if (result == 1 || result == -1) - break; - } - } - - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - if (waitMS == 0) - return; - - u8 i; - - if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { - if (pipe(RGFW_eventWait_forceStop) != -1) { - fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); - } - } - - struct pollfd fds[] = { - #ifdef RGFW_WAYLAND - { wl_display_get_fd(win->src.display), POLLIN, 0 }, - #else - { ConnectionNumber(win->src.display), POLLIN, 0 }, - #endif - { RGFW_eventWait_forceStop[0], POLLIN, 0 }, - #ifdef __linux__ /* blank space for 4 gamepad files*/ - { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} - #endif - }; - - u8 index = 2; - - #if defined(__linux__) - for (i = 0; i < RGFW_gamepadCount; i++) { - if (RGFW_gamepads[i] == 0) - continue; - - fds[index].fd = RGFW_gamepads[i]; - index++; - } - #endif - - - u64 start = RGFW_getTimeNS(); - - #ifdef RGFW_WAYLAND - while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) { - #else - while (XPending(win->src.display) == 0 && waitMS >= -1) { - #endif - if (poll(fds, index, waitMS) <= 0) - break; - - if (waitMS > 0) { - waitMS -= (RGFW_getTimeNS() - start) / 1e+6; - } - } - - /* drain any data in the stop request */ - if (RGFW_eventWait_forceStop[2]) { - char data[64]; - (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data)); - - RGFW_eventWait_forceStop[2] = 0; - } - } - - u64 RGFW_getTimeNS(void) { - struct timespec ts = { 0 }; - clock_gettime(1, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - - return nanoSeconds; - } - - u64 RGFW_getTime(void) { - struct timespec ts = { 0 }; - clock_gettime(1, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - - return (double)(nanoSeconds) * 1e-9; - } -#endif /* end of wayland or X11 time defines*/ /* @@ -4134,35 +2642,35 @@ Wayland TODO: RGFW_windowResized the window was resized (by the user), [on webASM this means the browser was resized] RGFW_windowRefresh The window content needs to be refreshed - RGFW_dnd a file has been dropped into the window - RGFW_dnd_init + RGFW_DND a file has been dropped into the window + RGFW_DNDInit - window args: - #define RGFW_NO_RESIZE the window cannot be resized by the user - #define RGFW_ALLOW_DND the window supports drag and drop - #define RGFW_SCALE_TO_MONITOR scale the window to the screen + #define RGFW_windowNoResize the window cannot be resized by the user + #define RGFW_windowAllowDND the window supports drag and drop + #define RGFW_scaleToMonitor scale the window to the screen - other missing functions functions ("TODO wayland") (~30 functions) - fix buffer rendering weird behavior */ - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include RGFW_window* RGFW_key_win = NULL; -void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) { +void RGFW_eventPipe_push(RGFW_window* win, RGFW_event event) { if (win == NULL) { win = RGFW_key_win; if (win == NULL) return; } - + if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0]))) return; @@ -4170,28 +2678,23 @@ void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) { win->src.eventLen += 1; } -RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) { - RGFW_Event ev; +RGFW_event RGFW_eventPipe_pop(RGFW_window* win) { + RGFW_event ev; ev.type = 0; - + if (win->src.eventLen > -1) win->src.eventLen -= 1; - - if (win->src.eventLen >= 0) + + if (win->src.eventLen >= 0) ev = win->src.events[win->src.eventLen]; - return ev; + return ev; } /* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */ #include "xdg-shell.h" #include "xdg-decoration-unstable-v1.h" -struct xdg_wm_base *xdg_wm_base; -struct wl_compositor* RGFW_compositor = NULL; -struct wl_shm* shm = NULL; -struct wl_shell* RGFW_shell = NULL; -static struct wl_seat *seat = NULL; static struct xkb_context *xkb_context; static struct xkb_keymap *keymap = NULL; static struct xkb_state *xkb_state = NULL; @@ -4217,7 +2720,7 @@ b8 RGFW_wl_configured = 0; static void xdg_surface_configure_handler(void *data, struct xdg_surface *xdg_surface, uint32_t serial) -{ +{ RGFW_UNUSED(data); xdg_surface_ack_configure(xdg_surface, serial); #ifdef RGFW_DEBUG @@ -4234,8 +2737,10 @@ static void xdg_toplevel_configure_handler(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) { - RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states) + RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states); + #ifdef RGFW_DEBUG fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height); + #endif } static void xdg_toplevel_close_handler(void *data, @@ -4245,11 +2750,11 @@ static void xdg_toplevel_close_handler(void *data, RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel); if (win == NULL) win = RGFW_key_win; - - RGFW_Event ev; + + RGFW_event ev; ev.type = RGFW_quit; - RGFW_eventPipe_push(win, ev); + RGFW_eventPipe_push(win, ev); RGFW_windowQuitCallback(win); } @@ -4258,7 +2763,9 @@ static void shm_format_handler(void *data, struct wl_shm *shm, uint32_t format) { RGFW_UNUSED(data); RGFW_UNUSED(shm); + #ifdef RGFW_DEBUG fprintf(stderr, "Format %d\n", format); + #endif } static const struct wl_shm_listener shm_listener = { @@ -4277,11 +2784,11 @@ static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t seria RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); RGFW_mouse_win = win; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseEnter; ev.point = win->event.point; - RGFW_eventPipe_push(win, ev); + RGFW_eventPipe_push(win, ev); RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE); } @@ -4290,8 +2797,8 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t seria RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); if (RGFW_mouse_win == win) RGFW_mouse_win = NULL; - - RGFW_Event ev; + + RGFW_event ev; ev.type = RGFW_mouseLeave; ev.point = win->event.point; RGFW_eventPipe_push(win, ev); @@ -4301,29 +2808,29 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t seria static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y); - assert(RGFW_mouse_win != NULL); - - RGFW_Event ev; + RGFW_ASSERT(RGFW_mouse_win != NULL); + + RGFW_event ev; ev.type = RGFW_mousePosChanged; ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)); RGFW_eventPipe_push(RGFW_mouse_win, ev); - + RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y))); } static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial); - assert(RGFW_mouse_win != NULL); + RGFW_ASSERT(RGFW_mouse_win != NULL); u32 b = (button - 0x110) + 1; /* flip right and middle button codes */ if (b == 2) b = 3; else if (b == 3) b = 2; - + RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current; RGFW_mouseButtons[b].current = state; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseButtonPressed + state; ev.button = b; RGFW_eventPipe_push(RGFW_mouse_win, ev); @@ -4332,11 +2839,11 @@ static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t seri } static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(axis); - assert(RGFW_mouse_win != NULL); + RGFW_ASSERT(RGFW_mouse_win != NULL); double scroll = wl_fixed_to_double(value); - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseButtonPressed; ev.button = RGFW_mouseScrollUp + (scroll < 0); RGFW_eventPipe_push(RGFW_mouse_win, ev); @@ -4353,18 +2860,18 @@ static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0); xkb_keymap_unref (keymap); keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - + munmap (keymap_string, size); close (fd); xkb_state_unref (xkb_state); xkb_state = xkb_state_new (keymap); } -static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { +static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys); RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface); - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_focusIn; ev.inFocus = RGFW_TRUE; RGFW_key_win->event.inFocus = RGFW_TRUE; @@ -4373,14 +2880,14 @@ static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t s RGFW_focusCallback(RGFW_key_win, RGFW_TRUE); } -static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { +static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); if (RGFW_key_win == win) - RGFW_key_win = NULL; + RGFW_key_win = NULL; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_focusOut; ev.inFocus = RGFW_FALSE; win->event.inFocus = RGFW_FALSE; @@ -4389,31 +2896,29 @@ static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t s RGFW_focusCallback(win, RGFW_FALSE); } static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); - assert(RGFW_key_win != NULL); + RGFW_ASSERT(RGFW_key_win != NULL); - xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8); - char name[16]; - xkb_keysym_get_name(keysym, name, 16); + xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, key + 8); - u32 RGFW_key = RGFW_apiKeyToRGFW(key); + u32 RGFW_key = RGFW_apiKeyToRGFW(key + 8); RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current; RGFW_keyboard[RGFW_key].current = state; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_keyPressed + state; ev.key = RGFW_key; ev.keyChar = (u8)keysym; - strcpy(ev.keyName, name); + ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key); RGFW_eventPipe_push(RGFW_key_win, ev); - - RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2")); - RGFW_keyCallback(RGFW_key_win, RGFW_key, (u8)keysym, name, RGFW_key_win->event.lockState, state); + RGFW_updateKeyMods(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2")); + + RGFW_keyCallback(RGFW_key_win, RGFW_key, (u8)keysym, RGFW_key_win->event.keyMod, state); } static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); } static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing}; @@ -4436,23 +2941,23 @@ static void wl_global_registry_handler(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { - RGFW_UNUSED(data); RGFW_UNUSED(version); - - if (strcmp(interface, "wl_compositor") == 0) { - RGFW_compositor = wl_registry_bind(registry, + RGFW_window* win = (RGFW_window*)data; + RGFW_UNUSED(version); + if (RGFW_STRNCMP(interface, "wl_compositor", 16) == 0) { + win->src.compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4); - } else if (strcmp(interface, "xdg_wm_base") == 0) { - xdg_wm_base = wl_registry_bind(registry, + } else if (RGFW_STRNCMP(interface, "xdg_wm_base", 12) == 0) { + win->src.xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); - } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) { + } else if (RGFW_STRNCMP(interface, zxdg_decoration_manager_v1_interface.name, 255) == 0) { decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1); - } else if (strcmp(interface, "wl_shm") == 0) { - shm = wl_registry_bind(registry, + } else if (RGFW_STRNCMP(interface, "wl_shm", 7) == 0) { + win->src.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - wl_shm_add_listener(shm, &shm_listener, NULL); - } else if (strcmp(interface,"wl_seat") == 0) { - seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); - wl_seat_add_listener(seat, &seat_listener, NULL); + wl_shm_add_listener(win->src.shm, &shm_listener, NULL); + } else if (RGFW_STRNCMP(interface,"wl_seat", 8) == 0) { + win->src.seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); + wl_seat_add_listener(win->src.seat, &seat_listener, NULL); } else { @@ -4462,9 +2967,9 @@ static void wl_global_registry_handler(void *data, #endif } - #ifdef RGFW_DEBUG - printf("registered %s\n", interface); - #endif + #ifdef RGFW_DEBUG + printf("registered %s\n", interface); + #endif } static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); } @@ -4488,7 +2993,9 @@ static void decoration_handle_configure(void *data, struct zxdg_toplevel_decoration_v1 *decoration, enum zxdg_toplevel_decoration_v1_mode mode) { RGFW_UNUSED(data); RGFW_UNUSED(decoration); + #ifdef RGFW_DEBUG printf("Using %s\n", get_mode_name(mode)); + #endif RGFW_current_mode = mode; } @@ -4506,12 +3013,18 @@ static void randname(char *buf) { } } +size_t wl_stringlen(char* name) { + size_t i = 0; + for (i; name[i]; i++); + return i; +} + static int anonymous_shm_open(void) { char name[] = "/RGFW-wayland-XXXXXX"; int retries = 100; do { - randname(name + strlen(name) - 6); + randname(name + wl_stringlen(name) - 6); --retries; // shm_open guarantees that O_CLOEXEC is set @@ -4544,23 +3057,9 @@ static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t t #ifdef RGFW_BUFFER RGFW_window* win = (RGFW_window*)data; - if ((win->_winArgs & RGFW_NO_CPU_RENDER)) - return; + if ((win->_flags & RGFW_NO_CPU_RENDER)) + return; - #ifndef RGFW_X11_DONT_CONVERT_BGR - u32 x, y; - for (y = 0; y < (u32)win->r.h; y++) { - for (x = 0; x < (u32)win->r.w; x++) { - u32 index = (y * 4 * win->r.w) + x * 4; - - u8 red = win->buffer[index]; - win->buffer[index] = win->buffer[index + 2]; - win->buffer[index + 2] = red; - - } - } - #endif - wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h); wl_surface_commit(win->src.surface); @@ -4570,425 +3069,2162 @@ static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t t static const struct wl_callback_listener wl_surface_frame_listener = { .done = wl_surface_frame_done, }; +#endif /* RGFW_WAYLAND */ +#if !defined(RGFW_NO_X11) && defined(RGFW_WAYLAND) +void RGFW_useWayland(b8 wayland) { RGFW_useWaylandBool = wayland; } +#define RGFW_GOTO_WAYLAND(fallback) if (RGFW_useWaylandBool && fallback == 0) goto wayland +#else +#define RGFW_GOTO_WAYLAND(fallback) +void RGFW_useWayland(b8 wayland) { RGFW_UNUSED(wayland); } +#endif + +/* + End of Wayland defines +*/ + +/* - /* normal wayland RGFW stuff */ +Start of Linux / Unix defines + + +*/ + +#ifdef RGFW_UNIX +#if !defined(RGFW_NO_X11_CURSOR) && defined(RGFW_X11) +#include +#endif + +#include + +#ifndef RGFW_NO_DPI +#include +#include +#endif + +#include +#include +#include +#include + +#include /* for converting keycode to string */ +#include /* for hiding */ +#include +#include +#include + +#include /* for data limits (mainly used in drag and drop functions) */ +#include + + +#if defined(__linux__) && !defined(RGFW_NO_LINUX) +#include +#endif + +u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; +/*atoms needed for drag and drop*/ +Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList; +Atom RGFW_XUTF8_STRING = 0; + +Atom wm_delete_window = 0, RGFW_XCLIPBOARD = 0; + +#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int); + typedef void (*PFN_XcursorImageDestroy)(XcursorImage*); + typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*); +#endif +#ifdef RGFW_OPENGL + typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); +#endif + +#if !defined(RGFW_NO_X11_XI_PRELOAD) + typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int); + PFN_XISelectEvents XISelectEventsSRC = NULL; + #define XISelectEvents XISelectEventsSRC + + void* X11Xihandle = NULL; +#endif + +#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + PFN_XcursorImageLoadCursor XcursorImageLoadCursorSRC = NULL; + PFN_XcursorImageCreate XcursorImageCreateSRC = NULL; + PFN_XcursorImageDestroy XcursorImageDestroySRC = NULL; + + #define XcursorImageLoadCursor XcursorImageLoadCursorSRC + #define XcursorImageCreate XcursorImageCreateSRC + #define XcursorImageDestroy XcursorImageDestroySRC + + void* X11Cursorhandle = NULL; +#endif + +u32 RGFW_windowsOpen = 0; + +#if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); } +#endif + +RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi); +void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) { + RGFW_GOTO_WAYLAND(0); + + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_X11 + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = (u8*)RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: createing a 4 channel %i by %i buffer\n", RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + + #ifdef RGFW_OSMESA + win->src.ctx = OSMesaCreateContext(OSMESA_BGRA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + + win->src.bitmap = XCreateImage( + win->src.display, XDefaultVisual(win->src.display, vi->screen), + vi->depth, + ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, + 32, 0 + ); + + win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); + #endif + #ifdef RGFW_WAYLAND + wayland: + size_t size = win->r.w * win->r.h * 4; + int fd = create_shm_file(size); + if (fd < 0) { + fprintf(stderr, "Failed to create a buffer. size: %ld\n", size); + exit(1); + } + + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = (u8*)RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->src.buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (win->src.buffer == MAP_FAILED) { + fprintf(stderr, "mmap failed!\n"); + close(fd); + exit(1); + } + + win->_flags |= RGFW_BUFFER_ALLOC; + + struct wl_shm_pool* pool = wl_shm_create_pool(win->src.shm, fd, size); + win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4, + WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + + close(fd); + + wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); + wl_surface_commit(win->src.surface); + + u8 color[] = {0x00, 0x00, 0x00, 0xFF}; + + size_t i; + for (i = 0; i < RGFW_bufferSize.w * RGFW_bufferSize.h * 4; i += 4) { + RGFW_MEMCPY(&win->buffer[i], color, 4); + } + + RGFW_MEMCPY(win->src.buffer, win->buffer, win->r.w * win->r.h * 4); + + #if defined(RGFW_OSMESA) + win->src.ctx = OSMesaCreateContext(OSMESA_BGRA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + #endif + #else + wayland: + RGFW_UNUSED(win); + RGFW_UNUSED(vi); + #endif +} + +#define RGFW_LOAD_ATOM(name) \ + static Atom name = 0; \ + if (name == 0) name = XInternAtom(RGFW_root->src.display, #name, False); + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + RGFW_LOAD_ATOM(_MOTIF_WM_HINTS); + + struct __x11WindowHints { + unsigned long flags, functions, decorations, status; + long input_mode; + } hints; + hints.flags = (1L << 1); + hints.decorations = border; + + XChangeProperty( + win->src.display, win->src.window, + _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, + 32, PropModeReplace, (u8*)&hints, 5 + ); + #endif + #ifdef RGFW_WAYLAND + wayland: + #endif +} + +void RGFW_releaseCursor(RGFW_window* win) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XUngrabPointer(win->src.display, CurrentTime); + + /* disable raw input */ + unsigned char mask[] = { 0 }; + XIEventMask em; + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + /* enable raw input */ + unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; + XISetMask(mask, XI_RawMotion); + + XIEventMask em; + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); + + XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2))); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = dlopen(lib, RTLD_LAZY | RTLD_LOCAL) +#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) name##SRC = (PFN_##name)(void*)dlsym(proc, #name) + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + #ifdef RGFW_USE_XDL + XDL_init(); + #endif + + #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor-1.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so"); + #else + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so.1"); + #endif + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageCreate); + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageDestroy); + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageLoadCursor); + #endif + + #if !defined(RGFW_NO_X11_XI_PRELOAD) + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi-6.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so"); + #else + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so.6"); + #endif + RGFW_PROC_DEF(X11Xihandle, XISelectEvents); + #endif + + XInitThreads(); /*!< init X11 threading*/ + + if (flags & RGFW_windowOpenglSoftware) + setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + + RGFW_window_basic_init(win, rect, flags); + +#ifdef RGFW_WAYLAND + win->src.compositor = NULL; +#endif + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/ + + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + u32* visual_attribs = (u32*)RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); + i32 fbcount; + GLXFBConfig* fbc = glXChooseFBConfig(win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount); + + i32 best_fbc = -1; + + if (fbcount == 0) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to find any valid GLX visual configs\n"); + #endif + return NULL; + } + + u32 i; + for (i = 0; i < (u32)fbcount; i++) { + XVisualInfo* vi = glXGetVisualFromFBConfig(win->src.display, fbc[i]); + if (vi == NULL) + continue; + + XFree(vi); + + i32 samp_buf, samples; + glXGetFBConfigAttrib(win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(win->src.display, fbc[i], GLX_SAMPLES, &samples); + + if ((!(flags & RGFW_windowTransparent) || vi->depth == 32) && + (best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) { + best_fbc = i; + } + } + + if (best_fbc == -1) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to get a valid GLX visual\n"); + #endif + return NULL; + } + + GLXFBConfig bestFbc = fbc[best_fbc]; + + /* Get a visual */ + XVisualInfo* vi = glXGetVisualFromFBConfig(win->src.display, bestFbc); + + XFree(fbc); + #else + XVisualInfo viNorm; + + viNorm.visual = DefaultVisual(win->src.display, DefaultScreen(win->src.display)); + + viNorm.depth = 0; + XVisualInfo* vi = &viNorm; + + XMatchVisualInfo(win->src.display, DefaultScreen(win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ + #endif + /* make X window attrubutes*/ + XSetWindowAttributes swa; + Colormap cmap; + + swa.colormap = cmap = XCreateColormap(win->src.display, + DefaultRootWindow(win->src.display), + vi->visual, AllocNone); + + swa.background_pixmap = None; + swa.border_pixel = 0; + swa.event_mask = event_mask; + + swa.background_pixel = 0; + + /* create the window*/ + win->src.window = XCreateWindow(win->src.display, DefaultRootWindow(win->src.display), win->r.x, win->r.y, win->r.w, win->r.h, + 0, vi->depth, InputOutput, vi->visual, + CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); + + XFreeColors(win->src.display, cmap, NULL, 0, 0); + + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + XFree(vi); + #endif - RGFW_area RGFW_getScreenSize(void) { - RGFW_area area = {}; + // In your .desktop app, if you set the property + // StartupWMClass=RGFW that will assoicate the launcher icon + // with your application - robrohan + + if (RGFW_className == NULL) + RGFW_className = (char*)name; + + XClassHint hint; + hint.res_class = (char*)RGFW_className; + hint.res_name = (char*)name; // just use the window name as the app name + XSetClassHint(win->src.display, win->src.window, &hint); + + if ((flags & RGFW_windowNoInitAPI) == 0) { + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ + i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; + context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; + if (RGFW_profile == RGFW_glCore) + context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else + context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + + if (RGFW_majorVersion || RGFW_minorVersion) { + context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; + context_attribs[3] = RGFW_majorVersion; + context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB; + context_attribs[5] = RGFW_minorVersion; + } + + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) + glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB"); + + GLXContext ctx = NULL; if (RGFW_root != NULL) - /* this isn't right but it's here for buffers */ - area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h); - - /* TODO wayland */ - return area; - } - - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); + ctx = RGFW_root->src.ctx; - /* TODO wayland */ + win->src.ctx = glXCreateContextAttribsARB(win->src.display, bestFbc, ctx, True, context_attribs); + #endif + + RGFW_init_buffer(win, vi); } - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - RGFW_UNUSED(win); RGFW_UNUSED(r); - - /* TODO wayland */ + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif + + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); } + if (flags & RGFW_windowNoResize) { /* make it so the user can't resize the window*/ + XSizeHints sh; + sh.flags = (1L << 4) | (1L << 5); + sh.min_width = sh.max_width = win->r.w; + sh.min_height = sh.max_height = win->r.h; - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - size_t size = win->r.w * win->r.h * 4; - int fd = create_shm_file(size); - if (fd < 0) { - fprintf(stderr, "Failed to create a buffer. size: %ld\n", size); - exit(1); - } + XSetWMSizeHints(win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); - win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (win->buffer == MAP_FAILED) { - fprintf(stderr, "mmap failed!\n"); - close(fd); - exit(1); - } - - struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size); - win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4, - WL_SHM_FORMAT_ARGB8888); - wl_shm_pool_destroy(pool); - - close(fd); - - wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); - wl_surface_commit(win->src.surface); - - u8 color[] = {0x00, 0x00, 0x00, 0xFF}; - - size_t i; - for (i = 0; i < size; i += 4) { - memcpy(&win->buffer[i], color, 4); - } - - #if defined(RGFW_OSMESA) - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - #else - RGFW_UNUSED(win); - #endif + win->_flags |= RGFW_windowNoResize; } - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - RGFW_window* win = RGFW_window_basic_init(rect, args); - - fprintf(stderr, "Warning: RGFW Wayland support is experimental\n"); - - win->src.display = wl_display_connect(NULL); - if (win->src.display == NULL) { - #ifdef RGFW_DEBUG - fprintf(stderr, "Failed to load Wayland display\n"); - #endif - return NULL; - } - - struct wl_registry *registry = wl_display_get_registry(win->src.display); - wl_registry_add_listener(registry, ®istry_listener, NULL); - - wl_display_dispatch(win->src.display); - wl_display_roundtrip(win->src.display); + if (flags & RGFW_windowNoBorder) { + RGFW_window_setBorder(win, 0); + } - if (RGFW_compositor == NULL) { - #ifdef RGFW_DEBUG - fprintf(stderr, "Can't find compositor.\n"); - #endif - - return NULL; - } - - if (RGFW_wl_cursor_theme == NULL) { - RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm); - RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor); - - struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr"); - RGFW_cursor_image = cursor->images[0]; - struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + XSelectInput(win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/ - wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } + /* make it so the user can't close the window until the program does*/ + if (wm_delete_window == 0) { + wm_delete_window = XInternAtom(win->src.display, "WM_DELETE_WINDOW", False); + RGFW_XUTF8_STRING = XInternAtom(win->src.display, "UTF8_STRING", False); + RGFW_XCLIPBOARD = XInternAtom(win->src.display, "CLIPBOARD", False); + } - if (RGFW_root == NULL) - xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL); - - xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + XSetWMProtocols(win->src.display, (Drawable) win->src.window, &wm_delete_window, 1); - win->src.surface = wl_compositor_create_surface(RGFW_compositor); - wl_surface_set_user_data(win->src.surface, win); + /* connect the context to the window*/ + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + if ((flags & RGFW_windowNoInitAPI) == 0) + glXMakeCurrent(win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); + #endif - win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface); - xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL); - - xdg_wm_base_set_user_data(xdg_wm_base, win); + /* set the background*/ + RGFW_window_setName(win, name); - win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface); - xdg_toplevel_set_user_data(win->src.xdg_toplevel, win); - xdg_toplevel_set_title(win->src.xdg_toplevel, name); - xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL); + XMapWindow(win->src.display, (Drawable) win->src.window); /* draw the window*/ + XMoveWindow(win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/ - xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); - - if (!(args & RGFW_NO_BORDER)) { - win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - decoration_manager, win->src.xdg_toplevel); - } + if (flags & RGFW_windowAllowDND) { /* init drag and drop atoms and turn on drag and drop for this window */ + win->_flags |= RGFW_windowAllowDND; - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } + XdndTypeList = XInternAtom(win->src.display, "XdndTypeList", False); + XdndSelection = XInternAtom(win->src.display, "XdndSelection", False); - if (args & RGFW_OPENGL_SOFTWARE) - setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + /* client messages */ + XdndEnter = XInternAtom(win->src.display, "XdndEnter", False); + XdndPosition = XInternAtom(win->src.display, "XdndPosition", False); + XdndStatus = XInternAtom(win->src.display, "XdndStatus", False); + XdndLeave = XInternAtom(win->src.display, "XdndLeave", False); + XdndDrop = XInternAtom(win->src.display, "XdndDrop", False); + XdndFinished = XInternAtom(win->src.display, "XdndFinished", False); - wl_display_roundtrip(win->src.display); + /* actions */ + XdndActionCopy = XInternAtom(win->src.display, "XdndActionCopy", False); - wl_surface_commit(win->src.surface); - - /* wait for the surface to be configured */ - while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { } - - - #ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h); - RGFW_createOpenGLContext(win); - } - #endif + XtextUriList = XInternAtom(win->src.display, "text/uri-list", False); + XtextPlain = XInternAtom(win->src.display, "text/plain", False); - RGFW_init_buffer(win); + XdndAware = XInternAtom(win->src.display, "XdndAware", False); + const u8 version = 5; - struct wl_callback* callback = wl_surface_frame(win->src.surface); - wl_callback_add_listener(callback, &wl_surface_frame_listener, win); - wl_surface_commit(win->src.surface); + XChangeProperty(win->src.display, win->src.window, + XdndAware, 4, 32, + PropModeReplace, &version, 1); /*!< turns on drag and drop */ + } - if (args & RGFW_HIDE_MOUSE) { - RGFW_window_showMouse(win, 0); - } - - if (RGFW_root == NULL) { - RGFW_root = win; - } - - win->src.eventIndex = 0; - win->src.eventLen = 0; - - #ifdef RGFW_DEBUG + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) + RGFW_createOpenGLContext(win); + #endif + #ifdef RGFW_DEBUG printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); - #endif - - return win; - } + #endif + RGFW_window_setMouseDefault(win); + RGFW_windowsOpen++; + return win; /*return newly created window*/ +#endif +#ifdef RGFW_WAYLAND + wayland: + fprintf(stderr, "Warning: RGFW Wayland support is experimental\n"); - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - if (win->_winArgs & RGFW_WINDOW_HIDE) - return NULL; - - if (win->src.eventIndex == 0) { - if (wl_display_roundtrip(win->src.display) == -1) { - return NULL; - } - RGFW_resetKey(); - } - - #ifdef __linux__ - RGFW_Event* event = RGFW_linux_updateGamepad(win); - if (event != NULL) - return event; - #endif - - if (win->src.eventLen == 0) { - return NULL; - } - - RGFW_Event ev = RGFW_eventPipe_pop(win); - - if (ev.type == 0 || win->event.type == RGFW_quit) { - return NULL; - } - - ev.frameTime = win->event.frameTime; - ev.frameTime2 = win->event.frameTime2; - ev.inFocus = win->event.inFocus; - win->event = ev; - - return &win->event; - } - - - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - RGFW_UNUSED(win); RGFW_UNUSED(v); - - /* TODO wayland */ - assert(win != NULL); - struct wl_pointer *pointer = wl_seat_get_pointer(win->seat); - if (!pointer) { - return; - } - - // Initiate the move operation - wl_shell_surface_move(win->shell_surface, pointer, win->serial); - win->r.x = v.x; - win->r.y = v.y; - - wl_display_flush(win->display); - } - - void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { - RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels) - /* TODO wayland */ - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { - win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); + win->src.wl_display = wl_display_connect(NULL); + if (win->src.wl_display == NULL) { #ifdef RGFW_DEBUG - printf("Wayland: The platform does not support moving the mouse\n"); + fprintf(stderr, "Failed to load Wayland display\n"); #endif - /* TODO wayland */ + #ifdef RGFW_X11 + fprintf(stderr, "Falling back to X11\n"); + RGFW_useWayland(0); + return RGFW_createWindowPtr(name, rect, flags, win); + #endif + return NULL; } - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - RGFW_UNUSED(win); - if (show) { + #ifdef RGFW_X11 + XSetWindowAttributes attributes; + attributes.background_pixel = 0; + attributes.override_redirect = True; + win->src.window = XCreateWindow(win->src.display, DefaultRootWindow(win->src.display), 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, + CWBackPixel | CWOverrideRedirect, &attributes); + + XMapWindow(win->src.display, win->src.window); + XFlush(win->src.display); + if (wm_delete_window == 0) { + wm_delete_window = XInternAtom(win->src.display, "WM_DELETE_WINDOW", False); + RGFW_XUTF8_STRING = XInternAtom(win->src.display, "UTF8_STRING", False); + RGFW_XCLIPBOARD = XInternAtom(win->src.display, "CLIPBOARD", False); } - else { - - } + #endif - /* TODO wayland */ + struct wl_registry *registry = wl_display_get_registry(win->src.wl_display); + wl_registry_add_listener(registry, ®istry_listener, win); + + wl_display_roundtrip(win->src.wl_display); + wl_display_dispatch(win->src.wl_display); + + if (win->src.compositor == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Can't find compositor.\n"); + #endif + + return NULL; } - b8 RGFW_window_isMaximized(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } + if (RGFW_wl_cursor_theme == NULL) { + RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, win->src.shm); + RGFW_cursor_surface = wl_compositor_create_surface(win->src.compositor); - b8 RGFW_window_isMinimized(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - b8 RGFW_window_isHidden(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - b8 RGFW_window_isFullscreen(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return RGFW_POINT(0, 0); - } - - RGFW_point RGFW_getGlobalMousePoint(void) { - /* TODO wayland */ - return RGFW_POINT(0, 0); - } - - void RGFW_window_show(RGFW_window* win) { - //wl_surface_attach(win->src.surface, win->rc., 0, 0); - wl_surface_commit(win->src.surface); - - if (win->_winArgs & RGFW_WINDOW_HIDE) - win->_winArgs ^= RGFW_WINDOW_HIDE; - } - - void RGFW_window_hide(RGFW_window* win) { - wl_surface_attach(win->src.surface, NULL, 0, 0); - wl_surface_commit(win->src.surface); - win->_winArgs |= RGFW_WINDOW_HIDE; - } - - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_UNUSED(win); - - RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - RGFW_UNUSED(win); - - static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" }; - - struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr"); RGFW_cursor_image = cursor->images[0]; struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } - - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels) - //struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); - //RGFW_cursor_image = image; - struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); - - wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - xdg_toplevel_set_title(win->src.xdg_toplevel, name); - } - - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - RGFW_UNUSED(win); RGFW_UNUSED(passthrough); - - /* TODO wayland */ - } - - void RGFW_window_setBorder(RGFW_window* win, b8 border) { - RGFW_UNUSED(win); RGFW_UNUSED(border); - - /* TODO wayland */ - } - - void RGFW_window_restore(RGFW_window* win) { - RGFW_UNUSED(win); - - /* TODO wayland */ - } - - void RGFW_window_minimize(RGFW_window* win) { - RGFW_UNUSED(win); - - /* TODO wayland */ - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ + wl_surface_commit(RGFW_cursor_surface); } - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - RGFW_monitor m = {}; - RGFW_UNUSED(win); - RGFW_UNUSED(m); - /* TODO wayland */ + xdg_wm_base_add_listener(win->src.xdg_wm_base, &xdg_wm_base_listener, NULL); - return m; + xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + win->src.surface = wl_compositor_create_surface(win->src.compositor); + wl_surface_set_user_data(win->src.surface, win); + + win->src.xdg_surface = xdg_wm_base_get_xdg_surface(win->src.xdg_wm_base, win->src.surface); + xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL); + + xdg_wm_base_set_user_data(win->src.xdg_wm_base, win); + + win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface); + xdg_toplevel_set_user_data(win->src.xdg_toplevel, win); + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL); + + xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); + + if (!(flags & RGFW_windowNoBorder)) { + win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + decoration_manager, win->src.xdg_toplevel); } + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } - #ifndef RGFW_EGL - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); } + if (flags & RGFW_windowOpenglSoftware) + setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + + wl_display_roundtrip(win->src.wl_display); + + wl_surface_commit(win->src.surface); + + /* wait for the surface to be configured */ + while (wl_display_dispatch(win->src.wl_display) != -1 && !RGFW_wl_configured) { } + + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { + win->src.eglWindow = wl_egl_window_create(win->src.surface, win->r.w, win->r.h); + RGFW_createOpenGLContext(win); + } #endif - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); + RGFW_init_buffer(win, NULL); - /* clear the window*/ - #ifdef RGFW_BUFFER - wl_surface_frame_done(win, NULL, 0); - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) - #endif - { - #ifdef RGFW_OPENGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #endif - } - - wl_display_flush(win->src.display); + struct wl_callback* callback = wl_surface_frame(win->src.surface); + wl_callback_add_listener(callback, &wl_surface_frame_listener, win); + wl_surface_commit(win->src.surface); + + if (flags & RGFW_windowHideMouse) { + RGFW_window_showMouse(win, 0); } - void RGFW_window_close(RGFW_window* win) { + win->src.eventIndex = 0; + win->src.eventLen = 0; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif + + RGFW_window_setMouseDefault(win); + RGFW_windowsOpen++; + return win; /*return newly created window*/ +#endif +} + +RGFW_area RGFW_getScreenSize(void) { + RGFW_GOTO_WAYLAND(1); + RGFW_ASSERT(RGFW_root != NULL); + + #ifdef RGFW_X11 + Screen* scrn = DefaultScreenOfDisplay(RGFW_root->src.display); + return RGFW_AREA(scrn->width, scrn->height); + #endif + #ifdef RGFW_WAYLAND + wayland: return RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h); // TODO + #endif +} + +RGFW_point RGFW_getGlobalMousePoint(void) { + RGFW_ASSERT(RGFW_root != NULL); + + RGFW_point RGFWMouse; + + i32 x, y; + u32 z; + Window window1, window2; + XQueryPointer(RGFW_root->src.display, XDefaultRootWindow(RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z); + + return RGFWMouse; +} + +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + RGFW_point RGFWMouse; + + i32 x, y; + u32 z; + Window window1, window2; + XQueryPointer(win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z); + + return RGFWMouse; +} + +char* RGFW_strtok(char* str, const char* delimStr) { + static char* static_str = NULL; + + if (str != NULL) + static_str = str; + + if (static_str == NULL) { + return NULL; + } + + while (*static_str != '\0') { + b8 delim = 0; + for (const char* d = delimStr; *d != '\0'; d++) { + if (*static_str == *d) { + delim = 1; + break; + } + } + if (!delim) + break; + static_str++; + } + + if (*static_str == '\0') + return NULL; + + char* token_start = static_str; + while (*static_str != '\0') { + int delim = 0; + for (const char* d = delimStr; *d != '\0'; d++) { + if (*static_str == *d) { + delim = 1; + break; + } + } + + if (delim) { + *static_str = '\0'; + static_str++; + break; + } + static_str++; + } + + return token_start; +} +int xAxis = 0, yAxis = 0; + +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + if (win->event.type == 0) + RGFW_resetKey(); + + if (win->event.type == RGFW_quit) { + return NULL; + } + + win->event.type = 0; + + #if defined(__linux__) && !defined(RGFW_NO_LINUX) + if (RGFW_linux_updateGamepad(win)) return &win->event; + #endif + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XPending(win->src.display); + + XEvent E; /*!< raw X11 event */ + + /* if there is no unread qued events, get a new one */ + if ((QLength(win->src.display) || XEventsQueued(win->src.display, QueuedAlready) + XEventsQueued(win->src.display, QueuedAfterReading)) + && win->event.type != RGFW_quit + ) + XNextEvent(win->src.display, &E); + else { + return NULL; + } + + win->event.type = 0; + + /* xdnd data */ + Window source = 0; + long version = 0; + i32 format = 0; + + XEvent reply = { ClientMessage }; + + switch (E.type) { + case KeyPress: + case KeyRelease: { + win->event.repeat = RGFW_FALSE; + /* check if it's a real key release */ + if (E.type == KeyRelease && XEventsQueued(win->src.display, QueuedAfterReading)) { /* get next event if there is one*/ + XEvent NE; + XPeekEvent(win->src.display, &NE); + + if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/ + win->event.repeat = RGFW_TRUE; + } + + /* set event key data */ + win->event.key = RGFW_apiKeyToRGFW(E.xkey.keycode); + + KeySym sym = (KeySym)XkbKeycodeToKeysym(win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); + + if ((E.xkey.state & LockMask) && sym >= XK_a && sym <= XK_z) + sym = (E.xkey.state & ShiftMask) ? sym + 32 : sym - 32; + if ((u8)sym != (u32)sym) + sym = 0; + + win->event.keyChar = (u8)sym; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + + /* get keystate data */ + win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; + + XKeyboardState keystate; + XGetKeyboardControl(win->src.display, &keystate); + + RGFW_keyboard[win->event.key].current = (E.type == KeyPress); + RGFW_updateKeyMods(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, (E.type == KeyPress)); + break; + } + case ButtonPress: + case ButtonRelease: + win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match + + win->event.button = E.xbutton.button; + switch(win->event.button) { + case RGFW_mouseScrollUp: + win->event.scroll = 1; + break; + case RGFW_mouseScrollDown: + win->event.scroll = -1; + break; + default: break; + } + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + + if (win->event.repeat == RGFW_FALSE) + win->event.repeat = RGFW_isPressed(win, win->event.key); + + RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); + break; + + case MotionNotify: + win->event.point.x = E.xmotion.x; + win->event.point.y = E.xmotion.y; + + if ((win->_flags & RGFW_HOLD_MOUSE)) { + win->event.point.y = E.xmotion.y; + + win->event.point.x = win->event.point.x - win->_lastMousePoint.x; + win->event.point.y = win->event.point.y - win->_lastMousePoint.y; + } + + win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); + + win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + break; + + case GenericEvent: { + /* MotionNotify is used for mouse events if the mouse isn't held */ + if (!(win->_flags & RGFW_HOLD_MOUSE)) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + XGetEventData(win->src.display, &E.xcookie); + if (E.xcookie.evtype == XI_RawMotion) { + XIRawEvent *raw = (XIRawEvent *)E.xcookie.data; + if (raw->valuators.mask_len == 0) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + double deltaX = 0.0f; + double deltaY = 0.0f; + + /* check if relative motion data exists where we think it does */ + if (XIMaskIsSet(raw->valuators.mask, 0) != 0) + deltaX += raw->raw_values[0]; + if (XIMaskIsSet(raw->valuators.mask, 1) != 0) + deltaY += raw->raw_values[1]; + + win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY); + + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); + + win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + } + + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + case Expose: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + break; + + case ClientMessage: { + /* if the client closed the window*/ + if (E.xclient.data.l[0] == (long)wm_delete_window) { + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + break; + } + + for (size_t i = 0; i < win->event.droppedFilesCount; i++) { + win->event.droppedFiles[i][0] = '\0'; + } + win->event.droppedFilesCount = 0; + + if ((win->_flags & RGFW_windowAllowDND) == 0) + break; + + reply.xclient.window = source; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long)win->src.window; + reply.xclient.data.l[1] = 0; + reply.xclient.data.l[2] = None; + + if (E.xclient.message_type == XdndEnter) { + if (version > 5) + break; + + unsigned long count; + Atom* formats; + Atom real_formats[6]; + Bool list = E.xclient.data.l[1] & 1; + + source = E.xclient.data.l[0]; + version = E.xclient.data.l[1] >> 24; + format = None; + + if (list) { + Atom actualType; + i32 actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty( + win->src.display, source, XdndTypeList, + 0, LONG_MAX, False, 4, + &actualType, &actualFormat, &count, &bytesAfter, (u8**)&formats + ); + } else { + count = 0; + + for (size_t i = 2; i < 5; i++) { + Window format = E.xclient.data.l[i]; + if (format != None) { + real_formats[count] = format; + count += 1; + } + } + + formats = real_formats; + } + + for (size_t i = 0; i < count; i++) { + if (formats[i] == XtextUriList || formats[i] == XtextPlain) { + format = (int)formats[i]; + break; + } + } + + if (list) { + XFree(formats); + } + + break; + } + + if (E.xclient.message_type == XdndPosition) { + const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff; + const i32 yabs = (E.xclient.data.l[2]) & 0xffff; + Window dummy; + i32 xpos, ypos; + + if (version > 5) + break; + + XTranslateCoordinates( + win->src.display, XDefaultRootWindow(win->src.display), win->src.window, + xabs, yabs, &xpos, &ypos, &dummy + ); + + win->event.point.x = xpos; + win->event.point.y = ypos; + + reply.xclient.window = source; + reply.xclient.message_type = XdndStatus; + + if (format) { + reply.xclient.data.l[1] = 1; + if (version >= 2) + reply.xclient.data.l[4] = (long)XdndActionCopy; + } + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + break; + } + + if (E.xclient.message_type != XdndDrop) + break; + + if (version > 5) + break; + + win->event.type = RGFW_DNDInit; + + if (format) { + Time time = (version >= 1) + ? (Time)E.xclient.data.l[2] + : CurrentTime; + + XConvertSelection( + win->src.display, XdndSelection, (Atom)format, + XdndSelection, win->src.window, time + ); + } else if (version >= 2) { + XEvent reply = { ClientMessage }; + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + } + + RGFW_dndInitCallback(win, win->event.point); + } break; + case SelectionNotify: { + /* this is only for checking for xdnd drops */ + if (E.xselection.property != XdndSelection || !(win->_flags & RGFW_windowAllowDND)) + break; + + char* data; + unsigned long result; + + Atom actualType; + i32 actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty(win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data); + + if (result == 0) + break; + + const char* prefix = (const char*)"file://"; + + char* line; + + win->event.droppedFilesCount = 0; + + win->event.type = RGFW_DND; + + while ((line = (char*)RGFW_strtok(data, "\r\n"))) { + char path[RGFW_MAX_PATH]; + + data = NULL; + + if (line[0] == '#') + continue; + + char* l; + for (l = line; 1; l++) { + if ((l - line) > 7) + break; + else if (*l != prefix[(l - line)]) + break; + else if (*l == '\0' && prefix[(l - line)] == '\0') { + line += 7; + while (*line != '/') + line++; + break; + } else if (*l == '\0') + break; + } + + win->event.droppedFilesCount++; + + size_t index = 0; + while (*line) { + if (line[0] == '%' && line[1] && line[2]) { + const char digits[3] = { line[1], line[2], '\0' }; + path[index] = (char) RGFW_STRTOL(digits, NULL, 16); + line += 2; + } else + path[index] = *line; + + index++; + line++; + } + path[index] = '\0'; + RGFW_MEMCPY(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); + } + + if (data) + XFree(data); + + if (version >= 2) { + XEvent reply = { ClientMessage }; + reply.xclient.format = 32; + reply.xclient.message_type = XdndFinished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = XdndActionCopy; + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + } + + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + break; + } + case FocusIn: + win->event.inFocus = 1; + win->event.type = RGFW_focusIn; + RGFW_focusCallback(win, 1); + break; + case FocusOut: + win->event.inFocus = 0; + win->event.type = RGFW_focusOut; + RGFW_focusCallback(win, 0); + break; + case EnterNotify: { + win->event.type = RGFW_mouseEnter; + win->event.point.x = E.xcrossing.x; + win->event.point.y = E.xcrossing.y; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; + } + + case LeaveNotify: { + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + } + + case ConfigureNotify: { + /* detect resize */ + if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) { + win->event.type = RGFW_windowResized; + win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); + RGFW_windowResizeCallback(win, win->r); + break; + } + + /* detect move */ + if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) { + win->event.type = RGFW_windowMoved; + win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); + RGFW_windowMoveCallback(win, win->r); + break; + } + + break; + } + default: + XFlush(win->src.display); + return RGFW_window_checkEvent(win); + } + + XFlush(win->src.display); + if (win->event.type) return &win->event; + else return NULL; +#endif +#ifdef RGFW_WAYLAND + wayland: + if (win->_flags & RGFW_windowHide) + return NULL; + + if (win->src.eventIndex == 0) { + if (wl_display_roundtrip(win->src.wl_display) == -1) { + return NULL; + } + } + + if (win->src.eventLen == 0) { + return NULL; + } + + RGFW_event ev = RGFW_eventPipe_pop(win); + + if (ev.type == 0 || win->event.type == RGFW_quit) { + return NULL; + } + + ev.frameTime = win->event.frameTime; + ev.frameTime2 = win->event.frameTime2; + ev.inFocus = win->event.inFocus; + win->event = ev; + if (win->event.type) return &win->event; + else return NULL; +#endif +} + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + win->r.x = v.x; + win->r.y = v.y; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XMoveWindow(win->src.display, win->src.window, v.x, v.y); +#endif +#ifdef RGFW_WAYLAND + wayland: + RGFW_ASSERT(win != NULL); + + if (win->src.compositor) { + struct wl_pointer *pointer = wl_seat_get_pointer(win->src.seat); + if (!pointer) { + return; + } + + wl_display_flush(win->src.wl_display); + } +#endif +} + + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->r.w = a.w; + win->r.h = a.h; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XResizeWindow(win->src.display, win->src.window, a.w, a.h); + + if (!(win->_flags & RGFW_windowNoResize)) + return; + + XSizeHints sh; + sh.flags = (1L << 4) | (1L << 5); + sh.min_width = sh.max_width = a.w; + sh.min_height = sh.max_height = a.h; + + XSetWMSizeHints(win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); +#endif +#ifdef RGFW_WAYLAND + wayland: + if (win->src.compositor) { + xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); + #ifdef RGFW_OPENGL + wl_egl_window_resize(win->src.eglWindow, a.w, a.h, 0, 0); + #endif + } +#endif +} + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + if (a.w == 0 && a.h == 0) + return; + + XSizeHints hints; + long flags; + + XGetWMNormalHints(win->src.display, win->src.window, &hints, &flags); + + hints.flags |= PMinSize; + + hints.min_width = a.w; + hints.min_height = a.h; + + XSetWMNormalHints(win->src.display, win->src.window, &hints); +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + if (a.w == 0 && a.h == 0) + return; + + XSizeHints hints; + long flags; + + XGetWMNormalHints(win->src.display, win->src.window, &hints, &flags); + + hints.flags |= PMaxSize; + + hints.max_width = a.w; + hints.max_height = a.h; + + XSetWMNormalHints(win->src.display, win->src.window, &hints); +} + + +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XIconifyWindow(win->src.display, win->src.window, DefaultScreen(win->src.display)); + XFlush(win->src.display); +} + +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XMapWindow(win->src.display, win->src.window); + XFlush(win->src.display); +} + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win); + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + XStoreName(win->src.display, win->src.window, name); + + RGFW_LOAD_ATOM(_NET_WM_NAME); + XChangeProperty( + win->src.display, win->src.window, _NET_WM_NAME, RGFW_XUTF8_STRING, + 8, PropModeReplace, (u8*)name, 256 + ); + #endif + #ifdef RGFW_WAYLAND + wayland: + if (win->src.compositor) + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + #endif +} + +void* RGFW_libxshape = NULL; + +#ifndef RGFW_NO_PASSTHROUGH + +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_ASSERT(win != NULL); + + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext-6.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext.so"); + #else + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext.so.6"); + #endif + + typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); + static PFN_XShapeCombineMask XShapeCombineMaskSRC; + + typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); + static PFN_XShapeCombineRegion XShapeCombineRegionSRC; + + RGFW_PROC_DEF(RGFW_libxshape, XShapeCombineRegion); + RGFW_PROC_DEF(RGFW_libxshape, XShapeCombineMask); + + if (passthrough) { + Region region = XCreateRegion(); + XShapeCombineRegionSRC(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + + return; + } + + XShapeCombineMaskSRC(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet); +} + +#endif /* RGFW_NO_PASSTHROUGH */ + +b32 RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { + RGFW_ASSERT(win != NULL); RGFW_ASSERT(icon != NULL); + RGFW_ASSERT(channels == 3 || channels == 4); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + i32 count = 2 + (a.w * a.h); + + unsigned long* data = (unsigned long*) RGFW_alloc(count * sizeof(unsigned long)); + data[0] = (unsigned long)a.w; + data[1] = (unsigned long)a.h; + + unsigned long* target = &data[2]; + + u32 x, y; + + for (x = 0; x < a.w; x++) { + for (y = 0; y < a.h; y++) { + size_t i = y * a.w + x; + u32 alpha = (channels == 4) ? icon[i * 4 + 3] : 0xFF; + + target[i] = (unsigned long)((icon[i * 4 + 0]) << 16) | + (unsigned long)((icon[i * 4 + 1]) << 8) | + (unsigned long)((icon[i * 4 + 2]) << 0) | + (unsigned long)(alpha << 24); + } + } + + RGFW_LOAD_ATOM(_NET_WM_ICON); + + b32 res = (b32)XChangeProperty( + win->src.display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32, + PropModeReplace, (u8*)data, count + ); + + RGFW_free(data); + + XFlush(win->src.display); + return res; +#endif +#ifdef RGFW_WAYLAND + wayland: + return 0; +#endif +} + +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + RGFW_ASSERT(icon); + RGFW_ASSERT(channels == 3 || channels == 4); + RGFW_GOTO_WAYLAND(0); + +#ifdef RGFW_X11 +#ifndef RGFW_NO_X11_CURSOR + XcursorImage* native = XcursorImageCreate(a.w, a.h); + native->xhot = 0; + native->yhot = 0; + + XcursorPixel* target = native->pixels; + for (size_t x = 0; x < a.w; x++) { + for (size_t y = 0; y < a.h; y++) { + size_t i = y * a.w + x; + u32 alpha = (channels == 4) ? icon[i * 4 + 3] : 0xFF; + + target[i] = (u32)((icon[i * 4 + 0]) << 16) + | (u32)((icon[i * 4 + 1]) << 8) + | (u32)((icon[i * 4 + 2]) << 0) + | (u32)(alpha << 24); + } + } + + Cursor cursor = XcursorImageLoadCursor(RGFW_root->src.display, native); + XcursorImageDestroy(native); + + return (void*)cursor; +#else + RGFW_UNUSED(image); RGFW_UNUSED(a.w); RGFW_UNUSED(channels); + return NULL; +#endif +#endif +#ifdef RGFW_WAYLAND + wayland: + RGFW_UNUSED(icon); RGFW_UNUSED(a); RGFW_UNUSED(channels); + return NULL; // TODO +#endif +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + RGFW_ASSERT(win && mouse); + XDefineCursor(win->src.display, win->src.window, (Cursor)mouse); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + RGFW_ASSERT(mouse); + XFreeCursor(RGFW_root->src.display, (Cursor)mouse); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { +RGFW_GOTO_WAYLAND(1); +#ifdef RGFW_X11 + RGFW_ASSERT(win != NULL); + + XEvent event; + XQueryPointer(win->src.display, DefaultRootWindow(win->src.display), + &event.xbutton.root, &event.xbutton.window, + &event.xbutton.x_root, &event.xbutton.y_root, + &event.xbutton.x, &event.xbutton.y, + &event.xbutton.state); + + win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); + if (event.xbutton.x == p.x && event.xbutton.y == p.y) + return; + + XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) p.x - win->r.x, (int) p.y - win->r.y); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8))) + return 0; + + mouse = RGFW_mouseIconSrc[mouse]; + + Cursor cursor = XCreateFontCursor(win->src.display, mouse); + XDefineCursor(win->src.display, win->src.window, (Cursor) cursor); + + XFreeCursor(win->src.display, (Cursor) cursor); + return 1; +#endif +#ifdef RGFW_WAYLAND + wayland: + static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" }; + + struct wl_cursor* wlcursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + RGFW_cursor_image = wlcursor->images[0]; + struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + + wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(RGFW_cursor_surface); + return 1; +#endif +} + +void RGFW_window_hide(RGFW_window* win) { + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XMapWindow(win->src.display, win->src.window); +#endif +#ifdef RGFW_WAYLAND + wayland: + wl_surface_attach(win->src.surface, NULL, 0, 0); + wl_surface_commit(win->src.surface); + win->_flags |= RGFW_windowHide; +#endif +} + +void RGFW_window_show(RGFW_window* win) { + if (win->_flags & RGFW_windowHide) + win->_flags ^= RGFW_windowHide; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XUnmapWindow(win->src.display, win->src.window); +#endif +#ifdef RGFW_WAYLAND + wayland: + //wl_surface_attach(win->src.surface, win->rc., 0, 0); + wl_surface_commit(win->src.surface); +#endif +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + XEvent event; + int format; + unsigned long N, sizeN; + char* data; + Atom target; + + RGFW_LOAD_ATOM(XSEL_DATA); + + XConvertSelection(RGFW_root->src.display, RGFW_XCLIPBOARD, RGFW_XUTF8_STRING, XSEL_DATA, RGFW_root->src.window, CurrentTime); + XSync(RGFW_root->src.display, 0); + XNextEvent(RGFW_root->src.display, &event); + + if (event.type != SelectionNotify || event.xselection.selection != RGFW_XCLIPBOARD || event.xselection.property == 0) + return -1; + + XGetWindowProperty(event.xselection.display, event.xselection.requestor, + event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target, + &format, &sizeN, &N, (unsigned char**) &data); + + RGFW_ssize_t size; + if (sizeN > strCapacity && str != NULL) + size = -1; + + if ((target == RGFW_XUTF8_STRING || target == XA_STRING) && str != NULL) { + RGFW_MEMCPY(str, data, sizeN); + str[sizeN] = '\0'; + XFree(data); + } else if (str != NULL) size = -1; + + XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property); + size = sizeN; + return size; + #endif + #if defined(RGFW_WAYLAND) + wayland: return 0; + #endif +} + +void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + RGFW_LOAD_ATOM(SAVE_TARGETS); + RGFW_LOAD_ATOM(TARGETS); + RGFW_LOAD_ATOM(MULTIPLE); + RGFW_LOAD_ATOM(ATOM_PAIR); + RGFW_LOAD_ATOM(CLIPBOARD_MANAGER); + + XSetSelectionOwner(RGFW_root->src.display, RGFW_XCLIPBOARD, RGFW_root->src.window, CurrentTime); + + XConvertSelection(RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, RGFW_root->src.window, CurrentTime); + for (;;) { + XEvent event; + + XNextEvent(RGFW_root->src.display, &event); + if (event.type != SelectionRequest) { + break; + } + + const XSelectionRequestEvent* request = &event.xselectionrequest; + + XEvent reply = { SelectionNotify }; + reply.xselection.property = 0; + + if (request->target == TARGETS) { + const Atom targets[] = { TARGETS, + MULTIPLE, + RGFW_XUTF8_STRING, + XA_STRING }; + + XChangeProperty(RGFW_root->src.display, + request->requestor, + request->property, + 4, + 32, + PropModeReplace, + (u8*) targets, + sizeof(targets) / sizeof(targets[0])); + + reply.xselection.property = request->property; + } + + if (request->target == MULTIPLE) { + Atom* targets = NULL; + + Atom actualType = 0; + int actualFormat = 0; + unsigned long count = 0, bytesAfter = 0; + + XGetWindowProperty(RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); + + unsigned long i; + for (i = 0; i < (u32)count; i += 2) { + if (targets[i] == RGFW_XUTF8_STRING || targets[i] == XA_STRING) { + XChangeProperty(RGFW_root->src.display, + request->requestor, + targets[i + 1], + targets[i], + 8, + PropModeReplace, + (u8*) text, + textLen); + XFlush(RGFW_root->src.display); + } else { + targets[i + 1] = None; + } + } + + XChangeProperty(RGFW_root->src.display, + request->requestor, + request->property, + ATOM_PAIR, + 32, + PropModeReplace, + (u8*) targets, + count); + + XFlush(RGFW_root->src.display); + XFree(targets); + + reply.xselection.property = request->property; + } + + reply.xselection.display = request->display; + reply.xselection.requestor = request->requestor; + reply.xselection.selection = request->selection; + reply.xselection.target = request->target; + reply.xselection.time = request->time; + + XSendEvent(RGFW_root->src.display, request->requestor, False, 0, &reply); + XFlush(RGFW_root->src.display); + } + #endif + #if defined(RGFW_WAYLAND) + wayland: + #endif +} + +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XWindowAttributes windowAttributes; + XGetWindowAttributes(win->src.display, win->src.window, &windowAttributes); + + /* check if the window is visable */ + if (windowAttributes.map_state != IsViewable) + return 0; + + /* check if the window covers the full screen */ + return (windowAttributes.x == 0 && windowAttributes.y == 0 && + windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) && + windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display))); +} + +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XWindowAttributes windowAttributes; + XGetWindowAttributes(win->src.display, win->src.window, &windowAttributes); + + return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win)); +} + +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + RGFW_LOAD_ATOM(WM_STATE); + + Atom actual_type; + i32 actual_format; + unsigned long nitems, bytes_after; + unsigned char* prop_data; + + i16 status = XGetWindowProperty(win->src.display, win->src.window, WM_STATE, 0, 2, False, + AnyPropertyType, &actual_type, &actual_format, + &nitems, &bytes_after, &prop_data); + + if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) { + XFree(prop_data); + return 1; + } + + if (prop_data != NULL) + XFree(prop_data); + + return 0; +} + +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_LOAD_ATOM(_NET_WM_STATE); + RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT); + RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ); + + Atom actual_type; + i32 actual_format; + unsigned long nitems, bytes_after; + unsigned char* prop_data; + + i16 status = XGetWindowProperty(win->src.display, win->src.window, _NET_WM_STATE, 0, 1024, False, + XA_ATOM, &actual_type, &actual_format, + &nitems, &bytes_after, &prop_data); + + if (status != Success) { + if (prop_data != NULL) + XFree(prop_data); + + return 0; + } + + Atom* atoms = (Atom*) prop_data; + u64 i; + for (i = 0; i < nitems; ++i) { + if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT || + atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) { + XFree(prop_data); + return 1; + } + } + + return 0; +} + +static float XGetSystemContentDPI(Display* display, i32 screen) { + float dpi = 96.0f; + + #ifndef RGFW_NO_DPI + RGFW_UNUSED(screen); + char* rms = XResourceManagerString(display); + XrmDatabase db = NULL; + + if (rms && db) { + db = XrmGetStringDatabase(rms); + XrmValue value; + char* type = NULL; + + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0) { + dpi = (float)atof(value.addr); + } + XrmDestroyDatabase(db); + } + #else + dpi = RGFW_ROUND(DisplayWidth(display, screen) / (DisplayWidthMM(display, screen) / 25.4)); + #endif + + return dpi; +} + +RGFW_monitor RGFW_XCreateMonitor(i32 screen) { + RGFW_monitor monitor; + + Display* display = XOpenDisplay(NULL); + + RGFW_area size = RGFW_getScreenSize(); + + monitor.rect = RGFW_RECT(0, 0, size.w, size.h); + monitor.physW = DisplayWidthMM(display, screen) / 25.4; + monitor.physH = DisplayHeightMM(display, screen) / 25.4; + + char* name = XDisplayName((const char*)display); + RGFW_MEMCPY(monitor.name, name, 128); + + float dpi = XGetSystemContentDPI(display, screen); + monitor.pixelRatio = dpi / 96.0f; + + #ifndef RGFW_NO_DPI + XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); + + XRRCrtcInfo* ci = NULL; + int crtc = screen; + + if (sr->ncrtc > crtc) { + ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); + } + #endif + + float ppi_width = RGFW_ROUND((float)monitor.rect.w/(float)monitor.physW); + float ppi_height = RGFW_ROUND((float)monitor.rect.h/(float)monitor.physH); + + monitor.scaleX = (float) (ppi_width) / dpi; + monitor.scaleY = (float) (ppi_height) / dpi; + + #ifndef RGFW_NO_DPI + XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]); + + if (info == NULL || ci == NULL) { + XRRFreeScreenResources(sr); + XCloseDisplay(display); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + return monitor; + } + + + float physW = info->mm_width / 25.4; + float physH = info->mm_height / 25.4; + + RGFW_MEMCPY(monitor.name, info->name, 128); + + if (physW && physH) { + monitor.physW = physW; + monitor.physH = physH; + } + + monitor.rect.x = ci->x; + monitor.rect.y = ci->y; + + float w = ci->width; + float h = ci->height; + + if (w && h) { + monitor.rect.w = w; + monitor.rect.h = h; + } + #endif + + if (monitor.physW == 0 || monitor.physH == 0) { + monitor.scaleX = 0; + monitor.scaleY = 0; + } else { + float ppi_width = RGFW_ROUND((float)monitor.rect.w/(float)monitor.physW); + float ppi_height = RGFW_ROUND((float)monitor.rect.h/(float)monitor.physH); + + monitor.scaleX = (float) (ppi_width) / (float) dpi; + monitor.scaleY = (float) (ppi_height) / (float) dpi; + + if ((monitor.scaleX > 1 && monitor.scaleX < 1.1)) + monitor.scaleX = 1; + + if ((monitor.scaleY > 1 && monitor.scaleY < 1.1)) + monitor.scaleY = 1; + } + + #ifndef RGFW_NO_DPI + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); + #endif + + XCloseDisplay(display); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + + return monitor; +} + +RGFW_monitor RGFW_monitors[6]; +RGFW_monitor* RGFW_getMonitors(void) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + size_t i; + for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) + RGFW_monitors[i] = RGFW_XCreateMonitor(i); + + return RGFW_monitors; + #endif + #ifdef RGFW_WAYLAND + wayland: return RGFW_monitors; // TODO WAYLAND + #endif +} + +RGFW_monitor RGFW_getPrimaryMonitor(void) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + RGFW_ASSERT(RGFW_root != NULL); + return RGFW_XCreateMonitor(DefaultScreen(RGFW_root->src.display)); + #endif + #ifdef RGFW_WAYLAND + wayland: return (RGFW_monitor){ }; // TODO WAYLAND + #endif +} + +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(1); +#ifdef RGFW_X11 + XWindowAttributes attrs; + if (!XGetWindowAttributes(win->src.display, win->src.window, &attrs)) { + return (RGFW_monitor){}; + } + + #ifndef RGFW_NO_DPI + XRRScreenResources* screenRes = XRRGetScreenResources(win->src.display, DefaultRootWindow(win->src.display)); + if (screenRes == NULL) { + return (RGFW_monitor){}; + } + + for (int i = 0; i < screenRes->ncrtc; i++) { + XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(win->src.display, screenRes, screenRes->crtcs[i]); + if (!crtcInfo) continue; + + int monitorX = crtcInfo->x; + int monitorY = crtcInfo->y; + int monitorWidth = crtcInfo->width; + int monitorHeight = crtcInfo->height; + + if (attrs.x >= monitorX && + attrs.x < monitorX + monitorWidth && + attrs.y >= monitorY && + attrs.y < monitorY + monitorHeight) { + XRRFreeCrtcInfo(crtcInfo); + XRRFreeScreenResources(screenRes); + return RGFW_XCreateMonitor(i); + } + + XRRFreeCrtcInfo(crtcInfo); + } + + XRRFreeScreenResources(screenRes); + #else + size_t i; + for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) { + Screen* screen = ScreenOfDisplay(RGFW_root->src.display, i); + if (attrs.x >= 0 && attrs.x < 0 + XWidthOfScreen(screen) && + attrs.y >= 0 && attrs.y < 0 + XHeightOfScreen(screen)) + return RGFW_XCreateMonitor(i); + } + #endif +#endif +wayland: + return (RGFW_monitor){}; + +} + +#if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + if (win == NULL) + glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL); + else + glXMakeCurrent(win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); +} +#endif + + +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + /* clear the window*/ + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + RGFW_area area = RGFW_bufferSize; + win->src.bitmap->data = (char*) win->buffer; + #if !defined(RGFW_X11_DONT_CONVERT_BGR) && !defined(RGFW_OSMESA) + u32 x, y; + for (y = 0; y < (u32)win->r.h; y++) { + for (x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * area.w) + x * 4; + + u8 red = win->src.bitmap->data[index]; + win->src.bitmap->data[index] = win->buffer[index + 2]; + win->src.bitmap->data[index + 2] = red; + + } + } + #endif + XPutImage(win->src.display, win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h); + win->src.bitmap->data = NULL; + #endif + } + + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + glXSwapBuffers(win->src.display, win->src.window); + #endif + } + return; +#endif +#ifdef RGFW_WAYLAND + wayland: + #if defined(RGFW_BUFFER) || defined(RGFW_OSMESA) + #if !defined(RGFW_X11_DONT_CONVERT_BGR) && !defined(RGFW_OSMESA) + for (u32 y = 0; y < (u32)win->r.h; y++) { + for (u32 x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * win->r.w) + x * 4; + u32 index2 = (y * 4 * RGFW_bufferSize.w) + x * 4; + + u8 red = win->buffer[index2]; + win->src.buffer[index] = win->buffer[index2 + 2]; + win->src.buffer[index + 1] = win->buffer[index2 + 1]; + win->src.buffer[index + 2] = red; + } + } + #else + for (size_t y = 0; y < win->r.h; y++) { + u32 index = (y * 4 * win->r.w); + u32 index2 = (y * 4 * RGFW_bufferSize.w); + RGFW_MEMCPY(&win->src.buffer[index], &win->buffer[index2], win->r.w * 4); + } + #endif + + wl_surface_frame_done(win, NULL, 0); + if (!(win->_flags & RGFW_NO_GPU_RENDER)) + #endif + { + #ifdef RGFW_OPENGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #endif + } + + wl_surface_commit(win->src.surface); +#endif +} + +#if !defined(RGFW_EGL) + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + #if defined(RGFW_OPENGL) + ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))(win->src.display, win->src.window, swapInterval); + #else + RGFW_UNUSED(swapInterval); + #endif +} +#endif + + +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + /* ungrab pointer if it was grabbed */ + if (win->_flags & RGFW_HOLD_MOUSE) + XUngrabPointer(win->src.display, CurrentTime); + + #ifdef RGFW_EGL + RGFW_closeEGL(win); + #endif + + if (RGFW_hiddenMouse != NULL && (RGFW_windowsOpen - 1) <= 0) { + RGFW_freeMouse(RGFW_hiddenMouse); + RGFW_hiddenMouse = 0; + } + + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (win->buffer != NULL) { + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + XDestroyImage((XImage*) win->src.bitmap); + XFreeGC(win->src.display, win->src.gc); + } + #endif + + if (win->src.display) { + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + glXDestroyContext(win->src.display, win->src.ctx); + #endif + + if (win == RGFW_root) + RGFW_root = NULL; + + if ((Drawable) win->src.window) + XDestroyWindow(win->src.display, (Drawable) win->src.window); /*!< close the window*/ + + XCloseDisplay(win->src.display); /*!< kill the display*/ + } + + #ifdef RGFW_ALLOC_DROPFILES + { + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); + + + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); + } + #endif + + /* set cleared display / window to NULL for error checking */ + win->src.display = 0; + win->src.window = 0; + + RGFW_windowsOpen--; + + #define RGFW_FREE_LIBRARY(x) if (x != NULL) dlclose(x); x = NULL; + if (RGFW_windowsOpen <= 0) { + #if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) + RGFW_FREE_LIBRARY(X11Cursorhandle); + #endif + #if !defined(RGFW_NO_X11_XI_PRELOAD) + RGFW_FREE_LIBRARY(X11Xihandle); + #endif + + #ifdef RGFW_USE_XDL + XDL_close(); + #endif + + #ifndef RGFW_NO_PASSTHROUGH + RGFW_FREE_LIBRARY(RGFW_libxshape); + #endif + + #ifndef RGFW_NO_LINUX + if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){ + close(RGFW_eventWait_forceStop[0]); + close(RGFW_eventWait_forceStop[1]); + } + + u8 i; + for (i = 0; i < RGFW_gamepadCount; i++) { + if(RGFW_gamepads[i]) + close(RGFW_gamepads[i]); + } + #endif + } + RGFW_clipboard_switch(NULL); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); + return; + #endif + + #ifdef RGFW_WAYLAND + wayland: + + #ifdef RGFW_X11 + XDestroyWindow(win->src.display, (Drawable) win->src.window); + XCloseDisplay(win->src.display); /*!< kill the display*/ + #endif + #ifdef RGFW_EGL RGFW_closeEGL(win); #endif @@ -5001,45 +5237,126 @@ static const struct wl_callback_listener wl_surface_frame_listener = { xdg_surface_destroy(win->src.xdg_surface); wl_surface_destroy(win->src.surface); - #ifdef RGFW_BUFFER - wl_buffer_destroy(win->src.wl_buffer); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + wl_buffer_destroy(win->src.wl_buffer); + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + + munmap(win->src.buffer, win->r.w * win->r.h * 4); #endif - - wl_display_disconnect(win->src.display); - RGFW_FREE(win); - } - RGFW_monitor RGFW_getPrimaryMonitor(void) { - /* TODO wayland */ + wl_display_disconnect(win->src.wl_display); + RGFW_clipboard_switch(NULL); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); + #endif +} - return (RGFW_monitor){}; - } - - RGFW_monitor* RGFW_getMonitors(void) { - /* TODO wayland */ - return NULL; - } - - void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(text); RGFW_UNUSED(textLen); - - /* TODO wayland */ - } - - char* RGFW_readClipboard(size_t* size) { - RGFW_UNUSED(size); - - /* TODO wayland */ - - return NULL; - } -#endif /* RGFW_WAYLAND */ - -/* - End of Wayland defines +/* + End of X11 linux / wayland / unix defines */ +#include +#include +#include + +void RGFW_stopCheckEvents(void) { + + RGFW_eventWait_forceStop[2] = 1; + while (1) { + const char byte = 0; + const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); + if (result == 1 || result == -1) + break; + } +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + if (waitMS == 0) + return; + + u8 i; + if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { + if (pipe(RGFW_eventWait_forceStop) != -1) { + fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); + } + } + + struct pollfd fds[] = { + #ifdef RGFW_WAYLAND + { wl_display_get_fd(win->src.wl_display), POLLIN, 0 }, + #else + { ConnectionNumber(win->src.display), POLLIN, 0 }, + #endif + { RGFW_eventWait_forceStop[0], POLLIN, 0 }, + #if defined(__linux__) + { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} + #endif + }; + + u8 index = 2; + + #if defined(__linux__) + for (i = 0; i < RGFW_gamepadCount; i++) { + if (RGFW_gamepads[i] == 0) + continue; + + fds[index].fd = RGFW_gamepads[i]; + index++; + } + #endif + + + u64 start = RGFW_getTimeNS(); + + + #ifdef RGFW_WAYLAND + while (wl_display_dispatch(win->src.wl_display) <= 0 && waitMS >= -1) { + #else + while (XPending(win->src.display) == 0 && waitMS >= -1) { + #endif + if (poll(fds, index, waitMS) <= 0) + break; + + if (waitMS > 0) { + waitMS -= (RGFW_getTimeNS() - start) / 1e+6; + } + } + + /* drain any data in the stop request */ + if (RGFW_eventWait_forceStop[2]) { + char data[64]; + (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data)); + + RGFW_eventWait_forceStop[2] = 0; + } +} + +u64 RGFW_getTimeNS(void) { + struct timespec ts = { 0, 0 }; + #ifndef RGFW_NO_UNIX_CLOCK + clock_gettime(1, &ts); + #endif + unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + + return nanoSeconds; +} + +u64 RGFW_getTime(void) { + struct timespec ts = { 0, 0 }; + #ifndef RGFW_NO_UNIX_CLOCK + clock_gettime(1, &ts); + #endif + unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + + return (double)(nanoSeconds) * 1e-9; +} +#endif /* end of wayland or X11 defines*/ + /* @@ -5049,22 +5366,21 @@ static const struct wl_callback_listener wl_surface_frame_listener = { */ #ifdef RGFW_WINDOWS - #define WIN32_LEAN_AND_MEAN - #define OEMRESOURCE - #include - - #include - #include - #include - #include - #include - #include +#define WIN32_LEAN_AND_MEAN +#define OEMRESOURCE +#include - #include +#include +#include +#include +#include +#include +#include +#include - __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); - - #ifndef RGFW_NO_XINPUT +__declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); + +#ifndef RGFW_NO_XINPUT typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); PFN_XInputGetState XInputGetStateSRC = NULL; #define XInputGetState XInputGetStateSRC @@ -5074,89 +5390,40 @@ static const struct wl_callback_listener wl_surface_frame_listener = { #define XInputGetKeystroke XInputGetKeystrokeSRC static HMODULE RGFW_XInput_dll = NULL; - #endif +#endif - u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO}; +u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO}; - char* createUTF8FromWideStringWin32(const WCHAR* source); +char* RGFW_createUTF8FromWideStringWin32(const WCHAR* source); #define GL_FRONT 0x0404 #define GL_BACK 0x0405 #define GL_LEFT 0x0406 #define GL_RIGHT 0x0407 -#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA) - - typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext); - typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int); - typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext); - - PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource; - PFN_OSMesaCreateContext OSMesaCreateContextSource; - PFN_OSMesaDestroyContext OSMesaDestroyContextSource; - -#define OSMesaCreateContext OSMesaCreateContextSource -#define OSMesaMakeCurrent OSMesaMakeCurrentSource -#define OSMesaDestroyContext OSMesaDestroyContextSource -#endif - - typedef int (*PFN_wglGetSwapIntervalEXT)(void); - PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL; +typedef int (*PFN_wglGetSwapIntervalEXT)(void); +PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL; #define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc - void* RGFWgamepadApi = NULL; +void* RGFWgamepadApi = NULL; - /* these two wgl functions need to be preloaded */ - typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList); - PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; - - /* defines for creating ARB attributes */ -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201a -#define WGL_ALPHA_BITS_ARB 0x201b -#define WGL_ALPHA_SHIFT_ARB 0x201c -#define WGL_ACCUM_BITS_ARB 0x201d -#define WGL_ACCUM_RED_BITS_ARB 0x201e -#define WGL_ACCUM_GREEN_BITS_ARB 0x201f -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_STEREO_ARB 0x2012 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 +/* these two wgl functions need to be preloaded */ +typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList); +PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; #ifndef RGFW_EGL -static HMODULE wglinstance = NULL; + static HMODULE RGFW_wgl_dll = NULL; #endif -#ifdef RGFW_WGL_LOAD +#ifndef RGFW_NO_LOAD_WGL typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC); typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC); typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR); typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC); - typedef HDC(WINAPI* PFN_wglGetCurrentDC)(); - typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(); + typedef HDC(WINAPI* PFN_wglGetCurrentDC)(void); + typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(void); + typedef BOOL(WINAPI* PFN_wglShareLists)(HGLRC, HGLRC); PFN_wglCreateContext wglCreateContextSRC; PFN_wglDeleteContext wglDeleteContextSRC; @@ -5164,94 +5431,100 @@ static HMODULE wglinstance = NULL; PFN_wglMakeCurrent wglMakeCurrentSRC; PFN_wglGetCurrentDC wglGetCurrentDCSRC; PFN_wglGetCurrentContext wglGetCurrentContextSRC; + PFN_wglShareLists wglShareListsSRC; #define wglCreateContext wglCreateContextSRC #define wglDeleteContext wglDeleteContextSRC #define wglGetProcAddress wglGetProcAddressSRC #define wglMakeCurrent wglMakeCurrentSRC - #define wglGetCurrentDC wglGetCurrentDCSRC #define wglGetCurrentContext wglGetCurrentContextSRC + #define wglShareLists wglShareListsSRC #endif #ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { + void* RGFW_getProcAddress(const char* procname) { void* proc = (void*) wglGetProcAddress(procname); if (proc) return proc; - return (void*) GetProcAddress(wglinstance, procname); + return (void*) GetProcAddress(RGFW_wgl_dll, procname); } typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; #endif - RGFW_window RGFW_eventWindow; +RGFW_window RGFW_eventWindow; - LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch (message) { - case WM_MOVE: - RGFW_eventWindow.r.x = LOWORD(lParam); - RGFW_eventWindow.r.y = HIWORD(lParam); - RGFW_eventWindow.src.window = hWnd; - return DefWindowProcA(hWnd, message, wParam, lParam); - case WM_SIZE: - RGFW_eventWindow.r.w = LOWORD(lParam); - RGFW_eventWindow.r.h = HIWORD(lParam); - RGFW_eventWindow.src.window = hWnd; - return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling - default: - return DefWindowProcA(hWnd, message, wParam, lParam); - } +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_MOVE: + RGFW_eventWindow.r.x = LOWORD(lParam); + RGFW_eventWindow.r.y = HIWORD(lParam); + RGFW_eventWindow.src.window = hWnd; + return DefWindowProcA(hWnd, message, wParam, lParam); + case WM_SIZE: + RGFW_eventWindow.r.w = LOWORD(lParam); + RGFW_eventWindow.r.h = HIWORD(lParam); + RGFW_eventWindow.src.window = hWnd; + return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling + default: + return DefWindowProcA(hWnd, message, wParam, lParam); } +} - #ifndef RGFW_NO_DPI +#ifndef RGFW_NO_DPI static HMODULE RGFW_Shcore_dll = NULL; typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL; #define GetDpiForMonitor GetDpiForMonitorSRC - #endif +#endif +#ifndef RGFW_NO_DWM +static HMODULE RGFW_dwm_dll = NULL; +typedef struct { DWORD dwFlags; int fEnable; HRGN hRgnBlur; int fTransitionOnMaximized;} DWM_BLURBEHIND; +typedef HRESULT (WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND, const DWM_BLURBEHIND*); +PFN_DwmEnableBlurBehindWindow DwmEnableBlurBehindWindowSRC = NULL; +#endif + +#if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + static HMODULE RGFW_winmm_dll = NULL; + typedef u32 (WINAPI * PFN_timeBeginPeriod)(u32); + PFN_timeBeginPeriod timeBeginPeriodSRC = NULL; + #define timeBeginPeriod timeBeginPeriodSRC +#elif !defined(RGFW_NO_WINMM) __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); - - #ifndef RGFW_NO_XINPUT - void RGFW_loadXInput(void) { - u32 i; - static const char* names[] = { - "xinput1_4.dll", - "xinput9_1_0.dll", - "xinput1_2.dll", - "xinput1_1.dll" - }; +#endif - for (i = 0; i < sizeof(names) / sizeof(const char*) && (XInputGetStateSRC == NULL || XInputGetStateSRC != NULL); i++) { - RGFW_XInput_dll = LoadLibraryA(names[i]); +#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) name##SRC = (PFN_##name)(void*)GetProcAddress(proc, #name) - if (RGFW_XInput_dll == NULL) - continue; - - if (XInputGetStateSRC == NULL) - XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); - - if (XInputGetKeystrokeSRC == NULL) - XInputGetKeystrokeSRC = (PFN_XInputGetKeystroke)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetKeystroke"); - } - - if (XInputGetStateSRC == NULL) - printf("RGFW ERR: Failed to load XInputGetState\n"); - if (XInputGetKeystrokeSRC == NULL) - printf("RGFW ERR: Failed to load XInputGetKeystroke\n"); +#ifndef RGFW_NO_XINPUT +void RGFW_loadXInput(void) { + u32 i; + static const char* names[] = {"xinput1_4.dll", "xinput9_1_0.dll", "xinput1_2.dll", "xinput1_1.dll"}; + for (i = 0; i < sizeof(names) / sizeof(const char*) && (XInputGetStateSRC == NULL || XInputGetStateSRC != NULL); i++) { + RGFW_XInput_dll = LoadLibraryA(names[i]); + RGFW_PROC_DEF(RGFW_XInput_dll, XInputGetState); + RGFW_PROC_DEF(RGFW_XInput_dll, XInputGetKeystroke); } - #endif - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { + #ifdef RGFW_DEBUG + if (XInputGetStateSRC == NULL) + printf("RGFW ERR: Failed to load XInputGetState\n"); + if (XInputGetKeystrokeSRC == NULL) + printf("RGFW ERR: Failed to load XInputGetKeystroke\n"); + #endif +} +#endif + +RGFWDEF void RGFW_init_buffer(RGFW_window* win); +void RGFW_init_buffer(RGFW_window* win) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) RGFW_bufferSize = RGFW_getScreenSize(); - + BITMAPV5HEADER bi = { 0 }; ZeroMemory(&bi, sizeof(bi)); bi.bV5Size = sizeof(bi); @@ -5271,137 +5544,149 @@ static HMODULE wglinstance = NULL; (void**) &win->buffer, NULL, (DWORD) 0); - + win->src.hdcMem = CreateCompatibleDC(win->src.hdc); #if defined(RGFW_OSMESA) win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif -#else -RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ -#endif - } + #else + RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ + #endif +} - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - DragAcceptFiles(win->src.window, allow); - } +void RGFW_window_setDND(RGFW_window* win, b8 allow) { + DragAcceptFiles(win->src.window, allow); +} - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); - ClipCursor(NULL); - const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; - RegisterRawInputDevices(&id, 1, sizeof(id)); - } +void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); + ClipCursor(NULL); + const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + RegisterRawInputDevices(&id, 1, sizeof(id)); +} - void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { - RGFW_UNUSED(win); RGFW_UNUSED(rect); +void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { + RGFW_UNUSED(win); RGFW_UNUSED(rect); - RECT clipRect; - GetClientRect(win->src.window, &clipRect); - ClientToScreen(win->src.window, (POINT*) &clipRect.left); - ClientToScreen(win->src.window, (POINT*) &clipRect.right); - ClipCursor(&clipRect); + RECT clipRect; + GetClientRect(win->src.window, &clipRect); + ClientToScreen(win->src.window, (POINT*) &clipRect.left); + ClientToScreen(win->src.window, (POINT*) &clipRect.right); + ClipCursor(&clipRect); - const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window }; - RegisterRawInputDevices(&id, 1, sizeof(id)); - } + const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window }; + RegisterRawInputDevices(&id, 1, sizeof(id)); +} - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - #ifndef RGFW_NO_XINPUT +#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = LoadLibraryA(lib) + +u32 RGFW_windowsOpen = 0; + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + #ifndef RGFW_NO_XINPUT if (RGFW_XInput_dll == NULL) RGFW_loadXInput(); - #endif + #endif - #ifndef RGFW_NO_DPI - if (RGFW_Shcore_dll == NULL) { - RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); - GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); - #if (_WIN32_WINNT >= 0x0600) - SetProcessDPIAware(); - #endif - } + #ifndef RGFW_NO_DPI + RGFW_LOAD_LIBRARY(RGFW_Shcore_dll, "shcore.dll"); + RGFW_PROC_DEF(RGFW_Shcore_dll, GetDpiForMonitor); + #if (_WIN32_WINNT >= 0x0600) + SetProcessDPIAware(); #endif + #endif - if (wglinstance == NULL) { - wglinstance = LoadLibraryA("opengl32.dll"); -#ifdef RGFW_WGL_LOAD - wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext"); - wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext"); - wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress"); - wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent"); - wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC"); - wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext"); -#endif - } + #if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + RGFW_LOAD_LIBRARY(RGFW_winmm_dll, "winmm.dll"); + RGFW_PROC_DEF(RGFW_winmm_dll, timeBeginPeriod); + #endif + + #ifndef RGFW_NO_DWM + RGFW_LOAD_LIBRARY(RGFW_dwm_dll, "dwmapi.dll"); + RGFW_PROC_DEF(RGFW_dwm_dll, DwmEnableBlurBehindWindow); + #endif + + RGFW_LOAD_LIBRARY(RGFW_wgl_dll, "opengl32.dll"); + #ifndef RGFW_NO_LOAD_WGL + RGFW_PROC_DEF(RGFW_wgl_dll, wglCreateContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetProcAddress); + RGFW_PROC_DEF(RGFW_wgl_dll, wglMakeCurrent); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentDC); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglShareLists); + #endif + + if (name[0] == 0) name = (char*) " "; + + RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); + RGFW_eventWindow.src.window = NULL; + + RGFW_window_basic_init(win, rect, flags); + + win->src.maxSize = RGFW_AREA(0, 0); + win->src.minSize = RGFW_AREA(0, 0); + + + HINSTANCE inh = GetModuleHandleA(NULL); + + #ifndef __cplusplus + WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */ + #else + WNDCLASSA Class = { }; + #endif + + if (RGFW_className == NULL) + RGFW_className = (char*)name; + + Class.lpszClassName = RGFW_className; + Class.hInstance = inh; + Class.hCursor = LoadCursor(NULL, IDC_ARROW); + Class.lpfnWndProc = WndProc; + + Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (Class.hIcon == NULL) { + Class.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + } + + RegisterClassA(&Class); + + DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + RECT windowRect, clientRect; + + if (!(flags & RGFW_windowNoBorder)) { + window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; + + if (!(flags & RGFW_windowNoResize)) + window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; + } else + window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX; + + HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0); + GetWindowRect(dummyWin, &windowRect); + GetClientRect(dummyWin, &clientRect); + + win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); + win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0); - if (name[0] == 0) name = (char*) " "; + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; + RGFW_window_setDND(win, 1); + } + win->src.hdc = GetDC(win->src.window); - RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); - RGFW_eventWindow.src.window = NULL; - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - win->src.maxSize = RGFW_AREA(0, 0); - win->src.minSize = RGFW_AREA(0, 0); - - - HINSTANCE inh = GetModuleHandleA(NULL); - - #ifndef __cplusplus - WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */ - #else - WNDCLASSA Class = { }; - #endif - - if (RGFW_className == NULL) - RGFW_className = (char*)name; - - Class.lpszClassName = RGFW_className; - Class.hInstance = inh; - Class.hCursor = LoadCursor(NULL, IDC_ARROW); - Class.lpfnWndProc = WndProc; - - Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - if (Class.hIcon == NULL) { - Class.hIcon = (HICON)LoadImageA(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - } - - RegisterClassA(&Class); - - DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - RECT windowRect, clientRect; - - if (!(args & RGFW_NO_BORDER)) { - window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; - - if (!(args & RGFW_NO_RESIZE)) - window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; - } else - window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX; - - - HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0); - - GetWindowRect(dummyWin, &windowRect); - GetClientRect(dummyWin, &clientRect); - - win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); - win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; - RGFW_window_setDND(win, 1); - } - win->src.hdc = GetDC(win->src.window); - - if ((args & RGFW_NO_INIT_API) == 0) { -#ifdef RGFW_DIRECTX - assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0); + if ((flags & RGFW_windowNoInitAPI) == 0) { + #ifdef RGFW_DIRECTX + RGFW_ASSERT(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0); if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) { - fprintf(stderr, "Failed to enumerate DXGI adapters\n"); + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to enumerate DXGI adapters\n"); + #endif RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); return NULL; } @@ -5409,7 +5694,9 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 }; if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) { - fprintf(stderr, "Failed to create Direct3D device\n"); + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to create Direct3D device\n"); + #endif RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter); RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); return NULL; @@ -5456,32 +5743,34 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture); RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView); -#endif + #endif -#ifdef RGFW_OPENGL + #ifdef RGFW_OPENGL HDC dummy_dc = GetDC(dummyWin); - - u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; - - //if (RGFW_DOUBLE_BUFFER) + + u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + + //if (RGFW_DOUBLE_BUFFER) pfd_flags |= PFD_DOUBLEBUFFER; - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(pfd), - 1, /* version */ - pfd_flags, - PFD_TYPE_RGBA, /* ipixel type */ - 24, /* color bits */ - 0, 0, 0, 0, 0, 0, - 8, /* alpha bits */ - 0, 0, 0, 0, 0, 0, - 32, /* depth bits */ - 8, /* stencil bits */ - 0, - PFD_MAIN_PLANE, /* Layer type */ - 0, 0, 0, 0 + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the descriptor + 1, // Version + pfd_flags, // Flags to specify what the pixel format supports (e.g., PFD_SUPPORT_OPENGL) + PFD_TYPE_RGBA, // Pixel type is RGBA + 32, // Color bits (red, green, blue channels) + 0, 0, 0, 0, 0, 0, // No color bits for unused channels + 8, // Alpha bits (important for transparency) + 0, // No accumulation buffer bits needed + 0, 0, 0, 0, // No accumulation bits + 32, // Depth buffer bits + 8, // Stencil buffer bits + 0, // Auxiliary buffer bits (unused) + PFD_MAIN_PLANE, // Use the main plane for rendering + 0, 0, 0, 0, 0 // Reserved fields }; + int pixel_format = ChoosePixelFormat(dummy_dc, &pfd); SetPixelFormat(dummy_dc, pixel_format, &pfd); @@ -5496,41 +5785,45 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ wglMakeCurrent(dummy_dc, 0); wglDeleteContext(dummy_context); ReleaseDC(dummyWin, dummy_dc); - - /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ + + /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ if (wglCreateContextAttribsARB != NULL) { PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - if (args & RGFW_OPENGL_SOFTWARE) + if (flags & RGFW_windowOpenglSoftware) pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED; if (wglChoosePixelFormatARB != NULL) { - i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); + i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); int pixel_format; UINT num_formats; wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats); if (!num_formats) { + #ifdef RGFW_DEBUG printf("Failed to create a pixel format for WGL.\n"); + #endif } DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd); if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) { + #ifdef RGFW_DEBUG printf("Failed to set the WGL pixel format.\n"); + #endif } } - - /* create opengl/WGL context for the specified version */ + + /* create opengl/WGL context for the specified version */ u32 index = 0; i32 attribs[40]; - if (RGFW_profile == RGFW_GL_CORE) { + if (RGFW_profile == RGFW_glCore) { SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB); } else { SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); } - + if (RGFW_majorVersion || RGFW_minorVersion) { SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion); SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion); @@ -5540,1260 +5833,1260 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs); } else { /* fall back to a default context (probably opengl 2 or something) */ + #ifdef RGFW_DEBUG fprintf(stderr, "Failed to create an accelerated OpenGL Context\n"); + #endif int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd); SetPixelFormat(win->src.hdc, pixel_format, &pfd); win->src.ctx = wglCreateContext(win->src.hdc); } - + wglMakeCurrent(win->src.hdc, win->src.ctx); -#endif + #endif } -#ifdef RGFW_OSMESA -#ifdef RGFW_LINK_OSM ESA - OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent"); - OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext"); - OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext"); -#endif -#endif - -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { ReleaseDC(win->src.window, win->src.hdc); win->src.hdc = GetDC(win->src.window); wglMakeCurrent(win->src.hdc, win->src.ctx); } -#endif + #endif - DestroyWindow(dummyWin); - RGFW_init_buffer(win); + DestroyWindow(dummyWin); + RGFW_init_buffer(win); - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); - #endif - - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif -#ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } + + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) RGFW_createOpenGLContext(win); -#endif + #endif - if (args & RGFW_HIDE_MOUSE) - RGFW_window_showMouse(win, 0); + if (flags & RGFW_windowHideMouse) + RGFW_window_showMouse(win, 0); - if (args & RGFW_TRANSPARENT_WINDOW) { - SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED); - SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA); - } - - ShowWindow(win->src.window, SW_SHOWNORMAL); - - if (RGFW_root == NULL) - RGFW_root = win; - - #ifdef RGFW_OPENGL - else - wglShareLists(RGFW_root->src.ctx, win->src.ctx); + if (flags & RGFW_windowTransparent) { + if (DwmEnableBlurBehindWindowSRC != NULL) { + #ifndef RGFW_NO_DWM + DWM_BLURBEHIND bb = {0, 0, 0, 0}; + bb.dwFlags = 0x1; + bb.fEnable = TRUE; + bb.hRgnBlur = NULL; + DwmEnableBlurBehindWindowSRC(win->src.window, &bb); #endif - - #ifdef RGFW_DEBUG - printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); - #endif - - return win; - } - - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - DWORD style = GetWindowLong(win->src.window, GWL_STYLE); - - if (border == 0) { - SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - SetWindowPos( - win->src.window, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE - ); - } - else { - SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - SetWindowPos( - win->src.window, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE - ); + } else { + SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED); + SetLayeredWindowAttributes(win->src.window, 0, 128, LWA_ALPHA); } } + ShowWindow(win->src.window, SW_SHOWNORMAL); - RGFW_area RGFW_getScreenSize(void) { - return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES)); + #ifdef RGFW_OPENGL + if (RGFW_root != win) + wglShareLists(RGFW_root->src.ctx, win->src.ctx); + #endif + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + + RGFW_windowsOpen++; + + return win; +} + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + DWORD style = GetWindowLong(win->src.window, GWL_STYLE); + + if (border == 0) { + SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); } - - RGFW_point RGFW_getGlobalMousePoint(void) { - POINT p; - GetCursorPos(&p); - - return RGFW_POINT(p.x, p.y); - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - POINT p; - GetCursorPos(&p); - ScreenToClient(win->src.window, &p); - - return RGFW_POINT(p.x, p.y); - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->src.minSize = a; - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->src.maxSize = a; + else { + SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); } +} - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); +RGFW_area RGFW_getScreenSize(void) { + HDC dc = GetDC(NULL); + RGFW_area area = RGFW_AREA(GetDeviceCaps(dc, HORZRES), GetDeviceCaps(dc, VERTRES)); + ReleaseDC(NULL, dc); + return area; +} - ShowWindow(win->src.window, SW_MINIMIZE); - } +RGFW_point RGFW_getGlobalMousePoint(void) { + POINT p; + GetCursorPos(&p); - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); + return RGFW_POINT(p.x, p.y); +} - ShowWindow(win->src.window, SW_RESTORE); - } +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + POINT p; + GetCursorPos(&p); + ScreenToClient(win->src.window, &p); + + return RGFW_POINT(p.x, p.y); +} + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->src.minSize = a; +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->src.maxSize = a; +} - u8 RGFW_xinput2RGFW[] = { - RGFW_GP_A, /* or PS X button */ - RGFW_GP_B, /* or PS circle button */ - RGFW_GP_X, /* or PS square button */ - RGFW_GP_Y, /* or PS triangle button */ - RGFW_GP_R1, /* right bumper */ - RGFW_GP_L1, /* left bump */ - RGFW_GP_L2, /* left trigger*/ - RGFW_GP_R2, /* right trigger */ - 0, 0, 0, 0, 0, 0, 0, 0, - RGFW_GP_UP, /* dpad up */ - RGFW_GP_DOWN, /* dpad down*/ - RGFW_GP_LEFT, /* dpad left */ - RGFW_GP_RIGHT, /* dpad right */ - RGFW_GP_START, /* start button */ - RGFW_GP_SELECT,/* select button */ - RGFW_GP_L3, - RGFW_GP_R3, - }; +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) { - RGFW_UNUSED(win) - size_t i; - for (i = 0; i < 4; i++) { - XINPUT_KEYSTROKE keystroke; + ShowWindow(win->src.window, SW_MINIMIZE); +} - if (XInputGetKeystroke == NULL) +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + ShowWindow(win->src.window, SW_RESTORE); +} + +u8 RGFW_xinput2RGFW[] = { + RGFW_gamepadA, /* or PS X button */ + RGFW_gamepadB, /* or PS circle button */ + RGFW_gamepadX, /* or PS square button */ + RGFW_gamepadY, /* or PS triangle button */ + RGFW_gamepadR1, /* right bumper */ + RGFW_gamepadL1, /* left bump */ + RGFW_gamepadL2, /* left trigger*/ + RGFW_gamepadR2, /* right trigger */ + 0, 0, 0, 0, 0, 0, 0, 0, + RGFW_gamepadUp, /* dpad up */ + RGFW_gamepadDown, /* dpad down*/ + RGFW_gamepadLeft, /* dpad left */ + RGFW_gamepadRight, /* dpad right */ + RGFW_gamepadStart, /* start button */ + RGFW_gamepadSelect,/* select button */ + RGFW_gamepadL3, + RGFW_gamepadR3, +}; + +static i32 RGFW_checkXInput(RGFW_window* win, RGFW_event* e) { + #ifndef RGFW_NO_XINPUT + + RGFW_UNUSED(win); + size_t i; + for (i = 0; i < 4; i++) { + XINPUT_KEYSTROKE keystroke; + + if (XInputGetKeystroke == NULL) + return 0; + + DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke); + + if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) { + if (result != ERROR_SUCCESS) return 0; - DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke); + if (keystroke.VirtualKey > VK_PAD_RTHUMB_PRESS) + continue; - if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) { - if (result != ERROR_SUCCESS) - return 0; - - if (keystroke.VirtualKey > VK_PAD_RTHUMB_PRESS) - continue; - - //gp + 1 = RGFW_gpButtonReleased - e->type = RGFW_gpButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); - e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; - RGFW_gpPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + //gamepad + 1 = RGFW_gamepadButtonReleased + e->type = RGFW_gamepadButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; + RGFW_gamepadPressed[i][e->button].prev = RGFW_gamepadPressed[i][e->button].current; + RGFW_gamepadPressed[i][e->button].current = (keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); - return 1; - } + RGFW_gamepadButtonCallback(win, i, e->button, e->type == RGFW_gamepadButtonPressed); + return 1; + } - XINPUT_STATE state; - if (XInputGetState == NULL || - XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED - ) - return 0; + XINPUT_STATE state; + if (XInputGetState == NULL || + XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED + ) { + if (RGFW_gamepads[i] == 0) + continue; + + RGFW_gamepads[i] = 0; + RGFW_gamepadCount--; + + win->event.type = RGFW_gamepadDisconnected; + win->event.gamepad = i; + RGFW_gamepadCallback(win, i, 0); + return 1; + } + + if (RGFW_gamepads[i] == 0) { + RGFW_gamepads[i] = 1; + RGFW_gamepadCount++; + + char str[] = "Microsoft X-Box (XInput device)"; + RGFW_MEMCPY(RGFW_gamepads_name[i], str, sizeof(str)); + RGFW_gamepads_name[i][sizeof(RGFW_gamepads_name[i]) - 1] = '\0'; + win->event.type = RGFW_gamepadConnected; + win->event.gamepad = i; + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + + RGFW_gamepadCallback(win, i, 1); + return 1; + } #define INPUT_DEADZONE ( 0.24f * (float)(0x7FFF) ) // Default to 24% of the +/- 32767 range. This is a reasonable default value but can be altered if needed. - if ((state.Gamepad.sThumbLX < INPUT_DEADZONE && - state.Gamepad.sThumbLX > -INPUT_DEADZONE) && - (state.Gamepad.sThumbLY < INPUT_DEADZONE && - state.Gamepad.sThumbLY > -INPUT_DEADZONE)) - { - state.Gamepad.sThumbLX = 0; - state.Gamepad.sThumbLY = 0; - } - - if ((state.Gamepad.sThumbRX < INPUT_DEADZONE && - state.Gamepad.sThumbRX > -INPUT_DEADZONE) && - (state.Gamepad.sThumbRY < INPUT_DEADZONE && - state.Gamepad.sThumbRY > -INPUT_DEADZONE)) - { - state.Gamepad.sThumbRX = 0; - state.Gamepad.sThumbRY = 0; - } - - e->axisesCount = 2; - RGFW_point axis1 = RGFW_POINT(((float)state.Gamepad.sThumbLX / 32768.0f) * 100, ((float)state.Gamepad.sThumbLY / -32768.0f) * 100); - RGFW_point axis2 = RGFW_POINT(((float)state.Gamepad.sThumbRX / 32768.0f) * 100, ((float)state.Gamepad.sThumbRY / -32768.0f) * 100); - - if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y){ - win->event.whichAxis = 0; - - e->type = RGFW_gpAxisMove; - - e->axis[0] = axis1; - - return 1; - } - - if (axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) { - win->event.whichAxis = 1; - e->type = RGFW_gpAxisMove; - e->axis[1] = axis2; - - return 1; - } + if ((state.Gamepad.sThumbLX < INPUT_DEADZONE && + state.Gamepad.sThumbLX > -INPUT_DEADZONE) && + (state.Gamepad.sThumbLY < INPUT_DEADZONE && + state.Gamepad.sThumbLY > -INPUT_DEADZONE)) + { + state.Gamepad.sThumbLX = 0; + state.Gamepad.sThumbLY = 0; } - return 0; + if ((state.Gamepad.sThumbRX < INPUT_DEADZONE && + state.Gamepad.sThumbRX > -INPUT_DEADZONE) && + (state.Gamepad.sThumbRY < INPUT_DEADZONE && + state.Gamepad.sThumbRY > -INPUT_DEADZONE)) + { + state.Gamepad.sThumbRX = 0; + state.Gamepad.sThumbRY = 0; + } + + e->axisesCount = 2; + RGFW_point axis1 = RGFW_POINT(((float)state.Gamepad.sThumbLX / 32768.0f) * 100, ((float)state.Gamepad.sThumbLY / -32768.0f) * 100); + RGFW_point axis2 = RGFW_POINT(((float)state.Gamepad.sThumbRX / 32768.0f) * 100, ((float)state.Gamepad.sThumbRY / -32768.0f) * 100); + + if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y){ + win->event.whichAxis = 0; + + e->type = RGFW_gamepadAxisMove; + e->axis[0] = axis1; + RGFW_gamepadAxes[i][0] = e->axis[0]; + + RGFW_gamepadAxisCallback(win, e->gamepad, e->axis, e->axisesCount, e->whichAxis); + return 1; + } + + if (axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) { + win->event.whichAxis = 1; + e->type = RGFW_gamepadAxisMove; + e->axis[1] = axis2; + RGFW_gamepadAxes[i][1] = e->axis[1]; + + RGFW_gamepadAxisCallback(win, e->gamepad, e->axis, e->axisesCount, e->whichAxis); + return 1; + } } - void RGFW_stopCheckEvents(void) { - PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0); + #endif + + return 0; +} + +void RGFW_stopCheckEvents(void) { + PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0); +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT); +} + +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + if (win->event.type == RGFW_quit) { + return NULL; } - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - RGFW_UNUSED(win); + MSG msg; - MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT); - } - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - - if (win->event.type == RGFW_quit) { - return NULL; + if (RGFW_eventWindow.src.window == win->src.window) { + if (RGFW_eventWindow.r.x != -1) { + win->r.x = RGFW_eventWindow.r.x; + win->r.y = RGFW_eventWindow.r.y; + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); } - MSG msg; - - if (RGFW_eventWindow.src.window == win->src.window) { - if (RGFW_eventWindow.r.x != -1) { - win->r.x = RGFW_eventWindow.r.x; - win->r.y = RGFW_eventWindow.r.y; - win->event.type = RGFW_windowMoved; - RGFW_windowMoveCallback(win, win->r); - } - - if (RGFW_eventWindow.r.w != -1) { - win->r.w = RGFW_eventWindow.r.w; - win->r.h = RGFW_eventWindow.r.h; - win->event.type = RGFW_windowResized; - RGFW_windowResizeCallback(win, win->r); - } - - RGFW_eventWindow.src.window = NULL; - RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); - - return &win->event; + if (RGFW_eventWindow.r.w != -1) { + win->r.w = RGFW_eventWindow.r.w; + win->r.h = RGFW_eventWindow.r.h; + win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); } - - static HDROP drop; - - if (win->event.type == RGFW_dnd_init) { - if (win->event.droppedFilesCount) { - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); - //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*)); - - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) { - const UINT length = DragQueryFileW(drop, i, NULL, 0); - WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR)); - - DragQueryFileW(drop, i, buffer, length + 1); - strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH); - win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; - RGFW_FREE(buffer); - } - - DragFinish(drop); - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); - - win->event.type = RGFW_dnd; - return &win->event; - } - - win->event.inFocus = (GetForegroundWindow() == win->src.window); - - if (RGFW_checkXInput(win, &win->event)) - return &win->event; - - static BYTE keyboardState[256]; - GetKeyboardState(keyboardState); - - - if (!IsWindow(win->src.window)) { - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); - return &win->event; - } - - if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE) == 0) - return NULL; - - switch (msg.message) { - case WM_CLOSE: - case WM_QUIT: - RGFW_windowQuitCallback(win); - win->event.type = RGFW_quit; - break; - - case WM_ACTIVATE: - win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE); - - if (win->event.inFocus) { - win->event.type = RGFW_focusIn; - RGFW_focusCallback(win, 1); - } - else { - win->event.type = RGFW_focusOut; - RGFW_focusCallback(win, 0); - } - - break; - - case WM_PAINT: - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - break; - - case WM_MOUSELEAVE: - win->event.type = RGFW_mouseLeave; - win->_winArgs |= RGFW_MOUSE_LEFT; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - - case WM_KEYUP: { - i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); - if (scancode == 0) - scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); - - switch (scancode) { - case 0x54: scancode = 0x137; break; /* Alt+PrtS */ - case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ - case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ - default: break; - } - - win->event.key = RGFW_apiKeyToRGFW((u32) scancode); - - if (msg.wParam == VK_CONTROL) { - if (HIWORD(msg.lParam) & KF_EXTENDED) - win->event.key = RGFW_ControlR; - else win->event.key = RGFW_ControlL; - } - - wchar_t charBuffer; - ToUnicodeEx(msg.wParam, scancode, keyboardState, (wchar_t*)&charBuffer, 1, 0, NULL); - - win->event.keyChar = (u8)charBuffer; - - RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); - - static char keyName[16]; - - { - GetKeyNameTextA((LONG) msg.lParam, keyName, 16); - if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) || - ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) { - CharLowerBuffA(keyName, 16); - } - } - - RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); - - strncpy(win->event.keyName, keyName, 16); - - if (RGFW_isPressed(win, RGFW_ShiftL)) { - ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), - keyboardState, (LPWORD) win->event.keyName, 0); - } - - win->event.type = RGFW_keyReleased; - RGFW_keyboard[win->event.key].current = 0; - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, 0); - break; - } - case WM_KEYDOWN: { - i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); - if (scancode == 0) - scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); - - switch (scancode) { - case 0x54: scancode = 0x137; break; /* Alt+PrtS */ - case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ - case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ - default: break; - } - - win->event.key = RGFW_apiKeyToRGFW((u32) scancode); - - if (msg.wParam == VK_CONTROL) { - if (HIWORD(msg.lParam) & KF_EXTENDED) - win->event.key = RGFW_ControlR; - else win->event.key = RGFW_ControlL; - } - - wchar_t charBuffer; - ToUnicodeEx(msg.wParam, scancode, keyboardState, &charBuffer, 1, 0, NULL); - win->event.keyChar = (u8)charBuffer; - - RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); - - static char keyName[16]; - - { - GetKeyNameTextA((LONG) msg.lParam, keyName, 16); - - if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) || - ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) { - CharLowerBuffA(keyName, 16); - } - } - - RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); - - strncpy(win->event.keyName, keyName, 16); - - if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) { - ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), - keyboardState, (LPWORD) win->event.keyName, 0); - } - - win->event.type = RGFW_keyPressed; - win->event.repeat = RGFW_isPressed(win, win->event.key); - RGFW_keyboard[win->event.key].current = 1; - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, 1); - break; - } - - case WM_MOUSEMOVE: { - if ((win->_winArgs & RGFW_HOLD_MOUSE)) - break; - - win->event.type = RGFW_mousePosChanged; - - i32 x = GET_X_LPARAM(msg.lParam); - i32 y = GET_Y_LPARAM(msg.lParam); - - RGFW_mousePosCallback(win, win->event.point); - - if (win->_winArgs & RGFW_MOUSE_LEFT) { - win->_winArgs ^= RGFW_MOUSE_LEFT; - win->event.type = RGFW_mouseEnter; - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - } - - /*if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - RGFW_point p = RGFW_getGlobalMousePoint(); - //p = RGFW_POINT(p.x + win->r.x, p.y + win->r.y); - - win->event.point.x = x - win->_lastMousePoint.x; - win->event.point.y = y - win->_lastMousePoint.y; - - win->_lastMousePoint = RGFW_POINT(x, y); - break; - }*/ - - win->event.point.x = x; - win->event.point.y = y; - win->_lastMousePoint = RGFW_POINT(x, y); - - break; - } - case WM_INPUT: { - if (!(win->_winArgs & RGFW_HOLD_MOUSE)) - break; - - unsigned size = sizeof(RAWINPUT); - static RAWINPUT raw = {}; - - GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER)); - - if (raw.header.dwType != RIM_TYPEMOUSE || (raw.data.mouse.lLastX == 0 && raw.data.mouse.lLastY == 0) ) - break; - - if (raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { - POINT pos = {0}; - int width, height; - - if (raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) { - pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN); - pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN); - width = GetSystemMetrics(SM_CXVIRTUALSCREEN); - height = GetSystemMetrics(SM_CYVIRTUALSCREEN); - } - else { - width = GetSystemMetrics(SM_CXSCREEN); - height = GetSystemMetrics(SM_CYSCREEN); - } - - pos.x += (int) ((raw.data.mouse.lLastX / 65535.f) * width); - pos.y += (int) ((raw.data.mouse.lLastY / 65535.f) * height); - ScreenToClient(win->src.window, &pos); - - win->event.point.x = pos.x - win->_lastMousePoint.x; - win->event.point.y = pos.y - win->_lastMousePoint.y; - } else { - win->event.point.x = raw.data.mouse.lLastX; - win->event.point.y = raw.data.mouse.lLastY; - } - - win->event.type = RGFW_mousePosChanged; - win->_lastMousePoint.x += win->event.point.x; - win->_lastMousePoint.y += win->event.point.y; - break; - } - - case WM_LBUTTONDOWN: - win->event.button = RGFW_mouseLeft; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - case WM_RBUTTONDOWN: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - case WM_MBUTTONDOWN: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case WM_MOUSEWHEEL: - if (msg.wParam > 0) - win->event.button = RGFW_mouseScrollUp; - else - win->event.button = RGFW_mouseScrollDown; - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - - win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; - - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case WM_LBUTTONUP: - - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonReleased; - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - case WM_RBUTTONUP: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonReleased; - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - case WM_MBUTTONUP: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonReleased; - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - /* - much of this event is source from glfw - */ - case WM_DROPFILES: { - win->event.type = RGFW_dnd_init; - - drop = (HDROP) msg.wParam; - POINT pt; - - /* Move the mouse to the position of the drop */ - DragQueryPoint(drop, &pt); - - win->event.point.x = pt.x; - win->event.point.y = pt.y; - - RGFW_dndInitCallback(win, win->event.point); - } - break; - case WM_GETMINMAXINFO: - { - if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) - break; - - MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam; - mmi->ptMinTrackSize.x = win->src.minSize.w; - mmi->ptMinTrackSize.y = win->src.minSize.h; - mmi->ptMaxTrackSize.x = win->src.maxSize.w; - mmi->ptMaxTrackSize.y = win->src.maxSize.h; - return 0; - } - default: - TranslateMessage(&msg); - DispatchMessageA(&msg); - - return RGFW_window_checkEvent(win); - break; - } - - TranslateMessage(&msg); - DispatchMessageA(&msg); - + RGFW_eventWindow.src.window = NULL; + RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); return &win->event; } - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMAXIMIZED; - } + static HDROP drop; - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); - - return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win); - } - - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); - - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMINIMIZED; - } - - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); - - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMAXIMIZED; - } - - typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo; - BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - RGFW_UNUSED(hdcMonitor) - RGFW_UNUSED(lprcMonitor) - - RGFW_mInfo* info = (RGFW_mInfo*) dwData; - if (info->hMonitor == hMonitor) - return FALSE; - - info->iIndex++; - return TRUE; - } - - #ifndef RGFW_NO_MONITOR - RGFW_monitor win32CreateMonitor(HMONITOR src) { - RGFW_monitor monitor; - MONITORINFO monitorInfo; - - monitorInfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfoA(src, &monitorInfo); - - RGFW_mInfo info; - info.iIndex = 0; - info.hMonitor = src; - - /* get the monitor's index */ - if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) { - DISPLAY_DEVICEA dd; - dd.cb = sizeof(dd); - - /* loop through the devices until you find a device with the monitor's index */ - size_t deviceIndex; - for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { - char* deviceName = dd.DeviceName; - if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { - strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */ - break; - } - } + if (win->event.type == RGFW_DNDInit) { + if (win->event.droppedFilesCount) { + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) + win->event.droppedFiles[i][0] = '\0'; } - monitor.rect.x = monitorInfo.rcWork.left; - monitor.rect.y = monitorInfo.rcWork.top; - monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left; - monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + win->event.droppedFilesCount = 0; + win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); -#ifndef RGFW_NO_DPI - #ifndef USER_DEFAULT_SCREEN_DPI - #define USER_DEFAULT_SCREEN_DPI 96 - #endif + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) { + UINT length = DragQueryFileW(drop, i, NULL, 0); + if (length == 0) + continue; + WCHAR buffer[RGFW_MAX_PATH * 2]; + if (length > (RGFW_MAX_PATH * 2) - 1) + length = RGFW_MAX_PATH * 2; + + DragQueryFileW(drop, i, buffer, length + 1); + + char* str = RGFW_createUTF8FromWideStringWin32(buffer); + if (str != NULL) + RGFW_MEMCPY(win->event.droppedFiles[i], str, length + 1); + + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; + } + + DragFinish(drop); + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + + win->event.type = RGFW_DND; + return &win->event; + } + + win->event.inFocus = (GetForegroundWindow() == win->src.window); + + if (RGFW_checkXInput(win, &win->event)) + return &win->event; + + static BYTE keyboardState[256]; + GetKeyboardState(keyboardState); + + + if (!IsWindow(win->src.window)) { + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + return &win->event; + } + + if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE) == 0) + return NULL; + + switch (msg.message) { + case WM_CLOSE: + case WM_QUIT: + RGFW_windowQuitCallback(win); + win->event.type = RGFW_quit; + break; + + case WM_ACTIVATE: + win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE); + + if (win->event.inFocus) { + win->event.type = RGFW_focusIn; + RGFW_focusCallback(win, 1); + } + else { + win->event.type = RGFW_focusOut; + RGFW_focusCallback(win, 0); + } + + break; + + case WM_PAINT: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + break; + + case WM_MOUSELEAVE: + win->event.type = RGFW_mouseLeave; + win->_flags |= RGFW_MOUSE_LEFT; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + + case WM_KEYUP: { + i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); + if (scancode == 0) + scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); + + switch (scancode) { + case 0x54: scancode = 0x137; break; /* Alt+PrtS */ + case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ + case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ + default: break; + } + + win->event.key = RGFW_apiKeyToRGFW((u32) scancode); + + if (msg.wParam == VK_CONTROL) { + if (HIWORD(msg.lParam) & KF_EXTENDED) + win->event.key = RGFW_controlR; + else win->event.key = RGFW_controlL; + } + + wchar_t charBuffer; + ToUnicodeEx(msg.wParam, scancode, keyboardState, (wchar_t*)&charBuffer, 1, 0, NULL); + + win->event.keyChar = (u8)charBuffer; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + win->event.type = RGFW_keyReleased; + RGFW_keyboard[win->event.key].current = 0; + + RGFW_updateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 0); + break; + } + case WM_KEYDOWN: { + i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); + if (scancode == 0) + scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); + + switch (scancode) { + case 0x54: scancode = 0x137; break; /* Alt+PrtS */ + case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ + case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ + default: break; + } + + win->event.key = RGFW_apiKeyToRGFW((u32) scancode); + + if (msg.wParam == VK_CONTROL) { + if (HIWORD(msg.lParam) & KF_EXTENDED) + win->event.key = RGFW_controlR; + else win->event.key = RGFW_controlL; + } + + wchar_t charBuffer; + ToUnicodeEx(msg.wParam, scancode, keyboardState, &charBuffer, 1, 0, NULL); + win->event.keyChar = (u8)charBuffer; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + + win->event.type = RGFW_keyPressed; + win->event.repeat = RGFW_isPressed(win, win->event.key); + RGFW_keyboard[win->event.key].current = 1; + RGFW_updateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 1); + break; + } + + case WM_MOUSEMOVE: { + if ((win->_flags & RGFW_HOLD_MOUSE)) + break; + + win->event.type = RGFW_mousePosChanged; + + i32 x = GET_X_LPARAM(msg.lParam); + i32 y = GET_Y_LPARAM(msg.lParam); + + RGFW_mousePosCallback(win, win->event.point); + + if (win->_flags & RGFW_MOUSE_LEFT) { + win->_flags ^= RGFW_MOUSE_LEFT; + win->event.type = RGFW_mouseEnter; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + } + + /*if ((win->_flags & RGFW_HOLD_MOUSE)) { + RGFW_point p = RGFW_getGlobalMousePoint(); + //p = RGFW_POINT(p.x + win->r.x, p.y + win->r.y); + + win->event.point.x = x - win->_lastMousePoint.x; + win->event.point.y = y - win->_lastMousePoint.y; + + win->_lastMousePoint = RGFW_POINT(x, y); + break; + }*/ + + win->event.point.x = x; + win->event.point.y = y; + win->_lastMousePoint = RGFW_POINT(x, y); + + break; + } + case WM_INPUT: { + if (!(win->_flags & RGFW_HOLD_MOUSE)) + break; + + unsigned size = sizeof(RAWINPUT); + static RAWINPUT raw = {}; + + GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER)); + + if (raw.header.dwType != RIM_TYPEMOUSE || (raw.data.mouse.lLastX == 0 && raw.data.mouse.lLastY == 0) ) + break; + + if (raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { + POINT pos = {0, 0}; + int width, height; + + if (raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) { + pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN); + pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN); + width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + height = GetSystemMetrics(SM_CYVIRTUALSCREEN); + } + else { + width = GetSystemMetrics(SM_CXSCREEN); + height = GetSystemMetrics(SM_CYSCREEN); + } + + pos.x += (int) ((raw.data.mouse.lLastX / 65535.f) * width); + pos.y += (int) ((raw.data.mouse.lLastY / 65535.f) * height); + ScreenToClient(win->src.window, &pos); + + win->event.point.x = pos.x - win->_lastMousePoint.x; + win->event.point.y = pos.y - win->_lastMousePoint.y; + } else { + win->event.point.x = raw.data.mouse.lLastX; + win->event.point.y = raw.data.mouse.lLastY; + } + + win->event.type = RGFW_mousePosChanged; + win->_lastMousePoint.x += win->event.point.x; + win->_lastMousePoint.y += win->event.point.y; + break; + } + + case WM_LBUTTONDOWN: + win->event.button = RGFW_mouseLeft; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + case WM_RBUTTONDOWN: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + case WM_MBUTTONDOWN: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case WM_MOUSEWHEEL: + if (msg.wParam > 0) + win->event.button = RGFW_mouseScrollUp; + else + win->event.button = RGFW_mouseScrollDown; + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + + win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; + + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case WM_LBUTTONUP: + + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonReleased; + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_RBUTTONUP: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonReleased; + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_MBUTTONUP: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonReleased; + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_DROPFILES: { + win->event.type = RGFW_DNDInit; + + drop = (HDROP) msg.wParam; + POINT pt; + + /* Move the mouse to the position of the drop */ + DragQueryPoint(drop, &pt); + + win->event.point.x = pt.x; + win->event.point.y = pt.y; + + RGFW_dndInitCallback(win, win->event.point); + } + break; + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam; + mmi->ptMinTrackSize.x = win->src.minSize.w; + mmi->ptMinTrackSize.y = win->src.minSize.h; + + if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) + return RGFW_window_checkEvent(win); + + mmi->ptMaxTrackSize.x = win->src.maxSize.w; + mmi->ptMaxTrackSize.y = win->src.maxSize.h; + return RGFW_window_checkEvent(win); + } + default: + TranslateMessage(&msg); + DispatchMessageA(&msg); + return RGFW_window_checkEvent(win); + } + + TranslateMessage(&msg); + DispatchMessageA(&msg); + + return &win->event; +} + +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMAXIMIZED; +} + +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win); +} + +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMINIMIZED; +} + +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMAXIMIZED; +} + +typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo; +BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + RGFW_UNUSED(hdcMonitor); + RGFW_UNUSED(lprcMonitor); + + RGFW_mInfo* info = (RGFW_mInfo*) dwData; + if (info->hMonitor == hMonitor) + return FALSE; + + info->iIndex++; + return TRUE; +} + +#ifndef RGFW_NO_MONITOR + +RGFW_monitor win32CreateMonitor(HMONITOR src) { + RGFW_monitor monitor; + MONITORINFOEX monitorInfo; + + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfoA(src, (LPMONITORINFO)&monitorInfo); + + RGFW_mInfo info; + info.iIndex = 0; + info.hMonitor = src; + + /* get the monitor's index */ + if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) { + DISPLAY_DEVICEA dd; + dd.cb = sizeof(dd); + + /* loop through the devices until you find a device with the monitor's index */ + size_t deviceIndex; + for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { + char* deviceName = dd.DeviceName; + if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { + RGFW_MEMCPY(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */ + break; + } + } + } + + monitor.rect.x = monitorInfo.rcWork.left; + monitor.rect.y = monitorInfo.rcWork.top; + monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left; + monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + + HDC hdc = CreateDC(monitorInfo.szDevice, NULL, NULL, NULL); + /* get pixels per inch */ + float dpiX = (float)GetDeviceCaps(hdc, LOGPIXELSX); + float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSX); + + monitor.scaleX = dpiX / 96.0f; + monitor.scaleY = dpiY / 96.0f; + + monitor.physW = GetDeviceCaps(hdc, HORZSIZE) / 25.4; + monitor.physH = GetDeviceCaps(hdc, VERTSIZE) / 25.4; + DeleteDC(hdc); + + #ifndef RGFW_NO_DPI if (GetDpiForMonitor != NULL) { u32 x, y; GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y); - - monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI; - monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI; + + monitor.pixelRatio = (float) (x) / (float) dpiX; + monitor.pixelRatio = (float) (y) / (float) dpiY; } -#endif - - HDC hdc = GetDC(NULL); - /* get pixels per inch */ - i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX); - i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - - /* Calculate physical height in inches */ - monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX; - monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY; - - #ifdef RGFW_DEBUG - printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY); - #endif - - return monitor; - } - #endif /* RGFW_NO_MONITOR */ - - - #ifndef RGFW_NO_MONITOR - RGFW_monitor RGFW_monitors[6]; - BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - RGFW_UNUSED(hdcMonitor) - RGFW_UNUSED(lprcMonitor) - - RGFW_mInfo* info = (RGFW_mInfo*) dwData; - - if (info->iIndex >= 6) - return FALSE; - - RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor); - info->iIndex++; - - return TRUE; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - #ifdef __cplusplus - return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); - #else - return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); - #endif - } - - RGFW_monitor* RGFW_getMonitors(void) { - RGFW_mInfo info; - info.iIndex = 0; - while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info)); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY); - return win32CreateMonitor(src); - } #endif - HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) { - assert(win != NULL); + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif - u32 i; - HDC dc; - HICON handle; - HBITMAP color, mask; - BITMAPV5HEADER bi; - ICONINFO ii; - u8* target = NULL; - u8* source = src; + return monitor; +} +#endif /* RGFW_NO_MONITOR */ - ZeroMemory(&bi, sizeof(bi)); - bi.bV5Size = sizeof(bi); - bi.bV5Width = a.w; - bi.bV5Height = -((LONG) a.h); - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5RedMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5BlueMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; +#ifndef RGFW_NO_MONITOR - dc = GetDC(NULL); - color = CreateDIBSection(dc, - (BITMAPINFO*) &bi, - DIB_RGB_COLORS, - (void**) &target, - NULL, - (DWORD) 0); - ReleaseDC(NULL, dc); +RGFW_monitor RGFW_monitors[6]; +BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + RGFW_UNUSED(hdcMonitor); + RGFW_UNUSED(lprcMonitor); - mask = CreateBitmap(a.w, a.h, 1, 1, NULL); + RGFW_mInfo* info = (RGFW_mInfo*) dwData; - for (i = 0; i < a.w * a.h; i++) { - target[0] = source[2]; - target[1] = source[1]; - target[2] = source[0]; - target[3] = source[3]; - target += 4; - source += 4; - } + if (info->iIndex >= 6) + return FALSE; - ZeroMemory(&ii, sizeof(ii)); - ii.fIcon = icon; - ii.xHotspot = 0; - ii.yHotspot = 0; - ii.hbmMask = mask; - ii.hbmColor = color; + RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor); + info->iIndex++; - handle = CreateIconIndirect(&ii); + return TRUE; +} - DeleteObject(color); - DeleteObject(mask); +RGFW_monitor RGFW_getPrimaryMonitor(void) { + #ifdef __cplusplus + return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); + #else + return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); + #endif +} - return handle; - } +RGFW_monitor* RGFW_getMonitors(void) { + RGFW_mInfo info; + info.iIndex = 0; + while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info)); - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); - RGFW_UNUSED(channels) + return RGFW_monitors; +} - HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE); - SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor); - SetCursor(cursor); - DestroyCursor(cursor); - } +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY); + return win32CreateMonitor(src); +} - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - assert(win != NULL); - - if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) - return; - - char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); - - SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); - SetCursor(LoadCursorA(NULL, icon)); - } - - void RGFW_window_hide(RGFW_window* win) { - ShowWindow(win->src.window, SW_HIDE); - } - - void RGFW_window_show(RGFW_window* win) { - ShowWindow(win->src.window, SW_RESTORE); - } - - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_EGL - RGFW_closeEGL(win); #endif - if (win == RGFW_root) { -#ifdef RGFW_DIRECTX +HICON RGFW_loadHandleImage(u8* src, RGFW_area a, BOOL icon) { + u32 i; + HDC dc; + HICON handle; + HBITMAP color, mask; + BITMAPV5HEADER bi; + ICONINFO ii; + u8* target = NULL; + u8* source = src; + + ZeroMemory(&bi, sizeof(bi)); + bi.bV5Size = sizeof(bi); + bi.bV5Width = a.w; + bi.bV5Height = -((LONG) a.h); + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5RedMask = 0x00ff0000; + bi.bV5GreenMask = 0x0000ff00; + bi.bV5BlueMask = 0x000000ff; + bi.bV5AlphaMask = 0xff000000; + + dc = GetDC(NULL); + color = CreateDIBSection(dc, + (BITMAPINFO*) &bi, + DIB_RGB_COLORS, + (void**) &target, + NULL, + (DWORD) 0); + ReleaseDC(NULL, dc); + + mask = CreateBitmap(a.w, a.h, 1, 1, NULL); + + for (i = 0; i < a.w * a.h; i++) { + target[0] = source[2]; + target[1] = source[1]; + target[2] = source[0]; + target[3] = source[3]; + target += 4; + source += 4; + } + + ZeroMemory(&ii, sizeof(ii)); + ii.fIcon = icon; + ii.xHotspot = 0; + ii.yHotspot = 0; + ii.hbmMask = mask; + ii.hbmColor = color; + + handle = CreateIconIndirect(&ii); + + DeleteObject(color); + DeleteObject(mask); + + return handle; +} + +void* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + RGFW_UNUSED(channels); + + HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(icon, a, FALSE); + return cursor; +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { + RGFW_ASSERT(win && mouse); + SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) mouse); + SetCursor((HCURSOR)mouse); +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { + RGFW_ASSERT(mouse); + DestroyCursor((HCURSOR)mouse); +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_ASSERT(win != NULL); + + if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) + return 0; + + char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); + + SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); + SetCursor(LoadCursorA(NULL, icon)); + return 1; +} + +void RGFW_window_hide(RGFW_window* win) { + ShowWindow(win->src.window, SW_HIDE); +} + +void RGFW_window_show(RGFW_window* win) { + ShowWindow(win->src.window, SW_RESTORE); +} + +#define RGFW_FREE_LIBRARY(x) if (x != NULL) FreeLibrary(x); x = NULL; + +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_windowsOpen--; + + #ifdef RGFW_EGL + RGFW_closeEGL(win); + #endif + + #ifdef RGFW_DIRECTX + win->src.swapchain->lpVtbl->Release(win->src.swapchain); + win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView); + win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView); + #endif + + #ifdef RGFW_BUFFER + DeleteDC(win->src.hdcMem); + DeleteObject(win->src.bitmap); + #endif + + #ifdef RGFW_OPENGL + wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */ + #endif + ReleaseDC(win->src.window, win->src.hdc); /*!< delete device context */ + DestroyWindow(win->src.window); /*!< delete window */ + + #ifdef RGFW_ALLOC_DROPFILES + { + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); + + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); + } + #endif + + if (RGFW_windowsOpen <= 0) { + #ifdef RGFW_DIRECTX RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext); RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice); RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter); RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); -#endif - - if (RGFW_XInput_dll != NULL) { - FreeLibrary(RGFW_XInput_dll); - RGFW_XInput_dll = NULL; - } + #endif - #ifndef RGFW_NO_DPI - if (RGFW_Shcore_dll != NULL) { - FreeLibrary(RGFW_Shcore_dll); - RGFW_Shcore_dll = NULL; - } - #endif + #ifndef RGFW_NO_XINPUT + RGFW_FREE_LIBRARY(RGFW_XInput_dll); + #endif - if (wglinstance != NULL) { - FreeLibrary(wglinstance); - wglinstance = NULL; - } + #ifndef RGFW_NO_DPI + RGFW_FREE_LIBRARY(RGFW_Shcore_dll); + #endif - RGFW_root = NULL; - } + #if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + RGFW_FREE_LIBRARY(RGFW_winmm_dll); + #endif -#ifdef RGFW_DIRECTX - win->src.swapchain->lpVtbl->Release(win->src.swapchain); - win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView); - win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView); -#endif + RGFW_FREE_LIBRARY(RGFW_wgl_dll); + RGFW_root = NULL; -#ifdef RGFW_BUFFER - DeleteDC(win->src.hdcMem); - DeleteObject(win->src.bitmap); -#endif - -#ifdef RGFW_OPENGL - wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */ -#endif - DeleteDC(win->src.hdc); /*!< delete device context */ - DestroyWindow(win->src.window); /*!< delete window */ - -#if defined(RGFW_OSMESA) - if (win->buffer != NULL) - RGFW_FREE(win->buffer); -#endif - -#ifdef RGFW_ALLOC_DROPFILES - { - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); - - - RGFW_FREE(win->event.droppedFiles); - } -#endif - - RGFW_FREE(win); - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); - - win->r.x = v.x; - win->r.y = v.y; - SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE); - } - - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - win->r.w = a.w; - win->r.h = a.h; - SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE); - } - - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - SetWindowTextA(win->src.window, name); - } - - /* sourced from GLFW */ - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - assert(win != NULL); - - COLORREF key = 0; - BYTE alpha = 0; - DWORD flags = 0; - DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE); - - if (exStyle & WS_EX_LAYERED) - GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags); - - if (passthrough) - exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); - else - { - exStyle &= ~WS_EX_TRANSPARENT; - // NOTE: Window opacity also needs the layered window style so do not - // remove it if the window is alpha blended - if (exStyle & WS_EX_LAYERED) - { - if (!(flags & LWA_ALPHA)) - exStyle &= ~WS_EX_LAYERED; - } - } - - SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle); - - if (passthrough) { - SetLayeredWindowAttributes(win->src.window, key, alpha, flags); + if (RGFW_hiddenMouse != NULL) { + RGFW_freeMouse(RGFW_hiddenMouse); + RGFW_hiddenMouse = 0; } } - #endif - /* much of this function is sourced from GLFW */ - void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { - assert(win != NULL); - #ifndef RGFW_WIN95 - RGFW_UNUSED(channels) + RGFW_clipboard_switch(NULL); - HICON handle = RGFW_loadHandleImage(win, src, a, TRUE); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); +} + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + + win->r.x = v.x; + win->r.y = v.y; + SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE); +} + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + win->r.w = a.w; + win->r.h = a.h; + SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE); +} + + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win != NULL); + + SetWindowTextA(win->src.window, name); +} + +#ifndef RGFW_NO_PASSTHROUGH + +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_ASSERT(win != NULL); + + COLORREF key = 0; + BYTE alpha = 0; + DWORD flags = 0; + DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE); + + if (exStyle & WS_EX_LAYERED) + GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags); + + if (passthrough) + exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); + else { + exStyle &= ~WS_EX_TRANSPARENT; + if (exStyle & WS_EX_LAYERED && !(flags & LWA_ALPHA)) + exStyle &= ~WS_EX_LAYERED; + } + + SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle); + + if (passthrough) + SetLayeredWindowAttributes(win->src.window, key, alpha, flags); +} +#endif + +b32 RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { + RGFW_ASSERT(win != NULL); + #ifndef RGFW_WIN95 + RGFW_UNUSED(channels); + + HICON handle = RGFW_loadHandleImage(src, a, TRUE); SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle); DestroyIcon(handle); - #else - RGFW_UNUSED(src) - RGFW_UNUSED(a) - RGFW_UNUSED(channels) + return 1; + #else + RGFW_UNUSED(src); + RGFW_UNUSED(a); + RGFW_UNUSED(channels); + return 0; + #endif +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + /* Open the clipboard */ + if (OpenClipboard(NULL) == 0) + return -1; + + /* Get the clipboard data as a Unicode string */ + HANDLE hData = GetClipboardData(CF_UNICODETEXT); + if (hData == NULL) { + CloseClipboard(); + return -1; + } + + wchar_t* wstr = (wchar_t*) GlobalLock(hData); + + RGFW_ssize_t textLen = 0; + + { + setlocale(LC_ALL, "en_US.UTF-8"); + + textLen = wcstombs(NULL, wstr, 0) + 1; + if (str != NULL && (RGFW_ssize_t)strCapacity <= textLen - 1) + textLen = 0; + + if (str != NULL && textLen) { + + if (textLen > 1) + wcstombs(str, wstr, (textLen) ); + + str[textLen] = '\0'; + } + } + + /* Release the clipboard data */ + GlobalUnlock(hData); + CloseClipboard(); + + return textLen; +} + +void RGFW_writeClipboard(const char* text, u32 textLen) { + HANDLE object; + WCHAR* buffer; + + object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR)); + if (!object) + return; + + buffer = (WCHAR*) GlobalLock(object); + if (!buffer) { + GlobalFree(object); + return; + } + + MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen); + GlobalUnlock(object); + + if (!OpenClipboard(RGFW_root->src.window)) { + GlobalFree(object); + return; + } + + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, object); + CloseClipboard(); +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { + RGFW_ASSERT(win != NULL); + win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); + SetCursorPos(p.x, p.y); +} + +#ifdef RGFW_OPENGL +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + if (win == NULL) + wglMakeCurrent(NULL, NULL); + else + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); +} +#endif + +#ifndef RGFW_EGL + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + #if defined(RGFW_OPENGL) + typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); + static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; + static void* loadSwapFunc = (void*) 1; + + if (loadSwapFunc == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "wglSwapIntervalEXT not supported\n"); + #endif + return; + } + + if (wglSwapIntervalEXT == NULL) { + loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; + } + + if (wglSwapIntervalEXT(swapInterval) == FALSE) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to set swap interval\n"); #endif } - - char* RGFW_readClipboard(size_t* size) { - /* Open the clipboard */ - if (OpenClipboard(NULL) == 0) - return (char*) ""; - - /* Get the clipboard data as a Unicode string */ - HANDLE hData = GetClipboardData(CF_UNICODETEXT); - if (hData == NULL) { - CloseClipboard(); - return (char*) ""; - } - - wchar_t* wstr = (wchar_t*) GlobalLock(hData); - - char* text; - - { - setlocale(LC_ALL, "en_US.UTF-8"); - - size_t textLen = wcstombs(NULL, wstr, 0); - if (textLen == 0) - return (char*) ""; - - text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1); - - wcstombs(text, wstr, (textLen) +1); - - if (size != NULL) - *size = textLen + 1; - - text[textLen] = '\0'; - } - - /* Release the clipboard data */ - GlobalUnlock(hData); - CloseClipboard(); - - return text; - } - - void RGFW_writeClipboard(const char* text, u32 textLen) { - HANDLE object; - WCHAR* buffer; - - object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR)); - if (!object) - return; - - buffer = (WCHAR*) GlobalLock(object); - if (!buffer) { - GlobalFree(object); - return; - } - - MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen); - GlobalUnlock(object); - - if (!OpenClipboard(RGFW_root->src.window)) { - GlobalFree(object); - return; - } - - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, object); - CloseClipboard(); - } - - u16 RGFW_registerGamepad(RGFW_window* win, i32 gpNumber) { - assert(win != NULL); - - RGFW_UNUSED(gpNumber) - - return RGFW_registerGamepadF(win, (char*) ""); - } - - u16 RGFW_registerGamepadF(RGFW_window* win, char* file) { - assert(win != NULL); - RGFW_UNUSED(file) - - return RGFW_gamepadCount - 1; - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { - assert(win != NULL); - win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); - SetCursorPos(p.x, p.y); - } - - #ifdef RGFW_OPENGL - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - if (win == NULL) - wglMakeCurrent(NULL, NULL); - else - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); - } + #else + RGFW_UNUSED(swapInterval); #endif +} - #ifndef RGFW_EGL - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - #if defined(RGFW_OPENGL) - typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); - static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - static void* loadSwapFunc = (void*) 1; +#endif - if (loadSwapFunc == NULL) { - fprintf(stderr, "wglSwapIntervalEXT not supported\n"); - return; - } - - if (wglSwapIntervalEXT == NULL) { - loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; - } - - if (wglSwapIntervalEXT(swapInterval) == FALSE) - fprintf(stderr, "Failed to set swap interval\n"); - #else - RGFW_UNUSED(swapInterval); - #endif - - } - #endif - - void RGFW_window_swapBuffers(RGFW_window* win) { - //assert(win != NULL); - /* clear the window*/ - - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + /* clear the window*/ + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap); BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY); SelectObject(win->src.hdcMem, oldbmp); -#endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - SwapBuffers(win->src.hdc); - #endif - - #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); - #endif - } + #endif } - char* createUTF8FromWideStringWin32(const WCHAR* source) { - char* target; - i32 size; + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + SwapBuffers(win->src.hdc); + #endif - size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); - if (!size) { - return NULL; - } - - target = (char*) RGFW_CALLOC(size, 1); - - if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) { - RGFW_FREE(target); - return NULL; - } - - return target; + #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); + #endif } - - static inline LARGE_INTEGER RGFW_win32_initTimer(void) { - static LARGE_INTEGER frequency = {{0, 0}}; - if (frequency.QuadPart == 0) { - timeBeginPeriod(1); - QueryPerformanceFrequency(&frequency); - } +} - return frequency; +char* RGFW_createUTF8FromWideStringWin32(const WCHAR* source) { + if (source == NULL) { + return NULL; + } + i32 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); + if (!size) { + return NULL; } - u64 RGFW_getTimeNS(void) { - LARGE_INTEGER frequency = RGFW_win32_initTimer(); + static char target[RGFW_MAX_PATH * 2]; + if (size > RGFW_MAX_PATH * 2) + size = RGFW_MAX_PATH * 2; - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); + target[size] = 0; - return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart); + if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) { + return NULL; } - u64 RGFW_getTime(void) { - LARGE_INTEGER frequency = RGFW_win32_initTimer(); + return target; +} - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (u64) (counter.QuadPart / (double) frequency.QuadPart); - } - - void RGFW_sleep(u64 ms) { - Sleep(ms); +static inline LARGE_INTEGER RGFW_win32_initTimer(void) { + static LARGE_INTEGER frequency = {{0, 0}}; + if (frequency.QuadPart == 0) { + #if !defined(RGFW_NO_WINMM) + timeBeginPeriod(1); + #endif + QueryPerformanceFrequency(&frequency); } + return frequency; +} + +u64 RGFW_getTimeNS(void) { + LARGE_INTEGER frequency = RGFW_win32_initTimer(); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart); +} + +u64 RGFW_getTime(void) { + LARGE_INTEGER frequency = RGFW_win32_initTimer(); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (u64) (counter.QuadPart / (double) frequency.QuadPart); +} + +void RGFW_sleep(u64 ms) { + Sleep(ms); +} + #ifndef RGFW_NO_THREADS - RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); } - void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); } - void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); } - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); } + +RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); } +void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); } +void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); } +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); } + #endif #endif /* RGFW_WINDOWS */ @@ -6803,7 +7096,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ -/* +/* Start of MacOS defines @@ -6811,677 +7104,837 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ */ #if defined(RGFW_MACOS) - /* - based on silicon.h - start of cocoa wrapper - */ +/* + based on silicon.h + start of cocoa wrapper +*/ -#include +#include #include #include #include #include - typedef CGRect NSRect; - typedef CGPoint NSPoint; - typedef CGSize NSSize; +typedef CGRect NSRect; +typedef CGPoint NSPoint; +typedef CGSize NSSize; - typedef void NSBitmapImageRep; - typedef void NSCursor; - typedef void NSDraggingInfo; - typedef void NSWindow; - typedef void NSApplication; - typedef void NSEvent; - typedef void NSString; - typedef void NSOpenGLContext; - typedef void NSPasteboard; - typedef void NSColor; - typedef void NSArray; - typedef void NSImageRep; - typedef void NSImage; - typedef void NSOpenGLView; - - - typedef const char* NSPasteboardType; - typedef unsigned long NSUInteger; - typedef long NSInteger; - typedef NSInteger NSModalResponse; +typedef const char* NSPasteboardType; +typedef unsigned long NSUInteger; +typedef long NSInteger; +typedef NSInteger NSModalResponse; #ifdef __arm64__ /* ARM just uses objc_msgSend */ #define abi_objc_msgSend_stret objc_msgSend #define abi_objc_msgSend_fpret objc_msgSend -#else /* __i386__ */ +#else /* __i386__ */ /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */ #define abi_objc_msgSend_stret objc_msgSend_stret #define abi_objc_msgSend_fpret objc_msgSend_fpret #endif #define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc")) -#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_uint ((NSUInteger (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend) -#define objc_msgSend_bool_void ((BOOL (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) -#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) -#define objc_msgSend_id_id ((id (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_id_bool ((BOOL (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend) -#define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend) -#define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend) -#define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend) -#define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend) +#define objc_msgSend_bool(x, y) ((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void(x, y) ((void (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_id(x, y, z) ((void (*)(id, SEL, id))objc_msgSend) ((id)x, (SEL)y, (id)z) +#define objc_msgSend_uint(x, y) ((NSUInteger (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_bool(x, y, z) ((void (*)(id, SEL, BOOL))objc_msgSend) ((id)(x), (SEL)y, (BOOL)z) +#define objc_msgSend_bool_void(x, y) ((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_SEL(x, y, z) ((void (*)(id, SEL, SEL))objc_msgSend) ((id)(x), (SEL)y, (SEL)z) +#define objc_msgSend_id(x, y) ((id (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_id_id(x, y, z) ((id (*)(id, SEL, id))objc_msgSend) ((id)(x), (SEL)y, (id)z) +#define objc_msgSend_id_bool(x, y, z) ((BOOL (*)(id, SEL, id))objc_msgSend) ((id)(x), (SEL)y, (id)z) +#define objc_msgSend_int(x, y, z) ((id (*)(id, SEL, int))objc_msgSend) ((id)(x), (SEL)y, (int)z) +#define objc_msgSend_arr(x, y, z) ((id (*)(id, SEL, int))objc_msgSend) ((id)(x), (SEL)y, (int)z) +#define objc_msgSend_ptr(x, y, z) ((id (*)(id, SEL, void*))objc_msgSend) ((id)(x), (SEL)y, (void*)z) +#define objc_msgSend_class(x, y) ((id (*)(Class, SEL))objc_msgSend) ((Class)(x), (SEL)y) +#define objc_msgSend_class_char(x, y, z) ((id (*)(Class, SEL, char*))objc_msgSend) ((Class)(x), (SEL)y, (char*)z) - NSApplication* NSApp = NULL; +id NSApp = NULL; - void NSRelease(id obj) { - objc_msgSend_void(obj, sel_registerName("release")); +#define NSRelease(obj) objc_msgSend_void((id)obj, sel_registerName("release")) + +id NSString_stringWithUTF8String(const char* str) { + return ((id(*)(id, SEL, const char*))objc_msgSend) + ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str); +} + +const char* NSString_to_char(id str) { + return ((const char* (*)(id, SEL)) objc_msgSend) ((id)(id)str, sel_registerName("UTF8String")); +} + +void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { + Class selected_class; + + if (RGFW_STRNCMP(class_name, "NSView", 6) == 0) { + selected_class = objc_getClass("ViewClass"); + } else if (RGFW_STRNCMP(class_name, "NSWindow", 8) == 0) { + selected_class = objc_getClass("WindowClass"); + } else { + selected_class = objc_getClass(class_name); } - #define release NSRelease + class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); +} - NSString* NSString_stringWithUTF8String(const char* str) { - return ((id(*)(id, SEL, const char*))objc_msgSend) - ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str); - } +/* Header for the array. */ +typedef struct siArrayHeader { + size_t count; + /* TODO(EimaMei): Add a `type_width` later on. */ +} siArrayHeader; - const char* NSString_to_char(NSString* str) { - return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String")); - } - - void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { - Class selected_class; - - if (strcmp(class_name, "NSView") == 0) { - selected_class = objc_getClass("ViewClass"); - } else if (strcmp(class_name, "NSWindow") == 0) { - selected_class = objc_getClass("WindowClass"); - } else { - selected_class = objc_getClass(class_name); - } - - class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); - } - - /* Header for the array. */ - typedef struct siArrayHeader { - size_t count; - /* TODO(EimaMei): Add a `type_width` later on. */ - } siArrayHeader; - - /* Gets the header of the siArray. */ +/* Gets the header of the siArray. */ #define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1) - - void* si_array_init_reserve(size_t sizeof_element, size_t count) { - siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); - void* array = ptr + sizeof(siArrayHeader); - - siArrayHeader* header = SI_ARRAY_HEADER(array); - header->count = count; - - return array; - } - #define si_array_len(array) (SI_ARRAY_HEADER(array)->count) -#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function) - /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ -#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function) - - unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) { - return ((unsigned char* (*)(id, SEL))objc_msgSend) - (imageRep, sel_registerName("bitmapData")); - } +#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", (void*)function) +/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ +#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", (void*)function) -#define NS_ENUM(type, name) type name; enum +unsigned char* NSBitmapImageRep_bitmapData(id imageRep) { + return ((unsigned char* (*)(id, SEL))objc_msgSend) ((id)imageRep, sel_registerName("bitmapData")); +} - typedef NS_ENUM(NSUInteger, NSBitmapFormat) { - NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) - NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied - NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer +typedef RGFW_ENUM(NSUInteger, NSBitmapFormat) { + NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) + NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied + NSBitmapFormatFloatingpointSamples = 1 << 2, // 0 is integer - NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), - NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), - NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), - NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) - }; + NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), + NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), + NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), + NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) +}; - NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { - void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); +id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { + SEL func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); - return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) - (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); - } + return (id) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, id, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) + (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); +} - NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { - void* nsclass = objc_getClass("NSColor"); - void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); - return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) - (nsclass, func, red, green, blue, alpha); - } +id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { + void* nsclass = objc_getClass("NSColor"); + SEL func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); + return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) + ((id)nsclass, func, red, green, blue, alpha); +} - NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { - void* func = sel_registerName("initWithImage:hotSpot:"); - void* nsclass = objc_getClass("NSCursor"); +id NSCursor_initWithImage(id newImage, NSPoint aPoint) { + SEL func = sel_registerName("initWithImage:hotSpot:"); + void* nsclass = objc_getClass("NSCursor"); - return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) - (NSAlloc(nsclass), func, newImage, aPoint); - } + return (id) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) + (NSAlloc(nsclass), func, newImage, aPoint); +} - void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) { - void* func = sel_registerName("addRepresentation:"); - objc_msgSend_void_id(image, func, imageRep); - } +void NSImage_addRepresentation(id image, id imageRep) { + SEL func = sel_registerName("addRepresentation:"); + objc_msgSend_void_id(image, func, (id)imageRep); +} - NSImage* NSImage_initWithSize(NSSize size) { - void* func = sel_registerName("initWithSize:"); - return ((id(*)(id, SEL, NSSize))objc_msgSend) - (NSAlloc((id)objc_getClass("NSImage")), func, size); - } +id NSImage_initWithSize(NSSize size) { + SEL func = sel_registerName("initWithSize:"); + return ((id(*)(id, SEL, NSSize))objc_msgSend) + (NSAlloc((id)objc_getClass("NSImage")), func, size); +} #define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers)) - typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) { - NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */ - NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ - NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ - NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ - NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */ - NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */ - NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */ - NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ - NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ - NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ +typedef RGFW_ENUM(NSInteger, NSOpenGLContextParameter) { + NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */ + NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ + NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ + NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ + NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */ + NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */ + NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */ + NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ + NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ + NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ - NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ - NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */ - NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */ - NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */ - NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ - }; + NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ + NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */ + NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */ + NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */ + NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ +}; - void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) { - void* func = sel_registerName("setValues:forParameter:"); - ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) - (context, func, vals, param); - } +void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param) { + SEL func = sel_registerName("setValues:forParameter:"); + ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) + (context, func, vals, param); +} - void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { - void* func = sel_registerName("initWithAttributes:"); - return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); - } +void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { + SEL func = sel_registerName("initWithAttributes:"); + return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); +} - NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { - void* func = sel_registerName("initWithFrame:pixelFormat:"); - return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); - } +id NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { + SEL func = sel_registerName("initWithFrame:pixelFormat:"); + return (id) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); +} - void NSCursor_performSelector(NSCursor* cursor, void* selector) { - void* func = sel_registerName("performSelector:"); - objc_msgSend_void_SEL(cursor, func, selector); - } +void NSCursor_performSelector(id cursor, SEL selector) { + SEL func = sel_registerName("performSelector:"); + objc_msgSend_void_SEL(cursor, func, selector); +} - NSPasteboard* NSPasteboard_generalPasteboard(void) { - return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); - } +id NSPasteboard_generalPasteboard(void) { + return (id) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); +} - NSString** cstrToNSStringArray(char** strs, size_t len) { - static NSString* nstrs[6]; - size_t i; - for (i = 0; i < len; i++) - nstrs[i] = NSString_stringWithUTF8String(strs[i]); +id* cstrToNSStringArray(char** strs, size_t len) { + static id nstrs[6]; + size_t i; + for (i = 0; i < len; i++) + nstrs[i] = NSString_stringWithUTF8String(strs[i]); - return nstrs; - } + return nstrs; +} - const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) { - void* func = sel_registerName("stringForType:"); - return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType))); - } +const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len) { + SEL func = sel_registerName("stringForType:"); + id nsstr = NSString_stringWithUTF8String(dataType); + id nsString = ((id(*)(id, SEL, id))objc_msgSend)(pasteboard, func, nsstr); + const char* str = NSString_to_char(nsString); + if (len != NULL) + *len = (size_t)((NSUInteger(*)(id, SEL, int))objc_msgSend)(nsString, sel_registerName("maximumLengthOfBytesUsingEncoding:"), 4); + return str; +} - NSArray* c_array_to_NSArray(void* array, size_t len) { - SEL func = sel_registerName("initWithObjects:count:"); - void* nsclass = objc_getClass("NSArray"); - return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) - (NSAlloc(nsclass), func, array, len); - } - - void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); +id c_array_to_NSArray(void* array, size_t len) { + SEL func = sel_registerName("initWithObjects:count:"); + void* nsclass = objc_getClass("NSArray"); + return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) + (NSAlloc(nsclass), func, array, len); +} - NSArray* array = c_array_to_NSArray(ntypes, len); - objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); - NSRelease(array); - } +void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len) { + id* ntypes = cstrToNSStringArray((char**)newTypes, len); - NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); + id array = c_array_to_NSArray(ntypes, len); + objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); + NSRelease(array); +} - void* func = sel_registerName("declareTypes:owner:"); +NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { + id* ntypes = cstrToNSStringArray((char**)newTypes, len); - NSArray* array = c_array_to_NSArray(ntypes, len); + SEL func = sel_registerName("declareTypes:owner:"); - NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, owner); - NSRelease(array); + id array = c_array_to_NSArray(ntypes, len); - return output; - } + NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) + (pasteboard, func, array, owner); + NSRelease(array); - bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) { - void* func = sel_registerName("setString:forType:"); - return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend) - (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); - } + return output; +} - void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } +bool NSPasteBoard_setString(id pasteboard, const char* stringToWrite, NSPasteboardType dataType) { + SEL func = sel_registerName("setString:forType:"); + return ((bool (*)(id, SEL, id, id))objc_msgSend) + (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); +} - typedef enum NSApplicationActivationPolicy { - NSApplicationActivationPolicyRegular, - NSApplicationActivationPolicyAccessory, - NSApplicationActivationPolicyProhibited - } NSApplicationActivationPolicy; +#define NSRetain(obj) objc_msgSend_void((id)obj, sel_registerName("retain")) - typedef NS_ENUM(u32, NSBackingStoreType) { - NSBackingStoreRetained = 0, - NSBackingStoreNonretained = 1, - NSBackingStoreBuffered = 2 - }; +typedef enum NSApplicationActivationPolicy { + NSApplicationActivationPolicyRegular, + NSApplicationActivationPolicyAccessory, + NSApplicationActivationPolicyProhibited +} NSApplicationActivationPolicy; - typedef NS_ENUM(u32, NSWindowStyleMask) { - NSWindowStyleMaskBorderless = 0, - NSWindowStyleMaskTitled = 1 << 0, - NSWindowStyleMaskClosable = 1 << 1, - NSWindowStyleMaskMiniaturizable = 1 << 2, - NSWindowStyleMaskResizable = 1 << 3, - NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ - NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, - NSWindowStyleMaskFullScreen = 1 << 14, - NSWindowStyleMaskFullSizeContentView = 1 << 15, - NSWindowStyleMaskUtilityWindow = 1 << 4, - NSWindowStyleMaskDocModalWindow = 1 << 6, - NSWindowStyleMaskNonactivatingPanel = 1 << 7, - NSWindowStyleMaskHUDWindow = 1 << 13 - }; +typedef RGFW_ENUM(u32, NSBackingStoreType) { + NSBackingStoreRetained = 0, + NSBackingStoreNonretained = 1, + NSBackingStoreBuffered = 2 +}; - NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType +typedef RGFW_ENUM(u32, NSWindowStyleMask) { + NSWindowStyleMaskBorderless = 0, + NSWindowStyleMaskTitled = 1 << 0, + NSWindowStyleMaskClosable = 1 << 1, + NSWindowStyleMaskMiniaturizable = 1 << 2, + NSWindowStyleMaskResizable = 1 << 3, + NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ + NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, + NSWindowStyleMaskFullScreen = 1 << 14, + NSWindowStyleMaskFullSizeContentView = 1 << 15, + NSWindowStyleMaskUtilityWindow = 1 << 4, + NSWindowStyleMaskDocModalWindow = 1 << 6, + NSWindowStyleMaskNonactivatingpanel = 1 << 7, + NSWindowStyleMaskHUDWindow = 1 << 13 +}; + +NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPasteboardType - typedef NS_ENUM(i32, NSDragOperation) { - NSDragOperationNone = 0, - NSDragOperationCopy = 1, - NSDragOperationLink = 2, - NSDragOperationGeneric = 4, - NSDragOperationPrivate = 8, - NSDragOperationMove = 16, - NSDragOperationDelete = 32, - NSDragOperationEvery = ULONG_MAX, +typedef RGFW_ENUM(i32, NSDragOperation) { + NSDragOperationNone = 0, + NSDragOperationCopy = 1, + NSDragOperationLink = 2, + NSDragOperationGeneric = 4, + NSDragOperationPrivate = 8, + NSDragOperationMove = 16, + NSDragOperationDelete = 32, + NSDragOperationEvery = ULONG_MAX, - //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery - //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery - }; + //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery + //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery +}; - void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { - void* func = sel_registerName("objectAtIndex:"); - return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); - } +void* NSArray_objectAtIndex(id array, NSUInteger index) { + SEL func = sel_registerName("objectAtIndex:"); + return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); +} - const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) { - void* func = sel_registerName("readObjectsForClasses:options:"); +id NSWindow_contentView(id window) { + SEL func = sel_registerName("contentView"); + return objc_msgSend_id(window, func); +} - NSArray* array = c_array_to_NSArray(classArray, len); +/* + End of cocoa wrapper +*/ - NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, options); - - NSRelease(array); - NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count")); - - const char** res = si_array_init_reserve(sizeof(const char*), count); - - void* path_func = sel_registerName("path"); - - for (NSUInteger i = 0; i < count; i++) { - void* url = NSArray_objectAtIndex(output, i); - NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func); - res[i] = NSString_to_char(url_str); - } - - return res; - } - - void* NSWindow_contentView(NSWindow* window) { - void* func = sel_registerName("contentView"); - return objc_msgSend_id(window, func); - } - - /* - End of cocoa wrapper - */ - - char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; - - void* RGFWnsglFramework = NULL; +const char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; #ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { - if (RGFWnsglFramework == NULL) - RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); +CFBundleRef RGFWnsglFramework = NULL; - CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII); +void* RGFW_getProcAddress(const char* procname) { + if (RGFWnsglFramework == NULL) + RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName); + CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII); - CFRelease(symbolName); + void* symbol = (void*)CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName); - return symbol; - } + CFRelease(symbolName); + + return symbol; +} #endif - CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { - RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext) - return kCVReturnSuccess; - } - - id NSWindow_delegate(RGFW_window* win) { - return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate")); - } - - u32 RGFW_OnClose(void* self) { - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return true; - - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); +id NSWindow_delegate(RGFW_window* win) { + return (id) objc_msgSend_id((id)win->src.window, sel_registerName("delegate")); +} +u32 RGFW_OnClose(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win); + if (win == NULL) return true; + + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + + return true; +} + +/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */ +bool acceptsFirstResponder(void) { return true; } +bool performKeyEquivalent(id event) { RGFW_UNUSED(event); return true; } + +NSDragOperation draggingEntered(id self, SEL sel, id sender) { + RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + + return NSDragOperationCopy; +} +NSDragOperation draggingUpdated(id self, SEL sel, id sender) { + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return 0; + + if (!(win->_flags & RGFW_windowAllowDND)) { + return 0; } - /* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */ - bool acceptsFirstResponder(void) { return true; } - bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; } + win->event.type = RGFW_DNDInit; + win->src.dndPassed = 0; - NSDragOperation draggingEntered(id self, SEL sel, id sender) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - return NSDragOperationCopy; - } - NSDragOperation draggingUpdated(id self, SEL sel, id sender) { - RGFW_UNUSED(sel); - - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return 0; - - if (!(win->_winArgs & RGFW_ALLOW_DND)) { - return 0; - } - - win->event.type = RGFW_dnd_init; - win->src.dndPassed = 0; - - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - RGFW_dndInitCallback(win, win->event.point); - - return NSDragOperationCopy; - } - bool prepareForDragOperation(id self) { - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return true; - - if (!(win->_winArgs & RGFW_ALLOW_DND)) { - return false; - } + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + RGFW_dndInitCallback(win, win->event.point); + return NSDragOperationCopy; +} +bool prepareForDragOperation(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) return true; + + if (!(win->_flags & RGFW_windowAllowDND)) { + return false; } - void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } + return true; +} - /* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */ - bool performDragOperation(id self, SEL sel, id sender) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); +void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); +/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */ +bool performDragOperation(id self, SEL sel, id sender) { + RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); - if (win == NULL) - return false; + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); - // NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); + if (win == NULL) + return false; - ///////////////////////////// - id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); + // id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - // Get the types of data available on the pasteboard - id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); + ///////////////////////////// + id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - // Get the string type for file URLs - id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); + // Get the types of data available on the pasteboard + id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); - // Check if the pasteboard contains file URLs - if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) { - #ifdef RGFW_DEBUG - printf("No files found on the pasteboard.\n"); - #endif + // Get the string type for file URLs + id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); - return 0; - } + // Check if the pasteboard contains file URLs + if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) { + #ifdef RGFW_DEBUG + printf("No files found on the pasteboard.\n"); + #endif - id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); - int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); + return 0; + } - if (count == 0) - return 0; + id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); + int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); - for (int i = 0; i < count; i++) { - id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); - const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); - strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); - win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; - } - win->event.droppedFilesCount = count; + if (count == 0) + return 0; - win->event.type = RGFW_dnd; - win->src.dndPassed = 0; - - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + for (int i = 0; i < count; i++) { + id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); + const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); + RGFW_MEMCPY(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; + } + win->event.droppedFilesCount = count; + + win->event.type = RGFW_DND; + win->src.dndPassed = 0; + + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + + return false; +} + +#ifndef RGFW_NO_IOKIT +#include +#include + +IOHIDDeviceRef RGFW_osxControllers[4] = {NULL}; + +int findControllerIndex(IOHIDDeviceRef device) { + for (int i = 0; i < 4; i++) + if (RGFW_osxControllers[i] == device) + return i; + return -1; +} + +#define RGFW_gamepadEventQueueMAX 11 +RGFW_event RGFW_gamepadEventQueue[RGFW_gamepadEventQueueMAX]; +size_t RGFW_gamepadEventQueueCount = 0; + +void RGFW__osxInputValueChangedCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); + + if (RGFW_gamepadEventQueueCount >= RGFW_gamepadEventQueueMAX - 1) + return; + + IOHIDElementRef element = IOHIDValueGetElement(value); + + IOHIDDeviceRef device = IOHIDElementGetDevice(element); + size_t index = findControllerIndex(device); + + uint32_t usagePage = IOHIDElementGetUsagePage(element); + uint32_t usage = IOHIDElementGetUsage(element); + + CFIndex intValue = IOHIDValueGetIntegerValue(value); + + u8 RGFW_osx2RGFWSrc[2][RGFW_gamepadFinal] = {{ + 0, RGFW_gamepadSelect, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadStart, + RGFW_gamepadUp, RGFW_gamepadRight, RGFW_gamepadDown, RGFW_gamepadLeft, + RGFW_gamepadL2, RGFW_gamepadR2, RGFW_gamepadL1, RGFW_gamepadR1, + RGFW_gamepadY, RGFW_gamepadB, RGFW_gamepadA, RGFW_gamepadX, RGFW_gamepadHome}, + {0, RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadR3, RGFW_gamepadX, + RGFW_gamepadY, RGFW_gamepadRight, RGFW_gamepadL1, RGFW_gamepadR1, + RGFW_gamepadL2, RGFW_gamepadR2, RGFW_gamepadDown, RGFW_gamepadStart, + RGFW_gamepadUp, RGFW_gamepadL3, RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome} + }; + + u8* RGFW_osx2RGFW = RGFW_osx2RGFWSrc[0]; + if (RGFW_gamepads_type[index] == RGFW_gamepadMicrosoft) + RGFW_osx2RGFW = RGFW_osx2RGFWSrc[1]; - return false; + RGFW_event event; + + switch (usagePage) { + case kHIDPage_Button: { + u8 button = 0; + if (usage < sizeof(RGFW_osx2RGFW)) + button = RGFW_osx2RGFW[usage]; + + RGFW_gamepadButtonCallback(RGFW_root, index, button, intValue); + RGFW_gamepadPressed[index][button].prev = RGFW_gamepadPressed[index][button].current; + RGFW_gamepadPressed[index][button].current = intValue; + event.type = intValue ? RGFW_gamepadButtonPressed: RGFW_gamepadButtonReleased; + event.button = button; + event.gamepad = index; + + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = event; + RGFW_gamepadEventQueueCount++; + break; + } + case kHIDPage_GenericDesktop: { + CFIndex logicalMin = IOHIDElementGetLogicalMin(element); + CFIndex logicalMax = IOHIDElementGetLogicalMax(element); + + if (logicalMax <= logicalMin) return; + if (intValue < logicalMin) intValue = logicalMin; + if (intValue > logicalMax) intValue = logicalMax; + + i8 value = (i8)(-100.0 + ((intValue - logicalMin) * 200.0) / (logicalMax - logicalMin)); + + switch (usage) { + case kHIDUsage_GD_X: RGFW_gamepadAxes[index][0].x = value; event.whichAxis = 0; break; + case kHIDUsage_GD_Y: RGFW_gamepadAxes[index][0].y = value; event.whichAxis = 0; break; + case kHIDUsage_GD_Z: RGFW_gamepadAxes[index][1].x = value; event.whichAxis = 1; break; + case kHIDUsage_GD_Rz: RGFW_gamepadAxes[index][1].y = value; event.whichAxis = 1; break; + default: return; + } + + event.type = RGFW_gamepadAxisMove; + event.gamepad = index; + + event.axis[0] = RGFW_gamepadAxes[index][0]; + event.axis[1] = RGFW_gamepadAxes[index][1]; + + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = event; + RGFW_gamepadEventQueueCount++; + + RGFW_gamepadAxisCallback(RGFW_root, index, event.axis, 2, event.whichAxis); + } + } +} + +void RGFW__osxDeviceAddedCallback(void* context, IOReturn result, void *sender, IOHIDDeviceRef device) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); + CFTypeRef usageRef = (CFTypeRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)); + int usage = 0; + if (usageRef) + CFNumberGetValue((CFNumberRef)usageRef, kCFNumberIntType, (void*)&usage); + + if (usage != kHIDUsage_GD_Joystick && usage != kHIDUsage_GD_GamePad && usage != kHIDUsage_GD_MultiAxisController) { + return; } - void NSMoveToResourceDir(void) { - /* sourced from glfw */ - char resourcesPath[255]; + for (size_t i = 0; i < 4; i++) { + if (RGFW_osxControllers[i] != NULL) + continue; - CFBundleRef bundle = CFBundleGetMainBundle(); - if (!bundle) - return; + RGFW_osxControllers[i] = device; - CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); - CFStringRef last = CFURLCopyLastPathComponent(resourcesURL); + IOHIDDeviceRegisterInputValueCallback(device, RGFW__osxInputValueChangedCallback, NULL); - if ( - CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo || - CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0 - ) { - CFRelease(last); - CFRelease(resourcesURL); - return; - } + CFStringRef deviceName = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); + if (deviceName) + CFStringGetCString(deviceName, RGFW_gamepads_name[i], sizeof(RGFW_gamepads_name[i]), kCFStringEncodingUTF8); + RGFW_gamepads_type[i] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[i], "Microsoft") || strstr(RGFW_gamepads_name[i], "X-Box") || strstr(RGFW_gamepads_name[i], "Xbox")) + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[i], "PlayStation") || strstr(RGFW_gamepads_name[i], "PS3") || strstr(RGFW_gamepads_name[i], "PS4") || strstr(RGFW_gamepads_name[i], "PS5")) + RGFW_gamepads_type[i] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[i], "Nintendo")) + RGFW_gamepads_type[i] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[i], "Logitech")) + RGFW_gamepads_type[i] = RGFW_gamepadLogitech; + + RGFW_gamepads[i] = i; + RGFW_gamepadCount++; + + RGFW_event ev; + ev.type = RGFW_gamepadConnected; + ev.gamepad = i; + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = ev; + RGFW_gamepadEventQueueCount++; + RGFW_gamepadCallback(RGFW_root, i, 1); + break; + } +} + +void RGFW__osxDeviceRemovedCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); RGFW_UNUSED(device); + CFNumberRef usageRef = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)); + int usage = 0; + if (usageRef) + CFNumberGetValue(usageRef, kCFNumberIntType, &usage); + + if (usage != kHIDUsage_GD_Joystick && usage != kHIDUsage_GD_GamePad && usage != kHIDUsage_GD_MultiAxisController) { + return; + } + + i32 index = findControllerIndex(device); + if (index != -1) + RGFW_osxControllers[index] = NULL; + + RGFW_event ev; + ev.type = RGFW_gamepadDisconnected; + ev.gamepad = index; + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = ev; + RGFW_gamepadEventQueueCount++; + RGFW_gamepadCallback(RGFW_root, index, 0); + + RGFW_gamepadCount--; +} + +RGFWDEF void RGFW_osxInitIOKit(void); +void RGFW_osxInitIOKit(void) { + IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (!hidManager) { + fprintf(stderr, "Failed to create IOHIDManager.\n"); + return; + } + + CFMutableDictionaryRef matchingDictionary = CFDictionaryCreateMutable( + kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks + ); + if (!matchingDictionary) { + fprintf(stderr, "Failed to create matching dictionary.\n"); + CFRelease(hidManager); + return; + } + + CFDictionarySetValue( + matchingDictionary, + CFSTR(kIOHIDDeviceUsagePageKey), + CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, (int[]){kHIDPage_GenericDesktop}) + ); + + IOHIDManagerSetDeviceMatching(hidManager, matchingDictionary); + + IOHIDManagerRegisterDeviceMatchingCallback(hidManager, RGFW__osxDeviceAddedCallback, NULL); + IOHIDManagerRegisterDeviceRemovalCallback(hidManager, RGFW__osxDeviceRemovedCallback, NULL); + + IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + + IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); + + // Execute the run loop once in order to register any initially-attached joysticks + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); +} +#endif + +void NSMoveToResourceDir(void) { + char resourcesPath[255]; + + CFBundleRef bundle = CFBundleGetMainBundle(); + if (!bundle) + return; + + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); + CFStringRef last = CFURLCopyLastPathComponent(resourcesURL); + + if ( + CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo || + CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0 + ) { CFRelease(last); CFRelease(resourcesURL); - - chdir(resourcesPath); + return; } + CFRelease(last); + CFRelease(resourcesURL); - NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) { - RGFW_UNUSED(sel); + chdir(resourcesPath); +} - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return frameSize; - - win->r.w = frameSize.width; - win->r.h = frameSize.height; - win->event.type = RGFW_windowResized; - RGFW_windowResizeCallback(win, win->r); + +NSSize RGFW__osxWindowResize(id self, SEL sel, NSSize frameSize) { + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) return frameSize; - } - void RGFW__osxWindowMove(void* self, SEL sel) { - RGFW_UNUSED(sel); + win->r.w = frameSize.width; + win->r.h = frameSize.height; + win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); + return frameSize; +} - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return; - - NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame")); - win->r.x = (i32) frame.origin.x; - win->r.y = (i32) frame.origin.y; +void RGFW__osxWindowMove(id self, SEL sel) { + RGFW_UNUSED(sel); - win->event.type = RGFW_windowMoved; - RGFW_windowMoveCallback(win, win->r); - } + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return; - void RGFW__osxUpdateLayer(void* self, SEL sel) { - RGFW_UNUSED(sel); + NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame")); + win->r.x = (i32) frame.origin.x; + win->r.y = (i32) frame.origin.y; - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return; - - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - } + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); +} - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) - RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); +void RGFW__osxUpdateLayer(id self, SEL sel) { + RGFW_UNUSED(sel); - #ifdef RGFW_OSMESA - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - #else + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return; + + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); +} + +RGFWDEF void RGFW_init_buffer(RGFW_window* win); +void RGFW_init_buffer(RGFW_window* win) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; + #ifdef RGFW_OSMESA + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ + #endif +} + +void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) { + objc_msgSend_void_id((id)win->src.view, sel_registerName("setLayer"), (id)layer); +} + +void* RGFW_cocoaGetLayer(void) { + return objc_msgSend_class((id)objc_getClass("CAMetalLayer"), (SEL)sel_registerName("layer")); +} + + +NSPasteboardType const NSPasteboardTypeURL = "public.url"; +NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + static u8 RGFW_loaded = 0; + + /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea??? + Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance). + */ + si_func_to_SEL_with_name("NSObject", "windowShouldClose", (void*)RGFW_OnClose); + + /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */ + si_func_to_SEL("NSWindow", acceptsFirstResponder); + si_func_to_SEL("NSWindow", performKeyEquivalent); + + // RR Create an autorelease pool + id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + pool = objc_msgSend_id(pool, sel_registerName("init")); + + if (NSApp == NULL) { + NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); + + ((void (*)(id, SEL, NSUInteger))objc_msgSend) + (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular); + + #ifndef RGFW_NO_IOKIT + RGFW_osxInitIOKit(); #endif } + RGFW_window_basic_init(win, rect, flags); - void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) { - objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer); + RGFW_window_setMouseDefault(win); + + NSRect windowRect; + windowRect.origin.x = win->r.x; + windowRect.origin.y = win->r.y; + windowRect.size.width = win->r.w; + windowRect.size.height = win->r.h; + + NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled; + + if (!(flags & RGFW_windowNoResize)) + macArgs |= NSWindowStyleMaskResizable; + if (!(flags & RGFW_windowNoBorder)) + macArgs |= NSWindowStyleMaskTitled; + else + macArgs = NSWindowStyleMaskBorderless; + { + void* nsclass = objc_getClass("NSWindow"); + SEL func = sel_registerName("initWithContentRect:styleMask:backing:defer:"); + + win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend) + (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false); } - void* RGFW_cocoaGetLayer(void) { - return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer")); - } + id str = NSString_stringWithUTF8String(name); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str); - - NSPasteboardType const NSPasteboardTypeURL = "public.url"; - NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - static u8 RGFW_loaded = 0; - - /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea??? - Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance). - */ - si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose); - - /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */ - si_func_to_SEL("NSWindow", acceptsFirstResponder); - si_func_to_SEL("NSWindow", performKeyEquivalent); - - // RR Create an autorelease pool - id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - pool = objc_msgSend_id(pool, sel_registerName("init")); - - if (NSApp == NULL) { - NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); - - ((void (*)(id, SEL, NSUInteger))objc_msgSend) - (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular); - } - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - RGFW_window_setMouseDefault(win); - - NSRect windowRect; - windowRect.origin.x = win->r.x; - windowRect.origin.y = win->r.y; - windowRect.size.width = win->r.w; - windowRect.size.height = win->r.h; - - NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled; - - if (!(args & RGFW_NO_RESIZE)) - macArgs |= NSWindowStyleMaskResizable; - if (!(args & RGFW_NO_BORDER)) - macArgs |= NSWindowStyleMaskTitled; - else - macArgs = NSWindowStyleMaskBorderless; - { - void* nsclass = objc_getClass("NSWindow"); - void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:"); - - win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend) - (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false); - } - - NSString* str = NSString_stringWithUTF8String(name); - objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); - -#ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) RGFW_createOpenGLContext(win); -#endif + #endif -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); - void* format = NSOpenGLPixelFormat_initWithAttributes(attrs); + #ifdef RGFW_OPENGL + + if ((flags & RGFW_windowNoInitAPI) == 0) { + void* attrs = RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); + void* format = NSOpenGLPixelFormat_initWithAttributes((uint32_t*)attrs); if (format == NULL) { + #ifdef RGFW_DEBUG printf("Failed to load pixel format for OpenGL\n"); + #endif void* attrs = RGFW_initFormatAttribs(1); - format = NSOpenGLPixelFormat_initWithAttributes(attrs); + format = NSOpenGLPixelFormat_initWithAttributes((uint32_t*)attrs); + + #ifdef RGFW_DEBUG if (format == NULL) printf("and loading software rendering OpenGL failed\n"); else printf("Switching to software rendering\n"); + #endif } - - /* the pixel format can be passed directly to opengl context creation to create a context + + /* the pixel format can be passed directly to opengl context creation to create a context this is because the format also includes information about the opengl version (which may be a bad thing) */ - win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format); + win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, (uint32_t*)format); objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL")); win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); } else -#endif + #endif { NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}}; win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend) @@ -7489,947 +7942,992 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ contentRect); } - void* contentView = NSWindow_contentView(win->src.window); - objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); + void* contentView = NSWindow_contentView((id)win->src.window); + objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); - objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view); -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); -#endif - if (args & RGFW_TRANSPARENT_WINDOW) { -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - i32 opacity = 0; - #define NSOpenGLCPSurfaceOpacity 236 - NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity); - } -#endif + #endif - objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false); - - objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"), - NSColor_colorWithSRGB(0, 0, 0, 0)); - } - - win->src.display = CGMainDisplayID(); - CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink); - CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win); - CVDisplayLinkStart(win->src.displayLink); - - RGFW_init_buffer(win); - - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); + if (flags & RGFW_windowTransparent) { + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { + i32 opacity = 0; + #define NSOpenGLCPSurfaceOpacity 236 + NSOpenGLContext_setValues((id)win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity); + } #endif - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } + objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false); - if (args & RGFW_HIDE_MOUSE) - RGFW_window_showMouse(win, 0); - - if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR) - NSMoveToResourceDir(); - - Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0); - - class_addIvar( - delegateClass, "RGFW_window", - sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))), - "L" - ); - - class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}"); - class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, ""); - class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, ""); - class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, ""); - class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@"); - class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@"); - class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); - class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); - class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@"); - class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@"); - - id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init")); - - object_setInstanceVariable(delegate, "RGFW_window", win); - - objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; - - NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString}; - NSregisterForDraggedTypes(win->src.window, types, 3); - } - - // Show the window - objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true); - ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - - if (!RGFW_loaded) { - objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow")); - - RGFW_loaded = 1; - } - - objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - - objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); - - if (RGFW_root == NULL) - RGFW_root = win; - - NSRetain(win->src.window); - NSRetain(NSApp); - - #ifdef RGFW_DEBUG - printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); - #endif - - return win; + objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"), + NSColor_colorWithSRGB(0, 0, 0, 0)); } - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - NSBackingStoreType storeType = NSWindowStyleMaskBorderless; - if (!border) { - storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; - } - if (!(win->_winArgs & RGFW_NO_RESIZE)) { - storeType |= NSWindowStyleMaskResizable; - } - - ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType); + RGFW_init_buffer(win); - objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif + + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); } - RGFW_area RGFW_getScreenSize(void) { - static CGDirectDisplayID display = 0; + if (flags & RGFW_windowHideMouse) + RGFW_window_showMouse(win, 0); - if (display == 0) - display = CGMainDisplayID(); + if (flags & RGFW_windowCocoaCHDirToRes) + NSMoveToResourceDir(); - return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); + Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0); + + class_addIvar( + delegateClass, "RGFW_window", + sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))), + "L" + ); + + class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}"); + class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, ""); + class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, ""); + class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, ""); + class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@"); + class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@"); + class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); + class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); + class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@"); + class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@"); + + id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init")); + + object_setInstanceVariable(delegate, "RGFW_window", win); + + objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), delegate); + + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; + + NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString}; + NSregisterForDraggedTypes((id)win->src.window, types, 3); } - RGFW_point RGFW_getGlobalMousePoint(void) { - assert(RGFW_root != NULL); + // Show the window + objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true); + ((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), (SEL)NULL); + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - CGEventRef e = CGEventCreate(NULL); - CGPoint point = CGEventGetLocation(e); - CFRelease(e); + if (!RGFW_loaded) { + objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow")); - return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */ + RGFW_loaded = 1; } - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); + objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); + + NSRetain(win->src.window); + NSRetain(NSApp); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + return win; +} + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + NSBackingStoreType storeType = NSWindowStyleMaskBorderless; + if (!border) { + storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; + } + if (!(win->_flags & RGFW_windowNoResize)) { + storeType |= NSWindowStyleMaskResizable; } - u32 RGFW_keysPressed[10]; /*10 keys at a time*/ - typedef NS_ENUM(u32, NSEventType) { /* various types of events */ - NSEventTypeLeftMouseDown = 1, - NSEventTypeLeftMouseUp = 2, - NSEventTypeRightMouseDown = 3, - NSEventTypeRightMouseUp = 4, - NSEventTypeMouseMoved = 5, - NSEventTypeLeftMouseDragged = 6, - NSEventTypeRightMouseDragged = 7, - NSEventTypeMouseEntered = 8, - NSEventTypeMouseExited = 9, - NSEventTypeKeyDown = 10, - NSEventTypeKeyUp = 11, - NSEventTypeFlagsChanged = 12, - NSEventTypeAppKitDefined = 13, - NSEventTypeSystemDefined = 14, - NSEventTypeApplicationDefined = 15, - NSEventTypePeriodic = 16, - NSEventTypeCursorUpdate = 17, - NSEventTypeScrollWheel = 22, - NSEventTypeTabletPoint = 23, - NSEventTypeTabletProximity = 24, - NSEventTypeOtherMouseDown = 25, - NSEventTypeOtherMouseUp = 26, - NSEventTypeOtherMouseDragged = 27, - /* The following event types are available on some hardware on 10.5.2 and later */ - NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29, - NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30, - NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31, - NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18, - NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19, - NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20, + ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), storeType); - NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32, - NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33, + objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); +} - NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34, - NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37, +RGFW_area RGFW_getScreenSize(void) { + static CGDirectDisplayID display = 0; - NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38, - }; + if (display == 0) + display = CGMainDisplayID(); - typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */ - NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown, - NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp, - NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown, - NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp, - NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved, - NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged, - NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged, - NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered, - NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited, - NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown, - NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp, - NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged, - NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined, - NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined, - NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined, - NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic, - NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate, - NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel, - NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint, - NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity, - NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown, - NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp, - NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged, - /* The following event masks are available on some hardware on 10.5.2 and later */ - NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture, - NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify, - NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe, - NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate, - NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture, - NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture, + return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); +} - /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit. - */ - NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify, - NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure, - NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch, +RGFW_point RGFW_getGlobalMousePoint(void) { + RGFW_ASSERT(RGFW_root != NULL); - NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode, + CGEventRef e = CGEventCreate(NULL); + CGPoint point = CGEventGetLocation(e); + CFRelease(e); - NSEventMaskAny = ULONG_MAX, + return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */ +} - }; +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)((id)win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); - typedef enum NSEventModifierFlags { - NSEventModifierFlagCapsLock = 1 << 16, - NSEventModifierFlagShift = 1 << 17, - NSEventModifierFlagControl = 1 << 18, - NSEventModifierFlagOption = 1 << 19, - NSEventModifierFlagCommand = 1 << 20, - NSEventModifierFlagNumericPad = 1 << 21 - } NSEventModifierFlags; + return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); +} - void RGFW_stopCheckEvents(void) { - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); +u32 RGFW_keysPressed[10]; /*10 keys at a time*/ +typedef RGFW_ENUM(u32, NSEventType) { /* various types of events */ + NSEventTypeLeftMouseDown = 1, + NSEventTypeLeftMouseUp = 2, + NSEventTypeRightMouseDown = 3, + NSEventTypeRightMouseUp = 4, + NSEventTypeMouseMoved = 5, + NSEventTypeLeftMouseDragged = 6, + NSEventTypeRightMouseDragged = 7, + NSEventTypeMouseEntered = 8, + NSEventTypeMouseExited = 9, + NSEventTypeKeyDown = 10, + NSEventTypeKeyUp = 11, + NSEventTypeFlagsChanged = 12, + NSEventTypeAppKitDefined = 13, + NSEventTypeSystemDefined = 14, + NSEventTypeApplicationDefined = 15, + NSEventTypePeriodic = 16, + NSEventTypeCursorUpdate = 17, + NSEventTypeScrollWheel = 22, + NSEventTypeTabletPoint = 23, + NSEventTypeTabletProximity = 24, + NSEventTypeOtherMouseDown = 25, + NSEventTypeOtherMouseUp = 26, + NSEventTypeOtherMouseDragged = 27, + /* The following event types are available on some hardware on 10.5.2 and later */ + NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29, + NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30, + NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31, + NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18, + NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19, + NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20, - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend) - (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), - NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0); + NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32, + NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33, + NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34, + NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37, + + NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38, +}; + +typedef RGFW_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */ + NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown, + NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp, + NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown, + NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp, + NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved, + NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged, + NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged, + NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered, + NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited, + NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown, + NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp, + NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged, + NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined, + NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined, + NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined, + NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic, + NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate, + NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel, + NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint, + NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity, + NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown, + NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp, + NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged, + /* The following event masks are available on some hardware on 10.5.2 and later */ + NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture, + NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify, + NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe, + NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate, + NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture, + NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture, + + /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit. + */ + NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify, + NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure, + NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch, + + NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode, + + NSEventMaskAny = ULONG_MAX, + +}; + +typedef enum NSEventModifierFlags { + NSEventModifierFlagCapsLock = 1 << 16, + NSEventModifierFlagShift = 1 << 17, + NSEventModifierFlagControl = 1 << 18, + NSEventModifierFlagOption = 1 << 19, + NSEventModifierFlagCommand = 1 << 20, + NSEventModifierFlagNumericPad = 1 << 21 +} NSEventModifierFlags; + +void RGFW_stopCheckEvents(void) { + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + id e = (id) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend) + (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), + NSEventTypeApplicationDefined, (NSPoint){0, 0}, (NSEventModifierFlags)0, NULL, (NSInteger)0, NULL, 0, 0, 0); + + ((void (*)(id, SEL, id, bool))objc_msgSend) + (NSApp, sel_registerName("postEvent:atStart:"), e, 1); + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend) + (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); + + id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend) + (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), + ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + + + if (e) { ((void (*)(id, SEL, id, bool))objc_msgSend) (NSApp, sel_registerName("postEvent:atStart:"), e, 1); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); } - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - RGFW_UNUSED(win); - - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); +} - void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend) - (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) - (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), - ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + if (win->event.type == RGFW_quit) + return NULL; - - if (e) { - ((void (*)(id, SEL, id, bool))objc_msgSend) - (NSApp, sel_registerName("postEvent:atStart:"), e, 1); - } - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - } - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - - if (win->event.type == RGFW_quit) - return NULL; - - if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) { - win->src.dndPassed = 1; - return &win->event; - } - - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); - - static void* eventFunc = NULL; - if (eventFunc == NULL) - eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); - - if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.key != 120) { - win->event.key = 120; - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return &win->event; - } - - void* date = NULL; - - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) - (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); - - if (e == NULL) { - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return NULL; - } - - if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) { - ((void (*)(id, SEL, id, bool))objc_msgSend) - (NSApp, sel_registerName("postEvent:atStart:"), e, 0); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return NULL; - } - - if (win->event.droppedFilesCount) { - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - win->event.type = 0; - - switch (objc_msgSend_uint(e, sel_registerName("type"))) { - case NSEventTypeMouseEntered: { - win->event.type = RGFW_mouseEnter; - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - - win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y)); - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - break; - } - - case NSEventTypeMouseExited: - win->event.type = RGFW_mouseLeave; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - - case NSEventTypeKeyDown: { - u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - - u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); - - win->event.keyChar = (u8)mappedKey; - - win->event.key = RGFW_apiKeyToRGFW(key); - RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; - - win->event.type = RGFW_keyPressed; - char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); - strncpy(win->event.keyName, str, 16); - win->event.repeat = RGFW_isPressed(win, win->event.key); - RGFW_keyboard[win->event.key].current = 1; - - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, 1); - break; - } - - case NSEventTypeKeyUp: { - u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - - u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); - win->event.keyChar = (u8)mappedKey; - - win->event.key = RGFW_apiKeyToRGFW(key); - - RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; - - win->event.type = RGFW_keyReleased; - char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); - strncpy(win->event.keyName, str, 16); - - RGFW_keyboard[win->event.key].current = 0; - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, 0); - break; - } - - case NSEventTypeFlagsChanged: { - u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); - RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255)); - - u8 i; - for (i = 0; i < 9; i++) - RGFW_keyboard[i + RGFW_CapsLock].prev = 0; - - for (i = 0; i < 5; i++) { - u32 shift = (1 << (i + 16)); - u32 key = i + RGFW_CapsLock; - - if ((flags & shift) && !RGFW_wasPressed(win, key)) { - RGFW_keyboard[key].current = 1; - - if (key != RGFW_CapsLock) - RGFW_keyboard[key+ 4].current = 1; - - win->event.type = RGFW_keyPressed; - win->event.key = key; - break; - } - - if (!(flags & shift) && RGFW_wasPressed(win, key)) { - RGFW_keyboard[key].current = 0; - - if (key != RGFW_CapsLock) - RGFW_keyboard[key + 4].current = 0; - - win->event.type = RGFW_keyReleased; - win->event.key = key; - break; - } - } - - RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed); - - break; - } - case NSEventTypeLeftMouseDragged: - case NSEventTypeOtherMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeMouseMoved: - win->event.type = RGFW_mousePosChanged; - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); - p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - - win->event.point = RGFW_POINT((i32)p.x, (i32)p.y); - } - - RGFW_mousePosCallback(win, win->event.point); - break; - - case NSEventTypeLeftMouseDown: - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeOtherMouseDown: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeRightMouseDown: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeLeftMouseUp: - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeOtherMouseUp: - win->event.button = RGFW_mouseMiddle; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeRightMouseUp: - win->event.button = RGFW_mouseRight; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeScrollWheel: { - double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - - if (deltaY > 0) { - win->event.button = RGFW_mouseScrollUp; - } - else if (deltaY < 0) { - win->event.button = RGFW_mouseScrollDown; - } - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - - win->event.scroll = deltaY; - - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - } - - default: return RGFW_window_checkEvent(win); - } - - objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + if ((win->event.type == RGFW_DND || win->event.type == RGFW_DNDInit) && win->src.dndPassed == 0) { + win->src.dndPassed = 1; ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return &win->event; } + #ifndef RGFW_NO_IOKIT + if (RGFW_gamepadEventQueueCount && win == RGFW_root) { + static u8 index = 0; - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); + /* check queued events */ + RGFW_gamepadEventQueueCount--; - win->r.x = v.x; - win->r.y = v.y; - ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); - } + RGFW_event ev = RGFW_gamepadEventQueue[index]; + win->event.type = ev.type; + win->event.gamepad = ev.gamepad; + win->event.button = ev.button; + win->event.whichAxis = ev.whichAxis; + for (size_t i = 0; i < 4; i++) + win->event.axis[i] = ev.axis[i]; - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); + if (RGFW_gamepadEventQueueCount) index++; + else index = 0; - win->r.w = a.w; - win->r.h = a.h; - ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); - } - - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); - - objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL); - } - - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); - - objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - NSString* str = NSString_stringWithUTF8String(name); - objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); - } - - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return &win->event; } #endif - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - if (a.w == 0 && a.h == 0) - return; + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); - ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h}); + static SEL eventFunc = (SEL)NULL; + if (eventFunc == NULL) + eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); + + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.key != 120) { + win->event.key = 120; + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return &win->event; } - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - if (a.w == 0 && a.h == 0) - return; + void* date = NULL; - ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); + id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend) + (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + + if (e == NULL) { + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return NULL; } - void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { - assert(win != NULL); + if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) { + ((void (*)(id, SEL, id, bool))objc_msgSend) + (NSApp, sel_registerName("postEvent:atStart:"), e, 0); - /* code by EimaMei */ - // Make a bitmap representation, then copy the loaded image into it. - void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels); - memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); - - // Add ze representation. - void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); - NSImage_addRepresentation(dock_image, (void*) representation); - - // Finally, set the dock image to it. - objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image); - // Free the garbage. - release(dock_image); - release(representation); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return NULL; } - NSCursor* NSCursor_arrowStr(char* str) { - void* nclass = objc_getClass("NSCursor"); - void* func = sel_registerName(str); - return (NSCursor*) objc_msgSend_id(nclass, func); + if (win->event.droppedFilesCount) { + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) + win->event.droppedFiles[i][0] = '\0'; } - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); + win->event.droppedFilesCount = 0; + win->event.type = 0; - if (image == NULL) { - objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set")); - return; + switch (objc_msgSend_uint(e, sel_registerName("type"))) { + case NSEventTypeMouseEntered: { + win->event.type = RGFW_mouseEnter; + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); + + win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y)); + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; } - /* NOTE(EimaMei): Code by yours truly. */ - // Make a bitmap representation, then copy the loaded image into it. - void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels); - memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels); + case NSEventTypeMouseExited: + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; - // Add ze representation. - void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); - NSImage_addRepresentation(cursor_image, representation); + case NSEventTypeKeyDown: { + u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - // Finally, set the cursor image. - void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); + u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); + if (((u8)mappedKey) == 239) + mappedKey = 0; - objc_msgSend_void(cursor, sel_registerName("set")); + win->event.keyChar = (u8)mappedKey; - // Free the garbage. - release(cursor_image); - release(representation); - } + win->event.key = RGFW_apiKeyToRGFW(key); + RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } + win->event.type = RGFW_keyPressed; + win->event.repeat = RGFW_isPressed(win, win->event.key); + RGFW_keyboard[win->event.key].current = 1; - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - RGFW_UNUSED(win); - - if (show) { - CGDisplayShowCursor(kCGDirectMainDisplay); + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 1); + break; } - else { - CGDisplayHideCursor(kCGDirectMainDisplay); + + case NSEventTypeKeyUp: { + u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); + + u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); + if (((u8)mappedKey) == 239) + mappedKey = 0; + + win->event.keyChar = (u8)mappedKey; + + win->event.key = RGFW_apiKeyToRGFW(key); + + RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; + + win->event.type = RGFW_keyReleased; + + RGFW_keyboard[win->event.key].current = 0; + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 0); + break; } + + case NSEventTypeFlagsChanged: { + u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); + RGFW_updateKeyModsPro(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255), + ((flags & NSEventModifierFlagControl) % 255), ((flags & NSEventModifierFlagOption) % 255), + ((flags & NSEventModifierFlagShift) % 255), ((flags & NSEventModifierFlagCommand) % 255)); + u8 i; + for (i = 0; i < 9; i++) + RGFW_keyboard[i + RGFW_capsLock].prev = 0; + + for (i = 0; i < 5; i++) { + u32 shift = (1 << (i + 16)); + u32 key = i + RGFW_capsLock; + + if ((flags & shift) && !RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 1; + + if (key != RGFW_capsLock) + RGFW_keyboard[key+ 4].current = 1; + + win->event.type = RGFW_keyPressed; + win->event.key = key; + break; + } + + if (!(flags & shift) && RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 0; + + if (key != RGFW_capsLock) + RGFW_keyboard[key + 4].current = 0; + + win->event.type = RGFW_keyReleased; + win->event.key = key; + break; + } + } + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, win->event.type == RGFW_keyPressed); + + break; + } + case NSEventTypeLeftMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeMouseMoved: { + win->event.type = RGFW_mousePosChanged; + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + + if ((win->_flags & RGFW_HOLD_MOUSE)) { + p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); + p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); + + win->event.point = RGFW_POINT((i32)p.x, (i32)p.y); + } + + RGFW_mousePosCallback(win, win->event.point); + break; + } + case NSEventTypeLeftMouseDown: + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeOtherMouseDown: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeRightMouseDown: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeLeftMouseUp: + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeOtherMouseUp: + win->event.button = RGFW_mouseMiddle; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeRightMouseUp: + win->event.button = RGFW_mouseRight; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeScrollWheel: { + double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); + + if (deltaY > 0) { + win->event.button = RGFW_mouseScrollUp; + } + else if (deltaY < 0) { + win->event.button = RGFW_mouseScrollDown; + } + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + + win->event.scroll = deltaY; + + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + } + + default: + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return RGFW_window_checkEvent(win); } - void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) { - if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*)))) - return; - - char* mouseStr = RGFW_mouseIconSrc[stdMouses]; - void* mouse = NSCursor_arrowStr(mouseStr); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); - if (mouse == NULL) - return; + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + return &win->event; +} - RGFW_UNUSED(win); + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + + win->r.x = v.x; + win->r.y = v.y; + ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) + ((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); +} + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + win->r.w = a.w; + win->r.h = a.h; + ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) + ((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); +} + +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL); +} + +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL); +} + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win != NULL); + + id str = NSString_stringWithUTF8String(name); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str); +} + +#ifndef RGFW_NO_PASSTHROUGH +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough); +} +#endif + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + + ((void (*)(id, SEL, NSSize))objc_msgSend) + ((id)win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h}); +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + + ((void (*)(id, SEL, NSSize))objc_msgSend) + ((id)win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); +} + +b32 RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { + RGFW_ASSERT(win != NULL); + + /* code by EimaMei */ + // Make a bitmap representation, then copy the loaded image into it. + id representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels); + RGFW_MEMCPY(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); + + // Add ze representation. + id dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); + NSImage_addRepresentation(dock_image, representation); + + // Finally, set the dock image to it. + objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image); + // Free the garbage. + NSRelease(dock_image); + NSRelease(representation); + + return 1; +} + +id NSCursor_arrowStr(const char* str) { + void* nclass = objc_getClass("NSCursor"); + SEL func = sel_registerName(str); + return (id) objc_msgSend_id(nclass, func); +} + +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + if (icon == NULL) { + objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set")); + return NULL; + } + + /* NOTE(EimaMei): Code by yours truly. */ + // Make a bitmap representation, then copy the loaded image into it. + id representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels); + RGFW_MEMCPY(NSBitmapImageRep_bitmapData(representation), icon, a.w * a.h * channels); + + // Add ze representation. + id cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); + NSImage_addRepresentation(cursor_image, representation); + + // Finally, set the cursor image. + id cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); + + // Free the garbage. + NSRelease(cursor_image); + NSRelease(representation); + + return (void*)cursor; +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { + RGFW_ASSERT(win); RGFW_ASSERT(mouse); + objc_msgSend_void((id)mouse, sel_registerName("set")); +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { + RGFW_ASSERT(mouse); + NSRelease((id)mouse); +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +void RGFW_window_showMouse(RGFW_window* win, i8 show) { + RGFW_UNUSED(win); + + if (show) { CGDisplayShowCursor(kCGDirectMainDisplay); - objc_msgSend_void(mouse, sel_registerName("set")); } - - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); - CGAssociateMouseAndMouseCursorPosition(1); + else { + CGDisplayHideCursor(kCGDirectMainDisplay); } +} - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - RGFW_UNUSED(win) +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) { + if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*)))) + return 0; - CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); - CGAssociateMouseAndMouseCursorPosition(0); - } + const char* mouseStr = RGFW_mouseIconSrc[stdMouses]; + id mouse = NSCursor_arrowStr(mouseStr); - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { - RGFW_UNUSED(win); + if (mouse == NULL) + return 0; - win->_lastMousePoint = RGFW_POINT(v.x - win->r.x, v.y - win->r.y); - CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); - } + RGFW_UNUSED(win); + CGDisplayShowCursor(kCGDirectMainDisplay); + objc_msgSend_void(mouse, sel_registerName("set")); + + return 1; +} + +void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); + CGAssociateMouseAndMouseCursorPosition(1); +} + +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + RGFW_UNUSED(win); + + CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); + CGAssociateMouseAndMouseCursorPosition(0); +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { + RGFW_UNUSED(win); + + win->_lastMousePoint = RGFW_POINT(v.x - win->r.x, v.y - win->r.y); + CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); +} - void RGFW_window_hide(RGFW_window* win) { - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false); - } +void RGFW_window_hide(RGFW_window* win) { + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false); +} - void RGFW_window_show(RGFW_window* win) { - ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - } +void RGFW_window_show(RGFW_window* win) { + ((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); +} - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask")); - return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; - } + NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask")); + return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; +} - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible")); - return visible == NO && !RGFW_window_isMinimized(win); - } + bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible")); + return visible == NO && !RGFW_window_isMinimized(win); +} - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES; - } + return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES; +} - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed")); - } + return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed")); +} - RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) { - RGFW_monitor monitor; +id RGFW_getNSScreenForDisplayID(CGDirectDisplayID display) { + Class NSScreenClass = objc_getClass("NSScreen"); - CGRect bounds = CGDisplayBounds(display); - monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); + id screens = objc_msgSend_id(NSScreenClass, sel_registerName("screens")); - CGSize screenSizeMM = CGDisplayScreenSize(display); - monitor.physW = (float)screenSizeMM.width / 25.4f; - monitor.physH = (float)screenSizeMM.height / 25.4f; + NSUInteger count = (NSUInteger)objc_msgSend_uint(screens, sel_registerName("count")); - float dpi_width = round((double)monitor.rect.w/(double)monitor.physW); - float dpi_height = round((double)monitor.rect.h/(double)monitor.physH); + for (NSUInteger i = 0; i < count; i++) { + id screen = ((id (*)(id, SEL, int))objc_msgSend) (screens, sel_registerName("objectAtIndex:"), (int)i); + id description = objc_msgSend_id(screen, sel_registerName("deviceDescription")); + id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber"); + id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey); - monitor.scaleX = (float) (dpi_width) / (float) 96; - monitor.scaleY = (float) (dpi_height) / (float) 96; - - if (isinf(monitor.scaleX) || (monitor.scaleX > 1 && monitor.scaleX < 1.1)) - monitor.scaleX = 1; - - if (isinf(monitor.scaleY) || (monitor.scaleY > 1 && monitor.scaleY < 1.1)) - monitor.scaleY = 1; - - #ifdef RGFW_DEBUG - printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY); - #endif - - return monitor; - } - - - RGFW_monitor RGFW_monitors[7]; - - RGFW_monitor* RGFW_getMonitors(void) { - static CGDirectDisplayID displays[7]; - u32 count; - - if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess) - return NULL; - - for (u32 i = 0; i < count; i++) - RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - CGDirectDisplayID primary = CGMainDisplayID(); - return RGFW_NSCreateMonitor(primary); - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - return RGFW_NSCreateMonitor(win->src.display); - } - - char* RGFW_readClipboard(size_t* size) { - char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString); - - size_t clip_len = 1; - - if (clip != NULL) { - clip_len = strlen(clip) + 1; + if ((CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue")) == display) { + return screen; } + } - char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len); - - if (clip != NULL) { - strncpy(str, clip, clip_len); - } + return NULL; +} + +RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display, id screen) { + RGFW_monitor monitor; + + const char name[] = "MacOS\0"; + RGFW_MEMCPY(monitor.name, name, 6); + + CGRect bounds = CGDisplayBounds(display); + monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); + + CGSize screenSizeMM = CGDisplayScreenSize(display); + monitor.physW = (float)screenSizeMM.width / 25.4f; + monitor.physH = (float)screenSizeMM.height / 25.4f; + + float ppi_width = (monitor.rect.w/monitor.physW); + float ppi_height = (monitor.rect.h/monitor.physH); + + monitor.pixelRatio = ((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret) (screen, sel_registerName("backingScaleFactor")); + float dpi = 96.0f * monitor.pixelRatio; + + monitor.scaleX = ((i32)(((float) (ppi_width) / dpi) * 10.0f)) / 10.0f; + monitor.scaleY = ((i32)(((float) (ppi_height) / dpi) * 10.0f)) / 10.0f; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + + return monitor; +} + + +RGFW_monitor RGFW_monitors[7]; + +RGFW_monitor* RGFW_getMonitors(void) { + static CGDirectDisplayID displays[7]; + u32 count; + + if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess) + return NULL; + + for (u32 i = 0; i < count; i++) + RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i], RGFW_getNSScreenForDisplayID(displays[i])); + + return RGFW_monitors; +} + +RGFW_monitor RGFW_getPrimaryMonitor(void) { + CGDirectDisplayID primary = CGMainDisplayID(); + return RGFW_NSCreateMonitor(primary, RGFW_getNSScreenForDisplayID(primary)); +} + +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + id screen = objc_msgSend_id(win->src.window, sel_registerName("screen")); + id description = objc_msgSend_id(screen, sel_registerName("deviceDescription")); + id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber"); + id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey); + + CGDirectDisplayID display = (CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue")); + + return RGFW_NSCreateMonitor(display, screen); +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + size_t clip_len; + char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString, &clip_len); + if (clip == NULL) return -1; + + if (str != NULL) { + if (strCapacity < clip_len) + return 0; + + RGFW_MEMCPY(str, clip, clip_len); str[clip_len] = '\0'; - - if (size != NULL) - *size = clip_len; - return str; } - void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(textLen); + return (RGFW_ssize_t)clip_len; +} - NSPasteboardType array[] = { NSPasteboardTypeString, NULL }; - NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL); +void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_UNUSED(textLen); - NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString); - } + NSPasteboardType array[] = { NSPasteboardTypeString, NULL }; + NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL); - u16 RGFW_registerGamepad(RGFW_window* win, i32 gpNumber) { - RGFW_UNUSED(gpNumber); - - assert(win != NULL); - - return RGFW_registerGamepadF(win, (char*) ""); - } - - u16 RGFW_registerGamepadF(RGFW_window* win, char* file) { - RGFW_UNUSED(file); - - assert(win != NULL); - - return RGFW_gamepadCount - 1; - } + NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString); +} #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); } #endif #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); #if defined(RGFW_OPENGL) - - NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); + + NSOpenGLContext_setValues((id)win->src.ctx, &swapInterval, 222); #else RGFW_UNUSED(swapInterval); #endif } + #endif - - // Function to create a CGImageRef from an array of bytes - CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height) - { - // Define color space - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - // Create bitmap context - CGContextRef context = CGBitmapContextCreate( - buffer, - width, height, - 8, - RGFW_bufferSize.w * 4, - colorSpace, - kCGImageAlphaPremultipliedLast); - // Create image from bitmap context - CGImageRef image = CGBitmapContextCreateImage(context); - // Release the color space and context - CGColorSpaceRelease(colorSpace); - CGContextRelease(context); - - return image; - } - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - /* clear the window*/ +// Function to create a CGImageRef from an array of bytes +CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height) +{ + // Define color space + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + // Create bitmap context + CGContextRef context = CGBitmapContextCreate( + buffer, + width, height, + 8, + RGFW_bufferSize.w * 4, + colorSpace, + kCGImageAlphaPremultipliedLast); + // Create image from bitmap context + CGImageRef image = CGBitmapContextCreateImage(context); + // Release the color space and context + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { + return image; +} + +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + /* clear the window*/ + + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif + id view = NSWindow_contentView((id)win->src.window); + id layer = objc_msgSend_id(view, sel_registerName("layer")); - void* view = NSWindow_contentView(win->src.window); - void* layer = objc_msgSend_id(view, sel_registerName("layer")); + ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, + sel_registerName("setFrame:"), + (NSRect){{0, 0}, {win->r.w, win->r.h}}); - ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, - sel_registerName("setFrame:"), - (NSRect){{0, 0}, {win->r.w, win->r.h}}); + CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h); + // Get the current graphics context + id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext")); + // Get the CGContext from the current NSGraphicsContext + id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort")); + // Draw the image in the context + NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}}; + CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image); + // Flush the graphics context to ensure the drawing is displayed + objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics")); - CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h); - // Get the current graphics context - id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext")); - // Get the CGContext from the current NSGraphicsContext - id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort")); - // Draw the image in the context - NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}}; - CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image); - // Flush the graphics context to ensure the drawing is displayed - objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics")); - - objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image); - objc_msgSend_id(layer, sel_registerName("setNeedsDisplay")); - - CGImageRelease(image); + objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image); + objc_msgSend_id(layer, sel_registerName("setNeedsDisplay")); + + CGImageRelease(image); #endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); - #endif - } } - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - release(win->src.view); + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); + #endif + } +} -#ifdef RGFW_ALLOC_DROPFILES +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + NSRelease(win->src.view); + + #ifdef RGFW_ALLOC_DROPFILES { u32 i; for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); - RGFW_FREE(win->event.droppedFiles); + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); } -#endif - -#ifdef RGFW_BUFFER - release(win->src.bitmap); - release(win->src.image); -#endif + #endif - CVDisplayLinkStop(win->src.displayLink); - CVDisplayLinkRelease(win->src.displayLink); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + NSRelease(win->src.bitmap); + NSRelease(win->src.image); + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + #endif - RGFW_FREE(win); + RGFW_clipboard_switch(NULL); + + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); +} + +u64 RGFW_getTimeNS(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); } + return mach_absolute_time() * timebase_info.numer / timebase_info.denom; +} - u64 RGFW_getTimeNS(void) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return mach_absolute_time() * timebase_info.numer / timebase_info.denom; - } - - u64 RGFW_getTime(void) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); +u64 RGFW_getTime(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); } + return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); +} #endif /* RGFW_MACOS */ /* @@ -8441,7 +8939,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ */ #ifdef RGFW_WEBASM -RGFW_Event RGFW_events[20]; +RGFW_event RGFW_events[20]; size_t RGFW_eventLen = 0; EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { @@ -8456,8 +8954,8 @@ EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* us EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) { static u8 fullscreen = RGFW_FALSE; - static RGFW_rect ogRect; - + static RGFW_rect ogRect; + if (fullscreen == RGFW_FALSE) { ogRect = RGFW_root->r; } @@ -8465,12 +8963,12 @@ EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreen fullscreen = !fullscreen; RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - + RGFW_events[RGFW_eventLen].type = RGFW_windowResized; RGFW_eventLen++; - + RGFW_root->r = RGFW_RECT(0, 0, e->screenWidth, e->screenHeight); - + EM_ASM("Module.canvas.focus();"); if (fullscreen == RGFW_FALSE) { @@ -8483,7 +8981,7 @@ EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreen FSStrat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF; FSStrat.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; emscripten_request_fullscreen_strategy("#canvas", 1, &FSStrat); - #else + #else emscripten_request_fullscreen("#canvas", 1); #endif } @@ -8523,14 +9021,14 @@ EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, vo RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; - if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) { + if ((RGFW_root->_flags & RGFW_HOLD_MOUSE)) { RGFW_point p = RGFW_POINT(e->movementX, e->movementY); RGFW_events[RGFW_eventLen].point = p; } else RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); RGFW_eventLen++; - + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); return EM_TRUE; } @@ -8540,15 +9038,15 @@ EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, vo RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); - RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].button = e->button + 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); RGFW_eventLen++; - + return EM_TRUE; } @@ -8557,10 +9055,10 @@ EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); - RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].button = e->button + 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); @@ -8573,10 +9071,10 @@ EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY); - RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); + RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); RGFW_events[RGFW_eventLen].scroll = e->deltaY < 0 ? 1 : -1; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); @@ -8585,18 +9083,18 @@ EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* return EM_TRUE; } -EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); - RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].button = 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); @@ -8607,11 +9105,11 @@ EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, v return EM_TRUE; } -EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); @@ -8623,17 +9121,17 @@ EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, vo EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); - RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].button = 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; - + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); RGFW_eventLen++; } @@ -8642,21 +9140,45 @@ EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, voi EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; } -EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { +EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); if (gamepadEvent->index >= 4) return 0; - + + size_t i = gamepadEvent->index; + if (gamepadEvent->connected) { + RGFW_MEMCPY(RGFW_gamepads_name[gamepadEvent->index], gamepadEvent->id, sizeof(RGFW_gamepads_name[gamepadEvent->index])); + RGFW_gamepads_type[i] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[i], "Microsoft") || strstr(RGFW_gamepads_name[i], "X-Box")) + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[i], "PlayStation") || strstr(RGFW_gamepads_name[i], "PS3") || strstr(RGFW_gamepads_name[i], "PS4") || strstr(RGFW_gamepads_name[i], "PS5")) + RGFW_gamepads_type[i] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[i], "Nintendo")) + RGFW_gamepads_type[i] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[i], "Logitech")) + RGFW_gamepads_type[i] = RGFW_gamepadLogitech; + + RGFW_gamepadCount++; + RGFW_events[RGFW_eventLen].type = RGFW_gamepadConnected; + } else { + RGFW_gamepadCount--; + RGFW_events[RGFW_eventLen].type = RGFW_gamepadDisconnected; + } + + RGFW_events[RGFW_eventLen].gamepad = gamepadEvent->index; + RGFW_eventLen++; + + RGFW_gamepadCallback(RGFW_root, gamepadEvent->index, gamepadEvent->connected); + RGFW_gamepads[gamepadEvent->index] = gamepadEvent->connected; return 1; // The event was consumed by the callback handler } - u32 RGFW_webasmPhysicalToRGFW(u32 hash) { switch(hash) { /* 0x0000 */ - case 0x67243A2DU /* Escape */: return RGFW_Escape; /* 0x0001 */ + case 0x67243A2DU /* Escape */: return RGFW_escape; /* 0x0001 */ case 0x67251058U /* Digit0 */: return RGFW_0; /* 0x0002 */ case 0x67251059U /* Digit1 */: return RGFW_1; /* 0x0003 */ case 0x6725105AU /* Digit2 */: return RGFW_2; /* 0x0004 */ @@ -8667,10 +9189,10 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0x6725105FU /* Digit7 */: return RGFW_7; /* 0x0009 */ case 0x67251050U /* Digit8 */: return RGFW_8; /* 0x000A */ case 0x67251051U /* Digit9 */: return RGFW_9; /* 0x000B */ - case 0x92E14DD3U /* Minus */: return RGFW_Minus; /* 0x000C */ - case 0x92E1FBACU /* Equal */: return RGFW_Equals; /* 0x000D */ - case 0x36BF1CB5U /* Backspace */: return RGFW_BackSpace; /* 0x000E */ - case 0x7B8E51E2U /* Tab */: return RGFW_Tab; /* 0x000F */ + case 0x92E14DD3U /* Minus */: return RGFW_minus; /* 0x000C */ + case 0x92E1FBACU /* Equal */: return RGFW_equals; /* 0x000D */ + case 0x36BF1CB5U /* Backspace */: return RGFW_backSpace; /* 0x000E */ + case 0x7B8E51E2U /* Tab */: return RGFW_tab; /* 0x000F */ case 0x2C595B51U /* KeyQ */: return RGFW_q; /* 0x0010 */ case 0x2C595B57U /* KeyW */: return RGFW_w; /* 0x0011 */ case 0x2C595B45U /* KeyE */: return RGFW_e; /* 0x0012 */ @@ -8680,10 +9202,10 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0x2C595B55U /* KeyU */: return RGFW_u; /* 0x0016 */ case 0x2C595B4FU /* KeyO */: return RGFW_o; /* 0x0018 */ case 0x2C595B50U /* KeyP */: return RGFW_p; /* 0x0019 */ - case 0x45D8158CU /* BracketLeft */: return RGFW_CloseBracket; /* 0x001A */ - case 0xDEEABF7CU /* BracketRight */: return RGFW_Bracket; /* 0x001B */ - case 0x92E1C5D2U /* Enter */: return RGFW_Return; /* 0x001C */ - case 0xE058958CU /* ControlLeft */: return RGFW_ControlL; /* 0x001D */ + case 0x45D8158CU /* BracketLeft */: return RGFW_closeBracket; /* 0x001A */ + case 0xDEEABF7CU /* BracketRight */: return RGFW_bracket; /* 0x001B */ + case 0x92E1C5D2U /* Enter */: return RGFW_return; /* 0x001C */ + case 0xE058958CU /* ControlLeft */: return RGFW_controlL; /* 0x001D */ case 0x2C595B41U /* KeyA */: return RGFW_a; /* 0x001E */ case 0x2C595B53U /* KeyS */: return RGFW_s; /* 0x001F */ case 0x2C595B44U /* KeyD */: return RGFW_d; /* 0x0020 */ @@ -8693,11 +9215,11 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0x2C595B4AU /* KeyJ */: return RGFW_j; /* 0x0024 */ case 0x2C595B4BU /* KeyK */: return RGFW_k; /* 0x0025 */ case 0x2C595B4CU /* KeyL */: return RGFW_l; /* 0x0026 */ - case 0x2707219EU /* Semicolon */: return RGFW_Semicolon; /* 0x0027 */ - case 0x92E0B58DU /* Quote */: return RGFW_Apostrophe; /* 0x0028 */ - case 0x36BF358DU /* Backquote */: return RGFW_Backtick; /* 0x0029 */ - case 0x26B1958CU /* ShiftLeft */: return RGFW_ShiftL; /* 0x002A */ - case 0x36BF2438U /* Backslash */: return RGFW_BackSlash; /* 0x002B */ + case 0x2707219EU /* Semicolon */: return RGFW_semicolon; /* 0x0027 */ + case 0x92E0B58DU /* Quote */: return RGFW_apostrophe; /* 0x0028 */ + case 0x36BF358DU /* Backquote */: return RGFW_backtick; /* 0x0029 */ + case 0x26B1958CU /* ShiftLeft */: return RGFW_shiftL; /* 0x002A */ + case 0x36BF2438U /* Backslash */: return RGFW_backSlash; /* 0x002B */ case 0x2C595B5AU /* KeyZ */: return RGFW_z; /* 0x002C */ case 0x2C595B58U /* KeyX */: return RGFW_x; /* 0x002D */ case 0x2C595B43U /* KeyC */: return RGFW_c; /* 0x002E */ @@ -8705,14 +9227,14 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0x2C595B42U /* KeyB */: return RGFW_b; /* 0x0030 */ case 0x2C595B4EU /* KeyN */: return RGFW_n; /* 0x0031 */ case 0x2C595B4DU /* KeyM */: return RGFW_m; /* 0x0032 */ - case 0x92E1A1C1U /* Comma */: return RGFW_Comma; /* 0x0033 */ - case 0x672FFAD4U /* Period */: return RGFW_Period; /* 0x0034 */ - case 0x92E0A438U /* Slash */: return RGFW_Slash; /* 0x0035 */ - case 0xC5A6BF7CU /* ShiftRight */: return RGFW_ShiftR; - case 0x5D64DA91U /* NumpadMultiply */: return RGFW_Multiply; - case 0xC914958CU /* AltLeft */: return RGFW_AltL; /* 0x0038 */ - case 0x92E09CB5U /* Space */: return RGFW_Space; /* 0x0039 */ - case 0xB8FAE73BU /* CapsLock */: return RGFW_CapsLock; /* 0x003A */ + case 0x92E1A1C1U /* Comma */: return RGFW_comma; /* 0x0033 */ + case 0x672FFAD4U /* Period */: return RGFW_period; /* 0x0034 */ + case 0x92E0A438U /* Slash */: return RGFW_slash; /* 0x0035 */ + case 0xC5A6BF7CU /* ShiftRight */: return RGFW_shiftR; + case 0x5D64DA91U /* NumpadMultiply */: return RGFW_multiply; + case 0xC914958CU /* AltLeft */: return RGFW_altL; /* 0x0038 */ + case 0x92E09CB5U /* Space */: return RGFW_space; /* 0x0039 */ + case 0xB8FAE73BU /* CapsLock */: return RGFW_capsLock; /* 0x003A */ case 0x7174B789U /* F1 */: return RGFW_F1; /* 0x003B */ case 0x7174B78AU /* F2 */: return RGFW_F2; /* 0x003C */ case 0x7174B78BU /* F3 */: return RGFW_F3; /* 0x003D */ @@ -8723,10 +9245,10 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0x7174B780U /* F8 */: return RGFW_F8; /* 0x0042 */ case 0x7174B781U /* F9 */: return RGFW_F9; /* 0x0043 */ case 0x7B8E57B0U /* F10 */: return RGFW_F10; /* 0x0044 */ - case 0xC925FCDFU /* Numpad7 */: return RGFW_Multiply; /* 0x0047 */ + case 0xC925FCDFU /* Numpad7 */: return RGFW_multiply; /* 0x0047 */ case 0xC925FCD0U /* Numpad8 */: return RGFW_KP_8; /* 0x0048 */ case 0xC925FCD1U /* Numpad9 */: return RGFW_KP_9; /* 0x0049 */ - case 0x5EA3E8A4U /* NumpadSubtract */: return RGFW_Minus; /* 0x004A */ + case 0x5EA3E8A4U /* NumpadSubtract */: return RGFW_minus; /* 0x004A */ case 0xC925FCDCU /* Numpad4 */: return RGFW_KP_4; /* 0x004B */ case 0xC925FCDDU /* Numpad5 */: return RGFW_KP_5; /* 0x004C */ case 0xC925FCDEU /* Numpad6 */: return RGFW_KP_6; /* 0x004D */ @@ -8734,24 +9256,24 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { case 0xC925FCDAU /* Numpad2 */: return RGFW_KP_2; /* 0x0050 */ case 0xC925FCDBU /* Numpad3 */: return RGFW_KP_3; /* 0x0051 */ case 0xC925FCD8U /* Numpad0 */: return RGFW_KP_0; /* 0x0052 */ - case 0x95852DACU /* NumpadDecimal */: return RGFW_KP_Period; /* 0x0053 */ + case 0x95852DACU /* NumpadDecimal */: return RGFW_period; /* 0x0053 */ case 0x7B8E57B1U /* F11 */: return RGFW_F11; /* 0x0057 */ case 0x7B8E57B2U /* F12 */: return RGFW_F12; /* 0x0058 */ case 0x7393FBACU /* NumpadEqual */: return RGFW_KP_Return; - case 0xB88EBF7CU /* AltRight */: return RGFW_AltR; /* 0xE038 */ - case 0xC925873BU /* NumLock */: return RGFW_Numlock; /* 0xE045 */ - case 0x2C595F45U /* Home */: return RGFW_Home; /* 0xE047 */ - case 0xC91BB690U /* ArrowUp */: return RGFW_Up; /* 0xE048 */ - case 0x672F9210U /* PageUp */: return RGFW_PageUp; /* 0xE049 */ - case 0x3799258CU /* ArrowLeft */: return RGFW_Left; /* 0xE04B */ - case 0x4CE33F7CU /* ArrowRight */: return RGFW_Right; /* 0xE04D */ - case 0x7B8E55DCU /* End */: return RGFW_End; /* 0xE04F */ - case 0x3799379EU /* ArrowDown */: return RGFW_Down; /* 0xE050 */ - case 0xBA90179EU /* PageDown */: return RGFW_PageDown; /* 0xE051 */ - case 0x6723CB2CU /* Insert */: return RGFW_Insert; /* 0xE052 */ - case 0x6725C50DU /* Delete */: return RGFW_Delete; /* 0xE053 */ - case 0x6723658CU /* OSLeft */: return RGFW_SuperL; /* 0xE05B */ - case 0x39643F7CU /* MetaRight */: return RGFW_SuperR; /* 0xE05C */ + case 0xB88EBF7CU /* AltRight */: return RGFW_altR; /* 0xE038 */ + case 0xC925873BU /* NumLock */: return RGFW_numLock; /* 0xE045 */ + case 0x2C595F45U /* Home */: return RGFW_home; /* 0xE047 */ + case 0xC91BB690U /* ArrowUp */: return RGFW_up; /* 0xE048 */ + case 0x672F9210U /* PageUp */: return RGFW_pageUp; /* 0xE049 */ + case 0x3799258CU /* ArrowLeft */: return RGFW_left; /* 0xE04B */ + case 0x4CE33F7CU /* ArrowRight */: return RGFW_right; /* 0xE04D */ + case 0x7B8E55DCU /* End */: return RGFW_end; /* 0xE04F */ + case 0x3799379EU /* ArrowDown */: return RGFW_down; /* 0xE050 */ + case 0xBA90179EU /* PageDown */: return RGFW_pageDown; /* 0xE051 */ + case 0x6723CB2CU /* Insert */: return RGFW_insert; /* 0xE052 */ + case 0x6725C50DU /* Delete */: return RGFW_delete; /* 0xE053 */ + case 0x6723658CU /* OSLeft */: return RGFW_superL; /* 0xE05B */ + case 0x39643F7CU /* MetaRight */: return RGFW_superR; /* 0xE05C */ } return 0; @@ -8759,46 +9281,49 @@ u32 RGFW_webasmPhysicalToRGFW(u32 hash) { void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyEvent(char* key, char* code, b8 press) { const char* iCode = code; - + u32 hash = 0; while(*iCode) hash = ((hash ^ 0x7E057D79U) << 3) ^ (unsigned int)*iCode++; - - u32 physicalKey = RGFW_webasmPhysicalToRGFW(hash); + + u32 physicalKey = RGFW_webasmPhysicalToRGFW(hash); u8 mappedKey = (u8)(*((u32*)key)); - + if (*((u16*)key) != mappedKey) { mappedKey = 0; - if (*((u32*)key) == *((u32*)"Tab")) mappedKey = RGFW_Tab; + if (*((u32*)key) == *((u32*)"Tab")) mappedKey = RGFW_tab; } RGFW_events[RGFW_eventLen].type = press ? RGFW_keyPressed : RGFW_keyReleased; - memcpy(RGFW_events[RGFW_eventLen].keyName, key, 16); RGFW_events[RGFW_eventLen].key = physicalKey; RGFW_events[RGFW_eventLen].keyChar = mappedKey; - RGFW_events[RGFW_eventLen].lockState = 0; + RGFW_events[RGFW_eventLen].keyMod = RGFW_root->event.keyMod; RGFW_eventLen++; RGFW_keyboard[physicalKey].prev = RGFW_keyboard[physicalKey].current; - RGFW_keyboard[physicalKey].current = 0; - - RGFW_keyCallback(RGFW_root, physicalKey, mappedKey, RGFW_events[RGFW_eventLen].keyName, 0, press); + RGFW_keyboard[physicalKey].current = press; - free(key); - free(code); + RGFW_keyCallback(RGFW_root, physicalKey, mappedKey, RGFW_root->event.keyMod, press); + + RGFW_free(key); + RGFW_free(code); +} + +void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyMods(b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super) { + RGFW_updateKeyModsPro(RGFW_root, capital, numlock, control, alt, shift, super); } void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) { - if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND)) + if (!(RGFW_root->_flags & RGFW_windowAllowDND)) return; - RGFW_events[RGFW_eventLen].droppedFilesCount = count; + RGFW_events[RGFW_eventLen].droppedFilesCount = count; RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count); RGFW_eventLen++; } b8 RGFW_stopCheckEvents_bool = RGFW_FALSE; -void RGFW_stopCheckEvents(void) { +void RGFW_stopCheckEvents(void) { RGFW_stopCheckEvents_bool = RGFW_TRUE; } @@ -8807,15 +9332,15 @@ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { if (waitMS == 0) return; - + u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6); - while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && + while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && (waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS) ) { emscripten_sleep(0); } - + RGFW_stopCheckEvents_bool = RGFW_FALSE; } @@ -8824,8 +9349,9 @@ void RGFW_init_buffer(RGFW_window* win) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + + win->buffer = RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; #ifdef RGFW_OSMESA win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); @@ -8835,19 +9361,19 @@ void RGFW_init_buffer(RGFW_window* win) { #endif } -void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { +void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { /* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */ - /* TODO: find a better way to do this, - strcpy doesn't seem to work, maybe because of asyncio + /* TODO: find a better way to do this */ - RGFW_events[RGFW_eventLen].type = RGFW_dnd; - strcpy((char*)RGFW_events[RGFW_eventLen].droppedFiles[index], file); + RGFW_events[RGFW_eventLen].type = RGFW_DND; + RGFW_MEMCPY((char*)RGFW_events[RGFW_eventLen].droppedFiles[index], file, RGFW_MAX_PATH); } #include #include #include +#include void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); } @@ -8860,47 +9386,45 @@ void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, siz fclose(file); } -RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - RGFW_UNUSED(name) +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + RGFW_UNUSED(name); - RGFW_UNUSED(RGFW_initFormatAttribs); - - RGFW_window* win = RGFW_window_basic_init(rect, args); - -#ifndef RGFW_WEBGPU - EmscriptenWebGLContextAttributes attrs; - attrs.alpha = EM_TRUE; - attrs.depth = EM_TRUE; - attrs.alpha = EM_TRUE; - attrs.stencil = RGFW_STENCIL; - attrs.antialias = RGFW_SAMPLES; - attrs.premultipliedAlpha = EM_TRUE; - attrs.preserveDrawingBuffer = EM_FALSE; - - if (RGFW_DOUBLE_BUFFER == 0) - attrs.renderViaOffscreenBackBuffer = 0; - else - attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; - - attrs.failIfMajorPerformanceCaveat = EM_FALSE; - attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; - attrs.minorVersion = RGFW_minorVersion; - - attrs.enableExtensionsByDefault = EM_TRUE; - attrs.explicitSwapControl = EM_TRUE; + RGFW_window_basic_init(win, rect, flags); - emscripten_webgl_init_context_attributes(&attrs); - win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs); - emscripten_webgl_make_context_current(win->src.ctx); + #ifndef RGFW_WEBGPU + EmscriptenWebGLContextAttributes attrs; + attrs.alpha = EM_TRUE; + attrs.depth = EM_TRUE; + attrs.alpha = EM_TRUE; + attrs.stencil = RGFW_STENCIL; + attrs.antialias = RGFW_SAMPLES; + attrs.premultipliedAlpha = EM_TRUE; + attrs.preserveDrawingBuffer = EM_FALSE; - #ifdef LEGACY_GL_EMULATION - EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + if (RGFW_DOUBLE_BUFFER == 0) + attrs.renderViaOffscreenBackBuffer = 0; + else + attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; + + attrs.failIfMajorPerformanceCaveat = EM_FALSE; + attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; + attrs.minorVersion = RGFW_minorVersion; + + attrs.enableExtensionsByDefault = EM_TRUE; + attrs.explicitSwapControl = EM_TRUE; + + emscripten_webgl_init_context_attributes(&attrs); + win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs); + emscripten_webgl_make_context_current(win->src.ctx); + + #ifdef LEGACY_GL_EMULATION + EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + #endif + #else + win->src.ctx = wgpuCreateInstance(NULL); + win->src.device = emscripten_webgpu_get_device(); + win->src.queue = wgpuDeviceGetQueue(win->src.device); #endif -#else - win->src.ctx = wgpuCreateInstance(NULL); - win->src.device = emscripten_webgpu_get_device(); - win->src.queue = wgpuDeviceGetQueue(win->src.device); -#endif emscripten_set_canvas_element_size("#canvas", rect.w, rect.h); emscripten_set_window_title(name); @@ -8920,25 +9444,24 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout); emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad); emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; + + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; } EM_ASM({ window.addEventListener("keydown", (event) => { - Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 1); - }, true, - ); - }); - - EM_ASM({ + Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta")); + Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 1); + }, + true); window.addEventListener("keyup", (event) => { - Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 0); - }, true, - ); + Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta")); + Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 0); + }, + true); }); EM_ASM({ @@ -8960,29 +9483,29 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { var path = '/' + drop_dir + '/' + file.name.replace("//", '_'); var reader = new FileReader(); - + reader.onloadend = (e) => { if (reader.readyState != 2) { out('failed to read dropped file: '+file.name+': '+reader.error); } else { var data = e.target.result; - + _RGFW_writeFile(path, new Uint8Array(data), file.size); } }; - reader.readAsArrayBuffer(file); + reader.readAsArrayBuffer(file); // This works weird on modern opengl var filename = stringToNewUTF8(path); filenamesArray.push(filename); - + Module._RGFW_makeSetValue(i, filename); } - + Module._Emscripten_onDrop(count); - + for (var i = 0; i < count; ++i) { _free(filenamesArray[i]); } @@ -8993,14 +9516,12 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { RGFW_init_buffer(win); glViewport(0, 0, rect.w, rect.h); - - RGFW_root = win; - if (args & RGFW_HIDE_MOUSE) { + if (flags & RGFW_windowHideMouse) { RGFW_window_showMouse(win, 0); } - if (args & RGFW_FULLSCREEN) { + if (flags & RGFW_windowFullscreen) { RGFW_window_resize(win, RGFW_getScreenSize()); } @@ -9011,13 +9532,13 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { return win; } -RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { static u8 index = 0; - - if (index == 0) { + + if (index == 0) { RGFW_resetKey(); } - + emscripten_sample_gamepad_data(); /* check gamepads */ for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) { @@ -9027,45 +9548,54 @@ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS) break; - + // Register buttons data for every connected gamepad for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) { u32 map[] = { - RGFW_GP_A, RGFW_GP_B, RGFW_GP_X, RGFW_GP_Y, - RGFW_GP_L1, RGFW_GP_R1, RGFW_GP_L2, RGFW_GP_R2, - RGFW_GP_SELECT, RGFW_GP_START, - RGFW_GP_L3, RGFW_GP_R3, - RGFW_GP_UP, RGFW_GP_DOWN, RGFW_GP_LEFT, RGFW_GP_RIGHT + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, + RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, + RGFW_gamepadL3, RGFW_gamepadR3, + RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight, RGFW_gamepadHome }; - u32 button = map[j]; + u32 button = map[j]; if (button == 404) continue; - if (RGFW_gpPressed[i][button] != gamepadState.digitalButton[j]) { + if (RGFW_gamepadPressed[i][button].current != gamepadState.digitalButton[j]) { if (gamepadState.digitalButton[j]) - win->event.type = RGFW_gpButtonPressed; + win->event.type = RGFW_gamepadButtonPressed; else - win->event.type = RGFW_gpButtonReleased; + win->event.type = RGFW_gamepadButtonReleased; win->event.gamepad = i; win->event.button = map[j]; - RGFW_gpPressed[i][button] = gamepadState.digitalButton[j]; + + RGFW_gamepadPressed[i][button].prev = RGFW_gamepadPressed[i][button].current; + RGFW_gamepadPressed[i][button].current = gamepadState.digitalButton[j]; + + RGFW_gamepadButtonCallback(win, win->event.gamepad, win->event.button, gamepadState.digitalButton[j]); return &win->event; } } for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) { win->event.axisesCount = gamepadState.numAxes / 2; - if (win->event.axis[j / 2].x != (i8)(gamepadState.axis[j] * 100.0f) || - win->event.axis[j / 2].y != (i8)(gamepadState.axis[j + 1] * 100.0f) + if (RGFW_gamepadAxes[i][(size_t)(j / 2)].x != (i8)(gamepadState.axis[j] * 100.0f) || + RGFW_gamepadAxes[i][(size_t)(j / 2)].y != (i8)(gamepadState.axis[j + 1] * 100.0f) ) { - win->event.axis[j / 2].x = (i8)(gamepadState.axis[j] * 100.0f); - win->event.axis[j / 2].y = (i8)(gamepadState.axis[j + 1] * 100.0f); - win->event.type = RGFW_gpAxisMove; + + RGFW_gamepadAxes[i][(size_t)(j / 2)].x = (i8)(gamepadState.axis[j] * 100.0f); + RGFW_gamepadAxes[i][(size_t)(j / 2)].y = (i8)(gamepadState.axis[j + 1] * 100.0f); + win->event.axis[(size_t)(j / 2)] = RGFW_gamepadAxes[i][(size_t)(j / 2)]; + + win->event.type = RGFW_gamepadAxisMove; win->event.gamepad = i; win->event.whichAxis = j / 2; + + RGFW_gamepadAxisCallback(win, win->event.gamepad, win->event.axis, win->event.axisesCount, win->event.whichAxis); return &win->event; } } @@ -9092,14 +9622,17 @@ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { } void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win) + RGFW_UNUSED(win); emscripten_set_canvas_element_size("#canvas", a.w, a.h); } /* NOTE: I don't know if this is possible */ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); } /* this one might be possible but it looks iffy */ -void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) } +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(channels); RGFW_UNUSED(a); RGFW_UNUSED(icon); return NULL; } + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { RGFW_UNUSED(win); RGFW_UNUSED(mouse); } +void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_UNUSED(mouse); } const char RGFW_CURSORS[11][12] = { "default", @@ -9115,13 +9648,14 @@ const char RGFW_CURSORS[11][12] = { "not-allowed" }; -void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - RGFW_UNUSED(win) +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_UNUSED(win); EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]); + return 1; } -void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseNormal); } void RGFW_window_showMouse(RGFW_window* win, i8 show) { @@ -9144,7 +9678,7 @@ RGFW_point RGFW_getGlobalMousePoint(void) { RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { RGFW_UNUSED(win); - + EmscriptenMouseEvent mouseEvent; emscripten_get_mouse_status(&mouseEvent); return RGFW_POINT( mouseEvent.targetX, mouseEvent.targetY); @@ -9164,45 +9698,39 @@ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { } void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(textLen) + RGFW_UNUSED(textLen); EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text); } -char* RGFW_readClipboard(size_t* size) { +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + RGFW_UNUSED(str); RGFW_UNUSED(strCapacity); /* placeholder code for later I'm not sure if this is possible do the the async stuff */ - - if (size != NULL) - *size = 0; - - char* str = (char*)malloc(1); - str[0] = '\0'; - - return str; + return 0; } void RGFW_window_swapBuffers(RGFW_window* win) { RGFW_UNUSED(win); - + #ifdef RGFW_BUFFER - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { glEnable(GL_TEXTURE_2D); GLuint texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer); - + float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w); float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h); @@ -9248,7 +9776,15 @@ void RGFW_window_close(RGFW_window* win) { emscripten_webgl_destroy_context(win->src.ctx); #endif - free(win); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + #endif + + RGFW_clipboard_switch(NULL); + + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); } int RGFW_innerWidth(void) { return EM_ASM_INT({ return window.innerWidth; }); } @@ -9258,7 +9794,7 @@ RGFW_area RGFW_getScreenSize(void) { return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight()); } -void* RGFW_getProcAddress(const char* procname) { +void* RGFW_getProcAddress(const char* procname) { return emscripten_webgl_get_proc_address(procname); } @@ -9279,14 +9815,14 @@ void RGFW_releaseCursor(RGFW_window* win) { emscripten_exit_pointerlock(); } -void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); emscripten_request_pointerlock("#canvas", 1); } -void RGFW_window_setName(RGFW_window* win, char* name) { +void RGFW_window_setName(RGFW_window* win, const char* name) { RGFW_UNUSED(win); emscripten_set_window_title(name); } @@ -9294,55 +9830,60 @@ void RGFW_window_setName(RGFW_window* win, char* name) { /* unsupported functions */ RGFW_monitor* RGFW_getMonitors(void) { return NULL; } RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; } -void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) } -void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } -void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } -void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)} -void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) } -void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) } -void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) } -void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) } -void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) } -b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; } - +void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); } +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win); RGFW_UNUSED(a); } +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win); RGFW_UNUSED(a); } +void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win); RGFW_UNUSED(border); } +b32 RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(icon); RGFW_UNUSED(a); RGFW_UNUSED(channels); return 0; } +void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win); } +b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win); return (RGFW_monitor){}; } #endif /* end of web asm defines */ /* unix (macOS, linux, web asm) only stuff */ #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) + /* unix threading */ #ifndef RGFW_NO_THREADS #include - RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { - RGFW_UNUSED(args); - - RGFW_thread t; - pthread_create((pthread_t*) &t, NULL, *ptr, NULL); - return t; - } - void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); } - void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); } -#ifdef __linux__ - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); } +RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { + RGFW_UNUSED(args); + + RGFW_thread t; + pthread_create((pthread_t*) &t, NULL, *ptr, NULL); + return t; +} +void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); } +void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); } + +#if defined(__linux__) +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); } #else - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { RGFW_UNUSED(thread); RGFW_UNUSED(priority); } +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { RGFW_UNUSED(thread); RGFW_UNUSED(priority); } #endif #endif #ifndef RGFW_WEBASM -/* unix sleep */ - void RGFW_sleep(u64 ms) { - struct timespec time; - time.tv_sec = 0; - time.tv_nsec = ms * 1e+6; - nanosleep(&time, NULL); - } +/* unix sleep */ +void RGFW_sleep(u64 ms) { + struct timespec time; + time.tv_sec = 0; + time.tv_nsec = ms * 1e+6; + + #ifndef RGFW_NO_UNIX_CLOCK + nanosleep(&time, NULL); + #endif +} + #endif #endif /* end of unix / mac stuff*/ @@ -9350,4 +9891,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return #if defined(__cplusplus) && !defined(__EMSCRIPTEN__) } + #ifdef __clang__ + #pragma clang diagnostic pop + #endif #endif diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 800f54658..710b05f39 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -86,8 +86,8 @@ void CloseWindow(void); #define Size NSSIZE #endif -#define RGFW_MALLOC RL_MALLOC -#define RGFW_FREE RL_FREE +#define RGFW_ALLOC(ptr, size) (RGFW_UNUSED(ptr),RL_MALLOC(size)) +#define RGFW_FREE(ptr, size) (RGFW_UNUSED(ptr),RL_FREE(size)) #define RGFW_CALLOC RL_CALLOC #include "../external/RGFW.h" @@ -127,15 +127,15 @@ static PlatformData platform = { NULL }; // Platform specific static bool RGFW_disableCursor = false; static const unsigned short keyMappingRGFW[] = { - [RGFW_KEY_NULL] = KEY_NULL, - [RGFW_Return] = KEY_ENTER, - [RGFW_Return] = KEY_ENTER, - [RGFW_Apostrophe] = KEY_APOSTROPHE, - [RGFW_Comma] = KEY_COMMA, - [RGFW_Minus] = KEY_MINUS, - [RGFW_Period] = KEY_PERIOD, - [RGFW_Slash] = KEY_SLASH, - [RGFW_Escape] = KEY_ESCAPE, + [RGFW_keyNULL] = KEY_NULL, + [RGFW_return] = KEY_ENTER, + [RGFW_return] = KEY_ENTER, + [RGFW_apostrophe] = KEY_APOSTROPHE, + [RGFW_comma] = KEY_COMMA, + [RGFW_minus] = KEY_MINUS, + [RGFW_period] = KEY_PERIOD, + [RGFW_slash] = KEY_SLASH, + [RGFW_escape] = KEY_ESCAPE, [RGFW_F1] = KEY_F1, [RGFW_F2] = KEY_F2, [RGFW_F3] = KEY_F3, @@ -148,7 +148,7 @@ static const unsigned short keyMappingRGFW[] = { [RGFW_F10] = KEY_F10, [RGFW_F11] = KEY_F11, [RGFW_F12] = KEY_F12, - [RGFW_Backtick] = KEY_GRAVE, + [RGFW_backtick] = KEY_GRAVE, [RGFW_0] = KEY_ZERO, [RGFW_1] = KEY_ONE, [RGFW_2] = KEY_TWO, @@ -159,19 +159,19 @@ static const unsigned short keyMappingRGFW[] = { [RGFW_7] = KEY_SEVEN, [RGFW_8] = KEY_EIGHT, [RGFW_9] = KEY_NINE, - [RGFW_Equals] = KEY_EQUAL, - [RGFW_BackSpace] = KEY_BACKSPACE, - [RGFW_Tab] = KEY_TAB, - [RGFW_CapsLock] = KEY_CAPS_LOCK, - [RGFW_ShiftL] = KEY_LEFT_SHIFT, - [RGFW_ControlL] = KEY_LEFT_CONTROL, - [RGFW_AltL] = KEY_LEFT_ALT, - [RGFW_SuperL] = KEY_LEFT_SUPER, + [RGFW_equals] = KEY_EQUAL, + [RGFW_backSpace] = KEY_BACKSPACE, + [RGFW_tab] = KEY_TAB, + [RGFW_capsLock] = KEY_CAPS_LOCK, + [RGFW_shiftL] = KEY_LEFT_SHIFT, + [RGFW_controlL] = KEY_LEFT_CONTROL, + [RGFW_altL] = KEY_LEFT_ALT, + [RGFW_superL] = KEY_LEFT_SUPER, #ifndef RGFW_MACOS - [RGFW_ShiftR] = KEY_RIGHT_SHIFT, - [RGFW_AltR] = KEY_RIGHT_ALT, + [RGFW_shiftR] = KEY_RIGHT_SHIFT, + [RGFW_altR] = KEY_RIGHT_ALT, #endif - [RGFW_Space] = KEY_SPACE, + [RGFW_space] = KEY_SPACE, [RGFW_a] = KEY_A, [RGFW_b] = KEY_B, @@ -199,23 +199,23 @@ static const unsigned short keyMappingRGFW[] = { [RGFW_x] = KEY_X, [RGFW_y] = KEY_Y, [RGFW_z] = KEY_Z, - [RGFW_Bracket] = KEY_LEFT_BRACKET, - [RGFW_BackSlash] = KEY_BACKSLASH, - [RGFW_CloseBracket] = KEY_RIGHT_BRACKET, - [RGFW_Semicolon] = KEY_SEMICOLON, - [RGFW_Insert] = KEY_INSERT, - [RGFW_Home] = KEY_HOME, - [RGFW_PageUp] = KEY_PAGE_UP, - [RGFW_Delete] = KEY_DELETE, - [RGFW_End] = KEY_END, - [RGFW_PageDown] = KEY_PAGE_DOWN, - [RGFW_Right] = KEY_RIGHT, - [RGFW_Left] = KEY_LEFT, - [RGFW_Down] = KEY_DOWN, - [RGFW_Up] = KEY_UP, - [RGFW_Numlock] = KEY_NUM_LOCK, + [RGFW_bracket] = KEY_LEFT_BRACKET, + [RGFW_backSlash] = KEY_BACKSLASH, + [RGFW_closeBracket] = KEY_RIGHT_BRACKET, + [RGFW_semicolon] = KEY_SEMICOLON, + [RGFW_insert] = KEY_INSERT, + [RGFW_home] = KEY_HOME, + [RGFW_pageUp] = KEY_PAGE_UP, + [RGFW_delete] = KEY_DELETE, + [RGFW_end] = KEY_END, + [RGFW_pageDown] = KEY_PAGE_DOWN, + [RGFW_right] = KEY_RIGHT, + [RGFW_left] = KEY_LEFT, + [RGFW_down] = KEY_DOWN, + [RGFW_up] = KEY_UP, + [RGFW_numLock] = KEY_NUM_LOCK, [RGFW_KP_Slash] = KEY_KP_DIVIDE, - [RGFW_Multiply] = KEY_KP_MULTIPLY, + [RGFW_multiply] = KEY_KP_MULTIPLY, [RGFW_KP_Minus] = KEY_KP_SUBTRACT, [RGFW_KP_Return] = KEY_KP_ENTER, [RGFW_KP_1] = KEY_KP_1, @@ -669,7 +669,7 @@ void SetClipboardText(const char *text) } // Get clipboard text content -// NOTE: returned string is allocated and freed by GLFW +// NOTE: returned string is allocated and freed by RGFW const char *GetClipboardText(void) { return RGFW_readClipboard(NULL); @@ -819,23 +819,23 @@ const char *GetKeyName(int key) static KeyboardKey ConvertScancodeToKey(u32 keycode); int RGFW_gpConvTable[18] = { - [RGFW_GP_Y] = GAMEPAD_BUTTON_RIGHT_FACE_UP, - [RGFW_GP_B] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, - [RGFW_GP_A] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN, - [RGFW_GP_X] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT, - [RGFW_GP_L1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, - [RGFW_GP_R1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, - [RGFW_GP_L2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, - [RGFW_GP_R2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2, - [RGFW_GP_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT, - [RGFW_GP_HOME] = GAMEPAD_BUTTON_MIDDLE, - [RGFW_GP_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT, - [RGFW_GP_UP] = GAMEPAD_BUTTON_LEFT_FACE_UP, - [RGFW_GP_RIGHT] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT, - [RGFW_GP_DOWN] = GAMEPAD_BUTTON_LEFT_FACE_DOWN, - [RGFW_GP_LEFT] = GAMEPAD_BUTTON_LEFT_FACE_LEFT, - [RGFW_GP_L3] = GAMEPAD_BUTTON_LEFT_THUMB, - [RGFW_GP_R3] = GAMEPAD_BUTTON_RIGHT_THUMB, + [RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP, + [RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, + [RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN, + [RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT, + [RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, + [RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, + [RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, + [RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2, + [RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT, + [RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE, + [RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT, + [RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP, + [RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT, + [RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN, + [RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT, + [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB, + [RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB, }; // Register all input events @@ -896,8 +896,7 @@ void PollInputEvents(void) CORE.Window.resizedLastFrame = false; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - #define RGFW_HOLD_MOUSE (1L<<2) - if (platform.window->_winArgs & RGFW_HOLD_MOUSE) + if (platform.window->_flags & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; @@ -909,7 +908,7 @@ void PollInputEvents(void) while (RGFW_window_checkEvent(platform.window)) { - if ((platform.window->event.type >= RGFW_gpButtonPressed) && (platform.window->event.type <= RGFW_gpAxisMove)) + if ((platform.window->event.type >= RGFW_gamepadButtonPressed) && (platform.window->event.type <= RGFW_gamepadAxisMove)) { if (!CORE.Input.Gamepad.ready[platform.window->event.gamepad]) { @@ -921,13 +920,13 @@ void PollInputEvents(void) } } - RGFW_Event *event = &platform.window->event; + RGFW_event *event = &platform.window->event; // All input events can be processed after polling switch (event->type) { case RGFW_quit: CORE.Window.shouldClose = true; break; - case RGFW_dnd: // Dropped file + case RGFW_DND: // Dropped file { for (int i = 0; i < event->droppedFilesCount; i++) { @@ -1019,7 +1018,7 @@ void PollInputEvents(void) int btn = event->button; if (btn == RGFW_mouseLeft) btn = 1; else if (btn == RGFW_mouseRight) btn = 2; - else if (btn == RGFW_mouseMiddle) btn = 3; + else if (btn == RGFW_mouseMiddle) btn = 3; CORE.Input.Mouse.currentButtonState[btn - 1] = 1; CORE.Input.Touch.currentTouchState[btn - 1] = 1; @@ -1046,7 +1045,7 @@ void PollInputEvents(void) } break; case RGFW_mousePosChanged: { - if (platform.window->_winArgs & RGFW_HOLD_MOUSE) + if (platform.window->_flags & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.currentPosition.x += (float)event->point.x; CORE.Input.Mouse.currentPosition.y += (float)event->point.y; @@ -1061,7 +1060,7 @@ void PollInputEvents(void) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; touchAction = 2; } break; - case RGFW_gpButtonPressed: + case RGFW_gamepadButtonPressed: { int button = RGFW_gpConvTable[event->button]; @@ -1071,14 +1070,14 @@ void PollInputEvents(void) CORE.Input.Gamepad.lastButtonPressed = button; } } break; - case RGFW_gpButtonReleased: + case RGFW_gamepadButtonReleased: { int button = RGFW_gpConvTable[event->button]; CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 0; if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } break; - case RGFW_gpAxisMove: + case RGFW_gamepadAxisMove: { int axis = -1; @@ -1153,26 +1152,26 @@ void PollInputEvents(void) int InitPlatform(void) { // Initialize RGFW internal global state, only required systems - unsigned int flags = RGFW_CENTER | RGFW_ALLOW_DND; + unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND; // Check window creation flags if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) { CORE.Window.fullscreen = true; - flags |= RGFW_FULLSCREEN; + flags |= RGFW_windowFullscreen; } - if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER; - if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE; - if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW; - if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN; + if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_windowNoBorder; + if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_windowNoResize; + if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_windowTransparent; + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_windowFullscreen; // NOTE: Some OpenGL context attributes must be set before window creation // Check selection OpenGL version - if (rlGetVersion() == RL_OPENGL_21) RGFW_setGLVersion(RGFW_GL_CORE, 2, 1); - else if (rlGetVersion() == RL_OPENGL_33) RGFW_setGLVersion(RGFW_GL_CORE, 3, 3); - else if (rlGetVersion() == RL_OPENGL_43) RGFW_setGLVersion(RGFW_GL_CORE, 4, 1); + if (rlGetVersion() == RL_OPENGL_21) RGFW_setGLVersion(RGFW_glCore, 2, 1); + else if (rlGetVersion() == RL_OPENGL_33) RGFW_setGLVersion(RGFW_glCore, 3, 3); + else if (rlGetVersion() == RL_OPENGL_43) RGFW_setGLVersion(RGFW_glCore, 4, 1); if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLSamples(4); From 7b570bdfdda663384a3cb49af28412df37e2d036 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jan 2025 19:47:06 +0100 Subject: [PATCH 04/39] Update models_point_rendering.c --- examples/models/models_point_rendering.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index d33cbdda8..f4f095c1d 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -163,9 +163,9 @@ static Mesh GenMeshPoints(int numPoints) float phi = (2.0f*PI*rand())/RAND_MAX; float r = (10.0f*rand())/RAND_MAX; - mesh.vertices[i*3 + 0] = r*sin(theta)*cos(phi); - mesh.vertices[i*3 + 1] = r*sin(theta)*sin(phi); - mesh.vertices[i*3 + 2] = r*cos(theta); + mesh.vertices[i*3 + 0] = r*sinf(theta)*cosf(phi); + mesh.vertices[i*3 + 1] = r*sinf(theta)*sinf(phi); + mesh.vertices[i*3 + 2] = r*cosf(theta); Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f); From 94f261c6d7e619676ed653b5edae173ed01e42e0 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jan 2025 19:47:12 +0100 Subject: [PATCH 05/39] Update rmodels.c --- src/rmodels.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index ed0ce9136..9ab2bcca9 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -183,6 +183,7 @@ void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color) } // Draw a point in 3D space, actually a small line +// WARNING: OpenGL ES 2.0 does not support point mode drawing void DrawPoint3D(Vector3 position, Color color) { rlPushMatrix(); @@ -3779,6 +3780,7 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float } // Draw a model points +// WARNING: OpenGL ES 2.0 does not support point mode drawing void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) { rlEnablePointMode(); @@ -3787,10 +3789,11 @@ void DrawModelPoints(Model model, Vector3 position, float scale, Color tint) DrawModel(model, position, scale, tint); rlEnableBackfaceCulling(); - rlDisableWireMode(); + rlDisablePointMode(); } // Draw a model points +// WARNING: OpenGL ES 2.0 does not support point mode drawing void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { rlEnablePointMode(); @@ -3799,7 +3802,7 @@ void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, floa DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); rlEnableBackfaceCulling(); - rlDisableWireMode(); + rlDisablePointMode(); } // Draw a billboard From 313067d749c2660218609a9c61ce2a576ab239ba Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jan 2025 19:47:21 +0100 Subject: [PATCH 06/39] Update rlgl.h --- src/rlgl.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 574b860b0..245fd059d 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -684,9 +684,10 @@ RLAPI void rlSetCullFace(int mode); // Set face culling mode RLAPI void rlEnableScissorTest(void); // Enable scissor test RLAPI void rlDisableScissorTest(void); // Disable scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test -RLAPI void rlEnableWireMode(void); // Enable wire mode RLAPI void rlEnablePointMode(void); // Enable point mode -RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode +RLAPI void rlDisablePointMode(void); // Disable point mode +RLAPI void rlEnableWireMode(void); // Enable wire mode +RLAPI void rlDisableWireMode(void); // Disable wire mode RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI void rlEnableSmoothLines(void); // Enable line aliasing @@ -1967,6 +1968,15 @@ void rlEnableWireMode(void) #endif } +// Disable wire mode +void rlDisableWireMode(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif +} + // Enable point mode void rlEnablePointMode(void) { @@ -1977,8 +1987,8 @@ void rlEnablePointMode(void) #endif } -// Disable wire mode -void rlDisableWireMode(void) +// Disable point mode +void rlDisablePointMode(void) { #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES From 7c7b087efb8c3c753eea3ff95a2afe309bf1ee54 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jan 2025 19:48:31 +0100 Subject: [PATCH 07/39] REVIEWED: example: `shaders_deferred_render` -WIP- Not working but shader compiles and example runs... not sure if deferred rendering could be supported in OpenGL ES 2.0. --- examples/Makefile.Web | 8 +-- .../shaders/glsl100/deferred_shading.fs | 59 ++++++++++++++++++ .../shaders/glsl100/deferred_shading.vs | 16 +++++ .../resources/shaders/glsl100/gbuffer.fs | 36 +++++++++++ .../resources/shaders/glsl100/gbuffer.vs | 60 +++++++++++++++++++ examples/shaders/shaders_deferred_render.c | 9 ++- 6 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 examples/shaders/resources/shaders/glsl100/deferred_shading.fs create mode 100644 examples/shaders/resources/shaders/glsl100/deferred_shading.vs create mode 100644 examples/shaders/resources/shaders/glsl100/gbuffer.fs create mode 100644 examples/shaders/resources/shaders/glsl100/gbuffer.vs diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 3757e4a3d..c9becc29b 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -1042,10 +1042,10 @@ shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c shaders/shaders_deferred_render: shaders/shaders_deferred_render.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \ - --preload-file shaders/resources/shaders/glsl330/gbuffer.vs@resources/shaders/glsl330/gbuffer.vs \ - --preload-file shaders/resources/shaders/glsl330/gbuffer.fs@resources/shaders/glsl330/gbuffer.fs \ - --preload-file shaders/resources/shaders/glsl330/deferred_shading.fs@resources/shaders/glsl330/deferred_shading.fs \ - --preload-file shaders/resources/shaders/glsl330/deferred_shading.fs@resources/shaders/glsl330/deferred_shading.fs + --preload-file shaders/resources/shaders/glsl100/gbuffer.vs@resources/shaders/glsl100/gbuffer.vs \ + --preload-file shaders/resources/shaders/glsl100/gbuffer.fs@resources/shaders/glsl100/gbuffer.fs \ + --preload-file shaders/resources/shaders/glsl100/deferred_shading.vs@resources/shaders/glsl100/deferred_shading.vs \ + --preload-file shaders/resources/shaders/glsl100/deferred_shading.fs@resources/shaders/glsl100/deferred_shading.fs shaders/shaders_eratosthenes: shaders/shaders_eratosthenes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ diff --git a/examples/shaders/resources/shaders/glsl100/deferred_shading.fs b/examples/shaders/resources/shaders/glsl100/deferred_shading.fs new file mode 100644 index 000000000..d782792b9 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/deferred_shading.fs @@ -0,0 +1,59 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D gPosition; +uniform sampler2D gNormal; +uniform sampler2D gAlbedoSpec; + +struct Light { + int enabled; + int type; // Unused in this demo. + vec3 position; + vec3 target; // Unused in this demo. + vec4 color; +}; + +const int NR_LIGHTS = 4; +uniform Light lights[NR_LIGHTS]; +uniform vec3 viewPosition; + +const float QUADRATIC = 0.032; +const float LINEAR = 0.09; + +void main() +{ + vec3 fragPosition = texture2D(gPosition, fragTexCoord).rgb; + vec3 normal = texture2D(gNormal, fragTexCoord).rgb; + vec3 albedo = texture2D(gAlbedoSpec, fragTexCoord).rgb; + float specular = texture2D(gAlbedoSpec, fragTexCoord).a; + + vec3 ambient = albedo*vec3(0.1); + vec3 viewDirection = normalize(viewPosition - fragPosition); + + for (int i = 0; i < NR_LIGHTS; ++i) + { + if(lights[i].enabled == 0) continue; + vec3 lightDirection = lights[i].position - fragPosition; + vec3 diffuse = max(dot(normal, lightDirection), 0.0)*albedo*lights[i].color.xyz; + + vec3 halfwayDirection = normalize(lightDirection + viewDirection); + float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0); + vec3 specular = specular*spec*lights[i].color.xyz; + + // Attenuation + float distance = length(lights[i].position - fragPosition); + float attenuation = 1.0/(1.0 + LINEAR * distance + QUADRATIC*distance*distance); + diffuse *= attenuation; + specular *= attenuation; + ambient += diffuse + specular; + } + + gl_FragColor = vec4(ambient, 1.0); +} + diff --git a/examples/shaders/resources/shaders/glsl100/deferred_shading.vs b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs new file mode 100644 index 000000000..bb108ce09 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs @@ -0,0 +1,16 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; + +// Output vertex attributes (to fragment shader) +varying vec2 fragTexCoord; + +void main() +{ + fragTexCoord = vertexTexCoord; + + // Calculate final vertex position + gl_Position = vec4(vertexPosition, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.fs b/examples/shaders/resources/shaders/glsl100/gbuffer.fs new file mode 100644 index 000000000..2945c5ddd --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.fs @@ -0,0 +1,36 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec3 fragNormal; +varying vec4 fragColor; + +// TODO: Is there some alternative for GLSL100 +//layout (location = 0) out vec3 gPosition; +//layout (location = 1) out vec3 gNormal; +//layout (location = 2) out vec4 gAlbedoSpec; +//uniform vec3 gPosition; +//uniform vec3 gNormal; +//uniform vec4 gAlbedoSpec; + +// Input uniform values +uniform sampler2D texture0; // Diffuse texture +uniform sampler2D specularTexture; + +void main() +{ + // Store the fragment position vector in the first gbuffer texture + //gPosition = fragPosition; + + // Store the per-fragment normals into the gbuffer + //gNormal = normalize(fragNormal); + + // Store the diffuse per-fragment color + gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb; + + // Store specular intensity in gAlbedoSpec's alpha component + gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r; +} diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.vs b/examples/shaders/resources/shaders/glsl100/gbuffer.vs new file mode 100644 index 000000000..2791ce5ee --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.vs @@ -0,0 +1,60 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 matModel; +uniform mat4 matView; +uniform mat4 matProjection; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec3 fragNormal; +varying vec4 fragColor; + + +// https://github.com/glslify/glsl-inverse +mat3 inverse(mat3 m) +{ + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + + float b01 = a22*a11 - a12*a21; + float b11 = -a22*a10 + a12*a20; + float b21 = a21*a10 - a11*a20; + + float det = a00*b01 + a01*b11 + a02*b21; + + return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), + b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10), + b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det; +} + +// https://github.com/glslify/glsl-transpose +mat3 transpose(mat3 m) +{ + return mat3(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +void main() +{ + // Calculate vertex attributes for fragment shader + vec4 worldPos = matModel*vec4(vertexPosition, 1.0); + fragPosition = worldPos.xyz; + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalMatrix*vertexNormal; + + // Calculate final vertex position + gl_Position = matProjection*matView*worldPos; +} diff --git a/examples/shaders/shaders_deferred_render.c b/examples/shaders/shaders_deferred_render.c index e03ad6009..f246f6a5a 100644 --- a/examples/shaders/shaders_deferred_render.c +++ b/examples/shaders/shaders_deferred_render.c @@ -76,11 +76,11 @@ int main(void) Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f)); // Load geometry buffer (G-buffer) shader and deferred shader - Shader gbufferShader = LoadShader("resources/shaders/glsl330/gbuffer.vs", - "resources/shaders/glsl330/gbuffer.fs"); + Shader gbufferShader = LoadShader(TextFormat("resources/shaders/glsl%i/gbuffer.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/gbuffer.fs", GLSL_VERSION)); - Shader deferredShader = LoadShader("resources/shaders/glsl330/deferred_shading.vs", - "resources/shaders/glsl330/deferred_shading.fs"); + Shader deferredShader = LoadShader(TextFormat("resources/shaders/glsl%i/deferred_shading.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/deferred_shading.fs", GLSL_VERSION)); deferredShader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(deferredShader, "viewPosition"); // Initialize the G-buffer @@ -130,7 +130,6 @@ int main(void) if (!rlFramebufferComplete(gBuffer.framebuffer)) { TraceLog(LOG_WARNING, "Framebuffer is not complete"); - exit(1); } // Now we initialize the sampler2D uniform's in the deferred shader. From 27e530eb18c1e09ccf53e2df7fe51e3d5876c31e Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Fri, 17 Jan 2025 03:42:30 -0600 Subject: [PATCH 08/39] update examples with difficulty stars (#4694) * update examples with difficulty stars * manual fix script issues * manual fix script issues --- examples/audio/audio_mixed_processor.c | 2 ++ examples/audio/audio_module_playing.c | 2 ++ examples/audio/audio_music_stream.c | 2 ++ examples/audio/audio_raw_stream.c | 2 ++ examples/audio/audio_sound_loading.c | 2 ++ examples/audio/audio_sound_multi.c | 2 ++ examples/audio/audio_stream_effects.c | 2 ++ examples/core/core_2d_camera.c | 2 ++ examples/core/core_2d_camera_mouse_zoom.c | 2 ++ examples/core/core_2d_camera_platformer.c | 2 ++ examples/core/core_2d_camera_split_screen.c | 2 ++ examples/core/core_3d_camera_first_person.c | 2 ++ examples/core/core_3d_camera_free.c | 2 ++ examples/core/core_3d_camera_mode.c | 2 ++ examples/core/core_3d_camera_split_screen.c | 2 ++ examples/core/core_3d_picking.c | 2 ++ examples/core/core_automation_events.c | 2 ++ examples/core/core_basic_screen_manager.c | 2 ++ examples/core/core_basic_window.c | 2 ++ examples/core/core_custom_frame_control.c | 2 ++ examples/core/core_custom_logging.c | 2 ++ examples/core/core_drop_files.c | 2 ++ examples/core/core_input_gamepad.c | 2 ++ examples/core/core_input_gestures.c | 2 ++ examples/core/core_input_keys.c | 2 ++ examples/core/core_input_mouse.c | 2 ++ examples/core/core_input_mouse_wheel.c | 2 ++ examples/core/core_input_multitouch.c | 2 ++ examples/core/core_loading_thread.c | 2 ++ examples/core/core_random_values.c | 2 ++ examples/core/core_scissor_test.c | 2 ++ examples/core/core_smooth_pixelperfect.c | 2 ++ examples/core/core_storage_values.c | 2 ++ examples/core/core_vr_simulator.c | 2 ++ examples/core/core_window_flags.c | 2 ++ examples/core/core_window_letterbox.c | 2 ++ examples/core/core_window_should_close.c | 2 ++ examples/core/core_world_screen.c | 2 ++ examples/models/models_animation.c | 2 ++ examples/models/models_billboard.c | 2 ++ examples/models/models_box_collisions.c | 2 ++ examples/models/models_cubicmap.c | 2 ++ examples/models/models_draw_cube_texture.c | 2 ++ examples/models/models_first_person_maze.c | 2 ++ examples/models/models_geometric_shapes.c | 2 ++ examples/models/models_heightmap.c | 2 ++ examples/models/models_loading.c | 2 ++ examples/models/models_loading_gltf.c | 2 ++ examples/models/models_loading_m3d.c | 2 ++ examples/models/models_loading_vox.c | 2 ++ examples/models/models_mesh_generation.c | 4 +++- examples/models/models_mesh_picking.c | 2 ++ examples/models/models_orthographic_projection.c | 2 ++ examples/models/models_rlgl_solar_system.c | 2 ++ examples/models/models_skybox.c | 2 ++ examples/models/models_waving_cubes.c | 2 ++ examples/models/models_yaw_pitch_roll.c | 2 ++ examples/shaders/shaders_basic_lighting.c | 2 ++ examples/shaders/shaders_custom_uniform.c | 2 ++ examples/shaders/shaders_deferred_render.c | 2 ++ examples/shaders/shaders_eratosthenes.c | 2 ++ examples/shaders/shaders_fog.c | 2 ++ examples/shaders/shaders_hot_reloading.c | 2 ++ examples/shaders/shaders_hybrid_render.c | 2 ++ examples/shaders/shaders_julia_set.c | 2 ++ examples/shaders/shaders_lightmap.c | 2 ++ examples/shaders/shaders_mesh_instancing.c | 2 ++ examples/shaders/shaders_model_shader.c | 2 ++ examples/shaders/shaders_multi_sample2d.c | 2 ++ examples/shaders/shaders_palette_switch.c | 2 ++ examples/shaders/shaders_postprocessing.c | 2 ++ examples/shaders/shaders_raymarching.c | 2 ++ examples/shaders/shaders_shapes_textures.c | 2 ++ examples/shaders/shaders_simple_mask.c | 2 ++ examples/shaders/shaders_spotlight.c | 2 ++ examples/shaders/shaders_texture_drawing.c | 4 +++- examples/shaders/shaders_texture_outline.c | 2 ++ examples/shaders/shaders_texture_tiling.c | 2 ++ examples/shaders/shaders_texture_waves.c | 2 ++ examples/shaders/shaders_write_depth.c | 2 ++ examples/shapes/shapes_basic_shapes.c | 2 ++ examples/shapes/shapes_bouncing_ball.c | 2 ++ examples/shapes/shapes_collision_area.c | 2 ++ examples/shapes/shapes_colors_palette.c | 2 ++ examples/shapes/shapes_draw_circle_sector.c | 2 ++ examples/shapes/shapes_draw_rectangle_rounded.c | 2 ++ examples/shapes/shapes_draw_ring.c | 2 ++ examples/shapes/shapes_easings_ball_anim.c | 2 ++ examples/shapes/shapes_easings_box_anim.c | 2 ++ examples/shapes/shapes_easings_rectangle_array.c | 2 ++ examples/shapes/shapes_following_eyes.c | 2 ++ examples/shapes/shapes_lines_bezier.c | 2 ++ examples/shapes/shapes_logo_raylib.c | 2 ++ examples/shapes/shapes_logo_raylib_anim.c | 2 ++ examples/shapes/shapes_rectangle_scaling.c | 2 ++ examples/shapes/shapes_splines_drawing.c | 2 ++ examples/shapes/shapes_top_down_lights.c | 2 ++ examples/text/text_codepoints_loading.c | 2 ++ examples/text/text_draw_3d.c | 2 ++ examples/text/text_font_filters.c | 2 ++ examples/text/text_font_loading.c | 2 ++ examples/text/text_font_sdf.c | 2 ++ examples/text/text_font_spritefont.c | 2 ++ examples/text/text_format_text.c | 2 ++ examples/text/text_input_box.c | 2 ++ examples/text/text_raylib_fonts.c | 2 ++ examples/text/text_rectangle_bounds.c | 2 ++ examples/text/text_unicode.c | 2 ++ examples/text/text_writing_anim.c | 2 ++ examples/textures/textures_background_scrolling.c | 2 ++ examples/textures/textures_blend_modes.c | 2 ++ examples/textures/textures_bunnymark.c | 2 ++ examples/textures/textures_draw_tiled.c | 2 ++ examples/textures/textures_fog_of_war.c | 2 ++ examples/textures/textures_gif_player.c | 2 ++ examples/textures/textures_image_drawing.c | 2 ++ examples/textures/textures_image_generation.c | 2 ++ examples/textures/textures_image_loading.c | 2 ++ examples/textures/textures_image_processing.c | 2 ++ examples/textures/textures_image_text.c | 4 +++- examples/textures/textures_logo_raylib.c | 2 ++ examples/textures/textures_mouse_painting.c | 2 ++ examples/textures/textures_npatch_drawing.c | 2 ++ examples/textures/textures_particles_blending.c | 4 +++- examples/textures/textures_polygon.c | 4 +++- examples/textures/textures_raw_data.c | 2 ++ examples/textures/textures_sprite_anim.c | 2 ++ examples/textures/textures_sprite_button.c | 2 ++ examples/textures/textures_sprite_explosion.c | 2 ++ examples/textures/textures_srcrec_dstrec.c | 2 ++ examples/textures/textures_textured_curve.c | 2 ++ examples/textures/textures_to_image.c | 2 ++ 132 files changed, 269 insertions(+), 5 deletions(-) diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c index df46edc4e..16c83f36d 100644 --- a/examples/audio/audio_mixed_processor.c +++ b/examples/audio/audio_mixed_processor.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Mixed audio processing * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by hkc (@hatkidchan) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/audio/audio_module_playing.c b/examples/audio/audio_module_playing.c index 6234f0e55..3b77ed3e6 100644 --- a/examples/audio/audio_module_playing.c +++ b/examples/audio/audio_module_playing.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Module playing (streaming) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_music_stream.c b/examples/audio/audio_music_stream.c index bdf141edf..99d270326 100644 --- a/examples/audio/audio_music_stream.c +++ b/examples/audio/audio_music_stream.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Music playing (streaming) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index 0b7954293..9b8338dfc 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Raw audio streaming * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.6, last time updated with raylib 4.2 * * Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox) diff --git a/examples/audio/audio_sound_loading.c b/examples/audio/audio_sound_loading.c index 41aa2160e..b96e613de 100644 --- a/examples/audio/audio_sound_loading.c +++ b/examples/audio/audio_sound_loading.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Sound loading and playing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_sound_multi.c b/examples/audio/audio_sound_multi.c index d5472efab..8d823b8eb 100644 --- a/examples/audio/audio_sound_multi.c +++ b/examples/audio/audio_sound_multi.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Playing sound multiple times * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.6 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_stream_effects.c b/examples/audio/audio_stream_effects.c index cc8273abc..ed5bdb105 100644 --- a/examples/audio/audio_stream_effects.c +++ b/examples/audio/audio_stream_effects.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Music stream processing effects * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 5.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_2d_camera.c b/examples/core/core_2d_camera.c index 99b61d4e5..6b3ef57d2 100644 --- a/examples/core/core_2d_camera.c +++ b/examples/core/core_2d_camera.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2D Camera system * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.5, last time updated with raylib 3.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_2d_camera_mouse_zoom.c b/examples/core/core_2d_camera_mouse_zoom.c index a9864b168..3b4fb5835 100644 --- a/examples/core/core_2d_camera_mouse_zoom.c +++ b/examples/core/core_2d_camera_mouse_zoom.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2d camera mouse zoom * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_2d_camera_platformer.c b/examples/core/core_2d_camera_platformer.c index 3743de80b..2fcf77b6e 100644 --- a/examples/core/core_2d_camera_platformer.c +++ b/examples/core/core_2d_camera_platformer.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2D Camera platformer * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.0 * * Example contributed by arvyy (@arvyy) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_2d_camera_split_screen.c b/examples/core/core_2d_camera_split_screen.c index 60b5a2e55..a5c645797 100644 --- a/examples/core/core_2d_camera_split_screen.c +++ b/examples/core/core_2d_camera_split_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2d camera split screen * +* Example complexity rating: [★★★★] 4/4 +* * Addapted from the core_3d_camera_split_screen example: * https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c * diff --git a/examples/core/core_3d_camera_first_person.c b/examples/core/core_3d_camera_first_person.c index 2b36c598b..809cb3962 100644 --- a/examples/core/core_3d_camera_first_person.c +++ b/examples/core/core_3d_camera_first_person.c @@ -2,6 +2,8 @@ * * raylib [core] example - 3d camera first person * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_3d_camera_free.c b/examples/core/core_3d_camera_free.c index 9899dbdb5..349a458cf 100644 --- a/examples/core/core_3d_camera_free.c +++ b/examples/core/core_3d_camera_free.c @@ -2,6 +2,8 @@ * * raylib [core] example - Initialize 3d camera free * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_3d_camera_mode.c b/examples/core/core_3d_camera_mode.c index 0600fd330..90e512965 100644 --- a/examples/core/core_3d_camera_mode.c +++ b/examples/core/core_3d_camera_mode.c @@ -2,6 +2,8 @@ * * raylib [core] example - Initialize 3d camera mode * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_3d_camera_split_screen.c b/examples/core/core_3d_camera_split_screen.c index 313b64f65..8b457bfab 100644 --- a/examples/core/core_3d_camera_split_screen.c +++ b/examples/core/core_3d_camera_split_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - 3d cmaera split screen * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.0 * * Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_3d_picking.c b/examples/core/core_3d_picking.c index 634afba8c..85d8482ef 100644 --- a/examples/core/core_3d_picking.c +++ b/examples/core/core_3d_picking.c @@ -2,6 +2,8 @@ * * raylib [core] example - Picking in 3d mode * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_automation_events.c b/examples/core/core_automation_events.c index 64ca51fda..2a0d5503f 100644 --- a/examples/core/core_automation_events.c +++ b/examples/core/core_automation_events.c @@ -2,6 +2,8 @@ * * raylib [core] example - automation events * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example based on 2d_camera_platformer example by arvyy (@arvyy) diff --git a/examples/core/core_basic_screen_manager.c b/examples/core/core_basic_screen_manager.c index df38a0623..964c922e4 100644 --- a/examples/core/core_basic_screen_manager.c +++ b/examples/core/core_basic_screen_manager.c @@ -2,6 +2,8 @@ * * raylib [core] examples - basic screen manager * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: This example illustrates a very simple screen manager based on a states machines * * Example originally created with raylib 4.0, last time updated with raylib 4.0 diff --git a/examples/core/core_basic_window.c b/examples/core/core_basic_window.c index 3cf2c7c5d..976227750 100644 --- a/examples/core/core_basic_window.c +++ b/examples/core/core_basic_window.c @@ -2,6 +2,8 @@ * * raylib [core] example - Basic window * +* Example complexity rating: [★☆☆☆] 1/4 +* * Welcome to raylib! * * To test examples, just press F6 and execute 'raylib_compile_execute' script diff --git a/examples/core/core_custom_frame_control.c b/examples/core/core_custom_frame_control.c index 9793fc359..0f1cd2391 100644 --- a/examples/core/core_custom_frame_control.c +++ b/examples/core/core_custom_frame_control.c @@ -2,6 +2,8 @@ * * raylib [core] example - custom frame control * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: WARNING: This is an example for advanced users willing to have full control over * the frame processes. By default, EndDrawing() calls the following processes: * 1. Draw remaining batch data: rlDrawRenderBatchActive() diff --git a/examples/core/core_custom_logging.c b/examples/core/core_custom_logging.c index f886267ee..7636585be 100644 --- a/examples/core/core_custom_logging.c +++ b/examples/core/core_custom_logging.c @@ -2,6 +2,8 @@ * * raylib [core] example - Custom logging * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Pablo Marcos Oltra (@pamarcos) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_drop_files.c b/examples/core/core_drop_files.c index 2e51d872b..addf7ec63 100644 --- a/examples/core/core_drop_files.c +++ b/examples/core/core_drop_files.c @@ -2,6 +2,8 @@ * * raylib [core] example - Windows drop files * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) * * Example originally created with raylib 1.3, last time updated with raylib 4.2 diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index f9310fdc3..2e6e79d7f 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -2,6 +2,8 @@ * * raylib [core] example - Gamepad input * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: This example requires a Gamepad connected to the system * raylib is configured to work with the following gamepads: * - Xbox 360 Controller (Xbox 360, Xbox One) diff --git a/examples/core/core_input_gestures.c b/examples/core/core_input_gestures.c index 27ecef56e..5c2fc9482 100644 --- a/examples/core/core_input_gestures.c +++ b/examples/core/core_input_gestures.c @@ -2,6 +2,8 @@ * * raylib [core] example - Input Gestures Detection * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_keys.c b/examples/core/core_input_keys.c index 8e74b93b0..a07739b22 100644 --- a/examples/core/core_input_keys.c +++ b/examples/core/core_input_keys.c @@ -2,6 +2,8 @@ * * raylib [core] example - Keyboard input * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c index e4c6f20ee..6091ded45 100644 --- a/examples/core/core_input_mouse.c +++ b/examples/core/core_input_mouse.c @@ -2,6 +2,8 @@ * * raylib [core] example - Mouse input * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 5.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_mouse_wheel.c b/examples/core/core_input_mouse_wheel.c index d261e9348..2583ebbb5 100644 --- a/examples/core/core_input_mouse_wheel.c +++ b/examples/core/core_input_mouse_wheel.c @@ -2,6 +2,8 @@ * * raylib [core] examples - Mouse wheel input * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index 093b6f386..af9a77a5a 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -2,6 +2,8 @@ * * raylib [core] example - Input multitouch * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.1, last time updated with raylib 2.5 * * Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_loading_thread.c b/examples/core/core_loading_thread.c index 8e09c99da..8d4302a16 100644 --- a/examples/core/core_loading_thread.c +++ b/examples/core/core_loading_thread.c @@ -2,6 +2,8 @@ * * raylib [core] example - loading thread * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires linking with pthreads library on MinGW, * it can be accomplished passing -static parameter to compiler * diff --git a/examples/core/core_random_values.c b/examples/core/core_random_values.c index 46516ea1c..cff33c69d 100644 --- a/examples/core/core_random_values.c +++ b/examples/core/core_random_values.c @@ -2,6 +2,8 @@ * * raylib [core] example - Generate random values * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 1.1 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c index 62ae080cb..d349feaa2 100644 --- a/examples/core/core_scissor_test.c +++ b/examples/core/core_scissor_test.c @@ -2,6 +2,8 @@ * * raylib [core] example - Scissor test * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.0 * * Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_smooth_pixelperfect.c b/examples/core/core_smooth_pixelperfect.c index d76557651..133f41700 100644 --- a/examples/core/core_smooth_pixelperfect.c +++ b/examples/core/core_smooth_pixelperfect.c @@ -2,6 +2,8 @@ * * raylib [core] example - Smooth Pixel-perfect camera * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.0 * * Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) and diff --git a/examples/core/core_storage_values.c b/examples/core/core_storage_values.c index 70386da6c..f0004bf9f 100644 --- a/examples/core/core_storage_values.c +++ b/examples/core/core_storage_values.c @@ -2,6 +2,8 @@ * * raylib [core] example - Storage save/load values * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c index 021698edb..bfea082e8 100644 --- a/examples/core/core_vr_simulator.c +++ b/examples/core/core_vr_simulator.c @@ -2,6 +2,8 @@ * * raylib [core] example - VR Simulator (Oculus Rift CV1 parameters) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_window_flags.c b/examples/core/core_window_flags.c index c9f858929..7e0ba8341 100644 --- a/examples/core/core_window_flags.c +++ b/examples/core/core_window_flags.c @@ -2,6 +2,8 @@ * * raylib [core] example - window flags * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_window_letterbox.c b/examples/core/core_window_letterbox.c index ded782431..293022eed 100644 --- a/examples/core/core_window_letterbox.c +++ b/examples/core/core_window_letterbox.c @@ -2,6 +2,8 @@ * * raylib [core] example - window scale letterbox (and virtual mouse) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_window_should_close.c b/examples/core/core_window_should_close.c index e28ef7dbd..f401bcfab 100644 --- a/examples/core/core_window_should_close.c +++ b/examples/core/core_window_should_close.c @@ -2,6 +2,8 @@ * * raylib [core] example - Window should close * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_world_screen.c b/examples/core/core_world_screen.c index 82fa31281..21c17b023 100644 --- a/examples/core/core_world_screen.c +++ b/examples/core/core_world_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - World to screen * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.4 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index 76998d1ec..b7fec2f47 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load 3d model with animations and play them * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index cfb49e55c..c7c6f0e84 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -2,6 +2,8 @@ * * raylib [models] example - Drawing billboards * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 4d98a776a..33f387fa3 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -2,6 +2,8 @@ * * raylib [models] example - Detect basic 3d collisions (box vs sphere vs box) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 2c6267ede..1e0cff91e 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -2,6 +2,8 @@ * * raylib [models] example - Cubicmap loading and drawing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_draw_cube_texture.c b/examples/models/models_draw_cube_texture.c index 87d83c8f3..d6655ce84 100644 --- a/examples/models/models_draw_cube_texture.c +++ b/examples/models/models_draw_cube_texture.c @@ -2,6 +2,8 @@ * * raylib [models] example - Draw textured cube * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index b1af7d47b..41520dfbc 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -2,6 +2,8 @@ * * raylib [models] example - first person maze * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_geometric_shapes.c b/examples/models/models_geometric_shapes.c index 7f66a69fe..75ef62888 100644 --- a/examples/models/models_geometric_shapes.c +++ b/examples/models/models_geometric_shapes.c @@ -2,6 +2,8 @@ * * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index d59e82814..e55228741 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -2,6 +2,8 @@ * * raylib [models] example - Heightmap loading and drawing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.8, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_loading.c b/examples/models/models_loading.c index d35db347c..01277b994 100644 --- a/examples/models/models_loading.c +++ b/examples/models/models_loading.c @@ -2,6 +2,8 @@ * * raylib [models] example - Models loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib supports multiple models file formats: * * - OBJ > Text file format. Must include vertex position-texcoords-normals information, diff --git a/examples/models/models_loading_gltf.c b/examples/models/models_loading_gltf.c index 8b8838c8d..867191843 100644 --- a/examples/models/models_loading_gltf.c +++ b/examples/models/models_loading_gltf.c @@ -2,6 +2,8 @@ * * raylib [models] example - loading gltf with animations * +* Example complexity rating: [★☆☆☆] 1/4 +* * LIMITATIONS: * - Only supports 1 armature per file, and skips loading it if there are multiple armatures * - Only supports linear interpolation (default method in Blender when checked diff --git a/examples/models/models_loading_m3d.c b/examples/models/models_loading_m3d.c index 6091d95f8..f79681432 100644 --- a/examples/models/models_loading_m3d.c +++ b/examples/models/models_loading_m3d.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load models M3D * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example contributed by bzt (@bztsrc) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_loading_vox.c b/examples/models/models_loading_vox.c index 1a2721a63..4796c9aa5 100644 --- a/examples/models/models_loading_vox.c +++ b/examples/models/models_loading_vox.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load models vox (MagicaVoxel) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 4.0, last time updated with raylib 4.0 * * Example contributed by Johann Nadalutti (@procfxgen) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index 03dc2b067..24816236e 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib example - procedural mesh generation +* raylib [models] example - procedural mesh generation +* +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 1.8, last time updated with raylib 4.0 * diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 15723e39d..5cdfe1584 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -2,6 +2,8 @@ * * raylib [models] example - Mesh picking in 3d mode, ground plane, triangle, mesh * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.7, last time updated with raylib 4.0 * * Example contributed by Joel Davis (@joeld42) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index b0f74413d..9889ac7f6 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -2,6 +2,8 @@ * * raylib [models] example - Show the difference between perspective and orthographic projection * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.0, last time updated with raylib 3.7 * * Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c index 7b35263ac..769a9da32 100644 --- a/examples/models/models_rlgl_solar_system.c +++ b/examples/models/models_rlgl_solar_system.c @@ -2,6 +2,8 @@ * * raylib [models] example - rlgl module usage with push/pop matrix transformations * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example uses [rlgl] module functionality (pseudo-OpenGL 1.1 style coding) * * Example originally created with raylib 2.5, last time updated with raylib 4.0 diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 4689acd77..b8b89f03b 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -2,6 +2,8 @@ * * raylib [models] example - Skybox loading and drawing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c index 521a4afd5..8a07c68cf 100644 --- a/examples/models/models_waving_cubes.c +++ b/examples/models/models_waving_cubes.c @@ -2,6 +2,8 @@ * * raylib [models] example - Waving cubes * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 5374c035e..679b011cc 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -2,6 +2,8 @@ * * raylib [models] example - Plane rotations (yaw, pitch, roll) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 4.0 * * Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c index 77fedfeb9..9eff43379 100644 --- a/examples/shaders/shaders_basic_lighting.c +++ b/examples/shaders/shaders_basic_lighting.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - basic lighting * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_custom_uniform.c b/examples/shaders/shaders_custom_uniform.c index 9d991bd1a..1c8419c91 100644 --- a/examples/shaders/shaders_custom_uniform.c +++ b/examples/shaders/shaders_custom_uniform.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Postprocessing with custom uniform variable * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_deferred_render.c b/examples/shaders/shaders_deferred_render.c index f246f6a5a..13600bc09 100644 --- a/examples/shaders/shaders_deferred_render.c +++ b/examples/shaders/shaders_deferred_render.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - deferred rendering * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 or OpenGL ES 3.0 * * Example originally created with raylib 4.5, last time updated with raylib 4.5 diff --git a/examples/shaders/shaders_eratosthenes.c b/examples/shaders/shaders_eratosthenes.c index 21b7ea8f9..0b8b08186 100644 --- a/examples/shaders/shaders_eratosthenes.c +++ b/examples/shaders/shaders_eratosthenes.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Sieve of Eratosthenes * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve. * * "Sift the twos and sift the threes, diff --git a/examples/shaders/shaders_fog.c b/examples/shaders/shaders_fog.c index ad514077d..eefce44fc 100644 --- a/examples/shaders/shaders_fog.c +++ b/examples/shaders/shaders_fog.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - fog * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_hot_reloading.c b/examples/shaders/shaders_hot_reloading.c index 2a9ea2d6d..f620a6247 100644 --- a/examples/shaders/shaders_hot_reloading.c +++ b/examples/shaders/shaders_hot_reloading.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Hot reloading * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330 * is currently supported. OpenGL ES 2.0 platforms are not supported at the moment. * diff --git a/examples/shaders/shaders_hybrid_render.c b/examples/shaders/shaders_hybrid_render.c index 5bf2e49a8..5f90f1724 100644 --- a/examples/shaders/shaders_hybrid_render.c +++ b/examples/shaders/shaders_hybrid_render.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Hybrid Rendering * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by Buğra Alptekin Sarı (@BugraAlptekinSari) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_julia_set.c b/examples/shaders/shaders_julia_set.c index 93a3436a8..3b30205f8 100644 --- a/examples/shaders/shaders_julia_set.c +++ b/examples/shaders/shaders_julia_set.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Julia sets * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_lightmap.c b/examples/shaders/shaders_lightmap.c index 91ed8bfd2..305399b98 100644 --- a/examples/shaders/shaders_lightmap.c +++ b/examples/shaders/shaders_lightmap.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - lightmap * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_mesh_instancing.c b/examples/shaders/shaders_mesh_instancing.c index 1e0bf0696..ca975beea 100644 --- a/examples/shaders/shaders_mesh_instancing.c +++ b/examples/shaders/shaders_mesh_instancing.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Mesh instancing * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.2 * * Example contributed by @seanpringle and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 9faa2d589..62a4dc003 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Model shader * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_multi_sample2d.c b/examples/shaders/shaders_multi_sample2d.c index ccdc6fa82..5e10cddce 100644 --- a/examples/shaders/shaders_multi_sample2d.c +++ b/examples/shaders/shaders_multi_sample2d.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Multiple sample2D with default batch system * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index 9ff86d83d..a2d01a11d 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -1,6 +1,8 @@ /******************************************************************************************* * * raylib [shaders] example - Color palette switch +* +* Example complexity rating: [★★★☆] 3/4 * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. diff --git a/examples/shaders/shaders_postprocessing.c b/examples/shaders/shaders_postprocessing.c index 54ffae931..1e5fe0d14 100644 --- a/examples/shaders/shaders_postprocessing.c +++ b/examples/shaders/shaders_postprocessing.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply a postprocessing shader to a scene * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_raymarching.c b/examples/shaders/shaders_raymarching.c index 812d683e6..0f21f6a56 100644 --- a/examples/shaders/shaders_raymarching.c +++ b/examples/shaders/shaders_raymarching.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Raymarching shapes generation * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330 * is currently supported. OpenGL ES 2.0 platforms are not supported at the moment. * diff --git a/examples/shaders/shaders_shapes_textures.c b/examples/shaders/shaders_shapes_textures.c index 65ccef659..95be102d5 100644 --- a/examples/shaders/shaders_shapes_textures.c +++ b/examples/shaders/shaders_shapes_textures.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply a shader to some shape or texture * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_simple_mask.c b/examples/shaders/shaders_simple_mask.c index 11e0ac2e7..02e6c606a 100644 --- a/examples/shaders/shaders_simple_mask.c +++ b/examples/shaders/shaders_simple_mask.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Simple shader mask * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_spotlight.c b/examples/shaders/shaders_spotlight.c index 2752a2db4..98a98e973 100644 --- a/examples/shaders/shaders_spotlight.c +++ b/examples/shaders/shaders_spotlight.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Simple shader mask * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c index ada44299d..d30b6e1f1 100644 --- a/examples/shaders/shaders_texture_drawing.c +++ b/examples/shaders/shaders_texture_drawing.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [textures] example - Texture drawing +* raylib [shaders] example - Texture drawing +* +* Example complexity rating: [★★☆☆] 2/4 * * NOTE: This example illustrates how to draw into a blank texture using a shader * diff --git a/examples/shaders/shaders_texture_outline.c b/examples/shaders/shaders_texture_outline.c index f90e41769..3c14bd0f2 100644 --- a/examples/shaders/shaders_texture_outline.c +++ b/examples/shaders/shaders_texture_outline.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply an shdrOutline to a texture * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_texture_tiling.c b/examples/shaders/shaders_texture_tiling.c index 0d07bdff9..ca32580b6 100644 --- a/examples/shaders/shaders_texture_tiling.c +++ b/examples/shaders/shaders_texture_tiling.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - texture tiling * +* Example complexity rating: [★★☆☆] 2/4 +* * Example demonstrates how to tile a texture on a 3D model using raylib. * * Example contributed by Luis Almeida (@luis605) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_texture_waves.c b/examples/shaders/shaders_texture_waves.c index 205fc636e..8d78b7593 100644 --- a/examples/shaders/shaders_texture_waves.c +++ b/examples/shaders/shaders_texture_waves.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Texture Waves * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_write_depth.c b/examples/shaders/shaders_write_depth.c index 531a7bfa6..c665a56d3 100644 --- a/examples/shaders/shaders_write_depth.c +++ b/examples/shaders/shaders_write_depth.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Depth buffer writing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by Buğra Alptekin Sarı (@BugraAlptekinSari) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_basic_shapes.c b/examples/shapes/shapes_basic_shapes.c index 9c0fff7d0..78297e37f 100644 --- a/examples/shapes/shapes_basic_shapes.c +++ b/examples/shapes/shapes_basic_shapes.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Draw basic shapes 2d (rectangle, circle, line...) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c index df0c37c1c..394e54886 100644 --- a/examples/shapes/shapes_bouncing_ball.c +++ b/examples/shapes/shapes_bouncing_ball.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - bouncing ball * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_collision_area.c b/examples/shapes/shapes_collision_area.c index c2e2c1e1d..ddb156831 100644 --- a/examples/shapes/shapes_collision_area.c +++ b/examples/shapes/shapes_collision_area.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - collision area * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_colors_palette.c b/examples/shapes/shapes_colors_palette.c index 60a6dd6a2..f94be8161 100644 --- a/examples/shapes/shapes_colors_palette.c +++ b/examples/shapes/shapes_colors_palette.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Colors palette * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.0, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index cb9ab859b..8be6b045f 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw circle sector (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index 58991884c..1dbfd5282 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw rectangle rounded (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index 8bccdf729..91c563dbe 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw ring (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_easings_ball_anim.c b/examples/shapes/shapes_easings_ball_anim.c index d54f24a1d..654ed8cd5 100644 --- a/examples/shapes/shapes_easings_ball_anim.c +++ b/examples/shapes/shapes_easings_ball_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings ball anim * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_easings_box_anim.c b/examples/shapes/shapes_easings_box_anim.c index c82beac05..8407dfc2f 100644 --- a/examples/shapes/shapes_easings_box_anim.c +++ b/examples/shapes/shapes_easings_box_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings box anim * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_easings_rectangle_array.c b/examples/shapes/shapes_easings_rectangle_array.c index ed13e93c1..e250007f8 100644 --- a/examples/shapes/shapes_easings_rectangle_array.c +++ b/examples/shapes/shapes_easings_rectangle_array.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings rectangle array * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy * the library to same directory as example or make sure it's available on include path. * diff --git a/examples/shapes/shapes_following_eyes.c b/examples/shapes/shapes_following_eyes.c index 7e428f2c3..97f5b2981 100644 --- a/examples/shapes/shapes_following_eyes.c +++ b/examples/shapes/shapes_following_eyes.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - following eyes * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_lines_bezier.c b/examples/shapes/shapes_lines_bezier.c index 1293e16e4..08559888d 100644 --- a/examples/shapes/shapes_lines_bezier.c +++ b/examples/shapes/shapes_lines_bezier.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Cubic-bezier lines * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.7, last time updated with raylib 1.7 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_logo_raylib.c b/examples/shapes/shapes_logo_raylib.c index f637df2c9..f7408bf78 100644 --- a/examples/shapes/shapes_logo_raylib.c +++ b/examples/shapes/shapes_logo_raylib.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Draw raylib logo using basic shapes * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_logo_raylib_anim.c b/examples/shapes/shapes_logo_raylib_anim.c index ace9c8d02..80fcbba1a 100644 --- a/examples/shapes/shapes_logo_raylib_anim.c +++ b/examples/shapes/shapes_logo_raylib_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - raylib logo animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_rectangle_scaling.c b/examples/shapes/shapes_rectangle_scaling.c index dcafab9da..416b02c0d 100644 --- a/examples/shapes/shapes_rectangle_scaling.c +++ b/examples/shapes/shapes_rectangle_scaling.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - rectangle scaling by mouse * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_splines_drawing.c b/examples/shapes/shapes_splines_drawing.c index 536b558e1..9b3a14926 100644 --- a/examples/shapes/shapes_splines_drawing.c +++ b/examples/shapes/shapes_splines_drawing.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - splines drawing * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_top_down_lights.c b/examples/shapes/shapes_top_down_lights.c index abe845f8c..39de6ccf7 100644 --- a/examples/shapes/shapes_top_down_lights.c +++ b/examples/shapes/shapes_top_down_lights.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - top down lights * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_codepoints_loading.c b/examples/text/text_codepoints_loading.c index 95a81dfc3..df3b76894 100644 --- a/examples/text/text_codepoints_loading.c +++ b/examples/text/text_codepoints_loading.c @@ -2,6 +2,8 @@ * * raylib [text] example - Codepoints loading * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c index 8d23b0450..8d93db439 100644 --- a/examples/text/text_draw_3d.c +++ b/examples/text/text_draw_3d.c @@ -2,6 +2,8 @@ * * raylib [text] example - Draw 3d * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set) * where the texture coodinates of each quad map to the texture coordinates of the glyphs * inside the font texture. diff --git a/examples/text/text_font_filters.c b/examples/text/text_font_filters.c index b12f26055..7893e01f2 100644 --- a/examples/text/text_font_filters.c +++ b/examples/text/text_font_filters.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font filters * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: After font loading, font texture atlas filter could be configured for a softer * display of the font when scaling it to different sizes, that way, it's not required * to generate multiple fonts at multiple sizes (as long as the scaling is not very different) diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c index 6b98a4e8a..17c06abac 100644 --- a/examples/text/text_font_loading.c +++ b/examples/text/text_font_loading.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib can load fonts from multiple input file formats: * * - TTF/OTF > Sprite font atlas is generated on loading, user can configure diff --git a/examples/text/text_font_sdf.c b/examples/text/text_font_sdf.c index 95245741e..d3b3098ad 100644 --- a/examples/text/text_font_sdf.c +++ b/examples/text/text_font_sdf.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font SDF loading * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_font_spritefont.c b/examples/text/text_font_spritefont.c index 1b2695c71..7655a0c2c 100644 --- a/examples/text/text_font_spritefont.c +++ b/examples/text/text_font_spritefont.c @@ -2,6 +2,8 @@ * * raylib [text] example - Sprite font loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Sprite fonts should be generated following this conventions: * * - Characters must be ordered starting with character 32 (Space) diff --git a/examples/text/text_format_text.c b/examples/text/text_format_text.c index 0f53f35dc..d9dc32d04 100644 --- a/examples/text/text_format_text.c +++ b/examples/text/text_format_text.c @@ -2,6 +2,8 @@ * * raylib [text] example - Text formatting * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 3.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c index c53057711..14bedf27a 100644 --- a/examples/text/text_input_box.c +++ b/examples/text/text_input_box.c @@ -2,6 +2,8 @@ * * raylib [text] example - Input Box * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.7, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_raylib_fonts.c b/examples/text/text_raylib_fonts.c index acd18d94c..45314c9a0 100644 --- a/examples/text/text_raylib_fonts.c +++ b/examples/text/text_raylib_fonts.c @@ -2,6 +2,8 @@ * * raylib [text] example - raylib fonts loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!) * To view details and credits for those fonts, check raylib license file * diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c index 173d3f93d..6da91a6a3 100644 --- a/examples/text/text_rectangle_bounds.c +++ b/examples/text/text_rectangle_bounds.c @@ -2,6 +2,8 @@ * * raylib [text] example - Rectangle bounds * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index 2b5245be9..ba37416fa 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -2,6 +2,8 @@ * * raylib [text] example - Unicode * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c index 8e2820fc9..0f91668ba 100644 --- a/examples/text/text_writing_anim.c +++ b/examples/text/text_writing_anim.c @@ -2,6 +2,8 @@ * * raylib [text] example - Text Writing Animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 1.4 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_background_scrolling.c b/examples/textures/textures_background_scrolling.c index 0df159cae..9dfa8d50a 100644 --- a/examples/textures/textures_background_scrolling.c +++ b/examples/textures/textures_background_scrolling.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Background scrolling * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.0, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_blend_modes.c b/examples/textures/textures_blend_modes.c index d97432cb2..4cb5b801c 100644 --- a/examples/textures/textures_blend_modes.c +++ b/examples/textures/textures_blend_modes.c @@ -2,6 +2,8 @@ * * raylib [textures] example - blend modes * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 3.5, last time updated with raylib 3.5 diff --git a/examples/textures/textures_bunnymark.c b/examples/textures/textures_bunnymark.c index f3ef694a2..18b9cda3b 100644 --- a/examples/textures/textures_bunnymark.c +++ b/examples/textures/textures_bunnymark.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Bunnymark * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.6, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_draw_tiled.c b/examples/textures/textures_draw_tiled.c index 699836555..c0d827feb 100644 --- a/examples/textures/textures_draw_tiled.c +++ b/examples/textures/textures_draw_tiled.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Draw part of the texture tiled * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.0, last time updated with raylib 4.2 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_fog_of_war.c b/examples/textures/textures_fog_of_war.c index 2f72c0d6d..fba8c2204 100644 --- a/examples/textures/textures_fog_of_war.c +++ b/examples/textures/textures_fog_of_war.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Fog of war * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_gif_player.c b/examples/textures/textures_gif_player.c index cf8492e0d..7eb4c5703 100644 --- a/examples/textures/textures_gif_player.c +++ b/examples/textures/textures_gif_player.c @@ -2,6 +2,8 @@ * * raylib [textures] example - gif playing * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_image_drawing.c b/examples/textures/textures_image_drawing.c index d0eee999d..4d73a2224 100644 --- a/examples/textures/textures_image_drawing.c +++ b/examples/textures/textures_image_drawing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image loading and drawing on it * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.4, last time updated with raylib 1.4 diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 47f9a9eb0..0a3610ab6 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Procedural images generation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 1.8 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_image_loading.c b/examples/textures/textures_image_loading.c index 95175e079..e26ccb645 100644 --- a/examples/textures/textures_image_loading.c +++ b/examples/textures/textures_image_loading.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image loading and texture creation * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 1.3 diff --git a/examples/textures/textures_image_processing.c b/examples/textures/textures_image_processing.c index 269273546..7a61cd024 100644 --- a/examples/textures/textures_image_processing.c +++ b/examples/textures/textures_image_processing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image processing * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.4, last time updated with raylib 3.5 diff --git a/examples/textures/textures_image_text.c b/examples/textures/textures_image_text.c index 856b64ed0..4d5c281f7 100644 --- a/examples/textures/textures_image_text.c +++ b/examples/textures/textures_image_text.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [texture] example - Image text drawing using TTF generated font +* raylib [textures] example - Image text drawing using TTF generated font +* +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 1.8, last time updated with raylib 4.0 * diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c index 35baa1223..4456fef02 100644 --- a/examples/textures/textures_logo_raylib.c +++ b/examples/textures/textures_logo_raylib.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Texture loading and drawing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_mouse_painting.c b/examples/textures/textures_mouse_painting.c index 27bbc74e9..324f88fa1 100644 --- a/examples/textures/textures_mouse_painting.c +++ b/examples/textures/textures_mouse_painting.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Mouse painting * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.0, last time updated with raylib 3.0 * * Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_npatch_drawing.c b/examples/textures/textures_npatch_drawing.c index 5fb39996b..5e23a0fb6 100644 --- a/examples/textures/textures_npatch_drawing.c +++ b/examples/textures/textures_npatch_drawing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - N-patch drawing * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 2.0, last time updated with raylib 2.5 diff --git a/examples/textures/textures_particles_blending.c b/examples/textures/textures_particles_blending.c index 113b2b068..6781668e9 100644 --- a/examples/textures/textures_particles_blending.c +++ b/examples/textures/textures_particles_blending.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib example - particles blending +* raylib [textures] example - particles blending +* +* Example complexity rating: [★☆☆☆] 1/4 * * Example originally created with raylib 1.7, last time updated with raylib 3.5 * diff --git a/examples/textures/textures_polygon.c b/examples/textures/textures_polygon.c index 2491e1bc2..82ccd1cf1 100644 --- a/examples/textures/textures_polygon.c +++ b/examples/textures/textures_polygon.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [shapes] example - Draw Textured Polygon +* raylib [textures] example - Draw Textured Polygon +* +* Example complexity rating: [★☆☆☆] 1/4 * * Example originally created with raylib 3.7, last time updated with raylib 3.7 * diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index 6fb41b143..51a50069f 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Load textures from raw data * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 3.5 diff --git a/examples/textures/textures_sprite_anim.c b/examples/textures/textures_sprite_anim.c index deb68216a..8b0378958 100644 --- a/examples/textures/textures_sprite_anim.c +++ b/examples/textures/textures_sprite_anim.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Sprite animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_sprite_button.c b/examples/textures/textures_sprite_button.c index 5d0153b57..0f5a6940d 100644 --- a/examples/textures/textures_sprite_button.c +++ b/examples/textures/textures_sprite_button.c @@ -2,6 +2,8 @@ * * raylib [textures] example - sprite button * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c index a65426cb6..09839f8fa 100644 --- a/examples/textures/textures_sprite_explosion.c +++ b/examples/textures/textures_sprite_explosion.c @@ -2,6 +2,8 @@ * * raylib [textures] example - sprite explosion * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_srcrec_dstrec.c b/examples/textures/textures_srcrec_dstrec.c index 035e30371..a3bd29af2 100644 --- a/examples/textures/textures_srcrec_dstrec.c +++ b/examples/textures/textures_srcrec_dstrec.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Texture source and destination rectangles * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_textured_curve.c b/examples/textures/textures_textured_curve.c index 6e4c53cff..86df6957a 100644 --- a/examples/textures/textures_textured_curve.c +++ b/examples/textures/textures_textured_curve.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Draw a texture along a segmented curve * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example contributed by Jeffery Myers and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c index e1d88c4cd..39907103e 100644 --- a/examples/textures/textures_to_image.c +++ b/examples/textures/textures_to_image.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Retrieve image data from texture: LoadImageFromTexture() * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 4.0 From 0275d13aa84f8a464b5246abbef9205b94c73c5e Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Jan 2025 11:32:23 +0100 Subject: [PATCH 09/39] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 29f0f61ff..4b242f171 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ raylib is present in several networks and raylib community is growing everyday. - Webpage: [https://www.raylib.com](https://www.raylib.com) - Discord: [https://discord.gg/raylib](https://discord.gg/raylib) - Twitter: [https://www.twitter.com/raysan5](https://www.twitter.com/raysan5) + - BlueSky: [https://bsky.app/profile/raysan5](https://bsky.app/profile/raysan5.bsky.social) - Twitch: [https://www.twitch.tv/raysan5](https://www.twitch.tv/raysan5) - Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) - Patreon: [https://www.patreon.com/raylib](https://www.patreon.com/raylib) From 8575150747ca3fccc07c431483b9558ef9cf8296 Mon Sep 17 00:00:00 2001 From: Auz Date: Sat, 18 Jan 2025 11:26:47 -0700 Subject: [PATCH 10/39] Bump BINDINGS.md version number for Raylib.nelua (#4698) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 860151b21..95aecd085 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -48,7 +48,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT | | [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT | | [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** | -| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.0** | [nelua](https://nelua.io) | Zlib | +| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.5** | [nelua](https://nelua.io) | Zlib | | [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib | | [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) | MIT | | [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib | From 74256943a41166b7f9b811727eb9d9fb03d83e25 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 Jan 2025 19:39:50 +0100 Subject: [PATCH 11/39] REVIEWED: `MAX_GAMEPAD_NAME_LENGTH` #4695 --- src/platforms/rcore_desktop_glfw.c | 6 +++--- src/platforms/rcore_desktop_sdl.c | 10 +++++----- src/rcore.c | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index dba821ddd..9159b302a 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1652,7 +1652,7 @@ int InitPlatform(void) // Retrieve gamepad names for (int i = 0; i < MAX_GAMEPADS; i++) { - if (glfwJoystickPresent(i)) strcpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i)); + if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1); } //---------------------------------------------------------------------------- @@ -1915,11 +1915,11 @@ static void JoystickCallback(int jid, int event) { if (event == GLFW_CONNECTED) { - strcpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid)); + strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1); } else if (event == GLFW_DISCONNECTED) { - memset(CORE.Input.Gamepad.name[jid], 0, 64); + memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); } } diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 4b3327ee1..33c182a70 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1670,8 +1670,8 @@ void PollInputEvents(void) CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid])); CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63); - CORE.Input.Gamepad.name[jid][63] = '\0'; + strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1); + CORE.Input.Gamepad.name[jid][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0'; } else { @@ -1688,7 +1688,7 @@ void PollInputEvents(void) SDL_GameControllerClose(platform.gamepad[jid]); platform.gamepad[jid] = SDL_GameControllerOpen(0); CORE.Input.Gamepad.ready[jid] = false; - memset(CORE.Input.Gamepad.name[jid], 0, 64); + memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); } } break; case SDL_CONTROLLERBUTTONDOWN: @@ -1977,8 +1977,8 @@ int InitPlatform(void) CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i])); CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63); - CORE.Input.Gamepad.name[i][63] = '\0'; + strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1); + CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0'; } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); } diff --git a/src/rcore.c b/src/rcore.c index a90a60387..59b1b31c8 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -233,6 +233,9 @@ __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod) #ifndef MAX_GAMEPADS #define MAX_GAMEPADS 4 // Maximum number of gamepads supported #endif +#ifndef MAX_GAMEPAD_NAME_LENGTH + #define MAX_GAMEPAD_NAME_LENGTH 128 // Maximum number of characters of gamepad name (byte size) +#endif #ifndef MAX_GAMEPAD_AXIS #define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad) #endif @@ -352,7 +355,7 @@ typedef struct CoreData { int lastButtonPressed; // Register last gamepad button pressed int axisCount[MAX_GAMEPADS]; // 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 name[MAX_GAMEPADS][MAX_GAMEPAD_NAME_LENGTH]; // 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 From 945f181f1d3605df83309e10f43811e50ddc3917 Mon Sep 17 00:00:00 2001 From: Anstro Pleuton <121956207+anstropleuton@users.noreply.github.com> Date: Sat, 18 Jan 2025 10:41:56 -0800 Subject: [PATCH 12/39] [examples] Update examples to be consistent (#4699) * Update examples inconsistencies * Happy new years, examples! * Missed one inconsistency * Update final few examples inconsistencies --------- Co-authored-by: Anstro Pleuton --- CHANGELOG | 2 +- examples/README.md | 2 +- examples/audio/audio_mixed_processor.c | 2 +- examples/audio/audio_module_playing.c | 2 +- examples/audio/audio_music_stream.c | 2 +- examples/audio/audio_raw_stream.c | 2 +- examples/audio/audio_sound_loading.c | 2 +- examples/audio/audio_sound_multi.c | 6 ++++-- examples/audio/audio_stream_effects.c | 2 +- examples/core/core_2d_camera.c | 2 +- examples/core/core_2d_camera_mouse_zoom.c | 4 +++- examples/core/core_2d_camera_platformer.c | 2 +- examples/core/core_2d_camera_split_screen.c | 2 +- examples/core/core_3d_camera_first_person.c | 2 +- examples/core/core_3d_camera_free.c | 2 +- examples/core/core_3d_camera_mode.c | 2 +- examples/core/core_3d_camera_split_screen.c | 2 +- examples/core/core_3d_picking.c | 2 +- examples/core/core_automation_events.c | 2 +- examples/core/core_basic_screen_manager.c | 2 +- examples/core/core_basic_window.c | 2 +- examples/core/core_basic_window_web.c | 2 +- examples/core/core_custom_frame_control.c | 2 +- examples/core/core_custom_logging.c | 2 +- examples/core/core_drop_files.c | 2 +- examples/core/core_input_gamepad.c | 2 +- examples/core/core_input_gestures.c | 2 +- examples/core/core_input_gestures_web.c | 2 +- examples/core/core_input_keys.c | 2 +- examples/core/core_input_mouse_wheel.c | 2 +- examples/core/core_input_multitouch.c | 2 +- examples/core/core_input_virtual_controls.c | 2 +- examples/core/core_loading_thread.c | 2 +- examples/core/core_random_sequence.c | 2 +- examples/core/core_random_values.c | 2 +- examples/core/core_scissor_test.c | 2 +- examples/core/core_smooth_pixelperfect.c | 2 +- examples/core/core_storage_values.c | 2 +- examples/core/core_vr_simulator.c | 2 +- examples/core/core_window_flags.c | 2 +- examples/core/core_window_letterbox.c | 2 +- examples/core/core_window_should_close.c | 2 +- examples/core/core_world_screen.c | 2 +- examples/examples_template.c | 4 ++-- examples/models/models_animation.c | 2 +- examples/models/models_billboard.c | 2 +- examples/models/models_bone_socket.c | 2 +- examples/models/models_box_collisions.c | 2 +- examples/models/models_cubicmap.c | 2 +- examples/models/models_draw_cube_texture.c | 2 +- examples/models/models_first_person_maze.c | 2 +- examples/models/models_geometric_shapes.c | 2 +- examples/models/models_gpu_skinning.c | 2 +- examples/models/models_heightmap.c | 2 +- examples/models/models_loading.c | 2 +- examples/models/models_loading_gltf.c | 2 +- examples/models/models_loading_m3d.c | 2 +- examples/models/models_loading_vox.c | 2 +- examples/models/models_mesh_generation.c | 2 +- examples/models/models_mesh_picking.c | 2 +- examples/models/models_orthographic_projection.c | 2 +- examples/models/models_point_rendering.c | 2 +- examples/models/models_rlgl_solar_system.c | 2 +- examples/models/models_skybox.c | 2 +- examples/models/models_tesseract_view.c | 4 +++- examples/models/models_waving_cubes.c | 2 +- examples/models/models_yaw_pitch_roll.c | 2 +- examples/others/easings_testbed.c | 2 +- examples/others/embedded_files_loading.c | 2 +- examples/others/raylib_opengl_interop.c | 2 +- examples/others/raymath_vector_angle.c | 2 +- examples/others/rlgl_compute_shader.c | 2 +- examples/others/rlgl_standalone.c | 4 +++- examples/shaders/shaders_basic_lighting.c | 2 +- examples/shaders/shaders_basic_pbr.c | 2 +- examples/shaders/shaders_custom_uniform.c | 2 +- examples/shaders/shaders_deferred_render.c | 2 +- examples/shaders/shaders_eratosthenes.c | 4 ++-- examples/shaders/shaders_fog.c | 2 +- examples/shaders/shaders_hot_reloading.c | 2 +- examples/shaders/shaders_hybrid_render.c | 2 +- examples/shaders/shaders_julia_set.c | 2 +- examples/shaders/shaders_lightmap.c | 4 +++- examples/shaders/shaders_mesh_instancing.c | 4 ++-- examples/shaders/shaders_model_shader.c | 2 +- examples/shaders/shaders_multi_sample2d.c | 2 +- examples/shaders/shaders_palette_switch.c | 6 +++--- examples/shaders/shaders_postprocessing.c | 2 +- examples/shaders/shaders_raymarching.c | 2 +- examples/shaders/shaders_shadowmap.c | 4 +++- examples/shaders/shaders_shapes_textures.c | 2 +- examples/shaders/shaders_simple_mask.c | 2 +- examples/shaders/shaders_spotlight.c | 2 +- examples/shaders/shaders_texture_drawing.c | 4 ++-- examples/shaders/shaders_texture_outline.c | 2 +- examples/shaders/shaders_texture_tiling.c | 4 +++- examples/shaders/shaders_texture_waves.c | 2 +- examples/shaders/shaders_vertex_displacement.c | 4 ++-- examples/shaders/shaders_write_depth.c | 2 +- examples/shapes/shapes_basic_shapes.c | 2 +- examples/shapes/shapes_bouncing_ball.c | 2 +- examples/shapes/shapes_collision_area.c | 2 +- examples/shapes/shapes_colors_palette.c | 2 +- examples/shapes/shapes_draw_circle_sector.c | 2 +- examples/shapes/shapes_draw_rectangle_rounded.c | 2 +- examples/shapes/shapes_draw_ring.c | 2 +- examples/shapes/shapes_easings_ball_anim.c | 2 +- examples/shapes/shapes_easings_box_anim.c | 2 +- examples/shapes/shapes_easings_rectangle_array.c | 2 +- examples/shapes/shapes_following_eyes.c | 2 +- examples/shapes/shapes_lines_bezier.c | 2 +- examples/shapes/shapes_logo_raylib.c | 2 +- examples/shapes/shapes_logo_raylib_anim.c | 2 +- examples/shapes/shapes_rectangle_advanced.c | 6 +++++- examples/shapes/shapes_rectangle_scaling.c | 2 +- examples/shapes/shapes_splines_drawing.c | 2 +- examples/shapes/shapes_top_down_lights.c | 4 ++-- examples/text/text_codepoints_loading.c | 2 +- examples/text/text_draw_3d.c | 2 +- examples/text/text_font_filters.c | 2 +- examples/text/text_font_loading.c | 2 +- examples/text/text_font_sdf.c | 2 +- examples/text/text_font_spritefont.c | 2 +- examples/text/text_format_text.c | 2 +- examples/text/text_input_box.c | 2 +- examples/text/text_raylib_fonts.c | 2 +- examples/text/text_rectangle_bounds.c | 2 +- examples/text/text_unicode.c | 2 +- examples/text/text_writing_anim.c | 2 +- examples/textures/textures_background_scrolling.c | 2 +- examples/textures/textures_blend_modes.c | 2 +- examples/textures/textures_bunnymark.c | 2 +- examples/textures/textures_draw_tiled.c | 2 +- examples/textures/textures_fog_of_war.c | 2 +- examples/textures/textures_gif_player.c | 2 +- examples/textures/textures_image_channel.c | 4 ++-- examples/textures/textures_image_drawing.c | 2 +- examples/textures/textures_image_generation.c | 4 +++- examples/textures/textures_image_kernel.c | 4 +++- examples/textures/textures_image_loading.c | 2 +- examples/textures/textures_image_processing.c | 2 +- examples/textures/textures_image_rotate.c | 2 +- examples/textures/textures_image_text.c | 2 +- examples/textures/textures_logo_raylib.c | 2 +- examples/textures/textures_mouse_painting.c | 2 +- examples/textures/textures_npatch_drawing.c | 2 +- examples/textures/textures_particles_blending.c | 2 +- examples/textures/textures_polygon.c | 2 +- examples/textures/textures_raw_data.c | 2 +- examples/textures/textures_sprite_anim.c | 2 +- examples/textures/textures_sprite_button.c | 2 +- examples/textures/textures_sprite_explosion.c | 2 +- examples/textures/textures_srcrec_dstrec.c | 2 +- examples/textures/textures_textured_curve.c | 4 ++-- examples/textures/textures_to_image.c | 2 +- 155 files changed, 188 insertions(+), 166 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 61e12a3d4..f792bca4d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1671,7 +1671,7 @@ Detailed changes: [examples] ADDED: models_waving_cubes, by @codecat [examples] ADDED: models_solar_system, by @aldrinmartoq [examples] ADDED: shaders_fog, by @chriscamacho -[examples] ADDED: shaders_texture_waves, by @Anata +[examples] ADDED: shaders_texture_waves, by @anatagawa [examples] ADDED: shaders_basic_lighting, by @chriscamacho [examples] ADDED: shaders_simple_mask, by @chriscamacho [examples] ADDED: audio_multichannel_sound, by @chriscamacho diff --git a/examples/README.md b/examples/README.md index d25ad10cc..1be82dbca 100644 --- a/examples/README.md +++ b/examples/README.md @@ -80,7 +80,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | 47 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | shapes_draw_circle_sector | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 48 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | shapes_draw_rectangle_rounded | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 49 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | -| 50 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐️⭐️⭐️⭐️⭐️| **5.0** | **5.0** | [ExCyber](https://github.com/evertonse) | +| 50 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐️⭐️⭐️⭐️ | **5.0** | **5.0** | [ExCyber](https://github.com/evertonse) | ### category: textures diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c index 16c83f36d..fc9785bc8 100644 --- a/examples/audio/audio_mixed_processor.c +++ b/examples/audio/audio_mixed_processor.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 hkc (@hatkidchan) +* Copyright (c) 2023-2025 hkc (@hatkidchan) * ********************************************************************************************/ #include "raylib.h" diff --git a/examples/audio/audio_module_playing.c b/examples/audio/audio_module_playing.c index 3b77ed3e6..0d6c48981 100644 --- a/examples/audio/audio_module_playing.c +++ b/examples/audio/audio_module_playing.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/audio/audio_music_stream.c b/examples/audio/audio_music_stream.c index 99d270326..609b12333 100644 --- a/examples/audio/audio_music_stream.c +++ b/examples/audio/audio_music_stream.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index 9b8338dfc..fb36830ce 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) and James Hofmann (@triplefox) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) and James Hofmann (@triplefox) * ********************************************************************************************/ diff --git a/examples/audio/audio_sound_loading.c b/examples/audio/audio_sound_loading.c index b96e613de..45028839b 100644 --- a/examples/audio/audio_sound_loading.c +++ b/examples/audio/audio_sound_loading.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/audio/audio_sound_multi.c b/examples/audio/audio_sound_multi.c index 8d823b8eb..243ca7bd8 100644 --- a/examples/audio/audio_sound_multi.c +++ b/examples/audio/audio_sound_multi.c @@ -4,12 +4,14 @@ * * Example complexity rating: [★★☆☆] 2/4 * -* Example originally created with raylib 4.6 +* Example originally created with raylib 4.6, last time updated with raylib 4.6 +* +* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Jeffery Myers (@JeffM2501) +* Copyright (c) 2023-2025 Jeffery Myers (@JeffM2501) * ********************************************************************************************/ diff --git a/examples/audio/audio_stream_effects.c b/examples/audio/audio_stream_effects.c index ed5bdb105..4a34d3030 100644 --- a/examples/audio/audio_stream_effects.c +++ b/examples/audio/audio_stream_effects.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2022-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_2d_camera.c b/examples/core/core_2d_camera.c index 6b3ef57d2..44d3c6961 100644 --- a/examples/core/core_2d_camera.c +++ b/examples/core/core_2d_camera.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_2d_camera_mouse_zoom.c b/examples/core/core_2d_camera_mouse_zoom.c index 3b4fb5835..cfdaf15aa 100644 --- a/examples/core/core_2d_camera_mouse_zoom.c +++ b/examples/core/core_2d_camera_mouse_zoom.c @@ -6,10 +6,12 @@ * * Example originally created with raylib 4.2, last time updated with raylib 4.2 * +* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) +* * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Jeffery Myers (@JeffM2501) +* Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501) * ********************************************************************************************/ diff --git a/examples/core/core_2d_camera_platformer.c b/examples/core/core_2d_camera_platformer.c index 2fcf77b6e..1ccb35167 100644 --- a/examples/core/core_2d_camera_platformer.c +++ b/examples/core/core_2d_camera_platformer.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 arvyy (@arvyy) +* Copyright (c) 2019-2025 arvyy (@arvyy) * ********************************************************************************************/ diff --git a/examples/core/core_2d_camera_split_screen.c b/examples/core/core_2d_camera_split_screen.c index a5c645797..900db450e 100644 --- a/examples/core/core_2d_camera_split_screen.c +++ b/examples/core/core_2d_camera_split_screen.c @@ -14,7 +14,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Gabriel dos Santos Sanches (@gabrielssanches) +* Copyright (c) 2023-2025 Gabriel dos Santos Sanches (@gabrielssanches) * ********************************************************************************************/ diff --git a/examples/core/core_3d_camera_first_person.c b/examples/core/core_3d_camera_first_person.c index 809cb3962..c26fe827c 100644 --- a/examples/core/core_3d_camera_first_person.c +++ b/examples/core/core_3d_camera_first_person.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_3d_camera_free.c b/examples/core/core_3d_camera_free.c index 349a458cf..b490575db 100644 --- a/examples/core/core_3d_camera_free.c +++ b/examples/core/core_3d_camera_free.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_3d_camera_mode.c b/examples/core/core_3d_camera_mode.c index 90e512965..372fd5923 100644 --- a/examples/core/core_3d_camera_mode.c +++ b/examples/core/core_3d_camera_mode.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_3d_camera_split_screen.c b/examples/core/core_3d_camera_split_screen.c index 8b457bfab..f825a52f9 100644 --- a/examples/core/core_3d_camera_split_screen.c +++ b/examples/core/core_3d_camera_split_screen.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Jeffery Myers (@JeffM2501) +* Copyright (c) 2021-2025 Jeffery Myers (@JeffM2501) * ********************************************************************************************/ diff --git a/examples/core/core_3d_picking.c b/examples/core/core_3d_picking.c index 85d8482ef..8a6fbd156 100644 --- a/examples/core/core_3d_picking.c +++ b/examples/core/core_3d_picking.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_automation_events.c b/examples/core/core_automation_events.c index 2a0d5503f..fab363d58 100644 --- a/examples/core/core_automation_events.c +++ b/examples/core/core_automation_events.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Ramon Santamaria (@raysan5) +* Copyright (c) 2023-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_basic_screen_manager.c b/examples/core/core_basic_screen_manager.c index 964c922e4..67de31159 100644 --- a/examples/core/core_basic_screen_manager.c +++ b/examples/core/core_basic_screen_manager.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_basic_window.c b/examples/core/core_basic_window.c index 976227750..b3f20367a 100644 --- a/examples/core/core_basic_window.c +++ b/examples/core/core_basic_window.c @@ -22,7 +22,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_basic_window_web.c b/examples/core/core_basic_window_web.c index 8726908cb..251544795 100644 --- a/examples/core/core_basic_window_web.c +++ b/examples/core/core_basic_window_web.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_custom_frame_control.c b/examples/core/core_custom_frame_control.c index 0f1cd2391..0d149ce9d 100644 --- a/examples/core/core_custom_frame_control.c +++ b/examples/core/core_custom_frame_control.c @@ -24,7 +24,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_custom_logging.c b/examples/core/core_custom_logging.c index 7636585be..d27c9fd6b 100644 --- a/examples/core/core_custom_logging.c +++ b/examples/core/core_custom_logging.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_drop_files.c b/examples/core/core_drop_files.c index addf7ec63..4aafbb8c9 100644 --- a/examples/core/core_drop_files.c +++ b/examples/core/core_drop_files.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 2e6e79d7f..6df29f8c8 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -15,7 +15,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_gestures.c b/examples/core/core_input_gestures.c index 5c2fc9482..b491da393 100644 --- a/examples/core/core_input_gestures.c +++ b/examples/core/core_input_gestures.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_gestures_web.c b/examples/core/core_input_gestures_web.c index e1492244c..b81aa07ab 100644 --- a/examples/core/core_input_gestures_web.c +++ b/examples/core/core_input_gestures_web.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 ubkp (@ubkp) +* Copyright (c) 2023-2025 ubkp (@ubkp) * ********************************************************************************************/ diff --git a/examples/core/core_input_keys.c b/examples/core/core_input_keys.c index a07739b22..670df1ef4 100644 --- a/examples/core/core_input_keys.c +++ b/examples/core/core_input_keys.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_mouse_wheel.c b/examples/core/core_input_mouse_wheel.c index 2583ebbb5..242eeafa6 100644 --- a/examples/core/core_input_mouse_wheel.c +++ b/examples/core/core_input_mouse_wheel.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index af9a77a5a..55015235c 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Berni (@Berni8k) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Berni (@Berni8k) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_input_virtual_controls.c b/examples/core/core_input_virtual_controls.c index 799c927c0..282c3b07d 100644 --- a/examples/core/core_input_virtual_controls.c +++ b/examples/core/core_input_virtual_controls.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2024-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_loading_thread.c b/examples/core/core_loading_thread.c index 8d4302a16..cd3d5a744 100644 --- a/examples/core/core_loading_thread.c +++ b/examples/core/core_loading_thread.c @@ -11,7 +11,7 @@ * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_random_sequence.c b/examples/core/core_random_sequence.c index 2cb067db4..4d245fbcc 100644 --- a/examples/core/core_random_sequence.c +++ b/examples/core/core_random_sequence.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Dalton Overmyer (@REDl3east) +* Copyright (c) 2023-2025 Dalton Overmyer (@REDl3east) * ********************************************************************************************/ diff --git a/examples/core/core_random_values.c b/examples/core/core_random_values.c index cff33c69d..4abc87694 100644 --- a/examples/core/core_random_values.c +++ b/examples/core/core_random_values.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c index d349feaa2..49e90c794 100644 --- a/examples/core/core_scissor_test.c +++ b/examples/core/core_scissor_test.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Dill (@MysteriousSpace) +* Copyright (c) 2019-2025 Chris Dill (@MysteriousSpace) * ********************************************************************************************/ diff --git a/examples/core/core_smooth_pixelperfect.c b/examples/core/core_smooth_pixelperfect.c index 133f41700..964bacdb3 100644 --- a/examples/core/core_smooth_pixelperfect.c +++ b/examples/core/core_smooth_pixelperfect.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_storage_values.c b/examples/core/core_storage_values.c index f0004bf9f..747b94d5b 100644 --- a/examples/core/core_storage_values.c +++ b/examples/core/core_storage_values.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c index bfea082e8..a793e62f4 100644 --- a/examples/core/core_vr_simulator.c +++ b/examples/core/core_vr_simulator.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_window_flags.c b/examples/core/core_window_flags.c index 7e0ba8341..ec4f6aac6 100644 --- a/examples/core/core_window_flags.c +++ b/examples/core/core_window_flags.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_window_letterbox.c b/examples/core/core_window_letterbox.c index 293022eed..b3622c8b9 100644 --- a/examples/core/core_window_letterbox.c +++ b/examples/core/core_window_letterbox.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Anata (@anatagawa) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Anata (@anatagawa) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_window_should_close.c b/examples/core/core_window_should_close.c index f401bcfab..56561795d 100644 --- a/examples/core/core_window_should_close.c +++ b/examples/core/core_window_should_close.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_world_screen.c b/examples/core/core_world_screen.c index 21c17b023..f302c3b27 100644 --- a/examples/core/core_world_screen.c +++ b/examples/core/core_world_screen.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/examples_template.c b/examples/examples_template.c index 5cf0b98d8..0a44117b4 100644 --- a/examples/examples_template.c +++ b/examples/examples_template.c @@ -58,14 +58,14 @@ * * raylib [core] example - Basic window * -* Example originally created with raylib 4.5, last time updated with raylib 4.5 +* Example originally created with raylib 5.5, last time updated with raylib 5.5 * * Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 (@) +* Copyright (c) - (@) * ********************************************************************************************/ diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index b7fec2f47..b334e17ea 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Culacant (@culacant) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Culacant (@culacant) and Ramon Santamaria (@raysan5) * ******************************************************************************************** * diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index c7c6f0e84..1d49ab89e 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_bone_socket.c b/examples/models/models_bone_socket.c index 66f952e89..ffcf048d5 100644 --- a/examples/models/models_bone_socket.c +++ b/examples/models/models_bone_socket.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024 iP (@ipzaur) +* Copyright (c) 2024-2025 iP (@ipzaur) * ********************************************************************************************/ diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 33f387fa3..00e7e541c 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 1e0cff91e..980215b2e 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_draw_cube_texture.c b/examples/models/models_draw_cube_texture.c index d6655ce84..172a50394 100644 --- a/examples/models/models_draw_cube_texture.c +++ b/examples/models/models_draw_cube_texture.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2022-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index 41520dfbc..43020974f 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_geometric_shapes.c b/examples/models/models_geometric_shapes.c index 75ef62888..8cce4fcb0 100644 --- a/examples/models/models_geometric_shapes.c +++ b/examples/models/models_geometric_shapes.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index 98bf09922..b92d1251d 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024 Daniel Holden (@orangeduck) +* Copyright (c) 2024-2025 Daniel Holden (@orangeduck) * * Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS * diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index e55228741..e24c01c9a 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_loading.c b/examples/models/models_loading.c index 01277b994..2a674eeaa 100644 --- a/examples/models/models_loading.c +++ b/examples/models/models_loading.c @@ -22,7 +22,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_loading_gltf.c b/examples/models/models_loading_gltf.c index 867191843..6309af84c 100644 --- a/examples/models/models_loading_gltf.c +++ b/examples/models/models_loading_gltf.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_loading_m3d.c b/examples/models/models_loading_m3d.c index f79681432..38dfbd51e 100644 --- a/examples/models/models_loading_m3d.c +++ b/examples/models/models_loading_m3d.c @@ -15,7 +15,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 bzt (@bztsrc) +* Copyright (c) 2022-2025 bzt (@bztsrc) * ********************************************************************************************/ diff --git a/examples/models/models_loading_vox.c b/examples/models/models_loading_vox.c index 4796c9aa5..75b975f94 100644 --- a/examples/models/models_loading_vox.c +++ b/examples/models/models_loading_vox.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Johann Nadalutti (@procfxgen) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Johann Nadalutti (@procfxgen) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index 24816236e..bc92873c2 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 5cdfe1584..f6fffd907 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Joel Davis (@joeld42) and Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Joel Davis (@joeld42) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index 9889ac7f6..8392f7a7d 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Max Danielsson (@autious) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Max Danielsson (@autious) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index f4f095c1d..c74b18a46 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024 Reese Gallagher (@satchelfrost) +* Copyright (c) 2024-2025 Reese Gallagher (@satchelfrost) * ********************************************************************************************/ diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c index 769a9da32..81f3e0f75 100644 --- a/examples/models/models_rlgl_solar_system.c +++ b/examples/models/models_rlgl_solar_system.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index b8b89f03b..e816b27e1 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_tesseract_view.c b/examples/models/models_tesseract_view.c index 495e9af9c..a166dcc9c 100644 --- a/examples/models/models_tesseract_view.c +++ b/examples/models/models_tesseract_view.c @@ -6,10 +6,12 @@ * * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * +* Example contributed by Timothy van der Valk (@arceryz) and reviewed by Ramon Santamaria (@raysan5) +* * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024-2025 raylib contributor (?) & Ramon Santamaria (@raysan5) +* Copyright (c) 2024-2025 Timothy van der Valk (@arceryz) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c index 8a07c68cf..6608eba48 100644 --- a/examples/models/models_waving_cubes.c +++ b/examples/models/models_waving_cubes.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Codecat (@codecat) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Codecat (@codecat) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 679b011cc..2c674824e 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Berni (@Berni8k) and Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Berni (@Berni8k) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/others/easings_testbed.c b/examples/others/easings_testbed.c index 1f31f5bb9..5ae33f12f 100644 --- a/examples/others/easings_testbed.c +++ b/examples/others/easings_testbed.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Juan Miguel López (@flashback-fx ) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Juan Miguel López (@flashback-fx) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/others/embedded_files_loading.c b/examples/others/embedded_files_loading.c index e46fe102f..efe5c1af5 100644 --- a/examples/others/embedded_files_loading.c +++ b/examples/others/embedded_files_loading.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Kristian Holmgren (@defutura) and Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Kristian Holmgren (@defutura) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/others/raylib_opengl_interop.c b/examples/others/raylib_opengl_interop.c index b0b7d6ff3..696ec85d7 100644 --- a/examples/others/raylib_opengl_interop.c +++ b/examples/others/raylib_opengl_interop.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Stephan Soller (@arkanis) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Stephan Soller (@arkanis) and Ramon Santamaria (@raysan5) * ******************************************************************************************** * diff --git a/examples/others/raymath_vector_angle.c b/examples/others/raymath_vector_angle.c index 5a69345b4..3cfdfc6d2 100644 --- a/examples/others/raymath_vector_angle.c +++ b/examples/others/raymath_vector_angle.c @@ -7,7 +7,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Ramon Santamaria (@raysan5) +* Copyright (c) 2023-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/others/rlgl_compute_shader.c b/examples/others/rlgl_compute_shader.c index e8a654d2a..0e39281e7 100644 --- a/examples/others/rlgl_compute_shader.c +++ b/examples/others/rlgl_compute_shader.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Teddy Astie (@tsnake41) +* Copyright (c) 2021-2025 Teddy Astie (@tsnake41) * ********************************************************************************************/ diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index 60d140598..9bb570ec4 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -5,6 +5,8 @@ * rlgl library is an abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) * that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) * +* Example originally created with raylib 1.6, last time updated with raylib 4.0 +* * WARNING: This example is intended only for PLATFORM_DESKTOP and OpenGL 3.3 Core profile. * It could work on other platforms if redesigned for those platforms (out-of-scope) * @@ -29,7 +31,7 @@ * This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * * 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. diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c index 9eff43379..eac7ac6e4 100644 --- a/examples/shaders/shaders_basic_lighting.c +++ b/examples/shaders/shaders_basic_lighting.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c index d02980afd..a35947cdc 100644 --- a/examples/shaders/shaders_basic_pbr.c +++ b/examples/shaders/shaders_basic_pbr.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023-2024 Afan OLOVCIC (@_DevDad) +* Copyright (c) 2023-2025 Afan OLOVCIC (@_DevDad) * * Model: "Old Rusty Car" (https://skfb.ly/LxRy) by Renafox, * licensed under Creative Commons Attribution-NonCommercial diff --git a/examples/shaders/shaders_custom_uniform.c b/examples/shaders/shaders_custom_uniform.c index 1c8419c91..432b240ee 100644 --- a/examples/shaders/shaders_custom_uniform.c +++ b/examples/shaders/shaders_custom_uniform.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_deferred_render.c b/examples/shaders/shaders_deferred_render.c index 13600bc09..879f9a68b 100644 --- a/examples/shaders/shaders_deferred_render.c +++ b/examples/shaders/shaders_deferred_render.c @@ -13,7 +13,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Justin Andreas Lacoste (@27justin) +* Copyright (c) 2023-2025 Justin Andreas Lacoste (@27justin) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_eratosthenes.c b/examples/shaders/shaders_eratosthenes.c index 0b8b08186..26075706e 100644 --- a/examples/shaders/shaders_eratosthenes.c +++ b/examples/shaders/shaders_eratosthenes.c @@ -18,12 +18,12 @@ * * Example originally created with raylib 2.5, last time updated with raylib 4.0 * -* Example contributed by ProfJski and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by ProfJski (@ProfJski) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 ProfJski and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 ProfJski (@ProfJski) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_fog.c b/examples/shaders/shaders_fog.c index eefce44fc..2e589eec4 100644 --- a/examples/shaders/shaders_fog.c +++ b/examples/shaders/shaders_fog.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_hot_reloading.c b/examples/shaders/shaders_hot_reloading.c index f620a6247..1005c0913 100644 --- a/examples/shaders/shaders_hot_reloading.c +++ b/examples/shaders/shaders_hot_reloading.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_hybrid_render.c b/examples/shaders/shaders_hybrid_render.c index 5f90f1724..4c9f5c978 100644 --- a/examples/shaders/shaders_hybrid_render.c +++ b/examples/shaders/shaders_hybrid_render.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Buğra Alptekin Sarı (@BugraAlptekinSari) +* Copyright (c) 2022-2025 Buğra Alptekin Sarı (@BugraAlptekinSari) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_julia_set.c b/examples/shaders/shaders_julia_set.c index 3b30205f8..c1be3f325 100644 --- a/examples/shaders/shaders_julia_set.c +++ b/examples/shaders/shaders_julia_set.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Josh Colclough (@joshcol9232) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Josh Colclough (@joshcol9232) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_lightmap.c b/examples/shaders/shaders_lightmap.c index 305399b98..0d26e54c8 100644 --- a/examples/shaders/shaders_lightmap.c +++ b/examples/shaders/shaders_lightmap.c @@ -9,12 +9,14 @@ * * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). * +* Example originally created with raylib 4.5, last time updated with raylib 4.5 +* * Example contributed by Jussi Viitala (@nullstare) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Jussi Viitala (@nullstare) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Jussi Viitala (@nullstare) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_mesh_instancing.c b/examples/shaders/shaders_mesh_instancing.c index ca975beea..805d5ef18 100644 --- a/examples/shaders/shaders_mesh_instancing.c +++ b/examples/shaders/shaders_mesh_instancing.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 3.7, last time updated with raylib 4.2 * -* Example contributed by @seanpringle and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5) +* Example contributed by seanpringle (@seanpringle) and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 @seanpringle, Max (@moliad) and Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 seanpringle (@seanpringle), Max (@moliad) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 62a4dc003..fda6377fc 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_multi_sample2d.c b/examples/shaders/shaders_multi_sample2d.c index 5e10cddce..8409e35cb 100644 --- a/examples/shaders/shaders_multi_sample2d.c +++ b/examples/shaders/shaders_multi_sample2d.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index a2d01a11d..50f80b8f0 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -1,8 +1,8 @@ /******************************************************************************************* * * raylib [shaders] example - Color palette switch -* -* Example complexity rating: [★★★☆] 3/4 +* +* Example complexity rating: [★★★☆] 3/4 * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. @@ -18,7 +18,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Marco Lizza (@MarcoLizza) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Marco Lizza (@MarcoLizza) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_postprocessing.c b/examples/shaders/shaders_postprocessing.c index 1e5fe0d14..ea55c9ca4 100644 --- a/examples/shaders/shaders_postprocessing.c +++ b/examples/shaders/shaders_postprocessing.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_raymarching.c b/examples/shaders/shaders_raymarching.c index 0f21f6a56..ab69fe69a 100644 --- a/examples/shaders/shaders_raymarching.c +++ b/examples/shaders/shaders_raymarching.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_shadowmap.c b/examples/shaders/shaders_shadowmap.c index 96c42d12f..fcd2ec96d 100644 --- a/examples/shaders/shaders_shadowmap.c +++ b/examples/shaders/shaders_shadowmap.c @@ -4,11 +4,13 @@ * * Example originally created with raylib 5.0, last time updated with raylib 5.0 * -* Example contributed by @TheManTheMythTheGameDev and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by TheManTheMythTheGameDev (@TheManTheMythTheGameDev) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * +* Copyright (c) 2023-2025 TheManTheMythTheGameDev (@TheManTheMythTheGameDev) +* ********************************************************************************************/ #include "raylib.h" diff --git a/examples/shaders/shaders_shapes_textures.c b/examples/shaders/shaders_shapes_textures.c index 95be102d5..107b09c03 100644 --- a/examples/shaders/shaders_shapes_textures.c +++ b/examples/shaders/shaders_shapes_textures.c @@ -16,7 +16,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_simple_mask.c b/examples/shaders/shaders_simple_mask.c index 02e6c606a..f12230373 100644 --- a/examples/shaders/shaders_simple_mask.c +++ b/examples/shaders/shaders_simple_mask.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) * ******************************************************************************************** * diff --git a/examples/shaders/shaders_spotlight.c b/examples/shaders/shaders_spotlight.c index 98a98e973..288292cb6 100644 --- a/examples/shaders/shaders_spotlight.c +++ b/examples/shaders/shaders_spotlight.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) * ******************************************************************************************** * diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c index d30b6e1f1..2cfe7e64d 100644 --- a/examples/shaders/shaders_texture_drawing.c +++ b/examples/shaders/shaders_texture_drawing.c @@ -8,12 +8,12 @@ * * Example originally created with raylib 2.0, last time updated with raylib 3.7 * -* Example contributed by Michał Ciesielski and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Michał Ciesielski (@ciessielski) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Michał Ciesielski and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Michał Ciesielski (@ciessielski) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_texture_outline.c b/examples/shaders/shaders_texture_outline.c index 3c14bd0f2..b2172aef9 100644 --- a/examples/shaders/shaders_texture_outline.c +++ b/examples/shaders/shaders_texture_outline.c @@ -14,7 +14,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Samuel SKiff (@GoldenThumbs) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Samuel SKiff (@GoldenThumbs) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_texture_tiling.c b/examples/shaders/shaders_texture_tiling.c index ca32580b6..d811e30ec 100644 --- a/examples/shaders/shaders_texture_tiling.c +++ b/examples/shaders/shaders_texture_tiling.c @@ -6,12 +6,14 @@ * * Example demonstrates how to tile a texture on a 3D model using raylib. * +* Example originally created with raylib 4.5, last time updated with raylib 4.5 +* * Example contributed by Luis Almeida (@luis605) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Luis Almeida (@luis605) +* Copyright (c) 2023-2025 Luis Almeida (@luis605) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_texture_waves.c b/examples/shaders/shaders_texture_waves.c index 8d78b7593..73ba738c6 100644 --- a/examples/shaders/shaders_texture_waves.c +++ b/examples/shaders/shaders_texture_waves.c @@ -18,7 +18,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Anata (@anatagawa) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Anata (@anatagawa) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_vertex_displacement.c b/examples/shaders/shaders_vertex_displacement.c index 207a237d0..78c97e4d8 100644 --- a/examples/shaders/shaders_vertex_displacement.c +++ b/examples/shaders/shaders_vertex_displacement.c @@ -4,12 +4,12 @@ * * Example originally created with raylib 5.0, last time updated with raylib 4.5 * -* Example contributed by (@ZzzhHe) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Alex ZH (@ZzzhHe) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 (@ZzzhHe) +* Copyright (c) 2023-2025 Alex ZH (@ZzzhHe) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_write_depth.c b/examples/shaders/shaders_write_depth.c index c665a56d3..d47ea1ae3 100644 --- a/examples/shaders/shaders_write_depth.c +++ b/examples/shaders/shaders_write_depth.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Buğra Alptekin Sarı (@BugraAlptekinSari) +* Copyright (c) 2022-2025 Buğra Alptekin Sarı (@BugraAlptekinSari) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_basic_shapes.c b/examples/shapes/shapes_basic_shapes.c index 78297e37f..bd1688453 100644 --- a/examples/shapes/shapes_basic_shapes.c +++ b/examples/shapes/shapes_basic_shapes.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c index 394e54886..187cd41af 100644 --- a/examples/shapes/shapes_bouncing_ball.c +++ b/examples/shapes/shapes_bouncing_ball.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_collision_area.c b/examples/shapes/shapes_collision_area.c index ddb156831..f492cf250 100644 --- a/examples/shapes/shapes_collision_area.c +++ b/examples/shapes/shapes_collision_area.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_colors_palette.c b/examples/shapes/shapes_colors_palette.c index f94be8161..81d008ff0 100644 --- a/examples/shapes/shapes_colors_palette.c +++ b/examples/shapes/shapes_colors_palette.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index 8be6b045f..e64055c81 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index 1dbfd5282..ed7e032d1 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index 91c563dbe..daee5cbf5 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_easings_ball_anim.c b/examples/shapes/shapes_easings_ball_anim.c index 654ed8cd5..d7f0bb72e 100644 --- a/examples/shapes/shapes_easings_ball_anim.c +++ b/examples/shapes/shapes_easings_ball_anim.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_easings_box_anim.c b/examples/shapes/shapes_easings_box_anim.c index 8407dfc2f..4a76e7ef3 100644 --- a/examples/shapes/shapes_easings_box_anim.c +++ b/examples/shapes/shapes_easings_box_anim.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_easings_rectangle_array.c b/examples/shapes/shapes_easings_rectangle_array.c index e250007f8..912926ea4 100644 --- a/examples/shapes/shapes_easings_rectangle_array.c +++ b/examples/shapes/shapes_easings_rectangle_array.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_following_eyes.c b/examples/shapes/shapes_following_eyes.c index 97f5b2981..b5b3fd7c8 100644 --- a/examples/shapes/shapes_following_eyes.c +++ b/examples/shapes/shapes_following_eyes.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_lines_bezier.c b/examples/shapes/shapes_lines_bezier.c index 08559888d..f963cd4de 100644 --- a/examples/shapes/shapes_lines_bezier.c +++ b/examples/shapes/shapes_lines_bezier.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_logo_raylib.c b/examples/shapes/shapes_logo_raylib.c index f7408bf78..d26db5ce6 100644 --- a/examples/shapes/shapes_logo_raylib.c +++ b/examples/shapes/shapes_logo_raylib.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_logo_raylib_anim.c b/examples/shapes/shapes_logo_raylib_anim.c index 80fcbba1a..81c1e6d3f 100644 --- a/examples/shapes/shapes_logo_raylib_anim.c +++ b/examples/shapes/shapes_logo_raylib_anim.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_rectangle_advanced.c b/examples/shapes/shapes_rectangle_advanced.c index 6dd7d2e7e..0c20c9e8b 100644 --- a/examples/shapes/shapes_rectangle_advanced.c +++ b/examples/shapes/shapes_rectangle_advanced.c @@ -2,12 +2,16 @@ * * raylib [shapes] example - Rectangle advanced * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 5.5, last time updated with raylib 5.5 * +* Example contributed by Everton Jr. (@evertonse) and reviewed by Ramon Santamaria (@raysan5) +* * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024-2025 raylib contributors and Ramon Santamaria (@raysan5) +* Copyright (c) 2024-2025 Everton Jr. (@evertonse) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_rectangle_scaling.c b/examples/shapes/shapes_rectangle_scaling.c index 416b02c0d..b5c778317 100644 --- a/examples/shapes/shapes_rectangle_scaling.c +++ b/examples/shapes/shapes_rectangle_scaling.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_splines_drawing.c b/examples/shapes/shapes_splines_drawing.c index 9b3a14926..065050e8e 100644 --- a/examples/shapes/shapes_splines_drawing.c +++ b/examples/shapes/shapes_splines_drawing.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2023 Ramon Santamaria (@raysan5) +* Copyright (c) 2023-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_top_down_lights.c b/examples/shapes/shapes_top_down_lights.c index 39de6ccf7..7e2640117 100644 --- a/examples/shapes/shapes_top_down_lights.c +++ b/examples/shapes/shapes_top_down_lights.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 4.2, last time updated with raylib 4.2 * -* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Jeffery Myers (@JeffM2501) +* Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501) * ********************************************************************************************/ diff --git a/examples/text/text_codepoints_loading.c b/examples/text/text_codepoints_loading.c index df3b76894..a4cd5ca79 100644 --- a/examples/text/text_codepoints_loading.c +++ b/examples/text/text_codepoints_loading.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2022-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c index 8d93db439..21be7dc62 100644 --- a/examples/text/text_draw_3d.c +++ b/examples/text/text_draw_3d.c @@ -24,7 +24,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Vlad Adrian (@demizdor) +* Copyright (c) 2021-2025 Vlad Adrian (@demizdor) * ********************************************************************************************/ diff --git a/examples/text/text_font_filters.c b/examples/text/text_font_filters.c index 7893e01f2..f3293e6be 100644 --- a/examples/text/text_font_filters.c +++ b/examples/text/text_font_filters.c @@ -13,7 +13,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c index 17c06abac..a7f8c60f4 100644 --- a/examples/text/text_font_loading.c +++ b/examples/text/text_font_loading.c @@ -18,7 +18,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_font_sdf.c b/examples/text/text_font_sdf.c index d3b3098ad..7a051710b 100644 --- a/examples/text/text_font_sdf.c +++ b/examples/text/text_font_sdf.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_font_spritefont.c b/examples/text/text_font_spritefont.c index 7655a0c2c..95b5cfee5 100644 --- a/examples/text/text_font_spritefont.c +++ b/examples/text/text_font_spritefont.c @@ -19,7 +19,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_format_text.c b/examples/text/text_format_text.c index d9dc32d04..eca6500e3 100644 --- a/examples/text/text_format_text.c +++ b/examples/text/text_format_text.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c index 14bedf27a..24672b2ad 100644 --- a/examples/text/text_input_box.c +++ b/examples/text/text_input_box.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_raylib_fonts.c b/examples/text/text_raylib_fonts.c index 45314c9a0..7248be128 100644 --- a/examples/text/text_raylib_fonts.c +++ b/examples/text/text_raylib_fonts.c @@ -12,7 +12,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c index 6da91a6a3..c9dad5f9e 100644 --- a/examples/text/text_rectangle_bounds.c +++ b/examples/text/text_rectangle_bounds.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index ba37416fa..31faafade 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c index 0f91668ba..3455cec33 100644 --- a/examples/text/text_writing_anim.c +++ b/examples/text/text_writing_anim.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_background_scrolling.c b/examples/textures/textures_background_scrolling.c index 9dfa8d50a..48ba314d4 100644 --- a/examples/textures/textures_background_scrolling.c +++ b/examples/textures/textures_background_scrolling.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_blend_modes.c b/examples/textures/textures_blend_modes.c index 4cb5b801c..555cdd7b5 100644 --- a/examples/textures/textures_blend_modes.c +++ b/examples/textures/textures_blend_modes.c @@ -13,7 +13,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Karlo Licudine (@accidentalrebel) +* Copyright (c) 2020-2025 Karlo Licudine (@accidentalrebel) * ********************************************************************************************/ diff --git a/examples/textures/textures_bunnymark.c b/examples/textures/textures_bunnymark.c index 18b9cda3b..6f58e8281 100644 --- a/examples/textures/textures_bunnymark.c +++ b/examples/textures/textures_bunnymark.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_draw_tiled.c b/examples/textures/textures_draw_tiled.c index c0d827feb..801a7c15a 100644 --- a/examples/textures/textures_draw_tiled.c +++ b/examples/textures/textures_draw_tiled.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2020-2024 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2020-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_fog_of_war.c b/examples/textures/textures_fog_of_war.c index fba8c2204..e9296f3f4 100644 --- a/examples/textures/textures_fog_of_war.c +++ b/examples/textures/textures_fog_of_war.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_gif_player.c b/examples/textures/textures_gif_player.c index 7eb4c5703..f62205b63 100644 --- a/examples/textures/textures_gif_player.c +++ b/examples/textures/textures_gif_player.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_channel.c b/examples/textures/textures_image_channel.c index 9afcda638..55c8b38fa 100644 --- a/examples/textures/textures_image_channel.c +++ b/examples/textures/textures_image_channel.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 5.1-dev, last time updated with raylib 5.1-dev * -* Example contributed by Bruno Cabral (github.com/brccabral) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Bruno Cabral (@brccabral) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024-2024 Bruno Cabral (github.com/brccabral) and Ramon Santamaria (@raysan5) +* Copyright (c) 2024-2025 Bruno Cabral (@brccabral) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_drawing.c b/examples/textures/textures_image_drawing.c index 4d73a2224..05f40df9b 100644 --- a/examples/textures/textures_image_drawing.c +++ b/examples/textures/textures_image_drawing.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 0a3610ab6..2372af9c3 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -6,10 +6,12 @@ * * Example originally created with raylib 1.8, last time updated with raylib 1.8 * +* Example contributed by Wilhem Barbier (@nounoursheureux) and reviewed by Ramon Santamaria (@raysan5) +* * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2O17-2024 Wilhem Barbier (@nounoursheureux) and Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Wilhem Barbier (@nounoursheureux) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_kernel.c b/examples/textures/textures_image_kernel.c index b850b63ed..67e073ec8 100644 --- a/examples/textures/textures_image_kernel.c +++ b/examples/textures/textures_image_kernel.c @@ -4,12 +4,14 @@ * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * +* Example contributed by Karim Salem (@kimo-s) and reviewed by Ramon Santamaria (@raysan5) +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Karim Salem (@kimo-s) +* Copyright (c) 2015-2025 Karim Salem (@kimo-s) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_loading.c b/examples/textures/textures_image_loading.c index e26ccb645..267216332 100644 --- a/examples/textures/textures_image_loading.c +++ b/examples/textures/textures_image_loading.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_processing.c b/examples/textures/textures_image_processing.c index 7a61cd024..8531d1dba 100644 --- a/examples/textures/textures_image_processing.c +++ b/examples/textures/textures_image_processing.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_rotate.c b/examples/textures/textures_image_rotate.c index 94c42034b..c08d46a3f 100644 --- a/examples/textures/textures_image_rotate.c +++ b/examples/textures/textures_image_rotate.c @@ -7,7 +7,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_image_text.c b/examples/textures/textures_image_text.c index 4d5c281f7..a0a41404a 100644 --- a/examples/textures/textures_image_text.c +++ b/examples/textures/textures_image_text.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c index 4456fef02..bd402baec 100644 --- a/examples/textures/textures_logo_raylib.c +++ b/examples/textures/textures_logo_raylib.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_mouse_painting.c b/examples/textures/textures_mouse_painting.c index 324f88fa1..c0e426232 100644 --- a/examples/textures/textures_mouse_painting.c +++ b/examples/textures/textures_mouse_painting.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Chris Dill (@MysteriousSpace) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Dill (@MysteriousSpace) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_npatch_drawing.c b/examples/textures/textures_npatch_drawing.c index 5e23a0fb6..005fc845e 100644 --- a/examples/textures/textures_npatch_drawing.c +++ b/examples/textures/textures_npatch_drawing.c @@ -13,7 +13,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2018-2024 Jorge A. Gomes (@overdev) and Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Jorge A. Gomes (@overdev) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_particles_blending.c b/examples/textures/textures_particles_blending.c index 6781668e9..65a55f30a 100644 --- a/examples/textures/textures_particles_blending.c +++ b/examples/textures/textures_particles_blending.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_polygon.c b/examples/textures/textures_polygon.c index 82ccd1cf1..4d114ab96 100644 --- a/examples/textures/textures_polygon.c +++ b/examples/textures/textures_polygon.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2024 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index 51a50069f..01248e979 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_sprite_anim.c b/examples/textures/textures_sprite_anim.c index 8b0378958..c8b401522 100644 --- a/examples/textures/textures_sprite_anim.c +++ b/examples/textures/textures_sprite_anim.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_sprite_button.c b/examples/textures/textures_sprite_button.c index 0f5a6940d..a7db93c4f 100644 --- a/examples/textures/textures_sprite_button.c +++ b/examples/textures/textures_sprite_button.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c index 09839f8fa..fe9669224 100644 --- a/examples/textures/textures_sprite_explosion.c +++ b/examples/textures/textures_sprite_explosion.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2024 Anata and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_srcrec_dstrec.c b/examples/textures/textures_srcrec_dstrec.c index a3bd29af2..cf3686d15 100644 --- a/examples/textures/textures_srcrec_dstrec.c +++ b/examples/textures/textures_srcrec_dstrec.c @@ -9,7 +9,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_textured_curve.c b/examples/textures/textures_textured_curve.c index 86df6957a..00417b038 100644 --- a/examples/textures/textures_textured_curve.c +++ b/examples/textures/textures_textured_curve.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 4.5, last time updated with raylib 4.5 * -* Example contributed by Jeffery Myers and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2022-2024 Jeffery Myers and Ramon Santamaria (@raysan5) +* Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c index 39907103e..84b4a72be 100644 --- a/examples/textures/textures_to_image.c +++ b/examples/textures/textures_to_image.c @@ -11,7 +11,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ From 896ff68540c362e1d7a0dbc14f7dcc3514463a69 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 Jan 2025 20:19:11 +0100 Subject: [PATCH 13/39] REVIEWED: Text functions usage notes #4704 --- src/raylib.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 27a8ab049..0d47e16f8 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1502,7 +1502,8 @@ RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) // Text strings management functions (no UTF-8 strings, only byte chars) -// NOTE: Some strings allocate memory internally for returned strings, just be careful! +// WARNING 1: Most of these functions use internal static buffers, it's recommended to store returned data on user-side for re-use +// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree() RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending From 09272e2e1159df86961464259920db3657ff2873 Mon Sep 17 00:00:00 2001 From: Chris <1041549+pejorativefox@users.noreply.github.com> Date: Sun, 19 Jan 2025 03:24:48 +0800 Subject: [PATCH 14/39] Updted the comment for SetShaderValueTexture to reflect the difference between SetShaderValue using sampler2d and SetShaderValueTexture is the automatic bind of the texture. (#4703) --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 0d47e16f8..b8428e7ac 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1061,7 +1061,7 @@ RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Ge RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4) -RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d) +RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d) RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) // Screen-space-related functions From e70f9157bcae046804e754e98a2694adcfdbfa5d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 18 Jan 2025 19:25:01 +0000 Subject: [PATCH 15/39] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 0044de007..9fd9bcef0 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -3899,7 +3899,7 @@ }, { "name": "SetShaderValueTexture", - "description": "Set shader uniform value for texture (sampler2d)", + "description": "Set shader uniform value and bind the texture (sampler2d)", "returnType": "void", "params": [ { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index ccf61cb0b..59eb4b0fc 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -3674,7 +3674,7 @@ return { }, { name = "SetShaderValueTexture", - description = "Set shader uniform value for texture (sampler2d)", + description = "Set shader uniform value and bind the texture (sampler2d)", returnType = "void", params = { {type = "Shader", name = "shader"}, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 896efbaff..f0fb4eab4 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -1431,7 +1431,7 @@ Function 082: SetShaderValueMatrix() (3 input parameters) Function 083: SetShaderValueTexture() (3 input parameters) Name: SetShaderValueTexture Return type: void - Description: Set shader uniform value for texture (sampler2d) + Description: Set shader uniform value and bind the texture (sampler2d) Param[1]: shader (type: Shader) Param[2]: locIndex (type: int) Param[3]: texture (type: Texture2D) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 241b28ae8..21e9d30e6 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -906,7 +906,7 @@ - + From 10d0616d1fa3dc3eefb29e4e33c9a6aa8c22d697 Mon Sep 17 00:00:00 2001 From: sleeptightAnsiC <91839286+sleeptightAnsiC@users.noreply.github.com> Date: Sun, 19 Jan 2025 12:06:27 +0100 Subject: [PATCH 16/39] fix(rtextures): TCC not being able to compile due to: 'emmintrin.h' not found (#4707) define STBIR_NO_SIMD when __TINYC__ is defined so stb_image_resize2 will not include *mmintrin which are not supported by all compilers. There are similar checks for __TINYC__ already elswere in raylib and they are also mostly there to disable SIMD headers. Additionally, move similar check for stb_image, to be a little bit deeper. Before it was defining STBI_NO_SIMD without including stb_image It was also clashing with note, causing said note to make no sense. Fixes: https://github.com/raysan5/raylib/discussions/2994 Reference: https://github.com/nothings/stb/issues/1738 --- src/rtextures.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 5248f1f4c..9dfc24738 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -124,10 +124,6 @@ #endif // Image fileformats not supported by default -#if defined(__TINYC__) - #define STBI_NO_SIMD -#endif - #if (defined(SUPPORT_FILEFORMAT_BMP) || \ defined(SUPPORT_FILEFORMAT_PNG) || \ defined(SUPPORT_FILEFORMAT_TGA) || \ @@ -149,6 +145,10 @@ #define STBI_NO_THREAD_LOCALS + #if defined(__TINYC__) + #define STBI_NO_SIMD + #endif + #define STB_IMAGE_IMPLEMENTATION #include "external/stb_image.h" // Required for: stbi_load_from_file() // NOTE: Used to read image data (multiple formats support) @@ -218,6 +218,9 @@ #pragma GCC diagnostic ignored "-Wunused-function" #endif +#if defined(__TINYC__) + #define STBIR_NO_SIMD +#endif #define STB_IMAGE_RESIZE_IMPLEMENTATION #include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()] From 773e3f5f9fd39a3f968f29d1f7e6d9ea491b7154 Mon Sep 17 00:00:00 2001 From: Anstro Pleuton <121956207+anstropleuton@users.noreply.github.com> Date: Sun, 19 Jan 2025 08:17:38 -0800 Subject: [PATCH 17/39] Update more examples inconsistencies (#4711) Co-authored-by: Anstro Pleuton --- examples/README.md | 274 ++++++++++-------- examples/core/core_basic_window_web.c | 2 + examples/core/core_input_gestures_web.c | 2 + examples/core/core_input_virtual_controls.c | 4 +- examples/core/core_random_sequence.c | 2 + examples/models/models_bone_socket.c | 2 + examples/models/models_gpu_skinning.c | 2 + examples/models/models_point_rendering.c | 2 + examples/models/models_tesseract_view.c | 2 + examples/others/easings_testbed.c | 2 + examples/others/embedded_files_loading.c | 2 + examples/others/raylib_opengl_interop.c | 2 + examples/others/raymath_vector_angle.c | 2 + examples/others/rlgl_compute_shader.c | 2 + examples/others/rlgl_standalone.c | 2 + examples/shaders/shaders_basic_lighting.c | 4 +- examples/shaders/shaders_basic_pbr.c | 2 + examples/shaders/shaders_shadowmap.c | 2 + .../shaders/shaders_vertex_displacement.c | 2 + examples/textures/textures_image_channel.c | 2 + examples/textures/textures_image_kernel.c | 2 + examples/textures/textures_image_rotate.c | 2 + examples/textures/textures_polygon.c | 4 +- 23 files changed, 193 insertions(+), 131 deletions(-) diff --git a/examples/README.md b/examples/README.md index 1be82dbca..ba14d82dd 100644 --- a/examples/README.md +++ b/examples/README.md @@ -23,187 +23,209 @@ You may find it easier to use than other toolchains, especially when it comes to Examples using raylib core platform functionality like window creation, inputs, drawing modes and system functionality. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| | 01 | [core_basic_window](core/core_basic_window.c) | core_basic_window | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 02 | [core_input_keys](core/core_input_keys.c) | core_input_keys | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 03 | [core_input_mouse](core/core_input_mouse.c) | core_input_mouse | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) | +| 03 | [core_input_mouse](core/core_input_mouse.c) | core_input_mouse | ⭐️☆☆☆ | 1.0 | 5.5 | [Ray](https://github.com/raysan5) | | 04 | [core_input_mouse_wheel](core/core_input_mouse_wheel.c) | core_input_mouse_wheel | ⭐️☆☆☆ | 1.1 | 1.3 | [Ray](https://github.com/raysan5) | -| 05 | [core_input_gamepad](core/core_input_gamepad.c) | core_input_gamepad | ⭐️☆☆☆ | 1.1 | **4.2** | [Ray](https://github.com/raysan5) | +| 05 | [core_input_gamepad](core/core_input_gamepad.c) | core_input_gamepad | ⭐️☆☆☆ | 1.1 | 4.2 | [Ray](https://github.com/raysan5) | | 06 | [core_input_multitouch](core/core_input_multitouch.c) | core_input_multitouch | ⭐️☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) | -| 07 | [core_input_gestures](core/core_input_gestures.c) | core_input_gestures | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | -| 08 | [core_input_virtual_controls](core/core_input_virtual_controls.c) | core_input_virtual_controls | ⭐️⭐️☆☆ | **5.0** | **5.0** | [oblerion](https://github.com/oblerion) | +| 07 | [core_input_gestures](core/core_input_gestures.c) | core_input_gestures | ⭐️⭐️☆☆ | 1.4 | 4.2 | [Ray](https://github.com/raysan5) | +| 08 | [core_input_virtual_controls](core/core_input_virtual_controls.c) | core_input_virtual_controls | ⭐️⭐️☆☆ | 5.0 | 5.0 | [oblerion](https://github.com/oblerion) | | 09 | [core_2d_camera](core/core_2d_camera.c) | core_2d_camera | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) | -| 10 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | core_2d_camera_mouse_zoom | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | -| 11 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | core_2d_camera_platformer | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) | -| 12 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | core_2d_camera_split_screen | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) | +| 10 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | core_2d_camera_mouse_zoom | ⭐️⭐️☆☆ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) | +| 11 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | core_2d_camera_platformer | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [arvyy](https://github.com/arvyy) | +| 12 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | core_2d_camera_split_screen | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) | | 13 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | core_3d_camera_mode | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 14 | [core_3d_camera_free](core/core_3d_camera_free.c) | core_3d_camera_free | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 15 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | core_3d_camera_first_person | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 16 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | core_3d_camera_split_screen | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) | -| 17 | [core_3d_picking](core/core_3d_picking.c) | core_3d_picking | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | +| 16 | [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | core_3d_camera_split_screen | ⭐️⭐️⭐️☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) | +| 17 | [core_3d_picking](core/core_3d_picking.c) | core_3d_picking | ⭐️⭐️☆☆ | 1.3 | 4.0 | [Ray](https://github.com/raysan5) | | 18 | [core_world_screen](core/core_world_screen.c) | core_world_screen | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) | | 19 | [core_custom_logging](core/core_custom_logging.c) | core_custom_logging | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | 20 | [core_window_flags](core/core_window_flags.c) | core_window_flags | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 21 | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) | -| 22 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 23 | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | +| 21 | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐️⭐️☆☆ | 2.5 | 4.0 | [Anata](https://github.com/anatagawa) | +| 22 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️☆☆☆ | 4.2 | 4.2 | [Ray](https://github.com/raysan5) | +| 23 | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐️⭐️☆☆ | 1.3 | 4.2 | [Ray](https://github.com/raysan5) | | 24 | [core_random_values](core/core_random_values.c) | core_random_values | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) | -| 25 | [core_storage_values](core/core_storage_values.c) | core_storage_values | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | -| 26 | [core_vr_simulator](core/core_vr_simulator.c) | core_vr_simulator | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | +| 25 | [core_storage_values](core/core_storage_values.c) | core_storage_values | ⭐️⭐️☆☆ | 1.4 | 4.2 | [Ray](https://github.com/raysan5) | +| 26 | [core_vr_simulator](core/core_vr_simulator.c) | core_vr_simulator | ⭐️⭐️⭐️☆ | 2.5 | 4.0 | [Ray](https://github.com/raysan5) | | 27 | [core_loading_thread](core/core_loading_thread.c) | core_loading_thread | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) | | 28 | [core_scissor_test](core/core_scissor_test.c) | core_scissor_test | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | -| 29 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | core_basic_screen_manager | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | -| 30 | [core_custom_frame_control](core/core_custom_frame_control.c) | core_custom_frame_control | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | -| 31 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | core_smooth_pixelperfect | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | -| 32 | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 33 | [core_random_sequence](core/core_random_sequence.c) | core_random_sequence | ⭐️☆☆☆ | **5.0** | **5.0** | [REDl3east](https://github.com/REDl3east) | +| 29 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | core_basic_screen_manager | ⭐️☆☆☆ | 4.0 | 4.0 | [Ray](https://github.com/raysan5) | +| 30 | [core_custom_frame_control](core/core_custom_frame_control.c) | core_custom_frame_control | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Ray](https://github.com/raysan5) | +| 31 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | core_smooth_pixelperfect | ⭐️⭐️⭐️☆ | 3.7 | 4.0 | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | +| 32 | [core_random_sequence](core/core_random_sequence.c) | core_random_sequence | ⭐️☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) | +| 33 | [core_basic_window_web](core/core_basic_window_web.c) | core_basic_window_web | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 34 | [core_input_gestures_web](core/core_input_gestures_web.c) | core_input_gestures_web | ⭐️⭐️☆☆ | 4.6-dev | 4.6-dev | [ubkp](https://github.com/ubkp) | +| 35 | [core_automation_events](core/core_automation_events.c) | core_automation_events | ⭐️⭐️⭐️☆ | 5.0 | 5.0 | [Ray](https://github.com/raysan5) | ### category: shapes Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/shapes.c) module. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 34 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | shapes_basic_shapes | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) | -| 35 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | shapes_bouncing_ball | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 36 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | shapes_colors_palette | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) | -| 37 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | shapes_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 38 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | shapes_logo_raylib_anim | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 39 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | shapes_rectangle_scaling | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 40 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | shapes_lines_bezier | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) | -| 41 | [shapes_collision_area](shapes/shapes_collision_area.c) | shapes_collision_area | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 42 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 43 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | shapes_easings_ball_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 44 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | shapes_easings_box_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 45 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | shapes_easings_rectangle_array | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 46 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | shapes_draw_ring | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 47 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | shapes_draw_circle_sector | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 48 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | shapes_draw_rectangle_rounded | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | -| 49 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | -| 50 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐️⭐️⭐️⭐️ | **5.0** | **5.0** | [ExCyber](https://github.com/evertonse) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 36 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | shapes_basic_shapes | ⭐️☆☆☆ | 1.0 | 4.2 | [Ray](https://github.com/raysan5) | +| 37 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | shapes_bouncing_ball | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 38 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | shapes_colors_palette | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) | +| 39 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | shapes_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 40 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | shapes_logo_raylib_anim | ⭐️⭐️☆☆ | 2.5 | 4.0 | [Ray](https://github.com/raysan5) | +| 41 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | shapes_rectangle_scaling | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 42 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | shapes_lines_bezier | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) | +| 43 | [shapes_collision_area](shapes/shapes_collision_area.c) | shapes_collision_area | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 44 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 45 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | shapes_easings_ball_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 46 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | shapes_easings_box_anim | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 47 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | shapes_easings_rectangle_array | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | +| 48 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | shapes_draw_ring | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 49 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | shapes_draw_circle_sector | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 50 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | shapes_draw_rectangle_rounded | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | +| 51 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) | +| 52 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐️⭐️⭐️⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) | +| 53 | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | shapes_splines_drawing | ⭐️⭐️⭐️☆ | 5.0 | 5.0 | [Ray](https://github.com/raysan5) | ### category: textures -Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/textures.c) module. +Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/textures.c) modul | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 51 | [textures_logo_raylib](textures/textures_logo_raylib.c) | textures_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 52 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | textures_srcrec_dstrec | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 53 | [textures_image_drawing](textures/textures_image_drawing.c) | textures_image_drawing | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | -| 54 | [textures_image_generation](textures/textures_image_generation.c) | textures_image_generation | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Ray](https://github.com/raysan5) | -| 55 | [textures_image_loading](textures/textures_image_loading.c) | textures_image_loading | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 56 | [textures_image_processing](textures/textures_image_processing.c) | textures_image_processing | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) | -| 57 | [textures_image_text](textures/textures_image_text.c) | textures_image_text | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | -| 58 | [textures_to_image](textures/textures_to_image.c) | textures_to_image | ⭐️☆☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 59 | [textures_raw_data](textures/textures_raw_data.c) | textures_raw_data | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 60 | [textures_particles_blending](textures/textures_particles_blending.c) | textures_particles_blending | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | -| 61 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | textures_npatch_drawing | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) | -| 62 | [textures_background_scrolling](textures/textures_background_scrolling.c) | textures_background_scrolling | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | -| 63 | [textures_sprite_anim](textures/textures_sprite_anim.c) | textures_sprite_anim | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | -| 64 | [textures_sprite_button](textures/textures_sprite_button.c) | textures_sprite_button | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | -| 65 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | textures_sprite_explosion | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 66 | [textures_bunnymark](textures/textures_bunnymark.c) | textures_bunnymark | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) | -| 67 | [textures_mouse_painting](textures/textures_mouse_painting.c) | textures_mouse_painting | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | -| 68 | [textures_blend_modes](textures/textures_blend_modes.c) | textures_blend_modes | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) | -| 69 | [textures_draw_tiled](textures/textures_draw_tiled.c) | textures_draw_tiled | ⭐️⭐️⭐️☆ | 3.0 | **4.2** | [Vlad Adrian](https://github.com/demizdor) | -| 70 | [textures_polygon](textures/textures_polygon.c) | textures_polygon | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 71 | [textures_fog_of_war](textures/textures_fog_of_war.c) | textures_fog_of_war | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | -| 72 | [textures_gif_player](textures/textures_gif_player.c) | textures_gif_player | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 54 | [textures_logo_raylib](textures/textures_logo_raylib.c) | textures_logo_raylib | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 55 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | textures_srcrec_dstrec | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 56 | [textures_image_drawing](textures/textures_image_drawing.c) | textures_image_drawing | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | +| 57 | [textures_image_generation](textures/textures_image_generation.c) | textures_image_generation | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Wilhem Barbier](https://github.com/nounoursheureux) | +| 58 | [textures_image_loading](textures/textures_image_loading.c) | textures_image_loading | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 59 | [textures_image_processing](textures/textures_image_processing.c) | textures_image_processing | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) | +| 60 | [textures_image_text](textures/textures_image_text.c) | textures_image_text | ⭐️⭐️☆☆ | 1.8 | 4.0 | [Ray](https://github.com/raysan5) | +| 61 | [textures_to_image](textures/textures_to_image.c) | textures_to_image | ⭐️☆☆☆ | 1.3 | 4.0 | [Ray](https://github.com/raysan5) | +| 62 | [textures_raw_data](textures/textures_raw_data.c) | textures_raw_data | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 63 | [textures_particles_blending](textures/textures_particles_blending.c) | textures_particles_blending | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | +| 64 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | textures_npatch_drawing | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) | +| 65 | [textures_background_scrolling](textures/textures_background_scrolling.c) | textures_background_scrolling | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | +| 66 | [textures_sprite_anim](textures/textures_sprite_anim.c) | textures_sprite_anim | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | +| 67 | [textures_sprite_button](textures/textures_sprite_button.c) | textures_sprite_button | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | +| 68 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | textures_sprite_explosion | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 69 | [textures_bunnymark](textures/textures_bunnymark.c) | textures_bunnymark | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) | +| 70 | [textures_mouse_painting](textures/textures_mouse_painting.c) | textures_mouse_painting | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | +| 71 | [textures_blend_modes](textures/textures_blend_modes.c) | textures_blend_modes | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) | +| 72 | [textures_draw_tiled](textures/textures_draw_tiled.c) | textures_draw_tiled | ⭐️⭐️⭐️☆ | 3.0 | 4.2 | [Vlad Adrian](https://github.com/demizdor) | +| 73 | [textures_polygon](textures/textures_polygon.c) | textures_polygon | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | +| 74 | [textures_fog_of_war](textures/textures_fog_of_war.c) | textures_fog_of_war | ⭐️⭐️⭐️☆ | 4.2 | 4.2 | [Ray](https://github.com/raysan5) | +| 75 | [textures_gif_player](textures/textures_gif_player.c) | textures_gif_player | ⭐️⭐️⭐️☆ | 4.2 | 4.2 | [Ray](https://github.com/raysan5) | +| 76 | [textures_image_kernel](textures/textures_image_kernel.c) | textures_image_kernel | ⭐️⭐️⭐️⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) | +| 77 | [textures_image_channel](textures/textures_image_channel.c) | textures_image_channel | ⭐️⭐️☆☆ | 5.1-dev | 5.1-dev | [Bruno Cabral](https://github.com/brccabral) | +| 78 | [textures_image_rotate](textures/textures_image_rotate.c) | textures_image_rotate | ⭐️⭐️☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 79 | [textures_textured_curve](textures/textures_textured_curve.c) | textures_textured_curve | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) | ### category: text Examples using raylib text functionality, including sprite fonts loading/generation and text drawing, provided by raylib [text](../src/text.c) module. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 73 | [text_raylib_fonts](text/text_raylib_fonts.c) | text_raylib_fonts | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | -| 74 | [text_font_spritefont](text/text_font_spritefont.c) | text_font_spritefont | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | -| 75 | [text_font_filters](text/text_font_filters.c) | text_font_filters | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | -| 76 | [text_font_loading](text/text_font_loading.c) | text_font_loading | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) | -| 77 | [text_font_sdf](text/text_font_sdf.c) | text_font_sdf | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 78 | [text_format_text](text/text_format_text.c) | text_format_text | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) | -| 79 | [text_input_box](text/text_input_box.c) | text_input_box | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | -| 80 | [text_writing_anim](text/text_writing_anim.c) | text_writing_anim | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | -| 81 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | text_rectangle_bounds | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 82 | [text_unicode](text/text_unicode.c) | text_unicode | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 83 | [text_draw_3d](text/text_draw_3d.c) | text_draw_3d | ⭐️⭐️⭐️⭐️ | 3.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | -| 84 | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 80 | [text_raylib_fonts](text/text_raylib_fonts.c) | text_raylib_fonts | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | +| 81 | [text_font_spritefont](text/text_font_spritefont.c) | text_font_spritefont | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | +| 82 | [text_font_filters](text/text_font_filters.c) | text_font_filters | ⭐️⭐️☆☆ | 1.3 | 4.2 | [Ray](https://github.com/raysan5) | +| 83 | [text_font_loading](text/text_font_loading.c) | text_font_loading | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) | +| 84 | [text_font_sdf](text/text_font_sdf.c) | text_font_sdf | ⭐️⭐️⭐️☆ | 1.3 | 4.0 | [Ray](https://github.com/raysan5) | +| 85 | [text_format_text](text/text_format_text.c) | text_format_text | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) | +| 86 | [text_input_box](text/text_input_box.c) | text_input_box | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | +| 87 | [text_writing_anim](text/text_writing_anim.c) | text_writing_anim | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | +| 88 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | text_rectangle_bounds | ⭐️⭐️⭐️⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | +| 89 | [text_unicode](text/text_unicode.c) | text_unicode | ⭐️⭐️⭐️⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | +| 90 | [text_draw_3d](text/text_draw_3d.c) | text_draw_3d | ⭐️⭐️⭐️⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | +| 91 | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐️⭐️⭐️☆ | 4.2 | 4.2 | [Ray](https://github.com/raysan5) | ### category: models Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/models.c) module. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 85 | [models_animation](models/models_animation.c) | models_animation | ⭐️⭐️☆☆ | 2.5 | 3.5 | [culacant](https://github.com/culacant) | -| 86 | [models_billboard](models/models_billboard.c) | models_billboard | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 87 | [models_box_collisions](models/models_box_collisions.c) | models_box_collisions | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | -| 88 | [models_cubicmap](models/models_cubicmap.c) | models_cubicmap | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | -| 89 | [models_first_person_maze](models/models_first_person_maze.c) | models_first_person_maze | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 90 | [models_geometric_shapes](models/models_geometric_shapes.c) | models_geometric_shapes | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) | -| 91 | [models_mesh_generation](models/models_mesh_generation.c) | models_mesh_generation | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | -| 92 | [models_mesh_picking](models/models_mesh_picking.c) | models_mesh_picking | ⭐️⭐️⭐️☆ | 1.7 | **4.0** | [Joel Davis](https://github.com/joeld42) | -| 93 | [models_loading](models/models_loading.c) | models_loading | ⭐️☆☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 94 | [models_loading_gltf](models/models_loading_gltf.c) | models_loading_gltf | ⭐️☆☆☆ | 3.7 | **4.2** | [Ray](https://github.com/raysan5) | -| 95 | [models_loading_vox](models/models_loading_vox.c) | models_loading_vox | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) | -| 96 | [models_loading_m3d](models/models_loading_m3d.c) | models_loading_m3d | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) | -| 97 | [models_orthographic_projection](models/models_orthographic_projection.c) | models_orthographic_projection | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | -| 98 | [models_point_rendering](models/models_point_rendering.c) | models_point_rendering | ⭐️⭐️☆☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) | -| 99 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | -| 100 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | -| 101 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | -| 102 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | -| 103 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 92 | [models_animation](models/models_animation.c) | models_animation | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Culacant](https://github.com/culacant) | +| 93 | [models_billboard](models/models_billboard.c) | models_billboard | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 94 | [models_box_collisions](models/models_box_collisions.c) | models_box_collisions | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | +| 95 | [models_cubicmap](models/models_cubicmap.c) | models_cubicmap | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | +| 96 | [models_first_person_maze](models/models_first_person_maze.c) | models_first_person_maze | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 97 | [models_geometric_shapes](models/models_geometric_shapes.c) | models_geometric_shapes | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) | +| 98 | [models_mesh_generation](models/models_mesh_generation.c) | models_mesh_generation | ⭐️⭐️☆☆ | 1.8 | 4.0 | [Ray](https://github.com/raysan5) | +| 99 | [models_mesh_picking](models/models_mesh_picking.c) | models_mesh_picking | ⭐️⭐️⭐️☆ | 1.7 | 4.0 | [Joel Davis](https://github.com/joeld42) | +| 100 | [models_loading](models/models_loading.c) | models_loading | ⭐️☆☆☆ | 2.0 | 4.2 | [Ray](https://github.com/raysan5) | +| 101 | [models_loading_gltf](models/models_loading_gltf.c) | models_loading_gltf | ⭐️☆☆☆ | 3.7 | 4.2 | [Ray](https://github.com/raysan5) | +| 102 | [models_loading_vox](models/models_loading_vox.c) | models_loading_vox | ⭐️☆☆☆ | 4.0 | 4.0 | [Johann Nadalutti](https://github.com/procfxgen) | +| 103 | [models_loading_m3d](models/models_loading_m3d.c) | models_loading_m3d | ⭐️⭐️☆☆ | 4.5 | 4.5 | [bzt](https://bztsrc.gitlab.io/model3d) | +| 104 | [models_orthographic_projection](models/models_orthographic_projection.c) | models_orthographic_projection | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | +| 105 | [models_point_rendering](models/models_point_rendering.c) | models_point_rendering | ⭐️⭐️⭐️☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) | +| 106 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | models_rlgl_solar_system | ⭐️⭐️⭐️⭐️ | 2.5 | 4.0 | [Ray](https://github.com/raysan5) | +| 107 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | models_yaw_pitch_roll | ⭐️⭐️☆☆ | 1.8 | 4.0 | [Berni](https://github.com/Berni8k) | +| 108 | [models_waving_cubes](models/models_waving_cubes.c) | models_waving_cubes | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Codecat](https://github.com/codecat) | +| 109 | [models_heightmap](models/models_heightmap.c) | models_heightmap | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | +| 110 | [models_skybox](models/models_skybox.c) | models_skybox | ⭐️⭐️☆☆ | 1.8 | 4.0 | [Ray](https://github.com/raysan5) | +| 111 | [models_draw_cube_texture](models/models_draw_cube_texture.c) | models_draw_cube_texture | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Ray](https://github.com/raysan5) | +| 112 | [models_gpu_skinning](models/models_gpu_skinning.c) | models_gpu_skinning | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) | +| 113 | [models_bone_socket](models/models_bone_socket.c) | models_bone_socket | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) | +| 114 | [models_tesseract_view](models/models_tesseract_view.c) | models_tesseract_view | ⭐️⭐️☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) | ### category: shaders Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 104 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | -| 105 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | -| 106 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | -| 107 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 108 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | -| 109 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | -| 110 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | -| 111 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | -| 112 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | -| 113 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | -| 114 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | -| 115 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | -| 116 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 117 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 118 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | -| 119 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | -| 120 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 121 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | -| 122 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 115 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | shaders_basic_lighting | ⭐️⭐️⭐️⭐️ | 3.0 | 4.2 | [Chris Camacho](https://github.com/chriscamacho) | +| 116 | [shaders_model_shader](shaders/shaders_model_shader.c) | shaders_model_shader | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | +| 117 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | shaders_shapes_textures | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | +| 118 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | shaders_custom_uniform | ⭐️⭐️☆☆ | 1.3 | 4.0 | [Ray](https://github.com/raysan5) | +| 119 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | shaders_postprocessing | ⭐️⭐️⭐️☆ | 1.3 | 4.0 | [Ray](https://github.com/raysan5) | +| 120 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | shaders_palette_switch | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | +| 121 | [shaders_raymarching](shaders/shaders_raymarching.c) | shaders_raymarching | ⭐️⭐️⭐️⭐️ | 2.0 | 4.2 | [Ray](https://github.com/raysan5) | +| 122 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | shaders_texture_drawing | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/ciessielski) | +| 123 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐️⭐️⭐️☆ | 4.0 | 4.0 | [Samuel Skiff](https://github.com/GoldenThumbs) | +| 124 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | +| 125 | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐️⭐️⭐️☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) | +| 126 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | shaders_eratosthenes | ⭐️⭐️⭐️☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) | +| 127 | [shaders_fog](shaders/shaders_fog.c) | shaders_fog | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | +| 128 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | +| 129 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | shaders_hot_reloading | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | +| 130 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | shaders_mesh_instancing | ⭐️⭐️⭐️⭐️ | 3.7 | 4.2 | [seanpringle](https://github.com/seanpringle) | +| 131 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | shaders_multi_sample2d | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 132 | [shaders_spotlight](shaders/shaders_spotlight.c) | shaders_spotlight | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | +| 133 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | shaders_deferred_render | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | +| 134 | [shaders_hybrid_render](shaders/shaders_hybrid_render.c) | shaders_hybrid_render | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) | +| 135 | [shaders_texture_tiling](shaders/shaders_texture_tiling.c) | shaders_texture_tiling | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Luis Almeida](https://github.com/luis605) | +| 136 | [shaders_shadowmap](shaders/shaders_shadowmap.c) | shaders_shadowmap | ⭐️⭐️⭐️⭐️ | 5.0 | 5.0 | [TheManTheMythTheGameDev](https://github.com/TheManTheMythTheGameDev) | +| 137 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | shaders_vertex_displacement | ⭐️⭐️⭐️☆ | 5.0 | 4.5 | [Alex ZH](https://github.com/ZzzhHe) | +| 138 | [shaders_write_depth](shaders/shaders_write_depth.c) | shaders_write_depth | ⭐️⭐️☆☆ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) | +| 139 | [shaders_basic_pbr](shaders/shaders_basic_pbr.c) | shaders_basic_pbr | ⭐️⭐️⭐️⭐️ | 5.0 | 5.1-dev | [Afan OLOVCIC](https://github.com/_DevDad) | +| 140 | [shaders_lightmap](shaders/shaders_lightmap.c) | shaders_lightmap | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | ### category: audio Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib, check [raudio_standalone](others/raudio_standalone.c) example. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 123 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 124 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | -| 125 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) | -| 126 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 141 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 142 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | 4.2 | [Ray](https://github.com/raysan5) | +| 143 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | 4.2 | [Ray](https://github.com/raysan5) | +| 144 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | +| 145 | [audio_mixed_processor](audio/audio_mixed_processor.c) | audio_mixed_processor | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) | +| 146 | [audio_stream_effects](audio/audio_stream_effects.c) | audio_stream_effects | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) | +| 147 | [audio_sound_multi](audio/audio_sound_multi.c) | audio_sound_multi | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) | ### category: others Examples showing raylib misc functionality that does not fit in other categories, like standalone modules usage or examples integrating external libraries. | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | -|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| -| 127 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) | -| 128 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) | -| 129 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | -| 130 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) | -| 131 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | +|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| +| 148 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | 4.0 | [Ray](https://github.com/raysan5) | +| 149 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) | +| 150 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | +| 151 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) | +| 152 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | +| 153 | [raymath_vector_angle](others/raymath_vector_angle.c) | raymath_vector_angle | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) | As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with! diff --git a/examples/core/core_basic_window_web.c b/examples/core/core_basic_window_web.c index 251544795..e8607432b 100644 --- a/examples/core/core_basic_window_web.c +++ b/examples/core/core_basic_window_web.c @@ -2,6 +2,8 @@ * * raylib [core] example - Basic window (adapted for HTML5 platform) * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: This example is prepared to compile for PLATFORM_WEB, and PLATFORM_DESKTOP * As you will notice, code structure is slightly diferent to the other examples... * To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning diff --git a/examples/core/core_input_gestures_web.c b/examples/core/core_input_gestures_web.c index b81aa07ab..613aff0ab 100644 --- a/examples/core/core_input_gestures_web.c +++ b/examples/core/core_input_gestures_web.c @@ -2,6 +2,8 @@ * * raylib [core] example - Input Gestures for Web * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.6-dev, last time updated with raylib 4.6-dev * * Example contributed by ubkp (@ubkp) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_input_virtual_controls.c b/examples/core/core_input_virtual_controls.c index 282c3b07d..80d9f0b3b 100644 --- a/examples/core/core_input_virtual_controls.c +++ b/examples/core/core_input_virtual_controls.c @@ -2,6 +2,8 @@ * * raylib [core] example - input virtual controls * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example create by GreenSnakeLinux (@GreenSnakeLinux), @@ -12,7 +14,7 @@ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2024-2025 Ramon Santamaria (@raysan5) +* Copyright (c) 2024-2025 oblerion (@oblerion) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_random_sequence.c b/examples/core/core_random_sequence.c index 4d245fbcc..1aa0a068c 100644 --- a/examples/core/core_random_sequence.c +++ b/examples/core/core_random_sequence.c @@ -2,6 +2,8 @@ * * raylib [core] example - Generates a random sequence * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example contributed by Dalton Overmyer (@REDl3east) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_bone_socket.c b/examples/models/models_bone_socket.c index ffcf048d5..ceea21b8c 100644 --- a/examples/models/models_bone_socket.c +++ b/examples/models/models_bone_socket.c @@ -1,6 +1,8 @@ /******************************************************************************************* * * raylib [core] example - Using bones as socket for calculating the positioning of something +* +* Example complexity rating: [★★★★] 4/4 * * Example originally created with raylib 4.5, last time updated with raylib 4.5 * diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index b92d1251d..c268d25d1 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -1,6 +1,8 @@ /******************************************************************************************* * * raylib [core] example - Doing skinning on the gpu using a vertex shader +* +* Example complexity rating: [★★★☆] 3/4 * * Example originally created with raylib 4.5, last time updated with raylib 4.5 * diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index c74b18a46..b7bf96742 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -2,6 +2,8 @@ * * raylib example - point rendering * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example contributed by Reese Gallagher (@satchelfrost) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_tesseract_view.c b/examples/models/models_tesseract_view.c index a166dcc9c..44484ca5b 100644 --- a/examples/models/models_tesseract_view.c +++ b/examples/models/models_tesseract_view.c @@ -4,6 +4,8 @@ * * NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * * Example contributed by Timothy van der Valk (@arceryz) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/others/easings_testbed.c b/examples/others/easings_testbed.c index 5ae33f12f..e3fa0e84b 100644 --- a/examples/others/easings_testbed.c +++ b/examples/others/easings_testbed.c @@ -4,6 +4,8 @@ * * Example originally created with raylib 2.5, last time updated with raylib 2.5 * +* Example complexity rating: [★★★☆] 3/4 +* * Example contributed by Juan Miguel López (@flashback-fx) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/others/embedded_files_loading.c b/examples/others/embedded_files_loading.c index efe5c1af5..8a66b4394 100644 --- a/examples/others/embedded_files_loading.c +++ b/examples/others/embedded_files_loading.c @@ -2,6 +2,8 @@ * * raylib [others] example - Embedded files loading (Wave and Image) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 3.0, last time updated with raylib 2.5 * * Example contributed by Kristian Holmgren (@defutura) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/others/raylib_opengl_interop.c b/examples/others/raylib_opengl_interop.c index 696ec85d7..9ab2bb220 100644 --- a/examples/others/raylib_opengl_interop.c +++ b/examples/others/raylib_opengl_interop.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - OpenGL point particle system * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 3.8, last time updated with raylib 2.5 * * Example contributed by Stephan Soller (@arkanis) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/others/raymath_vector_angle.c b/examples/others/raymath_vector_angle.c index 3cfdfc6d2..414546ac6 100644 --- a/examples/others/raymath_vector_angle.c +++ b/examples/others/raymath_vector_angle.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Vector Angle * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.0, last time updated with raylib 4.6 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/others/rlgl_compute_shader.c b/examples/others/rlgl_compute_shader.c index 0e39281e7..b17ba711a 100644 --- a/examples/others/rlgl_compute_shader.c +++ b/examples/others/rlgl_compute_shader.c @@ -5,6 +5,8 @@ * NOTE: This example requires raylib OpenGL 4.3 versions for compute shaders support, * shaders used in this example are #version 430 (OpenGL 4.3) * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.0, last time updated with raylib 2.5 * * Example contributed by Teddy Astie (@tsnake41) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index 9bb570ec4..713d1b908 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -5,6 +5,8 @@ * rlgl library is an abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) * that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 1.6, last time updated with raylib 4.0 * * WARNING: This example is intended only for PLATFORM_DESKTOP and OpenGL 3.3 Core profile. diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c index eac7ac6e4..f115338a5 100644 --- a/examples/shaders/shaders_basic_lighting.c +++ b/examples/shaders/shaders_basic_lighting.c @@ -11,12 +11,12 @@ * * Example originally created with raylib 3.0, last time updated with raylib 4.2 * -* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2019-2025 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* Copyright (c) 2019-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c index a35947cdc..e595ef9ca 100644 --- a/examples/shaders/shaders_basic_pbr.c +++ b/examples/shaders/shaders_basic_pbr.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Basic PBR * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.1-dev * * Example contributed by Afan OLOVCIC (@_DevDad) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_shadowmap.c b/examples/shaders/shaders_shadowmap.c index fcd2ec96d..4910b0908 100644 --- a/examples/shaders/shaders_shadowmap.c +++ b/examples/shaders/shaders_shadowmap.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Shadowmap * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example contributed by TheManTheMythTheGameDev (@TheManTheMythTheGameDev) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_vertex_displacement.c b/examples/shaders/shaders_vertex_displacement.c index 78c97e4d8..8008bc004 100644 --- a/examples/shaders/shaders_vertex_displacement.c +++ b/examples/shaders/shaders_vertex_displacement.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Vertex displacement * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 4.5 * * Example contributed by Alex ZH (@ZzzhHe) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_image_channel.c b/examples/textures/textures_image_channel.c index 55c8b38fa..cebe61651 100644 --- a/examples/textures/textures_image_channel.c +++ b/examples/textures/textures_image_channel.c @@ -4,6 +4,8 @@ * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 5.1-dev, last time updated with raylib 5.1-dev * * Example contributed by Bruno Cabral (@brccabral) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_image_kernel.c b/examples/textures/textures_image_kernel.c index 67e073ec8..456cd1c18 100644 --- a/examples/textures/textures_image_kernel.c +++ b/examples/textures/textures_image_kernel.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image loading and texture creation * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example contributed by Karim Salem (@kimo-s) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_image_rotate.c b/examples/textures/textures_image_rotate.c index c08d46a3f..4921dc8ac 100644 --- a/examples/textures/textures_image_rotate.c +++ b/examples/textures/textures_image_rotate.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image Rotation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_polygon.c b/examples/textures/textures_polygon.c index 4d114ab96..759f2b420 100644 --- a/examples/textures/textures_polygon.c +++ b/examples/textures/textures_polygon.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 3.7, last time updated with raylib 3.7 * -* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2021-2025 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* Copyright (c) 2021-2025 Chris Camacho (@chriscamacho) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ From 77c509db6ef2fec8e46593fd05c1fa69e5955cb8 Mon Sep 17 00:00:00 2001 From: Anthony Carbajal <5776225+CrackedPixel@users.noreply.github.com> Date: Mon, 20 Jan 2025 05:14:18 -0600 Subject: [PATCH 18/39] removed hardcoded sleep (#4713) --- src/platforms/rcore_web.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 4faf5b87f..55f5f11a0 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -154,14 +154,15 @@ static const char *GetCanvasId(void); //---------------------------------------------------------------------------------- // Check if application should close +// This will always return false on a web-build as web builds have no control over this functionality +// Sleep is handled in EndDrawing for sync code bool WindowShouldClose(void) { // Emterpreter-Async required to run sync code // https://github.com/emscripten-core/emscripten/wiki/Emterpreter#emterpreter-async-run-synchronous-code - // By default, this function is never called on a web-ready raylib example because we encapsulate - // frame code in a UpdateDrawFrame() function, to allow browser manage execution asynchronously - // but now emscripten allows sync code to be executed in an interpreted way, using emterpreter! - emscripten_sleep(16); + // This function should not called on a web-ready raylib build because you instead want to encapsulate + // frame code in an UpdateDrawFrame() function, to allow the browser to manage execution asynchronously + // using emscripten_set_main_loop return false; } From d48b8afbb5b01241bc85017d168965bdd5d2b6d8 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 Jan 2025 14:01:57 +0100 Subject: [PATCH 19/39] Update rcore_web.c --- src/platforms/rcore_web.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 55f5f11a0..ee10eb5d7 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -155,14 +155,20 @@ static const char *GetCanvasId(void); // Check if application should close // This will always return false on a web-build as web builds have no control over this functionality -// Sleep is handled in EndDrawing for sync code +// Sleep is handled in EndDrawing() for synchronous code bool WindowShouldClose(void) { - // Emterpreter-Async required to run sync code - // https://github.com/emscripten-core/emscripten/wiki/Emterpreter#emterpreter-async-run-synchronous-code - // This function should not called on a web-ready raylib build because you instead want to encapsulate - // frame code in an UpdateDrawFrame() function, to allow the browser to manage execution asynchronously - // using emscripten_set_main_loop + // Emscripten Asyncify is required to run synchronous code in asynchronous JS + // REF: https://emscripten.org/docs/porting/asyncify.html + + // WindowShouldClose() is not called on a web-ready raylib application if using emscripten_set_main_loop() + // and encapsulating one frame execution on a UpdateDrawFrame() function, + // allowing the browser to manage execution asynchronously + + // Optionally we can manage the time we give-control-back-to-browser if required, + // but it seems below line could generate stuttering on some browsers + //emscripten_sleep(16); + return false; } From 2c50da9a6ab38d9fac3d0525ddf19b79b6693275 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Jan 2025 19:18:23 +0100 Subject: [PATCH 20/39] REVIEWED: -sASSERTIONS usage by linker #4717 --- examples/Makefile | 3 --- examples/Makefile.Web | 3 --- src/Makefile | 7 ++++++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 834007c26..407abd793 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -233,9 +233,6 @@ CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -D_DEBUG - ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) - CFLAGS += -sASSERTIONS=1 --profiling - endif else ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) diff --git a/examples/Makefile.Web b/examples/Makefile.Web index c9becc29b..32d6daa57 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -189,9 +189,6 @@ CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -D_DEBUG - ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) - CFLAGS += -sASSERTIONS=1 --profiling - endif else ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) diff --git a/src/Makefile b/src/Makefile index a626db52e..eef157012 100644 --- a/src/Makefile +++ b/src/Makefile @@ -384,7 +384,7 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R # --source-map-base # allow debugging in browser with source map # --shell-file shell.html # define a custom shell .html and output extension ifeq ($(RAYLIB_BUILD_MODE),DEBUG) - CFLAGS += -sASSERTIONS=1 --profiling + CFLAGS += --profiling endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) @@ -533,6 +533,11 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) LDFLAGS += -L$(SDL_LIBRARY_PATH) endif +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) + ifeq ($(RAYLIB_BUILD_MODE),DEBUG) + LDFLAGS += -sASSERTIONS=1 + endif +endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) ifeq ($(USE_RPI_CROSSCOMPILER), TRUE) From 322ba54c084bba13e48453b0832151af43555962 Mon Sep 17 00:00:00 2001 From: sleeptightAnsiC <91839286+sleeptightAnsiC@users.noreply.github.com> Date: Tue, 21 Jan 2025 19:20:51 +0100 Subject: [PATCH 21/39] Fix(WEB): Makefile: throw an error when trying to build SHARED library (#4718) When asking Makefile to create SHARED library for WEB $ make TARGET_PLATFORM=PLATFORM_WEB RAYLIB_LIBTYPE=SHARED it would instead silently create STATIC library thus not fulfilling the request as expected This commit adds an error in this case and stops further execution. This is not consistent with Cmake, because Cmake throws the warning and does not stop, but Cmake can easily recover from this case and people probably does not even notice it. However, Makefile is something that you have to handle yourself and you have to recover from any issues so having an error and aborting with exit code 1 is more expected. Otherwise people may spend a lot of time debugging Makefile in order to understand what's even going on. Fixes: https://github.com/raysan5/raylib/issues/4717 --- src/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index eef157012..2d2a3e83c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -670,6 +670,9 @@ raylib: $(OBJS) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Compile raylib libray for web #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + @echo "Error: $(TARGET_PLATFORM) does not support SHARED libraries. Try RAYLIB_LIBTYPE=STATIC instead." && exit 1 + endif $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(OBJS) @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).web.a)!" else @@ -828,7 +831,7 @@ ifeq ($(ROOT),root) @echo "This function currently works on GNU/Linux systems. Add yours today (^;" endif else - @echo "Error: Root permissions needed for installation. Try sudo make install" + @echo "Error: Root permissions needed for installation. Try sudo make install" && exit 1 endif # Remove raylib dev files installed on the system @@ -855,7 +858,7 @@ ifeq ($(ROOT),root) @echo "This function currently works on GNU/Linux systems. Add yours today (^;" endif else - @echo "Error: Root permissions needed for uninstallation. Try sudo make uninstall" + @echo "Error: Root permissions needed for uninstallation. Try sudo make uninstall" && exit 1 endif .PHONY: clean_shell_cmd clean_shell_sh From 87f17538d0103e4a863d23860c4bc0400fe12792 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Jan 2025 19:23:16 +0100 Subject: [PATCH 22/39] Reviewed warning on shared library generation for web --- src/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2d2a3e83c..b05b257d3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -671,7 +671,7 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R # Compile raylib libray for web #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc ifeq ($(RAYLIB_LIBTYPE),SHARED) - @echo "Error: $(TARGET_PLATFORM) does not support SHARED libraries. Try RAYLIB_LIBTYPE=STATIC instead." && exit 1 + @echo "WARNING: $(TARGET_PLATFORM) does not support SHARED libraries. Generating STATIC library." endif $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(OBJS) @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).web.a)!" @@ -831,7 +831,7 @@ ifeq ($(ROOT),root) @echo "This function currently works on GNU/Linux systems. Add yours today (^;" endif else - @echo "Error: Root permissions needed for installation. Try sudo make install" && exit 1 + @echo "ERROR: Root permissions needed for installation. Try sudo make install" && exit 1 endif # Remove raylib dev files installed on the system @@ -858,7 +858,7 @@ ifeq ($(ROOT),root) @echo "This function currently works on GNU/Linux systems. Add yours today (^;" endif else - @echo "Error: Root permissions needed for uninstallation. Try sudo make uninstall" && exit 1 + @echo "ERROR: Root permissions needed for uninstallation. Try sudo make uninstall" && exit 1 endif .PHONY: clean_shell_cmd clean_shell_sh From 7bfc8e8ca75882de434c601c4294ca1774b69278 Mon Sep 17 00:00:00 2001 From: Anstro Pleuton <121956207+anstropleuton@users.noreply.github.com> Date: Thu, 23 Jan 2025 01:51:36 -0800 Subject: [PATCH 23/39] [example] Add shaders_rounded_rectangle example (#4719) * Add shaders_rounded_rectangle example * Minor tweaks to example template (add star, more) * Combine shaders * Fix changes after review --------- Co-authored-by: Anstro Pleuton --- examples/Makefile | 1 + examples/Makefile.Web | 1 + examples/README.md | 27 +- examples/examples_template.c | 6 +- .../shaders/glsl100/rounded_rectangle.fs | 76 ++++ .../shaders/glsl120/rounded_rectangle.fs | 74 ++++ .../shaders/glsl330/rounded_rectangle.fs | 77 ++++ examples/shaders/shaders_rounded_rectangle.c | 238 +++++++++++ .../shaders/shaders_rounded_rectangle.png | Bin 0 -> 13936 bytes .../shaders_rounded_rectangle.vcxproj | 387 ++++++++++++++++++ projects/VS2022/raylib.sln | 19 + 11 files changed, 891 insertions(+), 15 deletions(-) create mode 100644 examples/shaders/resources/shaders/glsl100/rounded_rectangle.fs create mode 100644 examples/shaders/resources/shaders/glsl120/rounded_rectangle.fs create mode 100644 examples/shaders/resources/shaders/glsl330/rounded_rectangle.fs create mode 100644 examples/shaders/shaders_rounded_rectangle.c create mode 100644 examples/shaders/shaders_rounded_rectangle.png create mode 100644 projects/VS2022/examples/shaders_rounded_rectangle.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 407abd793..0a2c908a3 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -634,6 +634,7 @@ SHADERS = \ shaders/shaders_palette_switch \ shaders/shaders_postprocessing \ shaders/shaders_raymarching \ + shaders/shaders_rounded_rectangle \ shaders/shaders_shadowmap \ shaders/shaders_shapes_textures \ shaders/shaders_simple_mask \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 32d6daa57..6f060652f 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -514,6 +514,7 @@ SHADERS = \ shaders/shaders_palette_switch \ shaders/shaders_postprocessing \ shaders/shaders_raymarching \ + shaders/shaders_rounded_rectangle \ shaders/shaders_shadowmap \ shaders/shaders_shapes_textures \ shaders/shaders_simple_mask \ diff --git a/examples/README.md b/examples/README.md index ba14d82dd..c42a701a2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -199,6 +199,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete | 138 | [shaders_write_depth](shaders/shaders_write_depth.c) | shaders_write_depth | ⭐️⭐️☆☆ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) | | 139 | [shaders_basic_pbr](shaders/shaders_basic_pbr.c) | shaders_basic_pbr | ⭐️⭐️⭐️⭐️ | 5.0 | 5.1-dev | [Afan OLOVCIC](https://github.com/_DevDad) | | 140 | [shaders_lightmap](shaders/shaders_lightmap.c) | shaders_lightmap | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | +| 141 | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | shaders_rounded_rectangle | ⭐️⭐️⭐️☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | ### category: audio @@ -206,13 +207,13 @@ Examples using raylib audio functionality, including sound/music loading and pla | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| -| 141 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | -| 142 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | 4.2 | [Ray](https://github.com/raysan5) | -| 143 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | 4.2 | [Ray](https://github.com/raysan5) | -| 144 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | -| 145 | [audio_mixed_processor](audio/audio_mixed_processor.c) | audio_mixed_processor | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) | -| 146 | [audio_stream_effects](audio/audio_stream_effects.c) | audio_stream_effects | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) | -| 147 | [audio_sound_multi](audio/audio_sound_multi.c) | audio_sound_multi | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) | +| 142 | [audio_module_playing](audio/audio_module_playing.c) | audio_module_playing | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | +| 143 | [audio_music_stream](audio/audio_music_stream.c) | audio_music_stream | ⭐️☆☆☆ | 1.3 | 4.2 | [Ray](https://github.com/raysan5) | +| 144 | [audio_raw_stream](audio/audio_raw_stream.c) | audio_raw_stream | ⭐️⭐️⭐️☆ | 1.6 | 4.2 | [Ray](https://github.com/raysan5) | +| 145 | [audio_sound_loading](audio/audio_sound_loading.c) | audio_sound_loading | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | +| 146 | [audio_mixed_processor](audio/audio_mixed_processor.c) | audio_mixed_processor | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) | +| 147 | [audio_stream_effects](audio/audio_stream_effects.c) | audio_stream_effects | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) | +| 148 | [audio_sound_multi](audio/audio_sound_multi.c) | audio_sound_multi | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) | ### category: others @@ -220,12 +221,12 @@ Examples showing raylib misc functionality that does not fit in other categories | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| -| 148 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | 4.0 | [Ray](https://github.com/raysan5) | -| 149 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) | -| 150 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | -| 151 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) | -| 152 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | -| 153 | [raymath_vector_angle](others/raymath_vector_angle.c) | raymath_vector_angle | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) | +| 149 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | 4.0 | [Ray](https://github.com/raysan5) | +| 150 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) | +| 151 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | +| 152 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) | +| 153 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | +| 154 | [raymath_vector_angle](others/raymath_vector_angle.c) | raymath_vector_angle | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) | As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with! diff --git a/examples/examples_template.c b/examples/examples_template.c index 0a44117b4..49136a4d4 100644 --- a/examples/examples_template.c +++ b/examples/examples_template.c @@ -56,7 +56,9 @@ /******************************************************************************************* * -* raylib [core] example - Basic window +* raylib [] example - +* +* Example complexity rating: [★☆??] ?/4 * * Example originally created with raylib 5.5, last time updated with raylib 5.5 * @@ -81,7 +83,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); + InitWindow(screenWidth, screenHeight, "raylib [] example - "); // TODO: Load resources / Initialize variables at this point diff --git a/examples/shaders/resources/shaders/glsl100/rounded_rectangle.fs b/examples/shaders/resources/shaders/glsl100/rounded_rectangle.fs new file mode 100644 index 000000000..3c8d07978 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/rounded_rectangle.fs @@ -0,0 +1,76 @@ +// Note: SDF by Iñigo Quilez is licensed under MIT License + +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height) +uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right) +uniform vec4 color; + +// Shadow parameters +uniform float shadowRadius; +uniform vec2 shadowOffset; +uniform float shadowScale; +uniform vec4 shadowColor; + +// Border parameters +uniform float borderThickness; +uniform vec4 borderColor; + +// Create a rounded rectangle using signed distance field +// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) +// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader +// MIT License +float RoundedRectangleSDF(vec2 fragCoord, vec2 center, vec2 halfSize, vec4 radius) +{ + vec2 fragFromCenter = fragCoord - center; + + // Determine which corner radius to use + radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw; + radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y; + + // Calculate signed distance field + vec2 dist = abs(fragFromCenter) - halfSize + radius.x; + return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x; +} + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + // Requires fragment coordinate varying pixels + vec2 fragCoord = gl_FragCoord.xy; + + // Calculate signed distance field for rounded rectangle + vec2 halfSize = rectangle.zw*0.5; + vec2 center = rectangle.xy + halfSize; + float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius); + + // Calculate signed distance field for rectangle shadow + vec2 shadowHalfSize = halfSize*shadowScale; + vec2 shadowCenter = center + shadowOffset; + float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius); + + // Caculate alpha factors + float recFactor = smoothstep(1.0, 0.0, recSDF); + float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF); + float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor; + + // Multiply each color by its respective alpha factor + vec4 recColor = vec4(color.rgb, color.a*recFactor); + vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor); + vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor); + + // Combine the colors varying the order (shadow, rectangle, border) + gl_FragColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl120/rounded_rectangle.fs b/examples/shaders/resources/shaders/glsl120/rounded_rectangle.fs new file mode 100644 index 000000000..eb96c28d3 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/rounded_rectangle.fs @@ -0,0 +1,74 @@ +// Note: SDF by Iñigo Quilez is licensed under MIT License + +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height) +uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right) +uniform vec4 color; + +// Shadow parameters +uniform float shadowRadius; +uniform vec2 shadowOffset; +uniform float shadowScale; +uniform vec4 shadowColor; + +// Border parameters +uniform float borderThickness; +uniform vec4 borderColor; + +// Create a rounded rectangle using signed distance field +// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) +// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader +// MIT License +float RoundedRectangleSDF(vec2 fragCoord, vec2 center, vec2 halfSize, vec4 radius) +{ + vec2 fragFromCenter = fragCoord - center; + + // Determine which corner radius to use + radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw; + radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y; + + // Calculate signed distance field + vec2 dist = abs(fragFromCenter) - halfSize + radius.x; + return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x; +} + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture2D(texture0, fragTexCoord); + + // Requires fragment coordinate varying pixels + vec2 fragCoord = gl_FragCoord.xy; + + // Calculate signed distance field for rounded rectangle + vec2 halfSize = rectangle.zw*0.5; + vec2 center = rectangle.xy + halfSize; + float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius); + + // Calculate signed distance field for rectangle shadow + vec2 shadowHalfSize = halfSize*shadowScale; + vec2 shadowCenter = center + shadowOffset; + float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius); + + // Caculate alpha factors + float recFactor = smoothstep(1.0, 0.0, recSDF); + float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF); + float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor; + + // Multiply each color by its respective alpha factor + vec4 recColor = vec4(color.rgb, color.a*recFactor); + vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor); + vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor); + + // Combine the colors varying the order (shadow, rectangle, border) + gl_FragColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/rounded_rectangle.fs b/examples/shaders/resources/shaders/glsl330/rounded_rectangle.fs new file mode 100644 index 000000000..a96c31fab --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/rounded_rectangle.fs @@ -0,0 +1,77 @@ +// Note: SDF by Iñigo Quilez is licensed under MIT License + +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height) +uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right) +uniform vec4 color; + +// Shadow parameters +uniform float shadowRadius; +uniform vec2 shadowOffset; +uniform float shadowScale; +uniform vec4 shadowColor; + +// Border parameters +uniform float borderThickness; +uniform vec4 borderColor; + +// Create a rounded rectangle using signed distance field +// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) +// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader +// MIT License +float RoundedRectangleSDF(vec2 fragCoord, vec2 center, vec2 halfSize, vec4 radius) +{ + vec2 fragFromCenter = fragCoord - center; + + // Determine which corner radius to use + radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw; + radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y; + + // Calculate signed distance field + vec2 dist = abs(fragFromCenter) - halfSize + radius.x; + return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x; +} + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + + // Requires fragment coordinate in pixels + vec2 fragCoord = gl_FragCoord.xy; + + // Calculate signed distance field for rounded rectangle + vec2 halfSize = rectangle.zw*0.5; + vec2 center = rectangle.xy + halfSize; + float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius); + + // Calculate signed distance field for rectangle shadow + vec2 shadowHalfSize = halfSize*shadowScale; + vec2 shadowCenter = center + shadowOffset; + float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius); + + // Caculate alpha factors + float recFactor = smoothstep(1.0, 0.0, recSDF); + float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF); + float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor; + + // Multiply each color by its respective alpha factor + vec4 recColor = vec4(color.rgb, color.a*recFactor); + vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor); + vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor); + + // Combine the colors in the order (shadow, rectangle, border) + finalColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a); +} \ No newline at end of file diff --git a/examples/shaders/shaders_rounded_rectangle.c b/examples/shaders/shaders_rounded_rectangle.c new file mode 100644 index 000000000..754110d92 --- /dev/null +++ b/examples/shaders/shaders_rounded_rectangle.c @@ -0,0 +1,238 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Rounded Rectangle +* +* Example complexity rating: [★★★☆] 3/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.5 +* +* Example contributed by Anstro Pleuton (@anstropleuton) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2025-2025 Anstro Pleuton (@anstropleuton) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +//------------------------------------------------------------------------------------ +// Declare custom Structs +//------------------------------------------------------------------------------------ + +// Rounded rectangle data +typedef struct { + Vector4 cornerRadius; // Individual corner radius (top-left, top-right, bottom-left, bottom-right) + + // Shadow variables + float shadowRadius; + Vector2 shadowOffset; + float shadowScale; + + // Border variables + float borderThickness; // Inner-border thickness + + // Shader locations + int rectangleLoc; + int radiusLoc; + int colorLoc; + int shadowRadiusLoc; + int shadowOffsetLoc; + int shadowScaleLoc; + int shadowColorLoc; + int borderThicknessLoc; + int borderColorLoc; +} RoundedRectangle; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration +//------------------------------------------------------------------------------------ + +// Create a rounded rectangle and set uniform locations +static RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader); + +// Update rounded rectangle uniforms +static void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + const Color rectangleColor = BLUE; + const Color shadowColor = DARKBLUE; + const Color borderColor = SKYBLUE; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Rounded Rectangle"); + + // Load the shader + Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/rounded_rectangle.fs", GLSL_VERSION)); + + // Create a rounded rectangle + RoundedRectangle roundedRectangle = CreateRoundedRectangle( + (Vector4){ 5.0f, 10.0f, 15.0f, 20.0f }, // Corner radius + 20.0f, // Shadow radius + (Vector2){ 0.0f, -5.0f }, // Shadow offset + 0.95f, // Shadow scale + 5.0f, // Border thickness + shader // Shader + ); + + // Update shader uniforms + UpdateRoundedRectangle(roundedRectangle, shader); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw rectangle box with rounded corners using shader + Rectangle rec = { 50, 70, 110, 60 }; + DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY); + DrawText("Rounded rectangle", rec.x - 20, rec.y - 35, 10, DARKGRAY); + + // Flip Y axis to match shader coordinate system + rec.y = screenHeight - rec.y - rec.height; + SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4); + + // Only rectangle color + SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + + BeginShaderMode(shader); + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); + EndShaderMode(); + + + + // Draw rectangle shadow using shader + rec = (Rectangle){ 50, 200, 110, 60 }; + DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY); + DrawText("Rounded rectangle shadow", rec.x - 20, rec.y - 35, 10, DARKGRAY); + + rec.y = screenHeight - rec.y - rec.height; + SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4); + + // Only shadow color + SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + + BeginShaderMode(shader); + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); + EndShaderMode(); + + + + // Draw rectangle's border using shader + rec = (Rectangle){ 50, 330, 110, 60 }; + DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY); + DrawText("Rounded rectangle border", rec.x - 20, rec.y - 35, 10, DARKGRAY); + + rec.y = screenHeight - rec.y - rec.height; + SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4); + + // Only border color + SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4); + + BeginShaderMode(shader); + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); + EndShaderMode(); + + + + // Draw one more rectangle with all three colors + rec = (Rectangle){ 240, 80, 500, 300 }; + DrawRectangleLines(rec.x - 30, rec.y - 30, rec.width + 60, rec.height + 60, DARKGRAY); + DrawText("Rectangle with all three combined", rec.x - 30, rec.y - 45, 10, DARKGRAY); + + rec.y = screenHeight - rec.y - rec.height; + SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4); + + // All three colors + SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4); + + BeginShaderMode(shader); + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); + EndShaderMode(); + + DrawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", screenWidth - 300, screenHeight - 20, 10, BLACK); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions +//------------------------------------------------------------------------------------ + +// Create a rounded rectangle and set uniform locations +RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader) +{ + RoundedRectangle rec; + rec.cornerRadius = cornerRadius; + rec.shadowRadius = shadowRadius; + rec.shadowOffset = shadowOffset; + rec.shadowScale = shadowScale; + rec.borderThickness = borderThickness; + + // Get shader uniform locations + rec.rectangleLoc = GetShaderLocation(shader, "rectangle"); + rec.radiusLoc = GetShaderLocation(shader, "radius"); + rec.colorLoc = GetShaderLocation(shader, "color"); + rec.shadowRadiusLoc = GetShaderLocation(shader, "shadowRadius"); + rec.shadowOffsetLoc = GetShaderLocation(shader, "shadowOffset"); + rec.shadowScaleLoc = GetShaderLocation(shader, "shadowScale"); + rec.shadowColorLoc = GetShaderLocation(shader, "shadowColor"); + rec.borderThicknessLoc = GetShaderLocation(shader, "borderThickness"); + rec.borderColorLoc = GetShaderLocation(shader, "borderColor"); + + UpdateRoundedRectangle(rec, shader); + + return rec; +} + +// Update rounded rectangle uniforms +void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader) +{ + SetShaderValue(shader, rec.radiusLoc, (float[]){ rec.cornerRadius.x, rec.cornerRadius.y, rec.cornerRadius.z, rec.cornerRadius.w }, SHADER_UNIFORM_VEC4); + SetShaderValue(shader, rec.shadowRadiusLoc, &rec.shadowRadius, SHADER_UNIFORM_FLOAT); + SetShaderValue(shader, rec.shadowOffsetLoc, (float[]){ rec.shadowOffset.x, rec.shadowOffset.y }, SHADER_UNIFORM_VEC2); + SetShaderValue(shader, rec.shadowScaleLoc, &rec.shadowScale, SHADER_UNIFORM_FLOAT); + SetShaderValue(shader, rec.borderThicknessLoc, &rec.borderThickness, SHADER_UNIFORM_FLOAT); +} diff --git a/examples/shaders/shaders_rounded_rectangle.png b/examples/shaders/shaders_rounded_rectangle.png new file mode 100644 index 0000000000000000000000000000000000000000..0d8c2b5f41e887c4558c2c8c594912ca797e2036 GIT binary patch literal 13936 zcmd6Oc{rPEzwV2+s$GhSAU8Y(4KLQPSEm_j3nDRN%l{?5L>eO>2|bM`*_T*rl6@;=Y=K6&2Xbl>;Si{H&n zcu$-=0RRB+EmI>a0N|1W0FIBxkAd$9yI1spFGrr-yk&D7{E9g45fA;p%HC3tG z_YqQRSJbXcUD421y{3IdUFvr;so$+_;%Bv{06+@3Wpu+PSB8mUM4zFzh))xi}pG+ab%9|hOc1I1kPtGw~ zk|Fq2IF(^O;T+A{Jn6p{O~B` zpBrI7^P=>r;!Ig06;jZF+DDjAu^YPhfM!Gm$1FBFLPgv1{lX{e1}!Vk*J{ z`F=^0s3YH;RO5VBSN(oO^Lfpn&CLk0j66m@6}5l2a!=PkY=ZH$lOeGNIgmYa8rW(# zzT2+778`24Cr}Aqs(jhDpz1&9g!Y%TC<5oU$m0pktN13LaW!+G$wy4}=yJ>AZ;b(O z_mwM^oZ*fdT07_06&Cm@<8!yW87pJUJCzc9xXOE%$87#NL%>kFKflf?@XrH*gGxx95H5ZISHtl z{>2Po4rg{L-DrQBeO2q$ScUjdF`;kMDfMl|;J)H&Ua<3P-XoSB-LuLWE#5Sa*!zAnf-&Rg(l9h& z&;1Nr&;3bg>+AY{hOF7b|I$&u^k4sb1ZgCW9NJue5|;(mGO+*eCmqzzOYT7T~5EP5I) zkP3&18REXCLh^GAU&aamF|G9(97R0m1>n%`7T>4cEe~&+!boOUN{^%dC98)YP4mZyM-QjfKskyk$G;97Lu1R_Y}F-+1o-jNF(%T;CgZqTUDS3@ z*p0#kGPSQ8LXOPOS&Bc)2~;y0WMgbL)jYmXkzaacBkoe2j+ffrG_~dtFdY6{(hzss zx5v%mX}m!tN9Y@ZHHlzz|o~?MptAwAhl67AiOxDqb5}fBb^e zC3ynbru?4FZpv;SRUUO|Ox_M6rfm$aBHekZ%FU)ogeu3s7LB_l$0mQ)?JP1?Rb&+V zd!@fAX9SV3+DqEk#crPfm(}r-;WDiqgMMl$&-J!rz_&xZz}3^#$l10ibU|N^)MGV8 z@Cdfz(n)R*r2%)%NeQXG$ISwTmFt!ss>(SD-R+k;+b`8;l$~WLps^2yet8$Jr(<>< zavXdl7sW&kd&~ST`IkU9JGyn`;JSWOICQR|RTo`4rmk;c@^Q=Q9@k7oSIF7W1Zg<9 zTo*$ta1d4OjBcvPNj#1Lqhc_!ji8%#o-rZNDG`%ySep(B>VeYb5} z`c{Cb1)56Vy2UtHyd_F3b`mVQ7n>DIs(5><*IHXw53@dPnF^oJ z6ik^TOL7+u#i5HizxfHlm{BIENTV=lI^x!p8Y%UmbqxSCjCvkTSsE&SHrXawD;uku ztGs7GMs%2H@Gj@2J+85`)!@Z^;{r`}%w{Ckxd_g+>znVUZGn39{c@_~2=dcnnTdih z$FD?ek2MK_c%UEzd{7^M1z3%k9W8pOA+Vw#HHZ);dy|ykkK5=7^(}N`1XC!ZOU_bT z9HO?upsRttlk>xJNL6ezTz~1^a@3rRgN#lt?8GPidT1Ea;csvkWx|Y>qYq(3qc=>M9V7kDkm81<;{u!LX1G z$zLkQy{w|&LZspl2MuKkW0AIQHP`C#CxNDHIR2rKJVsd9C3pPjOX}z=;M;4ddh6;j zQmQA)b0g|_sZd5T0!OMP)8uN4AFCBGE9my0G5`W4~DPRqSv((S`x4i%cR0?C=Wx=HtXklD$JPq*wE z3>WUWV`QLa)$hv6^PICX^&|&a0bSWY2mBm0<*n`}C=`b#+=6wMe{pks+kkz0;&Fb| z&joxRfpi7CfQK<-I9v&VS2eKYMD*N@7C}^;HGVV|Dkfl<$&w@}n2uJ)U9T#GTm;=b zRw*;Usl}hOx6W}ZIz7W0gIv7n0vn-`w#q{>ZuL}m)w!|+OR|k_*C2MZ`ceK&h;3*4 zyUCHacg-$c&XtGt@zfbCw8@4TeHmYTKKXc{73?N@r<% zy2Ll{vhIHhz2klr^o+A>RxS3W(ruHkkx@7~{#5ou8|KzWOaEjXm78477rDrgdEo z6pQU)U}5q;V=L)V6Uy3;G?)JD4HaZqKGewaE#Ze$h_;f}@*WBWyc=(|&2cWPeABcY zUItc}O)ok(=)U#T`kwL2#}kIOKtmU>fe7DyDL-40bX-b+7O~+RZ5Um-o4xpJD-%j` zoV+}KF#_{&k{HVf{QHU`=2dZg1bP4O{8=+}_btoLK%2|O-;ktA@96H0&d*Pj6r|Qo zHa8dv1Xc1jI+j$Ms`9??H7$Q^{N{V{z=2#b54H1Hh`yq>V z$dL^K93C~g4_Y1TOE3vGC`EEB5i|F)l~C$Hz|8m-W6N?Q_2-dytpy=sH;W+&-fW}y zyb^tGoTO4k=0L9T*_t&!DW}b~EcO-j)WKM5Q*cUpFo)~2FZ0OPuhZ$DnRh8(F1aRo z8hSN*6Jl5aj@ddmzgDEfTBh@Z`{C(Oad^=z()HFcBO3lv7YX}H+UZ#eD`QKicb zTCAamUMxYP5bxj|cHNR${9}_@_uX#t>?fCl4qa>q9rv6IaBP3qGc#D*vAr{;Yrg_( zL<~D>n8rC}x{K!cNFU;V_ z`XAvx*0`{?xVaS=ZlknS{caEAbXi#5e#Ipq>^3?7L6q&lYLaz#D_8VKpgIYhv%SXt z>pMZvQ3J~zJ2_I(Hgxm_F8ST~A{03e)Y<2}FS9EXSFA8Zu8?lqLnm$Y=V=P}seNLs zPM2u4{SQFQRjkrXE7LlH9W4H-AeucoxLWANt*U|-fDJ22*Q(svz(w?q<=OQt-26Pl zus@a=NrEQyHn@0dH_l%Je6hIX?Xhua#1fPIVrsvGa@9pr5Vp_ff7Xw?>);;CU1{?hOW|98$3jO3&kP^}lWhwit%A)BUK z%$WPAvzKz?@FMaW?~c<^k7BUkb)Z(1c(G{`g0NcQu@-V}Tp-7h2E)d{farp=Aj)bW zKuBPbH0s!-l%*KEs>X3ded6)XG^tO_terDv@=C59iZ?sAf+uKiD&%mY_`oWFFON+J zVcJS840b*D7rRY2|2n6BDbC}*O$e2AgkX7DqqQzj&GPh%_Oj!U$As0eN0m<-x^~p> zsVN5~xU2}N!~h@6Uv1j9D`39w=<^@mb5Weq%x}db1yrB$gx4?7S3GrA)(sfoqA#>< zgJY+r*(w|#oMANfyKz)+!r>r5&%poIy8Hvp=Q37wux8Gm{m0?r@9dCnf5CQrJb{@YYcMl$NZ z4o73_30MY#V2dCsH%Wpy9|GL3!2O;IR@B$mYL$FWn;3ZnD8zeEqYc1|H-P(>aS6tm zkRm0N5@C!MaUdZexPGD~FR!Ex!Cjll&f9o@Ks zqX3|BA?8Yxazx-C?gH9l%+QDa#4r~^reLaaQy^3TtPZ-nj-@z@eOPBaQ4ViD-4TO+lN}!%hiCr%z;L7kb0$$kjo`#j1f4(7+FL8t*vA6@)$APz0v=`nN! zEgMrFmtyIEViS7uh=&ho9Js$DRlKEM)OQLg&Hd5Z^=A%le zA2p}da(<|aUjEILsotN(T#TX;{u+(70gs$GesTG=HcMC-dK?Jl?=LjeLCvLwNVkVY`l za@50cMY!LeWj(gVcGokK=ULNDp*kW}aVdyB59}W!hy5Zz?hI{5OZE1Bu;_b4cs7N3UmG zU(b*=D`Hb1@L3z=9W)>CVGFEKPYP~BCtF(yU#lw9aU!L>&5L`H_ZJu9R7 zF$?rr2me~m9=9p*pz#x-d~+u^G`3il;B(Ql5_}*G|}N{XP^6hZJIhM&Xns^OWfEsl=b^*!vcWs z;$nh^(l|ZCH;r~if@yCS>6#*Qs(B*;nw4(qM0f3~FcMn3O#4lxyCtg!>lr%bonXq) zo`(e++?Z{+W&)ms)iZO@Dv{!O<7v_1 z-MG}1V>W`ntZp5=vP0e-lVyZvbhilW;-m(uqC5t!*9V8AY*I_&M|Dx5qzHeK?adq# zb}8jXe$}{=8tOq-hoAmhvB_m&UVG)Ni9cV2r+FrjSkI)LwRUb;yLnFzXK@LZjwjBXaqJ>mWX$%J*6hdXQt$y7PY9?}V(&mdMOt>-Qka z8NEwYu)fPs@Pw02stn{Nzdijp8!}gjQGgS?EuE%J8g*EUf`n7yN%JaZ>miHPCne1; z&XRAOF+UYHUFd*#|A2|KJbZGzAgaYS@OjvHSdN%I2_0>%T2~L8wX`#vds850C4}l* z5}KB&ngKD5yqb#j7ebk^>rIOuLAYP13>;%UmoT(qqmQsFUs4xau_(o9Af9&JNsF-D zSt!0gS#TCLzX3TepQ$IMo&kD~ICv}Ru`?4&LUIkz=2F+uI5eUcYQ)e-&FM=|ex_d{ z&cG}osadM|UaEN|uQH(HCf^F;1iftg-JrtyxJ5e*fu>yIjJzXjF_uwvYJAb|xf7qM z&fL=5TW3sj1gotkmUD=xsI}*%cK>7;jGjEzNvK<(zY9y6pKOqDVjA~KV;fX1_-lL+ zn}eMN!HzEK-?^0quI#G2((w;f)^y=8BDOdR;`$!UCbz3G zJU~ZSvK}Z%QoxYn9jw3hJSFOSQFaa~Lf2bETvtS;!z4A94~TK9r*r%&EhJZnOzn^G z8{MQ4 z=XZ-owI1y0?n(wTY0uHp!XWb>M6x}S62IUi;D58ntqR>agn3}$j0xI>);`;%mnS|8 zJ!9zUceKdcXw9PigkXxI{R%r3+p{NT9Hi)4-$!wJ_h9!%rcQ2f?n#Nn^-iniw1LO9 zHwG)gg{OwWg-QHa$I}f?n`I6`8pN^5CXA*iR5knUtAK`#pO!`?RlsmlvG|x z>O|k;*OKuOYu^*&-xB+pg>iig-}HWqtvPpFmKCYL4yJV{4q)YZ#R(|^0{=_6y!6tR zM^hxBR-_N(IfZ_cKyOKSW+^CFD;s#13QdQ$zKi-o2peEqGBY>l%9R|L~Egio1?-L$p+^zdWn;^aUxy15Ez-Dsl+QnQ1$+$rYd)mM2XvNlCF z-S5iWZ9GwLgQ%@#CNL6hb&0bFsiZEQC>!HZ%C23zUd$|$cKY*IVh&lLRRZK}{Xm+3 zVd0X5K~%(Yw_hfSM#grY#T?Kk(=l^HigI1Vk)k@pyiISWb*)uH#Ik}Ftl9L#?^i35 zlapuKpK*8Sihz|P7F04o_F9KWQh;z~I_m4YCGDjiA&k=|=smRp7qSRpYqieD7s+0& zUk8q+UC;~pDJ7vFq4~3r6L=)ltxDVgK)#m>XOA~3%}cHylzraSt#W{> z(B5zVLe2lD6r%FWF}h(J3lojaQD2%{*vQE_xK-32wlXWelqqd1LYXu#}f1pH9Nh2h6J-19Sq~^Tpah;jw9q#7!quS?)QuCE^|SDfYmhK<4|}T(L0VH zY8TfE97+xG@gdtkrz<4GoreR|s%A#(5=-RZEi7LNi~K&y^4b^5NU@~$6Sm9#rd*@` zG2lng{=`%WGkZMBcmI6|u~nKJY5(cYbI3%&EJ(+?TNPbeUor0r$f7C}YgGmL5yloE z3>h~9Mjw}ngLQaXJuUVW=y8(&BI9}b=}9?JS$-k3`Vj=pzHtt;!DR^$uKB*sdvFuq zcjbu#Xqm%$u}}QmuHgDqE8OL^0H6{<6*!X^txU0_BnKBwt= zQ#qZ)NdE*pqsDjgHxLwYt=IrN#Hfmd=#6F)?)eR)Ap!dAuQM74P03T+Adjr~V%x+Z z^`tZagd@C)T_cwU>wng?=f5`6-7VbJ=DmbqCn9do)@5&bDHw8h%;Ny`h z?^8LD47&lEWD@XkY@dvWa)5Qe2Ip}fMp7CQ4XUw!gM*TGxq%M{|0&n|uY>3Rg7kae z&)7KYB>0Rwp>fzekE@YF5(3qaU*{G^NRY;=-Oy@78rC#s;_$e!9L(Vn&P+4h=zMP zhXH_NNB`@i2dx&zrN(Cls$Yk6v^F3#e5zo6Rkc)GaA>Cd|*htKAH`j z7NGOBMVI9FoA0h2m`gB?mnA^&S;ks>t>Axl+!FM7rnl=MWWdTPeS9d*m2mc4g6z*& z6U1m)J04h}Wx}?cK}K%SQQ$*Dp8jv_ZiCdB z=>1Yh_uUT?k!mP|J>p4TDgeB$VU*1Cxe#XL3~WC|Z;CY}W%nP0h;kkfh zDJW03bFBa}=#T*MHr~7y13O8UU1cm@~m=1mr^gt7+kX!#1tU z8SQ8=L((bT%jY?D{*hsIL#kKr1Hhvf^-x1F`z?5+I&A)Ee|8vAanHdMzc_r4BLE9( zJ9`j5@b~}S?uCC(Ww{c|l@qhygRkc|N8~pK>^DmsW}qs2>N7l;wiF9={x}N6O#WLp z!P6cvyG2dYSZi9W9Vj|rw5C9#lJUB2%}iqNjp3FwaT>dZPYRgo+6J?q6PW$7pt`$q z#jHK2z>i_OTZE4t(B#O0@0E`Wa&^0)`6H|vfQd}I8&{#~1V7)X8n>KCc{6_WGyq6TV@oUwhLuUQ-jgqu%sJLW{OQ*}hd}su7uNTS31H|xF zTXW17L?h0#$AyEJjck{bKtlA^ap1HirI^BPEPSLU?sZT>r78`EPAx@=1p;OSD%Xa@6*< zN)E?Torp4ry;0?sLISYN>;98|qpP;YhnGbRqx!Rhp(aI#tYrMP`yN?5QeYH{+2i)I zXf3JLwh~Ik`qGE_WSUKZKQ7l}*w&mePMZ}fR4;^%R<=n#)>K~ljvxQ6W~YC!>gAc9 zBYNk6AGo$<2NN$u?iUN`x8*z+{I(w`To4#dZYVq{RXvUSFyO?qm^1VZabUm$1X<-v zx6vXyv&Y#ptdi75j-rznCh>dCVeOXS9lwIqY3SdRjssZj@Tq{BLUto(%;l{Yd}jR< z>Wa(T3*qK(>|@dMQ`-j*?GLxeJAyy)ax-_xN~n9VmS;92xFFBv1W;}P-h(OQ#ntmU z4a8ctm)3njHSvbWbKqD{V^c<;gP976;=RmQ*;V&P3qP5aF(z=>Ov$zeVUbdxumEloYJlBJFtyH4y0os;#*VZg(zte}(UQLy z{0_Kw7DT^|mps^>&K}2T&-k}8QL6p5B2-x7`q16>-kfMkaOB^j9I-dP5Vdag2k)bo z)sZB$u1{|r%cG&_q}@pS)dH{YN9 zfQWs*^ud@MAF(3B$S8t_AO#qHB0Zhb~lt>V>4 z#vj0A=wzIc)3bZQZ#`^^nl#GX_UEdMcF6wPj7WnGddKz;MaX`aiChEmjQh8%snFPu)!B0BqpZgLfdfIr(S!d`Ulf`ZPhg7lBaftJ5?Arl6s zbkLmXPE*?2!D;PnReIT-Xz_!9^NA=;k+-iBK~?-LrIPJ#QS1U)2?0uFfC zPZ>kbC$GOsWW1`&KwAzt+N=m=k8x^Uqqj*0h#ne=XgTfIm*c zVb-h%H%%WZN}26!xu%1iGHA(W=KJj>yZnmqcYxtFjFaBp$E+EXQwP5u($TrIgx>Bq z+`nFL%?r0;#ee@BSSQm*`|in#2q>(KrDB|7opY)nA(%kI_yiRUytiQ8{`A?GV9 z!XV5*TZdtTr#N|8JYa8T1%<_p+J>;Mrd=X>Yiuu1sf$Hj(UF4potuU@REje{b{DY< z#-@KouSJfG%>3q}m7o$i{X&Wp;L7e>-u{S>JWV0C3PhLg-))IV>Ab^jHb)_Y`2p0Z zpefQ0j`kB-OD3OAZN@}QX=KoK{44eIrq~Z9y5U0H@8iai+j$zOZG2l;1Cz4noZTIH z=O@|zwm|6QKA(?c(IrsK!zS-&qRYzMoz>Scxa76SEjjuuJGa}*OQoBBr|Q$4HSPFt z?mk^>;KzKK_Kb&Z=ePxxzOpP>QT&t zO!DRRI=g8Zx96NaCS)h$)P6(=lc=wg%>F4Ow=6m&p%bQvj@})u?fV)kL?4vQue@*6 zECUB6v^TxAA|tSLXhJAd<3>?$VYy5hjz19Ue27a|H~39_-{8*GETD`(`G7g0<9wj)hyx)idm2Ik=fj7}O*Y z6^|_&FEbI-FN?T%4dig7Cwh(JN`0w$wyL>ys+TdZ`mMzb%VZ;LkV68NCocdi)yhC% zF0iG+zWnX++cL`m8x>hdLPx-vo2&KHGjG*>Cvue(B`2w7Y?HR*%9Mun8h`65Z5=_w zgZW0{j7#MGz~U3@inPzw{Er*wp@WP7avdh#bBV-kv0&`@^^ED=IAn?Y-;`MoA+2fe zmiF)3n|h1h%e=EwEMh@;l~|^k4GmE9$4L4C@)&q^svhti3A@%_7~NjEOkBupD*$=f z05QXyGUK*i&ZR|M53E~TOJZn>lr-$K>^Q$R>%wV5QIToQPMN?&wfNBg*B*m&>JGl0N#jGqQAOzEHM}#&XdiD0Yxkd&4A*2lyiWzimrqlX$a7P#-~k)MJ91rS{O|XR zvd8I>RbQa`tM*ThUW6D4BK_es_*`M4E~@j?QlYmHrR8DfTHagDeD&$WLOz0Qb7LNQ zRnTXkM|W*W~!Q(EBfpo1=}Y zGWL*iU%cF|qnLGvo{5sTzYqgd3uEmM!pGJ)7R#h2uazIz%p-2w8l(rhh^eTbyNil@ zGF@0R2r|x#JYcR``*di7t0!O+$+w)l`C9Oa_yfPIxxZB2GKlqnwc78LH9t*jR1AGR zYbMzPhQ2_XDzINJ(h&C(Z0;QzI4o|Q8eZWdmZpfsd__E`DM8oEJNMi~HF2)k)4J;{ zXWEkVKjC}y9=#uOn%lwK7?Mlf!OOGa9V7KFS{^w-*W zHgNmd%RMG5Gj~>?YT|PJLEV~TN(sd-0Nv3Z1*&8UaTI+srirG&BEe%C1H0N+Qx7p zhV*ro1pM9+bSTVZ)ZuC4sAa2GF$k1`pjiT$V5<^)w)A#SY1c-jK~eLEEGl6S+4|~r zeK5z7El4l6$I7VJs>sG9e@Zrj!jIpmZxE-8EAJNeCqk>tAJ!xo(tVLcGt{6G6|k(Ky8=2|yvkLj|l z|40lsl070;BDf4vfj?(fr|^;>(H^wZ+Wlt^=t48bpI#1BawOJP2x;TH7R-p6{VtbTDn0s!U*KGs?(I4 z)uP6`TNV_Ua3+40?h+U=^1d~?oKVK2p|{28YE~}kW=IPrQd@1EXQ@FM-E9k-A*88x zv#tQ=IcjCco>_E$Fg>j86v){J4VhW+S8D6cD#+PoISI5SjjM#WEGJX26vv>MT~OFq zV&E2eeuVx#BR#^J)F(2MnQ!pR4e~J&EbS`v@?EZo)B=-3bKD)9Itr>3jQOgmS^bGNr}sHgc0>vU-K=OZ75O*V zVy82sAm?iSEv`oKj + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4} + Win32Proj + shaders_rounded_rectangle + 10.0 + shaders_rounded_rectangle + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + \ No newline at end of file diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index f4f0600e1..8f3323bc8 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -307,6 +307,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_bone_socket", "examp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_vertex_displacement", "examples\shaders_vertex_displacement.vcxproj", "{CCA63A76-D9FC-4130-9F67-4D97F9770D53}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_rounded_rectangle", "examples\shaders_rounded_rectangle.vcxproj", "{D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|x64 = Debug.DLL|x64 @@ -2615,6 +2617,22 @@ Global {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x64.Build.0 = Release|x64 {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x86.ActiveCfg = Release|Win32 {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x86.Build.0 = Release|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug|x64.ActiveCfg = Debug|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug|x64.Build.0 = Debug|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug|x86.ActiveCfg = Debug|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Debug|x86.Build.0 = Debug|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release|x64.ActiveCfg = Release|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release|x64.Build.0 = Release|x64 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release|x86.ActiveCfg = Release|Win32 + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2771,6 +2789,7 @@ Global {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {3A7FE53D-35F7-49DC-9C9A-A5204A53523F} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {CCA63A76-D9FC-4130-9F67-4D97F9770D53} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} + {D3493FFE-8873-4C53-8F6C-74DEF78EA3C4} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From 49d37b035f6d764d6bafdc835b5496fded3edcc0 Mon Sep 17 00:00:00 2001 From: Nikolas Date: Fri, 24 Jan 2025 10:41:32 +0100 Subject: [PATCH 24/39] [rtexture] Cubemap mipmap loading improvements (#4721) * [rtextures] Only build cubemap mipmaps when necessary * [rtextures] Assign correct mipmap count to cubemaps --- src/rtextures.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 9dfc24738..9d3f51f34 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -4208,8 +4208,11 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) Image mipmapped = ImageCopy(image); #if defined(SUPPORT_IMAGE_MANIPULATION) - ImageMipmaps(&mipmapped); - ImageMipmaps(&faces); + if (image.mipmaps > 1) + { + ImageMipmaps(&mipmapped); + ImageMipmaps(&faces); + } #endif // NOTE: Image formatting does not work with compressed textures @@ -4226,7 +4229,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout) if (cubemap.id != 0) { cubemap.format = faces.format; - cubemap.mipmaps = 1; + cubemap.mipmaps = faces.mipmaps; } else TRACELOG(LOG_WARNING, "IMAGE: Failed to load cubemap image"); From 139de05e9d68145422b0d625c23a7d7505b8762b Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sat, 25 Jan 2025 16:49:42 -0300 Subject: [PATCH 25/39] [rcore] [SDL2] Fix gamepad event handling by adding joystick instance id tracking (#4724) * Fix gamepad SDL_JOYDEVICEADDED and SDL_JOYDEVICEREMOVED event handling for PLATFORM_DESKTOP_SDL by adding joystick instance id tracking * Fix gamepad button handling --- src/platforms/rcore_desktop_sdl.c | 77 ++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 33c182a70..f248e2614 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -82,6 +82,7 @@ typedef struct { SDL_GLContext glContext; SDL_GameController *gamepad[MAX_GAMEPADS]; + SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids SDL_Cursor *cursor; bool cursorRelative; } PlatformData; @@ -1658,11 +1659,12 @@ void PollInputEvents(void) // Check gamepad events case SDL_JOYDEVICEADDED: { - int jid = event.jdevice.which; + int jid = event.jdevice.which; // Joystick device index if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) { platform.gamepad[jid] = SDL_GameControllerOpen(jid); + platform.gamepadId[jid] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid])); if (platform.gamepad[jid]) { @@ -1681,14 +1683,18 @@ void PollInputEvents(void) } break; case SDL_JOYDEVICEREMOVED: { - int jid = event.jdevice.which; + int jid = event.jdevice.which; // Joystick instance id - if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]))) + for (int i = 0; i < MAX_GAMEPADS; i++) { - SDL_GameControllerClose(platform.gamepad[jid]); - platform.gamepad[jid] = SDL_GameControllerOpen(0); - CORE.Input.Gamepad.ready[jid] = false; - memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); + if (platform.gamepadId[i] == jid) + { + SDL_GameControllerClose(platform.gamepad[i]); + CORE.Input.Gamepad.ready[i] = false; + memset(CORE.Input.Gamepad.name[i], 0, MAX_GAMEPAD_NAME_LENGTH); + platform.gamepadId[i] = -1; + break; + } } } break; case SDL_CONTROLLERBUTTONDOWN: @@ -1721,8 +1727,15 @@ void PollInputEvents(void) if (button >= 0) { - CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 1; - CORE.Input.Gamepad.lastButtonPressed = button; + for (int i = 0; i < MAX_GAMEPADS; i++) + { + if (platform.gamepadId[i] == event.jbutton.which) + { + CORE.Input.Gamepad.currentButtonState[i][button] = 1; + CORE.Input.Gamepad.lastButtonPressed = button; + break; + } + } } } break; case SDL_CONTROLLERBUTTONUP: @@ -1755,8 +1768,15 @@ void PollInputEvents(void) if (button >= 0) { - CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 0; - if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + for (int i = 0; i < MAX_GAMEPADS; i++) + { + if (platform.gamepadId[i] == event.jbutton.which) + { + CORE.Input.Gamepad.currentButtonState[i][button] = 0; + if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + break; + } + } } } break; case SDL_CONTROLLERAXISMOTION: @@ -1776,18 +1796,25 @@ void PollInputEvents(void) if (axis >= 0) { - // SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range - float value = event.jaxis.value/(float)32767; - CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value; - - // Register button state for triggers in addition to their axes - if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER)) + for (int i = 0; i < MAX_GAMEPADS; i++) { - int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; - int pressed = (value > 0.1f); - CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed; - if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; - else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + if (platform.gamepadId[i] == event.jaxis.which) + { + // SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range + float value = event.jaxis.value/(float)32767; + CORE.Input.Gamepad.axisState[i][axis] = value; + + // Register button state for triggers in addition to their axes + if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER)) + { + int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; + int pressed = (value > 0.1f); + CORE.Input.Gamepad.currentButtonState[i][button] = pressed; + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; + else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } + break; + } } } } break; @@ -1967,9 +1994,15 @@ int InitPlatform(void) // Initialize input events system //---------------------------------------------------------------------------- // Initialize gamepads + for (int i = 0; i < MAX_GAMEPADS; i++) + { + platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero + } + for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++) { platform.gamepad[i] = SDL_GameControllerOpen(i); + platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i])); if (platform.gamepad[i]) { From 861ebafe62afb8321abbae07b1ce91945407e9c1 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Jan 2025 19:42:52 +0100 Subject: [PATCH 26/39] Update shaders_mesh_instancing.c --- examples/shaders/shaders_mesh_instancing.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/shaders/shaders_mesh_instancing.c b/examples/shaders/shaders_mesh_instancing.c index 805d5ef18..17b2da33d 100644 --- a/examples/shaders/shaders_mesh_instancing.c +++ b/examples/shaders/shaders_mesh_instancing.c @@ -15,7 +15,6 @@ * ********************************************************************************************/ - #include "raylib.h" #include "raymath.h" From f6f31a9f216c54fe8bf661e042a4cfc9a6892e33 Mon Sep 17 00:00:00 2001 From: Asdqwe Date: Sun, 26 Jan 2025 17:26:18 -0300 Subject: [PATCH 27/39] [rtextures] Fix `HalfToFloat()` and `FloatToHalf()` dereferencing issues with an union (#4729) * Fix HalfToFloat() and FloatToHalf() dereferencing issues with an union * Remove unnecessary initialization * Moved the union to inside the functions --- src/rtextures.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/rtextures.c b/src/rtextures.c index 9d3f51f34..0317f0385 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -5390,13 +5390,19 @@ static float HalfToFloat(unsigned short x) { float result = 0.0f; + union + { + float fm; + unsigned int ui; + } uni; + const unsigned int e = (x & 0x7C00) >> 10; // Exponent const unsigned int m = (x & 0x03FF) << 13; // Mantissa - const float fm = (float)m; - const unsigned int v = (*(unsigned int *)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format - const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized + uni.fm = (float)m; + const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format + uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized - result = *(float *)&r; + result = uni.fm; return result; } @@ -5406,7 +5412,14 @@ static unsigned short FloatToHalf(float x) { unsigned short result = 0; - const unsigned int b = (*(unsigned int *) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa + union + { + float fm; + unsigned int ui; + } uni; + uni.fm = x; + + const unsigned int b = uni.ui + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa const unsigned int e = (b & 0x7F800000) >> 23; // Exponent const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding From 5504983c91f90df0e2f5acbc0545dd2dc28cbd80 Mon Sep 17 00:00:00 2001 From: elite0OG Date: Mon, 27 Jan 2025 13:50:10 +0530 Subject: [PATCH 28/39] Update CMakeLists.txt (#4727) Cmake warn remove --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9905ba144..af4444e07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.25) +#this change avoid the warning that appear when we include raylib using Cmake fatch content project(raylib) # Avoid excessive expansion of variables in conditionals. In particular, if From 2492dd3d0a69efe77185daf708f9f8aa458113a8 Mon Sep 17 00:00:00 2001 From: Peter0x44 Date: Mon, 27 Jan 2025 22:15:09 +0000 Subject: [PATCH 29/39] [build] [Makefile]: Undefine _GNU_SOURCE for rglfw.c (#4732) Currently, a warning about _GNU_SOURCE being redefined is emitted when compiling rglfw.c In file included from rglfw.c:99: external/glfw/src/posix_poll.c:27:9: warning: "_GNU_SOURCE" redefined 27 | #define _GNU_SOURCE | ^~~~~~~~~~~ : note: this is the location of the previous definition This can be avoided by not defining _GNU_SOURCE on the command line for this file. Defining feature test macros in source code is not really good practice so this should probably reviewed in glfw itself, at least to maybe check #ifdef _GNU_SOURCE first. But for now this change will suffice. Fixes #4725 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index b05b257d3..1b7562da4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -742,7 +742,7 @@ rcore.o : rcore.c raylib.h rlgl.h utils.h raymath.h rcamera.h rgestures.h # Compile rglfw module rglfw.o : rglfw.c - $(CC) $(GLFW_OSX) -c $< $(CFLAGS) $(INCLUDE_PATHS) + $(CC) $(GLFW_OSX) -c $< $(CFLAGS) $(INCLUDE_PATHS) -U_GNU_SOURCE # Compile shapes module rshapes.o : rshapes.c raylib.h rlgl.h From 9789ff123b86e36777ee7843c29ed5a96dc08659 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Jan 2025 16:19:30 +0100 Subject: [PATCH 30/39] REVERTING: `emscripten_sleep()` previous removal #4713 --- src/platforms/rcore_web.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index ee10eb5d7..07f6f79ba 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -167,7 +167,7 @@ bool WindowShouldClose(void) // Optionally we can manage the time we give-control-back-to-browser if required, // but it seems below line could generate stuttering on some browsers - //emscripten_sleep(16); + emscripten_sleep(12); return false; } From 1f6de0c507ae6f4de0a4ff2cd5aa1463bb593724 Mon Sep 17 00:00:00 2001 From: Eike Decker Date: Fri, 31 Jan 2025 00:34:51 +0100 Subject: [PATCH 31/39] Replacing hardcoded canvas id references with module variable usages (#4735) Should also have the benefit of being faster. --- src/platforms/rcore_web.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 07f6f79ba..0341bec31 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -185,8 +185,8 @@ void ToggleFullscreen(void) else if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) enterFullscreen = true; else { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); - const int canvasStyleWidth = EM_ASM_INT( { return parseInt(document.getElementById('canvas').style.width); }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); + const int canvasStyleWidth = EM_ASM_INT( { return parseInt(Module.canvas.style.width); }, 0); if (canvasStyleWidth > canvasWidth) enterFullscreen = false; else enterFullscreen = true; } @@ -293,7 +293,7 @@ void ToggleBorderlessWindowed(void) else if (CORE.Window.flags & FLAG_FULLSCREEN_MODE) enterBorderless = true; else { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); const int screenWidth = EM_ASM_INT( { return screen.width; }, 0); if (screenWidth == canvasWidth) enterBorderless = false; else enterBorderless = true; @@ -379,8 +379,8 @@ void SetWindowState(unsigned int flags) const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0); if (wasFullscreen) { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); - const int canvasStyleWidth = EM_ASM_INT( { return parseInt(document.getElementById('canvas').style.width); }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); + const int canvasStyleWidth = EM_ASM_INT( { return parseInt(Module.canvas.style.width); }, 0); if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) || canvasStyleWidth > canvasWidth) ToggleBorderlessWindowed(); } else ToggleBorderlessWindowed(); @@ -393,7 +393,7 @@ void SetWindowState(unsigned int flags) const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0); if (wasFullscreen) { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); const int screenWidth = EM_ASM_INT( { return screen.width; }, 0); if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) || screenWidth == canvasWidth ) ToggleFullscreen(); } @@ -512,7 +512,7 @@ void ClearWindowState(unsigned int flags) const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0); if (wasFullscreen) { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); const int screenWidth = EM_ASM_INT( { return screen.width; }, 0); if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) || (screenWidth == canvasWidth)) EM_ASM(document.exitFullscreen();); } @@ -526,8 +526,8 @@ void ClearWindowState(unsigned int flags) const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0); if (wasFullscreen) { - const int canvasWidth = EM_ASM_INT( { return document.getElementById('canvas').width; }, 0); - const int canvasStyleWidth = EM_ASM_INT( { return parseInt(document.getElementById('canvas').style.width); }, 0); + const int canvasWidth = EM_ASM_INT( { return Module.canvas.width; }, 0); + const int canvasStyleWidth = EM_ASM_INT( { return parseInt(Module.canvas.style.width); }, 0); if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) || (canvasStyleWidth > canvasWidth)) EM_ASM(document.exitFullscreen();); } @@ -685,7 +685,7 @@ void SetWindowOpacity(float opacity) { if (opacity >= 1.0f) opacity = 1.0f; else if (opacity <= 0.0f) opacity = 0.0f; - EM_ASM({ document.getElementById('canvas').style.opacity = $0; }, opacity); + EM_ASM({ Module.canvas.style.opacity = $0; }, opacity); } // Set window focused @@ -962,7 +962,7 @@ void SetMouseCursor(int cursor) { if (CORE.Input.Mouse.cursor != cursor) { - if (!CORE.Input.Mouse.cursorHidden) EM_ASM( { document.getElementById('canvas').style.cursor = UTF8ToString($0); }, cursorLUT[cursor]); + if (!CORE.Input.Mouse.cursorHidden) EM_ASM( { Module.canvas.style.cursor = UTF8ToString($0); }, cursorLUT[cursor]); CORE.Input.Mouse.cursor = cursor; } From 99dfec070a32d22dc1e1973a2a5e110e4304f435 Mon Sep 17 00:00:00 2001 From: sleeptightAnsiC <91839286+sleeptightAnsiC@users.noreply.github.com> Date: Fri, 31 Jan 2025 14:44:23 +0100 Subject: [PATCH 32/39] [rtext] fix: misuse of cast in GetCodepointCount (#4741) I was really wondering what is going on here :D I believe this code tried initially to out-cast 'const' specifier but this is not needed here at all. Currently, it just confuses whoever reads this so I changed it. The old code would also trigger -Wcast-qual warning on some compilers. --- src/rtext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtext.c b/src/rtext.c index d8d290053..982402f54 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1915,7 +1915,7 @@ void UnloadCodepoints(int *codepoints) int GetCodepointCount(const char *text) { unsigned int length = 0; - char *ptr = (char *)&text[0]; + const char *ptr = text; while (*ptr != '\0') { From e85ae86f707fb1115077a3d1e3dd589d61819106 Mon Sep 17 00:00:00 2001 From: whaley <63699160+whaleymar@users.noreply.github.com> Date: Sat, 1 Feb 2025 04:50:25 -0500 Subject: [PATCH 33/39] [platforms/glfw] fix: allow GetGamepadButtonPressed() to return GAMEPAD_BUTTON_LEFT_TRIGGER_2 / GAME_PAD_BUTTON_RIGHT_TRIGGER_2 if they are pressed (#4742) --- src/platforms/rcore_desktop_glfw.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 9159b302a..279f8c193 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1238,8 +1238,18 @@ void PollInputEvents(void) } // Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis) - CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f); - CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f); + if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f) + { + CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1; + CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_LEFT_TRIGGER_2; + } + else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 0; + if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f) + { + CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 1; + CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; + } + else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 0; CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1; } From 1958de4a12e3d0ae9db27e2ee0b1fe3d950f76b3 Mon Sep 17 00:00:00 2001 From: Chris Dill Date: Sat, 1 Feb 2025 20:29:27 +0000 Subject: [PATCH 34/39] Update raylib-cs binding link (#4746) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 95aecd085..6f96103c7 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -10,7 +10,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT | | [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | | [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib55.c3l) | **5.5** | [C3](https://c3-lang.org) | MIT | -| [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | +| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.1-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT | From 4f5a20a634918ca0fff893ad0ac586a515186c81 Mon Sep 17 00:00:00 2001 From: "Henrik A. Glass" Date: Sat, 1 Feb 2025 21:30:21 +0100 Subject: [PATCH 35/39] Add missing increments of k in LoadImageDataNormalized() (#4745) --- src/rtextures.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rtextures.c b/src/rtextures.c index 0317f0385..ee116b0e5 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -5512,6 +5512,7 @@ static Vector4 *LoadImageDataNormalized(Image image) pixels[i].z = 0.0f; pixels[i].w = 1.0f; + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: { @@ -5537,6 +5538,8 @@ static Vector4 *LoadImageDataNormalized(Image image) pixels[i].y = 0.0f; pixels[i].z = 0.0f; pixels[i].w = 1.0f; + + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16: { From 5a254e3d5e6564523075b88d91b21356bd6a956a Mon Sep 17 00:00:00 2001 From: Gil Reis Date: Sun, 2 Feb 2025 11:46:28 +0000 Subject: [PATCH 36/39] Set PLATFORM to Web by default when configuring web builds with emcmake (#4748) --- CMakeOptions.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 00ecb594d..4e413fe61 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -2,6 +2,10 @@ include(CMakeDependentOption) include(EnumOption) +if(EMSCRIPTEN) + # When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default + SET(PLATFORM Web CACHE STRING "Platform to build for.") +endif() enum_option(PLATFORM "Desktop;Web;Android;Raspberry Pi;DRM;SDL" "Platform to build for.") enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0" "Force a specific OpenGL Version?") From bddb5df0d407d1eb50a1e3974ac0d0d1a9c15d37 Mon Sep 17 00:00:00 2001 From: Nikolas Date: Sun, 2 Feb 2025 12:48:18 +0100 Subject: [PATCH 37/39] [rmodels] Separate GLTF roughness and metallic channels on load (#4739) --- src/rmodels.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/rmodels.c b/src/rmodels.c index 9ab2bcca9..d7bc05f71 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5347,7 +5347,33 @@ static Model LoadGLTF(const char *fileName) Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath); if (imMetallicRoughness.data != NULL) { - model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imMetallicRoughness); + Image imMetallic, imRoughness; + + imMetallic.data = RL_MALLOC(imMetallicRoughness.width * imMetallicRoughness.height); + imRoughness.data = RL_MALLOC(imMetallicRoughness.width * imMetallicRoughness.height); + + imMetallic.width = imRoughness.width = imMetallicRoughness.width; + imMetallic.height = imRoughness.height = imMetallicRoughness.height; + + imMetallic.format = imRoughness.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; + imMetallic.mipmaps = imRoughness.mipmaps = 1; + + for (int x = 0; x < imRoughness.width; x++) { + for (int y = 0; y < imRoughness.height; y++) { + Color color = GetImageColor(imMetallicRoughness, x, y); + + Color roughness = (Color) {color.g}; + Color metallic = (Color) {color.b}; + + ((unsigned char *)imRoughness.data)[y*imRoughness.width + x] = color.g; + ((unsigned char *)imMetallic.data)[y*imMetallic.width + x] = color.b; + } + } + model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imRoughness); + model.materials[j].maps[MATERIAL_MAP_METALNESS].texture = LoadTextureFromImage(imMetallic); + + UnloadImage(imRoughness); + UnloadImage(imMetallic); UnloadImage(imMetallicRoughness); } From cfe96931f559ee242fe98598e64942008f2d2218 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 2 Feb 2025 12:59:34 +0100 Subject: [PATCH 38/39] REVIEWED: Formatting #4739 --- src/rmodels.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index d7bc05f71..88101ce27 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5347,10 +5347,11 @@ static Model LoadGLTF(const char *fileName) Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath); if (imMetallicRoughness.data != NULL) { - Image imMetallic, imRoughness; + Image imMetallic = { 0 }; + Image imRoughness = { 0 }; - imMetallic.data = RL_MALLOC(imMetallicRoughness.width * imMetallicRoughness.height); - imRoughness.data = RL_MALLOC(imMetallicRoughness.width * imMetallicRoughness.height); + imMetallic.data = RL_MALLOC(imMetallicRoughness.width*imMetallicRoughness.height); + imRoughness.data = RL_MALLOC(imMetallicRoughness.width*imMetallicRoughness.height); imMetallic.width = imRoughness.width = imMetallicRoughness.width; imMetallic.height = imRoughness.height = imMetallicRoughness.height; @@ -5358,17 +5359,17 @@ static Model LoadGLTF(const char *fileName) imMetallic.format = imRoughness.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; imMetallic.mipmaps = imRoughness.mipmaps = 1; - for (int x = 0; x < imRoughness.width; x++) { - for (int y = 0; y < imRoughness.height; y++) { + for (int x = 0; x < imRoughness.width; x++) + { + for (int y = 0; y < imRoughness.height; y++) + { Color color = GetImageColor(imMetallicRoughness, x, y); - Color roughness = (Color) {color.g}; - Color metallic = (Color) {color.b}; - - ((unsigned char *)imRoughness.data)[y*imRoughness.width + x] = color.g; - ((unsigned char *)imMetallic.data)[y*imMetallic.width + x] = color.b; + ((unsigned char *)imRoughness.data)[y*imRoughness.width + x] = color.g; // Roughness color channel + ((unsigned char *)imMetallic.data)[y*imMetallic.width + x] = color.b; // Metallic color channel } } + model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imRoughness); model.materials[j].maps[MATERIAL_MAP_METALNESS].texture = LoadTextureFromImage(imMetallic); From cceabf69619bcb84fb3dd3f0e6c191f5b8732d5a Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 2 Feb 2025 13:00:20 +0100 Subject: [PATCH 39/39] Formatting review --- src/rmodels.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 88101ce27..4928d4bf1 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3879,10 +3879,10 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector } Vector2 texcoords[4]; - texcoords[0] = (Vector2) { (float)source.x/texture.width, (float)(source.y + source.height)/texture.height }; - texcoords[1] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height }; - texcoords[2] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)source.y/texture.height }; - texcoords[3] = (Vector2) { (float)source.x/texture.width, (float)source.y/texture.height }; + texcoords[0] = (Vector2){ (float)source.x/texture.width, (float)(source.y + source.height)/texture.height }; + texcoords[1] = (Vector2){ (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height }; + texcoords[2] = (Vector2){ (float)(source.x + source.width)/texture.width, (float)source.y/texture.height }; + texcoords[3] = (Vector2){ (float)source.x/texture.width, (float)source.y/texture.height }; rlSetTexture(texture.id); rlBegin(RL_QUADS); @@ -5141,7 +5141,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri)); } } - else if (cgltfImage->buffer_view != NULL && cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer + else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer { unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size); int offset = (int)cgltfImage->buffer_view->offset; @@ -5156,10 +5156,14 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat // Check mime_type for image: (cgltfImage->mime_type == "image/png") // NOTE: Detected that some models define mime_type as "image\\/png" - if ((strcmp(cgltfImage->mime_type, "image\\/png") == 0) || - (strcmp(cgltfImage->mime_type, "image/png") == 0)) image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size); - else if ((strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) || - (strcmp(cgltfImage->mime_type, "image/jpeg") == 0)) image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size); + if ((strcmp(cgltfImage->mime_type, "image\\/png") == 0) || (strcmp(cgltfImage->mime_type, "image/png") == 0)) + { + image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size); + } + else if ((strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) || (strcmp(cgltfImage->mime_type, "image/jpeg") == 0)) + { + image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size); + } else TRACELOG(LOG_WARNING, "MODEL: glTF image data MIME type not recognized", TextFormat("%s/%s", texPath, cgltfImage->uri)); RL_FREE(data);