public void RefreshNameOf(Transform target) { if (target) { Scene targetScene = target.gameObject.scene; for (int i = sceneData.Count - 1; i >= 0; i--) { HierarchyDataRoot data = sceneData[i]; if ((data is HierarchyDataRootPseudoScene) || ((HierarchyDataRootScene)data).Scene == targetScene) { sceneData[i].RefreshNameOf(target); } } if (m_isInSearchMode) { RefreshSearchResults(); for (int i = searchSceneData.Count - 1; i >= 0; i--) { searchSceneData[i].RefreshNameOf(target); } } for (int i = drawers.Count - 1; i >= 0; i--) { if (drawers[i].gameObject.activeSelf && drawers[i].Data.BoundTransform == target) { drawers[i].RefreshName(); } } shouldRecalculateContentWidth = true; } }
public bool Select(Transform selection, bool forceSelection = false) { if (!selection) { Deselect(); return(true); } else { if (!forceSelection && selection == m_currentSelection) { return(true); } CurrentSelection = selection; // Make sure that the contents of the hierarchy are up-to-date Refresh(); Scene selectionScene = selection.gameObject.scene; for (int i = 0; i < sceneData.Count; i++) { HierarchyDataRoot data = sceneData[i]; if ((data is HierarchyDataRootPseudoScene) || ((HierarchyDataRootScene)data).Scene == selectionScene) { HierarchyDataTransform selectionItem = sceneData[i].FindTransform(selection); if (selectionItem != null) { RefreshListView(); // Focus on selected HierarchyItem int itemIndex = selectionItem.AbsoluteIndex; for (int j = 0; j < i; j++) { itemIndex += sceneData[i].Height; } LayoutRebuilder.ForceRebuildLayoutImmediate(drawArea); scrollView.verticalNormalizedPosition = Mathf.Clamp01(1f - (float)itemIndex / totalItemCount); return(true); } } } } return(false); }
public HierarchyDataRootSearch(RuntimeHierarchy hierarchy, HierarchyDataRoot reference) : base(hierarchy) { this.reference = reference; }
private bool DropTransformOnto(Transform droppedTransform, HierarchyData target, HierarchyDataRoot newScene, Transform newParent, int newSiblingIndex, out bool decrementSiblingIndex, out bool shouldFocusObjectInHierarchy) { shouldFocusObjectInHierarchy = false; decrementSiblingIndex = false; // If we are only changing the sibling index of the dropped Transform and not its parent, then make sure // that the target sibling index won't be affected when the dropped Transform is shifted in the Hierarchy if (droppedTransform.parent == newParent) { if (newParent || (newScene is HierarchyDataRootScene && ((HierarchyDataRootScene)newScene).Scene == droppedTransform.gameObject.scene)) { if (newSiblingIndex > droppedTransform.GetSiblingIndex()) { newSiblingIndex--; decrementSiblingIndex = true; } } else if (newScene is HierarchyDataRootPseudoScene) { int pseudoSceneSiblingIndex = newScene.IndexOf(droppedTransform); if (pseudoSceneSiblingIndex >= 0 && newSiblingIndex > pseudoSceneSiblingIndex) { newSiblingIndex--; decrementSiblingIndex = true; } } } if (newParent) // Drop inside a Transform { if (!hierarchy.CanDropDraggedParentOnChild) { // Avoid setting child object as parent of the parent object if (newParent.IsChildOf(droppedTransform)) { return(false); } } else { Transform curr = newParent; while (curr.parent != null && curr.parent != droppedTransform) { curr = curr.parent; } // First, set the child object's parent as the dropped object's current parent so that // the dropped object can then become a child of the former child object if (curr.parent == droppedTransform) { HierarchyDataRootPseudoScene pseudoScene = target.Root as HierarchyDataRootPseudoScene; int pseudoSceneChildIndex; if (pseudoScene != null && (pseudoSceneChildIndex = pseudoScene.IndexOf(droppedTransform)) >= 0) { // Dropped object was a root pseudo-scene object, swap the child and parent objects in the pseudo-scene, as well if (hierarchy.CanDropDraggedObjectsToPseudoScenes) { pseudoScene.InsertChild(pseudoSceneChildIndex, curr); pseudoScene.RemoveChild(droppedTransform); } } int siblingIndex = droppedTransform.GetSiblingIndex(); curr.SetParent(droppedTransform.parent, true); curr.SetSiblingIndex(siblingIndex); shouldFocusObjectInHierarchy = true; } } droppedTransform.SetParent(newParent, true); } else // Drop at the root of a scene { if (newScene is HierarchyDataRootPseudoScene) { if (!hierarchy.CanDropDraggedObjectsToPseudoScenes) { return(false); } // Add object to pseudo-scene if (newSiblingIndex < 0) { ((HierarchyDataRootPseudoScene)newScene).AddChild(droppedTransform); } else { ((HierarchyDataRootPseudoScene)newScene).InsertChild(newSiblingIndex, droppedTransform); // Don't try to change the actual sibling index of the Transform newSiblingIndex = -1; target = newScene; } } else if (newScene is HierarchyDataRootScene) { if (droppedTransform.parent != null) { droppedTransform.SetParent(null, true); } // Change dropped object's scene Scene scene = ((HierarchyDataRootScene)newScene).Scene; if (droppedTransform.gameObject.scene != scene) { SceneManager.MoveGameObjectToScene(droppedTransform.gameObject, scene); } if (newSiblingIndex < 0) { // If object was dropped onto the scene, add it to the bottom of the scene newSiblingIndex = scene.rootCount + 1; shouldFocusObjectInHierarchy = true; } } } if (newSiblingIndex >= 0) { droppedTransform.SetSiblingIndex(newSiblingIndex); } shouldFocusObjectInHierarchy |= (newSiblingIndex < 0 && !target.IsExpanded); return(true); }
void IDropHandler.OnDrop(PointerEventData eventData) { ((IPointerExitHandler)this).OnPointerExit(eventData); if (!hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode) { return; } Transform[] droppedTransforms = RuntimeInspectorUtils.GetAssignableObjectsFromDraggedReferenceItem <Transform>(eventData); if (droppedTransforms == null || droppedTransforms.Length == 0) { return; } // Sorting the selection is necessary to preserve the sibling index order of the dragged Transforms if (droppedTransforms.Length > 1) { System.Array.Sort(droppedTransforms, (transform1, transform2) => CompareHierarchySiblingIndices(transform1, transform2)); } bool shouldFocusObjectInHierarchy = false; float contentYPos = pointerLastYPos + content.anchoredPosition.y; int dataIndex = (int)contentYPos / hierarchy.Skin.LineHeight; HierarchyData target = hierarchy.GetDataAt(dataIndex); if (target == null) { // Dropped Transform(s) onto the blank space at the bottom of the Hierarchy for (int i = 0; i < droppedTransforms.Length; i++) { if (droppedTransforms[i].parent != null) { droppedTransforms[i].SetParent(null, true); shouldFocusObjectInHierarchy = true; } } if (!shouldFocusObjectInHierarchy) { return; } } else { int insertDirection; float relativePosition = contentYPos % hierarchy.Skin.LineHeight; if (relativePosition < siblingIndexModificationArea) { insertDirection = -1; } else if (relativePosition > hierarchy.Skin.LineHeight - siblingIndexModificationArea) { insertDirection = 1; } else { insertDirection = 0; } // Inserting above/below a scene or pseudo-scene is a special case if (insertDirection != 0 && !(target is HierarchyDataTransform)) { if (insertDirection < 0 && dataIndex > 0) { // In an hierarchy with consecutive items A and B, insert below A instead of inserting above B because it makes calculations easier HierarchyData _target = hierarchy.GetDataAt(dataIndex - 1); if (_target != null) { target = _target; insertDirection = 1; } } else if (insertDirection > 0 && dataIndex < hierarchy.ItemCount - 1) { // In an hierarchy with consecutive items A and B where B is a Transform, insert above B instead of inserting below A because it makes calculations easier HierarchyData _target = hierarchy.GetDataAt(dataIndex + 1); if (_target != null && _target is HierarchyDataTransform) { target = _target; insertDirection = -1; } } } HierarchyDataRoot newScene = null; Transform newParent = null; int newSiblingIndex = -1; if (!(target is HierarchyDataTransform)) { // Dropped onto a scene or pseudo-scene newScene = (HierarchyDataRoot)target; } else { // Dropped onto a Transform newParent = ((HierarchyDataTransform)target).BoundTransform; if (!newParent) { return; } if (insertDirection != 0) { if (insertDirection > 0 && target.Height > 1) { // Dropped below an expanded Transform, make dropped object a child of it newSiblingIndex = 0; } else if (target.Depth == 1 && target.Root is HierarchyDataRootPseudoScene) { // Dropped above or below a root pseudo-scene object, don't actually change the parent if (insertDirection < 0) { newSiblingIndex = ((HierarchyDataRootPseudoScene)target.Root).IndexOf(newParent); } else { newSiblingIndex = ((HierarchyDataRootPseudoScene)target.Root).IndexOf(newParent) + 1; } newParent = null; } else { // Dropped above or below a regular Transform, calculate target sibling index if (insertDirection < 0) { newSiblingIndex = newParent.GetSiblingIndex(); } else { newSiblingIndex = newParent.GetSiblingIndex() + 1; } // To be able to drop the object at that sibling index, object's parent must also be changed newParent = newParent.parent; } } if (!newParent) { newScene = target.Root; } } int successfullyDroppedTransformCount = 0; for (int i = 0; i < droppedTransforms.Length; i++) { bool _shouldFocusObjectInHierarchy, decrementSiblingIndex; if (DropTransformOnto(droppedTransforms[i], target, newScene, newParent, (newSiblingIndex >= 0) ? (newSiblingIndex + successfullyDroppedTransformCount) : newSiblingIndex, out decrementSiblingIndex, out _shouldFocusObjectInHierarchy)) { successfullyDroppedTransformCount++; shouldFocusObjectInHierarchy |= _shouldFocusObjectInHierarchy; if (decrementSiblingIndex) { newSiblingIndex--; } } } if (successfullyDroppedTransformCount == 0) { return; } } // Don't reveal the selection unless it's necessary (i.e. selection is already fully visible) if (shouldFocusObjectInHierarchy) { hierarchy.SelectInternal(droppedTransforms, RuntimeHierarchy.SelectOptions.FocusOnSelection | RuntimeHierarchy.SelectOptions.ForceRevealSelection); } else { hierarchy.Refresh(); } }
void IDropHandler.OnDrop(PointerEventData eventData) { ((IPointerExitHandler)this).OnPointerExit(eventData); if (!hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode) { return; } Transform droppedTransform = RuntimeInspectorUtils.GetAssignableObjectFromDraggedReferenceItem(eventData, typeof(Transform)) as Transform; if (!droppedTransform) { return; } int newSiblingIndex = -1; bool shouldFocusObjectInHierarchy = false; float contentYPos = pointerLastYPos + content.anchoredPosition.y; int dataIndex = (int)contentYPos / hierarchy.Skin.LineHeight; HierarchyData target = hierarchy.GetDataAt(dataIndex); if (target == null) { // Dropped object onto the blank space at the bottom of the Hierarchy if (droppedTransform.parent == null) { return; } droppedTransform.SetParent(null, true); shouldFocusObjectInHierarchy = true; } else { int insertDirection; float relativePosition = contentYPos % hierarchy.Skin.LineHeight; if (relativePosition < siblingIndexModificationArea) { insertDirection = -1; } else if (relativePosition > hierarchy.Skin.LineHeight - siblingIndexModificationArea) { insertDirection = 1; } else { insertDirection = 0; } // Inserting above/below a scene or pseudo-scene is a special case if (insertDirection != 0 && !(target is HierarchyDataTransform)) { if (insertDirection < 0 && dataIndex > 0) { // In Hierarchy AB, if inserting above B, then instead insert below A; it is easier for calculations HierarchyData _target = hierarchy.GetDataAt(dataIndex - 1); if (_target != null) { target = _target; insertDirection = 1; } } else if (insertDirection > 0 && dataIndex < hierarchy.ItemCount - 1) { // In Hierarchy AB, if inserting below A, then instead insert above B if B is a Transform; it is easier for calculations HierarchyData _target = hierarchy.GetDataAt(dataIndex + 1); if (_target != null && _target is HierarchyDataTransform) { target = _target; insertDirection = -1; } } } HierarchyDataRoot newScene = null; if (!(target is HierarchyDataTransform)) { // Dropped onto a scene or pseudo-scene newScene = (HierarchyDataRoot)target; } else { // Dropped onto a Transform Transform newParent = ((HierarchyDataTransform)target).BoundTransform; // Dropped onto itself, ignore if (!newParent || droppedTransform == newParent) { return; } if (insertDirection != 0) { if (insertDirection > 0 && target.Height > 1) { // Dropped below an expanded Transform, make dropped object a child of it newSiblingIndex = 0; } else if (target.Depth == 1 && target.Root is HierarchyDataRootPseudoScene) { // Dropped above or below a root pseudo-scene object, don't actually change the parent if (insertDirection < 0) { newSiblingIndex = ((HierarchyDataRootPseudoScene)target.Root).IndexOf(newParent); } else { newSiblingIndex = ((HierarchyDataRootPseudoScene)target.Root).IndexOf(newParent) + 1; } newParent = null; } else { // Dropped above or below a regular Transform, calculate target sibling index if (insertDirection < 0) { newSiblingIndex = newParent.GetSiblingIndex(); } else { newSiblingIndex = newParent.GetSiblingIndex() + 1; } // To be able to drop the object at that sibling index, object's parent must also be changed newParent = newParent.parent; // If we are only changing the sibling index of the dropped Transform and not the parent, then make sure // that the target sibling index won't be affected when the dropped Transform is shifted in the Hierarchy if (newParent == droppedTransform.parent && (newParent || (target.Root is HierarchyDataRootScene && ((HierarchyDataRootScene)target.Root).Scene == droppedTransform.gameObject.scene))) { if (newSiblingIndex > droppedTransform.GetSiblingIndex()) { newSiblingIndex--; } } } } if (!newParent) { newScene = target.Root; } else { if (!canDropParentOnChild) { // Avoid setting child object as parent of the parent object if (newParent.IsChildOf(droppedTransform)) { return; } } else { // First, set the child object's parent as dropped object's current parent so that // the dropped object can then become a child of the former child object Transform curr = newParent; while (curr.parent != null && curr.parent != droppedTransform) { curr = curr.parent; } if (curr.parent == droppedTransform) { if (droppedTransform.parent == null && target.Root is HierarchyDataRootPseudoScene) { // Dropped object was a root pseudo-scene object, swap the child and parent objects in the pseudo-scene, as well if (!canAddObjectsToPseudoScenes) { return; } HierarchyDataRootPseudoScene pseudoScene = (HierarchyDataRootPseudoScene)target.Root; pseudoScene.InsertChild(pseudoScene.IndexOf(newParent), curr); pseudoScene.RemoveChild(newParent); } int siblingIndex = droppedTransform.GetSiblingIndex(); curr.SetParent(droppedTransform.parent, true); curr.SetSiblingIndex(siblingIndex); shouldFocusObjectInHierarchy = true; } } droppedTransform.SetParent(newParent, true); } } if (newScene != null) { if (newScene is HierarchyDataRootPseudoScene) { if (!canAddObjectsToPseudoScenes) { return; } // Add object to pseudo-scene if (newSiblingIndex < 0) { ((HierarchyDataRootPseudoScene)newScene).AddChild(droppedTransform); } else { ((HierarchyDataRootPseudoScene)newScene).InsertChild(newSiblingIndex, droppedTransform); // Don't try to change the actual sibling index of the Transform newSiblingIndex = -1; target = newScene; } } else if (newScene is HierarchyDataRootScene) { if (droppedTransform.parent != null) { droppedTransform.SetParent(null, true); } // Change dropped object's scene Scene scene = ((HierarchyDataRootScene)newScene).Scene; if (droppedTransform.gameObject.scene != scene) { SceneManager.MoveGameObjectToScene(droppedTransform.gameObject, scene); } if (newSiblingIndex < 0) { // If object was dropped onto the scene, add it to the bottom of the scene newSiblingIndex = scene.rootCount + 1; shouldFocusObjectInHierarchy = true; } } } if (newSiblingIndex >= 0) { droppedTransform.SetSiblingIndex(newSiblingIndex); } } // Selecting the object in Hierarchy automatically expands collapsed parent entries and snaps the scroll view to the // selected object. However, this snapping can be distracting, so don't select the object unless it is necessary if (shouldFocusObjectInHierarchy || (newSiblingIndex < 0 && !target.IsExpanded)) { hierarchy.Select(droppedTransform, true); } else { hierarchy.Refresh(); } }