// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.IO; using System.Text; using EpicGames.Core; using Microsoft.Extensions.Logging; namespace UnrealBuildTool { class EddieSourceFile : ProjectFile.SourceFile { /// /// Constructor /// public EddieSourceFile(FileReference InitFilePath, DirectoryReference? InitRelativeBaseFolder) : base(InitFilePath, InitRelativeBaseFolder) { } } class EddieFolder { public EddieFolder(string InName, string InPath) { Name = InName; Path = InPath; FullPath = null; bIsModuleFolder = false; } public string Name; public string Path; public string? FullPath; public string? WorksetPath; public bool bIsModuleFolder; public Dictionary Folders = new Dictionary(); public List Files = new List(); } class EddieProjectFile : ProjectFile { Dictionary Folders = new Dictionary(); public EddieProjectFile(FileReference InitFilePath, DirectoryReference BaseDir) : base(InitFilePath, BaseDir) { } public override string ToString() { return ProjectFilePath.GetFileNameWithoutExtension(); } private bool IsSourceCode(string Extension) { return Extension == ".c" || Extension == ".cc" || Extension == ".cxx" || Extension == ".cpp" || Extension == ".m" || Extension == ".mm" || Extension == ".cs"; } public override SourceFile? AllocSourceFile(FileReference InitFilePath, DirectoryReference? InitProjectSubFolder) { if (InitFilePath.GetFileName().StartsWith(".")) { return null; } return new EddieSourceFile(InitFilePath, InitProjectSubFolder); } public EddieFolder? FindFolderByRelativePath(ref Dictionary Groups, string RelativePath) { string[] Parts = RelativePath.Split(Path.DirectorySeparatorChar); string CurrentPath = ""; Dictionary CurrentParent = Groups; foreach (string Part in Parts) { EddieFolder CurrentGroup; if (!System.String.IsNullOrEmpty(CurrentPath)) { CurrentPath += Path.DirectorySeparatorChar; } CurrentPath += Part; if (!CurrentParent.ContainsKey(CurrentPath)) { CurrentGroup = new EddieFolder(Path.GetFileName(CurrentPath), CurrentPath); CurrentParent.Add(CurrentPath, CurrentGroup); } else { CurrentGroup = CurrentParent[CurrentPath]; } if (CurrentPath == RelativePath) { return CurrentGroup; } CurrentParent = CurrentGroup.Folders; } return null; } private static string ConvertPath(string InPath) { return InPath.Replace("\\", "/"); } private void ParseSourceFilesIntoGroups() { foreach (SourceFile CurSourceFile in SourceFiles) { EddieSourceFile SourceFile = (EddieSourceFile)CurSourceFile; string FileName = SourceFile.Reference.GetFileName(); //string FileExtension = Path.GetExtension(FileName); //string FilePath = SourceFile.Reference.MakeRelativeTo(ProjectFilePath.Directory); //string FilePathMac = Utils.CleanDirectorySeparators(FilePath, '/'); string ProjectRelativeSourceFile = CurSourceFile.Reference.MakeRelativeTo(ProjectFilePath.Directory); string RelativeSourceDirectory = Path.GetDirectoryName(ProjectRelativeSourceFile)!; // Use the specified relative base folder if (CurSourceFile.BaseFolder != null) // NOTE: We are looking for null strings, not empty strings! { RelativeSourceDirectory = Path.GetDirectoryName(CurSourceFile.Reference.MakeRelativeTo(CurSourceFile.BaseFolder))!; } EddieFolder? Group = FindFolderByRelativePath(ref Folders, RelativeSourceDirectory); if (Group != null) { if (FileName.EndsWith(".build.cs") || FileName.EndsWith(".Build.cs") || FileName.EndsWith(".csproj")) { Group.bIsModuleFolder = true; Group.WorksetPath = ProjectFilePath.FullName + "." + Group.Name + ".wkst"; } Group.FullPath = Path.GetDirectoryName(SourceFile.Reference.FullName); Group.Files.Add(SourceFile); } } } private void EmitProject(StringBuilder Content, Dictionary Folders, ILogger Logger) { foreach (KeyValuePair CurGroup in Folders) { if (Path.GetFileName(CurGroup.Key) != "Documentation") { Content.Append("AddFileGroup \"" + Path.GetFileName(CurGroup.Key) + "\" \"" + (CurGroup.Value.FullPath ?? CurGroup.Value.Path) + "\"" + ProjectFileGenerator.NewLine); if (CurGroup.Value.bIsModuleFolder) { StringBuilder ProjectFileContent = new StringBuilder(); ProjectFileContent.Append("# @Eddie Workset@" + ProjectFileGenerator.NewLine); ProjectFileContent.Append("AddWorkset \"" + Path.GetFileName(CurGroup.Key) + ".wkst\" \"" + CurGroup.Value.WorksetPath + "\"" + ProjectFileGenerator.NewLine); ProjectFileContent.Append("AddFileGroup \"" + Path.GetFileName(CurGroup.Key) + "\" \"" + (CurGroup.Value.FullPath ?? CurGroup.Value.Path) + "\"" + ProjectFileGenerator.NewLine); EmitProject(ProjectFileContent, CurGroup.Value.Folders, Logger); foreach (EddieSourceFile File in CurGroup.Value.Files) { ProjectFileContent.Append("AddFile \"" + File.Reference.GetFileName() + "\" \"" + File.Reference.FullName + "\"" + ProjectFileGenerator.NewLine); } ProjectFileContent.Append("EndFileGroup \"" + Path.GetFileName(CurGroup.Key) + "\"" + ProjectFileGenerator.NewLine); ProjectFileGenerator.WriteFileIfChanged(CurGroup.Value.WorksetPath!, ProjectFileContent.ToString(), Logger, new UTF8Encoding()); Content.Append("AddFile \"" + Path.GetFileName(CurGroup.Key) + "\" \"" + CurGroup.Value.WorksetPath + "\"" + ProjectFileGenerator.NewLine); } else { EmitProject(Content, CurGroup.Value.Folders, Logger); foreach (EddieSourceFile File in CurGroup.Value.Files) { Content.Append("AddFile \"" + File.Reference.GetFileName() + "\" \"" + File.Reference.FullName + "\"" + ProjectFileGenerator.NewLine); } } Content.Append("EndFileGroup \"" + Path.GetFileName(CurGroup.Key) + "\"" + ProjectFileGenerator.NewLine); } } } public override bool WriteProjectFile(List InPlatforms, List InConfigurations, PlatformProjectGeneratorCollection PlatformProjectGenerators, ILogger Logger) { bool bSuccess = false; //string TargetName = ProjectFilePath.GetFileNameWithoutExtension(); //FileReference GameProjectPath = null; //foreach(ProjectTarget Target in ProjectTargets) //{ // if(Target.UnrealProjectFilePath != null) // { // GameProjectPath = Target.UnrealProjectFilePath; // break; // } //} StringBuilder ProjectFileContent = new StringBuilder(); ProjectFileContent.Append("# @Eddie Workset@" + ProjectFileGenerator.NewLine); ProjectFileContent.Append("AddWorkset \"" + ToString() + ".wkst\" \"" + ProjectFilePath.FullName + "\"" + ProjectFileGenerator.NewLine); ParseSourceFilesIntoGroups(); EmitProject(ProjectFileContent, Folders, Logger); bSuccess = ProjectFileGenerator.WriteFileIfChanged(ProjectFilePath.FullName, ProjectFileContent.ToString(), Logger, new UTF8Encoding()); return bSuccess; } } }