187 lines
7.0 KiB
C#
187 lines
7.0 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Type = System.Type;
|
|
|
|
namespace ScriptableObjectArchitecture.Editor
|
|
{
|
|
[CustomPropertyDrawer(typeof(BaseReference), true)]
|
|
public sealed class BaseReferenceDrawer : PropertyDrawer
|
|
{
|
|
/// <summary>
|
|
/// Options to display in the popup to select constant or variable.
|
|
/// </summary>
|
|
private static readonly string[] popupOptions =
|
|
{
|
|
"Use Constant",
|
|
"Use Variable"
|
|
};
|
|
|
|
private const float MultilineThreshold = 20;
|
|
|
|
// Property Names
|
|
private const string VARIABLE_PROPERTY_NAME = "_variable";
|
|
private const string CONSTANT_VALUE_PROPERTY_NAME = "_constantValue";
|
|
private const string USE_CONSTANT_VALUE_PROPERTY_NAME = "_useConstant";
|
|
|
|
// Warnings
|
|
private const string COULD_NOT_FIND_VALUE_FIELD_WARNING_FORMAT =
|
|
"Could not find FieldInfo for [{0}] specific property drawer on type [{1}].";
|
|
|
|
private Type ValueType { get { return BaseReferenceHelper.GetValueType(fieldInfo); } }
|
|
private bool SupportsMultiLine { get { return SOArchitecture_EditorUtility.SupportsMultiLine(ValueType); } }
|
|
|
|
private SerializedProperty property;
|
|
private SerializedProperty useConstant;
|
|
private SerializedProperty constantValue;
|
|
private SerializedProperty variable;
|
|
|
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
// Get properties
|
|
this.property = property;
|
|
useConstant = property.FindPropertyRelative("_useConstant");
|
|
constantValue = property.FindPropertyRelative("_constantValue");
|
|
variable = property.FindPropertyRelative("_variable");
|
|
|
|
int oldIndent = ResetIndent();
|
|
|
|
Rect fieldRect = DrawLabel(position, property, label);
|
|
Rect valueRect = DrawField(position, fieldRect);
|
|
DrawValue(position, valueRect);
|
|
|
|
EndIndent(oldIndent);
|
|
|
|
property.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
private bool IsConstantValueMultiline(SerializedProperty property)
|
|
{
|
|
return GenericPropertyDrawer.GetHeight(property, ValueType) > MultilineThreshold;
|
|
}
|
|
private Rect DrawLabel(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
return EditorGUI.PrefixLabel(position, label);
|
|
}
|
|
private Rect DrawField(Rect position, Rect fieldRect)
|
|
{
|
|
Rect buttonRect = GetPopupButtonRect(fieldRect);
|
|
Rect valueRect = GetValueRect(fieldRect, buttonRect);
|
|
|
|
int result = DrawPopupButton(buttonRect, useConstant.boolValue ? 0 : 1);
|
|
useConstant.boolValue = result == 0;
|
|
|
|
return valueRect;
|
|
}
|
|
private void DrawValue(Rect position, Rect valueRect)
|
|
{
|
|
if (useConstant.boolValue)
|
|
{
|
|
DrawGenericPropertyField(position, valueRect);
|
|
}
|
|
else
|
|
{
|
|
EditorGUI.PropertyField(valueRect, variable, GUIContent.none);
|
|
}
|
|
}
|
|
private void DrawGenericPropertyField(Rect position, Rect valueRect)
|
|
{
|
|
if (IsConstantValueMultiline(constantValue))
|
|
{
|
|
using (new EditorGUI.IndentLevelScope())
|
|
{
|
|
position.y += EditorGUIUtility.singleLineHeight;
|
|
position.height = GenericPropertyDrawer.GetHeight(constantValue, ValueType);
|
|
|
|
GenericPropertyDrawer.DrawPropertyDrawer(position, constantValue, ValueType);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GenericPropertyDrawer.DrawPropertyDrawer(valueRect, constantValue, ValueType, false);
|
|
}
|
|
}
|
|
private Rect GetConstantMultilineRect(Rect position, Rect valueRect)
|
|
{
|
|
return new Rect(position.x, valueRect.y + EditorGUIUtility.singleLineHeight, position.width, GenericPropertyDrawer.GetHeight(constantValue, ValueType));
|
|
}
|
|
private Rect GetMultiLineFieldRect(Rect position)
|
|
{
|
|
return EditorGUI.IndentedRect(new Rect
|
|
{
|
|
position = new Vector2(position.x, position.y + EditorGUIUtility.singleLineHeight),
|
|
size = new Vector2(position.width, EditorGUI.GetPropertyHeight(constantValue) + EditorGUIUtility.singleLineHeight)
|
|
});
|
|
}
|
|
private bool ShouldDrawMultiLineField()
|
|
{
|
|
return useConstant.boolValue && SupportsMultiLine && EditorGUI.GetPropertyHeight(constantValue) > EditorGUIUtility.singleLineHeight;
|
|
}
|
|
private int ResetIndent()
|
|
{
|
|
// Store old indent level and set it to 0, the PrefixLabel takes care of it
|
|
int indent = EditorGUI.indentLevel;
|
|
EditorGUI.indentLevel = 0;
|
|
|
|
return indent;
|
|
}
|
|
private void EndIndent(int indent)
|
|
{
|
|
EditorGUI.indentLevel = indent;
|
|
}
|
|
private int DrawPopupButton(Rect rect, int value)
|
|
{
|
|
return EditorGUI.Popup(rect, value, popupOptions, Styles.PopupStyle);
|
|
}
|
|
private Rect GetValueRect(Rect fieldRect, Rect buttonRect)
|
|
{
|
|
Rect valueRect = new Rect(fieldRect);
|
|
valueRect.x += buttonRect.width;
|
|
valueRect.width -= buttonRect.width;
|
|
|
|
return valueRect;
|
|
}
|
|
private Rect GetPopupButtonRect(Rect fieldrect)
|
|
{
|
|
Rect buttonRect = new Rect(fieldrect);
|
|
buttonRect.yMin += Styles.PopupStyle.margin.top;
|
|
buttonRect.width = Styles.PopupStyle.fixedWidth + Styles.PopupStyle.margin.right;
|
|
buttonRect.height = Styles.PopupStyle.fixedHeight + Styles.PopupStyle.margin.top;
|
|
|
|
return buttonRect;
|
|
}
|
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
{
|
|
SerializedProperty useConstant = property.FindPropertyRelative(USE_CONSTANT_VALUE_PROPERTY_NAME);
|
|
SerializedProperty constantValue = property.FindPropertyRelative(CONSTANT_VALUE_PROPERTY_NAME);
|
|
|
|
if (useConstant.boolValue)
|
|
{
|
|
if (IsConstantValueMultiline(constantValue))
|
|
{
|
|
return GenericPropertyDrawer.GetHeight(constantValue, ValueType) + EditorGUIUtility.singleLineHeight;
|
|
}
|
|
else
|
|
{
|
|
return EditorGUIUtility.singleLineHeight;
|
|
}
|
|
}
|
|
|
|
return EditorGUIUtility.singleLineHeight;
|
|
}
|
|
|
|
static class Styles
|
|
{
|
|
static Styles()
|
|
{
|
|
PopupStyle = new GUIStyle(GUI.skin.GetStyle("PaneOptions"))
|
|
{
|
|
imagePosition = ImagePosition.ImageOnly,
|
|
};
|
|
}
|
|
|
|
public static GUIStyle PopupStyle { get; set; }
|
|
}
|
|
}
|
|
} |