Using raygui with raylib

Do you konw how to use raygui? raylib gui option. I’ve turned on the options for the raygui:

    const raylib_dep = b.dependency("raylib", .{
        .target = target,
        .optimize = optimize,
        .raygui = true,
    });

, but it seems that the source code of raygui has not been found. error info:

run
└─ run demo
   └─ zig build-exe demo Debug native
      └─ install ../raygui/src/raygui.h to raygui.h failure
error: unable to update file from '/root/.cache/zig/p/raygui/src/raygui.h' to '/root/workspace/demo/zig-cache/i/a92a39660ff6ff24bf9055882ff0d65f/include/raygui.h': FileNotFound

The zon file:

.{
    .name = "demo",
    .version = "0.0.0",
    .dependencies = .{
        .raylib = .{
            .url = "https://github.com/raysan5/raylib/archive/e9291fa4c77c85e1fe6808289632e5ce4a93eed6.tar.gz",
            .hash = "1220ee786fc07876bb53e359c0a204e13dfb1a89735c1221363888021322f0b9f131",
        },
    },
    .paths = .{""},
}
1 Like

Welcome to the forum @jiangbo!

I have moved this to a new topic, because it seemed only vaguely related to the original topic (both using raylib) and you maybe have a different problem.

Are you using raylib directly, or do you use the the binding Not-Nik/raylib-zig?

If you are using it directly you could try this:

The only thing I would try to change about this, is to use a second dependency on the raygui repository in the build.zig.zon instead of manually downloading the raygui header file.

This doesn’t use the raylib gui option, but just adds it directly in the cImport using the define, the problem with the raygui option (as far as I remember) is that it assumes a specific path where to find the raygui header and that doesn’t work well for all cases.

I guess in the future raylib could instead define raygui as an optional dependency and then it should work properly (without these shenanigans), but I think optional dependencies aren’t implemented yet.


If somebody tries / tests this, I would be happy to add this to the example repo as a raygui branch, or alternatively you could keep it in your own fork.

If you do, let me know and I will link to it in the readme, because it seems a bunch of people want this every few months.

I used raylib directly.

I downloaded the header file of raygui manually, but it didn’t work. I get a error:

root@jiangbo:~/workspace/demo# zig build run
run
└─ run demo
   └─ zig build-exe demo Debug native 1 errors
/root/workspace/demo/zig-cache/o/5204200a6170fd0d9018a4aabd4b699b/cimport.zig:7980:36: error: expected type 'usize', found '[*c]u8'
                    fileDataPtr += @as([*c]u8, @ptrFromInt(@sizeOf(c_int)));
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    GuiLoadStyle: /root/workspace/demo/zig-cache/o/5204200a6170fd0d9018a4aabd4b699b/cimport.zig:1554:17
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

build.zig.zon file:

.{
    .name = "demo",
    .version = "0.0.0",
    .dependencies = .{
        .raylib = .{
            .url = "https://github.com/raysan5/raylib/archive/ed9a6d862b9e31acaa59c6ffffd1f8aa398d54d8.tar.gz",
            .hash = "12200b5a963e542a0d0d3a4b588e2410951c407c68ea44d98ae0572f3a48cb2fa516",
        },
        .raygui = .{
            .path = "vendor/raygui", // contains the raygui.h
        },
    },
    .paths = .{""},
}

build.zig:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "demo",
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });

    const raylib_dep = b.dependency("raylib", .{
        .target = target,
        .optimize = optimize,
        // .raygui = true,
    });
    exe.linkLibrary(raylib_dep.artifact("raylib"));

    const raygui_dep = b.dependency("raygui", .{
        .target = target,
        .optimize = optimize,
    });
    exe.addIncludePath(raygui_dep.path(""));

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

raylib.zig:

pub usingnamespace @cImport({
    @cInclude("raylib.h");
    @cDefine("RAYGUI_IMPLEMENTATION", {});
    @cInclude("raygui.h");
});

main.zig:

const std = @import("std");
const ray = @import("raylib.zig");

