Skip to content

Commit 332e79d

Browse files
committed
Added ability to customize generic object field drawer
1 parent d3420ac commit 332e79d

File tree

5 files changed

+46
-28
lines changed

5 files changed

+46
-28
lines changed

.GenericUnityInternals/GenericUnityEditorInternals/EditorGUIHelper.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static class EditorGUIHelper
1414
[PublicAPI]
1515
public static Object GenericObjectField(Rect position, GUIContent label, Object currentTarget, Type objType, bool allowSceneObjects)
1616
{
17-
return ObjectFieldInternal(position, label, currentTarget, allowSceneObjects, new ObjectFieldHelper(currentTarget, objType));
17+
return GenericObjectField(position, label, currentTarget, allowSceneObjects, new ObjectFieldHelper(currentTarget, objType));
1818
}
1919

2020
/// <summary>
@@ -25,24 +25,20 @@ public static void GenericObjectField(Rect position, SerializedProperty property
2525
{
2626
GUIContent propertyLabel = EditorGUI.BeginProperty(position, label, property);
2727

28-
ObjectFieldInternal(position, property, label == null ? null : propertyLabel);
29-
30-
EditorGUI.EndProperty();
31-
}
32-
33-
private static void ObjectFieldInternal(Rect position, SerializedProperty property, [CanBeNull] GUIContent label)
34-
{
3528
Object objectBeingEdited = property.serializedObject.targetObject;
3629

3730
// Allow scene objects if the object being edited is NOT persistent
3831
bool allowSceneObjects = ! (objectBeingEdited == null || EditorUtility.IsPersistent(objectBeingEdited));
3932

40-
property.objectReferenceValue = ObjectFieldInternal(position, label, property.objectReferenceValue,
33+
property.objectReferenceValue = GenericObjectField(position, label == null ? null : propertyLabel, property.objectReferenceValue,
4134
allowSceneObjects, new ObjectFieldHelper(property));
35+
36+
EditorGUI.EndProperty();
4237
}
4338

44-
private static Object ObjectFieldInternal(Rect position, [CanBeNull] GUIContent label, Object currentTarget,
45-
bool allowSceneObjects, ObjectFieldHelper helper)
39+
[PublicAPI]
40+
public static Object GenericObjectField(Rect position, [CanBeNull] GUIContent label, Object currentTarget,
41+
bool allowSceneObjects, in ObjectFieldHelper helper)
4642
{
4743
const EditorGUI.ObjectFieldVisualType visualType = EditorGUI.ObjectFieldVisualType.IconAndText;
4844

.GenericUnityInternals/GenericUnityEditorInternals/ObjectFieldHelper.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/// When drawing ObjectField, there are things that need to be done differently for <see cref="Type"/> and <see cref="SerializedProperty"/>.
1111
/// This helper encapsulates such parts of the code so that the main method contains the same logic for Type and SerializedProperty.
1212
/// </summary>
13-
internal readonly struct ObjectFieldHelper
13+
public readonly struct ObjectFieldHelper
1414
{
1515
public readonly Type ObjType;
1616
public readonly Object CurrentTarget;
@@ -19,21 +19,25 @@ internal readonly struct ObjectFieldHelper
1919

2020
private readonly SerializedProperty _property;
2121

22+
private readonly Func<Object, bool> _validateObjectCustom;
23+
2224
public ObjectFieldHelper(Object currentTarget, Type type)
2325
{
2426
ObjType = type;
2527
CurrentTarget = currentTarget;
2628
_property = null;
29+
_validateObjectCustom = null;
2730
}
2831

29-
public ObjectFieldHelper(SerializedProperty property)
32+
public ObjectFieldHelper(SerializedProperty property, Func<Object, bool> validateObjectCustom = null)
3033
{
3134
_property = property;
3235
ObjType = GenericTypeHelper.GetGenericType(property);
3336
CurrentTarget = property.objectReferenceValue;
37+
_validateObjectCustom = validateObjectCustom;
3438
}
3539

36-
public Object ValidateObjectFieldAssignment(Object[] references, EditorGUI.ObjectFieldValidatorOptions options)
40+
internal Object ValidateObjectFieldAssignment(Object[] references, EditorGUI.ObjectFieldValidatorOptions options)
3741
{
3842
if (references.Length == 0)
3943
return null;
@@ -113,9 +117,20 @@ private Object ValidateAssignmentForType(Object[] references)
113117

114118
private Object ValidateAssignmentForProperty(Object[] references, EditorGUI.ObjectFieldValidatorOptions options)
115119
{
116-
if (references[0] == null || ! EditorGUI.ValidateObjectReferenceValue(_property, references[0], options))
120+
if (references[0] == null)
117121
return null;
118122

123+
if (options == EditorGUI.ObjectFieldValidatorOptions.None && _validateObjectCustom != null)
124+
{
125+
if ( ! _validateObjectCustom(references[0]))
126+
return null;
127+
}
128+
else
129+
{
130+
if ( ! EditorGUI.ValidateObjectReferenceValue(_property, references[0], options))
131+
return null;
132+
}
133+
119134
if (EditorSceneManager.preventCrossSceneReferences &&
120135
EditorGUI.CheckForCrossSceneReferencing(references[0], _property.serializedObject.targetObject))
121136
{

Editor/Drawers/CreatableObjectDrawer.cs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ static CreatableObjectDrawer()
4040

4141
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
4242
{
43-
(_, Type type) = property.GetFieldInfoAndType();
43+
Type propertyType = property.GetObjectType();
4444

45-
if (!type.InheritsFrom(typeof(ScriptableObject)) && !type.InheritsFrom(typeof(MonoBehaviour)))
45+
if (!propertyType.InheritsFrom(typeof(ScriptableObject)) && !propertyType.InheritsFrom(typeof(MonoBehaviour)))
4646
{
4747
EditorGUILayoutHelper.DrawErrorMessage("Creatable attribute can only be used on ScriptableObjects and MonoBehaviours.");
4848
return;
4949
}
5050

51-
if (type.IsAbstract)
51+
if (propertyType.IsAbstract)
5252
{
5353
EditorGUILayoutHelper.DrawErrorMessage("Creatable attribute can only be used on fields of non-abstract type.");
5454
return;
@@ -65,32 +65,37 @@ public override void OnGUI(Rect rect, SerializedProperty property, GUIContent la
6565
(var objectRect, var buttonRect) = rect.CutVertically(buttonWidth, true);
6666
objectRect.width -= paddingBetween;
6767

68-
GenericObjectDrawer.ObjectField(objectRect, property, label);
68+
DrawObjectField(objectRect, property, label);
6969

7070
if ( ! GUI.Button(buttonRect, "+"))
7171
return;
7272

7373
// this is for scriptable objects
74-
if (type.InheritsFrom(typeof(ScriptableObject)))
74+
if (propertyType.InheritsFrom(typeof(ScriptableObject)))
7575
{
76-
CreateScriptableObject(property, type);
76+
CreateScriptableObject(property, propertyType);
7777
}
7878
else
7979
{
80-
CreateMonoBehaviour(property, type);
80+
CreateMonoBehaviour(property, propertyType);
8181
}
8282
}
8383

84+
protected virtual void DrawObjectField(Rect objectRect, SerializedProperty property, GUIContent label)
85+
{
86+
GenericObjectDrawer.ObjectField(objectRect, property, label);
87+
}
88+
8489
#region Create Scriptable Object
8590

86-
private void CreateScriptableObject(SerializedProperty property, Type type)
91+
private static void CreateScriptableObject(SerializedProperty property, Type type)
8792
{
8893
var asset = CreateAsset(property, type);
8994
property.objectReferenceValue = asset;
9095
EditorGUIUtility.PingObject(asset);
9196
}
9297

93-
private ScriptableObject CreateAsset(SerializedProperty property, Type type)
98+
private static ScriptableObject CreateAsset(SerializedProperty property, Type type)
9499
{
95100
var folderPath = ProjectWindowUtilProxy.GetActiveFolderPath();
96101

@@ -121,12 +126,12 @@ private ScriptableObject CreateAsset(SerializedProperty property, Type type)
121126
return asset;
122127
}
123128

124-
private bool IsValidPath(string path)
129+
private static bool IsValidPath(string path)
125130
{
126131
return ! string.IsNullOrEmpty(path) && IsInProject(path) && HasCorrectExtension(path);
127132
}
128133

129-
private bool IsInProject(string path)
134+
private static bool IsInProject(string path)
130135
{
131136
if (PathHelper.IsSubPathOf(path, _assetsPath) || PathHelper.IsSubPathOf(path, _packagesPath))
132137
return true;
@@ -135,7 +140,7 @@ private bool IsInProject(string path)
135140
return false;
136141
}
137142

138-
private bool HasCorrectExtension(string path)
143+
private static bool HasCorrectExtension(string path)
139144
{
140145
if (path.EndsWith(".asset"))
141146
return true;
@@ -152,7 +157,7 @@ private bool HasCorrectExtension(string path)
152157
private const string PropertyPathKey = "CreatableObjectDrawer_PropertyPath";
153158
private const string AddedComponentTypeKey = "CreatableObjectDrawer_AddedComponent";
154159

155-
private void CreateMonoBehaviour(SerializedProperty property, Type type)
160+
public static void CreateMonoBehaviour(SerializedProperty property, Type type, Action<Component, bool> onComponentAdded = null)
156161
{
157162
var parentComponent = property.serializedObject.targetObject as MonoBehaviour;
158163

@@ -163,6 +168,8 @@ private void CreateMonoBehaviour(SerializedProperty property, Type type)
163168

164169
var component = AddComponentHelper.AddComponent(gameObject, type, out bool reloadRequired);
165170

171+
onComponentAdded?.Invoke(component, reloadRequired);
172+
166173
if (reloadRequired)
167174
{
168175
PersistentStorage.SaveData(TargetComponentKey, property.serializedObject.targetObject);

GenericUnityEditorInternals.dll

0 Bytes
Binary file not shown.

GenericUnityEditorInternals.pdb

4 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)