5 Commits

Author SHA1 Message Date
30fa673ef2 [build][Zig] 0.17 migration (#5951)
* Bump zemscripten to branch suporting latest zig 0.17

* zemscripten changes for build.zig

* general zig 0.17 changes for build.zig

- update calls to `buildDir` and `findProgram` to their new
interfaces/calling sites.
- fix issue where you can't import zon anymore as slice (?)

* Update minimum zig version

* Remove redundant emsdk activations

Examples depend on raylib anyway, and if using emsdk, it will be
activated already.  This activation was causing an error in zig
nightly, so the change here.

* better `getInstallPath` alternative

* Remove example install -> emcc dependency in graph

* Fix emrun path

* Fix file output issue

* Bump zig to latest nightly

* Get emrun step to work

* Remove zemscripten dependency and consolidate with emsdk struct

Bump zig to 0.17.0

Clean up zemscripten struct

Consolidate emscripten-related structs

* Less breaking changes, keep old name, bring back pub fields

* [build][Zig] Fix missing include path and make emsdk a lazy dependency

* [build][Zig] Replace deprecated lazyDependency with the new dependencyLazy

---------

Co-authored-by: Jairo Correa <jairo@omnidoki.com>
2026-10-04 19:08:17 +02:00
5c9e83e642 [rcore][SDL] Accumulate relative mouse motion per frame (#6215)
Co-authored-by: snowyukitty <270071858+snowyukitty@users.noreply.github.com>
2026-10-04 19:01:54 +02:00
791dd6d627 [rtext] Check for empty strings in TextToPascal and TextToCamel (#6213)
* [rtext] Check for empty strings in TextToPascal/TextToCamel

* [rtext] Add parentheses to conditions
2026-10-04 19:00:53 +02:00
a9e3027ebc [rcore][win32] Implement IsKeyPressedRepeat (#6218) 2026-10-04 18:55:27 +02:00
0e8385c890 [examples][textures_image_processing] Fix up arrow wraparound logic (#6217) 2026-10-04 16:54:33 +02:00
6 changed files with 304 additions and 112 deletions

354
build.zig
View File

@ -2,85 +2,257 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
pub const emsdk = struct { pub const emsdk = struct {
const zemscripten = @import("zemscripten"); const emsdk_version = "4.0.19"; // inline constant used only in activate
var emsdk_dep: ?*std.Build.Dependency = null;
pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath { // ---------- core types ----------
return raylib_dep.path("src/shell.html"); pub const EmccFlags = std.StringHashMap(void);
} pub const EmccSettings = std.StringHashMap([]const u8);
const EmsdkAllocator = enum {
pub const FlagsOptions = struct { none,
optimize: std.builtin.OptimizeMode, dlmalloc,
asyncify: bool = true, emmalloc,
@"emmalloc-debug",
@"emmalloc-memvalidate",
@"emmalloc-verbose",
mimalloc,
}; };
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: FlagsOptions) zemscripten.EmccFlags { pub const ResourceFile = struct {
var emcc_flags = zemscripten.emccDefaultFlags(allocator, .{ src_path: std.Build.LazyPath,
.optimize = options.optimize, virtual_path: ?[]const u8 = null,
.fsanitize = true,
});
if (options.asyncify) fn get(self: ResourceFile, b: *std.Build) []const u8 {
emcc_flags.put("-sASYNCIFY", {}) catch unreachable; return if (self.virtual_path) |vp|
b.fmt("{s}@{s}", .{ self.src_path.getDisplayName(), vp })
else
self.src_path.getDisplayName();
}
};
return emcc_flags; pub const EmccStepOptions = struct {
optimize: std.builtin.OptimizeMode,
flags: EmccFlags,
settings: EmccSettings,
use_preload_plugins: bool = false,
embed_paths: ?[]const ResourceFile = null,
preload_paths: ?[]const ResourceFile = null,
shell_file_path: ?std.Build.LazyPath = null,
js_library_path: ?std.Build.LazyPath = null,
out_file_name: []const u8,
install_dir: std.Build.InstallDir,
};
// ---------- helpers ----------
pub fn emsdkDep(b: *std.Build) !*std.Build.Dependency {
if (emsdk_dep == null) {
emsdk_dep = try b.dependencyLazy("emsdk", .{});
} }
pub const SettingsOptions = struct { return emsdk_dep.?;
}
pub fn path(b: *std.Build, sub_path: []const u8) !std.Build.LazyPath {
return (try emsdkDep(b)).path(sub_path);
}
pub fn emccPath(b: *std.Build) !std.Build.LazyPath {
return try emsdk.path(b, "upstream/emscripten/emcc.py");
}
pub fn emrunPath(b: *std.Build) !std.Build.LazyPath {
return switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "upstream/emscripten/emrun.bat"),
else => try emsdk.path(b, "upstream/emscripten/emrun"),
};
}
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: struct {
optimize: std.builtin.OptimizeMode,
asyncify: bool = true,
fsanitize: bool = true,
}) EmccFlags {
var flags = EmccFlags.init(allocator);
switch (options.optimize) {
.Debug => {
flags.put("-O0", {}) catch @panic("OOM");
flags.put("-gsource-map", {}) catch @panic("OOM");
if (options.fsanitize)
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
},
.ReleaseSafe => {
flags.put("-O3", {}) catch @panic("OOM");
if (options.fsanitize) {
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
flags.put("-fsanitize-minimal-runtime", {}) catch @panic("OOM");
}
},
.ReleaseFast => flags.put("-O3", {}) catch @panic("OOM"),
.ReleaseSmall => flags.put("-Oz", {}) catch @panic("OOM"),
}
if (options.asyncify)
flags.put("-sASYNCIFY", {}) catch @panic("OOM");
return flags;
}
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: struct {
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
es3: bool = false, es3: bool = false,
glfw3: bool = true, glfw3: bool = true,
memory_growth: bool = false, memory_growth: bool = false,
total_memory: u32 = 134217728, total_memory: u32 = 134217728,
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc, emsdk_allocator: EmsdkAllocator = .emmalloc,
}; }) EmccSettings {
var settings = EmccSettings.init(allocator);
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: SettingsOptions) zemscripten.EmccSettings { switch (options.optimize) {
var emcc_settings = zemscripten.emccDefaultSettings(allocator, .{ .Debug, .ReleaseSafe => {
.optimize = options.optimize, settings.put("SAFE_HEAP", "1") catch @panic("OOM");
.emsdk_allocator = options.emsdk_allocator, settings.put("STACK_OVERFLOW_CHECK", "1") catch @panic("OOM");
}); settings.put("ASSERTIONS", "1") catch @panic("OOM");
},
else => {},
}
settings.put("MALLOC", @tagName(options.emsdk_allocator)) catch @panic("OOM");
if (options.es3) { if (options.es3) {
emcc_settings.put("FULL_ES3", "1") catch unreachable; settings.put("FULL_ES3", "1") catch @panic("OOM");
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable; settings.put("MIN_WEBGL_VERSION", "2") catch @panic("OOM");
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable; settings.put("MAX_WEBGL_VERSION", "2") catch @panic("OOM");
}
if (options.glfw3) {
emcc_settings.put("USE_GLFW", "3") catch unreachable;
} }
if (options.glfw3)
settings.put("USE_GLFW", "3") catch @panic("OOM");
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable; const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch @panic("OOM");
settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch @panic("OOM");
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable; settings.put("TOTAL_MEMORY", total_memory) catch @panic("OOM");
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable; settings.put("FORCE_FILESYSTEM", "1") catch @panic("OOM");
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable; settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch @panic("OOM");
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
if (options.memory_growth) if (options.memory_growth)
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable; settings.put("ALLOW_MEMORY_GROWTH", "1") catch @panic("OOM");
return emcc_settings; return settings;
} }
pub fn emccStep(b: *std.Build, raylib: *std.Build.Step.Compile, wasm: *std.Build.Step.Compile, options: zemscripten.StepOptions) *std.Build.Step { // ---------- step builders ----------
const activate_emsdk_step = zemscripten.activateEmsdkStep(b); pub fn emccStep(b: *std.Build, src_paths: []const std.Build.LazyPath, compile_steps: []const *std.Build.Step.Compile, options: EmccStepOptions) !*std.Build.Step {
var emcc = b.addRunFile(try emccPath(b));
const emsdk_dep = b.dependency("emsdk", .{}); // flags
raylib.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include")); {
wasm.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include")); var it = options.flags.iterator();
while (it.next()) |kv| emcc.addArg(kv.key_ptr.*);
const emcc_step = zemscripten.emccStep(b, wasm, options);
emcc_step.dependOn(activate_emsdk_step);
return emcc_step;
} }
pub fn emrunStep( // settings
b: *std.Build, {
html_path: []const u8, var it = options.settings.iterator();
extra_args: []const []const u8, while (it.next()) |kv| {
) *std.Build.Step { emcc.addArg(b.fmt("-s{s}={s}", .{ kv.key_ptr.*, kv.value_ptr.* }));
return zemscripten.emrunStep(b, html_path, extra_args); }
}
// source files & artifact dependencies
for (src_paths) |sp| emcc.addFileArg(sp);
for (compile_steps) |cs| {
emcc.addArtifactArg(cs);
cs.root_module.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
for (cs.root_module.getGraph().modules) |mod| {
for (mod.link_objects.items) |lo| {
if (lo == .other_step) {
const linked = lo.other_step;
if (linked.kind == .lib) emcc.addArtifactArg(linked);
}
}
}
}
emcc.addArg("-o");
const out_file = emcc.addOutputFileArg(options.out_file_name);
// optional args
if (options.use_preload_plugins) emcc.addArg("--use-preload-plugins");
if (options.embed_paths) |eps| for (eps) |ep| {
emcc.addArg("--embed-file");
emcc.addFileArg(ep.src_path);
};
if (options.preload_paths) |pps| for (pps) |pp| {
emcc.addArg("--preload-file");
emcc.addArg(pp.get(b));
};
if (options.shell_file_path) |sfp| {
emcc.addArg("--shell-file");
emcc.addFileArg(sfp);
}
if (options.js_library_path) |jlp| {
emcc.addArg("--js-library");
emcc.addFileArg(jlp);
}
const install = b.addInstallDirectory(.{
.source_dir = out_file.dirname(),
.install_dir = options.install_dir,
.install_subdir = "",
});
install.step.dependOn(&emcc.step);
return &install.step;
}
pub fn emrunStep(b: *std.Build, html_path: std.Build.LazyPath, extra_args: []const []const u8) !*std.Build.Step {
var emrun = b.addRunFile(try emrunPath(b));
emrun.addArgs(extra_args);
emrun.addFileArg(html_path);
return &emrun.step;
}
pub fn activateEmsdkStep(b: *std.Build) !*std.Build.Step {
const user = b.step("Activate EMSDK", "Install/Update and prepare emscripten sdk");
const script = switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "emsdk.bat"),
else => try emsdk.path(b, "emsdk"),
};
var update = b.addRunFile(script);
update.addArg("update");
// chmod / takeown for script
const make_script_exec: ?*std.Build.Step.Run = switch (builtin.target.os.tag) {
.linux, .macos => blk: {
var cmd = b.addSystemCommand(&.{ "chmod", "+x" });
cmd.addFileArg(script);
break :blk cmd;
},
.windows => blk: {
var cmd = b.addSystemCommand(&.{ "takeown", "/f" });
cmd.addFileArg(script);
break :blk cmd;
},
else => null,
};
if (make_script_exec) |mse| update.step.dependOn(&mse.step);
var install = b.addRunFile(script);
install.addArg("install");
install.addArg(emsdk_version);
install.step.dependOn(&update.step);
var activate = b.addRunFile(script);
activate.addArg("activate");
activate.addArg(emsdk_version);
activate.step.dependOn(&install.step);
user.dependOn(&activate.step);
// also ensure emcc/emrun are executable on Unix
if (builtin.target.os.tag == .linux or builtin.target.os.tag == .macos) {
for ([_]std.Build.LazyPath{ try emccPath(b), try emrunPath(b) }) |p| {
var cmd = b.addSystemCommand(&.{ "chmod", "a+x" });
cmd.addFileArg(p);
cmd.step.dependOn(&install.step);
user.dependOn(&cmd.step);
}
}
return user;
} }
}; };
@ -92,7 +264,7 @@ pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool)
} }
fn findWaylandScanner(b: *std.Build) void { fn findWaylandScanner(b: *std.Build) void {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch { _ = b.findProgram(.{ .names = &.{"wayland-scanner"} }) orelse {
std.log.err( std.log.err(
\\ `wayland-scanner` may not be installed on the system. \\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend` \\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
@ -126,13 +298,13 @@ pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
mod.linkSystemLibrary("GL", .{}); mod.linkSystemLibrary("GL", .{});
} }
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void { pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) !void {
// Include xcode_frameworks for cross compilation // Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| { const dep = try b.dependencyLazy("xcode_frameworks", .{});
mod.addSystemFrameworkPath(dep.path("Frameworks")); mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include")); mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib")); mod.addLibraryPath(dep.path("lib"));
}
mod.linkFramework("Foundation", .{}); mod.linkFramework("Foundation", .{});
mod.linkFramework("CoreServices", .{}); mod.linkFramework("CoreServices", .{});
@ -268,7 +440,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}); });
_ = raylib_flags_arr.pop(); _ = raylib_flags_arr.pop();
linkMacOS(b, raylib_mod); try linkMacOS(b, raylib_mod);
}, },
.emscripten => { .emscripten => {
switch (opengl_version) { switch (opengl_version) {
@ -279,7 +451,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib_mod.addCMacro("PLATFORM_WEB", ""); raylib_mod.addCMacro("PLATFORM_WEB", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b); raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step); raylib.step.dependOn(activate_emsdk_step);
}, },
else => @panic("Target is not supported with this platform"), else => @panic("Target is not supported with this platform"),
@ -328,7 +502,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
} }
}, },
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod), .freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => linkMacOS(b, raylib_mod), .macos => try linkMacOS(b, raylib_mod),
.emscripten => { .emscripten => {
switch (opengl_version) { switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2, .auto => opengl_version = OpenglVersion.gles_2,
@ -337,7 +511,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
} }
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", ""); raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step); raylib.step.dependOn(activate_emsdk_step);
}, },
else => @panic("Target is not supported with this platform"), else => @panic("Target is not supported with this platform"),
@ -483,12 +660,13 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
return raylib; return raylib;
} }
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void { fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) !void {
if (b.lazyDependency("raygui", .{ const raygui_dep = try b.dependencyLazy("raygui", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.link_libc = true, .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);
@ -509,7 +687,6 @@ fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.buil
const c_mod = c.createModule(); const c_mod = c.createModule();
c_mod.linkLibrary(raylib); c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM"); b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
} }
pub const Options = struct { pub const Options = struct {
@ -630,7 +807,7 @@ pub fn build(b: *std.Build) !void {
translateCMod("rlgl", b, target, optimize, lib); translateCMod("rlgl", b, target, optimize, lib);
if (options.raygui) { if (options.raygui) {
addRaygui(b, target, optimize, lib); try addRaygui(b, target, optimize, lib);
} }
const examples = b.step("examples", "build/install all examples"); const examples = b.step("examples", "build/install all examples");
@ -655,7 +832,7 @@ fn addExamples(
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 });
var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true }); var dir = try b.root.openDir(b.graph.io, module_subpath, .{ .iterate = true });
defer dir.close(b.graph.io); defer dir.close(b.graph.io);
var iter = dir.iterate(); var iter = dir.iterate();
@ -705,7 +882,7 @@ fn addExamples(
exe_mod.addCMacro("PLATFORM_WEB", ""); exe_mod.addCMacro("PLATFORM_WEB", "");
const wasm = b.addLibrary(.{ const wasm = b.addLibrary(.{
.name = filename, .name = b.fmt("{s}.html", .{filename}),
.root_module = exe_mod, .root_module = exe_mod,
}); });
@ -713,24 +890,40 @@ fn addExamples(
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 EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const emsdk.zemscripten.EmccFilePath); const SerialResourceFile = struct { src_path: []const u8, virtual_path: []const u8 };
const EmccExamplesPreloadKV = struct { []const u8, []const emsdk.zemscripten.EmccFilePath }; const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const SerialResourceFile);
const emcc_examples_preloads: []const EmccExamplesPreloadKV = @import("examples/example_resources.zon"); const EmccExamplesPreloadSerial = struct { []const u8, []const SerialResourceFile };
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads); const emcc_examples_preloads_serial: []const EmccExamplesPreloadSerial = @import("examples/example_resources.zon");
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads_serial);
const preload_paths: ?[]emsdk.ResourceFile = blk: {
if (emcc_examples_preloads_map.get(filename)) |resource_files| {
var rfs = try b.allocator.alloc(emsdk.ResourceFile, resource_files.len);
for (resource_files, 0..) |resource_file, rfidx| {
rfs[rfidx] = .{
.src_path = b.path(resource_file.src_path),
.virtual_path = resource_file.virtual_path,
};
}
break :blk rfs;
} else break :blk null;
};
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{ const emcc_step = try emsdk.emccStep(b, &.{}, &.{ raylib, wasm }, .{
.optimize = optimize, .optimize = optimize,
.flags = emcc_flags, .flags = emcc_flags,
.settings = emcc_settings, .settings = emcc_settings,
.preload_paths = emcc_examples_preloads_map.get(filename) orelse &.{}, .preload_paths = preload_paths,
.shell_file_path = b.path("src/shell.html"), .shell_file_path = b.path("src/shell.html"),
.install_dir = install_dir, .install_dir = install_dir,
.out_file_name = wasm.name,
}); });
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name}); const emrun_step = try emsdk.emrunStep(
const emrun_step = emsdk.emrunStep(
b, b,
b.getInstallPath(install_dir, html_filename), b.graph.path(.install_prefix, b.fmt(
"web/{s}/{s}/{s}",
.{ module, filename, wasm.name },
)),
&.{}, &.{},
); );
@ -765,7 +958,7 @@ fn waylandGenerate(
comptime waylandDir: []const u8, comptime waylandDir: []const u8,
comptime source: bool, comptime source: bool,
) !void { ) !void {
const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true }); const dir = try b.root.openDir(b.graph.io, waylandDir, .{ .iterate = true });
defer dir.close(b.graph.io); defer dir.close(b.graph.io);
var iter = dir.iterate(); var iter = dir.iterate();
@ -799,4 +992,3 @@ fn waylandGenerate(
} }
} }
} }

View File

@ -1,7 +1,7 @@
.{ .{
.name = .raylib, .name = .raylib,
.version = "6.0.0", .version = "6.0.0",
.minimum_zig_version = "0.16.0", .minimum_zig_version = "0.17.0",
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications. .fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
@ -19,10 +19,7 @@
.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",
}, .lazy = true,
.zemscripten = .{
.url = "git+https://github.com/zig-gamedev/zemscripten#3fa4b778852226c7346bdcc3c1486e875a9a6d02",
.hash = "zemscripten-0.2.0-dev-sRlDqApRAACspTbAZnuNKWIzfWzSYgYkb2nWAXZ-tqqt",
}, },
}, },

View File

@ -109,7 +109,7 @@ int main(void)
else if (IsKeyPressed(KEY_UP)) else if (IsKeyPressed(KEY_UP))
{ {
currentProcess--; currentProcess--;
if (currentProcess < 0) currentProcess = 7; if (currentProcess < 0) currentProcess = (NUM_PROCESSES - 1);
textureReload = true; textureReload = true;
} }

View File

@ -1431,7 +1431,11 @@ void PollInputEvents(void)
CORE.Input.Mouse.currentWheelMove.y = 0; CORE.Input.Mouse.currentWheelMove.y = 0;
// Register previous mouse position // Register previous mouse position
if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; if (CORE.Input.Mouse.cursorLocked)
{
CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
}
else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
// Reset last gamepad button/axis registered state // Reset last gamepad button/axis registered state
@ -1727,9 +1731,8 @@ void PollInputEvents(void)
{ {
if (CORE.Input.Mouse.cursorLocked) if (CORE.Input.Mouse.cursorLocked)
{ {
CORE.Input.Mouse.currentPosition.x = (float)event.motion.xrel; CORE.Input.Mouse.currentPosition.x += (float)event.motion.xrel;
CORE.Input.Mouse.currentPosition.y = (float)event.motion.yrel; CORE.Input.Mouse.currentPosition.y += (float)event.motion.yrel;
CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
} }
else else
{ {

View File

@ -1374,7 +1374,6 @@ void PollInputEvents(void)
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
memcpy(CORE.Input.Keyboard.previousKeyState, CORE.Input.Keyboard.currentKeyState, sizeof(CORE.Input.Keyboard.previousKeyState)); memcpy(CORE.Input.Keyboard.previousKeyState, CORE.Input.Keyboard.currentKeyState, sizeof(CORE.Input.Keyboard.previousKeyState));
memset(CORE.Input.Keyboard.keyRepeatInFrame, 0, sizeof(CORE.Input.Keyboard.keyRepeatInFrame));
// Register previous mouse wheel state // Register previous mouse wheel state
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove; CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
@ -2074,6 +2073,7 @@ static void HandleKey(WPARAM wparam, LPARAM lparam, char state)
{ {
CORE.Input.Keyboard.currentKeyState[key] = state; CORE.Input.Keyboard.currentKeyState[key] = state;
if (((HIWORD(lparam) & KF_REPEAT) != 0) && (state == 1)) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
if ((key == CORE.Input.Keyboard.exitKey) && (state == 1)) CORE.Window.shouldClose = true; if ((key == CORE.Input.Keyboard.exitKey) && (state == 1)) CORE.Window.shouldClose = true;
} }
else TRACELOG(LOG_WARNING, "INPUT: Unknown (or currently unhandled) virtual keycode %d (0x%x)", wparam, wparam); else TRACELOG(LOG_WARNING, "INPUT: Unknown (or currently unhandled) virtual keycode %d (0x%x)", wparam, wparam);

View File

@ -2185,7 +2185,7 @@ char *TextToPascal(const char *text)
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
if (text != NULL) if ((text != NULL) && (text[0] != '\0'))
{ {
// Upper case first character // Upper case first character
if ((text[0] >= 'a') && (text[0] <= 'z')) buffer[0] = text[0] - 32; if ((text[0] >= 'a') && (text[0] <= 'z')) buffer[0] = text[0] - 32;
@ -2269,7 +2269,7 @@ char *TextToCamel(const char *text)
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
if (text != NULL) if ((text != NULL) && (text[0] != '\0'))
{ {
// Lower case first character // Lower case first character
if ((text[0] >= 'A') && (text[0] <= 'Z')) buffer[0] = text[0] + 32; if ((text[0] >= 'A') && (text[0] <= 'Z')) buffer[0] = text[0] + 32;