| @ -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)); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user