Lua向C#逻辑迁移 一期 #13

将整个插件代码上传
This commit is contained in:
2025-10-26 21:48:39 +08:00
parent 56994b3927
commit 648386cd73
785 changed files with 53683 additions and 2 deletions

View File

@ -0,0 +1,17 @@
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class ArrayPropertyTranslator : ContainerPropertyTranslator
{
public ArrayPropertyTranslator()
: base("ArrayCopyMarshaller",
"ArrayReadOnlyMarshaller",
"ArrayMarshaller",
"IReadOnlyList",
"IList")
{
}
}

View File

@ -0,0 +1,26 @@
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class BlittableCustomStructTypePropertyTranslator : BlittableTypePropertyTranslator
{
private readonly string _nativeName;
public override bool ExportDefaultParameter => false;
public BlittableCustomStructTypePropertyTranslator(string nativeName, string managedType) : base(typeof(UhtStructProperty), managedType, PropertyKind.Unknown)
{
_nativeName = nativeName;
}
public override bool CanExport(UhtProperty property)
{
UhtStructProperty structProperty = (UhtStructProperty) property;
return structProperty.ScriptStruct.SourceName == _nativeName;
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
ExportDefaultStructParameter(builder, variableName, defaultValue, paramProperty, this);
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Text;
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class BlittableStructPropertyTranslator : BlittableTypePropertyTranslator
{
public BlittableStructPropertyTranslator() : base(typeof(UhtStructProperty), "", PropertyKind.Unknown)
{
}
public override bool ExportDefaultParameter => false;
public override bool CanExport(UhtProperty property)
{
UhtStructProperty structProperty = (UhtStructProperty) property;
return structProperty.ScriptStruct.IsStructBlittable();
}
public override string GetManagedType(UhtProperty property)
{
UhtStructProperty structProperty = (UhtStructProperty) property;
return structProperty.ScriptStruct.GetFullManagedName();
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
ExportDefaultStructParameter(builder, variableName, defaultValue, paramProperty, this);
}
}

View File

@ -0,0 +1,28 @@
using System;
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class BlittableTypePropertyTranslator : SimpleTypePropertyTranslator
{
public BlittableTypePropertyTranslator(Type propertyType, string managedType, PropertyKind propertyKind) :
base(propertyType, managedType, propertyKind)
{
}
public override bool ExportDefaultParameter => true;
public override string GetMarshaller(UhtProperty property)
{
return $"BlittableMarshaller<{GetManagedType(property)}>";
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
string defaultValueString = ConvertCPPDefaultValue(defaultValue, function, paramProperty);
builder.AppendLine($"{ManagedType} {variableName} = {defaultValueString};");
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,85 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class BoolPropertyTranslator : SimpleTypePropertyTranslator
{
private const string OffSetPostfix = "_Offset";
private const string FieldMaskPostfix = "_FieldMask";
public BoolPropertyTranslator() : base(typeof(UhtBoolProperty), "bool", PropertyKind.Bool)
{
}
public override string GetMarshaller(UhtProperty property)
{
return property.IsBitfield ? "BitfieldBoolMarshaller" : "BoolMarshaller";
}
public override void ExportPropertyStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, string nativePropertyName)
{
if (property.IsBitfield && !property.HasGetterSetterPair())
{
builder.AppendLine($"{GetFieldMaskFieldName(nativePropertyName)} = {ExporterCallbacks.FPropertyCallbacks}.CallGetBoolPropertyFieldMaskFromName(NativeClassPtr, \"{nativePropertyName}\");");
}
base.ExportPropertyStaticConstructor(builder, property, nativePropertyName);
}
public override void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
if (property.IsBitfield)
{
builder.AppendLine($"static byte {GetFieldMaskFieldName(propertyEngineName)};");
}
base.ExportPropertyVariables(builder, property, propertyEngineName);
}
public override void ExportToNative(
GeneratorStringBuilder builder,
UhtProperty property,
string propertyName,
string destinationBuffer,
string offset,
string source)
{
if (property.IsBitfield)
{
builder.AppendLine($"{GetMarshaller(property)}.ToNative(IntPtr.Add({destinationBuffer}, {offset}), {GetFieldMaskFieldName(propertyName)}, {source});");
return;
}
base.ExportToNative(builder, property, propertyName, destinationBuffer, offset, source);
}
public override void ExportFromNative(
GeneratorStringBuilder builder,
UhtProperty property,
string propertyName,
string assignmentOrReturn,
string sourceBuffer,
string offset,
bool bCleanupSourceBuffer,
bool reuseRefMarshallers)
{
if (property.IsBitfield)
{
builder.AppendLine($"{assignmentOrReturn} {GetMarshaller(property)}.FromNative(IntPtr.Add({sourceBuffer}, {offset}), {GetFieldMaskFieldName(propertyName)});");
return;
}
base.ExportFromNative(builder, property, propertyName, assignmentOrReturn, sourceBuffer, offset, bCleanupSourceBuffer, reuseRefMarshallers);
}
private string GetOffsetFieldName(string nativePropertyName)
{
return $"{nativePropertyName}{OffSetPostfix}";
}
private string GetFieldMaskFieldName(string nativePropertyName)
{
return $"{nativePropertyName}{FieldMaskPostfix}";
}
}

View File

@ -0,0 +1,43 @@
using System;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class ClassPropertyTranslator : SimpleTypePropertyTranslator
{
public ClassPropertyTranslator() : base(typeof(UhtClassProperty))
{
}
public override string GetManagedType(UhtProperty property)
{
UhtClassProperty classProperty = (UhtClassProperty)property;
string fullName = property.IsGenericType() ? "DOT"
: classProperty.MetaClass!.GetFullManagedName();
return $"TSubclassOf<{fullName}>";
}
public override string GetMarshaller(UhtProperty property)
{
UhtClassProperty classProperty = (UhtClassProperty)property;
string fullName = property.IsGenericType() ? "DOT"
: classProperty.MetaClass!.GetFullManagedName();
return $"SubclassOfMarshaller<{fullName}>";
}
/*
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer, string offset, string source)
{
if (property.IsGenericType())
{
builder.AppendLine($"{GetMarshaller(property)}.ToNative(IntPtr.Add({destinationBuffer}, {offset}), 0, typeof(DOT));");
}
else
{
base.ExportToNative(builder, property, propertyName, destinationBuffer, offset, source);
}
}*/
}

View File

@ -0,0 +1,249 @@
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class ContainerPropertyTranslator : PropertyTranslator
{
public ContainerPropertyTranslator(string copyMarshallerName, string readOnlyMarshallerName, string marshallerName, string readOnlyInterfaceName, string interfaceName) : base(ContainerSupportedUsages)
{
CopyMarshallerName = copyMarshallerName;
ReadOnlyMarshallerName = readOnlyMarshallerName;
MarshallerName = marshallerName;
ReadOnlyInterfaceName = readOnlyInterfaceName;
InterfaceName = interfaceName;
}
public readonly string CopyMarshallerName;
public readonly string ReadOnlyMarshallerName;
public readonly string MarshallerName;
public readonly string ReadOnlyInterfaceName;
public readonly string InterfaceName;
public override bool IsBlittable => false;
public override bool SupportsSetter => true;
public override bool CacheProperty => true;
public override bool CanExport(UhtProperty property)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
PropertyTranslator? translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty);
return translator != null && translator.CanExport(containerProperty.ValueProperty) && translator.IsSupportedAsInner();
}
public override string GetManagedType(UhtProperty property)
{
return GetWrapperInterface(property);
}
public override string GetMarshaller(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override void ExportPropertyGetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
string wrapperType = GetWrapperType(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(containerProperty.ValueProperty);
builder.AppendLine($"{propertyManagedName}_Marshaller ??= new {wrapperType}({propertyManagedName}_NativeProperty, {marshallingDelegates});");
builder.AppendLine($"return {propertyManagedName}_Marshaller.FromNative(IntPtr.Add(NativeObject, {propertyManagedName}_Offset), 0);");
}
public override void ExportPropertySetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty)property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
string wrapperType = GetWrapperType(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(containerProperty.ValueProperty);
builder.AppendLine($"{propertyManagedName}_Marshaller ??= new {wrapperType}({propertyManagedName}_NativeProperty, {marshallingDelegates});");
builder.AppendLine($"{propertyManagedName}_Marshaller.ToNative(IntPtr.Add(NativeObject, {propertyManagedName}_Offset), value);");
}
public override void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
base.ExportPropertyVariables(builder, property, propertyEngineName);
if (property.IsGenericType()) return;
string wrapperType = GetWrapperType(property);
if (property.IsOuter<UhtScriptStruct>() || property.HasAnyNativeGetterSetter())
{
builder.AppendLine($"static {wrapperType} {propertyEngineName}_Marshaller = null;");
}
else
{
builder.AppendLine($"{wrapperType} {propertyEngineName}_Marshaller = null;");
}
}
public override void ExportParameterVariables(GeneratorStringBuilder builder, UhtFunction function,
string nativeMethodName,
UhtProperty property, string propertyEngineName)
{
base.ExportParameterVariables(builder, function, nativeMethodName, property, propertyEngineName);
builder.AppendLine($"static IntPtr {nativeMethodName}_{propertyEngineName}_NativeProperty;");
if (property.IsGenericType()) return;
string wrapperType = GetWrapperType(property);
if (function.FunctionFlags.HasAnyFlags(EFunctionFlags.Static))
{
builder.AppendLine($"static {wrapperType} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
else
{
builder.AppendLine($"{wrapperType} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
}
public override void ExportParameterStaticConstructor(GeneratorStringBuilder builder, UhtProperty property,
UhtFunction function, string propertyEngineName, string functionName)
{
base.ExportParameterStaticConstructor(builder, property, function, propertyEngineName, functionName);
builder.AppendLine($"{functionName}_{propertyEngineName}_NativeProperty = {ExporterCallbacks.FPropertyCallbacks}.CallGetNativePropertyFromName({functionName}_NativeFunction, \"{propertyEngineName}\");");
}
public override string GetNullValue(UhtProperty property)
{
return "null";
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
throw new System.NotImplementedException();
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string assignmentOrReturn,
string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
UhtProperty valueProperty = containerProperty.ValueProperty;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(valueProperty)!;
string nativeProperty = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativeProperty = $"{nativeMethodName}_{nativeProperty}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string marshallerType = GetWrapperType(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(valueProperty);
if (!reuseRefMarshallers)
{
if (property.IsGenericType())
{
builder.AppendLine($"var {marshaller} = new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
else
{
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
builder.AppendLine($"IntPtr {propertyName}_NativeBuffer = IntPtr.Add({sourceBuffer}, {offset});");
}
builder.AppendLine($"{assignmentOrReturn} {marshaller}.FromNative({propertyName}_NativeBuffer, 0);");
if (bCleanupSourceBuffer)
{
ExportCleanupMarshallingBuffer(builder, property, propertyName);
}
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
UhtProperty valueProperty = containerProperty.ValueProperty;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(valueProperty)!;
string nativeProperty = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativeProperty = $"{nativeMethodName}_{nativeProperty}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string marshallerType = GetWrapperType(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(valueProperty);
if (property.IsGenericType())
{
builder.AppendLine($"var {marshaller} = new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
else
{
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
builder.AppendLine($"IntPtr {propertyName}_NativeBuffer = IntPtr.Add({destinationBuffer}, {offset});");
builder.AppendLine($"{marshaller}.ToNative({propertyName}_NativeBuffer, 0, {source});");
}
public override void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property, string paramName)
{
string nativeMethodName = "";
if (property.Outer is UhtFunction function)
{
nativeMethodName = function.SourceName + "_";
}
string marshaller = $"{nativeMethodName}{paramName}_Marshaller";
builder.AppendLine($"{marshaller}.DestructInstance({paramName}_NativeBuffer, 0);");
}
private string GetWrapperType(UhtProperty property)
{
bool isStructProperty = property.IsOuter<UhtScriptStruct>();
bool isParameter = property.IsOuter<UhtFunction>();
bool isNativeGetterSetter = property.HasAnyNativeGetterSetter();
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
string innerManagedType = property.IsGenericType() ?
"DOT" : translator.GetManagedType(containerProperty.ValueProperty);
string containerType = isStructProperty || isParameter || isNativeGetterSetter ? CopyMarshallerName : property.PropertyFlags.HasAnyFlags(EPropertyFlags.BlueprintReadOnly) ? ReadOnlyMarshallerName : MarshallerName;
return $"{containerType}<{innerManagedType}>";
}
private string GetWrapperInterface(UhtProperty property)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
string innerManagedType = property.IsGenericType() ?
"DOT" : translator.GetManagedType(containerProperty.ValueProperty);
string interfaceType = property.PropertyFlags.HasAnyFlags(EPropertyFlags.BlueprintReadOnly) ? ReadOnlyInterfaceName : InterfaceName;
return $"System.Collections.Generic.{interfaceType}<{innerManagedType}>";
}
public override bool CanSupportGenericType(UhtProperty property)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty)property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
return translator.CanSupportGenericType(containerProperty.ValueProperty);
}
}

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Exporters;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class DelegateBasePropertyTranslator : PropertyTranslator
{
public DelegateBasePropertyTranslator(EPropertyUsageFlags supportedPropertyUsage) : base(supportedPropertyUsage)
{
}
public override bool CacheProperty => true;
public static string GetDelegateName(UhtFunction function, bool wrapperName = false)
{
string delegateName = function.EngineName;
int delegateSignatureIndex = delegateName.IndexOf("__DelegateSignature", StringComparison.Ordinal);
string strippedDelegateName = delegateName.Substring(0, delegateSignatureIndex);
return wrapperName ? "U" + strippedDelegateName : strippedDelegateName;
}
public static string GetFullDelegateName(UhtFunction function, bool wrapperName = false)
{
return $"{function.GetNamespace()}.{GetDelegateName(function, wrapperName)}";
}
public override bool CanExport(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string GetManagedType(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string GetMarshaller(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string GetNullValue(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName,
string assignmentOrReturn, string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
throw new System.NotImplementedException();
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
throw new System.NotImplementedException();
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
throw new System.NotImplementedException();
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,58 @@
using System;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class EnumPropertyTranslator : BlittableTypePropertyTranslator
{
public EnumPropertyTranslator() : base(typeof(UhtByteProperty), "", PropertyKind.Enum)
{
}
public override bool CanExport(UhtProperty property)
{
return property is UhtEnumProperty or UhtByteProperty && GetEnum(property) != null;
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
UhtEnum enumObj = GetEnum(parameter)!;
int index = enumObj.GetIndexByName(defaultValue);
string valueName = ScriptGeneratorUtilities.GetCleanEnumValueName(enumObj, enumObj.EnumValues[index]);
return $"{GetManagedType(parameter)}.{valueName}";
}
public override string GetManagedType(UhtProperty property)
{
UhtEnum enumObj = GetEnum(property)!;
return enumObj.GetFullManagedName();
}
public override string GetMarshaller(UhtProperty property)
{
return $"EnumMarshaller<{GetManagedType(property)}>";
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
if (defaultValue.Contains("::"))
{
defaultValue = defaultValue.Substring(defaultValue.LastIndexOf("::") + 2);
}
string fullEnumName = GetManagedType(paramProperty);
builder.AppendLine($"{fullEnumName} {variableName} = {fullEnumName}.{defaultValue};");
}
private static UhtEnum? GetEnum(UhtProperty property)
{
return property switch
{
UhtEnumProperty enumProperty => enumProperty.Enum,
UhtByteProperty byteProperty => byteProperty.Enum,
_ => throw new InvalidOperationException("Property is not an enum or byte property")
};
}
}

View File

@ -0,0 +1,30 @@
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class FieldPathPropertyTranslator : SimpleTypePropertyTranslator
{
public FieldPathPropertyTranslator() : base(typeof(UhtFieldPathProperty))
{
}
public override bool CanExport(UhtProperty property)
{
return property is UhtFieldPathProperty;
}
public override string GetManagedType(UhtProperty property)
{
return "FFieldPath";
}
public override string GetMarshaller(UhtProperty property)
{
return "FieldPathMarshaller";
}
public override bool CanSupportGenericType(UhtProperty property)
{
return false;
}
}

View File

@ -0,0 +1,15 @@
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class FloatPropertyTranslator : BlittableTypePropertyTranslator
{
public FloatPropertyTranslator() : base(typeof(UhtFloatProperty), "float", PropertyKind.Float)
{
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
return base.ConvertCPPDefaultValue(defaultValue, function, parameter) + "f";
}
}

View File

@ -0,0 +1,34 @@
using System.Linq;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class IntPropertyTranslator : BlittableTypePropertyTranslator
{
public IntPropertyTranslator() : base(typeof(UhtIntProperty), "int", PropertyKind.Int)
{
}
public override string GetManagedType(UhtProperty property)
{
if (property.Outer is UhtFunction function && property.IsCustomStructureType())
{
if (function.GetCustomStructParamCount() == 1) return "CSP";
return $"CSP{property.GetPrecedingCustomStructParams()}";
}
return base.GetManagedType(property);
}
public override string GetMarshaller(UhtProperty property)
{
if (property.Outer is UhtFunction && property.IsCustomStructureType())
{
return $"StructMarshaller<{GetManagedType(property)}>";
}
return base.GetMarshaller(property);
}
public override bool CanSupportCustomStruct(UhtProperty property) => true;
}

View File

@ -0,0 +1,24 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class InterfacePropertyTranslator : SimpleTypePropertyTranslator
{
public InterfacePropertyTranslator() : base(typeof(UhtInterfaceProperty))
{
}
public override string GetManagedType(UhtProperty property)
{
UhtInterfaceProperty interfaceProperty = (UhtInterfaceProperty)property;
return interfaceProperty.InterfaceClass.GetFullManagedName();
}
public override string GetMarshaller(UhtProperty property)
{
return $"{GetManagedType(property)}Marshaller";
}
public override bool CanSupportGenericType(UhtProperty property) => true;
}

View File

@ -0,0 +1,238 @@
using System;
using System.Collections.Generic;
using System.Text;
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class MapPropertyTranslator : PropertyTranslator
{
public MapPropertyTranslator() : base(ContainerSupportedUsages)
{
}
public override bool IsBlittable => false;
public override bool SupportsSetter => true;
public override bool CacheProperty => true;
public override bool CanExport(UhtProperty property)
{
if (property is not UhtMapProperty mapProperty)
{
return false;
}
PropertyTranslator? keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty);
PropertyTranslator? valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty);
// These can be null apparently
if (keyTranslator == null || valueTranslator == null)
{
return false;
}
return keyTranslator.IsSupportedAsInner() && valueTranslator.IsSupportedAsInner();
}
public override string GetManagedType(UhtProperty property)
{
UhtMapProperty mapProperty = (UhtMapProperty) property;
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty)!;
string keyManagedType = keyTranslator.GetManagedType(mapProperty.KeyProperty);
string valueManagedType = valueTranslator.GetManagedType(mapProperty.ValueProperty);
string interfaceType = property.HasAnyFlags(EPropertyFlags.BlueprintReadOnly) ? "IReadOnlyDictionary" : "IDictionary";
return $"System.Collections.Generic.{interfaceType}<{keyManagedType}, {valueManagedType}>";
}
public override void ExportParameterStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, UhtFunction function, string propertyEngineName, string functionName)
{
base.ExportParameterStaticConstructor(builder, property, function, propertyEngineName, functionName);
builder.AppendLine($"{functionName}_{propertyEngineName}_NativeProperty = {ExporterCallbacks.FPropertyCallbacks}.CallGetNativePropertyFromName({functionName}_NativeFunction, \"{property.EngineName}\");");
}
public override void ExportParameterVariables(GeneratorStringBuilder builder, UhtFunction function,
string nativeMethodName,
UhtProperty property, string propertyEngineName)
{
base.ExportParameterVariables(builder, function, nativeMethodName, property, propertyEngineName);
string marshaller = GetMarshaller((UhtMapProperty) property);
builder.AppendLine($"static IntPtr {nativeMethodName}_{propertyEngineName}_NativeProperty;");
if (function.FunctionFlags.HasAnyFlags(EFunctionFlags.Static))
{
builder.AppendLine($"static {marshaller} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
else
{
builder.AppendLine($"{marshaller} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
}
public override void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
base.ExportPropertyVariables(builder, property, propertyEngineName);
string marshaller = GetMarshaller((UhtMapProperty) property);
if (property.IsOuter<UhtScriptStruct>())
{
builder.AppendLine($"static {marshaller} {propertyEngineName}_Marshaller = null;");
}
else
{
builder.AppendLine($"{marshaller} {propertyEngineName}_Marshaller = null;");
}
}
public override void ExportPropertyGetter(GeneratorStringBuilder builder, UhtProperty property,
string propertyManagedName)
{
UhtMapProperty mapProperty = (UhtMapProperty) property;
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty)!;
string keyMarshallingDelegates = keyTranslator.ExportMarshallerDelegates(mapProperty.KeyProperty);
string valueMarshallingDelegates = valueTranslator.ExportMarshallerDelegates(mapProperty.ValueProperty);
string marshaller = GetMarshaller(mapProperty);
builder.AppendLine($"{property.SourceName}_Marshaller ??= new {marshaller}({property.SourceName}_NativeProperty, {keyMarshallingDelegates}, {valueMarshallingDelegates});");
builder.AppendLine($"return {property.SourceName}_Marshaller.FromNative(IntPtr.Add(NativeObject, {property.SourceName}_Offset), 0);");
}
public override void ExportPropertySetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
UhtMapProperty mapProperty = (UhtMapProperty)property;
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty)!;
string keyMarshallingDelegates = keyTranslator.ExportMarshallerDelegates(mapProperty.KeyProperty);
string valueMarshallingDelegates = valueTranslator.ExportMarshallerDelegates(mapProperty.ValueProperty);
string marshaller = GetMarshaller(mapProperty);
builder.AppendLine($"{property.SourceName}_Marshaller ??= new {marshaller}({property.SourceName}_NativeProperty, {keyMarshallingDelegates}, {valueMarshallingDelegates});");
builder.AppendLine($"{property.SourceName}_Marshaller.ToNative(IntPtr.Add(NativeObject, {property.SourceName}_Offset), 0, value);");
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string assignmentOrReturn,
string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
UhtMapProperty mapProperty = (UhtMapProperty) property;
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty)!;
string nativePropertyName = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativePropertyName = $"{nativeMethodName}_{nativePropertyName}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string keyType = keyTranslator.GetManagedType(mapProperty.KeyProperty);
string valueType = valueTranslator.GetManagedType(mapProperty.ValueProperty);
string marshallerType = $"MapCopyMarshaller<{keyType}, {valueType}>";
if (!reuseRefMarshallers)
{
string keyMarshallingDelegates = keyTranslator.ExportMarshallerDelegates(mapProperty.KeyProperty);
string valueMarshallingDelegates = valueTranslator.ExportMarshallerDelegates(mapProperty.ValueProperty);
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativePropertyName}, {keyMarshallingDelegates}, {valueMarshallingDelegates});");
builder.AppendLine($"IntPtr {nativePropertyName}_ParamsBuffer = IntPtr.Add({sourceBuffer}, {offset});");
}
builder.AppendLine($"{assignmentOrReturn} {marshaller}.FromNative({sourceBuffer}, 0);");
if (bCleanupSourceBuffer)
{
ExportCleanupMarshallingBuffer(builder, property, propertyName);
}
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
UhtMapProperty mapProperty = (UhtMapProperty) property;
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(mapProperty.ValueProperty)!;
string nativePropertyName = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativePropertyName = $"{nativeMethodName}_{nativePropertyName}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string keyType = keyTranslator.GetManagedType(mapProperty.KeyProperty);
string valueType = valueTranslator.GetManagedType(mapProperty.ValueProperty);
string marshallerType = GetWrapperType(property, keyType, valueType);
string keyMarshallingDelegates = keyTranslator.ExportMarshallerDelegates(mapProperty.KeyProperty);
string valueMarshallingDelegates = valueTranslator.ExportMarshallerDelegates(mapProperty.ValueProperty);
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativePropertyName}, {keyMarshallingDelegates}, {valueMarshallingDelegates});");
builder.AppendLine($"IntPtr {nativePropertyName}_NativeBuffer = IntPtr.Add({destinationBuffer}, {offset});");
builder.AppendLine($"{marshaller}.ToNative({nativePropertyName}_NativeBuffer, 0, {source});");
}
private string GetWrapperType(UhtProperty property, string keyType, string valueType)
{
bool isStructProperty = property.IsOuter<UhtScriptStruct>();
bool isParameter = property.IsOuter<UhtFunction>() || (property.Getter is not null && property.Setter is not null);
string containerType = isStructProperty || isParameter ? "MapCopyMarshaller" : property.PropertyFlags.HasAnyFlags(EPropertyFlags.BlueprintReadOnly) ? "MapReadOnlyMarshaller" : "MapMarshaller";
return $"{containerType}<{keyType}, {valueType}>";
}
public override string GetMarshaller(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string GetNullValue(UhtProperty property)
{
return "null";
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
throw new System.NotImplementedException();
}
private string GetMarshaller(UhtMapProperty property)
{
bool isStructProperty = property.IsOuter<UhtScriptStruct>();
bool isParameter = property.IsOuter<UhtFunction>() || property.HasAnyGetter();
PropertyTranslator keyTranslator = PropertyTranslatorManager.GetTranslator(property.KeyProperty)!;
PropertyTranslator valueTranslator = PropertyTranslatorManager.GetTranslator(property.ValueProperty)!;
string marshallerType = isStructProperty || isParameter ? "MapCopyMarshaller"
: property.PropertyFlags.HasAnyFlags(EPropertyFlags.BlueprintReadOnly) ? "MapReadOnlyMarshaller" : "MapMarshaller";
string keyType = keyTranslator.GetManagedType(property.KeyProperty);
string valueType = valueTranslator.GetManagedType(property.ValueProperty);
return $"{marshallerType}<{keyType}, {valueType}>";
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,87 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class MulticastDelegatePropertyTranslator : DelegateBasePropertyTranslator
{
public MulticastDelegatePropertyTranslator() : base(EPropertyUsageFlags.Property)
{
}
private string GetBackingField(UhtProperty property)
{
return $"{property.SourceName}_BackingField";
}
public override bool CanExport(UhtProperty property)
{
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
return ScriptGeneratorUtilities.CanExportParameters(multicastDelegateProperty.Function);
}
public override string GetManagedType(UhtProperty property)
{
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
return $"TMulticastDelegate<{GetFullDelegateName(multicastDelegateProperty.Function)}>";
}
public override void ExportPropertyStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, string nativePropertyName)
{
base.ExportPropertyStaticConstructor(builder, property, nativePropertyName);
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
if (multicastDelegateProperty.Function.HasParameters)
{
string fullDelegateName = GetFullDelegateName(((UhtMulticastDelegateProperty) property).Function, true);
builder.AppendLine($"{fullDelegateName}.InitializeUnrealDelegate({nativePropertyName}_NativeProperty);");
}
}
public override void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
base.ExportPropertyVariables(builder, property, propertyEngineName);
string backingField = GetBackingField(property);
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
string fullDelegateName = GetFullDelegateName(multicastDelegateProperty.Function);
builder.AppendLine($"private TMulticastDelegate<{fullDelegateName}> {backingField};");
}
public override void ExportPropertySetter(GeneratorStringBuilder builder, UhtProperty property,
string propertyManagedName)
{
string backingField = GetBackingField(property);
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
string fullDelegateName = GetFullDelegateName(multicastDelegateProperty.Function);
builder.AppendLine($"if (value == {backingField})");
builder.OpenBrace();
builder.AppendLine("return;");
builder.CloseBrace();
builder.AppendLine($"{backingField} = value;");
builder.AppendLine($"MulticastDelegateMarshaller<{fullDelegateName}>.ToNative(IntPtr.Add(NativeObject, {propertyManagedName}_Offset), 0, value);");
}
public override void ExportPropertyGetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
string backingField = GetBackingField(property);
string propertyFieldName = GetNativePropertyField(propertyManagedName);
UhtMulticastDelegateProperty multicastDelegateProperty = (UhtMulticastDelegateProperty) property;
string fullDelegateName = GetFullDelegateName(multicastDelegateProperty.Function);
builder.AppendLine($"if ({backingField} == null)");
builder.OpenBrace();
builder.AppendLine($"{backingField} = MulticastDelegateMarshaller<{fullDelegateName}>.FromNative(IntPtr.Add(NativeObject, {propertyManagedName}_Offset), {propertyFieldName}, 0);");
builder.CloseBrace();
builder.AppendLine($"return {backingField};");
}
public override string GetNullValue(UhtProperty property)
{
return "null";
}
}

View File

@ -0,0 +1,31 @@
using System;
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class NamePropertyTranslator : BlittableTypePropertyTranslator
{
public NamePropertyTranslator() : base(typeof(UhtNameProperty), "FName", PropertyKind.Unknown)
{
}
public override bool ExportDefaultParameter => false;
public override string GetNullValue(UhtProperty property)
{
return "default(FName)";
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
if (defaultValue == "None")
{
builder.AppendLine($"FName {variableName} = FName.None;");
}
else
{
builder.AppendLine($"FName {variableName} = new FName(\"{defaultValue}\");");
}
}
}

View File

@ -0,0 +1,59 @@
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class ObjectPropertyTranslator : SimpleTypePropertyTranslator
{
public ObjectPropertyTranslator() : base(typeof(UhtObjectProperty))
{
}
public override bool CanExport(UhtProperty property)
{
UhtObjectPropertyBase objectProperty = (UhtObjectPropertyBase) property;
UhtClass? metaClass = objectProperty.Class;
if (metaClass.HasAnyFlags(EClassFlags.Interface) ||
metaClass.EngineType == UhtEngineType.Interface ||
metaClass.EngineType == UhtEngineType.NativeInterface)
{
return false;
}
return base.CanExport(property);
}
public override string GetNullValue(UhtProperty property)
{
return "null";
}
public override string GetManagedType(UhtProperty property)
{
return GetManagedType(property, property.HasMetadata("Nullable"));
}
private static string GetManagedType(UhtProperty property, bool isNullable)
{
string nullableAnnotation = isNullable ? "?" : "";
if (property.IsGenericType()) return $"DOT{nullableAnnotation}";
UhtObjectProperty objectProperty = (UhtObjectProperty)property;
return $"{objectProperty.Class.GetFullManagedName()}{nullableAnnotation}";
}
public override string GetMarshaller(UhtProperty property)
{
if (property.Outer is UhtProperty outerProperty && outerProperty.IsGenericType())
{
return "ObjectMarshaller<DOT>";
}
return $"ObjectMarshaller<{GetManagedType(property, false)}>";
}
public override bool CanSupportGenericType(UhtProperty property) => true;
}

View File

@ -0,0 +1,206 @@
using EpicGames.Core;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class OptionalPropertyTranslator : PropertyTranslator
{
public OptionalPropertyTranslator() : base(ContainerSupportedUsages)
{
}
public override bool CacheProperty => true;
public override void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
base.ExportPropertyVariables(builder, property, propertyEngineName);
if (property.IsGenericType()) return;
string wrapperType = GetMarshaller(property);
builder.AppendLine($"static {wrapperType} {propertyEngineName}_Marshaller = null;");
}
public override void ExportPropertyGetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
var containerProperty = (UhtOptionalProperty) property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty)!;
string wrapperType = GetMarshaller(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(containerProperty.ValueProperty);
builder.AppendLine($"{propertyManagedName}_Marshaller ??= new {wrapperType}({propertyManagedName}_NativeProperty, {marshallingDelegates});");
builder.AppendLine($"return {propertyManagedName}_Marshaller.FromNative(IntPtr.Add(NativeObject, {propertyManagedName}_Offset), 0);");
}
public override void ExportParameterVariables(GeneratorStringBuilder builder, UhtFunction function,
string nativeMethodName,
UhtProperty property, string propertyEngineName)
{
base.ExportParameterVariables(builder, function, nativeMethodName, property, propertyEngineName);
builder.AppendLine($"static IntPtr {nativeMethodName}_{propertyEngineName}_NativeProperty;");
if (property.IsGenericType()) return;
string wrapperType = GetMarshaller(property);
if (function.FunctionFlags.HasAnyFlags(EFunctionFlags.Static))
{
builder.AppendLine($"static {wrapperType} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
else
{
builder.AppendLine($"{wrapperType} {nativeMethodName}_{propertyEngineName}_Marshaller = null;");
}
}
public override void ExportParameterStaticConstructor(GeneratorStringBuilder builder, UhtProperty property,
UhtFunction function, string propertyEngineName, string functionName)
{
base.ExportParameterStaticConstructor(builder, property, function, propertyEngineName, functionName);
builder.AppendLine($"{functionName}_{propertyEngineName}_NativeProperty = {ExporterCallbacks.FPropertyCallbacks}.CallGetNativePropertyFromName({functionName}_NativeFunction, \"{propertyEngineName}\");");
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string assignmentOrReturn,
string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
UhtProperty valueProperty = containerProperty.ValueProperty;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(valueProperty)!;
string nativeProperty = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativeProperty = $"{nativeMethodName}_{nativeProperty}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string marshallerType = GetMarshaller(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(valueProperty);
if (!reuseRefMarshallers)
{
if (property.IsGenericType())
{
builder.AppendLine($"var {marshaller} = new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
else
{
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
builder.AppendLine($"IntPtr {propertyName}_NativeBuffer = IntPtr.Add({sourceBuffer}, {offset});");
}
builder.AppendLine($"{assignmentOrReturn} {marshaller}.FromNative({propertyName}_NativeBuffer, 0);");
if (bCleanupSourceBuffer)
{
ExportCleanupMarshallingBuffer(builder, property, propertyName);
}
}
public override void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property,
string paramName)
{
var optionalProperty = (UhtOptionalProperty)property;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(optionalProperty.ValueProperty)!;
// Blittable types, booleans, and enums are all trivially destructible, and thus don't need a cleanup.
if (translator.IsBlittable || optionalProperty.ValueProperty is UhtBoolProperty or UhtEnumProperty)
{
return;
}
string nativeMethodName = "";
if (property.Outer is UhtFunction function)
{
nativeMethodName = function.SourceName + "_";
}
string marshaller = $"{nativeMethodName}{paramName}_Marshaller";
builder.AppendLine($"{marshaller}.DestructInstance({paramName}_NativeBuffer, 0);");
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
UhtContainerBaseProperty containerProperty = (UhtContainerBaseProperty) property;
UhtProperty valueProperty = containerProperty.ValueProperty;
PropertyTranslator translator = PropertyTranslatorManager.GetTranslator(valueProperty)!;
string nativeProperty = $"{propertyName}_NativeProperty";
string marshaller = $"{propertyName}_Marshaller";
if (property.Outer is UhtFunction function)
{
string nativeMethodName = function.SourceName;
nativeProperty = $"{nativeMethodName}_{nativeProperty}";
marshaller = $"{nativeMethodName}_{marshaller}";
}
string marshallerType = GetMarshaller(property);
string marshallingDelegates = translator.ExportMarshallerDelegates(valueProperty);
if (property.IsGenericType())
{
builder.AppendLine($"var {marshaller} = new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
else
{
builder.AppendLine($"{marshaller} ??= new {marshallerType}({nativeProperty}, {marshallingDelegates});");
}
builder.AppendLine($"IntPtr {propertyName}_NativeBuffer = IntPtr.Add({destinationBuffer}, {offset});");
builder.AppendLine($"{marshaller}.ToNative({propertyName}_NativeBuffer, 0, {source});");
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
throw new System.NotImplementedException();
}
public override string GetManagedType(UhtProperty property)
{
if (property.IsGenericType()) return "DOT";
var optionalProperty = (UhtOptionalProperty)property;
var translator = PropertyTranslatorManager.GetTranslator(optionalProperty.ValueProperty)!;
return $"UnrealSharp.TOptional<{translator.GetManagedType(optionalProperty.ValueProperty)}>";
}
public override string GetMarshaller(UhtProperty property)
{
if (property.Outer is UhtProperty outerProperty && outerProperty.IsGenericType())
{
return "OptionalMarshaller<DOT>";
}
var optionalProperty = (UhtOptionalProperty)property;
var translator = PropertyTranslatorManager.GetTranslator(optionalProperty.ValueProperty)!;
return $"OptionalMarshaller<{translator.GetManagedType(optionalProperty.ValueProperty)}>";
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
throw new System.NotImplementedException();
}
public override string GetNullValue(UhtProperty property)
{
var optionalProperty = (UhtOptionalProperty)property;
var translator = PropertyTranslatorManager.GetTranslator(optionalProperty.ValueProperty)!;
return $"UnrealSharp.TOptional<{translator.GetManagedType(optionalProperty.ValueProperty)}>.None";
}
public override bool CanExport(UhtProperty property)
{
var containerProperty = (UhtOptionalProperty) property;
var translator = PropertyTranslatorManager.GetTranslator(containerProperty.ValueProperty);
return translator != null && translator.CanExport(containerProperty.ValueProperty) && translator.IsSupportedAsInner();
}
public override bool CanSupportGenericType(UhtProperty property) => true;
}

View File

@ -0,0 +1,593 @@
using EpicGames.Core;
using EpicGames.UHT.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using UnrealSharpScriptGenerator.Exporters;
using UnrealSharpScriptGenerator.Tooltip;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public abstract class PropertyTranslator
{
private readonly PropertyKind _propertyKind;
private readonly EPropertyUsageFlags _supportedPropertyUsage;
protected const EPropertyUsageFlags ContainerSupportedUsages = EPropertyUsageFlags.Property
| EPropertyUsageFlags.StructProperty
| EPropertyUsageFlags.Parameter
| EPropertyUsageFlags.ReturnValue;
public bool IsSupportedAsProperty() => _supportedPropertyUsage.HasFlag(EPropertyUsageFlags.Property);
public bool IsSupportedAsParameter() => _supportedPropertyUsage.HasFlag(EPropertyUsageFlags.Parameter);
public bool IsSupportedAsReturnValue() => _supportedPropertyUsage.HasFlag(EPropertyUsageFlags.ReturnValue);
public bool IsSupportedAsInner() => _supportedPropertyUsage.HasFlag(EPropertyUsageFlags.Inner);
public bool IsSupportedAsStructProperty() => _supportedPropertyUsage.HasFlag(EPropertyUsageFlags.StructProperty);
public PropertyKind PropertyKind => _propertyKind;
public bool IsPrimitive => _propertyKind == PropertyKind.SByte ||
_propertyKind == PropertyKind.Byte ||
_propertyKind == PropertyKind.Short||
_propertyKind == PropertyKind.UShort ||
_propertyKind == PropertyKind.Int ||
_propertyKind == PropertyKind.UInt ||
_propertyKind == PropertyKind.Long ||
_propertyKind == PropertyKind.ULong ||
_propertyKind == PropertyKind.Float ||
_propertyKind == PropertyKind.Double ||
_propertyKind == PropertyKind.Bool ||
_propertyKind == PropertyKind.String ||
_propertyKind == PropertyKind.Enum;
public bool IsNumeric => _propertyKind == PropertyKind.Byte ||
_propertyKind == PropertyKind.SByte ||
_propertyKind == PropertyKind.Short ||
_propertyKind == PropertyKind.UShort ||
_propertyKind == PropertyKind.Int ||
_propertyKind == PropertyKind.UInt ||
_propertyKind == PropertyKind.Long ||
_propertyKind == PropertyKind.ULong ||
_propertyKind == PropertyKind.Float ||
_propertyKind == PropertyKind.Double;
// Is this property the same memory layout as the C++ type?
public virtual bool IsBlittable => false;
public virtual bool SupportsSetter => true;
public virtual bool ExportDefaultParameter => true;
public virtual bool CacheProperty => false;
// Should this property be declared as a parameter in the function signature?
// A property can support being a parameter but not be declared as one, such as WorldContextObjectPropertyTranslator
public virtual bool ShouldBeDeclaredAsParameter => true;
public PropertyTranslator(EPropertyUsageFlags supportedPropertyUsage,
PropertyKind propertyKind = PropertyKind.Unknown)
{
_supportedPropertyUsage = supportedPropertyUsage;
_propertyKind = propertyKind;
}
// Can we export this property?
public abstract bool CanExport(UhtProperty property);
// Can we support generic types?
public abstract bool CanSupportGenericType(UhtProperty property);
// Can we support custom structs?
public virtual bool CanSupportCustomStruct(UhtProperty property) => false;
// Get the managed type for this property
// Example: "int" for a property of type "int32"
public abstract string GetManagedType(UhtProperty property);
// Get the marshaller for this property to marshal back and forth between C++ and C#
public abstract string GetMarshaller(UhtProperty property);
// Get the marshaller delegates for this property
public abstract string ExportMarshallerDelegates(UhtProperty property);
// Get the null value for this property
public virtual string GetNullValue(UhtProperty property) => $"default({GetManagedType(property)})";
public virtual void ExportPropertyStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, string nativePropertyName)
{
string propertyPointerName = property.GetNativePropertyName();
bool hasNativeGetterSetter = property.HasAnyNativeGetterSetter();
bool hasBlueprintGetterSetter = property.HasBlueprintGetterSetterPair();
string adjustedNativePropertyName = nativePropertyName;
if (property.Deprecated)
{
int index = nativePropertyName.IndexOf("_DEPRECATED", StringComparison.OrdinalIgnoreCase);
adjustedNativePropertyName = index != -1 ? nativePropertyName.Substring(0, index) : nativePropertyName;
}
if (hasNativeGetterSetter || !hasBlueprintGetterSetter)
{
string variableDeclaration = CacheProperty || hasNativeGetterSetter ? "" : "IntPtr ";
builder.AppendLine($"{variableDeclaration}{propertyPointerName} = {ExporterCallbacks.FPropertyCallbacks}.CallGetNativePropertyFromName(NativeClassPtr, \"{adjustedNativePropertyName}\");");
builder.AppendLine($"{nativePropertyName}_Offset = {ExporterCallbacks.FPropertyCallbacks}.CallGetPropertyOffset({propertyPointerName});");
}
if (hasNativeGetterSetter)
{
builder.AppendLine($"{nativePropertyName}_Size = {ExporterCallbacks.FPropertyCallbacks}.CallGetSize({propertyPointerName});");
}
// Export the static constructors for the getter and setter
TryExportGetterSetterStaticConstructor(property, builder);
}
private void TryExportGetterSetterStaticConstructor(UhtProperty property, GeneratorStringBuilder builder)
{
if (!property.HasNativeGetter())
{
UhtFunction? getter = property.GetBlueprintGetter();
if (getter != null)
{
StaticConstructorUtilities.ExportClassFunctionStaticConstructor(builder, getter);
}
}
if (!property.HasNativeSetter())
{
UhtFunction? setter = property.GetBlueprintSetter();
if (setter != null)
{
StaticConstructorUtilities.ExportClassFunctionStaticConstructor(builder, setter);
}
}
}
public virtual void ExportParameterStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, UhtFunction function, string propertyEngineName, string functionName)
{
string variableName = $"{functionName}_{propertyEngineName}_{(property.GetPrecedingCustomStructParams() > 0 ? "NativeOffset" : "Offset")}";
builder.AppendLine($"{variableName} = {ExporterCallbacks.FPropertyCallbacks}.CallGetPropertyOffsetFromName({functionName}_NativeFunction, \"{propertyEngineName}\");");
}
public virtual void ExportPropertyVariables(GeneratorStringBuilder builder, UhtProperty property, string propertyEngineName)
{
builder.AppendLine($"static int {propertyEngineName}_Offset;");
if (property.HasAnyGetterOrSetter() || CacheProperty)
{
AddNativePropertyField(builder, propertyEngineName);
}
if (property.HasAnyGetterOrSetter())
{
builder.AppendLine($"static int {propertyEngineName}_Size;");
}
}
public virtual void ExportParameterVariables(GeneratorStringBuilder builder, UhtFunction function, string nativeMethodName, UhtProperty property, string propertyEngineName)
{
if (function.HasCustomStructParamSupport())
{
List<UhtProperty> precedingParams = property.GetPrecedingParams()!;
int precedingCustomStructProperties = precedingParams.Count(param => param.IsCustomStructureType());
if (precedingCustomStructProperties > 0)
{
builder.AppendLine($"static int {nativeMethodName}_{propertyEngineName}_NativeOffset;");
List<string> customStructParamTypes =
function.GetCustomStructParamTypes().GetRange(0, precedingCustomStructProperties);
builder.AppendLine($"static int {nativeMethodName}_{propertyEngineName}_Offset<{string.Join(", ", customStructParamTypes)}>()");
builder.Indent();
foreach (string customStructParamType in customStructParamTypes)
{
builder.AppendLine($"where {customStructParamType} : MarshalledStruct<{customStructParamType}>");
}
string variableNames = string.Join(" + ",
customStructParamTypes.ConvertAll(customStructParamType =>
$"{customStructParamType}.GetNativeDataSize()"));
string nativeOffsetSubtractionMultiplier = string.Empty;
if (precedingCustomStructProperties > 1)
nativeOffsetSubtractionMultiplier += $"{precedingCustomStructProperties} * ";
builder.AppendLine($"=> {nativeMethodName}_{propertyEngineName}_NativeOffset + {variableNames} - {nativeOffsetSubtractionMultiplier}sizeof(int);");
builder.UnIndent();
return;
}
}
builder.AppendLine($"static int {nativeMethodName}_{propertyEngineName}_Offset;");
}
public virtual void ExportPropertyGetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
ExportFromNative(builder, property, propertyManagedName, "return", "NativeObject", $"{propertyManagedName}_Offset", false, false);
}
public virtual void ExportPropertySetter(GeneratorStringBuilder builder, UhtProperty property, string propertyManagedName)
{
ExportToNative(builder, property, propertyManagedName, "NativeObject", $"{propertyManagedName}_Offset", "value");
}
public virtual void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName,
string defaultValue, UhtFunction function, UhtProperty paramProperty)
{
}
public virtual void ExportFunctionReturnStatement(GeneratorStringBuilder builder,
UhtProperty property,
string nativePropertyName,
string functionName,
string paramsCallString)
{
throw new NotImplementedException();
}
// Cleanup the marshalling buffer
public virtual void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property,
string paramName)
{
}
// Build the C# code to marshal this property from C++ to C#
public abstract void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName,
string assignmentOrReturn, string sourceBuffer, string offset, bool bCleanupSourceBuffer,
bool reuseRefMarshallers);
// Build the C# code to marshal this property from C# to C++
public abstract void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer, string offset, string source);
// Convert a C++ default value to a C# default value
// Example: "0.0f" for a float property
public abstract string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter);
public void ExportConstructor()
{
}
public void ExportCustomProperty(GeneratorStringBuilder builder, GetterSetterPair getterSetterPair,
string propertyName, UhtProperty property, bool isExplicitImplementation = false,
HashSet<string>? exportedFunctionNames = null)
{
GetterSetterFunctionExporter? getterExporter = getterSetterPair.GetterExporter;
GetterSetterFunctionExporter? setterExporter = getterSetterPair.SetterExporter;
void ExportBackingFields()
{
if (getterExporter != null && (exportedFunctionNames is null || !exportedFunctionNames.Contains(getterExporter.Function.SourceName)))
{
getterExporter.ExportFunctionVariables(builder);
}
if (setterExporter != null && (exportedFunctionNames is null || !exportedFunctionNames.Contains(setterExporter.Function.SourceName)))
{
setterExporter.ExportFunctionVariables(builder);
}
}
string ExportProtection()
{
if (setterExporter != null)
{
return setterExporter.Modifiers;
}
if (getterExporter != null)
{
return getterExporter.Modifiers;
}
throw new InvalidOperationException("No getter or setter found");
}
Action? exportGetterAction = getterExporter != null ? () => AppendInvoke(builder, getterExporter) : null;
Action? exportSetterAction = setterExporter != null ? () => AppendInvoke(builder, setterExporter) : null;
string? interfaceName = isExplicitImplementation ? getterSetterPair.Accessors.First().Outer?.GetFullManagedName() : null;
ExportProperty_Internal(builder, property, propertyName, ExportBackingFields, ExportProtection, exportGetterAction, exportSetterAction, interfaceName: interfaceName);
}
public void ExportGetSetProperty(GeneratorStringBuilder builder, GetterSetterPair getterSetterPair, UhtProperty property,
Dictionary<UhtFunction, FunctionExporter> exportedGetterSetters,
HashSet<string>? exportedFunctionName = null)
{
void ExportNativeGetter()
{
builder.BeginUnsafeBlock();
builder.AppendStackAllocProperty($"{property.SourceName}_Size", property.GetNativePropertyName());
builder.AppendLine($"FPropertyExporter.CallGetValue_InContainer({property.GetNativePropertyName()}, NativeObject, paramsBuffer);");
ExportFromNative(builder, property, property.SourceName, $"{GetManagedType(property)} newValue =", "paramsBuffer", "0", true, false);
builder.AppendLine("return newValue;");
builder.EndUnsafeBlock();
}
void ExportBlueprintGetter()
{
AppendInvoke(builder, getterSetterPair.GetterExporter!);
}
void ExportGetter()
{
ExportPropertyGetter(builder, property, property.SourceName);
}
void ExportNativeSetter()
{
builder.BeginUnsafeBlock();
builder.AppendStackAllocProperty($"{property.SourceName}_Size", property.GetNativePropertyName());
ExportToNative(builder, property, property.SourceName, "paramsBuffer", "0", "value");
builder.AppendLine($"FPropertyExporter.CallSetValue_InContainer({property.GetNativePropertyName()}, NativeObject, paramsBuffer);");
ExportCleanupMarshallingBuffer(builder, property, property.SourceName);
builder.EndUnsafeBlock();
}
void ExportBlueprintSetter()
{
AppendInvoke(builder, getterSetterPair.SetterExporter!);
}
void ExportSetter()
{
ExportPropertySetter(builder, property, property.SourceName);
}
Action? exportGetterAction;
if (property.HasNativeGetter())
{
exportGetterAction = ExportNativeGetter;
}
else if (getterSetterPair.GetterExporter != null)
{
exportGetterAction = ExportBlueprintGetter;
}
else
{
exportGetterAction = ExportGetter;
}
Action? exportSetterAction = null;
if (property.HasNativeSetter())
{
exportSetterAction = ExportNativeSetter;
}
else if (getterSetterPair.SetterExporter != null)
{
exportSetterAction = ExportBlueprintSetter;
}
else if (SupportsSetter && property.IsReadWrite())
{
exportSetterAction = ExportSetter;
}
void ExportBackingFields()
{
if (getterSetterPair.GetterExporter is not null && !exportedGetterSetters.ContainsKey(getterSetterPair.Getter!) && (exportedFunctionName is null || !exportedFunctionName.Contains(getterSetterPair.Getter!.SourceName)))
{
getterSetterPair.GetterExporter.ExportFunctionVariables(builder);
exportedGetterSetters.Add(getterSetterPair.Getter!, getterSetterPair.GetterExporter);
}
if (getterSetterPair.SetterExporter is not null && !exportedGetterSetters.ContainsKey(getterSetterPair.Setter!) && (exportedFunctionName is null || !exportedFunctionName.Contains(getterSetterPair.Setter!.SourceName)))
{
getterSetterPair.SetterExporter.ExportFunctionVariables(builder);
exportedGetterSetters.Add(getterSetterPair.Setter!, getterSetterPair.SetterExporter);
}
if (getterSetterPair.GetterExporter is null || getterSetterPair.SetterExporter is null)
{
ExportPropertyVariables(builder, property, property.SourceName);
}
}
ExportProperty_Internal(builder, property, getterSetterPair.PropertyName, ExportBackingFields, null, exportGetterAction, exportSetterAction);
}
public void ExportProperty(GeneratorStringBuilder builder, UhtProperty property)
{
void ExportGetter()
{
ExportPropertyGetter(builder, property, property.SourceName);
}
void ExportSetter()
{
ExportPropertySetter(builder, property, property.SourceName);
}
void ExportBackingFields()
{
ExportPropertyVariables(builder, property, property.SourceName);
}
bool isReadWrite = property.IsReadWrite();
bool isEditDefaultsOnly = property.IsEditDefaultsOnly();
Action? exportSetterAction = SupportsSetter && (isReadWrite || isEditDefaultsOnly) ? ExportSetter : null;
string setterOperation = isEditDefaultsOnly && !isReadWrite ? "init" : "set";
ExportProperty_Internal(builder, property, property.GetPropertyName(), ExportBackingFields, null, ExportGetter, exportSetterAction, setterOperation);
}
private void ExportProperty_Internal(GeneratorStringBuilder builder, UhtProperty property, string propertyName,
Action? backingFieldsExport,
Func<string>? exportProtection,
Action? exportGetter,
Action? exportSetter,
string setterOperation = "set",
string? interfaceName = null)
{
builder.AppendLine();
builder.TryAddWithEditor(property);
if (backingFieldsExport is not null)
{
backingFieldsExport();
builder.AppendLine();
}
string protection = exportProtection != null ? exportProtection.Invoke() : property.GetProtection();
builder.AppendTooltip(property);
string managedType = GetManagedType(property);
if (interfaceName is not null)
{
builder.AppendLine($"{managedType} {interfaceName}.{propertyName}");
}
else
{
builder.AppendLine($"{protection}{managedType} {propertyName}");
}
builder.OpenBrace();
if (exportGetter is not null)
{
builder.AppendLine("get");
builder.OpenBrace();
exportGetter();
builder.CloseBrace();
}
if (exportSetter is not null)
{
builder.AppendLine(setterOperation);
builder.OpenBrace();
exportSetter();
builder.CloseBrace();
}
builder.CloseBrace();
builder.TryEndWithEditor(property);
builder.AppendLine();
}
private void AppendInvoke(GeneratorStringBuilder builder, FunctionExporter exportedFunction)
{
exportedFunction.ExportInvoke(builder);
}
public void ExportMirrorProperty(UhtStruct structObj, GeneratorStringBuilder builder, UhtProperty property, bool suppressOffsets, List<string> reservedNames, bool isReadOnly, bool useProperties)
{
string propertyScriptName = property.GetPropertyName();
builder.AppendLine($"// {propertyScriptName}");
builder.AppendLine();
if (!suppressOffsets)
{
ExportPropertyVariables(builder, property, property.SourceName);
}
string protection = property.GetProtection();
string managedType = GetManagedType(property);
string required = property.HasMetadata("Required") ? "required " : "";;
builder.AppendTooltip(property);
if (structObj.IsStructNativelyCopyable())
{
builder.AppendLine($"{protection}{required}{managedType} {propertyScriptName}");
builder.OpenBrace();
builder.AppendLine("get");
builder.OpenBrace();
GenerateMirrorPropertyBody(structObj, builder, property, true);
builder.CloseBrace();
builder.AppendLine(isReadOnly ? "init" : "set");
builder.OpenBrace();
GenerateMirrorPropertyBody(structObj, builder, property, false);
builder.CloseBrace();
builder.CloseBrace();
}
else if (useProperties)
{
string setter = isReadOnly ? "init;" : "set;";
builder.AppendLine($"{protection}{required}{managedType} {propertyScriptName} {{ get; {setter} }}");
}
else
{
string @readonly = isReadOnly ? "readonly " : "";
builder.AppendLine($"{protection}{required}{@readonly}{managedType} {propertyScriptName};");
}
builder.AppendLine();
}
private void GenerateMirrorPropertyBody(UhtStruct structObj, GeneratorStringBuilder builder, UhtProperty property, bool isGetter)
{
bool isDestructible = structObj.IsStructNativelyDestructible();
builder.BeginUnsafeBlock();
if (isDestructible)
{
builder.AppendLine("if (NativeHandle is null)");
builder.OpenBrace();
builder.AppendLine("NativeHandle = new NativeStructHandle(NativeClassPtr);");
}
else
{
builder.AppendLine("if (Allocation is null)");
builder.OpenBrace();
builder.AppendLine("Allocation = new byte[NativeDataSize];");
}
builder.CloseBrace();
builder.AppendLine();
if (isDestructible)
{
builder.AppendLine("fixed (NativeStructHandleData* StructDataPointer = &NativeHandle.Data)");
builder.OpenBrace();
builder.AppendLine($"IntPtr AllocationPointer = {ExporterCallbacks.UScriptStructCallbacks}.CallGetStructLocation(StructDataPointer, NativeClassPtr);");
}
else
{
builder.AppendLine("fixed (byte* AllocationPointer = Allocation)");
builder.OpenBrace();
}
if (isGetter)
{
ExportFromNative(builder, property, property.SourceName, "return", "(IntPtr) AllocationPointer", $"{property.SourceName}_Offset", false, false);
}
else
{
ExportToNative(builder, property, property.SourceName, "(IntPtr) AllocationPointer", $"{property.SourceName}_Offset", "value");
}
builder.CloseBrace();
builder.CloseBrace();
}
public string GetCppDefaultValue(UhtFunction function, UhtProperty parameter)
{
string metaDataKey = $"CPP_Default_{parameter.SourceName}";
return function.GetMetadata(metaDataKey);
}
protected void AddNativePropertyField(GeneratorStringBuilder builder, string propertyName)
{
builder.AppendLine($"static IntPtr {GetNativePropertyField(propertyName)};");
}
protected string GetNativePropertyField(string propertyName)
{
return $"{propertyName}_NativeProperty";
}
public virtual void ExportPropertyArithmetic(GeneratorStringBuilder stringBuilder, UhtProperty property, ArithmeticKind arithmeticKind)
{
string scriptName = property.GetScriptName();
static string Bin(string op, string lhs, string rhs) => $"{lhs} {op} {rhs}";
string rhsExpr = arithmeticKind switch
{
ArithmeticKind.Add => Bin("+", $"lhs.{scriptName}", $"rhs.{scriptName}"),
ArithmeticKind.Subtract => Bin("-", $"lhs.{scriptName}", $"rhs.{scriptName}"),
ArithmeticKind.Multiply => Bin("*", $"lhs.{scriptName}", $"rhs.{scriptName}"),
ArithmeticKind.Divide => Bin("/", $"lhs.{scriptName}", $"rhs.{scriptName}"),
ArithmeticKind.Modulo => Bin("%", $"lhs.{scriptName}", $"rhs.{scriptName}"),
_ => throw new NotSupportedException($"Arithmetic kind {arithmeticKind} not supported.")
};
string managedType = GetManagedType(property);
stringBuilder.Append($"{scriptName} = ({managedType})({rhsExpr})");
}
}

View File

@ -0,0 +1,242 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Model;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public static class PropertyTranslatorManager
{
private static readonly Dictionary<Type, List<PropertyTranslator>?> RegisteredTranslators = new();
private static readonly HashSet<Type> RegisteredPrimitives = new();
private static readonly HashSet<Type> RegisteredNumerics = new();
public static SpecialTypeInfo SpecialTypeInfo { get; } = new();
static PropertyTranslatorManager()
{
var projectDirectory = Program.Factory.Session.ProjectDirectory;
var configDirectory = Path.Combine(projectDirectory!, "Config");
var pluginDirectory = Path.Combine(projectDirectory!, "Plugins");
var pluginDirInfo = new DirectoryInfo(pluginDirectory);
var files = pluginDirInfo.GetFiles("*.uplugin", SearchOption.AllDirectories)
.Select(x => x.DirectoryName!)
.Select(x => Path.Combine(x, "Config"))
.Concat(new List<string> { configDirectory })
.Select(x => new DirectoryInfo(x))
.Where(x => x.Exists)
.SelectMany(x => x.GetFiles("*.UnrealSharpTypes.json", SearchOption.AllDirectories))
.Select(x => x.FullName);
foreach (var pluginFile in files)
{
using var fileStream = File.OpenRead(pluginFile);
try
{
var manifest = JsonSerializer.Deserialize<TypeTranslationManifest>(fileStream);
AddTranslationManifest(manifest!);
}
catch (JsonException e)
{
Console.WriteLine($"Error reading {pluginFile}: {e.Message}");
}
}
EnumPropertyTranslator enumPropertyTranslator = new();
AddPropertyTranslator(typeof(UhtEnumProperty), enumPropertyTranslator);
AddPropertyTranslator(typeof(UhtByteProperty), enumPropertyTranslator);
AddBlittablePropertyTranslator(typeof(UhtInt8Property), "sbyte", PropertyKind.SByte);
AddBlittablePropertyTranslator(typeof(UhtInt16Property), "short", PropertyKind.Short);
AddBlittablePropertyTranslator(typeof(UhtInt64Property), "long", PropertyKind.Long);
AddBlittablePropertyTranslator(typeof(UhtUInt16Property), "ushort", PropertyKind.UShort);
AddBlittablePropertyTranslator(typeof(UhtUInt32Property), "uint", PropertyKind.UInt);
AddBlittablePropertyTranslator(typeof(UhtUInt64Property), "ulong", PropertyKind.ULong);
AddBlittablePropertyTranslator(typeof(UhtDoubleProperty), "double", PropertyKind.Double);
AddBlittablePropertyTranslator(typeof(UhtByteProperty), "byte", PropertyKind.Byte);
AddBlittablePropertyTranslator(typeof(UhtLargeWorldCoordinatesRealProperty), "double", PropertyKind.Double);
AddPropertyTranslator(typeof(UhtFloatProperty), new FloatPropertyTranslator());
AddPropertyTranslator(typeof(UhtIntProperty), new IntPropertyTranslator());
MulticastDelegatePropertyTranslator multicastDelegatePropertyTranslator = new();
AddPropertyTranslator(typeof(UhtMulticastSparseDelegateProperty), multicastDelegatePropertyTranslator);
AddPropertyTranslator(typeof(UhtMulticastDelegateProperty), multicastDelegatePropertyTranslator);
AddPropertyTranslator(typeof(UhtMulticastInlineDelegateProperty), multicastDelegatePropertyTranslator);
AddPropertyTranslator(typeof(UhtDelegateProperty), new SinglecastDelegatePropertyTranslator());
AddBlittablePropertyTranslator(typeof(UhtByteProperty), "byte", PropertyKind.Byte);
AddPropertyTranslator(typeof(UhtBoolProperty), new BoolPropertyTranslator());
AddPropertyTranslator(typeof(UhtStrProperty), new StringPropertyTranslator());
AddPropertyTranslator(typeof(UhtNameProperty), new NamePropertyTranslator());
AddPropertyTranslator(typeof(UhtTextProperty), new TextPropertyTranslator());
AddPropertyTranslator(typeof(UhtWeakObjectPtrProperty), new WeakObjectPropertyTranslator());
WorldContextObjectPropertyTranslator worldContextObjectPropertyTranslator = new();
AddPropertyTranslator(typeof(UhtObjectPropertyBase), worldContextObjectPropertyTranslator);
#if !UE_5_6_OR_LATER
AddPropertyTranslator(typeof(UhtObjectPtrProperty), worldContextObjectPropertyTranslator);
#endif
AddPropertyTranslator(typeof(UhtObjectProperty), worldContextObjectPropertyTranslator);
AddPropertyTranslator(typeof(UhtLazyObjectPtrProperty), worldContextObjectPropertyTranslator);
ObjectPropertyTranslator objectPropertyTranslator = new();
AddPropertyTranslator(typeof(UhtObjectPropertyBase), objectPropertyTranslator);
#if !UE_5_6_OR_LATER
AddPropertyTranslator(typeof(UhtObjectPtrProperty), objectPropertyTranslator);
#endif
AddPropertyTranslator(typeof(UhtObjectProperty), objectPropertyTranslator);
AddPropertyTranslator(typeof(UhtLazyObjectPtrProperty), objectPropertyTranslator);
AddPropertyTranslator(typeof(UhtInterfaceProperty), new InterfacePropertyTranslator());
AddPropertyTranslator(typeof(UhtClassProperty), new ClassPropertyTranslator());
#if !UE_5_6_OR_LATER
AddPropertyTranslator(typeof(UhtClassPtrProperty), new ClassPropertyTranslator());
#endif
AddPropertyTranslator(typeof(UhtSoftClassProperty), new SoftClassPropertyTranslator());
AddPropertyTranslator(typeof(UhtSoftObjectProperty), new SoftObjectPropertyTranslator());
AddPropertyTranslator(typeof(UhtFieldPathProperty), new FieldPathPropertyTranslator());
foreach (var (nativeName, managedType) in SpecialTypeInfo.Structs.BlittableTypes.Values)
{
if (managedType is null)
{
continue;
}
AddBlittableCustomStructPropertyTranslator(nativeName, managedType);
}
AddPropertyTranslator(typeof(UhtArrayProperty), new ArrayPropertyTranslator());
AddPropertyTranslator(typeof(UhtMapProperty), new MapPropertyTranslator());
AddPropertyTranslator(typeof(UhtSetProperty), new SetPropertyTranslator());
AddPropertyTranslator(typeof(UhtStructProperty), new BlittableStructPropertyTranslator());
AddPropertyTranslator(typeof(UhtStructProperty), new StructPropertyTranslator());
AddPropertyTranslator(typeof(UhtOptionalProperty), new OptionalPropertyTranslator());
// Manually exported properties
InclusionLists.BanProperty("UWorld", "GameState");
InclusionLists.BanProperty("UWorld", "AuthorityGameMode");
// Some reason == equality differs from .Equals
InclusionLists.BanEquality("FRandomStream");
// Renamed variables X/Y/Z to Pitch/Yaw/Roll
InclusionLists.BanEquality("FRotator");
// Fields not generating correctly
InclusionLists.BanEquality("FVector3f");
InclusionLists.BanEquality("FVector2f");
InclusionLists.BanEquality("FVector4f");
InclusionLists.BanEquality("FVector_NetQuantize");
InclusionLists.BanEquality("FVector_NetQuantize10");
InclusionLists.BanEquality("FVector_NetQuantize100");
InclusionLists.BanEquality("FVector_NetQuantizeNormal");
// Doesn't have any fields
InclusionLists.BanEquality("FSubsystemCollectionBaseRef");
// Custom arithmetic needed
InclusionLists.BanArithmetic("FQuat");
}
public static void AddTranslationManifest(TypeTranslationManifest manifest)
{
foreach (var skippedStruct in manifest.Structs.CustomTypes)
{
SpecialTypeInfo.Structs.SkippedTypes.Add(skippedStruct);
}
foreach (var structInfo in manifest.Structs.BlittableTypes)
{
if (SpecialTypeInfo.Structs.NativelyCopyableTypes.ContainsKey(structInfo.Name))
{
throw new InvalidOperationException(
$"A struct cannot be both blittable and natively copyable: {structInfo.Name}");
}
if (SpecialTypeInfo.Structs.BlittableTypes.TryGetValue(structInfo.Name, out var existing))
{
if (structInfo.ManagedType is not null && existing.ManagedType is not null &&
structInfo.ManagedType != existing.ManagedType)
{
throw new InvalidOperationException($"Duplicate struct name specified: {structInfo.Name}");
}
}
else
{
SpecialTypeInfo.Structs.BlittableTypes.Add(structInfo.Name, structInfo);
}
}
foreach (var structInfo in manifest.Structs.NativelyTranslatableTypes)
{
if (SpecialTypeInfo.Structs.NativelyCopyableTypes.TryGetValue(structInfo.Name, out var existing))
{
SpecialTypeInfo.Structs.NativelyCopyableTypes[structInfo.Name] = existing with { HasDestructor = existing.HasDestructor || structInfo.HasDestructor };
continue;
}
if (SpecialTypeInfo.Structs.BlittableTypes.ContainsKey(structInfo.Name))
{
throw new InvalidOperationException(
$"A struct cannot be both blittable and natively copyable: {structInfo.Name}");
}
SpecialTypeInfo.Structs.NativelyCopyableTypes.Add(structInfo.Name, structInfo);
}
}
public static PropertyTranslator? GetTranslator(UhtProperty property)
{
if (!RegisteredTranslators.TryGetValue(property.GetType(), out var translator))
{
return null;
}
foreach (PropertyTranslator propertyTranslator in translator!)
{
if (propertyTranslator.CanExport(property))
{
return propertyTranslator;
}
}
return null;
}
public static void AddBlittablePropertyTranslator(Type propertyType, string managedType, PropertyKind propertyKind = PropertyKind.Unknown)
{
if (RegisteredTranslators.TryGetValue(propertyType, out var translators))
{
translators!.Add(new BlittableTypePropertyTranslator(propertyType, managedType, propertyKind));
return;
}
RegisteredTranslators.Add(propertyType, new List<PropertyTranslator> {new BlittableTypePropertyTranslator(propertyType, managedType, propertyKind) });
}
private static void AddPropertyTranslator(Type propertyClass, PropertyTranslator translator)
{
if (RegisteredTranslators.TryGetValue(propertyClass, out var translators))
{
translators!.Add(translator);
return;
}
RegisteredTranslators.Add(propertyClass, new List<PropertyTranslator> {translator});
}
private static void AddBlittableCustomStructPropertyTranslator(string nativeName, string managedType)
{
AddPropertyTranslator(typeof(UhtStructProperty), new BlittableCustomStructTypePropertyTranslator(nativeName, managedType));
}
}

View File

@ -0,0 +1,13 @@
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class SetPropertyTranslator : ContainerPropertyTranslator
{
public SetPropertyTranslator()
: base("SetCopyMarshaller",
"SetReadOnlyMarshaller",
"SetMarshaller",
"IReadOnlySet",
"ISet")
{
}
}

View File

@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class SimpleTypePropertyTranslator : PropertyTranslator
{
public override bool IsBlittable => true;
private readonly Type _propertyType;
protected readonly string ManagedType;
protected SimpleTypePropertyTranslator(Type propertyType, string managedType = "", PropertyKind propertyKind = PropertyKind.Unknown)
: base(EPropertyUsageFlags.Any, propertyKind)
{
_propertyType = propertyType;
ManagedType = managedType;
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
if (defaultValue == "None")
{
return GetNullValue(parameter);
}
return defaultValue;
}
public override string GetNullValue(UhtProperty property)
{
string managedType = GetManagedType(property);
return $"default({managedType})";
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName,
string assignmentOrReturn, string sourceBuffer, string offset, bool bCleanupSourceBuffer,
bool reuseRefMarshallers)
{
builder.AppendLine($"{assignmentOrReturn} {GetMarshaller(property)}.FromNative(IntPtr.Add({sourceBuffer}, {offset}), 0);");
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
builder.AppendLine($"{GetMarshaller(property)}.ToNative(IntPtr.Add({destinationBuffer}, {offset}), 0, {source});");
}
public override string GetMarshaller(UhtProperty property)
{
throw new NotImplementedException();
}
public virtual string GetPropertyName(UhtProperty property)
{
return property.GetParameterName();
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
string marshaller = GetMarshaller(property);
return $"{marshaller}.ToNative, {marshaller}.FromNative";
}
public override bool CanExport(UhtProperty property)
{
return property.GetType() == _propertyType || property.GetType().IsSubclassOf(_propertyType);
}
public override string GetManagedType(UhtProperty property)
{
return property.IsGenericType() ? "DOT" : ManagedType;
}
protected void ExportDefaultStructParameter(GeneratorStringBuilder builder, string variableName, string cppDefaultValue,
UhtProperty paramProperty, PropertyTranslator translator)
{
UhtStructProperty structProperty = (UhtStructProperty)paramProperty;
string structName = structProperty.ScriptStruct.GetStructName();
string fieldInitializerList;
if (cppDefaultValue.StartsWith("(") && cppDefaultValue.EndsWith(")"))
{
fieldInitializerList = cppDefaultValue.Substring(1, cppDefaultValue.Length - 2);
}
else
{
fieldInitializerList = cppDefaultValue;
}
if (fieldInitializerList.Length == 0)
{
return;
}
List<string> fieldInitializers = new List<string>();
string[] parts = fieldInitializerList.Split(',');
foreach (string part in parts)
{
fieldInitializers.Add(part.Trim());
}
string foundCSharpType = translator.GetManagedType(paramProperty);
builder.AppendLine($"{foundCSharpType} {variableName} = new {foundCSharpType}");
builder.OpenBrace();
if (structName == "Color")
{
(fieldInitializers[0], fieldInitializers[2]) = (fieldInitializers[2], fieldInitializers[0]);
}
int fieldCount = fieldInitializers.Count;
for (int i = 0; i < fieldCount; i++)
{
UhtProperty property = (UhtProperty) structProperty.ScriptStruct.Children[i];
PropertyTranslator propertyTranslator = PropertyTranslatorManager.GetTranslator(property)!;
string managedType = propertyTranslator.GetManagedType(property);
bool isFloat = managedType is "float" or "double";
string scriptName = property.SourceName;
string fieldInitializer = fieldInitializers[i];
int pos = fieldInitializer.IndexOf("=", StringComparison.Ordinal);
if (pos < 0)
{
builder.AppendLine(isFloat ? $"{scriptName}={fieldInitializer}f," : $"{scriptName}={fieldInitializer},");
}
else
{
builder.AppendLine(isFloat ? $"{fieldInitializer}f," : $"{fieldInitializer},");
}
}
builder.CloseBrace();
builder.Append(";");
}
public override void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property,
string paramName)
{
// No cleanup needed
}
public override bool CanSupportGenericType(UhtProperty property) => true;
}

View File

@ -0,0 +1,65 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class SinglecastDelegatePropertyTranslator : DelegateBasePropertyTranslator
{
public SinglecastDelegatePropertyTranslator() : base(EPropertyUsageFlags.Parameter)
{
}
public override bool CanExport(UhtProperty property)
{
UhtDelegateProperty delegateProperty = (UhtDelegateProperty) property;
bool hasReturnValue = delegateProperty.Function.ReturnProperty != null;
return ScriptGeneratorUtilities.CanExportParameters(delegateProperty.Function) && !hasReturnValue;
}
public override string GetManagedType(UhtProperty property)
{
return $"TDelegate<{GetFullDelegateName(((UhtDelegateProperty) property).Function)}>";
}
public override void ExportPropertyStaticConstructor(GeneratorStringBuilder builder, UhtProperty property, string nativePropertyName)
{
base.ExportPropertyStaticConstructor(builder, property, nativePropertyName);
UhtDelegateProperty delegateProperty = (UhtDelegateProperty) property;
if (!delegateProperty.Function.HasParameters)
{
return;
}
string fullDelegateName = GetFullDelegateName(delegateProperty.Function, true);
builder.AppendLine($"{fullDelegateName}.InitializeUnrealDelegate({nativePropertyName}_NativeProperty);");
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
UhtDelegateProperty delegateProperty = (UhtDelegateProperty) property;
string fullDelegateName = GetFullDelegateName(delegateProperty.Function);
builder.AppendLine($"SingleDelegateMarshaller<{fullDelegateName}>.ToNative(IntPtr.Add({destinationBuffer}, {offset}), 0, {source});");
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName,
string assignmentOrReturn, string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
UhtDelegateProperty delegateProperty = (UhtDelegateProperty) property;
string fullDelegateName = GetFullDelegateName(delegateProperty.Function);
builder.AppendLine($"{assignmentOrReturn} SingleDelegateMarshaller<{fullDelegateName}>.FromNative(IntPtr.Add({sourceBuffer}, {offset}), 0);");
}
public override string GetNullValue(UhtProperty property)
{
return "null";
}
public override void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property,
string paramName)
{
}
}

View File

@ -0,0 +1,35 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class SoftClassPropertyTranslator : SimpleTypePropertyTranslator
{
public SoftClassPropertyTranslator() : base(typeof(UhtSoftClassProperty))
{
}
public override string GetManagedType(UhtProperty property)
{
UhtSoftClassProperty softClassProperty = (UhtSoftClassProperty)property;
string fullName = property.IsGenericType()
? "DOT" : softClassProperty.MetaClass!.GetFullManagedName();
return $"TSoftClassPtr<{fullName}>";
}
public override string GetMarshaller(UhtProperty property)
{
UhtSoftClassProperty softClassProperty = (UhtSoftClassProperty) property;
string fullName = property.IsGenericType()
? "DOT" : softClassProperty.MetaClass!.GetFullManagedName();
return $"SoftClassMarshaller<{fullName}>";
}
public override bool CanExport(UhtProperty property)
{
return property is UhtSoftClassProperty;
}
}

View File

@ -0,0 +1,33 @@
using System.Collections.Generic;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class SoftObjectPropertyTranslator : SimpleTypePropertyTranslator
{
public SoftObjectPropertyTranslator() : base(typeof(UhtSoftObjectProperty))
{
}
public override bool CanExport(UhtProperty property)
{
return property is UhtSoftObjectProperty;
}
public override string GetManagedType(UhtProperty property)
{
UhtSoftObjectProperty softObjectProperty = (UhtSoftObjectProperty)property;
string fullName = softObjectProperty.Class.GetFullManagedName();
return $"TSoftObjectPtr<{fullName}>";
}
public override string GetMarshaller(UhtProperty property)
{
UhtSoftObjectProperty softClassProperty = (UhtSoftObjectProperty) property;
string fullName = softClassProperty.Class.GetFullManagedName();
return $"SoftObjectMarshaller<{fullName}>";
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,74 @@
using System;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class StringPropertyTranslator : PropertyTranslator
{
public StringPropertyTranslator() : base(EPropertyUsageFlags.Any, PropertyKind.String)
{
}
public override bool CacheProperty => true;
public override bool CanExport(UhtProperty property)
{
return property is UhtStrProperty;
}
public override string GetManagedType(UhtProperty property)
{
return "string";
}
public override string GetMarshaller(UhtProperty property)
{
return "StringMarshaller";
}
public override string ExportMarshallerDelegates(UhtProperty property)
{
return "StringMarshaller.ToNative, StringMarshaller.FromNative";
}
public override string GetNullValue(UhtProperty property)
{
return "\"\"";
}
public override void ExportFunctionReturnStatement(GeneratorStringBuilder builder, UhtProperty property, string nativePropertyName,
string functionName, string paramsCallString)
{
builder.AppendLine($"return {ExporterCallbacks.FStringCallbacks}.CallConvertTCHARToUTF8(Invoke_{functionName}(NativeObject, {functionName}_NativeFunction{paramsCallString}));");
}
public override void ExportCleanupMarshallingBuffer(GeneratorStringBuilder builder, UhtProperty property,
string paramName)
{
builder.AppendLine($"StringMarshaller.DestructInstance({paramName}_NativePtr, 0);");
}
public override void ExportFromNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string assignmentOrReturn,
string sourceBuffer, string offset, bool bCleanupSourceBuffer, bool reuseRefMarshallers)
{
if (!reuseRefMarshallers)
{
builder.AppendLine($"IntPtr {propertyName}_NativePtr = IntPtr.Add({sourceBuffer},{offset});");
}
builder.AppendLine($"{assignmentOrReturn} StringMarshaller.FromNative({propertyName}_NativePtr,0);");
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer, string offset, string source)
{
builder.AppendLine($"IntPtr {propertyName}_NativePtr = IntPtr.Add({destinationBuffer}, {offset});");
builder.AppendLine($"StringMarshaller.ToNative({propertyName}_NativePtr,0,{source});");
}
public override string ConvertCPPDefaultValue(string defaultValue, UhtFunction function, UhtProperty parameter)
{
return "\"" + defaultValue + "\"";
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,33 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class StructPropertyTranslator : SimpleTypePropertyTranslator
{
public StructPropertyTranslator() : base(typeof(UhtStructProperty))
{
}
public override bool ExportDefaultParameter => false;
public override bool IsBlittable => false;
public override string GetManagedType(UhtProperty property)
{
UhtStructProperty structProperty = (UhtStructProperty)property;
return structProperty.ScriptStruct.GetFullManagedName();
}
public override string GetMarshaller(UhtProperty property)
{
return $"StructMarshaller<{GetManagedType(property)}>";
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
ExportDefaultStructParameter(builder, variableName, defaultValue, paramProperty, this);
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,32 @@
using System;
using System.Text;
using EpicGames.UHT.Types;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class TextPropertyTranslator : BlittableTypePropertyTranslator
{
public TextPropertyTranslator() : base(typeof(UhtTextProperty), "FText", PropertyKind.Unknown)
{
}
public override bool ExportDefaultParameter => false;
public override string GetNullValue(UhtProperty property)
{
return "FText.None";
}
public override void ExportCppDefaultParameterAsLocalVariable(GeneratorStringBuilder builder, string variableName, string defaultValue,
UhtFunction function, UhtProperty paramProperty)
{
builder.AppendLine($"FText {variableName} = FText.None;");
}
public override string GetMarshaller(UhtProperty property)
{
return "TextMarshaller";
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class WeakObjectPropertyTranslator : BlittableTypePropertyTranslator
{
public WeakObjectPropertyTranslator() : base(typeof(UhtWeakObjectPtrProperty), "TWeakObjectPtr", PropertyKind.Unknown)
{
}
public override bool ExportDefaultParameter => false;
public override string GetManagedType(UhtProperty property)
{
UhtWeakObjectPtrProperty weakObjectProperty = (UhtWeakObjectPtrProperty)property;
string fullName = weakObjectProperty.Class.GetFullManagedName();
return $"TWeakObjectPtr<{fullName}>";
}
public override bool CanExport(UhtProperty property)
{
return property is UhtWeakObjectPtrProperty;
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}

View File

@ -0,0 +1,22 @@
using EpicGames.UHT.Types;
using UnrealSharpScriptGenerator.Utilities;
namespace UnrealSharpScriptGenerator.PropertyTranslators;
public class WorldContextObjectPropertyTranslator : ObjectPropertyTranslator
{
public override bool ShouldBeDeclaredAsParameter => false;
public override bool CanExport(UhtProperty property)
{
return base.CanExport(property) && property.IsWorldContextParameter();
}
public override void ExportToNative(GeneratorStringBuilder builder, UhtProperty property, string propertyName, string destinationBuffer,
string offset, string source)
{
builder.AppendLine($"BlittableMarshaller<IntPtr>.ToNative(IntPtr.Add({destinationBuffer}, {offset}), 0, UnrealSharp.Core.FCSManagerExporter.CallGetCurrentWorldContext());");
}
public override bool CanSupportGenericType(UhtProperty property) => false;
}