summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-10-21 20:52:37 +0000
committers-ol <s-ol@users.noreply.github.com>2019-10-21 20:52:37 +0000
commitf0315f0c554b5622694948d65d0cf347a5dca07b (patch)
treec07a81ac792f541e70a1afd61ba18f3f24047bd6 /src
parentadd cimgui in the repo (diff)
downloadzig-imgui-f0315f0c554b5622694948d65d0cf347a5dca07b.tar.gz
zig-imgui-f0315f0c554b5622694948d65d0cf347a5dca07b.zip
zig-fmt everything
Diffstat (limited to 'src')
-rw-r--r--src/c.zig8
-rw-r--r--src/gl3_impl.zig795
-rw-r--r--src/glfw_impl.zig497
-rw-r--r--src/main.zig159
4 files changed, 731 insertions, 728 deletions
diff --git a/src/c.zig b/src/c.zig
index a4e20cc..54782ef 100644
--- a/src/c.zig
+++ b/src/c.zig
@@ -1,6 +1,6 @@
pub usingnamespace @cImport({
- @cInclude("epoxy/gl.h");
- @cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", "1");
- @cInclude("cimgui.h");
- @cInclude("GLFW/glfw3.h");
+ @cInclude("epoxy/gl.h");
+ @cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", "1");
+ @cInclude("cimgui.h");
+ @cInclude("GLFW/glfw3.h");
});
diff --git a/src/gl3_impl.zig b/src/gl3_impl.zig
index 70a60b5..b056056 100644
--- a/src/gl3_impl.zig
+++ b/src/gl3_impl.zig
@@ -1,3 +1,4 @@
+/// this is a port of cimgui/imgui/examples/imgui_impl_opengl3.cpp
const c = @import("c.zig");
const mem = @import("std").mem;
const math = @import("std").math;
@@ -5,440 +6,444 @@ const debug = @import("std").debug;
const builtin = @import("builtin");
const OpenGLHasDrawWithBaseVertex = @hasField(c, "IMGUI_IMPL_OPENGL_ES2") or
- @hasField(c, "IMGUI_IMPL_OPENGL_ES3");
+ @hasField(c, "IMGUI_IMPL_OPENGL_ES3");
// OpenGL Data
-var g_GlslVersionString_buf : [32]u8 = undefined;
-var g_GlslVersionString : []u8 = g_GlslVersionString_buf[0..0];
+var g_GlslVersionString_buf: [32]u8 = undefined;
+var g_GlslVersionString: []u8 = g_GlslVersionString_buf[0..0];
-var g_FontTexture : c.GLuint = 0;
-var g_ShaderHandle : c.GLuint = 0;
-var g_VertHandle : c.GLuint = 0;
+var g_FontTexture: c.GLuint = 0;
+var g_ShaderHandle: c.GLuint = 0;
+var g_VertHandle: c.GLuint = 0;
var g_FragHandle: c.GLuint = 0;
-var g_AttribLocationTex : c.GLint = 0;
-var g_AttribLocationProjMtx : c.GLint = 0;
-var g_AttribLocationVtxPos : c.GLint = 0;
-var g_AttribLocationVtxUV : c.GLint = 0;
-var g_AttribLocationVtxColor : c.GLint = 0;
-var g_VboHandle : c.GLuint = 0;
-var g_ElementsHandle : c.GLuint = 0;
+var g_AttribLocationTex: c.GLint = 0;
+var g_AttribLocationProjMtx: c.GLint = 0;
+var g_AttribLocationVtxPos: c.GLint = 0;
+var g_AttribLocationVtxUV: c.GLint = 0;
+var g_AttribLocationVtxColor: c.GLint = 0;
+var g_VboHandle: c.GLuint = 0;
+var g_ElementsHandle: c.GLuint = 0;
pub fn Init() void {
- const io = c.igGetIO();
- io.*.BackendRendererName = c"imgui_impl_gl3.zig";
- if (OpenGLHasDrawWithBaseVertex)
- io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_RendererHasVtxOffset);
- // @TODO: Viewports
- // io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_RendererHasViewports);
-
- // @TODO: GLSL versions?
- // g_GlslVersionString = g_GlslVersionString_buf[0..glsl_version.len];
- // mem.copy(u8, g_GlslVersionString, glsl_version);
-
- // @FIXME: just for testing:
- var tex : c.GLint = undefined;
- c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &tex);
-
- // @TODO: Viewports
- // if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
- // InitPlatformInterface();
+ const io = c.igGetIO();
+ io.*.BackendRendererName = c"imgui_impl_gl3.zig";
+ if (OpenGLHasDrawWithBaseVertex)
+ io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_RendererHasVtxOffset);
+ // @TODO: Viewports
+ // io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_RendererHasViewports);
+
+ // @TODO: GLSL versions?
+ // g_GlslVersionString = g_GlslVersionString_buf[0..glsl_version.len];
+ // mem.copy(u8, g_GlslVersionString, glsl_version);
+
+ // @FIXME: just for testing:
+ var tex: c.GLint = undefined;
+ c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &tex);
+
+ // @TODO: Viewports
+ // if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
+ // InitPlatformInterface();
}
pub fn Shutdown() void {
- // ImGui_ImplOpenGL3_ShutdownPlatformInterface();
- DestroyDeviceObjects();
+ // ImGui_ImplOpenGL3_ShutdownPlatformInterface();
+ DestroyDeviceObjects();
}
pub fn NewFrame() !void {
- if (g_ShaderHandle == 0)
- try CreateDeviceObjects();
+ if (g_ShaderHandle == 0)
+ try CreateDeviceObjects();
}
fn CreateDeviceObjects() !void {
- // back up GL state
- var last_texture : c.GLint = undefined;
- var last_array_buffer : c.GLint = undefined;
- var last_vertex_array : c.GLint = undefined;
-
- c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
- defer c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
-
- c.glGetIntegerv(c.GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
- c.glBindBuffer(c.GL_ARRAY_BUFFER, @intCast(c.GLuint, last_array_buffer));
-
- if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glGetIntegerv(c.GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
- defer if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glBindVertexArray(@intCast(c.GLuint, last_vertex_array));
-
- // @TODO: GLSL versions?
- const vertex_shader_glsl : [*]const c.GLchar =
- c\\#version 150
- c\\uniform mat4 ProjMtx;
- c\\in vec2 Position;
- c\\in vec2 UV;
- c\\in vec4 Color;
- c\\out vec2 Frag_UV;
- c\\out vec4 Frag_Color;
- c\\void main()
- c\\{
- c\\ Frag_UV = UV;
- c\\ Frag_Color = Color;
- c\\ gl_Position = ProjMtx * vec4(Position.xy, 0, 1);
- c\\}
- ;
-
- const fragment_shader_glsl : [*]const c.GLchar =
- c\\#version 150
- c\\uniform sampler2D Texture;
- c\\in vec2 Frag_UV;
- c\\in vec4 Frag_Color;
- c\\out vec4 Out_Color;
- c\\void main()
- c\\{
- c\\ Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
- c\\}
- ;
-
- // Create shaders / programs
- g_VertHandle = c.glCreateShader(c.GL_VERTEX_SHADER);
- c.glShaderSource(g_VertHandle, 1, &vertex_shader_glsl, null);
- c.glCompileShader(g_VertHandle);
- try CheckThing(.Shader, g_VertHandle, "vertex shader");
-
- g_FragHandle = c.glCreateShader(c.GL_FRAGMENT_SHADER);
- c.glShaderSource(g_FragHandle, 1, &fragment_shader_glsl, null);
- c.glCompileShader(g_FragHandle);
- try CheckThing(.Shader, g_FragHandle, "fragment shader");
-
- g_ShaderHandle = c.glCreateProgram();
- c.glAttachShader(g_ShaderHandle, g_VertHandle);
- c.glAttachShader(g_ShaderHandle, g_FragHandle);
- c.glLinkProgram(g_ShaderHandle);
- try CheckThing(.Program, g_ShaderHandle, "shader program");
-
- g_AttribLocationTex = c.glGetUniformLocation(g_ShaderHandle, c"Texture");
- g_AttribLocationProjMtx = c.glGetUniformLocation(g_ShaderHandle, c"ProjMtx");
- g_AttribLocationVtxPos = c.glGetAttribLocation(g_ShaderHandle, c"Position");
- g_AttribLocationVtxUV = c.glGetAttribLocation(g_ShaderHandle, c"UV");
- g_AttribLocationVtxColor = c.glGetAttribLocation(g_ShaderHandle, c"Color");
-
- // Create buffers
- c.glGenBuffers(1, &g_VboHandle);
- c.glGenBuffers(1, &g_ElementsHandle);
-
- CreateFontsTexture();
-}
+ // back up GL state
+ var last_texture: c.GLint = undefined;
+ var last_array_buffer: c.GLint = undefined;
+ var last_vertex_array: c.GLint = undefined;
+
+ c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
+ defer c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
+ c.glGetIntegerv(c.GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
+ c.glBindBuffer(c.GL_ARRAY_BUFFER, @intCast(c.GLuint, last_array_buffer));
+
+ if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glGetIntegerv(c.GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
+ defer if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glBindVertexArray(@intCast(c.GLuint, last_vertex_array));
+
+ // @TODO: GLSL versions?
+ const vertex_shader_glsl: [*]const c.GLchar =
+ c\\#version 150
+ c\\uniform mat4 ProjMtx;
+ c\\in vec2 Position;
+ c\\in vec2 UV;
+ c\\in vec4 Color;
+ c\\out vec2 Frag_UV;
+ c\\out vec4 Frag_Color;
+ c\\void main()
+ c\\{
+ c\\ Frag_UV = UV;
+ c\\ Frag_Color = Color;
+ c\\ gl_Position = ProjMtx * vec4(Position.xy, 0, 1);
+ c\\}
+ ;
+
+ const fragment_shader_glsl: [*]const c.GLchar =
+ c\\#version 150
+ c\\uniform sampler2D Texture;
+ c\\in vec2 Frag_UV;
+ c\\in vec4 Frag_Color;
+ c\\out vec4 Out_Color;
+ c\\void main()
+ c\\{
+ c\\ Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
+ c\\}
+ ;
+
+ // Create shaders / programs
+ g_VertHandle = c.glCreateShader(c.GL_VERTEX_SHADER);
+ c.glShaderSource(g_VertHandle, 1, &vertex_shader_glsl, null);
+ c.glCompileShader(g_VertHandle);
+ try CheckThing(.Shader, g_VertHandle, "vertex shader");
+
+ g_FragHandle = c.glCreateShader(c.GL_FRAGMENT_SHADER);
+ c.glShaderSource(g_FragHandle, 1, &fragment_shader_glsl, null);
+ c.glCompileShader(g_FragHandle);
+ try CheckThing(.Shader, g_FragHandle, "fragment shader");
+
+ g_ShaderHandle = c.glCreateProgram();
+ c.glAttachShader(g_ShaderHandle, g_VertHandle);
+ c.glAttachShader(g_ShaderHandle, g_FragHandle);
+ c.glLinkProgram(g_ShaderHandle);
+ try CheckThing(.Program, g_ShaderHandle, "shader program");
+
+ g_AttribLocationTex = c.glGetUniformLocation(g_ShaderHandle, c"Texture");
+ g_AttribLocationProjMtx = c.glGetUniformLocation(g_ShaderHandle, c"ProjMtx");
+ g_AttribLocationVtxPos = c.glGetAttribLocation(g_ShaderHandle, c"Position");
+ g_AttribLocationVtxUV = c.glGetAttribLocation(g_ShaderHandle, c"UV");
+ g_AttribLocationVtxColor = c.glGetAttribLocation(g_ShaderHandle, c"Color");
+
+ // Create buffers
+ c.glGenBuffers(1, &g_VboHandle);
+ c.glGenBuffers(1, &g_ElementsHandle);
+
+ CreateFontsTexture();
+}
const CheckableThing = enum {
- Shader,
- Program,
+ Shader,
+ Program,
};
fn CheckThing(comptime thingType: CheckableThing, handle: c.GLuint, desc: []const u8) !void {
- var status : c.GLint = undefined;
- var log_length : c.GLint = undefined;
- const getInfoLogFunc = switch (thingType) {
- .Shader => blk: {
- c.glGetShaderiv(handle, c.GL_COMPILE_STATUS, &status);
- c.glGetShaderiv(handle, c.GL_INFO_LOG_LENGTH, &log_length);
- break :blk c.glGetShaderInfoLog;
- },
- .Program => blk: {
- c.glGetProgramiv(handle, c.GL_LINK_STATUS, &status);
- c.glGetProgramiv(handle, c.GL_INFO_LOG_LENGTH, &log_length);
- break :blk c.glGetProgramInfoLog;
- },
- };
-
- if (log_length > 1)
- {
- var buf : [1024]u8 = undefined;
- var length : c.GLsizei = undefined;
- getInfoLogFunc(handle, buf.len, &length, &buf[0]);
- debug.warn("{}\n", buf[0..@intCast(usize, length)]);
- }
-
- if (@intCast(c.GLboolean, status) == c.GL_FALSE) {
- debug.warn("ERROR: CreateDeviceObjects: failed to compile/link {}! (with GLSL '{}')\n", desc, g_GlslVersionString);
- return error.ShaderLinkError;
- }
+ var status: c.GLint = undefined;
+ var log_length: c.GLint = undefined;
+ const getInfoLogFunc = switch (thingType) {
+ .Shader => blk: {
+ c.glGetShaderiv(handle, c.GL_COMPILE_STATUS, &status);
+ c.glGetShaderiv(handle, c.GL_INFO_LOG_LENGTH, &log_length);
+ break :blk c.glGetShaderInfoLog;
+ },
+ .Program => blk: {
+ c.glGetProgramiv(handle, c.GL_LINK_STATUS, &status);
+ c.glGetProgramiv(handle, c.GL_INFO_LOG_LENGTH, &log_length);
+ break :blk c.glGetProgramInfoLog;
+ },
+ };
+
+ if (log_length > 1) {
+ var buf: [1024]u8 = undefined;
+ var length: c.GLsizei = undefined;
+ getInfoLogFunc(handle, buf.len, &length, &buf[0]);
+ debug.warn("{}\n", buf[0..@intCast(usize, length)]);
+ }
+
+ if (@intCast(c.GLboolean, status) == c.GL_FALSE) {
+ debug.warn("ERROR: CreateDeviceObjects: failed to compile/link {}! (with GLSL '{}')\n", desc, g_GlslVersionString);
+ return error.ShaderLinkError;
+ }
}
fn DestroyDeviceObjects() void {
- if (g_VboHandle != 0) {
- c.glDeleteBuffers(1, &g_VboHandle);
- g_VboHandle = 0;
- }
-
- if (g_ElementsHandle != 0) {
- c.glDeleteBuffers(1, &g_ElementsHandle);
- g_ElementsHandle = 0;
- }
-
- if (g_ShaderHandle != 0 and g_VertHandle != 0)
- c.glDetachShader(g_ShaderHandle, g_VertHandle);
-
- if (g_ShaderHandle != 0 and g_FragHandle != 0)
- c.glDetachShader(g_ShaderHandle, g_FragHandle);
-
- if (g_VertHandle != 0) {
- c.glDeleteShader(g_VertHandle);
- g_VertHandle = 0;
- }
-
- if (g_FragHandle != 0) {
- c.glDeleteShader(g_FragHandle);
- g_FragHandle = 0;
- }
-
- if (g_ShaderHandle != 0) {
- c.glDeleteProgram(g_ShaderHandle);
- g_ShaderHandle = 0;
- }
-
- DestroyFontsTexture();
+ if (g_VboHandle != 0) {
+ c.glDeleteBuffers(1, &g_VboHandle);
+ g_VboHandle = 0;
+ }
+
+ if (g_ElementsHandle != 0) {
+ c.glDeleteBuffers(1, &g_ElementsHandle);
+ g_ElementsHandle = 0;
+ }
+
+ if (g_ShaderHandle != 0 and g_VertHandle != 0)
+ c.glDetachShader(g_ShaderHandle, g_VertHandle);
+
+ if (g_ShaderHandle != 0 and g_FragHandle != 0)
+ c.glDetachShader(g_ShaderHandle, g_FragHandle);
+
+ if (g_VertHandle != 0) {
+ c.glDeleteShader(g_VertHandle);
+ g_VertHandle = 0;
+ }
+
+ if (g_FragHandle != 0) {
+ c.glDeleteShader(g_FragHandle);
+ g_FragHandle = 0;
+ }
+
+ if (g_ShaderHandle != 0) {
+ c.glDeleteProgram(g_ShaderHandle);
+ g_ShaderHandle = 0;
+ }
+
+ DestroyFontsTexture();
}
fn CreateFontsTexture() void {
- const io = c.igGetIO();
-
- // Get current font image data
- var width : c_int = undefined;
- var height : c_int = undefined;
- var pixels : [*c]u8 = undefined;
- c.ImFontAtlas_GetTexDataAsRGBA32(io.*.Fonts, &pixels, &width, &height, null);
-
- // backup & restore state
- var last_texture : c.GLint = undefined;
- c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
- defer c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
-
- // Upload texture to graphics system
- c.glGenTextures(1, &g_FontTexture);
- c.glBindTexture(c.GL_TEXTURE_2D, g_FontTexture);
- c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_LINEAR);
- c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_LINEAR);
- if (@hasField(c, "GL_UNPACK_ROW_LENGTH"))
- c.glPixelStorei(c.GL_UNPACK_ROW_LENGTH, 0);
- c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_RGBA, width, height, 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, pixels);
-
- // Store texture ID
- io.*.Fonts.*.TexID = @intToPtr(c.ImTextureID, g_FontTexture);
+ const io = c.igGetIO();
+
+ // Get current font image data
+ var width: c_int = undefined;
+ var height: c_int = undefined;
+ var pixels: [*c]u8 = undefined;
+ c.ImFontAtlas_GetTexDataAsRGBA32(io.*.Fonts, &pixels, &width, &height, null);
+
+ // backup & restore state
+ var last_texture: c.GLint = undefined;
+ c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
+ defer c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
+
+ // Upload texture to graphics system
+ c.glGenTextures(1, &g_FontTexture);
+ c.glBindTexture(c.GL_TEXTURE_2D, g_FontTexture);
+ c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_LINEAR);
+ c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_LINEAR);
+ if (@hasField(c, "GL_UNPACK_ROW_LENGTH"))
+ c.glPixelStorei(c.GL_UNPACK_ROW_LENGTH, 0);
+ c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_RGBA, width, height, 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, pixels);
+
+ // Store texture ID
+ io.*.Fonts.*.TexID = @intToPtr(c.ImTextureID, g_FontTexture);
}
fn DestroyFontsTexture() void {
- if (g_FontTexture == 0)
- return;
+ if (g_FontTexture == 0)
+ return;
- const io = c.igGetIO();
- c.glDeleteTextures(1, &g_FontTexture);
- io.*.Fonts.*.TexID = @intToPtr(c.ImTextureID, 0);
- g_FontTexture = 0;
+ const io = c.igGetIO();
+ c.glDeleteTextures(1, &g_FontTexture);
+ io.*.Fonts.*.TexID = @intToPtr(c.ImTextureID, 0);
+ g_FontTexture = 0;
}
-pub fn RenderDrawData(draw_data : *c.ImDrawData) void {
- // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
- const fb_width = @floatToInt(i32, draw_data.*.DisplaySize.x * draw_data.*.FramebufferScale.x);
- const fb_height = @floatToInt(i32, draw_data.*.DisplaySize.y * draw_data.*.FramebufferScale.y);
- if (fb_width <= 0 or fb_height <= 0)
- return;
-
- // Backup GL state
- var last_program : c.GLint = undefined;
- var last_texture : c.GLint = undefined;
- var last_sampler : c.GLint = undefined;
- var last_array_buffer : c.GLint = undefined;
- var last_vertex_array_object : c.GLint = undefined;
- var last_polygon_mode : [2]c.GLint = undefined;
- var last_viewport : [4]c.GLint = undefined;
- var last_scissor_box : [4]c.GLint = undefined;
- var last_blend_src_rgb : c.GLint = undefined;
- var last_blend_dst_rgb : c.GLint = undefined;
- var last_blend_src_alpha : c.GLint = undefined;
- var last_blend_dst_alpha : c.GLint = undefined;
- var last_blend_equation_rgb : c.GLint = undefined;
- var last_blend_equation_alpha : c.GLint = undefined;
- var clip_origin_lower_left : bool = true;
- var last_clip_origin : c.GLint = 0;
- var last_active_texture : c.GLint = undefined;
-
- c.glGetIntegerv(c.GL_ACTIVE_TEXTURE, &last_active_texture);
- c.glActiveTexture(c.GL_TEXTURE0);
- c.glGetIntegerv(c.GL_CURRENT_PROGRAM, &last_program);
- c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
- if (@hasField(c, "GL_SAMPLER_BINDING"))
- c.glGetIntegerv(c.GL_SAMPLER_BINDING, &last_sampler);
- c.glGetIntegerv(c.GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
- if (!@hasField(c, "IMGUI_IMPL_OPENc.GL_ES2"))
- c.glGetIntegerv(c.GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object);
- if (@hasField(c, "GL_POLYGON_MODE"))
- c.glGetIntegerv(c.GL_POLYGON_MODE, last_polygon_mode);
- c.glGetIntegerv(c.GL_VIEWPORT, &last_viewport[0]);
- c.glGetIntegerv(c.GL_SCISSOR_BOX, &last_scissor_box[0]);
- c.glGetIntegerv(c.GL_BLEND_SRC_RGB, &last_blend_src_rgb);
- c.glGetIntegerv(c.GL_BLEND_DST_RGB, &last_blend_dst_rgb);
- c.glGetIntegerv(c.GL_BLEND_SRC_ALPHA, &last_blend_src_alpha);
- c.glGetIntegerv(c.GL_BLEND_DST_ALPHA, &last_blend_dst_alpha);
- c.glGetIntegerv(c.GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
- c.glGetIntegerv(c.GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
- var last_enable_blend : c.GLboolean = c.glIsEnabled(c.GL_BLEND);
- var last_enable_cull_face : c.GLboolean = c.glIsEnabled(c.GL_CULL_FACE);
- var last_enable_depth_test : c.GLboolean = c.glIsEnabled(c.GL_DEPTH_TEST);
- var last_enable_scissor_test : c.GLboolean = c.glIsEnabled(c.GL_SCISSOR_TEST);
- if (@hasField(c, "GL_CLIP_ORIGIN") and builtin.os != builtin.Os.osx) {
- // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
- c.glGetIntegerv(c.GL_CLIP_ORIGIN, &last_clip_origin);
- if (last_clip_origin == c.GL_UPPER_LEFT)
- clip_origin_lower_left = false;
- }
-
- defer {
- // Restore modified GL state
- c.glUseProgram(@intCast(c.GLuint, last_program));
- c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
+pub fn RenderDrawData(draw_data: *c.ImDrawData) void {
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ const fb_width = @floatToInt(i32, draw_data.*.DisplaySize.x * draw_data.*.FramebufferScale.x);
+ const fb_height = @floatToInt(i32, draw_data.*.DisplaySize.y * draw_data.*.FramebufferScale.y);
+ if (fb_width <= 0 or fb_height <= 0)
+ return;
+
+ // Backup GL state
+ var last_program: c.GLint = undefined;
+ var last_texture: c.GLint = undefined;
+ var last_sampler: c.GLint = undefined;
+ var last_array_buffer: c.GLint = undefined;
+ var last_vertex_array_object: c.GLint = undefined;
+ var last_polygon_mode: [2]c.GLint = undefined;
+ var last_viewport: [4]c.GLint = undefined;
+ var last_scissor_box: [4]c.GLint = undefined;
+ var last_blend_src_rgb: c.GLint = undefined;
+ var last_blend_dst_rgb: c.GLint = undefined;
+ var last_blend_src_alpha: c.GLint = undefined;
+ var last_blend_dst_alpha: c.GLint = undefined;
+ var last_blend_equation_rgb: c.GLint = undefined;
+ var last_blend_equation_alpha: c.GLint = undefined;
+ var clip_origin_lower_left: bool = true;
+ var last_clip_origin: c.GLint = 0;
+ var last_active_texture: c.GLint = undefined;
+
+ c.glGetIntegerv(c.GL_ACTIVE_TEXTURE, &last_active_texture);
+ c.glActiveTexture(c.GL_TEXTURE0);
+ c.glGetIntegerv(c.GL_CURRENT_PROGRAM, &last_program);
+ c.glGetIntegerv(c.GL_TEXTURE_BINDING_2D, &last_texture);
if (@hasField(c, "GL_SAMPLER_BINDING"))
- c.glBindSampler(0, @intCast(c.GLuint, last_sampler));
- c.glActiveTexture(@intCast(c.GLuint, last_active_texture));
- if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glBindVertexArray(@intCast(c.GLuint, last_vertex_array_object));
- c.glBindBuffer(c.GL_ARRAY_BUFFER, @intCast(c.GLuint, last_array_buffer));
- c.glBlendEquationSeparate(@intCast(c.GLuint, last_blend_equation_rgb), @intCast(c.GLuint, last_blend_equation_alpha));
- c.glBlendFuncSeparate(@intCast(c.GLuint, last_blend_src_rgb),
- @intCast(c.GLuint, last_blend_dst_rgb),
- @intCast(c.GLuint, last_blend_src_alpha),
- @intCast(c.GLuint, last_blend_dst_alpha));
- if (last_enable_blend == c.GL_TRUE) { c.glEnable(c.GL_BLEND); }
- else { c.glDisable(c.GL_BLEND); }
- if (last_enable_cull_face == c.GL_TRUE) { c.glEnable(c.GL_CULL_FACE); }
- else { c.glDisable(c.GL_CULL_FACE); }
- if (last_enable_depth_test == c.GL_TRUE) { c.glEnable(c.GL_DEPTH_TEST); }
- else { c.glDisable(c.GL_DEPTH_TEST); }
- if (last_enable_scissor_test == c.GL_TRUE) { c.glEnable(c.GL_SCISSOR_TEST); }
- else { c.glDisable(c.GL_SCISSOR_TEST); }
+ c.glGetIntegerv(c.GL_SAMPLER_BINDING, &last_sampler);
+ c.glGetIntegerv(c.GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
+ if (!@hasField(c, "IMGUI_IMPL_OPENc.GL_ES2"))
+ c.glGetIntegerv(c.GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object);
if (@hasField(c, "GL_POLYGON_MODE"))
- c.glPolygonMode(c.GL_FRONT_AND_BACK, @intCast(c.GLenum, last_polygon_mode[0]));
- c.glViewport(last_viewport[0], last_viewport[1], @intCast(c.GLsizei, last_viewport[2]), @intCast(c.GLsizei, last_viewport[3]));
- c.glScissor(last_scissor_box[0], last_scissor_box[1], @intCast(c.GLsizei, last_scissor_box[2]), @intCast(c.GLsizei, last_scissor_box[3]));
- }
-
- // Setup desired GL state
- // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
- // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
- var vertex_array_object : c.GLuint = 0;
- if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glGenVertexArrays(1, &vertex_array_object);
- defer if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glDeleteVertexArrays(1, &vertex_array_object);
-
- SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
-
- // Will project scissor/clipping rectangles into framebuffer space
- const clip_off = draw_data.*.DisplayPos; // (0,0) unless using multi-viewports
- const clip_scale = draw_data.*.FramebufferScale; // (1,1) unless using retina display which are often (2,2)
-
- // Render command lists
- var n : usize = 0;
- while (n < @intCast(usize, draw_data.*.CmdListsCount)) : (n += 1) {
- const cmd_list = draw_data.*.CmdLists[n];
-
- // Upload vertex/index buffers
- c.glBufferData(c.GL_ARRAY_BUFFER, cmd_list.*.VtxBuffer.Size * @sizeOf(c.ImDrawVert), @ptrCast(?*c.GLvoid, cmd_list.*.VtxBuffer.Data), c.GL_STREAM_DRAW);
- c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, cmd_list.*.IdxBuffer.Size * @sizeOf(c.ImDrawIdx), @ptrCast(*c.GLvoid, cmd_list.*.IdxBuffer.Data), c.GL_STREAM_DRAW);
-
- var cmd_i : usize = 0;
- while (cmd_i < @intCast(usize, cmd_list.*.CmdBuffer.Size)) : (cmd_i += 1) {
- const pcmd = &cmd_list.*.CmdBuffer.Data[cmd_i];
-
- if (pcmd.*.UserCallback != null) {
- // User callback, registered via ImDrawList::AddCallback()
- // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
- const ImDrawCallback_ResetRenderState = @intToPtr(c.ImDrawCallback, math.maxInt(usize));
- if (pcmd.*.UserCallback == ImDrawCallback_ResetRenderState) {
- SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
+ c.glGetIntegerv(c.GL_POLYGON_MODE, last_polygon_mode);
+ c.glGetIntegerv(c.GL_VIEWPORT, &last_viewport[0]);
+ c.glGetIntegerv(c.GL_SCISSOR_BOX, &last_scissor_box[0]);
+ c.glGetIntegerv(c.GL_BLEND_SRC_RGB, &last_blend_src_rgb);
+ c.glGetIntegerv(c.GL_BLEND_DST_RGB, &last_blend_dst_rgb);
+ c.glGetIntegerv(c.GL_BLEND_SRC_ALPHA, &last_blend_src_alpha);
+ c.glGetIntegerv(c.GL_BLEND_DST_ALPHA, &last_blend_dst_alpha);
+ c.glGetIntegerv(c.GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
+ c.glGetIntegerv(c.GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
+ var last_enable_blend: c.GLboolean = c.glIsEnabled(c.GL_BLEND);
+ var last_enable_cull_face: c.GLboolean = c.glIsEnabled(c.GL_CULL_FACE);
+ var last_enable_depth_test: c.GLboolean = c.glIsEnabled(c.GL_DEPTH_TEST);
+ var last_enable_scissor_test: c.GLboolean = c.glIsEnabled(c.GL_SCISSOR_TEST);
+ if (@hasField(c, "GL_CLIP_ORIGIN") and builtin.os != builtin.Os.osx) {
+ // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
+ c.glGetIntegerv(c.GL_CLIP_ORIGIN, &last_clip_origin);
+ if (last_clip_origin == c.GL_UPPER_LEFT)
+ clip_origin_lower_left = false;
+ }
+
+ defer {
+ // Restore modified GL state
+ c.glUseProgram(@intCast(c.GLuint, last_program));
+ c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, last_texture));
+ if (@hasField(c, "GL_SAMPLER_BINDING"))
+ c.glBindSampler(0, @intCast(c.GLuint, last_sampler));
+ c.glActiveTexture(@intCast(c.GLuint, last_active_texture));
+ if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glBindVertexArray(@intCast(c.GLuint, last_vertex_array_object));
+ c.glBindBuffer(c.GL_ARRAY_BUFFER, @intCast(c.GLuint, last_array_buffer));
+ c.glBlendEquationSeparate(@intCast(c.GLuint, last_blend_equation_rgb), @intCast(c.GLuint, last_blend_equation_alpha));
+ c.glBlendFuncSeparate(@intCast(c.GLuint, last_blend_src_rgb), @intCast(c.GLuint, last_blend_dst_rgb), @intCast(c.GLuint, last_blend_src_alpha), @intCast(c.GLuint, last_blend_dst_alpha));
+ if (last_enable_blend == c.GL_TRUE) {
+ c.glEnable(c.GL_BLEND);
} else {
- if (pcmd.*.UserCallback) |callback| {
- callback(cmd_list, pcmd);
- } else {
- unreachable;
- }
+ c.glDisable(c.GL_BLEND);
}
- } else {
- // Project scissor/clipping rectangles into framebuffer space
- var clip_rect : c.ImVec4 = undefined;
- clip_rect.x = (pcmd.*.ClipRect.x - clip_off.x) * clip_scale.x;
- clip_rect.y = (pcmd.*.ClipRect.y - clip_off.y) * clip_scale.y;
- clip_rect.z = (pcmd.*.ClipRect.z - clip_off.x) * clip_scale.x;
- clip_rect.w = (pcmd.*.ClipRect.w - clip_off.y) * clip_scale.y;
-
- if (clip_rect.x < @intToFloat(f32, fb_width) and clip_rect.y < @intToFloat(f32, fb_height)
- and clip_rect.z >= 0.0 and clip_rect.w >= 0.0) {
- // Apply scissor/clipping rectangle
- if (clip_origin_lower_left) {
- c.glScissor(@floatToInt(c.GLint, clip_rect.x), fb_height - @floatToInt(c.GLint, clip_rect.w),
- @floatToInt(c.GLint, clip_rect.z - clip_rect.x), @floatToInt(c.GLint, clip_rect.w - clip_rect.y));
- } else {
- // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
- c.glScissor(@floatToInt(c.GLint, clip_rect.x), @floatToInt(c.GLint, clip_rect.y),
- @floatToInt(c.GLint, clip_rect.z), @floatToInt(c.GLint, clip_rect.w));
- }
-
- // Bind texture, Draw
- c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, @ptrToInt(pcmd.*.TextureId)));
- const drawIndexSize = @sizeOf(c.ImDrawIdx);
- const drawIndexType = if (drawIndexSize == 2) c.GL_UNSIGNED_SHORT else c.GL_UNSIGNED_INT;
- const offset = @intToPtr(?*c.GLvoid, pcmd.*.IdxOffset * drawIndexSize);
- if (@hasField(c, "IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX")) {
- c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(c.GLsizei, pcmd.*.ElemCount), drawIndexType, offset, @intCast(c.GLint, pcmd.*.VtxOffset));
- } else {
- c.glDrawElements(c.GL_TRIANGLES, @intCast(c.GLsizei, pcmd.*.ElemCount), drawIndexType, offset);
- }
+ if (last_enable_cull_face == c.GL_TRUE) {
+ c.glEnable(c.GL_CULL_FACE);
+ } else {
+ c.glDisable(c.GL_CULL_FACE);
+ }
+ if (last_enable_depth_test == c.GL_TRUE) {
+ c.glEnable(c.GL_DEPTH_TEST);
+ } else {
+ c.glDisable(c.GL_DEPTH_TEST);
+ }
+ if (last_enable_scissor_test == c.GL_TRUE) {
+ c.glEnable(c.GL_SCISSOR_TEST);
+ } else {
+ c.glDisable(c.GL_SCISSOR_TEST);
+ }
+ if (@hasField(c, "GL_POLYGON_MODE"))
+ c.glPolygonMode(c.GL_FRONT_AND_BACK, @intCast(c.GLenum, last_polygon_mode[0]));
+ c.glViewport(last_viewport[0], last_viewport[1], @intCast(c.GLsizei, last_viewport[2]), @intCast(c.GLsizei, last_viewport[3]));
+ c.glScissor(last_scissor_box[0], last_scissor_box[1], @intCast(c.GLsizei, last_scissor_box[2]), @intCast(c.GLsizei, last_scissor_box[3]));
+ }
+
+ // Setup desired GL state
+ // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
+ // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
+ var vertex_array_object: c.GLuint = 0;
+ if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glGenVertexArrays(1, &vertex_array_object);
+ defer if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glDeleteVertexArrays(1, &vertex_array_object);
+
+ SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ const clip_off = draw_data.*.DisplayPos; // (0,0) unless using multi-viewports
+ const clip_scale = draw_data.*.FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ var n: usize = 0;
+ while (n < @intCast(usize, draw_data.*.CmdListsCount)) : (n += 1) {
+ const cmd_list = draw_data.*.CmdLists[n];
+
+ // Upload vertex/index buffers
+ c.glBufferData(c.GL_ARRAY_BUFFER, cmd_list.*.VtxBuffer.Size * @sizeOf(c.ImDrawVert), @ptrCast(?*c.GLvoid, cmd_list.*.VtxBuffer.Data), c.GL_STREAM_DRAW);
+ c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, cmd_list.*.IdxBuffer.Size * @sizeOf(c.ImDrawIdx), @ptrCast(*c.GLvoid, cmd_list.*.IdxBuffer.Data), c.GL_STREAM_DRAW);
+
+ var cmd_i: usize = 0;
+ while (cmd_i < @intCast(usize, cmd_list.*.CmdBuffer.Size)) : (cmd_i += 1) {
+ const pcmd = &cmd_list.*.CmdBuffer.Data[cmd_i];
+
+ if (pcmd.*.UserCallback != null) {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ const ImDrawCallback_ResetRenderState = @intToPtr(c.ImDrawCallback, math.maxInt(usize));
+ if (pcmd.*.UserCallback == ImDrawCallback_ResetRenderState) {
+ SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
+ } else {
+ if (pcmd.*.UserCallback) |callback| {
+ callback(cmd_list, pcmd);
+ } else {
+ unreachable;
+ }
+ }
+ } else {
+ // Project scissor/clipping rectangles into framebuffer space
+ var clip_rect: c.ImVec4 = undefined;
+ clip_rect.x = (pcmd.*.ClipRect.x - clip_off.x) * clip_scale.x;
+ clip_rect.y = (pcmd.*.ClipRect.y - clip_off.y) * clip_scale.y;
+ clip_rect.z = (pcmd.*.ClipRect.z - clip_off.x) * clip_scale.x;
+ clip_rect.w = (pcmd.*.ClipRect.w - clip_off.y) * clip_scale.y;
+
+ if (clip_rect.x < @intToFloat(f32, fb_width) and clip_rect.y < @intToFloat(f32, fb_height) and clip_rect.z >= 0.0 and clip_rect.w >= 0.0) {
+ // Apply scissor/clipping rectangle
+ if (clip_origin_lower_left) {
+ c.glScissor(@floatToInt(c.GLint, clip_rect.x), fb_height - @floatToInt(c.GLint, clip_rect.w), @floatToInt(c.GLint, clip_rect.z - clip_rect.x), @floatToInt(c.GLint, clip_rect.w - clip_rect.y));
+ } else {
+ // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
+ c.glScissor(@floatToInt(c.GLint, clip_rect.x), @floatToInt(c.GLint, clip_rect.y), @floatToInt(c.GLint, clip_rect.z), @floatToInt(c.GLint, clip_rect.w));
+ }
+
+ // Bind texture, Draw
+ c.glBindTexture(c.GL_TEXTURE_2D, @intCast(c.GLuint, @ptrToInt(pcmd.*.TextureId)));
+ const drawIndexSize = @sizeOf(c.ImDrawIdx);
+ const drawIndexType = if (drawIndexSize == 2) c.GL_UNSIGNED_SHORT else c.GL_UNSIGNED_INT;
+ const offset = @intToPtr(?*c.GLvoid, pcmd.*.IdxOffset * drawIndexSize);
+ if (@hasField(c, "IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX")) {
+ c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(c.GLsizei, pcmd.*.ElemCount), drawIndexType, offset, @intCast(c.GLint, pcmd.*.VtxOffset));
+ } else {
+ c.glDrawElements(c.GL_TRIANGLES, @intCast(c.GLsizei, pcmd.*.ElemCount), drawIndexType, offset);
+ }
+ }
+ }
}
- }
}
- }
}
fn SetupRenderState(draw_data: *c.ImDrawData, fb_width: i32, fb_height: i32, vertex_array_object: c.GLuint) void {
- // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
- c.glEnable(c.GL_BLEND);
- c.glBlendEquation(c.GL_FUNC_ADD);
- c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
- c.glDisable(c.GL_CULL_FACE);
- c.glDisable(c.GL_DEPTH_TEST);
- c.glEnable(c.GL_SCISSOR_TEST);
- if (@hasField(c, "GL_POLYGON_MODE"))
- c.glPolygonMode(c.GL_FRONT_AND_BACK, c.GL_FILL);
-
- // Setup viewport, orthographic projection matrix
- // Our visible imgui space lies from draw_data.*.DisplayPos (top left) to draw_data.*.DisplayPos+data_data.*.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
- c.glViewport(0, 0, @intCast(c.GLsizei, fb_width), @intCast(c.GLsizei, fb_height));
- const L = draw_data.*.DisplayPos.x;
- const R = draw_data.*.DisplayPos.x + draw_data.*.DisplaySize.x;
- const T = draw_data.*.DisplayPos.y;
- const B = draw_data.*.DisplayPos.y + draw_data.*.DisplaySize.y;
- const ortho_projection = [4][4]f32{
- [_]f32{ 2.0/(R-L), 0.0, 0.0, 0.0 },
- [_]f32{ 0.0, 2.0/(T-B), 0.0, 0.0 },
- [_]f32{ 0.0, 0.0, -1.0, 0.0 },
- [_]f32{ (R+L)/(L-R), (T+B)/(B-T), 0.0, 1.0 },
- };
- c.glUseProgram(g_ShaderHandle);
- c.glUniform1i(g_AttribLocationTex, 0);
- c.glUniformMatrix4fv(g_AttribLocationProjMtx, 1, c.GL_FALSE, &ortho_projection[0][0]);
- if (@hasField(c, "GL_SAMPLER_BINDING"))
- c.glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
-
- if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
- c.glBindVertexArray(vertex_array_object);
-
- // Bind vertex/index buffers and setup attributes for ImDrawVert
- c.glBindBuffer(c.GL_ARRAY_BUFFER, g_VboHandle);
- c.glBindBuffer(c.GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
- c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxPos));
- c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxUV));
- c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxColor));
- c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxPos), 2, c.GL_FLOAT, c.GL_FALSE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "pos")));
- c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxUV), 2, c.GL_FLOAT, c.GL_FALSE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "uv")));
- c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxColor), 4, c.GL_UNSIGNED_BYTE, c.GL_TRUE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "col")));
+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
+ c.glEnable(c.GL_BLEND);
+ c.glBlendEquation(c.GL_FUNC_ADD);
+ c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
+ c.glDisable(c.GL_CULL_FACE);
+ c.glDisable(c.GL_DEPTH_TEST);
+ c.glEnable(c.GL_SCISSOR_TEST);
+ if (@hasField(c, "GL_POLYGON_MODE"))
+ c.glPolygonMode(c.GL_FRONT_AND_BACK, c.GL_FILL);
+
+ // Setup viewport, orthographic projection matrix
+ // Our visible imgui space lies from draw_data.*.DisplayPos (top left) to draw_data.*.DisplayPos+data_data.*.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ c.glViewport(0, 0, @intCast(c.GLsizei, fb_width), @intCast(c.GLsizei, fb_height));
+ const L = draw_data.*.DisplayPos.x;
+ const R = draw_data.*.DisplayPos.x + draw_data.*.DisplaySize.x;
+ const T = draw_data.*.DisplayPos.y;
+ const B = draw_data.*.DisplayPos.y + draw_data.*.DisplaySize.y;
+ const ortho_projection = [4][4]f32{
+ [_]f32{ 2.0 / (R - L), 0.0, 0.0, 0.0 },
+ [_]f32{ 0.0, 2.0 / (T - B), 0.0, 0.0 },
+ [_]f32{ 0.0, 0.0, -1.0, 0.0 },
+ [_]f32{ (R + L) / (L - R), (T + B) / (B - T), 0.0, 1.0 },
+ };
+ c.glUseProgram(g_ShaderHandle);
+ c.glUniform1i(g_AttribLocationTex, 0);
+ c.glUniformMatrix4fv(g_AttribLocationProjMtx, 1, c.GL_FALSE, &ortho_projection[0][0]);
+ if (@hasField(c, "GL_SAMPLER_BINDING"))
+ c.glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
+
+ if (!@hasField(c, "IMGUI_IMPL_OPENGL_ES2"))
+ c.glBindVertexArray(vertex_array_object);
+
+ // Bind vertex/index buffers and setup attributes for ImDrawVert
+ c.glBindBuffer(c.GL_ARRAY_BUFFER, g_VboHandle);
+ c.glBindBuffer(c.GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
+ c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxPos));
+ c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxUV));
+ c.glEnableVertexAttribArray(@intCast(c.GLuint, g_AttribLocationVtxColor));
+ c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxPos), 2, c.GL_FLOAT, c.GL_FALSE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "pos")));
+ c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxUV), 2, c.GL_FLOAT, c.GL_FALSE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "uv")));
+ c.glVertexAttribPointer(@intCast(c.GLuint, g_AttribLocationVtxColor), 4, c.GL_UNSIGNED_BYTE, c.GL_TRUE, @sizeOf(c.ImDrawVert), @intToPtr(?*c.GLvoid, @byteOffsetOf(c.ImDrawVert, "col")));
}
diff --git a/src/glfw_impl.zig b/src/glfw_impl.zig
index dffd7bf..d2defa5 100644
--- a/src/glfw_impl.zig
+++ b/src/glfw_impl.zig
@@ -1,20 +1,21 @@
+/// this is a port of cimgui/imgui/examples/imgui_impl_glfw.cpp
const c = @import("c.zig");
const builtin = @import("builtin");
const debug = @import("std").debug;
const math = @import("std").math;
pub const ClientApi = enum {
- Unknown,
- OpenGL,
- Vulkan,
+ Unknown,
+ OpenGL,
+ Vulkan,
};
// Data
var g_Window: ?*c.GLFWwindow = null;
var g_ClientApi: ClientApi = .Unknown;
var g_Time: f64 = 0.0;
-var g_MouseJustPressed = [_]bool{ false } ** 5;
-var g_MouseCursors = [_]?*c.GLFWcursor{ null } ** @enumToInt(c.ImGuiMouseCursor_COUNT);
+var g_MouseJustPressed = [_]bool{false} ** 5;
+var g_MouseCursors = [_]?*c.GLFWcursor{null} ** @enumToInt(c.ImGuiMouseCursor_COUNT);
var g_WantUpdateMonitors = true;
// Chain GLFW callbacks for main viewport:
@@ -25,290 +26,286 @@ var g_PrevUserCallbackKey: c.GLFWkeyfun = null;
var g_PrevUserCallbackChar: c.GLFWcharfun = null;
pub fn Init(window: *c.GLFWwindow, install_callbacks: bool, client_api: ClientApi) void {
- g_Window = window;
- g_Time = 0.0;
-
- // Setup back-end capabilities flags
- const io = c.igGetIO();
- io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasMouseCursors); // We can honor GetMouseCursor() values (optional)
- io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasSetMousePos); // We can honor io.WantSetMousePos requests (optional, rarely used)
- if (false) io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
- if (false and @hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
- io.*.BackendFlags |= @enumToInt(ImGuiBackendFlags_HasMouseHoveredViewport); // We can set io.MouseHoveredViewport correctly (optional, not easy)
- }
- io.*.BackendPlatformName = c"imgui_impl_glfw.zig";
-
- // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Tab)] = c.GLFW_KEY_TAB;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_LeftArrow)] = c.GLFW_KEY_LEFT;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_RightArrow)] = c.GLFW_KEY_RIGHT;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_UpArrow)] = c.GLFW_KEY_UP;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_DownArrow)] = c.GLFW_KEY_DOWN;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_PageUp)] = c.GLFW_KEY_PAGE_UP;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_PageDown)] = c.GLFW_KEY_PAGE_DOWN;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Home)] = c.GLFW_KEY_HOME;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_End)] = c.GLFW_KEY_END;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Insert)] = c.GLFW_KEY_INSERT;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Delete)] = c.GLFW_KEY_DELETE;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Backspace)] = c.GLFW_KEY_BACKSPACE;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Space)] = c.GLFW_KEY_SPACE;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Enter)] = c.GLFW_KEY_ENTER;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Escape)] = c.GLFW_KEY_ESCAPE;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_KeyPadEnter)] = c.GLFW_KEY_KP_ENTER;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_A)] = c.GLFW_KEY_A;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_C)] = c.GLFW_KEY_C;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_V)] = c.GLFW_KEY_V;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_X)] = c.GLFW_KEY_X;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Y)] = c.GLFW_KEY_Y;
- io.*.KeyMap[@enumToInt(c.ImGuiKey_Z)] = c.GLFW_KEY_Z;
-
- // @TODO: Clipboard
- // io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
- // io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
- io.*.ClipboardUserData = g_Window;
-
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR);
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_TextInput)] = c.glfwCreateStandardCursor(c.GLFW_IBEAM_CURSOR);
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeAll)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNS)] = c.glfwCreateStandardCursor(c.GLFW_VRESIZE_CURSOR);
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeEW)] = c.glfwCreateStandardCursor(c.GLFW_HRESIZE_CURSOR);
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNESW)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNWSE)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
- g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Hand)] = c.glfwCreateStandardCursor(c.GLFW_HAND_CURSOR);
-
- // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
- g_PrevUserCallbackMousebutton = null;
- g_PrevUserCallbackScroll = null;
- g_PrevUserCallbackKey = null;
- g_PrevUserCallbackChar = null;
- if (install_callbacks) {
- g_PrevUserCallbackMousebutton = c.glfwSetMouseButtonCallback(window, Callback_MouseButton);
- g_PrevUserCallbackScroll = c.glfwSetScrollCallback(window, Callback_Scroll);
- g_PrevUserCallbackKey = c.glfwSetKeyCallback(window, Callback_Key);
- g_PrevUserCallbackChar = c.glfwSetCharCallback(window, Callback_Char);
- }
-
- // Our mouse update function expect PlatformHandle to be filled for the main viewport
- const main_viewport = c.igGetMainViewport();
- main_viewport.*.PlatformHandle = g_Window;
- if (builtin.os == builtin.Os.windows)
- main_viewport.*.PlatformHandleRaw = c.glfwGetWin32Window(g_Window);
-
- // @TODO: Platform Interface (Viewport)
- if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
- unreachable;
+ g_Window = window;
+ g_Time = 0.0;
+
+ // Setup back-end capabilities flags
+ const io = c.igGetIO();
+ io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasMouseCursors); // We can honor GetMouseCursor() values (optional)
+ io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasSetMousePos); // We can honor io.WantSetMousePos requests (optional, rarely used)
+ if (false) io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
+ if (false and @hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
+ io.*.BackendFlags |= @enumToInt(ImGuiBackendFlags_HasMouseHoveredViewport); // We can set io.MouseHoveredViewport correctly (optional, not easy)
+ }
+ io.*.BackendPlatformName = c"imgui_impl_glfw.zig";
+
+ // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Tab)] = c.GLFW_KEY_TAB;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_LeftArrow)] = c.GLFW_KEY_LEFT;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_RightArrow)] = c.GLFW_KEY_RIGHT;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_UpArrow)] = c.GLFW_KEY_UP;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_DownArrow)] = c.GLFW_KEY_DOWN;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_PageUp)] = c.GLFW_KEY_PAGE_UP;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_PageDown)] = c.GLFW_KEY_PAGE_DOWN;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Home)] = c.GLFW_KEY_HOME;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_End)] = c.GLFW_KEY_END;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Insert)] = c.GLFW_KEY_INSERT;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Delete)] = c.GLFW_KEY_DELETE;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Backspace)] = c.GLFW_KEY_BACKSPACE;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Space)] = c.GLFW_KEY_SPACE;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Enter)] = c.GLFW_KEY_ENTER;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Escape)] = c.GLFW_KEY_ESCAPE;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_KeyPadEnter)] = c.GLFW_KEY_KP_ENTER;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_A)] = c.GLFW_KEY_A;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_C)] = c.GLFW_KEY_C;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_V)] = c.GLFW_KEY_V;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_X)] = c.GLFW_KEY_X;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Y)] = c.GLFW_KEY_Y;
+ io.*.KeyMap[@enumToInt(c.ImGuiKey_Z)] = c.GLFW_KEY_Z;
+
+ // @TODO: Clipboard
+ // io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
+ // io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
+ io.*.ClipboardUserData = g_Window;
+
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR);
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_TextInput)] = c.glfwCreateStandardCursor(c.GLFW_IBEAM_CURSOR);
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeAll)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNS)] = c.glfwCreateStandardCursor(c.GLFW_VRESIZE_CURSOR);
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeEW)] = c.glfwCreateStandardCursor(c.GLFW_HRESIZE_CURSOR);
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNESW)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_ResizeNWSE)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Hand)] = c.glfwCreateStandardCursor(c.GLFW_HAND_CURSOR);
+
+ // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
+ g_PrevUserCallbackMousebutton = null;
+ g_PrevUserCallbackScroll = null;
+ g_PrevUserCallbackKey = null;
+ g_PrevUserCallbackChar = null;
+ if (install_callbacks) {
+ g_PrevUserCallbackMousebutton = c.glfwSetMouseButtonCallback(window, Callback_MouseButton);
+ g_PrevUserCallbackScroll = c.glfwSetScrollCallback(window, Callback_Scroll);
+ g_PrevUserCallbackKey = c.glfwSetKeyCallback(window, Callback_Key);
+ g_PrevUserCallbackChar = c.glfwSetCharCallback(window, Callback_Char);
+ }
+
+ // Our mouse update function expect PlatformHandle to be filled for the main viewport
+ const main_viewport = c.igGetMainViewport();
+ main_viewport.*.PlatformHandle = g_Window;
+ if (builtin.os == builtin.Os.windows)
+ main_viewport.*.PlatformHandleRaw = c.glfwGetWin32Window(g_Window);
+
+ // @TODO: Platform Interface (Viewport)
+ if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
+ unreachable;
// ImGui_ImplGlfw_InitPlatformInterface();
- g_ClientApi = client_api;
+ g_ClientApi = client_api;
}
pub fn Shutdown() void {
- // @TODO: Platform Interface (Viewport)
- // ImGui_ImplGlfw_ShutdownPlatformInterface();
-
- for (g_MouseCursors) |*cursor| {
- c.glfwDestroyCursor(cursor.*);
- cursor.* = null;
- }
- g_ClientApi = .Unknown;
+ // @TODO: Platform Interface (Viewport)
+ // ImGui_ImplGlfw_ShutdownPlatformInterface();
+ for (g_MouseCursors) |*cursor| {
+ c.glfwDestroyCursor(cursor.*);
+ cursor.* = null;
+ }
+ g_ClientApi = .Unknown;
}
pub fn NewFrame() void {
- const io = c.igGetIO();
- debug.assert(c.ImFontAtlas_IsBuilt(io.*.Fonts));
-
- var w : c_int = undefined;
- var h : c_int = undefined;
- var display_w : c_int = undefined;
- var display_h : c_int = undefined;
- c.glfwGetWindowSize(g_Window, &w, &h);
- c.glfwGetFramebufferSize(g_Window, &display_w, &display_h);
- io.*.DisplaySize = c.ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
-
- if (w > 0 and h > 0)
- io.*.DisplayFramebufferScale = c.ImVec2{
- .x = @intToFloat(f32, display_w) / @intToFloat(f32, w),
- .y = @intToFloat(f32, display_h) / @intToFloat(f32, h),
- };
- if (g_WantUpdateMonitors)
- UpdateMonitors();
-
- // Setup time step
- const current_time = c.glfwGetTime();
- io.*.DeltaTime = if (g_Time > 0.0) @floatCast(f32, current_time - g_Time) else 1.0 / 60.0;
- g_Time = current_time;
-
- UpdateMousePosAndButtons();
- UpdateMouseCursor();
-
- UpdateGamepads();
+ const io = c.igGetIO();
+ debug.assert(c.ImFontAtlas_IsBuilt(io.*.Fonts));
+
+ var w: c_int = undefined;
+ var h: c_int = undefined;
+ var display_w: c_int = undefined;
+ var display_h: c_int = undefined;
+ c.glfwGetWindowSize(g_Window, &w, &h);
+ c.glfwGetFramebufferSize(g_Window, &display_w, &display_h);
+ io.*.DisplaySize = c.ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
+
+ if (w > 0 and h > 0)
+ io.*.DisplayFramebufferScale = c.ImVec2{
+ .x = @intToFloat(f32, display_w) / @intToFloat(f32, w),
+ .y = @intToFloat(f32, display_h) / @intToFloat(f32, h),
+ };
+ if (g_WantUpdateMonitors)
+ UpdateMonitors();
+
+ // Setup time step
+ const current_time = c.glfwGetTime();
+ io.*.DeltaTime = if (g_Time > 0.0) @floatCast(f32, current_time - g_Time) else 1.0 / 60.0;
+ g_Time = current_time;
+
+ UpdateMousePosAndButtons();
+ UpdateMouseCursor();
+
+ UpdateGamepads();
}
fn UpdateMonitors() void {
- const platform_io = c.igGetPlatformIO();
- var monitors_count : c_int = 0;
- const glfw_monitors = c.glfwGetMonitors(&monitors_count)[0..@intCast(usize, monitors_count)];
-
- c.ImVector_ImGuiPlatformMonitor_Resize(&platform_io.*.Monitors, monitors_count);
- for (glfw_monitors) |glfw_monitor, n| {
- var monitor = &platform_io.*.Monitors.Data[n];
- var x : c_int = undefined;
- var y : c_int = undefined;
- c.glfwGetMonitorPos(glfw_monitor, &x, &y);
- const vid_mode = c.glfwGetVideoMode(glfw_monitor); // glfw_monitors[n]);
-
- monitor.*.MainPos = c.ImVec2{ .x = @intToFloat(f32, x), .y = @intToFloat(f32, y) };
- monitor.*.MainSize = c.ImVec2{
- .x = @intToFloat(f32, vid_mode.*.width),
- .y = @intToFloat(f32, vid_mode.*.height),
- };
- if (false and c.GLFW_HAS_MONITOR_WORK_AREA) {
- var w : c_int = undefined;
- var h : c_int = undefined;
- c.glfwGetMonitorWorkarea(glfw_monitor, &x, &y, &w, &h);
- monitor.*.WorkPos = ImVec2{ .x = @intToFloat(f32, x), .y = @intToFloat(f32, y) };
- monitor.*.WorkSize = ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
- }
- if (false and c.GLFW_HAS_PER_MONITOR_DPI) {
- // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings,
- // which generally needs to be set in the manifest or at runtime.
- var x_scale : f32 = undefined;
- var y_scale : f32 = undefined;
- c.glfwGetMonitorContentScale(glfw_monitor, &x_scale, &y_scale);
- monitor.*.DpiScale = x_scale;
+ const platform_io = c.igGetPlatformIO();
+ var monitors_count: c_int = 0;
+ const glfw_monitors = c.glfwGetMonitors(&monitors_count)[0..@intCast(usize, monitors_count)];
+
+ c.ImVector_ImGuiPlatformMonitor_Resize(&platform_io.*.Monitors, monitors_count);
+ for (glfw_monitors) |glfw_monitor, n| {
+ var monitor = &platform_io.*.Monitors.Data[n];
+ var x: c_int = undefined;
+ var y: c_int = undefined;
+ c.glfwGetMonitorPos(glfw_monitor, &x, &y);
+ const vid_mode = c.glfwGetVideoMode(glfw_monitor); // glfw_monitors[n]);
+
+ monitor.*.MainPos = c.ImVec2{ .x = @intToFloat(f32, x), .y = @intToFloat(f32, y) };
+ monitor.*.MainSize = c.ImVec2{
+ .x = @intToFloat(f32, vid_mode.*.width),
+ .y = @intToFloat(f32, vid_mode.*.height),
+ };
+ if (false and c.GLFW_HAS_MONITOR_WORK_AREA) {
+ var w: c_int = undefined;
+ var h: c_int = undefined;
+ c.glfwGetMonitorWorkarea(glfw_monitor, &x, &y, &w, &h);
+ monitor.*.WorkPos = ImVec2{ .x = @intToFloat(f32, x), .y = @intToFloat(f32, y) };
+ monitor.*.WorkSize = ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
+ }
+ if (false and c.GLFW_HAS_PER_MONITOR_DPI) {
+ // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings,
+ // which generally needs to be set in the manifest or at runtime.
+ var x_scale: f32 = undefined;
+ var y_scale: f32 = undefined;
+ c.glfwGetMonitorContentScale(glfw_monitor, &x_scale, &y_scale);
+ monitor.*.DpiScale = x_scale;
+ }
}
- }
- g_WantUpdateMonitors = false;
+ g_WantUpdateMonitors = false;
}
fn UpdateMousePosAndButtons() void {
- // Update buttons
- const io = c.igGetIO();
- for (io.*.MouseDown) |*isDown, i| {
- // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
- isDown.* = g_MouseJustPressed[i] or c.glfwGetMouseButton(g_Window, @intCast(c_int, i)) != 0;
- g_MouseJustPressed[i] = false;
- }
-
- // Update mouse position
- const mouse_pos_backup = io.*.MousePos;
- io.*.MousePos = c.ImVec2{ .x = math.f32_min, .y = math.f32_min };
- io.*.MouseHoveredViewport = 0;
- const platform_io = c.igGetPlatformIO();
- var n : usize = 0;
- while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
- const viewport = platform_io.*.Viewports.Data[n];
- const window = @ptrCast(*c.GLFWwindow, viewport.*.PlatformHandle);
- const focused = c.glfwGetWindowAttrib(window, c.GLFW_FOCUSED) != 0;
- if (focused) {
- if (io.*.WantSetMousePos) {
- c.glfwSetCursorPos(window, mouse_pos_backup.x - viewport.*.Pos.x, mouse_pos_backup.y - viewport.*.Pos.y);
- } else {
- var mouse_x : f64 = undefined;
- var mouse_y : f64 = undefined;
- c.glfwGetCursorPos(window, &mouse_x, &mouse_y);
- if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
- // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
- var window_x : c_int = undefined;
- var window_y : c_int = undefined;
- c.glfwGetWindowPos(window, &window_x, &window_y);
- io.*.MousePos = c.ImVec2{
- .x = @floatCast(f32, mouse_x) + @intToFloat(f32, window_x),
- .y = @floatCast(f32, mouse_y) + @intToFloat(f32, window_y),
- };
- } else {
- // Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
- io.*.MousePos = c.ImVec2{ .x = @floatCast(f32, mouse_x), .y = @floatCast(f32, mouse_y) };
- }
- }
+ // Update buttons
+ const io = c.igGetIO();
+ for (io.*.MouseDown) |*isDown, i| {
+ // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
+ isDown.* = g_MouseJustPressed[i] or c.glfwGetMouseButton(g_Window, @intCast(c_int, i)) != 0;
+ g_MouseJustPressed[i] = false;
+ }
- for (io.*.MouseDown) |*isDown, i|
- isDown.* = isDown.* or c.glfwGetMouseButton(window, @intCast(c_int, i)) != 0;
+ // Update mouse position
+ const mouse_pos_backup = io.*.MousePos;
+ io.*.MousePos = c.ImVec2{ .x = math.f32_min, .y = math.f32_min };
+ io.*.MouseHoveredViewport = 0;
+ const platform_io = c.igGetPlatformIO();
+ var n: usize = 0;
+ while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
+ const viewport = platform_io.*.Viewports.Data[n];
+ const window = @ptrCast(*c.GLFWwindow, viewport.*.PlatformHandle);
+ const focused = c.glfwGetWindowAttrib(window, c.GLFW_FOCUSED) != 0;
+ if (focused) {
+ if (io.*.WantSetMousePos) {
+ c.glfwSetCursorPos(window, mouse_pos_backup.x - viewport.*.Pos.x, mouse_pos_backup.y - viewport.*.Pos.y);
+ } else {
+ var mouse_x: f64 = undefined;
+ var mouse_y: f64 = undefined;
+ c.glfwGetCursorPos(window, &mouse_x, &mouse_y);
+ if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
+ // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
+ var window_x: c_int = undefined;
+ var window_y: c_int = undefined;
+ c.glfwGetWindowPos(window, &window_x, &window_y);
+ io.*.MousePos = c.ImVec2{
+ .x = @floatCast(f32, mouse_x) + @intToFloat(f32, window_x),
+ .y = @floatCast(f32, mouse_y) + @intToFloat(f32, window_y),
+ };
+ } else {
+ // Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
+ io.*.MousePos = c.ImVec2{ .x = @floatCast(f32, mouse_x), .y = @floatCast(f32, mouse_y) };
+ }
+ }
+
+ for (io.*.MouseDown) |*isDown, i|
+ isDown.* = isDown.* or c.glfwGetMouseButton(window, @intCast(c_int, i)) != 0;
+ }
}
- }
}
fn UpdateMouseCursor() void {
- const io = c.igGetIO();
- if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_NoMouseCursorChange) != 0
- or c.glfwGetInputMode(g_Window, c.GLFW_CURSOR) == c.GLFW_CURSOR_DISABLED)
- return;
-
- const imgui_cursor = c.igGetMouseCursor();
- const platform_io = c.igGetPlatformIO();
- var n : usize = 0;
- while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
- const window = @ptrCast(*c.GLFWwindow, platform_io.*.Viewports.Data[n].*.PlatformHandle);
- if (imgui_cursor == @enumToInt(c.ImGuiMouseCursor_None) or io.*.MouseDrawCursor) {
- // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
- c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_HIDDEN);
- } else {
- // Show OS mouse cursor
- // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
- c.glfwSetCursor(window,
- if (g_MouseCursors[@intCast(usize, imgui_cursor)]) |cursor| cursor
- else g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)]);
- c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_NORMAL);
+ const io = c.igGetIO();
+ if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_NoMouseCursorChange) != 0 or c.glfwGetInputMode(g_Window, c.GLFW_CURSOR) == c.GLFW_CURSOR_DISABLED)
+ return;
+
+ const imgui_cursor = c.igGetMouseCursor();
+ const platform_io = c.igGetPlatformIO();
+ var n: usize = 0;
+ while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
+ const window = @ptrCast(*c.GLFWwindow, platform_io.*.Viewports.Data[n].*.PlatformHandle);
+ if (imgui_cursor == @enumToInt(c.ImGuiMouseCursor_None) or io.*.MouseDrawCursor) {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_HIDDEN);
+ } else {
+ // Show OS mouse cursor
+ // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
+ c.glfwSetCursor(window, if (g_MouseCursors[@intCast(usize, imgui_cursor)]) |cursor| cursor else g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)]);
+ c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_NORMAL);
+ }
}
- }
}
fn UpdateGamepads() void {
- // @TODO
+ // @TODO
}
// GLFW Callbacks
extern fn Callback_MouseButton(window: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) void {
- if (g_PrevUserCallbackMousebutton) |prev| {
- prev(window, button, action, mods);
- }
+ if (g_PrevUserCallbackMousebutton) |prev| {
+ prev(window, button, action, mods);
+ }
- if (button < 0)
- return;
+ if (button < 0)
+ return;
- const button_u = @intCast(usize, button);
- if (action == c.GLFW_PRESS and button_u < g_MouseJustPressed.len)
- g_MouseJustPressed[button_u] = true;
+ const button_u = @intCast(usize, button);
+ if (action == c.GLFW_PRESS and button_u < g_MouseJustPressed.len)
+ g_MouseJustPressed[button_u] = true;
}
extern fn Callback_Scroll(window: ?*c.GLFWwindow, dx: f64, dy: f64) void {
- if (g_PrevUserCallbackScroll) |prev| {
- prev(window, dx, dy);
- }
+ if (g_PrevUserCallbackScroll) |prev| {
+ prev(window, dx, dy);
+ }
- const io = c.igGetIO();
- io.*.MouseWheelH += @floatCast(f32, dx);
- io.*.MouseWheel += @floatCast(f32, dy);
+ const io = c.igGetIO();
+ io.*.MouseWheelH += @floatCast(f32, dx);
+ io.*.MouseWheel += @floatCast(f32, dy);
}
extern fn Callback_Key(window: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, modifiers: c_int) void {
- if (g_PrevUserCallbackKey) |prev| {
- prev(window, key, scancode, action, modifiers);
- }
-
- if (key < 0)
- unreachable;
-
- const key_u = @intCast(usize, key);
-
- const io = c.igGetIO();
- if (action == c.GLFW_PRESS)
- io.*.KeysDown[key_u] = true;
- if (action == c.GLFW_RELEASE)
- io.*.KeysDown[key_u] = false;
-
- // Modifiers are not reliable across systems
- io.*.KeyCtrl = io.*.KeysDown[c.GLFW_KEY_LEFT_CONTROL] or io.*.KeysDown[c.GLFW_KEY_RIGHT_CONTROL];
- io.*.KeyShift = io.*.KeysDown[c.GLFW_KEY_LEFT_SHIFT] or io.*.KeysDown[c.GLFW_KEY_RIGHT_SHIFT];
- io.*.KeyAlt = io.*.KeysDown[c.GLFW_KEY_LEFT_ALT] or io.*.KeysDown[c.GLFW_KEY_RIGHT_ALT];
- io.*.KeySuper = io.*.KeysDown[c.GLFW_KEY_LEFT_SUPER] or io.*.KeysDown[c.GLFW_KEY_RIGHT_SUPER];
+ if (g_PrevUserCallbackKey) |prev| {
+ prev(window, key, scancode, action, modifiers);
+ }
+
+ if (key < 0)
+ unreachable;
+
+ const key_u = @intCast(usize, key);
+
+ const io = c.igGetIO();
+ if (action == c.GLFW_PRESS)
+ io.*.KeysDown[key_u] = true;
+ if (action == c.GLFW_RELEASE)
+ io.*.KeysDown[key_u] = false;
+
+ // Modifiers are not reliable across systems
+ io.*.KeyCtrl = io.*.KeysDown[c.GLFW_KEY_LEFT_CONTROL] or io.*.KeysDown[c.GLFW_KEY_RIGHT_CONTROL];
+ io.*.KeyShift = io.*.KeysDown[c.GLFW_KEY_LEFT_SHIFT] or io.*.KeysDown[c.GLFW_KEY_RIGHT_SHIFT];
+ io.*.KeyAlt = io.*.KeysDown[c.GLFW_KEY_LEFT_ALT] or io.*.KeysDown[c.GLFW_KEY_RIGHT_ALT];
+ io.*.KeySuper = io.*.KeysDown[c.GLFW_KEY_LEFT_SUPER] or io.*.KeysDown[c.GLFW_KEY_RIGHT_SUPER];
}
extern fn Callback_Char(window: ?*c.GLFWwindow, char: c_uint) void {
- if (g_PrevUserCallbackChar) |prev| {
- prev(window, char);
- }
+ if (g_PrevUserCallbackChar) |prev| {
+ prev(window, char);
+ }
- const io = c.igGetIO();
- c.ImGuiIO_AddInputCharacter(io, char);
+ const io = c.igGetIO();
+ c.ImGuiIO_AddInputCharacter(io, char);
}
diff --git a/src/main.zig b/src/main.zig
index 5d5f24a..79dab91 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,3 +1,4 @@
+/// this is a port of cimgui/imgui/examples/example_glfw_opengl3/main.cpp
const c = @import("c.zig");
const std = @import("std");
const panic = std.debug.panic;
@@ -6,88 +7,88 @@ const glfw_impl = @import("glfw_impl.zig");
const gl3_impl = @import("gl3_impl.zig");
extern fn errorCallback(err: c_int, description: [*c]const u8) void {
- panic("Error: {}\n", description);
+ panic("Error: {}\n", description);
}
var window: *c.GLFWwindow = undefined;
pub fn main() !void {
- _ = c.glfwSetErrorCallback(errorCallback);
-
- if (c.glfwInit() == c.GL_FALSE) {
- panic("GLFW init failure\n");
- }
- defer c.glfwTerminate();
-
- c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3);
- c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 2);
- c.glfwWindowHint(c.GLFW_OPENGL_FORWARD_COMPAT, c.GL_TRUE);
- c.glfwWindowHint(c.GLFW_OPENGL_DEBUG_CONTEXT, debug_gl.is_on);
- c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE);
- // c.glfwWindowHint(c.GLFW_DEPTH_BITS, 0);
- // c.glfwWindowHint(c.GLFW_STENCIL_BITS, 8);
- c.glfwWindowHint(c.GLFW_RESIZABLE, c.GL_TRUE);
-
- const window_width = 640;
- const window_height = 480;
- window = c.glfwCreateWindow(window_width, window_height, c"ImGUI Test", null, null) orelse {
- panic("unable to create window\n");
- };
- defer c.glfwDestroyWindow(window);
-
- c.glfwMakeContextCurrent(window);
- c.glfwSwapInterval(1);
-
- const context = c.igCreateContext(null);
- defer c.igDestroyContext(context);
-
- const io = c.igGetIO();
- io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_NavEnableKeyboard);
- // io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_DockingEnable);
- // io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_ViewportsEnable);
-
- const style = c.igGetStyle();
- c.igStyleColorsDark(style);
-
- if (false and io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
- style.*.WindowRounding = 0.0;
- style.*.Colors[@enumToInt(c.ImGuiCol_WindowBg)].w = 1.0;
- }
-
- glfw_impl.Init(window, true, glfw_impl.ClientApi.OpenGL);
- defer glfw_impl.Shutdown();
-
- gl3_impl.Init(); // #version 150
- defer gl3_impl.Shutdown();
-
- const start_time = c.glfwGetTime();
- var prev_time = start_time;
-
- while (c.glfwWindowShouldClose(window) == c.GL_FALSE) {
- c.glfwPollEvents();
-
- try gl3_impl.NewFrame();
- glfw_impl.NewFrame();
- c.igNewFrame();
-
- // main part
- c.igShowDemoWindow(null);
-
- c.igRender();
- var w: c_int = undefined;
- var h: c_int = undefined;
- c.glfwGetFramebufferSize(window, &w, &h);
- c.glViewport(0, 0, w, h);
- c.glClearColor(0.0, 0.0, 0.0, 0.0);
- c.glClear(c.GL_COLOR_BUFFER_BIT);
- gl3_impl.RenderDrawData(c.igGetDrawData());
-
- // const now_time = c.glfwGetTime();
- // const elapsed = now_time - prev_time;
- // prev_time = now_time;
- // nextFrame(t, elapsed);
- // draw(t, @This());
-
- c.glfwSwapBuffers(window);
- }
+ _ = c.glfwSetErrorCallback(errorCallback);
+
+ if (c.glfwInit() == c.GL_FALSE) {
+ panic("GLFW init failure\n");
+ }
+ defer c.glfwTerminate();
+
+ c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3);
+ c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 2);
+ c.glfwWindowHint(c.GLFW_OPENGL_FORWARD_COMPAT, c.GL_TRUE);
+ c.glfwWindowHint(c.GLFW_OPENGL_DEBUG_CONTEXT, debug_gl.is_on);
+ c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE);
+ // c.glfwWindowHint(c.GLFW_DEPTH_BITS, 0);
+ // c.glfwWindowHint(c.GLFW_STENCIL_BITS, 8);
+ c.glfwWindowHint(c.GLFW_RESIZABLE, c.GL_TRUE);
+
+ const window_width = 640;
+ const window_height = 480;
+ window = c.glfwCreateWindow(window_width, window_height, c"ImGUI Test", null, null) orelse {
+ panic("unable to create window\n");
+ };
+ defer c.glfwDestroyWindow(window);
+
+ c.glfwMakeContextCurrent(window);
+ c.glfwSwapInterval(1);
+
+ const context = c.igCreateContext(null);
+ defer c.igDestroyContext(context);
+
+ const io = c.igGetIO();
+ io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_NavEnableKeyboard);
+ // io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_DockingEnable);
+ // io.*.ConfigFlags |= @enumToInt(c.ImGuiConfigFlags_ViewportsEnable);
+
+ const style = c.igGetStyle();
+ c.igStyleColorsDark(style);
+
+ if (false and io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
+ style.*.WindowRounding = 0.0;
+ style.*.Colors[@enumToInt(c.ImGuiCol_WindowBg)].w = 1.0;
+ }
+
+ glfw_impl.Init(window, true, glfw_impl.ClientApi.OpenGL);
+ defer glfw_impl.Shutdown();
+
+ gl3_impl.Init(); // #version 150
+ defer gl3_impl.Shutdown();
+
+ const start_time = c.glfwGetTime();
+ var prev_time = start_time;
+
+ while (c.glfwWindowShouldClose(window) == c.GL_FALSE) {
+ c.glfwPollEvents();
+
+ try gl3_impl.NewFrame();
+ glfw_impl.NewFrame();
+ c.igNewFrame();
+
+ // main part
+ c.igShowDemoWindow(null);
+
+ c.igRender();
+ var w: c_int = undefined;
+ var h: c_int = undefined;
+ c.glfwGetFramebufferSize(window, &w, &h);
+ c.glViewport(0, 0, w, h);
+ c.glClearColor(0.0, 0.0, 0.0, 0.0);
+ c.glClear(c.GL_COLOR_BUFFER_BIT);
+ gl3_impl.RenderDrawData(c.igGetDrawData());
+
+ // const now_time = c.glfwGetTime();
+ // const elapsed = now_time - prev_time;
+ // prev_time = now_time;
+ // nextFrame(t, elapsed);
+ // draw(t, @This());
+
+ c.glfwSwapBuffers(window);
+ }
}