文章目录
- 1 说明
- 2 集合相关特性
- 2.1 DictionaryDrawerSettings
- 2.2 ListDrawerSettings
- 2.3 TableColumnWidth
- 2.4 TableList
- 2.5 TableMatrix
1 说明
本文介绍 Odin Inspector 插件中集合(Dictionary、List)相关特性的使用方法。
2 集合相关特性
2.1 DictionaryDrawerSettings
自定义 Dictionary 在 Inspector 窗口中的显示样式。类需要继承 SerializedMonoBehaviour。
string KeyLabel = "Key"
显示的键标题名。
ValueLabel = "Value"
显示的值标题名。
DictionaryDisplayOptions DisplayMode
字典显示样式。
bool IsReadOnly = false
键是否只读(不是值)。
// DictionaryExamplesComponent.csusing Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class DictionaryExamplesComponent : SerializedMonoBehaviour
{[InfoBox("In order to serialize dictionaries, all we need to do is to inherit our class from SerializedMonoBehaviour.")]public Dictionary<int, Material> IntMaterialLookup;[DictionaryDrawerSettings(IsReadOnly = true)]public Dictionary<string, string> StringStringDictionary;[DictionaryDrawerSettings(KeyLabel = "Custom Key Name", ValueLabel = "Custom Value Label")]public Dictionary<SomeEnum, MyCustomType> CustomLabels = new Dictionary<SomeEnum, MyCustomType>() {{ SomeEnum.First, new MyCustomType() },{ SomeEnum.Second, new MyCustomType() },};[DictionaryDrawerSettings(DisplayMode = DictionaryDisplayOptions.ExpandedFoldout)]public Dictionary<string, List<int>> StringListDictionary = new Dictionary<string, List<int>>() {{ "Numbers", new List<int>() { 1, 2, 3, 4, } },};[DictionaryDrawerSettings(DisplayMode = DictionaryDisplayOptions.Foldout)]public Dictionary<SomeEnum, MyCustomType> EnumObjectLookup = new Dictionary<SomeEnum, MyCustomType>() {{ SomeEnum.Third, new MyCustomType() },{ SomeEnum.Fourth, new MyCustomType() },};[InlineProperty(LabelWidth = 90)]public struct MyCustomType{public int SomeMember;public GameObject SomePrefab;}public enum SomeEnum{First, Second, Third, Fourth, AndSoOn}#if UNITY_EDITOR // Editor-related code must be excluded from builds[OnInspectorInit]private void CreateData() {IntMaterialLookup = new Dictionary<int, Material>() {{ 1, ExampleHelper.GetMaterial() },{ 7, ExampleHelper.GetMaterial() },};StringStringDictionary = new Dictionary<string, string>() {{ "One", ExampleHelper.GetString() },{ "Seven", ExampleHelper.GetString() },};}
#endif
}
2.2 ListDrawerSettings
自定义 List 在 Inspector 窗口中的显示样式。
bool IsReadOnly = true
是否在 Inspector 窗口中只读。
int NumberOfItemsPerPage
列表每页的成员个数,超过该个数则会翻页。
bool ShowIndexLabels
是否显示列表每个 item 的下标。
string ListElementLabelName
指定每个列表元素内的成员名称。
bool DraggableItems
列表成员是否可以在 Inspector 窗口中通过拖拽改变顺序。
bool ShowFoldout = true
列表成员是否折叠显示。
bool ShowPaging = true
是否启用分页显示。
bool ShowItemCount = true
是否显示成员个数。
string OnBeginListElementGUI
在每个列表元素之前调用的方法。引用的成员必须具有对应名称的方法。返回类型为 void,参数为 int 类型,表示该成员在列表中的索引。
string OnEndListElementGUI
在每个列表元素之后调用的方法。引用的成员必须具有对应名称的方法。返回类型为 void,参数为 int 类型,表示该成员在列表中的索引。
string OnTitleBarGUI
使用此功能将自定义 GUI 注入列表的标题栏。
string CustomAddFunction
覆盖向列表中添加对象的默认行为。
如果引用的方法返回列表类型元素,则每个选定对象将调用一次。
如果引用的方法返回 void,则无论选择了多少对象,都只会被调用一次。
// ListExamplesComponent.csusing Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.Utilities.Editor;
#endifpublic class ListExamplesComponent : MonoBehaviour
{
#if UNITY_EDITOR // Editor-related code must be excluded from builds[PropertyOrder(int.MinValue), OnInspectorGUI]private void DrawIntroInfoBox() {// SirenixEditorGUI.InfoMessageBox("Out of the box, Odin significantly upgrades the drawing of lists and arrays in the inspector - across the board, without you ever lifting a finger.");}
#endif[Title("List Basics")]// [InfoBox("List elements can now be dragged around to reorder them and deleted individually, and lists have paging (try adding a lot of elements!). You can still drag many assets at once into lists from the project view - just drag them into the list itself and insert them where you want to add them.")]public List<float> FloatList;// [InfoBox("Applying a [Range] attribute to this list instead applies it to all of its float entries.")][Range(0, 1)]public float[] FloatRangeArray;// [InfoBox("Lists can be made read-only in different ways.")][ListDrawerSettings(IsReadOnly = true)]public int[] ReadOnlyArray1 = new int[] { 1, 2, 3 };[ReadOnly]public int[] ReadOnlyArray2 = new int[] { 1, 2, 3 };public SomeOtherStruct[] SomeStructList;[Title("Advanced List Customization")]// [InfoBox("Using [ListDrawerSettings], lists can be customized in a wide variety of ways.")][ListDrawerSettings(NumberOfItemsPerPage = 5)]public int[] FiveItemsPerPage;[ListDrawerSettings(ShowIndexLabels = true, ListElementLabelName = "SomeString")]public SomeStruct[] IndexLabels;[ListDrawerSettings(DraggableItems = false, ShowFoldout = false, ShowIndexLabels = true, ShowPaging = false, ShowItemCount = false,HideRemoveButton = true)]public int[] MoreListSettings = new int[] { 1, 2, 3 };[ListDrawerSettings(OnBeginListElementGUI = "BeginDrawListElement", OnEndListElementGUI = "EndDrawListElement")]public SomeStruct[] InjectListElementGUI;[ListDrawerSettings(OnTitleBarGUI = "DrawRefreshButton")]public List<int> CustomButtons;[ListDrawerSettings(CustomAddFunction = "CustomAddFunction")]public List<int> CustomAddBehaviour;[Serializable]public struct SomeStruct{public string SomeString;public int One;public int Two;public int Three;}[Serializable]public struct SomeOtherStruct{[HorizontalGroup("Split", 55), PropertyOrder(-1)][PreviewField(50, Sirenix.OdinInspector.ObjectFieldAlignment.Left), HideLabel]public UnityEngine.MonoBehaviour SomeObject;[FoldoutGroup("Split/$Name", false)]public int A, B, C;[FoldoutGroup("Split/$Name", false)]public int Two;[FoldoutGroup("Split/$Name", false)]public int Three;private string Name { get { return this.SomeObject ? this.SomeObject.name : "Null"; } }}#if UNITY_EDITOR // Editor-related code must be excluded from buildsprivate void BeginDrawListElement(int index) {SirenixEditorGUI.BeginBox(this.InjectListElementGUI[index].SomeString);}private void EndDrawListElement(int index) {SirenixEditorGUI.EndBox();}private void DrawRefreshButton() {if (SirenixEditorGUI.ToolbarButton(EditorIcons.Refresh)) {Debug.Log(this.CustomButtons.Count.ToString());}}private int CustomAddFunction() {Debug.Log("Custom add function called!");return this.CustomAddBehaviour.Count;}
#endif
}
2.3 TableColumnWidth
控制 List 成员显示在表格中显示的宽度。
int width
宽度。
bool resizable = true
宽度是否可通过拖拽调节。
// TableColumnWidthExampleComponent.csusing Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class TableColumnWidthExampleComponent : MonoBehaviour
{[TableList(ShowIndexLabels = true)]public List<MyItem> List = new List<MyItem>() {new MyItem(),new MyItem(),new MyItem(),};[Serializable]public class MyItem{[PreviewField(Height = 20)][TableColumnWidth(30, Resizable = false)]public Texture2D Icon;[TableColumnWidth(60)]public int ID;public string Name;#if UNITY_EDITOR // Editor-related code must be excluded from builds[OnInspectorInit]private void CreateData() { // 每次点击 Inspector 窗口时,更新 TextureIcon = ExampleHelper.GetTexture();}
#endif}
}
2.4 TableList
将 List 绘制成表格形状。
bool IsReadOnly = true
是否在 Inspector 窗口中只读。
int NumberOfItemsPerPage
列表每页的成员个数,超过该个数则会翻页。
bool ShowIndexLabels
是否显示列表每个 item 的下标。
bool ShowPaging = true
是否启用分页显示。
bool ShowItemCount = true
是否显示成员个数。
bool HideToolbar = false
是否隐藏标题栏。
bool DrawScrollView = true
是否绘制滚动条。
int MaxScrollViewHeight/MinScrollViewHeight
滚动条绘制的范围(最大高度/最小高度),单位:像素。
bool AlwaysExpanded
List 是否可折叠。
// TableListExamplesComponent.csusing Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class TableListExamplesComponent : MonoBehaviour
{[TableList(ShowIndexLabels = true)]public List<SomeCustomClass> TableListWithIndexLabels = new List<SomeCustomClass>() {new SomeCustomClass(),new SomeCustomClass(),};[TableList(DrawScrollView = true, MaxScrollViewHeight = 200, MinScrollViewHeight = 100)]public List<SomeCustomClass> MinMaxScrollViewTable = new List<SomeCustomClass>() {new SomeCustomClass(),new SomeCustomClass(),};[TableList(AlwaysExpanded = true, DrawScrollView = false)]public List<SomeCustomClass> AlwaysExpandedTable = new List<SomeCustomClass>() {new SomeCustomClass(),new SomeCustomClass(),};[TableList(ShowPaging = true, NumberOfItemsPerPage = 3)]public List<SomeCustomClass> TableWithPaging = new List<SomeCustomClass>() {new SomeCustomClass(),new SomeCustomClass(),};[Serializable]public class SomeCustomClass{[TableColumnWidth(57, Resizable = false)][PreviewField(Alignment = ObjectFieldAlignment.Center)]public Texture Icon;[TextArea]public string Description;[VerticalGroup("Combined Column"), LabelWidth(22)]public string A, B, C;[TableColumnWidth(60)][Button, VerticalGroup("Actions")]public void Test1() { }[TableColumnWidth(60)][Button, VerticalGroup("Actions")]public void Test2() { }#if UNITY_EDITOR // Editor-related code must be excluded from builds[OnInspectorInit]private void CreateData() {Description = ExampleHelper.GetString();Icon = ExampleHelper.GetTexture();}
#endif}
}
2.5 TableMatrix
绘制二维数组。
-
单元格绘制。
-
string HorizontalTitle
水平标题。
-
bool SquareCells
如果为 true,则每行的高度将与第一个单元格的宽度相同。
-
// TableMatrixExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class TableMatrixExamplesComponent : SerializedMonoBehaviour
{[TableMatrix(HorizontalTitle = "Square Celled Matrix", SquareCells = true)]public Texture2D[,] SquareCelledMatrix;[TableMatrix(SquareCells = true)]public Mesh[,] PrefabMatrix;#if UNITY_EDITOR // Editor-related code must be excluded from builds[OnInspectorInit]private void CreateData() {SquareCelledMatrix = new Texture2D[8, 4] {{ ExampleHelper.GetTexture(), null, null, null },{ null, ExampleHelper.GetTexture(), null, null },{ null, null, ExampleHelper.GetTexture(), null },{ null, null, null, ExampleHelper.GetTexture() },{ ExampleHelper.GetTexture(), null, null, null },{ null, ExampleHelper.GetTexture(), null, null },{ null, null, ExampleHelper.GetTexture(), null },{ null, null, null, ExampleHelper.GetTexture() },};PrefabMatrix = new Mesh[8, 4] {{ ExampleHelper.GetMesh(), null, null, null },{ null, ExampleHelper.GetMesh(), null, null },{ null, null, ExampleHelper.GetMesh(), null },{ null, null, null, ExampleHelper.GetMesh() },{ null, null, null, ExampleHelper.GetMesh() },{ null, null, ExampleHelper.GetMesh(), null },{ null, ExampleHelper.GetMesh(), null, null },{ ExampleHelper.GetMesh(), null, null, null },};}
#endif
}
-
表格绘制
-
bool IsReadOnly
如果为 true,则插入、删除和拖动列和行将不可用。但单元格本身仍将是可修改的。
如果要禁用所有内容,可以使用 ReadOnly 属性。
-
string VerticalTitle
垂直标题。
-
// TableMatrixTitleExampleComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class TableMatrixTitleExampleComponent : SerializedMonoBehaviour
{[TableMatrix(HorizontalTitle = "Read Only Matrix", IsReadOnly = true)]public int[,] ReadOnlyMatrix = new int[5, 5];[TableMatrix(HorizontalTitle = "X axis", VerticalTitle = "Y axis")]public InfoMessageType[,] LabledMatrix = new InfoMessageType[6, 6];
}
-
图形绘制
-
string DrawElementMethod
覆盖绘制每个单元格的方式。
输入参数:
Rect rect, T value
输出:
T
-
bool ResizableColumns = true
列是否可调整大小。
-
RowHeight
行高,0 表示默认高度。
-
bool Transpose
如果为 true,则表的行/列颠倒绘制(C# 初始化顺序)。
-
// TransposeTableMatrixExampleComponent.csusing Sirenix.OdinInspector;
using Sirenix.Utilities;
using UnityEngine;public class TransposeTableMatrixExampleComponent : SerializedMonoBehaviour
{[TableMatrix(HorizontalTitle = "Custom Cell Drawing", DrawElementMethod = nameof(DrawColoredEnumElement), ResizableColumns = false, RowHeight = 16)]public bool[,] CustomCellDrawing;[ShowInInspector, DoNotDrawAsReference][TableMatrix(HorizontalTitle = "Transposed Custom Cell Drawing", DrawElementMethod = "DrawColoredEnumElement", ResizableColumns = false, RowHeight = 16, Transpose = true)]public bool[,] Transposed { get { return CustomCellDrawing; } set { CustomCellDrawing = value; } }#if UNITY_EDITOR // Editor-related code must be excluded from buildsprivate static bool DrawColoredEnumElement(Rect rect, bool value) {if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) {value = !value;GUI.changed = true;Event.current.Use();}UnityEditor.EditorGUI.DrawRect(rect.Padding(1), value ? new Color(0.1f, 0.8f, 0.2f) : new Color(0, 0, 0, 0.5f));return value;}[OnInspectorInit]private void CreateData() {// =)this.CustomCellDrawing = new bool[15, 15];this.CustomCellDrawing[6, 5] = true;this.CustomCellDrawing[6, 6] = true;this.CustomCellDrawing[6, 7] = true;this.CustomCellDrawing[8, 5] = true;this.CustomCellDrawing[8, 6] = true;this.CustomCellDrawing[8, 7] = true;this.CustomCellDrawing[5, 9] = true;this.CustomCellDrawing[5, 10] = true;this.CustomCellDrawing[9, 9] = true;this.CustomCellDrawing[9, 10] = true;this.CustomCellDrawing[6, 11] = true;this.CustomCellDrawing[7, 11] = true;this.CustomCellDrawing[8, 11] = true;}
#endif
}