using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor; namespace GeNa.Core { public static class PrefabUnpackerUtility { #region Methods /// /// Function used to perform the GeNa Unpack decorators /// This will get all of the decorators on the gameobject 'currentGameObject' /// Then unpacks all based on the decorator setup /// /// /// /// /// /// public static GameObject ExecuteUnpackMasterGameObject(GameObject currentGameObject, bool destroyDuplicatedObject = false, PrefabUnpackMode unpackMode = PrefabUnpackMode.OutermostRoot, InteractionMode interactionMode = InteractionMode.AutomatedAction) { if (currentGameObject == null) { Debug.LogError("No gameobject was provided to perform the prefab unpack"); return null; } GameObject duplicatedGameObject = DuplicateHierarchyObject(currentGameObject); IDecorator[] decorators = GetAllGeNaPrefabUnpackerFromObject(duplicatedGameObject); List currentGameObjects = new List(); foreach (IDecorator decorator in decorators) { if (decorator is MonoBehaviour mono) currentGameObjects.Add(mono.gameObject); } bool unpackPrefab = decorators.Length > 0; if (unpackPrefab) { UnpackGroupOfGameObjects(currentGameObjects.ToArray(), true, unpackMode, interactionMode); } if (destroyDuplicatedObject) Object.DestroyImmediate(duplicatedGameObject); return duplicatedGameObject; } /// /// Used to repack the an object to the source. /// /// /// /// public static void ExecuteRepackPrefab(GameObject sourcePrefab, GameObject sourceNonPrefab, InteractionMode interactionMode = InteractionMode.AutomatedAction) { if (sourcePrefab == null) { Debug.LogError("Source prefab was not provided"); return; } if (sourceNonPrefab == null) { Debug.LogError("Non prefab source gameobject was not provided"); return; } string path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(sourcePrefab); if (!string.IsNullOrEmpty(path)) { PrefabUtility.SaveAsPrefabAssetAndConnect(sourceNonPrefab, path, interactionMode); } } /// /// Used to destroy a gameobject immediately no undo recorded /// /// public static void ExecuteDeleteGameObject(GameObject currentGameObject) { if (currentGameObject == null) { Debug.LogError("No Gameobject was provided"); return; } Object.DestroyImmediate(currentGameObject); } private static bool ContainsPrefabs(GameObject currentGameObject) { Transform[] children = currentGameObject.GetComponentsInChildren(); foreach (Transform child in children) { if (child.gameObject == currentGameObject) continue; if (GeNaEditorUtility.IsPrefab(child.gameObject)) { return true; } } return false; } /// /// Performs the unpacking of the current GameObject /// /// /// /// /// private static void UnpackGroupOfGameObjects(GameObject[] currentGameObjects, bool destroyDecorator = true, PrefabUnpackMode unpackMode = PrefabUnpackMode.OutermostRoot, InteractionMode interactionMode = InteractionMode.AutomatedAction) { if (currentGameObjects.Length < 1) return; foreach (GameObject gameObject in currentGameObjects) { IDecorator[] decorators = gameObject.GetComponents(); bool unpackPrefab = false; if (decorators.Length > 0) unpackPrefab = decorators.Any(item => item.UnpackPrefab); if (destroyDecorator) { IEnumerable unpackers = decorators.Where(item => item.UnpackPrefab); foreach (IDecorator decorator in unpackers) { if (decorator is MonoBehaviour mono) GeNaEvents.Destroy(mono); } } if (unpackPrefab) UnPackPrefab(gameObject, unpackMode, interactionMode); } } /// /// Duplicates the prefab object in the Hierarchy /// /// /// private static GameObject DuplicateHierarchyObject(GameObject currentGameObject) { if (currentGameObject == null) { return null; } bool isPrefab = false; string path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(currentGameObject); GameObject prefabRoot = AssetDatabase.LoadAssetAtPath(path); if (prefabRoot != null) { if (prefabRoot != null) { isPrefab = true; } } GameObject instantiateGameObject = InstantiateGameObject(currentGameObject, prefabRoot, isPrefab); return instantiateGameObject; } /// /// Instantiate the GameObject if it's a prefab or not /// /// /// /// /// private static GameObject InstantiateGameObject(GameObject currentGameObject, GameObject prefabGameObject, bool isPrefab) { if (currentGameObject == null) { return null; } if (isPrefab) { return PrefabUtility.InstantiatePrefab(prefabGameObject) as GameObject; } else { GameObject newObject = Object.Instantiate(currentGameObject); newObject.name = currentGameObject.name; return newObject; } } /// /// Gets all the prefab unpacker components /// /// /// private static IDecorator[] GetAllGeNaPrefabUnpackerFromObject(GameObject currentGameObject) { List prefabUnpackers = new List(); if (currentGameObject != null) { IDecorator[] datas = currentGameObject.GetComponentsInChildren(); if (datas.Length > 0) { foreach (IDecorator data in datas) { if (data.UnpackPrefab) prefabUnpackers.Add(data); } } } return prefabUnpackers.ToArray(); } /// /// Unpacks the prefab based on the settings /// /// /// /// private static void UnPackPrefab(GameObject currentGameObject, PrefabUnpackMode unpackMode = PrefabUnpackMode.OutermostRoot, InteractionMode interactionMode = InteractionMode.AutomatedAction) { if (currentGameObject == null) return; if (PrefabUtility.IsOutermostPrefabInstanceRoot(currentGameObject)) PrefabUtility.UnpackPrefabInstance(currentGameObject, unpackMode, interactionMode); } #endregion } }