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 UnityEngine;
|
||||
|
||||
|
|
@ -8,79 +9,107 @@ namespace Module.Inspector.Editor
|
|||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorPropertyUtility.Result result = EditorPropertyUtility.Query(fieldInfo);
|
||||
EAccessType accessType = GetAccessType(property, result);
|
||||
EditorPropertyUtility.Result result = null;
|
||||
int propertyHash = EditorPropertyUtility.CalculateHash(property);
|
||||
bool isRootDrawer = false;
|
||||
|
||||
if (accessType == EAccessType.Hidden)
|
||||
return;
|
||||
|
||||
bool prevEnabled = GUI.enabled;
|
||||
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
try
|
||||
{
|
||||
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];
|
||||
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
|
||||
EditorGUI.PropertyField(position, property, label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
label.tooltip = result.tooltip;
|
||||
isRootDrawer = true;
|
||||
result.AddUsedBy(propertyHash);
|
||||
bool prevEnabled = GUI.enabled;
|
||||
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
|
||||
|
||||
for (var i = 0; i < result.predrawerModifiers.Count; i++)
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
|
||||
value.drawer.Modify(value.attribute, property, label);
|
||||
}
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
for (var i = 0; i < result.handleDrawers.Count; i++)
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value =
|
||||
result.handleDrawers[i];
|
||||
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
|
||||
}
|
||||
}
|
||||
|
||||
var isValid = true;
|
||||
var validationError = string.Empty;
|
||||
label.tooltip = result.tooltip;
|
||||
|
||||
for (var i = 0; i < result.validators.Count; i++)
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value = result.validators[i];
|
||||
for (var i = 0; i < result.predrawerModifiers.Count; i++)
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute,
|
||||
PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
|
||||
value.drawer.Modify(value.attribute, property, label);
|
||||
}
|
||||
|
||||
if (value.drawer.Validate(value.attribute, property))
|
||||
continue;
|
||||
var isValid = true;
|
||||
var validationError = string.Empty;
|
||||
|
||||
validationError += value.drawer.GetValidationError(value.attribute, property);
|
||||
isValid = false;
|
||||
}
|
||||
for (var i = 0; i < result.validators.Count; i++)
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value =
|
||||
result.validators[i];
|
||||
|
||||
Color prevColor = GUI.color;
|
||||
if (value.drawer.Validate(value.attribute, property))
|
||||
continue;
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(label.tooltip))
|
||||
label.tooltip = validationError;
|
||||
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
|
||||
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);
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
GUI.color = prevColor;
|
||||
GUI.enabled = prevEnabled;
|
||||
|
||||
for (var i = 0; i < result.valueModifiers.Count; i++)
|
||||
finally
|
||||
{
|
||||
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer> value = result.valueModifiers[i];
|
||||
value.drawer.Modify(value.attribute, property);
|
||||
if (isRootDrawer && result != null)
|
||||
result.RemoveUsedBy(propertyHash);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +129,8 @@ namespace Module.Inspector.Editor
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
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.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Module.Inspector.Editor.Utilities
|
||||
|
|
@ -64,6 +65,11 @@ namespace Module.Inspector.Editor.Utilities
|
|||
return result;
|
||||
}
|
||||
|
||||
public static int CalculateHash(SerializedProperty property)
|
||||
{
|
||||
return property.propertyPath.GetHashCode();
|
||||
}
|
||||
|
||||
private static Result InternalFetchProperties(FieldInfo fieldInfo)
|
||||
{
|
||||
ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> drawer = null;
|
||||
|
|
@ -192,6 +198,7 @@ namespace Module.Inspector.Editor.Utilities
|
|||
public readonly List<ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer>> handleDrawers;
|
||||
public readonly string tooltip;
|
||||
public readonly bool isObsolete;
|
||||
private List<int> usedBy = new List<int>();
|
||||
|
||||
public Result(ResultValue<DrawerPropertyAttribute, DrawerPropertyDrawer> draw,
|
||||
List<ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer>> predrawerModifiers,
|
||||
|
|
@ -212,6 +219,21 @@ namespace Module.Inspector.Editor.Utilities
|
|||
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
|
||||
{
|
||||
for (var i = 0; i < predrawerModifiers.Count; i++)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ List of all available drawer attributes:
|
|||
* `IntToAnimatorParameter`
|
||||
* Adds popup with all animator parameter names provided by animator field and converts to hash id
|
||||
* `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`
|
||||
* Adds a popup with a single layer selection and converts it to an integer
|
||||
* `IntToLayerMask`
|
||||
|
|
@ -93,6 +93,9 @@ List of all available drawer attributes:
|
|||
* `Naming`
|
||||
* Adds button to apply naming scheme to string value
|
||||
* 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`
|
||||
* Convert float value to percentage and back again (1% = 0.01f)
|
||||
* `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",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"displayName": "Module.Inspector",
|
||||
"description": "Custom inspector with various useful property drawers",
|
||||
"unity": "2019.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue