static internal void ApplyChanges(this PEPrefabScript _this, bool buildModifications = false)
        {
            if (!_this)
            {
                return;
            }

            if (PEPrefs.DebugLevel > 0)
            {
                Debug.Log(string.Format("[Begin Apply] {0}", _this.name));
            }

            EditorUtility.DisplayProgressBar("Apply changes", _this.name, 0f);

            if (buildModifications)
            {
                foreach (var pi in _this.GetComponentsInChildren <PEPrefabScript>(true))
                {
                    pi.BuildModifications();
                }
            }

            if (recursionCounter++ > 100)
            {
                Debug.LogError("Recursion");
                recursionCounter = 0;
                EditorUtility.ClearProgressBar();
                return;
            }

            _this.BuildLinks(true);
            _this.BuildModifications();

            var newPrefab = !AssetDatabase.Contains(_this.gameObject) ? PrefabUtility.ReplacePrefab(_this.gameObject, _this.Prefab, ReplacePrefabOptions.ConnectToPrefab) : _this.gameObject;

            var prefabs = _this.GetPrefabsWithInstances();

            foreach (var prefab in prefabs)
            {
                if (PEPrefs.DebugLevel > 0)
                {
                    Debug.Log("[Apply] Found Nested instance:" + prefab.name);
                }

                var instantiatedPrefabsList = new List <GameObject>();
                var instances = new List <PEPrefabScript>();
                if (prefab == null)
                {
                    continue;
                }

                var pi = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                PrefabUtility.DisconnectPrefabInstance(pi);
                var nestedInstances = PEUtils.GetNestedInstances(pi).Where(p => p.PrefabGUID == _this.PrefabGUID && p.enabled).ToArray();

                instances.AddRange(nestedInstances);

                var rootInstance = pi.GetComponent <PEPrefabScript>();
                if (rootInstance && rootInstance.ParentPrefabGUID == _this.PrefabGUID)
                {
                    instances.Insert(0, rootInstance);
                }

                instantiatedPrefabsList.Add(pi);
                var counter = 0;

                foreach (var instance in instances)
                {
                    if (instance == null || instance.gameObject == null)
                    {
                        Debug.LogWarning("[Apply] Huston we have a problem. Prefab is destroyed before replace");
                        continue;
                    }

                    instantiatedPrefabsList.Remove(instance.gameObject);

                    var newObject = instance.ReplaceInPlace(newPrefab);

                    if (newObject == null || newObject.gameObject == null)
                    {
                        Debug.LogWarning("[Apply] Huston we have a problem. Prefab is destroyed after replace");
                        continue;
                    }

                    if (newObject.ParentPrefab == newPrefab)
                    {
                        instantiatedPrefabsList.Add(newObject.gameObject);
                    }

                    PrefabUtility.RecordPrefabInstancePropertyModifications(newObject);
                    EditorUtility.DisplayProgressBar("Apply changes", _this.name + " replaced in " + newObject.gameObject, ((float)counter++) / (float)instances.Count);
                }

                foreach (var instantiatedPrefab in instantiatedPrefabsList)
                {
                    if (instantiatedPrefab == null)
                    {
                        continue;
                    }

                    var instance = instantiatedPrefab.GetComponent <PEPrefabScript>();

                    if (instance)
                    {
                        instance.ApplyChanges();
                    }
                    else
                    {
                        PrefabUtility.ReplacePrefab(instantiatedPrefab, PrefabUtility.GetPrefabParent(instantiatedPrefab), ReplacePrefabOptions.ConnectToPrefab);
                    }

                    Object.DestroyImmediate(instantiatedPrefab);
                }
            }

            recursionCounter--;

            if (PEPrefs.DebugLevel > 0)
            {
                Debug.Log(string.Format("[End Apply] {0}", _this.name));
            }
        }
