public static void ApplyStrippingType(Scene scene, StrippingType strippingType)
        {
                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Assert(RootGameObjects.Count == 0);
                        #endif

            scene.GetRootGameObjects(RootGameObjects);

                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Log("Stripping " + RootGameObjects.Count + " root objects in scene " + scene.name + "...");
                        #endif

            for (int n = 0, count = RootGameObjects.Count; n < count; n++)
            {
                CheckForAndRemoveHierarchyFoldersInChildren(RootGameObjects[n].transform, strippingType, true, SetChildrenActiveDelayed);
            }
            RootGameObjects.Clear();

            for (int n = 0, count = SetChildrenActiveDelayed.Count; n < count; n++)
            {
                var child = SetChildrenActiveDelayed[n];
                if (child == null)
                {
                    continue;
                }
                child.SetActive(true);
            }
            SetChildrenActiveDelayed.Clear();

                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Log("Stripping scene " + scene.name + " done.");
                        #endif
        }
 public static void ApplyStrippingTypeToAllLoadedScenes(StrippingType strippingType)
 {
     for (int s = 0, scount = SceneManager.sceneCount; s < scount; s++)
     {
         ApplyStrippingType(SceneManager.GetSceneAt(s), strippingType);
     }
 }
        public PlayModeStripper(StrippingType setStrippingType, PlayModeStrippingMethod setStrippingMethod)
        {
                        #if DEV_MODE && DEBUG_RESET_STATE
            Debug.Log("PlayModeStripper(" + setStrippingType + ", " + setStrippingMethod + ").");
                        #endif

            playModeStripping       = setStrippingType;
            playModeStrippingMethod = setStrippingMethod;

            SceneManager.sceneLoaded               += OnSceneLoaded;
            SceneManager.sceneUnloaded             += OnSceneUnloaded;
            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        }
        private static void StripPrefab(GameObject root, StrippingType strippingType)
        {
            var transform  = root.transform;
            int childCount = transform.childCount;
            var children   = new Transform[childCount];

            for (int n = 0; n < childCount; n++)
            {
                children[n] = transform.GetChild(n);
            }
            for (int n = 0; n < childCount; n++)
            {
                HierarchyFolderUtility.CheckForAndRemoveHierarchyFoldersInChildren(children[n], strippingType, true);
            }
        }
        private static void StripHierarchyFoldersFromAllPrefabs(StrippingType strippingType)
        {
            if (paths != null)
            {
                foreach (var assetAndBackupPath in paths)
                {
                    var assetPath  = assetAndBackupPath.Key;
                    var gameObject = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath);
                    StripPrefab(gameObject, strippingType);
                }
                return;
            }

            paths = new List <KeyValuePair <string, string> >();

            string backupRootDir = Path.Combine(Application.persistentDataPath, "HierarchyFolders/PrefabBackups");
            var    assets        = AssetDatabase.FindAssets("t:GameObject");

            foreach (var guid in assets)
            {
                var assetPath  = AssetDatabase.GUIDToAssetPath(guid);
                var gameObject = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath);
                if (gameObject == null)
                {
                    continue;
                }
                var o = gameObject.GetComponentInChildren <HierarchyFolder>();
                if (o == null)
                {
                    continue;
                }

                // Risk of path being too long to write to???
                string backupPath = Path.Combine(backupRootDir, assetPath);

                                #if DEV_MODE
                Debug.Log("Stripping prefab " + assetPath);
                                #endif

                paths.Add(new KeyValuePair <string, string>(assetPath, backupPath));

                StripPrefab(gameObject, strippingType);
            }
        }
        public static void ApplyStrippingType(Scene scene, StrippingType strippingType)
        {
                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Assert(RootGameObjects.Count == 0);
                        #endif

            scene.GetRootGameObjects(RootGameObjects);

                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Log("Stripping " + RootGameObjects.Count + " root objects in scene " + scene.name + "...");
                        #endif

            for (int n = 0, count = RootGameObjects.Count; n < count; n++)
            {
                CheckForAndRemoveHierarchyFoldersInChildren(RootGameObjects[n].transform, strippingType);
            }
            RootGameObjects.Clear();

                        #if DEV_MODE && DEBUG_STRIP_SCENE
            Debug.Log("Stripping scene " + scene.name + " done.");
                        #endif
        }
