public override void OnInspectorGUI()
        {
            if (m_TextStyle == null)
            {
                m_TextStyle = "ScriptText";
            }

            Hash128 dependencyHash = AssetDatabase.GetSourceAssetFileHash(m_AssetGUID);

            if (m_LastDependencyHash != dependencyHash)
            {
                CachePreview();
                m_LastDependencyHash = dependencyHash;
            }

            bool enabledTemp = GUI.enabled;

            GUI.enabled = true;
            if (m_TextAsset != null)
            {
                Rect rect = GUILayoutUtility.GetRect(m_CachedPreview, m_TextStyle);
                rect.x     = 0;
                rect.y    -= 3;
                rect.width = GUIClip.visibleRect.width + 1;
                GUI.Box(rect, m_CachedPreview, m_TextStyle);
            }
            GUI.enabled = enabledTemp;
        }
        public static PrefabAssetInfo GetState(string guid)
        {
            var id = GetPrefabAssetIdentifier(guid);
            var cachedPrefabAssetInfo = s_StateCache.GetState(id);

            if (cachedPrefabAssetInfo == null)
            {
                return(null); // not cached yet
            }
            var currentPrefabSourceFileHash = AssetDatabase.GetSourceAssetFileHash(guid);

            if (currentPrefabSourceFileHash != cachedPrefabAssetInfo.prefabFileHash)
            {
                return(null); // cache is out of sync
            }
            return(cachedPrefabAssetInfo);
        }
        // Returns true if overrides count changed during the update
        public bool MoveNext()
        {
            if (IsDone())
            {
                return(false);
            }

            var assetRoot  = m_PrefabAssetRoots[m_CurrentAssetIndex];
            var startCount = m_OverridesCount[m_CurrentAssetIndex];

            switch (m_CurrentStep)
            {
            case 0:
            {
                // First check if we have cached overides count for the prefab
                var path = AssetDatabase.GetAssetPath(assetRoot);
                var guid = AssetDatabase.AssetPathToGUID(path);
                var cachedPrefabAssetInfo = PrefabAssetStateCache.GetState(guid);
                if (cachedPrefabAssetInfo != null)
                {
                    m_OverridesCount[m_CurrentAssetIndex] = cachedPrefabAssetInfo.overrideCount;
                    m_ChangedCount = true;
                    m_CurrentAssetIndex++;
                    if (m_Debug)
                    {
                        Debug.Log($"[OverridesCounterForPrefabAssets] Using cached overridecount {cachedPrefabAssetInfo.overrideCount} ({path})");
                    }
                    return(true);
                }
            }
            break;

            case 1:
                PropertyModification[] mods = PrefabUtility.GetPropertyModifications(assetRoot);
                foreach (PropertyModification mod in mods)
                {
                    if (mod.target == null)
                    {
                        continue;
                    }

                    if (!PrefabUtility.IsDefaultOverride(mod))
                    {
                        m_OverridesCount[m_CurrentAssetIndex]++;
                    }
                }
                break;

            case 2:
                m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetAddedComponents(assetRoot).Count;
                break;

            case 3:
                m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetRemovedComponents(assetRoot).Count;
                break;

            case 4:
                m_OverridesCount[m_CurrentAssetIndex] += PrefabOverridesUtility.GetAddedGameObjects(assetRoot).Count;
                break;

            default:
            {
                // Cache result
                var path            = AssetDatabase.GetAssetPath(assetRoot);
                var guid            = AssetDatabase.AssetPathToGUID(path);
                var prefabAssetInfo = new PrefabAssetInfo();
                prefabAssetInfo.overrideCount  = m_OverridesCount[m_CurrentAssetIndex];
                prefabAssetInfo.prefabFileHash = AssetDatabase.GetSourceAssetFileHash(guid);
                PrefabAssetStateCache.SetState(guid, prefabAssetInfo);
                if (m_Debug)
                {
                    Debug.Log($"[OverridesCounterForPrefabAssets] Set cached overridecount {prefabAssetInfo.overrideCount} for {path}");
                }

                // Move to next asset
                m_CurrentAssetIndex++;
                m_CurrentStep = 0;
            }
            break;
            }

            if (m_Debug)
            {
                Debug.Log($"[OverridesCounterForPrefabAssets] Current asset index: {m_CurrentAssetIndex}, current step: {m_CurrentStep}");
            }

            m_CurrentStep++;

            // Simulate heavy calculation
            if (m_Debug)
            {
                System.Threading.Thread.Sleep(500);
            }

            m_ChangedCount = m_OverridesCount[m_CurrentAssetIndex] != startCount;

            return(true);
        }
