From 2bedfd589896013fe92b85fb31a8ce89783f2c99 Mon Sep 17 00:00:00 2001 From: Thraka Date: Wed, 23 Nov 2022 15:28:59 -0800 Subject: [PATCH 1/8] Add new command line system; expose internals --- src/CodeGenerator/CodeGenerator.csproj | 1 + src/CodeGenerator/ImguiDefinitions.cs | 40 ++++-- src/CodeGenerator/Program.cs | 178 +++++++++++++++++-------- src/CodeGenerator/TypeInfo.cs | 12 ++ 4 files changed, 163 insertions(+), 68 deletions(-) diff --git a/src/CodeGenerator/CodeGenerator.csproj b/src/CodeGenerator/CodeGenerator.csproj index 6c2760d7..c15d0c0c 100644 --- a/src/CodeGenerator/CodeGenerator.csproj +++ b/src/CodeGenerator/CodeGenerator.csproj @@ -25,5 +25,6 @@ + diff --git a/src/CodeGenerator/ImguiDefinitions.cs b/src/CodeGenerator/ImguiDefinitions.cs index 92e7d741..c9cc936d 100644 --- a/src/CodeGenerator/ImguiDefinitions.cs +++ b/src/CodeGenerator/ImguiDefinitions.cs @@ -21,7 +21,7 @@ static int GetInt(JToken token, string key) if (v == null) return 0; return v.ToObject(); } - public void LoadFrom(string directory) + public void LoadFrom(string directory, bool excludeInternals = true) { JObject typesJson; @@ -65,23 +65,27 @@ public void LoadFrom(string directory) { JProperty jp = (JProperty)jt; string name = jp.Name; - if (typeLocations?[jp.Name]?.Value().Contains("internal") ?? false) { + bool isInternal = typeLocations?[jp.Name]?.Value().Contains("internal") ?? false; + + if (excludeInternals && isInternal) return null; - } + EnumMember[] elements = jp.Values().Select(v => { return new EnumMember(v["name"].ToString(), v["calc_value"].ToString()); }).ToArray(); - return new EnumDefinition(name, elements); + return new EnumDefinition(name, elements, isInternal); }).Where(x => x != null).ToArray(); Types = typesJson["structs"].Select(jt => { JProperty jp = (JProperty)jt; string name = jp.Name; - if (typeLocations?[jp.Name]?.Value().Contains("internal") ?? false) { + bool isInternal = typeLocations?[jp.Name]?.Value().Contains("internal") ?? false; + + if (excludeInternals && isInternal) return null; - } + TypeReference[] fields = jp.Values().Select(v => { if (v["type"].ToString().Contains("static")) { return null; } @@ -94,7 +98,7 @@ public void LoadFrom(string directory) v["template_type"]?.ToString(), Enums); }).Where(tr => tr != null).ToArray(); - return new TypeDefinition(name, fields); + return new TypeDefinition(name, fields, isInternal); }).Where(x => x != null).ToArray(); Functions = functionsJson.Children().Select(jt => @@ -120,7 +124,9 @@ public void LoadFrom(string directory) } } if (friendlyName == null) { return null; } - if (val["location"]?.ToString().Contains("internal") ?? false) return null; + bool isInternal = val["location"]?.ToString().Contains("internal") ?? false; + if (excludeInternals && isInternal) + return null; string exportedName = ov_cimguiname; if (exportedName == null) @@ -184,7 +190,8 @@ public void LoadFrom(string directory) structName, comment, isConstructor, - isDestructor); + isDestructor, + isInternal); }).Where(od => od != null).ToArray(); if(overloads.Length == 0) return null; return new FunctionDefinition(name, overloads, Enums); @@ -231,8 +238,9 @@ class EnumDefinition public string Name { get; } public string FriendlyName { get; } public EnumMember[] Members { get; } + public bool IsInternal { get; } - public EnumDefinition(string name, EnumMember[] elements) + public EnumDefinition(string name, EnumMember[] elements, bool isInternal) { Name = name; if (Name.EndsWith('_')) @@ -250,6 +258,7 @@ public EnumDefinition(string name, EnumMember[] elements) { _sanitizedNames.Add(el.Name, SanitizeMemberName(el.Name)); } + IsInternal = isInternal; } public string SanitizeNames(string text) @@ -302,11 +311,13 @@ class TypeDefinition { public string Name { get; } public TypeReference[] Fields { get; } + public bool IsInternal { get; } - public TypeDefinition(string name, TypeReference[] fields) + public TypeDefinition(string name, TypeReference[] fields, bool isInternal) { Name = name; Fields = fields; + IsInternal = isInternal; } } @@ -496,6 +507,7 @@ class OverloadDefinition public string Comment { get; } public bool IsConstructor { get; } public bool IsDestructor { get; } + public bool IsInternal { get; } public OverloadDefinition( string exportedName, @@ -506,7 +518,8 @@ public OverloadDefinition( string structName, string comment, bool isConstructor, - bool isDestructor) + bool isDestructor, + bool isInternal) { ExportedName = exportedName; FriendlyName = friendlyName; @@ -518,11 +531,12 @@ public OverloadDefinition( Comment = comment; IsConstructor = isConstructor; IsDestructor = isDestructor; + IsInternal = isInternal; } public OverloadDefinition WithParameters(TypeReference[] parameters) { - return new OverloadDefinition(ExportedName, FriendlyName, parameters, DefaultValues, ReturnType, StructName, Comment, IsConstructor, IsDestructor); + return new OverloadDefinition(ExportedName, FriendlyName, parameters, DefaultValues, ReturnType, StructName, Comment, IsConstructor, IsDestructor, IsInternal); } } } diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index d85f7c2b..fb39deb8 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -8,37 +8,85 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using System.CommandLine; +using System.Linq.Expressions; +using System.Runtime.CompilerServices; namespace CodeGenerator { internal static class Program { - static void Main(string[] args) + private const string InternalNamespace = ".Internal"; + + static async Task Main(string[] args) { - string outputPath; - if (args.Length > 0) - { - outputPath = args[0]; - } - else - { - outputPath = AppContext.BaseDirectory; - } + // internal vars for command line results used by the rest of the program. + bool runApp = false; + string outputPath = string.Empty; + string libraryName = string.Empty; + bool useInternals = false; - if (!Directory.Exists(outputPath)) - { - Directory.CreateDirectory(outputPath); - } + #region Command line handler + var optionOutputPath = new Option( + aliases: new[] { "--outputDir", "-o" }, + description: "The directory to place generated code files.", + parseArgument: result => + { + if (result.Tokens.Count == 0) + return new DirectoryInfo(AppContext.BaseDirectory); - string libraryName; - if (args.Length > 1) - { - libraryName = args[1]; - } - else + string value = result.Tokens.Single().Value; + + try { return Directory.CreateDirectory(value); } + catch (Exception) { result.ErrorMessage = $"Unable to create directory: {value}"; return null; } + }, + isDefault: true); + + var optionLibraryname = new Option( + aliases: new[] { "--library", "-l" }, + description: "The library to read parse.", + getDefaultValue: () => "cimgui") + .FromAmong("cimgui", "cimplot", "cimnodes", "cimguizmo"); + + var optionInternal = new Option( + name: "--internal", + description: "When set to true, includes the internal header file.", + parseArgument: result => + { + // Using parse with isDefault: false, instead of the normal validation, allows us to use "--internal" without specifying true to mean true. + if (result.Tokens.Count == 0) + return true; + + if (bool.TryParse(result.Tokens.Single().Value, out var value)) + return value; + + result.ErrorMessage = "Invalid option for --internal. Value must be true or false."; + return false; // ignored because of error message. + }, + isDefault: false); + + var rootCommand = new RootCommand("Generates code for the ImGui.NET libraries based on the cimgui definition files."); + + rootCommand.AddOption(optionInternal); + rootCommand.AddOption(optionOutputPath); + rootCommand.AddOption(optionLibraryname); + + rootCommand.SetHandler((outputPathValue, libNameValue, useInternalValue) => { - libraryName = "cimgui"; - } + outputPath = outputPathValue.FullName; + libraryName = libNameValue; + useInternals = useInternalValue; + + runApp = true; + + }, optionOutputPath, optionLibraryname, optionInternal); + + var commandResult = await rootCommand.InvokeAsync(args); + + if (!runApp) + return commandResult; + + #endregion string projectNamespace = libraryName switch { @@ -78,7 +126,7 @@ static void Main(string[] args) string definitionsPath = Path.Combine(AppContext.BaseDirectory, "definitions", libraryName); var defs = new ImguiDefinitions(); - defs.LoadFrom(definitionsPath); + defs.LoadFrom(definitionsPath, !useInternals); Console.WriteLine($"Outputting generated code files to {outputPath}."); @@ -118,7 +166,7 @@ static void Main(string[] args) writer.Using("ImGuiNET"); } writer.WriteLine(string.Empty); - writer.PushBlock($"namespace {projectNamespace}"); + writer.PushBlock($"namespace {projectNamespace}{(td.IsInternal ? InternalNamespace : string.Empty)}"); writer.PushBlock($"public unsafe partial struct {td.Name}"); foreach (TypeReference field in td.Fields) @@ -284,6 +332,10 @@ static void Main(string[] args) { writer.Using("ImGuiNET"); } + if (useInternals) + { + writer.Using($"{projectNamespace}{InternalNamespace}"); + } writer.WriteLine(string.Empty); writer.PushBlock($"namespace {projectNamespace}"); writer.PushBlock($"public static unsafe partial class {classPrefix}Native"); @@ -347,6 +399,7 @@ static void Main(string[] args) writer.PopBlock(); } + // Root ImGui* class items - Noninternal using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, $"{classPrefix}.gen.cs"))) { writer.Using("System"); @@ -360,52 +413,65 @@ static void Main(string[] args) writer.WriteLine(string.Empty); writer.PushBlock($"namespace {projectNamespace}"); writer.PushBlock($"public static unsafe partial class {classPrefix}"); - foreach (FunctionDefinition fd in defs.Functions) + EmitFunctions(false); + writer.PopBlock(); + writer.PopBlock(); + + if (useInternals) { - if (TypeInfo.SkippedFunctions.Contains(fd.Name)) { continue; } + writer.PushBlock($"namespace {projectNamespace}{InternalNamespace}"); + writer.PushBlock($"public static unsafe partial class {classPrefix}"); + EmitFunctions(true); + writer.PopBlock(); + writer.PopBlock(); + } - foreach (OverloadDefinition overload in fd.Overloads) + void EmitFunctions(bool isInternal) + { + foreach (FunctionDefinition fd in defs.Functions) { - string exportedName = overload.ExportedName; - if (exportedName.StartsWith("ig")) - { - exportedName = exportedName.Substring(2, exportedName.Length - 2); - } - if (exportedName.Contains("~")) { continue; } - if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. + if (TypeInfo.SkippedFunctions.Contains(fd.Name)) { continue; } - bool hasVaList = false; - for (int i = 0; i < overload.Parameters.Length; i++) + foreach (OverloadDefinition overload in fd.Overloads.Where(o => !o.IsMemberFunction && o.IsInternal == isInternal)) { - TypeReference p = overload.Parameters[i]; - string paramType = GetTypeString(p.Type, p.IsFunctionPointer); - if (p.Name == "...") { continue; } + string exportedName = overload.ExportedName; + if (exportedName.StartsWith("ig")) + { + exportedName = exportedName.Substring(2, exportedName.Length - 2); + } + if (exportedName.Contains("~")) { continue; } + if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. - if (paramType == "va_list") + bool hasVaList = false; + for (int i = 0; i < overload.Parameters.Length; i++) { - hasVaList = true; - break; + TypeReference p = overload.Parameters[i]; + string paramType = GetTypeString(p.Type, p.IsFunctionPointer); + if (p.Name == "...") { continue; } + + if (paramType == "va_list") + { + hasVaList = true; + break; + } } - } - if (hasVaList) { continue; } + if (hasVaList) { continue; } - KeyValuePair[] orderedDefaults = overload.DefaultValues.OrderByDescending( - kvp => GetIndex(overload.Parameters, kvp.Key)).ToArray(); + KeyValuePair[] orderedDefaults = overload.DefaultValues.OrderByDescending( + kvp => GetIndex(overload.Parameters, kvp.Key)).ToArray(); - for (int i = overload.DefaultValues.Count; i >= 0; i--) - { - if (overload.IsMemberFunction) { continue; } - Dictionary defaults = new Dictionary(); - for (int j = 0; j < i; j++) + for (int i = overload.DefaultValues.Count; i >= 0; i--) { - defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); + Dictionary defaults = new Dictionary(); + for (int j = 0; j < i; j++) + { + defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); + } + EmitOverload(writer, overload, defaults, null, classPrefix); } - EmitOverload(writer, overload, defaults, null, classPrefix); } } } - writer.PopBlock(); - writer.PopBlock(); } foreach (var method in defs.Variants) @@ -415,6 +481,8 @@ static void Main(string[] args) if (!variant.Used) Console.WriteLine($"Error: Variants targetting parameter {variant.Name} with type {variant.OriginalType} could not be applied to method {method.Key}."); } } + + return 0; } private static bool IsStringFieldName(string name) diff --git a/src/CodeGenerator/TypeInfo.cs b/src/CodeGenerator/TypeInfo.cs index 2f37689e..034e66ec 100644 --- a/src/CodeGenerator/TypeInfo.cs +++ b/src/CodeGenerator/TypeInfo.cs @@ -55,6 +55,17 @@ public class TypeInfo { "ImPlotFormatter", "IntPtr" }, { "ImPlotGetter", "IntPtr" }, { "ImPlotTransform", "IntPtr" }, + // internals + { "char[5]", "byte*"}, + { "ImGuiDir*", "IntPtr" }, + //{ "ImGuiStoragePair", "IntPtr" }, + { "ImGuiDockRequest", "IntPtr" }, + { "ImGuiDockNodeSettings", "IntPtr" }, + { "ImGuiTableColumnIdx", "sbyte" }, + { "ImGuiTableDrawChannelIdx", "byte"}, + { "ImGuiContextHookCallback", "IntPtr" }, + { "ImGuiErrorLogCallback", "IntPtr" }, + //{ "ImGuiSizeCallback", "IntPtr"} }; public static readonly List WellKnownEnums = new List() @@ -73,6 +84,7 @@ public class TypeInfo "ImVec2", "ImVec4", "ImGuiStoragePair", + "ImGuiStyleMod", }; public static readonly Dictionary WellKnownDefaultValues = new Dictionary() From 70a7b35459b260377b7487981b65839a02e3a8c6 Mon Sep 17 00:00:00 2001 From: Thraka Date: Wed, 23 Nov 2022 15:47:09 -0800 Subject: [PATCH 2/8] use logic that makes sense --- src/CodeGenerator/ImguiDefinitions.cs | 8 ++++---- src/CodeGenerator/Program.cs | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/CodeGenerator/ImguiDefinitions.cs b/src/CodeGenerator/ImguiDefinitions.cs index c9cc936d..0dd327fb 100644 --- a/src/CodeGenerator/ImguiDefinitions.cs +++ b/src/CodeGenerator/ImguiDefinitions.cs @@ -21,7 +21,7 @@ static int GetInt(JToken token, string key) if (v == null) return 0; return v.ToObject(); } - public void LoadFrom(string directory, bool excludeInternals = true) + public void LoadFrom(string directory, bool useInternals = false) { JObject typesJson; @@ -67,7 +67,7 @@ public void LoadFrom(string directory, bool excludeInternals = true) string name = jp.Name; bool isInternal = typeLocations?[jp.Name]?.Value().Contains("internal") ?? false; - if (excludeInternals && isInternal) + if (!useInternals && isInternal) return null; EnumMember[] elements = jp.Values().Select(v => @@ -83,7 +83,7 @@ public void LoadFrom(string directory, bool excludeInternals = true) string name = jp.Name; bool isInternal = typeLocations?[jp.Name]?.Value().Contains("internal") ?? false; - if (excludeInternals && isInternal) + if (!useInternals && isInternal) return null; TypeReference[] fields = jp.Values().Select(v => @@ -125,7 +125,7 @@ public void LoadFrom(string directory, bool excludeInternals = true) } if (friendlyName == null) { return null; } bool isInternal = val["location"]?.ToString().Contains("internal") ?? false; - if (excludeInternals && isInternal) + if (!useInternals && isInternal) return null; string exportedName = ov_cimguiname; diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index fb39deb8..b30cb68d 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -9,8 +9,6 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.CommandLine; -using System.Linq.Expressions; -using System.Runtime.CompilerServices; namespace CodeGenerator { @@ -126,7 +124,7 @@ static async Task Main(string[] args) string definitionsPath = Path.Combine(AppContext.BaseDirectory, "definitions", libraryName); var defs = new ImguiDefinitions(); - defs.LoadFrom(definitionsPath, !useInternals); + defs.LoadFrom(definitionsPath, useInternals); Console.WriteLine($"Outputting generated code files to {outputPath}."); From 2c2bc9bd74e12e57cb302d93276f57b082ffa702 Mon Sep 17 00:00:00 2001 From: Thraka Date: Fri, 22 Mar 2024 14:47:26 -0700 Subject: [PATCH 3/8] Update code to handle latest ImGui that's in the repo. --- src/CodeGenerator/CodeGenerator.csproj | 2 +- src/CodeGenerator/ImguiDefinitions.cs | 12 +- src/CodeGenerator/Program.cs | 170 +++++++++++++++++-------- src/CodeGenerator/TypeInfo.cs | 63 ++++++++- 4 files changed, 187 insertions(+), 60 deletions(-) diff --git a/src/CodeGenerator/CodeGenerator.csproj b/src/CodeGenerator/CodeGenerator.csproj index f36199ef..0781663c 100644 --- a/src/CodeGenerator/CodeGenerator.csproj +++ b/src/CodeGenerator/CodeGenerator.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/CodeGenerator/ImguiDefinitions.cs b/src/CodeGenerator/ImguiDefinitions.cs index 5cc3981f..15882ade 100644 --- a/src/CodeGenerator/ImguiDefinitions.cs +++ b/src/CodeGenerator/ImguiDefinitions.cs @@ -116,16 +116,20 @@ public void LoadFrom(string directory, bool useInternals = false) { friendlyName = "Destroy"; } - //skip internal functions + // Hunt for internal and react + bool isInternal = val["location"]?.ToString().Contains("internal") ?? false; var typename = val["stname"]?.ToString(); if (!string.IsNullOrEmpty(typename)) { - if (!Types.Any(x => x.Name == val["stname"]?.ToString())) { + TypeDefinition foundType = Types.FirstOrDefault(x => !x.IsInternal && x.Name == val["stname"]?.ToString()); + + if (foundType != null) + isInternal = foundType.IsInternal; + else return null; - } } if (friendlyName == null) { return null; } - bool isInternal = val["location"]?.ToString().Contains("internal") ?? false; + if (!useInternals && isInternal) return null; diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index 4c790fb4..30b6f72a 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -21,6 +21,7 @@ static async Task Main(string[] args) // internal vars for command line results used by the rest of the program. bool runApp = false; string outputPath = string.Empty; + string outputPathInternal = string.Empty; string libraryName = string.Empty; bool useInternals = false; @@ -72,6 +73,7 @@ static async Task Main(string[] args) rootCommand.SetHandler((outputPathValue, libNameValue, useInternalValue) => { outputPath = outputPathValue.FullName; + outputPathInternal = Path.Combine(outputPath, "Internal"); libraryName = libNameValue; useInternals = useInternalValue; @@ -127,12 +129,18 @@ static async Task Main(string[] args) defs.LoadFrom(definitionsPath, useInternals); Console.WriteLine($"Outputting generated code files to {outputPath}."); + Directory.CreateDirectory(outputPath); + if (useInternals) + { + Console.WriteLine($"Outputting internals generated code files to {outputPathInternal}."); + Directory.CreateDirectory(outputPathInternal); + } foreach (EnumDefinition ed in defs.Enums) { - using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, ed.FriendlyNames[0] + ".gen.cs"))) + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(GetOutputPath(ed.IsInternal), ed.FriendlyNames[0] + ".gen.cs"))) { - writer.PushBlock($"namespace {projectNamespace}"); + writer.PushBlock($"namespace {projectNamespace}{(ed.IsInternal ? InternalNamespace : string.Empty)}"); if (ed.FriendlyNames[0].Contains("Flags")) { writer.WriteLine("[System.Flags]"); @@ -152,8 +160,9 @@ static async Task Main(string[] args) foreach (TypeDefinition td in defs.Types) { if (TypeInfo.CustomDefinedTypes.Contains(td.Name)) { continue; } + if (TypeInfo.ScratchedTypes.Contains(td.Name)) { continue; } - using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, td.Name + ".gen.cs"))) + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(GetOutputPath(td.IsInternal), td.Name + ".gen.cs"))) { writer.Using("System"); writer.Using("System.Numerics"); @@ -171,6 +180,9 @@ static async Task Main(string[] args) { string typeStr = GetTypeString(field.Type, field.IsFunctionPointer); + if (TypeInfo.SkippedMembers.Contains($"{td.Name}.{field.Name}")) { continue; } + if (TypeInfo.ScratchedTypes.Contains(field.Type)) { continue; } + if (field.ArraySize != 0) { if (TypeInfo.LegalFixedTypes.Contains(typeStr)) @@ -206,6 +218,9 @@ static async Task Main(string[] args) string typeStr = GetTypeString(field.Type, field.IsFunctionPointer); string rawType = typeStr; + if (TypeInfo.SkippedMembers.Contains($"{ptrTypeName}.{field.Name}")) { continue; } + if (TypeInfo.ScratchedTypes.Contains(field.Type)) { continue; } + if (TypeInfo.WellKnownFieldReplacements.TryGetValue(field.Type, out string wellKnownFieldType)) { typeStr = wellKnownFieldType; @@ -278,6 +293,9 @@ static async Task Main(string[] args) continue; } + if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } + if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } + string exportedName = overload.ExportedName; if (exportedName.StartsWith("ig")) { @@ -321,6 +339,7 @@ static async Task Main(string[] args) } } + // Root ImGuiNative declarations - NonInternal using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, $"{classPrefix}Native.gen.cs"))) { writer.Using("System"); @@ -330,17 +349,44 @@ static async Task Main(string[] args) { writer.Using("ImGuiNET"); } - if (useInternals) - { - writer.Using($"{projectNamespace}{InternalNamespace}"); - } writer.WriteLine(string.Empty); writer.PushBlock($"namespace {projectNamespace}"); writer.PushBlock($"public static unsafe partial class {classPrefix}Native"); + EmitImGuiNativeFunctions(writer, false); + writer.PopBlock(); + writer.PopBlock(); + } + + // Root ImGuiNative declarations - Internal + if (useInternals) + { + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPathInternal, $"{classPrefix}Native.gen.cs"))) + { + writer.Using("System"); + writer.Using("System.Numerics"); + writer.Using("System.Runtime.InteropServices"); + if (referencesImGui) + { + writer.Using("ImGuiNET"); + } + writer.Using($"{projectNamespace}{InternalNamespace}"); + writer.WriteLine(string.Empty); + writer.PushBlock($"namespace {projectNamespace}"); + writer.PushBlock($"public static unsafe partial class {classPrefix}Native"); + EmitImGuiNativeFunctions(writer, true); + writer.PopBlock(); + writer.PopBlock(); + } + } + + // Function referenced by the non-internals and internals when building the appropriate ImGuiNative declarations + void EmitImGuiNativeFunctions(CSharpCodeWriter writer, bool isInternal) + { foreach (FunctionDefinition fd in defs.Functions) { foreach (OverloadDefinition overload in fd.Overloads) { + if (overload.IsInternal != isInternal) { continue; } string exportedName = overload.ExportedName; if (exportedName.Contains("~")) { continue; } if (exportedName.Contains("ImVector_")) { continue; } @@ -348,6 +394,9 @@ static async Task Main(string[] args) if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. + if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } + if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } + string ret = GetTypeString(overload.ReturnType, false); bool hasVaList = false; @@ -393,8 +442,6 @@ static async Task Main(string[] args) writer.WriteLine($"public static extern {ret} {methodName}({parameters});"); } } - writer.PopBlock(); - writer.PopBlock(); } // Root ImGui* class items - Noninternal @@ -411,68 +458,85 @@ static async Task Main(string[] args) writer.WriteLine(string.Empty); writer.PushBlock($"namespace {projectNamespace}"); writer.PushBlock($"public static unsafe partial class {classPrefix}"); - EmitFunctions(false); + EmitImGuiFunctions(writer, false); writer.PopBlock(); writer.PopBlock(); + } - if (useInternals) + // Root ImGui* class items - Internal + if (useInternals) + { + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPathInternal, $"{classPrefix}.gen.cs"))) { + writer.Using("System"); + writer.Using("System.Numerics"); + writer.Using("System.Runtime.InteropServices"); + writer.Using("System.Text"); + if (referencesImGui) + { + writer.Using("ImGuiNET"); + } + writer.WriteLine(string.Empty); writer.PushBlock($"namespace {projectNamespace}{InternalNamespace}"); writer.PushBlock($"public static unsafe partial class {classPrefix}"); - EmitFunctions(true); + EmitImGuiFunctions(writer, true); writer.PopBlock(); writer.PopBlock(); } + } - void EmitFunctions(bool isInternal) + // Function referenced by the non-internals and internals when building the appropriate ImGui class + void EmitImGuiFunctions(CSharpCodeWriter writer, bool isInternal) + { + foreach (FunctionDefinition fd in defs.Functions) { - foreach (FunctionDefinition fd in defs.Functions) + if (TypeInfo.SkippedFunctions.Contains(fd.Name)) { continue; } + + foreach (OverloadDefinition overload in fd.Overloads.Where(o => !o.IsMemberFunction && o.IsInternal == isInternal)) { - if (TypeInfo.SkippedFunctions.Contains(fd.Name)) { continue; } + string exportedName = overload.ExportedName; + if (exportedName.StartsWith("ig")) + { + exportedName = exportedName.Substring(2, exportedName.Length - 2); + } + if (exportedName.Contains("~")) { continue; } + if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. + if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } + if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } - foreach (OverloadDefinition overload in fd.Overloads.Where(o => !o.IsMemberFunction && o.IsInternal == isInternal)) + if ((overload.FriendlyName == "GetID" || overload.FriendlyName == "PushID") && overload.Parameters.Length > 1) { - string exportedName = overload.ExportedName; - if (exportedName.StartsWith("ig")) - { - exportedName = exportedName.Substring(2, exportedName.Length - 2); - } - if (exportedName.Contains("~")) { continue; } - if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. + // skip ImGui.Get/PushID(start, end) overloads as they would overlap with existing + continue; + } - if ((overload.FriendlyName == "GetID" || overload.FriendlyName == "PushID") && overload.Parameters.Length > 1) - { - // skip ImGui.Get/PushID(start, end) overloads as they would overlap with existing - continue; - } - - bool hasVaList = false; - for (int i = 0; i < overload.Parameters.Length; i++) - { - TypeReference p = overload.Parameters[i]; - string paramType = GetTypeString(p.Type, p.IsFunctionPointer); - if (p.Name == "...") { continue; } - if (paramType == "va_list") - { - hasVaList = true; - break; - } + bool hasVaList = false; + for (int i = 0; i < overload.Parameters.Length; i++) + { + TypeReference p = overload.Parameters[i]; + string paramType = GetTypeString(p.Type, p.IsFunctionPointer); + if (p.Name == "...") { continue; } + + if (paramType == "va_list") + { + hasVaList = true; + break; } - if (hasVaList) { continue; } + } + if (hasVaList) { continue; } - KeyValuePair[] orderedDefaults = overload.DefaultValues.OrderByDescending( - kvp => GetIndex(overload.Parameters, kvp.Key)).ToArray(); + KeyValuePair[] orderedDefaults = overload.DefaultValues.OrderByDescending( + kvp => GetIndex(overload.Parameters, kvp.Key)).ToArray(); - for (int i = overload.DefaultValues.Count; i >= 0; i--) + for (int i = overload.DefaultValues.Count; i >= 0; i--) + { + Dictionary defaults = new Dictionary(); + for (int j = 0; j < i; j++) { - Dictionary defaults = new Dictionary(); - for (int j = 0; j < i; j++) - { - defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); - } - EmitOverload(writer, overload, defaults, null, classPrefix); + defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); } + EmitOverload(writer, overload, defaults, null, classPrefix); } } } @@ -487,6 +551,12 @@ void EmitFunctions(bool isInternal) } return 0; + + // Helper to determine the path + string GetOutputPath(bool isInternal) + { + return isInternal ? outputPathInternal : outputPath; + } } private static bool IsStringFieldName(string name) diff --git a/src/CodeGenerator/TypeInfo.cs b/src/CodeGenerator/TypeInfo.cs index 986d529f..3209ced5 100644 --- a/src/CodeGenerator/TypeInfo.cs +++ b/src/CodeGenerator/TypeInfo.cs @@ -22,6 +22,7 @@ public class TypeInfo { "ImS64", "long" }, { "unsigned short", "ushort" }, { "unsigned int", "uint" }, + { "ImVec1", "float" }, { "ImVec2", "Vector2" }, { "ImVec2_Simple", "Vector2" }, { "ImVec3", "Vector3" }, @@ -66,12 +67,15 @@ public class TypeInfo { "ImGuiTableDrawChannelIdx", "byte"}, { "ImGuiContextHookCallback", "IntPtr" }, { "ImGuiErrorLogCallback", "IntPtr" }, + { "ImGuiSelectionUserData", "ulong" }, //ImU64 + { "ImGuiKeyRoutingIndex", "short" } //ImS16 //{ "ImGuiSizeCallback", "IntPtr"} }; public static readonly List WellKnownEnums = new List() { - "ImGuiMouseButton" + "ImGuiMouseButton", + "ImGuiDir" }; public static readonly Dictionary AlternateEnumPrefixes = new Dictionary() @@ -81,7 +85,7 @@ public class TypeInfo public static readonly Dictionary AlternateEnumPrefixSubstitutions = new Dictionary() { - { "ImGuiMod_", "Mod" }, + { "ImGuiMod_", "Mod" } }; public static readonly Dictionary WellKnownFieldReplacements = new Dictionary() @@ -92,10 +96,10 @@ public class TypeInfo public static readonly HashSet CustomDefinedTypes = new HashSet() { "ImVector", + "ImVec1", "ImVec2", "ImVec4", "ImGuiStoragePair", - "ImGuiStyleMod", }; public static readonly Dictionary WellKnownDefaultValues = new Dictionary() @@ -117,10 +121,11 @@ public class TypeInfo { "ImPlotPoint(0,0)", "new ImPlotPoint { x = 0, y = 0 }" }, { "ImPlotPoint(1,1)", "new ImPlotPoint { x = 1, y = 1 }" }, { "ImDrawCornerFlags_All", "ImDrawCornerFlags.All" }, + { "ImGuiCond_Once", "ImGuiCond.Once"}, + { "ImGuiTypingSelectFlags_None", "ImGuiTypingSelectFlags.None" }, { "ImPlotFlags_None", "ImPlotFlags.None"}, { "ImPlotAxisFlags_None", "ImPlotAxisFlags.None"}, { "ImPlotAxisFlags_NoGridLines", "ImPlotAxisFlags.NoGridLines"}, - { "ImGuiCond_Once", "ImGuiCond.Once"}, { "ImPlotOrientation_Vertical", "ImPlotOrientation.Vertical"}, { "PinShape_CircleFilled", "PinShape.CircleFilled"}, { "ImGuiPopupFlags_None", "ImGuiPopupFlags.None"}, @@ -149,6 +154,7 @@ public class TypeInfo { "in", "@in" }, { "out", "@out" }, { "ref", "@ref" }, + { "base", "@base" } }; public static readonly HashSet LegalFixedTypes = new HashSet() @@ -166,11 +172,58 @@ public class TypeInfo "double", }; + public static readonly HashSet ScratchedTypes = new HashSet() + { + "ImGuiStyleMod", + "ImGuiStyleMod*", + "ImGuiInputEvent", + "ImGuiInputEvent*", + "ImGuiDockNode", + "ImGuiDockNode*", + "ImDrawDataBuilder", + "ImDrawDataBuilder*", + "ImGuiTable", + "ImGuiTable*", + "ImGuiInputEvent", + "ImGuiInputEvent*", + }; + public static readonly HashSet SkippedFunctions = new HashSet() { "igInputText", "igInputTextMultiline", - "igInputTextWithHint" + "igInputTextWithHint", + "igFindBestWindowPosForPopupEx", + + // Table related + "igDebugNodeTable", + "igGetCurrentTable" + }; + + public static readonly HashSet SkippedMembers = new HashSet() + { + "ImGuiContextPtr.StyleVarStack", + "ImGuiContextPtr.SettingsWindows", + "ImGuiContextPtr.SettingsTables", + "ImGuiContextPtr.ItemFlagsStack", + "ImGuiContextPtr.Tables", + "ImGuiContextPtr.TabBars", + "ImGuiContextPtr.LocalizationTable", + "ImGuiContextPtr.InputEventsQueue", + "ImGuiContextPtr.InputEventsTrail", + "ImGuiContextPtr.DrawChannelsTempMergeBuffer", + + "ImGuiContext.StyleVarStack", + "ImGuiContext.SettingsWindows", + "ImGuiContext.SettingsTables", + "ImGuiContext.ItemFlagsStack", + "ImGuiContext.Tables", + "ImGuiContext.TabBars", + "ImGuiContext.InputEventsQueue", + "ImGuiContext.InputEventsTrail", + "ImGuiContext.DrawChannelsTempMergeBuffer", + + "ImGuiViewportPPtr.BgFgDrawLists", }; } } \ No newline at end of file From 5c45b25c77e7558492547bbcbc4fc3ad068448d9 Mon Sep 17 00:00:00 2001 From: Thraka Date: Fri, 22 Mar 2024 15:31:08 -0700 Subject: [PATCH 4/8] Revert some of my changes now that I understand a bit more. --- src/CodeGenerator/Program.cs | 13 ---------- src/CodeGenerator/TypeInfo.cs | 48 ++++------------------------------- 2 files changed, 5 insertions(+), 56 deletions(-) diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index 30b6f72a..16b44e57 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -160,7 +160,6 @@ static async Task Main(string[] args) foreach (TypeDefinition td in defs.Types) { if (TypeInfo.CustomDefinedTypes.Contains(td.Name)) { continue; } - if (TypeInfo.ScratchedTypes.Contains(td.Name)) { continue; } using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(GetOutputPath(td.IsInternal), td.Name + ".gen.cs"))) { @@ -180,9 +179,6 @@ static async Task Main(string[] args) { string typeStr = GetTypeString(field.Type, field.IsFunctionPointer); - if (TypeInfo.SkippedMembers.Contains($"{td.Name}.{field.Name}")) { continue; } - if (TypeInfo.ScratchedTypes.Contains(field.Type)) { continue; } - if (field.ArraySize != 0) { if (TypeInfo.LegalFixedTypes.Contains(typeStr)) @@ -219,7 +215,6 @@ static async Task Main(string[] args) string rawType = typeStr; if (TypeInfo.SkippedMembers.Contains($"{ptrTypeName}.{field.Name}")) { continue; } - if (TypeInfo.ScratchedTypes.Contains(field.Type)) { continue; } if (TypeInfo.WellKnownFieldReplacements.TryGetValue(field.Type, out string wellKnownFieldType)) { @@ -293,9 +288,6 @@ static async Task Main(string[] args) continue; } - if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } - if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } - string exportedName = overload.ExportedName; if (exportedName.StartsWith("ig")) { @@ -394,9 +386,6 @@ void EmitImGuiNativeFunctions(CSharpCodeWriter writer, bool isInternal) if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. - if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } - if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } - string ret = GetTypeString(overload.ReturnType, false); bool hasVaList = false; @@ -501,8 +490,6 @@ void EmitImGuiFunctions(CSharpCodeWriter writer, bool isInternal) } if (exportedName.Contains("~")) { continue; } if (overload.Parameters.Any(tr => tr.Type.Contains('('))) { continue; } // TODO: Parse function pointer parameters. - if (overload.Parameters.Any(tr => TypeInfo.ScratchedTypes.Contains(tr.Type))) { continue; } - if (TypeInfo.ScratchedTypes.Contains(overload.ReturnType)) { continue; } if ((overload.FriendlyName == "GetID" || overload.FriendlyName == "PushID") && overload.Parameters.Length > 1) { diff --git a/src/CodeGenerator/TypeInfo.cs b/src/CodeGenerator/TypeInfo.cs index 3209ced5..0b4194aa 100644 --- a/src/CodeGenerator/TypeInfo.cs +++ b/src/CodeGenerator/TypeInfo.cs @@ -172,58 +172,20 @@ public class TypeInfo "double", }; - public static readonly HashSet ScratchedTypes = new HashSet() - { - "ImGuiStyleMod", - "ImGuiStyleMod*", - "ImGuiInputEvent", - "ImGuiInputEvent*", - "ImGuiDockNode", - "ImGuiDockNode*", - "ImDrawDataBuilder", - "ImDrawDataBuilder*", - "ImGuiTable", - "ImGuiTable*", - "ImGuiInputEvent", - "ImGuiInputEvent*", - }; - public static readonly HashSet SkippedFunctions = new HashSet() { "igInputText", "igInputTextMultiline", "igInputTextWithHint", - "igFindBestWindowPosForPopupEx", - - // Table related - "igDebugNodeTable", - "igGetCurrentTable" }; public static readonly HashSet SkippedMembers = new HashSet() { - "ImGuiContextPtr.StyleVarStack", - "ImGuiContextPtr.SettingsWindows", - "ImGuiContextPtr.SettingsTables", - "ImGuiContextPtr.ItemFlagsStack", - "ImGuiContextPtr.Tables", - "ImGuiContextPtr.TabBars", - "ImGuiContextPtr.LocalizationTable", - "ImGuiContextPtr.InputEventsQueue", - "ImGuiContextPtr.InputEventsTrail", - "ImGuiContextPtr.DrawChannelsTempMergeBuffer", - - "ImGuiContext.StyleVarStack", - "ImGuiContext.SettingsWindows", - "ImGuiContext.SettingsTables", - "ImGuiContext.ItemFlagsStack", - "ImGuiContext.Tables", - "ImGuiContext.TabBars", - "ImGuiContext.InputEventsQueue", - "ImGuiContext.InputEventsTrail", - "ImGuiContext.DrawChannelsTempMergeBuffer", - - "ImGuiViewportPPtr.BgFgDrawLists", + // This can be used to rip members out of internal when you simply want to exclude them. + // You must be careful when using this to not mess with data structures that are used + // by ImGui + // Add an entry for the type.name, such as: + // "ImGuiContextPtr.StyleVarStack" }; } } \ No newline at end of file From 10f5f9024acefad423ee18a2588ac97c6aaad0b8 Mon Sep 17 00:00:00 2001 From: Thraka Date: Fri, 22 Mar 2024 15:56:50 -0700 Subject: [PATCH 5/8] Create default directory if not passed; add launchsettings. --- src/CodeGenerator/Program.cs | 5 +-- .../Properties/launchSettings.json | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/CodeGenerator/Properties/launchSettings.json diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index 16b44e57..3c636638 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -32,7 +32,7 @@ static async Task Main(string[] args) parseArgument: result => { if (result.Tokens.Count == 0) - return new DirectoryInfo(AppContext.BaseDirectory); + return Directory.CreateDirectory(Path.Combine(AppContext.BaseDirectory, "Generated")); string value = result.Tokens.Single().Value; @@ -128,8 +128,9 @@ static async Task Main(string[] args) var defs = new ImguiDefinitions(); defs.LoadFrom(definitionsPath, useInternals); + // Directory should be created by the optionOutputPath command parser Console.WriteLine($"Outputting generated code files to {outputPath}."); - Directory.CreateDirectory(outputPath); + if (useInternals) { Console.WriteLine($"Outputting internals generated code files to {outputPathInternal}."); diff --git a/src/CodeGenerator/Properties/launchSettings.json b/src/CodeGenerator/Properties/launchSettings.json new file mode 100644 index 00000000..fdb2be9e --- /dev/null +++ b/src/CodeGenerator/Properties/launchSettings.json @@ -0,0 +1,36 @@ +{ + "profiles": { + "CodeGenerator - ImGui": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImGui.NET\\Generated -l cimgui" + }, + "CodeGenerator - ImPlot": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImPlot.NET\\Generated -l cimplot" + }, + "CodeGenerator - ImNodes": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImNodes.NET\\Generated -l cimnodes" + }, + "CodeGenerator - ImGuizmo": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImGuizmo.NET\\Generated -l cimguizmo" + }, + "CodeGenerator (internal) - ImGui": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImGui.NET\\Generated -l cimgui --internal" + }, + "CodeGenerator (internal) - ImPlot": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImPlot.NET\\Generated -l cimplot --internal" + }, + "CodeGenerator (internal) - ImNodes": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImNodes.NET\\Generated -l cimnodes --internal" + }, + "CodeGenerator (internal) - ImGuizmo": { + "commandName": "Project", + "commandLineArgs": "-o ..\\..\\..\\..\\src\\ImGuizmo.NET\\Generated -l cimguizmo --internal" + } + } +} \ No newline at end of file From d503ac0d60acc0b7d6b69391ab1b4f5b6d47634c Mon Sep 17 00:00:00 2001 From: Thraka Date: Sat, 23 Mar 2024 14:22:47 -0700 Subject: [PATCH 6/8] CHECK MY WORK! Fixed the RangeAcc invalid to typePtr versions --- src/CodeGenerator/Program.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index 3c636638..e3fc27eb 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -225,7 +225,17 @@ static async Task Main(string[] args) if (field.ArraySize != 0) { string addrTarget = TypeInfo.LegalFixedTypes.Contains(rawType) ? $"NativePtr->{field.Name}" : $"&NativePtr->{field.Name}_0"; - writer.WriteLine($"public RangeAccessor<{typeStr}> {field.Name} => new RangeAccessor<{typeStr}>({addrTarget}, {field.ArraySize});"); + if (typeStr.Contains("*")) + { + if (GetWrappedType(typeStr, out string wrappedTypeName)) + { + writer.WriteLine($"public RangeAccessor<{wrappedTypeName}> {field.Name} => new RangeAccessor<{wrappedTypeName}>({addrTarget}, {field.ArraySize});"); + } + else + throw new Exception("Expected to wrap type, but wrapped type not found"); + } + else + writer.WriteLine($"public RangeAccessor<{typeStr}> {field.Name} => new RangeAccessor<{typeStr}>({addrTarget}, {field.ArraySize});"); } else if (typeStr.Contains("ImVector")) { From 4a45326b6224cd8e230f15e7fedc0f57548aefa0 Mon Sep 17 00:00:00 2001 From: Thraka Date: Sat, 23 Mar 2024 15:05:27 -0700 Subject: [PATCH 7/8] CHECK MY WORK! Fixed the RangeAcc to check LegalFixedTypes and correct. --- src/CodeGenerator/Program.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index e3fc27eb..1645bd4d 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -231,6 +231,11 @@ static async Task Main(string[] args) { writer.WriteLine($"public RangeAccessor<{wrappedTypeName}> {field.Name} => new RangeAccessor<{wrappedTypeName}>({addrTarget}, {field.ArraySize});"); } + + // Try best to hit the primitive pointers + else if (TypeInfo.LegalFixedTypes.Contains(typeStr[0..^1])) + writer.WriteLine($"public RangeAccessor<{typeStr[0..^1]}> {field.Name} => new RangeAccessor<{typeStr[0..^1]}>({addrTarget}, {field.ArraySize});"); + else throw new Exception("Expected to wrap type, but wrapped type not found"); } From 02a1a7ff97c975e56bea992ccdd28833d4b40bb0 Mon Sep 17 00:00:00 2001 From: Thraka Date: Sat, 23 Mar 2024 15:05:47 -0700 Subject: [PATCH 8/8] Fixed logic flaw on finding internal types in definitions file --- src/CodeGenerator/ImguiDefinitions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CodeGenerator/ImguiDefinitions.cs b/src/CodeGenerator/ImguiDefinitions.cs index 15882ade..337f8d0b 100644 --- a/src/CodeGenerator/ImguiDefinitions.cs +++ b/src/CodeGenerator/ImguiDefinitions.cs @@ -121,7 +121,7 @@ public void LoadFrom(string directory, bool useInternals = false) var typename = val["stname"]?.ToString(); if (!string.IsNullOrEmpty(typename)) { - TypeDefinition foundType = Types.FirstOrDefault(x => !x.IsInternal && x.Name == val["stname"]?.ToString()); + TypeDefinition foundType = Types.FirstOrDefault(x => x.Name == val["stname"]?.ToString()); if (foundType != null) isInternal = foundType.IsInternal;