pub fn main() !void {
    const screenWidth: c_int = 800;
    const screenHeight: c_int = 450;

    ray.InitWindow(screenWidth, screenHeight, "raylib [shapes] example");
    defer ray.CloseWindow();
    ray.SetTargetFPS(60);

    while (!ray.WindowShouldClose()) {

        // Update

        // Draw
        ray.BeginDrawing();
        defer ray.EndDrawing();
        ray.ClearBackground(ray.RAYWHITE);

        const rec = ray.Rectangle{ .x = 600, .y = 40, .width = 120, .height = 20 };
        _ = ray.GuiSliderBar(rec, "StartAngle", null, 0, -450, 450);

        ray.DrawFPS(10, 10);
    }
}

zig version: 0.12.0-dev.3076+6e078883e

github repo: GitHub - jiangbo/demo

1 Like

your raygui version is too old (at least I suspect that if you downloaded it from the raygui 4 release):

raygui v4.1-dev

try a recent commit like raygui/src/raygui.h at bc67f42209cc32965c7d1c00028e3ed0c4158659 · raysan5/raygui · GitHub
(the comment is still old but I think the source is updated)

I downloaded it from the URL you gave and still get the same error. I’m not quite sure if it’s a problem with raygui or zig source conversion.

I also got that error.
I modified the source to fileDataPtr += @as(usize, @sizeOf(c_int)); to make it more similar like other lines and with that I got a few similar errors.
(I currently don’t know why these don’t get generated correctly, automatically)

After that it compiled and segfaulted, because of a null pointer being dereferenced.
I had to change the code to:

    ...
    const rec = ray.Rectangle{ .x = 600, .y = 40, .width = 120, .height = 20 };
    var value: f32 = 0;

    while (!ray.WindowShouldClose()) {

        // Update

        // Draw
        ray.BeginDrawing();
        defer ray.EndDrawing();
        ray.ClearBackground(ray.RAYWHITE);

        _ = ray.GuiSliderBar(rec, "StartAngle", null, &value, -450, 450);

        ray.DrawFPS(10, 10);
    }

The &value parameter expects a pointer to a float variable that can be set to the value of the slider.

With that it worked.

It seems the cImport generates code that doesn’t work, I wonder whether there are more cases in other functions (that just aren’t used yet).
I don’t know whether there is a general solution to this, or if maybe raygui uses something that isn’t well supported by cImport.
It seems the sscanf calls in GuiLoadStyle don’t always get converted correctly.


Somehow becomes:

fileDataPtr += @as([*c]u8, @ptrFromInt(@sizeOf(c_int)));

I think it should just be:

fileDataPtr += @as(usize, @intCast(recsDataCompressedSize));
// and the next ones:
// fileDataPtr += @as([*c]u8, @ptrFromInt(@sizeOf(Rectangle)));
fileDataPtr += @as(usize, @sizeOf(Rectangle));
// fileDataPtr += @as([*c]u8, @ptrFromInt(@sizeOf(c_int)));
fileDataPtr += @as(usize, @sizeOf(c_int));

It seems cImport gets confused by the pointer arithmetic and instead wants to add a pointer to the pointer instead of adding an integer value to the pointer.


Edit:
I think the whole issue can be avoided by only applying translate-c to the cImported header file of raygui, but using a c source file for the implementation part. Raylib does this in its build.zig: raylib/src/build.zig at 30f9ca7eb60d527e623066bbdc7257474da2baef · raysan5/raylib · GitHub

This uses raygui directly via the addRaylib function provided by raylib: Adding raygui · Issue #5 · SimonLSchlee/zigraylib · GitHub and commit added raygui #5 · SimonLSchlee/zigraylib@60b2ed0 · GitHub

2 Likes

Hi, jiangbo!

You can try exploring what I do in my Zig Raylib examples collection, namely in examples 42, 43, and 44 - I just download raygui/src/raygui.h at master · raysan5/raygui · GitHub to their folders.
There’s a small C “adapter”, raygui_impl.c in these examples. I use it because raygui.h is a single-header C library.

The command that is actually used to build these three examples is

zig build-exe main.zig raygui_impl.c -O Debug  -idirafter ./ -lc -lraylib

You can try playing with my project to see if it compiles and work from that point in the direction you want.

2 Likes

Wow, thank you, raygui works.

2 Likes

This is a great learning material for Raylib and Zig, and I believe I can learn a lot from it.

3 Likes