Preparing code generator for ImPlot, ImNodes and ImGuizmo code generation

internals
Alex Hildebrand 4 years ago
parent 9b74ee4f79
commit 02a838f88f
  1. 19
      src/CodeGenerator/CodeGenerator.csproj
  2. 7
      src/CodeGenerator/ImguiDefinitions.cs
  3. 96
      src/CodeGenerator/Program.cs
  4. 34
      src/CodeGenerator/TypeInfo.cs
  5. 0
      src/CodeGenerator/definitions/cimgui/definitions.json
  6. 0
      src/CodeGenerator/definitions/cimgui/structs_and_enums.json
  7. 0
      src/CodeGenerator/definitions/cimgui/variants.json

@ -6,13 +6,24 @@
</PropertyGroup>
<ItemGroup>
<Content Include="structs_and_enums.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="variants.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimgui\structs_and_enums.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimgui\definitions.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimgui\variants.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimplot\structs_and_enums.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimplot\definitions.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimplot\variants.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimnodes\structs_and_enums.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimnodes\definitions.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimnodes\variants.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimguizmo\structs_and_enums.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimguizmo\definitions.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="definitions\cimguizmo\variants.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
</Project>

@ -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)

@ -25,8 +25,46 @@ 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}.");
@ -34,7 +72,7 @@ namespace CodeGenerator
{
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<string, string> 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;
}

@ -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*" },
@ -45,6 +51,11 @@ namespace CodeGenerator
{ "unsigned char[256]", "byte*"},
};
public static readonly List<string> WellKnownEnums = new List<string>()
{
"ImGuiMouseButton"
};
public static readonly Dictionary<string, string> WellKnownFieldReplacements = new Dictionary<string, string>()
{
{ "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<string, string> IdentifierReplacements = new Dictionary<string, string>()

Loading…
Cancel
Save