文章目录
- 1 说明
- 2 重要特性
- 2.1 AssetsOnly / SceneObjectsOnly
- 2.2 CustomValueDrawer
- 2.3 OnValueChanged
- 2.4 DetailedInfoBox
- 2.5 EnableGUI
- 2.6 GUIColor
- 2.7 HideLabel
- 2.8 PropertyOrder
- 2.9 PropertySpace
- 2.10 ReadOnly
- 2.11 Required
- 2.12 RequiredIn(*)
- 2.13 Searchable
- 2.14 ShowInInspector
- 2.15 Title
- 2.16 TypeFilter
- 2.17 TypeInfoBox
- 2.18 ValidateInput
- 2.19 ValueDropdown
1 说明
本章介绍 Odin Inspector 插件中重要特性的使用方法。
2 重要特性
2.1 AssetsOnly / SceneObjectsOnly
使目标对象在 Inspector 窗口中只能关联资源 / 场景对象,限制拖拽的资源类型。
// SceneAndAssetsOnlyExamplesComponent.csusing Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;public class SceneAndAssetsOnlyExamplesComponent : MonoBehaviour
{[Title("Assets only")][AssetsOnly]public List<GameObject> OnlyPrefabs;[AssetsOnly]public GameObject SomePrefab;[AssetsOnly]public Material MaterialAsset;[AssetsOnly]public MeshRenderer SomeMeshRendererOnPrefab;[Title("Scene Objects only")][SceneObjectsOnly]public List<GameObject> OnlySceneObjects;[SceneObjectsOnly]public GameObject SomeSceneObject;[SceneObjectsOnly]public MeshRenderer SomeMeshRenderer;
}
2.2 CustomValueDrawer
自定义属性的显示方式。
string action
显示属性的方法名。
- action 方法中写 GUI 的显示逻辑,并返回字段的值。
- 该特性应用于数组时,将对数组的每个元素应用一次。
- 使用该特性时,需要配合 UNITY_EDITOR 指令,用法如下。
// CustomValueDrawerExamplesComponent.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;
using UnityEditor;
#endifpublic class CustomValueDrawerExamplesComponent : MonoBehaviour
{public float From = 2, To = 7;[CustomValueDrawer("MyCustomDrawerStatic")]public float CustomDrawerStatic;[CustomValueDrawer("MyCustomDrawerInstance")]public float CustomDrawerInstance;[CustomValueDrawer("MyCustomDrawerAppendRange")]public float AppendRange;[CustomValueDrawer("MyCustomDrawerArrayNoLabel")]public float[] CustomDrawerArrayNoLabel = new float[] { 3f, 5f, 6f };#if UNITY_EDITOR // Editor-related code must be excluded from buildsprivate static float MyCustomDrawerStatic(float value, GUIContent label) {return EditorGUILayout.Slider(label, value, 0f, 10f);}private float MyCustomDrawerInstance(float value, GUIContent label) {return EditorGUILayout.Slider(label, value, this.From, this.To);}private float MyCustomDrawerAppendRange(float value, GUIContent label, Func<GUIContent, bool> callNextDrawer) {SirenixEditorGUI.BeginBox();callNextDrawer(label);var result = EditorGUILayout.Slider(value, this.From, this.To);SirenixEditorGUI.EndBox();return result;}private float MyCustomDrawerArrayNoLabel(float value) {return EditorGUILayout.Slider(value, this.From, this.To);}
#endif
}
2.3 OnValueChanged
在检查器中编辑属性时,延迟对属性应用更改。更改值时,不会应用(黄色显示)。仅更改完成后,才会应用该值。
类似于 Unity 的内置延迟属性,但此特性也可以应用于属性。
// DelayedPropertyExampleComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class DelayedPropertyExampleComponent : MonoBehaviour
{// Delayed and DelayedProperty attributes are virtually identical...[Delayed][OnValueChanged("OnValueChanged")]public int DelayedField;// ... but the DelayedProperty can, as the name suggests, also be applied to properties.[ShowInInspector, DelayedProperty][OnValueChanged("OnValueChanged")]public string DelayedProperty { get; set; }private void OnValueChanged() {Debug.Log("Value changed!");}
}
2.4 DetailedInfoBox
为属性设置消息盒。
string message
默认显示的信息。
string details
点击后展开显示的详细信息。
InfoMessageType infoMessageType = InfoMessageType.Info
消息盒种类。
string visibleIf = null
如果表达式为 true,则显示,否则不显示。
// DetailedInfoBoxExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class DetailedInfoBoxExampleComponent : MonoBehaviour
{[DetailedInfoBox("Click the DetailedInfoBox...","... to reveal more information!\n" +"This allows you to reduce unnecessary clutter in your editors, and still have all the relavant information available when required.")]public int Field;
}
2.5 EnableGUI
激活 GUI 交互,使得能够在 Inspector 窗口进行编辑。
// EnableGUIExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class EnableGUIExampleComponent : MonoBehaviour
{[ShowInInspector]public int GUIDisabledProperty { get { return 10; } }[ShowInInspector, EnableGUI]public int GUIEnabledProperty { get { return 10; } }
}
2.6 GUIColor
为 GUI 上色。
float r, float g, float b, float a = 1f
使用 RGBA 指定颜色。
string getColor
指定颜色名。
// GUIColorExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class GUIColorExamplesComponent : MonoBehaviour
{[GUIColor(0.3f, 0.8f, 0.8f, 1f)]public int ColoredInt1;[GUIColor(0.3f, 0.8f, 0.8f, 1f)]public int ColoredInt2;[GUIColor("#FF0000")]public int Hex1;[GUIColor("#FF000077")]public int Hex2;[GUIColor("RGB(0, 1, 0)")]public int Rgb;[GUIColor("RGBA(0, 1, 0, 0.5)")]public int Rgba;[GUIColor("orange")]public int NamedColors;[ButtonGroup][GUIColor(0, 1, 0)]private void Apply() { }[ButtonGroup][GUIColor(1, 0.6f, 0.4f)]private void Cancel() { }[InfoBox("You can also reference a color member to dynamically change the color of a property.")][GUIColor("GetButtonColor")][Button("I Am Fabulous", ButtonSizes.Gigantic)]private static void IAmFabulous() { }[Button(ButtonSizes.Large)][GUIColor("@Color.Lerp(Color.red, Color.green, Mathf.Abs(Mathf.Sin((float)EditorApplication.timeSinceStartup)))")]private static void Expressive() { }#if UNITY_EDITOR // Editor-related code must be excluded from buildsprivate static Color GetButtonColor() {Sirenix.Utilities.Editor.GUIHelper.RequestRepaint();return Color.HSVToRGB(Mathf.Cos((float)UnityEditor.EditorApplication.timeSinceStartup + 1f) * 0.225f + 0.325f, 1, 1);}
#endif
}
2.7 HideLabel
隐藏属性名。
// HideLabelExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class HideLabelExamplesComponent : MonoBehaviour
{[Title("Wide Colors")][HideLabel][ColorPalette("Fall")]public Color WideColor1;[HideLabel][ColorPalette("Fall")]public Color WideColor2;[Title("Wide Vector")][HideLabel]public Vector3 WideVector1;[HideLabel]public Vector4 WideVector2;[Title("Wide String")][HideLabel]public string WideString;[Title("Wide Multiline Text Field")][HideLabel][MultiLineProperty]public string WideMultilineTextField = "";
}
2.8 PropertyOrder
指定属性显示的顺序。
float order
显示顺序,从小到大排列。
// PropertyOrderExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class PropertyOrderExamplesComponent : MonoBehaviour
{[PropertyOrder(1)]public int Second;[InfoBox("PropertyOrder is used to change the order of properties in the inspector.")][PropertyOrder(-1)]public int First;
}
2.9 PropertySpace
指定属性显示的间距。
float spaceBefore
上间距。
float spaceAfter
下间距。
// SpaceExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class SpaceExampleComponent : MonoBehaviour
{// PropertySpace and Space attributes are virtually identical.[Space][BoxGroup("Space", ShowLabel = false)]public int Space;// You can also control spacing both before and after the PropertySpace attribute.[PropertySpace(SpaceBefore = 30, SpaceAfter = 60)][BoxGroup("BeforeAndAfter", ShowLabel = false)]public int BeforeAndAfter;// The PropertySpace attribute can, as the name suggests, also be applied to properties.[PropertySpace][ShowInInspector, BoxGroup("Property", ShowLabel = false)]public string Property { get; set; }
}
2.10 ReadOnly
只在 Inspector 窗口显示,而不能改变值。
// ReadOnlyExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class ReadOnlyExamplesComponent : MonoBehaviour
{[ReadOnly]public string MyString = "This is displayed as text";[ReadOnly]public int MyInt = 9001;[ReadOnly]public int[] MyIntList = new int[] { 1, 2, 3, 4, 5, 6, 7, };
}
2.11 Required
如果对象没有关联值,则显示信息。
string errorMessage
显示信息。
InfoMessageType messageType
信息类型。
// RequiredExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class RequiredExamplesComponent : MonoBehaviour
{[Required]public GameObject MyGameObject;[Required("Custom error message.")]public Rigidbody MyRigidbody;[InfoBox("Use $ to indicate a member string as message.")][Required("$DynamicMessage")]public GameObject GameObject;public string DynamicMessage = "Dynamic error message";
}
2.12 RequiredIn(*)
说实话,看了半天没看懂。。。
// RequiredInAttributeExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;public class RequiredInAttributeExamplesComponent : MonoBehaviour
{[RequiredIn(PrefabKind.InstanceInScene, ErrorMessage = "Error messages can be customized. Odin expressions is supported.")]public string InstanceInScene = "Instances of prefabs in scenes";[RequiredIn(PrefabKind.InstanceInPrefab)]public string InstanceInPrefab = "Instances of prefabs nested inside other prefabs";[RequiredIn(PrefabKind.Regular)]public string Regular = "Regular prefab assets";[RequiredIn(PrefabKind.Variant)]public string Variant = "Prefab variant assets";[RequiredIn(PrefabKind.NonPrefabInstance)]public string NonPrefabInstance = "Non-prefab component or gameobject instances in scenes";[RequiredIn(PrefabKind.PrefabInstance)]public string PrefabInstance = "Instances of regular prefabs, and prefab variants in scenes or nested in other prefabs";[RequiredIn(PrefabKind.PrefabAsset)]public string PrefabAsset = "Prefab assets and prefab variant assets";[RequiredIn(PrefabKind.PrefabInstanceAndNonPrefabInstance)]public string PrefabInstanceAndNonPrefabInstance = "Prefab Instances, as well as non-prefab instances";
}
2.13 Searchable
可查询 chiledren 的类型和名称。
bool FuzzySearch = true
是否使用模糊字符串匹配进行搜索。
SearchFilterOptions FilterOptions = SearchFilterOptions.All
搜索方式。
bool Recursive = true
是递归搜索,还是只搜索顶级属性。
// SearchablePerksExampleComponent.csusing Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;public class SearchablePerksExampleComponent : MonoBehaviour
{[Searchable]public List<Perk> Perks = new List<Perk>() {new Perk() {Name = "Old Sage",Effects = new List<Effect>() {new Effect() { Skill = Skill.Wisdom, Value = 2, },new Effect() { Skill = Skill.Intelligence, Value = 1, },new Effect() { Skill = Skill.Strength, Value = -2 },},},new Perk() {Name = "Hardened Criminal",Effects = new List<Effect>() {new Effect() { Skill = Skill.Dexterity, Value = 2, },new Effect() { Skill = Skill.Strength, Value = 1, },new Effect() { Skill = Skill.Charisma, Value = -2 },},},new Perk() {Name = "Born Leader",Effects = new List<Effect>() {new Effect() { Skill = Skill.Charisma, Value = 2, },new Effect() { Skill = Skill.Intelligence, Value = -3 },},},new Perk() {Name = "Village Idiot",Effects = new List<Effect>() {new Effect() { Skill = Skill.Charisma, Value = 4, },new Effect() { Skill = Skill.Constitution, Value = 2, },new Effect() { Skill = Skill.Intelligence, Value = -3 },new Effect() { Skill = Skill.Wisdom, Value = -3 },},},};[Serializable]public class Perk{public string Name;[TableList]public List<Effect> Effects;}[Serializable]public class Effect{public Skill Skill;public float Value;}public enum Skill{Strength,Dexterity,Constitution,Intelligence,Wisdom,Charisma,}
}
2.14 ShowInInspector
在 Inspector 窗口中显示任意成员。
注意:
ShowInInspector 不会序列化成员,仅使用该特性不会保存任何改动。
// ShowPropertiesInTheInspectorExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class ShowPropertiesInTheInspectorExamplesComponent : MonoBehaviour
{[SerializeField, HideInInspector]private int evenNumber;[ShowInInspector]public int EvenNumber {get { return this.evenNumber; }set { this.evenNumber = value - (value % 2); }}
}
2.15 Title
在属性上方显示标题。
string title
标题名。
string subtitle = null
副标题。
TitleAlignments titleAlignment = TitleAlignments.Left
对齐方式。
bool horizontalLine = true
是否显示水平线。
bool bold = true
标题是否加粗显示。
// TitleExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;public class TitleExamplesComponent : MonoBehaviour
{[Title("Titles and Headers")]public string MyTitle = "My Dynamic Title";public string MySubtitle = "My Dynamic Subtitle";[Title("Static title")]public int C;public int D;[Title("Static title", "Static subtitle")]public int E;public int F;[Title("$MyTitle", "$MySubtitle")]public int G;public int H;[Title("Non bold title", "$MySubtitle", bold: false)]public int I;public int J;[Title("Non bold title", "With no line seperator", horizontalLine: false, bold: false)]public int K;public int L;[Title("$MyTitle", "$MySubtitle", TitleAlignments.Right)]public int M;public int N;[Title("$MyTitle", "$MySubtitle", TitleAlignments.Centered)]public int O;public int P;[Title("@DateTime.Now.ToString(\"dd:MM:yyyy\")", "@DateTime.Now.ToString(\"HH:mm:ss\")")]public int Expression;[ShowInInspector][Title("Title on a Property")]public int S { get; set; }[Title("Title on a Method")][Button]public void DoNothing() { }
}
2.16 TypeFilter
依据类型显示属性。
string filterGetter
获取显示属性的方法。
// TypeFilterExamplesComponent.cs
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;public class TypeFilterExamplesComponent : SerializedMonoBehaviour
{[TypeFilter("GetFilteredTypeList")]public BaseClass A, B;[TypeFilter("GetFilteredTypeList")]public BaseClass[] Array = new BaseClass[3];public IEnumerable<Type> GetFilteredTypeList(){var q = typeof(BaseClass).Assembly.GetTypes().Where(x => !x.IsAbstract) // Excludes BaseClass.Where(x => !x.IsGenericTypeDefinition) // Excludes C1<>.Where(x => typeof(BaseClass).IsAssignableFrom(x)); // Excludes classes not inheriting from BaseClass// Adds various C1<T> type variants.q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(GameObject)));q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(AnimationCurve)));q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(List<float>)));return q;}public abstract class BaseClass{public int BaseField;}public class A1 : BaseClass { public int _A1; }public class A2 : A1 { public int _A2; }public class A3 : A2 { public int _A3; }public class B1 : BaseClass { public int _B1; }public class B2 : B1 { public int _B2; }public class B3 : B2 { public int _B3; }public class C1<T> : BaseClass { public T C; }
}
2.17 TypeInfoBox
在类型的每个示例顶部绘制一个信息框。
string message
绘制的信息。
// TypeInfoBoxExampleComponent.csusing Sirenix.OdinInspector;
using System;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class TypeInfoBoxExampleComponent : MonoBehaviour
{public MyType MyObject = new MyType();#if UNITY_EDITOR // MyScriptyScriptableObject is an example type and only exists in the editor[InfoBox("Click the pen icon to open a new inspector for the Scripty object.")][InlineEditor]public MyScriptyScriptableObject Scripty;
#endif[Serializable][TypeInfoBox("The TypeInfoBox attribute can be put on type definitions and will result in an InfoBox being drawn at the top of a property.")]public class MyType{public int Value;}#if UNITY_EDITOR // Editor-related code must be excluded from builds[OnInspectorInit]private void CreateData() {Scripty = ExampleHelper.GetScriptableObject<MyScriptyScriptableObject>("Scripty");}[OnInspectorDispose]private void CleanupData() {if (Scripty != null) UnityEngine.Object.DestroyImmediate(Scripty);}
#endif
}
2.18 ValidateInput
允许检查 Inspector 窗口中拖拽关联值是否正确。
string condition
判断是否正确的方法。
string defaultMessage
显示信息。
InfoMessageType messageType
信息类型。
// ValidateInputExamplesComponent.csusing Sirenix.OdinInspector;
using UnityEngine;#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endifpublic class ValidateInputExamplesComponent : MonoBehaviour
{
#if UNITY_EDITOR // MyScriptyScriptableObject is an example type and only exists in the editor[HideLabel][Title("Default message", "You can just provide a default message that is always used")][ValidateInput("MustBeNull", "This field should be null.")]public MyScriptyScriptableObject DefaultMessage;
#endif[Space(12), HideLabel][Title("Dynamic message", "Or the validation method can dynamically provide a custom message")][ValidateInput("HasMeshRendererDynamicMessage", "Prefab must have a MeshRenderer component")]public GameObject DynamicMessage;[Space(12), HideLabel][Title("Dynamic message type", "The validation method can also control the type of the message")][ValidateInput("HasMeshRendererDynamicMessageAndType", "Prefab must have a MeshRenderer component")]public GameObject DynamicMessageAndType;[Space(8), HideLabel][InfoBox("Change GameObject value to update message type", InfoMessageType.None)]public InfoMessageType MessageType;[Space(12), HideLabel][Title("Dynamic default message", "Use $ to indicate a member string as default message")][ValidateInput("AlwaysFalse", "$Message", InfoMessageType.Warning)]public string Message = "Dynamic ValidateInput message";#if UNITY_EDITOR // Editor-related code must be excluded from buildsprivate bool AlwaysFalse(string value) {return false;}private bool MustBeNull(MyScriptyScriptableObject scripty) {return scripty == null;}private bool HasMeshRendererDefaultMessage(GameObject gameObject) {if (gameObject == null) return true;return gameObject.GetComponentInChildren<MeshRenderer>() != null;}private bool HasMeshRendererDynamicMessage(GameObject gameObject, ref string errorMessage) {if (gameObject == null) return true;if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {// If errorMessage is left as null, the default error message from the attribute will be usederrorMessage = "\"" + gameObject.name + "\" must have a MeshRenderer component";return false;}return true;}private bool HasMeshRendererDynamicMessageAndType(GameObject gameObject, ref string errorMessage, ref InfoMessageType? messageType) {if (gameObject == null) return true;if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {// If errorMessage is left as null, the default error message from the attribute will be usederrorMessage = "\"" + gameObject.name + "\" should have a MeshRenderer component";// If messageType is left as null, the default message type from the attribute will be usedmessageType = this.MessageType;return false;}return true;}
#endif
}
2.19 ValueDropdown
创建下拉列表,以供在 Inspector 面板上选择对应的值。
string valuesGetter
获取下拉列表可选值的方法。返回值可以是数组,或者 ValueDropdownList<T> 的 IEnumerable。
ValueDropdownList 的成员为 ValueDropdownItem,其成员 Text 为显示在 Inspector 窗口上对应值 Value 的信息。
bool AppendNextDrawer = false
如果为 true,则改为用小按钮开启下拉列表,而不是用宽按钮。
bool DisableGUIInAppendedDrawer = false
是否可以在 Inspector 窗口上编辑值。
bool ExpandAllMenuItems = false
如果为 true,则下拉菜单呈现树状图,用 ‘/’ 号表示父子关系。
bool DrawDropdownForListElements = true
如果对象为列表,则需禁用此属性,以正常显示子元素。
bool IsUniqueList = false
对象为列表时,其内容是否唯一,不可重复。
bool ExcludeExistingValuesInList = false
如果对象为列表,且 IsUniqueList 为 true,则启用此属性将排除现有值;
否则,将显示一个复选框,指示该项是否已包含。
// ValueDropdownExamplesComponent.csusing Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;public class ValueDropdownExamplesComponent : MonoBehaviour
{[ValueDropdown("TextureSizes")]public int SomeSize1;[ValueDropdown("FriendlyTextureSizes")]public int SomeSize2;[ValueDropdown("FriendlyTextureSizes", AppendNextDrawer = true, DisableGUIInAppendedDrawer = true)]public int SomeSize3;[ValueDropdown("GetListOfMonoBehaviours", AppendNextDrawer = true)]public MonoBehaviour SomeMonoBehaviour;[ValueDropdown("KeyCodes")]public KeyCode FilteredEnum;[ValueDropdown("TreeViewOfInts", ExpandAllMenuItems = true)]public List<int> IntTreview = new List<int>() { 1, 2, 7 };[ValueDropdown("GetAllSceneObjects", IsUniqueList = true)]public List<GameObject> UniqueGameobjectList;[ValueDropdown("GetAllSceneObjects", IsUniqueList = true, DropdownTitle = "Select Scene Object", DrawDropdownForListElements = false, ExcludeExistingValuesInList = true)]public List<GameObject> UniqueGameobjectListMode2;#if UNITY_EDITOR // Editor-related code must be excluded from builds
#pragma warning disable // And these members are in fact being used, though the compiler cannot tell. Let's not have bothersome warnings.private IEnumerable TreeViewOfInts = new ValueDropdownList<int>() {{ "Node 1/Node 1.1", 1 },{ "Node 1/Node 1.2", 2 },{ "Node 2/Node 2.1", 3 },{ "Node 3/Node 3.1", 4 },{ "Node 3/Node 3.2", 5 },{ "Node 1/Node 3.1/Node 3.1.1", 6 },{ "Node 1/Node 3.1/Node 3.1.2", 7 },};private IEnumerable<MonoBehaviour> GetListOfMonoBehaviours() {return GameObject.FindObjectsOfType<MonoBehaviour>();}private static IEnumerable<KeyCode> KeyCodes = Enumerable.Range((int)KeyCode.Alpha0, 10).Cast<KeyCode>();private static IEnumerable GetAllSceneObjects() {Func<Transform, string> getPath = null;getPath = x => (x ? getPath(x.parent) + "/" + x.gameObject.name : "");return GameObject.FindObjectsOfType<GameObject>().Select(x => new ValueDropdownItem(getPath(x.transform), x));}private static IEnumerable GetAllScriptableObjects() {return UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject").Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x)).Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<ScriptableObject>(x)));}private static IEnumerable GetAllSirenixAssets() {var root = "Assets/Plugins/Sirenix/";return UnityEditor.AssetDatabase.GetAllAssetPaths().Where(x => x.StartsWith(root)).Select(x => x.Substring(root.Length)).Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(root + x)));}private static IEnumerable FriendlyTextureSizes = new ValueDropdownList<int>() {{ "Small", 256 },{ "Medium", 512 },{ "Large", 1024 },};private static int[] TextureSizes = new int[] { 256, 512, 1024 };
#endif
}