diff --git a/3rd-party/cimgui/build.zig b/3rd-party/cimgui/build.zig deleted file mode 100644 index 76574c8..0000000 --- a/3rd-party/cimgui/build.zig +++ /dev/null @@ -1,66 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -pub fn build(b: *std.Build) void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); - - const dep_cimgui = b.dependency("cimgui", .{}); - const dep_imgui = b.dependency("imgui", .{}); - - // create file tree for cimgui and imgui - const wf = b.addNamedWriteFiles("cimgui"); - _ = wf.addCopyDirectory(dep_cimgui.path(""), "", .{}); - _ = wf.addCopyDirectory(dep_imgui.path(""), "imgui", .{}); - const root = wf.getDirectory(); - - // build cimgui as C/C++ library - const lib_cimgui = b.addStaticLibrary(.{ - .name = "cimgui_clib", - .target = target, - .optimize = optimize, - .link_libc = true, - }); - lib_cimgui.linkLibCpp(); - lib_cimgui.addCSourceFiles(.{ - .root = root, - .files = &.{ - b.pathJoin(&.{"cimgui.cpp"}), - b.pathJoin(&.{ "imgui", "imgui.cpp" }), - b.pathJoin(&.{ "imgui", "imgui_widgets.cpp" }), - b.pathJoin(&.{ "imgui", "imgui_draw.cpp" }), - b.pathJoin(&.{ "imgui", "imgui_tables.cpp" }), - b.pathJoin(&.{ "imgui", "imgui_demo.cpp" }), - }, - }); - lib_cimgui.addIncludePath(root); - - // make cimgui available as artifact, this then allows to inject - // the Emscripten include path in another build.zig - b.installArtifact(lib_cimgui); - - // lib compilation depends on file tree - lib_cimgui.step.dependOn(&wf.step); - - // translate-c the cimgui.h file - // NOTE: always run this with the host target, that way we don't need to inject - // the Emscripten SDK include path into the translate-C step when building for WASM - const cimgui_h = dep_cimgui.path("cimgui.h"); - const translateC = b.addTranslateC(.{ - .root_source_file = cimgui_h, - .target = b.host, - .optimize = optimize, - }); - translateC.defineCMacroRaw("CIMGUI_DEFINE_ENUMS_AND_STRUCTS=\"\""); - const entrypoint = translateC.getOutput(); - - // build cimgui as a module with the header file as the entrypoint - const mod_cimgui = b.addModule("cimgui", .{ - .root_source_file = entrypoint, - .target = target, - .optimize = optimize, - .link_libc = true, - .link_libcpp = true, - }); - mod_cimgui.linkLibrary(lib_cimgui); -} diff --git a/3rd-party/cimgui/build.zig.zon b/3rd-party/cimgui/build.zig.zon deleted file mode 100644 index 0e6b930..0000000 --- a/3rd-party/cimgui/build.zig.zon +++ /dev/null @@ -1,18 +0,0 @@ -.{ - .name = "cimgui", - .version = "0.0.0", - - .dependencies = .{ - .cimgui = .{ - .url = "git+https://github.com/cimgui/cimgui.git#1.90.7", - .hash = "1220d925a8374fbc3a21a5b46025fb867672d85b4099d2151bed607618e08b0cd71c", - }, - .imgui = .{ - .url = "git+https://github.com/ocornut/imgui.git#v1.90.7", - .hash = "122072b125179c7cbdbbee8fa81d22a1050a950ad61cfeefee8dc0dca5423b5d05b9", - }, - }, - .paths = .{ - "", - }, -} diff --git a/build.zig b/build.zig index bc7da3d..8992841 100644 --- a/build.zig +++ b/build.zig @@ -1,90 +1,30 @@ const std = @import("std"); -const Build = std.Build; -const OptimizeMode = std.builtin.OptimizeMode; -const ResolvedTarget = Build.ResolvedTarget; -const Dependency = Build.Dependency; -const sokol = @import("sokol"); +const capy = @import("capy"); -pub fn build(b: *Build) !void { +pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); + const mode = b.standardOptimizeOption(.{}); - // note that the sokol dependency is built with `.with_imgui_sokol = true` - const dep_sokol = b.dependency("sokol", .{ + const exe = b.addExecutable(.{ + .name = "doggo", + .root_source_file = .{ .path = "src/main.zig" }, .target = target, - .optimize = optimize, - .with_sokol_imgui = true, - }); - const dep_cimgui = b.dependency("cimgui", .{ - .target = target, - .optimize = optimize, + .optimize = mode, }); - // inject the cimgui header search path into the sokol C library compile step - const cimgui_root = dep_cimgui.namedWriteFiles("cimgui").getDirectory(); - dep_sokol.artifact("sokol_clib").addIncludePath(cimgui_root); + b.installArtifact(exe); - // from here on different handling for native vs wasm builds - if (target.result.isWasm()) { - try buildWasm(b, target, optimize, dep_sokol, dep_cimgui); - } else { - try buildNative(b, target, optimize, dep_sokol, dep_cimgui); - } -} - -fn buildNative(b: *Build, target: ResolvedTarget, optimize: OptimizeMode, dep_sokol: *Dependency, dep_cimgui: *Dependency) !void { - const demo = b.addExecutable(.{ - .name = "demo", - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - }); - demo.root_module.addImport("sokol", dep_sokol.module("sokol")); - demo.root_module.addImport("cimgui", dep_cimgui.module("cimgui")); - b.installArtifact(demo); - b.step("run", "Run demo").dependOn(&b.addRunArtifact(demo).step); -} - -fn buildWasm(b: *Build, target: ResolvedTarget, optimize: OptimizeMode, dep_sokol: *Dependency, dep_cimgui: *Dependency) !void { - // build the main file into a library, this is because the WASM 'exe' - // needs to be linked in a separate build step with the Emscripten linker - const demo = b.addStaticLibrary(.{ - .name = "demo", - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - }); - demo.root_module.addImport("sokol", dep_sokol.module("sokol")); - demo.root_module.addImport("cimgui", dep_cimgui.module("cimgui")); - - // get the Emscripten SDK dependency from the sokol dependency - const dep_emsdk = dep_sokol.builder.dependency("emsdk", .{}); - - // need to inject the Emscripten system header include path into - // the cimgui C library otherwise the C/C++ code won't find - // C stdlib headers - const emsdk_incl_path = dep_emsdk.path("upstream/emscripten/cache/sysroot/include"); - dep_cimgui.artifact("cimgui_clib").addSystemIncludePath(emsdk_incl_path); - - // all C libraries need to depend on the sokol library, when building for - // WASM this makes sure that the Emscripten SDK has been setup before - // C compilation is attempted (since the sokol C library depends on the - // Emscripten SDK setup step) - dep_cimgui.artifact("cimgui_clib").step.dependOn(&dep_sokol.artifact("sokol_clib").step); - - // create a build step which invokes the Emscripten linker - const link_step = try sokol.emLinkStep(b, .{ - .lib_main = demo, - .target = target, - .optimize = optimize, - .emsdk = dep_emsdk, - .use_webgl2 = true, - .use_emmalloc = true, - .use_filesystem = false, - .shell_file_path = dep_sokol.path("src/sokol/web/shell.html").getPath(b), - }); - // ...and a special run step to start the web build output via 'emrun' - const run = sokol.emRunStep(b, .{ .name = "demo", .emsdk = dep_emsdk }); - run.step.dependOn(&link_step.step); - b.step("run", "Run demo").dependOn(&run.step); + const run_cmd = try capy.install(exe, .{ .args = b.args }); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(run_cmd); + + const exe_tests = b.addTest(.{ + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = mode, + }); + + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&exe_tests.step); } diff --git a/build.zig.zon b/build.zig.zon index 51b1b1e..7dd480c 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,12 +7,13 @@ "src", }, .dependencies = .{ - .sokol = .{ - .url = "git+https://github.com/floooh/sokol-zig.git#d9f3ef983b7021417cc91bd5788cd925ca06aa83", - .hash = "12200a472b4f1a3a6db1002f39f10ae0cccf58ada45bf25ddc5fd48384dd187f55ea", + .capy = .{ + .url = "https://github.com/ffreling/capy/archive/refs/heads/zig-0.12.0.tar.gz", + .hash = "12207fd2f0d02eb929d1e8a05843de4dc3f4b362055e9e47a014fb6b806a592d9808", }, - .cimgui = .{ - .path = "3rd-party/cimgui", + .zigimg = .{ + .url = "https://github.com/zigimg/zigimg/archive/8873f29fc449e1b63400e9f4ad86d3c76204f962.tar.gz", + .hash = "122019f6439545235af116d0d8eb81fde1ff05fdb070da57c723772c557f84c5bf39", }, }, } diff --git a/flake.lock b/flake.lock index 883ab66..66a0d8f 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1720058333, - "narHash": "sha256-gM2RCi5XkxmcsZ44pUkKIYBiBMfZ6u7MdcZcykmccrs=", + "lastModified": 1714750952, + "narHash": "sha256-oOUdvPrO8CbupgDSaPou+Jv6GL+uQA2QlE33D7OLzkM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6842b061970bf96965d66fcc86a28e1f719aae95", + "rev": "5fd8536a9a5932d4ae8de52b7dc08d92041237fc", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d321eb0..9cf7396 100644 --- a/flake.nix +++ b/flake.nix @@ -12,15 +12,7 @@ zls ]; buildInputs = [ - alsa-lib - xorg.libX11 - xorg.libXcursor - xorg.libXi - xorg.libXext - xorg.libXrandr - xorg.libXinerama - libGL - libGLU + gtk4 ]; }; }; diff --git a/src/main.zig b/src/main.zig index a5fe269..b19dee6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,77 +1,20 @@ -const ig = @import("cimgui"); -const sokol = @import("sokol"); -const slog = sokol.log; -const sg = sokol.gfx; -const sapp = sokol.app; -const sglue = sokol.glue; -const simgui = sokol.imgui; +const std = @import("std"); +const capy = @import("capy"); -const state = struct { - var pass_action: sg.PassAction = .{}; -}; +// This is required for your app to build to WebAssembly and other particular architectures +pub usingnamespace capy.cross_platform; -export fn init() void { - // initialize sokol-gfx - sg.setup(.{ - .environment = sglue.environment(), - .logger = .{ .func = slog.func }, - }); - // initialize sokol-imgui - simgui.setup(.{ - .logger = .{ .func = slog.func }, - }); +pub fn main() !void { + try capy.backend.init(); - // initial clear color - state.pass_action.colors[0] = .{ - .load_action = .CLEAR, - .clear_value = .{ .r = 0.0, .g = 0.5, .b = 1.0, .a = 1.0 }, - }; -} - -export fn frame() void { - // call simgui.newFrame() before any ImGui calls - simgui.newFrame(.{ - .width = sapp.width(), - .height = sapp.height(), - .delta_time = sapp.frameDuration(), - .dpi_scale = sapp.dpiScale(), - }); - - //=== UI CODE STARTS HERE - ig.igSetNextWindowPos(.{ .x = 10, .y = 10 }, ig.ImGuiCond_Once, .{ .x = 0, .y = 0 }); - ig.igSetNextWindowSize(.{ .x = 400, .y = 100 }, ig.ImGuiCond_Once); - _ = ig.igBegin("Hello Dear ImGui!", 0, ig.ImGuiWindowFlags_None); - _ = ig.igColorEdit3("Background", &state.pass_action.colors[0].clear_value.r, ig.ImGuiColorEditFlags_None); - ig.igEnd(); - //=== UI CODE ENDS HERE - - // call simgui.render() inside a sokol-gfx pass - sg.beginPass(.{ .action = state.pass_action, .swapchain = sglue.swapchain() }); - simgui.render(); - sg.endPass(); - sg.commit(); -} - -export fn cleanup() void { - simgui.shutdown(); - sg.shutdown(); -} - -export fn event(ev: [*c]const sapp.Event) void { - // forward input events to sokol-imgui - _ = simgui.handleEvent(ev.*); -} - -pub fn main() void { - sapp.run(.{ - .init_cb = init, - .frame_cb = frame, - .cleanup_cb = cleanup, - .event_cb = event, - .window_title = "sokol-zig + Dear Imgui", - .width = 800, - .height = 600, - .icon = .{ .sokol_default = true }, - .logger = .{ .func = slog.func }, - }); + var window = try capy.Window.init(); + try window.set( + capy.label(.{ .text = "Hello, World", .alignment = .Center }), + ); + + window.setTitle("Hello"); + window.setPreferredSize(250, 100); + window.show(); + + capy.runEventLoop(); }