198 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Collections.Immutable;
 | 
						|
using System.Diagnostics;
 | 
						|
using System.IO;
 | 
						|
using System.Linq;
 | 
						|
using EpicGames.Core;
 | 
						|
using EpicGames.UHT.Tables;
 | 
						|
using EpicGames.UHT.Types;
 | 
						|
using EpicGames.UHT.Utils;
 | 
						|
using UnrealSharp.Shared;
 | 
						|
using UnrealSharpScriptGenerator.Utilities;
 | 
						|
 | 
						|
namespace UnrealSharpScriptGenerator;
 | 
						|
 | 
						|
[UnrealHeaderTool]
 | 
						|
public static class Program
 | 
						|
{
 | 
						|
    public static IUhtExportFactory Factory { get; private set; } = null!;
 | 
						|
    public static UHTManifest.Module PluginModule => Factory.PluginModule!;
 | 
						|
 | 
						|
    public static string EngineGluePath { get; private set; } = "";
 | 
						|
    public static string PluginsPath { get; private set; } = "";
 | 
						|
    public static string ProjectGluePath_LEGACY { get; private set; } = "";
 | 
						|
    public static string ProjectName => Path.GetFileNameWithoutExtension(Factory.Session.ProjectFile!);
 | 
						|
 | 
						|
    public static bool BuildingEditor { get; private set; }
 | 
						|
    public static UhtClass BlueprintFunctionLibrary { get; private set; } = null!;
 | 
						|
 | 
						|
    public static string PluginDirectory { get; private set; } = "";
 | 
						|
    public static string ManagedBinariesPath { get; private set; } = "";
 | 
						|
    public static string ManagedPath { get; private set; } = "";
 | 
						|
    public static string ScriptFolder { get; private set; } = "";
 | 
						|
    public static ImmutableArray<ProjectDirInfo> PluginDirs { get; private set; }
 | 
						|
 | 
						|
    [UhtExporter(Name = "UnrealSharpCore", Description = "Exports C++ to C# code", Options = UhtExporterOptions.Default,
 | 
						|
        ModuleName = "UnrealSharpCore")]
 | 
						|
    private static void Main(IUhtExportFactory factory)
 | 
						|
    {
 | 
						|
        Console.WriteLine("Initializing C# Glue Generator...");
 | 
						|
        Factory = factory;
 | 
						|
 | 
						|
        InitializeStatics();
 | 
						|
 | 
						|
        UhtType? foundType = factory.Session.FindType(null, UhtFindOptions.SourceName | UhtFindOptions.Class, "UBlueprintFunctionLibrary");
 | 
						|
        if (foundType is not UhtClass blueprintFunctionLibrary)
 | 
						|
        {
 | 
						|
            throw new InvalidOperationException("Failed to find UBlueprintFunctionLibrary class.");
 | 
						|
        }
 | 
						|
 | 
						|
        BlueprintFunctionLibrary = blueprintFunctionLibrary;
 | 
						|
 | 
						|
        try
 | 
						|
        {
 | 
						|
            Stopwatch stopwatch = new Stopwatch();
 | 
						|
            stopwatch.Start();
 | 
						|
 | 
						|
            CSharpExporter.StartExport();
 | 
						|
            FileExporter.CleanOldExportedFiles();
 | 
						|
 | 
						|
            stopwatch.Stop();
 | 
						|
            Console.WriteLine($"Export process completed successfully in {stopwatch.Elapsed.TotalSeconds:F2} seconds.");
 | 
						|
 | 
						|
            if (CSharpExporter.HasModifiedEngineGlue && BuildingEditor)
 | 
						|
            {
 | 
						|
                Console.WriteLine("Detected modified engine glue. Building UnrealSharp solution...");
 | 
						|
                DotNetUtilities.BuildSolution(Path.Combine(ManagedPath, "UnrealSharp"), ManagedBinariesPath);
 | 
						|
            }
 | 
						|
 | 
						|
            CreateGlueProjects();
 | 
						|
        }
 | 
						|
        catch (Exception ex)
 | 
						|
        {
 | 
						|
            Console.ForegroundColor = ConsoleColor.Red;
 | 
						|
            Console.WriteLine("An error occurred during the export process:");
 | 
						|
            Console.WriteLine($"Error Message: {ex.Message}");
 | 
						|
            Console.WriteLine("Stack Trace:");
 | 
						|
            Console.WriteLine(ex.StackTrace);
 | 
						|
            Console.ResetColor();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private static void InitializeStatics()
 | 
						|
    {
 | 
						|
        PluginDirectory = ScriptGeneratorUtilities.TryGetPluginDefine("PLUGIN_PATH");
 | 
						|
 | 
						|
        string projectDirectory = Factory.Session.ProjectDirectory!;
 | 
						|
		ScriptFolder = Path.Combine(projectDirectory, "Script");
 | 
						|
        PluginsPath = Path.Combine(projectDirectory, "Plugins");
 | 
						|
        ProjectGluePath_LEGACY = Path.Combine(ScriptFolder, "ProjectGlue");
 | 
						|
 | 
						|
        EngineGluePath = ScriptGeneratorUtilities.TryGetPluginDefine("GENERATED_GLUE_PATH");
 | 
						|
 | 
						|
        ManagedBinariesPath = Path.Combine(PluginDirectory, "Binaries", "Managed");
 | 
						|
 | 
						|
        ManagedPath = Path.Combine(PluginDirectory, "Managed");
 | 
						|
 | 
						|
        BuildingEditor = ScriptGeneratorUtilities.TryGetPluginDefine("BUILDING_EDITOR") == "1";
 | 
						|
 | 
						|
        DirectoryInfo pluginsDir = new DirectoryInfo(PluginsPath);
 | 
						|
 | 
						|
        PluginDirs = pluginsDir.GetFiles("*.uplugin", SearchOption.AllDirectories)
 | 
						|
                .Where(x => x.Directory!.GetDirectories("Source").Length != 0)
 | 
						|
                .Select(x => new ProjectDirInfo(Path.GetFileNameWithoutExtension(x.Name), x.DirectoryName!))
 | 
						|
                .Where(x => x.GlueProjectName != "UnrealSharp")
 | 
						|
                .ToImmutableArray();
 | 
						|
    }
 | 
						|
    
 | 
						|
    private static void CreateGlueProjects()
 | 
						|
    {
 | 
						|
        bool hasProjectGlue = false;
 | 
						|
        foreach (ProjectDirInfo pluginDir in PluginUtilities.PluginInfo.Values)
 | 
						|
        {
 | 
						|
            if (pluginDir.IsPartOfEngine) continue;
 | 
						|
            
 | 
						|
            if (pluginDir.IsUProject)
 | 
						|
            {
 | 
						|
                hasProjectGlue = true;
 | 
						|
            }
 | 
						|
            
 | 
						|
            TryCreateGlueProject(pluginDir.GlueCsProjPath, pluginDir.GlueProjectName, pluginDir.Dependencies, pluginDir.ProjectRoot);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!hasProjectGlue)
 | 
						|
        {
 | 
						|
            UhtSession session = Factory.Session;
 | 
						|
            string projectRoot = session.ProjectDirectory!;
 | 
						|
            string baseName = Path.GetFileNameWithoutExtension(session.ProjectFile!);
 | 
						|
            string projectName = baseName + ".Glue";
 | 
						|
            string csprojPath = Path.Join(projectRoot, "Script", projectName, projectName + ".csproj");
 | 
						|
 | 
						|
            TryCreateGlueProject(csprojPath, projectName, null, projectRoot);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private static void TryCreateGlueProject(string csprojPath, string projectName, IEnumerable<string>? dependencyPaths, string projectRoot)
 | 
						|
    {
 | 
						|
        if (!File.Exists(csprojPath))
 | 
						|
        {
 | 
						|
            string projectDirectory = Path.GetDirectoryName(csprojPath)!;
 | 
						|
            List<KeyValuePair<string, string>> arguments = new List<KeyValuePair<string, string>>
 | 
						|
            {
 | 
						|
                new("NewProjectName", projectName),
 | 
						|
                new("NewProjectFolder", Path.GetDirectoryName(projectDirectory)!),
 | 
						|
                new("SkipIncludeProjectGlue", "true"),
 | 
						|
                new("SkipSolutionGeneration", "true"),
 | 
						|
            };
 | 
						|
 | 
						|
            arguments.Add(new KeyValuePair<string, string>("ProjectRoot", projectRoot));
 | 
						|
            if (!DotNetUtilities.InvokeUSharpBuildTool("GenerateProject", ManagedBinariesPath,
 | 
						|
                    ProjectName,
 | 
						|
                    PluginDirectory,
 | 
						|
                    Factory.Session.ProjectDirectory!,
 | 
						|
                    Factory.Session.EngineDirectory!,
 | 
						|
                    arguments))
 | 
						|
            {
 | 
						|
                throw new InvalidOperationException($"Failed to create project file at {csprojPath}");
 | 
						|
            }
 | 
						|
            
 | 
						|
            Console.WriteLine($"Successfully created project file: {projectName}");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            Console.WriteLine($"Project file already exists: {projectName}. Skipping creation.");
 | 
						|
        }
 | 
						|
        
 | 
						|
        AddPluginDependencies(projectName, csprojPath, dependencyPaths);
 | 
						|
    }
 | 
						|
 | 
						|
    private static void AddPluginDependencies(string projectName, string projectPath, IEnumerable<string>? dependencies)
 | 
						|
    {
 | 
						|
        List<KeyValuePair<string, string>> arguments = new()
 | 
						|
        {
 | 
						|
            new KeyValuePair<string, string>("ProjectPath", projectPath),
 | 
						|
        };
 | 
						|
 | 
						|
        if (dependencies != null)
 | 
						|
        {
 | 
						|
            foreach (string path in dependencies)
 | 
						|
            {
 | 
						|
                arguments.Add(new KeyValuePair<string, string>("Dependency", path));
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (!DotNetUtilities.InvokeUSharpBuildTool("UpdateProjectDependencies", ManagedBinariesPath,
 | 
						|
                ProjectName,
 | 
						|
                PluginDirectory,
 | 
						|
                Factory.Session.ProjectDirectory!,
 | 
						|
                Factory.Session.EngineDirectory!,
 | 
						|
                arguments))
 | 
						|
        {
 | 
						|
            throw new InvalidOperationException($"Failed to update project dependencies for {projectPath}");
 | 
						|
        }
 | 
						|
        
 | 
						|
        Console.WriteLine($"Updated project dependencies for {projectName}");
 | 
						|
    }
 | 
						|
}
 |