4 Commits

Author SHA1 Message Date
Ray
e18de07224 Update rcore_desktop_win32.c 2026-10-05 10:19:16 +02:00
Ray
3c1ab87ae1 Update Makefile 2026-10-05 10:19:08 +02:00
Ray
e8b23bfbe4 Minor tweaks 2026-10-05 09:39:02 +02:00
e5c0709fa2 [Examples] Clarify Camera2d.offset and how it works with High DPI scale mode (#6203)
* rlparser: update raylib_api.* by CI

* Notate that the offset in Camera2d is in pixels space (unscaled by DPI)
Update all the examples that use Camera2d.offset so that they are DPI aware if the user enables DPI scaling.

* rlparser: update raylib_api.* by CI

* remove DPI flag

* remove gltf tests that should not have been part of this PR

* formatting

* formatting

* formatting

* more formatting

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-05 09:29:59 +02:00
17 changed files with 50 additions and 51 deletions

View File

@ -54,7 +54,7 @@ int main(void)
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f }; camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;

View File

@ -65,8 +65,8 @@ int main(void)
// Get the world point that is under the mouse // Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is // Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = GetMousePosition(); camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the target to match, so that the camera maps the world space point // Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom // under the cursor to the screen space point under the cursor at any zoom
@ -86,8 +86,8 @@ int main(void)
// Get the world point that is under the mouse // Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is // Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = GetMousePosition(); camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the target to match, so that the camera maps the world space point // Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom // under the cursor to the screen space point under the cursor at any zoom

View File

@ -75,7 +75,7 @@ int main(void)
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;

View File

@ -19,6 +19,7 @@
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include "raymath.h"
#define PLAYER_SIZE 40 #define PLAYER_SIZE 40
@ -39,13 +40,13 @@ int main(void)
Camera2D camera1 = { 0 }; Camera2D camera1 = { 0 };
camera1.target = (Vector2){ player1.x, player1.y }; camera1.target = (Vector2){ player1.x, player1.y };
camera1.offset = (Vector2){ 200.0f, 200.0f }; camera1.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera1.rotation = 0.0f; camera1.rotation = 0.0f;
camera1.zoom = 1.0f; camera1.zoom = 1.0f;
Camera2D camera2 = { 0 }; Camera2D camera2 = { 0 };
camera2.target = (Vector2){ player2.x, player2.y }; camera2.target = (Vector2){ player2.x, player2.y };
camera2.offset = (Vector2){ 200.0f, 200.0f }; camera2.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera2.rotation = 0.0f; camera2.rotation = 0.0f;
camera2.zoom = 1.0f; camera2.zoom = 1.0f;

View File

@ -69,7 +69,7 @@ int main(void)
// Define camera // Define camera
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
@ -117,7 +117,7 @@ int main(void)
player.canJump = false; player.canJump = false;
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
} }
@ -169,7 +169,7 @@ int main(void)
player.canJump = false; player.canJump = false;
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
} }
@ -205,7 +205,7 @@ int main(void)
// Update camera // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000; float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
// WARNING: On event replay, mouse-wheel internal value is set // WARNING: On event replay, mouse-wheel internal value is set
@ -267,7 +267,7 @@ int main(void)
player.canJump = false; player.canJump = false;
camera.target = player.position; camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f }; camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
} }

View File

@ -106,4 +106,3 @@ int main(void)
} }

View File