예제 #7
0
        public PlayModeStripper(StrippingType setStrippingType, PlayModeStrippingMethod setStrippingMethod)
        {
            playModeStripping       = setStrippingType;
            playModeStrippingMethod = setStrippingMethod;

            if (playModeStripping == StrippingType.None)
            {
                return;
            }

            SceneManager.sceneLoaded               += OnSceneLoaded;
            SceneManager.sceneUnloaded             += OnSceneUnloaded;
            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;

            for (int s = 0, scount = SceneManager.sceneCount; s < scount; s++)
            {
                var scene = SceneManager.GetSceneAt(s);
                if (scene.isLoaded && playModeStrippingHandledForScenes.Add(scene))
                {
                    HierarchyFolderUtility.ApplyStrippingType(scene, playModeStripping);
                }
            }
        }
        public static void CheckForAndRemoveHierarchyFoldersInChildren([NotNull] Transform transform, StrippingType strippingType, bool destroyImmediate)
        {
            CheckForAndRemoveHierarchyFoldersInChildren(transform, strippingType, destroyImmediate, SetChildrenActiveDelayed);

            for (int n = 0, count = SetChildrenActiveDelayed.Count; n < count; n++)
            {
                var child = SetChildrenActiveDelayed[n];
                if (child == null)
                {
                    continue;
                }
                child.SetActive(true);
            }
            SetChildrenActiveDelayed.Clear();
        }
        private static void CheckForAndRemoveHierarchyFoldersInChildren([NotNull] Transform transform, StrippingType strippingType, bool destroyImmediate, List <GameObject> setChildrenActiveDelayed)
        {
            bool wasStripping = NowStripping;

            NowStripping = true;

            int childCount = transform.childCount;
            var children   = new Transform[childCount];

            for (int n = 0; n < childCount; n++)
            {
                children[n] = transform.GetChild(n);
            }

            var hierarchyFolder = transform.GetComponent <HierarchyFolder>();

            if (hierarchyFolder != null)
            {
                var hierarchyFolderParent = transform.parent;
                int setSiblingIndex       = transform.GetSiblingIndex() + 1;

                                #if DEV_MODE && DEBUG_STRIP_FOLDER
                Debug.Log("Stripping " + transform.name + " with " + childCount + " children...");
                                #endif

                switch (strippingType)
                {
                case StrippingType.FlattenHierarchyAndRemoveGameObject:
                case StrippingType.FlattenHierarchy:
                case StrippingType.FlattenHierarchyAndRemoveComponent:
                case StrippingType.FlattenHierarchyAndDisableComponent:
                    for (int n = 0; n < childCount; n++)
                    {
                        var child = children[n];

                        if (!transform.gameObject.activeSelf && child.gameObject.activeSelf && Application.isPlaying)
                        {
                            child.gameObject.SetActive(false);
                            setChildrenActiveDelayed.Add(child.gameObject);
                        }

                        child.SetParent(hierarchyFolderParent, true);

                        child.SetSiblingIndex(setSiblingIndex);
                        setSiblingIndex++;
                    }
                    for (int n = 0; n < childCount; n++)
                    {
                        CheckForAndRemoveHierarchyFoldersInChildren(children[n], strippingType, destroyImmediate, setChildrenActiveDelayed);
                    }
                    break;

                default:
                    for (int n = 0; n < childCount; n++)
                    {
                        var child = children[n];
                        CheckForAndRemoveHierarchyFoldersInChildren(child, strippingType, destroyImmediate, setChildrenActiveDelayed);
                    }
                    break;
                }

                                #if ASSERT_COMPONENT_COUNT
                var componentCount = transform.GetComponents <Component>().Length;
                if (componentCount != 2)
                {
                    Debug.LogError("HierarchyFolder " + transform.name + " contained " + componentCount + " components! All components will be destroyed along with the Hierarchy Folder.");
                }
                                #endif

                                #if ASSERT_CHILD_COUNT
                Debug.Assert(transform.childCount == 0);
                                #endif

                                #if DEV_MODE && DEBUG_REMOVE_HIERARCHY_FOLDER
                Debug.Log("Destroying HierarchyFolder: " + transform.name + " using " + (destroyImmediate ? "DestroyImmediate" : "Destroy") + "\nstrippingType=" + strippingType + ", prefabInstanceStatus=" + PrefabUtility.GetPrefabInstanceStatus(transform.gameObject), strippingType == StrippingType.FlattenHierarchyAndRemoveGameObject ? null : transform);
                                #endif

                switch (strippingType)
                {
                case StrippingType.FlattenHierarchyAndRemoveGameObject:
                    // During scene load using DestroyImmediate instead of Destroy even in play mode so that other scripts won't be aware of the hierarchy folders ever having existed.
                    // With prefab instances being instantiated after initial scene loading we unfortunately can't use DestroyImmediate, because it would it will result in
                    // "UnityException: Instantiate failed because the clone was destroyed during creation. This can happen if DestroyImmediate is called in MonoBehaviour.Awake."
                    if (destroyImmediate)
                    {
                        Object.DestroyImmediate(transform.gameObject, true);
                    }
                    else
                    {
                        // Since Destroy will only remove the GameObject after a short delay, set the GameObject inactive
                        // and move it to root to hide it as well as possible from other scripts. This way the GameObject
                        // cannot be found using Transform.parent, Transform.GetChild, Transform.root nor FindObjectsOfType<Transform>().
                        transform.gameObject.SetActive(false);
                        transform.SetParent(null, false);
                        Object.Destroy(transform.gameObject);
                    }
                    break;

                case StrippingType.FlattenHierarchyAndRemoveComponent:
                case StrippingType.RemoveComponent:
                    Object.DestroyImmediate(hierarchyFolder, true);
                    break;

                case StrippingType.FlattenHierarchyAndDisableComponent:
                case StrippingType.DisableComponent:
                    hierarchyFolder.enabled   = false;
                    transform.hideFlags       = HideFlags.None;
                    hierarchyFolder.hideFlags = HideFlags.None;
                    break;
                }
            }
            else
            {
                for (int n = 0; n < childCount; n++)
                {
                    CheckForAndRemoveHierarchyFoldersInChildren(children[n], strippingType, true, setChildrenActiveDelayed);
                }
            }

            NowStripping = wasStripping;
        }
        private static void OnPostProcessScene()
        {
            // This will also get called when entering Playmode, when SceneManager.LoadScene is called,
            // but we only want to do stripping just after building the Scene.
            if (Application.isPlaying)
            {
                return;
            }

            if (PrefabsStripped)
            {
                return;
            }

            var preferences = HierarchyFolderPreferences.Get();

            if (preferences == null)
            {
                Debug.LogWarning("Failed to find Hierarchy Folder Preferences asset; will not strip hierarchy folders from build.");
                return;
            }

            StrippingType strippingType = StrippingType.FlattenHierarchyAndRemoveGameObject;

            switch (preferences.foldersInPrefabs)
            {
            case HierachyFoldersInPrefabs.NotAllowed:
                // No need to do any build stripping if no hierarchy folders are allowed to exist in prefabs.
                return;

            case HierachyFoldersInPrefabs.StrippedAtRuntime:
                // No need to do any build stripping if stripping occurs at runtime only.
                return;

            case HierachyFoldersInPrefabs.NotStripped:
                if (!preferences.warnWhenNotRemovedFromBuild || warnedAboutRemoveFromBuildDisabled)
                {
                    return;
                }

                warnedAboutRemoveFromBuildDisabled = true;
                if (EditorUtility.DisplayDialog("Warning: Hierarchy Folder Prefab Stripping Disabled", "This is a reminder that you have disabled stripping of hierarchy folders from prefabs from builds. If you have any hierarchy folders inside prefabs this will result in suboptimal performance and is not recommended when making a release build.", "Continue Anyway", "Enable Stripping"))
                {
                    return;
                }

                // If not stripped is true we need to disable all HierarchyFolders in prefabs to ensure that runtime stripping does no take place.
                strippingType = StrippingType.DisableComponent;
                break;

            case HierachyFoldersInPrefabs.StrippedAtBuildTime:
                break;

            default:
                Debug.LogWarning("Unrecognized HierachyFoldersInPrefabs value: " + preferences.foldersInPrefabs);
                return;
            }

            CreateBackups();
            StripHierarchyFoldersFromAllPrefabs(strippingType);

            PrefabsStripped = true;
        }
        public static void CheckForAndRemoveHierarchyFoldersInChildren([NotNull] Transform transform, StrippingType strippingType)
        {
            bool wasStripping = NowStripping;

            NowStripping = true;

            int childCount = transform.childCount;
            var children   = new Transform[childCount];

            for (int n = 0; n < childCount; n++)
            {
                children[n] = transform.GetChild(n);
            }

            var hierarchyFolder = transform.GetComponent <HierarchyFolder>();

            if (hierarchyFolder != null)
            {
                var hierarchyFolderParent = transform.parent;
                int setSiblingIndex       = transform.GetSiblingIndex() + 1;

                                #if DEV_MODE && DEBUG_STRIP_FOLDER
                Debug.Log("Stripping " + transform.name + " with " + childCount + " children...");
                                #endif

                switch (strippingType)
                {
                case StrippingType.FlattenHierarchyAndRemoveGameObject:
                case StrippingType.FlattenHierarchy:
                case StrippingType.FlattenHierarchyAndRemoveComponent:
                case StrippingType.FlattenHierarchyAndDisableComponent:
                    for (int n = 0; n < childCount; n++)
                    {
                        var child = children[n];
                        child.SetParent(hierarchyFolderParent, true);
                        child.SetSiblingIndex(setSiblingIndex);
                        setSiblingIndex++;
                    }
                    for (int n = 0; n < childCount; n++)
                    {
                        CheckForAndRemoveHierarchyFoldersInChildren(children[n], strippingType);
                    }
                    break;

                default:
                    for (int n = 0; n < childCount; n++)
                    {
                        var child = children[n];
                        CheckForAndRemoveHierarchyFoldersInChildren(child, strippingType);
                    }
                    break;
                }

                                #if ASSERT_COMPONENT_COUNT
                var componentCount = transform.GetComponents <Component>().Length;
                if (componentCount != 2)
                {
                    Debug.LogError("HierarchyFolder " + transform.name + " contained " + componentCount + " components! All components will be destroyed along with the Hierarchy Folder.");
                }
                                #endif

                                #if ASSERT_CHILD_COUNT
                Debug.Assert(transform.childCount == 0);
                                #endif

                                #if DEBUG_REMOVE_HIERARCHY_FOLDER
                Debug.Log("Destroying HierarchyFolder: " + transform.name);
                                #endif

                switch (strippingType)
                {
                case StrippingType.FlattenHierarchyAndRemoveGameObject:
                    Object.DestroyImmediate(transform.gameObject);
                    break;

                case StrippingType.FlattenHierarchyAndRemoveComponent:
                case StrippingType.RemoveComponent:
                    Object.DestroyImmediate(hierarchyFolder);
                    break;

                case StrippingType.FlattenHierarchyAndDisableComponent:
                case StrippingType.DisableComponent:
                    hierarchyFolder.enabled   = false;
                    transform.hideFlags       = HideFlags.None;
                    hierarchyFolder.hideFlags = HideFlags.None;
                    break;
                }
            }
            else
            {
                for (int n = 0, count = children.Length; n < count; n++)
                {
                    CheckForAndRemoveHierarchyFoldersInChildren(children[n], strippingType);
                }
            }

            NowStripping = wasStripping;
        }