1270 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1270 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Concurrent;
 | |
| using System.Collections.Generic;
 | |
| using System.Data.Common;
 | |
| using System.Linq;
 | |
| using System.Reflection.Metadata;
 | |
| using System.Reflection.Metadata.Ecma335;
 | |
| using System.Runtime.InteropServices;
 | |
| using System.Threading.Tasks;
 | |
| using EpicGames.Core;
 | |
| using EpicGames.UHT.Types;
 | |
| using UnrealSharpScriptGenerator.PropertyTranslators;
 | |
| using UnrealSharpScriptGenerator.Tooltip;
 | |
| using UnrealSharpScriptGenerator.Utilities;
 | |
| 
 | |
| namespace UnrealSharpScriptGenerator.Exporters;
 | |
| 
 | |
| public enum EFunctionProtectionMode
 | |
| {
 | |
|     UseUFunctionProtection,
 | |
|     OverrideWithInternal,
 | |
| }
 | |
| 
 | |
| public struct ExtensionMethod
 | |
| {
 | |
|     public UhtClass Class;
 | |
|     public UhtFunction Function;
 | |
|     public UhtProperty SelfParameter;
 | |
| }
 | |
| 
 | |
| public enum FunctionType
 | |
| {
 | |
|     Normal,
 | |
|     BlueprintEvent,
 | |
|     ExtensionOnAnotherClass,
 | |
|     InternalWhitelisted,
 | |
|     GetterSetter,
 | |
| };
 | |
| 
 | |
| public enum OverloadMode
 | |
| {
 | |
|     AllowOverloads,
 | |
|     SuppressOverloads,
 | |
| };
 | |
| 
 | |
| public enum EBlueprintVisibility
 | |
| {
 | |
|     Call,
 | |
|     Event,
 | |
|     GetterSetter,
 | |
|     Throwing
 | |
| };
 | |
| 
 | |
| public struct FunctionOverload
 | |
| {
 | |
|     public string ParamStringApiWithDefaults;
 | |
|     public string ParamsStringCall;
 | |
|     public string CSharpParamName;
 | |
|     public string CppDefaultValue;
 | |
|     public PropertyTranslator Translator;
 | |
|     public UhtProperty Parameter;
 | |
| }
 | |
| 
 | |
| public class FunctionExporter
 | |