@ -56,7 +56,7 @@ int main(void)
Vector2 mousePos = { 0 }; Vector2 mousePos = { 0 };
Vector2 prevMousePos = { 0 }; Vector2 prevMousePos = { 0 };
Vector2 scaleVector = { 1.0f, -1.0f }; Vector2 scaleVector = { 1.0f, -1.0f };
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f }; Vector2 offset = { GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.target = (Vector2){ 0 }; camera.target = (Vector2){ 0 };

View File

@ -16,12 +16,13 @@
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include <math.h>
#include <stdio.h>
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#include "raygui.h" #include "raygui.h"
#include <math.h>
#include <stdio.h>
#define MAX_PIE_SLICES 10 // Max pie slices #define MAX_PIE_SLICES 10 // Max pie slices
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -39,12 +40,8 @@ int main(void)
int sliceCount = 7; int sliceCount = 7;
float donutInnerRadius = 25.0f; float donutInnerRadius = 25.0f;
float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values
char labels[MAX_PIE_SLICES][32] = { 0 };
bool editingLabel[MAX_PIE_SLICES] = { 0 }; bool editingLabel[MAX_PIE_SLICES] = { 0 };
for (int i = 0; i < MAX_PIE_SLICES; i++)
snprintf(labels[i], 32, "Slice %02i", i + 1);
bool showValues = true; bool showValues = true;
bool showPercentages = false; bool showPercentages = false;
bool showDonut = false; bool showDonut = false;
@ -72,7 +69,7 @@ int main(void)
// Pie chart geometry // Pie chart geometry
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight }; const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f}; const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f };
const float radius = 205.0f; const float radius = 205.0f;
// Total value for percentage calculations // Total value for percentage calculations
@ -93,6 +90,7 @@ int main(void)
// Check for mouse hover over slices // Check for mouse hover over slices
hoveredSlice = -1; // Reset hovered slice hoveredSlice = -1; // Reset hovered slice
Vector2 mousePos = GetMousePosition(); Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
{ {
float dx = mousePos.x - center.x; float dx = mousePos.x - center.x;
@ -176,7 +174,7 @@ int main(void)
if (showDonut) GuiDisable(); if (showDonut) GuiDisable();
GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 }, GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 },
"Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f); "Inner Radius", NULL, & donutInnerRadius, 5.0f, radius - 10.0f);
GuiEnable(); GuiEnable();
GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL); GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL);
@ -190,8 +188,7 @@ int main(void)
}; };
int contentHeight = sliceCount*35; int contentHeight = sliceCount*35;
GuiScrollPanel(scrollPanelBounds, NULL, GuiScrollPanel(scrollPanelBounds, NULL, (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
(Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
&scrollContentOffset, &view); &scrollContentOffset, &view);
const float contentX = view.x + scrollContentOffset.x; // Left of content const float contentX = view.x + scrollContentOffset.x; // Left of content
@ -208,7 +205,8 @@ int main(void)
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color); DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);
// Label textbox // Label textbox
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i]; if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, TextFormat("Slice %02i", i + 1), 32, editingLabel[i]))
editingLabel[i] = !editingLabel[i];
GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f); GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f);
} }

View File

@ -16,7 +16,9 @@
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include "rlgl.h" // for rlSetBlendFactorsSeparate()
#include "rlgl.h" // Required for: rlSetBlendFactorsSeparate()
#include "raymath.h" // Required for: Vector2Multiply()
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -45,8 +47,7 @@ int main(void)
// Set magnifying glass zoom // Set magnifying glass zoom
camera.zoom = 2; camera.zoom = 2;
// Offset by half the size of the magnifying glass to counteract drawing the texture centered on the mouse position // Offset by half the size of the magnifying glass to counteract drawing the texture centered on the mouse position
camera.offset = (Vector2){128, 128}; camera.offset = Vector2Multiply((Vector2){ 128, 128 }, GetWindowScaleDPI());
SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -356,6 +356,16 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
AR = $(ANDROID_TOOLCHAIN)/bin/llvm-ar AR = $(ANDROID_TOOLCHAIN)/bin/llvm-ar
endif endif
# NOTE: Native Linux links against glibc, on glibc >= 2.38, _GNU_SOURCE redirects
# sscanf(), strtol()... to __isoc23_*(), so the library fails to link with older glibc
# Web and Android set PLATFORM_OS from the host, but they are not glibc and keep _GNU_SOURCE
DEFINED_SOURCE_MACRO = _GNU_SOURCE
ifeq ($(PLATFORM_OS), LINUX)
ifeq ($(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW PLATFORM_ANDROID),)
DEFINED_SOURCE_MACRO = _DEFAULT_SOURCE
endif
endif
# Define compiler flags: CFLAGS # Define compiler flags: CFLAGS
#------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------
# -O1 defines optimization level # -O1 defines optimization level
@ -370,17 +380,7 @@ endif
# -D_GNU_SOURCE access to lots of nonstandard GNU/Linux extension functions # -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 # -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) # -fno-strict-aliasing jar_xm.h does shady stuff (breaks strict aliasing)
CFLAGS = -Wall -D$(DEFINED_SOURCE_MACRO) -D$(TARGET_PLATFORM) -D$(GRAPHICS) -Wno-missing-braces -Werror=pointer-arith -fno-strict-aliasing
# NOTE: Native Linux links against glibc. On glibc >= 2.38, _GNU_SOURCE redirects
# sscanf(), strtol()... to __isoc23_*(), so the library fails to link with older glibc.
# Web and Android set PLATFORM_OS from the host, but they are not glibc and keep _GNU_SOURCE.
FEATURE_TEST_MACRO = _GNU_SOURCE
ifeq ($(PLATFORM_OS), LINUX)
ifeq ($(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW PLATFORM_ANDROID),)
FEATURE_TEST_MACRO = _DEFAULT_SOURCE
endif
endif
CFLAGS = -Wall -D$(FEATURE_TEST_MACRO) -D$(TARGET_PLATFORM) -D$(GRAPHICS) -Wno-missing-braces -Werror=pointer-arith -fno-strict-aliasing
ifneq ($(RAYLIB_CONFIG_FLAGS), NONE) ifneq ($(RAYLIB_CONFIG_FLAGS), NONE)
CFLAGS += -DEXTERNAL_CONFIG_FLAGS $(RAYLIB_CONFIG_FLAGS) CFLAGS += -DEXTERNAL_CONFIG_FLAGS $(RAYLIB_CONFIG_FLAGS)

