public static void Run(IEnumerable <string> paths, IEnumerable <ScriptReferenceReplacement> replacements, Mode mode) { if (!canRun) { var message = "Cannot run missing script resolver with the current serialization mode.\nSet the project serialization mode to 'Force Text' and try again."; if (mode == Mode.Dialog) { EditorUtility.DisplayDialog("Script Reference Resolver", message, "OK"); } else if (mode == Mode.Console) { Debug.LogWarning(message); } return; } // Doing a naive approach here: replacing the exact string by regex instead of parsing the YAML, // since Unity sometimes breaks YAML specifications. This is whitespace dependant, but it should work. var newContents = new Dictionary <string, string[]>(); var _paths = paths.ToArray(); var pathIndex = 0; var regexes = new Dictionary <ScriptReferenceReplacement, Regex>(); foreach (var replacement in replacements) { var regex = new Regex($@"\{{fileID: {replacement.previousReference.fileID}, guid: {replacement.previousReference.guid}, type: 3\}}", RegexOptions.Compiled); regexes.Add(replacement, regex); } foreach (var path in _paths) { if (newContents.ContainsKey(path)) { // Duplicate path continue; } var replaced = false; var fileContents = new List <string>(); if (mode == Mode.Dialog) { ProgressUtility.DisplayProgressBar("Script Reference Resolver", $"Analyzing '{path}'...", pathIndex++ / (float)_paths.Length); } foreach (var line in File.ReadAllLines(path)) { var newLine = line; foreach (var replacement in replacements) { newLine = regexes[replacement].Replace(newLine, (match) => { replaced = true; return($@"{{fileID: {replacement.newReference.fileID}, guid: {replacement.newReference.guid}, type: 3}}"); }); } fileContents.Add(newLine); } if (replaced) { newContents.Add(path, fileContents.ToArray()); } } pathIndex = 0; if (newContents.Count > 0) { var pathMaxLength = 40; var fileLimit = 15; var fileList = newContents.Keys.Select(p => StringUtility.PathEllipsis(PathUtility.FromProject(p), pathMaxLength)).Take(fileLimit).ToLineSeparatedString(); if (newContents.Count > fileLimit) { fileList += "\n..."; } var replace = true; if (mode == Mode.Dialog) { var message = $"Missing script references have been found in {newContents.Count} file{(newContents.Count > 1 ? "s" : "")}: \n\n{fileList}\n\nProceed with replacement?"; replace = EditorUtility.DisplayDialog("Script Reference Resolver", message, "Replace References", "Cancel"); } if (replace) { foreach (var newContent in newContents) { if (mode == Mode.Dialog) { ProgressUtility.DisplayProgressBar("Script Reference Resolver", $"Fixing '{newContent.Key}'...", pathIndex++ / (float)_paths.Length); } VersionControlUtility.Unlock(newContent.Key); File.WriteAllLines(newContent.Key, newContent.Value); } if (mode == Mode.Dialog) { EditorUtility.DisplayDialog("Script Reference Resolver", "Script references have been successfully replaced.\nRestarting Unity is recommended.", "OK"); } else if (mode == Mode.Console) { Debug.Log($"Missing script references have been replaced in {newContents.Count} file{(newContents.Count > 1 ? "s" : "")}.\nRestarting Unity is recommended.\n{fileList}\n"); } AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } } else { var message = "No missing script reference was found."; if (mode == Mode.Dialog) { EditorUtility.DisplayDialog("Script Reference Resolver", message, "OK"); } else if (mode == Mode.Console) { // Debug.Log(message); } } if (mode == Mode.Dialog) { ProgressUtility.ClearProgressBar(); } }
private static bool Match(string query, string haystack, bool strictOnly, float strictWeight, float looseWeight, out float score, bool[] indices) { score = 0; var isStreaking = false; var haystackIndex = 0; var matchedAny = false; var wordBeginnings = 0; var expectsWordBeginning = true; if (haystack == null) { return(false); } for (var queryIndex = 0; queryIndex < query.Length; queryIndex++) { var queryCharacter = query[queryIndex]; if (char.IsWhiteSpace(queryCharacter)) { expectsWordBeginning = true; continue; } else if (!expectsWordBeginning) { expectsWordBeginning = char.IsUpper(queryCharacter); } var matched = false; for (; haystackIndex < haystack.Length; haystackIndex++) { var haystackCharacter = haystack[haystackIndex]; if (char.IsWhiteSpace(haystackCharacter)) { isStreaking = false; continue; } var matchesInvariant = char.ToLowerInvariant(queryCharacter) == char.ToLowerInvariant(haystackCharacter); var isWordBeginning = matchesInvariant && StringUtility.IsWordBeginning(haystack, haystackIndex); var matchesLoose = matchesInvariant && (isWordBeginning || !expectsWordBeginning || (char.IsUpper(queryCharacter) && queryCharacter == haystackCharacter)); var matchesStrict = matchesLoose && (isStreaking || isWordBeginning); if (isWordBeginning) { wordBeginnings++; } var matches = strictOnly ? matchesStrict : matchesLoose; if (matches) { score += matchesStrict ? strictWeight : looseWeight; matched = true; if (indices != null) { indices[haystackIndex] = true; } isStreaking = true; haystackIndex++; break; } else { isStreaking = false; } } if (matched) { matchedAny = true; } else { return(false); } expectsWordBeginning = false; } if (!matchedAny) { return(false); } // Bonus to single word queries if (wordBeginnings == 1) { score += strictWeight; } score /= query.Length; return(true); }
public static void GenerateLicenseFile(string path) { var acknowledgements = PluginContainer.plugins .SelectMany(plugin => plugin.resources.acknowledgements) .Distinct() .ToArray(); var sb = new StringBuilder(); sb.AppendLine("The Unity Asset Store policy requires that all third-party"); sb.AppendLine("licenses be contained in a single LICENSES files."); sb.AppendLine("This file is auto-generated for this purpose."); sb.AppendLine(); sb.AppendLine("However, you can find a more readable version of each product's"); sb.AppendLine("acknowledgements in its About window, found in the Tools menu."); sb.AppendLine(); sb.AppendLine("Acknowledgements below:"); foreach (var acknowledgement in acknowledgements) { sb.AppendLine(" - " + acknowledgement.title); } foreach (var acknowledgement in acknowledgements) { sb.AppendLine(); sb.AppendLine("============================="); sb.AppendLine(); sb.AppendLine(acknowledgement.title); var hasAuthor = !StringUtility.IsNullOrWhiteSpace(acknowledgement.author); var hasCopyright = acknowledgement.copyrightYear != null; if (hasAuthor && hasCopyright) { sb.AppendLine($"Copyright \u00a9 {acknowledgement.copyrightYear} {acknowledgement.author}"); } else if (hasAuthor) { sb.AppendLine($"Author: {acknowledgement.author}"); } else if (hasCopyright) { sb.AppendLine($"Copyright \u00a9 {acknowledgement.copyrightYear}"); } if (!StringUtility.IsNullOrWhiteSpace(acknowledgement.url)) { sb.AppendLine(acknowledgement.url); } if (!StringUtility.IsNullOrWhiteSpace(acknowledgement.licenseName)) { sb.AppendLine("License: " + acknowledgement.licenseName.Trim()); } if (!StringUtility.IsNullOrWhiteSpace(acknowledgement.licenseName)) { var licenseText = string.Join("\n\n", acknowledgement.licenseText.Split(new[] { "\r\n\r\n", "\n\n" }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Replace("\r\n", "").Replace("\n", "")).ToArray()); sb.AppendLine(); sb.AppendLine(licenseText); } } if (path == null) { path = EditorUtility.SaveFilePanelInProject("License File", "LICENSES", "txt", null); } if (path != null) { File.WriteAllText(path, sb.ToString()); AssetDatabase.Refresh(); } }