Пример #1
0
 public static void DeleteAllProjectSettings()
 {
     foreach (var plugin in PluginContainer.plugins)
     {
         AssetDatabase.DeleteAsset(PathUtility.FromProject(plugin.configuration.projectSettingsStoragePath));
     }
 }
Пример #2
0
        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);
        }
Пример #3
0
        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();
            }
        }
Пример #4
0
        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();
            }
        }
Пример #5
0
        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;
                    }
                }
            }
            );
        }