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