Add support for curves in C++ scripting api

#2546
This commit is contained in:
Wojtek Figat
2024-12-04 13:30:56 +01:00
parent c01824cd09
commit 12d9d94138
5 changed files with 131 additions and 23 deletions

View File

@@ -20,12 +20,12 @@ namespace Flax.Build.Bindings
private static readonly Dictionary<string, string> CSharpAdditionalCodeCache = new Dictionary<string, string>();
#if USE_NETCORE
private static readonly TypeInfo CSharpEventBindReturn = new TypeInfo("void");
private static readonly List<FunctionInfo.ParameterInfo> CSharpEventBindParams = new List<FunctionInfo.ParameterInfo>() { new FunctionInfo.ParameterInfo() { Name = "bind", Type = new TypeInfo("bool") } };
private static readonly List<FunctionInfo.ParameterInfo> CSharpEventBindParams = new List<FunctionInfo.ParameterInfo> { new FunctionInfo.ParameterInfo { Name = "bind", Type = new TypeInfo("bool") } };
#endif
public static event Action<BuildData, ApiTypeInfo, StringBuilder, string> GenerateCSharpTypeInternals;
internal static readonly Dictionary<string, string> CSharpNativeToManagedBasicTypes = new Dictionary<string, string>()
internal static readonly Dictionary<string, string> CSharpNativeToManagedBasicTypes = new Dictionary<string, string>
{
// Language types
{ "bool", "bool" },
@@ -46,7 +46,7 @@ namespace Flax.Build.Bindings
{ "double", "double" },
};
internal static readonly Dictionary<string, string> CSharpNativeToManagedDefault = new Dictionary<string, string>()
internal static readonly Dictionary<string, string> CSharpNativeToManagedDefault = new Dictionary<string, string>
{
// Engine types
{ "String", "string" },
@@ -632,11 +632,11 @@ namespace Flax.Build.Bindings
else if (returnValueType == "object[]")
returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemObjectArrayMarshaller))";
else if (functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer" || functionInfo.ReturnType.Type == "BytesContainer" || returnNativeType == "Array")
returnMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = nameof(__returnCount))";
returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = nameof(__returnCount))";
else if (functionInfo.ReturnType.Type == "Dictionary")
returnMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
else if (returnValueType == "byte[]")
returnMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = \"__returnCount\")";
returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = \"__returnCount\")";
else if (returnValueType == "bool[]")
{
// Boolean arrays does not support custom marshalling for some unknown reason
@@ -691,11 +691,15 @@ namespace Flax.Build.Bindings
parameterMarshalType += ", In"; // The usage of 'LibraryImportAttribute' does not follow recommendations. It is recommended to use explicit '[In]' and '[Out]' attributes on array parameters.
}
else if (parameterInfo.Type.Type == "Dictionary")
parameterMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
else if (nativeType == "bool")
parameterMarshalType = "MarshalAs(UnmanagedType.U1)";
else if (nativeType == "char")
parameterMarshalType = "MarshalAs(UnmanagedType.I2)";
else if (nativeType.EndsWith("[]"))
{
parameterMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>))";
}
if (!string.IsNullOrEmpty(parameterMarshalType))
contents.Append($"[{parameterMarshalType}] ");
@@ -730,7 +734,7 @@ namespace Flax.Build.Bindings
if (parameterInfo.Type.Type == "Array" || parameterInfo.Type.Type == "Span" || parameterInfo.Type.Type == "DataContainer" || parameterInfo.Type.Type == "BytesContainer")
parameterMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = \"{parameterInfo.Name}Count\")";
else if (parameterInfo.Type.Type == "Dictionary")
parameterMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.DictionaryMarshaller<,>), ConstantElementCount = 0)";
}
if (nativeType == "System.Type")
parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemTypeMarshaller))";

View File

@@ -980,6 +980,10 @@ namespace Flax.Build.Bindings
UseReferenceForResult = UsePassByReference(buildData, functionInfo.ReturnType, caller),
CustomParameters = new List<FunctionInfo.ParameterInfo>(),
};
var returnType = functionInfo.ReturnType;
var returnApiType = FindApiTypeInfo(buildData, returnType, caller);
if (returnApiType != null && returnApiType.MarshalAs != null)
returnType = returnApiType.MarshalAs;
bool returnTypeIsContainer = false;
var returnValueConvert = GenerateCppWrapperNativeToManaged(buildData, functionInfo.ReturnType, caller, out var returnValueType, functionInfo);
@@ -999,7 +1003,7 @@ namespace Flax.Build.Bindings
});
}
#if USE_NETCORE
else if (functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer" || functionInfo.ReturnType.Type == "BitArray" || functionInfo.ReturnType.Type == "BytesContainer")
else if (returnType.Type == "Array" || returnType.Type == "Span" || returnType.Type == "DataContainer" || returnType.Type == "BitArray" || returnType.Type == "BytesContainer")
{
returnTypeIsContainer = true;
functionInfo.Glue.CustomParameters.Add(new FunctionInfo.ParameterInfo
@@ -1173,7 +1177,7 @@ namespace Flax.Build.Bindings
{
callBegin += "*__resultAsRef = ";
}
else if (!functionInfo.ReturnType.IsVoid)
else if (!returnType.IsVoid)
{
if (useInlinedReturn)
callBegin += "return ";
@@ -1186,7 +1190,7 @@ namespace Flax.Build.Bindings
if (returnTypeIsContainer)
{
callReturnCount = indent;
if (functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "BytesContainer")
if (returnType.Type == "Span" || returnType.Type == "BytesContainer")
callReturnCount += "*__returnCount = {0}.Length();";
else
callReturnCount += "*__returnCount = {0}.Count();";
@@ -1278,7 +1282,8 @@ namespace Flax.Build.Bindings
#if USE_NETCORE
if (!string.IsNullOrEmpty(callReturnCount))
{
contents.Append(indent).Append("const auto& __callTemp = ").Append(string.Format(callFormat, call, callParams)).Append(";").AppendLine();
var tempVar = returnTypeIsContainer && returnType != functionInfo.ReturnType ? $"{returnType} __callTemp = " : "const auto& __callTemp = ";
contents.Append(indent).Append(tempVar).Append(string.Format(callFormat, call, callParams)).Append(";").AppendLine();
call = "__callTemp";
contents.Append(string.Format(callReturnCount, call));
contents.AppendLine();
@@ -1357,7 +1362,7 @@ namespace Flax.Build.Bindings
}
}
if (!useInlinedReturn && !functionInfo.Glue.UseReferenceForResult && !functionInfo.ReturnType.IsVoid)
if (!useInlinedReturn && !functionInfo.Glue.UseReferenceForResult && !returnType.IsVoid)
{
contents.Append(indent).Append("return __result;").AppendLine();
}
@@ -1817,6 +1822,10 @@ namespace Flax.Build.Bindings
// Add includes to properly compile bindings (eg. SoftObjectReference<class Texture>)
GenerateCppAddFileReference(buildData, caller, typeInfo, apiTypeInfo);
// TODO: find a better way to reference other include files for types that have separate serialization header
if (typeInfo.Type.EndsWith("Curve") && typeInfo.GenericArgs != null)
CppIncludeFilesList.Add("Engine/Animations/CurveSerialization.h");
return false;
}
@@ -3126,13 +3135,12 @@ namespace Flax.Build.Bindings
// Includes
header.Clear();
CppReferencesFiles.Remove(null);
CppIncludeFilesList.Clear();
foreach (var fileInfo in CppReferencesFiles)
CppIncludeFilesList.Add(fileInfo.Name);
CppIncludeFilesList.AddRange(CppIncludeFiles);
CppIncludeFilesList.Sort();
if (CppIncludeFilesList.Remove("Engine/Serialization/Serialization.h"))
CppIncludeFilesList.Add("Engine/Serialization/Serialization.h");
CppIncludeFilesList.Add("Engine/Serialization/Serialization.h"); // Include serialization header as the last one to properly handle specialization of custom types serialization
foreach (var path in CppIncludeFilesList)
header.AppendFormat("#include \"{0}\"", path).AppendLine();
contents.Insert(headerPos, header.ToString());