View File

@ -92,8 +92,8 @@ typedef struct {
HBITMAP hbitmap; // GDI bitmap handler HBITMAP hbitmap; // GDI bitmap handler
unsigned int *pixels; // Pointer to pixel data buffer (BGRA format) unsigned int *pixels; // Pointer to pixel data buffer (BGRA format)
unsigned int appScreenWidth; int appScreenWidth;
unsigned int appScreenHeight; int appScreenHeight;
unsigned int desiredFlags; unsigned int desiredFlags;
LARGE_INTEGER timerFrequency; LARGE_INTEGER timerFrequency;
@ -1957,8 +1957,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
case WM_DPICHANGED: case WM_DPICHANGED:
{ {
// Get current dpi scale factor // Get current dpi scale factor
float scalex = HIWORD(wparam)/96.0f; //float scalex = HIWORD(wparam)/96.0f;
float scaley = LOWORD(wparam)/96.0f; //float scaley = LOWORD(wparam)/96.0f;
RECT *suggestedRect = (RECT *)lparam; RECT *suggestedRect = (RECT *)lparam;

View File

@ -336,7 +336,7 @@ typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
// Camera2D, defines position/orientation in 2d space // Camera2D, defines position/orientation in 2d space
typedef struct Camera2D { typedef struct Camera2D {
Vector2 offset; // Camera offset (screen space offset from window origin) Vector2 offset; // Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)
Vector2 target; // Camera target (world space target point that is mapped to screen space offset) Vector2 target; // Camera target (world space target point that is mapped to screen space offset)
float rotation; // Camera rotation in degrees (pivots around target) float rotation; // Camera rotation in degrees (pivots around target)
float zoom; // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale float zoom; // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale

View File

@ -763,7 +763,7 @@
{ {
"type": "Vector2", "type": "Vector2",
"name": "offset", "name": "offset",
"description": "Camera offset (screen space offset from window origin)" "description": "Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)"
}, },
{ {
"type": "Vector2", "type": "Vector2",

View File

@ -763,7 +763,7 @@ return {
{ {
type = "Vector2", type = "Vector2",
name = "offset", name = "offset",
description = "Camera offset (screen space offset from window origin)" description = "Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)"
}, },
{ {
type = "Vector2", type = "Vector2",

View File

@ -486,7 +486,7 @@
(fields (fields
((type "Vector2") ((type "Vector2")
(name "offset") (name "offset")
(description "Camera offset (screen space offset from window origin)")) (description "Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)"))
((type "Vector2") ((type "Vector2")
(name "target") (name "target")
(description "Camera target (world space target point that is mapped to screen space offset)")) (description "Camera target (world space target point that is mapped to screen space offset)"))

View File

@ -394,7 +394,7 @@ Struct 13: Camera3D (5 fields)
Struct 14: Camera2D (4 fields) Struct 14: Camera2D (4 fields)
Name: Camera2D Name: Camera2D
Description: Camera2D, defines position/orientation in 2d space Description: Camera2D, defines position/orientation in 2d space
Field[1]: Vector2 offset // Camera offset (screen space offset from window origin) Field[1]: Vector2 offset // Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)
Field[2]: Vector2 target // Camera target (world space target point that is mapped to screen space offset) Field[2]: Vector2 target // Camera target (world space target point that is mapped to screen space offset)
Field[3]: float rotation // Camera rotation in degrees (pivots around target) Field[3]: float rotation // Camera rotation in degrees (pivots around target)
Field[4]: float zoom // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale Field[4]: float zoom // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale

View File

@ -154,7 +154,7 @@
<Field type="int" name="projection" desc="Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC" /> <Field type="int" name="projection" desc="Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC" />
</Struct> </Struct>
<Struct name="Camera2D" fieldCount="4" desc="Camera2D, defines position/orientation in 2d space"> <Struct name="Camera2D" fieldCount="4" desc="Camera2D, defines position/orientation in 2d space">
<Field type="Vector2" name="offset" desc="Camera offset (screen space offset from window origin)" /> <Field type="Vector2" name="offset" desc="Camera offset (screen space offset from window origin, unscaled by DPI, real pixel size)" />
<Field type="Vector2" name="target" desc="Camera target (world space target point that is mapped to screen space offset)" /> <Field type="Vector2" name="target" desc="Camera target (world space target point that is mapped to screen space offset)" />
<Field type="float" name="rotation" desc="Camera rotation in degrees (pivots around target)" /> <Field type="float" name="rotation" desc="Camera rotation in degrees (pivots around target)" />
<Field type="float" name="zoom" desc="Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale" /> <Field type="float" name="zoom" desc="Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale" />