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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM