• Unity编辑器开发:官方风格的Table控件


    Unity编辑器开发:官方风格的Table控件

    Table控件能够非常直观地展现批量的数据。在Unity中,Light Explorer就是一个典型的具有Table控件的窗口。

    20170729_1

    如上图所示,窗口上方是4个TabButton。下面就是一个Table。这个Table功能非常强大,有列表,排序,筛选,实时同步数据更新,实时同步选择等功能。

    在Unity项目开发中,也常常需要做这种Table数据的展示或者类似的功能,比如简单的一个需求,找出当前场景中所有的Camra,并显示它的某些属性。用Table控件展示如下

    20170729_2

    这个是一个简单的窗口,满足上述的需求。这种官方风格的Table窗口不仅在功能上满足了需求,在外观上非常OK。

    在实现上,这种控件,其实是Unity提供的TreeView控件的扩展。Light Explorer中使用到了继承于TreeView的SerializedPropertyTreeView。但是非常遗憾的是,目前SerializedPropertyTreeView是internal的class,所以我们无法通过继承来实现。查看它的源码可以看到,有部分代码依赖了内部的类,或者这也是官方无法公开这个SerializedPropertyTreeView的原因。但是,如果去除掉一些无关紧要的功能,事实上是完全可以脱耦而独立出来。涉及到SerializedPropertyTable,SerializedPropertyTreeView,SerializedPropertyFilters以及SerializedPropertyDataStore这4个类。

    而在使用时,也较为简单,提供一个搜索方法,列信息即可。比如完成上面提到的显示相机的需求,可以用以下代码:

    首先定义一个窗口,实现从菜单打开

    public class ComponentFindWindow : EditorWindow
    {
            [MenuItem("Tools/Windows/ComponentFindWindow")]
            public static void Open()
            {
                GetWindow<ComponentFindWindow>();
            }

    }

    在ComponentFindWindow中增加一个SerializedPropertyTable声明,并进行绘制

    private SerializedPropertyTable m_table;

    public void OnGUI()
    {
        using (new EditorGUILayout.VerticalScope())
        {
            if (m_table != null)
            {
                m_table.OnGUI();
            }
        }
    }
    当然,这时候什么都不会发生,我们还要对m_table进行实例化

    public void OnEnable()
    {
        m_table = new SerializedPropertyTable("Table", FindObjects, CreateCameraColumn);
    }

    SerializedPropertyTable的构造函数有3个参数

    • 第一个是唯一的标签。用于表示这个TreeView序列号信息的ID
    • 第二个是显示内容的搜索函数。例如我们要显示所有的Camera,就要提供找到这个Camera的方法
    • 第三个是列信息。包括列名,长度,可拉伸的最大最小长度,对齐方式,是否可排序,列的绘制方法,排序方法,筛选方法等等

    这里FindObjects声明如下

    private Camera[] FindObjects()
    {
        return FindObjectsOfType<Camera>();
    }

    创建列方法CreateCameraColumn如下

    private SerializedPropertyTreeView.Column[] CreateCameraColumn(out string[] propnames)
    {
        propnames = new string[3];
        var columns = new SerializedPropertyTreeView.Column[3];
        columns[0] = new SerializedPropertyTreeView.Column
        {
            headerContent = new GUIContent("Name"),
            headerTextAlignment = TextAlignment.Left,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Center,
            width = 200,
            minWidth = 25f,
            maxWidth = 400,
            autoResize = false,
            allowToggleVisibility = true,
            propertyName = null,
            dependencyIndices = null,
            compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareName,
            drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawName,
            filter = new SerializedPropertyFilters.Name()
        };
        columns[1] = new SerializedPropertyTreeView.Column
        {
            headerContent = new GUIContent("On"),
            headerTextAlignment = TextAlignment.Left,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Center,
            width = 25,
            autoResize = false,
            allowToggleVisibility = true,
            propertyName = "m_Enabled",
            dependencyIndices = null,
            compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox,
            drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox,
        };

        columns[2] = new SerializedPropertyTreeView.Column
        {
            headerContent = new GUIContent("Mask"),
            headerTextAlignment = TextAlignment.Left,
            sortedAscending = true,
            sortingArrowAlignment = TextAlignment.Center,
            width = 200,
            minWidth = 25f,
            maxWidth = 400,
            autoResize = false,
            allowToggleVisibility = true,
            propertyName = "m_CullingMask",
            dependencyIndices = null,
            compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareInt,
            drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault,
            filter = new SerializedPropertyFilters.Name()
        };
        for (var i = 0; i < columns.Length; i++)
        {
            var column = columns[i];
            propnames[i] = column.propertyName;
        }

        return columns;
    }
    至此,就实现了所有功能。

    这个控件实用性非常高,非常希望Unity团队能够早日把这个控件公开。

    项目地址:https://github.com/CodeGize/UnityTable

    个人博客请访问:http://www.cnblogs.com/CodeGize/
  • 相关阅读:
    C++ FFLIB之FFXML: 极简化TinyXml 读取
    使用ffpython嵌入和扩展python
    Json 备忘录
    一位软件工程师的6年工作总结
    Sql Server 备忘录
    走出软件作坊
    asp.net 使用Jquery 调用WebService返回JSON 类型数据
    .NET 页面间传值的几种方法
    CKeditor安全使用
    新浪短信Web Service
  • 原文地址:https://www.cnblogs.com/CodeGize/p/7255738.html
Copyright © 2020-2023  润新知