From 02a838f88f8689068b70a3a709758acb6d8510b8 Mon Sep 17 00:00:00 2001 From: Alex Hildebrand Date: Sat, 28 Nov 2020 22:58:17 +0100 Subject: [PATCH] Preparing code generator for ImPlot, ImNodes and ImGuizmo code generation --- src/CodeGenerator/CodeGenerator.csproj | 19 +++- src/CodeGenerator/ImguiDefinitions.cs | 7 +- src/CodeGenerator/Program.cs | 98 +++++++++++++------ src/CodeGenerator/TypeInfo.cs | 36 ++++++- .../{ => definitions/cimgui}/definitions.json | 0 .../cimgui}/structs_and_enums.json | 0 .../{ => definitions/cimgui}/variants.json | 0 7 files changed, 123 insertions(+), 37 deletions(-) rename src/CodeGenerator/{ => definitions/cimgui}/definitions.json (100%) rename src/CodeGenerator/{ => definitions/cimgui}/structs_and_enums.json (100%) rename src/CodeGenerator/{ => definitions/cimgui}/variants.json (100%) diff --git a/src/CodeGenerator/CodeGenerator.csproj b/src/CodeGenerator/CodeGenerator.csproj index 78613cf..5d22d8f 100644 --- a/src/CodeGenerator/CodeGenerator.csproj +++ b/src/CodeGenerator/CodeGenerator.csproj @@ -6,13 +6,24 @@ - - - + + + + + + + + + + + + + + + - diff --git a/src/CodeGenerator/ImguiDefinitions.cs b/src/CodeGenerator/ImguiDefinitions.cs index 7e8e9e7..7cc75af 100644 --- a/src/CodeGenerator/ImguiDefinitions.cs +++ b/src/CodeGenerator/ImguiDefinitions.cs @@ -41,7 +41,7 @@ namespace CodeGenerator JObject variantsJson = null; if (File.Exists(Path.Combine(directory, "variants.json"))) { - using (StreamReader fs = File.OpenText(Path.Combine(AppContext.BaseDirectory, "variants.json"))) + using (StreamReader fs = File.OpenText(Path.Combine(directory, "variants.json"))) using (JsonTextReader jr = new JsonTextReader(fs)) { variantsJson = JObject.Load(jr); @@ -275,6 +275,9 @@ namespace CodeGenerator ret = ret.Substring(0, ret.Length - 1); } + if (Char.IsDigit(ret.First())) + ret = "_" + ret; + return ret; } } @@ -368,7 +371,7 @@ namespace CodeGenerator TypeVariants = typeVariants; - IsEnum = enums.Any(t => t.Name == type || t.FriendlyName == type); + IsEnum = enums.Any(t => t.Name == type || t.FriendlyName == type || TypeInfo.WellKnownEnums.Contains(type)); } private int ParseSizeString(string sizePart, EnumDefinition[] enums) diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index ba3f057..48da5a9 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -24,17 +24,55 @@ namespace CodeGenerator { outputPath = AppContext.BaseDirectory; } + + string libraryName; + if (args.Length > 1) + { + libraryName = args[1]; + } + else + { + libraryName = "cimgui"; + } + + string projectNamespace = libraryName switch + { + "cimgui" => "ImGuiNET", + "cimplot" => "ImGuiNET", + "cimnodes" => "ImGuiNET", + "cimguizmo" => "ImGuiNET", + _ => throw new NotImplementedException() + }; + + string classPrefix = libraryName switch + { + "cimgui" => "ImGui", + "cimplot" => "ImPlot", + "cimnodes" => "ImNodes", + "cimguizmo" => "ImGuizmo", + _ => throw new NotImplementedException() + }; + + string dllName = libraryName switch + { + "cimgui" => "cimgui", + "cimplot" => "cimgui", + "cimnodes" => "cimgui", + "cimguizmo" => "cimgui", + _ => throw new NotImplementedException() + }; + string definitionsPath = Path.Combine(AppContext.BaseDirectory, "definitions", libraryName); var defs = new ImguiDefinitions(); - defs.LoadFrom(AppContext.BaseDirectory); - + defs.LoadFrom(definitionsPath); + Console.WriteLine($"Outputting generated code files to {outputPath}."); foreach (EnumDefinition ed in defs.Enums) { using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, ed.FriendlyName + ".gen.cs"))) { - writer.PushBlock("namespace ImGuiNET"); + writer.PushBlock($"namespace {projectNamespace}"); if (ed.FriendlyName.Contains("Flags")) { writer.WriteLine("[System.Flags]"); @@ -62,7 +100,7 @@ namespace CodeGenerator writer.Using("System.Runtime.CompilerServices"); writer.Using("System.Text"); writer.WriteLine(string.Empty); - writer.PushBlock("namespace ImGuiNET"); + writer.PushBlock($"namespace {projectNamespace}"); writer.PushBlock($"public unsafe partial struct {td.Name}"); foreach (TypeReference field in td.Fields) @@ -209,7 +247,7 @@ namespace CodeGenerator { defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); } - EmitOverload(writer, overload, defaults, "NativePtr"); + EmitOverload(writer, overload, defaults, "NativePtr", classPrefix); } } } @@ -219,14 +257,14 @@ namespace CodeGenerator } } - using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, "ImGuiNative.gen.cs"))) + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, $"{classPrefix}Native.gen.cs"))) { writer.Using("System"); writer.Using("System.Numerics"); writer.Using("System.Runtime.InteropServices"); writer.WriteLine(string.Empty); - writer.PushBlock("namespace ImGuiNET"); - writer.PushBlock("public static unsafe partial class ImGuiNative"); + writer.PushBlock($"namespace {projectNamespace}"); + writer.PushBlock($"public static unsafe partial class {classPrefix}Native"); foreach (FunctionDefinition fd in defs.Functions) { foreach (OverloadDefinition overload in fd.Overloads) @@ -273,12 +311,12 @@ namespace CodeGenerator if (isUdtVariant) { - writer.WriteLine($"[DllImport(\"cimgui\", CallingConvention = CallingConvention.Cdecl, EntryPoint = \"{exportedName}\")]"); + writer.WriteLine($"[DllImport(\"{dllName}\", CallingConvention = CallingConvention.Cdecl, EntryPoint = \"{exportedName}\")]"); } else { - writer.WriteLine("[DllImport(\"cimgui\", CallingConvention = CallingConvention.Cdecl)]"); + writer.WriteLine($"[DllImport(\"{dllName}\", CallingConvention = CallingConvention.Cdecl)]"); } writer.WriteLine($"public static extern {ret} {methodName}({parameters});"); } @@ -287,15 +325,15 @@ namespace CodeGenerator writer.PopBlock(); } - using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, "ImGui.gen.cs"))) + using (CSharpCodeWriter writer = new CSharpCodeWriter(Path.Combine(outputPath, $"{classPrefix}.gen.cs"))) { writer.Using("System"); writer.Using("System.Numerics"); writer.Using("System.Runtime.InteropServices"); writer.Using("System.Text"); writer.WriteLine(string.Empty); - writer.PushBlock("namespace ImGuiNET"); - writer.PushBlock("public static unsafe partial class ImGui"); + writer.PushBlock($"namespace {projectNamespace}"); + writer.PushBlock($"public static unsafe partial class {classPrefix}"); foreach (FunctionDefinition fd in defs.Functions) { if (TypeInfo.SkippedFunctions.Contains(fd.Name)) { continue; } @@ -336,7 +374,7 @@ namespace CodeGenerator { defaults.Add(orderedDefaults[j].Key, orderedDefaults[j].Value); } - EmitOverload(writer, overload, defaults, null); + EmitOverload(writer, overload, defaults, null, classPrefix); } } } @@ -381,7 +419,8 @@ namespace CodeGenerator CSharpCodeWriter writer, OverloadDefinition overload, Dictionary defaultValues, - string selfName) + string selfName, + string classPrefix) { if (overload.Parameters.Where(tr => tr.Name.EndsWith("_begin") || tr.Name.EndsWith("_end")) .Any(tr => !defaultValues.ContainsKey(tr.Name))) @@ -481,6 +520,15 @@ namespace CodeGenerator postCallLines.Add($"}}"); } } + else if (defaultValues.TryGetValue(tr.Name, out string defaultVal)) + { + if (!CorrectDefaultValue(defaultVal, tr, out string correctedDefault)) + { + correctedDefault = defaultVal; + } + marshalledParameters[i] = new MarshalledParameter(nativeTypeName, false, correctedIdentifier, true); + preCallLines.Add($"{nativeTypeName} {correctedIdentifier} = {correctedDefault};"); + } else if (tr.Type == "char* []") { string nativeArgName = "native_" + tr.Name; @@ -518,15 +566,6 @@ namespace CodeGenerator preCallLines.Add($" offset += {correctedIdentifier}_byteCounts[i] + 1;"); preCallLines.Add("}"); } - else if (defaultValues.TryGetValue(tr.Name, out string defaultVal)) - { - if (!CorrectDefaultValue(defaultVal, tr, out string correctedDefault)) - { - correctedDefault = defaultVal; - } - marshalledParameters[i] = new MarshalledParameter(nativeTypeName, false, correctedIdentifier, true); - preCallLines.Add($"{nativeTypeName} {correctedIdentifier} = {correctedDefault};"); - } else if (tr.Type == "bool") { string nativeArgName = "native_" + tr.Name; @@ -557,7 +596,7 @@ namespace CodeGenerator marshalledParameters[i] = new MarshalledParameter(wrappedParamType, false, nativeArgName, false); preCallLines.Add($"{tr.Type} {nativeArgName} = {correctedIdentifier}.NativePtr;"); } - else if ((tr.Type.EndsWith("*") || tr.Type.Contains("[") || tr.Type.EndsWith("&")) && tr.Type != "void*" && tr.Type != "ImGuiContext*") + else if ((tr.Type.EndsWith("*") || tr.Type.Contains("[") || tr.Type.EndsWith("&")) && tr.Type != "void*" && tr.Type != "ImGuiContext*" && tr.Type != "ImPlotContext*"&& tr.Type != "EditorContext*") { string nonPtrType; if (tr.Type.Contains("[")) @@ -634,7 +673,7 @@ namespace CodeGenerator targetName = targetName.Substring(0, targetName.IndexOf("_nonUDT")); } - writer.WriteLine($"{ret}ImGuiNative.{targetName}({nativeInvocationStr});"); + writer.WriteLine($"{ret}{classPrefix}Native.{targetName}({nativeInvocationStr});"); foreach (string line in postCallLines) { @@ -736,7 +775,7 @@ namespace CodeGenerator private static bool CorrectDefaultValue(string defaultVal, TypeReference tr, out string correctedDefault) { - if (tr.Type == "ImGuiContext*") + if (tr.Type == "ImGuiContext*" || tr.Type == "ImPlotContext*" || tr.Type == "EditorContext*") { correctedDefault = "IntPtr.Zero"; return true; @@ -754,7 +793,10 @@ namespace CodeGenerator if (tr.IsEnum) { - correctedDefault = $"({tr.Type}){defaultVal}"; + if (defaultVal.StartsWith("-")) + correctedDefault = $"({tr.Type})({defaultVal})"; + else + correctedDefault = $"({tr.Type}){defaultVal}"; return true; } diff --git a/src/CodeGenerator/TypeInfo.cs b/src/CodeGenerator/TypeInfo.cs index b4f94b4..ce578fa 100644 --- a/src/CodeGenerator/TypeInfo.cs +++ b/src/CodeGenerator/TypeInfo.cs @@ -14,7 +14,12 @@ namespace CodeGenerator { "ImFileHandle", "IntPtr" }, { "ImU8", "byte" }, { "ImS8", "sbyte" }, + { "ImU16", "ushort" }, + { "ImS16", "short" }, + { "ImU32", "uint" }, + { "ImS32", "int" }, { "ImU64", "ulong" }, + { "ImS64", "long" }, { "unsigned short", "ushort" }, { "unsigned int", "uint" }, { "ImVec2", "Vector2" }, @@ -29,10 +34,11 @@ namespace CodeGenerator { "ImDrawIdx", "ushort" }, { "ImDrawListSharedData", "IntPtr" }, { "ImDrawListSharedData*", "IntPtr" }, - { "ImU32", "uint" }, { "ImDrawCallback", "IntPtr" }, { "size_t", "uint" }, { "ImGuiContext*", "IntPtr" }, + { "ImPlotContext*", "IntPtr" }, + { "EditorContext*", "IntPtr" }, { "float[2]", "Vector2*" }, { "float[3]", "Vector3*" }, { "float[4]", "Vector4*" }, @@ -44,7 +50,12 @@ namespace CodeGenerator { "char* []", "byte**" }, { "unsigned char[256]", "byte*"}, }; - + + public static readonly List WellKnownEnums = new List() + { + "ImGuiMouseButton" + }; + public static readonly Dictionary WellKnownFieldReplacements = new Dictionary() { { "bool", "bool" }, // Force bool to remain as bool in type-safe wrappers. @@ -62,6 +73,8 @@ namespace CodeGenerator { { "((void *)0)", "null" }, { "((void*)0)", "null" }, + { "NULL", "null"}, + { "nullptr", "null"}, { "ImVec2(0,0)", "new Vector2()" }, { "ImVec2(-1,0)", "new Vector2(-1, 0)" }, { "ImVec2(1,0)", "new Vector2(1, 0)" }, @@ -69,9 +82,26 @@ namespace CodeGenerator { "ImVec2(0,1)", "new Vector2(0, 1)" }, { "ImVec4(0,0,0,0)", "new Vector4()" }, { "ImVec4(1,1,1,1)", "new Vector4(1, 1, 1, 1)" }, + { "ImVec4(0,0,0,-1)", "new Vector4(0, 0, 0, -1)" }, + { "ImPlotPoint(0,0)", "new ImPlotPoint { x = 0, y = 0 }" }, + { "ImPlotPoint(1,1)", "new ImPlotPoint { x = 1, y = 1 }" }, { "ImDrawCornerFlags_All", "ImDrawCornerFlags.All" }, + { "ImPlotFlags_None", "ImPlotFlags.None"}, + { "ImPlotAxisFlags_None", "ImPlotAxisFlags.None"}, + { "ImPlotAxisFlags_NoGridLines", "ImPlotAxisFlags.NoGridLines"}, + { "ImGuiCond_Once", "ImGuiCond.Once"}, + { "ImPlotOrientation_Vertical", "ImPlotOrientation.Vertical"}, + { "PinShape_CircleFilled", "PinShape._CircleFilled"}, { "FLT_MAX", "float.MaxValue" }, - { "(((ImU32)(255)<<24)|((ImU32)(255)<<16)|((ImU32)(255)<<8)|((ImU32)(255)<<0))", "0xFFFFFFFF" } + { "(((ImU32)(255)<<24)|((ImU32)(255)<<16)|((ImU32)(255)<<8)|((ImU32)(255)<<0))", "0xFFFFFFFF" }, + { "sizeof(ImU8)", "sizeof(byte)"}, + { "sizeof(ImS8)", "sizeof(sbyte)"}, + { "sizeof(ImU16)", "sizeof(ushort)"}, + { "sizeof(ImS16)", "sizeof(short)"}, + { "sizeof(ImU32)", "sizeof(uint)"}, + { "sizeof(ImS32)", "sizeof(int)"}, + { "sizeof(ImU64)", "sizeof(ulong)"}, + { "sizeof(ImS64)", "sizeof(long)"} }; public static readonly Dictionary IdentifierReplacements = new Dictionary() diff --git a/src/CodeGenerator/definitions.json b/src/CodeGenerator/definitions/cimgui/definitions.json similarity index 100% rename from src/CodeGenerator/definitions.json rename to src/CodeGenerator/definitions/cimgui/definitions.json diff --git a/src/CodeGenerator/structs_and_enums.json b/src/CodeGenerator/definitions/cimgui/structs_and_enums.json similarity index 100% rename from src/CodeGenerator/structs_and_enums.json rename to src/CodeGenerator/definitions/cimgui/structs_and_enums.json diff --git a/src/CodeGenerator/variants.json b/src/CodeGenerator/definitions/cimgui/variants.json similarity index 100% rename from src/CodeGenerator/variants.json rename to src/CodeGenerator/definitions/cimgui/variants.json