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