├── .gitignore ├── README.md ├── .github └── workflows │ └── main.yml ├── LICENSE └── src └── main.zig /.gitignore: -------------------------------------------------------------------------------- 1 | zig-*/ 2 | .zig-*/ 3 | .vscode/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sokol-zig-imgui-sample 2 | 3 | [![build](https://github.com/floooh/sokol-zig-imgui-sample/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-zig-imgui-sample/actions/workflows/main.yml) 4 | 5 | Sample project for using Dear ImGui with the Sokol Zig bindings. 6 | 7 | > NOTE: no longer compatible with Zig 0.13.0, please use the latest Zig nightly 8 | 9 | On macOS, Windows and Linux just run: 10 | 11 | `zig build run` 12 | 13 | To build and run the web version: 14 | 15 | `zig build --release=small -Dtarget=wasm32-emscripten run` 16 | 17 | ...or for the Dear ImGui docking branch: 18 | 19 | `zig build -Ddocking run` 20 | 21 | `zig build --release=small -Ddocking -Dtarget=wasm32-emscripten run` 22 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest, macos-latest, windows-latest] 10 | runs-on: ${{matrix.os}} 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: mlugg/setup-zig@v2 14 | with: 15 | version: 0.15.2 16 | - name: prepare-linux 17 | if: runner.os == 'Linux' 18 | run: | 19 | sudo apt-get update 20 | sudo apt-get install libglu1-mesa-dev mesa-common-dev xorg-dev libasound-dev 21 | - name: build-native 22 | run: zig build --summary all 23 | - name: build-web 24 | run: zig build --summary all -Dtarget=wasm32-emscripten 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Andre Weissflog 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const use_docking = @import("build_options").docking; 2 | const ig = if (use_docking) @import("cimgui_docking") else @import("cimgui"); 3 | const sokol = @import("sokol"); 4 | const slog = sokol.log; 5 | const sg = sokol.gfx; 6 | const sapp = sokol.app; 7 | const sglue = sokol.glue; 8 | const simgui = sokol.imgui; 9 | const sgimgui = sokol.sgimgui; 10 | 11 | const state = struct { 12 | var pass_action: sg.PassAction = .{}; 13 | var show_first_window: bool = true; 14 | var show_second_window: bool = true; 15 | }; 16 | 17 | export fn init() void { 18 | // initialize sokol-gfx 19 | sg.setup(.{ 20 | .environment = sglue.environment(), 21 | .logger = .{ .func = slog.func }, 22 | }); 23 | // the debug/tracing ui 24 | sgimgui.setup(.{}); 25 | // initialize sokol-imgui 26 | simgui.setup(.{ 27 | .logger = .{ .func = slog.func }, 28 | }); 29 | if (use_docking) { 30 | ig.igGetIO().*.ConfigFlags |= ig.ImGuiConfigFlags_DockingEnable; 31 | } 32 | 33 | // initial clear color 34 | state.pass_action.colors[0] = .{ 35 | .load_action = .CLEAR, 36 | .clear_value = .{ .r = 0.0, .g = 0.5, .b = 1.0, .a = 1.0 }, 37 | }; 38 | } 39 | 40 | export fn frame() void { 41 | // call simgui.newFrame() before any ImGui calls 42 | simgui.newFrame(.{ 43 | .width = sapp.width(), 44 | .height = sapp.height(), 45 | .delta_time = sapp.frameDuration(), 46 | .dpi_scale = sapp.dpiScale(), 47 | }); 48 | 49 | const backendName: [*c]const u8 = switch (sg.queryBackend()) { 50 | .D3D11 => "Direct3D11", 51 | .GLCORE => "OpenGL", 52 | .GLES3 => "OpenGLES3", 53 | .METAL_IOS => "Metal iOS", 54 | .METAL_MACOS => "Metal macOS", 55 | .METAL_SIMULATOR => "Metal Simulator", 56 | .WGPU => "WebGPU", 57 | .VULKAN => "Vulkan", 58 | .DUMMY => "Dummy", 59 | }; 60 | 61 | //=== UI CODE STARTS HERE 62 | ig.igSetNextWindowPos(.{ .x = 10, .y = 30 }, ig.ImGuiCond_Once); 63 | ig.igSetNextWindowSize(.{ .x = 400, .y = 100 }, ig.ImGuiCond_Once); 64 | if (ig.igBegin("Hello Dear ImGui!", &state.show_first_window, ig.ImGuiWindowFlags_None)) { 65 | _ = ig.igColorEdit3("Background", &state.pass_action.colors[0].clear_value.r, ig.ImGuiColorEditFlags_None); 66 | _ = ig.igText("Dear ImGui Version: %s", ig.IMGUI_VERSION); 67 | } 68 | ig.igEnd(); 69 | 70 | ig.igSetNextWindowPos(.{ .x = 50, .y = 150 }, ig.ImGuiCond_Once); 71 | ig.igSetNextWindowSize(.{ .x = 400, .y = 100 }, ig.ImGuiCond_Once); 72 | if (ig.igBegin("Another Window", &state.show_second_window, ig.ImGuiWindowFlags_None)) { 73 | _ = ig.igText("Sokol Backend: %s", backendName); 74 | } 75 | ig.igEnd(); 76 | 77 | // the sokol-gfx-imgui debugging ui 78 | if (ig.igBeginMainMenuBar()) { 79 | sgimgui.drawMenu("sokol-gfx"); 80 | ig.igEndMainMenuBar(); 81 | } 82 | sgimgui.draw(); 83 | //=== UI CODE ENDS HERE 84 | 85 | // call simgui.render() inside a sokol-gfx pass 86 | sg.beginPass(.{ .action = state.pass_action, .swapchain = sglue.swapchain() }); 87 | simgui.render(); 88 | sg.endPass(); 89 | sg.commit(); 90 | } 91 | 92 | export fn cleanup() void { 93 | simgui.shutdown(); 94 | sgimgui.shutdown(); 95 | sg.shutdown(); 96 | } 97 | 98 | export fn event(ev: [*c]const sapp.Event) void { 99 | // forward input events to sokol-imgui 100 | _ = simgui.handleEvent(ev.*); 101 | } 102 | 103 | pub fn main() void { 104 | sapp.run(.{ 105 | .init_cb = init, 106 | .frame_cb = frame, 107 | .cleanup_cb = cleanup, 108 | .event_cb = event, 109 | .window_title = "sokol-zig + Dear Imgui", 110 | .width = 800, 111 | .height = 600, 112 | .icon = .{ .sokol_default = true }, 113 | .logger = .{ .func = slog.func }, 114 | }); 115 | } 116 | --------------------------------------------------------------------------------