28 Commits

Author SHA1 Message Date
Ray
dbc56a87da Update HISTORY.md 2026-04-23 00:18:40 +02:00
Ray
932558ca7a Update HISTORY.md 2026-04-22 13:41:27 +02:00
Ray
7495a77a79 Update CHANGELOG 2026-04-22 13:41:15 +02:00
Ray
a4680fc677 Update HISTORY.md 2026-04-19 20:03:35 +02:00
Ray
d6445b55d6 Update core_basic_window.c 2026-04-19 20:03:31 +02:00
Ray
d87bf55607 Update CHANGELOG 2026-04-19 20:03:29 +02:00
a32b53f4d6 [build.zig] Refactor (#5764)
* Add better structure for build.zig

Temporarily disabled the tests

* Cleanup build.zig a bit

* Fixed zemscripten and cleanup other platforms

* Make opengl_version selection more restritive

* Add traslateC to build; Renable examples

* Add raygui build to build.zig

* Deny glfw from android target

* Fix android platform includes

* Add Zig project example

* Add Zig project mention to README

* Set right name for web build in zig example

* Cleanup last parts of build.zig

* Add linking method for build.zig

* Fix lshcore link for glfw and rgfw build.zig

* Fix weird sdl linkage build.zig

* Add zig example to zig project

* Fix win32, mac build bugs in build.zig

* Rename argument lshcore to shcore build.zig
2026-04-19 13:57:58 +02:00
Ray
cc752037b9 Update rmodels.c 2026-04-19 13:54:39 +02:00
90e9145978 Making it similar to CheckCollisionSpheres to remove pow function (#5776) 2026-04-19 13:51:52 +02:00
9060ac7c95 Mouse delta calculation with scaling (#5779)
Added scaling from SetMouseScale to mouse GetMouseDelta
2026-04-19 13:50:15 +02:00
Ray
4ced756474 Merge branch 'master' of https://github.com/raysan5/raylib 2026-04-18 18:53:05 +02:00
Ray
88f8ca42f5 Update rcore_drm.c 2026-04-18 18:53:03 +02:00
9a3283f698 [examples] shapes_collision_ellipses (#5722)
* Added shapes_collision_ellipses example

* Address review comments from raysan

* Address review comments

* update collision ellipses screenshot

* Restore shapes_following_eyes.c to upstream

* Rename shapes_collision_ellipses to shapes_ellipse_collision and fix header
2026-04-18 18:40:07 +02:00
f0a043bb75 [Platform/RGFW] add support for software rendering (#5773)
* add support for software rendering

* null check on freeing

* add back line

* rename framebuffer to surface

* add guard on free

* update makefile to prevent software on web

* update for mac
2026-04-17 18:09:57 +02:00
dde8c8e07e [build-windows.bat] Update build-windows script (#5769)
* Update build-windows script

* Use vswhere in build-windows script
2026-04-17 18:04:08 +02:00
Ray
1cbe438f93 Update rcore_desktop_rgfw.c 2026-04-17 18:03:29 +02:00
Ray
7c96c24cf9 Update rcore.c 2026-04-17 17:57:05 +02:00
Ray
d116c92f13 Merge branch 'master' of https://github.com/raysan5/raylib 2026-04-17 17:57:01 +02:00
Ray
14fe0cbfd8 Update rlgl.h 2026-04-17 17:56:49 +02:00
Ray
94f3c094e7 Update raudio.c 2026-04-17 17:56:47 +02:00
be768e27f9 fix issue with gettime (#5772) 2026-04-17 17:55:04 +02:00
6ef36c0a17 fix examples makefile define (#5767) 2026-04-16 13:01:54 +02:00
Ray
49f88dc6ed Update config.h 2026-04-16 11:12:50 +02:00
86aa0950bd [raymath] Refactor QuaternionFromAxisAngle (#5766)
Checking if lenght equals 0 inside the if statement is not necessary.
2026-04-16 08:37:04 +02:00
Ray
96e30549f5 Align default values on comments for config variables 2026-04-16 00:05:23 +02:00
Ray
1e43c1d372 Revert "Remap stb_vorbis malloc/free calls to RL_MALLOC/RL_FREE (#5763)"
This reverts commit 21897f4bb9.
2026-04-15 23:58:05 +02:00
21897f4bb9 Remap stb_vorbis malloc/free calls to RL_MALLOC/RL_FREE (#5763) 2026-04-15 23:51:47 +02:00
Ray
d8ebeb8939 Update raymath.h 2026-04-15 21:03:25 +02:00
27 changed files with 1314 additions and 497 deletions

View File

@ -17,7 +17,7 @@ KEY CHANGES:
- New File System API - New File System API
- New Text Management API - New Text Management API
- New tool: [rexm] raylib examples manager - New tool: [rexm] raylib examples manager
- Added +50 new examples to learn from - Added +70 new examples to learn from
Detailed changes: Detailed changes:
@ -115,6 +115,7 @@ Detailed changes:
[rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar [rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar
[rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC [rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley [rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
[rcore][RGFW] ADDED: Support for software rendering (#5773) by @CrackedPixel
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX [rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc [rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395 [rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395
@ -326,6 +327,7 @@ Detailed changes:
[rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski [rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski
[rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm [rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm
[rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71 [rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71
[rmodels] REVIEWED: `CheckCollisionBoxSphere()`, improved performance and consistency (#5776) by @maiconpintoabreu
[raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron [raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron
[raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron [raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron
[raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501 [raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501
@ -410,11 +412,12 @@ Detailed changes:
[build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral [build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral
[build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2 [build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2
[build][Zig] ADDED: Android target to build by @lumenkeyes [build][Zig] ADDED: Android target to build by @lumenkeyes
[build][Zig] REDESIGNED: Complete refactor of build.zig to support Zig 0.16.0 (#5764) by @HaxSam
[build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes [build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes
[build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam [build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam
[build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki [build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki
[build][Zig] REVIEWED: Fix emscripten building by @johnnymarler [build][Zig] REVIEWED: Fix emscripten building by @johnnymarler
[build][Zig] REVIWED: Move examples/build.zig into main build.zig by @johnnymarler [build][Zig] REVIEWED: Move examples/build.zig into main build.zig by @johnnymarler
[build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik [build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik
[build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415 [build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415
[build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik [build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik
@ -462,6 +465,7 @@ Detailed changes:
[examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary [examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary
[examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates [examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates
[examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe [examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe
[examples] ADDED: `shapes_collision_ellipses` (#5722) by @Monjaris
[examples] ADDED: `text_inline_styling` by @raysan5 [examples] ADDED: `text_inline_styling` by @raysan5
[examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto [examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto
[examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates [examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates

View File

@ -530,10 +530,10 @@ A new `raylib` release is finally ready and, again, this is the **biggest `rayli
Some astonishing numbers for this release: Some astonishing numbers for this release:
- **+320** closed issues (for a TOTAL of **+2140**!) - **+330** closed issues (for a TOTAL of **+2150**!)
- **+1950** commits since previous RELEASE (for a TOTAL of **+9700**!) - **+2000** commits since previous RELEASE (for a TOTAL of **+9760**!)
- **+20** new functions ADDED to raylib API (for a TOTAL of **600**!) - **+20** new functions ADDED to raylib API (for a TOTAL of **600**!)
- **+50** new examples to learn from (for a TOTAL of **+210**!) - **+70** new examples to learn from (for a TOTAL of **+215**!)
- **+210** new contributors (for a TOTAL of **+850**!) - **+210** new contributors (for a TOTAL of **+850**!)
Highlights for `raylib 6.0`: Highlights for `raylib 6.0`:
@ -591,14 +591,14 @@ COMMANDS:
update : Validate and update examples collection, generates report update : Validate and update examples collection, generates report
``` ```
- **`NEW` +50 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +50 new examples to leearn from, most of them contributed by community. - **`NEW` +70 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +70 new examples to learn from, most of them contributed by community. Multiple examples have also been renamed for consistency and all examples header and structure have been reviewed and unified.
Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes! Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes!
I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years. I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years.
Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **supporting and sponsoring the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library! Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **using raylib and supporting the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library!
**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphic programming!** **After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphics programming!**
**Enjoy graphics programming with raylib!** :) **Enjoy graphics programming with raylib!** :)

770
build.zig
View File

@ -1,14 +1,11 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
const emccOutputFile = "index.html";
pub const emsdk = struct { pub const emsdk = struct {
const zemscripten = @import("zemscripten"); const zemscripten = @import("zemscripten");
pub fn shell(b: *std.Build) std.Build.LazyPath { pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
return b.dependency("raylib", .{}).path("src/shell.html"); return raylib_dep.path("src/shell.html");
} }
pub const FlagsOptions = struct { pub const FlagsOptions = struct {
@ -30,7 +27,10 @@ pub const emsdk = struct {
pub const SettingsOptions = struct { pub const SettingsOptions = struct {
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
es3: bool = true, es3: bool = false,
glfw3: bool = true,
memory_growth: bool = false,
total_memory: u32 = 134217728,
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc, emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
}; };
@ -40,10 +40,24 @@ pub const emsdk = struct {
.emsdk_allocator = options.emsdk_allocator, .emsdk_allocator = options.emsdk_allocator,
}); });
if (options.es3) if (options.es3) {
emcc_settings.put("FULL_ES3", "1") catch unreachable; emcc_settings.put("FULL_ES3", "1") catch unreachable;
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
}
if (options.glfw3) {
emcc_settings.put("USE_GLFW", "3") catch unreachable; emcc_settings.put("USE_GLFW", "3") catch unreachable;
}
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable; emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
if (options.memory_growth)
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
return emcc_settings; return emcc_settings;
} }
@ -70,45 +84,96 @@ pub const emsdk = struct {
} }
}; };
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool) void {
switch (platform) { if (opengl) mod.linkSystemLibrary("opengl32", .{});
.glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""), mod.linkSystemLibrary("winmm", .{});
.rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""), mod.linkSystemLibrary("gdi32", .{});
.sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""), if (shcore) mod.linkSystemLibrary("shcore", .{});
.android => raylib.root_module.addCMacro("PLATFORM_ANDROID", ""),
else => {},
} }
fn findWaylandScanner(b: *std.Build) void {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("`wayland-scanner` not found");
};
}
pub fn linkLinux(mod: *std.Build.Module, comptime display_backend: LinuxDisplayBackend) void {
if (display_backend == .None) {
mod.linkSystemLibrary("GL", .{});
}
if (display_backend == .X11) {
mod.linkSystemLibrary("X11", .{});
mod.linkSystemLibrary("Xrandr", .{});
mod.linkSystemLibrary("Xinerama", .{});
mod.linkSystemLibrary("Xi", .{});
mod.linkSystemLibrary("Xcursor", .{});
}
if (display_backend == .Wayland) {
mod.linkSystemLibrary("wayland-client", .{});
mod.linkSystemLibrary("wayland-cursor", .{});
mod.linkSystemLibrary("wayland-egl", .{});
mod.linkSystemLibrary("xkbcommon", .{});
}
}
pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
mod.linkSystemLibrary("GL", .{});
}
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
// Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
}
mod.linkFramework("Foundation", .{});
mod.linkFramework("CoreServices", .{});
mod.linkFramework("CoreGraphics", .{});
mod.linkFramework("AppKit", .{});
mod.linkFramework("IOKit", .{});
} }
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
const raylib = b.addLibrary(.{ const raylib_mod = b.createModule(.{
.name = "raylib",
.linkage = options.linkage,
.root_module = b.createModule(.{
.optimize = optimize, .optimize = optimize,
.target = target, .target = target,
.link_libc = true, .link_libc = true,
}),
}); });
raylib.root_module.addCMacro("_GNU_SOURCE", ""); const raylib = b.addLibrary(.{
raylib.root_module.addCMacro("GL_SILENCE_DEPRECATION", "199309L"); .name = "raylib",
.linkage = options.linkage,
.root_module = raylib_mod,
});
var raylib_flags_arr: std.ArrayList([]const u8) = .empty; raylib_mod.addCMacro("_GNU_SOURCE", "");
defer raylib_flags_arr.deinit(b.allocator); raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
try raylib_flags_arr.append( var arena: std.heap.ArenaAllocator = .init(b.allocator);
b.allocator, defer arena.deinit();
"-std=gnu99",
); var raylib_flags_arr: std.array_list.Managed([]const u8) = .init(arena.allocator());
var c_source_files: std.array_list.Managed([]const u8) = .init(arena.allocator());
try c_source_files.append("src/rcore.c");
if (target.result.os.tag == .emscripten) {
try raylib_flags_arr.append("-std=gnu99");
} else {
try raylib_flags_arr.append("-std=c99");
}
if (options.linkage == .dynamic) { if (options.linkage == .dynamic) {
try raylib_flags_arr.append( raylib_mod.pic = true;
b.allocator, raylib_mod.addCMacro("BUILD_LIBTYPE_SHARED", "");
"-fPIC",
);
raylib.root_module.addCMacro("BUILD_LIBTYPE_SHARED", "");
} }
if (options.config.len > 0) { if (options.config.len > 0) {
@ -120,88 +185,237 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
// Apply config flags supplied by the user // Apply config flags supplied by the user
while (config_iter.next()) |config_flag| { while (config_iter.next()) |config_flag| {
try raylib_flags_arr.append(b.allocator, config_flag); try raylib_flags_arr.append(config_flag);
} }
} }
// No GLFW required on PLATFORM_DRM raylib_mod.addCMacro("SUPPORT_MODULE_RSHAPES", &.{@as(u8, @intFromBool(options.rshapes)) + 0x30});
if (options.platform != .drm) {
raylib.root_module.addIncludePath(b.path("src/external/glfw/include"));
}
var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{"src/rcore.c"});
if (options.rshapes) { if (options.rshapes) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "1"); try c_source_files.append("src/rshapes.c");
try c_source_files.append(b.allocator, "src/rshapes.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RSHAPES", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXTURES", &.{@as(u8, @intFromBool(options.rtextures)) + 0x30});
if (options.rtextures) { if (options.rtextures) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "1"); try c_source_files.append("src/rtextures.c");
try c_source_files.append(b.allocator, "src/rtextures.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXTURES", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXT", &.{@as(u8, @intFromBool(options.rtext)) + 0x30});
if (options.rtext) { if (options.rtext) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "1"); try c_source_files.append("src/rtext.c");
try c_source_files.append(b.allocator, "src/rtext.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RTEXT", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RMODELS", &.{@as(u8, @intFromBool(options.rmodels)) + 0x30});
if (options.rmodels) { if (options.rmodels) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "1"); try c_source_files.append("src/rmodels.c");
try c_source_files.append(b.allocator, "src/rmodels.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RMODELS", "0");
} }
raylib_mod.addCMacro("SUPPORT_MODULE_RAUDIO", &.{@as(u8, @intFromBool(options.raudio)) + 0x30});
if (options.raudio) { if (options.raudio) {
raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "1"); try c_source_files.append("src/raudio.c");
try c_source_files.append(b.allocator, "src/raudio.c");
} else {
raylib.root_module.addCMacro("SUPPORT_MODULE_RAUDIO", "0");
} }
if (options.opengl_version != .auto) { raylib_mod.addIncludePath(b.path("src/platforms"));
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
}
raylib.root_module.addIncludePath(b.path("src/platforms"));
switch (target.result.os.tag) {
.windows => {
switch (options.platform) { switch (options.platform) {
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), .glfw => {
.rgfw, .sdl, .drm, .android => {}, var opengl_version: OpenglVersion = options.opengl_version;
if (opengl_version == .gl_soft) {
@panic("The opengl version is not supported by this platform");
} }
raylib.root_module.linkSystemLibrary("winmm", .{}); raylib_mod.addIncludePath(b.path("src/external/glfw/include"));
raylib.root_module.linkSystemLibrary("gdi32", .{});
raylib.root_module.linkSystemLibrary("opengl32", .{});
setDesktopPlatform(raylib, options.platform); if (target.result.os.tag != .emscripten) {
}, if (opengl_version == .auto) {
opengl_version = OpenglVersion.gl_3_3;
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_GLFW", "");
try c_source_files.append("src/rglfw.c");
}
switch (target.result.os.tag) {
.windows => linkWindows(raylib_mod, true, false),
.linux => { .linux => {
if (options.platform == .drm) { if (target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
linkLinux(raylib_mod, .None);
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib_mod.addCMacro("_GLFW_X11", "");
linkLinux(raylib_mod, .X11);
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
findWaylandScanner(b);
raylib_mod.addCMacro("_GLFW_WAYLAND", "");
linkLinux(raylib_mod, .Wayland);
try waylandGenerate(b, raylib, "src/external/glfw/deps/wayland/", false);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => {
// On macos rglfw.c include Objective-C files.
_ = c_source_files.pop();
try raylib_flags_arr.append("-ObjC");
raylib_mod.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
linkMacOS(b, raylib_mod);
},
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
.gles_2, .gles_3, .gl_soft => {},
else => @panic("opengl version not supported"),
}
raylib_mod.addCMacro("PLATFORM_WEB", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
}
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
},
.rgfw => {
var opengl_version: OpenglVersion = options.opengl_version;
if (target.result.os.tag != .emscripten) {
if (opengl_version == .auto) {
opengl_version = OpenglVersion.gl_3_3;
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_RGFW", "");
}
switch (target.result.os.tag) {
.windows => linkWindows(raylib_mod, true, false),
.linux => {
if (target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
linkLinux(raylib_mod, .None);
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib_mod.addCMacro("RGFW_X11", "");
raylib_mod.addCMacro("RGFW_UNIX", "");
linkLinux(raylib_mod, .X11);
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
findWaylandScanner(b);
if (options.linux_display_backend != .Both) {
raylib_mod.addCMacro("RGFW_NO_X11", "");
}
raylib_mod.addCMacro("RGFW_WAYLAND", "");
raylib_mod.addCMacro("EGLAPIENTRY", "");
linkLinux(raylib_mod, .Wayland);
try waylandGenerate(b, raylib, "src/external/RGFW/deps/wayland/", true);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => linkMacOS(b, raylib_mod),
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
.gles_2, .gles_3, .gl_soft => {},
else => @panic("opengl version not supported"),
}
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
}
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
},
.sdl, .sdl2, .sdl3 => {
if (options.opengl_version == .auto) { if (options.opengl_version == .auto) {
raylib.root_module.linkSystemLibrary("GLESv2", .{}); raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); } else {
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
} }
if (options.opengl_version != .gl_soft) { raylib_mod.addCMacro("PLATFORM_DESKTOP_SDL", "");
raylib.root_module.linkSystemLibrary("EGL", .{});
raylib.root_module.linkSystemLibrary("gbm", .{});
}
raylib.root_module.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force });
raylib.root_module.addCMacro("PLATFORM_DRM", ""); if (options.platform == .sdl2) {
raylib.root_module.addCMacro("EGL_NO_X11", ""); raylib_mod.addCMacro("USING_SDL2_PACKAGE", "");
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", ""); }
} else if (target.result.abi.isAndroid()) { if (options.platform == .sdl3) {
raylib_mod.addCMacro("USING_SDL3_PACKAGE", "");
}
},
.memory => {
if (options.opengl_version != .auto and options.opengl_version != .gl_soft) {
@panic("The opengl version is not supported by this platform");
}
raylib_mod.addCMacro(OpenglVersion.gl_soft.toCMacroStr(), "");
raylib_mod.addCMacro("PLATFORM_MEMORY", "");
},
.win32 => {
if (target.result.os.tag != .windows) {
@panic("Target is not supported with this platform");
}
if (options.opengl_version == .auto) {
raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
} else {
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
}
raylib_mod.addCMacro("PLATFORM_DESKTOP_WIN32", "");
linkWindows(raylib_mod, options.opengl_version != .gl_soft, true);
},
.drm => {
if (target.result.os.tag != .linux) {
@panic("Target is not supported with this platform");
}
raylib_mod.addCMacro("PLATFORM_DRM", "");
raylib_mod.addCMacro("EGL_NO_X11", "");
raylib_mod.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
try raylib_flags_arr.append("-Werror=implicit-function-declaration");
raylib_mod.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force });
raylib_mod.linkSystemLibrary("drm", .{});
raylib_mod.linkSystemLibrary("gbm", .{});
switch (options.opengl_version) {
.auto, .gles_2 => {
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
raylib_mod.linkSystemLibrary("GLESv2", .{});
raylib_mod.linkSystemLibrary("EGL", .{});
},
.gl_soft => {},
else => @panic("The opengl version is not supported by this platform"),
}
},
.android => {
if (!target.result.abi.isAndroid()) {
@panic("Target is not supported with this platform");
}
raylib_mod.addCMacro("PLATFORM_ANDROID", "");
raylib_mod.linkSystemLibrary("EGL", .{});
switch (options.opengl_version) {
.auto, .gles_2 => {
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
raylib_mod.linkSystemLibrary("GLESv2", .{});
},
else => @panic("The opengl version is not supported by this platform"),
}
//these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems //these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems
const hostTuple = switch (builtin.target.os.tag) { const hostTuple = switch (builtin.target.os.tag) {
@ -231,126 +445,30 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" }); const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" });
const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" }); const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" });
raylib.root_module.addLibraryPath(.{ .cwd_relative = androidLibPath }); raylib_mod.addLibraryPath(.{ .cwd_relative = androidLibPath });
raylib.root_module.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath }); raylib_mod.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidIncludePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidIncludePath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidAsmPath });
raylib.root_module.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidGluePath });
var libcData: std.ArrayList(u8) = .empty; const libc_data = try std.fmt.allocPrint(b.allocator,
var aw: std.Io.Writer.Allocating = .fromArrayList(b.allocator, &libcData); \\include_dir={0s}/sysroot/usr/include
try (std.zig.LibCInstallation{ \\sys_include_dir={0s}/sysroot/usr/include/aarch64-linux-android
.include_dir = androidIncludePath, \\crt_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
.sys_include_dir = androidIncludePath, \\static_lib_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
.crt_dir = androidApiSpecificPath, \\msvc_lib_dir=
}).render(&aw.writer); \\kernel32_lib_dir=
const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice(b.allocator)); \\gcc_dir=
\\
, .{androidNdkPathString});
const write_step = b.addWriteFiles();
const libcFile = write_step.add("android-libc.txt", libc_data);
raylib.setLibCFile(libcFile); raylib.setLibCFile(libcFile);
if (options.opengl_version == .auto) {
raylib.root_module.linkSystemLibrary("GLESv2", .{});
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
}
raylib.root_module.linkSystemLibrary("EGL", .{});
setDesktopPlatform(raylib, .android);
} else {
switch (options.platform) {
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"),
.rgfw, .sdl, .drm, .android => {},
}
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib.root_module.addCMacro("_GLFW_X11", "");
raylib.root_module.linkSystemLibrary("GLX", .{});
raylib.root_module.linkSystemLibrary("X11", .{});
raylib.root_module.linkSystemLibrary("Xcursor", .{});
raylib.root_module.linkSystemLibrary("Xext", .{});
raylib.root_module.linkSystemLibrary("Xfixes", .{});
raylib.root_module.linkSystemLibrary("Xi", .{});
raylib.root_module.linkSystemLibrary("Xinerama", .{});
raylib.root_module.linkSystemLibrary("Xrandr", .{});
raylib.root_module.linkSystemLibrary("Xrender", .{});
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("`wayland-scanner` not found");
};
raylib.root_module.addCMacro("_GLFW_WAYLAND", "");
raylib.root_module.linkSystemLibrary("EGL", .{});
raylib.root_module.linkSystemLibrary("wayland-client", .{});
raylib.root_module.linkSystemLibrary("xkbcommon", .{});
waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
}
setDesktopPlatform(raylib, options.platform);
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
try c_source_files.append(b.allocator, "src/rglfw.c");
raylib.root_module.linkSystemLibrary("GL", .{});
raylib.root_module.linkSystemLibrary("rt", .{});
raylib.root_module.linkSystemLibrary("dl", .{});
raylib.root_module.linkSystemLibrary("m", .{});
raylib.root_module.linkSystemLibrary("X11", .{});
raylib.root_module.linkSystemLibrary("Xrandr", .{});
raylib.root_module.linkSystemLibrary("Xinerama", .{});
raylib.root_module.linkSystemLibrary("Xi", .{});
raylib.root_module.linkSystemLibrary("Xxf86vm", .{});
raylib.root_module.linkSystemLibrary("Xcursor", .{});
setDesktopPlatform(raylib, options.platform);
},
.macos => {
// Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
raylib.root_module.addSystemFrameworkPath(dep.path("Frameworks"));
raylib.root_module.addSystemIncludePath(dep.path("include"));
raylib.root_module.addLibraryPath(dep.path("lib"));
}
// On macos rglfw.c include Objective-C files.
try raylib_flags_arr.append(b.allocator, "-ObjC");
raylib.root_module.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
raylib.root_module.linkFramework("Foundation", .{});
raylib.root_module.linkFramework("CoreServices", .{});
raylib.root_module.linkFramework("CoreGraphics", .{});
raylib.root_module.linkFramework("AppKit", .{});
raylib.root_module.linkFramework("IOKit", .{});
setDesktopPlatform(raylib, options.platform);
},
.emscripten => {
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
raylib.root_module.addCMacro("PLATFORM_WEB", "");
if (options.opengl_version == .auto) {
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES3", "");
}
},
else => {
@panic("Unsupported OS");
}, },
} }
raylib.root_module.addCSourceFiles(.{ raylib_mod.addCSourceFiles(.{
.files = c_source_files.items, .files = c_source_files.items,
.flags = raylib_flags_arr.items, .flags = raylib_flags_arr.items,
}); });
@ -358,17 +476,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
return raylib; return raylib;
} }
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency, options: Options) void { fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
const raylib_dep = b.dependencyFromBuildZig(@This(), options); if (b.lazyDependency("raygui", .{
.target = target,
.optimize = optimize,
.link_libc = true,
})) |raygui_dep| {
var gen_step = b.addWriteFiles(); var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step); raylib.step.dependOn(&gen_step.step);
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path }); raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src")); raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(raylib_dep.path("src")); raylib.root_module.addIncludePath(b.path("src"));
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
} }
pub const Options = struct { pub const Options = struct {
@ -377,6 +511,7 @@ pub const Options = struct {
rshapes: bool = true, rshapes: bool = true,
rtext: bool = true, rtext: bool = true,
rtextures: bool = true, rtextures: bool = true,
raygui: bool = false,
platform: PlatformBackend = .glfw, platform: PlatformBackend = .glfw,
linkage: std.builtin.LinkMode = .static, linkage: std.builtin.LinkMode = .static,
linux_display_backend: LinuxDisplayBackend = .X11, linux_display_backend: LinuxDisplayBackend = .X11,
@ -396,6 +531,7 @@ pub const Options = struct {
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes, .rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
.raygui = b.option(bool, "raygui", "Include raygui") orelse defaults.raygui,
.linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage, .linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage,
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend, .linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version, .opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
@ -441,15 +577,38 @@ pub const PlatformBackend = enum {
glfw, glfw,
rgfw, rgfw,
sdl, sdl,
sdl2,
sdl3,
memory,
win32,
drm, drm,
android, android,
}; };
fn translateCMod(
comptime header: []const u8,
b: *std.Build,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
raylib: *std.Build.Step.Compile,
) void {
const c = b.addTranslateC(.{
.root_source_file = b.path("src/" ++ header ++ ".h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, header, c_mod) catch @panic("OOM");
}
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const options: Options = .getOptions(b);
const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); const lib = try compileRaylib(b, target, optimize, options);
lib.installHeader(b.path("src/raylib.h"), "raylib.h"); lib.installHeader(b.path("src/raylib.h"), "raylib.h");
lib.installHeader(b.path("src/rcamera.h"), "rcamera.h"); lib.installHeader(b.path("src/rcamera.h"), "rcamera.h");
@ -458,15 +617,24 @@ pub fn build(b: *std.Build) !void {
b.installArtifact(lib); b.installArtifact(lib);
const examples = b.step("examples", "Build/Install all examples"); translateCMod("raylib", b, target, optimize, lib);
examples.dependOn(try addExamples("audio", b, target, optimize, lib)); translateCMod("rcamera", b, target, optimize, lib);
examples.dependOn(try addExamples("core", b, target, optimize, lib)); translateCMod("raymath", b, target, optimize, lib);
examples.dependOn(try addExamples("models", b, target, optimize, lib)); translateCMod("rlgl", b, target, optimize, lib);
examples.dependOn(try addExamples("others", b, target, optimize, lib));
examples.dependOn(try addExamples("shaders", b, target, optimize, lib)); if (options.raygui) {
examples.dependOn(try addExamples("shapes", b, target, optimize, lib)); addRaygui(b, target, optimize, lib);
examples.dependOn(try addExamples("text", b, target, optimize, lib)); }
examples.dependOn(try addExamples("textures", b, target, optimize, lib));
const examples = b.step("examples", "build/install all examples");
examples.dependOn(try addExamples("core", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("audio", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("models", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("shaders", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("shapes", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("text", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("textures", b, target, optimize, lib, options.platform));
examples.dependOn(try addExamples("others", b, target, optimize, lib, options.platform));
} }
fn addExamples( fn addExamples(
@ -475,6 +643,7 @@ fn addExamples(
target: std.Build.ResolvedTarget, target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
raylib: *std.Build.Step.Compile, raylib: *std.Build.Step.Compile,
platform: PlatformBackend,
) !*std.Build.Step { ) !*std.Build.Step {
const all = b.step(module, "All " ++ module ++ " examples"); const all = b.step(module, "All " ++ module ++ " examples");
const module_subpath = b.pathJoin(&.{ "examples", module }); const module_subpath = b.pathJoin(&.{ "examples", module });
@ -485,118 +654,88 @@ fn addExamples(
var iter = dir.iterate(); var iter = dir.iterate();
while (try iter.next(b.graph.io)) |entry| { while (try iter.next(b.graph.io)) |entry| {
if (entry.kind != .file) continue; if (entry.kind != .file) continue;
const extension_idx = std.mem.lastIndexOf(u8, entry.name, ".c") orelse continue;
const name = entry.name[0..extension_idx];
const filename = try std.fmt.allocPrint(b.allocator, "{s}.c", .{name});
const path = b.pathJoin(&.{ module_subpath, filename });
// zig's mingw headers do not include pthread.h const filetype = std.fs.path.extension(entry.name);
if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue; if (!std.mem.eql(u8, filetype, ".c")) continue;
const filename = std.fs.path.stem(entry.name);
const path = b.pathJoin(&.{ module_subpath, entry.name });
const exe_mod = b.createModule(.{ const exe_mod = b.createModule(.{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.link_libc = true,
}); });
exe_mod.addCSourceFile(.{ .file = b.path(path), .flags = &.{} }); exe_mod.addCSourceFile(.{ .file = b.path(path) });
exe_mod.linkLibrary(raylib); exe_mod.linkLibrary(raylib);
const run_step = b.step(name, name); if (platform == .sdl) {
exe_mod.linkSystemLibrary("SDL2", .{});
exe_mod.linkSystemLibrary("SDL3", .{});
}
if (platform == .sdl2) {
exe_mod.linkSystemLibrary("SDL2", .{});
}
if (platform == .sdl3) {
exe_mod.linkSystemLibrary("SDL3", .{});
}
if (target.result.os.tag == .emscripten) { if (std.mem.eql(u8, filename, "rlgl_standalone")) {
const wasm = b.addLibrary(.{ if (platform != .glfw) continue;
.name = name,
.linkage = .static,
.root_module = exe_mod,
});
if (std.mem.eql(u8, name, "rlgl_standalone")) {
exe_mod.addIncludePath(b.path("src")); exe_mod.addIncludePath(b.path("src"));
exe_mod.addIncludePath(b.path("src/external/glfw/include")); exe_mod.addIncludePath(b.path("src/external/glfw/include"));
} }
if (std.mem.eql(u8, name, "raylib_opengl_interop")) { if (std.mem.eql(u8, filename, "raylib_opengl_interop")) {
if (platform == .drm) continue;
if (target.result.os.tag == .macos) continue;
exe_mod.addIncludePath(b.path("src/external")); exe_mod.addIncludePath(b.path("src/external"));
} }
const run_step = b.step(filename, filename);
// web exports are completely separate
if (target.query.os_tag == .emscripten) {
exe_mod.addCMacro("PLATFORM_WEB", "");
const wasm = b.addLibrary(.{
.name = filename,
.root_module = exe_mod,
});
const install_dir: std.Build.InstallDir = .{ .custom = b.fmt("web/{s}/{s}", .{ module, filename }) };
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize }); const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize }); const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const install_dir: std.Build.InstallDir = .{ .custom = "htmlout" };
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{ const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
.optimize = optimize, .optimize = optimize,
.flags = emcc_flags, .flags = emcc_flags,
.settings = emcc_settings, .settings = emcc_settings,
.shell_file_path = b.path("src/shell.html"), .shell_file_path = b.path("src/shell.html"),
.embed_paths = &.{
.{
.src_path = b.pathJoin(&.{ module_subpath, "resources" }),
.virtual_path = "resources",
},
},
.install_dir = install_dir, .install_dir = install_dir,
}); });
b.getInstallStep().dependOn(emcc_step);
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name}); const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep( const emrun_step = emsdk.emrunStep(
b, b,
b.getInstallPath(install_dir, html_filename), b.getInstallPath(install_dir, html_filename),
&.{"--no_browser"}, &.{},
); );
emrun_step.dependOn(emcc_step);
emrun_step.dependOn(emcc_step);
run_step.dependOn(emrun_step); run_step.dependOn(emrun_step);
all.dependOn(emcc_step); all.dependOn(emcc_step);
} else { } else {
// special examples that test using these external dependencies directly
// alongside raylib
if (std.mem.eql(u8, name, "rlgl_standalone")) {
exe_mod.addIncludePath(b.path("src"));
exe_mod.addIncludePath(b.path("src/external/glfw/include"));
if (!hasCSource(raylib.root_module, "rglfw.c")) {
exe_mod.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = &.{} });
}
}
if (std.mem.eql(u8, name, "raylib_opengl_interop")) {
exe_mod.addIncludePath(b.path("src/external"));
}
switch (target.result.os.tag) {
.windows => {
exe_mod.linkSystemLibrary("winmm", .{});
exe_mod.linkSystemLibrary("gdi32", .{});
exe_mod.linkSystemLibrary("opengl32", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", ""); exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
.linux => {
exe_mod.linkSystemLibrary("GL", .{});
exe_mod.linkSystemLibrary("rt", .{});
exe_mod.linkSystemLibrary("dl", .{});
exe_mod.linkSystemLibrary("m", .{});
exe_mod.linkSystemLibrary("X11", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
.macos => {
exe_mod.linkFramework("Foundation", .{});
exe_mod.linkFramework("Cocoa", .{});
exe_mod.linkFramework("OpenGL", .{});
exe_mod.linkFramework("CoreAudio", .{});
exe_mod.linkFramework("CoreVideo", .{});
exe_mod.linkFramework("IOKit", .{});
exe_mod.addCMacro("PLATFORM_DESKTOP", "");
},
else => {
@panic("Unsupported OS");
},
}
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = name, .name = filename,
.root_module = exe_mod, .root_module = exe_mod,
.use_lld = target.result.os.tag == .windows,
}); });
b.installArtifact(exe);
const install_cmd = b.addInstallArtifact(exe, .{}); const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
const run_cmd = b.addRunArtifact(exe); const run_cmd = b.addRunArtifact(exe);
run_cmd.cwd = b.path(module_subpath); run_cmd.cwd = b.path(module_subpath);
@ -606,41 +745,46 @@ fn addExamples(
all.dependOn(&install_cmd.step); all.dependOn(&install_cmd.step);
} }
} }
return all; return all;
} }
fn waylandGenerate( fn waylandGenerate(
b: *std.Build, b: *std.Build,
raylib: *std.Build.Step.Compile, raylib: *std.Build.Step.Compile,
comptime protocol: []const u8, comptime waylandDir: []const u8,
comptime basename: []const u8, comptime source: bool,
) void { ) !void {
const waylandDir = "src/external/glfw/deps/wayland"; const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
const protocolDir = b.pathJoin(&.{ waylandDir, protocol }); defer dir.close(b.graph.io);
const clientHeader = basename ++ ".h";
const privateCode = basename ++ "-code.h";
var iter = dir.iterate();
while (try iter.next(b.graph.io)) |entry| {
if (entry.kind != .file) continue;
const protocolDir = b.pathJoin(&.{ waylandDir, entry.name });
const filename = std.fs.path.stem(entry.name);
const clientHeader = b.fmt("{s}-client-protocol.h", .{filename});
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" }); const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
client_step.addFileArg(b.path(protocolDir)); client_step.addFileArg(b.path(protocolDir));
raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname()); raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
raylib.step.dependOn(&client_step.step);
if (comptime source) {
const privateCode = b.fmt("{s}-client-protocol-code.c", .{filename});
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" }); const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
private_step.addFileArg(b.path(protocolDir)); private_step.addFileArg(b.path(protocolDir));
raylib.root_module.addIncludePath(private_step.addOutputFileArg(privateCode).dirname()); raylib.root_module.addCSourceFile(.{
.file = private_step.addOutputFileArg(privateCode),
raylib.step.dependOn(&client_step.step); .flags = &.{ "-std=c99", "-O2" },
});
raylib.step.dependOn(&private_step.step); raylib.step.dependOn(&private_step.step);
} else {
const privateCodeHeader = b.fmt("{s}-client-protocol-code.h", .{filename});
const private_head_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
private_head_step.addFileArg(b.path(protocolDir));
raylib.root_module.addIncludePath(private_head_step.addOutputFileArg(privateCodeHeader).dirname());
raylib.step.dependOn(&private_head_step.step);
}
} }
fn hasCSource(module: *std.Build.Module, name: []const u8) bool {
for (module.link_objects.items) |o| switch (o) {
.c_source_file => |c| if (switch (c.file) {
.src_path => |s| std.ascii.endsWithIgnoreCase(s.sub_path, name),
.generated, .cwd_relative, .dependency => false,
}) return true,
.c_source_files => |s| for (s.files) |c| if (std.ascii.endsWithIgnoreCase(c, name)) return true,
else => {},
};
return false;
} }

View File

@ -11,6 +11,11 @@
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ", .hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
.lazy = true, .lazy = true,
}, },
.raygui = .{
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
.lazy = true,
},
.emsdk = .{ .emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9", .url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ", .hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",

View File

@ -510,7 +510,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
# Libraries for Windows desktop compilation # Libraries for Windows desktop compilation
LDFLAGS += -L..\src LDFLAGS += -L..\src
LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore
ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE) ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
LDLIBS += -lopengl32 LDLIBS += -lopengl32
endif endif
endif endif

View File

@ -22,7 +22,7 @@
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software * BSD-like license that allows static linking with closed source software
* *
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
* *
********************************************************************************************/ ********************************************************************************************/

View File

@ -0,0 +1,133 @@
/*******************************************************************************************
*
* raylib [shapes] example - ellipse collision
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Ziya (@Monjaris)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Ziya (@Monjaris)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
// Check if point is inside ellipse
static bool CheckCollisionPointEllipse(Vector2 point, Vector2 center, float rx, float ry)
{
float dx = (point.x - center.x)/rx;
float dy = (point.y - center.y)/ry;
return (dx*dx + dy*dy) <= 1.0f;
}
// Check if two ellipses collide
// Uses radial boundary distance in the direction between centers — scales correctly with radii
static bool CheckCollisionEllipses(Vector2 c1, float rx1, float ry1, Vector2 c2, float rx2, float ry2)
{
float dx = c2.x - c1.x;
float dy = c2.y - c1.y;
float dist = sqrtf(dx*dx + dy*dy);
// Ellipses are on top of each other
if (dist == 0.0f) return true;
float theta = atan2f(dy, dx);
float cosT = cosf(theta);
float sinT = sinf(theta);
// Radial distance from center to ellipse boundary in direction theta
// r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2)
float r1 = (rx1*ry1)/sqrtf((ry1*cosT)*(ry1*cosT) + (rx1*sinT)*(rx1*sinT));
float r2 = (rx2*ry2)/sqrtf((ry2*cosT)*(ry2*cosT) + (rx2*sinT)*(rx2*sinT));
return dist <= (r1 + r2);
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
SetTargetFPS(60);
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };
float ellipseARx = 120.0f;
float ellipseARy = 70.0f;
Vector2 ellipseBCenter = { (float)screenWidth*3/4, (float)screenHeight/2 };
float ellipseBRx = 90.0f;
float ellipseBRy = 140.0f;
// 0 = controlling A, 1 = controlling B
int controlled = 0;
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_A)) controlled = 0;
if (IsKeyPressed(KEY_B)) controlled = 1;
if (controlled == 0) ellipseACenter = GetMousePosition();
else ellipseBCenter = GetMousePosition();
bool ellipsesCollide = CheckCollisionEllipses(
ellipseACenter, ellipseARx, ellipseARy,
ellipseBCenter, ellipseBRx, ellipseBRy
);
bool mouseInA = CheckCollisionPointEllipse(GetMousePosition(), ellipseACenter, ellipseARx, ellipseARy);
bool mouseInB = CheckCollisionPointEllipse(GetMousePosition(), ellipseBCenter, ellipseBRx, ellipseBRy);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawEllipse((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, ellipsesCollide ? RED : BLUE);
DrawEllipse((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, ellipsesCollide ? RED : GREEN);
DrawEllipseLines((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, WHITE);
DrawEllipseLines((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, WHITE);
DrawCircleV(ellipseACenter, 4, WHITE);
DrawCircleV(ellipseBCenter, 4, WHITE);
if (ellipsesCollide) DrawText("ELLIPSES COLLIDE", screenWidth/2 - 120, 40, 28, RED);
else DrawText("NO COLLISION", screenWidth/2 - 80, 40, 28, DARKGRAY);
DrawText(controlled == 0 ? "Controlling: A" : "Controlling: B", 20, screenHeight - 40, 20, YELLOW);
if (mouseInA && controlled != 0) DrawText("Mouse inside ellipse A", 20, screenHeight - 70, 20, BLUE);
if (mouseInB && controlled != 1) DrawText("Mouse inside ellipse B", 20, screenHeight - 70, 20, GREEN);
DrawText("Press [A] or [B] to switch control", 20, 20, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
CloseWindow();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -13,6 +13,7 @@ IDE | Platform(s) | Source | Example(s)
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️ [SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️ [VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️ [VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️
scripts | Windows, Linux, macOS | ✔️ | ✔️ scripts | Windows, Linux, macOS | ✔️ | ✔️
*New IDEs config files are welcome!* *New IDEs config files are welcome!*

84
projects/Zig/README.md Normal file
View File

@ -0,0 +1,84 @@
# Starting your raylib project with Zig (0.16.0)
## How to compile and run it
To compile the project:
```sh
zig build
```
To run the project:
```sh
zig build run
```
## Compile with different optimization
To change from debug to release build you can do it with the `-Doptimze=` flag.
```
Debug
ReleaseSafe
ReleaseFast
ReleaseSmall
```
## Choose a different platform
To compile with a different platform you can use the `-Dplatform=` flag.
Here all the options:
```
glfw
rgfw
sdl
sdl2
sdl3
memory
win32
drm
android
```
In this example the platform `sdl` and `sdl2` are not supported
Important for the android platform you also have to compile for the right target
## Compile for a different target
To compile for a different [target](https://ziglang.org/download/0.16.0/release-notes.html#Support-Table) you can use the `-Dtarget=` flag.
Not all targets are supported
## Example: Compile for web and run it
To compile for the web we use emscripten and you run it like that:
```sh
zig build -Dtarget=wasm32-emscripten
```
To run it we do:
```sh
zig build run -Dtarget=wasm32-emscripten
```
And to make a relase build we do:
```sh
zig build -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
```
If we want to use rgfw for the web build we could do:
```sh
zig build -Dplatform=rgfw -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
```
## Compiling the Zig code? Just add `-Dzig` and try out zig ;)
## More Resources
See [Zig Build System](https://ziglang.org/learn/build-system/)

87
projects/Zig/build.zig Normal file
View File

@ -0,0 +1,87 @@
const std = @import("std");
const rl = @import("raylib");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const platform = b.option(rl.PlatformBackend, "platform", "select the platform") orelse rl.PlatformBackend.glfw;
const zig = b.option(bool, "zig", "compile zig code") orelse false;
const raylib_dep = b.dependency("raylib", .{
.target = target,
.optimize = optimize,
.platform = platform,
});
const raylib_artifact = raylib_dep.artifact("raylib");
if (platform == .sdl3) {
if (b.lazyDependency("sdl3", .{ .optimize = optimize, .target = target })) |dep| {
raylib_artifact.root_module.linkLibrary(dep.artifact("SDL3"));
}
}
var exe_mod: *std.Build.Module = undefined;
if (zig) {
exe_mod = b.createModule(.{
.root_source_file = b.path("src/core_basic_window.zig"),
.target = target,
.optimize = optimize,
});
exe_mod.addImport("raylib", raylib_dep.module("raylib"));
} else {
exe_mod = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
});
exe_mod.addCSourceFile(.{ .file = b.path("src/core_basic_window.c") });
exe_mod.linkLibrary(raylib_artifact);
}
const run_step = b.step("run", "Run the app");
// web exports are completely separate
if (target.query.os_tag == .emscripten) {
const emsdk = rl.emsdk;
const wasm = b.addLibrary(.{
.name = "core_basic_window_web",
.root_module = exe_mod,
});
const install_dir: std.Build.InstallDir = .{ .custom = "web" };
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const emcc_step = emsdk.emccStep(b, raylib_artifact, wasm, .{
.optimize = optimize,
.flags = emcc_flags,
.settings = emcc_settings,
.shell_file_path = emsdk.shell(raylib_dep),
.install_dir = install_dir,
});
b.getInstallStep().dependOn(emcc_step);
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep(
b,
b.getInstallPath(install_dir, html_filename),
&.{},
);
emrun_step.dependOn(emcc_step);
run_step.dependOn(emrun_step);
} else {
const exe = b.addExecutable(.{
.name = "core_basic_window",
.root_module = exe_mod,
.use_lld = target.result.os.tag == .windows,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
run_step.dependOn(&run_cmd.step);
}
}

View File

@ -0,0 +1,23 @@
.{
.name = .example,
.version = "0.0.1",
.minimum_zig_version = "0.16.0",
.paths = .{""},
.dependencies = .{
.raylib = .{
.path = "../../",
},
.emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk?ref=4.0.9#3bcf1dcd01f040f370e10fe673a092d9ed79ebb5",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
},
.sdl3 = .{
.url = "git+https://codeberg.org/7Games/zig-sdl3?ref=master#6d418ef3ddae99098414a96a88bf5e5fdb41785e",
.hash = "sdl3-0.1.9-NmT1QwiEJwByePqkmArtppCHQn8Y7kiSWcncT_Mop8ie",
.lazy = true,
},
},
.fingerprint = 0x6eec9b9f1a9d7aca,
}

View File

@ -0,0 +1,83 @@
/*******************************************************************************************
*
* raylib [core] example - Basic window (adapted for HTML5 platform)
*
* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples...
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
*
* This example has been created using raylib 1.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void); // Update and Draw one frame
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -0,0 +1,73 @@
//*******************************************************************************************
//*
//* raylib [core] example - Basic window (adapted for HTML5 platform)
//*
//* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
//* As you will notice, code structure is slightly different to the other examples...
//* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
//*
//* This example has been created using raylib 6.0 (www.raylib.com)
//* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
//*
//* Copyright (c) 2015 Ramon Santamaria (@raysan5)
//* Rewrite in Zig by HaxSam (@haxsam)
//*
//*******************************************************************************************
const rl = @import("raylib");
const std = @import("std");
const builtin = @import("builtin");
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
const screenWidth: c_int = 800;
const screenHeight: c_int = 450;
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
pub fn main() void {
// Initialization
//--------------------------------------------------------------------------------------
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
if (builtin.os.tag == .emscripten) {
std.os.emscripten.emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
} else {
rl.SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!rl.WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl.CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
fn UpdateDrawFrame() callconv(.c) void {
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl.BeginDrawing();
rl.ClearBackground(rl.RAYWHITE);
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LIGHTGRAY);
rl.EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -26,13 +26,13 @@ REM Checks if cl is available and skips to the argument loop if it is
REM (Prevents calling vcvarsall every time you run this script) REM (Prevents calling vcvarsall every time you run this script)
WHERE cl >nul 2>nul WHERE cl >nul 2>nul
IF %ERRORLEVEL% == 0 goto READ_ARGS IF %ERRORLEVEL% == 0 goto READ_ARGS
REM Activate the msvc build environment if cl isn't available yet REM Activate the msvc build environment if cl isn't available yet
IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" ( for /f "tokens=*" %%i in (
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" '"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath 2^>nul'
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" ( ) do set VS_PATH=%%i
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" IF defined VS_PATH (
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" ( set VC_INIT="%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat"
set VC_INIT="C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
) ELSE ( ) ELSE (
REM Initialize your vc environment here if the defaults don't work REM Initialize your vc environment here if the defaults don't work
REM set VC_INIT="C:\your\path\here\vcvarsall.bat" REM set VC_INIT="C:\your\path\here\vcvarsall.bat"
@ -167,7 +167,7 @@ IF NOT EXIST !TEMP_DIR!\ (
cd !TEMP_DIR! cd !TEMP_DIR!
REM raylib source folder REM raylib source folder
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33" set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c" set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c"
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include" set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
IF DEFINED REALLY_QUIET ( IF DEFINED REALLY_QUIET (

View File

@ -275,11 +275,20 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
#GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
endif endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
#GRAPHICS = GRAPHICS_API_OPENGL_ES3 #GRAPHICS = GRAPHICS_API_OPENGL_ES3
endif endif
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW)
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
#GRAPHICS = GRAPHICS_API_OPENGL_ES3
ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
$(error WEB_RGFW: Software rendering not supported!)
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
# By default use OpenGL ES 2.0 on Android # By default use OpenGL ES 2.0 on Android
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 GRAPHICS ?= GRAPHICS_API_OPENGL_ES2

View File

@ -252,7 +252,7 @@
#ifndef SUPPORT_FILEFORMAT_PIC #ifndef SUPPORT_FILEFORMAT_PIC
#define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default #define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default
#endif #endif
#ifdef SUPPORT_FILEFORMAT_PNM #ifndef SUPPORT_FILEFORMAT_PNM
#define SUPPORT_FILEFORMAT_PNM 0 // Disabled by default #define SUPPORT_FILEFORMAT_PNM 0 // Disabled by default
#endif #endif
#ifndef SUPPORT_FILEFORMAT_KTX #ifndef SUPPORT_FILEFORMAT_KTX

View File

@ -177,6 +177,13 @@ typedef struct {
RGFW_window *window; // Native display device (physical screen connection) RGFW_window *window; // Native display device (physical screen connection)
RGFW_monitor *monitor; RGFW_monitor *monitor;
mg_gamepads minigamepad; mg_gamepads minigamepad;
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
RGFW_surface *surface;
u8 *surfacePixels;
i32 surfaceWidth;
i32 surfaceHeight;
#endif
} PlatformData; } PlatformData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1120,9 +1127,37 @@ 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_SOFTWARE)
{
if (platform.surface)
{
// copy rlsw pixel data to the surface framebuffer
swReadPixels(0, 0, platform.surfaceWidth, platform.surfaceHeight, SW_RGBA, SW_UNSIGNED_BYTE, platform.surfacePixels);
// Mac wants a different pixel order. I cant seem to get this to work any other way
#if defined(__APPLE__)
unsigned char temp = 0;
unsigned char *p = NULL;
for (int i = 0; i < (platform.surfaceWidth * platform.surfaceHeight); i += 1)
{
p = platform.surfacePixels + (i * 4);
temp = p[0];
p[0] = p[2];
p[2] = temp;
}
#endif
// blit surface to the window
RGFW_window_blitSurface(platform.window, platform.surface);
}
}
#else
{ {
RGFW_window_swapBuffers_OpenGL(platform.window); RGFW_window_swapBuffers_OpenGL(platform.window);
} }
#endif
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition: Misc // Module Functions Definition: Misc
@ -1131,7 +1166,9 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds since InitTimer() // Get elapsed time measure in seconds since InitTimer()
double GetTime(void) double GetTime(void)
{ {
double time = get_time_seconds() - CORE.Time.base; // CORE.Time.base is nanoseconds as integer
double baseTime = (double)CORE.Time.base*1e-9;
double time = get_time_seconds() - baseTime;
return time; return time;
} }
@ -1313,6 +1350,9 @@ void PollInputEvents(void)
// Window events are also polled (Minimized, maximized, close...) // Window events are also polled (Minimized, maximized, close...)
case RGFW_windowResized: case RGFW_windowResized:
{ {
// set flag that the window was resized
CORE.Window.resizedLastFrame = true;
#if defined(__APPLE__) #if defined(__APPLE__)
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{ {
@ -1361,7 +1401,42 @@ void PollInputEvents(void)
CORE.Window.currentFbo.width = CORE.Window.screen.width; CORE.Window.currentFbo.width = CORE.Window.screen.width;
CORE.Window.currentFbo.height = CORE.Window.screen.height; CORE.Window.currentFbo.height = CORE.Window.screen.height;
#endif #endif
CORE.Window.resizedLastFrame = true;
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
#if defined(__APPLE__)
RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window);
CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f);
SetupViewport(platform.window->w * currentMonitor->pixelRatio, platform.window->h * currentMonitor->pixelRatio);
CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio;
CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio;
CORE.Window.currentFbo.width = CORE.Window.render.width;
CORE.Window.currentFbo.height = CORE.Window.render.height;
#endif
platform.surfaceWidth = CORE.Window.currentFbo.width;
platform.surfaceHeight = CORE.Window.currentFbo.height;
// in software mode we dont have the viewport so we need to reverse the highdpi changes
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
Vector2 scaleDpi = GetWindowScaleDPI();
platform.surfaceWidth *= scaleDpi.x;
platform.surfaceHeight *= scaleDpi.y;
}
if (platform.surfacePixels != NULL)
{
RL_FREE(platform.surfacePixels);
platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4);
}
if (platform.surface != NULL)
{
RGFW_surface_free(platform.surface);
platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8);
swResize(platform.surfaceWidth, platform.surfaceHeight);
}
#endif
} break; } break;
case RGFW_windowMaximized: case RGFW_windowMaximized:
{ {
@ -1639,6 +1714,12 @@ int InitPlatform(void)
hints->major = 4; hints->major = 4;
hints->minor = 3; hints->minor = 3;
} }
else if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
hints->major = 1;
hints->minor = 1;
hints->renderer = RGFW_glSoftware;
}
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4; if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4;
@ -1654,7 +1735,6 @@ int InitPlatform(void)
RGFW_setGlobalHints_OpenGL(hints); RGFW_setGlobalHints_OpenGL(hints);
platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL); platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL);
CORE.Time.base = get_time_seconds();
#ifndef PLATFORM_WEB_RGFW #ifndef PLATFORM_WEB_RGFW
i32 screenSizeWidth; i32 screenSizeWidth;
@ -1719,6 +1799,39 @@ int InitPlatform(void)
#endif #endif
} }
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// apple always scales for retina
#if defined(__APPLE__)
RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window);
CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f);
CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio;
CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio;
CORE.Window.currentFbo.width = CORE.Window.render.width;
CORE.Window.currentFbo.height = CORE.Window.render.height;
#endif
platform.surfaceWidth = CORE.Window.currentFbo.width;
platform.surfaceHeight = CORE.Window.currentFbo.height;
platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4);
if (platform.surfacePixels == NULL)
{
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software pixel buffer");
return -1;
}
platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8);
if (platform.surface == NULL)
{
RL_FREE(platform.surfacePixels);
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software surface");
return -1;
}
#endif
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s", TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : ""); FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
@ -1749,20 +1862,63 @@ int InitPlatform(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#if defined(RGFW_WAYLAND) #if defined(RGFW_WAYLAND)
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland, Software): Initialized successfully");
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software (fallback)): Initialized successfully");
}
else
{
if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully"); if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully");
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully"); else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully");
}
#elif defined(RGFW_X11) #elif defined(RGFW_X11)
#if defined(__APPLE__) #if defined(__APPLE__)
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully"); if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software, (MacOS)): Initialized successfully");
}
else
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, (MacOS)): Initialized successfully");
}
#else #else
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software): Initialized successfully");
}
else
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully");
}
#endif #endif
#elif defined (RGFW_WINDOWS) #elif defined (RGFW_WINDOWS)
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32, Software): Initialized successfully");
}
else
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully");
}
#elif defined(RGFW_WASM) #elif defined(RGFW_WASM)
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs, Software): Initialized successfully");
}
else
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully");
}
#elif defined(RGFW_MACOS) #elif defined(RGFW_MACOS)
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS, Software): Initialized successfully");
}
else
{
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully"); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully");
}
#endif #endif
mg_gamepads_init(&platform.minigamepad); mg_gamepads_init(&platform.minigamepad);
@ -1775,6 +1931,18 @@ void ClosePlatform(void)
{ {
mg_gamepads_free(&platform.minigamepad); mg_gamepads_free(&platform.minigamepad);
RGFW_window_close(platform.window); RGFW_window_close(platform.window);
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
if (platform.surfacePixels != NULL)
{
RL_FREE(platform.surfacePixels);
}
if (platform.surface != NULL)
{
RGFW_surface_free(platform.surface);
}
#endif
} }
// Keycode mapping // Keycode mapping
@ -1792,33 +1960,35 @@ double get_time_seconds(void)
#if defined(_WIN32) #if defined(_WIN32)
static LARGE_INTEGER freq = { 0 }; static LARGE_INTEGER freq = { 0 };
static int freq_init = 0; static bool freqInitialized = false;
LARGE_INTEGER counter; LARGE_INTEGER counter = { 0 };
if (!freq_init) { if (!freqInitialized)
{
// Lazy initialization
QueryPerformanceFrequency(&freq); QueryPerformanceFrequency(&freq);
freq_init = 1; freqInitialized = true;
} }
QueryPerformanceCounter(&counter); QueryPerformanceCounter(&counter);
currentTime = (double)counter.QuadPart/(double)freq.QuadPart; currentTime = (double)counter.QuadPart/(double)freq.QuadPart;
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__)
currentTime = emscripten_get_now()/1000.0; currentTime = emscripten_get_now()/1000.0;
#elif defined(__APPLE__) #elif defined(__APPLE__)
static mach_timebase_info_data_t tb; static mach_timebase_info_data_t tb = { 0 };
static int tb_initialized = 0; static bool tbInitialized = false;
if (!tbInitialized)
if (!tb_initialized) { {
mach_timebase_info(&tb); mach_timebase_info(&tb);
tb_initialized = 1; tbInitialized = true;
} }
uint64_t ticks = mach_absolute_time(); uint64_t ticks = mach_absolute_time();
currentTime = (double)ticks*(double)tb.numer/(double)tb.denom/1e9; currentTime = (double)ticks*(double)tb.numer/(double)tb.denom/1e9;
#elif defined(__linux__) #elif defined(__linux__)
struct timespec ts; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
currentTime = (double)ts.tv_sec + (double)ts.tv_nsec/1e9; currentTime = (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
#else #else
// fallback to cstd // Fallback to cstd
currentTime = (double)clock()/(double)CLOCKS_PER_SEC; currentTime = (double)clock()/(double)CLOCKS_PER_SEC;
#endif #endif

View File

@ -1426,7 +1426,7 @@ int InitPlatform(void)
if (eglGetPlatformDisplayEXT != NULL) platform.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, platform.gbmDevice, NULL); if (eglGetPlatformDisplayEXT != NULL) platform.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, platform.gbmDevice, NULL);
} }
// In case extension not found or display could not be retrieved, try useing legacy version // In case extension not found or display could not be retrieved, try using legacy version
if (platform.device == EGL_NO_DISPLAY) platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice); if (platform.device == EGL_NO_DISPLAY) platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice);
#endif #endif
if (platform.device == EGL_NO_DISPLAY) if (platform.device == EGL_NO_DISPLAY)

View File

@ -1702,8 +1702,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
// Copy data to allocated memory for default UnloadMusicStream // Copy data to allocated memory for default UnloadMusicStream
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize); unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
int it = dataSize/sizeof(unsigned char); for (int i = 0; i < dataSize; i++) newData[i] = data[i];
for (int i = 0; i < it; i++) newData[i] = data[i];
// Memory loaded version for jar_mod_load_file() // Memory loaded version for jar_mod_load_file()
if (dataSize && (dataSize < 32*1024*1024)) if (dataSize && (dataSize < 32*1024*1024))

View File

@ -1264,19 +1264,21 @@ RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Vector4 math // Module Functions Definition - Vector4 math
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Get vector zero
RMAPI Vector4 Vector4Zero(void) RMAPI Vector4 Vector4Zero(void)
{ {
Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f }; Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f };
return result; return result;
} }
// Get vector one
RMAPI Vector4 Vector4One(void) RMAPI Vector4 Vector4One(void)
{ {
Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f }; Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f };
return result; return result;
} }
// Add two vectors
RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
{ {
Vector4 result = { Vector4 result = {
@ -1288,6 +1290,7 @@ RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
return result; return result;
} }
// Add value to vector components
RMAPI Vector4 Vector4AddValue(Vector4 v, float add) RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
{ {
Vector4 result = { Vector4 result = {
@ -1299,6 +1302,7 @@ RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
return result; return result;
} }
// Substract vectors
RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
{ {
Vector4 result = { Vector4 result = {
@ -1310,6 +1314,7 @@ RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
return result; return result;
} }
// Substract value from vector components
RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
{ {
Vector4 result = { Vector4 result = {
@ -1321,18 +1326,21 @@ RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
return result; return result;
} }
// Vector length
RMAPI float Vector4Length(Vector4 v) RMAPI float Vector4Length(Vector4 v)
{ {
float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w)); float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
return result; return result;
} }
// Vector square length
RMAPI float Vector4LengthSqr(Vector4 v) RMAPI float Vector4LengthSqr(Vector4 v)
{ {
float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w); float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w);
return result; return result;
} }
// Vectors dot product
RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2) RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2)
{ {
float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w); float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w);
@ -1358,6 +1366,7 @@ RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2)
return result; return result;
} }
// Scale vector components by value (multiply)
RMAPI Vector4 Vector4Scale(Vector4 v, float scale) RMAPI Vector4 Vector4Scale(Vector4 v, float scale)
{ {
Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale }; Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale };
@ -1753,6 +1762,7 @@ RMAPI Matrix MatrixMultiply(Matrix left, Matrix right)
return result; return result;
} }
// Multiply matrix components by value
RMAPI Matrix MatrixMultiplyValue(Matrix left, float value) RMAPI Matrix MatrixMultiplyValue(Matrix left, float value)
{ {
Matrix result = { Matrix result = {
@ -2495,19 +2505,14 @@ RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
{ {
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
if (axisLength != 0.0f) if (length != 0.0f)
{ {
angle *= 0.5f; angle *= 0.5f;
float length = 0.0f;
float ilength = 0.0f;
// Vector3Normalize(axis) // Vector3Normalize(axis)
length = axisLength; float ilength = 1.0f/length;
if (length == 0.0f) length = 1.0f;
ilength = 1.0f/length;
axis.x *= ilength; axis.x *= ilength;
axis.y *= ilength; axis.y *= ilength;
axis.z *= ilength; axis.z *= ilength;

View File

@ -379,14 +379,14 @@ typedef struct CoreData {
} Gamepad; } Gamepad;
} Input; } Input;
struct { struct {
double current; // Current time measure double current; // Current time measure (seconds)
double previous; // Previous time measure double previous; // Previous time measure (seconds)
double update; // Time measure for frame update double update; // Time measure for frame update (seconds)
double draw; // Time measure for frame draw double draw; // Time measure for frame draw (seconds)
double frame; // Time measure for one frame double frame; // Time measure for one frame (seconds)
double target; // Desired time for one frame, if 0 not applied double target; // Desired time for one frame, if 0 not applied (seconds)
unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM) unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds)
unsigned int frameCounter; // Frame counter unsigned int frameCounter; // Frame counter (frames)
} Time; } Time;
} CoreData; } CoreData;
@ -4125,8 +4125,8 @@ Vector2 GetMouseDelta(void)
{ {
Vector2 delta = { 0 }; Vector2 delta = { 0 };
delta.x = CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x; delta.x = (CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x)*CORE.Input.Mouse.scale.x;
delta.y = CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y; delta.y = (CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y)*CORE.Input.Mouse.scale.y;
return delta; return delta;
} }

View File

@ -1139,21 +1139,23 @@ typedef struct rlglData {
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static bool isGpuReady = false;
static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR; static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR;
static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR; static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
static rlglData RLGL = { 0 }; static rlglData RLGL = { 0 };
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 #endif
static bool isGpuReady = false;
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3) #if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
// VAO functions entry points
// NOTE: VAO functionality is exposed through extensions (OES) // NOTE: VAO functionality is exposed through extensions (OES)
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL; static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL; static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL; static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
// NOTE: Instancing functionality could also be available through extension // Instancing functionality entry points
// NOTE: Instancing functionality could be available through extensions
static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL; static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL;
static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL; static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL;
static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;

View File

@ -4105,7 +4105,7 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa
// Check for distances squared to avoid sqrtf() // Check for distances squared to avoid sqrtf()
float radSum = radius1 + radius2; float radSum = radius1 + radius2;
if (Vector3DistanceSqr(center1, center2) <= radSum*radSum) collision = true; if (Vector3DistanceSqr(center1, center2) <= (radSum*radSum)) collision = true;
return collision; return collision;
} }
@ -4131,18 +4131,13 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)
{ {
bool collision = false; bool collision = false;
float dmin = 0; Vector3 closestPoint = {
Clamp(center.x, box.min.x, box.max.x),
Clamp(center.y, box.min.y, box.max.y),
Clamp(center.z, box.min.z, box.max.z)
};
if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2); if (Vector3DistanceSqr(center, closestPoint) <= (radius*radius)) collision = true;
else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);
if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);
else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);
if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);
else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);
if (dmin <= (radius*radius)) collision = true;
return collision; return collision;
} }

View File

@ -13,7 +13,7 @@
* supported by default, to remove support, #define as 0 in this module or your build system * supported by default, to remove support, #define as 0 in this module or your build system
* *
* #define MAX_TEXT_BUFFER_LENGTH 1024 * #define MAX_TEXT_BUFFER_LENGTH 1024
* TextSplit() function static buffer max size * Text functions using static buffer max size
* *
* #define MAX_TEXTSPLIT_COUNT 128 * #define MAX_TEXTSPLIT_COUNT 128
* TextSplit() function static substrings pointers array (pointing to static buffer) * TextSplit() function static substrings pointers array (pointing to static buffer)