com.alicizax.unity.tuyoogam.../Editor/UIElements/TreeViewer/TreeViewer.cs

152 lines
4.2 KiB
C#
Raw Normal View History

2025-04-01 21:12:28 +08:00
#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<TreeViewer, UxmlTraits>
{
}
private readonly ListView _listView;
private readonly List<TreeNode> _flattenList = new List<TreeNode>(1000);
private readonly List<TreeNode> _rootList = new List<TreeNode>(100);
/// <summary>
/// 制作列表元素
/// </summary>
public Action<VisualElement> makeItem { get; set; }
/// <summary>
/// 绑定列表数据
/// </summary>
public Action<VisualElement, object> 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);
}
/// <summary>
/// 设置根节点数据
/// </summary>
public void SetRootItem(TreeNode rootNode)
{
_rootList.Add(rootNode);
}
/// <summary>
/// 设置根节点数据
/// </summary>
public void SetRootItems(List<TreeNode> rootNodes)
{
_rootList.AddRange(rootNodes);
}
/// <summary>
/// 清理数据
/// </summary>
public void ClearAll()
{
_rootList.Clear();
}
/// <summary>
/// 重新绘制视图
/// </summary>
public void RebuildView()
{
_flattenList.Clear();
foreach (var treeRoot in _rootList)
{
FlattenTree(treeRoot, 0);
}
_listView.Rebuild();
}
/// <summary>
/// 将树形结构扁平化为列表
/// </summary>
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<bool> 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<ToggleFoldout>("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