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:
Anders Ejlersen 2024-03-10 14:11:49 +01:00
parent f609ba6f51
commit c87dd743f6
8 changed files with 189 additions and 63 deletions

View file

@ -1,4 +1,5 @@
using Module.Inspector.Editor.Utilities;
using System;
using Module.Inspector.Editor.Utilities;
using UnityEditor;
using UnityEngine;
@ -8,12 +9,26 @@ namespace Module.Inspector.Editor
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorPropertyUtility.Result result = EditorPropertyUtility.Query(fieldInfo);
EditorPropertyUtility.Result result = null;
int propertyHash = EditorPropertyUtility.CalculateHash(property);
bool isRootDrawer = false;
try
{
result = EditorPropertyUtility.Query(fieldInfo);
EAccessType accessType = GetAccessType(property, result);
if (accessType == EAccessType.Hidden)
return;
if (result.IsUsedBy(propertyHash))
{
EditorGUI.PropertyField(position, property, label);
return;
}
isRootDrawer = true;
result.AddUsedBy(propertyHash);
bool prevEnabled = GUI.enabled;
GUI.enabled = prevEnabled && accessType == EAccessType.Enabled;
@ -21,7 +36,8 @@ namespace Module.Inspector.Editor
{
for (var i = 0; i < result.handleDrawers.Count; i++)
{
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value = result.handleDrawers[i];
EditorPropertyUtility.ResultValue<HandleDrawerPropertyAttribute, HandlePropertyDrawer> value =
result.handleDrawers[i];
HandleDrawerEditor.Add(value.attribute, property, value.drawer);
}
}
@ -30,7 +46,8 @@ namespace Module.Inspector.Editor
for (var i = 0; i < result.predrawerModifiers.Count; i++)
{
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute, PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
EditorPropertyUtility.ResultValue<PredrawerModifierPropertyAttribute,
PredrawerModifierPropertyDrawer> value = result.predrawerModifiers[i];
value.drawer.Modify(value.attribute, property, label);
}
@ -39,7 +56,8 @@ namespace Module.Inspector.Editor
for (var i = 0; i < result.validators.Count; i++)
{
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value = result.validators[i];
EditorPropertyUtility.ResultValue<ValidatePropertyAttribute, ValidatePropertyDrawer> value =
result.validators[i];
if (value.drawer.Validate(value.attribute, property))
continue;
@ -79,10 +97,21 @@ namespace Module.Inspector.Editor
for (var i = 0; i < result.valueModifiers.Count; i++)
{
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer> value = result.valueModifiers[i];
EditorPropertyUtility.ResultValue<ValueModifierPropertyAttribute, ValueModifierPropertyDrawer>
value = result.valueModifiers[i];
value.drawer.Modify(value.attribute, property);
}
}
catch (Exception)
{
// Ignore
}
finally
{
if (isRootDrawer && result != null)
result.RemoveUsedBy(propertyHash);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
@ -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);
}

View 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()));
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5fbf47456b2f487aa93a36acf40ad59b
timeCreated: 1710067726

View file

@ -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++)

View file

@ -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`

View 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

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d28d8d7fb04e4318989ef8e27fcb71ee
timeCreated: 1710067651

View file

@ -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",