/// <summary> /// Sets parent Transform of child, with option to skip Hierarchy Folders. /// When <paramref name="skipHierarchyFolders"/> is false will also automatically handle Flatten Hierarchy play mode behaviour (when enabled in preferences). /// </summary> /// <param name="child"> Child whose parent is being set. </param> /// <param name="parent"> New parent for child. </param> /// <param name="worldPositionStays"></param> /// <param name="skipHierarchyFolders"> /// If true then Hierarchy Folders will be skipped when determining the parent. If <paramref name="parent"/> and all parents it might have are hierarchy folders, /// then <paramref name="child"/> will be moved to hierarchy root. /// </param> public static void SetParent([NotNull] this Transform child, [CanBeNull] Transform parent, bool worldPositionStays, bool skipHierarchyFolders) { #if UNITY_EDITOR if (parent != null && parent.gameObject.IsHierarchyFolder()) { if (skipHierarchyFolders) { child.SetParent(parent.GetParent(true), worldPositionStays); } else if (HierarchyFolderPreferences.FlattenHierarchy) { int moveToIndex = HierarchyFolderUtility.GetLastChildIndexInFlatMode(parent.gameObject); var parentOfFolder = parent.parent; child.transform.SetParent(parentOfFolder, worldPositionStays); if (moveToIndex < 0) { #if DEV_MODE Debug.LogWarning("GetLastChildIndexInFlatMode result < 0"); #endif return; } child.transform.SetSiblingIndex(moveToIndex); return; } } #endif child.transform.SetParent(parent, worldPositionStays); }
private void OnHierarchyChangedInPlayModeFlattened() { if (this == null) { EditorApplication.hierarchyChanged -= OnHierarchyChangedInPlayModeFlattened; return; } OnHierarchyChangedShared(); #if DEV_MODE if (transform.childCount > 0) { if (HierarchyFolderUtility.NowStripping) { Debug.LogWarning(name + " child count is " + transform.childCount + " but won't flatten because HierarchyFolderUtility.NowStripping already true.", gameObject); } else { Debug.Log(name + " child count " + transform.childCount + ". Flattening now...", gameObject); } } #endif if (transform.childCount > 0 && !HierarchyFolderUtility.NowStripping) { int moveToIndex = HierarchyFolderUtility.GetLastChildIndexInFlatMode(gameObject); for (int n = transform.childCount - 1; n >= 0; n--) { var child = transform.GetChild(n); child.SetParent(null, true); child.SetSiblingIndex(moveToIndex); } } }
internal static void CreateHierarchyFolderParent() { int count = Selection.transforms.Length; var members = new Transform[count]; Array.Copy(Selection.transforms, 0, members, 0, count); Array.Sort(members, SortByHierarchyOrder); var firstMember = members[0]; var hierarchyFolderParent = firstMember.parent; var folder = CreateHierarchyFolderInternal(firstMember is RectTransform); // if not all selected have the same parent, then create folders as last item in hierarchy for (int n = 1; n < count; n++) { if (members[n].parent != hierarchyFolderParent) { hierarchyFolderParent = null; break; } } if (hierarchyFolderParent != null) { folder.transform.UndoableSetParent(hierarchyFolderParent, "Hierarchy Folder Parent"); } int hierarchyFolderSiblingIndex = firstMember.GetSiblingIndex(); folder.transform.SetSiblingIndex(hierarchyFolderSiblingIndex); Undo.RegisterCreatedObjectUndo(folder, "Hierarchy Folder Parent"); #if UNITY_EDITOR if (EditorApplication.isPlayingOrWillChangePlaymode && HierarchyFolderPreferences.Get().playModeBehaviour == StrippingType.FlattenHierarchy) { int moveToIndex = HierarchyFolderUtility.GetLastChildIndexInFlatMode(folder); for (int n = count - 1; n >= 0; n--) { Undo.SetTransformParent(members[n], hierarchyFolderParent, "Hierarchy Folder Parent"); members[n].SetSiblingIndex(moveToIndex); } return; } #endif for (int n = 0; n < count; n++) { Undo.SetTransformParent(members[n], folder.transform, "Hierarchy Folder Parent"); members[n].SetAsLastSibling(); } Selection.activeGameObject = folder; }
/// <summary> /// Sets parent Transform of child, with option to skip Hierarchy Folders. /// When <paramref name="skipHierarchyFolders"/> is false will also automatically handle Flatten Hierarchy play mode behaviour (when enabled in preferences). /// </summary> /// <param name="child"> Child whose parent is being set. </param> /// <param name="parent"> New parent for child. </param> /// <param name="worldPositionStays"></param> /// <param name="skipHierarchyFolders"> /// If true then Hierarchy Folders will be skipped when determining the parent. If <paramref name="parent"/> and all parents it might have are hierarchy folders, /// then <paramref name="child"/> will be moved to hierarchy root. /// </param> public static void UndoableSetParent([NotNull] this Transform child, [CanBeNull] Transform parent, string undoName, bool skipHierarchyFolders = false) { #if UNITY_EDITOR if (parent != null && parent.gameObject.IsHierarchyFolder()) { if (skipHierarchyFolders) { if (!Application.isPlaying) { Undo.SetTransformParent(child, parent.GetParent(true), undoName); //NOTE: Doesn't support worldPositionStays=false } else { child.SetParent(parent.GetParent(true), true); } } else if (HierarchyFolderPreferences.FlattenHierarchy) { int moveToIndex = HierarchyFolderUtility.GetLastChildIndexInFlatMode(parent.gameObject); var parentOfFolder = parent.parent; if (!Application.isPlaying) { Undo.SetTransformParent(child, parentOfFolder, undoName); //NOTE: Doesn't support worldPositionStays=false } else { child.transform.SetParent(parentOfFolder, true); } if (moveToIndex < 0) { #if DEV_MODE Debug.LogWarning("GetLastChildIndexInFlatMode result < 0"); #endif return; } child.transform.SetSiblingIndex(moveToIndex); return; } } if (!Application.isPlaying) { Undo.SetTransformParent(child, parent, undoName); return; } #endif child.transform.SetParent(parent, true); }
private void OnHierarchyChangedInPlayModeFlattened() { hierarchyFolders.RemoveAll(isNull); hierarchyFolders.Sort(compareHierarchyDepth); for (int n = 0, count = hierarchyFolders.Count - 1; n < count; n++) { var hierarchyFolder = hierarchyFolders[n]; // Only process scene objects, not prefabs. if (!hierarchyFolder.gameObject.scene.IsValid()) { continue; } OnHierarchyChangedShared(hierarchyFolder); var transform = hierarchyFolder.transform; #if DEV_MODE if (transform.childCount > 0) { if (HierarchyFolderUtility.NowStripping) { Debug.LogWarning(hierarchyFolder.name + " child count is " + transform.childCount + " but won't flatten because HierarchyFolderUtility.NowStripping already true.", hierarchyFolder); } else { Debug.Log(hierarchyFolder.name + " child count " + transform.childCount + ". Flattening now...", hierarchyFolder); } } #endif if (transform.childCount > 0 && !HierarchyFolderUtility.NowStripping) { // todo: should we keep track of flattened children in play mode? Or only for prefabs? // Would there be benefits to keeping track of them? // Could select them when hierarchy folder is double clicked in hierarchy view? // Could draw some sort of bounds around the children in the hierarchy?!!! int moveToIndex = HierarchyFolderUtility.GetLastChildIndexInFlatMode(transform.gameObject); for (int c = transform.childCount - 1; c >= 0; c--) { var child = transform.GetChild(c); child.SetParent(null, true); child.SetSiblingIndex(moveToIndex); } } } hierarchyFolders.RemoveAll(isNull); }