public static void DeleteAllProjectSettings() { foreach (var plugin in PluginContainer.plugins) { AssetDatabase.DeleteAsset(PathUtility.FromProject(plugin.configuration.projectSettingsStoragePath)); } }
public static bool TryLoadIfExists <T>(string path, out T asset) where T : ScriptableObject { var assetDatabasePath = PathUtility.FromProject(path); if (File.Exists(path)) { // Try loading the existing asset file. asset = AssetDatabase.LoadAssetAtPath <T>(assetDatabasePath); if (asset == null) { // The file exists, but it isn't a valid asset. // Warn and leave the asset as is to prevent losing its serialized contents // because we might be able to salvage them by deserializing later on. // Return a new empty instance in the mean time. Debug.LogWarning($"Loading {typeof(T).FullName} failed:\n{assetDatabasePath}"); asset = ScriptableObject.CreateInstance <T>(); return(false); } return(true); } asset = default; return(false); }
public static void SaveVariableAsset(VariablesAsset asset, string fileName) { var path = Path.Combine(BoltCore.Paths.variableResources, fileName + ".asset"); if (String.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset))) { var assetDatabasePath = PathUtility.FromProject(path); PathUtility.CreateParentDirectoryIfNeeded(path); AssetDatabase.CreateAsset(asset, assetDatabasePath); AssetDatabase.SaveAssets(); } }
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(); } }
public static string GetPluginRuntimeGUID(Plugin plugin) { Ensure.That(nameof(plugin)).IsNotNull(plugin); return(AssetDatabase.AssetPathToGUID(PathUtility.FromProject(plugin.runtimeAssembly.Location))); }
// Perforce and other VCS have a lock mechanism that usually // only makes the file writable once checked out. We need to // check them out before writing to them for auto-generated files. public static void Unlock(string path) { Ensure.That(nameof(path)).IsNotNull(path); UnityAPI.Await ( () => { // The API changed in 2019, adding a third optional ChangeSet parameter // which defaults to null but breaks the compiled signature below // Furthermore, we can't even so much as have the call in the body of this method, // or it will fail even if the if branch evaluates to false. So we if (File.Exists(path) && Provider.enabled && Provider.isActive && Provider.hasCheckoutSupport) { try { var provider = typeof(Provider); if (EditorApplicationUtility.unityVersion >= "2019.1.0") { var method = provider.GetMethods() .FirstOrDefault ( m => m.Name == "Checkout" && m.GetParameters().Length == 3 && m.GetParameters()[0].ParameterType == typeof(string) && m.GetParameters()[1].ParameterType == typeof(CheckoutMode) ); if (method == null) { throw new MissingMemberException(provider.FullName, "Checkout"); } method.InvokeOptimized(null, PathUtility.FromProject(path), CheckoutMode.Both, null); } else { var method = provider.GetMethods() .FirstOrDefault ( m => m.Name == "Checkout" && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(string) && m.GetParameters()[1].ParameterType == typeof(CheckoutMode) ); if (method == null) { throw new MissingMemberException(provider.FullName, "Checkout"); } method.InvokeOptimized(null, PathUtility.FromProject(path), CheckoutMode.Both); } } catch (Exception ex) { Debug.LogWarning($"Failed to automatically checkout file from version control:\n{path}\n{ex}"); } } if (File.Exists(path)) { var info = new FileInfo(path); if (info.IsReadOnly) { var sb = new StringBuilder(); sb.AppendLine($"File '{info.Name}' is read-only despite attempted checkout. Manually forcing to writable."); sb.AppendLine($"This may cause version control issues. Please report the following debug information:"); sb.AppendLine($"File Exists: {File.Exists(path)}"); sb.AppendLine($"Provider.enabled: {Provider.enabled}"); sb.AppendLine($"Provider.isActive: {Provider.isActive}"); sb.AppendLine($"Provider.hasCheckoutSupport: {Provider.hasCheckoutSupport}"); Debug.LogWarning(sb.ToString()); info.IsReadOnly = false; } } } ); }