using System.Collections.Generic; using System.IO; namespace Ubisoft { public class HtCscRsp { public const string PATH = "Assets/csc.rsp"; private const string HEADER = "#_File_generated_and_added_to_.gitignore_by_Hotel.\n#_DO_NOT_ADD_STUFF_HERE.\n#_Instead_create_a_csc.rsp_file_next_to_the_.asmdef_that_needs_to_be_affected_by_your_stuff.\n"; public HtCscRsp() { Reset(); } private SortedSet Symbols { get; set; } private SortedSet References { get; set; } public void Reset() { if (Symbols == null) { Symbols = new SortedSet(); } else { Symbols.Clear(); } if (References == null) { References = new SortedSet(); } else { References.Clear(); } } public void AddSymbol(string value) { _ = Symbols.Add(value); } public void AddSymbols(List values) { if (values != null) { _ = Symbols.AddRange(values); } } public void AddReference(string value) { _ = References.Add(value); } public void AddReferences(List values) { if (values != null) { _ = References.AddRange(values); } } public bool ExistsFile() { return HtAssetDatabase.ExistsFile(PATH); } public void Save() { SortedSet oldSymbols = new SortedSet(); string oldContent = string.Empty; if (ExistsFile()) { oldContent = LoadSymbols(oldSymbols); } string content = ""; // Header content += HEADER; // Define symbols if (Symbols != null) { foreach (string value in Symbols) { content += $"-define:{value}\n"; } } // References if (References != null && References.Count > 0) { foreach (string value in References) { content += $"-r:{value}\n"; } //content += "\n"; } if (!oldContent.Equals(content)) { File.WriteAllText(PATH, content); // Recreate assemblies if the set of symbols has changed if (!oldSymbols.SetEquals(Symbols)) { // Some assemblies might have define constraints that might not be met anymore with the new set of define symbols. // Unfortunately Unity doesn't recreate assemblies after crc.rsp gets modified so we need to do it manually RecreateAssemblies(); } } } private string LoadSymbols(SortedSet symbols) { string returnValue = ""; if (ExistsFile()) { string symbol; string defineToken = "-define:"; IEnumerable lines = File.ReadLines(PATH); foreach (string line in lines) { if (line.StartsWith(defineToken)) { symbol = line.Replace(defineToken, ""); _ = symbols.Add(symbol.Trim()); } returnValue += line + "\n"; } } return returnValue; } private void RecreateAssemblies() { Debug.EditorLog($"Recreating assemblies to adapt them to changes in the set of define symbols in {PATH} ..."); string unityPath; string directoryUnityPath; List asmDefDirectories = new List(); // Load all asmdef files string[] files = Directory.GetFiles(HtAssetDatabase.UnityPathToPlatformPath("Assets", true), "*.asmdef", SearchOption.AllDirectories); // We need to reimport all scripts affected by every asmdef. If they share the same root directory then only the root // directory is reimported foreach (string file in files) { // Translate platform path into unity path unityPath = HtAssetDatabase.PlatformPathToUnityPath(file, true); // Retrieve the directory path directoryUnityPath = HtAssetDatabase.UnityPathGetDirectoryName(unityPath); // Make sure that this directory is not included yet if (!AsmDefDirectoryContainsPath(asmDefDirectories, directoryUnityPath)) { // Add this directory to the list of paths AddAsmDefDirectory(asmDefDirectories, directoryUnityPath); } } // Reimport directories foreach (string s in asmDefDirectories) { UnityEditor.AssetDatabase.ImportAsset(s, UnityEditor.ImportAssetOptions.ImportRecursive); } } /// /// Return whether or not directoryPath is already part of any directories in asmDefDirectories. /// /// List of asmdef directories. /// Directory to search for. /// true is asmDefDirectories already contains directoryPath. private bool AsmDefDirectoryContainsPath(List asmDefDirectories, string directoryPath) { if (!string.IsNullOrEmpty(directoryPath)) { // If 'directoryPath' starts with any directory in 'asmDefDirectories' then 'directoryPath' is already contained foreach (string directory in asmDefDirectories) { if (directoryPath.StartsWith(directory)) { return true; } } } return false; } /// /// Add a directory to the list of assmebly directories to reimport. /// /// List of directories to reimport. /// Directory to add to the list. private void AddAsmDefDirectory(List asmDefDirectories, string directoryPath) { if (!string.IsNullOrEmpty(directoryPath)) { // Check if 'directoryPath' is shorter than any directories in 'asmDefDirectories', if so then // longer directories are deleted from 'asmDefDirectories' for (int i = asmDefDirectories.Count - 1; i > -1 && asmDefDirectories.Count > 0;) { if (asmDefDirectories[i].StartsWith(directoryPath)) { asmDefDirectories.RemoveAt(i); } else { i--; } } asmDefDirectories.Add(directoryPath); } } } }