Last active
April 26, 2024 11:33
-
-
Save SolarianZ/d7572ff6047dccabe58f861022fb0b53 to your computer and use it in GitHub Desktop.
{"category": "Unity Engine/Editor/Extensions", "keywords": "Unity, Editor, UI, Odin, Foldout, Collapse, List, Element"} Odin extenssion for foldout elements in list.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Odin extension for foldout elements in list. | |
// Example: | |
// [Serializable] | |
// public class MyData1 : IFoldoutableInList | |
// { | |
// // members... | |
// } | |
// [Serializable] | |
// public class MyData2 : IForceFoldoutableInList | |
// { | |
// // members... | |
// } | |
// public class Test : MonoBehaviour | |
// { | |
// [ElementFoldoutable] | |
// public List<MyData1> dataList1 = new List<MyData1>(); | |
// public List<MyData2> dataList2 = new List<MyData2>(); | |
// } | |
using System; | |
using System.Collections; | |
using System.Diagnostics; | |
using Sirenix.OdinInspector.Editor; | |
using UnityEditor; | |
using UnityEngine; | |
// Put the following classes to the runtime folder | |
public interface IFoldoutableInList { } // Work with ElementFoldoutableAttribute | |
public interface IForceFoldoutableInList : IFoldoutableInList { } // No need to use ElementFoldoutableAttribute | |
[Conditional("UNITY_EDITOR")] | |
public class ElementFoldoutableAttribute : Attribute { } // Work with IFoldoutableInList | |
// Put the following class to the editor folder | |
public class FoldoutableListElementDrawer : OdinValueDrawer<IFoldoutableInList> // use OdinValueDrawer<object> for all types | |
{ | |
protected override void DrawPropertyLayout(GUIContent label) | |
{ | |
if (!(Property.Parent.ValueEntry.WeakSmartValue is IList)) | |
{ | |
CallNextDrawer(label); | |
return; | |
} | |
string propertyLabel = null; | |
foreach (InspectorProperty child in Property.Children) | |
{ | |
if (child.Info.TypeOfValue == typeof(string)) | |
{ | |
string childValue = child.ValueEntry.WeakSmartValue?.ToString(); | |
if (!string.IsNullOrEmpty(childValue)) | |
{ | |
propertyLabel = childValue; | |
} | |
break; | |
} | |
} | |
propertyLabel ??= $"Element {Property.Index}"; | |
Property.State.Expanded = EditorGUILayout.Foldout(Property.State.Expanded, propertyLabel); | |
if (!Property.State.Expanded) | |
{ | |
return; | |
} | |
using (new EditorGUI.IndentLevelScope()) | |
{ | |
CallNextDrawer(label); | |
} | |
} | |
protected override bool CanDrawValueProperty(InspectorProperty property) | |
{ | |
if (typeof(IForceFoldoutableInList).IsAssignableFrom(property.Info.TypeOfValue)) | |
{ | |
return true && base.CanDrawValueProperty(property); | |
} | |
foreach (Attribute attribute in property.Attributes) | |
{ | |
if (attribute is ElementFoldoutableAttribute) | |
{ | |
return true && base.CanDrawValueProperty(property); | |
} | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is a simpler way to achieve foldoutable list elements:
Sirenix.OdinInspector.ListDrawerSettingsAttribute
to the list and assign values to theShowIndexLabel
andListElementLabelName
parameters.ListElementLabelName
parameter (in this example, the name is "_comment").