/*WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW*\ ( ( ) ) |/ \| ) ) _((_ || (c) Wanzyee Studio < wanzyeestudio.blogspot.com > || ( ( |_ _ |=n |\ /| _____)) | ! ] U \.ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ./ (_(__(S) |___*/ using UnityEditor; using UnityEngine; using System; using System.Linq; using Object = UnityEngine.Object; namespace WanzyeeStudio.Editrix.Toolkit{ /// /// Group or ungroup scene UnityEngine.Transform for better arrangement. /// /// /// /// Menu "GameObject/Group/Make Group" or hotkey Ctrl-G to group selected children. /// Menu "GameObject/Group/Ungroup Parent" or hotkey Ctrl-Shift-G to ungroup selected parents. /// Menu "GameObject/Group/Ungroup Children" or hotkey Ctrl-Alt-G to move selected children out from the group. /// /// public static class ObjectGrouper{ #region Menu /// /// Make a group UnityEngine.Transform contains selected children in the scene, with hotkey Ctrl-G. /// [MenuItem("GameObject/Group/Make Group %g", false, 90)] public static void MakeGroup(){ if(!MakeGroupValid()) throw new InvalidOperationException("No transform selected."); Selection.objects = new Object[]{MakeGroup(null, Selection.transforms).gameObject}; } /// /// Check if MakeGroup() valid, any scene UnityEngine.Transform selected. /// /// true, if valid. [MenuItem("GameObject/Group/Make Group %g", true)] private static bool MakeGroupValid(){ return Selection.transforms.Any(); } /// /// Ungroup children UnityEngine.Transform from selected parent in the scene, with hotkey Ctrl-Shift-G. /// /// /// /// This'll destroy the parent if it has no other UnityEngine.Component. /// Works like Transform.DetachChildren but detach to upward parent instead of root. /// /// /* * It causes crash when called with both destroying and selecting at once sometimes. * It can be avoided by delay call, it may be an Unity internal execution order problem. */ [MenuItem("GameObject/Group/Ungroup Parent %#g", false, 90)] public static void UngroupParent(){ if(!UngroupParentValid()) throw new InvalidOperationException("No parent transform selected."); EditorApplication.delayCall += () => { var _p = Selection.transforms.Where(_v => 0 < _v.childCount); var _c = _p.SelectMany(_v => UngroupParent(_v, 2 > _v.GetComponents().Length)); Selection.objects = _c.Select(_v => _v.gameObject).ToArray(); }; } /// /// Check if UngroupParent() valid, any scene parent UnityEngine.Transform selected. /// /// true, if valid. [MenuItem("GameObject/Group/Ungroup Parent %#g", true)] private static bool UngroupParentValid(){ return Selection.transforms.Any(_v => 0 < _v.childCount); } /// /// Ungroup selected children UnityEngine.Transform to upward parent, with hotkey Ctrl-Alt-G. /// [MenuItem("GameObject/Group/Ungroup Children %&g", false, 90)] public static void UngroupChildren(){ if(!UngroupChildrenValid()) throw new InvalidOperationException("No child transform selected."); var _c = Selection.transforms.Where(_v => null != _v.parent).OrderBy(_v => -_v.GetSiblingIndex()); foreach(var _v in _c) UngroupChild(_v); } /// /// Check if UngroupParent() valid, any scene child UnityEngine.Transform selected. /// /// true, if valid. [MenuItem("GameObject/Group/Ungroup Children %&g", true)] private static bool UngroupChildrenValid(){ return Selection.transforms.Any(_v => null != _v.parent); } #endregion #region Methods /// /// Filter the top level transforms, excluding prefabs, ordered by sibling index. /// /// The tops. /// Transforms. public static Transform[] FilterTops(params Transform[] transforms){ if(null == transforms) throw new ArgumentNullException("transforms"); var _t = transforms.Distinct().Where(_v => null != _v && !EditorUtility.IsPersistent(_v)).ToArray(); var _f = _t.Where(_v => !_t.Any(_o => _o != _v && _v.IsChildOf(_o))); return _f.OrderBy(_v => EditrixUtility.GetObjectOrder(_v)).ToArray(); } /// /// Make a group UnityEngine.Transform contains specified children. /// /// The group parent. /// Name. /// Children. public static Transform MakeGroup(string name, params Transform[] children){ if(null == children) throw new ArgumentNullException("children"); children = FilterTops(children); if(!children.Any()) throw new ArgumentException("No children assigned.", "children"); var _g = new GameObject(string.IsNullOrEmpty(name) ? "New Group" : name); var _result = children.All(_v => _v is RectTransform) ? _g.AddComponent() : _g.transform; Undo.RegisterCreatedObjectUndo(_g, "Make Group"); Undo.SetTransformParent(_result, children[0].parent, "Arrange Group"); _result.SetSiblingIndex(children[0].GetSiblingIndex()); foreach(var _v in children) Undo.SetTransformParent(_v, _result, "Join Group"); return _result; } /// /// Ungroup all children UnityEngine.Transform from specified parent. /// /// /// /// Optional to destroy the original parent after done. /// Works like UnityEngine.Transform.DetachChildren but detach to upward parent instead of root. /// /// /// The children from the parent. /// Parent. /// If set to true destroy. /// public static Transform[] UngroupParent(Transform parent, bool destroy = false){ if(null == parent) throw new ArgumentNullException("parent"); var _result = parent.Cast().Reverse().ToArray(); if(!_result.Any()) throw new ArgumentException("No children included.", "parent"); foreach(var _v in _result) UngroupChild(_v); if(destroy) Undo.DestroyObjectImmediate(parent.gameObject); return _result; } /// /// Ungroup a child UnityEngine.Transform from current parent to upward. /// /// The new parent. /// Child. public static Transform UngroupChild(Transform child){ if(null == child) throw new ArgumentNullException("child"); var _p = child.parent; if(null == _p) throw new ArgumentException("Given child is a root.", "child"); Undo.SetTransformParent(child, _p.parent, "Ungroup Child"); child.SetAsLastSibling(); child.SetSiblingIndex(_p.GetSiblingIndex() + 1); return child.parent; } #endregion } }