diff --git a/.github/workflows/update_examples.yml b/.github/workflows/update_examples.yml index 4da73e871..a861f6e1d 100644 --- a/.github/workflows/update_examples.yml +++ b/.github/workflows/update_examples.yml @@ -50,6 +50,17 @@ jobs: export REXM_EXAMPLES_VS2022_SLN_FILE="${{ github.workspace }}/projects/VS2022/raylib.sln" export EMSDK_PATH="${{ github.workspace }}/emsdk-cache/emsdk-main" ./rexm update + cd tools/rexm/VS2022 + msbuild.exe rexm.sln /target:rexm /property:Configuration=Release /property:Platform=x64 + cd ../../.. + set REXM_EXAMPLES_BASE_PATH="examples" + set REXM_EXAMPLES_WEB_PATH="../raylib.com/examples" + set REXM_EXAMPLES_TEMPLATE_FILE_PATH="examples/examples_template.c" + set REXM_EXAMPLES_TEMPLATE_SCREENSHOT_PATH="examples/examples_template.png" + set REXM_EXAMPLES_COLLECTION_FILE_PATH="examples/examples_list.txt" + set REXM_EXAMPLES_VS2022_SLN_FILE="projects/VS2022/raylib.sln" + #set EMSDK_PATH="D:/a/raylib/raylib/emsdk-cache/emsdk-main" + .\tools\rexm\VS2022\build\rexm\bin\x64\Release\rexm.exe build core_basic_window cd ../.. shell: bash diff --git a/build.zig b/build.zig index 409c57ab5..1546e41fb 100644 --- a/build.zig +++ b/build.zig @@ -2,7 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); /// Minimum supported version of Zig -const min_ver = "0.13.0"; +const min_ver = "0.15.1"; const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str; const emccOutputFile = "index.html"; @@ -100,25 +100,31 @@ const config_h_flags = outer: { }; fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { - var raylib_flags_arr = std.ArrayList([]const u8).init(b.allocator); - defer raylib_flags_arr.deinit(); + var raylib_flags_arr: std.ArrayList([]const u8) = .empty; + defer raylib_flags_arr.deinit(b.allocator); - try raylib_flags_arr.appendSlice(&[_][]const u8{ - "-std=gnu99", - "-D_GNU_SOURCE", - "-DGL_SILENCE_DEPRECATION=199309L", - "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 - }); + try raylib_flags_arr.appendSlice( + b.allocator, + &[_][]const u8{ + "-std=gnu99", + "-D_GNU_SOURCE", + "-DGL_SILENCE_DEPRECATION=199309L", + "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 + }, + ); if (options.shared) { - try raylib_flags_arr.appendSlice(&[_][]const u8{ - "-fPIC", - "-DBUILD_LIBTYPE_SHARED", - }); + try raylib_flags_arr.appendSlice( + b.allocator, + &[_][]const u8{ + "-fPIC", + "-DBUILD_LIBTYPE_SHARED", + }, + ); } // Sets a flag indiciating the use of a custom `config.h` - try raylib_flags_arr.append("-DEXTERNAL_CONFIG_FLAGS"); + try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); if (options.config.len > 0) { // Splits a space-separated list of config flags into multiple flags // @@ -128,7 +134,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // Apply config flags supplied by the user while (config_iter.next()) |config_flag| - try raylib_flags_arr.append(config_flag); + try raylib_flags_arr.append(b.allocator, config_flag); // Apply all relevant configs from `src/config.h` *except* the user-specified ones // @@ -146,11 +152,11 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } // Otherwise, append default value from config.h to compile flags - try raylib_flags_arr.append(flag); + try raylib_flags_arr.append(b.allocator, flag); } } else { // Set default config if no custome config got set - try raylib_flags_arr.appendSlice(&config_h_flags); + try raylib_flags_arr.appendSlice(b.allocator, &config_h_flags); } const raylib = b.addLibrary(.{ @@ -168,28 +174,28 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.addIncludePath(b.path("src/external/glfw/include")); } - var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); + var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2); c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" }); if (options.rshapes) { - try c_source_files.append("src/rshapes.c"); - try raylib_flags_arr.append("-DSUPPORT_MODULE_RSHAPES"); + try c_source_files.append(b.allocator, "src/rshapes.c"); + try raylib_flags_arr.append(b.allocator, "-DSUPPORT_MODULE_RSHAPES"); } if (options.rtextures) { - try c_source_files.append("src/rtextures.c"); - try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXTURES"); + try c_source_files.append(b.allocator, "src/rtextures.c"); + try raylib_flags_arr.append(b.allocator, "-DSUPPORT_MODULE_RTEXTURES"); } if (options.rtext) { - try c_source_files.append("src/rtext.c"); - try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXT"); + try c_source_files.append(b.allocator, "src/rtext.c"); + try raylib_flags_arr.append(b.allocator, "-DSUPPORT_MODULE_RTEXT"); } if (options.rmodels) { - try c_source_files.append("src/rmodels.c"); - try raylib_flags_arr.append("-DSUPPORT_MODULE_RMODELS"); + try c_source_files.append(b.allocator, "src/rmodels.c"); + try raylib_flags_arr.append(b.allocator, "-DSUPPORT_MODULE_RMODELS"); } if (options.raudio) { - try c_source_files.append("src/raudio.c"); - try raylib_flags_arr.append("-DSUPPORT_MODULE_RAUDIO"); + try c_source_files.append(b.allocator, "src/raudio.c"); + try raylib_flags_arr.append(b.allocator, "-DSUPPORT_MODULE_RAUDIO"); } if (options.opengl_version != .auto) { @@ -200,7 +206,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. switch (target.result.os.tag) { .windows => { switch (options.platform) { - .glfw => try c_source_files.append("src/rglfw.c"), + .glfw => try c_source_files.append(b.allocator, "src/rglfw.c"), .rgfw, .sdl, .drm, .android => {}, } @@ -261,14 +267,14 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); raylib.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); - var libcData = std.ArrayList(u8).init(b.allocator); - const writer = libcData.writer(); + var libcData: std.ArrayList(u8) = .empty; + var aw: std.Io.Writer.Allocating = .fromArrayList(b.allocator, &libcData); try (std.zig.LibCInstallation{ .include_dir = androidIncludePath, .sys_include_dir = androidIncludePath, .crt_dir = androidApiSpecificPath, - }).render(writer); - const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice()); + }).render(&aw.writer); + const libcFile = b.addWriteFiles().add("android-libc.txt", try libcData.toOwnedSlice(b.allocator)); raylib.setLibCFile(libcFile); if (options.opengl_version == .auto) { @@ -279,7 +285,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, .android); } else { - try c_source_files.append("src/rglfw.c"); + try c_source_files.append(b.allocator, "src/rglfw.c"); if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { raylib.root_module.addCMacro("_GLFW_X11", ""); @@ -320,7 +326,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } }, .freebsd, .openbsd, .netbsd, .dragonfly => { - try c_source_files.append("rglfw.c"); + try c_source_files.append(b.allocator, "rglfw.c"); raylib.linkSystemLibrary("GL"); raylib.linkSystemLibrary("rt"); raylib.linkSystemLibrary("dl"); @@ -343,7 +349,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } // On macos rglfw.c include Objective-C files. - try raylib_flags_arr.append("-ObjC"); + try raylib_flags_arr.append(b.allocator, "-ObjC"); raylib.root_module.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = raylib_flags_arr.items, diff --git a/build.zig.zon b/build.zig.zon index 571550860..7037008ed 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .raylib, .version = "5.5.0", - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.1", .fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications. diff --git a/examples/core/core_3d_fps_controller.c b/examples/core/core_3d_fps_controller.c index 68fec1af9..4d8962654 100644 --- a/examples/core/core_3d_fps_controller.c +++ b/examples/core/core_3d_fps_controller.c @@ -106,9 +106,9 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - Vector2 mouse_delta = GetMouseDelta(); - lookRotation.x -= mouse_delta.x*sensitivity.x; - lookRotation.y += mouse_delta.y*sensitivity.y; + Vector2 mouseDelta = GetMouseDelta(); + lookRotation.x -= mouseDelta.x*sensitivity.x; + lookRotation.y += mouseDelta.y*sensitivity.y; char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A)); char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S)); @@ -261,7 +261,10 @@ static void UpdateCameraAngle(Camera *camera) Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up)); // Rotate view vector around right axis - Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, -lookRotation.y - lean.y); + float pitchAngle = -lookRotation.y - + lean.y; + pitchAngle = Clamp(pitchAngle, -PI / 2 + 0.0001f, PI / 2 - 0.0001f); // Clamp angle so it doesn't go past straight up or straight down + Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, pitchAngle); // Head animation // Rotate up direction around forward axis diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c index 58c1c4035..55f00b809 100644 --- a/examples/core/core_input_mouse.c +++ b/examples/core/core_input_mouse.c @@ -29,7 +29,6 @@ int main(void) Vector2 ballPosition = { -100.0f, -100.0f }; Color ballColor = DARKBLUE; - int isCursorHidden = 0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- @@ -41,15 +40,13 @@ int main(void) //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_H)) { - if (isCursorHidden == 0) + if (IsCursorHidden()) { - HideCursor(); - isCursorHidden = 1; + ShowCursor(); } else { - ShowCursor(); - isCursorHidden = 0; + HideCursor(); } } @@ -75,7 +72,7 @@ int main(void) DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY); - if (isCursorHidden == 1) DrawText("CURSOR HIDDEN", 20, 60, 20, RED); + if (!IsCursorHidden()) DrawText("CURSOR HIDDEN", 20, 60, 20, RED); else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME); EndDrawing(); diff --git a/examples/shaders/resources/shaders/glsl100/julia_set.fs b/examples/shaders/resources/shaders/glsl100/julia_set.fs index 84d2d204a..a6f397926 100644 --- a/examples/shaders/resources/shaders/glsl100/julia_set.fs +++ b/examples/shaders/resources/shaders/glsl100/julia_set.fs @@ -1,4 +1,6 @@ -#version 120 +#version 100 + +precision mediump float; // Input vertex attributes (from vertex shader) varying vec2 fragTexCoord; diff --git a/examples/shaders/resources/shaders/glsl100/mask.fs b/examples/shaders/resources/shaders/glsl100/mask.fs index 8203a7008..2136ec1d3 100644 --- a/examples/shaders/resources/shaders/glsl100/mask.fs +++ b/examples/shaders/resources/shaders/glsl100/mask.fs @@ -1,4 +1,6 @@ -#version 120 +#version 100 + +precision mediump float; // Input vertex attributes (from vertex shader) varying vec2 fragTexCoord; diff --git a/examples/shaders/resources/shaders/glsl120/write_depth.fs b/examples/shaders/resources/shaders/glsl120/write_depth.fs index 0d0e19da7..a2bc38516 100644 --- a/examples/shaders/resources/shaders/glsl120/write_depth.fs +++ b/examples/shaders/resources/shaders/glsl120/write_depth.fs @@ -1,4 +1,4 @@ -#version 100 +#version 120 #extension GL_EXT_frag_depth : enable diff --git a/projects/VS2022/examples/shaders_normal_map.vcxproj b/projects/VS2022/examples/shaders_normal_map.vcxproj index 5af02f256..a3e8e9981 100644 --- a/projects/VS2022/examples/shaders_normal_map.vcxproj +++ b/projects/VS2022/examples/shaders_normal_map.vcxproj @@ -51,11 +51,11 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} Win32Proj - shaders_normalmap + shaders_normal_map 10.0 - shaders_normalmap + shaders_normal_map @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 19cf337c0..65d48a2dc 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -335,12 +335,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_virtual_controls EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_fps_controller", "examples\core_3d_fps_controller.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_normal_map", "examples\shaders_normal_map.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_normal_map", "examples\shaders_normal_map.vcxproj", "{6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "text_unicode_font", "examples\text_unicode_font.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "text_unicode_ranges", "examples\text_unicode_ranges.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4113,82 +4109,34 @@ Global {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|ARM64.Build.0 = Debug|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|x64.ActiveCfg = Debug|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|x64.Build.0 = Debug|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|x86.ActiveCfg = Debug|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Debug|x86.Build.0 = Debug|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|ARM64.ActiveCfg = Release|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|ARM64.Build.0 = Release|ARM64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|x64.ActiveCfg = Release|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|x64.Build.0 = Release|x64 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|x86.ActiveCfg = Release|Win32 + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection GlobalSection(NestedProjects) = preSolution {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {278D8859-20B1-428F-8448-064F46E1F021} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} @@ -4353,12 +4301,10 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} - EndGlobalSection -EndGlobal + {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} + EndGlobalSection +EndGlobal diff --git a/src/raudio.c b/src/raudio.c index e21bf578c..e9d76fa99 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1767,7 +1767,7 @@ void UnloadMusicStream(Music music) else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData); #endif #if defined(SUPPORT_FILEFORMAT_FLAC) - else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL); + else if (music.ctxType == MUSIC_AUDIO_FLAC) { drflac_close((drflac *)music.ctxData); drflac_free((drflac *)music.ctxData, NULL); } #endif #if defined(SUPPORT_FILEFORMAT_XM) else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData); diff --git a/src/rtext.c b/src/rtext.c index 50ea6c883..78423c522 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -93,6 +93,9 @@ #pragma GCC diagnostic ignored "-Wunused-function" #endif + #define STBTT_malloc(x,u) ((void)(u),RL_MALLOC(x)) + #define STBTT_free(x,u) ((void)(u),RL_FREE(x)) + #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION #include "external/stb_truetype.h" // Required for: ttf font data reading diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 64a253934..aefd6c479 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -99,8 +99,9 @@ typedef enum { VALID_NOT_IN_JS = 1 << 9, // Not listed in examples.js VALID_INCONSISTENT_INFO = 1 << 10, // Inconsistent info between collection and example header (stars, author...) VALID_MISSING_WEB_OUTPUT = 1 << 11, // Missing .html/.data/.wasm/.js - VALID_INVALID_CATEGORY = 1 << 12, // Not a recognized category - VALID_UNKNOWN_ERROR = 1 << 13 // Unknown failure case (fallback) + VALID_MISSING_WEB_METADATA = 1 << 12, // Missing .html example metadata + VALID_INVALID_CATEGORY = 1 << 13, // Not a recognized category + VALID_UNKNOWN_ERROR = 1 << 14 // Unknown failure case (fallback) } rlExampleValidationStatus; // Example management operations @@ -112,6 +113,7 @@ typedef enum { OP_REMOVE = 4, // Remove existing example OP_VALIDATE = 5, // Validate examples, using [examples_list.txt] as main source by default OP_UPDATE = 6, // Validate and update required examples (as far as possible) + OP_BUILD = 7, // Build example for desktop and web, copy web output } rlExampleOperation; static const char *exCategories[REXM_MAX_EXAMPLE_CATEGORIES] = { "core", "shapes", "textures", "text", "models", "shaders", "audio", "others" }; @@ -173,7 +175,10 @@ static int AddVSProjectToSolution(const char *projFile, const char *slnFile, con // Generate unique UUID v4 string // Output format: {9A2F48CC-0DA8-47C0-884E-02E37F9BE6C1} -const char *GenerateUUIDv4(void); +static const char *GenerateUUIDv4(void); + +// Update generated Web example .html file metadata +static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath); //------------------------------------------------------------------------------------ // Program main entry point @@ -356,6 +361,29 @@ int main(int argc, char *argv[]) opCode = OP_UPDATE; } + else if (strcmp(argv[1], "build") == 0) + { + // Build example for PLATFORM_DESKTOP and PLATFORM_WEB + // NOTE: Build outputs to default directory, usually where the .c file is located, + // to avoid issues with copying resources (at least on Desktop) + // Web build files (.html, .wasm, .js, .data) are copied to raylib.com/examples repo + // Check for valid upcoming argument + if (argc == 2) LOG("WARNING: No example name provided to build\n"); + else if (argc > 3) LOG("WARNING: Too many arguments provided\n"); + else + { + // Verify example exists in collection to be removed + char *exColInfo = LoadFileText(exCollectionFilePath); + if (TextFindIndex(exColInfo, argv[2]) != -1) // Example in the collection + { + strcpy(exName, argv[2]); // Register example name for removal + strncpy(exCategory, exName, TextFindIndex(exName, "_")); + opCode = OP_BUILD; + } + else LOG("WARNING: REMOVE: Example not available in the collection\n"); + UnloadFileText(exColInfo); + } + } } switch (opCode) @@ -540,25 +568,16 @@ int main(int argc, char *argv[]) // Compile to: raylib.com/examples//_example_name.wasm // Compile to: raylib.com/examples//_example_name.js //------------------------------------------------------------------------------------------------ - // TODO: Avoid platform-specific .BAT file - /* - SET RAYLIB_PATH=C:\GitHub\raylib - SET COMPILER_PATH=C:\raylib\w64devkit\bin - ENV_SET PATH=$(COMPILER_PATH) - SET MAKE=mingw32-make - $(MAKE) -f Makefile.Web shaders/shaders_deferred_render PLATFORM=$(PLATFORM) -B - - //int putenv(char *string); // putenv takes a string of the form NAME=VALUE - //int setenv(const char *envname, const char *envval, int overwrite); - //int unsetenv(const char *name); //unset variable - putenv("RAYLIB_DIR=C:\\GitHub\\raylib"); - putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); - setenv("RAYLIB_DIR", "C:\\GitHub\\raylib", 1); - unsetenv("RAYLIB_DIR"); - getenv("RAYLIB_DIR"); + //putenv("RAYLIB_DIR=C:\\GitHub\\raylib"); + //putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + // WARNING: EMSDK_PATH must be set to proper location when calling from GitHub Actions system(TextFormat("make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exCategory, exName)); - */ - system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exCategory, exName)); + //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exCategory, exName)); + + // Update generated .html metadata + char exHtmlPath[512] = { 0 }; + strcpy(exHtmlPath, TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName)); // WARNING: Cache path for saving + UpdateWebMetadata(exHtmlPath, TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); // Copy results to web side FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName), @@ -583,9 +602,9 @@ int main(int argc, char *argv[]) TextFormat("%s;%s", exRecategory, exRename)); // Edit: Rename example code and screenshot files .c and .png - rename(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), + FileRename(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.c", exBasePath, exCategory, exRename)); - rename(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName), + FileRename(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.png", exBasePath, exCategory, exRename)); // NOTE: Example resource files do not need to be changed... @@ -599,7 +618,8 @@ int main(int argc, char *argv[]) exName + strlen(exCategory) + 1, exRename + strlen(exRecategory) + 1); // Skip category // Edit: Rename example project and solution - rename(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName), + FileTextReplace(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName), exName, exRename); + FileRename(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName), TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exRename)); FileTextReplace(TextFormat("%s/../projects/VS2022/raylib.sln", exBasePath), exName, exRename); } @@ -616,25 +636,31 @@ int main(int argc, char *argv[]) // Edit: Rename example code file (copy and remove) FileCopy(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.c", exBasePath, exCategory, exRename)); - remove(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); // Edit: Rename example screenshot file (copy and remove) FileCopy(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.png", exBasePath, exCategory, exRename)); - remove(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); // Edit: Update required files: Makefile, Makefile.Web, README.md, examples.js UpdateRequiredFiles(); } // Remove old web compilation - remove(TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName)); // Recompile example (on raylib side) - // NOTE: Tools requirements: emscripten, w64devkit - system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exRecategory, exRename)); + // WARNING: EMSDK_PATH must be set to proper location when calling from GitHub Actions + system(TextFormat("%s/make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename)); + //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exRecategory, exRename)); + + // Update generated .html metadata + char exHtmlPath[512] = { 0 }; + strcpy(exHtmlPath, TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName)); // WARNING: Cache path for saving + UpdateWebMetadata(exHtmlPath, TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); // Copy results to web side FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exRecategory, exRename), @@ -692,11 +718,11 @@ int main(int argc, char *argv[]) for (int v = 0; v < 3; v++) { char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v])); - remove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated)); + FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated)); RL_FREE(resPathUpdated); } } - else remove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r])); + else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r])); } } @@ -706,14 +732,14 @@ int main(int argc, char *argv[]) // Remove: raylib/examples//_example_name.c // Remove: raylib/examples//_example_name.png - remove(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); // Edit: Update required files: Makefile, Makefile.Web, README.md, examples.js UpdateRequiredFiles(); // Remove: raylib/projects/VS2022/examples/_example_name.vcxproj - remove(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); + FileRemove(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); // Edit: raylib/projects/VS2022/raylib.sln --> Remove example project //--------------------------------------------------------------------------- @@ -726,10 +752,10 @@ int main(int argc, char *argv[]) // Remove: raylib.com/examples//_example_name.data // Remove: raylib.com/examples//_example_name.wasm // Remove: raylib.com/examples//_example_name.js - remove(TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); - remove(TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName)); } break; case OP_VALIDATE: // Validate: report and actions @@ -762,10 +788,10 @@ int main(int argc, char *argv[]) char *exListUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); bool listUpdated = false; - int exListLen = strlen(exList); + int exListLen = (int)strlen(exList); strcpy(exListUpdated, exList); - for (int i = 0; i < list.count; i++) + for (unsigned int i = 0; i < list.count; i++) { if ((strcmp("examples_template", GetFileNameWithoutExt(list.paths[i])) != 0) && // HACK: Skip "examples_template" (TextFindIndex(exList, GetFileNameWithoutExt(list.paths[i])) == -1)) @@ -896,6 +922,23 @@ int main(int argc, char *argv[]) exInfo->status |= VALID_MISSING_WEB_OUTPUT; } + // Validate: raylib.com/examples//_example_name.html -> Metadata + if (FileExists(TextFormat("%s/%s/%s.html", exWebPath, exInfo->category, exInfo->name))) + { + char *exHtmlText = LoadFileText(TextFormat("%s/%s/%s.html", exWebPath, exInfo->category, exInfo->name)); + + if ((TextFindIndex(exHtmlText, "raylib web game") > -1) || // title + (TextFindIndex(exHtmlText, "New raylib web videogame, developed using raylib videogames library") > -1) || // description + (TextFindIndex(exHtmlText, "https://www.raylib.com/common/raylib_logo.png") > -1) || // image + (TextFindIndex(exHtmlText, "https://www.raylib.com/games.html") > -1) || // url + (TextFindIndex(exHtmlText, "https://github.com/raysan5/raylib") > -1)) // source code button + { + exInfo->status |= VALID_MISSING_WEB_METADATA; + } + + UnloadFileText(exHtmlText); + } + // NOTE: Additional validation elements // Validate: Example naming conventions: /_example_name, valid category if ((TextFindIndex(exInfo->name, exInfo->category) == -1) || @@ -974,9 +1017,15 @@ int main(int argc, char *argv[]) // Review: Add/Remove: raylib.com/examples//_example_name.js // Solves: VALID_MISSING_WEB_OUTPUT if ((strcmp(exInfo->category, "others") != 0) && // Skipping "others" category - exInfo->status & VALID_MISSING_WEB_OUTPUT) + ((exInfo->status & VALID_MISSING_WEB_OUTPUT) || (exInfo->status & VALID_MISSING_WEB_METADATA))) { - system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name)); + system(TextFormat("%s/make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name)); + //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name)); + + // Update generated .html metadata + char exHtmlPath[512] = { 0 }; + strcpy(exHtmlPath, TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName)); // WARNING: Cache path for saving + UpdateWebMetadata(exHtmlPath, TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); // Copy results to web side FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exInfo->category, exInfo->name), @@ -1021,14 +1070,15 @@ int main(int argc, char *argv[]) [RDME] VALID_NOT_IN_README // Not listed in README.md [JS] VALID_NOT_IN_JS // Not listed in examples.js [WOUT] VALID_MISSING_WEB_OUTPUT // Missing .html/.data/.wasm/.js + [WMETA] VALID_MISSING_WEB_METADATA // Missing .html example metadata [INFO] VALID_INCONSISTENT_INFO // Inconsistent info between collection and example header (stars, author...) [CAT] VALID_INVALID_CATEGORY // Not a recognized category - | [EXAMPLE NAME] | [C] |[CAT]|[INFO]|[PNG]|[WPNG]|[RES]|[MK] |[MKWEB]|[VCX]|[SOL]|[RDME]|[JS] |[WOUT]| - |:-----------------------------|:---:|:---:|:----:|:---:|:----:|:---:|:---:|:-----:|:---:|:---:|:----:|:---:|:----:| - | core_basic_window | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | - | shapes_colors_palette | ✘ | ✔ | ✘ | ✔ | ✘ | ✔ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ | - | text_format_text | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✔ | ✘ | ✔ | ✔ | ✔ | + | [EXAMPLE NAME] | [C] |[CAT]|[INFO]|[PNG]|[WPNG]|[RES]|[MK] |[MKWEB]|[VCX]|[SOL]|[RDME]|[JS] |[WOUT]|[WMETA]| + |:-----------------------------|:---:|:---:|:----:|:---:|:----:|:---:|:---:|:-----:|:---:|:---:|:----:|:---:|:----:|:-----:| + | core_basic_window | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | + | shapes_colors_palette | ✘ | ✔ | ✘ | ✔ | ✘ | ✔ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | + | text_format_text | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | */ char *report = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); @@ -1049,14 +1099,15 @@ int main(int argc, char *argv[]) repIndex += sprintf(report + repIndex, " - [SOL] : Project not included in solution file\n"); repIndex += sprintf(report + repIndex, " - [RDME] : Not listed in README.md\n"); repIndex += sprintf(report + repIndex, " - [JS] : Not listed in Web (examples.js)\n"); - repIndex += sprintf(report + repIndex, " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n```\n"); + repIndex += sprintf(report + repIndex, " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n"); + repIndex += sprintf(report + repIndex, " - [WMETA] : Missing Web .html example metadata\n```\n"); - repIndex += sprintf(report + repIndex, "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|\n"); - repIndex += sprintf(report + repIndex, "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|\n"); + repIndex += sprintf(report + repIndex, "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]|\n"); + repIndex += sprintf(report + repIndex, "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:|\n"); for (int i = 0; i < exCollectionCount; i++) { - repIndex += sprintf(report + repIndex, "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n", + repIndex += sprintf(report + repIndex, "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n", exCollection[i].name, (exCollection[i].status & VALID_MISSING_C)? "❌" : "✔", (exCollection[i].status & VALID_INVALID_CATEGORY)? "❌" : "✔", @@ -1070,7 +1121,8 @@ int main(int argc, char *argv[]) (exCollection[i].status & VALID_NOT_IN_VCXSOL)? "❌" : "✔", (exCollection[i].status & VALID_NOT_IN_README)? "❌" : "✔", (exCollection[i].status & VALID_NOT_IN_JS)? "❌" : "✔", - (exCollection[i].status & VALID_MISSING_WEB_OUTPUT)? "❌" : "✔"); + (exCollection[i].status & VALID_MISSING_WEB_OUTPUT)? "❌" : "✔", + (exCollection[i].status & VALID_MISSING_WEB_METADATA)? "❌" : "✔"); } SaveFileText(TextFormat("%s/../tools/rexm/%s", exBasePath, "examples_report.md"), report); @@ -1097,16 +1149,17 @@ int main(int argc, char *argv[]) repIndex += sprintf(reportIssues + repIndex, " - [SOL] : Project not included in solution file\n"); repIndex += sprintf(reportIssues + repIndex, " - [RDME] : Not listed in README.md\n"); repIndex += sprintf(reportIssues + repIndex, " - [JS] : Not listed in Web (examples.js)\n"); - repIndex += sprintf(reportIssues + repIndex, " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n```\n"); + repIndex += sprintf(reportIssues + repIndex, " - [WOUT] : Missing Web build (.html/.data/.wasm/.js)\n"); + repIndex += sprintf(reportIssues + repIndex, " - [WMETA] : Missing Web .html example metadata\n```\n"); - repIndex += sprintf(reportIssues + repIndex, "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|\n"); - repIndex += sprintf(reportIssues + repIndex, "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|\n"); + repIndex += sprintf(reportIssues + repIndex, "| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]|\n"); + repIndex += sprintf(reportIssues + repIndex, "|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:|\n"); for (int i = 0; i < exCollectionCount; i++) { if (exCollection[i].status > 0) { - repIndex += sprintf(reportIssues + repIndex, "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n", + repIndex += sprintf(reportIssues + repIndex, "| %-32s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n", exCollection[i].name, (exCollection[i].status & VALID_MISSING_C)? "❌" : "✔", (exCollection[i].status & VALID_INVALID_CATEGORY)? "❌" : "✔", @@ -1120,7 +1173,8 @@ int main(int argc, char *argv[]) (exCollection[i].status & VALID_NOT_IN_VCXSOL)? "❌" : "✔", (exCollection[i].status & VALID_NOT_IN_README)? "❌" : "✔", (exCollection[i].status & VALID_NOT_IN_JS)? "❌" : "✔", - (exCollection[i].status & VALID_MISSING_WEB_OUTPUT)? "❌" : "✔"); + (exCollection[i].status & VALID_MISSING_WEB_OUTPUT)? "❌" : "✔", + (exCollection[i].status & VALID_MISSING_WEB_METADATA)? "❌" : "✔"); } } @@ -1132,6 +1186,41 @@ int main(int argc, char *argv[]) //------------------------------------------------------------------------------------------------ } break; + case OP_BUILD: + { + // Build: raylib.com/examples//_example_name.html + // Build: raylib.com/examples//_example_name.data + // Build: raylib.com/examples//_example_name.wasm + // Build: raylib.com/examples//_example_name.js + if (strcmp(exCategory, "others") != 0) // Skipping "others" category + { + // Build example for PLATFORM_DESKTOP + //putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath)); + //putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + //putenv("MAKE=mingw32-make"); + ChangeDirectory(exBasePath); + system(TextFormat("make %s/%s PLATFORM=PLATFORM_DESKTOP -B", exCategory, exName)); + + // Build example for PLATFORM_WEB + system(TextFormat("make -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exCategory, exName)); + //system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name)); + + // Update generated .html metadata + char exHtmlPath[512] = { 0 }; + strcpy(exHtmlPath, TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName)); // WARNING: Cache path for saving + UpdateWebMetadata(exHtmlPath, TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); + + // Copy results to web side + FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName), + TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); + FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exCategory, exName), + TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); + FileCopy(TextFormat("%s/%s/%s.wasm", exBasePath, exCategory, exName), + TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); + FileCopy(TextFormat("%s/%s/%s.js", exBasePath, exCategory, exName), + TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName)); + } + } break; default: // Help { // Supported commands: @@ -1620,7 +1709,11 @@ static int FileRename(const char *fileName, const char *fileRename) { int result = 0; - if (FileExists(fileName)) rename(fileName, TextFormat("%s/%s", GetDirectoryPath(fileName), fileRename)); + if (FileExists(fileName)) + { + result = rename(fileName, TextFormat("%s/%s", GetDirectoryPath(fileName), fileRename)); + } + else result = -1; return result; } @@ -1630,7 +1723,11 @@ static int FileRemove(const char *fileName) { int result = 0; - if (FileExists(fileName)) remove(fileName); + if (FileExists(fileName)) + { + result = remove(fileName); + } + else result = -1; return result; } @@ -1646,6 +1743,7 @@ static int FileMove(const char *srcPath, const char *dstPath) FileCopy(srcPath, dstPath); remove(srcPath); } + else result = -1; return result; } @@ -2041,7 +2139,7 @@ static int AddVSProjectToSolution(const char *projFile, const char *slnFile, con // Generate unique UUID v4 string // Output format: {9A2F48CC-0DA8-47C0-884E-02E37F9BE6C1} -const char *GenerateUUIDv4(void) +static const char *GenerateUUIDv4(void) { static char uuid[38] = { 0 }; memset(uuid, 0, 38); @@ -2064,3 +2162,66 @@ const char *GenerateUUIDv4(void) return uuid; } + +// Update generated Web example .html file metadata +static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath) +{ + if (FileExists(exHtmlPath) && IsFileExtension(exHtmlPath, ".html")) + { + char *fileText = LoadFileText(exHtmlPath); + char *fileTextUpdated[6] = { 0 }; // Pointers to multiple updated text versions + + char *exText = NULL; // Example code file, required to get description + char **lines = NULL; // Pointers to example code lines + int lineCount = 0; // Example code line count + + char exName[64] = { 0 }; // Example name: fileName without extension + char exCategory[16] = { 0 }; // Example category: core, shapes, text, textures, models, audio, shaders + char exDescription[256] = { 0 }; // Example description: example text line #3 + char exTitle[64] = { 0 }; // Example title: fileName without extension, replacing underscores by spaces + + memset(exName, 0, 64); + memset(exTitle, 0, 64); + memset(exDescription, 0, 256); + memset(exCategory, 0, 16); + + // Get example name: replace underscore by spaces + strcpy(exName, GetFileNameWithoutExt(exHtmlPath)); + strcpy(exTitle, exName); + for (int i = 0; (i < 256) && (exTitle[i] != '\0'); i++) { if (exTitle[i] == '_') exTitle[i] = ' '; } + + // Get example category from exName: copy until first underscore + for (int i = 0; (exName[i] != '_'); i++) exCategory[i] = exName[i]; + + // Get example description: copy line #3 from example file + exText = LoadFileText(exFilePath); + lines = LoadTextLines(exText, &lineCount); + int lineLength = (int)strlen(lines[2]); + strncpy(exDescription, lines[2] + 4, lineLength - 4); + UnloadTextLines(lines); + UnloadFileText(exText); + + // Update example.html required text + fileTextUpdated[0] = TextReplace(fileText, "raylib web game", exTitle); + fileTextUpdated[1] = TextReplace(fileTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription); + fileTextUpdated[2] = TextReplace(fileTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png", + TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName)); + fileTextUpdated[3] = TextReplace(fileTextUpdated[2], "https://www.raylib.com/games.html", + TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName)); + fileTextUpdated[4] = TextReplace(fileTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name + fileTextUpdated[5] = TextReplace(fileTextUpdated[4], "https://github.com/raysan5/raylib", + TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName)); + + SaveFileText(exHtmlPath, fileTextUpdated[5]); + + //LOG("INFO: [%s] Updated successfully\n",files.paths[i]); + //LOG(" - Name / Title: %s / %s\n", exName, exTitle); + //LOG(" - Description: %s\n", exDescription); + //LOG(" - URL: %s\n", TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName)); + //LOG(" - URL Source: %s\n", TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName)); + + for (int i = 0; i < 6; i++) { MemFree(fileTextUpdated[i]); fileTextUpdated[i] = NULL; } + + UnloadFileText(fileText); + } +}