98 lines
3.4 KiB
C#
98 lines
3.4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace Obi{
|
|
|
|
[System.AttributeUsage(System.AttributeTargets.Field)]
|
|
public abstract class MultiPropertyAttribute : PropertyAttribute
|
|
{
|
|
#if UNITY_EDITOR
|
|
public IOrderedEnumerable<object> stored = null;
|
|
|
|
public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
EditorGUI.PropertyField(position,property,label,true);
|
|
}
|
|
|
|
internal virtual void OnPreGUI(Rect position, SerializedProperty property){}
|
|
internal virtual void OnPostGUI(Rect position, SerializedProperty property){}
|
|
|
|
internal virtual bool IsVisible(SerializedProperty property){return true;}
|
|
internal virtual float? GetPropertyHeight( SerializedProperty property, GUIContent label){return null;}
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[CustomPropertyDrawer(typeof(MultiPropertyAttribute),true)]
|
|
public class MultiPropertyDrawer : PropertyDrawer
|
|
{
|
|
private MultiPropertyAttribute RetrieveAttributes()
|
|
{
|
|
MultiPropertyAttribute mAttribute = attribute as MultiPropertyAttribute;
|
|
|
|
// Get the attribute list, sorted by "order".
|
|
if (mAttribute.stored == null)
|
|
{
|
|
mAttribute.stored = fieldInfo.GetCustomAttributes(typeof(MultiPropertyAttribute), false).OrderBy(s => ((PropertyAttribute)s).order);
|
|
}
|
|
|
|
return mAttribute;
|
|
}
|
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
{
|
|
MultiPropertyAttribute mAttribute = RetrieveAttributes();
|
|
|
|
// If the attribute is invisible, regain the standard vertical spacing.
|
|
foreach (MultiPropertyAttribute attr in mAttribute.stored)
|
|
if (!attr.IsVisible(property))
|
|
return -EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
// In case no attribute returns a modified height, return the property's default one:
|
|
float height = EditorGUI.GetPropertyHeight(property, label, true);
|
|
//base.GetPropertyHeight(property, label);
|
|
|
|
// Check if any of the attributes wants to modify height:
|
|
foreach (object atr in mAttribute.stored)
|
|
{
|
|
if (atr as MultiPropertyAttribute != null)
|
|
{
|
|
var tempheight = ((MultiPropertyAttribute)atr).GetPropertyHeight(property, label);
|
|
if (tempheight.HasValue)
|
|
{
|
|
height = tempheight.Value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return height;
|
|
}
|
|
|
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
MultiPropertyAttribute mAttribute = RetrieveAttributes();
|
|
|
|
// Calls to IsVisible. If it returns false for any attribute, the property will not be rendered.
|
|
foreach (MultiPropertyAttribute attr in mAttribute.stored)
|
|
if (!attr.IsVisible(property)) return;
|
|
|
|
// Calls to OnPreRender before the last attribute draws the UI.
|
|
foreach (MultiPropertyAttribute attr in mAttribute.stored)
|
|
attr.OnPreGUI(position,property);
|
|
|
|
// The last attribute is in charge of actually drawing something:
|
|
((MultiPropertyAttribute)mAttribute.stored.Last()).OnGUI(position,property,label);
|
|
|
|
// Calls to OnPostRender after the last attribute draws the UI. These are called in inverse order.
|
|
foreach (MultiPropertyAttribute attr in mAttribute.stored.Reverse())
|
|
attr.OnPostGUI(position,property);
|
|
}
|
|
}
|
|
#endif
|
|
}
|