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;
 | 
						|
    }
 | 
						|
}
 |