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
|
|
@ -15,7 +15,7 @@ namespace Module.Inspector.Editor
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool prevEnabled = GUI.enabled;
|
bool prevEnabled = GUI.enabled;
|
||||||
GUI.enabled = accessType == EAccessType.Enabled;
|
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
||||||
|
|
||||||
label.tooltip = result.tooltip;
|
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;
|
return false;
|
||||||
if (typeof(Object).IsAssignableFrom(type))
|
if (typeof(Object).IsAssignableFrom(type))
|
||||||
return false;
|
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(' ');
|
return !type.IsGenericType;
|
||||||
string str;
|
|
||||||
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
str = unityNaming.Substring(0, index).Trim();
|
|
||||||
str += ", ";
|
|
||||||
str += unityNaming.Substring(index).Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
str = unityNaming;
|
|
||||||
}
|
|
||||||
|
|
||||||
return str.Replace('/', '+');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ConvertUnityTypeFullnameToCSharpName(string unityNaming)
|
private static string ConvertUnityTypeFullnameToCSharpName(string unityNaming)
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -91,8 +91,12 @@ List of all available drawer attributes:
|
||||||
* Adds popup with all const fields of type string in provided type
|
* Adds popup with all const fields of type string in provided type
|
||||||
* `QuaternionToEuler`
|
* `QuaternionToEuler`
|
||||||
* Converts quaternion value to Euler angles and back again
|
* Converts quaternion value to Euler angles and back again
|
||||||
|
* `ReadableScriptableObject`
|
||||||
|
* Creates an inline editor in the inspector window, so you can edit `ScriptableObjects` without finding the object first
|
||||||
* `SceneDropdown`
|
* `SceneDropdown`
|
||||||
* Adds a popup with all scenes in EditorBuildSettings scenes
|
* Adds a popup with all scenes in EditorBuildSettings scenes
|
||||||
|
* `SerializeReferenceTo`
|
||||||
|
* Adds a popup for `SerializeReference` fields with types inheriting from assigned type or field type
|
||||||
* `Slider`
|
* `Slider`
|
||||||
* Adds a min & max slider and clamps value (Requirement: MinValue and MaxValue)
|
* Adds a min & max slider and clamps value (Requirement: MinValue and MaxValue)
|
||||||
* `StringToAnimatorParameter`
|
* `StringToAnimatorParameter`
|
||||||
|
|
@ -105,8 +109,7 @@ List of all available drawer attributes:
|
||||||
* Adds popup with all tag values for field of type string
|
* Adds popup with all tag values for field of type string
|
||||||
* `UrlGoTo`
|
* `UrlGoTo`
|
||||||
* Adds a button to the field that calls Application.OpenUrl with string value
|
* Adds a button to the field that calls Application.OpenUrl with string value
|
||||||
* `SerializeReferenceTo`
|
|
||||||
* Adds a popup for `SerializeReference` fields with types inheriting from assigned type or field type
|
|
||||||
|
|
||||||
|
|
||||||
## Value
|
## Value
|
||||||
|
|
@ -115,6 +118,8 @@ List of all value attributes:
|
||||||
|
|
||||||
* `ArrayIndex`
|
* `ArrayIndex`
|
||||||
* Clamps value between other fields array size `[0;size[`
|
* Clamps value between other fields array size `[0;size[`
|
||||||
|
* `AssignIfNull`
|
||||||
|
* If value is null will either use field or custom type to get from self or children
|
||||||
* `LargerThanField`
|
* `LargerThanField`
|
||||||
* If value is greater than other fields value, then set value to other fields value
|
* If value is greater than other fields value, then set value to other fields value
|
||||||
* `MaxValue`
|
* `MaxValue`
|
||||||
|
|
@ -123,8 +128,7 @@ List of all value attributes:
|
||||||
* If value is less than min value, then set value to min value
|
* If value is less than min value, then set value to min value
|
||||||
* `SmallerThanField`
|
* `SmallerThanField`
|
||||||
* If value is less than other fields value, then set value to other fields value
|
* If value is less than other fields value, then set value to other fields value
|
||||||
* `AssignIfNull`
|
|
||||||
* If value is null will either use field or custom type to get from self or children
|
|
||||||
|
|
||||||
|
|
||||||
## Validate
|
## Validate
|
||||||
|
|
|
||||||
22
Runtime/Drawers/ReadableScriptableObjectAttribute.cs
Normal file
22
Runtime/Drawers/ReadableScriptableObjectAttribute.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#if UNITY_2019_3_OR_NEWER
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Module.Inspector
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class ReadableScriptableObjectAttribute : DrawerPropertyAttribute
|
||||||
|
{
|
||||||
|
public readonly bool editable;
|
||||||
|
|
||||||
|
public ReadableScriptableObjectAttribute()
|
||||||
|
{
|
||||||
|
editable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadableScriptableObjectAttribute(bool editable)
|
||||||
|
{
|
||||||
|
this.editable = editable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 319dfc0b017247d69fbe91575384ccf8
|
||||||
|
timeCreated: 1639910607
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "com.module.inspector",
|
"name": "com.module.inspector",
|
||||||
"version": "1.3.2",
|
"version": "1.4.0",
|
||||||
"displayName": "Module.Inspector",
|
"displayName": "Module.Inspector",
|
||||||
"description": "Custom inspector with various useful property drawers",
|
"description": "Custom inspector with various useful property drawers",
|
||||||
"unity": "2019.2",
|
"unity": "2019.2",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue