1.4.0: Added ReadableScriptableObjectAttribute and fixed an GUI.enable isssue
* Attribute: Added ReadableScriptableObjectAttribute to allow for inline editing of ScriptableObjects in the inspector * Attribute: Fixed issue, where root drawer wouldn't use existing value of GUI.enabled, when setting GUI.enabled state with new access value
This commit is contained in:
parent
05f04657c5
commit
ee7326c33a
8 changed files with 198 additions and 31 deletions
|
|
@ -15,7 +15,7 @@ namespace Module.Inspector.Editor
|
|||
return;
|
||||
|
||||
bool prevEnabled = GUI.enabled;
|
||||
GUI.enabled = accessType == EAccessType.Enabled;
|
||||
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
||||
|
||||
label.tooltip = result.tooltip;
|
||||
|
||||
|
|
|
|||
159
Editor/Drawers/ReadableScriptableObjectAttributeDrawer.cs
Normal file
159
Editor/Drawers/ReadableScriptableObjectAttributeDrawer.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
using Module.Inspector.Editor.Utilities;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Module.Inspector.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ReadableScriptableObjectAttribute))]
|
||||
internal sealed class ReadableScriptableObjectAttributeDrawer : DrawerPropertyDrawer
|
||||
{
|
||||
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
|
||||
{
|
||||
if (!IsSupported(property))
|
||||
return false;
|
||||
|
||||
var att = (ReadableScriptableObjectAttribute)attribute;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
{
|
||||
if (property.objectReferenceValue != null)
|
||||
{
|
||||
property.isExpanded = DrawFoldout(position, property, label);
|
||||
|
||||
if (property.isExpanded)
|
||||
DrawContent(position, property.objectReferenceValue, att.editable);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: Why not use EditorGUI.PropertyField?
|
||||
// The reason is that the foldout uses Toggle and ObjectField and if if we don't use
|
||||
// Label and ObjectField here, then ObjectField will be given a new control id when changing
|
||||
// objectReferenceValue from an existing object to null and back again. The new object will
|
||||
// not be set, due to null giving a new control id.
|
||||
var rectObj = new Rect
|
||||
{
|
||||
x = position.x + EditorGUIUtility.labelWidth + 2.0f,
|
||||
y = position.y,
|
||||
width = position.width - EditorGUIUtility.labelWidth - 2.0f,
|
||||
height = position.height
|
||||
};
|
||||
|
||||
GUI.Label(position, label);
|
||||
property.objectReferenceValue = EditorGUI.ObjectField(rectObj, property.objectReferenceValue, property.GetValueType(), false);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
bool hasChanged = EditorGUI.EndChangeCheck();
|
||||
|
||||
if (hasChanged)
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool DrawFoldout(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
// Note: Why not use EditorGUI.BeginFoldoutHeaderGroup?
|
||||
// FoldoutHeaderGroup doesn't support nesting, so any ScriptableObject with a field that uses
|
||||
// a FoldoutHeaderGroup will not be drawn, e.g. arrays.
|
||||
|
||||
const float FOLDOUT_OFFSET = 14.0f;
|
||||
const float FIELD_OFFSET = 16.0f;
|
||||
|
||||
position.x -= FOLDOUT_OFFSET;
|
||||
position.width += FOLDOUT_OFFSET;
|
||||
position.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
var rectObj = new Rect
|
||||
{
|
||||
x = position.x + EditorGUIUtility.labelWidth + FIELD_OFFSET,
|
||||
y = position.y,
|
||||
width = position.width - EditorGUIUtility.labelWidth - FIELD_OFFSET,
|
||||
height = position.height
|
||||
};
|
||||
|
||||
GUIStyle style = property.objectReferenceValue != null ? EditorStyles.foldoutHeader : EditorStyles.label;
|
||||
bool foldout = property.isExpanded;
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
GUI.Toggle(position, foldout, label, style);
|
||||
EditorGUI.ObjectField(rectObj, property.objectReferenceValue, property.GetValueType(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
property.objectReferenceValue = EditorGUI.ObjectField(rectObj, property.objectReferenceValue, property.GetValueType(), false);
|
||||
foldout = GUI.Toggle(position, foldout, label, style);
|
||||
}
|
||||
|
||||
return foldout;
|
||||
}
|
||||
|
||||
private static void DrawContent(Rect rect, Object obj, bool editable)
|
||||
{
|
||||
var serializedObject = new SerializedObject(obj);
|
||||
SerializedProperty it = serializedObject.GetIterator();
|
||||
|
||||
it.NextVisible(true);
|
||||
rect.y += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
{
|
||||
bool prevEnabled = GUI.enabled;
|
||||
GUI.enabled = prevEnabled && editable;
|
||||
|
||||
while (it.NextVisible(false))
|
||||
{
|
||||
rect.height = EditorGUI.GetPropertyHeight(it);
|
||||
EditorGUI.PropertyField(rect, it, new GUIContent(it.displayName), true);
|
||||
rect.y += rect.height;
|
||||
}
|
||||
|
||||
GUI.enabled = prevEnabled;
|
||||
}
|
||||
|
||||
bool hasChanged = EditorGUI.EndChangeCheck();
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
if (hasChanged)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public override string GetErrorMessage(SerializedProperty property)
|
||||
{
|
||||
return IsSupported(property)
|
||||
? "Unknown error"
|
||||
: "Only supports types which inherits from ScriptableObject type";
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.objectReferenceValue == null || !property.isExpanded)
|
||||
return base.GetPropertyHeight(property, label);
|
||||
|
||||
var so = new SerializedObject(property.objectReferenceValue);
|
||||
SerializedProperty it = so.GetIterator();
|
||||
var height = 0.0f;
|
||||
it.NextVisible(true);
|
||||
height += EditorGUI.GetPropertyHeight(it);
|
||||
|
||||
while (it.NextVisible(false))
|
||||
{
|
||||
height += EditorGUI.GetPropertyHeight(it);
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
private static bool IsSupported(SerializedProperty property)
|
||||
{
|
||||
return property.propertyType == SerializedPropertyType.ObjectReference &&
|
||||
typeof(ScriptableObject).IsAssignableFrom(property.GetValueType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 63160a5efc0643de9a3cb8058efb1038
|
||||
timeCreated: 1639910668
|
||||
|
|
@ -114,32 +114,8 @@ namespace Module.Inspector.Editor
|
|||
return false;
|
||||
if (typeof(Object).IsAssignableFrom(type))
|
||||
return false;
|
||||
if (type.IsGenericType)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string ConvertUnityTypeFullnameToCSharpFullname(string unityNaming)
|
||||
{
|
||||
if (string.IsNullOrEmpty(unityNaming))
|
||||
return string.Empty;
|
||||
|
||||
int index = unityNaming.LastIndexOf(' ');
|
||||
string str;
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
str = unityNaming.Substring(0, index).Trim();
|
||||
str += ", ";
|
||||
str += unityNaming.Substring(index).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
str = unityNaming;
|
||||
}
|
||||
|
||||
return str.Replace('/', '+');
|
||||
return !type.IsGenericType;
|
||||
}
|
||||
|
||||
private static string ConvertUnityTypeFullnameToCSharpName(string unityNaming)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue