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