Exemple #2
0
        static internal void BuildMenu(GenericMenu menu, PEPrefabScript prefabInstance, bool rootPrefab, string path = "", bool showParent = true, bool showInstances = true)
        {
            if (buildMenuRecursionList.Contains(prefabInstance.Prefab))
            {
                buildMenuRecursionList.AddLast(prefabInstance.Prefab);
                var prefabsArray = buildMenuRecursionList.Select(p => AssetDatabase.GetAssetPath(p)).ToArray();
                buildMenuRecursionList.Clear();
                throw new System.Exception("Prefab recursion detected:\n" + string.Join("\n", prefabsArray));
            }
            buildMenuRecursionList.AddLast(prefabInstance.Prefab);

            if (prefabInstance.ParentPrefab == null || !showParent)
            {
                menu.AddItem(new GUIContent(path + prefabInstance.Prefab.name), false, () =>
                {
                });
            }
            else
            {
                BuildMenu(menu, prefabInstance.ParentPrefab.GetComponent <PEPrefabScript>(), false, path + prefabInstance.Prefab.name + "/", true, false);
                menu.AddItem(new GUIContent(path + prefabInstance.Prefab.name), false, () =>
                {
                });
            }

            menu.AddSeparator(path + "");
            var isPrefab = prefabInstance.gameObject == prefabInstance.Prefab.gameObject;

            menu.AddItem(new GUIContent(path + "Select"), false, SelectPrefab, prefabInstance);

            var prefabType = PrefabUtility.GetPrefabType(prefabInstance.gameObject);
            var canApply   = rootPrefab && prefabType != PrefabType.ModelPrefab && prefabType != PrefabType.ModelPrefabInstance && prefabType != PrefabType.DisconnectedModelPrefabInstance;

            if (canApply)
            {
                menu.AddItem(new GUIContent(path + "Apply"), false, Apply, prefabInstance);
            }
            if (!AssetDatabase.Contains(prefabInstance) || !isPrefab)
            {
                menu.AddItem(new GUIContent(path + "Revert"), false, Revert, prefabInstance);

                if (prefabInstance.ParentPrefab != null)
                {
                    menu.AddItem(new GUIContent(path + "Revert To Parent"), false, RevertToParent, prefabInstance);
                }
            }
            menu.AddSeparator(path + "");
            menu.AddItem(new GUIContent(path + "Create Child"), false, CreateChild, prefabInstance);

                        #if INJECTION
            if (prefabInstance.ParentPrefab != null)
            {
                menu.AddItem(new GUIContent(path + "Insert Parent"), false, InjectParent, prefabInstance);
            }
                        #endif

            if (!rootPrefab && !AssetDatabase.Contains(prefabInstance))
            {
                menu.AddSeparator(path);
                if (prefabInstance.enabled)
                {
                    menu.AddItem(new GUIContent(path + "Disable"), false, obj => (obj as PEPrefabScript).enabled = false, prefabInstance);
                }
                else
                {
                    menu.AddItem(new GUIContent(path + "Enable"), false, obj => (obj as PEPrefabScript).enabled = true, prefabInstance);
                }
            }

            menu.AddSeparator(path);

            if (prefabInstance.GetPrefabsWithInstances().Any())
            {
                menu.AddItem(new GUIContent(path + "Instances/Select All Instances"), false, SelectInstances, prefabInstance);
            }
            if (showInstances)
            {
                foreach (var prefab in prefabInstance.GetPrefabsWithInstances())
                {
                    if (prefab == null)
                    {
                        continue;
                    }
                    var pi = prefab.GetComponent <PEPrefabScript>();

                    var name = prefab.name;

                    name = (pi != null && pi.ParentPrefab == prefabInstance.Prefab) ? "Child: " + name : "Contains in: " + name;


                    if (pi != null)
                    {
                        BuildMenu(menu, prefab.GetComponent <PEPrefabScript>(), false, path + "Instances/" + name + "/", false);
                    }

                    var current = prefab;
                    menu.AddItem(new GUIContent(path + "Instances/" + name), false, () =>
                    {
                        Selection.activeObject = current;
                    });
                }
            }

            menu.AddItem(new GUIContent(path + "Instantiate"), false,
                         pi => Selection.activeObject = PrefabUtility.InstantiatePrefab(((PEPrefabScript)pi).Prefab), prefabInstance);

            if (!AssetDatabase.Contains(prefabInstance))
            {
                menu.AddItem(new GUIContent(path + "Replace"), false, Replace, prefabInstance);
            }
            buildMenuRecursionList.Remove(prefabInstance.Prefab);
        }