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