public static void BackupAssetsFolder(string backupLabel) { backupLabel = PathUtility.MakeSafeFilename(backupLabel, '_'); PathUtility.CreateDirectoryIfNeeded(Paths.backups); var fileName = $"Assets_{backupLabel}.zip"; var addEntryIndex = 0; var saveEntryIndex = 0; using (var zip = new ZipFile()) { zip.UseZip64WhenSaving = Zip64Option.AsNecessary; zip.AddProgress += (sender, e) => { EditorUtility.DisplayProgressBar("Creating Backup...", e.CurrentEntry != null ? e.CurrentEntry.FileName : "...", (float)(addEntryIndex++) / e.EntriesTotal); }; zip.SaveProgress += (sender, e) => { EditorUtility.DisplayProgressBar("Creating Backup...", e.CurrentEntry != null ? e.CurrentEntry.FileName : "...", (float)(saveEntryIndex++) / e.EntriesTotal); }; List <string> listOfAssets = Find <LudiqScriptableObject>(); foreach (string assetPath in listOfAssets) { zip.AddFile(assetPath); } var zipPath = Path.Combine(Paths.backups, fileName); VersionControlUtility.Unlock(zipPath); zip.Save(zipPath); EditorUtility.ClearProgressBar(); } }
public void GenerateProviderScripts() { if (Directory.Exists(BoltCore.Paths.propertyProviders)) { foreach (var file in Directory.GetFiles(BoltCore.Paths.propertyProviders)) { File.Delete(file); } } if (Directory.Exists(BoltCore.Paths.propertyProvidersEditor)) { foreach (var file in Directory.GetFiles(BoltCore.Paths.propertyProvidersEditor)) { File.Delete(file); } } PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.propertyProviders); PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.propertyProvidersEditor); foreach (var type in typeset.Where(SerializedPropertyUtility.HasCustomDrawer)) { var directory = Codebase.IsEditorType(type) ? BoltCore.Paths.propertyProvidersEditor : BoltCore.Paths.propertyProviders; var path = Path.Combine(directory, GetProviderScriptName(type) + ".cs"); VersionControlUtility.Unlock(path); File.WriteAllText(path, GenerateProviderSource(type)); } AssetDatabase.Refresh(); }
public static void Rebuild() { if (IsUnitOptionsBuilt()) { VersionControlUtility.Unlock(BoltFlow.Paths.unitOptions); File.Delete(BoltFlow.Paths.unitOptions); } Build(); }
public static void DeleteProjectFileIfExists(string filePath, bool checkoutInVersionControl = false) { if (File.Exists(filePath)) { string metaFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileName(filePath) + ".meta"); if (checkoutInVersionControl) { VersionControlUtility.Unlock(filePath); VersionControlUtility.Unlock(metaFilePath); } File.Delete(filePath); File.Delete(metaFilePath); } }
public static void Update() { if (!IsUnitOptionsBuilt()) { Build(); return; } lock (@lock) { using (ProfilingUtility.SampleBlock("Update Node Database")) { using (NativeUtility.Module("sqlite3.dll")) { var progressTitle = "Updating node database..."; SQLiteConnection database = null; try { VersionControlUtility.Unlock(BoltFlow.Paths.unitOptions); var steps = 7f; var step = 0f; ProgressUtility.DisplayProgressBar(progressTitle, "Connecting to database...", step++ / steps); database = new SQLiteConnection(BoltFlow.Paths.unitOptions); ProgressUtility.DisplayProgressBar(progressTitle, "Updating type mappings...", step++ / steps); UpdateTypeMappings(); ProgressUtility.DisplayProgressBar(progressTitle, "Fetching modified scripts...", step++ / steps); var modifiedScriptGuids = GetModifiedScriptGuids().Distinct().ToHashSet(); ProgressUtility.DisplayProgressBar(progressTitle, "Fetching deleted scripts...", step++ / steps); var deletedScriptGuids = GetDeletedScriptGuids().Distinct().ToHashSet(); ProgressUtility.DisplayProgressBar(progressTitle, "Updating codebase...", step++ / steps); var modifiedScriptTypes = modifiedScriptGuids.SelectMany(GetScriptTypes).ToArray(); UpdateCodebase(modifiedScriptTypes); var outdatedScriptGuids = new HashSet <string>(); outdatedScriptGuids.UnionWith(modifiedScriptGuids); outdatedScriptGuids.UnionWith(deletedScriptGuids); ProgressUtility.DisplayProgressBar(progressTitle, "Removing outdated node options...", step++ / steps); options?.RemoveWhere(option => outdatedScriptGuids.Overlaps(option.sourceScriptGuids)); // We want to use the database level WHERE here for speed, // so we'll run multiple queries, one for each outdated script GUID. foreach (var outdatedScriptGuid in outdatedScriptGuids) { foreach (var outdatedRowId in database.Table <UnitOptionRow>() .Where(row => row.sourceScriptGuids.Contains(outdatedScriptGuid)) .Select(row => row.id)) { database.Delete <UnitOptionRow>(outdatedRowId); } } ProgressUtility.DisplayProgressBar(progressTitle, "Converting codebase to node options...", step++ / steps); var newOptions = new HashSet <IUnitOption>(modifiedScriptGuids.SelectMany(GetScriptTypes) .Distinct() .SelectMany(GetIncrementalOptions)); var rows = new HashSet <UnitOptionRow>(); float progress = 0; foreach (var newOption in newOptions) { options?.Add(newOption); try { ProgressUtility.DisplayProgressBar(progressTitle, newOption.label, (step / steps) + ((1 / step) * (progress / newOptions.Count))); rows.Add(newOption.Serialize()); } catch (Exception ex) { Debug.LogError($"Failed to serialize option '{newOption.GetType()}'.\n{ex}"); } progress++; } ProgressUtility.DisplayProgressBar(progressTitle, "Writing to database...", 1); try { database.InsertAll(rows); } catch (Exception ex) { Debug.LogError($"Failed to write options to database.\n{ex}"); } // Make sure the database is touched to the current date, // even if we didn't do any change. This will avoid unnecessary // analysis in future update checks. File.SetLastWriteTimeUtc(BoltFlow.Paths.unitOptions, DateTime.UtcNow); } finally { database?.Close(); ProgressUtility.ClearProgressBar(); UnityAPI.Async(AssetDatabase.Refresh); //ConsoleProfiler.Dump(); } } } } }
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(); } }