#if UNITY_2019_4_OR_NEWER using System; using System.Linq; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEditor.UIElements; using UnityEngine.UIElements; namespace YooAsset.Editor { public class TreeViewer : VisualElement { public new class UxmlFactory : UxmlFactory { } private readonly ListView _listView; private readonly List _flattenList = new List(1000); private readonly List _rootList = new List(100); /// /// 制作列表元素 /// public Action makeItem { get; set; } /// /// 绑定列表数据 /// public Action bindItem { get; set; } public TreeViewer() { this.style.flexShrink = 1f; this.style.flexGrow = 1f; // 创建ListView _listView = new ListView(); _listView.style.flexShrink = 1f; _listView.style.flexGrow = 1f; _listView.itemsSource = _flattenList; _listView.makeItem = MakeItemInternal; _listView.bindItem = BindItemInternal; this.Add(_listView); } /// /// 设置根节点数据 /// public void SetRootItem(TreeNode rootNode) { _rootList.Add(rootNode); } /// /// 设置根节点数据 /// public void SetRootItems(List rootNodes) { _rootList.AddRange(rootNodes); } /// /// 清理数据 /// public void ClearAll() { _rootList.Clear(); } /// /// 重新绘制视图 /// public void RebuildView() { _flattenList.Clear(); foreach (var treeRoot in _rootList) { FlattenTree(treeRoot, 0); } _listView.Rebuild(); } /// /// 将树形结构扁平化为列表 /// private void FlattenTree(TreeNode node, int depth) { _flattenList.Add(node); if (node.IsExpanded) { foreach (var child in node.Children) { FlattenTree(child, depth + 1); } } } private VisualElement MakeItemInternal() { var container = new VisualElement(); container.style.flexDirection = FlexDirection.Row; // 折叠按钮 var toggle = new ToggleFoldout(); toggle.text = string.Empty; toggle.name = "foldout"; toggle.style.alignSelf = Align.Center; toggle.style.width = 15; toggle.style.height = 15; toggle.RegisterValueChangedCallback((ChangeEvent callback) => { var treeNode = toggle.userData as TreeNode; treeNode.IsExpanded = toggle.value; RebuildView(); }); container.Add(toggle); // 用户自定义元素 if (makeItem != null) { makeItem.Invoke(container); } return container; } private void BindItemInternal(VisualElement item, int index) { var treeNode = _flattenList[index]; // 设置折叠状态 var toggle = item.Q("foldout"); toggle.SetValueWithoutNotify(treeNode.IsExpanded); toggle.userData = treeNode; toggle.style.marginLeft = treeNode.GetDepth() * 15; // 隐藏折叠按钮 if (treeNode.Children.Count == 0) { toggle.style.visibility = Visibility.Hidden; } // 用户自定义元素 if (bindItem != null) { bindItem.Invoke(item, treeNode.UserData); } } } } #endif