Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/#133 inspector lag #264

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
382 changes: 355 additions & 27 deletions Assets/NaughtyAttributes/Samples/DemoScene/DemoScene.unity

Large diffs are not rendered by default.

184 changes: 132 additions & 52 deletions Assets/NaughtyAttributes/Scripts/Editor/NaughtyInspector.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using UnityEditor;
using UnityEngine;

@@ -10,35 +11,80 @@ namespace NaughtyAttributes.Editor
[CustomEditor(typeof(UnityEngine.Object), true)]
public class NaughtyInspector : UnityEditor.Editor
{
private List<SerializedProperty> _serializedProperties = new List<SerializedProperty>();
private IEnumerable<FieldInfo> _nonSerializedFields;
private IEnumerable<PropertyInfo> _nativeProperties;
private IEnumerable<MethodInfo> _methods;
protected List<NaughtyProperty> _serializedProperties = new List<NaughtyProperty>();
protected List<FieldInfo> _nonSerializedFields;
protected List<PropertyInfo> _nativeProperties;
protected List<MethodInfo> _methods;

protected List<NaughtyProperty> _nonGroupedSerializedProperty;
protected SerializedProperty m_ScriptProperty;

protected List<IGrouping<string, NaughtyProperty>> _groupedSerialzedProperty;
protected List<IGrouping<string, NaughtyProperty>> _foldoutGroupedSerializedProperty;

private Dictionary<string, SavedBool> _foldouts = new Dictionary<string, SavedBool>();

private bool _anyNaughtyAttribute;

protected bool _useCachedMetaAttributes;
protected bool _changeDetected;

protected virtual void OnEnable()
{
_nonSerializedFields = ReflectionUtility.GetAllFields(
target, f => f.GetCustomAttributes(typeof(ShowNonSerializedFieldAttribute), true).Length > 0);

_nativeProperties = ReflectionUtility.GetAllProperties(
target, p => p.GetCustomAttributes(typeof(ShowNativePropertyAttribute), true).Length > 0);

_methods = ReflectionUtility.GetAllMethods(
target, m => m.GetCustomAttributes(typeof(ButtonAttribute), true).Length > 0);
this.Prepare();
}

protected virtual void OnDisable()
{
//cleanup memory
ReorderableListPropertyDrawer.Instance.ClearCache();

_nonSerializedFields.Clear();
_nativeProperties.Clear();
_methods.Clear();
_foldouts.Clear();

_foldoutGroupedSerializedProperty.Clear();
_groupedSerialzedProperty.Clear();
_nonGroupedSerializedProperty.Clear();
_serializedProperties.Clear();

m_ScriptProperty = default;
}

public override void OnInspectorGUI()
public virtual void Prepare()
{
_nonSerializedFields = ReflectionUtility.GetAllFields(
target, f => f.GetCustomAttributes(typeof(ShowNonSerializedFieldAttribute), true).Length > 0).ToList();

_nativeProperties = ReflectionUtility.GetAllProperties(
target, p => p.GetCustomAttributes(typeof(ShowNativePropertyAttribute), true).Length > 0).ToList();

_methods = ReflectionUtility.GetAllMethods(
target, m => m.GetCustomAttributes(typeof(ButtonAttribute), true).Length > 0).ToList();

GetSerializedProperties(ref _serializedProperties);

_anyNaughtyAttribute = _serializedProperties.Any(p => PropertyUtility.GetAttribute<INaughtyAttribute>(p.serializedProperty) != null);

_nonGroupedSerializedProperty = GetNonGroupedProperties(_serializedProperties).ToList();

//.First(...) doesnt work for some reason because the m_Script field isnt loaded yet I assume
NaughtyProperty[] mScripts = _serializedProperties.Where(p => p.serializedProperty.name.Equals("m_Script")).ToArray();
m_ScriptProperty = mScripts.Length > 0 ? mScripts[0].serializedProperty : null;

_groupedSerialzedProperty = GetGroupedProperties(_serializedProperties).ToList();

bool anyNaughtyAttribute = _serializedProperties.Any(p => PropertyUtility.GetAttribute<INaughtyAttribute>(p) != null);
if (!anyNaughtyAttribute)
_foldoutGroupedSerializedProperty = GetFoldoutProperties(_serializedProperties).ToList();

_useCachedMetaAttributes = false;
}

public override void OnInspectorGUI()
{
_changeDetected = false;

if (!_anyNaughtyAttribute)
{
DrawDefaultInspector();
}
@@ -50,90 +96,124 @@ public override void OnInspectorGUI()
DrawNonSerializedFields();
DrawNativeProperties();
DrawButtons();
}

protected void GetSerializedProperties(ref List<SerializedProperty> outSerializedProperties)
_useCachedMetaAttributes = !_changeDetected;
}

