Have you made any useful utilities with Odin?
Login and submit your creations hereAttribute that displays list elements as string, and when selected that element is drawn fully below list.
You can provide method that returns string to customize element string to your needs.
Gist version is easier and faster to modify, so use it as it may have newer version than here
ListAsStringAttribute.cs
using System;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class ListAsStringAttribute : Attribute
{
public string StringAction;
public ListAsStringAttribute(string action = null)
{
StringAction = action;
}
}
ListAsStringAttributeDrawer.cs
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector.Editor.ValueResolvers;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using UnityEditor;
using UnityEngine;
using NamedValue = Sirenix.OdinInspector.Editor.ValueResolvers.NamedValue;
// Based on ListItemSelector
// https://www.odininspector.com/community-tools/561/listitemselector-attribute-easily-select-items-in-lists
[DrawerPriority(10)]
public class ListAsStringAttributeDrawer : OdinAttributeDrawer<ListAsStringAttribute>
{
private static readonly Color SELECTED_COLOR = new Color(0.301f, 0.563f, 1f, 0.4f);
private bool m_isListElement;
private PropertyContext<InspectorProperty> m_globalSelectedProperty;
private InspectorProperty m_selectedProperty;
private PropertyContext<bool> m_drawingSelected;
private ValueResolver<string> m_stringResolver;
protected override void Initialize()
{
m_isListElement = Property.Parent != null && Property.Parent.ChildResolver is IOrderedCollectionResolver;
var listProperty = !m_isListElement ? Property : Property.Parent;
var baseMemberProperty = listProperty.FindParent(x =>
x.Info.PropertyType == PropertyType.Value, true);
m_globalSelectedProperty =
baseMemberProperty.Context.GetGlobal("SelectedProperty" + baseMemberProperty.GetHashCode(),
(InspectorProperty) null);
m_drawingSelected =
baseMemberProperty.Context.GetGlobal("DrawingSelected" + baseMemberProperty.GetHashCode(),
false);
if (!m_drawingSelected.Value && Attribute.StringAction != null)
m_stringResolver = ValueResolver.Get<string>(Property, Attribute.StringAction,
new NamedValue("index", typeof(int), 0));
}
protected override void DrawPropertyLayout(GUIContent label)
{
var eventType = Event.current.type;
if (m_isListElement)
{
var isSelected = m_globalSelectedProperty.Value == Property;
if (isSelected && m_drawingSelected.Value)
{
SirenixEditorGUI.BeginBox("Selected");
CallNextDrawer(label);
SirenixEditorGUI.EndBox();
}
else
{
Property.PushDraw();
if (eventType != EventType.Layout)
{
var rect = GUIHelper.GetCurrentLayoutRect();
switch (eventType)
{
case EventType.Repaint when isSelected:
EditorGUI.DrawRect(rect, SELECTED_COLOR);
break;
case EventType.MouseDown when rect.Contains(Event.current.mousePosition):
{
if (Property != m_globalSelectedProperty.Value)
{
m_globalSelectedProperty.Value = Property;
}
break;
}
}
}
Property.AnimateVisibility = false;
m_stringResolver?.Context.NamedValues.Set("index", Property.Index);
var str = m_stringResolver?.GetValue();
if (m_stringResolver != null && m_stringResolver.HasError)
m_stringResolver.DrawError();
// Copied from DisplayAsString
if (str == null)
str = Property.ValueEntry.WeakSmartValue?.ToString() ?? "Null";
if (label == null)
EditorGUILayout.LabelField(str, SirenixGUIStyles.MultiLineLabel,
GUILayoutOptions.MinWidth(0.0f));
else
{
GUIContent content = GUIHelper.TempContent(str);
GUI.Label(EditorGUI.PrefixLabel(EditorGUILayout.GetControlRect(false,
SirenixGUIStyles.MultiLineLabel.CalcHeight(content,
Property.LastDrawnValueRect.width - GUIHelper.BetterLabelWidth),
GUILayoutOptions.MinWidth(0.0f)), label), content,
SirenixGUIStyles.MultiLineLabel);
}
Property.PopDraw();
}
}
else
{
CallNextDrawer(label);
if (Event.current.type != EventType.Layout)
{
var sel = m_globalSelectedProperty.Value;
// Select
if (sel != null && sel != m_selectedProperty)
{
m_selectedProperty = sel;
Select();
}
// Deselect when destroyed or not expanded
else if (!Property.State.Expanded || m_selectedProperty != null &&
(m_selectedProperty.Index < Property.Children.Count &&
m_selectedProperty != Property.Children[m_selectedProperty.Index] ||
m_selectedProperty.Index >= Property.Children.Count))
{
Select();
m_selectedProperty = null;
m_globalSelectedProperty.Value = null;
}
}
if (Property.State.Expanded && m_globalSelectedProperty.Value != null)
{
m_drawingSelected.Value = true;
m_globalSelectedProperty.Value.Draw(null);
m_drawingSelected.Value = false;
}
}
}
private void Select()
{
GUIHelper.RequestRepaint();
}
}