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