347 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			347 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 
								 | 
							
								using System;
							 | 
						|||
| 
								 | 
							
								using System.Collections.Generic;
							 | 
						|||
| 
								 | 
							
								using System.IO;
							 | 
						|||
| 
								 | 
							
								using System.Linq;
							 | 
						|||
| 
								 | 
							
								using System.Reflection;
							 | 
						|||
| 
								 | 
							
								using System.Text.Json;
							 | 
						|||
| 
								 | 
							
								using System.Threading.Tasks;
							 | 
						|||
| 
								 | 
							
								using EpicGames.Core;
							 | 
						|||
| 
								 | 
							
								using EpicGames.UHT.Types;
							 | 
						|||
| 
								 | 
							
								using EpicGames.UHT.Utils;
							 | 
						|||
| 
								 | 
							
								using UnrealSharpScriptGenerator.Exporters;
							 | 
						|||
| 
								 | 
							
								using UnrealSharpScriptGenerator.Model;
							 | 
						|||
| 
								 | 
							
								using UnrealSharpScriptGenerator.PropertyTranslators;
							 | 
						|||
| 
								 | 
							
								using UnrealSharpScriptGenerator.Utilities;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace UnrealSharpScriptGenerator;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								class ModuleFolders
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    public Dictionary<string, DateTime> DirectoryToWriteTime { get; set; } = new();
							 | 
						|||
| 
								 | 
							
								    public bool HasBeenExported;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								public static class CSharpExporter
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    const string ModuleDataFileName = "UnrealSharpModuleData.json";
							 | 
						|||
| 
								 | 
							
								    private const string SpecialtypesJson = "SpecialTypes.json";
							 | 
						|||
| 
								 | 
							
								    public static bool HasModifiedEngineGlue;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static readonly List<Task> Tasks = new();
							 | 
						|||
| 
								 | 
							
								    private static readonly List<string> ExportedDelegates = new();
							 | 
						|||
| 
								 | 
							
								    private static readonly Dictionary<string, DateTime> CachedDirectoryTimes = new();
							 | 
						|||
| 
								 | 
							
								    private static Dictionary<string, ModuleFolders?> _modulesWriteInfo = new();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    public static void StartExport()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (!HasChangedGeneratorSourceRecently())
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            // The source for this generator hasn't changed, so we don't need to re-export the whole API.
							 | 
						|||
| 
								 | 
							
								            DeserializeModuleData();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        else
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            // Just in case the source has changed, we need to clean the old files
							 | 
						|||
| 
								 | 
							
								            Console.WriteLine("Detected new source since last export, cleaning old files...");
							 | 
						|||
| 
								 | 
							
								            FileExporter.CleanModuleFolders();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        Console.WriteLine("Exporting C++ to C#...");
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        #if UE_5_5_OR_LATER
							 | 
						|||
| 
								 | 
							
								        foreach (UhtModule module in Program.Factory.Session.Modules)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            foreach (UhtPackage modulePackage in module.Packages)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                ExportPackage(modulePackage);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        #else
							 | 
						|||
| 
								 | 
							
								        foreach (UhtPackage package in Program.Factory.Session.Packages)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            ExportPackage(package);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        #endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        WaitForTasks();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FunctionExporter.StartExportingExtensionMethods(Tasks);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        WaitForTasks();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        AutocastExporter.StartExportingAutocastFunctions(Tasks);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        WaitForTasks();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        SerializeModuleData();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        string generatedCodeDirectory = Program.PluginModule.OutputDirectory;
							 | 
						|||
| 
								 | 
							
								        string typeInfoFilePath = Path.Combine(generatedCodeDirectory, SpecialtypesJson);
							 | 
						|||
