mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-25 10:22:33 -05:00
Compare commits
41 Commits
b465b4e2ea
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 101502103a | |||
| 20dd4641c8 | |||
| fc843dc557 | |||
| 9103f6e055 | |||
| ced84333a9 | |||
| 05f42aa119 | |||
| a1e84caa8c | |||
| ddb827fb6f | |||
| 0a4583ca54 | |||
| 6a701b2679 | |||
| aa2884bd78 | |||
| f27f2d097f | |||
| e4baf682ab | |||
| 8516750975 | |||
| 3212becc91 | |||
| b9446863d7 | |||
| 13f9112d8c | |||
| f16fb065ea | |||
| 66392fe0ae | |||
| 720dd22491 | |||
| ca578b8b08 | |||
| 4b760091da | |||
| 6d562e5e87 | |||
| 7553e9d586 | |||
| 80ad96acc2 | |||
| 7a5e8aa3a5 | |||
| 1c94e94873 | |||
| 33adda1983 | |||
| f031b2f4f4 | |||
| 1c7240a01d | |||
| cf0d6fc664 | |||
| 615fc36eeb | |||
| cbe31759ab | |||
| d74556d35c | |||
| 8d246fdaff | |||
| a0fd5ab1d9 | |||
| 9a337f3b3b | |||
| 5025009860 | |||
| 6f5cabf60c | |||
| c96669e123 | |||
| 9c04b1de82 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -58,6 +58,10 @@ packages/
|
|||||||
*.h.pch
|
*.h.pch
|
||||||
./*.obj
|
./*.obj
|
||||||
|
|
||||||
|
# Ignore SDL libs for testing
|
||||||
|
src/external/SDL2
|
||||||
|
src/external/SDL3
|
||||||
|
|
||||||
# Emscripten
|
# Emscripten
|
||||||
emsdk
|
emsdk
|
||||||
|
|
||||||
|
|||||||
@ -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-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 |
|
| [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) | **???** |
|
| [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 |
|
| [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-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 |
|
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
|
||||||
|
|||||||
18
SECURITY.md
Normal file
18
SECURITY.md
Normal 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._
|
||||||
12
build.zig
12
build.zig
@ -106,9 +106,9 @@ const config_h_flags = outer: {
|
|||||||
if (std.mem.startsWith(u8, line, "//")) continue;
|
if (std.mem.startsWith(u8, line, "//")) continue;
|
||||||
if (std.mem.startsWith(u8, line, "#if")) 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 = 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 = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
|
||||||
flag = "-D" ++ flag; // Prepend with -D
|
flag = "-D" ++ flag; // Prepend with -D
|
||||||
|
|
||||||
@ -155,9 +155,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a flag indicating the use of a custom `config.h`
|
|
||||||
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
|
|
||||||
if (options.config.len > 0) {
|
if (options.config.len > 0) {
|
||||||
|
// Sets a flag indicating the use of a custom `config.h`
|
||||||
|
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
|
||||||
// Splits a space-separated list of config flags into multiple flags
|
// Splits a space-separated list of config flags into multiple flags
|
||||||
//
|
//
|
||||||
// Note: This means certain flags like `-x c++` won't be processed properly.
|
// Note: This means certain flags like `-x c++` won't be processed properly.
|
||||||
@ -193,7 +193,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
|
|
||||||
// No GLFW required on PLATFORM_DRM
|
// No GLFW required on PLATFORM_DRM
|
||||||
if (options.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);
|
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.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) {
|
switch (target.result.os.tag) {
|
||||||
.windows => {
|
.windows => {
|
||||||
switch (options.platform) {
|
switch (options.platform) {
|
||||||
|
|||||||
@ -531,7 +531,7 @@ CORE = \
|
|||||||
core/core_delta_time \
|
core/core_delta_time \
|
||||||
core/core_directory_files \
|
core/core_directory_files \
|
||||||
core/core_drop_files \
|
core/core_drop_files \
|
||||||
core/core_high_dpi \
|
core/core_highdpi_demo \
|
||||||
core/core_highdpi_testbed \
|
core/core_highdpi_testbed \
|
||||||
core/core_input_actions \
|
core/core_input_actions \
|
||||||
core/core_input_gamepad \
|
core/core_input_gamepad \
|
||||||
|
|||||||
@ -519,7 +519,7 @@ CORE = \
|
|||||||
core/core_delta_time \
|
core/core_delta_time \
|
||||||
core/core_directory_files \
|
core/core_directory_files \
|
||||||
core/core_drop_files \
|
core/core_drop_files \
|
||||||
core/core_high_dpi \
|
core/core_highdpi_demo \
|
||||||
core/core_highdpi_testbed \
|
core/core_highdpi_testbed \
|
||||||
core/core_input_actions \
|
core/core_input_actions \
|
||||||
core/core_input_gamepad \
|
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
|
core/core_drop_files: core/core_drop_files.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
$(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)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||||
|
|
||||||
core/core_highdpi_testbed: core/core_highdpi_testbed.c
|
core/core_highdpi_testbed: core/core_highdpi_testbed.c
|
||||||
|
|||||||
@ -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_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_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_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_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_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) |
|
| [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) |
|
||||||
|
|||||||
@ -125,8 +125,8 @@ int main(void)
|
|||||||
DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f));
|
DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f));
|
||||||
DrawRectangleLines( 10, 10, 250, 113, BLUE);
|
DrawRectangleLines( 10, 10, 250, 113, BLUE);
|
||||||
|
|
||||||
DrawText("Free 2d camera controls:", 20, 20, 10, BLACK);
|
DrawText("Free 2D camera controls:", 20, 20, 10, BLACK);
|
||||||
DrawText("- Right/Left to move Offset", 40, 40, 10, DARKGRAY);
|
DrawText("- Right/Left to move player", 40, 40, 10, DARKGRAY);
|
||||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY);
|
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY);
|
||||||
DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY);
|
DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY);
|
||||||
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY);
|
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY);
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 8.3 KiB |
@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib [core] example - high dpi
|
* raylib [core] example - highdpi demo
|
||||||
*
|
*
|
||||||
* Example complexity rating: [★★☆☆] 2/4
|
* Example complexity rating: [★★☆☆] 2/4
|
||||||
*
|
*
|
||||||
@ -33,7 +33,7 @@ int main(void)
|
|||||||
const int screenHeight = 450;
|
const int screenHeight = 450;
|
||||||
|
|
||||||
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
|
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);
|
SetWindowMinSize(450, 450);
|
||||||
|
|
||||||
int logicalGridDescY = 120;
|
int logicalGridDescY = 120;
|
||||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
@ -27,9 +27,13 @@ int main(void)
|
|||||||
const int screenWidth = 800;
|
const int screenWidth = 800;
|
||||||
const int screenHeight = 450;
|
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");
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
|
||||||
|
|
||||||
|
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||||
|
Vector2 mousePos = GetMousePosition();
|
||||||
|
int currentMonitor = GetCurrentMonitor();
|
||||||
|
|
||||||
int gridSpacing = 40; // Grid spacing in pixels
|
int gridSpacing = 40; // Grid spacing in pixels
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
@ -40,7 +44,11 @@ int main(void)
|
|||||||
{
|
{
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// TODO: Update variables / Implement example logic at this point
|
mousePos = GetMousePosition();
|
||||||
|
currentMonitor = GetCurrentMonitor();
|
||||||
|
scaleDpi = GetWindowScaleDPI();
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_SPACE)) ToggleBorderlessWindowed();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
@ -50,11 +58,30 @@ int main(void)
|
|||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
// Draw grid
|
// Draw grid
|
||||||
for (int h = 0; h < 20; h++) DrawLine(0, h*gridSpacing, GetRenderWidth(), h*gridSpacing, LIGHTGRAY);
|
for (int h = 0; h < 20; h++)
|
||||||
for (int v = 0; v < 40; v++) DrawLine(v*gridSpacing, 0, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
|
{
|
||||||
|
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
|
// 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();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -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_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_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_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_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_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
|
||||||
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
|
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
|
||||||
|
|||||||
@ -316,7 +316,7 @@ void SliceTextParticle(TextParticle *tp, int particlePos, int sliceLength, TextP
|
|||||||
void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *tps, int *particleCount)
|
void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *tps, int *particleCount)
|
||||||
{
|
{
|
||||||
int tokenCount = 0;
|
int tokenCount = 0;
|
||||||
const char **tokens = TextSplit(tp->text, charToSlice, &tokenCount);
|
char **tokens = TextSplit(tp->text, charToSlice, &tokenCount);
|
||||||
|
|
||||||
if (tokenCount > 1)
|
if (tokenCount > 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "raymath.h" // Required for: Lerp()
|
#include "raymath.h" // Required for: Lerp()
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef enum TextAlignment {
|
typedef enum TextAlignment {
|
||||||
TEXT_ALIGN_LEFT = 0,
|
TEXT_ALIGN_LEFT = 0,
|
||||||
TEXT_ALIGN_TOP = 0,
|
TEXT_ALIGN_TOP = 0,
|
||||||
@ -58,7 +60,7 @@ int main(void)
|
|||||||
// And of course the font...
|
// And of course the font...
|
||||||
Font font = GetFontDefault();
|
Font font = GetFontDefault();
|
||||||
|
|
||||||
// Intialize the alignment variables
|
// Initialize the alignment variables
|
||||||
TextAlignment hAlign = TEXT_ALIGN_CENTRE;
|
TextAlignment hAlign = TEXT_ALIGN_CENTRE;
|
||||||
TextAlignment vAlign = TEXT_ALIGN_MIDDLE;
|
TextAlignment vAlign = TEXT_ALIGN_MIDDLE;
|
||||||
|
|
||||||
@ -72,8 +74,7 @@ int main(void)
|
|||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
if (IsKeyPressed(KEY_LEFT))
|
if (IsKeyPressed(KEY_LEFT))
|
||||||
{
|
{
|
||||||
hAlign = hAlign - 1;
|
if (hAlign > 0) hAlign = hAlign - 1;
|
||||||
if (hAlign < 0) hAlign = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_RIGHT))
|
if (IsKeyPressed(KEY_RIGHT))
|
||||||
@ -84,8 +85,7 @@ int main(void)
|
|||||||
|
|
||||||
if (IsKeyPressed(KEY_UP))
|
if (IsKeyPressed(KEY_UP))
|
||||||
{
|
{
|
||||||
vAlign = vAlign - 1;
|
if (vAlign > 0) vAlign = vAlign - 1;
|
||||||
if (vAlign < 0) vAlign = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_DOWN))
|
if (IsKeyPressed(KEY_DOWN))
|
||||||
@ -95,7 +95,8 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// One word per second
|
// One word per second
|
||||||
wordIndex = (int)GetTime()%wordCount;
|
if (wordCount > 0) wordIndex = (int)GetTime()%wordCount;
|
||||||
|
else wordIndex = 0;
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
@ -132,4 +133,4 @@ int main(void)
|
|||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -57,7 +57,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_custom_logging", "exam
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_drop_files", "examples\core_drop_files.vcxproj", "{0199E349-0701-40BC-8A7F-06A54FFA3E7C}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_drop_files", "examples\core_drop_files.vcxproj", "{0199E349-0701-40BC-8A7F-06A54FFA3E7C}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_gamepad", "examples\core_input_gamepad.vcxproj", "{8F19E3DA-8929-4000-87B5-3CA6929636CC}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_gamepad", "examples\core_input_gamepad.vcxproj", "{8F19E3DA-8929-4000-87B5-3CA6929636CC}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -5543,7 +5543,7 @@ Global
|
|||||||
{19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
{19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
||||||
{2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021}
|
{2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021}
|
||||||
{9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A}
|
{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}
|
{8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021}
|
||||||
{A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
|
{A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
|
||||||
{5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {278D8859-20B1-428F-8448-064F46E1F021}
|
{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}
|
{124935CC-73BB-489E-92E8-4F922A85DB5D} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
||||||
{AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021}
|
{AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021}
|
||||||
{0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} = {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}
|
{1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
||||||
{9DE2FC01-A839-4F89-8319-9071D4C54821} = {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}
|
{2F578155-D51F-4C03-AB7F-5C5122CA46CC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
||||||
|
|||||||
8
src/external/rl_gputex.h
vendored
8
src/external/rl_gputex.h
vendored
@ -308,7 +308,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
|
|||||||
unsigned char alpha = 0;
|
unsigned char alpha = 0;
|
||||||
|
|
||||||
// NOTE: Data comes as A1R5G5B5, it must be reordered to R5G5B5A1
|
// 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;
|
alpha = ((unsigned short *)image_data)[i] >> 15;
|
||||||
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 1;
|
((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;
|
unsigned char alpha = 0;
|
||||||
|
|
||||||
// NOTE: Data comes as A4R4G4B4, it must be reordered R4G4B4A4
|
// 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;
|
alpha = ((unsigned short *)image_data)[i] >> 12;
|
||||||
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 4;
|
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 4;
|
||||||
@ -339,7 +339,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed
|
else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed
|
||||||
{
|
{
|
||||||
int data_size = image_pixel_size*3*sizeof(unsigned char);
|
int data_size = image_pixel_size*3*sizeof(unsigned char);
|
||||||
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
|
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
|
||||||
@ -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)
|
// 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
|
// DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
|
||||||
// So, we must realign B8G8R8A8 to R8G8B8A8
|
// 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];
|
blue = ((unsigned char *)image_data)[i];
|
||||||
((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2];
|
((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2];
|
||||||
|
|||||||
8
src/external/rlsw.h
vendored
8
src/external/rlsw.h
vendored
@ -2217,7 +2217,7 @@ static inline bool sw_triangle_face_culling(void)
|
|||||||
const float *h2 = RLSW.vertexBuffer[2].homogeneous;
|
const float *h2 = RLSW.vertexBuffer[2].homogeneous;
|
||||||
|
|
||||||
// Compute a value proportional to the signed area in the projected 2D plane,
|
// Compute a value proportional to the signed area in the projected 2D plane,
|
||||||
// calculated directly using homogeneous coordinates BEFORE division by w.
|
// calculated directly using homogeneous coordinates BEFORE division by w
|
||||||
// This is the determinant of the matrix formed by the (x, y, w) components
|
// This is the determinant of the matrix formed by the (x, y, w) components
|
||||||
// of the vertices, which correctly captures the winding order in homogeneous
|
// of the vertices, which correctly captures the winding order in homogeneous
|
||||||
// space and its relationship to the projected 2D winding order, even with
|
// space and its relationship to the projected 2D winding order, even with
|
||||||
@ -2235,13 +2235,13 @@ static inline bool sw_triangle_face_culling(void)
|
|||||||
// Discard the triangle if its winding order (determined by the sign
|
// Discard the triangle if its winding order (determined by the sign
|
||||||
// of the homogeneous area/determinant) matches the culled direction
|
// of the homogeneous area/determinant) matches the culled direction
|
||||||
// A positive hSgnArea typically corresponds to a counter-clockwise
|
// A positive hSgnArea typically corresponds to a counter-clockwise
|
||||||
// winding in the projected space when all w > 0.
|
// winding in the projected space when all w > 0
|
||||||
// This test is robust for points with w > 0 or w < 0, correctly
|
// This test is robust for points with w > 0 or w < 0, correctly
|
||||||
// capturing the change in orientation when crossing the w=0 plane
|
// capturing the change in orientation when crossing the w=0 plane
|
||||||
|
|
||||||
// The culling logic remains the same based on the signed area/determinant
|
// The culling logic remains the same based on the signed area/determinant
|
||||||
// A value of 0 for hSgnArea means the points are collinear in (x, y, w)
|
// A value of 0 for hSgnArea means the points are collinear in (x, y, w)
|
||||||
// space, which corresponds to a degenerate triangle projection.
|
// space, which corresponds to a degenerate triangle projection
|
||||||
// Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
|
// Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
|
||||||
// and should be handled by the clipper if necessary
|
// and should be handled by the clipper if necessary
|
||||||
return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0) : (hSgnArea > 0); // Cull if winding is "clockwise" : "counter-clockwise"
|
return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0) : (hSgnArea > 0); // Cull if winding is "clockwise" : "counter-clockwise"
|
||||||
@ -2602,7 +2602,7 @@ static inline bool sw_quad_face_culling(void)
|
|||||||
// space, which corresponds to a degenerate triangle projection
|
// space, which corresponds to a degenerate triangle projection
|
||||||
// Such quads might also be degenerate or non-planar. They are typically
|
// Such quads might also be degenerate or non-planar. They are typically
|
||||||
// not culled by this test (0 < 0 is false, 0 > 0 is false)
|
// not culled by this test (0 < 0 is false, 0 > 0 is false)
|
||||||
// and should be handled by the clipper if necessary.
|
// and should be handled by the clipper if necessary
|
||||||
|
|
||||||
return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0.0f) : (hSgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
|
return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0.0f) : (hSgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -357,13 +357,17 @@ void RestoreWindow(void)
|
|||||||
// Set window configuration state using flags
|
// Set window configuration state using flags
|
||||||
void SetWindowState(unsigned int 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
|
// Clear window configuration state flags
|
||||||
void ClearWindowState(unsigned int 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
|
// Set icon for window
|
||||||
@ -601,7 +605,7 @@ void DisableCursor(void)
|
|||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
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;
|
int pollEvents = 0;
|
||||||
|
|
||||||
// Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
|
// 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)
|
// 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? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
|
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
|
// Process this event
|
||||||
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||||
@ -1162,8 +1166,8 @@ static GamepadButton AndroidTranslateGamepadButton(int button)
|
|||||||
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
{
|
{
|
||||||
// If additional inputs are required check:
|
// If additional inputs are required check:
|
||||||
// Ref: https://developer.android.com/ndk/reference/group/input
|
// REF: https://developer.android.com/ndk/reference/group/input
|
||||||
// Ref: https://developer.android.com/training/game-controllers/controller-input
|
// REF: https://developer.android.com/training/game-controllers/controller-input
|
||||||
|
|
||||||
int type = AInputEvent_getType(event);
|
int type = AInputEvent_getType(event);
|
||||||
int source = AInputEvent_getSource(event);
|
int source = AInputEvent_getSource(event);
|
||||||
|
|||||||
@ -134,12 +134,13 @@ static void ErrorCallback(int error, const char *description);
|
|||||||
|
|
||||||
// Window callbacks events
|
// Window callbacks events
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
||||||
static void WindowPosCallback(GLFWwindow* window, int x, int y); // GLFW3 WindowPos Callback, runs when window is moved
|
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 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 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 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 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
|
// Input callbacks events
|
||||||
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
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 *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 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
|
// 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);
|
glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -231,22 +229,22 @@ void ToggleBorderlessWindowed(void)
|
|||||||
bool wasOnFullscreen = false;
|
bool wasOnFullscreen = false;
|
||||||
if (CORE.Window.fullscreen)
|
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();
|
ToggleFullscreen();
|
||||||
wasOnFullscreen = true;
|
wasOnFullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int monitor = GetCurrentMonitor();
|
int monitorCount = 0;
|
||||||
int monitorCount;
|
|
||||||
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
||||||
|
const int monitor = GetCurrentMonitor();
|
||||||
|
|
||||||
if ((monitor >= 0) && (monitor < monitorCount))
|
if ((monitor >= 0) && (monitor < monitorCount))
|
||||||
{
|
{
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
|
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
|
// Store screen position and size
|
||||||
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
|
// 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);
|
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
|
||||||
FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNDECORATED);
|
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
|
// 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
|
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
|
||||||
glfwSetWindowMonitor(
|
glfwSetWindowMonitor(
|
||||||
@ -475,13 +483,13 @@ void ClearWindowState(unsigned int flags)
|
|||||||
// NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running
|
// NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running
|
||||||
if ((FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE)) && (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE)))
|
if ((FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE)) && (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE)))
|
||||||
{
|
{
|
||||||
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
|
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_FULLSCREEN_MODE
|
// State change: FLAG_FULLSCREEN_MODE
|
||||||
if ((FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) && (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE)))
|
if ((FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) && (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE)))
|
||||||
{
|
{
|
||||||
ToggleFullscreen(); // NOTE: Window state flag updated inside function
|
ToggleFullscreen(); // NOTE: Window state flag updated inside function
|
||||||
}
|
}
|
||||||
|
|
||||||
// State change: FLAG_WINDOW_RESIZABLE
|
// State change: FLAG_WINDOW_RESIZABLE
|
||||||
@ -894,7 +902,8 @@ Vector2 GetMonitorPosition(int monitor)
|
|||||||
|
|
||||||
if ((monitor >= 0) && (monitor < monitorCount))
|
if ((monitor >= 0) && (monitor < monitorCount))
|
||||||
{
|
{
|
||||||
int x, y;
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
glfwGetMonitorPos(monitors[monitor], &x, &y);
|
glfwGetMonitorPos(monitors[monitor], &x, &y);
|
||||||
|
|
||||||
return (Vector2){ (float)x, (float)y };
|
return (Vector2){ (float)x, (float)y };
|
||||||
@ -1015,8 +1024,8 @@ Vector2 GetWindowPosition(void)
|
|||||||
// Get window scale DPI factor for current monitor
|
// Get window scale DPI factor for current monitor
|
||||||
Vector2 GetWindowScaleDPI(void)
|
Vector2 GetWindowScaleDPI(void)
|
||||||
{
|
{
|
||||||
Vector2 scale = { 0 };
|
Vector2 scale = { 1.0f, 1.0f };
|
||||||
glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,7 +1131,7 @@ double GetTime(void)
|
|||||||
// NOTE: This function is only safe to use if you control the URL given
|
// NOTE: This function is only safe to use if you control the URL given
|
||||||
// A user could craft a malicious string performing another action
|
// A user could craft a malicious string performing another action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself
|
// Only call this function yourself not with user input or make sure to check the string yourself
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// REF: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
@ -1234,8 +1243,8 @@ void PollInputEvents(void)
|
|||||||
// Map touch position to mouse position for convenience
|
// Map touch position to mouse position for convenience
|
||||||
// WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!
|
// WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!
|
||||||
// TODO: GLFW does not support multi-touch input yet
|
// TODO: GLFW does not support multi-touch input yet
|
||||||
// Ref: https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
// REF: https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
|
||||||
// Ref: https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
// REF: https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
|
||||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
// Check if gamepads are ready
|
// Check if gamepads are ready
|
||||||
@ -1328,7 +1337,8 @@ void PollInputEvents(void)
|
|||||||
|
|
||||||
CORE.Window.resizedLastFrame = false;
|
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)
|
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
||||||
CORE.Time.previous = GetTime();
|
CORE.Time.previous = GetTime();
|
||||||
@ -1347,7 +1357,7 @@ void PollInputEvents(void)
|
|||||||
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
|
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
|
||||||
// We need to provide these because GLFWallocator expects function pointers with specific signatures
|
// We need to provide these because GLFWallocator expects function pointers with specific signatures
|
||||||
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch
|
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch
|
||||||
// Ref: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
// REF: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
||||||
static void *AllocateWrapper(size_t size, void *user)
|
static void *AllocateWrapper(size_t size, void *user)
|
||||||
{
|
{
|
||||||
(void)user;
|
(void)user;
|
||||||
@ -1433,31 +1443,27 @@ int InitPlatform(void)
|
|||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
|
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
|
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))
|
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__)
|
#if defined(__APPLE__)
|
||||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
|
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
|
||||||
#endif
|
#endif
|
||||||
// Resize window content area based on the monitor content scale
|
// 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
|
// 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__)
|
#if defined(__APPLE__)
|
||||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||||
#endif
|
#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
|
// Mouse passthrough
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MOUSE_PASSTHROUGH)) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MOUSE_PASSTHROUGH)) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
||||||
@ -1527,17 +1533,24 @@ int InitPlatform(void)
|
|||||||
GLFWmonitor *monitor = NULL;
|
GLFWmonitor *monitor = NULL;
|
||||||
if (CORE.Window.fullscreen)
|
if (CORE.Window.fullscreen)
|
||||||
{
|
{
|
||||||
// According to glfwCreateWindow(), if the user does not have a choice, fullscreen applications
|
// NOTE: Fullscreen applications default to the primary monitor
|
||||||
// should default to the primary monitor
|
|
||||||
|
|
||||||
monitor = glfwGetPrimaryMonitor();
|
monitor = glfwGetPrimaryMonitor();
|
||||||
if (!monitor)
|
if (!monitor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");
|
||||||
return -1;
|
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
|
// 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))
|
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
|
||||||
@ -1626,7 +1639,15 @@ int InitPlatform(void)
|
|||||||
if (monitorIndex < monitorCount)
|
if (monitorIndex < monitorCount)
|
||||||
{
|
{
|
||||||
monitor = monitors[monitorIndex];
|
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);
|
if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
}
|
}
|
||||||
@ -1638,6 +1659,7 @@ int InitPlatform(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Not considering scale factor now, considered below
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
}
|
}
|
||||||
@ -1668,16 +1690,15 @@ int InitPlatform(void)
|
|||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||||
{
|
{
|
||||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
|
// 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);
|
// Framebuffer scaling is activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||||
#if !defined(__APPLE__)
|
|
||||||
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
||||||
|
|
||||||
// Screen scaling matrix is required in case desired screen area is different from display area
|
// 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);
|
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
|
// Mouse input scaling for the new screen size
|
||||||
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
|
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.render.width = fbWidth;
|
CORE.Window.render.width = fbWidth;
|
||||||
@ -1734,28 +1755,24 @@ int InitPlatform(void)
|
|||||||
// Initialize input events callbacks
|
// Initialize input events callbacks
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Set window callback events
|
// 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);
|
glfwSetWindowPosCallback(platform.handle, WindowPosCallback);
|
||||||
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
|
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
|
||||||
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
|
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
|
||||||
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
|
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
|
||||||
glfwSetDropCallback(platform.handle, WindowDropCallback);
|
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
|
// Set input callback events
|
||||||
glfwSetKeyCallback(platform.handle, KeyCallback);
|
glfwSetKeyCallback(platform.handle, KeyCallback);
|
||||||
glfwSetCharCallback(platform.handle, CharCallback);
|
glfwSetCharCallback(platform.handle, CharCallback);
|
||||||
glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);
|
glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);
|
||||||
glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes
|
glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes
|
||||||
glfwSetScrollCallback(platform.handle, MouseScrollCallback);
|
glfwSetScrollCallback(platform.handle, MouseScrollCallback);
|
||||||
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
|
glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);
|
||||||
glfwSetJoystickCallback(JoystickCallback);
|
glfwSetJoystickCallback(JoystickCallback);
|
||||||
|
glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)
|
||||||
glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)
|
|
||||||
|
|
||||||
// Retrieve gamepad names
|
// Retrieve gamepad names
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
@ -1813,79 +1830,116 @@ void ClosePlatform(void)
|
|||||||
#endif
|
#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)
|
static void ErrorCallback(int error, const char *description)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, 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()
|
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
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,
|
// WARNING: On window minimization, callback is called,
|
||||||
// but we don't want to change internal screen values, it breaks things
|
// but we don't want to change internal screen values, it breaks things
|
||||||
if ((width == 0) || (height == 0)) return;
|
if ((width == 0) || (height == 0)) return;
|
||||||
|
|
||||||
// Reset viewport and projection matrix for new size
|
// Reset viewport and projection matrix for new size
|
||||||
|
// NOTE: Stores current render size: CORE.Window.render
|
||||||
SetupViewport(width, height);
|
SetupViewport(width, height);
|
||||||
|
|
||||||
|
// Set render size
|
||||||
CORE.Window.currentFbo.width = width;
|
CORE.Window.currentFbo.width = width;
|
||||||
CORE.Window.currentFbo.height = height;
|
CORE.Window.currentFbo.height = height;
|
||||||
CORE.Window.resizedLastFrame = true;
|
CORE.Window.resizedLastFrame = true;
|
||||||
|
|
||||||
if (IsWindowFullscreen()) return;
|
// Check if render size was actually scaled for high-dpi
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
|
||||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
|
||||||
{
|
{
|
||||||
width = (int)(width/GetWindowScaleDPI().x);
|
// Set screen size to logical pixel size, considering content scaling
|
||||||
height = (int)(height/GetWindowScaleDPI().y);
|
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||||
|
CORE.Window.screen.width = (int)((float)width/scaleDpi.x);
|
||||||
|
CORE.Window.screen.height = (int)((float)height/scaleDpi.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set screen size to render size (physical pixel size)
|
||||||
|
CORE.Window.screen.width = width;
|
||||||
|
CORE.Window.screen.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set render size
|
|
||||||
CORE.Window.render.width = width;
|
|
||||||
CORE.Window.render.height = height;
|
|
||||||
|
|
||||||
// Set current screen size
|
|
||||||
CORE.Window.screen.width = width;
|
|
||||||
CORE.Window.screen.height = height;
|
|
||||||
|
|
||||||
// WARNING: If using a render texture, it is not scaled to new size
|
// WARNING: If using a render texture, it is not scaled to new size
|
||||||
}
|
}
|
||||||
static void WindowPosCallback(GLFWwindow* window, int x, int y)
|
|
||||||
|
// 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
|
// Set current window position
|
||||||
CORE.Window.position.x = x;
|
CORE.Window.position.x = x;
|
||||||
CORE.Window.position.y = y;
|
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)
|
static void WindowIconifyCallback(GLFWwindow *window, int iconified)
|
||||||
{
|
{
|
||||||
if (iconified) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED); // The window was 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
|
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)
|
static void WindowMaximizeCallback(GLFWwindow *window, int maximized)
|
||||||
{
|
{
|
||||||
if (maximized) FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED); // The window was 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
|
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)
|
static void WindowFocusCallback(GLFWwindow *window, int focused)
|
||||||
{
|
{
|
||||||
if (focused) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); // The window was 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
|
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)
|
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
|
||||||
{
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@ -1908,12 +1962,12 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
|||||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
||||||
{
|
{
|
||||||
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
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)
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (key < 0) return; // Security check, macOS fn key generates -1
|
if (key < 0) return; // Security check, macOS fn key generates -1
|
||||||
@ -1940,13 +1994,13 @@ 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);
|
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)
|
static void CharCallback(GLFWwindow *window, unsigned int codepoint)
|
||||||
{
|
{
|
||||||
// NOTE: Registers any key down considering OS keyboard layout but
|
// NOTE: Registers any key down considering OS keyboard layout but
|
||||||
// does not detect action events, those should be managed by user...
|
// does not detect action events, those should be managed by user...
|
||||||
// Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
// REF: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
||||||
// Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char
|
// REF: https://www.glfw.org/docs/latest/input_guide.html#input_char
|
||||||
|
|
||||||
// Check if there is space available in the queue
|
// Check if there is space available in the queue
|
||||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
||||||
@ -1957,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)
|
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,
|
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
|
||||||
@ -1993,7 +2047,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
|
|||||||
#endif
|
#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)
|
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentPosition.x = (float)x;
|
CORE.Input.Mouse.currentPosition.x = (float)x;
|
||||||
@ -2024,20 +2078,20 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
|||||||
#endif
|
#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)
|
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentWheelMove = (Vector2){ (float)xoffset, (float)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)
|
static void CursorEnterCallback(GLFWwindow *window, int enter)
|
||||||
{
|
{
|
||||||
if (enter) CORE.Input.Mouse.cursorOnScreen = true;
|
if (enter) CORE.Input.Mouse.cursorOnScreen = true;
|
||||||
else CORE.Input.Mouse.cursorOnScreen = false;
|
else CORE.Input.Mouse.cursorOnScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Joystick Connected/Disconnected Callback
|
// GLFW3: Joystick connected/disconnected callback
|
||||||
static void JoystickCallback(int jid, int event)
|
static void JoystickCallback(int jid, int event)
|
||||||
{
|
{
|
||||||
if (event == GLFW_CONNECTED)
|
if (event == GLFW_CONNECTED)
|
||||||
@ -2053,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
|
#ifdef _WIN32
|
||||||
# define WIN32_CLIPBOARD_IMPLEMENTATION
|
# define WIN32_CLIPBOARD_IMPLEMENTATION
|
||||||
# include "../external/win32_clipboard.h"
|
# include "../external/win32_clipboard.h"
|
||||||
|
|||||||
@ -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)
|
#if defined(PLATFORM_WEB_RGFW)
|
||||||
#define RGFW_NO_GL_HEADER
|
#define RGFW_NO_GL_HEADER
|
||||||
#endif
|
#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
|
// Set icon for window
|
||||||
void SetWindowIcon(Image image)
|
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
|
// Set icon for window
|
||||||
@ -583,12 +547,17 @@ void SetWindowIcons(Image *images, int count)
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
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 ((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) || ((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 (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), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar);
|
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), 4, RGFW_iconTaskbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,7 +57,7 @@
|
|||||||
// SDL base library (window/rendered, input, timing... functionality)
|
// SDL base library (window/rendered, input, timing... functionality)
|
||||||
#ifdef USING_SDL3_PROJECT
|
#ifdef USING_SDL3_PROJECT
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
#elif USING_SDL2_PROJECT
|
#elif defined(USING_SDL2_PROJECT)
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
#else
|
#else
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
@ -71,7 +71,7 @@
|
|||||||
// SDL OpenGL functionality (if required, instead of internal renderer)
|
// SDL OpenGL functionality (if required, instead of internal renderer)
|
||||||
#ifdef USING_SDL3_PROJECT
|
#ifdef USING_SDL3_PROJECT
|
||||||
#include "SDL3/SDL_opengl.h"
|
#include "SDL3/SDL_opengl.h"
|
||||||
#elif USING_SDL2_PROJECT
|
#elif defined(USING_SDL2_PROJECT)
|
||||||
#include "SDL2/SDL_opengl.h"
|
#include "SDL2/SDL_opengl.h"
|
||||||
#else
|
#else
|
||||||
#include "SDL_opengl.h"
|
#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");
|
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
|
// 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");
|
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_DisplayMode mode;
|
||||||
SDL_GetCurrentDisplayMode(monitor, &mode);
|
SDL_GetCurrentDisplayMode(monitor, &mode);
|
||||||
// Calculate size on inches, then convert to millimeter
|
// 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");
|
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
|
||||||
|
|
||||||
@ -1065,7 +1066,7 @@ int GetMonitorPhysicalHeight(int monitor)
|
|||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
SDL_GetCurrentDisplayMode(monitor, &mode);
|
SDL_GetCurrentDisplayMode(monitor, &mode);
|
||||||
// Calculate size on inches, then convert to millimeter
|
// 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");
|
else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor");
|
||||||
|
|
||||||
@ -1127,14 +1128,15 @@ Vector2 GetWindowScaleDPI(void)
|
|||||||
{
|
{
|
||||||
Vector2 scale = { 1.0f, 1.0f };
|
Vector2 scale = { 1.0f, 1.0f };
|
||||||
|
|
||||||
#ifndef USING_VERSION_SDL3
|
#if defined(USING_VERSION_SDL3)
|
||||||
// NOTE: SDL_GetWindowDisplayScale was only added on SDL3
|
// NOTE: SDL_GetWindowDisplayScale added on SDL3
|
||||||
// Ref: https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale
|
// 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.x = SDL_GetWindowDisplayScale(platform.window);
|
||||||
scale.y = scale.x;
|
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
|
#endif
|
||||||
|
|
||||||
return scale;
|
return scale;
|
||||||
@ -1195,7 +1197,7 @@ Image GetClipboardImage(void)
|
|||||||
|
|
||||||
if (fileData)
|
if (fileData)
|
||||||
{
|
{
|
||||||
image = LoadImageFromMemory(imageExtensions[i], fileData, dataSize);
|
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
|
||||||
if (IsImageValid(image))
|
if (IsImageValid(image))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
|
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
|
||||||
@ -1279,7 +1281,7 @@ double GetTime(void)
|
|||||||
// NOTE: This function is only safe to use if you control the URL given
|
// NOTE: This function is only safe to use if you control the URL given
|
||||||
// A user could craft a malicious string performing another action
|
// A user could craft a malicious string performing another action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself
|
// Only call this function yourself not with user input or make sure to check the string yourself
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// REF: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
@ -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,
|
// 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,
|
// 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
|
// 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
|
#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);
|
SDL_free(event.drop.file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1442,9 +1444,9 @@ void PollInputEvents(void)
|
|||||||
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||||
|
|
||||||
#if defined(USING_VERSION_SDL3)
|
#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
|
#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);
|
SDL_free(event.drop.file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1454,7 +1456,7 @@ void PollInputEvents(void)
|
|||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Window events are also polled (Minimized, maximized, close...)
|
// Window events are also polled (minimized, maximized, close...)
|
||||||
|
|
||||||
#ifndef USING_VERSION_SDL3
|
#ifndef USING_VERSION_SDL3
|
||||||
// SDL3 states:
|
// SDL3 states:
|
||||||
@ -1473,7 +1475,7 @@ void PollInputEvents(void)
|
|||||||
const int height = event.window.data2;
|
const int height = event.window.data2;
|
||||||
SetupViewport(width, height);
|
SetupViewport(width, height);
|
||||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
// 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.width = (int)(width/GetWindowScaleDPI().x);
|
||||||
CORE.Window.screen.height = (int)(height/GetWindowScaleDPI().y);
|
CORE.Window.screen.height = (int)(height/GetWindowScaleDPI().y);
|
||||||
@ -1488,7 +1490,8 @@ void PollInputEvents(void)
|
|||||||
CORE.Window.resizedLastFrame = true;
|
CORE.Window.resizedLastFrame = true;
|
||||||
|
|
||||||
#ifndef USING_VERSION_SDL3
|
#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))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED))
|
||||||
{
|
{
|
||||||
int borderTop = 0;
|
int borderTop = 0;
|
||||||
@ -1504,14 +1507,8 @@ void PollInputEvents(void)
|
|||||||
#endif
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_ENTER:
|
case SDL_WINDOWEVENT_ENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
|
||||||
{
|
case SDL_WINDOWEVENT_LEAVE: CORE.Input.Mouse.cursorOnScreen = false; break;
|
||||||
CORE.Input.Mouse.cursorOnScreen = true;
|
|
||||||
} break;
|
|
||||||
case SDL_WINDOWEVENT_LEAVE:
|
|
||||||
{
|
|
||||||
CORE.Input.Mouse.cursorOnScreen = false;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_MINIMIZED:
|
case SDL_WINDOWEVENT_MINIMIZED:
|
||||||
{
|
{
|
||||||
@ -1750,7 +1747,11 @@ void PollInputEvents(void)
|
|||||||
{
|
{
|
||||||
int button = -1;
|
int button = -1;
|
||||||
|
|
||||||
|
#if defined(USING_VERSION_SDL3)
|
||||||
switch (event.gbutton.button)
|
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_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
|
||||||
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; 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++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
|
#if defined(USING_VERSION_SDL3)
|
||||||
if (platform.gamepadId[i] == event.gbutton.which)
|
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.currentButtonState[i][button] = 1;
|
||||||
CORE.Input.Gamepad.lastButtonPressed = button;
|
CORE.Input.Gamepad.lastButtonPressed = button;
|
||||||
@ -1791,7 +1796,11 @@ void PollInputEvents(void)
|
|||||||
{
|
{
|
||||||
int button = -1;
|
int button = -1;
|
||||||
|
|
||||||
|
#if defined(USING_VERSION_SDL3)
|
||||||
switch (event.gbutton.button)
|
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_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
|
||||||
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; 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++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
|
#if defined(USING_VERSION_SDL3)
|
||||||
if (platform.gamepadId[i] == event.gbutton.which)
|
if (platform.gamepadId[i] == event.gbutton.which)
|
||||||
|
#else
|
||||||
|
if (platform.gamepadId[i] == event.jbutton.which)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
|
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
|
||||||
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||||
@ -2054,28 +2067,23 @@ int InitPlatform(void)
|
|||||||
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
|
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
|
||||||
}
|
}
|
||||||
|
|
||||||
int numJoysticks = 0;
|
int numJoysticks = SDL_NumJoysticks();
|
||||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); // array of joystick IDs, they do not start from 0
|
|
||||||
|
|
||||||
if (joysticks)
|
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
|
platform.gamepad[i] = SDL_GameControllerOpen(i);
|
||||||
{
|
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
|
||||||
platform.gamepad[i] = SDL_GameControllerOpen(joysticks[i]);
|
|
||||||
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
|
|
||||||
|
|
||||||
if (platform.gamepad[i])
|
if (platform.gamepad[i])
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.ready[i] = true;
|
CORE.Input.Gamepad.ready[i] = true;
|
||||||
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(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_LEFT_TRIGGER] = -1.0f;
|
||||||
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
||||||
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||||
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
|
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
|
||||||
}
|
|
||||||
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
|
|
||||||
}
|
}
|
||||||
SDL_free(joysticks);
|
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable mouse events being interpreted as touch events
|
// Disable mouse events being interpreted as touch events
|
||||||
@ -2196,7 +2204,7 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
|
|||||||
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
|
for (int i = 0; i < CORE.Input.Touch.pointCount; i++)
|
||||||
{
|
{
|
||||||
SDL_Finger *finger = SDL_GetTouchFinger(event.touchId, 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].x = finger->x*CORE.Window.screen.width;
|
||||||
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
|
CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height;
|
||||||
CORE.Input.Touch.currentTouchState[i] = 1;
|
CORE.Input.Touch.currentTouchState[i] = 1;
|
||||||
|
|||||||
@ -1239,7 +1239,7 @@ double GetTime(void)
|
|||||||
// NOTE: This function is only safe to use if you control the URL given
|
// NOTE: This function is only safe to use if you control the URL given
|
||||||
// A user could craft a malicious string performing another action
|
// A user could craft a malicious string performing another action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself
|
// Only call this function yourself not with user input or make sure to check the string yourself
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// REF: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code on target platform
|
||||||
|
|||||||
@ -220,7 +220,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = {
|
|||||||
248, 0, 0, 0, 0, 0, 0, 0,
|
248, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
// Gamepads are mapped according to:
|
// Gamepads are mapped according to:
|
||||||
// Ref: https://www.kernel.org/doc/html/next/input/gamepad.html
|
// REF: https://www.kernel.org/doc/html/next/input/gamepad.html
|
||||||
// Those mappings are standardized, but that doesn't mean people follow
|
// Those mappings are standardized, but that doesn't mean people follow
|
||||||
// the standards, so this is more of an approximation
|
// the standards, so this is more of an approximation
|
||||||
[BTN_DPAD_UP] = GAMEPAD_BUTTON_LEFT_FACE_UP,
|
[BTN_DPAD_UP] = GAMEPAD_BUTTON_LEFT_FACE_UP,
|
||||||
@ -1013,7 +1013,7 @@ double GetTime(void)
|
|||||||
// NOTE: This function is only safe to use if you control the URL given
|
// NOTE: This function is only safe to use if you control the URL given
|
||||||
// A user could craft a malicious string performing another action
|
// A user could craft a malicious string performing another action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself
|
// Only call this function yourself not with user input or make sure to check the string yourself
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// REF: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
|
||||||
|
|||||||
@ -383,7 +383,7 @@ double GetTime(void)
|
|||||||
// NOTE: This function is only safe to use if you control the URL given.
|
// NOTE: This function is only safe to use if you control the URL given.
|
||||||
// A user could craft a malicious string performing another action.
|
// A user could craft a malicious string performing another action.
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself.
|
// Only call this function yourself not with user input or make sure to check the string yourself.
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// REF: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code on target platform
|
||||||
@ -428,7 +428,7 @@ void SetMouseCursor(int cursor)
|
|||||||
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get physical key name.
|
// Get physical key name
|
||||||
const char *GetKeyName(int key)
|
const char *GetKeyName(int key)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
|
||||||
|
|||||||
@ -54,11 +54,6 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
// TODO: Define the platform specific variables required
|
// 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;
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -346,10 +341,10 @@ void SwapScreenBuffer(void)
|
|||||||
double GetTime(void)
|
double GetTime(void)
|
||||||
{
|
{
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
|
|
||||||
struct timespec ts = { 0 };
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
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;
|
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()
|
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||||
|
|
||||||
return time;
|
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");
|
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO: Load url using default browser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,86 +457,18 @@ int InitPlatform(void)
|
|||||||
CORE.Window.fullscreen = true;
|
CORE.Window.fullscreen = true;
|
||||||
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
|
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))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT))
|
||||||
{
|
{
|
||||||
samples = 4;
|
// TODO: Enable MSAA
|
||||||
sampleBuffer = 1;
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
|
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
|
||||||
}
|
}
|
||||||
|
|
||||||
const EGLint framebufferAttribs[] =
|
// TODO: Init display and graphic device
|
||||||
{
|
|
||||||
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
|
|
||||||
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
|
|
||||||
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
|
|
||||||
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
|
||||||
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
|
||||||
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
|
||||||
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
|
||||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
|
||||||
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
const EGLint contextAttribs[] =
|
// TODO: Check display, device and context activation
|
||||||
{
|
bool result = true;
|
||||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
if (result)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
CORE.Window.ready = true;
|
CORE.Window.ready = true;
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,13 @@ typedef struct {
|
|||||||
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen
|
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen
|
||||||
int unmaximizedWidth; // Internal var to store the unmaximized window (canvas) width
|
int unmaximizedWidth; // Internal var to store the unmaximized window (canvas) width
|
||||||
int unmaximizedHeight; // Internal var to store the unmaximized window (canvas) height
|
int unmaximizedHeight; // Internal var to store the unmaximized window (canvas) height
|
||||||
|
|
||||||
|
char canvasId[64]; // Keep current canvas id where wasm app is running
|
||||||
|
// NOTE: Useful when trying to run multiple wasms in different canvases in same webpage
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
|
||||||
|
unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format)
|
||||||
|
#endif
|
||||||
} PlatformData;
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -129,7 +136,7 @@ static void MouseEnterCallback(GLFWwindow *window, int enter);
|
|||||||
|
|
||||||
// Emscripten window callback events
|
// Emscripten window callback events
|
||||||
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
||||||
// static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
//static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
||||||
static EM_BOOL EmscriptenFocusCallback(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
|
static EM_BOOL EmscriptenFocusCallback(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenVisibilityChangeCallback(int eventType, const EmscriptenVisibilityChangeEvent *visibilityChangeEvent, void *userData);
|
static EM_BOOL EmscriptenVisibilityChangeCallback(int eventType, const EmscriptenVisibilityChangeEvent *visibilityChangeEvent, void *userData);
|
||||||
@ -142,7 +149,11 @@ static EM_BOOL EmscriptenPointerlockCallback(int eventType, const EmscriptenPoin
|
|||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
||||||
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
||||||
|
|
||||||
static const char *GetCanvasId(void);
|
// JS: Set the canvas id provided by the module configuration
|
||||||
|
EM_JS(void, SetCanvasIdJs, (char *out, int outSize), {
|
||||||
|
var canvasId = "#" + Module.canvas.id;
|
||||||
|
stringToUTF8(canvasId, out, outSize);
|
||||||
|
});
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
@ -159,7 +170,7 @@ static const char *GetCanvasId(void);
|
|||||||
bool WindowShouldClose(void)
|
bool WindowShouldClose(void)
|
||||||
{
|
{
|
||||||
// Emscripten Asyncify is required to run synchronous code in asynchronous JS
|
// Emscripten Asyncify is required to run synchronous code in asynchronous JS
|
||||||
// Ref: https://emscripten.org/docs/porting/asyncify.html
|
// REF: https://emscripten.org/docs/porting/asyncify.html
|
||||||
|
|
||||||
// WindowShouldClose() is not called on a web-ready raylib application if using emscripten_set_main_loop()
|
// WindowShouldClose() is not called on a web-ready raylib application if using emscripten_set_main_loop()
|
||||||
// and encapsulating one frame execution on a UpdateDrawFrame() function,
|
// and encapsulating one frame execution on a UpdateDrawFrame() function,
|
||||||
@ -233,11 +244,11 @@ void ToggleFullscreen(void)
|
|||||||
// This option does not seem to work at all:
|
// This option does not seem to work at all:
|
||||||
// emscripten_request_pointerlock() and emscripten_request_fullscreen() are affected by web security,
|
// emscripten_request_pointerlock() and emscripten_request_fullscreen() are affected by web security,
|
||||||
// the user must click once on the canvas to hide the pointer or transition to full screen
|
// the user must click once on the canvas to hide the pointer or transition to full screen
|
||||||
//emscripten_request_fullscreen("#canvas", false);
|
//emscripten_request_fullscreen(platform.canvasId, false);
|
||||||
|
|
||||||
// Option 2: Request fullscreen for the canvas element with strategy
|
// Option 2: Request fullscreen for the canvas element with strategy
|
||||||
// This option does not seem to work at all
|
// This option does not seem to work at all
|
||||||
// Ref: https://github.com/emscripten-core/emscripten/issues/5124
|
// REF: https://github.com/emscripten-core/emscripten/issues/5124
|
||||||
// EmscriptenFullscreenStrategy strategy = {
|
// EmscriptenFullscreenStrategy strategy = {
|
||||||
// .scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH, //EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT,
|
// .scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH, //EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT,
|
||||||
// .canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF,
|
// .canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF,
|
||||||
@ -245,7 +256,7 @@ void ToggleFullscreen(void)
|
|||||||
// .canvasResizedCallback = EmscriptenWindowResizedCallback,
|
// .canvasResizedCallback = EmscriptenWindowResizedCallback,
|
||||||
// .canvasResizedCallbackUserData = NULL
|
// .canvasResizedCallbackUserData = NULL
|
||||||
// };
|
// };
|
||||||
//emscripten_request_fullscreen_strategy("#canvas", EM_FALSE, &strategy);
|
//emscripten_request_fullscreen_strategy(platform.canvasId, EM_FALSE, &strategy);
|
||||||
|
|
||||||
// Option 3: Request fullscreen for the canvas element with strategy
|
// Option 3: Request fullscreen for the canvas element with strategy
|
||||||
// It works as expected but only inside the browser (client area)
|
// It works as expected but only inside the browser (client area)
|
||||||
@ -256,10 +267,11 @@ void ToggleFullscreen(void)
|
|||||||
.canvasResizedCallback = EmscriptenWindowResizedCallback,
|
.canvasResizedCallback = EmscriptenWindowResizedCallback,
|
||||||
.canvasResizedCallbackUserData = NULL
|
.canvasResizedCallbackUserData = NULL
|
||||||
};
|
};
|
||||||
emscripten_enter_soft_fullscreen("#canvas", &strategy);
|
emscripten_enter_soft_fullscreen(platform.canvasId, &strategy);
|
||||||
|
|
||||||
int width, height;
|
int width = 0;
|
||||||
emscripten_get_canvas_element_size("#canvas", &width, &height);
|
int height = 0;
|
||||||
|
emscripten_get_canvas_element_size(platform.canvasId, &width, &height);
|
||||||
TRACELOG(LOG_WARNING, "Emscripten: Enter fullscreen: Canvas size: %i x %i", width, height);
|
TRACELOG(LOG_WARNING, "Emscripten: Enter fullscreen: Canvas size: %i x %i", width, height);
|
||||||
|
|
||||||
CORE.Window.fullscreen = true; // Toggle fullscreen flag
|
CORE.Window.fullscreen = true; // Toggle fullscreen flag
|
||||||
@ -271,7 +283,7 @@ void ToggleFullscreen(void)
|
|||||||
//emscripten_exit_soft_fullscreen();
|
//emscripten_exit_soft_fullscreen();
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
emscripten_get_canvas_element_size("#canvas", &width, &height);
|
emscripten_get_canvas_element_size(platform.canvasId, &width, &height);
|
||||||
TRACELOG(LOG_WARNING, "Emscripten: Exit fullscreen: Canvas size: %i x %i", width, height);
|
TRACELOG(LOG_WARNING, "Emscripten: Exit fullscreen: Canvas size: %i x %i", width, height);
|
||||||
|
|
||||||
CORE.Window.fullscreen = false; // Toggle fullscreen flag
|
CORE.Window.fullscreen = false; // Toggle fullscreen flag
|
||||||
@ -866,7 +878,7 @@ void EnableCursor(void)
|
|||||||
// Disables cursor (lock cursor)
|
// Disables cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
emscripten_request_pointerlock(GetCanvasId(), 1);
|
emscripten_request_pointerlock(platform.canvasId, 1);
|
||||||
|
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
|
||||||
@ -877,7 +889,32 @@ void DisableCursor(void)
|
|||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
{
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
|
||||||
|
// Update framebuffer
|
||||||
|
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.pixels);
|
||||||
|
|
||||||
|
// Copy framebuffer data into canvas
|
||||||
|
EM_ASM({
|
||||||
|
const width = $0;
|
||||||
|
const height = $1;
|
||||||
|
const ptr = $2;
|
||||||
|
|
||||||
|
// Get canvas and 2d context created
|
||||||
|
const canvas = Module.canvas;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
if (!Module.__img || (Module.__img.width !== width) || (Module.__img.height !== height)) {
|
||||||
|
Module.__img = ctx.createImageData(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const src = HEAPU8.subarray(ptr, ptr + width*height*4); // RGBA (4 bytes)
|
||||||
|
Module.__img.data.set(src);
|
||||||
|
ctx.putImageData(Module.__img, 0, 0);
|
||||||
|
|
||||||
|
}, CORE.Window.screen.width, CORE.Window.screen.height, platform.pixels);
|
||||||
|
#else
|
||||||
glfwSwapBuffers(platform.handle);
|
glfwSwapBuffers(platform.handle);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -968,7 +1005,7 @@ void SetMouseCursor(int cursor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get physical key name.
|
// Get physical key name
|
||||||
const char *GetKeyName(int key)
|
const char *GetKeyName(int key)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
|
||||||
@ -1097,6 +1134,8 @@ void PollInputEvents(void)
|
|||||||
// Initialize platform: graphics, inputs and more
|
// Initialize platform: graphics, inputs and more
|
||||||
int InitPlatform(void)
|
int InitPlatform(void)
|
||||||
{
|
{
|
||||||
|
SetCanvasIdJs(platform.canvasId, 64); // Get the current canvas id
|
||||||
|
|
||||||
glfwSetErrorCallback(ErrorCallback);
|
glfwSetErrorCallback(ErrorCallback);
|
||||||
|
|
||||||
// Initialize GLFW internal global state
|
// Initialize GLFW internal global state
|
||||||
@ -1206,7 +1245,21 @@ int InitPlatform(void)
|
|||||||
|
|
||||||
// Init fullscreen toggle required var:
|
// Init fullscreen toggle required var:
|
||||||
platform.ourFullscreen = false;
|
platform.ourFullscreen = false;
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
|
||||||
|
// Avoid creating a WebGL canvas, avoid calling glfwCreateWindow()
|
||||||
|
emscripten_set_canvas_element_size(platform.canvasId, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
|
EM_ASM({
|
||||||
|
const canvas = document.getElementById("canvas");
|
||||||
|
Module.canvas = canvas;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load memory framebuffer with desired screen size
|
||||||
|
// NOTE: Despite using a software framebuffer for blitting, GLFW still creates a WebGL canvas,
|
||||||
|
// but it is not being used, on SwapScreenBuffer() the pure software renderer is used
|
||||||
|
// TODO: Consider requesting another type of canvas, not a WebGL one --> Replace GLFW-web by Emscripten?
|
||||||
|
platform.pixels = (unsigned int *)RL_CALLOC(CORE.Window.screen.width*CORE.Window.screen.height, sizeof(unsigned int));
|
||||||
|
#else
|
||||||
if (CORE.Window.fullscreen)
|
if (CORE.Window.fullscreen)
|
||||||
{
|
{
|
||||||
// remember center for switchinging from fullscreen to window
|
// remember center for switchinging from fullscreen to window
|
||||||
@ -1281,6 +1334,7 @@ int InitPlatform(void)
|
|||||||
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// WARNING: glfwCreateWindow() title doesn't work with emscripten
|
// WARNING: glfwCreateWindow() title doesn't work with emscripten
|
||||||
emscripten_set_window_title((CORE.Window.title != 0)? CORE.Window.title : " ");
|
emscripten_set_window_title((CORE.Window.title != 0)? CORE.Window.title : " ");
|
||||||
@ -1347,14 +1401,14 @@ int InitPlatform(void)
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Setup window events callbacks
|
// Setup window events callbacks
|
||||||
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenFullscreenChangeCallback);
|
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenFullscreenChangeCallback);
|
||||||
emscripten_set_blur_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback);
|
emscripten_set_blur_callback(platform.canvasId, platform.handle, 1, EmscriptenFocusCallback);
|
||||||
emscripten_set_focus_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback);
|
emscripten_set_focus_callback(platform.canvasId, platform.handle, 1, EmscriptenFocusCallback);
|
||||||
emscripten_set_visibilitychange_callback(NULL, 1, EmscriptenVisibilityChangeCallback);
|
emscripten_set_visibilitychange_callback(NULL, 1, EmscriptenVisibilityChangeCallback);
|
||||||
|
|
||||||
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
||||||
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
// Check fullscreen change events(note this is done on the window since most browsers don't support this on canvas)
|
||||||
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
// Check Resize event (note this is done on the window since most browsers don't support this on canvas)
|
||||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
||||||
|
|
||||||
// Trigger resize callback to force initial size
|
// Trigger resize callback to force initial size
|
||||||
@ -1362,15 +1416,15 @@ int InitPlatform(void)
|
|||||||
|
|
||||||
// Setup input events
|
// Setup input events
|
||||||
// NOTE: Keyboard callbacks only used to consume some events, libglfw.js takes care of the actual input
|
// NOTE: Keyboard callbacks only used to consume some events, libglfw.js takes care of the actual input
|
||||||
//emscripten_set_keypress_callback(GetCanvasId(), NULL, 1, EmscriptenKeyboardCallback); // WRNING: Breaks input
|
//emscripten_set_keypress_callback(platform.canvasId, NULL, 1, EmscriptenKeyboardCallback); // WRNING: Breaks input
|
||||||
//emscripten_set_keydown_callback(GetCanvasId(), NULL, 1, EmscriptenKeyboardCallback);
|
//emscripten_set_keydown_callback(platform.canvasId, NULL, 1, EmscriptenKeyboardCallback);
|
||||||
emscripten_set_click_callback(GetCanvasId(), NULL, 1, EmscriptenMouseCallback);
|
emscripten_set_click_callback(platform.canvasId, NULL, 1, EmscriptenMouseCallback);
|
||||||
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenPointerlockCallback);
|
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenPointerlockCallback);
|
||||||
emscripten_set_mousemove_callback(GetCanvasId(), NULL, 1, EmscriptenMouseMoveCallback);
|
emscripten_set_mousemove_callback(platform.canvasId, NULL, 1, EmscriptenMouseMoveCallback);
|
||||||
emscripten_set_touchstart_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback);
|
emscripten_set_touchstart_callback(platform.canvasId, NULL, 1, EmscriptenTouchCallback);
|
||||||
emscripten_set_touchend_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback);
|
emscripten_set_touchend_callback(platform.canvasId, NULL, 1, EmscriptenTouchCallback);
|
||||||
emscripten_set_touchmove_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback);
|
emscripten_set_touchmove_callback(platform.canvasId, NULL, 1, EmscriptenTouchCallback);
|
||||||
emscripten_set_touchcancel_callback(GetCanvasId(), NULL, 1, EmscriptenTouchCallback);
|
emscripten_set_touchcancel_callback(platform.canvasId, NULL, 1, EmscriptenTouchCallback);
|
||||||
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -1477,7 +1531,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
|||||||
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
||||||
{
|
{
|
||||||
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1512,8 +1566,8 @@ static void CharCallback(GLFWwindow *window, unsigned int key)
|
|||||||
|
|
||||||
// NOTE: Registers any key down considering OS keyboard layout but
|
// NOTE: Registers any key down considering OS keyboard layout but
|
||||||
// does not detect action events, those should be managed by user...
|
// does not detect action events, those should be managed by user...
|
||||||
// Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
// REF: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
||||||
// Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char
|
// REF: https://www.glfw.org/docs/latest/input_guide.html#input_char
|
||||||
|
|
||||||
// Check if there is space available in the queue
|
// Check if there is space available in the queue
|
||||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
||||||
@ -1691,7 +1745,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
|||||||
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
||||||
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
||||||
// EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
// EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
emscripten_get_element_css_size(GetCanvasId(), &canvasWidth, &canvasHeight);
|
emscripten_get_element_css_size(platform.canvasId, &canvasWidth, &canvasHeight);
|
||||||
|
|
||||||
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
{
|
{
|
||||||
@ -1802,7 +1856,7 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *
|
|||||||
if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
|
if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
|
||||||
else if ((height > (int)CORE.Window.screenMax.height) && (CORE.Window.screenMax.height > 0)) height = CORE.Window.screenMax.height;
|
else if ((height > (int)CORE.Window.screenMax.height) && (CORE.Window.screenMax.height > 0)) height = CORE.Window.screenMax.height;
|
||||||
|
|
||||||
emscripten_set_canvas_element_size(GetCanvasId(), width, height);
|
emscripten_set_canvas_element_size(platform.canvasId, width, height);
|
||||||
|
|
||||||
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
||||||
|
|
||||||
@ -1845,21 +1899,4 @@ static EM_BOOL EmscriptenVisibilityChangeCallback(int eventType, const Emscripte
|
|||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// JS: Get the canvas id provided by the module configuration
|
|
||||||
EM_JS(char *, GetCanvasIdJs, (), {
|
|
||||||
var canvasId = "#" + Module.canvas.id;
|
|
||||||
var lengthBytes = lengthBytesUTF8(canvasId) + 1;
|
|
||||||
var stringOnWasmHeap = _malloc(lengthBytes);
|
|
||||||
stringToUTF8(canvasId, stringOnWasmHeap, lengthBytes);
|
|
||||||
return stringOnWasmHeap;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get canvas id (using embedded JS function)
|
|
||||||
static const char *GetCanvasId(void)
|
|
||||||
{
|
|
||||||
static char *canvasId = NULL;
|
|
||||||
if (canvasId == NULL) canvasId = GetCanvasIdJs();
|
|
||||||
return canvasId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|||||||
1701
src/platforms/rcore_web_emscripten.c
Normal file
1701
src/platforms/rcore_web_emscripten.c
Normal file
File diff suppressed because it is too large
Load Diff
41
src/rcore.c
41
src/rcore.c
@ -117,7 +117,7 @@
|
|||||||
#include <time.h> // Required for: time() [Used in InitTimer()]
|
#include <time.h> // Required for: time() [Used in InitTimer()]
|
||||||
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
|
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
|
||||||
|
|
||||||
#if defined(PLATFORM_MEMORY)
|
#if defined(PLATFORM_MEMORY) || defined(PLATFORM_WEB)
|
||||||
#define SW_GL_FRAMEBUFFER_COPY_BGRA false
|
#define SW_GL_FRAMEBUFFER_COPY_BGRA false
|
||||||
#endif
|
#endif
|
||||||
#define RLGL_IMPLEMENTATION
|
#define RLGL_IMPLEMENTATION
|
||||||
@ -273,7 +273,7 @@
|
|||||||
#define FLAG_SET(n, f) ((n) |= (f))
|
#define FLAG_SET(n, f) ((n) |= (f))
|
||||||
#define FLAG_CLEAR(n, f) ((n) &= ~(f))
|
#define FLAG_CLEAR(n, f) ((n) &= ~(f))
|
||||||
#define FLAG_TOGGLE(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
|
// Types and Structures Definition
|
||||||
@ -816,30 +816,22 @@ int GetScreenHeight(void)
|
|||||||
// Get current render width which is equal to screen width*dpi scale
|
// Get current render width which is equal to screen width*dpi scale
|
||||||
int GetRenderWidth(void)
|
int GetRenderWidth(void)
|
||||||
{
|
{
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
|
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
#if defined(__APPLE__)
|
|
||||||
Vector2 scale = GetWindowScaleDPI();
|
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
|
||||||
width = (int)((float)CORE.Window.render.width*scale.x);
|
else width = CORE.Window.render.width;
|
||||||
#else
|
|
||||||
width = CORE.Window.render.width;
|
|
||||||
#endif
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current screen height which is equal to screen height*dpi scale
|
// Get current screen height which is equal to screen height*dpi scale
|
||||||
int GetRenderHeight(void)
|
int GetRenderHeight(void)
|
||||||
{
|
{
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
|
|
||||||
|
|
||||||
int height = 0;
|
int height = 0;
|
||||||
#if defined(__APPLE__)
|
|
||||||
Vector2 scale = GetWindowScaleDPI();
|
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
|
||||||
height = (int)((float)CORE.Window.render.height*scale.y);
|
else height = CORE.Window.render.height;
|
||||||
#else
|
|
||||||
height = CORE.Window.render.height;
|
|
||||||
#endif
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1660,8 +1652,8 @@ float GetFrameTime(void)
|
|||||||
// Wait for some time (stop program execution)
|
// Wait for some time (stop program execution)
|
||||||
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
||||||
// take longer than expected... for that reason we use the busy wait loop
|
// take longer than expected... for that reason we use the busy wait loop
|
||||||
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
// REF: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
||||||
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
|
// REF: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
|
||||||
void WaitTime(double seconds)
|
void WaitTime(double seconds)
|
||||||
{
|
{
|
||||||
if (seconds < 0) return; // Security check
|
if (seconds < 0) return; // Security check
|
||||||
@ -1833,7 +1825,7 @@ void TakeScreenshot(const char *fileName)
|
|||||||
|
|
||||||
// Apply a scale if we are doing HIGHDPI auto-scaling
|
// Apply a scale if we are doing HIGHDPI auto-scaling
|
||||||
Vector2 scale = { 1.0f, 1.0f };
|
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));
|
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 };
|
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;
|
CORE.Window.render.height = height;
|
||||||
|
|
||||||
// Set viewport width and 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);
|
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
|
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
|
||||||
rlLoadIdentity(); // Reset current matrix (projection)
|
rlLoadIdentity(); // Reset current matrix (projection)
|
||||||
|
|||||||
58
src/rlgl.h
58
src/rlgl.h
@ -1762,11 +1762,6 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
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)
|
switch (param)
|
||||||
{
|
{
|
||||||
case RL_TEXTURE_WRAP_S:
|
case RL_TEXTURE_WRAP_S:
|
||||||
@ -1786,6 +1781,9 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||||||
case RL_TEXTURE_FILTER_ANISOTROPIC:
|
case RL_TEXTURE_FILTER_ANISOTROPIC:
|
||||||
{
|
{
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
#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);
|
if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
|
||||||
else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
|
else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
|
||||||
{
|
{
|
||||||
@ -3355,8 +3353,8 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
|||||||
|
|
||||||
mipWidth /= 2;
|
mipWidth /= 2;
|
||||||
mipHeight /= 2;
|
mipHeight /= 2;
|
||||||
mipOffset += mipSize; // Increment offset position to next mipmap
|
mipOffset += mipSize; // Increment offset position to next mipmap
|
||||||
if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap
|
if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap
|
||||||
|
|
||||||
// Security check for NPOT textures
|
// Security check for NPOT textures
|
||||||
if (mipWidth < 1) mipWidth = 1;
|
if (mipWidth < 1) mipWidth = 1;
|
||||||
@ -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_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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);
|
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
|
#endif
|
||||||
|
|
||||||
@ -3914,7 +3918,7 @@ void rlUnloadFramebuffer(unsigned int id)
|
|||||||
|
|
||||||
// TODO: Review warning retrieving object name in WebGL
|
// TODO: Review warning retrieving object name in WebGL
|
||||||
// WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name
|
// WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name
|
||||||
// Ref: https://registry.khronos.org/webgl/specs/latest/1.0/
|
// REF: https://registry.khronos.org/webgl/specs/latest/1.0/
|
||||||
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
|
||||||
|
|
||||||
unsigned int depthIdU = (unsigned int)depthId;
|
unsigned int depthIdU = (unsigned int)depthId;
|
||||||
@ -4485,7 +4489,7 @@ void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)
|
|||||||
glUniformMatrix4fv(locIndex, count, true, (const float *)matrices);
|
glUniformMatrix4fv(locIndex, count, true, (const float *)matrices);
|
||||||
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// WARNING: WebGL does not support Matrix transpose ("true" parameter)
|
// WARNING: WebGL does not support Matrix transpose ("true" parameter)
|
||||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix
|
// REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix
|
||||||
glUniformMatrix4fv(locIndex, count, false, (const float *)matrices);
|
glUniformMatrix4fv(locIndex, count, false, (const float *)matrices);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -5220,24 +5224,36 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
|||||||
case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
|
case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB:
|
case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_PVRT_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_DXT3_RGBA:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
|
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
|
case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
|
case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 16 bytes per each 4x4 block
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
|
{
|
||||||
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
double bytesPerPixel = (double)bpp/8.0;
|
// Compute dataSize for uncompressed texture data (no blocks)
|
||||||
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
|
||||||
|
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
||||||
// 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;
|
double bytesPerPixel = (double)bpp/8.0;
|
||||||
else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
|
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSize;
|
return dataSize;
|
||||||
|
|||||||
@ -127,10 +127,13 @@
|
|||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#ifndef MAX_MATERIAL_MAPS
|
#ifndef MAX_MATERIAL_MAPS
|
||||||
#define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported
|
#define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_MESH_VERTEX_BUFFERS
|
#ifndef MAX_MESH_VERTEX_BUFFERS
|
||||||
#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
|
#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
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -3655,7 +3658,7 @@ void GenMeshTangents(Mesh *mesh)
|
|||||||
for (int t = 0; t < mesh->triangleCount; t++)
|
for (int t = 0; t < mesh->triangleCount; t++)
|
||||||
{
|
{
|
||||||
// Get triangle vertex indices
|
// Get triangle vertex indices
|
||||||
int i0, i1, i2;
|
int i0 = 0, i1 = 0, i2 = 0;
|
||||||
|
|
||||||
if (mesh->indices != NULL)
|
if (mesh->indices != NULL)
|
||||||
{
|
{
|
||||||
@ -4150,7 +4153,9 @@ RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)
|
|||||||
// Test against all triangles in mesh
|
// Test against all triangles in mesh
|
||||||
for (int i = 0; i < triangleCount; i++)
|
for (int i = 0; i < triangleCount; i++)
|
||||||
{
|
{
|
||||||
Vector3 a, b, c;
|
Vector3 a = { 0 };
|
||||||
|
Vector3 b = { 0 };
|
||||||
|
Vector3 c = { 0 };
|
||||||
Vector3 *vertdata = (Vector3 *)mesh.vertices;
|
Vector3 *vertdata = (Vector3 *)mesh.vertices;
|
||||||
|
|
||||||
if (mesh.indices)
|
if (mesh.indices)
|
||||||
@ -4193,8 +4198,10 @@ RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3
|
|||||||
RayCollision collision = { 0 };
|
RayCollision collision = { 0 };
|
||||||
Vector3 edge1 = { 0 };
|
Vector3 edge1 = { 0 };
|
||||||
Vector3 edge2 = { 0 };
|
Vector3 edge2 = { 0 };
|
||||||
Vector3 p, q, tv;
|
Vector3 p = { 0 };
|
||||||
float det, invDet, u, v, t;
|
Vector3 q = { 0 };
|
||||||
|
Vector3 tv = { 0 };
|
||||||
|
float det = 0.0f, invDet = 0.0f, u = 0.0f, v = 0.0f, t = 0.0f;
|
||||||
|
|
||||||
// Find vectors for two edges sharing V1
|
// Find vectors for two edges sharing V1
|
||||||
edge1 = Vector3Subtract(p2, p1);
|
edge1 = Vector3Subtract(p2, p1);
|
||||||
@ -5998,8 +6005,8 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Load animation data
|
// Load animation data
|
||||||
// Ref: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins
|
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins
|
||||||
// Ref: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
|
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
|
||||||
//
|
//
|
||||||
// LIMITATIONS:
|
// LIMITATIONS:
|
||||||
// - Only supports 1 armature per file, and skips loading it if there are multiple armatures
|
// - Only supports 1 armature per file, and skips loading it if there are multiple armatures
|
||||||
|
|||||||
41
src/rtext.c
41
src/rtext.c
@ -167,7 +167,7 @@ extern void LoadFontDefault(void)
|
|||||||
if (defaultFont.glyphs != NULL) return;
|
if (defaultFont.glyphs != NULL) return;
|
||||||
|
|
||||||
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||||
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
// REF: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||||
|
|
||||||
defaultFont.glyphCount = 224; // Number of glyphs included in our default font
|
defaultFont.glyphCount = 224; // Number of glyphs included in our default font
|
||||||
defaultFont.glyphPadding = 0; // Characters padding
|
defaultFont.glyphPadding = 0; // Characters padding
|
||||||
@ -649,7 +649,9 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||||||
|
|
||||||
// Calculate font basic metrics
|
// Calculate font basic metrics
|
||||||
// NOTE: ascent is equivalent to font baseline
|
// NOTE: ascent is equivalent to font baseline
|
||||||
int ascent, descent, lineGap;
|
int ascent = 0;
|
||||||
|
int descent = 0;
|
||||||
|
int lineGap = 0;
|
||||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||||
|
|
||||||
// In case no chars count provided, default to 95
|
// In case no chars count provided, default to 95
|
||||||
@ -698,7 +700,11 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case FONT_DEFAULT:
|
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:
|
case FONT_SDF:
|
||||||
{
|
{
|
||||||
if (cp != 32)
|
if (cp != 32)
|
||||||
@ -1591,14 +1597,13 @@ float TextToFloat(const char *text)
|
|||||||
|
|
||||||
#if defined(SUPPORT_TEXT_MANIPULATION)
|
#if defined(SUPPORT_TEXT_MANIPULATION)
|
||||||
// Copy one string to another, returns bytes copied
|
// 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 TextCopy(char *dst, const char *src)
|
||||||
{
|
{
|
||||||
int bytes = 0;
|
int bytes = 0;
|
||||||
|
|
||||||
if ((src != NULL) && (dst != NULL))
|
if ((src != NULL) && (dst != NULL))
|
||||||
{
|
{
|
||||||
// NOTE: Alternative: use strcpy(dst, src)
|
|
||||||
|
|
||||||
while (*src != '\0')
|
while (*src != '\0')
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
@ -1711,11 +1716,13 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
|||||||
{
|
{
|
||||||
char *insertPoint = NULL; // Next insert point
|
char *insertPoint = NULL; // Next insert point
|
||||||
char *temp = NULL; // Temp pointer
|
char *temp = NULL; // Temp pointer
|
||||||
|
int textLen = 0; // Text string length
|
||||||
int searchLen = 0; // Search string length of (the string to remove)
|
int searchLen = 0; // Search string length of (the string to remove)
|
||||||
int replaceLen = 0; // Replacement length (the string to replace by)
|
int replaceLen = 0; // Replacement length (the string to replace by)
|
||||||
int lastReplacePos = 0; // Distance between next search and end of last replace
|
int lastReplacePos = 0; // Distance between next search and end of last replace
|
||||||
int count = 0; // Number of replacements
|
int count = 0; // Number of replacements
|
||||||
|
|
||||||
|
textLen = TextLength(text);
|
||||||
searchLen = TextLength(search);
|
searchLen = TextLength(search);
|
||||||
if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
|
if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
|
||||||
|
|
||||||
@ -1726,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;
|
for (count = 0; (temp = strstr(insertPoint, search)); count++) insertPoint = temp + searchLen;
|
||||||
|
|
||||||
// Allocate returning string and point temp to it
|
// 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
|
if (!result) return NULL; // Memory could not be allocated
|
||||||
|
|
||||||
@ -1738,13 +1746,16 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
|||||||
{
|
{
|
||||||
insertPoint = (char *)strstr(text, search);
|
insertPoint = (char *)strstr(text, search);
|
||||||
lastReplacePos = (int)(insertPoint - text);
|
lastReplacePos = (int)(insertPoint - text);
|
||||||
temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
|
temp = strncpy(temp, text, tempLen - 1) + lastReplacePos;
|
||||||
temp = strcpy(temp, replacement) + replaceLen;
|
tempLen -= lastReplacePos;
|
||||||
|
temp = strncpy(temp, replacement, tempLen - 1) + replaceLen;
|
||||||
|
tempLen -= replaceLen;
|
||||||
|
|
||||||
text += lastReplacePos + searchLen; // Move to next "end of replace"
|
text += lastReplacePos + searchLen; // Move to next "end of replace"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy remaind text part after replacement to result (pointed by moving temp)
|
// Copy remaind text part after replacement to result (pointed by moving temp)
|
||||||
strcpy(temp, text);
|
strncpy(temp, text, tempLen - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -2084,7 +2095,7 @@ int *LoadCodepoints(const char *text, int *count)
|
|||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
||||||
// Allocate a big enough buffer to store as many codepoints as text bytes
|
// 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;
|
int codepointSize = 0;
|
||||||
for (int i = 0; i < textLength; codepointCount++)
|
for (int i = 0; i < textLength; codepointCount++)
|
||||||
@ -2483,7 +2494,15 @@ static Font LoadBMFont(const char *fileName)
|
|||||||
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX, pageID;
|
int charId = 0;
|
||||||
|
int charX = 0;
|
||||||
|
int charY = 0;
|
||||||
|
int charWidth = 0;
|
||||||
|
int charHeight = 0;
|
||||||
|
int charOffsetX = 0;
|
||||||
|
int charOffsetY = 0;
|
||||||
|
int charAdvanceX = 0;
|
||||||
|
int pageID = 0;
|
||||||
|
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1727,7 +1727,8 @@ void ImageResizeNN(Image *image, int newWidth, int newHeight)
|
|||||||
int xRatio = (int)((image->width << 16)/newWidth) + 1;
|
int xRatio = (int)((image->width << 16)/newWidth) + 1;
|
||||||
int yRatio = (int)((image->height << 16)/newHeight) + 1;
|
int yRatio = (int)((image->height << 16)/newHeight) + 1;
|
||||||
|
|
||||||
int x2, y2;
|
int x2 = 0;
|
||||||
|
int y2 = 0;
|
||||||
for (int y = 0; y < newHeight; y++)
|
for (int y = 0; y < newHeight; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < newWidth; x++)
|
for (int x = 0; x < newWidth; x++)
|
||||||
@ -2488,8 +2489,13 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
|
|||||||
Color oldPixel = WHITE;
|
Color oldPixel = WHITE;
|
||||||
Color newPixel = WHITE;
|
Color newPixel = WHITE;
|
||||||
|
|
||||||
int rError, gError, bError;
|
int rError = 0;
|
||||||
unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
|
int gError = 0;
|
||||||
|
int bError = 0;
|
||||||
|
unsigned short rPixel = 0; // Used for 16bit pixel composition
|
||||||
|
unsigned short gPixel = 0;
|
||||||
|
unsigned short bPixel = 0;
|
||||||
|
unsigned short aPixel = 0;
|
||||||
|
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
|
||||||
@ -4006,7 +4012,9 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
|
|||||||
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
|
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
|
||||||
// [ ] TODO: Support 16bit and 32bit (float) channels drawing
|
// [ ] TODO: Support 16bit and 32bit (float) channels drawing
|
||||||
|
|
||||||
Color colSrc, colDst, blend;
|
Color colSrc = { 0 };
|
||||||
|
Color colDst = { 0 };
|
||||||
|
Color blend = { 0 };
|
||||||
bool blendRequired = true;
|
bool blendRequired = true;
|
||||||
|
|
||||||
// Fast path: Avoid blend if source has no alpha to blend
|
// Fast path: Avoid blend if source has no alpha to blend
|
||||||
@ -4203,7 +4211,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||||||
/*else if (layout == CUBEMAP_LAYOUT_PANORAMA)
|
/*else if (layout == CUBEMAP_LAYOUT_PANORAMA)
|
||||||
{
|
{
|
||||||
// TODO: Implement panorama by converting image to square faces...
|
// TODO: Implement panorama by converting image to square faces...
|
||||||
// Ref: https://github.com/denivip/panorama/blob/master/panorama.cpp
|
// REF: https://github.com/denivip/panorama/blob/master/panorama.cpp
|
||||||
} */
|
} */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4681,17 +4689,23 @@ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest,
|
|||||||
bottomBorder = patchHeight - topBorder;
|
bottomBorder = patchHeight - topBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 vertA, vertB, vertC, vertD;
|
Vector2 vertA = { 0 };
|
||||||
vertA.x = 0.0f; // outer left
|
Vector2 vertB = { 0 };
|
||||||
vertA.y = 0.0f; // outer top
|
Vector2 vertC = { 0 };
|
||||||
vertB.x = leftBorder; // inner left
|
Vector2 vertD = { 0 };
|
||||||
vertB.y = topBorder; // inner top
|
vertA.x = 0.0f; // Outer left
|
||||||
vertC.x = patchWidth - rightBorder; // inner right
|
vertA.y = 0.0f; // Outer top
|
||||||
vertC.y = patchHeight - bottomBorder; // inner bottom
|
vertB.x = leftBorder; // Inner left
|
||||||
vertD.x = patchWidth; // outer right
|
vertB.y = topBorder; // Inner top
|
||||||
vertD.y = patchHeight; // outer bottom
|
vertC.x = patchWidth - rightBorder; // Inner right
|
||||||
|
vertC.y = patchHeight - bottomBorder; // Inner bottom
|
||||||
|
vertD.x = patchWidth; // Outer right
|
||||||
|
vertD.y = patchHeight; // Outer bottom
|
||||||
|
|
||||||
Vector2 coordA, coordB, coordC, coordD;
|
Vector2 coordA = { 0 };
|
||||||
|
Vector2 coordB = { 0 };
|
||||||
|
Vector2 coordC = { 0 };
|
||||||
|
Vector2 coordD = { 0 };
|
||||||
coordA.x = nPatchInfo.source.x/width;
|
coordA.x = nPatchInfo.source.x/width;
|
||||||
coordA.y = nPatchInfo.source.y/height;
|
coordA.y = nPatchInfo.source.y/height;
|
||||||
coordB.x = (nPatchInfo.source.x + leftBorder)/width;
|
coordB.x = (nPatchInfo.source.x + leftBorder)/width;
|
||||||
@ -4907,7 +4921,9 @@ Vector3 ColorToHSV(Color color)
|
|||||||
{
|
{
|
||||||
Vector3 hsv = { 0 };
|
Vector3 hsv = { 0 };
|
||||||
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
|
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
|
||||||
float min, max, delta;
|
float min = 0.0f;
|
||||||
|
float max = 0.0f;
|
||||||
|
float delta = 0.0f;
|
||||||
|
|
||||||
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
||||||
min = min < rgb.z? min : rgb.z;
|
min = min < rgb.z? min : rgb.z;
|
||||||
@ -5410,7 +5426,7 @@ int GetPixelDataSize(int width, int height, int format)
|
|||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Convert half-float (stored as unsigned short) to float
|
// Convert half-float (stored as unsigned short) to float
|
||||||
// Ref: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308
|
// REF: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308
|
||||||
static float HalfToFloat(unsigned short x)
|
static float HalfToFloat(unsigned short x)
|
||||||
{
|
{
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
|
|||||||
@ -446,7 +446,7 @@ void InitAssetManager(AAssetManager *manager, const char *dataPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replacement for fopen()
|
// Replacement for fopen()
|
||||||
// Ref: https://developer.android.com/ndk/reference/group/asset
|
// REF: https://developer.android.com/ndk/reference/group/asset
|
||||||
FILE *android_fopen(const char *fileName, const char *mode)
|
FILE *android_fopen(const char *fileName, const char *mode)
|
||||||
{
|
{
|
||||||
if (mode[0] == 'w')
|
if (mode[0] == 'w')
|
||||||
@ -454,7 +454,7 @@ FILE *android_fopen(const char *fileName, const char *mode)
|
|||||||
// NOTE: fopen() is mapped to android_fopen() that only grants read access to
|
// NOTE: fopen() is mapped to android_fopen() that only grants read access to
|
||||||
// assets directory through AAssetManager but we want to also be able to
|
// assets directory through AAssetManager but we want to also be able to
|
||||||
// write data when required using the standard stdio FILE access functions
|
// write data when required using the standard stdio FILE access functions
|
||||||
// Ref: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
|
// REF: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
|
||||||
#undef fopen
|
#undef fopen
|
||||||
return fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
|
return fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
|
||||||
#define fopen(name, mode) android_fopen(name, mode)
|
#define fopen(name, mode) android_fopen(name, mode)
|
||||||
|
|||||||
Reference in New Issue
Block a user