541 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			541 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using EpicGames.UHT.Types;
 | 
						|
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Text;
 | 
						|
using UnrealSharpScriptGenerator.PropertyTranslators;
 | 
						|
using UnrealSharpScriptGenerator.Tooltip;
 | 
						|
using UnrealSharpScriptGenerator.Utilities;
 | 
						|
 | 
						|
namespace UnrealSharpScriptGenerator.Exporters;
 | 
						|
 | 
						|
public static class StructExporter
 | 
						|
{
 | 
						|
    public static void ExportStruct(UhtScriptStruct structObj, bool isManualExport)
 | 
						|
    {
 | 
						|
        GeneratorStringBuilder stringBuilder = new();
 | 
						|
        List<UhtProperty> exportedProperties = new();
 | 
						|
        Dictionary<UhtProperty, GetterSetterPair> getSetBackedProperties = new();
 | 
						|
        List<UhtStruct> inheritanceHierarchy = new();
 | 
						|
        UhtStruct? currentStruct = structObj;
 | 
						|
        while (currentStruct is not null)
 | 
						|
        {
 | 
						|
            inheritanceHierarchy.Add(currentStruct);
 | 
						|
            currentStruct = currentStruct.SuperStruct;
 | 
						|
        }
 | 
						|
 | 
						|
        inheritanceHierarchy.Reverse();
 | 
						|
        foreach (UhtStruct inheritance in inheritanceHierarchy)
 | 
						|
        {
 | 
						|
            ScriptGeneratorUtilities.GetExportedProperties(inheritance, exportedProperties, getSetBackedProperties);
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Check there are not properties with the same name, remove otherwise
 | 
						|
        List<string> propertyNames = new();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetParameterName();
 | 
						|
            if (propertyNames.Contains(scriptName))
 | 
						|
            {
 | 
						|
                exportedProperties.RemoveAt(i);
 | 
						|
                i--;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                propertyNames.Add(scriptName);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        bool nullableEnabled = structObj.HasMetadata(UhtTypeUtilities.NullableEnable);
 | 
						|
        bool isRecordStruct = structObj.HasMetadata("RecordStruct");
 | 
						|
        bool isReadOnly = structObj.HasMetadata("ReadOnly");
 | 
						|
        bool useProperties = structObj.HasMetadata("UseProperties");
 | 
						|
        bool isBlittable = structObj.IsStructBlittable();
 | 
						|
        bool isCopyable = structObj.IsStructNativelyCopyable();
 | 
						|
        bool isDestructible = structObj.IsStructNativelyDestructible();
 | 
						|
        bool isEquatable = structObj.IsStructEquatable(exportedProperties);
 | 
						|
 | 
						|
        string typeNameSpace = structObj.GetNamespace();
 | 
						|
        stringBuilder.GenerateTypeSkeleton(typeNameSpace, isBlittable, nullableEnabled);
 | 
						|
                
 | 
						|
        stringBuilder.AppendTooltip(structObj);
 | 
						|
        
 | 
						|
        AttributeBuilder attributeBuilder = new AttributeBuilder(structObj);
 | 
						|
        if (isBlittable)
 | 
						|
        {
 | 
						|
            attributeBuilder.AddIsBlittableAttribute();
 | 
						|
            attributeBuilder.AddStructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential);
 | 
						|
        }
 | 
						|
        attributeBuilder.AddGeneratedTypeAttribute(structObj);
 | 
						|
        attributeBuilder.Finish();
 | 
						|
        stringBuilder.AppendLine(attributeBuilder.ToString());
 | 
						|
 | 
						|
        string structName = structObj.GetStructName();
 | 
						|
        List<string>? csInterfaces = null;
 | 
						|
 | 
						|
        if (isBlittable || !isManualExport) 
 | 
						|
        { 
 | 
						|
            csInterfaces = new List<string> { $"MarshalledStruct<{structName}>" };
 | 
						|
            
 | 
						|
            if (isDestructible) 
 | 
						|
            {
 | 
						|
                csInterfaces.Add("IDisposable");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (isEquatable)
 | 
						|
        {
 | 
						|
            // If null create the list and add the interface
 | 
						|
            (csInterfaces ??= new()).Add($"IEquatable<{structName}>");
 | 
						|
        }
 | 
						|
 | 
						|
        stringBuilder.DeclareType(structObj, isRecordStruct ? "record struct" : "struct", structName, csInterfaces: csInterfaces, 
 | 
						|
            modifiers: isReadOnly ? " readonly" : null);
 | 
						|
 | 
						|
        if (isCopyable)
 | 
						|
        {
 | 
						|
            stringBuilder.AppendLine(isDestructible
 | 
						|
                ? "private NativeStructHandle NativeHandle;"
 | 
						|
                : "private byte[] Allocation;");
 | 
						|
        }
 | 
						|
        
 | 
						|
        // For manual exports we just want to generate attributes
 | 
						|
        if (!isManualExport)
 | 
						|
        {
 | 
						|
            List<string> reservedNames = GetReservedNames(exportedProperties);
 | 
						|
 | 
						|
            ExportStructProperties(structObj, stringBuilder, exportedProperties, isBlittable, reservedNames, isReadOnly, useProperties);
 | 
						|
        }
 | 
						|
 | 
						|
        if (isBlittable)
 | 
						|
        {
 | 
						|
            StaticConstructorUtilities.ExportStaticConstructor(stringBuilder, structObj, 
 | 
						|
                new List<UhtProperty>(), 
 | 
						|
                new List<UhtFunction>(),
 | 
						|
                new Dictionary<string, GetterSetterPair>(),
 | 
						|
                new Dictionary<UhtProperty, GetterSetterPair>(),
 | 
						|
                new List<UhtFunction>(), 
 | 
						|
                true);
 | 
						|
            stringBuilder.AppendLine();
 | 
						|
            stringBuilder.AppendLine($"public static {structName} FromNative(IntPtr buffer) => BlittableMarshaller<{structName}>.FromNative(buffer, 0);");
 | 
						|
            stringBuilder.AppendLine();
 | 
						|
            stringBuilder.AppendLine($"public void ToNative(IntPtr buffer) => BlittableMarshaller<{structName}>.ToNative(buffer, 0, this);");
 | 
						|
        }
 | 
						|
        else if (!isManualExport)
 | 
						|
        {
 | 
						|
            stringBuilder.AppendLine();
 | 
						|
            StaticConstructorUtilities.ExportStaticConstructor(stringBuilder, structObj, exportedProperties, 
 | 
						|
                new List<UhtFunction>(), 
 | 
						|
                new Dictionary<string, GetterSetterPair>(), 
 | 
						|
                new Dictionary<UhtProperty, GetterSetterPair>(),
 | 
						|
                new List<UhtFunction>());
 | 
						|
            
 | 
						|
            stringBuilder.AppendLine();
 | 
						|
            ExportMirrorStructMarshalling(stringBuilder, structObj, exportedProperties);
 | 
						|
 | 
						|
            if (isDestructible) 
 | 
						|
            {
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
                stringBuilder.AppendLine("public void Dispose()");
 | 
						|
                stringBuilder.OpenBrace();
 | 
						|
                stringBuilder.AppendLine("NativeHandle?.Dispose();");
 | 
						|
                stringBuilder.CloseBrace();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (isEquatable)
 | 
						|
        {
 | 
						|
            ExportStructEquality(structObj, structName, stringBuilder, exportedProperties);
 | 
						|
        }
 | 
						|
 | 
						|
        if (structObj.CanSupportArithmetic(exportedProperties))
 | 
						|
        {
 | 
						|
            ExportStructArithmetic(structObj, structName, stringBuilder, exportedProperties);
 | 
						|
        }
 | 
						|
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        if (!isBlittable && !isManualExport)
 | 
						|
        {
 | 
						|
            ExportStructMarshaller(stringBuilder, structObj);
 | 
						|
        }
 | 
						|
        
 | 
						|
        
 | 
						|
        FileExporter.SaveGlueToDisk(structObj, stringBuilder);
 | 
						|
    }
 | 
						|
 | 
						|
    public static void ExportStructEquality(UhtStruct structObj, string structName, GeneratorStringBuilder stringBuilder, List<UhtProperty> exportedProperties)
 | 
						|
    {
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public override bool Equals(object? obj)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return obj is {structName} other && Equals(other);");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
        
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public bool Equals({structName} other)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        if (exportedProperties.Count == 0)
 | 
						|
        {
 | 
						|
            stringBuilder.AppendLine("return true;");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            StringBuilder equalitySb = new StringBuilder();
 | 
						|
            for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
            {
 | 
						|
                UhtProperty property = exportedProperties[i];
 | 
						|
                string scriptName = property.GetPropertyName();
 | 
						|
                equalitySb.Append($"this.{scriptName} == other.{scriptName}");
 | 
						|
                if (i < exportedProperties.Count - 1)
 | 
						|
                {
 | 
						|
                    equalitySb.Append(" && ");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            stringBuilder.AppendLine($"return {equalitySb};");
 | 
						|
        }
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine("public override int GetHashCode()");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        if (exportedProperties.Count == 0)
 | 
						|
        {
 | 
						|
            stringBuilder.AppendLine("return 0;");
 | 
						|
        }
 | 
						|
        // More accurate hashcode equality
 | 
						|
        else if (exportedProperties.Count <= 8)
 | 
						|
        {
 | 
						|
            StringBuilder hashSb = new StringBuilder();
 | 
						|
            for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
            {
 | 
						|
                UhtProperty property = exportedProperties[i];
 | 
						|
                string scriptName = property.GetPropertyName();
 | 
						|
                hashSb.Append($"{scriptName}");
 | 
						|
                if (i < exportedProperties.Count - 1)
 | 
						|
                {
 | 
						|
                    hashSb.Append(", ");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            stringBuilder.AppendLine($"return HashCode.Combine({hashSb});");
 | 
						|
        }
 | 
						|
        // Fallback to xor for more than 8 properties as HashCode.Combine only supports up to 8 parameters
 | 
						|
        else
 | 
						|
        {
 | 
						|
            StringBuilder hashSb = new StringBuilder();
 | 
						|
            for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
            {
 | 
						|
                UhtProperty property = exportedProperties[i];
 | 
						|
                string scriptName = property.GetPropertyName();
 | 
						|
                hashSb.Append($"{scriptName}.GetHashCode()");
 | 
						|
                if (i < exportedProperties.Count - 1)
 | 
						|
                {
 | 
						|
                    hashSb.Append(" ^ ");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            stringBuilder.AppendLine($"return {hashSb};");
 | 
						|
        }
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static bool operator ==({structName} left, {structName} right)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine("return left.Equals(right);");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static bool operator !=({structName} left, {structName} right)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine("return !(left == right);");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
    }
 | 
						|
 | 
						|
    public static void ExportStructArithmetic(UhtStruct structObj, string structName, GeneratorStringBuilder stringBuilder, List<UhtProperty> exportedProperties)
 | 
						|
    {
 | 
						|
        // Addition operator
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static {structName} operator +({structName} lhs, {structName} rhs)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return new {structName}");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetPropertyName();
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
 | 
						|
            translator.ExportPropertyArithmetic(stringBuilder, property, ArithmeticKind.Add);
 | 
						|
 | 
						|
            if (i < exportedProperties.Count - 1)
 | 
						|
            {
 | 
						|
                stringBuilder.Append(", ");
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        stringBuilder.UnIndent();
 | 
						|
        stringBuilder.AppendLine("};");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        // Subtraction operator
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static {structName} operator -({structName} lhs, {structName} rhs)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return new {structName}");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetPropertyName();
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
 | 
						|
            translator.ExportPropertyArithmetic(stringBuilder, property, ArithmeticKind.Subtract);
 | 
						|
 | 
						|
            if (i < exportedProperties.Count - 1)
 | 
						|
            {
 | 
						|
                stringBuilder.Append(", ");
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        stringBuilder.UnIndent();
 | 
						|
        stringBuilder.AppendLine("};");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        // Multiplication operator
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static {structName} operator *({structName} lhs, {structName} rhs)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return new {structName}");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetPropertyName();
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
 | 
						|
            translator.ExportPropertyArithmetic(stringBuilder, property, ArithmeticKind.Multiply);
 | 
						|
 | 
						|
            if (i < exportedProperties.Count - 1)
 | 
						|
            {
 | 
						|
                stringBuilder.Append(", ");
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        stringBuilder.UnIndent();
 | 
						|
        stringBuilder.AppendLine("};");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        // Division operator
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static {structName} operator /({structName} lhs, {structName} rhs)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return new {structName}");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetPropertyName();
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
 | 
						|
            translator.ExportPropertyArithmetic(stringBuilder, property, ArithmeticKind.Divide);
 | 
						|
 | 
						|
            if (i < exportedProperties.Count - 1)
 | 
						|
            {
 | 
						|
                stringBuilder.Append(", ");
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        stringBuilder.UnIndent();
 | 
						|
        stringBuilder.AppendLine("};");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
 | 
						|
        // Modulo operator
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        stringBuilder.AppendLine($"public static {structName} operator %({structName} lhs, {structName} rhs)");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine($"return new {structName}");
 | 
						|
        stringBuilder.OpenBrace();
 | 
						|
        stringBuilder.AppendLine();
 | 
						|
        for (int i = 0; i < exportedProperties.Count; i++)
 | 
						|
        {
 | 
						|
            UhtProperty property = exportedProperties[i];
 | 
						|
            string scriptName = property.GetPropertyName();
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
 | 
						|
            translator.ExportPropertyArithmetic(stringBuilder, property, ArithmeticKind.Modulo);
 | 
						|
 | 
						|
            if (i < exportedProperties.Count - 1)
 | 
						|
            {
 | 
						|
                stringBuilder.Append(", ");
 | 
						|
                stringBuilder.AppendLine();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        stringBuilder.UnIndent();
 | 
						|
        stringBuilder.AppendLine("};");
 | 
						|
        stringBuilder.CloseBrace();
 | 
						|
    }
 | 
						|
	
 | 
						|
    public static void ExportStructProperties(UhtStruct structObj, GeneratorStringBuilder stringBuilder, List<UhtProperty> exportedProperties, bool suppressOffsets, List<string> reservedNames, bool isReadOnly, bool useProperties)
 | 
						|
    {
 | 
						|
        foreach (UhtProperty property in exportedProperties)
 | 
						|
        {
 | 
						|
            PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
            translator.ExportMirrorProperty(structObj, stringBuilder, property, suppressOffsets, reservedNames, isReadOnly, useProperties);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    public static List<string> GetReservedNames(List<UhtProperty> properties)
 | 
						|
    {
 | 
						|
        List<string> reservedNames = new();
 | 
						|
        foreach (UhtProperty property in properties)
 | 
						|
        {
 | 
						|
            if (reservedNames.Contains(property.SourceName))
 | 
						|
            {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            reservedNames.Add(property.SourceName);
 | 
						|
        }
 | 
						|
        return reservedNames;
 | 
						|
    }
 | 
						|
 | 
						|
    public static void ExportStructMarshaller(GeneratorStringBuilder builder, UhtScriptStruct structObj)
 | 
						|
    {
 | 
						|
        string structName = structObj.GetStructName();
 | 
						|
        
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine($"public static class {structName}Marshaller");
 | 
						|
        builder.OpenBrace();
 | 
						|
        
 | 
						|
        builder.AppendLine($"public static {structName} FromNative(IntPtr nativeBuffer, int arrayIndex)");
 | 
						|
        builder.OpenBrace();
 | 
						|
        builder.AppendLine($"return new {structName}(nativeBuffer + (arrayIndex * GetNativeDataSize()));");
 | 
						|
        builder.CloseBrace();
 | 
						|
        
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine($"public static void ToNative(IntPtr nativeBuffer, int arrayIndex, {structName} obj)");
 | 
						|
        builder.OpenBrace();
 | 
						|
        builder.AppendLine($"obj.ToNative(nativeBuffer + (arrayIndex * GetNativeDataSize()));");
 | 
						|
        builder.CloseBrace();
 | 
						|
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine($"public static int GetNativeDataSize()");
 | 
						|
        builder.OpenBrace();
 | 
						|
        builder.AppendLine($"return {structName}.NativeDataSize;");
 | 
						|
        builder.CloseBrace();
 | 
						|
        builder.CloseBrace();
 | 
						|
    }
 | 
						|
 | 
						|
    public static void ExportMirrorStructMarshalling(GeneratorStringBuilder builder, UhtScriptStruct structObj, List<UhtProperty> properties)
 | 
						|
    {
 | 
						|
        string structName = structObj.GetStructName();
 | 
						|
        bool isCopyable = structObj.IsStructNativelyCopyable();
 | 
						|
        bool isDestructible = structObj.IsStructNativelyDestructible();
 | 
						|
        if (isCopyable)
 | 
						|
        {
 | 
						|
            builder.AppendLine();
 | 
						|
            builder.AppendLine($"public {structName}()");
 | 
						|
            builder.OpenBrace();
 | 
						|
            builder.AppendLine(isDestructible
 | 
						|
                ? "NativeHandle = new NativeStructHandle(NativeClassPtr);"
 | 
						|
                : "Allocation = new byte[NativeDataSize];");
 | 
						|
            builder.CloseBrace();
 | 
						|
        }
 | 
						|
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine("[System.Diagnostics.CodeAnalysis.SetsRequiredMembers]");
 | 
						|
        builder.AppendLine($"public {structName}(IntPtr InNativeStruct)");
 | 
						|
        builder.OpenBrace();
 | 
						|
        builder.BeginUnsafeBlock();
 | 
						|
 | 
						|
        if (isCopyable)
 | 
						|
        {
 | 
						|
            if (isDestructible)
 | 
						|
            {
 | 
						|
                builder.AppendLine("NativeHandle = new NativeStructHandle(NativeClassPtr);");
 | 
						|
                builder.AppendLine("fixed (NativeStructHandleData* StructDataPointer = &NativeHandle.Data)");
 | 
						|
                builder.OpenBrace();
 | 
						|
                builder.AppendLine($"IntPtr AllocationPointer = {ExporterCallbacks.UScriptStructCallbacks}.CallGetStructLocation(StructDataPointer, NativeClassPtr);");
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                builder.AppendLine("Allocation = new byte[NativeDataSize];");
 | 
						|
                builder.AppendLine("fixed (byte* AllocationPointer = Allocation)");
 | 
						|
                builder.OpenBrace();
 | 
						|
            }
 | 
						|
            
 | 
						|
            builder.AppendLine($"{ExporterCallbacks.UScriptStructCallbacks}.CallNativeCopy(NativeClassPtr, InNativeStruct, (nint) AllocationPointer);");
 | 
						|
            builder.CloseBrace();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            foreach (UhtProperty property in properties)
 | 
						|
            {
 | 
						|
                PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
                string scriptName = property.GetPropertyName();
 | 
						|
                string assignmentOrReturn = $"{scriptName} =";
 | 
						|
                string offsetName = $"{property.SourceName}_Offset";
 | 
						|
                builder.TryAddWithEditor(property);
 | 
						|
                translator.ExportFromNative(builder, property, property.SourceName, assignmentOrReturn, "InNativeStruct", offsetName, false, false);
 | 
						|
                builder.TryEndWithEditor(property);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        builder.EndUnsafeBlock();
 | 
						|
        builder.CloseBrace();
 | 
						|
        
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine($"public static {structName} FromNative(IntPtr buffer) => new {structName}(buffer);");
 | 
						|
        
 | 
						|
        builder.AppendLine();
 | 
						|
        builder.AppendLine("public void ToNative(IntPtr buffer)");
 | 
						|
        builder.OpenBrace();
 | 
						|
        builder.BeginUnsafeBlock();
 | 
						|
        
 | 
						|
        if (structObj.IsStructNativelyCopyable())
 | 
						|
        {
 | 
						|
            if (structObj.IsStructNativelyDestructible())
 | 
						|
            {
 | 
						|
                builder.AppendLine("if (NativeHandle is null)");
 | 
						|
                builder.OpenBrace();
 | 
						|
                builder.AppendLine("NativeHandle = new NativeStructHandle(NativeClassPtr);");
 | 
						|
                builder.CloseBrace();
 | 
						|
                builder.AppendLine();
 | 
						|
                builder.AppendLine("fixed (NativeStructHandleData* StructDataPointer = &NativeHandle.Data)");
 | 
						|
                builder.OpenBrace();
 | 
						|
                builder.AppendLine($"IntPtr AllocationPointer = {ExporterCallbacks.UScriptStructCallbacks}.CallGetStructLocation(StructDataPointer, NativeClassPtr);");
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                builder.AppendLine("if (Allocation is null)");
 | 
						|
                builder.OpenBrace();
 | 
						|
                builder.AppendLine("Allocation = new byte[NativeDataSize];");
 | 
						|
                builder.AppendLine();
 | 
						|
                builder.CloseBrace();
 | 
						|
                builder.AppendLine("fixed (byte* AllocationPointer = Allocation)");
 | 
						|
                builder.OpenBrace();
 | 
						|
            }
 | 
						|
            
 | 
						|
            builder.AppendLine($"{ExporterCallbacks.UScriptStructCallbacks}.CallNativeCopy(NativeClassPtr, (nint) AllocationPointer, buffer);");
 | 
						|
            builder.CloseBrace();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            foreach (UhtProperty property in properties)
 | 
						|
            {
 | 
						|
                PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(property)!;
 | 
						|
                string scriptName = property.GetPropertyName();
 | 
						|
                string offsetName = $"{property.SourceName}_Offset";
 | 
						|
                builder.TryAddWithEditor(property);
 | 
						|
                translator.ExportToNative(builder, property, property.SourceName, "buffer", offsetName, scriptName);
 | 
						|
                builder.TryEndWithEditor(property);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        builder.EndUnsafeBlock();
 | 
						|
        builder.CloseBrace();
 | 
						|
    }
 | 
						|
} |