Version: Unity 6.6 (6000.6)
LanguageEnglish
  • C#

HierarchyNodeFlags

enumeration

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

Description

Bit flags used to describe the state of a hierarchy node.

You can define custom flags by casting an unused bit position to this enum. The built-in values occupy bits 0–3, so bits 4 and above are available for extension. Use HierarchyViewModel.SetFlags, HierarchyViewModel.SetFlagsRecursive, HierarchyViewModel.ClearFlags, and HierarchyViewModel.ClearFlagsRecursive with your custom flags to track additional per-node states without affecting built-in behavior.

The following example draws visual connector lines in the Hierarchy window to show the parent and child relationships between GameObjects. It uses HierarchyNodeFlags to define a custom flag at bit 4 to track the hover state for visual connector lines. The example sets and clears the flag recursively on an ancestor and its descendants when your mouse enters or leaves a connector line.

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; }

Properties

Property Description
None The hierarchy node has no flags.
Expanded The hierarchy node is expanded.
Selected The hierarchy node is selected.
Cut The hierarchy node is cut.
Hidden The hierarchy node is hidden (also hides children).