예제 #4
0
        // Internal for testing framework
        internal void SaveDirtyPrefabAssets(bool reloadInspectors)
        {
            if (assetTargets == null)
            {
                return;
            }

            if (assetTarget == null)
            {
                return;
            }

            m_DirtyPrefabAssets.Clear();
            foreach (var asset in assetTargets)
            {
                // The asset could have been deleted when this method is called from OnDestroy().
                // E.g delete the selected prefab asset from the Project Browser.
                if (asset == null)
                {
                    continue;
                }

                if (!EditorUtility.IsPersistent(asset))
                {
                    continue;
                }

                if (!(asset is GameObject))
                {
                    continue;
                }

                var rootGameObject = (GameObject)asset;
                if (IsDirty(rootGameObject))
                {
                    string currentGuid    = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(rootGameObject));
                    var    changeTracking = new TrackedAsset()
                    {
                        asset = rootGameObject,
                        guid  = currentGuid,
                        hash  = AssetDatabase.GetSourceAssetFileHash(currentGuid)
                    };
                    m_DirtyPrefabAssets.Add(changeTracking);
                }
            }

            if (m_DirtyPrefabAssets.Count > 0)
            {
                AssetDatabase.StartAssetEditing();
                try
                {
                    foreach (var trackedAsset in m_DirtyPrefabAssets)
                    {
                        bool savedSuccesfully;
                        PrefabUtility.SavePrefabAsset(trackedAsset.asset, out savedSuccesfully);
                        if (!savedSuccesfully)
                        {
                            string title   = L10n.Tr("Saving Failed");
                            string message = L10n.Tr("Check the Console window to get more insight into what needs to be fixed on the Prefab Asset.\n\nYou can open Prefab Mode to fix any issues on child GameObjects");
                            EditorUtility.DisplayDialog(title, message, L10n.Tr("OK"));

                            m_SavingHasFailed = true;
                            break;
                        }
                    }
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();

                    if (reloadInspectors)
                    {
                        foreach (var trackedAsset in m_DirtyPrefabAssets)
                        {
                            if (AssetDatabase.GetSourceAssetFileHash(trackedAsset.guid) != trackedAsset.hash)
                            {
                                // We only call ForceReloadInspectors (and not ForceRebuildInspectors) to ensure local inspector state
                                // is not destroyed, such as a foldout state maintained by an editor (case 1255013).
                                // And we need to reload Prefab asset inspectors in order for the preview to be regenerated since the preview shows
                                // an instantiated Prefab. E.g disable a MeshRenderer on a Prefab Asset and the mesh should be hidden in the preview.
                                EditorUtility.ForceReloadInspectors();
                                break;
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        // Internal for testing framework
        internal void SaveDirtyPrefabAssets(bool rebuildInspectors)
        {
            if (assetTargets == null)
            {
                return;
            }

            if (assetTarget == null)
            {
                return;
            }

            m_DirtyPrefabAssets.Clear();
            foreach (var asset in assetTargets)
            {
                // The asset could have been deleted when this method is called from OnDestroy().
                // E.g delete the selected prefab asset from the Project Browser.
                if (asset == null)
                {
                    continue;
                }

                if (!EditorUtility.IsPersistent(asset))
                {
                    continue;
                }

                if (!(asset is GameObject))
                {
                    continue;
                }

                var rootGameObject = (GameObject)asset;
                if (IsDirty(rootGameObject))
                {
                    m_DirtyPrefabAssets.Add(rootGameObject);
                }
            }

            if (m_DirtyPrefabAssets.Count > 0)
            {
                bool sourceFileChangedAfterSaving = false;
                AssetDatabase.StartAssetEditing();
                try
                {
                    foreach (var rootGameObject in m_DirtyPrefabAssets)
                    {
                        var guid             = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(rootGameObject));
                        var hashBeforeSaving = AssetDatabase.GetSourceAssetFileHash(guid);

                        bool savedSuccesfully;
                        PrefabUtility.SavePrefabAsset(rootGameObject, out savedSuccesfully);
                        if (!savedSuccesfully)
                        {
                            string title   = L10n.Tr("Saving Failed");
                            string message = L10n.Tr("Check the Console window to get more insight into what needs to be fixed on the Prefab Asset.\n\nYou can open Prefab Mode to fix any issues on child GameObjects");
                            EditorUtility.DisplayDialog(title, message, L10n.Tr("OK"));

                            m_SavingHasFailed = true;
                            break;
                        }

                        // Fix case 1239807: Prevent calling ForceRebuildInspectors() if the the user is dirtying the prefab asset on every CustomEditor::OnEnable() with a
                        // value that is the same as before (so the artifact does not change). This fix avoids constant rebuilding of the Inspector window.
                        sourceFileChangedAfterSaving |= AssetDatabase.GetSourceAssetFileHash(guid) != hashBeforeSaving;
                    }
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();

                    // All inspectors needs to be rebuild to ensure property changes are reflected after saving the Prefab shown.
                    // (Saving clears the m_DirtyIndex of the target which is used for updating inspectors via SerializedObject::UpdateIfRequiredOrScript()
                    // and thus the cached dirty index in SerializedObject is not updated meaning the source object is not reloaded even though it changed)
                    if (sourceFileChangedAfterSaving && rebuildInspectors)
                    {
                        EditorUtility.ForceRebuildInspectors();
                    }
                }
            }
        }