protected virtual void GetSerializedProperties(ref List<NaughtyProperty> outSerializedProperties)
{
outSerializedProperties.Clear();
outSerializedProperties.TrimExcess();

using (var iterator = serializedObject.GetIterator())
{
if (iterator.NextVisible(true))
{
do
{
outSerializedProperties.Add(serializedObject.FindProperty(iterator.name));
outSerializedProperties.Add(
PropertyUtility.CreateNaughtyProperty(
serializedObject.FindProperty(iterator.name)));
}
while (iterator.NextVisible(false));
}
}
}

protected void DrawSerializedProperties()
protected virtual void DrawSerializedProperties()
{
serializedObject.Update();

// Draw non-grouped serialized properties
foreach (var property in GetNonGroupedProperties(_serializedProperties))
if (m_ScriptProperty != null)
{
if (property.name.Equals("m_Script", System.StringComparison.Ordinal))
using (new EditorGUI.DisabledScope(disabled: true))
{
using (new EditorGUI.DisabledScope(disabled: true))
{
EditorGUILayout.PropertyField(property);
}
EditorGUILayout.PropertyField(m_ScriptProperty);
}
else
}

// Draw non-grouped serialized properties
foreach (var naughtyProperty in _nonGroupedSerializedProperty)
{
if (!_useCachedMetaAttributes)
{
NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
naughtyProperty.cachedIsVisible = PropertyUtility.IsVisible(naughtyProperty.showIfAttribute,
naughtyProperty.serializedProperty);

naughtyProperty.cachedIsEnabled = PropertyUtility.IsEnabled(naughtyProperty.readOnlyAttribute, naughtyProperty.enableIfAttribute,
naughtyProperty.serializedProperty);
}

_changeDetected |= NaughtyEditorGUI.PropertyField_Layout(naughtyProperty, includeChildren: true);
}

// Draw grouped serialized properties
foreach (var group in GetGroupedProperties(_serializedProperties))
foreach (var group in _groupedSerialzedProperty)
{
IEnumerable<SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
IEnumerable<NaughtyProperty> visibleProperties =
_useCachedMetaAttributes
? group.Where(p => p.cachedIsVisible)
: group.Where(p =>
{
p.cachedIsEnabled = PropertyUtility.IsEnabled(p.readOnlyAttribute, p.enableIfAttribute,
p.serializedProperty);

return p.cachedIsVisible =
PropertyUtility.IsVisible(p.showIfAttribute, p.serializedProperty);
});

if (!visibleProperties.Any())
{
continue;
}

NaughtyEditorGUI.BeginBoxGroup_Layout(group.Key);
foreach (var property in visibleProperties)
foreach (var naughtyProperty in visibleProperties)
{
NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
_changeDetected |= NaughtyEditorGUI.PropertyField_Layout(naughtyProperty, includeChildren: true);
}

NaughtyEditorGUI.EndBoxGroup_Layout();
}

// Draw foldout serialized properties
foreach (var group in GetFoldoutProperties(_serializedProperties))
foreach (var group in _foldoutGroupedSerializedProperty)
{
IEnumerable<SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
IEnumerable<NaughtyProperty> visibleProperties =
_useCachedMetaAttributes
? group.Where(p => p.cachedIsVisible)
: group.Where(p =>
{
p.cachedIsEnabled = PropertyUtility.IsEnabled(p.readOnlyAttribute, p.enableIfAttribute,
p.serializedProperty);

return p.cachedIsVisible =
PropertyUtility.IsVisible(p.showIfAttribute, p.serializedProperty);
});

if (!visibleProperties.Any())
{
continue;
}

if (!_foldouts.ContainsKey(group.Key))
{
_foldouts[group.Key] = new SavedBool($"{target.GetInstanceID()}.{group.Key}", false);
}

_foldouts[group.Key].Value = EditorGUILayout.Foldout(_foldouts[group.Key].Value, group.Key, true);
if (_foldouts[group.Key].Value)
{
foreach (var property in visibleProperties)
foreach (var naughtyProperty in visibleProperties)
{
NaughtyEditorGUI.PropertyField_Layout(property, true);
_changeDetected |= NaughtyEditorGUI.PropertyField_Layout(naughtyProperty, true);
}
}
}

serializedObject.ApplyModifiedProperties();
}

protected void DrawNonSerializedFields(bool drawHeader = false)
protected virtual void DrawNonSerializedFields(bool drawHeader = false)
{
if (_nonSerializedFields.Any())
{
@@ -152,7 +232,7 @@ protected void DrawNonSerializedFields(bool drawHeader = false)
}
}

protected void DrawNativeProperties(bool drawHeader = false)
protected virtual void DrawNativeProperties(bool drawHeader = false)
{
if (_nativeProperties.Any())
{
@@ -171,7 +251,7 @@ protected void DrawNativeProperties(bool drawHeader = false)
}
}

