34 Commits

Author SHA1 Message Date
101502103a Fixed FLAG_IS_SET to check if all bits in the flag are set in the value (#5441) 2025-12-24 20:58:40 +01:00
Ray
20dd4641c8 REVIEWED: Potential security concerns while copying unbounded text data between strings
Note that issue has been reported by CodeQL static analysis system
2025-12-24 19:35:06 +01:00
Ray
fc843dc557 Create SECURITY.md 2025-12-24 19:21:43 +01:00
Ray
9103f6e055 ADDED: New platform backend for Web: Emscripten, not dependant on GLFW.js -WIP- 2025-12-24 18:58:20 +01:00
Ray
ced84333a9 Update rl_gputex.h 2025-12-24 18:02:24 +01:00
Ray
05f42aa119 Update core_highdpi_testbed.c 2025-12-24 18:02:04 +01:00
a1e84caa8c RGFW also requires RGBA8 images as window icons, as raylib already reports in raylib.h (#5431) 2025-12-24 09:04:41 +01:00
ddb827fb6f Fixed LoadCodepoints declaring a new local variable shadowing codpoints (#5430) 2025-12-24 08:59:51 +01:00
0a4583ca54 [rl_gputex.h] Possibly fixed the swizzling in rl_load_dds_from_memory() function (#5422)
* Possibly fixed the swizzling bug

* Removed examples, and generation.
2025-12-23 17:10:55 +01:00
6a701b2679 fix android SetWindowState (#5424) 2025-12-23 15:37:08 +01:00
Ray
aa2884bd78 Update rcore_desktop_glfw.c 2025-12-22 22:50:38 +01:00
Ray
f27f2d097f REVIEWED: HighDPI support on macOS (when requested by app)
Tested on two monitors with different DPI configuration, for HigDPI enabled and not, including window resizing (with framebuffer resizing if required). Verified mouse coordinates follow the requested screen size.
2025-12-22 22:48:08 +01:00
Ray
e4baf682ab Update rtext.c 2025-12-22 20:30:11 +01:00
Ray
8516750975 Remove internal function 2025-12-22 20:29:57 +01:00
3212becc91 Update BINDINGS.md (#5421) 2025-12-21 20:15:38 +01:00
Ray
b9446863d7 REXM: RENAMED: core_high_dpi --> core_highdpi_demo 2025-12-20 22:36:44 +01:00
Ray
13f9112d8c Update rcore_desktop_sdl.c 2025-12-19 01:16:34 +01:00
Ray
f16fb065ea Update rcore_template.c 2025-12-19 01:15:34 +01:00
Ray
66392fe0ae REVIEWED: rlGetPixelDataSize(), correct compressed data size calculation per blocks #5416 2025-12-19 00:06:44 +01:00
Ray
720dd22491 REVIEWED: rlLoadTexture(), un complete texture do to issue on mipmap loading #5416 2025-12-18 17:04:58 +01:00
Ray
ca578b8b08 Update raylib.sln 2025-12-18 17:03:53 +01:00
Ray
4b760091da REVIEWED: Window scaling with HighDPI on macOS #5059 2025-12-17 21:23:25 +01:00
Ray
6d562e5e87 REVIEWED: HiggDPI content scaling on changing monitors with different DPI #5335 #5356
Note that high-dpi awareness must be enabled by users and `CORE.Window.render` reports the scaled framebuffer size, while `CORE.Window.screen` reports the logical size.

`ToggleBorderlessWindow()` has also been reviewed to be consistent with scaling, if monitor physical display size is reported as 1920x1080 but there is a content scale of 1.5, then the borderless fullscreen window will be 1280x720, with the 1920x1080 framebuffer
2025-12-17 19:20:18 +01:00
Ray
7553e9d586 REVIEWED: Gamepads on latest SDL2 2.32.8 and SDL3 3.3.6 #5403 2025-12-16 19:36:01 +01:00
Ray
80ad96acc2 Fix #5413 2025-12-16 18:33:07 +01:00
Ray
7a5e8aa3a5 Update rcore_android.c 2025-12-16 18:30:33 +01:00
1c94e94873 [rcore] Implement FLAG_WINDOW_ALWAYS_RUN on Android (#5414) 2025-12-16 18:26:20 +01:00
33adda1983 fixed build errors with zig. now compatible with zig master 0.16.0-dev.1593+c13857e50. still backwards compatible with 0.15.1 (#5415) 2025-12-16 18:24:53 +01:00
Ray
f031b2f4f4 Alignment with other platform backends, avoid unneeded includes 2025-12-16 18:20:02 +01:00
Ray
1c7240a01d Revert "REVIEWED: Alignment with other platforms"
This reverts commit cf0d6fc664.
2025-12-16 18:18:42 +01:00
Ray
cf0d6fc664 REVIEWED: Alignment with other platforms 2025-12-15 20:44:28 +01:00
Ray
615fc36eeb Fix #5406 2025-12-15 18:56:14 +01:00
Ray
cbe31759ab Fix #5405 2025-12-15 18:52:27 +01:00
d74556d35c Modify text_words_alignment.c (#5411) 2025-12-15 18:49:40 +01:00
27 changed files with 2638 additions and 926 deletions

4
.gitignore vendored
View File

@ -58,6 +58,10 @@ packages/
*.h.pch
./*.obj
# Ignore SDL libs for testing
src/external/SDL2
src/external/SDL3
# Emscripten
emsdk

View File

@ -76,6 +76,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
| [ringraylib5](https://github.com/ring-lang/ring/tree/master/extensions/ringraylib5) | **5.0** | [Ring](https://ring-lang.github.io/) | **???** |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |

18
SECURITY.md Normal file
View File

@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
Most considerations of errors and defects can be handled using the project Issues and/or Discussions.
| Version | Supported |
| ------- | ------------------ |
| 6.0.x | :white_check_mark: |
| < 5.5 | :x: |
## Reporting a Vulnerability
Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
_TODO: Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc._

View File

@ -106,9 +106,9 @@ const config_h_flags = outer: {
if (std.mem.startsWith(u8, line, "//")) continue;
if (std.mem.startsWith(u8, line, "#if")) continue;
var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
var flag = std.mem.trimStart(u8, line, " \t"); // Trim whitespace
flag = flag["#define ".len - 1 ..]; // Remove #define
flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
flag = std.mem.trimStart(u8, flag, " \t"); // Trim whitespace
flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
flag = "-D" ++ flag; // Prepend with -D
@ -193,7 +193,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
// No GLFW required on PLATFORM_DRM
if (options.platform != .drm) {
raylib.addIncludePath(b.path("src/external/glfw/include"));
raylib.root_module.addIncludePath(b.path("src/external/glfw/include"));
}
var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2);
@ -224,7 +224,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
}
raylib.addIncludePath(b.path("src/platforms"));
raylib.root_module.addIncludePath(b.path("src/platforms"));
switch (target.result.os.tag) {
.windows => {
switch (options.platform) {

View File

@ -531,7 +531,7 @@ CORE = \
core/core_delta_time \
core/core_directory_files \
core/core_drop_files \
core/core_high_dpi \
core/core_highdpi_demo \
core/core_highdpi_testbed \
core/core_input_actions \
core/core_input_gamepad \

View File

@ -519,7 +519,7 @@ CORE = \
core/core_delta_time \
core/core_directory_files \
core/core_drop_files \
core/core_high_dpi \
core/core_highdpi_demo \
core/core_highdpi_testbed \
core/core_input_actions \
core/core_input_gamepad \
@ -783,7 +783,7 @@ core/core_directory_files: core/core_directory_files.c
core/core_drop_files: core/core_drop_files.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_high_dpi: core/core_high_dpi.c
core/core_highdpi_demo: core/core_highdpi_demo.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_highdpi_testbed: core/core_highdpi_testbed.c

View File

@ -61,7 +61,7 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) |
| [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) |
| [core_automation_events](core/core_automation_events.c) | <img src="core/core_automation_events.png" alt="core_automation_events" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_high_dpi](core/core_high_dpi.c) | <img src="core/core_high_dpi.png" alt="core_high_dpi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
| [core_highdpi_demo](core/core_highdpi_demo.c) | <img src="core/core_highdpi_demo.png" alt="core_highdpi_demo" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
| [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_viewport_scaling](core/core_viewport_scaling.c) | <img src="core/core_viewport_scaling.png" alt="core_viewport_scaling" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |

View File

@ -1,6 +1,6 @@
/*******************************************************************************************
*
* raylib [core] example - high dpi
* raylib [core] example - highdpi demo
*
* Example complexity rating: [] 2/4
*
@ -33,7 +33,7 @@ int main(void)
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - high dpi");
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi demo");
SetWindowMinSize(450, 450);
int logicalGridDescY = 120;

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -27,9 +27,13 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI);
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
Vector2 scaleDpi = GetWindowScaleDPI();
Vector2 mousePos = GetMousePosition();
int currentMonitor = GetCurrentMonitor();
int gridSpacing = 40; // Grid spacing in pixels
SetTargetFPS(60);
@ -40,7 +44,11 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update variables / Implement example logic at this point
mousePos = GetMousePosition();
currentMonitor = GetCurrentMonitor();
scaleDpi = GetWindowScaleDPI();
if (IsKeyPressed(KEY_SPACE)) ToggleBorderlessWindowed();
//----------------------------------------------------------------------------------
// Draw
@ -50,11 +58,30 @@ int main(void)
ClearBackground(RAYWHITE);
// Draw grid
for (int h = 0; h < 20; h++) DrawLine(0, h*gridSpacing, GetRenderWidth(), h*gridSpacing, LIGHTGRAY);
for (int v = 0; v < 40; v++) DrawLine(v*gridSpacing, 0, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
for (int h = 0; h < 20; h++)
{
DrawText(TextFormat("%02i", h*gridSpacing), 4, h*gridSpacing - 4, 10, GRAY);
DrawLine(24, h*gridSpacing, GetScreenWidth(), h*gridSpacing, LIGHTGRAY);
}
for (int v = 0; v < 40; v++)
{
DrawText(TextFormat("%02i", v*gridSpacing), v*gridSpacing - 10, 4, 10, GRAY);
DrawLine(v*gridSpacing, 20, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
}
// Draw UI info
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 10, 10, 20, BLACK);
DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(),
GetMonitorWidth(currentMonitor), GetMonitorHeight(currentMonitor)), 50, 50, 20, DARKGRAY);
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 90, 20, DARKGRAY);
DrawText(TextFormat("RENDER SIZE: %ix%i", GetRenderWidth(), GetRenderHeight()), 50, 130, 20, DARKGRAY);
DrawText(TextFormat("SCALE FACTOR: %.1fx%.1f", scaleDpi.x, scaleDpi.y), 50, 170, 20, GRAY);
// Draw mouse position
DrawCircleV(GetMousePosition(), 20, MAROON);
DrawRectangle(mousePos.x - 25, mousePos.y, 50, 2, BLACK);
DrawRectangle(mousePos.x, mousePos.y - 25, 2, 50, BLACK);
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
(mousePos.y > GetScreenHeight() - 60)? mousePos.y - 46 : mousePos.y + 30, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------

View File

@ -43,7 +43,7 @@ core;core_custom_frame_control;★★★★;4.0;4.0;2021;2025;"Ramon Santamaria"
core;core_smooth_pixelperfect;★★★☆;3.7;4.0;2021;2025;"Giancamillo Alessandroni";@NotManyIdeasDev
core;core_random_sequence;★☆☆☆;5.0;5.0;2023;2025;"Dalton Overmyer";@REDl3east
core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
core;core_high_dpi;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
core;core_highdpi_demo;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers

View File

@ -316,7 +316,7 @@ void SliceTextParticle(TextParticle *tp, int particlePos, int sliceLength, TextP
void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *tps, int *particleCount)
{
int tokenCount = 0;
const char **tokens = TextSplit(tp->text, charToSlice, &tokenCount);
char **tokens = TextSplit(tp->text, charToSlice, &tokenCount);
if (tokenCount > 1)
{

View File

@ -19,6 +19,8 @@
#include "raymath.h" // Required for: Lerp()
#include <stdio.h>
typedef enum TextAlignment {
TEXT_ALIGN_LEFT = 0,
TEXT_ALIGN_TOP = 0,
@ -58,7 +60,7 @@ int main(void)
// And of course the font...
Font font = GetFontDefault();
// Intialize the alignment variables
// Initialize the alignment variables
TextAlignment hAlign = TEXT_ALIGN_CENTRE;
TextAlignment vAlign = TEXT_ALIGN_MIDDLE;
@ -72,8 +74,7 @@ int main(void)
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_LEFT))
{
hAlign = hAlign - 1;
if (hAlign < 0) hAlign = 0;
if (hAlign > 0) hAlign = hAlign - 1;
}
if (IsKeyPressed(KEY_RIGHT))
@ -84,8 +85,7 @@ int main(void)
if (IsKeyPressed(KEY_UP))
{
vAlign = vAlign - 1;
if (vAlign < 0) vAlign = 0;
if (vAlign > 0) vAlign = vAlign - 1;
}
if (IsKeyPressed(KEY_DOWN))
@ -95,7 +95,8 @@ int main(void)
}
// One word per second
wordIndex = (int)GetTime()%wordCount;
if (wordCount > 0) wordIndex = (int)GetTime()%wordCount;
else wordIndex = 0;
//----------------------------------------------------------------------------------
// Draw

View File

@ -53,9 +53,9 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{BCB71111-8505-4B35-8CEF-EC6115DC9D4D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>core_high_dpi</RootNamespace>
<RootNamespace>core_highdpi_demo</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>core_high_dpi</ProjectName>
<ProjectName>core_highdpi_demo</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -553,7 +553,7 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\examples\core\core_high_dpi.c" />
<ClCompile Include="..\..\..\examples\core\core_highdpi_demo.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\examples\examples.rc" />

View File

@ -57,7 +57,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_custom_logging", "exam
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_drop_files", "examples\core_drop_files.vcxproj", "{0199E349-0701-40BC-8A7F-06A54FFA3E7C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_high_dpi", "examples\core_high_dpi.vcxproj", "{BCB71111-8505-4B35-8CEF-EC6115DC9D4D}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_demo", "examples\core_highdpi_demo.vcxproj", "{BCB71111-8505-4B35-8CEF-EC6115DC9D4D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_gamepad", "examples\core_input_gamepad.vcxproj", "{8F19E3DA-8929-4000-87B5-3CA6929636CC}"
EndProject
@ -5543,7 +5543,7 @@ Global
{19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021}
{9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A}
{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE}
{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
{8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021}
{A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
{5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {278D8859-20B1-428F-8448-064F46E1F021}
@ -5559,7 +5559,7 @@ Global
{124935CC-73BB-489E-92E8-4F922A85DB5D} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021}
{0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} = {278D8859-20B1-428F-8448-064F46E1F021}
{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE}
{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {278D8859-20B1-428F-8448-064F46E1F021}
{1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{9DE2FC01-A839-4F89-8319-9071D4C54821} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{2F578155-D51F-4C03-AB7F-5C5122CA46CC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}

View File

@ -308,7 +308,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
unsigned char alpha = 0;
// NOTE: Data comes as A1R5G5B5, it must be reordered to R5G5B5A1
for (int i = 0; i < image_pixel_size; i++)
for (int i = 0; i < data_size/sizeof(unsigned short); i++)
{
alpha = ((unsigned short *)image_data)[i] >> 15;
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 1;
@ -328,7 +328,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
unsigned char alpha = 0;
// NOTE: Data comes as A4R4G4B4, it must be reordered R4G4B4A4
for (int i = 0; i < image_pixel_size; i++)
for (int i = 0; i < data_size/sizeof(unsigned short); i++)
{
alpha = ((unsigned short *)image_data)[i] >> 12;
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 4;
@ -362,7 +362,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
// NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment)
// DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
// So, we must realign B8G8R8A8 to R8G8B8A8
for (int i = 0; i < image_pixel_size*4; i += 4)
for (int i = 0; i < data_size; i += 4)
{
blue = ((unsigned char *)image_data)[i];
((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2];

View File

@ -357,13 +357,17 @@ void RestoreWindow(void)
// Set window configuration state using flags
void SetWindowState(unsigned int flags)
{
TRACELOG(LOG_WARNING, "SetWindowState() not available on target platform");
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
// State change: FLAG_WINDOW_ALWAYS_RUN
if (FLAG_IS_SET(flags, FLAG_WINDOW_ALWAYS_RUN)) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN);
}
// Clear window configuration state flags
void ClearWindowState(unsigned int flags)
{
TRACELOG(LOG_WARNING, "ClearWindowState() not available on target platform");
// State change: FLAG_WINDOW_ALWAYS_RUN
if (FLAG_IS_SET(flags, FLAG_WINDOW_ALWAYS_RUN)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN);
}
// Set icon for window
@ -601,7 +605,7 @@ void DisableCursor(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
eglSwapBuffers(platform.device, platform.surface);
if (platform.surface != EGL_NO_SURFACE) eglSwapBuffers(platform.device, platform.surface);
}
//----------------------------------------------------------------------------------
@ -740,8 +744,8 @@ void PollInputEvents(void)
int pollEvents = 0;
// Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
// NOTE: Activity is paused if not enabled (platform.appEnabled)
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
// NOTE: Activity is paused if not enabled (platform.appEnabled) and always run flag is not set (FLAG_WINDOW_ALWAYS_RUN)
while ((pollResult = ALooper_pollOnce((platform.appEnabled || FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN))? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
{
// Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source);

View File

@ -134,12 +134,13 @@ static void ErrorCallback(int error, const char *description);
// Window callbacks events
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void FramebufferSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 FramebufferSize Callback, runs when window is resized
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley); // GLFW3 Window Content Scale Callback, runs when window changes scale
static void WindowPosCallback(GLFWwindow *window, int x, int y); // GLFW3 WindowPos Callback, runs when window is moved
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowMaximizeCallback(GLFWwindow *window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley); // GLFW3 Window Content Scale Callback, runs when window changes scale
// Input callbacks events
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
@ -155,8 +156,6 @@ static void *AllocateWrapper(size_t size, void *user);
static void *ReallocateWrapper(void *block, size_t size, void *user); // GLFW3 GLFWreallocatefun, wrapps around RL_REALLOC macro
static void DeallocateWrapper(void *block, void *user); // GLFW3 GLFWdeallocatefun, wraps around RL_FREE macro
static void SetDimensionsFromMonitor(GLFWmonitor *monitor); // Set screen dimensions from monitor/display dimensions
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
@ -205,7 +204,6 @@ void ToggleFullscreen(void)
glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
}
}
else
{
@ -231,22 +229,22 @@ void ToggleBorderlessWindowed(void)
bool wasOnFullscreen = false;
if (CORE.Window.fullscreen)
{
// fullscreen already saves the previous position so it does not need to be set here again
// Fullscreen already saves the previous position so it does not need to be set here again
ToggleFullscreen();
wasOnFullscreen = true;
}
const int monitor = GetCurrentMonitor();
int monitorCount;
int monitorCount = 0;
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
const int monitor = GetCurrentMonitor();
if ((monitor >= 0) && (monitor < monitorCount))
{
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
if (mode)
if (mode != NULL)
{
if (!IsWindowState(FLAG_BORDERLESS_WINDOWED_MODE))
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
{
// Store screen position and size
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
@ -286,6 +284,16 @@ void ToggleBorderlessWindowed(void)
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNDECORATED);
#if !defined(__APPLE__)
// Make sure to restore size to HighDPI
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
Vector2 scaleDpi = GetWindowScaleDPI();
CORE.Window.previousScreen.width *= scaleDpi.x;
CORE.Window.previousScreen.height *= scaleDpi.y;
}
#endif
// Return previous screen size and position
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
glfwSetWindowMonitor(
@ -1016,8 +1024,8 @@ Vector2 GetWindowPosition(void)
// Get window scale DPI factor for current monitor
Vector2 GetWindowScaleDPI(void)
{
Vector2 scale = { 0 };
glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
Vector2 scale = { 1.0f, 1.0f };
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
return scale;
}
@ -1329,7 +1337,8 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = false;
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
if ((CORE.Window.eventWaiting) ||
(FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED) && !FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN)))
{
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
CORE.Time.previous = GetTime();
@ -1434,31 +1443,27 @@ int InitPlatform(void)
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
// HACK: Most of this was written before GLFW_SCALE_FRAMEBUFFER existed and
// was enabled by default. Disabling it gets back the old behavior. A
// complete fix will require removing a lot of CORE.Window.render
// manipulation code
// NOTE: This currently doesn't work on macOS(see #5185), so we skip it there
// when FLAG_WINDOW_HIGHDPI is *unset*
#if !defined(__APPLE__)
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
#endif
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
// since we skipped it before, now make sure to set this on macOS
#if defined(__APPLE__)
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
#endif
// Resize window content area based on the monitor content scale
// NOTE: This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11
// NOTE: This hint only has an effect on platforms where screen coordinates and
// pixels always map 1:1 such as Windows and X11
// On platforms like macOS the resolution of the framebuffer is changed independently of the window size
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
#if defined(__APPLE__)
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
#endif
}
else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
else
{
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
#if defined(__APPLE__)
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
#endif
}
// Mouse passthrough
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MOUSE_PASSTHROUGH)) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
@ -1528,9 +1533,7 @@ int InitPlatform(void)
GLFWmonitor *monitor = NULL;
if (CORE.Window.fullscreen)
{
// According to glfwCreateWindow(), if the user does not have a choice, fullscreen applications
// should default to the primary monitor
// NOTE: Fullscreen applications default to the primary monitor
monitor = glfwGetPrimaryMonitor();
if (!monitor)
{
@ -1538,7 +1541,16 @@ int InitPlatform(void)
return -1;
}
SetDimensionsFromMonitor(monitor);
// Set dimensions from monitor
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
// Default display resolution to that of the current mode
CORE.Window.display.width = mode->width;
CORE.Window.display.height = mode->height;
// Set screen width/height to the display width/height if they are 0
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
// Remember center for switching from fullscreen to window
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
@ -1627,7 +1639,15 @@ int InitPlatform(void)
if (monitorIndex < monitorCount)
{
monitor = monitors[monitorIndex];
SetDimensionsFromMonitor(monitor);
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
// Default display resolution to that of the current mode
CORE.Window.display.width = mode->width;
CORE.Window.display.height = mode->height;
// Set screen width/height to the display width/height if they are 0
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
}
@ -1639,6 +1659,7 @@ int InitPlatform(void)
return -1;
}
// NOTE: Not considering scale factor now, considered below
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
}
@ -1669,13 +1690,12 @@ int InitPlatform(void)
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
#if !defined(__APPLE__)
// Framebuffer scaling is activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
// Screen scaling matrix is required in case desired screen area is different from display area
CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
#if !defined(__APPLE__)
// Mouse input scaling for the new screen size
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
#endif
@ -1735,17 +1755,14 @@ int InitPlatform(void)
// Initialize input events callbacks
//----------------------------------------------------------------------------
// Set window callback events
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing is not enabled by default
glfwSetFramebufferSizeCallback(platform.handle, FramebufferSizeCallback);
glfwSetWindowPosCallback(platform.handle, WindowPosCallback);
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
glfwSetDropCallback(platform.handle, WindowDropCallback);
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);
}
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);
// Set input callback events
glfwSetKeyCallback(platform.handle, KeyCallback);
@ -1755,7 +1772,6 @@ int InitPlatform(void)
glfwSetScrollCallback(platform.handle, MouseScrollCallback);
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
glfwSetJoystickCallback(JoystickCallback);
glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)
// Retrieve gamepad names
@ -1814,79 +1830,116 @@ void ClosePlatform(void)
#endif
}
// GLFW3 Error Callback, runs on GLFW3 error
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
// NOTE: Those functions are only required for current platform
//----------------------------------------------------------------------------------
// GLFW3: Error callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description)
{
TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description);
}
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
// GLFW3: Window size change callback, runs when window is resized
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
{
// Nothing to do for now on window resize...
//TRACELOG(LOG_INFO, "GLFW3: Window size callback called [%i,%i]", width, height);
}
// GLFW3: Framebuffer size change callback, runs when framebuffer is resized
// WARNING: If FLAG_WINDOW_HIGHDPI is set, WindowContentScaleCallback() is called before this function
static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
{
//TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
// WARNING: On window minimization, callback is called,
// but we don't want to change internal screen values, it breaks things
if ((width == 0) || (height == 0)) return;
// Reset viewport and projection matrix for new size
// NOTE: Stores current render size: CORE.Window.render
SetupViewport(width, height);
// Set render size
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
if (IsWindowFullscreen()) return;
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
// Check if render size was actually scaled for high-dpi
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
width = (int)(width/GetWindowScaleDPI().x);
height = (int)(height/GetWindowScaleDPI().y);
// Set screen size to logical pixel size, considering content scaling
Vector2 scaleDpi = GetWindowScaleDPI();
CORE.Window.screen.width = (int)((float)width/scaleDpi.x);
CORE.Window.screen.height = (int)((float)height/scaleDpi.y);
}
// Set render size
CORE.Window.render.width = width;
CORE.Window.render.height = height;
// Set current screen size
else
{
// Set screen size to render size (physical pixel size)
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
// WARNING: If using a render texture, it is not scaled to new size
}
// GLFW3: Window content scale callback, runs on monitor content scale change detected
// WARNING: If FLAG_WINDOW_HIGHDPI is not set, this function is not called
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)
{
TRACELOG(LOG_INFO, "GLFW3: Window content scale changed, scale: [%.2f,%.2f]", scalex, scaley);
float fbWidth = (float)CORE.Window.screen.width*scalex;
float fbHeight = (float)CORE.Window.screen.height*scaley;
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
// Framebuffer scaling is activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
#if !defined(__APPLE__)
// Mouse input scaling for the new screen size
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
#endif
CORE.Window.render.width = (int)fbWidth;
CORE.Window.render.height = (int)fbHeight;
CORE.Window.currentFbo.width = (int)fbWidth;
CORE.Window.currentFbo.height = (int)fbHeight;
}
// GLFW3: Window position callback, runs when window position changes
static void WindowPosCallback(GLFWwindow *window, int x, int y)
{
// Set current window position
CORE.Window.position.x = x;
CORE.Window.position.y = y;
}
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)
{
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
}
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
// GLFW3: Window iconify callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow *window, int iconified)
{
if (iconified) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED); // The window was iconified
else FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MINIMIZED); // The window was restored
}
// GLFW3 WindowMaximize Callback, runs when window is maximized/restored
// GLFW3: Window maximize callback, runs when window is maximized/restored
static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
{
if (maximized) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED); // The window was maximized
else FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED); // The window was restored
}
// GLFW3 WindowFocus Callback, runs when window get/lose focus
// GLFW3: Window focus callback, runs when window get/lose focus
static void WindowFocusCallback(GLFWwindow *window, int focused)
{
if (focused) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); // The window was focused
else FLAG_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); // The window lost focus
}
// GLFW3 Window Drop Callback, runs when drop files into window
// GLFW3: Window drop callback, runs when files are dropped into window
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
{
if (count > 0)
@ -1909,12 +1962,12 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
strcpy(CORE.Window.dropFilepaths[i], paths[i]);
strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1);
}
}
}
// GLFW3 Keyboard Callback, runs on key pressed
// GLFW3: Keyboard callback, runs on key pressed
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key < 0) return; // Security check, macOS fn key generates -1
@ -1941,7 +1994,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);
}
// GLFW3 Char Callback, get unicode codepoint value
// GLFW3: Char callback, runs on key pressed to get unicode codepoint value
static void CharCallback(GLFWwindow *window, unsigned int codepoint)
{
// NOTE: Registers any key down considering OS keyboard layout but
@ -1958,7 +2011,7 @@ static void CharCallback(GLFWwindow *window, unsigned int codepoint)
}
}
// GLFW3 Mouse Button Callback, runs on mouse button pressed
// GLFW3: Mouse button callback, runs on mouse button pressed
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
{
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
@ -1994,7 +2047,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
#endif
}
// GLFW3 Cursor Position Callback, runs on mouse move
// GLFW3: Cursor position callback, runs on mouse movement
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
{
CORE.Input.Mouse.currentPosition.x = (float)x;
@ -2025,20 +2078,20 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
#endif
}
// GLFW3 Scrolling Callback, runs on mouse wheel
// GLFW3: Mouse wheel scroll callback, runs on mouse wheel changes
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
{
CORE.Input.Mouse.currentWheelMove = (Vector2){ (float)xoffset, (float)yoffset };
}
// GLFW3 CursorEnter Callback, when cursor enters the window
// GLFW3: Cursor ennter callback, when cursor enters the window
static void CursorEnterCallback(GLFWwindow *window, int enter)
{
if (enter) CORE.Input.Mouse.cursorOnScreen = true;
else CORE.Input.Mouse.cursorOnScreen = false;
}
// GLFW3 Joystick Connected/Disconnected Callback
// GLFW3: Joystick connected/disconnected callback
static void JoystickCallback(int jid, int event)
{
if (event == GLFW_CONNECTED)
@ -2054,20 +2107,6 @@ static void JoystickCallback(int jid, int event)
}
}
// Set screen dimensions from monitor/display dimensions
static void SetDimensionsFromMonitor(GLFWmonitor *monitor)
{
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
// Default display resolution to that of the current mode
CORE.Window.display.width = mode->width;
CORE.Window.display.height = mode->height;
// Set screen width/height to the display width/height if they are 0
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
}
#ifdef _WIN32
# define WIN32_CLIPBOARD_IMPLEMENTATION
# include "../external/win32_clipboard.h"

View File

@ -48,11 +48,6 @@
*
**********************************************************************************************/
#ifndef RAYLIB_H /* this should never actually happen, it's only here for IDEs */
#include "raylib.h"
#include "../rcore.c"
#endif
#if defined(PLATFORM_WEB_RGFW)
#define RGFW_NO_GL_HEADER
#endif
@ -527,46 +522,15 @@ void ClearWindowState(unsigned int flags)
}
}
int RGFW_formatToChannels(int format)
{
switch (format)
{
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float)
case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float)
return 1;
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
return 2;
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
return 3;
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)
case PIXELFORMAT_COMPRESSED_DXT3_RGBA: // 8 bpp
case PIXELFORMAT_COMPRESSED_DXT5_RGBA: // 8 bpp
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
return 4;
default: return 4;
}
}
// Set icon for window
void SetWindowIcon(Image image)
{
RGFW_window_setIcon(platform.window, (u8 *)image.data, RGFW_AREA(image.width, image.height), RGFW_formatToChannels(image.format));
if (image.format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
{
TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
return;
}
RGFW_window_setIcon(platform.window, (u8 *)image.data, RGFW_AREA(image.width, image.height), 4);
}
// Set icon for window
@ -583,12 +547,17 @@ void SetWindowIcons(Image *images, int count)
for (int i = 0; i < count; i++)
{
if (images[i].format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
{
TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
continue;
}
if ((bigIcon == NULL) || ((images[i].width > bigIcon->width) && (images[i].height > bigIcon->height))) bigIcon = &images[i];
if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i];
}
if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow);
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar);
if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), 4, RGFW_iconWindow);
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), 4, RGFW_iconTaskbar);
}
}

