Adds support for dear_imgui_internal.h
This commit is contained in:
parent
76e41b87cd
commit
8a7d77cdd4
8 changed files with 168922 additions and 136 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
4128
src/cached/dcimgui_internal.cpp
Normal file
4128
src/cached/dcimgui_internal.cpp
Normal file
File diff suppressed because it is too large
Load diff
4142
src/cached/dcimgui_internal.h
Normal file
4142
src/cached/dcimgui_internal.h
Normal file
File diff suppressed because it is too large
Load diff
81831
src/cached/dcimgui_internal.json
Normal file
81831
src/cached/dcimgui_internal.json
Normal file
File diff suppressed because it is too large
Load diff
7
src/cached/dcimgui_internal_imconfig.json
Normal file
7
src/cached/dcimgui_internal_imconfig.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"defines": [],
|
||||||
|
"enums": [],
|
||||||
|
"typedefs": [],
|
||||||
|
"structs": [],
|
||||||
|
"functions": []
|
||||||
|
}
|
||||||
78535
src/cached/dcimgui_internal_imgui.json
Normal file
78535
src/cached/dcimgui_internal_imgui.json
Normal file
File diff suppressed because it is too large
Load diff
404
src/generate.zig
404
src/generate.zig
|
|
@ -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..];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue