243 lines
11 KiB
C#
243 lines
11 KiB
C#
|
|
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));
|
||
|
|
}
|
||
|
|
}
|