| 
								 | 
							
								        OutputTypeRules(typeInfoFilePath);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    static void DeserializeModuleData()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (!Directory.Exists(Program.EngineGluePath))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        string outputPath = Path.Combine(Program.PluginModule.OutputDirectory, ModuleDataFileName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (!File.Exists(outputPath))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        using FileStream fileStream = new FileStream(outputPath, FileMode.Open, FileAccess.Read, FileShare.Read);
							 | 
						|||
| 
								 | 
							
								        Dictionary<string, ModuleFolders>? jsonValue = JsonSerializer.Deserialize<Dictionary<string, ModuleFolders>>(fileStream);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (jsonValue != null)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _modulesWriteInfo = new Dictionary<string, ModuleFolders?>(jsonValue!);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    static void SerializeModuleData()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        string outputPath = Path.Combine(Program.PluginModule.OutputDirectory, ModuleDataFileName);
							 | 
						|||
| 
								 | 
							
								        using FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
							 | 
						|||
| 
								 | 
							
								        JsonSerializer.Serialize(fs, _modulesWriteInfo);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    static bool HasChangedGeneratorSourceRecently()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        string executingAssemblyPath = Assembly.GetExecutingAssembly().Location;
							 | 
						|||
| 
								 | 
							
								        DateTime executingAssemblyLastWriteTime = File.GetLastWriteTimeUtc(executingAssemblyPath);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        string generatedCodeDirectory = Program.PluginModule.OutputDirectory;
							 | 
						|||
| 
								 | 
							
								        string timestampFilePath = Path.Combine(generatedCodeDirectory, "Timestamp");
							 | 
						|||
| 
								 | 
							
								        string typeInfoFilePath = Path.Combine(generatedCodeDirectory, SpecialtypesJson);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (!File.Exists(timestampFilePath) || !File.Exists(typeInfoFilePath) || !Directory.Exists(Program.EngineGluePath))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (TypeRulesChanged(typeInfoFilePath))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        DateTime savedTimestampUtc = File.GetLastWriteTimeUtc(timestampFilePath);
							 | 
						|||
| 
								 | 
							
								        return executingAssemblyLastWriteTime > savedTimestampUtc;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    static bool TypeRulesChanged(string typeInfoFilePath)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        using var fs = new FileStream(typeInfoFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
							 | 
						|||
| 
								 | 
							
								        var rules = JsonSerializer.Deserialize<SpecialTypeInfo>(fs);
							 | 
						|||
| 
								 | 
							
								        if (rules == null)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        return !rules.Equals(PropertyTranslatorManager.SpecialTypeInfo);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    static void OutputTypeRules(string typeInfoFilePath)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        using var fs = new FileStream(typeInfoFilePath, FileMode.Create, FileAccess.Write);
							 | 
						|||
| 
								 | 
							
								        JsonSerializer.Serialize(fs, PropertyTranslatorManager.SpecialTypeInfo);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static void WaitForTasks()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        Task[] waitTasks = Tasks.ToArray();
							 | 
						|||
| 
								 | 
							
								        if (waitTasks.Length > 0)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            Task.WaitAll(waitTasks);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        Tasks.Clear();
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static void ExportPackage(UhtPackage package)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (!package.ShouldExport())
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (!Program.BuildingEditor && package.PackageFlags.HasAnyFlags(EPackageFlags.EditorOnly | EPackageFlags.UncookedOnly))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (!package.IsPartOfEngine())
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            package.FindOrAddProjectInfo();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        string packageName = package.GetShortName();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (!_modulesWriteInfo.TryGetValue(packageName, out ModuleFolders? lastEditTime))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            lastEditTime = new ModuleFolders();
							 | 
						|||
| 
								 | 
							
								            _modulesWriteInfo.Add(packageName, lastEditTime);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        HashSet<string> processedDirectories = new();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        string generatedPath = FileExporter.GetDirectoryPath(package);
							 | 
						|||
| 
								 | 
							
								        bool doesDirectoryExist = Directory.Exists(generatedPath);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        foreach (UhtType child in package.Children)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            string directoryName = Path.GetDirectoryName(child.HeaderFile.FilePath)!;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // We only need to export the C++ directory if it doesn't exist or if it has been modified
							 | 
						|||
| 
								 | 
							
								            if (!doesDirectoryExist || ShouldExportDirectory(directoryName, lastEditTime!))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                processedDirectories.Add(directoryName);
							 | 
						|||
| 
								 | 
							
								                ForEachChild(child, ExportType);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                ForEachChild(child, FileExporter.AddUnchangedType);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (processedDirectories.Count == 0)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            // No directories in this package have been exported or modified
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // The glue has been exported, so we need to update the last write times
							 | 
						|||
| 
								 | 
							
								        UpdateLastWriteTimes(processedDirectories, lastEditTime!);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static void ForEachChild(UhtType child, Action<UhtType> action)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        #if UE_5_5_OR_LATER
							 | 
						|||
| 
								 | 
							
								        action(child);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        foreach (UhtType type in child.Children)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            action(type);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        #else
							 | 
						|||
| 
								 | 
							
								        foreach (UhtType type in child.Children)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            action(type);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (UhtType innerType in type.Children)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                action(innerType);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        #endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    public static bool HasBeenExported(string directory)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        return _modulesWriteInfo.TryGetValue(directory, out ModuleFolders? lastEditTime) && lastEditTime is
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            HasBeenExported: true
							 | 
						|||
| 
								 | 
							
								        };
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static bool ShouldExportDirectory(string directoryPath, ModuleFolders lastEditTime)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (!CachedDirectoryTimes.TryGetValue(directoryPath, out DateTime cachedTime))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            DateTime currentWriteTime = Directory.GetLastWriteTimeUtc(directoryPath);
							 | 
						|||
| 
								 | 
							
								            CachedDirectoryTimes[directoryPath] = currentWriteTime;
							 | 
						|||
| 
								 | 
							
								            cachedTime = currentWriteTime;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        return !lastEditTime.DirectoryToWriteTime.TryGetValue(directoryPath, out DateTime lastEditTimeValue) || lastEditTimeValue != cachedTime;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static void UpdateLastWriteTimes(HashSet<string> directories, ModuleFolders lastEditTime)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        foreach (string directory in directories)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (!CachedDirectoryTimes.TryGetValue(directory, out DateTime cachedTime))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                continue;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            lastEditTime.DirectoryToWriteTime[directory] = cachedTime;
							 | 
						|||
| 
								 | 
							
								            lastEditTime.HasBeenExported = true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    private static void ExportType(UhtType type)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (type.HasMetadata(PackageUtilities.SkipGlueGenerationDefine) 
							 | 
						|||
| 
								 | 
							
								            || PropertyTranslatorManager.SpecialTypeInfo.Structs.SkippedTypes.Contains(type.SourceName))
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        bool isManualExport = PropertyTranslatorManager.SpecialTypeInfo.Structs.BlittableTypes.ContainsKey(type.SourceName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if (type is UhtClass classObj)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (classObj.HasAllFlags(EClassFlags.Interface))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (isManualExport)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    return;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (classObj.ClassType is not UhtClassType.Interface && type != Program.Factory.Session.IInterface)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    return;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                Tasks.Add(Program.Factory.CreateTask(_ => { InterfaceExporter.ExportInterface(classObj); })!);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Tasks.Add(Program.Factory.CreateTask(_ => { ClassExporter.ExportClass(classObj, isManualExport); })!);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        else if (type is UhtEnum enumObj)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (isManualExport)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            Tasks.Add(Program.Factory.CreateTask(_ => { EnumExporter.ExportEnum(enumObj); })!);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        else if (type is UhtScriptStruct structObj)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            isManualExport = PropertyTranslatorManager.SpecialTypeInfo.Structs.BlittableTypes.TryGetValue(structObj.SourceName, out var info) && info.ManagedType is not null;
							 | 
						|||
| 
								 | 
							
								            Tasks.Add(Program.Factory.CreateTask(_ => { StructExporter.ExportStruct(structObj, isManualExport); })!);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        else if (type.EngineType == UhtEngineType.Delegate)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (isManualExport)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            UhtFunction delegateFunction = (UhtFunction) type;
							 | 
						|||
| 
								 | 
							
								            if (!ScriptGeneratorUtilities.CanExportParameters(delegateFunction) || delegateFunction.ReturnProperty != null)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // There are some duplicate delegates in the same modules, so we need to check if we already exported it
							 | 
						|||
| 
								 | 
							
								            string delegateName = DelegateBasePropertyTranslator.GetFullDelegateName(delegateFunction);
							 | 
						|||
| 
								 | 
							
								            if (ExportedDelegates.Contains(delegateName))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            ExportedDelegates.Add(delegateName);
							 | 
						|||
| 
								 | 
							
								            Tasks.Add(Program.Factory.CreateTask(_ => { DelegateExporter.ExportDelegate(delegateFunction); })!);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |