feat(examples): sokol + imgui smoke test example - #39
Conversation
Adds examples/sokol_imgui/ — a minimal end-to-end test that exercises
the full sokol + Dear ImGui + labelle-imgui bridge stack. If this
example builds and runs with a clickable button, the entire chain is
wired correctly:
- sokol backend with `with_sokol_imgui = true` (provided by the
labelle-imgui sokol bridge that owns its own sokol-with-imgui dep)
- cimgui linked once into the final exe
- sokol_imgui_bridge artifact resolving simgui_* symbols
- generated sokolEvent forwarding sapp events to imgui_bridge_handle_event
so simgui's IO state actually receives mouse / keyboard input
The example is a near-copy of examples/raylib (same scenes, prefabs,
components, gizmos, scene switcher, player movement) so the side-by-side
diff between the two project.labelle files is the minimum surface area
needed to add ImGui to a sokol project:
- backend = .sokol
- gui = .{ .plugin = "imgui" }
- plugins includes labelle-imgui
scripts/imgui_demo.zig opens a "Sokol + ImGui Bridge" window each frame
and renders a label, a click counter button, and a slider — three
widgets that each exercise a different piece of the IO path:
- label proves the render side works
- button proves mouse_pos + mouse_button events flow through
- slider proves drag deltas accumulate via the same event channel
Depends on #38 (sokol event forwarding,
already merged) for the click/slider widgets to actually respond.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR SummaryLow Risk Overview The example includes minimal ECS components, prefabs, scenes (with Adds Reviewed by Cursor Bugbot for commit a0a7d0b. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Code Review
This pull request introduces a new example project, sokol_imgui, which demonstrates the integration of Sokol and Dear ImGui within the engine. It includes a full suite of components, prefabs, scenes, and scripts to showcase features like player movement, state management, and UI rendering. However, several compilation issues were identified in the imgui_demo.zig script, specifically regarding a call to an undefined supportsWidgets function and type mismatches in catch expressions when formatting strings for GUI labels.
|
|
||
| pub fn drawGui(game: anytype) void { | ||
| const Gui = @TypeOf(game.*).Gui; | ||
| if (!Gui.supportsWidgets()) return; |
There was a problem hiding this comment.
| Gui.separator(); | ||
|
|
||
| var fps_buf: [64]u8 = undefined; | ||
| Gui.label(std.fmt.bufPrintZ(&fps_buf, "frame: {d}", .{frame_counter}) catch "frame: ?"); |
There was a problem hiding this comment.
In Zig, the catch expression requires both branches to have the same type or coerce to a common type. std.fmt.bufPrintZ returns a sentinel-terminated slice [:0]u8, while the string literal "frame: ?" is a pointer to an array (*const [8:0]u8). This will result in a compilation error. Slicing the literal to [:0]const u8 resolves the type mismatch.
Gui.label(std.fmt.bufPrintZ(&fps_buf, "frame: {d}", .{frame_counter}) catch "frame: ?"[0..:0]);
| if (Gui.button("Click me")) click_count += 1; | ||
| Gui.sameLine(); | ||
| var click_buf: [32]u8 = undefined; | ||
| Gui.label(std.fmt.bufPrintZ(&click_buf, "clicks: {d}", .{click_count}) catch "clicks: ?"); |
There was a problem hiding this comment.
Similar to the frame counter label, this catch block will fail to compile due to a type mismatch between the slice returned by bufPrintZ and the string literal. Slicing the literal to [:0]const u8 ensures compatibility with the expected [*:0]const u8 parameter of Gui.label.
Gui.label(std.fmt.bufPrintZ(&click_buf, "clicks: {d}", .{click_count}) catch "clicks: ?"[0..:0]);
Summary
Adds `examples/sokol_imgui/` — a minimal end-to-end test that exercises the full sokol + Dear ImGui + labelle-imgui bridge stack. If this example builds and runs with a clickable button, the entire chain is wired correctly:
Diff against `examples/raylib`
The example is a near-copy of `examples/raylib` (same scenes, prefabs, components, gizmos, scene switcher, player movement) so the side-by-side diff between the two `project.labelle` files is the minimum surface area needed to add ImGui to a sokol project:
```zon
.backend = .sokol,
.gui = .{ .plugin = "imgui" },
.plugins = .{
.{ .name = "imgui", .repo = "local:../../../labelle-imgui" },
},
```
scripts/imgui_demo.zig
Opens a "Sokol + ImGui Bridge" window each frame and renders three widgets that each exercise a different piece of the IO path:
Dependencies
Test plan
🤖 Generated with Claude Code