Unity

仅适用于2018之前的版本,有UIElements或者UIWidgets的最好用新的

基本实现

树节点

public interface ITreeNode
{
    ITreeNode Parent { get; set; }
    List<ITreeNode> Children { get; }
    bool IsOpen { get; set; }
    string DisplayString { get; }

    void AddChild(ITreeNode node);
    void Dispose();
}

public class TreeNode : ITreeNode
{
    private string m_Message;

    public ITreeNode Parent { get; set; }
    List<ITreeNode> Children { get; private set; }
    bool IsOpen { get; set; }
    string DisplayString { get { return m_Message; } }

    public TreeNode(string message)
    {
        m_Message = message;
    }

    public void AddChild(ITreeNode node)
    {
        if (Children == null)
        {
            Children = new List<ITreeNode>();
        }

        node.Parent = this;
        Children.Add(node);
    }

    public void Dispose()
    {
        if (Children = null)
        {
            return;
        }

        foreach (ITreeNode node in Children)
        {
            node.Dispose();
        }

        Children.Clear();
        Children = null;
    }
}

窗口

public class TestWindow : EditorWindow
{
    [MenuItem("Tools/Test")]
    public static void OpenWindow()
    {
        GetWindow<TestWindow>();
    }

    private static float s_LineHeight = 20;
    private static float s_Indentation = 20;
    private static float s_CharacterWidth = 20;

    private TreeNode m_Root;

    private void OnEnable()
    {
        m_Root = new TreeNode("Root");
        m_Root.AddChild(new TreeNode("Child1"));
        m_Root.AddChild(new TreeNode("Child2"));
        var child3 = new TreeNode("Child3");
        m_Root.AddChild(child3);
        child3.AddChild(new TreeNode("Child3-1"));
    }

    private void OnGUI()
    {
        if (m_Root == null)
        {
            return;
        }

        int depth = 0;
        int index = 0;
        DrawNode(m_Root, ref depth, ref index);        
    }

    private void DrawNode(ITreeNode node, ref int depth, ref int index)
    {
        string content = node.DisplayString;
        Rect rect = new Rect(s_Indentation * depth, s_LineHeight * index, content.Length * s_CharacterWidth, s_LineHeight);
        node.IsOpen = EditorGUI.Foldout(rect, node.IsOpen, content, true);
        index++;

        if (node.IsOpen && node.Children != null)
        {
            depth++;
            foreach(ITreeNode child in node.Children)
            {
                DrawNode(child, ref depth, ref index);
            }
            depth--;
        }
    }
}

不显示多余的折叠箭头

最简单的方法是改用Button

public class TestWindow : EditorWindow
{
    // ...
    private GUIStyle m_NormalStyle;
    private GUIStyle m_FoldoutStyle;

    private void OnEnable()
    {
        //...
        m_FoldoutStyle = new GUIStyle("Foldout");
        m_NormalStyle = new GUIStyle();
        m_NormalStyle.normal.background = null;
        m_NormalStyle.normal.textColor = m_FoldoutStyle.normal.textColor;
    }

    private void DrawNode(ITreeNode node, ref int depth, ref int index)
    {
        //...

        // node.IsOpen = EditorGUI.Foldout(rect, node.IsOpen, content, true);
        bool isOpen = node.IsOpen;
        GUIStyle style = node.Children == null ? m_NormalStyle : m_FoldoutStyle;
        if (GUI.Button(rect, content, style))
        {
            node.IsOpen = !isOpen;
            node.OnClick();
        }

        //...
    }
}
原文地址:https://www.cnblogs.com/lunoctis/p/12579984.html