147 lines
5.4 KiB
C#
147 lines
5.4 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.Utilities;
|
|||
|
|
|
|||
|
|
public static class PluginUtilities
|
|||
|
|
{
|
|||
|
|
public static readonly Dictionary<UhtPackage, ProjectDirInfo> PluginInfo = new();
|
|||
|
|
|
|||
|
|
private static readonly Dictionary<string, string> ExtractedEngineModules = new();
|
|||
|
|
|
|||
|
|
static PluginUtilities()
|
|||
|
|
{
|
|||
|
|
string? projectDirectory = Program.Factory.Session.ProjectDirectory;
|
|||
|
|
string pluginDirectory = Path.Combine(projectDirectory!, "Plugins");
|
|||
|
|
DirectoryInfo pluginDirInfo = new DirectoryInfo(pluginDirectory);
|
|||
|
|
|
|||
|
|
IEnumerable<(string DirectoryName, string FullName)> files = pluginDirInfo.GetFiles("*.uplugin", SearchOption.AllDirectories)
|
|||
|
|
.Select(x => x.DirectoryName!)
|
|||
|
|
.Select(x => (DirectoryName: x, ConfigPath: Path.Combine(x, "Config")))
|
|||
|
|
.Select(x => (x.DirectoryName, ConfigDir: new DirectoryInfo(x.ConfigPath)))
|
|||
|
|
.Where(x => x.ConfigDir.Exists)
|
|||
|
|
.SelectMany(x => x.ConfigDir.GetFiles("*.ExtractedModules.json", SearchOption.AllDirectories),
|
|||
|
|
(x, y) => (x.DirectoryName, FileInfo: y))
|
|||
|
|
.Select(x => (x.DirectoryName, x.FileInfo.FullName));
|
|||
|
|
|
|||
|
|
foreach ((string pluginDir, string pluginFile) in files)
|
|||
|
|
{
|
|||
|
|
using FileStream fileStream = File.OpenRead(pluginFile);
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
List<string>? manifest = JsonSerializer.Deserialize<List<string>>(fileStream);
|
|||
|
|
foreach (string module in manifest!)
|
|||
|
|
{
|
|||
|
|
ExtractedEngineModules.Add($"/Script/{module}", pluginDir);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (JsonException e)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"Error reading {pluginFile}: {e.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static ProjectDirInfo FindOrAddProjectInfo(this UhtPackage package)
|
|||
|
|
{
|
|||
|
|
if (PluginInfo.TryGetValue(package, out ProjectDirInfo plugin))
|
|||
|
|
{
|
|||
|
|
return plugin;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ProjectDirInfo info;
|
|||
|
|
HashSet<string> dependencies = [];
|
|||
|
|
if (package.IsPartOfEngine())
|
|||
|
|
{
|
|||
|
|
if (ExtractedEngineModules.TryGetValue(package.SourceName, out string? pluginPath))
|
|||
|
|
{
|
|||
|
|
DirectoryInfo pluginDir = new(pluginPath);
|
|||
|
|
info = new ProjectDirInfo(pluginDir.Name, pluginPath, dependencies);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
info = new ProjectDirInfo("Engine", Program.EngineGluePath, dependencies);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
string baseDirectory = package.GetModule().BaseDirectory;
|
|||
|
|
DirectoryInfo? currentDirectory = new DirectoryInfo(baseDirectory);
|
|||
|
|
|
|||
|
|
FileInfo? projectFile = null;
|
|||
|
|
while (currentDirectory is not null)
|
|||
|
|
{
|
|||
|
|
FileInfo[] foundFiles = currentDirectory.GetFiles("*.*", SearchOption.TopDirectoryOnly);
|
|||
|
|
projectFile = foundFiles.FirstOrDefault(f =>
|
|||
|
|
f.Extension.Equals(".uplugin", StringComparison.OrdinalIgnoreCase) ||
|
|||
|
|
f.Extension.Equals(".uproject", StringComparison.OrdinalIgnoreCase));
|
|||
|
|
|
|||
|
|
if (projectFile is not null)
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
currentDirectory = currentDirectory.Parent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (projectFile is null)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException(
|
|||
|
|
$"Could not find .uplugin or .uproject file for package {package.SourceName} in {baseDirectory}");
|
|||
|
|
}
|
|||
|
|
info = new ProjectDirInfo(Path.GetFileNameWithoutExtension(projectFile.Name), currentDirectory!.FullName, dependencies);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PluginInfo.Add(package, info);
|
|||
|
|
|
|||
|
|
foreach (UhtHeaderFile header in package.GetHeaderFiles())
|
|||
|
|
{
|
|||
|
|
HashSet<UhtHeaderFile> referencedHeaders = header.References.ReferencedHeaders;
|
|||
|
|
referencedHeaders.UnionWith(header.ReferencedHeadersNoLock);
|
|||
|
|
|
|||
|
|
foreach (UhtHeaderFile refHeader in referencedHeaders)
|
|||
|
|
{
|
|||
|
|
foreach (UhtPackage refPackage in refHeader.GetPackages())
|
|||
|
|
{
|
|||
|
|
if (refPackage == package)
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (refPackage.IsPartOfEngine())
|
|||
|
|
{
|
|||
|
|
if (!ExtractedEngineModules.TryGetValue(refPackage.SourceName, out string? pluginPath))
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (info.IsPartOfEngine)
|
|||
|
|
{
|
|||
|
|
DirectoryInfo pluginDir = new(pluginPath);
|
|||
|
|
info = new ProjectDirInfo(pluginDir.Name, pluginPath, dependencies);
|
|||
|
|
PluginInfo[package] = info;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
ProjectDirInfo projectInfo = refPackage.FindOrAddProjectInfo();
|
|||
|
|
if (info.GlueCsProjPath == projectInfo.GlueCsProjPath)
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dependencies.Add(projectInfo.GlueCsProjPath);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return info;
|
|||
|
|
}
|
|||
|
|
}
|