diff --git a/src/CodeGenerator/CodeGenerator.csproj b/src/CodeGenerator/CodeGenerator.csproj index 9f05ccc..861e6a6 100644 --- a/src/CodeGenerator/CodeGenerator.csproj +++ b/src/CodeGenerator/CodeGenerator.csproj @@ -5,9 +5,16 @@ netcoreapp2.1 + + + + + + PreserveNewest + diff --git a/src/CodeGenerator/Program.cs b/src/CodeGenerator/Program.cs index 18ddf86..5c87592 100644 --- a/src/CodeGenerator/Program.cs +++ b/src/CodeGenerator/Program.cs @@ -130,6 +130,27 @@ namespace CodeGenerator functionsJson = JObject.Load(jr); } + JObject variantsJson = null; + if (File.Exists(Path.Combine(AppContext.BaseDirectory, "variants.json"))) + { + using (StreamReader fs = File.OpenText(Path.Combine(AppContext.BaseDirectory, "variants.json"))) + using (JsonTextReader jr = new JsonTextReader(fs)) + { + variantsJson = JObject.Load(jr); + } + } + + Dictionary variants = new Dictionary(); + foreach (var jt in variantsJson.Children()) + { + JProperty jp = (JProperty)jt; + ParameterVariant[] methodVariants = jp.Values().Select(jv => + { + return new ParameterVariant(jv["name"].ToString(), jv["type"].ToString(), jv["variants"].Select(s => s.ToString()).ToArray()); + }).ToArray(); + variants.Add(jp.Name, new MethodVariant(jp.Name, methodVariants)); + } + EnumDefinition[] enums = typesJson["enums"].Select(jt => { JProperty jp = (JProperty)jt; @@ -195,11 +216,20 @@ namespace CodeGenerator List parameters = new List(); + // find any variants that can be applied to the parameters of this method based on the method name + MethodVariant methodVariants = null; + variants.TryGetValue(jp.Name, out methodVariants); + foreach (JToken p in val["argsT"]) { string pType = p["type"].ToString(); string pName = p["name"].ToString(); - parameters.Add(new TypeReference(pName, pType, enums)); + + // if there are possible variants for this method then try to match them based on the parameter name and expected type + ParameterVariant matchingVariant = methodVariants?.Parameters.Where(pv => pv.Name == pName && pv.OriginalType == pType).FirstOrDefault() ?? null; + if (matchingVariant != null) matchingVariant.Used = true; + + parameters.Add(new TypeReference(pName, pType, enums, matchingVariant?.VariantTypes)); } Dictionary defaultValues = new Dictionary(); @@ -231,7 +261,7 @@ namespace CodeGenerator isDestructor); }).Where(od => od != null).ToArray(); - return new FunctionDefinition(name, overloads); + return new FunctionDefinition(name, overloads, enums); }).OrderBy(fd => fd.Name).ToArray(); foreach (EnumDefinition ed in enums) @@ -545,6 +575,14 @@ namespace CodeGenerator writer.PopBlock(); writer.PopBlock(); } + + foreach (var method in variants) + { + foreach (var variant in method.Value.Parameters) + { + if (!variant.Used) Console.WriteLine($"Error: Variants targetting parameter {variant.Name} with type {variant.OriginalType} could not be applied to method {method.Key}."); + } + } } private static bool IsStringFieldName(string name) @@ -963,6 +1001,38 @@ namespace CodeGenerator } } + class MethodVariant + { + public string Name { get; } + + public ParameterVariant[] Parameters { get; } + + public MethodVariant(string name, ParameterVariant[] parameters) + { + Name = name; + Parameters = parameters; + } + } + + class ParameterVariant + { + public string Name { get; } + + public string OriginalType { get; } + + public string[] VariantTypes { get; } + + public bool Used { get; set; } + + public ParameterVariant(string name, string originalType, string[] variantTypes) + { + Name = name; + OriginalType = originalType; + VariantTypes = variantTypes; + Used = false; + } + } + class EnumDefinition { private readonly Dictionary _sanitizedNames; @@ -1049,11 +1119,18 @@ namespace CodeGenerator public string TemplateType { get; } public int ArraySize { get; } public bool IsFunctionPointer { get; } + public string[] TypeVariants { get; } public TypeReference(string name, string type, EnumDefinition[] enums) - : this(name, type, null, enums) { } + : this(name, type, null, enums, null) { } + + public TypeReference(string name, string type, EnumDefinition[] enums, string[] typeVariants) + : this(name, type, null, enums, typeVariants) { } public TypeReference(string name, string type, string templateType, EnumDefinition[] enums) + : this(name, type, templateType, enums, null) { } + + public TypeReference(string name, string type, string templateType, EnumDefinition[] enums, string[] typeVariants) { Name = name; Type = type.Replace("const", string.Empty).Trim(); @@ -1082,6 +1159,8 @@ namespace CodeGenerator } IsFunctionPointer = Type.IndexOf('(') != -1; + + TypeVariants = typeVariants; } private int ParseSizeString(string sizePart, EnumDefinition[] enums) @@ -1117,6 +1196,12 @@ namespace CodeGenerator return ret; } + + public TypeReference WithVariant(int variantIndex, EnumDefinition[] enums) + { + if (variantIndex == 0) return this; + else return new TypeReference(Name, TypeVariants[variantIndex - 1], TemplateType, enums); + } } class FunctionDefinition @@ -1124,10 +1209,63 @@ namespace CodeGenerator public string Name { get; } public OverloadDefinition[] Overloads { get; } - public FunctionDefinition(string name, OverloadDefinition[] overloads) + public FunctionDefinition(string name, OverloadDefinition[] overloads, EnumDefinition[] enums) { Name = name; - Overloads = overloads; + Overloads = ExpandOverloadVariants(overloads, enums); + } + + private OverloadDefinition[] ExpandOverloadVariants(OverloadDefinition[] overloads, EnumDefinition[] enums) + { + List newDefinitions = new List(); + + foreach (OverloadDefinition overload in overloads) + { + bool hasVariants = false; + int[] variantCounts = new int[overload.Parameters.Length]; + + for (int i = 0; i < overload.Parameters.Length; i++) + { + if (overload.Parameters[i].TypeVariants != null) + { + hasVariants = true; + variantCounts[i] = overload.Parameters[i].TypeVariants.Length + 1; + } + else + { + variantCounts[i] = 1; + } + } + + if (hasVariants) + { + int totalVariants = variantCounts[0]; + for (int i = 1; i < variantCounts.Length; i++) totalVariants *= variantCounts[i]; + + for (int i = 0; i < totalVariants; i++) + { + TypeReference[] parameters = new TypeReference[overload.Parameters.Length]; + int div = 1; + + for (int j = 0; j < parameters.Length; j++) + { + int k = (i / div) % variantCounts[j]; + + parameters[j] = overload.Parameters[j].WithVariant(k, enums); + + if (j > 0) div *= variantCounts[j]; + } + + newDefinitions.Add(overload.WithParameters(parameters)); + } + } + else + { + newDefinitions.Add(overload); + } + } + + return newDefinitions.ToArray(); } } @@ -1166,6 +1304,11 @@ namespace CodeGenerator IsConstructor = isConstructor; IsDestructor = isDestructor; } + + public OverloadDefinition WithParameters(TypeReference[] parameters) + { + return new OverloadDefinition(ExportedName, FriendlyName, parameters, DefaultValues, ReturnType, StructName, Comment, IsConstructor, IsDestructor); + } } class MarshalledParameter diff --git a/src/CodeGenerator/variants.json b/src/CodeGenerator/variants.json new file mode 100644 index 0000000..8b94900 --- /dev/null +++ b/src/CodeGenerator/variants.json @@ -0,0 +1,16 @@ +{ + "ImFontAtlas_GetTexDataAsAlpha8": [ + { + "name": "out_pixels", + "type": "unsigned char**", + "variants": [ "IntPtr*" ] + } + ], + "ImFontAtlas_GetTexDataAsRGBA32": [ + { + "name": "out_pixels", + "type": "unsigned char**", + "variants": [ "IntPtr*" ] + } + ] +} \ No newline at end of file diff --git a/src/ImGui.NET.SampleProgram/ImGuiController.cs b/src/ImGui.NET.SampleProgram/ImGuiController.cs index 64d6ef9..ca40da7 100644 --- a/src/ImGui.NET.SampleProgram/ImGuiController.cs +++ b/src/ImGui.NET.SampleProgram/ImGuiController.cs @@ -244,11 +244,11 @@ namespace ImGuiNET /// /// Recreates the device texture used to render text. /// - public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd) + public void RecreateFontDeviceTexture(GraphicsDevice gd) { ImGuiIOPtr io = ImGui.GetIO(); // Build - byte* pixels; + IntPtr pixels; int width, height, bytesPerPixel; io.Fonts.GetTexDataAsRGBA32(out pixels, out width, out height, out bytesPerPixel); // Store our identifier @@ -264,7 +264,7 @@ namespace ImGuiNET _fontTexture.Name = "ImGui.NET Font Texture"; gd.UpdateTexture( _fontTexture, - (IntPtr)pixels, + pixels, (uint)(bytesPerPixel * width * height), 0, 0, diff --git a/src/ImGui.NET/Generated/ImFontAtlas.gen.cs b/src/ImGui.NET/Generated/ImFontAtlas.gen.cs index d398228..70a2c5d 100644 --- a/src/ImGui.NET/Generated/ImFontAtlas.gen.cs +++ b/src/ImGui.NET/Generated/ImFontAtlas.gen.cs @@ -434,6 +434,36 @@ namespace ImGuiNET } } } + public void GetTexDataAsAlpha8(out IntPtr out_pixels, out int out_width, out int out_height) + { + int* out_bytes_per_pixel = null; + fixed (IntPtr* native_out_pixels = &out_pixels) + { + fixed (int* native_out_width = &out_width) + { + fixed (int* native_out_height = &out_height) + { + ImGuiNative.ImFontAtlas_GetTexDataAsAlpha8(NativePtr, native_out_pixels, native_out_width, native_out_height, out_bytes_per_pixel); + } + } + } + } + public void GetTexDataAsAlpha8(out IntPtr out_pixels, out int out_width, out int out_height, out int out_bytes_per_pixel) + { + fixed (IntPtr* native_out_pixels = &out_pixels) + { + fixed (int* native_out_width = &out_width) + { + fixed (int* native_out_height = &out_height) + { + fixed (int* native_out_bytes_per_pixel = &out_bytes_per_pixel) + { + ImGuiNative.ImFontAtlas_GetTexDataAsAlpha8(NativePtr, native_out_pixels, native_out_width, native_out_height, native_out_bytes_per_pixel); + } + } + } + } + } public void GetTexDataAsRGBA32(out byte* out_pixels, out int out_width, out int out_height) { int* out_bytes_per_pixel = null; @@ -464,6 +494,36 @@ namespace ImGuiNET } } } + public void GetTexDataAsRGBA32(out IntPtr out_pixels, out int out_width, out int out_height) + { + int* out_bytes_per_pixel = null; + fixed (IntPtr* native_out_pixels = &out_pixels) + { + fixed (int* native_out_width = &out_width) + { + fixed (int* native_out_height = &out_height) + { + ImGuiNative.ImFontAtlas_GetTexDataAsRGBA32(NativePtr, native_out_pixels, native_out_width, native_out_height, out_bytes_per_pixel); + } + } + } + } + public void GetTexDataAsRGBA32(out IntPtr out_pixels, out int out_width, out int out_height, out int out_bytes_per_pixel) + { + fixed (IntPtr* native_out_pixels = &out_pixels) + { + fixed (int* native_out_width = &out_width) + { + fixed (int* native_out_height = &out_height) + { + fixed (int* native_out_bytes_per_pixel = &out_bytes_per_pixel) + { + ImGuiNative.ImFontAtlas_GetTexDataAsRGBA32(NativePtr, native_out_pixels, native_out_width, native_out_height, native_out_bytes_per_pixel); + } + } + } + } + } public bool IsBuilt() { byte ret = ImGuiNative.ImFontAtlas_IsBuilt(NativePtr); diff --git a/src/ImGui.NET/Generated/ImGuiNative.gen.cs b/src/ImGui.NET/Generated/ImGuiNative.gen.cs index 37bf3da..39bc715 100644 --- a/src/ImGui.NET/Generated/ImGuiNative.gen.cs +++ b/src/ImGui.NET/Generated/ImGuiNative.gen.cs @@ -909,8 +909,12 @@ namespace ImGuiNET [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] public static extern void ImFontAtlas_GetTexDataAsAlpha8(ImFontAtlas* self, byte** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] + public static extern void ImFontAtlas_GetTexDataAsAlpha8(ImFontAtlas* self, IntPtr* out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); + [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] public static extern void ImFontAtlas_GetTexDataAsRGBA32(ImFontAtlas* self, byte** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] + public static extern void ImFontAtlas_GetTexDataAsRGBA32(ImFontAtlas* self, IntPtr* out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); + [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] public static extern ImFontAtlas* ImFontAtlas_ImFontAtlas(); [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] public static extern byte ImFontAtlas_IsBuilt(ImFontAtlas* self);