Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


BindViewItem

Raised when a HierarchyViewItem is bound to a HierarchyView. Use this event to customize the view item.
Read time 4 minutesLast updated 13 days ago

Definition

  • Type: Event
  • Namespace: Unity.Hierarchy
  • Assembly: UnityEngine.HierarchyModule
public event HierarchyView.BindViewItemEventHandler BindViewItem

Remarks

The following example draws visual connector lines in the Hierarchy window to show the parent and child relationships between GameObjects. It uses the instance-level
BindViewItem
event to register a per-view binding handler that adds the visual connector lines between each parent and child item in the Hierarchy window.
The example requires three USS files:
Connectors.uss
for the base styles,
Connectors_dark.uss
for the Dark theme, and
Connectors_light.uss
for the Light theme.
To use this example, save the script and USS files in a folder called
Assets/Editor/Connectors
. Scripts in an
Editor
folder can use the Hierarchy module API without additional setup. If you save the script outside of an
Editor
folder, you must enable the Hierarchy built-in module in the Package Manager window, which also adds the module to your Player builds.
using System;using System.Collections.Generic;using Unity.Hierarchy;using Unity.Hierarchy.Editor;using UnityEditor;using UnityEngine.Pool;using UnityEngine.UIElements;namespace Unity.HierarchySamples.Editor{ class Connectors { const string k_ConnectorUssClassName = "connector"; const string k_ConnectorHoverUssClassName = "connector--hovered"; const string k_ConnectorContainerClassName = "connector-container"; [InitializeOnLoadMethod] static void Initialize() { HierarchyWindow.BindView += OnBindView; HierarchyWindow.UnbindView += OnUnbindView; } static void OnBindView(HierarchyWindow window, HierarchyView view) { view.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/Connectors/Connectors.uss")); view.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>($"Assets/Editor/Connectors/Connectors{(EditorGUIUtility.isProSkin ? "_dark" : "_light")}.uss")); ConnectorsHandler connectorHandler = new ConnectorsHandler(view); view.BindViewItem += connectorHandler.OnBindViewItem; view.userData = connectorHandler; } static void OnUnbindView(HierarchyWindow window, HierarchyView view) { if (view.userData is ConnectorsHandler connectorHandler) view.BindViewItem -= connectorHandler.OnBindViewItem; } class ConnectorsHandler { static readonly List<VisualElement> s_ConnectorsCache = new(); static readonly ObjectPool<VisualElement> s_ConnectorVisualElementPool = new(() => new VisualElement(), actionOnRelease: e => e.userData = null); readonly HierarchyView m_View; int m_HoverDepth = -1; internal ConnectorsHandler(HierarchyView view) => m_View = view; internal void OnBindViewItem(HierarchyView view, HierarchyViewItem viewItem) { HierarchyViewModel viewModel = view.ViewModel; VisualElement connectorContainer = viewItem.Q(className: k_ConnectorContainerClassName); if (connectorContainer == null) { connectorContainer = new VisualElement(); connectorContainer.AddToClassList(k_ConnectorContainerClassName); viewItem.Add(connectorContainer); } s_ConnectorsCache.Clear(); connectorContainer.Query(className: k_ConnectorUssClassName).ToList(s_ConnectorsCache); // Depth is 0 when filtering because the tree is flattened int nodeDepth = view.Filtering ? 0 : viewModel.GetDepth(viewItem.Node); HierarchyNode nodeParent = viewModel.GetParent(viewItem.Node); bool parentHasHoveredFlag = viewModel.HasFlags(nodeParent, (HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered); for (int i = 0; i < nodeDepth; i++) { VisualElement connector; if (i < s_ConnectorsCache.Count) { connector = s_ConnectorsCache[i]; } else { connector = s_ConnectorVisualElementPool.Get(); connector.AddToClassList(k_ConnectorUssClassName); connectorContainer.Add(connector); connector.RegisterCallback<MouseEnterEvent>(OnMouseEnter); connector.RegisterCallback<MouseLeaveEvent>(OnMouseLeave); connector.RegisterCallback<MouseDownEvent>(OnConnectorPressed); } connector.userData = (viewItem, i); connector.style.left = i * 14; connector.EnableInClassList(k_ConnectorHoverUssClassName, parentHasHoveredFlag && i == m_HoverDepth); } for (int i = nodeDepth; i < s_ConnectorsCache.Count; i++) { VisualElement connector = s_ConnectorsCache[i]; connector.RemoveFromHierarchy(); connector.UnregisterCallback<MouseEnterEvent>(OnMouseEnter); connector.UnregisterCallback<MouseLeaveEvent>(OnMouseLeave); connector.UnregisterCallback<MouseDownEvent>(OnConnectorPressed); s_ConnectorVisualElementPool.Release(connector); } } static (HierarchyViewItem viewItem, int depth) GetConnectorData(EventBase evt) => ((HierarchyViewItem, int))((VisualElement)evt.currentTarget).userData; void OnMouseEnter(MouseEnterEvent evt) { (HierarchyViewItem viewItem, int depth) = GetConnectorData(evt); m_HoverDepth = depth; HierarchyNode ancestor = GetAncestorAtDepth(viewItem, depth); viewItem.View.ViewModel.SetFlagsRecursive(ancestor, (HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered, HierarchyTraversalDirection.Children); } void OnMouseLeave(MouseLeaveEvent evt) { m_HoverDepth = -1; m_View.ViewModel.ClearFlags((HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered); } void OnConnectorPressed(MouseDownEvent evt) { (HierarchyViewItem viewItem, int depth) = GetConnectorData(evt); HierarchyNode ancestor = GetAncestorAtDepth(viewItem, depth); if (evt.altKey) viewItem.View.ViewModel.ClearFlagsRecursive(ancestor, HierarchyNodeFlags.Expanded, HierarchyTraversalDirection.Children); else viewItem.View.ViewModel.ClearFlags(ancestor, HierarchyNodeFlags.Expanded); } HierarchyNode GetAncestorAtDepth(HierarchyViewItem viewItem, int depth) { HierarchyNode ancestor = viewItem.Node; for (int i = viewItem.View.ViewModel.GetDepth(viewItem.Node); i > depth; i--) ancestor = viewItem.View.ViewModel.GetParent(ancestor); return ancestor; } } // Custom flags can be defined by using unused bits in the HierarchyNodeFlags enum. // This example uses bit 4 to track hover state for connector visualization. enum HierarchyNodeFlagsExtended : uint { ConnectorsHovered = 1 << 4 } }}
The following example shows how to style
Connectors.uss
.
.connector { width: 10px; border-left-width: 1px; height: 100%; position: absolute;}.connector-container { position: absolute; left: 12px; top: 0; background-color: chartreuse; height: 20px; width: auto;}.connector.connector--hovered{ border-left-width: 1px;}
The following example shows how to style
Connectors_dark.uss
.
.connector { border-left-color: rgba(169, 169, 169, 0.42);}.connector.connector--hovered{ border-left-color: darkgrey;}
The following example shows how to style
Connectors_light.uss
.
.connector { border-left-color: darkgrey;}.connector.connector--hovered{ border-left-color: grey;}