protected void DrawButtons(bool drawHeader = false)
protected virtual void DrawButtons(bool drawHeader = false)
{
if (_methods.Any())
{
@@ -190,23 +270,23 @@ protected void DrawButtons(bool drawHeader = false)
}
}

private static IEnumerable<SerializedProperty> GetNonGroupedProperties(IEnumerable<SerializedProperty> properties)
private static IEnumerable<NaughtyProperty> GetNonGroupedProperties(IEnumerable<NaughtyProperty> properties)
{
return properties.Where(p => PropertyUtility.GetAttribute<IGroupAttribute>(p) == null);
return properties.Where(p => PropertyUtility.GetAttribute<IGroupAttribute>(p.serializedProperty) == null && !p.serializedProperty.name.Equals("m_Script"));
}

private static IEnumerable<IGrouping<string, SerializedProperty>> GetGroupedProperties(IEnumerable<SerializedProperty> properties)
private static IEnumerable<IGrouping<string, NaughtyProperty>> GetGroupedProperties(IEnumerable<NaughtyProperty> properties)
{
return properties
.Where(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p) != null)
.GroupBy(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p).Name);
.Where(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p.serializedProperty) != null)
.GroupBy(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p.serializedProperty).Name);
}

private static IEnumerable<IGrouping<string, SerializedProperty>> GetFoldoutProperties(IEnumerable<SerializedProperty> properties)
private static IEnumerable<IGrouping<string, NaughtyProperty>> GetFoldoutProperties(IEnumerable<NaughtyProperty> properties)
{
return properties
.Where(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p) != null)
.GroupBy(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p).Name);
.Where(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p.serializedProperty) != null)
.GroupBy(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p.serializedProperty).Name);
}

private static GUIStyle GetHeaderGUIStyle()
21 changes: 21 additions & 0 deletions Assets/NaughtyAttributes/Scripts/Editor/NaughtyProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using UnityEditor;

namespace NaughtyAttributes.Editor
{
public class NaughtyProperty
{
public SerializedProperty serializedProperty;

public LabelAttribute labelAttribute;

public SpecialCaseDrawerAttribute specialCaseDrawerAttribute;

public ShowIfAttributeBase showIfAttribute;
public EnableIfAttributeBase enableIfAttribute;
public ReadOnlyAttribute readOnlyAttribute;
public ValidatorAttribute[] validatorAttributes;

public bool cachedIsVisible = true;
public bool cachedIsEnabled = true;
}
}
11 changes: 11 additions & 0 deletions Assets/NaughtyAttributes/Scripts/Editor/NaughtyProperty.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -9,12 +9,17 @@ namespace NaughtyAttributes.Editor
[CustomPropertyDrawer(typeof(AnimatorParamAttribute))]
public class AnimatorParamPropertyDrawer : PropertyDrawerBase
{
private AnimatorParamAttribute _cachedAnimatorParamAttribute;

private const string InvalidAnimatorControllerWarningMessage = "Target animator controller is null";
private const string InvalidTypeWarningMessage = "{0} must be an int or a string";

protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
{
AnimatorParamAttribute animatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);
if (_cachedAnimatorParamAttribute == null)
_cachedAnimatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);

AnimatorParamAttribute animatorParamAttribute = _cachedAnimatorParamAttribute;
bool validAnimatorController = GetAnimatorController(property, animatorParamAttribute.AnimatorName) != null;
bool validPropertyType = property.propertyType == SerializedPropertyType.Integer || property.propertyType == SerializedPropertyType.String;

@@ -27,7 +32,10 @@ protected override void OnGUI_Internal(Rect rect, SerializedProperty property, G
{
EditorGUI.BeginProperty(rect, label, property);

AnimatorParamAttribute animatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);
if (_cachedAnimatorParamAttribute == null)
_cachedAnimatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);

AnimatorParamAttribute animatorParamAttribute = _cachedAnimatorParamAttribute;

AnimatorController animatorController = GetAnimatorController(property, animatorParamAttribute.AnimatorName);
if (animatorController == null)
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@ namespace NaughtyAttributes.Editor
[CustomPropertyDrawer(typeof(CurveRangeAttribute))]
public class CurveRangePropertyDrawer : PropertyDrawerBase
{
private CurveRangeAttribute _cachedCurveRangeAttribute;

protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
{
float propertyHeight = property.propertyType == SerializedPropertyType.AnimationCurve
@@ -27,7 +29,10 @@ protected override void OnGUI_Internal(Rect rect, SerializedProperty property, G
return;
}

var attribute = PropertyUtility.GetAttribute<CurveRangeAttribute>(property);
if (_cachedCurveRangeAttribute == null)
_cachedCurveRangeAttribute = PropertyUtility.GetAttribute<CurveRangeAttribute>(property);

var attribute = _cachedCurveRangeAttribute;

EditorGUI.CurveField(
rect,
Loading