diff --git a/.gitignore b/.gitignore index eeb1ed09d..d857bf2d4 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,7 @@ GRTAGS GTAGS # Zig programming language +.zig-cache/ zig-cache/ zig-out/ build/ diff --git a/README.md b/README.md index 79e883034..303bbcdd1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html) [![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE) [![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib) -[![Subreddit Subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?label=reddit%20r%2Fraylib&logo=reddit)](https://www.reddit.com/r/raylib/) +[![Reddit Static Badge](https://img.shields.io/badge/-r%2Fraylib-red?style=flat&logo=reddit&label=reddit)](https://www.reddit.com/r/raylib/) [![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/raylib) [![Twitch Status](https://img.shields.io/twitch/status/raysan5?style=flat&label=Twitch&logo=twitch)](https://www.twitch.tv/raysan5) diff --git a/examples/Makefile b/examples/Makefile index 3c39e09e5..be8d87204 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -4,7 +4,9 @@ # # This file supports building raylib examples for the following platforms: # -# > PLATFORM_DESKTOP (GLFW backend): +# > PLATFORM_DESKTOP +# - Defaults to PLATFORM_DESKTOP_GLFW +# > PLATFORM_DESKTOP_GFLW (GLFW backend): # - Windows (Win32, Win64) # - Linux (X11/Wayland desktop mode) # - macOS/OSX (x64, arm64) @@ -52,9 +54,15 @@ # Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB PLATFORM ?= PLATFORM_DESKTOP +ifeq ($(PLATFORM), PLATFORM_DESKTOP) + TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW +else + TARGET_PLATFORM = $(PLATFORM) +endif + # Define required raylib variables PROJECT_NAME ?= raylib_examples -RAYLIB_VERSION ?= 5.0.0 +RAYLIB_VERSION ?= 5.5.0 RAYLIB_PATH ?= .. # Define raylib source code path @@ -91,7 +99,7 @@ BUILD_WEB_RESOURCES ?= TRUE BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources # Determine PLATFORM_OS when required -ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_DESKTOP_RGFW)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -118,7 +126,7 @@ ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLA endif endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) UNAMEOS = $(shell uname) ifeq ($(UNAMEOS),Linux) PLATFORM_OS = LINUX @@ -127,7 +135,7 @@ endif # RAYLIB_PATH adjustment for LINUX platform # TODO: Do we really need this? -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),LINUX) RAYLIB_PREFIX ?= .. RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) @@ -135,14 +143,14 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif # Default path for raylib on Raspberry Pi -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) RAYLIB_PATH ?= /home/pi/raylib endif # Define raylib release directory for compiled library RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM_OS),WINDOWS) # Emscripten required variables EMSDK_PATH ?= C:/emsdk @@ -158,7 +166,7 @@ endif #------------------------------------------------------------------------------------------------ CC = gcc -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),OSX) # OSX default compiler CC = clang @@ -168,7 +176,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) CC = clang endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler # WARNING: To compile to HTML5, code must be redesigned # to use emscripten.h and emscripten_set_main_loop() @@ -179,15 +187,15 @@ endif #------------------------------------------------------------------------------------------------ MAKE ?= make -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) MAKE = mingw32-make endif endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) MAKE = emmake make endif @@ -206,11 +214,11 @@ CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -D_DEBUG - ifeq ($(PLATFORM),PLATFORM_WEB) + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) CFLAGS += -sASSERTIONS=1 --profiling endif else - ifeq ($(PLATFORM),PLATFORM_WEB) + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) CFLAGS += -O3 else @@ -227,7 +235,7 @@ endif # -Wstrict-prototypes warn if a function is declared or defined without specifying the argument types # -Werror=implicit-function-declaration catch function calls without prior declaration #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),LINUX) ifeq ($(RAYLIB_LIBTYPE),STATIC) CFLAGS += -D_DEFAULT_SOURCE @@ -238,7 +246,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) CFLAGS += -std=gnu99 -DEGL_NO_X11 endif @@ -248,7 +256,7 @@ endif INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),BSD) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) endif @@ -256,10 +264,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) INCLUDE_PATHS += -I$(SDL_INCLUDE_PATH) endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) INCLUDE_PATHS += -I/usr/include/libdrm endif @@ -273,7 +281,7 @@ endif #------------------------------------------------------------------------------------------------ LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) # NOTE: The resource .rc file contains windows executable icon and properties LDFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data @@ -289,7 +297,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH) endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) ifeq ($(PLATFORM_OS),WINDOWS) # NOTE: The resource .rc file contains windows executable icon and properties LDFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data @@ -300,7 +308,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) endif LDFLAGS += -L$(SDL_LIBRARY_PATH) endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 # -sUSE_GLFW=3 # Use glfw3 library (context/input management) @@ -347,7 +355,7 @@ endif # Define libraries required on linking: LDLIBS # NOTE: To link libraries (lib.so or lib.a), use -l #------------------------------------------------------------------------------------------------ -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation # NOTE: WinMM library required to set high-res timer resolution @@ -393,7 +401,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDLIBS += -lglfw endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation LDLIBS = -lraylib -lSDL2 -lSDL2main -lopengl32 -lgdi32 @@ -421,7 +429,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) LDLIBS += -latomic endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation LDLIBS = ..\src\libraylib.a -lgdi32 -lwinmm -lopengl32 @@ -446,12 +454,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW) LDLIBS += -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # Libraries for DRM compiling # NOTE: Required packages: libasound2-dev (ALSA) LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # Libraries for web (HTML5) compiling LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.a endif @@ -638,17 +646,17 @@ others: $(OTHERS) # Generic compilation pattern # NOTE: Examples must be ready for Android compilation! %: %.c -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) $(MAKE) -f Makefile.Android PROJECT_NAME=$@ PROJECT_SOURCE_FILES=$< -else ifeq ($(PLATFORM),PLATFORM_WEB) +else ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) $(MAKE) -f Makefile.Web $@ else - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -D$(TARGET_PLATFORM) endif # Clean everything clean: -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) del *.o *.exe /s endif @@ -661,11 +669,11 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) rm -f *.o endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) find . -type f -executable -delete rm -fv *.o endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM_OS),WINDOWS) del *.wasm *.html *.js *.data else diff --git a/examples/examples.rc b/examples/examples.rc new file mode 100644 index 000000000..4767ad480 --- /dev/null +++ b/examples/examples.rc @@ -0,0 +1,27 @@ +GLFW_ICON ICON "raylib.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + //BLOCK "080904E4" // English UK + BLOCK "040904E4" // English US + BEGIN + VALUE "CompanyName", "raylib technologies" + VALUE "FileDescription", "raylib example" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "raylib-example" + VALUE "LegalCopyright", "(c) 2024 raylib technologies (@raylibtech)" + //VALUE "OriginalFilename", "raylib_app.exe" + VALUE "ProductName", "raylib-example" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + //VALUE "Translation", 0x809, 1252 // English UK + VALUE "Translation", 0x409, 1252 // English US + END +END diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index 237e1b69d..cfb49e55c 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -44,10 +44,12 @@ int main(void) // NOTE: Billboard locked on axis-Y Vector3 billUp = { 0.0f, 1.0f, 0.0f }; + // Set the height of the rotating billboard to 1.0 with the aspect ratio fixed + Vector2 size = { source.width/source.height, 1.0f }; + // Rotate around origin // Here we choose to rotate around the image center - // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture - Vector2 rotateOrigin = { 0.0f }; + Vector2 origin = Vector2Scale(size, 0.5f); // Distance is needed for the correct billboard draw order // Larger distance (further away from the camera) should be drawn prior to smaller distance. @@ -84,11 +86,11 @@ int main(void) if (distanceStatic > distanceRotating) { DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE); - DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE); + DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); } else { - DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE); + DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE); } @@ -108,4 +110,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/models/models_loading_gltf.c b/examples/models/models_loading_gltf.c index e85b30e6c..8b8838c8d 100644 --- a/examples/models/models_loading_gltf.c +++ b/examples/models/models_loading_gltf.c @@ -30,11 +30,11 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf"); + InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf animations"); // Define the camera to look into our 3d world Camera camera = { 0 }; - camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position + camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y @@ -42,17 +42,14 @@ int main(void) // Load gltf model Model model = LoadModel("resources/models/gltf/robot.glb"); - + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position + // Load gltf model animations int animsCount = 0; unsigned int animIndex = 0; unsigned int animCurrentFrame = 0; ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/robot.glb", &animsCount); - Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - - DisableCursor(); // Limit cursor to relative movement inside the window - SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -61,7 +58,8 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - UpdateCamera(&camera, CAMERA_THIRD_PERSON); + UpdateCamera(&camera, CAMERA_ORBITAL); + // Select current animation if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) animIndex = (animIndex + 1)%animsCount; else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) animIndex = (animIndex + animsCount - 1)%animsCount; @@ -79,10 +77,8 @@ int main(void) ClearBackground(RAYWHITE); BeginMode3D(camera); - DrawModel(model, position, 1.0f, WHITE); // Draw animated model DrawGrid(10, 1.0f); - EndMode3D(); DrawText("Use the LEFT/RIGHT mouse buttons to switch animation", 10, 10, 20, GRAY); @@ -101,3 +97,6 @@ int main(void) return 0; } + + + diff --git a/examples/raylib.ico b/examples/raylib.ico new file mode 100644 index 000000000..0cedcc55c Binary files /dev/null and b/examples/raylib.ico differ diff --git a/examples/textures/textures_image_channel.c b/examples/textures/textures_image_channel.c new file mode 100644 index 000000000..39618c5f4 --- /dev/null +++ b/examples/textures/textures_image_channel.c @@ -0,0 +1,106 @@ +/******************************************************************************************* +* +* raylib [textures] example - Retrive image channel (mask) +* +* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) +* +* 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 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) +* +********************************************************************************************/ + +#include + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - extract channel from image"); + + Image fudesumiImage = LoadImage("resources/fudesumi.png"); + + Image imageAlpha = ImageFromChannel(fudesumiImage, 3); + ImageAlphaMask(&imageAlpha, imageAlpha); + + Image imageRed = ImageFromChannel(fudesumiImage, 0); + ImageAlphaMask(&imageRed, imageAlpha); + + Image imageGreen = ImageFromChannel(fudesumiImage, 1); + ImageAlphaMask(&imageGreen, imageAlpha); + + Image imageBlue = ImageFromChannel(fudesumiImage, 2); + ImageAlphaMask(&imageBlue, imageAlpha); + + Image backgroundImage = GenImageChecked(screenWidth, screenHeight, screenWidth/20, screenHeight/20, ORANGE, YELLOW); + + Texture2D fudesumiTexture = LoadTextureFromImage(fudesumiImage); + Texture2D textureAlpha = LoadTextureFromImage(imageAlpha); + Texture2D textureRed = LoadTextureFromImage(imageRed); + Texture2D textureGreen = LoadTextureFromImage(imageGreen); + Texture2D textureBlue = LoadTextureFromImage(imageBlue); + Texture2D backgroundTexture = LoadTextureFromImage(backgroundImage); + + UnloadImage(fudesumiImage); + UnloadImage(imageAlpha); + UnloadImage(imageRed); + UnloadImage(imageGreen); + UnloadImage(imageBlue); + UnloadImage(backgroundImage); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + + Rectangle fudesumiRec = {0, 0, fudesumiImage.width, fudesumiImage.height}; + + Rectangle fudesumiPos = {50, 10, fudesumiImage.width*0.8f, fudesumiImage.height*0.8f}; + Rectangle redPos = { 410, 10, fudesumiPos.width / 2, fudesumiPos.height / 2 }; + Rectangle greenPos = { 600, 10, fudesumiPos.width / 2, fudesumiPos.height / 2 }; + Rectangle bluePos = { 410, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 }; + Rectangle alphaPos = { 600, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 }; + + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + DrawTexture(backgroundTexture, 0, 0, WHITE); + DrawTexturePro(fudesumiTexture, fudesumiRec, fudesumiPos, (Vector2) {0, 0}, 0, WHITE); + + DrawTexturePro(textureRed, fudesumiRec, redPos, (Vector2) {0, 0}, 0, RED); + DrawTexturePro(textureGreen, fudesumiRec, greenPos, (Vector2) {0, 0}, 0, GREEN); + DrawTexturePro(textureBlue, fudesumiRec, bluePos, (Vector2) {0, 0}, 0, BLUE); + DrawTexturePro(textureAlpha, fudesumiRec, alphaPos, (Vector2) {0, 0}, 0, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(backgroundTexture); + UnloadTexture(fudesumiTexture); + UnloadTexture(textureRed); + UnloadTexture(textureGreen); + UnloadTexture(textureBlue); + UnloadTexture(textureAlpha); + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/textures/textures_image_channel.png b/examples/textures/textures_image_channel.png new file mode 100644 index 000000000..55e1d2eaa Binary files /dev/null and b/examples/textures/textures_image_channel.png differ diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 2baa6c3f3..c00407dc6 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -15,7 +15,7 @@ { "name": "RAYLIB_VERSION_MINOR", "type": "INT", - "value": 1, + "value": 5, "description": "" }, { @@ -27,7 +27,7 @@ { "name": "RAYLIB_VERSION", "type": "STRING", - "value": "5.1-dev", + "value": "5.5", "description": "" }, { @@ -1058,7 +1058,7 @@ { "type": "Vector3", "name": "direction", - "description": "Ray direction" + "description": "Ray direction (normalized)" } ] }, @@ -7183,6 +7183,21 @@ } ] }, + { + "name": "ImageFromChannel", + "description": "Create an image from a selected channel of another image (GRAYSCALE)", + "returnType": "Image", + "params": [ + { + "type": "Image", + "name": "image" + }, + { + "type": "int", + "name": "selectedChannel" + } + ] + }, { "name": "ImageText", "description": "Create an image from text (default font)", @@ -10385,7 +10400,7 @@ }, { "type": "float", - "name": "size" + "name": "scale" }, { "type": "Color", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index a6d91cd6d..9cbd1b9da 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -15,7 +15,7 @@ return { { name = "RAYLIB_VERSION_MINOR", type = "INT", - value = 1, + value = 5, description = "" }, { @@ -27,7 +27,7 @@ return { { name = "RAYLIB_VERSION", type = "STRING", - value = "5.1-dev", + value = "5.5", description = "" }, { @@ -1058,7 +1058,7 @@ return { { type = "Vector3", name = "direction", - description = "Ray direction" + description = "Ray direction (normalized)" } } }, @@ -5521,6 +5521,15 @@ return { {type = "Rectangle", name = "rec"} } }, + { + name = "ImageFromChannel", + description = "Create an image from a selected channel of another image (GRAYSCALE)", + returnType = "Image", + params = { + {type = "Image", name = "image"}, + {type = "int", name = "selectedChannel"} + } + }, { name = "ImageText", description = "Create an image from text (default font)", @@ -7221,7 +7230,7 @@ return { {type = "Camera", name = "camera"}, {type = "Texture2D", name = "texture"}, {type = "Vector3", name = "position"}, - {type = "float", name = "size"}, + {type = "float", name = "scale"}, {type = "Color", name = "tint"} } }, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index f283ad795..31433073e 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -14,7 +14,7 @@ Define 002: RAYLIB_VERSION_MAJOR Define 003: RAYLIB_VERSION_MINOR Name: RAYLIB_VERSION_MINOR Type: INT - Value: 1 + Value: 5 Description: Define 004: RAYLIB_VERSION_PATCH Name: RAYLIB_VERSION_PATCH @@ -24,7 +24,7 @@ Define 004: RAYLIB_VERSION_PATCH Define 005: RAYLIB_VERSION Name: RAYLIB_VERSION Type: STRING - Value: "5.1-dev" + Value: "5.5" Description: Define 006: __declspec(x) Name: __declspec(x) @@ -473,7 +473,7 @@ Struct 23: Ray (2 fields) Name: Ray Description: Ray, ray for raycasting Field[1]: Vector3 position // Ray position (origin) - Field[2]: Vector3 direction // Ray direction + Field[2]: Vector3 direction // Ray direction (normalized) Struct 24: RayCollision (4 fields) Name: RayCollision Description: RayCollision, ray hit information @@ -984,7 +984,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 572 +Functions found: 573 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -2773,14 +2773,20 @@ Function 293: ImageFromImage() (2 input parameters) Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 294: ImageText() (3 input parameters) +Function 294: ImageFromChannel() (2 input parameters) + Name: ImageFromChannel + Return type: Image + Description: Create an image from a selected channel of another image (GRAYSCALE) + Param[1]: image (type: Image) + Param[2]: selectedChannel (type: int) +Function 295: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 295: ImageTextEx() (5 input parameters) +Function 296: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2789,76 +2795,76 @@ Function 295: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 296: ImageFormat() (2 input parameters) +Function 297: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 297: ImageToPOT() (2 input parameters) +Function 298: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 298: ImageCrop() (2 input parameters) +Function 299: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 299: ImageAlphaCrop() (2 input parameters) +Function 300: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 300: ImageAlphaClear() (3 input parameters) +Function 301: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 301: ImageAlphaMask() (2 input parameters) +Function 302: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 302: ImageAlphaPremultiply() (1 input parameters) +Function 303: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 303: ImageBlurGaussian() (2 input parameters) +Function 304: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 304: ImageKernelConvolution() (3 input parameters) +Function 305: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 305: ImageResize() (3 input parameters) +Function 306: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 306: ImageResizeNN() (3 input parameters) +Function 307: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 307: ImageResizeCanvas() (6 input parameters) +Function 308: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2868,12 +2874,12 @@ Function 307: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 308: ImageMipmaps() (1 input parameters) +Function 309: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 309: ImageDither() (5 input parameters) +Function 310: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2882,109 +2888,109 @@ Function 309: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 310: ImageFlipVertical() (1 input parameters) +Function 311: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 311: ImageFlipHorizontal() (1 input parameters) +Function 312: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 312: ImageRotate() (2 input parameters) +Function 313: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 313: ImageRotateCW() (1 input parameters) +Function 314: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 314: ImageRotateCCW() (1 input parameters) +Function 315: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 315: ImageColorTint() (2 input parameters) +Function 316: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 316: ImageColorInvert() (1 input parameters) +Function 317: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 317: ImageColorGrayscale() (1 input parameters) +Function 318: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 318: ImageColorContrast() (2 input parameters) +Function 319: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 319: ImageColorBrightness() (2 input parameters) +Function 320: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 320: ImageColorReplace() (3 input parameters) +Function 321: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 321: LoadImageColors() (1 input parameters) +Function 322: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 322: LoadImagePalette() (3 input parameters) +Function 323: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 323: UnloadImageColors() (1 input parameters) +Function 324: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 324: UnloadImagePalette() (1 input parameters) +Function 325: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 325: GetImageAlphaBorder() (2 input parameters) +Function 326: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 326: GetImageColor() (3 input parameters) +Function 327: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 327: ImageClearBackground() (2 input parameters) +Function 328: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 328: ImageDrawPixel() (4 input parameters) +Function 329: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -2992,14 +2998,14 @@ Function 328: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 329: ImageDrawPixelV() (3 input parameters) +Function 330: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 330: ImageDrawLine() (6 input parameters) +Function 331: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3009,7 +3015,7 @@ Function 330: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 331: ImageDrawLineV() (4 input parameters) +Function 332: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3017,7 +3023,7 @@ Function 331: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 332: ImageDrawLineEx() (5 input parameters) +Function 333: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3026,7 +3032,7 @@ Function 332: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 333: ImageDrawCircle() (5 input parameters) +Function 334: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3035,7 +3041,7 @@ Function 333: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 334: ImageDrawCircleV() (4 input parameters) +Function 335: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3043,7 +3049,7 @@ Function 334: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 335: ImageDrawCircleLines() (5 input parameters) +Function 336: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3052,7 +3058,7 @@ Function 335: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 336: ImageDrawCircleLinesV() (4 input parameters) +Function 337: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3060,7 +3066,7 @@ Function 336: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 337: ImageDrawRectangle() (6 input parameters) +Function 338: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3070,7 +3076,7 @@ Function 337: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 338: ImageDrawRectangleV() (4 input parameters) +Function 339: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3078,14 +3084,14 @@ Function 338: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 339: ImageDrawRectangleRec() (3 input parameters) +Function 340: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 340: ImageDrawRectangleLines() (4 input parameters) +Function 341: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3093,7 +3099,7 @@ Function 340: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 341: ImageDrawTriangle() (5 input parameters) +Function 342: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3102,7 +3108,7 @@ Function 341: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 342: ImageDrawTriangleEx() (7 input parameters) +Function 343: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3113,7 +3119,7 @@ Function 342: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 343: ImageDrawTriangleLines() (5 input parameters) +Function 344: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3122,7 +3128,7 @@ Function 343: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 344: ImageDrawTriangleFan() (4 input parameters) +Function 345: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3130,7 +3136,7 @@ Function 344: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 345: ImageDrawTriangleStrip() (4 input parameters) +Function 346: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3138,7 +3144,7 @@ Function 345: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 346: ImageDraw() (5 input parameters) +Function 347: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3147,7 +3153,7 @@ Function 346: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 347: ImageDrawText() (6 input parameters) +Function 348: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3157,7 +3163,7 @@ Function 347: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 348: ImageDrawTextEx() (7 input parameters) +Function 349: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3168,79 +3174,79 @@ Function 348: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 349: LoadTexture() (1 input parameters) +Function 350: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 350: LoadTextureFromImage() (1 input parameters) +Function 351: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 351: LoadTextureCubemap() (2 input parameters) +Function 352: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 352: LoadRenderTexture() (2 input parameters) +Function 353: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 353: IsTextureReady() (1 input parameters) +Function 354: IsTextureReady() (1 input parameters) Name: IsTextureReady Return type: bool Description: Check if a texture is ready Param[1]: texture (type: Texture2D) -Function 354: UnloadTexture() (1 input parameters) +Function 355: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 355: IsRenderTextureReady() (1 input parameters) +Function 356: IsRenderTextureReady() (1 input parameters) Name: IsRenderTextureReady Return type: bool Description: Check if a render texture is ready Param[1]: target (type: RenderTexture2D) -Function 356: UnloadRenderTexture() (1 input parameters) +Function 357: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 357: UpdateTexture() (2 input parameters) +Function 358: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 358: UpdateTextureRec() (3 input parameters) +Function 359: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 359: GenTextureMipmaps() (1 input parameters) +Function 360: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 360: SetTextureFilter() (2 input parameters) +Function 361: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 361: SetTextureWrap() (2 input parameters) +Function 362: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 362: DrawTexture() (4 input parameters) +Function 363: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3248,14 +3254,14 @@ Function 362: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 363: DrawTextureV() (3 input parameters) +Function 364: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 364: DrawTextureEx() (5 input parameters) +Function 365: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3264,7 +3270,7 @@ Function 364: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 365: DrawTextureRec() (4 input parameters) +Function 366: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3272,7 +3278,7 @@ Function 365: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 366: DrawTexturePro() (6 input parameters) +Function 367: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3282,7 +3288,7 @@ Function 366: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 367: DrawTextureNPatch() (6 input parameters) +Function 368: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3292,112 +3298,112 @@ Function 367: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 368: ColorIsEqual() (2 input parameters) +Function 369: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 369: Fade() (2 input parameters) +Function 370: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 370: ColorToInt() (1 input parameters) +Function 371: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 371: ColorNormalize() (1 input parameters) +Function 372: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 372: ColorFromNormalized() (1 input parameters) +Function 373: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 373: ColorToHSV() (1 input parameters) +Function 374: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 374: ColorFromHSV() (3 input parameters) +Function 375: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 375: ColorTint() (2 input parameters) +Function 376: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 376: ColorBrightness() (2 input parameters) +Function 377: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 377: ColorContrast() (2 input parameters) +Function 378: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 378: ColorAlpha() (2 input parameters) +Function 379: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 379: ColorAlphaBlend() (3 input parameters) +Function 380: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 380: GetColor() (1 input parameters) +Function 381: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 381: GetPixelColor() (2 input parameters) +Function 382: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 382: SetPixelColor() (3 input parameters) +Function 383: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 383: GetPixelDataSize() (3 input parameters) +Function 384: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 384: GetFontDefault() (0 input parameters) +Function 385: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 385: LoadFont() (1 input parameters) +Function 386: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 386: LoadFontEx() (4 input parameters) +Function 387: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont @@ -3405,14 +3411,14 @@ Function 386: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 387: LoadFontFromImage() (3 input parameters) +Function 388: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 388: LoadFontFromMemory() (6 input parameters) +Function 389: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3422,12 +3428,12 @@ Function 388: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 389: IsFontReady() (1 input parameters) +Function 390: IsFontReady() (1 input parameters) Name: IsFontReady Return type: bool Description: Check if a font is ready Param[1]: font (type: Font) -Function 390: LoadFontData() (6 input parameters) +Function 391: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3437,7 +3443,7 @@ Function 390: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 391: GenImageFontAtlas() (6 input parameters) +Function 392: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3447,30 +3453,30 @@ Function 391: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 392: UnloadFontData() (2 input parameters) +Function 393: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 393: UnloadFont() (1 input parameters) +Function 394: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 394: ExportFontAsCode() (2 input parameters) +Function 395: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 395: DrawFPS() (2 input parameters) +Function 396: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 396: DrawText() (5 input parameters) +Function 397: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3479,7 +3485,7 @@ Function 396: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 397: DrawTextEx() (6 input parameters) +Function 398: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3489,7 +3495,7 @@ Function 397: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 398: DrawTextPro() (8 input parameters) +Function 399: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3501,7 +3507,7 @@ Function 398: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 399: DrawTextCodepoint() (5 input parameters) +Function 400: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3510,7 +3516,7 @@ Function 399: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 400: DrawTextCodepoints() (7 input parameters) +Function 401: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3521,18 +3527,18 @@ Function 400: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 401: SetTextLineSpacing() (1 input parameters) +Function 402: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 402: MeasureText() (2 input parameters) +Function 403: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 403: MeasureTextEx() (4 input parameters) +Function 404: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3540,195 +3546,195 @@ Function 403: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 404: GetGlyphIndex() (2 input parameters) +Function 405: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 405: GetGlyphInfo() (2 input parameters) +Function 406: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 406: GetGlyphAtlasRec() (2 input parameters) +Function 407: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 407: LoadUTF8() (2 input parameters) +Function 408: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 408: UnloadUTF8() (1 input parameters) +Function 409: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 409: LoadCodepoints() (2 input parameters) +Function 410: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 410: UnloadCodepoints() (1 input parameters) +Function 411: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 411: GetCodepointCount() (1 input parameters) +Function 412: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 412: GetCodepoint() (2 input parameters) +Function 413: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 413: GetCodepointNext() (2 input parameters) +Function 414: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 414: GetCodepointPrevious() (2 input parameters) +Function 415: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 415: CodepointToUTF8() (2 input parameters) +Function 416: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 416: TextCopy() (2 input parameters) +Function 417: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 417: TextIsEqual() (2 input parameters) +Function 418: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 418: TextLength() (1 input parameters) +Function 419: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 419: TextFormat() (2 input parameters) +Function 420: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 420: TextSubtext() (3 input parameters) +Function 421: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 421: TextReplace() (3 input parameters) +Function 422: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 422: TextInsert() (3 input parameters) +Function 423: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 423: TextJoin() (3 input parameters) +Function 424: TextJoin() (3 input parameters) Name: TextJoin Return type: const char * Description: Join text strings with delimiter Param[1]: textList (type: const char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 424: TextSplit() (3 input parameters) +Function 425: TextSplit() (3 input parameters) Name: TextSplit Return type: const char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 425: TextAppend() (3 input parameters) +Function 426: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 426: TextFindIndex() (2 input parameters) +Function 427: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 427: TextToUpper() (1 input parameters) +Function 428: TextToUpper() (1 input parameters) Name: TextToUpper Return type: const char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 428: TextToLower() (1 input parameters) +Function 429: TextToLower() (1 input parameters) Name: TextToLower Return type: const char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 429: TextToPascal() (1 input parameters) +Function 430: TextToPascal() (1 input parameters) Name: TextToPascal Return type: const char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 430: TextToSnake() (1 input parameters) +Function 431: TextToSnake() (1 input parameters) Name: TextToSnake Return type: const char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 431: TextToCamel() (1 input parameters) +Function 432: TextToCamel() (1 input parameters) Name: TextToCamel Return type: const char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 432: TextToInteger() (1 input parameters) +Function 433: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text (negative values not supported) Param[1]: text (type: const char *) -Function 433: TextToFloat() (1 input parameters) +Function 434: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text (negative values not supported) Param[1]: text (type: const char *) -Function 434: DrawLine3D() (3 input parameters) +Function 435: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 435: DrawPoint3D() (2 input parameters) +Function 436: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 436: DrawCircle3D() (5 input parameters) +Function 437: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3737,7 +3743,7 @@ Function 436: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 437: DrawTriangle3D() (4 input parameters) +Function 438: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3745,14 +3751,14 @@ Function 437: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 438: DrawTriangleStrip3D() (3 input parameters) +Function 439: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 439: DrawCube() (5 input parameters) +Function 440: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3761,14 +3767,14 @@ Function 439: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 440: DrawCubeV() (3 input parameters) +Function 441: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 441: DrawCubeWires() (5 input parameters) +Function 442: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3777,21 +3783,21 @@ Function 441: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 442: DrawCubeWiresV() (3 input parameters) +Function 443: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 443: DrawSphere() (3 input parameters) +Function 444: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 444: DrawSphereEx() (5 input parameters) +Function 445: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3800,7 +3806,7 @@ Function 444: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 445: DrawSphereWires() (5 input parameters) +Function 446: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3809,7 +3815,7 @@ Function 445: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 446: DrawCylinder() (6 input parameters) +Function 447: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3819,7 +3825,7 @@ Function 446: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 447: DrawCylinderEx() (6 input parameters) +Function 448: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3829,7 +3835,7 @@ Function 447: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 448: DrawCylinderWires() (6 input parameters) +Function 449: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3839,7 +3845,7 @@ Function 448: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 449: DrawCylinderWiresEx() (6 input parameters) +Function 450: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3849,7 +3855,7 @@ Function 449: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 450: DrawCapsule() (6 input parameters) +Function 451: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3859,7 +3865,7 @@ Function 450: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 451: DrawCapsuleWires() (6 input parameters) +Function 452: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3869,51 +3875,51 @@ Function 451: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 452: DrawPlane() (3 input parameters) +Function 453: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 453: DrawRay() (2 input parameters) +Function 454: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 454: DrawGrid() (2 input parameters) +Function 455: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 455: LoadModel() (1 input parameters) +Function 456: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 456: LoadModelFromMesh() (1 input parameters) +Function 457: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 457: IsModelReady() (1 input parameters) +Function 458: IsModelReady() (1 input parameters) Name: IsModelReady Return type: bool Description: Check if a model is ready Param[1]: model (type: Model) -Function 458: UnloadModel() (1 input parameters) +Function 459: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 459: GetModelBoundingBox() (1 input parameters) +Function 460: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 460: DrawModel() (4 input parameters) +Function 461: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3921,7 +3927,7 @@ Function 460: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 461: DrawModelEx() (6 input parameters) +Function 462: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3931,7 +3937,7 @@ Function 461: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 462: DrawModelWires() (4 input parameters) +Function 463: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3939,7 +3945,7 @@ Function 462: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 463: DrawModelWiresEx() (6 input parameters) +Function 464: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3949,22 +3955,22 @@ Function 463: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 464: DrawBoundingBox() (2 input parameters) +Function 465: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 465: DrawBillboard() (5 input parameters) +Function 466: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture Param[1]: camera (type: Camera) Param[2]: texture (type: Texture2D) Param[3]: position (type: Vector3) - Param[4]: size (type: float) + Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 466: DrawBillboardRec() (6 input parameters) +Function 467: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -3974,7 +3980,7 @@ Function 466: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 467: DrawBillboardPro() (9 input parameters) +Function 468: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -3987,13 +3993,13 @@ Function 467: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 468: UploadMesh() (2 input parameters) +Function 469: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 469: UpdateMeshBuffer() (5 input parameters) +Function 470: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4002,19 +4008,19 @@ Function 469: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 470: UnloadMesh() (1 input parameters) +Function 471: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 471: DrawMesh() (3 input parameters) +Function 472: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 472: DrawMeshInstanced() (4 input parameters) +Function 473: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4022,35 +4028,35 @@ Function 472: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 473: GetMeshBoundingBox() (1 input parameters) +Function 474: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 474: GenMeshTangents() (1 input parameters) +Function 475: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 475: ExportMesh() (2 input parameters) +Function 476: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 476: ExportMeshAsCode() (2 input parameters) +Function 477: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 477: GenMeshPoly() (2 input parameters) +Function 478: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 478: GenMeshPlane() (4 input parameters) +Function 479: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4058,42 +4064,42 @@ Function 478: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 479: GenMeshCube() (3 input parameters) +Function 480: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 480: GenMeshSphere() (3 input parameters) +Function 481: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 481: GenMeshHemiSphere() (3 input parameters) +Function 482: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 482: GenMeshCylinder() (3 input parameters) +Function 483: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 483: GenMeshCone() (3 input parameters) +Function 484: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 484: GenMeshTorus() (4 input parameters) +Function 485: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4101,7 +4107,7 @@ Function 484: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 485: GenMeshKnot() (4 input parameters) +Function 486: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4109,84 +4115,84 @@ Function 485: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 486: GenMeshHeightmap() (2 input parameters) +Function 487: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 487: GenMeshCubicmap() (2 input parameters) +Function 488: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 488: LoadMaterials() (2 input parameters) +Function 489: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 489: LoadMaterialDefault() (0 input parameters) +Function 490: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 490: IsMaterialReady() (1 input parameters) +Function 491: IsMaterialReady() (1 input parameters) Name: IsMaterialReady Return type: bool Description: Check if a material is ready Param[1]: material (type: Material) -Function 491: UnloadMaterial() (1 input parameters) +Function 492: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 492: SetMaterialTexture() (3 input parameters) +Function 493: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 493: SetModelMeshMaterial() (3 input parameters) +Function 494: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 494: LoadModelAnimations() (2 input parameters) +Function 495: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 495: UpdateModelAnimation() (3 input parameters) +Function 496: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 496: UnloadModelAnimation() (1 input parameters) +Function 497: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 497: UnloadModelAnimations() (2 input parameters) +Function 498: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 498: IsModelAnimationValid() (2 input parameters) +Function 499: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 499: CheckCollisionSpheres() (4 input parameters) +Function 500: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4194,40 +4200,40 @@ Function 499: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 500: CheckCollisionBoxes() (2 input parameters) +Function 501: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 501: CheckCollisionBoxSphere() (3 input parameters) +Function 502: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 502: GetRayCollisionSphere() (3 input parameters) +Function 503: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 503: GetRayCollisionBox() (2 input parameters) +Function 504: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 504: GetRayCollisionMesh() (3 input parameters) +Function 505: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 505: GetRayCollisionTriangle() (4 input parameters) +Function 506: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4235,7 +4241,7 @@ Function 505: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 506: GetRayCollisionQuad() (5 input parameters) +Function 507: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4244,158 +4250,158 @@ Function 506: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 507: InitAudioDevice() (0 input parameters) +Function 508: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 508: CloseAudioDevice() (0 input parameters) +Function 509: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 509: IsAudioDeviceReady() (0 input parameters) +Function 510: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 510: SetMasterVolume() (1 input parameters) +Function 511: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 511: GetMasterVolume() (0 input parameters) +Function 512: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 512: LoadWave() (1 input parameters) +Function 513: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 513: LoadWaveFromMemory() (3 input parameters) +Function 514: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 514: IsWaveReady() (1 input parameters) +Function 515: IsWaveReady() (1 input parameters) Name: IsWaveReady Return type: bool Description: Checks if wave data is ready Param[1]: wave (type: Wave) -Function 515: LoadSound() (1 input parameters) +Function 516: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 516: LoadSoundFromWave() (1 input parameters) +Function 517: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 517: LoadSoundAlias() (1 input parameters) +Function 518: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 518: IsSoundReady() (1 input parameters) +Function 519: IsSoundReady() (1 input parameters) Name: IsSoundReady Return type: bool Description: Checks if a sound is ready Param[1]: sound (type: Sound) -Function 519: UpdateSound() (3 input parameters) +Function 520: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 520: UnloadWave() (1 input parameters) +Function 521: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 521: UnloadSound() (1 input parameters) +Function 522: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 522: UnloadSoundAlias() (1 input parameters) +Function 523: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 523: ExportWave() (2 input parameters) +Function 524: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 524: ExportWaveAsCode() (2 input parameters) +Function 525: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 525: PlaySound() (1 input parameters) +Function 526: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 526: StopSound() (1 input parameters) +Function 527: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 527: PauseSound() (1 input parameters) +Function 528: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 528: ResumeSound() (1 input parameters) +Function 529: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 529: IsSoundPlaying() (1 input parameters) +Function 530: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 530: SetSoundVolume() (2 input parameters) +Function 531: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 531: SetSoundPitch() (2 input parameters) +Function 532: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 532: SetSoundPan() (2 input parameters) +Function 533: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 533: WaveCopy() (1 input parameters) +Function 534: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 534: WaveCrop() (3 input parameters) +Function 535: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 535: WaveFormat() (4 input parameters) +Function 536: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4403,203 +4409,203 @@ Function 535: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 536: LoadWaveSamples() (1 input parameters) +Function 537: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 537: UnloadWaveSamples() (1 input parameters) +Function 538: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 538: LoadMusicStream() (1 input parameters) +Function 539: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 539: LoadMusicStreamFromMemory() (3 input parameters) +Function 540: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 540: IsMusicReady() (1 input parameters) +Function 541: IsMusicReady() (1 input parameters) Name: IsMusicReady Return type: bool Description: Checks if a music stream is ready Param[1]: music (type: Music) -Function 541: UnloadMusicStream() (1 input parameters) +Function 542: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 542: PlayMusicStream() (1 input parameters) +Function 543: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 543: IsMusicStreamPlaying() (1 input parameters) +Function 544: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 544: UpdateMusicStream() (1 input parameters) +Function 545: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 545: StopMusicStream() (1 input parameters) +Function 546: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 546: PauseMusicStream() (1 input parameters) +Function 547: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 547: ResumeMusicStream() (1 input parameters) +Function 548: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 548: SeekMusicStream() (2 input parameters) +Function 549: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 549: SetMusicVolume() (2 input parameters) +Function 550: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 550: SetMusicPitch() (2 input parameters) +Function 551: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 551: SetMusicPan() (2 input parameters) +Function 552: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 552: GetMusicTimeLength() (1 input parameters) +Function 553: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 553: GetMusicTimePlayed() (1 input parameters) +Function 554: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 554: LoadAudioStream() (3 input parameters) +Function 555: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 555: IsAudioStreamReady() (1 input parameters) +Function 556: IsAudioStreamReady() (1 input parameters) Name: IsAudioStreamReady Return type: bool Description: Checks if an audio stream is ready Param[1]: stream (type: AudioStream) -Function 556: UnloadAudioStream() (1 input parameters) +Function 557: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 557: UpdateAudioStream() (3 input parameters) +Function 558: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 558: IsAudioStreamProcessed() (1 input parameters) +Function 559: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 559: PlayAudioStream() (1 input parameters) +Function 560: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 560: PauseAudioStream() (1 input parameters) +Function 561: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 561: ResumeAudioStream() (1 input parameters) +Function 562: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 562: IsAudioStreamPlaying() (1 input parameters) +Function 563: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 563: StopAudioStream() (1 input parameters) +Function 564: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 564: SetAudioStreamVolume() (2 input parameters) +Function 565: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 565: SetAudioStreamPitch() (2 input parameters) +Function 566: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 566: SetAudioStreamPan() (2 input parameters) +Function 567: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 567: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 568: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 568: SetAudioStreamCallback() (2 input parameters) +Function 569: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 569: AttachAudioStreamProcessor() (2 input parameters) +Function 570: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 570: DetachAudioStreamProcessor() (2 input parameters) +Function 571: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 571: AttachAudioMixedProcessor() (1 input parameters) +Function 572: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 572: DetachAudioMixedProcessor() (1 input parameters) +Function 573: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index fa953b626..51473562c 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -3,9 +3,9 @@ - + - + @@ -220,7 +220,7 @@ - + @@ -670,7 +670,7 @@ - + @@ -1798,6 +1798,10 @@ + + + + @@ -2641,7 +2645,7 @@ - + diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index ee258d604..3b22964c5 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -5,7 +5,7 @@ project(example) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Dependencies -set(RAYLIB_VERSION 5.0) +set(RAYLIB_VERSION 5.5) find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED if (NOT raylib_FOUND) # If there's none, fetch and build raylib include(FetchContent) diff --git a/projects/VS2022/examples/models_loading_gltf.vcxproj b/projects/VS2022/examples/models_loading_gltf.vcxproj index 141fb9423..aba2e6843 100644 --- a/projects/VS2022/examples/models_loading_gltf.vcxproj +++ b/projects/VS2022/examples/models_loading_gltf.vcxproj @@ -376,6 +376,9 @@ + + + {e89d61ac-55de-4482-afd4-df7242ebc859} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1360ee29..8f4d0e26e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ # Setup the project and settings project(raylib C) -set(PROJECT_VERSION 5.0.0) -set(API_VERSION 500) +set(PROJECT_VERSION 5.5.0) +set(API_VERSION 550) include(GNUInstallDirs) include(JoinPaths) diff --git a/src/Makefile b/src/Makefile index 19251b956..c68a03797 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,9 @@ # # This file supports building raylib library for the following platforms: # -# > PLATFORM_DESKTOP (GLFW backend): +# > PLATFORM_DESKTOP +# - Defaults to PLATFORM_DESKTOP_GLFW +# > PLATFORM_DESKTOP_GLFW (GLFW backend): # - Windows (Win32, Win64) # - Linux (X11/Wayland desktop mode) # - macOS/OSX (x64, arm64) @@ -55,12 +57,18 @@ # Define required environment variables #------------------------------------------------------------------------------------------------ -# Define target platform: PLATFORM_DESKTOP, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB +# Define target platform PLATFORM ?= PLATFORM_DESKTOP +ifeq ($(PLATFORM), PLATFORM_DESKTOP) + TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW +else + TARGET_PLATFORM = $(PLATFORM) +endif + # Define required raylib variables -RAYLIB_VERSION = 5.0.0 -RAYLIB_API_VERSION = 500 +RAYLIB_VERSION = 5.5.0 +RAYLIB_API_VERSION = 550 # Define raylib source code path RAYLIB_SRC_PATH ?= ../src @@ -119,7 +127,7 @@ HOST_PLATFORM_OS ?= WINDOWS PLATFORM_OS ?= WINDOWS # Determine PLATFORM_OS when required -ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_ANDROID PLATFORM_DESKTOP_RGFW)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_ANDROID)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -152,7 +160,7 @@ ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLA endif endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) UNAMEOS = $(shell uname) ifeq ($(UNAMEOS),Linux) PLATFORM_OS = LINUX @@ -161,7 +169,7 @@ ifeq ($(PLATFORM),PLATFORM_DRM) PLATFORM_SHELL = sh endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM_OS),LINUX) ifndef PLATFORM_SHELL PLATFORM_SHELL = sh @@ -169,7 +177,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM_OS), WINDOWS) # Emscripten required variables EMSDK_PATH ?= C:/emsdk @@ -181,7 +189,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # Android architecture # Starting at 2019 using arm64 is mandatory for published apps, # Starting on August 2020, minimum required target API is Android 10 (API level 29) @@ -221,7 +229,7 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID) endif # Define raylib graphics api depending on selected platform -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) # By default use OpenGL 3.3 on desktop platforms GRAPHICS ?= GRAPHICS_API_OPENGL_33 #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 @@ -229,28 +237,28 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW) - # By default use OpenGL 3.3 on desktop platforms - GRAPHICS ?= GRAPHICS_API_OPENGL_33 - #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 - #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 - #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 - #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) -endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) # By default use OpenGL 3.3 on desktop platform with SDL backend GRAPHICS ?= GRAPHICS_API_OPENGL_33 endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) + # By default use OpenGL 3.3 on desktop platforms + GRAPHICS ?= GRAPHICS_API_OPENGL_33 + #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 + #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 + #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 + #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) +endif +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # On DRM OpenGL ES 2.0 must be used GRAPHICS = GRAPHICS_API_OPENGL_ES2 endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 GRAPHICS = GRAPHICS_API_OPENGL_ES2 #GRAPHICS = GRAPHICS_API_OPENGL_ES3 # Uncomment to use ES3/WebGL2 (preliminary support). endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android GRAPHICS = GRAPHICS_API_OPENGL_ES2 endif @@ -260,7 +268,7 @@ endif CC = gcc AR = ar -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),OSX) # OSX default compiler CC = clang @@ -271,7 +279,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) CC = clang endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) # Define RPI cross-compiler #CC = armv6j-hardfloat-linux-gnueabi-gcc @@ -279,12 +287,12 @@ ifeq ($(PLATFORM),PLATFORM_DRM) AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler CC = emcc AR = emar endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # Android toolchain (must be provided for desired architecture and compiler) ifeq ($(ANDROID_ARCH),arm) CC = $(ANDROID_TOOLCHAIN)/bin/$(ANDROID_COMPILER_ARCH)-linux-androideabi$(ANDROID_API_VERSION)-clang @@ -316,13 +324,13 @@ endif # -D_GNU_SOURCE access to lots of nonstandard GNU/Linux extension functions # -Werror=pointer-arith catch unportable code that does direct arithmetic on void pointers # -fno-strict-aliasing jar_xm.h does shady stuff (breaks strict aliasing) -CFLAGS = -Wall -D_GNU_SOURCE -D$(PLATFORM) -D$(GRAPHICS) -Wno-missing-braces -Werror=pointer-arith -fno-strict-aliasing +CFLAGS = -Wall -D_GNU_SOURCE -D$(TARGET_PLATFORM) -D$(GRAPHICS) -Wno-missing-braces -Werror=pointer-arith -fno-strict-aliasing ifneq ($(RAYLIB_CONFIG_FLAGS), NONE) CFLAGS += -DEXTERNAL_CONFIG_FLAGS $(RAYLIB_CONFIG_FLAGS) endif -ifeq ($(PLATFORM), PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM), PLATFORM_WEB) # NOTE: When using multi-threading in the user code, it requires -pthread enabled CFLAGS += -std=gnu99 else @@ -338,13 +346,13 @@ ifeq ($(RAYLIB_BUILD_MODE),DEBUG) endif ifeq ($(RAYLIB_BUILD_MODE),RELEASE) - ifeq ($(PLATFORM),PLATFORM_WEB) + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) CFLAGS += -Os endif - ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CFLAGS += -O1 endif - ifeq ($(PLATFORM),PLATFORM_ANDROID) + ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) CFLAGS += -O2 endif endif @@ -354,10 +362,10 @@ endif # -Wmissing-prototypes warn if a global function is defined without a previous prototype declaration # -Wstrict-prototypes warn if a function is declared or defined without specifying the argument types # -Werror=implicit-function-declaration catch function calls without prior declaration -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CFLAGS += -Werror=implicit-function-declaration endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 # -sUSE_GLFW=3 # Use glfw3 library (context/input management) -> Only for linker! @@ -375,7 +383,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif #CFLAGS += -sGL_ENABLE_GET_PROC_ADDRESS endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # Compiler flags for arquitecture ifeq ($(ANDROID_ARCH),arm) CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 @@ -411,19 +419,18 @@ ifeq ($(RAYLIB_LIBTYPE),SHARED) endif endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # without EGL_NO_X11 eglplatform.h tears Xlib.h in which tears X.h in # which contains a conflicting type Font CFLAGS += -DEGL_NO_X11 CFLAGS += -Werror=implicit-function-declaration endif # Use Wayland display on Linux desktop -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS), LINUX) ifeq ($(GLFW_LINUX_ENABLE_X11),TRUE) CFLAGS += -D_GLFW_X11 endif - ifeq ($(GLFW_LINUX_ENABLE_WAYLAND),TRUE) CFLAGS += -D_GLFW_WAYLAND LDFLAGS += $(shell pkg-config wayland-client wayland-cursor wayland-egl xkbcommon --libs) @@ -457,26 +464,26 @@ CFLAGS += $(CUSTOM_CFLAGS) INCLUDE_PATHS = -I. # Define additional directories containing required header files -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) INCLUDE_PATHS += -Iexternal/glfw/include ifeq ($(PLATFORM_OS),BSD) INCLUDE_PATHS += -I/usr/local/include endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) INCLUDE_PATHS += -I$(SDL_INCLUDE_PATH) endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) INCLUDE_PATHS += -Iexternal/glfw/include endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) INCLUDE_PATHS += -I/usr/include/libdrm ifeq ($(USE_RPI_CROSSCOMPILER), TRUE) INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/usr/include INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include endif endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) NATIVE_APP_GLUE = $(ANDROID_NDK)/sources/android/native_app_glue # Include android_native_app_glue.h INCLUDE_PATHS += -I$(NATIVE_APP_GLUE) @@ -502,7 +509,7 @@ endif #------------------------------------------------------------------------------------------------ LDFLAGS = $(CUSTOM_LDFLAGS) -L. -L$(RAYLIB_RELEASE_PATH) -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) ifneq ($(CC), tcc) LDFLAGS += -Wl,--out-implib,$(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME)dll.a @@ -518,17 +525,17 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) LDFLAGS += -L$(SDL_LIBRARY_PATH) endif -ifeq ($(PLATFORM),PLATFORM_DRM) +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) ifeq ($(USE_RPI_CROSSCOMPILER), TRUE) LDFLAGS += -L$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/lib -L$(RPI_TOOLCHAIN_SYSROOT)/usr/lib endif endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) LDFLAGS += -Wl,-soname,libraylib.$(RAYLIB_API_VERSION).so -Wl,--exclude-libs,libatomic.a LDFLAGS += -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings # Force linking of library module to define symbol @@ -542,7 +549,7 @@ endif # Define libraries required on linking: LDLIBS # NOTE: This is only required for dynamic library generation #------------------------------------------------------------------------------------------------ -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),WINDOWS) ifeq ($(CC), tcc) LDLIBS = -lopengl32 -lgdi32 -lwinmm -lshell32 @@ -570,7 +577,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDLIBS = -lglfw endif endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) ifeq ($(PLATFORM_OS),WINDOWS) LDLIBS = -static-libgcc -lopengl32 -lgdi32 endif @@ -582,16 +589,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL) endif LDLIBS += -lSDL2 -lSDL2main endif -ifeq ($(PLATFORM),PLATFORM_DRM) - LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl - ifeq ($(RAYLIB_MODULE_AUDIO),TRUE) - LDLIBS += -latomic - endif -endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) - LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm -endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation LDLIBS = -lgdi32 -lwinmm -lopengl32 @@ -615,6 +613,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW) LDLIBS += -lm -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo endif endif +ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) + LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl + ifeq ($(RAYLIB_MODULE_AUDIO),TRUE) + LDLIBS += -latomic + endif +endif +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) + LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm +endif # Define source code object files required #------------------------------------------------------------------------------------------------ @@ -624,8 +631,7 @@ OBJS = rcore.o \ rtext.o \ utils.o - -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(USE_EXTERNAL_GLFW),FALSE) OBJS += rglfw.o endif @@ -640,7 +646,7 @@ ifeq ($(RAYLIB_MODULE_RAYGUI),TRUE) OBJS += raygui.o endif -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) OBJS += android_native_app_glue.o endif @@ -652,14 +658,14 @@ all: raylib # Compile raylib library # NOTE: Release directory is created if not exist raylib: $(OBJS) -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) # Compile raylib libray for web #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(OBJS) @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).a)!" else ifeq ($(RAYLIB_LIBTYPE),SHARED) - ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) + ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) ifeq ($(PLATFORM_OS),WINDOWS) # NOTE: Linking with provided resource file $(CC) -shared -o $(RAYLIB_RELEASE_PATH)/$(RAYLIB_LIB_NAME).dll $(OBJS) $(RAYLIB_RES_FILE) $(LDFLAGS) $(LDLIBS) @@ -688,7 +694,7 @@ else cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).so lib$(RAYLIB_LIB_NAME).so endif endif - ifeq ($(PLATFORM),PLATFORM_DRM) + ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # Compile raylib shared library version $(RAYLIB_VERSION). # WARNING: you should type "make clean" before doing this target $(CC) -shared -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_VERSION) $(OBJS) $(LDFLAGS) $(LDLIBS) @@ -696,7 +702,7 @@ else cd $(RAYLIB_RELEASE_PATH) && ln -fsv lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_VERSION) lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) cd $(RAYLIB_RELEASE_PATH) && ln -fsv lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) lib$(RAYLIB_LIB_NAME).so endif - ifeq ($(PLATFORM),PLATFORM_ANDROID) + ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) $(CC) -shared -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).so $(OBJS) $(LDFLAGS) $(LDLIBS) @echo "raylib shared library generated (lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).so)!" # WARNING: symbolic links creation on Windows should be done using mklink command, no ln available @@ -851,7 +857,7 @@ clean: clean_shell_$(PLATFORM_SHELL) clean_shell_sh: rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h -ifeq ($(PLATFORM),PLATFORM_ANDROID) +ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o endif diff --git a/src/build.zig b/src/build.zig index 0b85e5f87..3b462de61 100644 --- a/src/build.zig +++ b/src/build.zig @@ -207,15 +207,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory"); defer b.allocator.free(cache_include); - if (comptime builtin.zig_version.minor > 12) { - var dir = std.fs.cwd().openDir(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); - dir.close(); - raylib.addIncludePath(b.path(cache_include)); - } else { - var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); - dir.close(); - raylib.addIncludePath(.{ .path = cache_include }); - } + var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); + dir.close(); + raylib.addIncludePath(.{ .cwd_relative = cache_include }); }, else => { @panic("Unsupported OS"); diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 86e68a17f..646ecc9a0 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -37,7 +37,6 @@ This version doesn't work for desktops (I'm pretty sure) #define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2) #define RGFW_OPENGL_ES3 - (optional) use OpenGL ES (version 3) - #define RGFW_VULKAN - (optional) use vulkan for the rendering backend (rather than opengl) #define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix) #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX) @@ -59,7 +58,7 @@ /* Credits : - EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support + 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 @@ -72,6 +71,13 @@ Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2006-2019 Camilla Löwy + + 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 + AICDG (@THISISAGOODNAME) -> vulkan support (example) */ #ifndef RGFW_MALLOC @@ -90,6 +96,12 @@ #endif #endif +/* for windows 95 testing (not that it works well) */ +#ifdef RGFW_WIN95 +#define RGFW_NO_MONITOR +#define RGFW_NO_PASSTHROUGH +#endif + #ifndef RGFWDEF #ifdef __APPLE__ #define RGFWDEF static inline @@ -98,8 +110,12 @@ #endif #endif +#ifndef RGFW_ENUM +#define RGFW_ENUM(type, name) type name; enum +#endif + #ifndef RGFW_UNUSED -#define RGFW_UNUSED(x) if (x){} +#define RGFW_UNUSED(x) (void)(x); #endif #ifdef __cplusplus @@ -135,6 +151,10 @@ extern "C" { #endif #endif +#if !defined(b8) + typedef u8 b8; +#endif + #if defined(RGFW_X11) && defined(__APPLE__) #define RGFW_MACOS_X11 #undef __APPLE__ @@ -161,16 +181,18 @@ extern "C" { #undef _X86_ #else #undef _AMD64_ +#ifndef _X86_ #define _X86_ #endif +#endif -#include - +#ifndef RGFW_NO_XINPUT #ifdef __MINGW32__ #include #else #include #endif +#endif #else #if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11) @@ -192,28 +214,10 @@ extern "C" { #undef RGFW_EGL #endif -#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined (RGFW_VULKAN) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API) +#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API) #define RGFW_OPENGL #endif -#ifdef RGFW_VULKAN -#ifndef RGFW_MAX_FRAMES_IN_FLIGHT -#define RGFW_MAX_FRAMES_IN_FLIGHT 2 -#endif - -#ifdef RGFW_X11 -#define VK_USE_PLATFORM_XLIB_KHR -#endif -#ifdef RGFW_WINDOWS -#define VK_USE_PLATFORM_WIN32_KHR -#endif -#ifdef RGFW_MACOS -#define VK_USE_PLATFORM_MACOS_MVK -#endif - -#include -#endif - #if defined(RGFW_X11) && (defined(RGFW_OPENGL)) #ifndef GLX_MESA_swap_control #define GLX_MESA_swap_control @@ -244,8 +248,12 @@ extern "C" { #endif #endif - /*! Optional arguments for making a windows */ -#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent */ +#ifndef RGFW_ALPHA +#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */ +#endif + +/*! 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*/ @@ -255,6 +263,7 @@ extern "C" { #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 */ #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)*/ @@ -298,6 +307,11 @@ extern "C" { #define RGFW_focusIn 12 /*!< window is in focus now */ #define RGFW_focusOut 13 /*!< window is out of focus now */ +#define RGFW_mouseEnter 14 /* mouse entered the window */ +#define RGFW_mouseLeave 15 /* mouse left the window */ + +#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */ + /* attribs change event note The event data is sent straight to the window structure with win->r.x, win->r.y, win->r.w and win->r.h @@ -334,23 +348,25 @@ extern "C" { #define RGFW_NUMLOCK (1L << 2) /*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */ -#ifndef RGFW_JS_A +#ifndef RGFW_joystick_codes -#define RGFW_JS_A 0 /* or PS X button */ -#define RGFW_JS_B 1 /* or PS circle button */ -#define RGFW_JS_Y 2 /* or PS triangle button */ -#define RGFW_JS_X 3 /* or PS square button */ -#define RGFW_JS_START 9 /* start button */ -#define RGFW_JS_SELECT 8 /* select button */ -#define RGFW_JS_HOME 10 /* home button */ -#define RGFW_JS_UP 13 /* dpad up */ -#define RGFW_JS_DOWN 14 /* dpad down*/ -#define RGFW_JS_LEFT 15 /* dpad left */ -#define RGFW_JS_RIGHT 16 /* dpad right */ -#define RGFW_JS_L1 4 /* left bump */ -#define RGFW_JS_L2 5 /* left trigger*/ -#define RGFW_JS_R1 6 /* right bumper */ -#define RGFW_JS_R2 7 /* right trigger */ +typedef RGFW_ENUM(u8, RGFW_joystick_codes) { + RGFW_JS_A = 0, /* or PS X button */ + RGFW_JS_B = 1, /* or PS circle button */ + RGFW_JS_Y = 2, /* or PS triangle button */ + RGFW_JS_X = 3, /* or PS square button */ + RGFW_JS_START = 9, /* start button */ + RGFW_JS_SELECT = 8, /* select button */ + RGFW_JS_HOME = 10, /* home button */ + RGFW_JS_UP = 13, /* dpad up */ + RGFW_JS_DOWN = 14, /* dpad down*/ + RGFW_JS_LEFT = 15, /* dpad left */ + RGFW_JS_RIGHT = 16, /* dpad right */ + RGFW_JS_L1 = 4, /* left bump */ + RGFW_JS_L2 = 5, /* left trigger*/ + RGFW_JS_R1 = 6, /* right bumper */ + RGFW_JS_R2 = 7, /* right trigger */ +}; #endif @@ -373,6 +389,7 @@ typedef struct { i32 x, y; } RGFW_vector; #define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h} #define RGFW_AREA(w, h) (RGFW_area){w, h} + #ifndef RGFW_NO_MONITOR typedef struct RGFW_monitor { char name[128]; /* monitor name */ RGFW_rect rect; /* monitor Workarea */ @@ -388,14 +405,11 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF RGFW_monitor* RGFW_getMonitors(void); /* get the primary monitor */ 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) */ typedef struct RGFW_Event { -#ifdef RGFW_WINDOWS char keyName[16]; /* key name of event*/ -#else - char* keyName; /*!< key name of event */ -#endif /*! drag and drop data */ /* 260 max paths with a max length of 260 */ @@ -408,12 +422,13 @@ typedef struct { i32 x, y; } RGFW_vector; u32 type; /*!< which event has been sent?*/ RGFW_vector point; /*!< mouse x, y of event (or drop point) */ - u32 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - + u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/ u64 frameTime, frameTime2; /* this is used for counting the fps */ + + u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - u8 inFocus; /*if the window is in focus or not*/ + 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; @@ -441,7 +456,7 @@ typedef struct { i32 x, y; } RGFW_vector; u32 display; void* displayLink; void* window; - u8 dndPassed; + b8 dndPassed; #endif #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) @@ -455,15 +470,6 @@ typedef struct { i32 x, y; } RGFW_vector; GLXContext rSurf; /*!< source graphics context */ #endif #else -#ifdef RGFW_VULKAN - VkSurfaceKHR rSurf; /*!< source graphics context */ - - /* vulkan data */ - VkSwapchainKHR swapchain; - u32 image_count; - VkImage* swapchain_images; - VkImageView* swapchain_image_views; -#endif #ifdef RGFW_OSMESA OSMesaContext rSurf; @@ -495,6 +501,7 @@ typedef struct { i32 x, y; } RGFW_vector; #endif #ifdef RGFW_X11 XImage* bitmap; + GC gc; #endif #ifdef RGFW_MACOS void* bitmap; /* API's bitmap for storing or managing */ @@ -513,7 +520,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_area scale; /* window scaling */ #ifdef RGFW_MACOS - u8 cursorChanged; /* for steve jobs */ + b8 cursorChanged; /* for steve jobs */ #endif u32 winArgs; /* windows args (for RGFW to check) */ @@ -545,6 +552,9 @@ typedef struct { i32 x, y; } RGFW_vector; typedef void* RGFW_thread; /* thread type for window */ #endif + /* 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) */ + RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ RGFW_rect rect, /* rect of window */ @@ -561,9 +571,19 @@ typedef struct { i32 x, y; } RGFW_vector; ex. 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, + although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` */ - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check events (returns a pointer to win->event or NULL if there is no event)*/ + RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ + + /* + 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); + /*! window managment functions*/ RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ @@ -572,9 +592,10 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_vector v/* new pos*/ ); + #ifndef RGFW_NO_MONITOR /* move to a specific monitor */ RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m); - + #endif RGFWDEF void RGFW_window_resize(RGFW_window* win, RGFW_area a/* new size*/ ); @@ -588,6 +609,14 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/ RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/ + RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); /* if the window should have a border or not (borderless) based on bool value of `border` */ + + RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); /* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ + + #ifndef RGFW_NO_PASSTHROUGH + RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); /* turn on / off mouse passthrough */ + #endif + RGFWDEF void RGFW_window_setName(RGFW_window* win, char* name ); @@ -638,16 +667,18 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v); /* if the window should close (RGFW_close was sent or escape was pressed) */ - RGFWDEF u8 RGFW_window_shouldClose(RGFW_window* win); + RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win); /* if window is fullscreen'd */ - RGFWDEF u8 RGFW_window_isFullscreen(RGFW_window* win); + RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win); /* if window is hidden */ - RGFWDEF u8 RGFW_window_isHidden(RGFW_window* win); + RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win); /* if window is minimized */ - RGFWDEF u8 RGFW_window_isMinimized(RGFW_window* win); + RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); /* if window is maximized */ - RGFWDEF u8 RGFW_window_isMaximized(RGFW_window* win); + RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); + + #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 @@ -655,53 +686,91 @@ typedef struct { i32 x, y; } RGFW_vector; 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 /*!< make the window the current opengl drawing context */ RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); /*error handling*/ - RGFWDEF u8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ + 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 u8 RGFW_isPressedI(RGFW_window* win, u32 key); /*!< if key is pressed (key code)*/ + RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ - RGFWDEF u8 RGFW_wasPressedI(RGFW_window* win, u32 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ + RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ - RGFWDEF u8 RGFW_isHeldI(RGFW_window* win, u32 key); /*!< if key is held (key code)*/ - RGFWDEF u8 RGFW_isReleasedI(RGFW_window* win, u32 key); /*!< if key is released (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 u8 RGFW_isMousePressed(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_isMouseHeld(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_isMouseReleased(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_wasMousePressed(RGFW_window* win, u8 button); + RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key); - /* - !!Keycodes defined at the bottom of RGFW_HEADER part of this file!! - */ - /*!< converts a key code to it's key string */ - RGFWDEF char* RGFW_keyCodeTokeyStr(u64 key); - /*!< converts a string of a key to it's key code */ - RGFWDEF u32 RGFW_keyStrToKeyCode(char* key); - /*!< if key is pressed (key string) */ -#define RGFW_isPressedS(win, key) RGFW_isPressedI(win, RGFW_keyStrToKeyCode(key)) + RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button); + RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button); + RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button); + RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button); /*! clipboard functions*/ RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ -#define RGFW_clipboardFree free /* the string returned from RGFW_readClipboard must be freed */ + RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */ RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ - /* - convert a keyString to a char version - */ - RGFWDEF char RGFW_keystrToChar(const char*); - /* - ex. - "parenleft" -> '(' - "A" -> 'A', - "Return" -> "\n" + /* + + + Event callbacks, + these are completely optional, you can use the normal + RGFW_checkEvent() method if you prefer that + */ + /* RGFW_windowMoved, the window and its new rect value */ + typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r); + /* RGFW_windowResized, the window and its new rect value */ + typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r); + /* RGFW_quit, the window that was closed */ + typedef void (* RGFW_windowquitfunc)(RGFW_window* win); + /* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */ + typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); + /* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */ + typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_vector 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_vector point); + /* RGFW_dnd_init, the window, the point of the drop on the windows */ + typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_vector 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 keycode, 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 keycode, char keyName[16], u8 lockState, 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); + /* RGFW_jsButtonPressed / RGFW_jsButtonReleased, 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_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed); + /* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ + typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount); + + /* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */ + #ifdef RGFW_ALLOC_DROPFILES + typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount); + #else + typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount); + #endif + + RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func); + RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func); + RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func); + RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func); + RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func); + RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func); + RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func); + RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func); + RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func); + RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func); + RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); + RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); + RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); + + #ifndef RGFW_NO_THREADS /*! threading functions*/ @@ -715,7 +784,7 @@ typedef struct { i32 x, y; } RGFW_vector; #if defined(__unix__) || defined(__APPLE__) typedef void* (* RGFW_threadFunc_ptr)(void*); #else - typedef DWORD (* RGFW_threadFunc_ptr)(void*); + typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); #endif RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ @@ -746,63 +815,14 @@ typedef struct { i32 x, y; } RGFW_vector; /*! Set OpenGL version hint */ RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor); 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 */ #endif /* supports openGL, directX, OSMesa, EGL and software rendering */ RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */ RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval); RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set); - -#ifdef RGFW_VULKAN - typedef struct { - VkInstance instance; - VkPhysicalDevice physical_device; - VkDevice device; - - VkDebugUtilsMessengerEXT debugMessenger; - - VkQueue graphics_queue; - VkQueue present_queue; - - VkFramebuffer* framebuffers; - - VkRenderPass render_pass; - VkPipelineLayout pipeline_layout; - VkPipeline graphics_pipeline; - - VkCommandPool command_pool; - VkCommandBuffer* command_buffers; - - VkSemaphore* available_semaphores; - VkSemaphore* finished_semaphore; - VkFence* in_flight_fences; - VkFence* image_in_flight; - size_t current_frame; - } RGFW_vulkanInfo; - - /*! initializes a vulkan rendering context for the RGFW window, - this outputs the vulkan surface into wwin->src.rSurf - other vulkan data is stored in the global instance of the RGFW_vulkanInfo structure which is returned - by the initVulkan() function - RGFW_VULKAN must be defined for this function to be defined - - */ - RGFWDEF RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win); - RGFWDEF void RGFW_freeVulkan(void); - - RGFWDEF RGFW_vulkanInfo* RGFW_getVulkanInfo(void); - - RGFWDEF int RGFW_initData(RGFW_window* win); - RGFWDEF void RGFW_createSurface(VkInstance instance, RGFW_window* win); - int RGFW_deviceInitialization(RGFW_window* win); - int RGFW_createSwapchain(RGFW_window* win); - RGFWDEF int RGFW_createRenderPass(void); - int RGFW_createCommandPool(void); - int RGFW_createCommandBuffers(RGFW_window* win); - int RGFW_createSyncObjects(RGFW_window* win); - RGFWDEF int RGFW_createFramebuffers(RGFW_window* win); -#endif - + RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); #ifdef RGFW_DIRECTX typedef struct { IDXGIFactory* pFactory; @@ -824,7 +844,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */ RGFWDEF void RGFW_sleep(u64 microsecond); /* sleep for a set time */ - typedef enum { + typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_KEY_NULL = 0, RGFW_Escape, RGFW_F1, @@ -932,10 +952,12 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_KP_9, RGFW_KP_0, RGFW_KP_Period, - RGFW_KP_Return - } RGFW_Key; + RGFW_KP_Return, - typedef enum RGFW_mouseIcons { + final_key, + }; + + typedef RGFW_ENUM(u8, RGFW_mouseIcons) { RGFW_MOUSE_NORMAL = 0, RGFW_MOUSE_ARROW, RGFW_MOUSE_IBEAM, @@ -947,7 +969,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_MOUSE_RESIZE_NESW, RGFW_MOUSE_RESIZE_ALL, RGFW_MOUSE_NOT_ALLOWED, - } RGFW_mouseIcons; + }; #endif /* RGFW_HEADER */ @@ -970,7 +992,7 @@ typedef struct { i32 x, y; } RGFW_vector; for (;;) { RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag - if (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_Escape)) + if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) break; RGFW_window_swapBuffers(win); @@ -1024,11 +1046,14 @@ typedef struct { i32 x, y; } RGFW_vector; #include /* - +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) +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 */ u8 RGFW_keycodes[] = { @@ -1146,17 +1171,13 @@ This is the start of keycode data [RGFW_OS_BASED_VALUE(110, 0x24, 116)] = RGFW_Home, }; - #ifdef RGFW_X11 - u8 RGFW_mouseIconSrc[] = {68, 68, 152, 34, 60, 108, 116, 12, 14, 52, 0}; - #elif defined(RGFW_WINDOWS) - u32 RGFW_mouseIconSrc[] = {32512, 32512, 32513, 32515, 32649, 32644, 32645, 32642, 32643, 32646, 32648}; - #elif defined(RGFW_MACOS) - char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; - #endif - - u8 RGFW_keyboard[128] = { 0 }; - u8 RGFW_keyboard_prev[128]; + typedef struct { + b8 current : 1; + b8 prev : 1; + } RGFW_keyState; + RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; + RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { @@ -1166,415 +1187,81 @@ This is the start of keycode data return RGFW_keycodes[keycode]; } + RGFWDEF void RGFW_resetKey(void); + void RGFW_resetKey(void) { + size_t len = final_key; + + size_t i; + for (i = 0; i < len; i++) + RGFW_keyboard[i].prev = 0; + } + /* - -this is the end of keycode data - + this is the end of keycode data */ -#ifdef RGFW_WINDOWS -#include +/* + event callback defines start here +*/ -#endif -#ifdef RGFW_MACOS /* - based on silicon.h + 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); } + void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } + void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); } + void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);} + void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_vector point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);} + void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} + void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} + void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); } + void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); 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_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } + void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); } -#ifndef GL_SILENCE_DEPRECATION -#define GL_SILENCE_DEPRECATION -#endif + #ifdef RGFW_ALLOC_DROPFILES + void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} + #else + void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} + #endif -#include -#include -#include -#include + RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY; + RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY; + RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY; + RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY; + RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY; + RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY; + RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY; + 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_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY; + RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY; - 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 NSScreen; - 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; - -#ifdef __arm64__ - /* ARM just uses objc_msgSend */ -#define abi_objc_msgSend_stret objc_msgSend -#define abi_objc_msgSend_fpret objc_msgSend -#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_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) -#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) - -#define si_declare_single(class, name, func) \ - void class##_##name(class* obj) { \ - return objc_msgSend_void(obj, sel_registerName(func)); \ - } - - -#define loadFunc(funcName) \ - static void* func = NULL;\ - if (func == NULL) \ - func = sel_registerName(funcName); - - void NSRelease(id obj) { - loadFunc("release"); - objc_msgSend_void(obj, func); - } - -#define release NSRelease - - si_declare_single(NSApplication, finishLaunching, "finishLaunching") - si_declare_single(NSOpenGLContext, flushBuffer, "flushBuffer") - - NSString* NSString_stringWithUTF8String(const char* str) { - loadFunc("stringWithUTF8String:"); - - return ((id(*)(id, SEL, const char*))objc_msgSend) - ((id)objc_getClass("NSString"), func, str); - } - - 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. */ -#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) - - NSRect NSMakeRect(double x, double y, double width, double height) { - NSRect r; - r.origin.x = x; - r.origin.y = y; - r.size.width = width; - r.size.height = height; - - return r; - } - - NSPoint NSMakePoint(double x, double y) { - NSPoint point; - point.x = x; - point.y = y; - return point; - } - - NSSize NSMakeSize(double w, double h) { - NSSize size; - size.width = w; - size.height = h; - return size; - } - - void* si_array_init(void* allocator, size_t sizeof_element, size_t count) { - void* array = si_array_init_reserve(sizeof_element, count); - memcpy(array, allocator, sizeof_element * count); - - return array; - } + void RGFW_window_checkEvents(RGFW_window* win) { while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { if (win->event.type == RGFW_quit) return; }} - unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) { - return ((unsigned char* (*)(id, SEL))objc_msgSend) - (imageRep, sel_registerName("bitmapData")); - } - -#define NS_ENUM(type, name) type name; enum - - 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 - - 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:"); - - 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); - } - - 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); - } - - NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { - void* func = sel_registerName("initWithImage:hotSpot:"); - void* nsclass = objc_getClass("NSCursor"); - - return (NSCursor*) ((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); - } - - NSImage* NSImage_initWithSize(NSSize size) { - void* 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 */ - NSOpenGLContextParameterSurfaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ - NSOpenGLContextParameterSurfaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ - NSOpenGLContextParameterSurfaceBackingSize 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 */ - NSOpenGLContextParameterSurfaceSurfaceVolatile 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* 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); - } - - 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); - } - - void NSCursor_performSelector(NSCursor* cursor, void* selector) { - void* 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")); - } - - 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]); - - 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))); - } - - 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); - - NSArray* array = c_array_to_NSArray(ntypes, len); - objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); - NSRelease(array); - } - - NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); - - void* func = sel_registerName("declareTypes:owner:"); - - NSArray* array = c_array_to_NSArray(ntypes, len); - - NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, owner); - NSRelease(array); - - return output; - } - - 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)); - } - - void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } - - typedef enum NSApplicationActivationPolicy { - NSApplicationActivationPolicyRegular, - NSApplicationActivationPolicyAccessory, - NSApplicationActivationPolicyProhibited - } NSApplicationActivationPolicy; - - typedef NS_ENUM(u32, NSBackingStoreType) { - NSBackingStoreRetained = 0, - NSBackingStoreNonretained = 1, - NSBackingStoreBuffered = 2 - }; - - 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 const char* NSPasteboardType; - NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType - - - - typedef NS_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 - }; - - - NSUInteger NSArray_count(NSArray* array) { - void* func = sel_registerName("count"); - return ((NSUInteger(*)(id, SEL))objc_msgSend)(array, func); - } - - void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { - void* 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:"); - - NSArray* array = c_array_to_NSArray(classArray, len); - - NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, options); - - NSRelease(array); - NSUInteger count = NSArray_count(output); - - 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); - } -#endif - + void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; } + void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; } + void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; } + void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; } + void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; } + void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; } + void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; } + void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; } + void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; } + void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; } + void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; } + void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; } + void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; } +/* + no more event call back defines +*/ #define RGFW_ASSERT(check, str) {\ if (!(check)) { \ @@ -1583,44 +1270,26 @@ this is the end of keycode data } \ } - u8 RGFW_error = 0; - u8 RGFW_Error() { return RGFW_error; } + b8 RGFW_error = 0; + b8 RGFW_Error() { return RGFW_error; } #define SET_ATTRIB(a, v) { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ attribs[index++] = v; \ } - -#define ADD_ATTRIB(a) { \ - assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ - attribs[index++] = a; \ -} - -#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); + + RGFW_area RGFW_bufferSize = {0, 0}; + void RGFW_setBufferSize(RGFW_area size) { + RGFW_bufferSize = size; } -#endif - #ifdef RGFW_WINDOWS - __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); - #endif RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); - RGFWDEF void RGFW_init_buffer(RGFW_window* win); 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 */ - #ifdef RGFW_WINDOWS - timeBeginPeriod(1); - #endif - #ifdef RGFW_ALLOC_DROPFILES win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); u32 i; @@ -1628,13 +1297,6 @@ this is the end of keycode data win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); #endif -#ifdef RGFW_X11 - /* open X11 display */ - /* this is done here so the screen size can be accessed */ - win->src.display = XOpenDisplay(NULL); - assert(win->src.display != NULL); -#endif - #ifndef RGFW_X11 RGFW_area screenR = RGFW_getScreenSize(); #else @@ -1657,662 +1319,236 @@ this is the end of keycode data win->event.inFocus = 1; win->event.droppedFilesCount = 0; win->src.joystickCount = 0; -#ifdef RGFW_MACOS - RGFW_window_setMouseDefault(win); -#endif -#ifdef RGFW_WINDOWS - win->src.maxSize = RGFW_AREA(0, 0); - win->src.minSize = RGFW_AREA(0, 0); -#endif win->src.winArgs = 0; + win->event.lockState = 0; return win; } + #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) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); } + #endif - void RGFW_init_buffer(RGFW_window* win) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - RGFW_area area = RGFW_getScreenSize(); -#if !(defined(RGFW_WINDOWS)) || defined(RGFW_OSMESA) - win->buffer = RGFW_MALLOC(area.w * area.h * 4); +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 */ + + void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } + + b8 RGFW_mouseButtons[5] = { 0 }; + b8 RGFW_mouseButtons_prev[5]; + + b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { + assert(win != NULL); + return RGFW_mouseButtons[button] && (win != NULL) && win->event.inFocus; + } + b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { + assert(win != NULL); + return RGFW_mouseButtons_prev[button] && (win != NULL) && win->event.inFocus; + } + b8 RGFW_isMouseHeld(RGFW_window* win, u8 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_isPressed(RGFW_window* win, u8 key) { + assert(win != NULL); + return RGFW_keyboard[key].current && win->event.inFocus; + } + + b8 RGFW_wasPressed(RGFW_window* win, u8 key) { + assert(win != NULL); + return RGFW_keyboard[key].prev && win->event.inFocus; + } + + b8 RGFW_isHeld(RGFW_window* win, u8 key) { + return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); + } + + b8 RGFW_isClicked(RGFW_window* win, u8 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)); + } + + void RGFW_window_makeCurrent(RGFW_window* win) { + assert(win != NULL); + +#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); #endif -#ifdef RGFW_OSMESA - win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); -#endif -#ifdef RGFW_X11 - win->src.bitmap = XCreateImage( - win->src.display, DefaultVisual(win->src.display, XDefaultScreen(win->src.display)), - DefaultDepth(win->src.display, XDefaultScreen(win->src.display)), - ZPixmap, 0, NULL, area.w, area.h, - 32, 0 - ); -#endif -#ifdef RGFW_WINDOWS - BITMAPV5HEADER bi = { 0 }; - ZeroMemory(&bi, sizeof(bi)); - bi.bV5Size = sizeof(bi); - bi.bV5Width = area.w; - bi.bV5Height = -((LONG) area.h); - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5BlueMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5RedMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; - - win->src.bitmap = CreateDIBSection(win->src.hdc, - (BITMAPINFO*) &bi, - DIB_RGB_COLORS, - (void**) &win->buffer, - NULL, - (DWORD) 0); - - win->src.hdcMem = CreateCompatibleDC(win->src.hdc); -#endif -#else -RGFW_UNUSED(win); /* if buffer rendering is not being used */ +#ifdef RGFW_OPENGL + RGFW_window_makeCurrent_OpenGL(win); #endif } + void RGFW_window_setGPURender(RGFW_window* win, i8 set) { + if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER)) + win->src.winArgs |= RGFW_NO_GPU_RENDER; + + else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER) + win->src.winArgs ^= RGFW_NO_GPU_RENDER; + } + + void RGFW_window_setCPURender(RGFW_window* win, i8 set) { + if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER)) + win->src.winArgs |= RGFW_NO_CPU_RENDER; + + else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER) + win->src.winArgs ^= RGFW_NO_CPU_RENDER; + } + + void RGFW_window_maximize(RGFW_window* win) { + assert(win != NULL); + + RGFW_area screen = RGFW_getScreenSize(); + + RGFW_window_move(win, RGFW_VECTOR(0, 0)); + RGFW_window_resize(win, screen); + } + + b8 RGFW_window_shouldClose(RGFW_window* win) { + 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_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y)); + } + #endif + + RGFWDEF void RGFW_clipCursor(RGFW_rect); + + #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) + void RGFW_clipCursor(RGFW_rect r) { RGFW_UNUSED(r) } + #endif + + void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { + if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) { + RGFW_clipCursor(win->r); + win->src.winArgs |= RGFW_HOLD_MOUSE; + } + + if (!area.w && !area.h) + area = RGFW_AREA(win->r.w / 2, win->r.h / 2); + + #ifndef RGFW_MACOS + RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); + #endif + } + + void RGFW_window_mouseUnhold(RGFW_window* win) { + if ((win->src.winArgs & RGFW_HOLD_MOUSE)) { + win->src.winArgs ^= RGFW_HOLD_MOUSE; + + RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0)); + } + } + + void RGFW_window_checkFPS(RGFW_window* win) { + u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; + + u64 fps = round(1e+9 / deltaTime); + win->event.fps = fps; + + if (win->fpsCap && fps > win->fpsCap) { + u64 frameTimeNS = 1e+9 / win->fpsCap; + u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6; + + if (sleepTimeMS > 0) { + RGFW_sleep(sleepTimeMS); + win->event.frameTime = 0; + } + } + + win->event.frameTime = RGFW_getTimeNS(); + + if (win->fpsCap == 0) + return; + + deltaTime = RGFW_getTimeNS() - win->event.frameTime2; + win->event.fps = round(1e+9 / deltaTime); + win->event.frameTime2 = RGFW_getTimeNS(); + } + + u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; } + + #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); + } + #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; + } + + #if defined(RGFW_X11) || defined(RGFW_MACOS) + 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); + + void RGFW_window_setDND(RGFW_window* win, b8 allow) { + if (allow && !(win->src.winArgs & RGFW_ALLOW_DND)) + win->src.winArgs |= RGFW_ALLOW_DND; + + else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND)) + win->src.winArgs ^= RGFW_ALLOW_DND; + } + #endif + +/* + graphics API spcific code (end of generic code) + starts here +*/ + + +/* + OpenGL defines start here (Normal, EGL, OSMesa) +*/ + #if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) #ifndef __APPLE__ #include #else +#ifndef GL_SILENCE_DEPRECATION +#define GL_SILENCE_DEPRECATION +#endif #include -#endif +#include #endif -#ifdef RGFW_VULKAN - RGFW_vulkanInfo RGFW_vulkan_info; - - RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win) { - assert(win != NULL); - - if ( - RGFW_initData(win) || - RGFW_deviceInitialization(win) || - RGFW_createSwapchain(win) - ) - return NULL; - - u32 graphics_family_index = 0; - u32 present_family_index = 0; - - vkGetDeviceQueue(RGFW_vulkan_info.device, graphics_family_index, 0, &RGFW_vulkan_info.graphics_queue); - vkGetDeviceQueue(RGFW_vulkan_info.device, present_family_index, 0, &RGFW_vulkan_info.present_queue); - - if ( - RGFW_createRenderPass() || - RGFW_createFramebuffers(win) || - RGFW_createCommandPool() || - RGFW_createCommandBuffers(win) || - RGFW_createSyncObjects(win) - ) - return NULL; - - return &RGFW_vulkan_info; - } - - int RGFW_initData(RGFW_window* win) { - assert(win != NULL); - - win->src.swapchain = VK_NULL_HANDLE; - win->src.image_count = 0; - RGFW_vulkan_info.current_frame = 0; - - return 0; - } - - void RGFW_createSurface(VkInstance instance, RGFW_window* win) { - assert(win != NULL); - assert(instance); - - win->src.rSurf = VK_NULL_HANDLE; - -#ifdef RGFW_X11 - VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) win->src.display, (Window) win->src.window }; - - vkCreateXlibSurfaceKHR(RGFW_vulkan_info.instance, &x11, NULL, &win->src.rSurf); -#endif -#ifdef RGFW_WINDOWS - VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), win->src.window }; - - vkCreateWin32SurfaceKHR(RGFW_vulkan_info.instance, &win32, NULL, &win->src.rSurf); -#endif -#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) - VkMacOSSurfaceCreateFlagsMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, win->src.display, win->src.window }; - - vkCreateMacOSSurfaceMVK(RGFW_vulkan_info.instance, &macos, NULL, &win->src.rSurf); -#endif - } - - RGFW_vulkanInfo* RGFW_getVulkanInfo(void) { - return &RGFW_vulkan_info; - } - - int RGFW_deviceInitialization(RGFW_window* win) { - assert(win != NULL); - - VkApplicationInfo appInfo = { 0 }; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "RGFW app"; - appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0); - - char* extension = -#ifdef RGFW_WINDOWS - "VK_KHR_win32_surface"; -#elif defined(RGFW_X11) - VK_KHR_XLIB_SURFACE_EXTENSION_NAME; -#elif defined(RGFW_MACOS) - "VK_MVK_macos_surface"; -#else - NULL; -#endif - - VkInstanceCreateInfo instance_create_info = { 0 }; - instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instance_create_info.pApplicationInfo = &appInfo; - instance_create_info.enabledExtensionCount = extension ? 2 : 0, - instance_create_info.ppEnabledExtensionNames = (const char* [2]){ - VK_KHR_SURFACE_EXTENSION_NAME, - extension - }; - - if (vkCreateInstance(&instance_create_info, NULL, &RGFW_vulkan_info.instance) != VK_SUCCESS) { - fprintf(stderr, "failed to create instance!\n"); - return -1; - } - - - RGFW_createSurface(RGFW_vulkan_info.instance, win); - - u32 deviceCount = 0; - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, NULL); - VkPhysicalDevice* devices = (VkPhysicalDevice*) RGFW_MALLOC(sizeof(VkPhysicalDevice) * deviceCount); - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, devices); - - RGFW_vulkan_info.physical_device = devices[0]; - - u32 queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, NULL); - VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*) RGFW_MALLOC(sizeof(VkQueueFamilyProperties) * queue_family_count); - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, queueFamilies); - - float queuePriority = 1.0f; - - VkPhysicalDeviceFeatures device_features = { 0 }; - - VkDeviceCreateInfo device_create_info = { 0 }; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - VkDeviceQueueCreateInfo queue_create_infos[2] = { - {0}, - {0}, - }; - queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[0].queueCount = 1; - queue_create_infos[0].pQueuePriorities = &queuePriority; - queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[1].queueCount = 1; - queue_create_infos[1].pQueuePriorities = &queuePriority; - device_create_info.queueCreateInfoCount = 2; - device_create_info.pQueueCreateInfos = queue_create_infos; - - device_create_info.enabledExtensionCount = 1; - - const char* device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - device_create_info.ppEnabledExtensionNames = device_extensions; - device_create_info.pEnabledFeatures = &device_features; - - if (vkCreateDevice(RGFW_vulkan_info.physical_device, &device_create_info, NULL, &RGFW_vulkan_info.device) != VK_SUCCESS) { - fprintf(stderr, "failed to create logical device!\n"); - return -1; - } - - return 0; - } - - int RGFW_createSwapchain(RGFW_window* win) { - assert(win != NULL); - - VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; - VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; - - VkSurfaceCapabilitiesKHR capabilities = { 0 }; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(RGFW_vulkan_info.physical_device, win->src.rSurf, &capabilities); - - win->src.image_count = capabilities.minImageCount + 1; - if (capabilities.maxImageCount > 0 && win->src.image_count > capabilities.maxImageCount) { - win->src.image_count = capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR swapchain_create_info = { 0 }; - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_create_info.surface = win->src.rSurf; - swapchain_create_info.minImageCount = win->src.image_count; - swapchain_create_info.imageFormat = surfaceFormat.format; - swapchain_create_info.imageColorSpace = surfaceFormat.colorSpace; - swapchain_create_info.imageExtent = (VkExtent2D){ win->r.w, win->r.h }; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 2; - swapchain_create_info.preTransform = capabilities.currentTransform; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = presentMode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(RGFW_vulkan_info.device, &swapchain_create_info, NULL, &win->src.swapchain) != VK_SUCCESS) { - fprintf(stderr, "failed to create swap chain!\n"); - return -1; - } - - u32 imageCount; - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, NULL); - win->src.swapchain_images = (VkImage*) RGFW_MALLOC(sizeof(VkImage) * imageCount); - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, win->src.swapchain_images); - - win->src.swapchain_image_views = (VkImageView*) RGFW_MALLOC(sizeof(VkImageView) * imageCount); - for (u32 i = 0; i < imageCount; i++) { - VkImageViewCreateInfo image_view_cre_infos = { 0 }; - image_view_cre_infos.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_cre_infos.image = win->src.swapchain_images[i]; - image_view_cre_infos.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_cre_infos.format = VK_FORMAT_B8G8R8A8_SRGB; - image_view_cre_infos.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_view_cre_infos.subresourceRange.baseMipLevel = 0; - image_view_cre_infos.subresourceRange.levelCount = 1; - image_view_cre_infos.subresourceRange.baseArrayLayer = 0; - image_view_cre_infos.subresourceRange.layerCount = 1; - if (vkCreateImageView(RGFW_vulkan_info.device, &image_view_cre_infos, NULL, &win->src.swapchain_image_views[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create image views!"); - return -1; - } - } - - return 0; - } - - int RGFW_createRenderPass(void) { - VkAttachmentDescription color_attachment = { 0 }; - color_attachment.format = VK_FORMAT_B8G8R8A8_SRGB; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference color_attachment_ref = { 0 }; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = { 0 }; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - - VkSubpassDependency dependency = { 0 }; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo render_pass_info = { 0 }; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; - - if (vkCreateRenderPass(RGFW_vulkan_info.device, &render_pass_info, NULL, &RGFW_vulkan_info.render_pass) != VK_SUCCESS) { - fprintf(stderr, "failed to create render pass\n"); - return -1; // failed to create render pass! - } - return 0; - } - - int RGFW_createCommandPool(void) { - VkCommandPoolCreateInfo pool_info = { 0 }; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.queueFamilyIndex = 0; - - if (vkCreateCommandPool(RGFW_vulkan_info.device, &pool_info, NULL, &RGFW_vulkan_info.command_pool) != VK_SUCCESS) { - fprintf(stderr, "failed to create command pool\n"); - return -1; // failed to create command pool - } - return 0; - } - - int RGFW_createCommandBuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.command_buffers = (VkCommandBuffer*) RGFW_MALLOC(sizeof(VkCommandBuffer) * win->src.image_count); - - VkCommandBufferAllocateInfo allocInfo = { 0 }; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = RGFW_vulkan_info.command_pool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = (u32) win->src.image_count; - - if (vkAllocateCommandBuffers(RGFW_vulkan_info.device, &allocInfo, RGFW_vulkan_info.command_buffers) != VK_SUCCESS) { - return -1; // failed to allocate command buffers; - } - - return 0; - } - - int RGFW_createSyncObjects(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.available_semaphores = (VkSemaphore*) RGFW_MALLOC(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.finished_semaphore = (VkSemaphore*) RGFW_MALLOC(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.in_flight_fences = (VkFence*) RGFW_MALLOC(sizeof(VkFence) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.image_in_flight = (VkFence*) RGFW_MALLOC(sizeof(VkFence) * win->src.image_count); - - VkSemaphoreCreateInfo semaphore_info = { 0 }; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fence_info = { 0 }; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.available_semaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.finished_semaphore[i]) != VK_SUCCESS || - vkCreateFence(RGFW_vulkan_info.device, &fence_info, NULL, &RGFW_vulkan_info.in_flight_fences[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create sync objects\n"); - return -1; // failed to create synchronization objects for a frame - } - } - - for (size_t i = 0; i < win->src.image_count; i++) { - RGFW_vulkan_info.image_in_flight[i] = VK_NULL_HANDLE; - } - - return 0; - } - - int RGFW_createFramebuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.framebuffers = (VkFramebuffer*) RGFW_MALLOC(sizeof(VkFramebuffer) * win->src.image_count); - - for (size_t i = 0; i < win->src.image_count; i++) { - VkImageView attachments[] = { win->src.swapchain_image_views[i] }; - - VkFramebufferCreateInfo framebuffer_info = { 0 }; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = RGFW_vulkan_info.render_pass; - framebuffer_info.attachmentCount = 1; - framebuffer_info.pAttachments = attachments; - framebuffer_info.width = win->r.w; - framebuffer_info.height = win->r.h; - framebuffer_info.layers = 1; - - if (vkCreateFramebuffer(RGFW_vulkan_info.device, &framebuffer_info, NULL, &RGFW_vulkan_info.framebuffers[i]) != VK_SUCCESS) { - return -1; // failed to create framebuffer - } - } - return 0; - } - - void RGFW_freeVulkan(void) { - vkDeviceWaitIdle(RGFW_vulkan_info.device); - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.finished_semaphore[i], NULL); - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.available_semaphores[i], NULL); - vkDestroyFence(RGFW_vulkan_info.device, RGFW_vulkan_info.in_flight_fences[i], NULL); - } - - vkDestroyCommandPool(RGFW_vulkan_info.device, RGFW_vulkan_info.command_pool, NULL); - - vkDestroyPipeline(RGFW_vulkan_info.device, RGFW_vulkan_info.graphics_pipeline, NULL); - vkDestroyPipelineLayout(RGFW_vulkan_info.device, RGFW_vulkan_info.pipeline_layout, NULL); - vkDestroyRenderPass(RGFW_vulkan_info.device, RGFW_vulkan_info.render_pass, NULL); - -#ifdef RGFW_DEBUG - PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(RGFW_vulkan_info.instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != NULL) { - func(RGFW_vulkan_info.instance, RGFW_vulkan_info.debugMessenger, NULL); - } -#endif - - vkDestroyDevice(RGFW_vulkan_info.device, NULL); - vkDestroyInstance(RGFW_vulkan_info.instance, NULL); - - RGFW_FREE(RGFW_vulkan_info.framebuffers); - RGFW_FREE(RGFW_vulkan_info.command_buffers); - RGFW_FREE(RGFW_vulkan_info.available_semaphores); - RGFW_FREE(RGFW_vulkan_info.finished_semaphore); - RGFW_FREE(RGFW_vulkan_info.in_flight_fences); - RGFW_FREE(RGFW_vulkan_info.image_in_flight); - } - -#endif /* RGFW_VULKAN */ - - RGFW_window* RGFW_root = NULL; - -#ifdef RGFW_X11 -#include -#ifndef RGFW_NO_X11_CURSOR -#include -#endif -#include - -#ifndef RGFW_NO_DPI -#include -#include -#endif -#endif - -#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ - -#ifdef RGFW_WINDOWS -#include -#include -#include -#include -#include -#include -#endif - - u8 RGFW_mouseButtons[5] = { 0 }; - u8 RGFW_mouseButtons_prev[5]; - - u8 RGFW_isMousePressed(RGFW_window* win, u8 button) { - if (win != NULL && !win->event.inFocus) - return 0; - - return RGFW_mouseButtons[button]; - } - u8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { - if (win != NULL && !win->event.inFocus) - return 0; - - return RGFW_mouseButtons_prev[button]; - } - u8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { - return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } - u8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { - return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } - - u8 RGFW_isPressedI(RGFW_window* win, u32 key) { - RGFW_UNUSED(win); - - return RGFW_keyboard[key]; - } - - u8 RGFW_wasPressedI(RGFW_window* win, u32 key) { - RGFW_UNUSED(win); - - return RGFW_keyboard_prev[key]; - } - - u8 RGFW_isHeldI(RGFW_window* win, u32 key) { - return (RGFW_isPressedI(win, key) && RGFW_wasPressedI(win, key)); - } - - u8 RGFW_isReleasedI(RGFW_window* win, u32 key) { - return (!RGFW_isPressedI(win, key) && RGFW_wasPressedI(win, key)); - } - - char* RGFW_keyCodeTokeyStr(u64 key) { - static char* keyStrs[128] = {"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Backtick", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "=", "BackSpace", "Tab", "CapsLock", "ShiftL", "ControlL", "AltL", "SuperL", "ShiftR", "ControlR", "AltR", "SuperR", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", "-", "[", "]", ";", "Return", "'", "\\", "Up", "Down", "Left", "Right", "Delete", "Insert", "End", "Home", "PageUp", "PageDown", "Numlock", "KP_Slash", "Multiply", "KP_Minus", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "KP_8", "KP_9", "KP_0", "KP_Period", "KP_Return" }; - - return keyStrs[key]; - } - - u32 RGFW_keyStrToKeyCode(char* key) { - static char* keyStrs[128] = {"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Backtick", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "=", "BackSpace", "Tab", "CapsLock", "ShiftL", "ControlL", "AltL", "SuperL", "ShiftR", "ControlR", "AltR", "SuperR", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", "-", "[", "]", ";", "Return", "'", "\\", "Up", "Down", "Left", "Right", "Delete", "Insert", "End", "Home", "PageUp", "PageDown", "Numlock", "KP_Slash", "Multiply", "KP_Minus", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "KP_8", "KP_9", "KP_0", "KP_Period", "KP_Return" }; - - key--; - while (key++) { - u32 i; - for (i = 0; i < 128; i++) { - if (*keyStrs[i] == '\1') - continue; - - if (*keyStrs[i] != *key) { - keyStrs[i] = "\1"; - continue; - } - - if (*keyStrs[i] == '\0' && *key == '\0') - return RGFW_apiKeyCodeToRGFW(i); - - else - keyStrs[i]++; - } - - if (*key == '\0') - break; - } - - return 0; - } - - - char RGFW_keystrToChar(const char* str) { - if (str[1] == 0) - return str[0]; - - static const char* map[] = { - "asciitilde", "`", - "grave", "~", - "exclam", "!", - "at", "@", - "numbersign", "#", - "dollar", "$", - "percent", "%%", - "asciicircum", "^", - "ampersand", "&", - "asterisk", "*", - "parenleft", "(", - "parenright", ")", - "underscore", "_", - "minus", "-", - "plus", "+", - "equal", "=", - "braceleft", "{", - "bracketleft", "[", - "bracketright", "]", - "braceright", "}", - "colon", ":", - "semicolon", ";", - "quotedbl", "\"", - "apostrophe", "'", - "bar", "|", - "backslash", "\'", - "less", "<", - "comma", ",", - "greater", ">", - "period", ".", - "question", "?", - "slash", "/", - "space", " ", - "Return", "\n", - "Enter", "\n", - "enter", "\n", - }; - - u8 i = 0; - for (i = 0; i < (sizeof(map) / sizeof(char*)); i += 2) - if (strcmp(map[i], str) == 0) - return *map[i + 1]; - - return '\0'; - } - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef RGFW_WINDOWS - 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); - - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; } -#else - - typedef u64 (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); - PFN_XInputGetState XInputGetStateSRC = NULL; - #define XInputGetState XInputGetStateSRC - static HMODULE RGFW_XInput_dll = NULL; - - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { - RGFW_UNUSED(win) - - XINPUT_STATE state; - if (XInputGetState == NULL || XInputGetState(c, &state) == ERROR_DEVICE_NOT_CONNECTED) - return 0; - - if (button == RGFW_JS_A) return state.Gamepad.wButtons & XINPUT_GAMEPAD_A; - else if (button == RGFW_JS_B) return state.Gamepad.wButtons & XINPUT_GAMEPAD_B; - else if (button == RGFW_JS_Y) return state.Gamepad.wButtons & XINPUT_GAMEPAD_Y; - else if (button == RGFW_JS_X) return state.Gamepad.wButtons & XINPUT_GAMEPAD_X; - else if (button == RGFW_JS_START) return state.Gamepad.wButtons & XINPUT_GAMEPAD_START; - else if (button == RGFW_JS_SELECT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK; - else if (button == RGFW_JS_UP) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP; - else if (button == RGFW_JS_DOWN) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN; - else if (button == RGFW_JS_LEFT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT; - else if (button == RGFW_JS_RIGHT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT; - else if (button == RGFW_JS_L1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER; - else if (button == RGFW_JS_R1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER; - else if (button == RGFW_JS_L2 && state.Gamepad.bLeftTrigger) return 1; - else if (button == RGFW_JS_R2 && state.Gamepad.bRightTrigger) return 1; - - return 0; - } -#endif - -#if defined(RGFW_OPENGL) || defined(RGFW_EGL) +/* EGL, normal OpenGL only */ +#if !defined(RGFW_OSMESA) i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; #ifndef RGFW_EGL @@ -2346,6 +1582,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return version; } +/* OPENGL normal only (no EGL / OSMesa) */ #ifndef RGFW_EGL #define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73) @@ -2377,6 +1614,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_TYPE_RGBA_ARB 0x202B + +#define WGL_TRANSPARENT_ARB 0x200A #endif static u32* RGFW_initAttribs(u32 useSoftware) { @@ -2412,6 +1653,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #endif #ifdef RGFW_WINDOWS + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_TRANSPARENT_ARB, TRUE, WGL_COLOR_BITS_ARB, 32, #endif @@ -2459,7 +1702,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return attribs; } -#else +/* EGL only (no OSMesa nor normal OPENGL) */ +#elif defined(RGFW_EGL) #include @@ -2619,14 +1863,71 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ eglTerminate(win->src.EGL_display); } -#endif /* RGFW_EGL */ -#endif /* RGFW_GL stuff? */ + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + + eglSwapInterval(win->src.EGL_display, swapInterval); - /* - This is where OS specific stuff starts - */ + win->fpsCap = (swapInterval == 1) ? 0 : 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 )*/ + +/* +This is where OS specific stuff starts +*/ + + +/* + + +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 @@ -2634,6 +1935,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #include /* for converting keycode to string */ #include /* for hiding */ +#include +#include #include /* for data limits (mainly used in drag and drop functions) */ #include @@ -2642,6 +1945,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #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, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate; @@ -2674,6 +1978,55 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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 = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + + #ifdef RGFW_OSMESA + win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + + win->src.bitmap = XCreateImage( + win->src.display, vi->visual, + 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 + ); + } + 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) { @@ -2698,7 +2051,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_window* win = RGFW_window_basic_init(rect, args); - u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask; /* X11 events accepted*/ + u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/ #ifdef RGFW_OPENGL u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); @@ -2740,45 +2093,60 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XFree(fbc); - u32 valuemask = CWBorderPixel | CWColormap; + if (args & RGFW_TRANSPARENT_WINDOW) { + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + } #else - XVisualInfo* vi = (XVisualInfo*) RGFW_MALLOC(sizeof(XVisualInfo)); - vi->screen = DefaultScreen((Display*) win->src.display); - vi->visual = DefaultVisual((Display*) win->src.display, vi->screen); + XVisualInfo viNorm; - vi->depth = 0; - u32 valuemask = 0; + 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, - RootWindow(win->src.display, vi->screen), + 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, RootWindow((Display*) win->src.display, vi->screen), win->r.x, win->r.y, win->r.w, win->r.h, + 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, - valuemask | CWEventMask, &swa); - + CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0); - if (args & RGFW_TRANSPARENT_WINDOW) - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + #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 + XClassHint *hint = XAllocClassHint(); + assert(hint != NULL); + hint->res_class = "RGFW"; + 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 i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; 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; @@ -2800,14 +2168,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (RGFW_root == NULL) RGFW_root = win; - RGFW_init_buffer(win); - -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif + RGFW_init_buffer(win, vi); + } + + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ XSizeHints* sh = XAllocSizeHints(); @@ -2820,29 +2188,21 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } if (args & RGFW_NO_BORDER) { - /* Atom vars for no-border*/ - static Atom window_type = 0; - static Atom value = 0; - - if (window_type == 0) { - window_type = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE", False); - value = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE_DOCK", False); - } - - XChangeProperty((Display*) win->src.display, (Drawable) win->src.window, window_type, XA_ATOM, 32, PropModeReplace, (u8*) &value, 1); /* toggle 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", 1); + 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 - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + if ((args & RGFW_NO_INIT_API) == 0) + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); #endif /* set the background*/ @@ -2880,7 +2240,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } #ifdef RGFW_EGL - RGFW_createOpenGLContext(win); + if ((args & RGFW_NO_INIT_API) == 0) + RGFW_createOpenGLContext(win); #endif RGFW_window_setMouseDefault(win); @@ -2933,6 +2294,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); + + if (win->event.type == 0) + RGFW_resetKey(); + + if (win->event.type == RGFW_quit) { + return NULL; + } + win->event.type = 0; #ifdef __linux__ @@ -2942,7 +2311,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ struct js_event e; - if (!win->src.joysticks[i]) + if (win->src.joysticks[i] == 0) continue; i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0); @@ -2955,6 +2324,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; win->event.button = e.number; win->src.jsPressed[i][e.number] = e.value; + RGFW_jsButtonCallback(win, i, e.number, e.value); return &win->event; case JS_EVENT_AXIS: ioctl(win->src.joysticks[i], JSIOCGAXES, &win->event.axisesCount); @@ -2967,7 +2337,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.axis[e.number / 2].x = xAxis; win->event.axis[e.number / 2].y = yAxis; win->event.type = RGFW_jsAxisMove; - win->event.joystick = e.number / 2; + win->event.joystick = i; + RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount); return &win->event; default: break; @@ -3005,54 +2376,64 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ /* set event key data */ KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode); - win->event.keyName = XKeysymToString(sym); /* convert to string */ + + char* str = XKeysymToString(sym); + if (str != NULL) + strncpy(win->event.keyName, str, 16); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + win->event.keyName[15] = '\0'; + + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); /* get keystate data */ win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; - if (win->event.type == RGFW_keyReleased) { - if (sym == XK_Caps_Lock && win->event.lockState & RGFW_CAPSLOCK) - win->event.lockState ^= RGFW_CAPSLOCK; - else if (sym == XK_Caps_Lock) - win->event.lockState |= RGFW_CAPSLOCK; + XKeyboardState keystate; + XGetKeyboardControl((Display*) win->src.display, &keystate); - else if (sym == XK_Num_Lock && win->event.lockState & RGFW_NUMLOCK) - win->event.lockState ^= RGFW_NUMLOCK; - else if (sym == XK_Num_Lock) - win->event.lockState |= RGFW_NUMLOCK; - } - - RGFW_keyboard[win->event.keyCode] = (E.type == KeyPress); + RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); + + RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress); + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress)); break; case ButtonPress: case ButtonRelease: - win->event.type = (E.type == ButtonPress) ? RGFW_mouseButtonPressed : RGFW_mouseButtonReleased; - - if (win->event.button == RGFW_mouseScrollUp) { - win->event.scroll = 1; - } - else if (win->event.button == RGFW_mouseScrollDown) { - win->event.scroll = -1; + win->event.type = E.type; // the events match + + switch(win->event.button) { + case RGFW_mouseScrollUp: + win->event.scroll = 1; + break; + case RGFW_mouseScrollDown: + win->event.scroll = -1; + break; + default: break; } win->event.button = E.xbutton.button; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = (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; win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + 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; } @@ -3071,10 +2452,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if ((win->src.winArgs & RGFW_ALLOW_DND) == 0) break; - u8 formFree = 0; if (E.xclient.message_type == XdndEnter) { u64 count; - Atom* formats = (Atom*) 0; + Atom* formats; + Atom real_formats[6]; + Bool list = E.xclient.data.l[1] & 1; xdnd.source = E.xclient.data.l[0]; @@ -3102,17 +2484,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ (unsigned long*) &bytesAfter, (u8**) &formats); } else { - formats = (Atom*) RGFW_MALLOC(E.xclient.data.l[2] + E.xclient.data.l[3] + E.xclient.data.l[4]); - formFree = 1; - count = 0; if (E.xclient.data.l[2] != None) - formats[count++] = E.xclient.data.l[2]; + real_formats[count++] = E.xclient.data.l[2]; if (E.xclient.data.l[3] != None) - formats[count++] = E.xclient.data.l[3]; + real_formats[count++] = E.xclient.data.l[3]; if (E.xclient.data.l[4] != None) - formats[count++] = E.xclient.data.l[4]; + real_formats[count++] = E.xclient.data.l[4]; + + formats = real_formats; } u32 i; @@ -3140,14 +2521,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } } - if (list && formats) { + if (list) { XFree(formats); - formats = (Atom*) 0; - } else if (formFree && formats != (Atom*) 0) { - RGFW_FREE(formats); - - formats = (Atom*) 0; - formFree = 1; } break; @@ -3223,6 +2598,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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 */ @@ -3293,7 +2670,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ line++; } path[index] = '\0'; - strcpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path); + strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); } if (data) @@ -3312,37 +2689,54 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XFlush((Display*) win->src.display); } + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); break; case FocusIn: win->event.inFocus = 1; - - XKeyboardState keystate; - XGetKeyboardControl((Display*) win->src.display, &keystate); - win->event.lockState = keystate.led_mask; - 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 + /* 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); - break; + 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 + /* 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); + 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: { break; @@ -3357,76 +2751,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return NULL; } - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_VULKAN - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } - - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); -#endif - -#ifdef RGFW_EGL - RGFW_closeEGL(win); -#endif - -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (win->buffer != NULL) { - XDestroyImage((XImage*) win->src.bitmap); - } -#endif - - if ((Display*) win->src.display) { -#ifdef RGFW_OPENGL - glXDestroyContext((Display*) win->src.display, win->src.rSurf); -#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*/ - - if (win->src.display) - 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 - - /* set cleared display / window to NULL for error checking */ - win->src.display = (Display*) 0; - win->src.window = (Window) 0; - - u8 i; - for (i = 0; i < win->src.joystickCount; i++) - close(win->src.joysticks[i]); - - RGFW_FREE(win); /* free collected window data */ - } - void RGFW_window_move(RGFW_window* win, RGFW_vector v) { assert(win != NULL); win->r.x = v.x; @@ -3447,13 +2771,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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; @@ -3463,6 +2790,9 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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; @@ -3489,13 +2819,51 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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 @@ -3587,8 +2955,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (event.xbutton.x == v.x && event.xbutton.y == v.y) return; - XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, -event.xbutton.x, -event.xbutton.y); - XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, v.x, v.y); + XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y); } RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) { @@ -3654,7 +3021,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (target == UTF8 || target == XA_STRING) { s = (char*)RGFW_MALLOC(sizeof(char) * sizeN); - strcpy(s, data); + strncpy(s, data, sizeN); + s[sizeN] = '\0'; XFree(data); } @@ -3937,7 +3305,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XrmValue value; char* type = NULL; - if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strcmp(type, "String") == 0) + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0) xdpi = ydpi = atof(value.addr); XrmDestroyDatabase(db); #endif @@ -3955,7 +3323,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ monitor.physW = (monitor.rect.w * 25.4f / 96.f); monitor.physH = (monitor.rect.h * 25.4f / 96.f); - strcpy(monitor.name, DisplayString(display)); + strncpy(monitor.name, DisplayString(display), 128); XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); @@ -4024,9 +3392,187 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ 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) { + assert(win != NULL); + + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + } + #endif + + + void RGFW_window_swapBuffers(RGFW_window* win) { + assert(win != NULL); + + RGFW_window_makeCurrent(win); + + /* clear the window*/ + if (!(win->src.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->src.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 + } + + RGFW_window_checkFPS(win); + } + + #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); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + } + #endif + + + void RGFW_window_close(RGFW_window* win) { + 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.rSurf); +#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 (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) { + dlclose(RGFW_libxshape); + RGFW_libxshape = NULL; + } + + /* set cleared display / window to NULL for error checking */ + win->src.display = (Display*) 0; + win->src.window = (Window) 0; + + u8 i; + for (i = 0; i < win->src.joystickCount; i++) + close(win->src.joysticks[i]); + + RGFW_FREE(win); /* free collected window data */ + } + + 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; + } +/* + End of linux / unix defines +*/ + +#endif /* RGFW_X11 */ + + +/* + + Start of Windows defines + + +*/ + #ifdef RGFW_WINDOWS + #include + #include + #include + #include + #include + #include + #include + #include + + #ifndef RGFW_NO_XINPUT + typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); + PFN_XInputGetState XInputGetStateSRC = NULL; + #define XInputGetState XInputGetStateSRC + + typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE); + PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL; + #define XInputGetKeystroke XInputGetKeystrokeSRC + + static HMODULE RGFW_XInput_dll = NULL; + #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}; + char* createUTF8FromWideStringWin32(const WCHAR* source); #define GL_FRONT 0x0404 @@ -4064,21 +3610,18 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void* RGFWjoystickApi = NULL; /* these two wgl functions need to be preloaded */ - typedef long long int (WINAPI* wglCreateContextAttribsARB_type)(HDC hdc, HGLRC hShareContext, - const int* attribList); - wglCreateContextAttribsARB_type wglCreateContextAttribsARB = NULL; + 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_TRANSPARENT_ARB 0x200A #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 @@ -4099,7 +3642,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_TYPE_RGBA_ARB 0x202B #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 @@ -4144,7 +3686,7 @@ static HMODULE wglinstance = NULL; return (void*) GetProcAddress(wglinstance, procname); } - typedef u64 (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); + typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; #endif @@ -4169,11 +3711,14 @@ static HMODULE wglinstance = NULL; #ifndef RGFW_NO_DPI static HMODULE RGFW_Shcore_dll = NULL; - typedef u64 (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); + typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL; #define GetDpiForMonitor GetDpiForMonitorSRC #endif + __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); + + #ifndef RGFW_NO_XINPUT void RGFW_loadXInput(void) { u32 i; static const char* names[] = { @@ -4188,22 +3733,76 @@ static HMODULE wglinstance = NULL; RGFW_XInput_dll = LoadLibraryA(names[i]); if (RGFW_XInput_dll) { - XInputGetStateSRC = (PFN_XInputGetState)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); + XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); if (XInputGetStateSRC == NULL) printf("Failed to load XInputGetState"); } } } + #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); + bi.bV5Width = RGFW_bufferSize.w; + bi.bV5Height = -((LONG) RGFW_bufferSize.h); + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5BlueMask = 0x00ff0000; + bi.bV5GreenMask = 0x0000ff00; + bi.bV5RedMask = 0x000000ff; + bi.bV5AlphaMask = 0xff000000; + + win->src.bitmap = CreateDIBSection(win->src.hdc, + (BITMAPINFO*) &bi, + DIB_RGB_COLORS, + (void**) &win->buffer, + NULL, + (DWORD) 0); + + win->src.hdcMem = CreateCompatibleDC(win->src.hdc); + + #if defined(RGFW_OSMESA) + win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.rSurf, 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_setDND(RGFW_window* win, b8 allow) { + DragAcceptFiles(win->src.window, allow); + } + + void RGFW_clipCursor(RGFW_rect rect) { + if (!rect.x && !rect.y && rect.w && !rect.h) { + ClipCursor(NULL); + return; + } + + RECT r = {rect.x, rect.y, rect.x + rect.w, rect.y + rect.h}; + ClipCursor(&r); + } RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { + #ifndef RGFW_NO_XINPUT if (RGFW_XInput_dll == NULL) RGFW_loadXInput(); - + #endif + #ifndef RGFW_NO_DPI if (RGFW_Shcore_dll == NULL) { RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); - GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); + GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); } #endif @@ -4219,6 +3818,8 @@ static HMODULE wglinstance = NULL; #endif } + timeBeginPeriod(1); + if (name[0] == 0) name = (char*) " "; RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); @@ -4226,10 +3827,10 @@ static HMODULE wglinstance = NULL; RGFW_window* win = RGFW_window_basic_init(rect, args); - if (RGFW_root == NULL) { - RGFW_root = win; - } - + win->src.maxSize = RGFW_AREA(0, 0); + win->src.minSize = RGFW_AREA(0, 0); + + HINSTANCE inh = GetModuleHandleA(NULL); WNDCLASSA Class = { 0 }; /* Setup the Window class. */ @@ -4260,15 +3861,13 @@ static HMODULE wglinstance = NULL; 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_TRANSPARENT_WINDOW) { - SetWindowLongA(win->src.window, GWL_EXSTYLE, GetWindowLongA(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED); - } if (args & RGFW_ALLOW_DND) { win->src.winArgs |= RGFW_ALLOW_DND; - DragAcceptFiles(win->src.window, TRUE); + 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); @@ -4338,10 +3937,10 @@ static HMODULE wglinstance = NULL; .nVersion = 1, .iPixelType = PFD_TYPE_RGBA, .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - .cColorBits = 32, + .cColorBits = 24, .cAlphaBits = 8, .iLayerType = PFD_MAIN_PLANE, - .cDepthBits = 24, + .cDepthBits = 32, .cStencilBits = 8, }; @@ -4352,8 +3951,8 @@ static HMODULE wglinstance = NULL; wglMakeCurrent(dummy_dc, dummy_context); if (wglChoosePixelFormatARB == NULL) { - wglCreateContextAttribsARB = (wglCreateContextAttribsARB_type) wglGetProcAddress("wglCreateContextAttribsARB"); - wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB"); + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB"); } wglMakeCurrent(dummy_dc, 0); @@ -4412,8 +4011,8 @@ static HMODULE wglinstance = NULL; } wglMakeCurrent(win->src.hdc, win->src.rSurf); - wglShareLists(RGFW_root->src.rSurf, win->src.rSurf); #endif + } #ifdef RGFW_OSMESA #ifdef RGFW_LINK_OSM ESA @@ -4424,33 +4023,67 @@ static HMODULE wglinstance = NULL; #endif #ifdef RGFW_OPENGL - ReleaseDC(win->src.window, win->src.hdc); - win->src.hdc = GetDC(win->src.window); - wglMakeCurrent(win->src.hdc, win->src.rSurf); + if ((args & RGFW_NO_INIT_API) == 0) { + ReleaseDC(win->src.window, win->src.hdc); + win->src.hdc = GetDC(win->src.window); + wglMakeCurrent(win->src.hdc, win->src.rSurf); + } #endif DestroyWindow(dummyWin); RGFW_init_buffer(win); -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif #ifdef RGFW_EGL - RGFW_createOpenGLContext(win); + if ((args & RGFW_NO_INIT_API) == 0) + RGFW_createOpenGLContext(win); #endif if (args & RGFW_HIDE_MOUSE) 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.rSurf, win->src.rSurf); + #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 + ); + } + } + RGFW_area RGFW_getScreenSize(void) { return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES)); @@ -4494,98 +4127,55 @@ static HMODULE wglinstance = NULL; ShowWindow(win->src.window, SW_RESTORE); } - static i32 RGFW_checkXInput(RGFW_Event* e) { - static WORD buttons[4]; - static BYTE triggers[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; + u8 RGFW_xinput2RGFW[] = { + RGFW_JS_A, /* or PS X button */ + RGFW_JS_B, /* or PS circle button */ + RGFW_JS_X, /* or PS square button */ + RGFW_JS_Y, /* or PS triangle button */ + RGFW_JS_R1, /* right bumper */ + RGFW_JS_L1, /* left bump */ + RGFW_JS_L2, /* left trigger*/ + RGFW_JS_R2, /* right trigger */ + 0, 0, 0, 0, 0, 0, 0, 0, + RGFW_JS_UP, /* dpad up */ + RGFW_JS_DOWN, /* dpad down*/ + RGFW_JS_LEFT, /* dpad left */ + RGFW_JS_RIGHT, /* dpad right */ + RGFW_JS_START, /* start button */ + RGFW_JS_SELECT/* select button */ + }; + + static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) { 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; + + if (keystroke.VirtualKey > VK_PAD_BACK) + continue; + + // RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased + e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; + win->src.jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + + return 1; + } + XINPUT_STATE state; if (XInputGetState == NULL || XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED ) return 0; - - e->button = 0; - if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A && !(buttons[i] & XINPUT_GAMEPAD_A)) { - e->button = RGFW_JS_A; - e->type = RGFW_jsButtonPressed; - buttons[i] = state.Gamepad.wButtons; - return 1; - } else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B && !(buttons[i] & XINPUT_GAMEPAD_B)) - e->button = RGFW_JS_B; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y && !(buttons[i] & XINPUT_GAMEPAD_Y)) - e->button = RGFW_JS_Y; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X && !(buttons[i] & XINPUT_GAMEPAD_X)) - e->button = RGFW_JS_X; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START && !(buttons[i] & XINPUT_GAMEPAD_START)) - e->button = RGFW_JS_START; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK && !(buttons[i] & XINPUT_GAMEPAD_BACK)) - e->button = RGFW_JS_SELECT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP && !(buttons[i] & XINPUT_GAMEPAD_DPAD_UP)) - e->button = RGFW_JS_UP; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN && !(buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN)) - e->button = RGFW_JS_DOWN; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT)) - e->button = RGFW_JS_LEFT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT)) - e->button = RGFW_JS_RIGHT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER)) - e->button = RGFW_JS_L1; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER)) - e->button = RGFW_JS_R1; - else if (state.Gamepad.bLeftTrigger && triggers[i][0] == 0) - e->button = RGFW_JS_L2; - else if (state.Gamepad.bRightTrigger && triggers[i][1] == 0) - e->button = RGFW_JS_R2; - - triggers[i][0] = state.Gamepad.bLeftTrigger; - triggers[i][1] = state.Gamepad.bRightTrigger; - - if (e->button) { - buttons[i] = state.Gamepad.wButtons; - e->type = RGFW_jsButtonPressed; - return 1; - } - - if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_A) && (buttons[i] & XINPUT_GAMEPAD_A)) { - e->button = RGFW_JS_A; - e->type = RGFW_jsButtonReleased; - buttons[i] = state.Gamepad.wButtons; - return 1; - } else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_B) && (buttons[i] & XINPUT_GAMEPAD_B)) - e->button = RGFW_JS_B; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) && (buttons[i] & XINPUT_GAMEPAD_Y)) - e->button = RGFW_JS_Y; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_X) && (buttons[i] & XINPUT_GAMEPAD_X)) - e->button = RGFW_JS_X; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_START) && (buttons[i] & XINPUT_GAMEPAD_START)) - e->button = RGFW_JS_START; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) && (buttons[i] & XINPUT_GAMEPAD_BACK)) - e->button = RGFW_JS_SELECT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) && (buttons[i] & XINPUT_GAMEPAD_DPAD_UP)) - e->button = RGFW_JS_UP; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) && (buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN)) - e->button = RGFW_JS_DOWN; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT)) - e->button = RGFW_JS_LEFT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT)) - e->button = RGFW_JS_RIGHT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER)) - e->button = RGFW_JS_L1; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER)) - e->button = RGFW_JS_R1; - else if (state.Gamepad.bLeftTrigger == 0 && triggers[i][0] != 0) - e->button = RGFW_JS_L2; - else if (state.Gamepad.bRightTrigger == 0 && triggers[i][1] != 0) - e->button = RGFW_JS_R2; - - buttons[i] = state.Gamepad.wButtons; - - if (e->button) { - e->type = RGFW_jsButtonReleased; - 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 && @@ -4629,6 +4219,10 @@ static HMODULE wglinstance = NULL; RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); + if (win->event.type == RGFW_quit) { + return NULL; + } + MSG msg; if (RGFW_eventWindow.src.window == win->src.window) { @@ -4636,12 +4230,14 @@ static HMODULE wglinstance = NULL; 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; @@ -4650,37 +4246,82 @@ static HMODULE wglinstance = NULL; return &win->event; } + + 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->event)) + if (RGFW_checkXInput(win, &win->event)) return &win->event; - if (win->event.type == RGFW_quit) - return NULL; - static BYTE keyboardState[256]; if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) { 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) + if (win->event.inFocus) { win->event.type = RGFW_focusIn; - else + RGFW_focusCallback(win, 1); + } + else { win->event.type = RGFW_focusOut; - - break; + 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->src.winArgs |= RGFW_MOUSE_LEFT; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + case WM_KEYUP: { win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); static char keyName[16]; @@ -4692,22 +4333,25 @@ static HMODULE wglinstance = NULL; CharLowerBuffA(keyName, 16); } } - + + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + strncpy(win->event.keyName, keyName, 16); - if (RGFW_isPressedI(win, RGFW_ShiftL)) { + 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.keyCode] = 0; + RGFW_keyboard[win->event.keyCode].current = 0; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); break; } case WM_KEYDOWN: { win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); static char keyName[16]; @@ -4719,24 +4363,36 @@ static HMODULE wglinstance = NULL; CharLowerBuffA(keyName, 16); } } - + + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + strncpy(win->event.keyName, keyName, 16); - if (RGFW_isPressedI(win, RGFW_ShiftL) & 0x8000) { + 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; - RGFW_keyboard[win->event.keyCode] = 1; + RGFW_keyboard[win->event.keyCode].current = 1; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); break; } case WM_MOUSEMOVE: + win->event.type = RGFW_mousePosChanged; + win->event.point.x = GET_X_LPARAM(msg.lParam); win->event.point.y = GET_Y_LPARAM(msg.lParam); - win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + + if (win->src.winArgs & RGFW_MOUSE_LEFT) { + win->src.winArgs ^= RGFW_MOUSE_LEFT; + win->event.type = RGFW_mouseEnter; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + } + break; case WM_LBUTTONDOWN: @@ -4744,18 +4400,21 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 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_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 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_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case WM_MOUSEWHEEL: @@ -4770,6 +4429,7 @@ static HMODULE wglinstance = NULL; 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: @@ -4779,6 +4439,7 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_RBUTTONUP: win->event.button = RGFW_mouseRight; @@ -4786,6 +4447,7 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_MBUTTONUP: win->event.button = RGFW_mouseMiddle; @@ -4793,29 +4455,17 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; /* much of this event is source from glfw */ - case WM_DROPFILES: { + case WM_DROPFILES: { + 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.type = RGFW_dnd; - - HDROP drop = (HDROP) msg.wParam; + drop = (HDROP) msg.wParam; POINT pt; - u32 i; - - win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); - //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*)); /* Move the mouse to the position of the drop */ DragQueryPoint(drop, &pt); @@ -4823,19 +4473,9 @@ static HMODULE wglinstance = NULL; win->event.point.x = pt.x; win->event.point.y = pt.y; - 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); - strcpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer)); - - RGFW_FREE(buffer); - } - - DragFinish(drop); + RGFW_dndInitCallback(win, win->event.point); } - break; + break; case WM_GETMINMAXINFO: { if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) @@ -4860,18 +4500,10 @@ static HMODULE wglinstance = NULL; else win->event.type = 0; - win->event.lockState = 0; - - if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0) - win->event.lockState |= RGFW_CAPSLOCK; - if ((GetKeyState(VK_NUMLOCK) & 0x0001) != 0) - win->event.lockState |= RGFW_NUMLOCK; - if ((GetKeyState(VK_SCROLL) & 0x0001) != 0) - win->event.lockState |= 3; - - - if (!IsWindow(win->src.window)) + if (!IsWindow(win->src.window)) { win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + } if (win->event.type) return &win->event; @@ -4921,7 +4553,8 @@ static HMODULE wglinstance = NULL; info->iIndex++; return TRUE; } - + + #ifndef RGFW_NO_MONITOR RGFW_monitor win32CreateMonitor(HMONITOR src) { RGFW_monitor monitor; MONITORINFO monitorInfo; @@ -4943,7 +4576,7 @@ static HMODULE wglinstance = NULL; for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { char* deviceName = dd.DeviceName; if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { - strcpy(monitor.name, dd.DeviceString); /* copy the monitor's name */ + strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */ break; } } @@ -4975,7 +4608,10 @@ static HMODULE wglinstance = NULL; 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) @@ -5008,6 +4644,7 @@ static HMODULE wglinstance = NULL; 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); @@ -5087,10 +4724,8 @@ static HMODULE wglinstance = NULL; if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) return; - - mouse = RGFW_mouseIconSrc[mouse]; - char* icon = MAKEINTRESOURCEA(mouse); + char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); SetCursor(LoadCursorA(NULL, icon)); @@ -5107,21 +4742,6 @@ static HMODULE wglinstance = NULL; void RGFW_window_close(RGFW_window* win) { assert(win != NULL); -#ifdef RGFW_VULKAN - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL); - } - - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } - - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); -#endif - #ifdef RGFW_EGL RGFW_closeEGL(win); #endif @@ -5213,9 +4833,45 @@ static HMODULE wglinstance = 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); + } + } + #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) HICON handle = RGFW_loadHandleImage(win, src, a, TRUE); @@ -5223,6 +4879,11 @@ static HMODULE wglinstance = NULL; SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle); DestroyIcon(handle); + #else + RGFW_UNUSED(src) + RGFW_UNUSED(a) + RGFW_UNUSED(channels) + #endif } char* RGFW_readClipboard(size_t* size) { @@ -5254,6 +4915,8 @@ static HMODULE wglinstance = NULL; if (size != NULL) *size = textLen + 1; + + text[textLen] = '\0'; } /* Release the clipboard data */ @@ -5311,6 +4974,76 @@ static HMODULE wglinstance = NULL; SetCursorPos(p.x, p.y); } + #ifdef RGFW_OPENGL + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + assert(win != NULL); + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf); + } + #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; + + if (loadSwapFunc == NULL) { + fprintf(stderr, "wglSwapIntervalEXT not supported\n"); + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + return; + } + + if (wglSwapIntervalEXT == NULL) { + loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; + } + + if (wglSwapIntervalEXT(swapInterval) == FALSE) + fprintf(stderr, "Failed to set swap interval\n"); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + + } + #endif + + void RGFW_window_swapBuffers(RGFW_window* win) { + assert(win != NULL); + + RGFW_window_makeCurrent(win); + + /* clear the window*/ + + if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_OSMESA + RGFW_OSMesa_reorganize(); + #endif + + 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->src.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 + } + + RGFW_window_checkFPS(win); + } + char* createUTF8FromWideStringWin32(const WCHAR* source) { char* target; i32 size; @@ -5330,15 +5063,395 @@ static HMODULE wglinstance = NULL; return target; } + u64 RGFW_getTimeNS(void) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart); + } + + u64 RGFW_getTime(void) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + + 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); } #endif -#endif +#endif /* RGFW_WINDOWS */ + +/* + End of Windows defines +*/ + + + +/* + + Start of MacOS defines + + +*/ #if defined(RGFW_MACOS) + /* + based on silicon.h + start of cocoa wrapper + */ + +#include +#include +#include +#include +#include + + 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 NSScreen; + 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; + +#ifdef __arm64__ + /* ARM just uses objc_msgSend */ +#define abi_objc_msgSend_stret objc_msgSend +#define abi_objc_msgSend_fpret objc_msgSend +#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_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) +#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) + + void NSRelease(id obj) { + objc_msgSend_void(obj, sel_registerName("release")); + } + + #define release NSRelease + + NSString* 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(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. */ +#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 NS_ENUM(type, name) type name; enum + + 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 + + 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:"); + + 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); + } + + 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); + } + + NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { + void* func = sel_registerName("initWithImage:hotSpot:"); + void* nsclass = objc_getClass("NSCursor"); + + return (NSCursor*) ((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); + } + + NSImage* NSImage_initWithSize(NSSize size) { + void* 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 */ + NSOpenGLContextParameterSurfaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ + NSOpenGLContextParameterSurfaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ + NSOpenGLContextParameterSurfaceBackingSize 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 */ + NSOpenGLContextParameterSurfaceSurfaceVolatile 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* 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); + } + + 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); + } + + void NSCursor_performSelector(NSCursor* cursor, void* selector) { + void* 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")); + } + + 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]); + + 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))); + } + + 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); + + NSArray* array = c_array_to_NSArray(ntypes, len); + objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); + NSRelease(array); + } + + NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { + NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); + + void* func = sel_registerName("declareTypes:owner:"); + + NSArray* array = c_array_to_NSArray(ntypes, len); + + NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) + (pasteboard, func, array, owner); + NSRelease(array); + + return output; + } + + 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)); + } + + void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } + + typedef enum NSApplicationActivationPolicy { + NSApplicationActivationPolicyRegular, + NSApplicationActivationPolicyAccessory, + NSApplicationActivationPolicyProhibited + } NSApplicationActivationPolicy; + + typedef NS_ENUM(u32, NSBackingStoreType) { + NSBackingStoreRetained = 0, + NSBackingStoreNonretained = 1, + NSBackingStoreBuffered = 2 + }; + + 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 const char* NSPasteboardType; + NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType + + + + typedef NS_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 + }; + + void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { + void* 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:"); + + NSArray* array = c_array_to_NSArray(classArray, len); + + 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; @@ -5362,20 +5475,18 @@ static HMODULE wglinstance = NULL; return kCVReturnSuccess; } - RGFW_window* RGFW_windows[10]; - u32 RGFW_windows_size = 0; - id NSWindow_delegate(RGFW_window* win) { return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate")); } u32 RGFW_OnClose(void* self) { - u32 i; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - RGFW_windows[i]->event.type = RGFW_quit; - return true; - } + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); return true; } @@ -5386,13 +5497,44 @@ static HMODULE wglinstance = NULL; NSDragOperation draggingEntered(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + + printf("hi\n"); return NSDragOperationCopy; } NSDragOperation draggingUpdated(id self, SEL sel, id sender) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + if (!(win->src.winArgs & RGFW_ALLOW_DND)) { + return false; + } + + 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_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + RGFW_dndInitCallback(win, win->event.point); + return NSDragOperationCopy; } - bool prepareForDragOperation(void) { return true; } + bool prepareForDragOperation(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + if (!(win->src.winArgs & RGFW_ALLOW_DND)) { + return false; + } + + return true; + } void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } @@ -5400,16 +5542,15 @@ static HMODULE wglinstance = NULL; bool performDragOperation(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); - NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow")); + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + //NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow")); u32 i; bool found = 0; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i]->src.window == window) { - found = 1; - break; - } - if (!found) i = 0; @@ -5418,20 +5559,23 @@ static HMODULE wglinstance = NULL; char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(pasteBoard, array, 1, NULL); - RGFW_windows[i]->event.droppedFilesCount = si_array_len(droppedFiles); + win->event.droppedFilesCount = si_array_len(droppedFiles); u32 y; - for (y = 0; y < RGFW_windows[i]->event.droppedFilesCount; y++) - strcpy(RGFW_windows[i]->event.droppedFiles[y], droppedFiles[y]); + for (y = 0; y < win->event.droppedFilesCount; y++) { + strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH); - RGFW_windows[i]->event.type = RGFW_dnd; - RGFW_windows[i]->src.dndPassed = 0; + win->event.droppedFiles[y][RGFW_MAX_PATH - 1] = '\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_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); - RGFW_windows[i]->event.point.x = (i32)p.x; - RGFW_windows[i]->event.point.x = (i32)p.y; + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); return true; } @@ -5468,41 +5612,62 @@ static HMODULE wglinstance = NULL; NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) { RGFW_UNUSED(sel); - u32 i; - for (i = 0; i < RGFW_windows_size; i++) { - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - RGFW_windows[i]->r.w = frameSize.width; - RGFW_windows[i]->r.h = frameSize.height; - RGFW_windows[i]->event.type = RGFW_windowResized; - - return frameSize; - } - } - + 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); return frameSize; } void RGFW__osxWindowMove(void* self, SEL sel) { RGFW_UNUSED(sel); - u32 i; - for (i = 0; i < RGFW_windows_size; i++) { - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(RGFW_windows[i]->src.window, sel_registerName("frame")); - RGFW_windows[i]->r.x = (i32) frame.origin.x; - RGFW_windows[i]->r.y = (i32) frame.origin.y; + 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; - RGFW_windows[i]->event.type = RGFW_windowMoved; - return; - } - } + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); } - #ifdef __cplusplus - #define APPKIT_EXTERN extern "C" - #else - #define APPKIT_EXTERN extern - #endif + void RGFW__osxUpdateLayer(void* self, SEL sel) { + RGFW_UNUSED(sel); + + 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_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + + #ifdef RGFW_OSMESA + win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else + RGFW_UNUSED(win); /* if buffer rendering is not being used */ + #endif + } NSPasteboardType const NSPasteboardTypeURL = "public.url"; NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; @@ -5527,6 +5692,8 @@ static HMODULE wglinstance = NULL; } RGFW_window* win = RGFW_window_basic_init(rect, args); + + RGFW_window_setMouseDefault(win); NSRect windowRect; windowRect.origin.x = win->r.x; @@ -5554,6 +5721,7 @@ static HMODULE wglinstance = NULL; objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); #ifdef RGFW_OPENGL + if ((args & RGFW_NO_INIT_API) == 0) { void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); void* format = NSOpenGLPixelFormat_initWithAttributes(attrs); @@ -5568,17 +5736,17 @@ static HMODULE wglinstance = NULL; printf("Switching to software rendering\n"); } - win->src.view = NSOpenGLView_initWithFrame(NSMakeRect(0, 0, win->r.w, win->r.h), format); + win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format); objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL")); win->src.rSurf = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); - -#else - NSRect contentRect = NSMakeRect(0, 0, win->r.w, win->r.h); + } else +#endif + { + NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}}; win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend) (NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"), contentRect); -#endif - + } void* contentView = NSWindow_contentView(win->src.window); objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); @@ -5586,21 +5754,22 @@ static HMODULE wglinstance = NULL; objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view); #ifdef RGFW_OPENGL - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + if ((args & RGFW_NO_INIT_API) == 0) + objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); #endif if (args & RGFW_TRANSPARENT_WINDOW) { #ifdef RGFW_OPENGL + if ((args & RGFW_NO_INIT_API) == 0) { i32 opacity = 0; - NSOpenGLContext_setValues(win->src.rSurf, &opacity, 304); + #define NSOpenGLCPSurfaceOpacity 236 + NSOpenGLContext_setValues(win->src.rSurf, &opacity, NSOpenGLCPSurfaceOpacity); + } #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)); - - ((void (*)(id, SEL, CGFloat))objc_msgSend) - (win->src.window, sel_registerName("setAlphaValue:"), 0x00); } win->src.display = CGMainDisplayID(); @@ -5610,12 +5779,10 @@ static HMODULE wglinstance = NULL; RGFW_init_buffer(win); -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif - + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif if (args & RGFW_HIDE_MOUSE) RGFW_window_showMouse(win, 0); @@ -5624,9 +5791,15 @@ static HMODULE wglinstance = NULL; 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@:@"); @@ -5661,16 +5834,7 @@ static HMODULE wglinstance = NULL; objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - NSApplication_finishLaunching(NSApp); - - RGFW_windows_size++; - - size_t i; - for (i = 0; i < RGFW_windows_size; i++) - if (!RGFW_windows[i]) { - RGFW_windows[i] = win; - break; - } + objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); if (RGFW_root == NULL) RGFW_root = win; @@ -5681,6 +5845,19 @@ static HMODULE wglinstance = NULL; return win; } + void RGFW_window_setBorder(RGFW_window* win, u8 border) { + NSBackingStoreType storeType = NSWindowStyleMaskBorderless; + if (!border) { + storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; + } + if (!(win->src.winArgs & RGFW_NO_RESIZE)) { + storeType |= NSWindowStyleMaskResizable; + } + + ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType); + + objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); + } RGFW_area RGFW_getScreenSize(void) { static CGDirectDisplayID display = 0; @@ -5704,7 +5881,7 @@ static HMODULE wglinstance = NULL; RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) { NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); - return RGFW_VECTOR((u32) p.x, (u32) (p.y)); + return RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); } u32 RGFW_keysPressed[10]; /*10 keys at a time*/ @@ -5798,16 +5975,17 @@ static HMODULE wglinstance = NULL; NSEventModifierFlagShift = 1 << 17, NSEventModifierFlagControl = 1 << 18, NSEventModifierFlagOption = 1 << 19, - NSEventModifierFlagCommand = 1 << 20 + NSEventModifierFlagCommand = 1 << 20, + NSEventModifierFlagNumericPad = 1 << 21 } NSEventModifierFlags; RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); - + if (win->event.type == RGFW_quit) - return &win->event; + return NULL; - if (win->event.type == RGFW_dnd && win->src.dndPassed == 0) { + if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) { win->src.dndPassed = 1; return &win->event; } @@ -5816,7 +5994,7 @@ static HMODULE wglinstance = NULL; if (eventFunc == NULL) eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); - if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized) && win->event.keyCode != 120) { + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) { win->event.keyCode = 120; return &win->event; } @@ -5824,7 +6002,6 @@ static HMODULE wglinstance = NULL; NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) (NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); - if (e == NULL) return NULL; @@ -5844,29 +6021,32 @@ static HMODULE wglinstance = NULL; win->event.droppedFilesCount = 0; win->event.type = 0; - bool isKey = (bool) objc_msgSend_bool(win->src.window, sel_registerName("isKeyWindow")); - - if (win->event.inFocus != isKey) { - win->event.inFocus = isKey; - - if (win->event.inFocus) - win->event.type = RGFW_focusIn; - else - win->event.type = RGFW_focusOut; - - return &win->event; - } - 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_VECTOR((u32) p.x, (u32) (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")); win->event.keyCode = RGFW_apiKeyCodeToRGFW(key); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_keyboard[win->event.keyCode]; + RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; win->event.type = RGFW_keyPressed; - win->event.keyName = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + 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.keyCode].current = 1; - RGFW_keyboard[win->event.keyCode] = 1; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); break; } @@ -5874,86 +6054,53 @@ static HMODULE wglinstance = NULL; u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);; - RGFW_keyboard_prev[win->event.keyCode] = RGFW_keyboard[win->event.keyCode]; + RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; win->event.type = RGFW_keyReleased; - win->event.keyName = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + 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.keyCode] = 0; + RGFW_keyboard[win->event.keyCode].current = 0; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); break; } case NSEventTypeFlagsChanged: { u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); - memcpy(RGFW_keyboard_prev + RGFW_CapsLock, RGFW_keyboard + RGFW_CapsLock, 9); + 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 & NSEventModifierFlagCapsLock) && !RGFW_wasPressedI(win, RGFW_CapsLock)) { - RGFW_keyboard[RGFW_CapsLock] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(57); - break; - } if (!(flags & NSEventModifierFlagCapsLock) && RGFW_wasPressedI(win, RGFW_CapsLock)) { - RGFW_keyboard[RGFW_CapsLock] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(57); - break; + 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.keyCode = 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.keyCode = key; + break; + } } - if ((flags & NSEventModifierFlagOption) && !RGFW_wasPressedI(win, RGFW_AltL)) { - RGFW_keyboard[RGFW_AltL] = 1; - RGFW_keyboard[RGFW_AltR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(58); - break; - } if (!(flags & NSEventModifierFlagOption) && RGFW_wasPressedI(win, RGFW_AltL)) { - RGFW_keyboard[RGFW_AltL] = 0; - RGFW_keyboard[RGFW_AltR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(58); - break; - } - - if ((flags & NSEventModifierFlagControl) && !RGFW_wasPressedI(win, RGFW_ControlL)) { - RGFW_keyboard[RGFW_ControlL] = 1; - RGFW_keyboard[RGFW_ControlR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(59); - break; - } if (!(flags & NSEventModifierFlagControl) && RGFW_wasPressedI(win, RGFW_ControlL)) { - RGFW_keyboard[RGFW_ControlL] = 0; - RGFW_keyboard[RGFW_ControlR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = 59; - break; - } - - if ((flags & NSEventModifierFlagCommand) && !RGFW_wasPressedI(win, RGFW_SuperL)) { - RGFW_keyboard[RGFW_SuperL] = 1; - RGFW_keyboard[RGFW_SuperR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(55); - break; - } if (!(flags & NSEventModifierFlagCommand) && RGFW_wasPressedI(win, RGFW_SuperL)) { - RGFW_keyboard[RGFW_SuperL] = 0; - RGFW_keyboard[RGFW_SuperR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(55); - break; - } - - if ((flags & NSEventModifierFlagShift) && !RGFW_wasPressedI(win, RGFW_ShiftL)) { - RGFW_keyboard[RGFW_ShiftL] = 1; - RGFW_keyboard[RGFW_ShiftR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(56); - break; - } if (!(flags & NSEventModifierFlagShift) && RGFW_wasPressedI(win, RGFW_ShiftL)) { - RGFW_keyboard[RGFW_ShiftL] = 0; - RGFW_keyboard[RGFW_ShiftR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(56); - break; - } + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed); break; } @@ -5963,8 +6110,18 @@ static HMODULE wglinstance = NULL; case NSEventTypeMouseMoved: win->event.type = RGFW_mousePosChanged; NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + + if ((win->src.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")); + + p.x = ((win->r.w / 2)) + p.x; + p.y = ((win->r.h / 2)) + p.y; + win->event.point = RGFW_VECTOR((u32) p.x, (u32) (p.y)); + } + + RGFW_mousePosCallback(win, win->event.point); break; case NSEventTypeLeftMouseDown: @@ -5972,6 +6129,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeOtherMouseDown: @@ -5979,6 +6137,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeRightMouseDown: @@ -5986,6 +6145,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeLeftMouseUp: @@ -5993,6 +6153,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonReleased; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeOtherMouseUp: @@ -6000,6 +6161,15 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 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_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; + RGFW_mouseButtons[win->event.button] = 0; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeScrollWheel: { @@ -6017,15 +6187,10 @@ static HMODULE wglinstance = NULL; win->event.scroll = deltaY; - win->event.type = RGFW_mouseButtonReleased; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; } - case NSEventTypeRightMouseUp: - win->event.button = RGFW_mouseRight; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; - win->event.type = RGFW_mouseButtonReleased; - break; default: break; @@ -6043,7 +6208,7 @@ static HMODULE wglinstance = NULL; 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:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true); + (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) { @@ -6052,7 +6217,7 @@ static HMODULE wglinstance = NULL; 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:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true); + (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) { @@ -6074,14 +6239,26 @@ static HMODULE wglinstance = NULL; 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); + } + #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) - (win->src.window, sel_registerName("setMinSize:"), NSMakeSize(a.w, a.h)); + (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) - (win->src.window, sel_registerName("setMaxSize:"), NSMakeSize(a.w, a.h)); + (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); } void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { @@ -6093,7 +6270,7 @@ static HMODULE wglinstance = NULL; memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); // Add ze representation. - void* dock_image = NSImage_initWithSize(NSMakeSize(area.w, area.h)); + void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); NSImage_addRepresentation(dock_image, (void*) representation); // Finally, set the dock image to it. @@ -6123,11 +6300,11 @@ static HMODULE wglinstance = NULL; memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels); // Add ze representation. - void* cursor_image = NSImage_initWithSize(NSMakeSize(a.w, a.h)); + void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); NSImage_addRepresentation(cursor_image, representation); // Finally, set the cursor image. - void* cursor = NSCursor_initWithImage(cursor_image, NSMakePoint(0, 0)); + void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); objc_msgSend_void(cursor, sel_registerName("set")); @@ -6166,11 +6343,15 @@ static HMODULE wglinstance = NULL; objc_msgSend_void(mouse, sel_registerName("set")); } + void RGFW_clipCursor(RGFW_rect r) { + CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); + CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h)); + } + void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) { RGFW_UNUSED(win); - assert(win != NULL); - CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); + CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); } @@ -6252,19 +6433,23 @@ static HMODULE wglinstance = NULL; return RGFW_NSCreateMonitor(win->src.display); } -#ifdef __cplusplus -#define APPKIT_EXTERN extern "C" -#else -#define APPKIT_EXTERN extern -#endif - char* RGFW_readClipboard(size_t* size) { char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString); - size_t clip_len = strlen(clip); + + size_t clip_len = 1; + + if (clip != NULL) { + clip_len = strlen(clip) + 1; + } char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len); - strcpy(str, clip); + + if (clip != NULL) { + strncpy(str, clip, clip_len); + } + str[clip_len] = '\0'; + if (size != NULL) *size = clip_len; return str; @@ -6295,24 +6480,73 @@ static HMODULE wglinstance = NULL; return win->src.joystickCount - 1; } - void RGFW_window_close(RGFW_window* win) { + #ifdef RGFW_OPENGL + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + assert(win != NULL); + objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + } + #endif + + #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + #if defined(RGFW_OPENGL) + + NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + } + #endif + + void RGFW_window_swapBuffers(RGFW_window* win) { assert(win != NULL); -#ifdef RGFW_VULKAN - for (int i = 0; i < win->src.image_count; i++) { - vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL); - } + RGFW_window_makeCurrent(win); - for (int i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } + /* clear the window*/ - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); + if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_OSMESA + RGFW_OSMesa_reorganize(); + #endif + + RGFW_area area = RGFW_bufferSize; + 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}}); + + NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData( + &win->buffer, win->r.w, win->r.h, 8, 4, true, false, + "NSDeviceRGBColorSpace", 0, + area.w * 4, 32 + ); + id image = NSAlloc((id)objc_getClass("NSImage")); + NSImage_addRepresentation(image, rep); + objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image); + + release(image); + release(rep); #endif + } + if (!(win->src.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.rSurf, sel_registerName("flushBuffer")); + #endif + } + + RGFW_window_checkFPS(win); + } + + void RGFW_window_close(RGFW_window* win) { + assert(win != NULL); release(win->src.view); #ifdef RGFW_ALLOC_DROPFILES @@ -6326,16 +6560,7 @@ static HMODULE wglinstance = NULL; } #endif - u32 i; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i]->src.window == win->src.window) { - RGFW_windows[i] = NULL; - break; - } - - if (!i) { - RGFW_windows_size = 0; - + if (RGFW_root == win) { objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window); NSApp = NULL; } @@ -6350,10 +6575,31 @@ static HMODULE wglinstance = NULL; RGFW_FREE(win); } -#endif + 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); + } +#endif /* RGFW_MACOS */ + +/* + End of MaOS defines +*/ + +/* unix (macOS, linux) only stuff */ #if defined(RGFW_X11) || defined(RGFW_MACOS) - +/* unix threading */ #ifndef RGFW_NO_THREADS #include @@ -6370,340 +6616,16 @@ static HMODULE wglinstance = NULL; void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); } #endif #endif -#endif - - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_OPENGL -#ifdef RGFW_X11 - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); -#endif -#ifdef RGFW_WINDOWS - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf); -#endif -#if defined(RGFW_MACOS) - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); -#endif -#else -#ifdef RGFW_EGL - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); -#endif -#endif - - } - - void RGFW_window_makeCurrent(RGFW_window* win) { - assert(win != NULL); - -#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); -#endif - -#ifdef RGFW_OPENGL - RGFW_window_makeCurrent_OpenGL(win); -#endif - } - - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - -#ifdef RGFW_OPENGL -#ifdef RGFW_X11 - ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); -#endif -#ifdef RGFW_WINDOWS - - typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); - static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - static void* loadSwapFunc = (void*) 1; - - if (loadSwapFunc == NULL) { - fprintf(stderr, "wglSwapIntervalEXT not supported\n"); - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; - return; - } - - if (wglSwapIntervalEXT == NULL) { - loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; - } - - if (wglSwapIntervalEXT(swapInterval) == FALSE) - fprintf(stderr, "Failed to set swap interval\n"); - -#endif -#if defined(RGFW_MACOS) - NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222); -#endif -#endif - -#ifdef RGFW_EGL - eglSwapInterval(win->src.EGL_display, swapInterval); -#endif - - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; - - } - - void RGFW_window_setGPURender(RGFW_window* win, i8 set) { - if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER)) - win->src.winArgs |= RGFW_NO_GPU_RENDER; - - else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER) - win->src.winArgs ^= RGFW_NO_GPU_RENDER; - } - - void RGFW_window_setCPURender(RGFW_window* win, i8 set) { - if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER)) - win->src.winArgs |= RGFW_NO_CPU_RENDER; - - else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER) - win->src.winArgs ^= RGFW_NO_CPU_RENDER; - } - - - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_window_makeCurrent(win); - - /* clear the window*/ - - if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -#ifdef RGFW_OSMESA - 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 - -#ifdef RGFW_X11 - RGFW_area area = RGFW_getScreenSize(); - -#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, XDefaultGC(win->src.display, XDefaultScreen(win->src.display)), win->src.bitmap, 0, 0, 0, 0, win->r.w, win->r.h); -#endif -#ifdef RGFW_WINDOWS - 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 defined(RGFW_MACOS) - RGFW_area area = RGFW_getScreenSize(); - 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:"), - NSMakeRect(0, 0, win->r.w, win->r.h)); - - NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData( - &win->buffer, win->r.w, win->r.h, 8, 4, true, false, - "NSDeviceRGBColorSpace", 0, - area.w * 4, 32 - ); - id image = NSAlloc((id)objc_getClass("NSImage")); - NSImage_addRepresentation(image, rep); - objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image); - - release(image); - release(rep); -#endif -#endif - -#ifdef RGFW_VULKAN -#ifdef RGFW_PRINT_ERRORS - fprintf(stderr, "RGFW_window_swapBuffers %s\n", "RGFW_window_swapBuffers is not yet supported for Vulkan"); - RGFW_error = 1; -#endif -#endif - } - - if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - #if defined(RGFW_X11) && defined(RGFW_OPENGL) - glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); - #elif defined(RGFW_WINDOWS) - SwapBuffers(win->src.hdc); - #elif defined(RGFW_MACOS) - NSOpenGLContext_flushBuffer(win->src.rSurf); - #endif - #endif - - #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); - #endif - } - - RGFW_window_checkFPS(win); - } - - void RGFW_window_maximize(RGFW_window* win) { - assert(win != NULL); - - RGFW_area screen = RGFW_getScreenSize(); - - RGFW_window_move(win, RGFW_VECTOR(0, 0)); - RGFW_window_resize(win, screen); - } - - u8 RGFW_window_shouldClose(RGFW_window* win) { - assert(win != NULL); - - /* || RGFW_isPressedI(win, RGFW_Escape) */ - return (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_Escape)); - } - - void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; } - - void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { - RGFW_window_move(win, RGFW_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y)); - } - - void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { - if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) { - #ifdef RGFW_WINDOWS - RECT rect = {win->r.x, win->r.y, win->r.x + win->r.w, win->r.y + win->r.h}; - ClipCursor(&rect); - #endif - } - - win->src.winArgs |= RGFW_HOLD_MOUSE; - - if (!area.w && !area.h) - area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - - RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); - } - - void RGFW_window_mouseUnhold(RGFW_window* win) { - win->src.winArgs ^= RGFW_HOLD_MOUSE; - - #ifdef RGFW_WINDOWS - ClipCursor(NULL); - #endif - } - +/* unix sleep */ void RGFW_sleep(u64 ms) { -#ifndef RGFW_WINDOWS struct timespec time; time.tv_sec = 0; time.tv_nsec = ms * 1e+6; nanosleep(&time, NULL); -#else - Sleep(ms); -#endif - } - - void RGFW_window_checkFPS(RGFW_window* win) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; - - u64 fps = round(1e+9 / deltaTime); - win->event.fps = fps; - - if (win->fpsCap && fps > win->fpsCap) { - u64 frameTimeNS = 1e+9 / win->fpsCap; - u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6; - - if (sleepTimeMS > 0) { - RGFW_sleep(sleepTimeMS); - win->event.frameTime = 0; - } - } - - win->event.frameTime = RGFW_getTimeNS(); - - if (win->fpsCap) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - - win->event.fps = round(1e+9 / deltaTime); - - win->event.frameTime2 = RGFW_getTimeNS(); - } - } - -#ifdef __APPLE__ -#include -#endif - - u64 RGFW_getTimeNS(void) { -#ifdef RGFW_WINDOWS - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - - return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart); -#elif defined(__unix__) - 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; -#elif defined(__APPLE__) - 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; -#endif - return 0; - } - - u64 RGFW_getTime(void) { -#ifdef RGFW_WINDOWS - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (u64) (counter.QuadPart / (double) frequency.QuadPart); -#elif defined(__unix__) - 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; -#elif defined(__APPLE__) - 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 - return 0; } +#endif /* end of unix / mac stuff*/ #endif /*RGFW_IMPLEMENTATION*/ #ifdef __cplusplus diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index d8568d929..8fc51d0e1 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -81,7 +81,7 @@ static PlatformData platform = { 0 }; // Platform specific data // Local Variables Definition //---------------------------------------------------------------------------------- #define KEYCODE_MAP_SIZE 162 -static const KeyboardKey KeycodeMap[KEYCODE_MAP_SIZE] = { +static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = { KEY_NULL, // AKEYCODE_UNKNOWN 0, // AKEYCODE_SOFT_LEFT 0, // AKEYCODE_SOFT_RIGHT @@ -660,7 +660,7 @@ void PollInputEvents(void) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; } } - + // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; @@ -1133,9 +1133,9 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_Y] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RZ, 0); CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_TRIGGER] = AMotionEvent_getAxisValue( - event, AMOTION_EVENT_AXIS_BRAKE, 0) * 2.0f - 1.0f; + event, AMOTION_EVENT_AXIS_BRAKE, 0)*2.0f - 1.0f; CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_TRIGGER] = AMotionEvent_getAxisValue( - event, AMOTION_EVENT_AXIS_GAS, 0) * 2.0f - 1.0f; + event, AMOTION_EVENT_AXIS_GAS, 0)*2.0f - 1.0f; // dpad is reported as an axis on android float dpadX = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0); @@ -1201,7 +1201,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) return 1; // Handled gamepad button } - KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE) ? KeycodeMap[keycode] : KEY_NULL; + KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[keycode] : KEY_NULL; if (key != KEY_NULL) { // Save current key and its state @@ -1252,10 +1252,10 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) }; // Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height - float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x) / (float)CORE.Window.display.width; - float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y) / (float)CORE.Window.display.height; - CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x * widthRatio - (float)CORE.Window.renderOffset.x / 2; - CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y * heightRatio - (float)CORE.Window.renderOffset.y / 2; + float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width; + float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height; + CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2; + CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2; } int32_t action = AMotionEvent_getAction(event); diff --git a/src/platforms/rcore_desktop.c b/src/platforms/rcore_desktop_glfw.c similarity index 99% rename from src/platforms/rcore_desktop.c rename to src/platforms/rcore_desktop_glfw.c index bb3fcf4f0..56a4e2619 100644 --- a/src/platforms/rcore_desktop.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1147,7 +1147,7 @@ void PollInputEvents(void) const unsigned char *buttons = state.buttons; - for (int k = 0; (buttons != NULL) && (k < GLFW_GAMEPAD_BUTTON_DPAD_LEFT + 1) && (k < MAX_GAMEPAD_BUTTONS); k++) + for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++) { int button = -1; // GamepadButton enum values assigned @@ -1189,7 +1189,7 @@ void PollInputEvents(void) // Get current axis state const float *axes = state.axes; - for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1) && (k < MAX_GAMEPAD_AXIS); k++) + for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++) { CORE.Input.Gamepad.axisState[i][k] = axes[k]; } @@ -1617,7 +1617,11 @@ int InitPlatform(void) CORE.Storage.basePath = GetWorkingDirectory(); //---------------------------------------------------------------------------- - char* glfwPlatform = ""; +#if defined(__NetBSD__) + // Workaround for NetBSD + char *glfwPlatform = "X11"; +#else + char *glfwPlatform = ""; switch (glfwGetPlatform()) { case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break; @@ -1626,6 +1630,7 @@ int InitPlatform(void) case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break; case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break; } +#endif TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully"); @@ -1664,23 +1669,9 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) if (IsWindowFullscreen()) return; // Set current screen size -#if defined(__APPLE__) + CORE.Window.screen.width = width; CORE.Window.screen.height = height; -#else - if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) - { - Vector2 windowScaleDPI = GetWindowScaleDPI(); - - CORE.Window.screen.width = (unsigned int)(width/windowScaleDPI.x); - CORE.Window.screen.height = (unsigned int)(height/windowScaleDPI.y); - } - else - { - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - } -#endif // NOTE: Postprocessing texture is not scaled to new size } diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index e85f7a0eb..83430f511 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -8,19 +8,17 @@ * - MacOS (Cocoa) * * LIMITATIONS: -* - Limitation 01 -* - Limitation 02 +* - TODO * * POSSIBLE IMPROVEMENTS: -* - Improvement 01 -* - Improvement 02 +* - TODO * * ADDITIONAL NOTES: * - TRACELOG() function is located in raylib [utils] module * * CONFIGURATION: -* #define RCORE_PLATFORM_CUSTOM_FLAG -* Custom flag for rcore on target platform -not used- +* #define RCORE_PLATFORM_RGFW +* Custom flag for rcore on target platform RGFW * * DEPENDENCIES: * - RGFW.h (main library): Windowing and inputs management @@ -49,64 +47,61 @@ **********************************************************************************************/ #ifdef GRAPHICS_API_OPENGL_ES2 -#define RGFW_OPENGL_ES2 + #define RGFW_OPENGL_ES2 #endif void ShowCursor(void); void CloseWindow(void); -#ifdef __linux__ -#define _INPUT_EVENT_CODES_H +#if defined(__linux__) + #define _INPUT_EVENT_CODES_H #endif #if defined(__unix__) || defined(__linux__) -#define _XTYPEDEF_FONT + #define _XTYPEDEF_FONT #endif #define RGFW_IMPLEMENTATION #if defined(__WIN32) || defined(__WIN64) -#define WIN32_LEAN_AND_MEAN -#define Rectangle rectangle_win32 -#define CloseWindow CloseWindow_win32 -#define ShowCursor __imp_ShowCursor -#define _APISETSTRING_ + #define WIN32_LEAN_AND_MEAN + #define Rectangle rectangle_win32 + #define CloseWindow CloseWindow_win32 + #define ShowCursor __imp_ShowCursor + #define _APISETSTRING_ #endif -#ifdef __APPLE__ -#define Point NSPOINT -#define Size NSSIZE +#if defined(__APPLE__) + #define Point NSPOINT + #define Size NSSIZE #endif -#ifdef _MSC_VER -__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar); +#if defined(_MSC_VER) +__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); #endif #include "../external/RGFW.h" - - #if defined(__WIN32) || defined(__WIN64) -#undef DrawText -#undef ShowCursor -#undef CloseWindow -#undef Rectangle + #undef DrawText + #undef ShowCursor + #undef CloseWindow + #undef Rectangle #endif -#ifdef __APPLE__ -#undef Point -#undef Size +#if defined(__APPLE__) + #undef Point + #undef Size #endif #include +#include // Required for: strcmp() //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- typedef struct { - // TODO: Define the platform specific variables required - - RGFW_window* window; // Native display device (physical screen connection) + RGFW_window *window; // Native display device (physical screen connection) } PlatformData; //---------------------------------------------------------------------------------- @@ -114,9 +109,11 @@ typedef struct { //---------------------------------------------------------------------------------- extern CoreData CORE; // Global CORE state context -static PlatformData platform = { NULL }; // Platform specific +static PlatformData platform = { NULL }; // Platform specific -static const unsigned short RGFWKeyToRayKey[] = { +static bool RGFW_disableCursor = false; + +static const unsigned short keyMappingRGFW[] = { [RGFW_KEY_NULL] = KEY_NULL, [RGFW_Quote] = KEY_APOSTROPHE, [RGFW_Comma] = KEY_COMMA, @@ -157,7 +154,7 @@ static const unsigned short RGFWKeyToRayKey[] = { [RGFW_SuperL] = KEY_LEFT_SUPER, #ifndef RGFW_MACOS [RGFW_ShiftR] = KEY_RIGHT_SHIFT, - + [RGFW_AltR] = KEY_RIGHT_ALT, #endif [RGFW_Space] = KEY_SPACE, @@ -237,7 +234,7 @@ bool InitGraphicsDevice(void); // Initialize graphics device // Check if application should close bool WindowShouldClose(void) -{ +{ if (CORE.Window.shouldClose == false) CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window); if (CORE.Window.ready) return CORE.Window.shouldClose; @@ -254,10 +251,10 @@ void ToggleFullscreen(void) // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) { - CORE.Window.flags & FLAG_WINDOW_UNDECORATED; - if (platform.window != NULL) - TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() after window creation not available on target platform"); + { + RGFW_window_setBorder(platform.window, CORE.Window.flags & FLAG_WINDOW_UNDECORATED); + } } // Set window state: maximized, if resizable @@ -294,6 +291,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_RESIZABLE) { + printf("%i %i\n", platform.window->r.w, platform.window->r.h); RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); } @@ -315,7 +313,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_UNFOCUSED) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL"); + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_WINDOW_TOPMOST) { @@ -327,7 +325,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_TRANSPARENT) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW"); + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT post window creation post window creation is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_WINDOW_HIGHDPI) { @@ -335,7 +333,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW"); + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); } if (flags & FLAG_BORDERLESS_WINDOWED_MODE) { @@ -410,7 +408,7 @@ void ClearWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) { - //SDL_SetWindowGrab(platform.window, SDL_TRUE); + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_BORDERLESS_WINDOWED_MODE) @@ -430,33 +428,34 @@ void ClearWindowState(unsigned int flags) // Set icon for window void SetWindowIcon(Image image) { - i32 channels = 4; + i32 channels = 4; - switch (image.format) { + switch (image.format) + { case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float) case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float) + { channels = 1; - break; - + } break; case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: // 8*2 bpp (2 channels) case PIXELFORMAT_UNCOMPRESSED_R5G6B5: // 16 bpp case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // 24 bpp case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: // 16 bpp (1 bit alpha) case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: // 16 bpp (4 bit alpha) case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: // 32 bpp + { channels = 2; - break; - + } break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: // 32*3 bpp (3 channels - float) case PIXELFORMAT_UNCOMPRESSED_R16G16B16: // 16*3 bpp (3 channels - half float) case PIXELFORMAT_COMPRESSED_DXT1_RGB: // 4 bpp (no alpha) case PIXELFORMAT_COMPRESSED_ETC1_RGB: // 4 bpp case PIXELFORMAT_COMPRESSED_ETC2_RGB: // 4 bpp case PIXELFORMAT_COMPRESSED_PVRT_RGB: // 4 bpp + { channels = 3; - break; - + } break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: // 32*4 bpp (4 channels - float) case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: // 16*4 bpp (4 channels - half float) case PIXELFORMAT_COMPRESSED_DXT1_RGBA: // 4 bpp (1 bit alpha) @@ -465,10 +464,10 @@ void SetWindowIcon(Image image) case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: // 8 bpp case PIXELFORMAT_COMPRESSED_PVRT_RGBA: // 4 bpp case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 8 bpp - case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 2 bpp + case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 2 bpp + { channels = 4; - break; - + } break; default: break; } @@ -537,37 +536,42 @@ void SetWindowFocused(void) // Get native window handle void *GetWindowHandle(void) { - #ifndef RGFW_WINDOWS - return (void*)platform.window->src.window; - #else +#ifndef RGFW_WINDOWS + return (void *)platform.window->src.window; +#else return platform.window->src.hwnd; - #endif +#endif } // Get number of monitors int GetMonitorCount(void) { - RGFW_monitor* mons = RGFW_getMonitors(); - size_t i; - for (i = 0; i < 6; i++) { + #define MAX_MONITORS_SUPPORTED 6 + + int count = MAX_MONITORS_SUPPORTED; + RGFW_monitor *mons = RGFW_getMonitors(); + + for (int i = 0; i < 6; i++) + { if (!mons[i].rect.x && !mons[i].rect.y && !mons[i].rect.w && mons[i].rect.h) - return i; + { + count = i; + break; + } } - return 6; + return count; } // Get number of monitors int GetCurrentMonitor(void) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); RGFW_monitor mon = RGFW_window_getMonitor(platform.window); - size_t i; - for (i = 0; i < 6; i++) { - if (mons[i].rect.x == mon.rect.x && - mons[i].rect.y == mon.rect.y) - return i; + for (int i = 0; i < 6; i++) + { + if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) return i; } return 0; @@ -576,26 +580,25 @@ int GetCurrentMonitor(void) // Get selected monitor position Vector2 GetMonitorPosition(int monitor) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); - return (Vector2){mons[monitor].rect.x, mons[monitor].rect.y}; + return (Vector2){mons[monitor].rect.x, mons[monitor].rect.y}; } // Get selected monitor width (currently used by monitor) int GetMonitorWidth(int monitor) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); - return mons[monitor].rect.w; + return mons[monitor].rect.w; } // Get selected monitor height (currently used by monitor) int GetMonitorHeight(int monitor) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); - return mons[monitor].rect.h; - return 0; + return mons[monitor].rect.h; } // Get selected monitor physical width in millimetres @@ -603,15 +606,15 @@ int GetMonitorPhysicalWidth(int monitor) { RGFW_monitor* mons = RGFW_getMonitors(); - return mons[monitor].physW; + return mons[monitor].physW; } // Get selected monitor physical height in millimetres int GetMonitorPhysicalHeight(int monitor) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); - return mons[monitor].physH; + return mons[monitor].physH; } // Get selected monitor refresh rate @@ -624,7 +627,7 @@ int GetMonitorRefreshRate(int monitor) // Get the human-readable, UTF-8 encoded name of the selected monitor const char *GetMonitorName(int monitor) { - RGFW_monitor* mons = RGFW_getMonitors(); + RGFW_monitor *mons = RGFW_getMonitors(); return mons[monitor].name; } @@ -640,7 +643,7 @@ Vector2 GetWindowScaleDPI(void) { RGFW_monitor monitor = RGFW_window_getMonitor(platform.window); - return (Vector2){((u32)monitor.scaleX) * platform.window->r.w, ((u32) monitor.scaleX) * platform.window->r.h}; + return (Vector2){((u32)monitor.scaleX)*platform.window->r.w, ((u32) monitor.scaleX)*platform.window->r.h}; } // Set clipboard text content @@ -670,8 +673,6 @@ void HideCursor(void) CORE.Input.Mouse.cursorHidden = true; } -bool RGFW_disableCursor = false; - // Enables cursor (unlock cursor) void EnableCursor(void) { @@ -688,6 +689,7 @@ void EnableCursor(void) void DisableCursor(void) { RGFW_disableCursor = true; + // Set cursor position in the middle SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); @@ -725,7 +727,7 @@ void OpenURL(const char *url) if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); else { - // TODO: + // TODO: Open URL implementation } } @@ -756,8 +758,60 @@ void SetMouseCursor(int cursor) static KeyboardKey ConvertScancodeToKey(u32 keycode); +// TODO: Review function to avoid duplicate with RSGL +char RSGL_keystrToChar(const char *str) +{ + if (str[1] == 0) return str[0]; + + static const char *map[] = { + "asciitilde", "`", + "grave", "~", + "exclam", "!", + "at", "@", + "numbersign", "#", + "dollar", "$", + "percent", "%%", + "asciicircum", "^", + "ampersand", "&", + "asterisk", "*", + "parenleft", "(", + "parenright", ")", + "underscore", "_", + "minus", "-", + "plus", "+", + "equal", "=", + "braceleft", "{", + "bracketleft", "[", + "bracketright", "]", + "braceright", "}", + "colon", ":", + "semicolon", ";", + "quotedbl", "\"", + "apostrophe", "'", + "bar", "|", + "backslash", "\'", + "less", "<", + "comma", ",", + "greater", ">", + "period", ".", + "question", "?", + "slash", "/", + "space", " ", + "Return", "\n", + "Enter", "\n", + "enter", "\n", + }; + + for (unsigned char i = 0; i < (sizeof(map)/sizeof(char *)); i += 2) + { + if (strcmp(map[i], str) == 0) return *map[i + 1]; + } + + return '\0'; +} + // Register all input events -void PollInputEvents(void) +void PollInputEvents(void) { #if defined(SUPPORT_GESTURES_SYSTEM) // NOTE: Gestures update must be called every frame to reset gestures correctly @@ -774,7 +828,7 @@ void PollInputEvents(void) CORE.Input.Mouse.currentWheelMove.y = 0; // Register previous mouse position - + // Reset last gamepad button/axis registered state for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) @@ -808,30 +862,31 @@ void PollInputEvents(void) } // Register previous mouse states - for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) - CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; + for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; // Poll input events for current platform //----------------------------------------------------------------------------- CORE.Window.resizedLastFrame = false; +#define RGFW_HOLD_MOUSE (1L<<2) - #define RGFW_HOLD_MOUSE (1L<<2) - #if defined(RGFW_X11) //|| defined(RGFW_MACOS) - if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) +#if defined(RGFW_X11) //|| defined(RGFW_MACOS) + if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; } - else { + else + { CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } - #endif +#endif while (RGFW_window_checkEvent(platform.window)) { - if (platform.window->event.type >= RGFW_jsButtonPressed && platform.window->event.type <= RGFW_jsAxisMove) { + if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove)) + { if (!CORE.Input.Gamepad.ready[platform.window->event.joystick]) { CORE.Input.Gamepad.ready[platform.window->event.joystick] = true; @@ -842,17 +897,16 @@ 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 { - size_t i; - for (i = 0; i < event->droppedFilesCount; i++) { + for (int i = 0; i < event->droppedFilesCount; i++) + { if (CORE.Window.dropFileCount == 0) { // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files @@ -862,7 +916,7 @@ void PollInputEvents(void) CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); - + CORE.Window.dropFileCount++; } else if (CORE.Window.dropFileCount < 1024) @@ -896,8 +950,9 @@ void PollInputEvents(void) case RGFW_keyPressed: { KeyboardKey key = ConvertScancodeToKey(event->keyCode); - - if (key != KEY_NULL) { + + if (key != KEY_NULL) + { // If key was up, add it to the key pressed queue if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) { @@ -919,11 +974,10 @@ void PollInputEvents(void) if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) { // Add character (codepoint) to the queue - CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RGFW_keystrToChar(event->keyName); + CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RSGL_keystrToChar(event->keyName); CORE.Input.Keyboard.charPressedQueueCount++; } } break; - case RGFW_keyReleased: { KeyboardKey key = ConvertScancodeToKey(event->keyCode); @@ -933,7 +987,8 @@ void PollInputEvents(void) // Check mouse events case RGFW_mouseButtonPressed: { - if (event->button == RGFW_mouseScrollUp || event->button == RGFW_mouseScrollDown) { + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { CORE.Input.Mouse.currentWheelMove.y = event->scroll; break; } @@ -951,11 +1006,12 @@ void PollInputEvents(void) case RGFW_mouseButtonReleased: { - if (event->button == RGFW_mouseScrollUp || event->button == RGFW_mouseScrollDown) { + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { CORE.Input.Mouse.currentWheelMove.y = event->scroll; break; } - + int btn = event->button; if (btn == RGFW_mouseLeft) btn = 1; else if (btn == RGFW_mouseRight) btn = 2; @@ -968,20 +1024,21 @@ void PollInputEvents(void) } break; case RGFW_mousePosChanged: { - if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) { - + if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) + { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; - - if ((event->point.x - (platform.window->r.w / 2)) * 2) - CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x; - if ((event->point.y - (platform.window->r.h / 2)) * 2) + + if ((event->point.x - (platform.window->r.w/2))*2) + CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x; + if ((event->point.y - (platform.window->r.h/2))*2) CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y; - CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w / 2)) * 2; - CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h / 2)) * 2; + CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w/2))*2; + CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h/2))*2; } - else { - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + else + { + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; CORE.Input.Mouse.currentPosition.x = (float)event->point.x; CORE.Input.Mouse.currentPosition.y = (float)event->point.y; } @@ -989,7 +1046,6 @@ void PollInputEvents(void) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; touchAction = 2; } break; - case RGFW_jsButtonPressed: { int button = -1; @@ -1061,43 +1117,49 @@ void PollInputEvents(void) case RGFW_jsAxisMove: { int axis = -1; - - size_t i; - for (i = 0; i < event->axisesCount; i++) + for (int i = 0; i < event->axisesCount; i++) { - switch(i) { - case 0: - if (abs(event->axis[i].x) > abs(event->axis[i].y)) { - axis = GAMEPAD_AXIS_LEFT_X; + switch(i) + { + case 0: + { + if (abs(event->axis[i].x) > abs(event->axis[i].y)) + { + axis = GAMEPAD_AXIS_LEFT_X; break; } - + axis = GAMEPAD_AXIS_LEFT_Y; - break; - case 1: - if (abs(event->axis[i].x) > abs(event->axis[i].y)) { - axis = GAMEPAD_AXIS_RIGHT_X; break; + } break; + case 1: + { + if (abs(event->axis[i].x) > abs(event->axis[i].y)) + { + axis = GAMEPAD_AXIS_RIGHT_X; + break; } - axis = GAMEPAD_AXIS_RIGHT_Y; break; + axis = GAMEPAD_AXIS_RIGHT_Y; + } break; case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break; case 3: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break; default: break; } #ifdef __linux__ - float value = (event->axis[i].x + event->axis[i].y) / (float) 32767; + float value = (event->axis[i].x + event->axis[i].y)/(float)32767; #else - float value = (event->axis[i].x + -event->axis[i].y) / (float) 32767; + float value = (event->axis[i].x + -event->axis[i].y)/(float)32767; #endif CORE.Input.Gamepad.axisState[event->joystick][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 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->joystick][button] = pressed; + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } @@ -1137,9 +1199,7 @@ void PollInputEvents(void) #endif } - if (RGFW_disableCursor && platform.window->event.inFocus) - RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); - + if (RGFW_disableCursor && platform.window->event.inFocus) RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); //----------------------------------------------------------------------------- } @@ -1151,15 +1211,7 @@ void PollInputEvents(void) // Initialize platform: graphics, inputs and more int InitPlatform(void) { - // TODO: Initialize graphic device: display/window - // It usually requires setting up the platform display system configuration - // and connexion with the GPU through some system graphic API - // raylib uses OpenGL so, platform should create that kind of connection - // Below example illustrates that process using EGL library - //---------------------------------------------------------------------------- // Initialize RGFW internal global state, only required systems - // Initialize graphic device: display/window and graphic context - //---------------------------------------------------------------------------- unsigned int flags = RGFW_CENTER | RGFW_ALLOW_DND; // Check window creation flags @@ -1199,16 +1251,15 @@ int InitPlatform(void) platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); - if (CORE.Window.flags & FLAG_VSYNC_HINT) - RGFW_window_swapInterval(platform.window, 1); - + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); + RGFW_window_makeCurrent(platform.window); // Check surface and context activation if (platform.window != NULL) { CORE.Window.ready = true; - + CORE.Window.render.width = CORE.Window.screen.width; CORE.Window.render.height = CORE.Window.screen.height; CORE.Window.currentFbo.width = CORE.Window.render.width; @@ -1241,7 +1292,7 @@ int InitPlatform(void) TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); - // TODO: Load OpenGL extensions + // Load OpenGL extensions // NOTE: GL procedures address loader is required to load extensions //---------------------------------------------------------------------------- rlLoadExtensions((void*)RGFW_getProcAddress); @@ -1255,22 +1306,22 @@ int InitPlatform(void) // ... //---------------------------------------------------------------------------- - // TODO: Initialize timing system + // Initialize timing system //---------------------------------------------------------------------------- InitTimer(); //---------------------------------------------------------------------------- - // TODO: Initialize storage system + // Initialize storage system //---------------------------------------------------------------------------- CORE.Storage.basePath = GetWorkingDirectory(); //---------------------------------------------------------------------------- - #ifdef RGFW_X11 +#ifdef RGFW_X11 for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) { RGFW_registerJoystick(platform.window, i); } - #endif +#endif TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully"); @@ -1281,14 +1332,12 @@ int InitPlatform(void) void ClosePlatform(void) { RGFW_window_close(platform.window); - // TODO: De-initialize graphics, inputs and more } +// Keycode mapping +static KeyboardKey ConvertScancodeToKey(u32 keycode) +{ + if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0; -static KeyboardKey ConvertScancodeToKey(u32 keycode) { - if (keycode > sizeof(RGFWKeyToRayKey) / sizeof(unsigned short)) - return 0; - - return RGFWKeyToRayKey[keycode]; + return keyMappingRGFW[keycode]; } -// EOF \ No newline at end of file diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index c22150efb..3d6293597 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -64,7 +64,7 @@ typedef struct { SDL_Window *window; SDL_GLContext glContext; - SDL_Joystick *gamepad[MAX_GAMEPADS]; + SDL_GameController *gamepad[MAX_GAMEPADS]; SDL_Cursor *cursor; bool cursorRelative; } PlatformData; @@ -80,7 +80,7 @@ static PlatformData platform = { 0 }; // Platform specific data // Local Variables Definition //---------------------------------------------------------------------------------- #define SCANCODE_MAPPED_NUM 232 -static const KeyboardKey ScancodeToKey[SCANCODE_MAPPED_NUM] = { +static const KeyboardKey mapScancodeToKey[SCANCODE_MAPPED_NUM] = { KEY_NULL, // SDL_SCANCODE_UNKNOWN 0, 0, @@ -476,9 +476,9 @@ void ClearWindowState(unsigned int flags) // Set icon for window void SetWindowIcon(Image image) { - SDL_Surface* iconSurface = NULL; + SDL_Surface *iconSurface = NULL; - Uint32 rmask, gmask, bmask, amask; + unsigned int rmask = 0, gmask = 0, bmask = 0, amask = 0; int depth = 0; // Depth in bits int pitch = 0; // Pixel spacing (pitch) in bytes @@ -492,72 +492,67 @@ void SetWindowIcon(Image image) case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: rmask = 0xFF, gmask = 0xFF00; bmask = 0, amask = 0; - depth = 16, pitch = image.width * 2; + depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R5G6B5: rmask = 0xF800, gmask = 0x07E0; bmask = 0x001F, amask = 0; - depth = 16, pitch = image.width * 2; + depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit rmask = 0x0000FF, gmask = 0x00FF00; bmask = 0xFF0000, amask = 0; - depth = 24, pitch = image.width * 3; + depth = 24, pitch = image.width*3; break; case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: rmask = 0xF800, gmask = 0x07C0; bmask = 0x003E, amask = 0x0001; - depth = 16, pitch = image.width * 2; + depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: rmask = 0xF000, gmask = 0x0F00; bmask = 0x00F0, amask = 0x000F; - depth = 16, pitch = image.width * 2; + depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: rmask = 0xFF000000, gmask = 0x00FF0000; bmask = 0x0000FF00, amask = 0x000000FF; - depth = 32, pitch = image.width * 4; + depth = 32, pitch = image.width*4; break; case PIXELFORMAT_UNCOMPRESSED_R32: rmask = 0xFFFFFFFF, gmask = 0; bmask = 0, amask = 0; - depth = 32, pitch = image.width * 4; + depth = 32, pitch = image.width*4; break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; bmask = 0xFFFFFFFF, amask = 0; - depth = 96, pitch = image.width * 12; + depth = 96, pitch = image.width*12; break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF; - depth = 128, pitch = image.width * 16; + depth = 128, pitch = image.width*16; break; case PIXELFORMAT_UNCOMPRESSED_R16: rmask = 0xFFFF, gmask = 0; bmask = 0, amask = 0; - depth = 16, pitch = image.width * 2; + depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16: rmask = 0xFFFF, gmask = 0xFFFF; bmask = 0xFFFF, amask = 0; - depth = 48, pitch = image.width * 6; + depth = 48, pitch = image.width*6; break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: rmask = 0xFFFF, gmask = 0xFFFF; bmask = 0xFFFF, amask = 0xFFFF; - depth = 64, pitch = image.width * 8; + depth = 64, pitch = image.width*8; break; - default: - // Compressed formats are not supported - return; + default: return; // Compressed formats are not supported } - iconSurface = SDL_CreateRGBSurfaceFrom( - image.data, image.width, image.height, depth, pitch, - rmask, gmask, bmask, amask - ); + iconSurface = SDL_CreateRGBSurfaceFrom( image.data, image.width, image.height, depth, pitch, rmask, gmask, bmask, amask ); if (iconSurface) { @@ -599,7 +594,7 @@ void SetWindowMonitor(int monitor) // 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3, // see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba // 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again. - const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false; + const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)? true : false; const int screenWidth = CORE.Window.screen.width; const int screenHeight = CORE.Window.screen.height; @@ -941,15 +936,15 @@ int SetGamepadMappings(const char *mappings) // Set gamepad vibration void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) { - //Limit input values to between 0.0f and 1.0f - leftMotor = (0.0f > leftMotor) ? 0.0f : leftMotor; - rightMotor = (0.0f > rightMotor) ? 0.0f : rightMotor; - leftMotor = (1.0f < leftMotor) ? 1.0f : leftMotor; - rightMotor = (1.0f < rightMotor) ? 1.0f : rightMotor; + // Limit input values to between 0.0f and 1.0f + leftMotor = (0.0f > leftMotor)? 0.0f : leftMotor; + rightMotor = (0.0f > rightMotor)? 0.0f : rightMotor; + leftMotor = (1.0f < leftMotor)? 1.0f : leftMotor; + rightMotor = (1.0f < rightMotor)? 1.0f : rightMotor; if (IsGamepadAvailable(gamepad)) { - SDL_JoystickRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); + SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); } } @@ -1132,7 +1127,8 @@ void PollInputEvents(void) { KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); - if (key != KEY_NULL) { + if (key != KEY_NULL) + { // If key was up, add it to the key pressed queue if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) { @@ -1249,15 +1245,15 @@ void PollInputEvents(void) if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) { - platform.gamepad[jid] = SDL_JoystickOpen(jid); + platform.gamepad[jid] = SDL_GameControllerOpen(jid); if (platform.gamepad[jid]) { CORE.Input.Gamepad.ready[jid] = true; - CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]); + 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_JoystickName(platform.gamepad[jid]), 63); + strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63); CORE.Input.Gamepad.name[jid][63] = '\0'; } else @@ -1270,15 +1266,15 @@ void PollInputEvents(void) { int jid = event.jdevice.which; - if (jid == SDL_JoystickInstanceID(platform.gamepad[jid])) + if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]))) { - SDL_JoystickClose(platform.gamepad[jid]); - platform.gamepad[jid] = SDL_JoystickOpen(0); + 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); } } break; - case SDL_JOYBUTTONDOWN: + case SDL_CONTROLLERBUTTONDOWN: { int button = -1; @@ -1312,7 +1308,7 @@ void PollInputEvents(void) CORE.Input.Gamepad.lastButtonPressed = button; } } break; - case SDL_JOYBUTTONUP: + case SDL_CONTROLLERBUTTONUP: { int button = -1; @@ -1346,7 +1342,7 @@ void PollInputEvents(void) if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } } break; - case SDL_JOYAXISMOTION: + case SDL_CONTROLLERAXISMOTION: { int axis = -1; @@ -1364,13 +1360,13 @@ 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; + 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)) { - int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; + 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; @@ -1552,14 +1548,15 @@ int InitPlatform(void) // Initialize gamepads for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++) { - platform.gamepad[i] = SDL_JoystickOpen(i); + platform.gamepad[i] = SDL_GameControllerOpen(i); + if (platform.gamepad[i]) { CORE.Input.Gamepad.ready[i] = true; - CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(platform.gamepad[i]); + 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_JoystickName(platform.gamepad[i]), 63); + strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63); CORE.Input.Gamepad.name[i][63] = '\0'; } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); @@ -1579,13 +1576,15 @@ int InitPlatform(void) CORE.Time.previous = GetTime(); // Get time as double #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) - SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod() + SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod() #endif //---------------------------------------------------------------------------- // Initialize storage system //---------------------------------------------------------------------------- - CORE.Storage.basePath = GetWorkingDirectory(); // Define base path for storage + // Define base path for storage + CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); + CHDIR(CORE.Storage.basePath); //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); @@ -1607,8 +1606,9 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode) { if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM) { - return ScancodeToKey[sdlScancode]; + return mapScancodeToKey[sdlScancode]; } + return KEY_NULL; // No equivalent key in Raylib } // EOF diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index ba6071460..f888d0e47 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -398,7 +398,7 @@ int GetMonitorWidth(int monitor) { width = platform.connector->modes[platform.modeIndex].hdisplay; } - + return width; } @@ -415,7 +415,7 @@ int GetMonitorHeight(int monitor) { height = platform.connector->modes[platform.modeIndex].vdisplay; } - + return height; } @@ -479,7 +479,7 @@ const char *GetMonitorName(int monitor) { name = platform.connector->modes[platform.modeIndex].name; } - + return name; } @@ -1028,7 +1028,7 @@ int InitPlatform(void) // If graphic device is no properly initialized, we end program if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; } - else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2); + else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2); // Set some default window flags CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false @@ -1136,7 +1136,8 @@ void ClosePlatform(void) // Close the evdev devices - if (platform.mouseFd != -1) { + if (platform.mouseFd != -1) + { close(platform.mouseFd); platform.mouseFd = -1; } @@ -1613,7 +1614,7 @@ static void PollKeyboardEvents(void) } } - TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0) ? "UP " : "DOWN", event.code, keycode); + TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0)? "UP " : "DOWN", event.code, keycode); } } } @@ -1640,7 +1641,7 @@ static void PollGamepadEvents(void) { short keycodeRaylib = linuxToRaylibMap[event.code]; - TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0) ? "UP " : "DOWN", event.code, keycodeRaylib); + TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0)? "UP" : "DOWN", event.code, keycodeRaylib); if ((keycodeRaylib != 0) && (keycodeRaylib < MAX_GAMEPAD_BUTTONS)) { @@ -1665,7 +1666,7 @@ static void PollGamepadEvents(void) int range = platform.gamepadAbsAxisRange[i][event.code][1]; // NOTE: Scaling of event.value to get values between -1..1 - CORE.Input.Gamepad.axisState[i][axisRaylib] = (2 * (float)(event.value - min) / range) - 1; + CORE.Input.Gamepad.axisState[i][axisRaylib] = (2*(float)(event.value - min)/range) - 1; } } } @@ -1924,9 +1925,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt const int nearestHeightDiff = abs(platform.connector->modes[nearestIndex].vdisplay - height); const int nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps); - if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) { - nearestIndex = i; - } + if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i; } return nearestIndex; diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index afe8adfb1..47b8d42d6 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -190,7 +190,8 @@ void ToggleFullscreen(void) if (enterFullscreen) { // NOTE: The setTimeouts handle the browser mode change delay - EM_ASM( + EM_ASM + ( setTimeout(function() { Module.requestFullscreen(false, false); @@ -298,7 +299,8 @@ void ToggleBorderlessWindowed(void) { // NOTE: 1. The setTimeouts handle the browser mode change delay // 2. The style unset handles the possibility of a width="value%" like on the default shell.html file - EM_ASM( + EM_ASM + ( setTimeout(function() { Module.requestFullscreen(false, true); diff --git a/src/raudio.c b/src/raudio.c index 623984e1d..21d1adae3 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1464,7 +1464,7 @@ Music LoadMusicStream(const char *fileName) jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song musicLoaded = true; } - else + else { jar_xm_free_context(ctxXm); } @@ -1550,7 +1550,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0)) { // Open ogg audio stream - stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char*)data, dataSize, NULL, NULL); + stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL); if (ctxOgg != NULL) { @@ -1566,7 +1566,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, music.looping = true; // Looping enabled by default musicLoaded = true; } - else + else { stb_vorbis_close(ctxOgg); } diff --git a/src/raylib.dll.rc b/src/raylib.dll.rc index ba2f5bbf4..b0c2f58f8 100644 --- a/src/raylib.dll.rc +++ b/src/raylib.dll.rc @@ -1,8 +1,8 @@ GLFW_ICON ICON "raylib.ico" 1 VERSIONINFO -FILEVERSION 5,0,0,0 -PRODUCTVERSION 5,0,0,0 +FILEVERSION 5,5,0,0 +PRODUCTVERSION 5,5,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,12 +11,12 @@ BEGIN BEGIN //VALUE "CompanyName", "raylib technologies" VALUE "FileDescription", "raylib dynamic library (www.raylib.com)" - VALUE "FileVersion", "5.0.0" + VALUE "FileVersion", "5.5.0" VALUE "InternalName", "raylib.dll" - VALUE "LegalCopyright", "(c) 2023 Ramon Santamaria (@raysan5)" + VALUE "LegalCopyright", "(c) 2024 Ramon Santamaria (@raysan5)" VALUE "OriginalFilename", "raylib.dll" VALUE "ProductName", "raylib" - VALUE "ProductVersion", "5.0.0" + VALUE "ProductVersion", "5.5.0" END END BLOCK "VarFileInfo" diff --git a/src/raylib.dll.rc.data b/src/raylib.dll.rc.data index e93edcffb..3c87c5ca3 100644 Binary files a/src/raylib.dll.rc.data and b/src/raylib.dll.rc.data differ diff --git a/src/raylib.h b/src/raylib.h index c3c546c36..60ec3c23e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v5.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib @@ -82,9 +82,9 @@ #include // Required for: va_list - Only used by TraceLogCallback #define RAYLIB_VERSION_MAJOR 5 -#define RAYLIB_VERSION_MINOR 1 +#define RAYLIB_VERSION_MINOR 5 #define RAYLIB_VERSION_PATCH 0 -#define RAYLIB_VERSION "5.1-dev" +#define RAYLIB_VERSION "5.5" // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll @@ -421,7 +421,7 @@ typedef struct ModelAnimation { // Ray, ray for raycasting typedef struct Ray { Vector3 position; // Ray position (origin) - Vector3 direction; // Ray direction + Vector3 direction; // Ray direction (normalized) } Ray; // RayCollision, ray hit information @@ -1332,6 +1332,7 @@ RLAPI Image GenImageText(int width, int height, const char *text); // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece +RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format @@ -1545,7 +1546,7 @@ RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, floa RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation diff --git a/src/raylib.rc b/src/raylib.rc index 12f35aaed..5076b4a26 100644 --- a/src/raylib.rc +++ b/src/raylib.rc @@ -1,8 +1,8 @@ GLFW_ICON ICON "raylib.ico" 1 VERSIONINFO -FILEVERSION 5,0,0,0 -PRODUCTVERSION 5,0,0,0 +FILEVERSION 5,5,0,0 +PRODUCTVERSION 5,5,0,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -11,12 +11,12 @@ BEGIN BEGIN //VALUE "CompanyName", "raylib technologies" VALUE "FileDescription", "raylib application (www.raylib.com)" - VALUE "FileVersion", "5.0.0" + VALUE "FileVersion", "5.5.0" VALUE "InternalName", "raylib app" - VALUE "LegalCopyright", "(c) 2023 Ramon Santamaria (@raysan5)" - //VALUE "OriginalFilename", "raylib_app.exe" + VALUE "LegalCopyright", "(c) 2024 Ramon Santamaria (@raysan5)" + //VALUE "OriginalFilename", "raylib_app" VALUE "ProductName", "raylib app" - VALUE "ProductVersion", "5.0.0" + VALUE "ProductVersion", "5.5.0" END END BLOCK "VarFileInfo" diff --git a/src/raylib.rc.data b/src/raylib.rc.data index 1476a1cba..5a9aa4ea0 100644 Binary files a/src/raylib.rc.data and b/src/raylib.rc.data differ diff --git a/src/raymath.h b/src/raymath.h index 63947ee8d..62d52f8fd 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -175,7 +175,7 @@ typedef struct float16 { // Clamp float value RMAPI float Clamp(float value, float min, float max) { - float result = (value < min) ? min : value; + float result = (value < min)? min : value; if (result > max) result = max; @@ -962,12 +962,12 @@ RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vect { Vector3 result = { 0 }; - float amountPow2 = amount * amount; - float amountPow3 = amount * amount * amount; + float amountPow2 = amount*amount; + float amountPow3 = amount*amount*amount; - result.x = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.x + (amountPow3 - 2 * amountPow2 + amount) * tangent1.x + (-2 * amountPow3 + 3 * amountPow2) * v2.x + (amountPow3 - amountPow2) * tangent2.x; - result.y = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.y + (amountPow3 - 2 * amountPow2 + amount) * tangent1.y + (-2 * amountPow3 + 3 * amountPow2) * v2.y + (amountPow3 - amountPow2) * tangent2.y; - result.z = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.z + (amountPow3 - 2 * amountPow2 + amount) * tangent1.z + (-2 * amountPow3 + 3 * amountPow2) * v2.z + (amountPow3 - amountPow2) * tangent2.z; + result.x = (2*amountPow3 - 3*amountPow2 + 1)*v1.x + (amountPow3 - 2*amountPow2 + amount)*tangent1.x + (-2*amountPow3 + 3*amountPow2)*v2.x + (amountPow3 - amountPow2)*tangent2.x; + result.y = (2*amountPow3 - 3*amountPow2 + 1)*v1.y + (amountPow3 - 2*amountPow2 + amount)*tangent1.y + (-2*amountPow3 + 3*amountPow2)*v2.y + (amountPow3 - amountPow2)*tangent2.y; + result.z = (2*amountPow3 - 3*amountPow2 + 1)*v1.z + (amountPow3 - 2*amountPow2 + amount)*tangent1.z + (-2*amountPow3 + 3*amountPow2)*v2.z + (amountPow3 - amountPow2)*tangent2.z; return result; } @@ -2218,12 +2218,12 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) // as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t) { - float t2 = t * t; - float t3 = t2 * t; - float h00 = 2 * t3 - 3 * t2 + 1; - float h10 = t3 - 2 * t2 + t; - float h01 = -2 * t3 + 3 * t2; - float h11 = t3 - t2; + float t2 = t*t; + float t3 = t2*t; + float h00 = 2*t3 - 3*t2 + 1; + float h10 = t3 - 2*t2 + t; + float h01 = -2*t3 + 3*t2; + float h11 = t3 - t2; Quaternion p0 = QuaternionScale(q1, h00); Quaternion m0 = QuaternionScale(outTangent1, h10); @@ -2533,7 +2533,7 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio translation->y = mat.m13; translation->z = mat.m14; - // Extract upper-left for determinant computation. + // Extract upper-left for determinant computation const float a = mat.m0; const float b = mat.m4; const float c = mat.m8; @@ -2543,28 +2543,33 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio const float g = mat.m2; const float h = mat.m6; const float i = mat.m10; - const float A = e * i - f * h; - const float B = f * g - d * i; - const float C = d * h - e * g; + const float A = e*i - f*h; + const float B = f*g - d*i; + const float C = d*h - e*g; - // Extract scale. - const float det = a * A + b * B + c * C; - float scalex = Vector3Length((Vector3) {a, b, c}); - float scaley = Vector3Length((Vector3) {d, e, f}); - float scalez = Vector3Length((Vector3) {g, h, i}); - Vector3 s = {scalex, scaley, scalez}; + // Extract scale + const float det = a*A + b*B + c*C; + Vector3 abc = { a, b, c }; + Vector3 def = { d, e, f }; + Vector3 ghi = { g, h, i }; + + float scalex = Vector3Length(abc); + float scaley = Vector3Length(def); + float scalez = Vector3Length(ghi); + Vector3 s = { scalex, scaley, scalez }; if (det < 0) s = Vector3Negate(s); *scale = s; - // Remove scale from the matrix if it is not close to zero. + // Remove scale from the matrix if it is not close to zero Matrix clone = mat; if (!FloatEquals(det, 0)) { clone.m0 /= s.x; clone.m5 /= s.y; clone.m10 /= s.z; + // Extract rotation *rotation = QuaternionFromMatrix(clone); } diff --git a/src/rcamera.h b/src/rcamera.h index 9c19556c4..d3042d306 100644 --- a/src/rcamera.h +++ b/src/rcamera.h @@ -490,8 +490,8 @@ void UpdateCamera(Camera *camera, int mode) if (IsGamepadAvailable(0)) { // Gamepad controller support - CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); - CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); + CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); + CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); diff --git a/src/rcore.c b/src/rcore.c index 2c9af11d5..e68a9a7d5 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3,7 +3,7 @@ * rcore - Window/display management, Graphic device/context management and input management * * PLATFORMS SUPPORTED: -* > PLATFORM_DESKTOP (GLFW backend): +* > PLATFORM_DESKTOP_GLFW (GLFW backend): * - Windows (Win32, Win64) * - Linux (X11/Wayland desktop mode) * - macOS/OSX (x64, arm64) @@ -493,9 +493,13 @@ void __stdcall Sleep(unsigned long msTimeout); // Required for: Wai const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' #endif // !SUPPORT_MODULE_RTEXT -// Include platform-specific submodules #if defined(PLATFORM_DESKTOP) - #include "platforms/rcore_desktop.c" + #define PLATFORM_DESKTOP_GLFW +#endif + +// Include platform-specific submodules +#if defined(PLATFORM_DESKTOP_GLFW) + #include "platforms/rcore_desktop_glfw.c" #elif defined(PLATFORM_DESKTOP_SDL) #include "platforms/rcore_desktop_sdl.c" #elif defined(PLATFORM_DESKTOP_RGFW) @@ -564,10 +568,12 @@ void InitWindow(int width, int height, const char *title) { TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP_GLFW) TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)"); #elif defined(PLATFORM_DESKTOP_SDL) TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)"); +#elif defined(PLATFORM_DESKTOP_RGFW) + TRACELOG(LOG_INFO, "Platform backend: DESKTOP (RGFW)"); #elif defined(PLATFORM_WEB) TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)"); #elif defined(PLATFORM_DRM) diff --git a/src/rlgl.h b/src/rlgl.h index 98d43ea57..5b921ab9c 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -844,9 +844,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define GL_GLEXT_PROTOTYPES #include // OpenGL ES 2.0 extensions library #elif defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP, + // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms, // in that case, functions are loaded from a custom glad for OpenGL ES 2.0 - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) #define GLAD_GLES2_IMPLEMENTATION #include "external/glad_gles2.h" #else @@ -1560,7 +1560,7 @@ void rlNormal3f(float x, float y, float z) float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); if (length != 0.0f) { - float ilength = 1.0f / length; + float ilength = 1.0f/length; normalx *= ilength; normaly *= ilength; normalz *= ilength; @@ -2390,7 +2390,7 @@ void rlLoadExtensions(void *loader) #elif defined(GRAPHICS_API_OPENGL_ES2) - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) // TODO: Support GLAD loader for OpenGL ES 3.0 if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully"); diff --git a/src/rmodels.c b/src/rmodels.c index cc6ac823c..c1d56765e 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -424,11 +424,16 @@ void DrawSphere(Vector3 centerPos, float radius, Color color) // Draw sphere with extended parameters void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color) { +#if 0 + // Basic implementation, do not use it! + // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls! + // New optimized version below only requires 4 cos()/sin() calls + rlPushMatrix(); // NOTE: Transformation is applied in inverse order (scale -> translate) rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); - + rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -459,6 +464,51 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color } rlEnd(); rlPopMatrix(); +#endif + + rlPushMatrix(); + // NOTE: Transformation is applied in inverse order (scale -> translate) + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlScalef(radius, radius, radius); + + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + + float ringangle = DEG2RAD*(180.0f/(rings + 1)); // Angle between latitudinal parallels + float sliceangle = DEG2RAD*(360.0f/slices); // Angle between longitudinal meridians + + float cosring = cosf(ringangle); + float sinring = sinf(ringangle); + float cosslice = cosf(sliceangle); + float sinslice = sinf(sliceangle); + + Vector3 vertices[4] = { 0 }; // Required to store face vertices + vertices[2] = (Vector3){ 0, 1, 0 }; + vertices[3] = (Vector3){ sinring, cosring, 0 }; + + for (int i = 0; i < rings + 1; i++) + { + for (int j = 0; j < slices; j++) + { + vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face + vertices[1] = vertices[3]; + vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis + vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z }; + + rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z); + rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z); + rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z); + + rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z); + rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z); + rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z); + } + + vertices[2] = vertices[3]; // Rotate around z axis to set up starting vertices for next ring + vertices[3] = (Vector3){ cosring*vertices[3].x + sinring*vertices[3].y, -sinring*vertices[3].x + cosring*vertices[3].y, vertices[3].z }; // Rotation matrix around z axis + } + rlEnd(); + rlPopMatrix(); } // Draw sphere wires @@ -1022,16 +1072,10 @@ void DrawGrid(int slices, float spacing) if (i == 0) { rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); } else { rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); } rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); @@ -3588,11 +3632,11 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float } // Draw a billboard -void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint) +void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) { Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height }; - DrawBillboardRec(camera, texture, source, position, (Vector2){ size, size }, tint); + DrawBillboardRec(camera, texture, source, position, (Vector2) { scale*fabsf((float)source.width/source.height), scale }, tint); } // Draw a billboard (part of a texture defined by a rectangle) @@ -3601,116 +3645,82 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector // NOTE: Billboard locked on axis-Y Vector3 up = { 0.0f, 1.0f, 0.0f }; - DrawBillboardPro(camera, texture, source, position, up, size, Vector2Zero(), 0.0f, tint); + DrawBillboardPro(camera, texture, source, position, up, size, Vector2Scale(size, 0.5), 0.0f, tint); } // Draw a billboard with additional parameters -// NOTE: Size defines the destination rectangle size, stretching the source texture as required void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint) { - // NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width - Vector2 sizeRatio = { size.x*fabsf((float)source.width/source.height), size.y }; - + // Compute the up vector and the right vector Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - Vector3 right = { matView.m0, matView.m4, matView.m8 }; - //Vector3 up = { matView.m1, matView.m5, matView.m9 }; + right = Vector3Scale(right, size.x); + up = Vector3Scale(up, size.y); - Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2); - Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2); - - Vector3 p1 = Vector3Add(rightScaled, upScaled); - Vector3 p2 = Vector3Subtract(rightScaled, upScaled); - - Vector3 topLeft = Vector3Scale(p2, -1); - Vector3 topRight = p1; - Vector3 bottomRight = p2; - Vector3 bottomLeft = Vector3Scale(p1, -1); - - if (rotation != 0.0f) + // Flip the content of the billboard while maintaining the counterclockwise edge rendering order + if (size.x < 0.0f) { - float sinRotation = sinf(rotation*DEG2RAD); - float cosRotation = cosf(rotation*DEG2RAD); - - // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture - float rotateAboutX = sizeRatio.x*origin.x/2; - float rotateAboutY = sizeRatio.y*origin.y/2; - - float xtvalue, ytvalue; - float rotatedX, rotatedY; - - xtvalue = Vector3DotProduct(right, topLeft) - rotateAboutX; // Project points to x and y coordinates on the billboard plane - ytvalue = Vector3DotProduct(up, topLeft) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; // Rotate about the point origin - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - topLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); // Translate back to cartesian coordinates - - xtvalue = Vector3DotProduct(right, topRight) - rotateAboutX; - ytvalue = Vector3DotProduct(up, topRight) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - topRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); - - xtvalue = Vector3DotProduct(right, bottomRight) - rotateAboutX; - ytvalue = Vector3DotProduct(up, bottomRight) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - bottomRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); - - xtvalue = Vector3DotProduct(right, bottomLeft)-rotateAboutX; - ytvalue = Vector3DotProduct(up, bottomLeft)-rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - bottomLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); + source.x += size.x; + source.width *= -1.0; + right = Vector3Negate(right); + origin.x *= -1.0f; + } + if (size.y < 0.0f) + { + source.y += size.y; + source.height *= -1.0; + up = Vector3Negate(up); + origin.y *= -1.0f; } - // Translate points to the draw center (position) - topLeft = Vector3Add(topLeft, position); - topRight = Vector3Add(topRight, position); - bottomRight = Vector3Add(bottomRight, position); - bottomLeft = Vector3Add(bottomLeft, position); + // Draw the texture region described by source on the following rectangle in 3D space: + // + // size.x <--. + // 3 ^---------------------------+ 2 \ rotation + // | | / + // | | + // | origin.x position | + // up |.............. | size.y + // | . | + // | . origin.y | + // | . | + // 0 +---------------------------> 1 + // right + Vector3 forward; + if (rotation != 0.0) forward = Vector3CrossProduct(right, up); + + Vector3 origin3D = Vector3Add(Vector3Scale(Vector3Normalize(right), origin.x), Vector3Scale(Vector3Normalize(up), origin.y)); + + Vector3 points[4]; + points[0] = Vector3Zero(); + points[1] = right; + points[2] = Vector3Add(up, right); + points[3] = up; + + for (int i = 0; i < 4; i++) + { + points[i] = Vector3Subtract(points[i], origin3D); + if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD); + points[i] = Vector3Add(points[i], position); + } + + 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 }; rlSetTexture(texture.id); - rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); - - if (sizeRatio.x*sizeRatio.y >= 0.0f) + for (int i = 0; i < 4; i++) { - // Bottom-left corner for texture and quad - rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); - rlVertex3f(topLeft.x, topLeft.y, topLeft.z); - - // Top-left corner for texture and quad - rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - - // Top-right corner for texture and quad - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - - // Bottom-right corner for texture and quad - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); - rlVertex3f(topRight.x, topRight.y, topRight.z); - } - else - { - // Reverse vertex order if the size has only one negative dimension - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); - rlVertex3f(topRight.x, topRight.y, topRight.z); - - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - - rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - - rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); - rlVertex3f(topLeft.x, topLeft.y, topLeft.z); + rlTexCoord2f(texcoords[i].x, texcoords[i].y); + rlVertex3f(points[i].x, points[i].y, points[i].z); } rlEnd(); - rlSetTexture(0); } @@ -4278,7 +4288,7 @@ static Model LoadIQM(const char *fileName) // In case file can not be read, return an empty model if (fileDataPtr == NULL) return model; - const char* basePath = GetDirectoryPath(fileName); + const char *basePath = GetDirectoryPath(fileName); // Read IQM header IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr; @@ -4327,7 +4337,7 @@ static Model LoadIQM(const char *fileName) model.materials[i].maps[MATERIAL_MAP_ALBEDO].texture = LoadTexture(TextFormat("%s/%s", basePath, material)); model.meshMaterial[i] = i; - + TRACELOG(LOG_DEBUG, "MODEL: [%s] mesh name (%s), material (%s)", fileName, name, material); model.meshes[i].vertexCount = imesh[i].num_vertexes; @@ -4636,7 +4646,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou animations[a].boneCount = iqmHeader->num_poses; animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo)); animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *)); - memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here + memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here TraceLog(LOG_INFO, "IQM Anim %s", animations[a].name); // animations[a].framerate = anim.framerate; // TODO: Use animation framerate data? @@ -4913,7 +4923,7 @@ static Model LoadGLTF(const char *fileName) PBR specular/glossiness flow and extended texture flows not supported - Supports multiple meshes per model (every primitives is loaded as a separate mesh) - Supports basic animations - - Transforms, including parent-child relations, are applied on the mesh data, but the + - Transforms, including parent-child relations, are applied on the mesh data, but the hierarchy is not kept (as it can't be represented). - Mesh instances in the glTF file (i.e. same mesh linked from multiple nodes) are turned into separate raylib Meshes. @@ -5101,7 +5111,7 @@ static Model LoadGLTF(const char *fileName) // Each primitive within a glTF node becomes a Raylib Mesh. // The local-to-world transform of each node is used to transform the // points/normals/tangents of the created Mesh(es). - // Any glTF mesh linked from more than one Node (i.e. instancing) + // Any glTF mesh linked from more than one Node (i.e. instancing) // is turned into multiple Mesh's, as each Node will have its own // transform applied. // Note: the code below disregards the scenes defined in the file, all nodes are used. @@ -5156,7 +5166,7 @@ static Model LoadGLTF(const char *fileName) // Transform the vertices float *vertices = model.meshes[meshIndex].vertices; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix); vertices[3*k] = vt.x; @@ -5180,7 +5190,7 @@ static Model LoadGLTF(const char *fileName) // Transform the normals float *normals = model.meshes[meshIndex].normals; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals); normals[3*k] = nt.x; @@ -5204,7 +5214,7 @@ static Model LoadGLTF(const char *fileName) // Transform the tangents float *tangents = model.meshes[meshIndex].tangents; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 tt = Vector3Transform((Vector3){ tangents[3*k], tangents[3*k+1], tangents[3*k+2] }, worldMatrix); tangents[3*k] = tt.x; @@ -5262,7 +5272,7 @@ static Model LoadGLTF(const char *fileName) else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported", fileName); } else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported, use vec2 float", fileName); - + int index = mesh->primitives[p].attributes[j].index; if (index == 0) model.meshes[meshIndex].texcoords = texcoordPtr; else if (index == 1) model.meshes[meshIndex].texcoords2 = texcoordPtr; @@ -5649,7 +5659,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ } // Constant animation, no need to interpolate - if (FloatEquals(tend, tstart)) return false; + if (FloatEquals(tend, tstart)) return true; float duration = fmaxf((tend - tstart), EPSILON); float t = (time - tstart)/duration; diff --git a/src/rshapes.c b/src/rshapes.c index b119f50ec..89339708a 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -337,7 +337,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA } // NOTE: In case number of segments is odd, we add one last piece to the cake - if (((unsigned int)segments%2) == 1) + if ((((unsigned int)segments)%2) == 1) { rlColor4ub(color.r, color.g, color.b, color.a); @@ -1834,7 +1834,7 @@ void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thic if (pointCount >= 3) { for (int i = 0; i < pointCount - 2; i += 2) DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color); - + // Cap circle drawing at the end of every segment //for (int i = 2; i < pointCount - 2; i += 2) DrawCircleV(points[i], thick/2.0f, color); } @@ -1846,7 +1846,7 @@ void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, C if (pointCount >= 4) { for (int i = 0; i < pointCount - 3; i += 3) DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color); - + // Cap circle drawing at the end of every segment //for (int i = 3; i < pointCount - 3; i += 3) DrawCircleV(points[i], thick/2.0f, color); } @@ -2172,7 +2172,9 @@ bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius) { bool collision = false; - collision = CheckCollisionCircles(point, 0, center, radius); + float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y); + + if (distanceSquared <= radius*radius) collision = true; return collision; } @@ -2235,10 +2237,10 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa float dx = center2.x - center1.x; // X distance between centers float dy = center2.y - center1.y; // Y distance between centers - float distanceSquared = dx * dx + dy * dy; // Distance between centers squared + float distanceSquared = dx*dx + dy*dy; // Distance between centers squared float radiusSum = radius1 + radius2; - collision = (distanceSquared <= (radiusSum * radiusSum)); + collision = (distanceSquared <= (radiusSum*radiusSum)); return collision; } @@ -2329,17 +2331,17 @@ RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Ve return CheckCollisionCircles(p1, 0, center, radius); } - float lengthSQ = ((dx * dx) + (dy * dy)); - float dotProduct = (((center.x - p1.x) * (p2.x - p1.x)) + ((center.y - p1.y) * (p2.y - p1.y))) / (lengthSQ); + float lengthSQ = ((dx*dx) + (dy*dy)); + float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ); if (dotProduct > 1.0f) dotProduct = 1.0f; else if (dotProduct < 0.0f) dotProduct = 0.0f; - float dx2 = (p1.x - (dotProduct * (dx))) - center.x; - float dy2 = (p1.y - (dotProduct * (dy))) - center.y; - float distanceSQ = ((dx2 * dx2) + (dy2 * dy2)); + float dx2 = (p1.x - (dotProduct*(dx))) - center.x; + float dy2 = (p1.y - (dotProduct*(dy))) - center.y; + float distanceSQ = ((dx2*dx2) + (dy2*dy2)); - return (distanceSQ <= radius * radius); + return (distanceSQ <= radius*radius); } // Get collision rectangle for two rectangles collision diff --git a/src/rtext.c b/src/rtext.c index 8daf3a7bc..755b15efd 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1572,7 +1572,7 @@ char *TextReplace(const char *text, const char *replace, const char *by) byLen = TextLength(by); // Count the number of replacements needed - insertPoint = (char*)text; + insertPoint = (char *)text; for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen; // Allocate returning string and point temp to it @@ -2339,7 +2339,7 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i int readBytes = 0; // Data bytes read (line) int readVars = 0; // Variables filled by sscanf() - const char *fileText = (const char*)fileData; + const char *fileText = (const char *)fileData; const char *fileTextPtr = fileText; bool fontMalformed = false; // Is the font malformed diff --git a/src/rtextures.c b/src/rtextures.c index e914db419..1e88b64a4 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1630,6 +1630,174 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co return imText; } +// Create an image from a selected channel of another image +Image ImageFromChannel(Image image, int selectedChannel) +{ + Image result = { 0 }; + + // Security check to avoid program crash + if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; + + // Check selected channel is valid + if (selectedChannel < 0) + { + TRACELOG(LOG_WARNING, "Channel cannot be negative. Setting channel to 0."); + selectedChannel = 0; + } + + if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE || + image.format == PIXELFORMAT_UNCOMPRESSED_R32 || + image.format == PIXELFORMAT_UNCOMPRESSED_R16) + { + if (selectedChannel > 0) + { + TRACELOG(LOG_WARNING, "This image has only 1 channel. Setting channel to it."); + selectedChannel = 0; + } + } + else if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) + { + if (selectedChannel > 1) + { + TRACELOG(LOG_WARNING, "This image has only 2 channels. Setting channel to alpha."); + selectedChannel = 1; + } + } + else if (image.format == PIXELFORMAT_UNCOMPRESSED_R5G6B5 || + image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8 || + image.format == PIXELFORMAT_UNCOMPRESSED_R32G32B32 || + image.format == PIXELFORMAT_UNCOMPRESSED_R16G16B16) + { + if (selectedChannel > 2) + { + TRACELOG(LOG_WARNING, "This image has only 3 channels. Setting channel to red."); + selectedChannel = 0; + } + } + + // Check for RGBA formats + if (selectedChannel > 3) + { + TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (rgba). Setting channel to alpha."); + selectedChannel = 3; + } + + // TODO: Consider other one-channel formats: R16, R32 + result.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; + result.height = image.height; + result.width = image.width; + result.mipmaps = 1; + + unsigned char *pixels = (unsigned char *)RL_CALLOC(image.width*image.height, sizeof(unsigned char)); // Values from 0 to 255 + + if (image.format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "IMAGE: Pixel data retrieval not supported for compressed image formats"); + else + { + for (int i = 0, k = 0; i < image.width*image.height; i++) + { + float pixelValue = -1; + switch (image.format) + { + case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: + { + pixelValue = (float)((unsigned char *)image.data)[i + selectedChannel]/255.0f; + + } break; + case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: + { + pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f; + k += 2; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31); + else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000011111000000) >> 6)*(1.0f/31); + else if (selectedChannel == 2) pixelValue = (float)((pixel & 0b0000000000111110) >> 1)*(1.0f/31); + else if (selectedChannel == 3) pixelValue = ((pixel & 0b0000000000000001) == 0)? 0.0f : 1.0f; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R5G6B5: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31); + else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000011111100000) >> 5)*(1.0f/63); + else if (selectedChannel == 2) pixelValue = (float)(pixel & 0b0000000000011111)*(1.0f/31); + + } break; + case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111000000000000) >> 12)*(1.0f/15); + else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000111100000000) >> 8)*(1.0f/15); + else if (selectedChannel == 2) pixelValue = (float)((pixel & 0b0000000011110000) >> 4)*(1.0f/15); + else if (selectedChannel == 3) pixelValue = (float)(pixel & 0b0000000000001111)*(1.0f/15); + + } break; + case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: + { + pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f; + k += 4; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R8G8B8: + { + pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f; + k += 3; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R32: + { + pixelValue = ((float *)image.data)[k]; + k += 1; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32: + { + pixelValue = ((float *)image.data)[k + selectedChannel]; + k += 3; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: + { + pixelValue = ((float *)image.data)[k + selectedChannel]; + k += 4; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R16: + { + pixelValue = HalfToFloat(((unsigned short *)image.data)[k]); + k += 1; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R16G16B16: + { + pixelValue = HalfToFloat(((unsigned short *)image.data)[k+selectedChannel]); + k += 3; + + } break; + case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: + { + pixelValue = HalfToFloat(((unsigned short *)image.data)[k + selectedChannel]); + k += 4; + + } break; + default: break; + } + + pixels[i] = (unsigned char)(pixelValue*255); + } + } + + result.data = pixels; + + return result; +} + // Resize and image to new size using Nearest-Neighbor scaling algorithm void ImageResizeNN(Image *image,int newWidth,int newHeight) { @@ -2943,6 +3111,7 @@ Color *LoadImageColors(Image image) pixels[i].b = 0; pixels[i].a = 255; + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: { @@ -2956,9 +3125,9 @@ Color *LoadImageColors(Image image) case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: { pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f); - pixels[i].g = (unsigned char)(((float *)image.data)[k]*255.0f); - pixels[i].b = (unsigned char)(((float *)image.data)[k]*255.0f); - pixels[i].a = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].g = (unsigned char)(((float *)image.data)[k + 1]*255.0f); + pixels[i].b = (unsigned char)(((float *)image.data)[k + 2]*255.0f); + pixels[i].a = (unsigned char)(((float *)image.data)[k + 3]*255.0f); k += 4; } break; @@ -2969,6 +3138,7 @@ Color *LoadImageColors(Image image) pixels[i].b = 0; pixels[i].a = 255; + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16: { @@ -2982,9 +3152,9 @@ Color *LoadImageColors(Image image) case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: { pixels[i].r = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f); - pixels[i].g = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f); - pixels[i].b = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f); - pixels[i].a = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f); + pixels[i].g = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 1])*255.0f); + pixels[i].b = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 2])*255.0f); + pixels[i].a = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 3])*255.0f); k += 4; } break; @@ -3431,7 +3601,7 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en } // Calculate fixed-point increment for shorter length - int decInc = (longLen == 0)? 0 : (shortLen<<16) / longLen; + int decInc = (longLen == 0)? 0 : (shortLen << 16)/longLen; // Draw the line pixel by pixel if (yLonger) @@ -3440,7 +3610,7 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc) { // Calculate pixel position and draw it - ImageDrawPixel(dst, startPosX + (j>>16), startPosY + i, color); + ImageDrawPixel(dst, startPosX + (j >> 16), startPosY + i, color); } } else @@ -3449,7 +3619,7 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc) { // Calculate pixel position and draw it - ImageDrawPixel(dst, startPosX + i, startPosY + (j>>16), color); + ImageDrawPixel(dst, startPosX + i, startPosY + (j >> 16), color); } } } @@ -3488,7 +3658,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co { // Line is more horizontal // Calculate half the width of the line - int wy = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dx)); + int wy = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dx)); // Draw additional lines above and below the main line for (int i = 1; i <= wy; i++) @@ -3501,7 +3671,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co { // Line is more vertical or perfectly horizontal // Calculate half the width of the line - int wx = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dy)); + int wx = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dy)); // Draw additional lines to the left and right of the main line for (int i = 1; i <= wx; i++) @@ -3647,10 +3817,10 @@ void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color col { // Calculate the 2D bounding box of the triangle // Determine the minimum and maximum x and y coordinates of the triangle vertices - int xMin = (int)((v1.x < v2.x)? ((v1.x < v3.x) ? v1.x : v3.x) : ((v2.x < v3.x) ? v2.x : v3.x)); - int yMin = (int)((v1.y < v2.y)? ((v1.y < v3.y) ? v1.y : v3.y) : ((v2.y < v3.y) ? v2.y : v3.y)); - int xMax = (int)((v1.x > v2.x)? ((v1.x > v3.x) ? v1.x : v3.x) : ((v2.x > v3.x) ? v2.x : v3.x)); - int yMax = (int)((v1.y > v2.y)? ((v1.y > v3.y) ? v1.y : v3.y) : ((v2.y > v3.y) ? v2.y : v3.y)); + int xMin = (int)((v1.x < v2.x)? ((v1.x < v3.x)? v1.x : v3.x) : ((v2.x < v3.x)? v2.x : v3.x)); + int yMin = (int)((v1.y < v2.y)? ((v1.y < v3.y)? v1.y : v3.y) : ((v2.y < v3.y)? v2.y : v3.y)); + int xMax = (int)((v1.x > v2.x)? ((v1.x > v3.x)? v1.x : v3.x) : ((v2.x > v3.x)? v2.x : v3.x)); + int yMax = (int)((v1.y > v2.y)? ((v1.y > v3.y)? v1.y : v3.y) : ((v2.y > v3.y)? v2.y : v3.y)); // Clamp the bounding box to the image dimensions if (xMin < 0) xMin = 0; @@ -4709,12 +4879,12 @@ Color Fade(Color color, float alpha) int ColorToInt(Color color) { int result = 0; - - result = (int)(((unsigned int)color.r << 24) | - ((unsigned int)color.g << 16) | - ((unsigned int)color.b << 8) | + + result = (int)(((unsigned int)color.r << 24) | + ((unsigned int)color.g << 16) | + ((unsigned int)color.b << 8) | (unsigned int)color.a); - + return result; }