Skip to content

Commit 3b62e70

Browse files
authored
Merge pull request #18 from arimger/develop
Develop
2 parents 7d83701 + 1860f93 commit 3b62e70

32 files changed

+423
-158
lines changed

Assets/Editor Toolbox/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
## 0.8.11 [02.07.2021]
2+
3+
### Added:
4+
- IgnoreParentAttribute
5+
- ShowDisabledIfAttribute
6+
- HideDisabledIfAttribute
7+
- Default constraint to the SerializedType drawer
8+
9+
### Changed:
10+
- Fix assigning and clearing multiple drawers at once
11+
- Fix drawing default numeric types (Vector2, Vector3, etc.)
12+
- Fix drawing ReorderableList within horizontal groups
13+
114
## 0.8.6 [13.06.2021]
215

316
### Added:

Assets/Editor Toolbox/Editor/Drawers/RegularDrawers/SerializedTypeDrawer.cs

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
namespace Toolbox.Editor.Drawers
88
{
9-
[CustomPropertyDrawer(typeof(ClassTypeConstraintAttribute), true)]
9+
[CustomPropertyDrawer(typeof(TypeConstraintAttribute), true)]
1010
[CustomPropertyDrawer(typeof(SerializedType))]
1111
public sealed class SerializedTypeDrawer : ToolboxNativePropertyDrawer
1212
{
1313
/// <summary>
14-
/// Dictionary used to store all previously filtered types.
14+
/// Dictionary used to store all previously filtered types matched to the targt attribute.
1515
/// </summary>
16-
private readonly static Dictionary<Type, List<Type>> filteredTypes = new Dictionary<Type, List<Type>>();
16+
private readonly static Dictionary<int, List<Type>> cachedfilteredTypes = new Dictionary<int, List<Type>>();
1717

1818

1919
/// <summary>
@@ -60,55 +60,82 @@ private static string GetClassReferencValue(int selectedType, List<Type> types)
6060
return selectedType > 0 ? SerializedType.GetClassReference(types[selectedType - 1]) : string.Empty;
6161
}
6262

63-
private bool IsDefaultField(Attribute attribute)
63+
private bool IsDefaultField(TypeConstraintAttribute attribute)
6464
{
65-
return IsDefaultField(attribute as ClassTypeConstraintAttribute);
65+
return attribute == null || attribute.AssemblyType == null;
6666
}
6767

68-
private bool IsDefaultField(ClassTypeConstraintAttribute attribute)
68+
/// <summary>
69+
/// Creates default constraint attribute if the given one is invalid.
70+
/// </summary>
71+
private TypeConstraintAttribute GetVerifiedAttribute(Attribute attribute)
6972
{
70-
return attribute == null || attribute.AssemblyType == null;
73+
return GetVerifiedAttribute(attribute as TypeConstraintAttribute);
7174
}
7275

76+
/// <summary>
77+
/// Creates default constraint attribute if the given one is invalid.
78+
/// </summary>
79+
private TypeConstraintAttribute GetVerifiedAttribute(TypeConstraintAttribute attribute)
80+
{
81+
return IsDefaultField(attribute) ? GetDefaultConstraint() : attribute;
82+
}
7383

74-
protected override float GetPropertyHeightSafe(SerializedProperty property, GUIContent label)
84+
/// <summary>
85+
/// Returns default <see cref="TypeConstraintAttribute"/>.
86+
/// </summary>
87+
private TypeConstraintAttribute GetDefaultConstraint()
7588
{
76-
return IsDefaultField(attribute)
77-
? EditorGUI.GetPropertyHeight(property)
78-
: EditorStyles.popup.CalcHeight(GUIContent.none, 0);
89+
return new ClassExtendsAttribute()
90+
{
91+
AddTextSearchField = true
92+
};
7993
}
8094

81-
protected override void OnGUISafe(Rect position, SerializedProperty property, GUIContent label)
95+
/// <summary>
96+
/// Returns all <see cref="Type"/>s associated to the given constraint.
97+
/// </summary>
98+
private List<Type> GetFilteredTypes(TypeConstraintAttribute attribute)
8299
{
83-
var attribute = Attribute;
84-
//TODO: default drawer for fields without attributes
85-
//validate serialized field
86-
if (IsDefaultField(attribute))
100+
var hashCode = attribute.GetHashCode();
101+
if (cachedfilteredTypes.TryGetValue(hashCode, out var filteredTypes))
87102
{
88-
EditorGUI.PropertyField(position, property, label, property.isExpanded);
89-
return;
103+
return filteredTypes;
90104
}
91-
92-
//TODO: cache different filter settings
93-
//get stored types if possible or try to cache them
94-
if (!filteredTypes.TryGetValue(attribute.AssemblyType, out var refTypes))
105+
else
95106
{
96-
filteredTypes[attribute.AssemblyType] = refTypes = attribute.GetFilteredTypes();
107+
return cachedfilteredTypes[hashCode] = attribute.GetFilteredTypes();
97108
}
109+
}
110+
111+
112+
protected override float GetPropertyHeightSafe(SerializedProperty property, GUIContent label)
113+
{
114+
return EditorStyles.popup.CalcHeight(GUIContent.none, 0);
115+
}
116+
117+
protected override void OnGUISafe(Rect position, SerializedProperty property, GUIContent label)
118+
{
119+
var validAttribute = GetVerifiedAttribute(attribute);
98120

99121
var referenceProperty = property.FindPropertyRelative("classReference");
100122
var referenceValue = referenceProperty.stringValue;
101-
var referenceType = !string.IsNullOrEmpty(referenceValue) ? Type.GetType(referenceValue) : null;
102-
var optionsCount = refTypes.Count + 1;
123+
var referenceType = !string.IsNullOrEmpty(referenceValue)
124+
? Type.GetType(referenceValue)
125+
: null;
126+
127+
var filteredTypes = GetFilteredTypes(validAttribute);
128+
129+
var optionsCount = filteredTypes.Count + 1;
103130
var options = new string[optionsCount];
104131
var index = 0;
105132

106133
//create labels for all types
107134
options[0] = "<None>";
108135
for (var i = 1; i < optionsCount; i++)
109136
{
110-
var menuType = refTypes[i - 1];
111-
var menuLabel = FormatGroupedTypeName(menuType, attribute.Grouping);
137+
var menuType = filteredTypes[i - 1];
138+
var menuLabel = FormatGroupedTypeName(menuType, validAttribute.Grouping);
112139
if (menuType == referenceType)
113140
{
114141
index = i;
@@ -124,20 +151,20 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
124151
position = EditorGUI.PrefixLabel(position, label);
125152

126153
//try to draw associated popup
127-
if (attribute.AddTextSearchField)
154+
if (validAttribute.AddTextSearchField)
128155
{
129156
var buttonLabel = new GUIContent(options[index]);
130157
ToolboxEditorGui.DrawSearchablePopup(position, buttonLabel, index, options, (i) =>
131158
{
132159
referenceProperty.serializedObject.Update();
133-
referenceProperty.stringValue = GetClassReferencValue(i, refTypes);
160+
referenceProperty.stringValue = GetClassReferencValue(i, filteredTypes);
134161
referenceProperty.serializedObject.ApplyModifiedProperties();
135162
});
136163
}
137164
else
138165
{
139166
index = EditorGUI.Popup(position, index, options);
140-
referenceProperty.stringValue = GetClassReferencValue(index, refTypes);
167+
referenceProperty.stringValue = GetClassReferencValue(index, filteredTypes);
141168
}
142169

143170
EditorGUI.EndProperty();
@@ -149,8 +176,5 @@ public override bool IsPropertyValid(SerializedProperty property)
149176
{
150177
return property.type == nameof(SerializedType);
151178
}
152-
153-
154-
private ClassTypeConstraintAttribute Attribute => attribute as ClassTypeConstraintAttribute;
155179
}
156180
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using UnityEngine;
2+
3+
namespace Toolbox.Editor.Drawers
4+
{
5+
public class HideDisabledIfAttributeDrawer : ComparisonAttributeDrawer<HideDisabledIfAttribute>
6+
{
7+
protected override PropertyCondition OnComparisonResult(bool result)
8+
{
9+
return result ? PropertyCondition.NonValid : PropertyCondition.Disabled;
10+
}
11+
}
12+
}

Assets/Editor Toolbox/Editor/Drawers/ToolboxDrawers/ConditionDrawers/HideDisabledIfAttributeDrawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using UnityEngine;
2+
3+
namespace Toolbox.Editor.Drawers
4+
{
5+
public class ShowDisabledIfAttributeDrawer : ComparisonAttributeDrawer<ShowDisabledIfAttribute>
6+
{
7+
protected override PropertyCondition OnComparisonResult(bool result)
8+
{
9+
return result ? PropertyCondition.Disabled : PropertyCondition.NonValid;
10+
}
11+
}
12+
}

Assets/Editor Toolbox/Editor/Drawers/ToolboxDrawers/ConditionDrawers/ShowDisabledIfAttributeDrawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Editor Toolbox/Editor/Drawers/ToolboxDrawers/DecoratorDrawers/EditorButtonAttributeDrawer.cs

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using System.Collections;
22
using System.Reflection;
33

4+
using Unity.EditorCoroutines.Editor;
45
using UnityEditor;
56
using UnityEngine;
6-
using Unity.EditorCoroutines.Editor;
77

88
namespace Toolbox.Editor.Drawers
99
{
@@ -31,6 +31,43 @@ private bool IsCoroutine(MethodInfo method)
3131
return method.ReturnType == typeof(IEnumerator);
3232
}
3333

34+
private void CallMethods(EditorButtonAttribute attribute, Object[] targetObjects)
35+
{
36+
var methodInfo = ReflectionUtility.GetObjectMethod(attribute.MethodName, targetObjects);
37+
//validate method name (check if method exists)
38+
if (methodInfo == null)
39+
{
40+
ToolboxEditorLog.AttributeUsageWarning(attribute, string.Format("{0} method not found.", attribute.MethodName));
41+
return;
42+
}
43+
44+
//validate parameters count and log warning
45+
var parameters = methodInfo.GetParameters();
46+
if (parameters.Length > 0)
47+
{
48+
ToolboxEditorLog.AttributeUsageWarning(attribute, string.Format("{0} method has to be parameterless.", attribute.MethodName));
49+
return;
50+
}
51+
52+
//invoke method for all selected components
53+
var isCoroutine = IsCoroutine(methodInfo);
54+
for (var i = 0; i < targetObjects.Length; i++)
55+
{
56+
var target = targetObjects[i];
57+
if (target == null)
58+
{
59+
continue;
60+
}
61+
62+
var result = methodInfo.Invoke(target, null);
63+
//additionaly run Coroutine if possible
64+
if (isCoroutine)
65+
{
66+
EditorCoroutineUtility.StartCoroutineOwnerless((IEnumerator)result);
67+
}
68+
}
69+
}
70+
3471

3572
protected override void OnGuiCloseSafe(EditorButtonAttribute attribute)
3673
{
@@ -52,39 +89,7 @@ protected override void OnGuiCloseSafe(EditorButtonAttribute attribute)
5289

5390
if (GUILayout.Button(content, Style.buttonStyle))
5491
{
55-
var methodInfo = ReflectionUtility.GetObjectMethod(attribute.MethodName, targetObjects);
56-
//validate method name (check if method exists)
57-
if (methodInfo == null)
58-
{
59-
ToolboxEditorLog.AttributeUsageWarning(attribute, string.Format("{0} method not found.", attribute.MethodName));
60-
return;
61-
}
62-
63-
//validate parameters count and log warning
64-
var parameters = methodInfo.GetParameters();
65-
if (parameters.Length > 0)
66-
{
67-
ToolboxEditorLog.AttributeUsageWarning(attribute, string.Format("{0} method has to be parameterless.", attribute.MethodName));
68-
return;
69-
}
70-
71-
//invoke method for all selected components
72-
var isCoroutine = IsCoroutine(methodInfo);
73-
for (var i = 0; i < targetObjects.Length; i++)
74-
{
75-
var target = targetObjects[i];
76-
if (target == null)
77-
{
78-
continue;
79-
}
80-
81-
var result = methodInfo.Invoke(target, null);
82-
//additionaly run Coroutine if possible
83-
if (isCoroutine)
84-
{
85-
EditorCoroutineUtility.StartCoroutineOwnerless((IEnumerator)result);
86-
}
87-
}
92+
CallMethods(attribute, targetObjects);
8893
}
8994
}
9095
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using UnityEditor;
2+
using UnityEngine;
3+
4+
namespace Toolbox.Editor.Drawers
5+
{
6+
public class IgnoreParentAttributeDrawer : ToolboxSelfPropertyDrawer<IgnoreParentAttribute>
7+
{
8+
protected override void OnGuiSafe(SerializedProperty property, GUIContent label, IgnoreParentAttribute attribute)
9+
{
10+
var targetProperty = property.Copy();
11+
targetProperty.NextVisible(true);
12+
//draw first child, right after the parent property
13+
ToolboxEditorGui.DrawToolboxProperty(targetProperty.Copy());
14+
var targetDepth = targetProperty.depth;
15+
while (targetProperty.NextVisible(false))
16+
{
17+
if (targetProperty.depth > targetDepth)
18+
{
19+
break;
20+
}
21+
22+
//draw all children in order but only one level depth
23+
ToolboxEditorGui.DrawToolboxProperty(targetProperty.Copy());
24+
}
25+
}
26+
}
27+
}

Assets/Editor Toolbox/Editor/Drawers/ToolboxDrawers/PropertySelfDrawers/IgnoreParentAttributeDrawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Editor Toolbox/Editor/Drawers/ToolboxDrawers/PropertySelfDrawers/InLineEditorAttributeDrawer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ protected override void OnGuiSafe(SerializedProperty property, GUIContent label,
124124
}
125125

126126
InspectorUtility.SetIsEditorExpanded(editor, true);
127-
128127
//make useage of the created (cached) Editor instance
129128
using (new FixedFieldsScope())
130129
{

0 commit comments

Comments
 (0)