diff --git a/src/examples/imgui.zig b/src/examples/imgui.zig index 2ad59f5..c7eee13 100644 --- a/src/examples/imgui.zig +++ b/src/examples/imgui.zig @@ -1,9 +1,17 @@ const delve = @import("delve"); const app = delve.app; +const graphics = delve.platform.graphics; const std = @import("std"); const imgui = delve.imgui; +const test_image_asset = @embedFile("static/test.png"); +var test_texture: graphics.Texture = undefined; +var test_material: graphics.Material = undefined; + +var imgui_texture_1: ?*anyopaque = undefined; +var imgui_texture_2: ?*anyopaque = undefined; + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; // This example shows how to use Dear Imgui! @@ -13,6 +21,7 @@ const imgui_module = delve.modules.Module{ .init_fn = on_init, .tick_fn = on_tick, .draw_fn = on_draw, + .cleanup_fn = on_cleanup, }; var bg_color: [4]f32 = [4]f32{ 0.25, 0.85, 0.55, 1.0 }; @@ -40,6 +49,35 @@ pub fn registerModule() !void { pub fn on_init() !void { delve.debug.log("Imgui Example Initializing.", .{}); + + // load an image + var test_image = try delve.images.loadBytes(test_image_asset); + defer test_image.deinit(); + + // make a texture from it + test_texture = graphics.Texture.init(test_image); + + // make an imgui texture for it + imgui_texture_1 = test_texture.makeImguiTexture(); + + // make a material to use a different sampler mode + test_material = try graphics.Material.init(.{ + .shader = graphics.getDefaultShader(), + .texture_0 = test_texture, + .samplers = &[_]graphics.FilterMode{.NEAREST}, + }); + + // make an imgui image out of our material + // materials have more than one texture / sampler, have to pick which to use + const img_idx: usize = 0; + const sampler_idx: usize = 0; + imgui_texture_2 = test_material.makeImguiTexture(img_idx, sampler_idx); +} + +fn on_cleanup() !void { + delve.debug.log("Imgui example cleaning up", .{}); + test_texture.destroy(); + test_material.deinit(); } pub fn on_tick(delta: f32) void { @@ -52,12 +90,39 @@ pub fn on_tick(delta: f32) void { delve.platform.app.startImguiFrame(); imgui.igSetNextWindowPos(.{ .x = 40, .y = 60 }, imgui.ImGuiCond_Once, .{ .x = 0, .y = 0 }); - imgui.igSetNextWindowSize(.{ .x = 400, .y = 100 }, imgui.ImGuiCond_Once); + imgui.igSetNextWindowSize(.{ .x = 400, .y = 300 }, imgui.ImGuiCond_Once); + + // start a window _ = imgui.igBegin("Hello Dear ImGui!", 0, imgui.ImGuiWindowFlags_None); + _ = imgui.igColorEdit3("Background", &bg_color[0], imgui.ImGuiColorEditFlags_None); + + _ = imgui.igSpacing(); + + _ = imgui.igImage( + imgui_texture_1, + .{ .x = 80, .y = 80 }, // size + .{ .x = 0, .y = 0 }, // u + .{ .x = 1.0, .y = 1.0 }, // v + .{ .x = 1.0, .y = 1.0, .z = 1.0, .w = 1.0 }, // tint color + .{ .x = 1.0, .y = 1.0, .z = 1.0, .w = 1.0 }, // border color + ); + + _ = imgui.igSpacing(); + + _ = imgui.igImage( + imgui_texture_2, + .{ .x = 140, .y = 140 }, // size + .{ .x = 0, .y = 0 }, // u + .{ .x = 1.0, .y = 1.0 }, // v + .{ .x = 1.0, .y = 1.0, .z = 1.0, .w = 1.0 }, // tint color + .{ .x = 1.0, .y = 1.0, .z = 1.0, .w = 1.0 }, // border color + ); + + // end the window imgui.igEnd(); - delve.platform.graphics.setClearColor(delve.colors.Color.fromArray(bg_color)); + graphics.setClearColor(delve.colors.Color.fromArray(bg_color)); } pub fn on_draw() void { diff --git a/src/framework/platform/graphics.zig b/src/framework/platform/graphics.zig index 89f96ce..1496422 100644 --- a/src/framework/platform/graphics.zig +++ b/src/framework/platform/graphics.zig @@ -10,6 +10,7 @@ const sokol_gfx_backend = @import("backends/sokol/graphics.zig"); const shaders = @import("../graphics/shaders.zig"); const sokol = @import("sokol"); +const simgui = sokol.imgui; const slog = sokol.log; const sg = sokol.gfx; const sapp = sokol.app; @@ -517,6 +518,12 @@ pub const Texture = struct { sg.destroyImage(self.sokol_image.?); self.sokol_image = null; } + + /// Returns an Imgui Texture ID that can be used with Imgui + pub fn makeImguiTexture(self: *const Texture) ?*anyopaque { + const img = simgui.makeImage(.{ .image = self.sokol_image.?, .sampler = state.debug_material.state.sokol_samplers[0].? }); + return simgui.imtextureid(img); + } }; pub const RenderPassConfig = struct { @@ -1040,6 +1047,15 @@ pub const Material = struct { self.state.shader.applyUniformBlockByName(.FS, "fs_params", asAnything(data.bytes.items)); } } + + /// Returns an Imgui Texture ID from Texture 0 and Sampler 0 that can be used with Imgui + pub fn makeImguiTexture(self: *const Material, texture_idx: usize, sampler_idx: usize) ?*anyopaque { + const img = simgui.makeImage(.{ + .image = self.state.textures[texture_idx].?.sokol_image.?, + .sampler = self.state.sokol_samplers[sampler_idx].?, + }); + return simgui.imtextureid(img); + } }; pub const state = struct {