1.9.2: Added OpenPropertyEditor and fixed some issues regarding using multiple drawers with EditorGUI.PropertyField
- Property: `OpenPropertyEditor` adds a "show"-button next to a `ScriptableObject` or `Component` to open a property window - Property: Fixed issue, where x PropertyDrawers would invoke each other x times
This commit is contained in:
parent
f609ba6f51
commit
c87dd743f6
|
|
@ -1,4 +1,5 @@
|
||||||
using Module.Inspector.Editor.Utilities;
|
using System;
|
||||||
|
using Module.Inspector.Editor.Utilities;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -8,79 +9,107 @@ namespace Module.Inspector.Editor
|
||||||
{
|
{
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
{
|
{
|
||||||
EditorPropertyUtility.Result result = EditorPropertyUtility.Query(fieldInfo);
|
EditorPropertyUtility.Result result = null;
|
||||||
EAccessType accessType = GetAccessType(property, result);
|
int propertyHash = EditorPropertyUtility.CalculateHash(property);
|
||||||
|
bool isRootDrawer = false;
|
||||||
if (accessType == EAccessType.Hidden)
|
|
||||||
return;
|
try
|
||||||
|
|
||||||
bool prevEnabled = GUI.enabled;
|
|
||||||
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
|
||||||
|
|
||||||
if (Event.current.type == EventType.Repaint)
|
|
||||||
{
|
{
|
||||||
for (var i = 0; i < result.handleDrawers.Count; i++)
|
result = EditorPropertyUtility.Query(fieldInfo);
|
||||||
|
EAccessType accessType = GetAccessType(property, result);
|
||||||
|
|
||||||
|
if (accessType == EAccessType.Hidden)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result.IsUsedBy(propertyHash))
|
||||||
{
|
{
|
||||||
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value = result.handleDrawers[i];
|
EditorGUI.PropertyField(position, property, label);
|
||||||
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
label.tooltip = result.tooltip;
|
isRootDrawer = true;
|
||||||
|
result.AddUsedBy(propertyHash);
|
||||||
for (var i = 0; i < result.predrawerModifiers.Count; i++)
|
bool prevEnabled = GUI.enabled;
|
||||||
{
|
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
||||||
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
|
|
||||||
value.drawer.Modify(value.attribute, property, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
var isValid = true;
|
if (Event.current.type == EventType.Repaint)
|
||||||
var validationError = string.Empty;
|
{
|
||||||
|
for (var i = 0; i < result.handleDrawers.Count; i++)
|
||||||
|
{
|
||||||
|
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value =
|
||||||
|
result.handleDrawers[i];
|
||||||
|
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < result.validators.Count; i++)
|
label.tooltip = result.tooltip;
|
||||||
{
|
|
||||||
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value = result.validators[i];
|
|
||||||
|
|
||||||
if (value.drawer.Validate(value.attribute, property))
|
for (var i = 0; i < result.predrawerModifiers.Count; i++)
|
||||||
continue;
|
{
|
||||||
|
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute,
|
||||||
|
PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
|
||||||
|
value.drawer.Modify(value.attribute, property, label);
|
||||||
|
}
|
||||||
|
|
||||||
validationError += value.drawer.GetValidationError(value.attribute, property);
|
var isValid = true;
|
||||||
isValid = false;
|
var validationError = string.Empty;
|
||||||
}
|
|
||||||
|
|
||||||
Color prevColor = GUI.color;
|
|
||||||
|
|
||||||
if (!isValid)
|
for (var i = 0; i < result.validators.Count; i++)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(label.tooltip))
|
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value =
|
||||||
label.tooltip = validationError;
|
result.validators[i];
|
||||||
|
|
||||||
|
if (value.drawer.Validate(value.attribute, property))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
validationError += value.drawer.GetValidationError(value.attribute, property);
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color prevColor = GUI.color;
|
||||||
|
|
||||||
|
if (!isValid)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(label.tooltip))
|
||||||
|
label.tooltip = validationError;
|
||||||
|
else
|
||||||
|
label.tooltip += "\n" + validationError;
|
||||||
|
|
||||||
|
EditorIcons.SetErrorIcon(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.draw != null)
|
||||||
|
{
|
||||||
|
if (!result.draw.drawer.Draw(position, result.draw.attribute, property, label, result))
|
||||||
|
{
|
||||||
|
GUI.color = Color.red;
|
||||||
|
var errorContent = new GUIContent(result.draw.drawer.GetErrorMessage(property));
|
||||||
|
EditorGUI.LabelField(position, label, errorContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
label.tooltip += "\n" + validationError;
|
|
||||||
|
|
||||||
EditorIcons.SetErrorIcon(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.draw != null)
|
|
||||||
{
|
|
||||||
if (!result.draw.drawer.Draw(position, result.draw.attribute, property, label, result))
|
|
||||||
{
|
{
|
||||||
GUI.color = Color.red;
|
EditorGUI.PropertyField(position, property, label, true);
|
||||||
var errorContent = new GUIContent(result.draw.drawer.GetErrorMessage(property));
|
}
|
||||||
EditorGUI.LabelField(position, label, errorContent);
|
|
||||||
|
GUI.color = prevColor;
|
||||||
|
GUI.enabled = prevEnabled;
|
||||||
|
|
||||||
|
for (var i = 0; i < result.valueModifiers.Count; i++)
|
||||||
|
{
|
||||||
|
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>
|
||||||
|
value = result.valueModifiers[i];
|
||||||
|
value.drawer.Modify(value.attribute, property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception)
|
||||||
{
|
{
|
||||||
EditorGUI.PropertyField(position, property, label, true);
|
// Ignore
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
GUI.color = prevColor;
|
|
||||||
GUI.enabled = prevEnabled;
|
|
||||||
|
|
||||||
for (var i = 0; i < result.valueModifiers.Count; i++)
|
|
||||||
{
|
{
|
||||||
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer> value = result.valueModifiers[i];
|
if (isRootDrawer && result != null)
|
||||||
value.drawer.Modify(value.attribute, property);
|
result.RemoveUsedBy(propertyHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,10 +126,11 @@ namespace Module.Inspector.Editor
|
||||||
return EAccessType.Enabled;
|
return EAccessType.Enabled;
|
||||||
|
|
||||||
EAccessType accessType = 0;
|
EAccessType accessType = 0;
|
||||||
|
|
||||||
for (var i = 0; i < result.accessModifiers.Count; i++)
|
for (var i = 0; i < result.accessModifiers.Count; i++)
|
||||||
{
|
{
|
||||||
EditorPropertyUtility.ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer> value = result.accessModifiers[i];
|
EditorPropertyUtility.ResultValue<AccessModifierPropertyAttribute, AccessModifierPropertyDrawer> value =
|
||||||
|
result.accessModifiers[i];
|
||||||
accessType = value.drawer.GetAccessType(value.attribute, property, accessType);
|
accessType = value.drawer.GetAccessType(value.attribute, property, accessType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
49
Editor/Drawers/OpenPropertyEditorAttributeDrawer.cs
Normal file
49
Editor/Drawers/OpenPropertyEditorAttributeDrawer.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
using Module.Inspector.Editor.Utilities;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Module.Inspector.Editor
|
||||||
|
{
|
||||||
|
[CustomPropertyDrawer(typeof(OpenPropertyEditorAttribute))]
|
||||||
|
internal sealed class OpenPropertyEditorAttributeDrawer : DrawerPropertyDrawer
|
||||||
|
{
|
||||||
|
public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result)
|
||||||
|
{
|
||||||
|
if (!IsSupported(property))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EditorGUI.BeginProperty(position, label, property);
|
||||||
|
{
|
||||||
|
const float WIDTH = 50;
|
||||||
|
|
||||||
|
var rect0 = new Rect(position.x, position.y, position.width - WIDTH, position.height);
|
||||||
|
var rect1 = new Rect(rect0.xMax, position.y, WIDTH, position.height);
|
||||||
|
EditorGUI.PropertyField(rect0, property, label);
|
||||||
|
|
||||||
|
var prevValue = GUI.enabled;
|
||||||
|
GUI.enabled = prevValue && property.objectReferenceValue != null;
|
||||||
|
|
||||||
|
if (GUI.Button(rect1, "Show"))
|
||||||
|
EditorUtility.OpenPropertyEditor(property.objectReferenceValue);
|
||||||
|
|
||||||
|
GUI.enabled = prevValue;
|
||||||
|
}
|
||||||
|
EditorGUI.EndProperty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetErrorMessage(SerializedProperty property)
|
||||||
|
{
|
||||||
|
return IsSupported(property)
|
||||||
|
? "Unknown error"
|
||||||
|
: "Only supports types which inherits from ScriptableObject/Component type";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSupported(SerializedProperty property)
|
||||||
|
{
|
||||||
|
return property.propertyType == SerializedPropertyType.ObjectReference &&
|
||||||
|
(typeof(ScriptableObject).IsAssignableFrom(property.GetValueType()) ||
|
||||||
|
typeof(Component).IsAssignableFrom(property.GetValueType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Editor/Drawers/OpenPropertyEditorAttributeDrawer.cs.meta
Normal file
3
Editor/Drawers/OpenPropertyEditorAttributeDrawer.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5fbf47456b2f487aa93a36acf40ad59b
|
||||||
|
timeCreated: 1710067726
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Module.Inspector.Editor.Utilities
|
namespace Module.Inspector.Editor.Utilities
|
||||||
|
|
@ -64,6 +65,11 @@ namespace Module.Inspector.Editor.Utilities
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int CalculateHash(SerializedProperty property)
|
||||||
|
{
|
||||||
|
return property.propertyPath.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
private static Result InternalFetchProperties(FieldInfo fieldInfo)
|
private static Result InternalFetchProperties(FieldInfo fieldInfo)
|
||||||
{
|
{
|
||||||
ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> drawer = null;
|
ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> drawer = null;
|
||||||
|
|
@ -192,7 +198,8 @@ namespace Module.Inspector.Editor.Utilities
|
||||||
public readonly List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>> handleDrawers;
|
public readonly List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>> handleDrawers;
|
||||||
public readonly string tooltip;
|
public readonly string tooltip;
|
||||||
public readonly bool isObsolete;
|
public readonly bool isObsolete;
|
||||||
|
private List<int> usedBy = new List<int>();
|
||||||
|
|
||||||
public Result(ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> draw,
|
public Result(ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> draw,
|
||||||
List<ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer>> predrawerModifiers,
|
List<ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer>> predrawerModifiers,
|
||||||
List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers,
|
List<ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>> valueModifiers,
|
||||||
|
|
@ -212,6 +219,21 @@ namespace Module.Inspector.Editor.Utilities
|
||||||
this.isObsolete = isObsolete;
|
this.isObsolete = isObsolete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsUsedBy(int propertyHash)
|
||||||
|
{
|
||||||
|
return usedBy.Contains(propertyHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddUsedBy(int propertyHash)
|
||||||
|
{
|
||||||
|
usedBy.Add(propertyHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUsedBy(int propertyHash)
|
||||||
|
{
|
||||||
|
usedBy.Remove(propertyHash);
|
||||||
|
}
|
||||||
|
|
||||||
public T GetPredrawerModifier<T>() where T : PredrawerModifierPropertyAttribute
|
public T GetPredrawerModifier<T>() where T : PredrawerModifierPropertyAttribute
|
||||||
{
|
{
|
||||||
for (var i = 0; i < predrawerModifiers.Count; i++)
|
for (var i = 0; i < predrawerModifiers.Count; i++)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ List of all available drawer attributes:
|
||||||
* `IntToAnimatorParameter`
|
* `IntToAnimatorParameter`
|
||||||
* Adds popup with all animator parameter names provided by animator field and converts to hash id
|
* Adds popup with all animator parameter names provided by animator field and converts to hash id
|
||||||
* `IntToEnum`
|
* `IntToEnum`
|
||||||
* Adds a popup with enum type provided and converts it to an integer
|
* Adds a popup with enum type provided and converts it to an integer
|
||||||
* `IntToLayer`
|
* `IntToLayer`
|
||||||
* Adds a popup with a single layer selection and converts it to an integer
|
* Adds a popup with a single layer selection and converts it to an integer
|
||||||
* `IntToLayerMask`
|
* `IntToLayerMask`
|
||||||
|
|
@ -93,6 +93,9 @@ List of all available drawer attributes:
|
||||||
* `Naming`
|
* `Naming`
|
||||||
* Adds button to apply naming scheme to string value
|
* Adds button to apply naming scheme to string value
|
||||||
* Types: Camel, Pascal, Snake, Snake (All caps), Kebab, Kebab (All caps)
|
* Types: Camel, Pascal, Snake, Snake (All caps), Kebab, Kebab (All caps)
|
||||||
|
* `OpenPropertyEditor`
|
||||||
|
* Adds a button to open a property window, if object reference is not null and either a `ScriptableObject` or `Component`
|
||||||
|
* _Note: `OpenPropertyEditor` and `ReadableScriptableObject` currently doesn't support each other_
|
||||||
* `Percentage`
|
* `Percentage`
|
||||||
* Convert float value to percentage and back again (1% = 0.01f)
|
* Convert float value to percentage and back again (1% = 0.01f)
|
||||||
* `PopupFromConst`
|
* `PopupFromConst`
|
||||||
|
|
|
||||||
16
Runtime/Drawers/OpenPropertyEditorAttribute.cs
Normal file
16
Runtime/Drawers/OpenPropertyEditorAttribute.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#if UNITY_2019_3_OR_NEWER
|
||||||
|
using System;
|
||||||
|
using UnityEngine.Scripting;
|
||||||
|
|
||||||
|
namespace Module.Inspector
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class OpenPropertyEditorAttribute : DrawerPropertyAttribute
|
||||||
|
{
|
||||||
|
[Preserve]
|
||||||
|
public OpenPropertyEditorAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
3
Runtime/Drawers/OpenPropertyEditorAttribute.cs.meta
Normal file
3
Runtime/Drawers/OpenPropertyEditorAttribute.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d28d8d7fb04e4318989ef8e27fcb71ee
|
||||||
|
timeCreated: 1710067651
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "com.module.inspector",
|
"name": "com.module.inspector",
|
||||||
"version": "1.9.1",
|
"version": "1.9.2",
|
||||||
"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