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