| {
 | |
|     protected static readonly ConcurrentDictionary<UhtPackage, List<ExtensionMethod>> ExtensionMethods = new();
 | |
|     
 | |
|     public UhtFunction Function { get; }
 | |
|     protected string _functionName = null!;
 | |
|     protected List<PropertyTranslator> _parameterTranslators = null!;
 | |
|     protected PropertyTranslator? ReturnValueTranslator => Function.ReturnProperty != null ? _parameterTranslators.Last() : null;
 | |
|     protected OverloadMode _overloadMode = OverloadMode.AllowOverloads;
 | |
|     protected EFunctionProtectionMode _protectionMode = EFunctionProtectionMode.UseUFunctionProtection;
 | |
|     protected EBlueprintVisibility _blueprintVisibility = EBlueprintVisibility.Call;
 | |
| 
 | |
|     protected bool BlittableFunction;
 | |
|     
 | |
|     public string Modifiers { get; private set; } = "";
 | |
| 
 | |
|     protected bool BlueprintEvent => Function.HasAllFlags(EFunctionFlags.BlueprintEvent);
 | |
|     protected bool BlueprintNativeEvent => Function.IsBlueprintNativeEvent();
 | |
|     protected bool BlueprintImplementableEvent => Function.IsBlueprintImplementableEvent();
 | |
|     protected bool Throwing => _blueprintVisibility == EBlueprintVisibility.Throwing;
 | |
|     
 | |
|     protected string _invokeFunction = "";
 | |
|     protected string _invokeFirstArgument = "";
 | |
| 
 | |
|     protected string _customInvoke = "";
 | |
| 
 | |
|     protected string _paramStringApiWithDefaults = "";
 | |
|     protected string _paramsStringCall = "";
 | |
| 
 | |
|     protected bool _hasGenericTypeSupport = false;
 | |
|     protected bool _hasCustomStructParamSupport = false;
 | |
| 
 | |
|     protected List<string> _customStructParamTypes = null!;
 | |
| 
 | |
|     protected readonly UhtProperty? _selfParameter;
 | |
|     protected readonly UhtClass? _classBeingExtended;
 | |
| 
 | |
|     protected readonly List<FunctionOverload> _overloads = new();
 | |
|     
 | |
|     public string NativeFunctionIntPtr => $"{Function.SourceName}_NativeFunction";
 | |
|     public string InstanceFunctionPtr => $"{Function.SourceName}_InstanceFunction";
 | |
|     
 | |
|     public FunctionExporter(ExtensionMethod extensionMethod)
 | |
|     {
 | |
|         _selfParameter = extensionMethod.SelfParameter;
 | |
|         Function = extensionMethod.Function;
 | |
|         _classBeingExtended = extensionMethod.Class;
 | |
|     }
 | |
| 
 | |
|     public FunctionExporter(UhtFunction function) 
 | |
|     {
 | |
|         Function = function;
 | |
|     }
 | |
|     
 | |
|     string GetRefQualifier(UhtProperty parameter)
 | |
|     {
 | |
|         if (parameter.HasAllFlags(EPropertyFlags.ConstParm))
 | |
|         {
 | |
|             return "";
 | |
|         }
 | |
|         
 | |
|         if (parameter.HasAllFlags(EPropertyFlags.ReferenceParm))
 | |
|         {
 | |
|             return "ref ";
 | |
|         }
 | |
|         
 | |
|         if (parameter.HasAllFlags(EPropertyFlags.OutParm))
 | |
|         {
 | |
|             return "out ";
 | |
|         }
 | |
| 
 | |
|         return "";
 | |
|     }
 | |
| 
 | |
|     public void Initialize(OverloadMode overloadMode, EFunctionProtectionMode protectionMode, EBlueprintVisibility blueprintVisibility, bool withGenerics = false)
 | |
|     {
 | |
|         _functionName = protectionMode != EFunctionProtectionMode.OverrideWithInternal
 | |
|             ? Function.GetFunctionName()
 | |
|             : Function.SourceName;
 | |
|         
 | |
|         _overloadMode = overloadMode;
 | |
|         _protectionMode = protectionMode;
 | |
|         _blueprintVisibility = blueprintVisibility;
 | |
| 
 | |
|         _parameterTranslators = new List<PropertyTranslator>(Function.Children.Count);
 | |
|         
 | |
|         bool isBlittable = true;
 | |
|         foreach (UhtProperty parameter in Function.Properties)
 | |
|         {
 | |
|             PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(parameter)!;
 | |
|             _parameterTranslators.Add(translator);
 | |
| 
 | |
|             if (!translator.IsBlittable && isBlittable)
 | |
|             {
 | |
|                 isBlittable = false;
 | |
|             }
 | |
|         }
 | |
|         BlittableFunction = isBlittable;
 | |
| 
 | |
|         _hasGenericTypeSupport = Function.HasGenericTypeSupport();
 | |
| 
 | |
|         _hasCustomStructParamSupport = Function.HasCustomStructParamSupport();
 | |
| 
 | |
|         DetermineProtectionMode();
 | |
|         _invokeFunction = DetermineInvokeFunction();
 | |
| 
 | |
|         if (Function.HasAllFlags(EFunctionFlags.Static))
 | |
|         {
 | |
|             Modifiers += "static ";
 | |
|             _invokeFirstArgument = "NativeClassPtr";
 | |
|         }
 | |
|         else if (Function.HasAllFlags(EFunctionFlags.Delegate))
 | |
|         {
 | |
|             if (Function.HasParametersOrReturnValue())
 | |
|             {
 | |
|                 _customInvoke = "ProcessDelegate(paramsBuffer);";
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 _customInvoke = "ProcessDelegate(IntPtr.Zero);";
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (BlueprintEvent)
 | |
|             {
 | |
|                 Modifiers += "virtual ";
 | |
|             }
 | |
| 		
 | |
|             if (Function.IsInterfaceFunction())
 | |
|             {
 | |
|                 Modifiers = ScriptGeneratorUtilities.PublicKeyword;
 | |
|             }
 | |
|             
 | |
|             _invokeFirstArgument = "NativeObject";
 | |
|         }
 | |
| 
 | |
|         string paramString = "";
 | |
|         bool hasDefaultParameters = false;
 | |
| 
 | |
|         if (_selfParameter != null)
 | |
|         {
 | |
|             PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(_selfParameter)!;
 | |
|             string paramType = _classBeingExtended != null
 | |
|                 ? _classBeingExtended.GetFullManagedName()
 | |
|                 : translator.GetManagedType(_selfParameter);
 | |
|             
 | |
|             paramString = $"this {paramType} {_selfParameter.GetParameterName()}, ";
 | |
|             _paramStringApiWithDefaults = paramString;
 | |
|         }
 | |
|         
 | |
|         string paramsStringCallNative = "";
 | |
| 
 | |
|         string paramsStringCallGenerics = "";
 | |
|         string paramStringApiWithDefaultsWithGenerics = "";
 | |
| 
 | |
|         bool hasGenericClassParam = false;
 | |
| 
 | |
|         _customStructParamTypes = Function.GetCustomStructParamTypes();
 | |
|         
 | |
|         for (int i = 0; i < Function.Children.Count; i++)
 | |
|         {
 | |
|             UhtProperty parameter = (UhtProperty) Function.Children[i];
 | |
|             if (parameter.HasAllFlags(EPropertyFlags.ReturnParm))
 | |
|             {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             PropertyTranslator translator = _parameterTranslators[i];
 | |
|             
 | |
|             string refQualifier = GetRefQualifier(parameter);
 | |
|             string parameterName = GetParameterName(parameter);
 | |
|             string parameterManagedType = translator.GetManagedType(parameter);
 | |
| 
 | |
|             if (!translator.ShouldBeDeclaredAsParameter)
 | |
|             {
 | |
|                 continue;
 | |
|             }
 | |
|             
 | |
|             if (_selfParameter == parameter)
 | |
|             {
 | |
|                 if (string.IsNullOrEmpty(paramsStringCallGenerics))
 | |
|                 {
 | |
|                     paramsStringCallGenerics += refQualifier + parameterName;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     paramsStringCallGenerics = $"{parameterName},  " + _paramsStringCall.Substring(0, _paramsStringCall.Length - 2);
 | |
|                 }
 | |
| 
 | |
|                 if (string.IsNullOrEmpty(_paramsStringCall))
 | |
|                 {
 | |
|                     _paramsStringCall += refQualifier + parameterName;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     _paramsStringCall = $"{parameterName},  " + _paramsStringCall.Substring(0, _paramsStringCall.Length - 2);
 | |
|                 }
 | |
|                 paramsStringCallNative += parameterName;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 string cppDefaultValue = translator.GetCppDefaultValue(Function, parameter);
 | |
|                 bool isGenericClassParam = _hasGenericTypeSupport && parameter.IsGenericType() && !parameter.HasAnyFlags(EPropertyFlags.OutParm) && parameter is UhtClassProperty;
 | |
| 
 | |
|                 if (cppDefaultValue == "()" && parameter is UhtStructProperty structProperty)
 | |
|                 {
 | |
|                     _paramsStringCall += $"new {structProperty.ScriptStruct.GetFullManagedName()}()";
 | |
|                     paramsStringCallGenerics += $"new {structProperty.ScriptStruct.GetFullManagedName()}()";
 | |
|                 }
 | |
|                 else if (isGenericClassParam)
 | |
|                 {
 | |
|                     _paramsStringCall += $"{refQualifier}{parameterName}";
 | |
|                     paramsStringCallGenerics += $"typeof(DOT)";
 | |
| 
 | |
|                     hasGenericClassParam = true;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     _paramsStringCall += $"{refQualifier}{parameterName}";
 | |
|                     paramsStringCallGenerics += $"{refQualifier}{parameterName}";
 | |
|                 }
 | |
| 
 | |
|                 paramsStringCallNative += $"{refQualifier}{parameterName}";
 | |
|                 paramString += $"{refQualifier}{parameterManagedType} {parameterName}";
 | |
| 
 | |
|                 if (!isGenericClassParam)
 | |
|                 {
 | |
|                     paramStringApiWithDefaultsWithGenerics += $"{refQualifier}{parameterManagedType} {parameterName}";
 | |
|                 }
 | |
| 
 | |
|                 if ((hasDefaultParameters || cppDefaultValue.Length > 0) && _overloadMode == OverloadMode.AllowOverloads)
 | |
|                 {
 | |
|                     hasDefaultParameters = true;
 | |
|                     string csharpDefaultValue = "";
 | |
|                     
 | |
|                     if (cppDefaultValue.Length == 0 || cppDefaultValue == "None")
 | |
|                     {
 | |
|                         csharpDefaultValue = translator.GetNullValue(parameter);
 | |
|                     }
 | |
|                     else if (translator.ExportDefaultParameter)
 | |
|                     {
 | |
|                         csharpDefaultValue = translator.ConvertCPPDefaultValue(cppDefaultValue, Function, parameter);
 | |
|                     }
 | |
|                     
 | |
|                     if (!string.IsNullOrEmpty(csharpDefaultValue))
 | |
|                     {
 | |
|                         string defaultValue = $" = {csharpDefaultValue}";
 | |
|                         _paramStringApiWithDefaults += $"{refQualifier}{parameterManagedType} {parameterName}{defaultValue}";
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         if (_paramStringApiWithDefaults.Length > 0)
 | |
|                         {
 | |
|                             _paramStringApiWithDefaults = _paramStringApiWithDefaults.Substring(0, _paramStringApiWithDefaults.Length - 2);
 | |
|                         }
 | |
| 
 | |
|                         FunctionOverload overload = new FunctionOverload
 | |
|                         {
 | |
|                             ParamStringApiWithDefaults = _paramStringApiWithDefaults,
 | |
|                             ParamsStringCall = _paramsStringCall,
 | |
|                             CSharpParamName = parameterName,
 | |
|                             CppDefaultValue = cppDefaultValue,
 | |
|                             Translator = translator,
 | |
|                             Parameter = parameter,
 | |
|                         };
 | |
|                         
 | |
|                         _overloads.Add(overload);
 | |
| 
 | |
|                         _paramStringApiWithDefaults = paramString;
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     _paramStringApiWithDefaults = paramString;
 | |
|                 }
 | |
|                 
 | |
|                 paramString += ", ";
 | |
|                 _paramStringApiWithDefaults += ", ";
 | |
| 
 | |
|                 if (!isGenericClassParam)
 | |
|                 {
 | |
|                     paramStringApiWithDefaultsWithGenerics += ", ";
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             _paramsStringCall += ", ";
 | |
|             paramsStringCallGenerics += ", ";
 | |
|             paramsStringCallNative += ", ";
 | |
|         }
 | |
| 
 | |
|         if (_selfParameter == null)
 | |
|         {
 | |
|             _paramsStringCall = paramsStringCallNative;
 | |
|         }
 | |
|         
 | |
|         // remove last comma
 | |
|         if (_paramStringApiWithDefaults.Length > 0)
 | |
|         {
 | |
|             _paramStringApiWithDefaults = _paramStringApiWithDefaults.Substring(0, _paramStringApiWithDefaults.Length - 2);
 | |
|         }  
 | |
|         
 | |
|         if (_paramsStringCall.Length > 0)
 | |
|         {
 | |
|             _paramsStringCall = _paramsStringCall.Substring(0, _paramsStringCall.Length - 2);
 | |
|         }
 | |
| 
 | |
|         if (paramsStringCallGenerics.Length > 0)
 | |
|         {
 | |
|             paramsStringCallGenerics = paramsStringCallGenerics[..^2];
 | |
|         }
 | |
| 
 | |
|         if (paramStringApiWithDefaultsWithGenerics.Length > 0)
 | |
|         {
 | |
|             paramStringApiWithDefaultsWithGenerics = paramStringApiWithDefaultsWithGenerics[..^2];
 | |
|         }
 | |
| 
 | |
|         if (hasGenericClassParam)
 | |
|         {
 | |
|             FunctionOverload overload = new FunctionOverload
 | |
|             {
 | |
|                 ParamStringApiWithDefaults = paramStringApiWithDefaultsWithGenerics,
 | |
|                 ParamsStringCall = paramsStringCallGenerics,
 | |
|             };
 | |
| 
 | |
|             _overloads.Add(overload);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     protected virtual string GetParameterName(UhtProperty parameter)
 | |
|     {
 | |
|         return parameter.GetParameterName();
 | |
|     }
 | |
|     
 | |
|     public static void TryAddExtensionMethod(UhtFunction function)
 | |
|     {
 | |
|         if (!function.HasMetadata("ExtensionMethod") && !function.IsAutocast())
 | |
|         {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         UhtPackage package = function.Outer!.Package;
 | |
|         
 | |
|         if (!ExtensionMethods.TryGetValue(package, out var extensionMethods))
 | |
|         {
 | |
|             extensionMethods = new List<ExtensionMethod>();
 | |
|             ExtensionMethods.TryAdd(package, extensionMethods);
 | |
|         }
 | |
|         
 | |
|         UhtProperty firstParameter = (function.Children[0] as UhtProperty)!;
 | |
|         ExtensionMethod newExtensionMethod = new ExtensionMethod
 | |
|         {
 | |
|             Function = function,
 | |
|             SelfParameter = firstParameter,
 | |
|         };
 | |
|         
 | |
|         if (firstParameter is UhtObjectPropertyBase objectSelfProperty)
 | |
|         {
 | |
|             newExtensionMethod.Class = objectSelfProperty.MetaClass!;
 | |
|         }
 | |
|         
 | |
|         extensionMethods.Add(newExtensionMethod);
 | |
|     }
 | |
| 
 | |
|     public static void StartExportingExtensionMethods(List<Task> tasks)
 | |
|     {
 | |
|         foreach (KeyValuePair<UhtPackage, List<ExtensionMethod>> extensionInfo in ExtensionMethods)
 | |
|         {
 | |
|             tasks.Add(Program.Factory.CreateTask(_ =>
 | |
|             {
 | |
|                 ExtensionsClassExporter.ExportExtensionsClass(extensionInfo.Key, extensionInfo.Value); 
 | |
|             })!);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public static FunctionExporter ExportFunction(GeneratorStringBuilder builder, UhtFunction function, FunctionType functionType, HashSet<string>? exportedFunctions = null)
 | |
|     {
 | |
|         EFunctionProtectionMode protectionMode = EFunctionProtectionMode.UseUFunctionProtection;
 | |
|         OverloadMode overloadMode = OverloadMode.AllowOverloads;
 | |
|         EBlueprintVisibility blueprintVisibility = EBlueprintVisibility.Call;
 | |
| 
 | |
|         if (functionType == FunctionType.ExtensionOnAnotherClass)
 | |
|         {
 | |
|             protectionMode = EFunctionProtectionMode.OverrideWithInternal;
 | |
|             overloadMode = OverloadMode.SuppressOverloads;
 | |
|         }
 | |
|         else if (functionType == FunctionType.BlueprintEvent)
 | |
|         {
 | |
|             overloadMode = OverloadMode.SuppressOverloads;
 | |
|             blueprintVisibility = EBlueprintVisibility.Event;
 | |
|         }
 | |
|         else if (functionType == FunctionType.GetterSetter)
 | |
|         {
 | |
|             protectionMode = EFunctionProtectionMode.OverrideWithInternal;
 | |
|             overloadMode = OverloadMode.SuppressOverloads;
 | |
|             blueprintVisibility = EBlueprintVisibility.GetterSetter;
 | |
|         }
 | |
|         
 | |
|         builder.TryAddWithEditor(function);
 | |
|         FunctionExporter exporter = new FunctionExporter(function);
 | |
|         exporter.Initialize(overloadMode, protectionMode, blueprintVisibility);
 | |
|         if (exportedFunctions is null || !exportedFunctions.Contains(function.SourceName))
 | |
|         {
 | |
|             exporter.ExportFunctionVariables(builder);
 | |
|         }
 | |
| 
 | |
|         exporter.ExportOverloads(builder);
 | |
|         exporter.ExportFunction(builder);
 | |
| 
 | |
|         builder.TryEndWithEditor(function);
 | |
| 
 | |
|         return exporter;
 | |
|     }
 | |
|     
 | |
|     public static void ExportOverridableFunction(GeneratorStringBuilder builder, UhtFunction function, HashSet<string>? exportedFunctions = null)
 | |
|     {
 | |
|         builder.TryAddWithEditor(function);
 | |
|         
 | |
|         string paramsStringApi = "";
 | |
|         string paramsCallString = "";
 | |
|         string methodName = function.GetFunctionName();
 | |
| 
 | |
|         foreach (UhtProperty parameter in function.Properties)
 | |
|         {
 | |
|             if (parameter.HasAllFlags(EPropertyFlags.ReturnParm))
 | |
|             {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             string paramName = parameter.GetParameterName();
 | |
|             string paramType = PropertyTranslatorManager.GetTranslator(parameter)!.GetManagedType(parameter);
 | |
|             
 | |
|             string refQualifier = "";
 | |
|             if (!parameter.HasAllFlags(EPropertyFlags.ConstParm))
 | |
|             {
 | |
|                 if (parameter.HasAllFlags(EPropertyFlags.ReferenceParm))
 | |
|                 {
 | |
|                     refQualifier = "ref ";
 | |
|                 }
 | |
|                 else if (parameter.HasAllFlags(EPropertyFlags.OutParm))
 | |
|                 {
 | |
|                     refQualifier = "out ";
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             paramsStringApi += $"{refQualifier}{paramType} {paramName}, ";
 | |
|             paramsCallString += $"{refQualifier}{paramName}, ";
 | |
|         }
 | |
|         
 | |
|         if (paramsStringApi.Length > 0)
 | |
|         {
 | |
|             paramsStringApi = paramsStringApi.Substring(0, paramsStringApi.Length - 2);
 | |
|         }
 | |
|         if (paramsCallString.Length > 0)
 | |
|         {
 | |
|             paramsCallString = paramsCallString.Substring(0, paramsCallString.Length - 2);
 | |
|         }
 | |
|         
 | |
|         FunctionExporter exportFunction = ExportFunction(builder, function, FunctionType.BlueprintEvent, exportedFunctions);
 | |
|         
 | |
|         string returnType = function.ReturnProperty != null
 | |
|             ? PropertyTranslatorManager.GetTranslator(function.ReturnProperty)!.GetManagedType(function.ReturnProperty)
 | |
|             : "void";
 | |
|         
 | |
|         builder.AppendLine("// Hide implementation function from Intellisense");
 | |
|         builder.AppendLine("[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]");
 | |
|         builder.AppendLine($"protected virtual {returnType} {methodName}_Implementation({paramsStringApi})");
 | |
|         
 | |
|         builder.OpenBrace();
 | |
|         if (exportFunction.BlueprintNativeEvent)
 | |
|         {
 | |
|             exportFunction.ExportInvoke(builder);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             exportFunction.ForEachParameter((translator, parameter) =>
 | |
|             {
 | |
|                 if (!parameter.HasAllFlags(EPropertyFlags.OutParm) || parameter.HasAnyFlags(EPropertyFlags.ReturnParm | EPropertyFlags.ConstParm | EPropertyFlags.ReferenceParm))
 | |
|                 {
 | |
|                     return;
 | |
|                 }
 | |
|                 
 | |
|                 string paramName = parameter.GetParameterName();
 | |
|                 string nullValue = translator.GetNullValue(parameter);
 | |
|                 builder.AppendLine($"{paramName} = {nullValue};");
 | |
|             });
 | |
| 
 | |
|             if (function.ReturnProperty != null)
 | |
|             {
 | |
|                 PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(function.ReturnProperty)!;
 | |
|                 string nullValue = translator.GetNullValue(function.ReturnProperty);
 | |
|                 builder.AppendLine($"return {nullValue};");
 | |
|             }
 | |
|         }
 | |
|         builder.CloseBrace();
 | |
|         
 | |
|         builder.AppendLine($"void Invoke_{function.EngineName}(IntPtr buffer, IntPtr returnBuffer)");
 | |
|         builder.OpenBrace();
 | |
|         builder.BeginUnsafeBlock();
 | |
|         
 | |
|         string returnAssignment = "";
 | |
|         exportFunction.ForEachParameter((translator, parameter) =>
 | |
|         {
 | |
|             string paramType = translator.GetManagedType(parameter);
 | |
| 
 | |
|             if (parameter.HasAllFlags(EPropertyFlags.ReturnParm))
 | |
|             {
 | |
|                 returnAssignment = $"{paramType} returnValue = ";
 | |
|             }
 | |
|             else if (!parameter.HasAnyFlags(EPropertyFlags.ConstParm)
 | |
|                      && !parameter.HasAnyFlags(EPropertyFlags.ReferenceParm)
 | |
|                      && parameter.HasAnyFlags(EPropertyFlags.OutParm))
 | |
|             {
 | |
|                 builder.AppendLine($"{paramType} {parameter.GetParameterName()} = default;");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 string parameterName = parameter.GetParameterName();
 | |
|                 string assignmentOrReturn = $"{paramType} {parameterName} = ";
 | |
|                 string offsetName = parameter.GetOffsetVariableName();
 | |
| 
 | |
|                 translator.ExportFromNative(builder, parameter, parameter.SourceName, assignmentOrReturn, "buffer",
 | |
|                     offsetName, false, false);
 | |
|             }
 | |
|         });
 | |
|         
 | |
|         builder.AppendLine($"{returnAssignment}{methodName}_Implementation({paramsCallString});");
 | |
| 
 | |
|         if (function.ReturnProperty != null)
 | |
|         {
 | |
|             PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(function.ReturnProperty)!;
 | |
|             translator.ExportToNative(builder, function.ReturnProperty, function.ReturnProperty.SourceName, "returnBuffer", "0", "returnValue");
 | |
|         }
 | |
| 
 | |
|         exportFunction.ForEachParameter((translator, parameter) =>
 | |
|         {
 | |
|             if (parameter.HasAnyFlags(EPropertyFlags.ReturnParm | EPropertyFlags.ConstParm) ||
 | |
|                 !parameter.HasAnyFlags(EPropertyFlags.OutParm))
 | |
|             {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             translator.ExportToNative(builder, parameter, parameter.SourceName, "buffer", parameter.GetOffsetVariableName(), parameter.GetParameterName());
 | |
|         });
 | |
|         
 | |
|         builder.EndUnsafeBlock();
 | |
|         builder.CloseBrace();
 | |
|         
 | |
|         builder.TryEndWithEditor(function);
 | |
|         
 | |
|         builder.AppendLine();
 | |
|     }
 | |
| 
 | |
|     public static FunctionExporter ExportDelegateSignature(GeneratorStringBuilder builder, UhtFunction function, string delegateName)
 | |
|     {
 | |
|         FunctionExporter exporter = new FunctionExporter(function);
 | |
|         exporter.Initialize(OverloadMode.SuppressOverloads, EFunctionProtectionMode.UseUFunctionProtection, EBlueprintVisibility.Call);
 | |
| 
 | |
|         AttributeBuilder attributeBuilder = new AttributeBuilder();
 | |
|         attributeBuilder.AddGeneratedTypeAttribute(function);
 | |
|         
 | |
|         if (function.HasAllFlags(EFunctionFlags.MulticastDelegate))
 | |
|         {
 | |
|             attributeBuilder.AddAttribute("UMultiDelegate");
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             attributeBuilder.AddAttribute("USingleDelegate");
 | |
|         }
 | |
|         
 | |
|         attributeBuilder.Finish();
 | |
|         builder.AppendLine(attributeBuilder.ToString());
 | |
|         
 | |
|         builder.AppendLine($"public delegate void {delegateName}({exporter._paramStringApiWithDefaults});");
 | |
|         builder.AppendLine();
 | |
|         
 | |
|         return exporter;
 | |
|     }
 | |
| 
 | |
|     public static void ExportDelegateGlue(GeneratorStringBuilder builder, FunctionExporter exporter)
 | |
|     {
 | |
|         exporter.ExportFunctionVariables(builder);
 | |
|         builder.AppendLine();
 | |
|         
 | |
|         builder.AppendLine($"protected void Invoker({exporter._paramStringApiWithDefaults})");
 | |
|         
 | |
|         builder.OpenBrace();
 | |
|         exporter.ExportInvoke(builder);
 | |
|         builder.CloseBrace();
 | |
|     }
 | |
|     
 | |
|     public static void ExportInterfaceFunction(GeneratorStringBuilder builder, UhtFunction function)
 | |
|     {
 | |
|         builder.TryAddWithEditor(function);
 | |
| 
 | |
|         FunctionExporter exporter = new FunctionExporter(function);
 | |
|         exporter.Initialize(OverloadMode.SuppressOverloads, EFunctionProtectionMode.UseUFunctionProtection, EBlueprintVisibility.Call);
 | |
|         exporter.ExportSignature(builder, ScriptGeneratorUtilities.PublicKeyword);
 | |
|         builder.Append(";");
 | |
|         
 | |
|         builder.TryEndWithEditor(function);
 | |
|     }
 | |
|     
 | |
|     public void ForEachParameter(Action<PropertyTranslator, UhtProperty> action)
 | |
|     {
 | |
|         for (int i = 0; i < Function.Children.Count; i++)
 | |
|         {
 | |
|             UhtProperty parameter = (UhtProperty) Function.Children[i];
 | |
|             PropertyTranslator translator = _parameterTranslators[i];
 | |
|             action(translator, parameter);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void ExportExtensionMethodOverloads(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         foreach (FunctionOverload overload in _overloads)
 | |
|         {
 | |
|             builder.AppendLine();
 | |
|             ExportDeprecation(builder);
 | |
| 
 | |
|             string returnType = "void";
 | |
|             string returnStatement = "";
 | |
|             if (Function.ReturnProperty != null)
 | |
|             {
 | |
|                 returnType = ReturnValueTranslator!.GetManagedType(Function.ReturnProperty);
 | |
|                 returnStatement = "return ";
 | |
|             }
 | |
| 
 | |
|             List<string> genericTypes = new List<string>();
 | |
|             List<string> genericConstraints = new List<string>();
 | |
|             if (_hasGenericTypeSupport)
 | |
|             {
 | |
|                 genericTypes.Add("DOT");
 | |
|                 genericConstraints.Add(Function.GetGenericTypeConstraint());
 | |
|             }
 | |
| 
 | |
|             if (_hasCustomStructParamSupport)
 | |
|             {
 | |
|                 genericTypes.AddRange(_customStructParamTypes);
 | |
|                 genericConstraints.AddRange(_customStructParamTypes.ConvertAll(paramType => $"MarshalledStruct<{paramType}>"));
 | |
|             }
 | |
| 
 | |
|             string genericTypeString = string.Join(", ", genericTypes);
 | |
| 
 | |
|             if (genericTypes.Count > 0)
 | |
|             {
 | |
|                 PropertyTranslator translator = _parameterTranslators[0];
 | |
|                 string paramType = _classBeingExtended != null
 | |
|                     ? _classBeingExtended.GetFullManagedName()
 | |
|                     : translator.GetManagedType(_selfParameter!);
 | |
|                 builder.AppendLine($"{Modifiers}{returnType} {_functionName}<{genericTypeString}>(this {paramType} {_selfParameter!.GetParameterName()}, {overload.ParamStringApiWithDefaults})");
 | |
|                 builder.Indent();
 | |
|                 foreach (var (genericType, constraint) in genericTypes.Zip(genericConstraints))
 | |
|                     builder.AppendLine($"where {genericType} : {constraint}");
 | |
|                 builder.UnIndent();
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine($"{Modifiers}{returnType} {_functionName}(this {overload.ParamStringApiWithDefaults})");
 | |
|             }
 | |
| 
 | |
|             builder.OpenBrace();
 | |
|             overload.Translator?.ExportCppDefaultParameterAsLocalVariable(builder, overload.CSharpParamName, overload.CppDefaultValue, Function, overload.Parameter);
 | |
| 
 | |
|             UhtClass functionOwner = (UhtClass) Function.Outer!;
 | |
|             string fullClassName = functionOwner.GetFullManagedName();
 | |
|             if (genericTypes.Count > 0)
 | |
|             {
 | |
|                 builder.AppendLine($"{returnStatement}{fullClassName}.{_functionName}<{genericTypeString}>({overload.ParamsStringCall});");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine($"{returnStatement}{fullClassName}.{_functionName}({overload.ParamsStringCall});");
 | |
|             }
 | |
|             builder.CloseBrace();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void ExportExtensionMethod(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         builder.AppendLine();
 | |
|         builder.AppendTooltip(Function);
 | |
|         ExportDeprecation(builder);
 | |
| 
 | |
|         string returnManagedType = "void";
 | |
|         if (ReturnValueTranslator != null)
 | |
|         {
 | |
|             returnManagedType = ReturnValueTranslator.GetManagedType(Function.ReturnProperty!);
 | |
|         }
 | |
|         
 | |
|         string functionNameToUse = Function.IsAutocast() ? Function.GetBlueprintAutocastName() : _functionName;
 | |
|         
 | |
|         List<string> genericTypes = new List<string>();
 | |
|         List<string> genericConstraints = new List<string>();
 | |
|         if (_hasGenericTypeSupport)
 | |
|         {
 | |
|             genericTypes.Add("DOT");
 | |
|             genericConstraints.Add(Function.GetGenericTypeConstraint());
 | |
|         }
 | |
| 
 | |
|         if (_hasCustomStructParamSupport)
 | |
|         {
 | |
|             genericTypes.AddRange(_customStructParamTypes);
 | |
|             genericConstraints.AddRange(_customStructParamTypes.ConvertAll(paramType => $"MarshalledStruct<{paramType}>"));
 | |
|         }
 | |
| 
 | |
|         string genericTypeString = string.Join(", ", genericTypes);
 | |
| 
 | |
|         if (genericTypes.Count > 0)
 | |
|         {
 | |
|             builder.AppendLine($"{Modifiers}{returnManagedType} {functionNameToUse}<{genericTypeString}>({_paramStringApiWithDefaults})");
 | |
|             builder.Indent();
 | |
|             foreach (var (genericType, constraint) in genericTypes.Zip(genericConstraints))
 | |
|                 builder.AppendLine($"where {genericType} : {constraint}");
 | |
|             builder.UnIndent();
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             builder.AppendLine($"{Modifiers}{returnManagedType} {functionNameToUse}({_paramStringApiWithDefaults})");
 | |
|         }
 | |
|         
 | |
|         builder.OpenBrace();
 | |
|         string returnStatement = Function.ReturnProperty != null ? "return " : "";
 | |
|         UhtClass functionOwner = (UhtClass) Function.Outer!;
 | |
| 
 | |
|         string fullClassName = functionOwner.GetFullManagedName();
 | |
|         builder.AppendLine($"{returnStatement}{fullClassName}.{_functionName}({_paramsStringCall});");
 | |
|         builder.CloseBrace();
 | |
|     }
 | |
| 
 | |
|     public void ExportFunctionVariables(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         builder.AppendLine($"// {Function.SourceName}");
 | |
| 
 | |
|         if (!BlueprintImplementableEvent)
 | |
|         {
 | |
|             builder.AppendLine($"static IntPtr {NativeFunctionIntPtr};");
 | |
|         }
 | |
| 
 | |
|         if (BlueprintEvent)
 | |
|         {
 | |
|             builder.AppendLine($"IntPtr {InstanceFunctionPtr};");
 | |
|         }
 | |
|         
 | |
|         if (Function.HasParametersOrReturnValue())
 | |
|         {
 | |
|             if (_hasCustomStructParamSupport)
 | |
|             {
 | |
|                 string genericTypes = string.Join(", ", _customStructParamTypes);
 | |
|                 builder.AppendLine($"static int {Function.SourceName}_NativeParamsSize;");
 | |
|                 builder.AppendLine($"static int {Function.SourceName}_ParamsSize<{genericTypes}>()");
 | |
|                 builder.Indent();
 | |
|                 foreach (string genericType in _customStructParamTypes)
 | |
|                 {
 | |
|                     builder.AppendLine($"where {genericType}: MarshalledStruct<{genericType}>");
 | |
|                 }
 | |
|                 List<string> variableNames = new List<string>{$"{Function.SourceName}_NativeParamsSize"};
 | |
|                 int customStructureParamIndex = 0;
 | |
|                 ForEachParameter((translator, parameter) =>
 | |
|                 {
 | |
|                     if (!parameter.IsCustomStructureType()) return;
 | |
|                     variableNames.Add($"{_customStructParamTypes[customStructureParamIndex]}.GetNativeDataSize()");
 | |
|                     customStructureParamIndex++;
 | |
|                 });
 | |
|                 builder.AppendLine($"=> {string.Join(" + ", variableNames)};");
 | |
|                 builder.UnIndent();
 | |
|                 builder.AppendLine($"static IntPtr[] {Function.SourceName}_CustomStructureNativeProperties;");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine($"static int {Function.SourceName}_ParamsSize;");
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         ForEachParameter((translator, parameter) =>
 | |
|         {
 | |
|             translator.ExportParameterVariables(builder, Function, Function.SourceName, parameter, parameter.SourceName);
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     void ExportOverloads(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         foreach (FunctionOverload overload in _overloads)
 | |
|         {
 | |
|             builder.AppendLine();
 | |
|             ExportDeprecation(builder);
 | |
| 
 | |
|             string returnType = "void";
 | |
|             string returnStatement = "";
 | |
|             if (Function.ReturnProperty != null)
 | |
|             {
 | |
|                 returnType = ReturnValueTranslator!.GetManagedType(Function.ReturnProperty);
 | |
|                 returnStatement = "return ";
 | |
|             }
 | |
| 
 | |
|             List<string> genericTypes = new List<string>();
 | |
|             List<string> genericConstraints = new List<string>();
 | |
|             if (_hasGenericTypeSupport)
 | |
|             {
 | |
|                 genericTypes.Add("DOT");
 | |
|                 genericConstraints.Add(Function.GetGenericTypeConstraint());
 | |
|             }
 | |
| 
 | |
|             if (_hasCustomStructParamSupport)
 | |
|             {
 | |
|                 genericTypes.AddRange(_customStructParamTypes);
 | |
|                 genericConstraints.AddRange(_customStructParamTypes.ConvertAll(paramType => $"MarshalledStruct<{paramType}>"));
 | |
|             }
 | |
| 
 | |
|             string genericTypeString = string.Join(", ", genericTypes);
 | |
| 
 | |
|             if (genericTypes.Count > 0)
 | |
|             {
 | |
|                 builder.AppendLine($"{Modifiers}{returnType} {_functionName}<{genericTypeString}>({overload.ParamStringApiWithDefaults})");
 | |
|                 builder.Indent();
 | |
|                 foreach (var (genericType, constraint) in genericTypes.Zip(genericConstraints))
 | |
|                     builder.AppendLine($"where {genericType} : {constraint}");
 | |
|                 builder.UnIndent();
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine($"{Modifiers}{returnType} {_functionName}({overload.ParamStringApiWithDefaults})");
 | |
|             }
 | |
| 
 | |
|             builder.OpenBrace();
 | |
|             overload.Translator?.ExportCppDefaultParameterAsLocalVariable(builder, overload.CSharpParamName, overload.CppDefaultValue, Function, overload.Parameter);
 | |
| 
 | |
|             if (genericTypes.Count > 0)
 | |
|             {
 | |
|                 builder.AppendLine($"{returnStatement}{_functionName}<{genericTypeString}>({overload.ParamsStringCall});");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine($"{returnStatement}{_functionName}({overload.ParamsStringCall});");
 | |
|             }
 | |
|             builder.CloseBrace();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     void ExportFunction(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         builder.AppendLine();
 | |
|         ExportDeprecation(builder);
 | |
|         ExportSpecializationGetter(builder);
 | |
|         
 | |
|         ExportSignature(builder, Modifiers);
 | |
|         
 | |
|         builder.OpenBrace();
 | |
|         
 | |
|         if (Throwing)
 | |
|         {
 | |
|             builder.AppendLine($"throw new InvalidOperationException(\"Function {Function.EngineName} cannot be called on a Blueprint-only implementer\");");
 | |
|         }
 | |
|         
 | |
|         else if (BlueprintEvent)
 | |
|         {
 | |
|             builder.AppendLine($"if ({InstanceFunctionPtr} == IntPtr.Zero)");
 | |
|             builder.OpenBrace();
 | |
|             builder.AppendLine($"{InstanceFunctionPtr} = {ExporterCallbacks.UClassCallbacks}.CallGetNativeFunctionFromInstanceAndName(NativeObject, \"{Function.EngineName}\");");
 | |
|             builder.CloseBrace();
 | |
| 
 | |
|             if (BlueprintImplementableEvent)
 | |
|             {
 | |
|                 builder.AppendLine($"if (!{ExporterCallbacks.UFunctionCallbacks}.IsFunctionImplemented({InstanceFunctionPtr}))");
 | |
|                 builder.OpenBrace();
 | |
|                 builder.AppendLine($"throw new System.NotImplementedException(\"Tried calling {Function.Outer!.EngineName}.{_functionName} which is not implemented in C# or Blueprint!\");");
 | |
|                 builder.CloseBrace();
 | |
|             }
 | |
|             
 | |
|             ExportInvoke(builder, InstanceFunctionPtr);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             ExportInvoke(builder);
 | |
|         }
 | |
|         
 | |
|         builder.CloseBrace();
 | |
|         builder.AppendLine();
 | |
|     }
 | |
| 
 | |
|     public void ExportInvoke(GeneratorStringBuilder builder, string functionPtr = "")
 | |
|     {
 | |
|         builder.BeginUnsafeBlock();
 | |
|         string nativeFunctionIntPtr = string.IsNullOrEmpty(functionPtr) ? NativeFunctionIntPtr : functionPtr;
 | |
|         
 | |
|         if (!Function.HasParametersOrReturnValue())
 | |
|         {
 | |
|             if (string.IsNullOrEmpty(_customInvoke))
 | |
|             {
 | |
|                 builder.AppendLine($"{_invokeFunction}({_invokeFirstArgument}, {nativeFunctionIntPtr}, {ScriptGeneratorUtilities.IntPtrZero}, {ScriptGeneratorUtilities.IntPtrZero});");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine(_customInvoke);
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (_hasCustomStructParamSupport)
 | |
|             {
 | |
|                 string genericTypes = string.Join(", ", _customStructParamTypes);
 | |
|                 builder.AppendLine($"IntPtr Specialization = {Function.SourceName}_GetSpecialization<{genericTypes}>();");
 | |
|                 builder.AppendStackAllocFunction($"{Function.SourceName}_ParamsSize<{genericTypes}>()",
 | |
|                     "Specialization");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendStackAllocFunction($"{Function.SourceName}_ParamsSize", 
 | |
|                     nativeFunctionIntPtr, 
 | |
|                     !BlittableFunction);
 | |
|             }
 | |
| 
 | |
|             ForEachParameter((translator, parameter) =>
 | |
|             {
 | |
|                 if (parameter.HasAllFlags(EPropertyFlags.ReturnParm))
 | |
|                 {
 | |
|                     return;
 | |
|                 }
 | |
|                 
 | |
|                 string propertyName = GetParameterName(parameter);
 | |
|                 
 | |
|                 if (parameter.HasAllFlags(EPropertyFlags.ReferenceParm) || !parameter.HasAllFlags(EPropertyFlags.OutParm))
 | |
|                 {
 | |
|                     string offsetName = TryAddPrecedingCustomStructParams(parameter, parameter.GetOffsetVariableName());
 | |
|                     translator.ExportToNative(builder, parameter, parameter.SourceName, "paramsBuffer", offsetName, propertyName);
 | |
|                 }
 | |
|             });
 | |
|             
 | |
|             builder.AppendLine();
 | |
| 
 | |
|             if (string.IsNullOrEmpty(_customInvoke))
 | |
|             {
 | |
|                 string invokedFunctionIntPtr = _hasCustomStructParamSupport ? "Specialization" : nativeFunctionIntPtr;
 | |
|                 
 | |
|                 string returnValueAddressStr = Function.ReturnProperty != null
 | |
|                     ? $"paramsBuffer + {TryAddPrecedingCustomStructParams(Function.ReturnProperty, Function.ReturnProperty.GetOffsetVariableName())}"
 | |
|                     : ScriptGeneratorUtilities.IntPtrZero;
 | |
|                 
 | |
|                 builder.AppendLine($"{_invokeFunction}({_invokeFirstArgument}, {invokedFunctionIntPtr}, paramsBuffer, {returnValueAddressStr});");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 builder.AppendLine(_customInvoke);
 | |
|             }
 | |
| 
 | |
|             if (Function.ReturnProperty != null || Function.HasOutParams())
 | |
|             {
 | |
|                 builder.AppendLine();
 | |
| 
 | |
|                 ForEachParameter((translator, parameter) =>
 | |
|                 {
 | |
|                     if (!parameter.HasAllFlags(EPropertyFlags.ReturnParm) &&
 | |
|                         (parameter.HasAllFlags(EPropertyFlags.ConstParm) ||
 | |
|                          !parameter.HasAllFlags(EPropertyFlags.OutParm)))
 | |
|                     {
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
|                     string marshalDestination;
 | |
|                     if (parameter.HasAllFlags(EPropertyFlags.ReturnParm))
 | |
|                     {
 | |
|                         builder.AppendLine($"{ReturnValueTranslator!.GetManagedType(parameter)} returnValue;");
 | |
|                         marshalDestination = "returnValue";
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         marshalDestination = MakeOutMarshalDestination(parameter, translator, builder);
 | |
|                     }
 | |
| 
 | |
|                     string offsetName = TryAddPrecedingCustomStructParams(parameter, parameter.GetOffsetVariableName());
 | |
| 
 | |
|                     translator.ExportFromNative(builder,
 | |
|                         parameter,
 | |
|                         parameter.SourceName,
 | |
|                         $"{marshalDestination} =",
 | |
|                         "paramsBuffer",
 | |
|                         offsetName,
 | |
|                         true,
 | |
|                         parameter.HasAllFlags(EPropertyFlags.ReferenceParm) &&
 | |
|                         !parameter.HasAllFlags(EPropertyFlags.ReturnParm));
 | |
|                 });
 | |
|             }
 | |
|             
 | |
|             builder.AppendLine();
 | |
|             
 | |
|             ForEachParameter((translator, parameter) =>
 | |
|             {
 | |
|                 if (!parameter.HasAnyFlags(EPropertyFlags.ReturnParm | EPropertyFlags.OutParm))
 | |
|                 {
 | |
|                     translator.ExportCleanupMarshallingBuffer(builder, parameter, parameter.SourceName);
 | |
|                 }
 | |
|             });
 | |
|             
 | |
|             ExportReturnStatement(builder);
 | |
|         }
 | |
|         builder.EndUnsafeBlock();
 | |
|     }
 | |
|     
 | |
|     protected virtual string MakeOutMarshalDestination(UhtProperty parameter, PropertyTranslator propertyTranslator, GeneratorStringBuilder builder)
 | |
|     {
 | |
|         return GetParameterName(parameter);
 | |
|     }
 | |
|     
 | |
|     protected virtual void ExportReturnStatement(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         if (Function.ReturnProperty != null)
 | |
|         {
 | |
|             builder.AppendLine("return returnValue;");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void ExportSignature(GeneratorStringBuilder builder, string protection)
 | |
|     {
 | |
|         builder.AppendTooltip(Function);
 | |
| 
 | |
|         AttributeBuilder attributeBuilder = new AttributeBuilder(Function);
 | |
|         
 | |
|         if (BlueprintEvent)
 | |
|         {
 | |
|             attributeBuilder.AddArgument("FunctionFlags.BlueprintEvent");
 | |
|         }
 | |
|         
 | |
|         attributeBuilder.AddGeneratedTypeAttribute(Function);
 | |
| 
 | |
|         if (_hasGenericTypeSupport)
 | |
|         {
 | |
|             if (Function.HasMetadata("DeterminesOutputType"))
 | |
|             {
 | |
|                 attributeBuilder.AddAttribute("UMetaData");
 | |
|                 attributeBuilder.AddArgument($"\"DeterminesOutputType\"");
 | |
|                 attributeBuilder.AddArgument($"\"{Function.GetMetadata("DeterminesOutputType")}\"");
 | |
|             }
 | |
| 
 | |
|             if (Function.HasMetadata("DynamicOutputParam"))
 | |
|             {
 | |
|                 attributeBuilder.AddAttribute("UMetaData");
 | |
|                 attributeBuilder.AddArgument($"\"DynamicOutputParam\"");
 | |
|                 attributeBuilder.AddArgument($"\"{Function.GetMetadata("DynamicOutputParam")}\"");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (_hasCustomStructParamSupport)
 | |
|         {
 | |
|             attributeBuilder.AddAttribute("UMetaData");
 | |
|             attributeBuilder.AddArgument($"\"CustomStructureParam\"");
 | |
|             attributeBuilder.AddArgument($"\"{Function.GetMetadata("CustomStructureParam")}\"");
 | |
|         }
 | |
| 
 | |
|         attributeBuilder.Finish();
 | |
|         builder.AppendLine(attributeBuilder.ToString());
 | |
| 
 | |
|         string returnType = Function.ReturnProperty != null
 | |
|             ? ReturnValueTranslator!.GetManagedType(Function.ReturnProperty)
 | |
|             : "void";
 | |
| 
 | |
|         List<string> genericTypes = new List<string>();
 | |
|         List<string> genericConstraints = new List<string>();
 | |
|         if (_hasGenericTypeSupport)
 | |
|         {
 | |
|             genericTypes.Add("DOT");
 | |
|             genericConstraints.Add(Function.GetGenericTypeConstraint());
 | |
|         }
 | |
| 
 | |
|         if (_hasCustomStructParamSupport)
 | |
|         {
 | |
|             genericTypes.AddRange(_customStructParamTypes);
 | |
|             genericConstraints.AddRange(_customStructParamTypes.ConvertAll(paramType => $"MarshalledStruct<{paramType}>"));
 | |
|         }
 | |
| 
 | |
|         if (genericTypes.Count > 0)
 | |
|         {
 | |
|             builder.AppendLine($"{protection}{returnType} {_functionName}<{string.Join(", ", genericTypes)}>({_paramStringApiWithDefaults})");
 | |
|             builder.Indent();
 | |
|             foreach (var (genericType, constraint) in genericTypes.Zip(genericConstraints))
 | |
|                 builder.AppendLine($"where {genericType} : {constraint}");
 | |
|             builder.UnIndent();
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             builder.AppendLine($"{protection}{returnType} {_functionName}({_paramStringApiWithDefaults})");
 | |
|         }
 | |
|     }
 | |
|     
 | |
| 
 | |
|     void ExportDeprecation(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         if (Function.HasMetadata("DeprecatedFunction"))
 | |
|         {
 | |
|             string deprecationMessage = Function.GetMetadata("DeprecationMessage");
 | |
|             if (deprecationMessage.Length == 0)
 | |
|             {
 | |
|                 deprecationMessage = "This function is deprecated.";
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // Remove nested quotes
 | |
|                 deprecationMessage = deprecationMessage.Replace("\"", "");
 | |
|             }
 | |
|             builder.AppendLine($"[Obsolete(\"{Function.SourceName} is deprecated: {deprecationMessage}\")]");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void ExportSpecializationGetter(GeneratorStringBuilder builder)
 | |
|     {
 | |
|         if (_hasCustomStructParamSupport)
 | |
|         {
 | |
|             int customStructureParamCount = _customStructParamTypes.Count;
 | |
|             string dictionaryKey = customStructureParamCount == 1
 | |
|                 ? "IntPtr"
 | |
|                 : $"({string.Join(", ", Enumerable.Repeat("IntPtr", customStructureParamCount))})";
 | |
|             builder.AppendLine($"static Dictionary<{dictionaryKey}, IntPtr> {Function.SourceName}_Specializations = new Dictionary<{dictionaryKey}, IntPtr>();");
 | |
|             builder.AppendLine($"static IntPtr {Function.SourceName}_GetSpecialization<{string.Join(", ", _customStructParamTypes)}>()");
 | |
|             builder.Indent();
 | |
|             foreach (string customStructParamType in _customStructParamTypes)
 | |
|             {
 | |
|                 builder.AppendLine($"where {customStructParamType} : MarshalledStruct<{customStructParamType}>");
 | |
|             }
 | |
|             builder.UnIndent();
 | |
|             builder.OpenBrace();
 | |
|             builder.AppendLine("IntPtr specializationNativeFunction;");
 | |
|             List<string> nativeClassPtrs = _customStructParamTypes.ConvertAll(customStructParamType =>
 | |
|                 $"{customStructParamType}.GetNativeClassPtr()");
 | |
|             string specializationKeyInitializer = nativeClassPtrs.Count == 1 ? nativeClassPtrs[0] : $"({string.Join(", ", nativeClassPtrs)})";
 | |
|             builder.AppendLine($"{dictionaryKey} specializationKey = {specializationKeyInitializer};");
 | |
|             builder.AppendLine($"if(!{Function.SourceName}_Specializations.TryGetValue(specializationKey, out specializationNativeFunction))");
 | |
|             builder.OpenBrace();
 | |
|             builder.BeginUnsafeBlock();
 | |
|             string customStructBufferInitializationList = customStructureParamCount == 1 ? "specializationKey" : string.Join(", ", Enumerable.Range(1, customStructureParamCount).ToList().ConvertAll(i => $"specializationKey.Item{i}"));
 | |
|             builder.AppendLine($"IntPtr* customStructBufferAllocation = stackalloc IntPtr[]{{{customStructBufferInitializationList}}};");
 | |
|             builder.AppendLine("IntPtr customStructBuffer = (IntPtr) customStructBufferAllocation;");
 | |
|             string nativeFunctionIntPtr = $"{Function.SourceName}_NativeFunction";
 | |
|             string customStructNativePropertiesIntPtr = $"{Function.SourceName}_CustomStructureNativeProperties";
 | |
|             builder.AppendLine($"fixed(nint* nativePropertyBuffer = {customStructNativePropertiesIntPtr})");
 | |
|             builder.OpenBrace();
 | |
|             builder.AppendLine($"specializationNativeFunction = {ExporterCallbacks.UFunctionCallbacks}.CallCreateNativeFunctionCustomStructSpecialization({nativeFunctionIntPtr}, (nint) nativePropertyBuffer, customStructBuffer);");
 | |
|             builder.CloseBrace();
 | |
|             builder.AppendLine($"{Function.SourceName}_Specializations.Add(specializationKey, specializationNativeFunction);");
 | |
|             builder.EndUnsafeBlock();
 | |
|             builder.CloseBrace();
 | |
|             builder.AppendLine("return specializationNativeFunction;");
 | |
|             builder.CloseBrace();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void DetermineProtectionMode()
 | |
|     {
 | |
|         switch (_protectionMode)
 | |
|         {
 | |
|             case EFunctionProtectionMode.UseUFunctionProtection:
 | |
|                 if (Function.HasAnyFlags(EFunctionFlags.Public | EFunctionFlags.BlueprintCallable))
 | |
|                 {
 | |
|                     Modifiers = ScriptGeneratorUtilities.PublicKeyword;
 | |
|                 }
 | |
|                 else if (Function.HasAllFlags(EFunctionFlags.Protected) || Function.HasMetadata("BlueprintProtected"))
 | |
|                 {
 | |
|                     Modifiers = ScriptGeneratorUtilities.ProtectedKeyword;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Modifiers = ScriptGeneratorUtilities.PrivateKeyword;
 | |
|                 }
 | |
|                 break;
 | |
|             case EFunctionProtectionMode.OverrideWithInternal:
 | |
|                 Modifiers = "internal ";
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     string DetermineInvokeFunction()
 | |
|     {
 | |
|         string invokeFunction = ExporterCallbacks.UObjectCallbacks;
 | |
|         
 | |
|         if (Function.HasAllFlags(EFunctionFlags.Static))
 | |
|         {
 | |
|             return invokeFunction + ".CallInvokeNativeStaticFunction";
 | |
|         }
 | |
|         
 | |
|         if (Function.HasAllFlags(EFunctionFlags.Net))
 | |
|         {
 | |
|             return invokeFunction + ".CallInvokeNativeNetFunction";
 | |
|         }
 | |
|         
 | |
|         if (Function.HasAllFlags(EFunctionFlags.HasOutParms) || Function.HasReturnProperty)
 | |
|         {
 | |
|             return invokeFunction + ".CallInvokeNativeFunctionOutParms";
 | |
|         } 
 | |
|         
 | |
|         return invokeFunction + ".CallInvokeNativeFunction";
 | |
|     }
 | |
|     
 | |
|     public string TryAddPrecedingCustomStructParams(UhtProperty parameter, string name)
 | |
|     {
 | |
|         if (!_hasCustomStructParamSupport)
 | |
|         {
 | |
|             return name;
 | |
|         }
 | |
|         
 | |
|         int precedingCustomStructParams = parameter.GetPrecedingCustomStructParams();
 | |
|         if (precedingCustomStructParams > 0)
 | |
|         {
 | |
|             return name + $"<{string.Join(", ", _customStructParamTypes.GetRange(0, precedingCustomStructParams))}>()";
 | |
|         }
 | |
|         
 | |
|         return name;
 | |
|     }
 | |
| }
 |