Adds support for dear_imgui_internal.h

This commit is contained in:
Mason Remaley 2025-11-16 03:25:19 -08:00
parent 76e41b87cd
commit 8a7d77cdd4
8 changed files with 168922 additions and 136 deletions

View file

@ -44,6 +44,11 @@ Here's how to build `cimgui.h`:
python3 $DEAR_BINDINGS_PATH/dear_bindings.py -o src/cached/cimgui $DEAR_IMGUI_PATH/imgui.h python3 $DEAR_BINDINGS_PATH/dear_bindings.py -o src/cached/cimgui $DEAR_IMGUI_PATH/imgui.h
``` ```
Here's how to build `cimgui_internal.h`:
```sh
python3 $DEAR_BINDINGS_PATH/dear_bindings.py -o src/cached/cimgui_internal --include $DEAR_IMGUI_PATH/imgui.h $DEAR_IMGUI_PATH/imgui_internal.h
```
Here's how to build a backend, using Vulkan as an example: Here's how to build a backend, using Vulkan as an example:
```sh ```sh

View file

@ -49,7 +49,10 @@ pub fn build(b: *std.Build) void {
}); });
dear_imgui_lib.addCSourceFiles(.{ dear_imgui_lib.addCSourceFiles(.{
.root = b.path("src/cached"), .root = b.path("src/cached"),
.files = &.{"dcimgui.cpp"}, .files = &.{
"dcimgui.cpp",
"dcimgui_internal.cpp",
},
.flags = flags, .flags = flags,
}); });
b.installArtifact(dear_imgui_lib); b.installArtifact(dear_imgui_lib);
@ -119,6 +122,7 @@ pub fn build(b: *std.Build) void {
const dear_imgui_zig = generate_dear_imgui.addOutputFileArg("dear_imgui.zig"); const dear_imgui_zig = generate_dear_imgui.addOutputFileArg("dear_imgui.zig");
generate_dear_imgui.addFileArg(b.path("src/templates/cimgui_prefix.zig.template")); generate_dear_imgui.addFileArg(b.path("src/templates/cimgui_prefix.zig.template"));
generate_dear_imgui.addFileArg(b.path("src/templates/cimgui_postfix.zig.template")); generate_dear_imgui.addFileArg(b.path("src/templates/cimgui_postfix.zig.template"));
generate_dear_imgui.addFileArg(b.path("src/cached/dcimgui_internal.json"));
const dear_imgui_zig_module = b.addModule("dear_imgui", .{ const dear_imgui_zig_module = b.addModule("dear_imgui", .{
.root_source_file = dear_imgui_zig, .root_source_file = dear_imgui_zig,
.target = target, .target = target,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
{
"defines": [],
"enums": [],
"typedefs": [],
"structs": [],
"functions": []
}

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,37 @@ const DeclarationKind = enum {
}; };
const Declarations = std.StringArrayHashMap(DeclarationKind); const Declarations = std.StringArrayHashMap(DeclarationKind);
const Symbols = struct {
public: std.StringArrayHashMap(void),
front_buf: std.StringArrayHashMap(void),
pub fn init(allocator: Allocator) @This() {
return .{
.public = .init(allocator),
.front_buf = .init(allocator),
};
}
pub fn deinit(self: *@This()) void {
self.public.deinit();
self.front_buf.deinit();
}
/// Returns true if there's already a public symbol with this name.
pub fn put(self: *@This(), name: []const u8) !bool {
const trimmed = std.mem.trimRight(u8, name, "_");
if (self.public.contains(trimmed)) return false;
try self.front_buf.put(trimmed, {});
return true;
}
pub fn makePublic(self: *@This()) void {
std.mem.swap(@FieldType(@This(), "public"), &self.public, &self.front_buf);
self.front_buf.clearRetainingCapacity();
}
};
const max_size = 5000000; const max_size = 5000000;
// The header type we'll parse from JSON. Fields are only included as needed. // The header type we'll parse from JSON. Fields are only included as needed.
@ -55,6 +86,7 @@ const Header = struct {
const Struct = struct { const Struct = struct {
name: []const u8, name: []const u8,
is_internal: bool,
is_anonymous: bool, is_anonymous: bool,
kind: enum { @"struct", @"union" }, kind: enum { @"struct", @"union" },
forward_declaration: bool, forward_declaration: bool,
@ -66,7 +98,7 @@ const Header = struct {
is_anonymous: bool, is_anonymous: bool,
type: Type, type: Type,
width: ?usize = null, width: ?usize = null,
default_value: ?std.json.Value = null, default_value: ?[]const u8 = null,
conditionals: []const Conditional = &.{}, conditionals: []const Conditional = &.{},
}; };
}; };
@ -155,6 +187,7 @@ pub fn main() !void {
const out_path = args.next().?; const out_path = args.next().?;
const prefix_path = args.next(); const prefix_path = args.next();
const postfix_path = args.next(); const postfix_path = args.next();
const internal_path = args.next();
std.debug.assert(args.next() == null); std.debug.assert(args.next() == null);
const out = try std.fs.cwd().createFile(out_path, .{}); const out = try std.fs.cwd().createFile(out_path, .{});
@ -171,45 +204,36 @@ pub fn main() !void {
try writer.writeAll("\n// End of prefix\n\n"); try writer.writeAll("\n// End of prefix\n\n");
} }
// Build a list of symbols so we can skip duplicates of public symbols in the internal headers
var symbols: Symbols = .init(allocator);
defer symbols.deinit();
// Write the source // Write the source
{ const main_source = try std.fs.cwd().readFileAlloc(allocator, in_path, max_size);
const source = try std.fs.cwd().readFileAlloc(allocator, in_path, max_size); defer allocator.free(main_source);
defer allocator.free(source); try writeSource(
allocator,
main_source,
writer,
&symbols,
false,
);
symbols.makePublic();
const header = try std.json.parseFromSlice(Header, allocator, source, .{ // Write the internal source, if supplied
.ignore_unknown_fields = true, if (internal_path) |p| {
}); const internal_source = try std.fs.cwd().readFileAlloc(allocator, p, max_size);
defer header.deinit(); defer allocator.free(internal_source);
// We need the list of declarations up front. try writer.writeAll("pub const internal = struct {\n");
var declarations = try getDeclarations(allocator, &header.value); try writeSource(
defer declarations.deinit(); allocator,
internal_source,
// Write all defines as private constants. writer,
try writeDefines(writer, &header.value); &symbols,
true,
// Write all typedefs as private constants. );
try writeTypedefs(writer, &header.value, &declarations); try writer.writeAll("};\n");
// Write all cimgui functions as private extern functions.
try writeExternFunctions(writer, &header.value, &declarations);
// Alias cimgui free functions under Zig friendly names.
try writeFreeFunctions(writer, &header.value);
// Get a list of cimgui methods. These were already written as externs, and can be aliased
// when we write their respective types.
var methods = try Methods.get(allocator, &header.value);
defer methods.deinit(allocator);
// Write cimgui enums as Zig enums.
try writeEnums(allocator, writer, &header.value);
// Write cimgui structs as Zig structs and unions.
try writeStructs(writer, &header.value, &declarations, &methods);
// Write helpers used by the other generated code.
try writeHelpers(writer);
} }
// Write the postfix // Write the postfix
@ -224,12 +248,61 @@ pub fn main() !void {
try writer.flush(); try writer.flush();
} }
fn writeSource(
allocator: Allocator,
source: []const u8,
writer: *std.Io.Writer,
symbols: *Symbols,
internal: bool,
) !void {
const header = try std.json.parseFromSlice(Header, allocator, source, .{
.ignore_unknown_fields = true,
});
defer header.deinit();
// We need the list of declarations up front.
var declarations = try getDeclarations(allocator, &header.value);
defer declarations.deinit();
// Write all defines as private constants.
try writeDefines(writer, internal, symbols, &header.value);
// Write all typedefs as private constants.
try writeTypedefs(writer, &header.value, symbols, &declarations);
// Write all cimgui functions as private extern functions.
try writeExternFunctions(writer, &header.value, symbols, &declarations);
// Alias cimgui free functions under Zig friendly names.
try writeFreeFunctions(writer, &header.value, symbols);
// Get a list of cimgui methods. These were already written as externs, and can be aliased
// when we write their respective types.
var methods = try Methods.get(allocator, &header.value);
defer methods.deinit(allocator);
// Write cimgui enums as Zig enums.
try writeEnums(allocator, writer, internal, &header.value, symbols);
// Write cimgui structs as Zig structs and unions.
try writeStructs(writer, &header.value, &declarations, &methods, symbols);
// Write helpers used by the other generated code. We skip this for the internal header
// since we're going to concatenate it with the main header, so this stuff will already be
// available.
if (!internal) {
try writeHelpers(writer);
}
}
fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations { fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
var declarations = Declarations.init(allocator); var declarations = Declarations.init(allocator);
errdefer declarations.deinit(); errdefer declarations.deinit();
for (header.structs) |ty| { for (header.structs) |ty| {
if (skip(ty.conditionals)) continue; if (skip(ty.conditionals)) continue;
const trimmed = std.mem.trimRight(u8, ty.name, "_");
var kind: DeclarationKind = .normal; var kind: DeclarationKind = .normal;
if (ty.forward_declaration) { if (ty.forward_declaration) {
if (std.mem.eql(u8, "ImDrawData", ty.name)) { if (std.mem.eql(u8, "ImDrawData", ty.name)) {
@ -259,12 +332,10 @@ fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
}; };
} }
const trimmed = std.mem.trimRight(u8, ty.name, "_");
try declarations.put(trimmed, kind); try declarations.put(trimmed, kind);
} }
for (header.enums) |e| { for (header.enums) |e| {
if (e.is_internal) continue;
if (skip(e.conditionals)) continue; if (skip(e.conditionals)) continue;
const trimmed = std.mem.trimRight(u8, e.name, "_"); const trimmed = std.mem.trimRight(u8, e.name, "_");
@ -274,26 +345,36 @@ fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
return declarations; return declarations;
} }
fn writeDefines(writer: anytype, header: *const Header) !void { fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *const Header) !void {
// We skip defines from the internal namespace for now
if (internal) return;
for (header.defines) |define| { for (header.defines) |define| {
if (define.is_internal) continue; if (define.is_internal != internal) continue;
if (skip(define.conditionals)) continue; if (skip(define.conditionals)) continue;
if (define.content) |content| { if (define.content) |content| {
if (std.mem.startsWith(u8, content, "(")) { if (try symbols.put(define.name)) {
const end = std.mem.indexOfScalar(u8, content, ')').?; if (std.mem.startsWith(u8, content, "(")) {
const ty = content[1..end]; const end = std.mem.indexOfScalar(u8, content, ')').?;
const val = content[end + 1 ..]; const ty = content[1..end];
try writer.print("const {s}: ", .{define.name}); const val = content[end + 1 ..];
try writeTypeName(writer, ty); try writer.print("const {s}: ", .{define.name});
try writer.print(" = {s};\n", .{val}); try writeTypeName(writer, ty);
} else { try writer.print(" = {s};\n", .{val});
try writer.print("const {s} = {s};\n", .{ define.name, content }); } else {
try writer.print("const {s} = {s};\n", .{ define.name, content });
}
} }
} }
} }
} }
fn writeTypedefs(writer: anytype, header: *const Header, declarations: *const Declarations) !void { fn writeTypedefs(
writer: anytype,
header: *const Header,
symbols: *Symbols,
declarations: *const Declarations,
) !void {
for (header.typedefs) |typedef| { for (header.typedefs) |typedef| {
// Skip typedefs skipped by the preprocessor // Skip typedefs skipped by the preprocessor
if (skip(typedef.conditionals)) continue; if (skip(typedef.conditionals)) continue;
@ -306,41 +387,46 @@ fn writeTypedefs(writer: anytype, header: *const Header, declarations: *const De
std.mem.eql(u8, typedef.name, typedef.type.declaration.?)) continue; std.mem.eql(u8, typedef.name, typedef.type.declaration.?)) continue;
// Write the typedef prefix // Write the typedef prefix
try writer.writeAll("const "); if (try symbols.put(typedef.name)) {
try writeTypeName(writer, typedef.name); try writer.writeAll("const ");
try writer.writeAll(" = "); try writeTypeName(writer, typedef.name);
try writeType(writer, typedef.type, declarations, .{}); try writer.writeAll(" = ");
try writer.writeAll(";\n"); try writeType(writer, typedef.type, declarations, .{});
try writer.writeAll(";\n");
}
} }
} }
fn writeExternFunctions( fn writeExternFunctions(
writer: anytype, writer: anytype,
header: *const Header, header: *const Header,
symbols: *Symbols,
declarations: *const Declarations, declarations: *const Declarations,
) !void { ) !void {
for (header.functions) |function| { for (header.functions) |function| {
if (skip(function.conditionals)) continue; if (skip(function.conditionals)) continue;
if (argsContainsVaList(function.arguments)) continue; if (argsContainsVaList(function.arguments)) continue;
try writer.print("extern fn {s}(", .{function.name}); if (try symbols.put(function.name)) {
for (function.arguments) |argument| { try writer.print("extern fn {s}(", .{function.name});
if (argument.type) |ty| { for (function.arguments) |argument| {
std.debug.assert(!argument.is_varargs); if (argument.type) |ty| {
try writeType(writer, ty, declarations, .{ std.debug.assert(!argument.is_varargs);
.is_instance_pointer = argument.is_instance_pointer, try writeType(writer, ty, declarations, .{
.is_argument = true, .is_instance_pointer = argument.is_instance_pointer,
.default_null = if (argument.default_value) |d| std.mem.eql(u8, d, "NULL") else false, .is_argument = true,
}); .default_null = if (argument.default_value) |d| std.mem.eql(u8, d, "NULL") else false,
} else { });
std.debug.assert(argument.is_varargs); } else {
try writer.writeAll("..."); std.debug.assert(argument.is_varargs);
try writer.writeAll("...");
}
try writer.writeAll(", ");
} }
try writer.writeAll(", "); try writer.writeAll(") callconv(.c) ");
try writeType(writer, function.return_type, declarations, .{ .is_result = true });
try writer.writeAll(";\n");
} }
try writer.writeAll(") callconv(.c) ");
try writeType(writer, function.return_type, declarations, .{ .is_result = true });
try writer.writeAll(";\n");
} }
} }
@ -355,15 +441,17 @@ fn argsContainsVaList(arguments: []const Header.Function.Argument) bool {
return false; return false;
} }
fn writeFreeFunctions(writer: anytype, header: *const Header) !void { fn writeFreeFunctions(writer: anytype, header: *const Header, symbols: *Symbols) !void {
for (header.functions) |function| { for (header.functions) |function| {
if (skip(function.conditionals)) continue; if (skip(function.conditionals)) continue;
if (function.original_class != null) continue; if (function.original_class != null) continue;
if (argsContainsVaList(function.arguments)) continue; if (argsContainsVaList(function.arguments)) continue;
try writer.writeAll("pub const "); if (try symbols.put(function.name)) {
try writeFunctionName(writer, function.name); try writer.writeAll("pub const ");
try writer.print(" = {s};\n", .{function.name}); try writeFunctionName(writer, function.name);
try writer.print(" = {s};\n", .{function.name});
}
} }
} }
@ -406,24 +494,31 @@ const Methods = struct {
} }
}; };
fn writeEnums(allocator: Allocator, writer: anytype, header: *const Header) !void { fn writeEnums(
allocator: Allocator,
writer: anytype,
internal: bool,
header: *const Header,
symbols: *Symbols,
) !void {
for (header.enums) |e| { for (header.enums) |e| {
if (e.is_internal) continue;
if (skip(e.conditionals)) continue; if (skip(e.conditionals)) continue;
try writer.writeAll("pub const "); if (try symbols.put(e.name)) {
try writeTypeName(writer, e.name); try writer.writeAll("pub const ");
try writer.writeAll(" = "); try writeTypeName(writer, e.name);
try writer.writeAll(" = ");
if (e.is_flags_enum) { if (e.is_flags_enum) {
try writeFlagsEnum(writer, e); try writeFlagsEnum(writer, internal, e);
} else { } else {
try writeNormalEnum(allocator, writer, e); try writeNormalEnum(allocator, writer, internal, e);
}
} }
} }
} }
fn writeFlagsEnum(writer: anytype, e: Header.Enum) !void { fn writeFlagsEnum(writer: anytype, internal: bool, e: Header.Enum) !void {
const backing, const backing_bits = switch (e.storage_type.declaration) { const backing, const backing_bits = switch (e.storage_type.declaration) {
.int => .{ "c_int", @typeInfo(c_int).int.bits }, .int => .{ "c_int", @typeInfo(c_int).int.bits },
.ImU8 => .{ "u8", 8 }, .ImU8 => .{ "u8", 8 },
@ -432,9 +527,9 @@ fn writeFlagsEnum(writer: anytype, e: Header.Enum) !void {
var current_offset: usize = 0; var current_offset: usize = 0;
var padding_i: usize = 0; var padding_i: usize = 0;
for (e.elements) |element| { for (e.elements) |element| {
// Skip internal elements, and elements discarded by preprocessor // Skip elements without matching visibility, and elements discarded by preprocessor
if (skip(element.conditionals)) continue; if (skip(element.conditionals)) continue;
if (element.is_internal) continue; if (element.is_internal != internal) continue;
if (element.value == 0) continue; if (element.value == 0) continue;
// Calculate the offset of this element // Calculate the offset of this element
@ -471,7 +566,7 @@ fn writeFlagsEnum(writer: anytype, e: Header.Enum) !void {
try writer.writeAll("};\n"); try writer.writeAll("};\n");
} }
fn writeNormalEnum(allocator: Allocator, writer: anytype, e: Header.Enum) !void { fn writeNormalEnum(allocator: Allocator, writer: anytype, internal: bool, e: Header.Enum) !void {
var values = std.AutoArrayHashMap(i64, void).init(allocator); var values = std.AutoArrayHashMap(i64, void).init(allocator);
defer values.deinit(); defer values.deinit();
@ -484,8 +579,8 @@ fn writeNormalEnum(allocator: Allocator, writer: anytype, e: Header.Enum) !void
// Write elements // Write elements
for (e.elements) |element| { for (e.elements) |element| {
// Skip internal and count // Skip non visible elements and count elements
if (element.is_internal) continue; if (element.is_internal != internal) continue;
if (element.is_count) continue; if (element.is_count) continue;
if (skip(element.conditionals)) continue; if (skip(element.conditionals)) continue;
@ -517,6 +612,7 @@ fn writeStructs(
header: *const Header, header: *const Header,
declarations: *const Declarations, declarations: *const Declarations,
methods: *const Methods, methods: *const Methods,
symbols: *Symbols,
) !void { ) !void {
for (header.structs) |ty| { for (header.structs) |ty| {
// Skip structs skipped by the preprocessor. We don't skip structs marked as internal, // Skip structs skipped by the preprocessor. We don't skip structs marked as internal,
@ -528,56 +624,79 @@ fn writeStructs(
const decl_kind = declarations.get(ty.name).?; const decl_kind = declarations.get(ty.name).?;
if (decl_kind == .import) continue; if (decl_kind == .import) continue;
// Write the struct if (try symbols.put(ty.name)) {
try writer.writeAll("pub const "); // Write the struct
try writeTypeName(writer, ty.name); try writer.writeAll("pub const ");
try writer.writeAll(" = "); try writeTypeName(writer, ty.name);
try writer.writeAll(" = ");
// If we're opaque, don't try to fill out the struct fields // If we're opaque, don't try to fill out the struct fields
if (decl_kind == .@"opaque") { if (decl_kind == .@"opaque") {
try writer.writeAll("opaque {};\n"); try writer.writeAll("opaque {};\n");
continue; continue;
}
// Declare the struct or union
switch (ty.kind) {
.@"struct" => try writer.writeAll("extern struct {\n"),
.@"union" => try writer.writeAll("extern union {\n"),
}
// Fill in the fields
for (ty.fields) |field| {
// Skip fields skipped by the preprocessor.
if (skip(field.conditionals)) continue;
// Not yet used, but when it is we want to start using it. Safe to disable this assert
// if you're just trying to get things working with a different version.
if (field.default_value != null) @panic("unimplemented");
// Write the field.
try writer.writeAll(" ");
if (field.is_anonymous) {
try writer.writeAll("data");
} else {
try writeFieldName(writer, field.name);
} }
try writer.writeAll(": ");
try writeType(writer, field.type, declarations, .{});
try writer.writeAll(",\n");
}
// Alias all relevant methods into the type. // Declare the struct or union
const method_names = methods.types.getPtr(ty.name).?; switch (ty.kind) {
for (method_names.items) |name| { .@"struct" => try writer.writeAll("extern struct {\n"),
try writer.writeAll(" pub const "); .@"union" => try writer.writeAll("extern union {\n"),
try writeFunctionName(writer, name[ty.name.len + 1 ..]); }
try writer.print(" = {s};\n", .{name});
}
try writer.writeAll("};\n"); // Fill in the fields
for (ty.fields) |field| {
// Skip fields skipped by the preprocessor.
if (skip(field.conditionals)) continue;
// Write the field.
try writer.writeAll(" ");
if (field.is_anonymous) {
try writer.writeAll("data");
} else {
try writeFieldName(writer, field.name);
}
try writer.writeAll(": ");
try writeType(writer, field.type, declarations, .{});
if (field.default_value) |v| {
try writer.writeAll(" = ");
try writeValue(writer, v);
}
try writer.writeAll(",\n");
}
// Alias all relevant methods into the type.
const method_names = methods.types.getPtr(ty.name).?;
for (method_names.items) |name| {
try writer.writeAll(" pub const ");
try writeFunctionName(writer, name[ty.name.len + 1 ..]);
try writer.print(" = {s};\n", .{name});
}
try writer.writeAll("};\n");
}
} }
} }
pub fn writeValue(writer: anytype, value: []const u8) !void {
// Strip the `f` postfix off of floats
float: {
if (value.len > 0 and
value[value.len - 1] == 'f' and
value[0] >= '0' and
value[0] <= '9')
{
switch (value[0]) {
'0'...'9' => {},
else => break :float,
}
try writer.writeAll(value[0 .. value.len - 1]);
return;
}
}
// Write everything else as is
try writer.writeAll(value);
}
fn writeHelpers(writer: anytype) !void { fn writeHelpers(writer: anytype) !void {
try writer.writeAll( try writer.writeAll(
\\fn toUsize(v: anytype) usize { \\fn toUsize(v: anytype) usize {
@ -836,6 +955,12 @@ fn skip(conditionals: []const Header.Conditional) bool {
if (std.mem.eql(u8, conditional.expression, "defined(VK_USE_PLATFORM_WIN32_KHR)&&!defined(NOMINMAX)")) break :b true; if (std.mem.eql(u8, conditional.expression, "defined(VK_USE_PLATFORM_WIN32_KHR)&&!defined(NOMINMAX)")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING")) break :b true; if (std.mem.eql(u8, conditional.expression, "IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING")) break :b true;
if (std.mem.eql(u8, conditional.expression, "defined(VK_VERSION_1_3)|| defined(VK_KHR_dynamic_rendering)")) break :b true; if (std.mem.eql(u8, conditional.expression, "defined(VK_VERSION_1_3)|| defined(VK_KHR_dynamic_rendering)")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_HAS_DOCK")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_ENABLE_SSE")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_ENABLE_STB_TRUETYPE")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_ENABLE_FREETYPE")) break :b true;
if (std.mem.eql(u8, conditional.expression, "IMGUI_ENABLE_TEST_ENGINE")) break :b true;
// False conditionals // False conditionals
if (std.mem.eql(u8, conditional.expression, "IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT")) break :b false; if (std.mem.eql(u8, conditional.expression, "IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT")) break :b false;
@ -854,6 +979,9 @@ fn skip(conditionals: []const Header.Conditional) bool {
if (std.mem.eql(u8, conditional.expression, "IMGUI_HAS_IMSTR")) break :b false; if (std.mem.eql(u8, conditional.expression, "IMGUI_HAS_IMSTR")) break :b false;
if (std.mem.eql(u8, conditional.expression, "IMGUI_DISABLE_DEBUG_TOOLS")) break :b false; if (std.mem.eql(u8, conditional.expression, "IMGUI_DISABLE_DEBUG_TOOLS")) break :b false;
if (std.mem.eql(u8, conditional.expression, "ImTextureID_Invalid")) break :b false; if (std.mem.eql(u8, conditional.expression, "ImTextureID_Invalid")) break :b false;
if (std.mem.eql(u8, conditional.expression, "IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS")) break :b false;
if (std.mem.eql(u8, conditional.expression, "IMGUI_DISABLE_FILE_FUNCTIONS")) break :b false;
if (std.mem.eql(u8, conditional.expression, "IMGUI_STB_NAMESPACE")) break :b false;
std.debug.panic("unexpected preprocessor conditional: {s}", .{conditional.expression}); std.debug.panic("unexpected preprocessor conditional: {s}", .{conditional.expression});
}; };
@ -974,7 +1102,13 @@ fn writeFunctionName(writer: anytype, raw: []const u8) !void {
// Imgui prefixes // Imgui prefixes
{ {
const prefixes: []const []const u8 = &.{ "cImGui_ImplVulkan", "cImGui_ImplSDL3", "ImGui", "Im" }; const prefixes: []const []const u8 = &.{
"cImGui_ImplVulkan",
"cImGui_ImplSDL3",
"ImGui",
"Im",
"cIm",
};
for (prefixes) |prefix| { for (prefixes) |prefix| {
if (std.mem.startsWith(u8, name, prefix)) { if (std.mem.startsWith(u8, name, prefix)) {
name = name[prefix.len..]; name = name[prefix.len..];