View File

@ -57,7 +57,7 @@
// SDL base library (window/rendered, input, timing... functionality)
#ifdef USING_SDL3_PROJECT
#include "SDL3/SDL.h"
#elif USING_SDL2_PROJECT
#elif defined(USING_SDL2_PROJECT)
#include "SDL2/SDL.h"
#else
#include "SDL.h"
@ -71,7 +71,7 @@
// SDL OpenGL functionality (if required, instead of internal renderer)
#ifdef USING_SDL3_PROJECT
#include "SDL3/SDL_opengl.h"
#elif USING_SDL2_PROJECT
#elif defined(USING_SDL2_PROJECT)
#include "SDL2/SDL_opengl.h"
#else
#include "SDL_opengl.h"
@ -679,6 +679,7 @@ void ClearWindowState(unsigned int flags)
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_SDL");
}
if (FLAG_IS_SET(flags, FLAG_WINDOW_HIGHDPI))
{
// NOTE: There also doesn't seem to be a feature to disable high DPI once enabled
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_SDL");
@ -1041,7 +1042,7 @@ int GetMonitorPhysicalWidth(int monitor)
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
// Calculate size on inches, then convert to millimeter
if (ddpi > 0.0f) width = (mode.w/ddpi)*25.4f;
if (ddpi > 0.0f) width = (int)((mode.w/ddpi)*25.4f);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
@ -1065,7 +1066,7 @@ int GetMonitorPhysicalHeight(int monitor)
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(monitor, &mode);
// Calculate size on inches, then convert to millimeter
if (ddpi > 0.0f) height = (mode.h/ddpi)*25.4f;
if (ddpi > 0.0f) height = (int)((mode.h/ddpi)*25.4f);
}
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
@ -1127,14 +1128,15 @@ Vector2 GetWindowScaleDPI(void)
{
Vector2 scale = { 1.0f, 1.0f };
#ifndef USING_VERSION_SDL3
// NOTE: SDL_GetWindowDisplayScale was only added on SDL3
#if defined(USING_VERSION_SDL3)
// NOTE: SDL_GetWindowDisplayScale added on SDL3
// REF: https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale
// TODO: Implement the window scale factor calculation manually
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#else
scale.x = SDL_GetWindowDisplayScale(platform.window);
scale.y = scale.x;
#else
// NOTE: SDL_GetWindowDisplayScale not available on SDL2
// TODO: Implement the window scale factor calculation manually
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#endif
return scale;
@ -1195,7 +1197,7 @@ Image GetClipboardImage(void)
if (fileData)
{
image = LoadImageFromMemory(imageExtensions[i], fileData, dataSize);
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
if (IsImageValid(image))
{
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
@ -1429,9 +1431,9 @@ void PollInputEvents(void)
// Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE,
// and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events,
// you should make a copy of it. SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
#else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
SDL_free(event.drop.file);
#endif
@ -1442,9 +1444,9 @@ void PollInputEvents(void)
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3)
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
#else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
SDL_free(event.drop.file);
#endif
@ -1454,7 +1456,7 @@ void PollInputEvents(void)
} break;
// Window events are also polled (Minimized, maximized, close...)
// Window events are also polled (minimized, maximized, close...)
#ifndef USING_VERSION_SDL3
// SDL3 states:
@ -1473,7 +1475,7 @@ void PollInputEvents(void)
const int height = event.window.data2;
SetupViewport(width, height);
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
CORE.Window.screen.width = (int)(width/GetWindowScaleDPI().x);
CORE.Window.screen.height = (int)(height/GetWindowScaleDPI().y);
@ -1488,7 +1490,8 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = true;
#ifndef USING_VERSION_SDL3
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms) to remove the FLAG_WINDOW_MAXIMIZED accordingly
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms)
// to remove the FLAG_WINDOW_MAXIMIZED accordingly
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED))
{
int borderTop = 0;
@ -1504,14 +1507,8 @@ void PollInputEvents(void)
#endif
} break;
case SDL_WINDOWEVENT_ENTER:
{
CORE.Input.Mouse.cursorOnScreen = true;
} break;
case SDL_WINDOWEVENT_LEAVE:
{
CORE.Input.Mouse.cursorOnScreen = false;
} break;
case SDL_WINDOWEVENT_ENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
case SDL_WINDOWEVENT_LEAVE: CORE.Input.Mouse.cursorOnScreen = false; break;
case SDL_WINDOWEVENT_MINIMIZED:
{
@ -1750,7 +1747,11 @@ void PollInputEvents(void)
{
int button = -1;
#if defined(USING_VERSION_SDL3)
switch (event.gbutton.button)
#else
switch (event.jbutton.button)
#endif
{
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
@ -1778,7 +1779,11 @@ void PollInputEvents(void)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
#if defined(USING_VERSION_SDL3)
if (platform.gamepadId[i] == event.gbutton.which)
#else
if (platform.gamepadId[i] == event.jbutton.which)
#endif
{
CORE.Input.Gamepad.currentButtonState[i][button] = 1;
CORE.Input.Gamepad.lastButtonPressed = button;
@ -1791,7 +1796,11 @@ void PollInputEvents(void)
{
int button = -1;
#if defined(USING_VERSION_SDL3)
switch (event.gbutton.button)
#else
switch (event.jbutton.button)
#endif
{
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
@ -1819,7 +1828,11 @@ void PollInputEvents(void)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
#if defined(USING_VERSION_SDL3)
if (platform.gamepadId[i] == event.gbutton.which)
#else
if (platform.gamepadId[i] == event.jbutton.which)
#endif
{
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
@ -2054,14 +2067,11 @@ int InitPlatform(void)
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
}
int numJoysticks = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); // array of joystick IDs, they do not start from 0
int numJoysticks = SDL_NumJoysticks();
if (joysticks)
{
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
{
platform.gamepad[i] = SDL_GameControllerOpen(joysticks[i]);
platform.gamepad[i] = SDL_GameControllerOpen(i);
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
if (platform.gamepad[i])
@ -2075,8 +2085,6 @@ int InitPlatform(void)
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
SDL_free(joysticks);
}
// Disable mouse events being interpreted as touch events
// NOTE: This is wanted because there are SDL_FINGER* events available which provide unique data
@ -2196,7 +2204,7 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
{
SDL_Finger *finger = SDL_GetTouchFinger(event.touchId, i);
CORE.Input.Touch.pointId[i] = finger->id;
CORE.Input.Touch.pointId[i] = (int)finger->id;
CORE.Input.Touch.position[i].x = finger->x*CORE.Window.screen.width;
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
CORE.Input.Touch.currentTouchState[i] = 1;

View File

@ -54,11 +54,6 @@
typedef struct {
// TODO: Define the platform specific variables required
// Display data
EGLDisplay device; // Native display device (physical screen connection)
EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
EGLContext context; // Graphic context, mode in which drawing can be done
EGLConfig config; // Graphic config
} PlatformData;
//----------------------------------------------------------------------------------
@ -346,10 +341,10 @@ void SwapScreenBuffer(void)
double GetTime(void)
{
double time = 0.0;
struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
return time;
@ -366,7 +361,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: Load url using default browser
}
}
@ -462,86 +457,18 @@ int InitPlatform(void)
CORE.Window.fullscreen = true;
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
EGLint samples = 0;
EGLint sampleBuffer = 0;
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT))
{
samples = 4;
sampleBuffer = 1;
// TODO: Enable MSAA
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
}
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
EGL_NONE
};
// TODO: Init display and graphic device
const EGLint contextAttribs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLint numConfigs = 0;
// Get an EGL device connection
platform.device = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (platform.device == EGL_NO_DISPLAY)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
}
// Initialize the EGL device connection
if (eglInitialize(platform.device, NULL, NULL) == EGL_FALSE)
{
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
TRACELOG(LOG_WARNING, "DISPLAY: Failed to initialize EGL device");
return false;
}
// Get an appropriate EGL framebuffer configuration
eglChooseConfig(platform.device, framebufferAttribs, &platform.config, 1, &numConfigs);
// Set rendering API
eglBindAPI(EGL_OPENGL_ES_API);
// Create an EGL rendering context
platform.context = eglCreateContext(platform.device, platform.config, EGL_NO_CONTEXT, contextAttribs);
if (platform.context == EGL_NO_CONTEXT)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to create EGL context");
return -1;
}
// Create an EGL window surface
EGLint displayFormat = 0;
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry()
// As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
eglGetConfigAttrib(platform.device, platform.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
// Android specific call
ANativeWindow_setBuffersGeometry(platform.app->window, 0, 0, displayFormat); // Force use of native display size
platform.surface = eglCreateWindowSurface(platform.device, platform.config, platform.app->window, NULL);
// There must be at least one frame displayed before the buffers are swapped
eglSwapInterval(platform.device, 1);
EGLBoolean result = eglMakeCurrent(platform.device, platform.surface, platform.surface, platform.context);
// Check surface and context activation
if (result != EGL_FALSE)
// TODO: Check display, device and context activation
bool result = true;
if (result)
{
CORE.Window.ready = true;

View File

@ -1531,7 +1531,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
strcpy(CORE.Window.dropFilepaths[i], paths[i]);
strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -273,7 +273,7 @@
#define FLAG_SET(n, f) ((n) |= (f))
#define FLAG_CLEAR(n, f) ((n) &= ~(f))
#define FLAG_TOGGLE(n, f) ((n) ^= (f))
#define FLAG_IS_SET(n, f) (((n) & (f)) > 0)
#define FLAG_IS_SET(n, f) (((n) & (f)) == (f))
//----------------------------------------------------------------------------------
// Types and Structures Definition
@ -816,30 +816,22 @@ int GetScreenHeight(void)
// Get current render width which is equal to screen width*dpi scale
int GetRenderWidth(void)
{
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
int width = 0;
#if defined(__APPLE__)
Vector2 scale = GetWindowScaleDPI();
width = (int)((float)CORE.Window.render.width*scale.x);
#else
width = CORE.Window.render.width;
#endif
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
else width = CORE.Window.render.width;
return width;
}
// Get current screen height which is equal to screen height*dpi scale
int GetRenderHeight(void)
{
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
int height = 0;
#if defined(__APPLE__)
Vector2 scale = GetWindowScaleDPI();
height = (int)((float)CORE.Window.render.height*scale.y);
#else
height = CORE.Window.render.height;
#endif
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
else height = CORE.Window.render.height;
return height;
}
@ -1833,7 +1825,7 @@ void TakeScreenshot(const char *fileName)
// Apply a scale if we are doing HIGHDPI auto-scaling
Vector2 scale = { 1.0f, 1.0f };
if (IsWindowState(FLAG_WINDOW_HIGHDPI)) scale = GetWindowScaleDPI();
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) scale = GetWindowScaleDPI();
unsigned char *imgData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
@ -3823,14 +3815,7 @@ void SetupViewport(int width, int height)
CORE.Window.render.height = height;
// Set viewport width and height
// NOTE: We consider render size (scaled) and offset in case black bars are required and
// render area does not match full display area (this situation is only applicable on fullscreen mode)
#if defined(__APPLE__)
Vector2 scale = GetWindowScaleDPI();
rlViewport(CORE.Window.renderOffset.x/2*scale.x, CORE.Window.renderOffset.y/2*scale.y, (CORE.Window.render.width)*scale.x, (CORE.Window.render.height)*scale.y);
#else
rlViewport(CORE.Window.renderOffset.x/2, CORE.Window.renderOffset.y/2, CORE.Window.render.width, CORE.Window.render.height);
#endif
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlLoadIdentity(); // Reset current matrix (projection)

View File

@ -1762,11 +1762,6 @@ void rlTextureParameters(unsigned int id, int param, int value)
{
glBindTexture(GL_TEXTURE_2D, id);
#if !defined(GRAPHICS_API_OPENGL_11)
// Reset anisotropy filter, in case it was set
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
#endif
switch (param)
{
case RL_TEXTURE_WRAP_S:
@ -1786,6 +1781,9 @@ void rlTextureParameters(unsigned int id, int param, int value)
case RL_TEXTURE_FILTER_ANISOTROPIC:
{
#if !defined(GRAPHICS_API_OPENGL_11)
// Reset anisotropy filter, in case it was set
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
{
@ -3394,8 +3392,14 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Define thee maximum number of mipmap levels to be used, 0 is default texture size
// Define the maximum number of mipmap levels to be used, 0 is base texture size
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmapCount - 1);
// Check if the loaded texture with mipmaps is complete,
// uncomplete textures will draw in black if mipmap filtering is required
//GLint complete = 0;
//glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &complete);
}
#endif
@ -5220,24 +5224,36 @@ static int rlGetPixelDataSize(int width, int height, int format)
case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB:
case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB:
case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: // 8 bytes per each 4x4 block
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*8;
} break;
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 16 bytes per each 4x4 block
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*16;
} break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*4;
} break;
default: break;
}
// Compute dataSize for uncompressed texture data (no blocks)
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
{
double bytesPerPixel = (double)bpp/8.0;
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
// Most compressed formats works on 4x4 blocks,
// if texture is smaller, minimum dataSize is 8 or 16
if ((width < 4) && (height < 4))
{
if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
}
return dataSize;

View File

@ -132,6 +132,9 @@
#ifndef MAX_MESH_VERTEX_BUFFERS
#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
#endif
#ifndef MAX_FILEPATH_LENGTH
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition

View File

@ -700,7 +700,11 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
switch (type)
{
case FONT_DEFAULT:
case FONT_BITMAP: glyphs[k].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, cp, &cpWidth, &cpHeight, &glyphs[k].offsetX, &glyphs[k].offsetY); break;
case FONT_BITMAP:
{
glyphs[k].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, cp,
&cpWidth, &cpHeight, &glyphs[k].offsetX, &glyphs[k].offsetY);
} break;
case FONT_SDF:
{
if (cp != 32)
@ -1593,14 +1597,13 @@ float TextToFloat(const char *text)
#if defined(SUPPORT_TEXT_MANIPULATION)
// Copy one string to another, returns bytes copied
// NOTE: Alternative implementation to strcpy(dst, src) from C standard library
int TextCopy(char *dst, const char *src)
{
int bytes = 0;
if ((src != NULL) && (dst != NULL))
{
// NOTE: Alternative: use strcpy(dst, src)
while (*src != '\0')
{
*dst = *src;
@ -1713,11 +1716,13 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
{
char *insertPoint = NULL; // Next insert point
char *temp = NULL; // Temp pointer
int textLen = 0; // Text string length
int searchLen = 0; // Search string length of (the string to remove)
int replaceLen = 0; // Replacement length (the string to replace by)
int lastReplacePos = 0; // Distance between next search and end of last replace
int count = 0; // Number of replacements
textLen = TextLength(text);
searchLen = TextLength(search);
if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
@ -1728,7 +1733,8 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
for (count = 0; (temp = strstr(insertPoint, search)); count++) insertPoint = temp + searchLen;
// Allocate returning string and point temp to it
temp = result = (char *)RL_MALLOC(TextLength(text) + (replaceLen - searchLen)*count + 1);
int tempLen = textLen + (replaceLen - searchLen)*count + 1;
temp = result = (char *)RL_MALLOC(tempLen);
if (!result) return NULL; // Memory could not be allocated
@ -1740,13 +1746,16 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
{
insertPoint = (char *)strstr(text, search);
lastReplacePos = (int)(insertPoint - text);
temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
temp = strcpy(temp, replacement) + replaceLen;
temp = strncpy(temp, text, tempLen - 1) + lastReplacePos;
tempLen -= lastReplacePos;
temp = strncpy(temp, replacement, tempLen - 1) + replaceLen;
tempLen -= replaceLen;
text += lastReplacePos + searchLen; // Move to next "end of replace"
}
// Copy remaind text part after replacement to result (pointed by moving temp)
strcpy(temp, text);
strncpy(temp, text, tempLen - 1);
}
return result;
@ -2086,7 +2095,7 @@ int *LoadCodepoints(const char *text, int *count)
int textLength = TextLength(text);
// Allocate a big enough buffer to store as many codepoints as text bytes
int *codepoints = (int *)RL_CALLOC(textLength, sizeof(int));
codepoints = (int *)RL_CALLOC(textLength, sizeof(int));
int codepointSize = 0;
for (int i = 0; i < textLength; codepointCount++)