diff --git a/Editor/Drawers/CustomObjectDrawer.cs b/Editor/Drawers/CustomObjectDrawer.cs
index b1931f2..5b6b27e 100644
--- a/Editor/Drawers/CustomObjectDrawer.cs
+++ b/Editor/Drawers/CustomObjectDrawer.cs
@@ -94,6 +94,7 @@ private void HandleMouseDown(Rect position, Rect positionWithoutThumb)
else if (Event.button == 1 && positionWithoutThumb.Contains(Event.mousePosition))
{
GenericMenu menu = new GenericMenu();
+ menu.AddItem(new GUIContent("Clear"), false, () => { DeletePressed?.Invoke(); });
menu.AddItem(new GUIContent("Properties..."), false, () => { PropertiesClicked?.Invoke(); });
menu.DropDown(position);
Event.Use();
diff --git a/Editor/Drawers/RawReferenceDrawer.cs b/Editor/Drawers/RawReferenceDrawer.cs
index 72fa6e7..1c42b30 100644
--- a/Editor/Drawers/RawReferenceDrawer.cs
+++ b/Editor/Drawers/RawReferenceDrawer.cs
@@ -9,28 +9,15 @@ namespace TNRD.Drawers
internal class RawReferenceDrawer : ReferenceDrawer, IReferenceDrawer
{
private readonly GUIContent label;
- private readonly FieldInfo fieldInfo;
- private object RawReferenceValue
- {
- get
- {
-#if UNITY_2021_1_OR_NEWER
- return RawReferenceProperty.managedReferenceValue;
-#else
- ISerializableInterface instance =
- (ISerializableInterface)fieldInfo.GetValue(Property.serializedObject.targetObject);
- return instance.GetRawReference();
-#endif
- }
- }
+ private static object previousReferenceValue;
+ private static string previousPropertyPath;
///
public RawReferenceDrawer(SerializedProperty property, GUIContent label, Type genericType, FieldInfo fieldInfo)
- : base(property, genericType)
+ : base(property, genericType, fieldInfo)
{
this.label = label;
- this.fieldInfo = fieldInfo;
}
///
@@ -47,6 +34,8 @@ public float GetHeight()
///
public void OnGUI(Rect position)
{
+ AvoidDuplicateReferencesInArray();
+
Rect objectFieldRect = new Rect(position)
{
height = EditorGUIUtility.singleLineHeight
@@ -59,6 +48,9 @@ public void OnGUI(Rect position)
: new GUIContent(rawReferenceValue.GetType().Name, IconUtility.ScriptIcon);
CustomObjectDrawer.OnGUI(objectFieldRect, label, content);
+
+ HandleDragAndDrop(objectFieldRect);
+
if (rawReferenceValue == null)
return;
@@ -70,12 +62,20 @@ public void OnGUI(Rect position)
new GUIContent(rawReferenceValue.GetType().Name),
true);
- HandleDragAndDrop(objectFieldRect);
+ previousPropertyPath = Property.propertyPath;
+ }
+
+ protected override void PingObject()
+ {
+ // No support for pinging raw objects for now (I guess this would ping the MonoScript?)
}
///
protected override void OnPropertiesClicked()
{
+ if (RawReferenceValue == null)
+ return;
+
Type type = RawReferenceValue.GetType();
string typeName = type.Name;
@@ -91,5 +91,37 @@ protected override void OnPropertiesClicked()
}
}
}
+
+ private void AvoidDuplicateReferencesInArray()
+ {
+ if (!IsPropertyInArray(Property))
+ return;
+ if (previousPropertyPath == null)
+ return;
+ if (previousPropertyPath == Property.propertyPath)
+ return;
+
+ object currentReferenceValue = RawReferenceValue;
+
+ if (currentReferenceValue == null)
+ return;
+
+ if (previousReferenceValue == currentReferenceValue)
+ PropertyValue = CreateInstance(currentReferenceValue);
+
+ previousReferenceValue = currentReferenceValue;
+ }
+
+ private static bool IsPropertyInArray(SerializedProperty prop)
+ {
+ return prop.propertyPath.Contains(".Array.data[");
+ }
+
+ private static object CreateInstance(object source)
+ {
+ object instance = Activator.CreateInstance(source.GetType());
+ EditorUtility.CopySerializedManagedFieldsOnly(source, instance);
+ return instance;
+ }
}
}
diff --git a/Editor/Drawers/ReferenceDrawer.cs b/Editor/Drawers/ReferenceDrawer.cs
index 984dc05..a64eb99 100644
--- a/Editor/Drawers/ReferenceDrawer.cs
+++ b/Editor/Drawers/ReferenceDrawer.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using System.Reflection;
using TNRD.Utilities;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
@@ -29,10 +30,72 @@ private enum DragAndDropMode
protected SerializedProperty RawReferenceProperty => Property.FindPropertyRelative("rawReference");
protected SerializedProperty UnityReferenceProperty => Property.FindPropertyRelative("unityReference");
- protected ReferenceDrawer(SerializedProperty property, Type genericType)
+ protected readonly FieldInfo fieldInfo;
+
+ protected ReferenceMode ModeValue
+ {
+ get => (ReferenceMode)ReferenceModeProperty.enumValueIndex;
+ set => ReferenceModeProperty.enumValueIndex = (int)value;
+ }
+
+ protected object RawReferenceValue
+ {
+ get
+ {
+#if UNITY_2021_1_OR_NEWER
+ return RawReferenceProperty.managedReferenceValue;
+#else
+ ISerializableInterface instance =
+ (ISerializableInterface)fieldInfo.GetValue(Property.serializedObject.targetObject);
+ return instance.GetRawReference();
+#endif
+ }
+ set
+ {
+#if UNITY_2021_1_OR_NEWER
+ RawReferenceProperty.managedReferenceValue = value;
+#else
+ fieldInfo.SetValue(Property.serializedObject.targetObject, value);
+#endif
+ }
+ }
+
+ protected object PropertyValue
+ {
+ get
+ {
+ return ModeValue switch
+ {
+ ReferenceMode.Raw => RawReferenceValue,
+ ReferenceMode.Unity => UnityReferenceProperty.objectReferenceValue,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ }
+ set
+ {
+ switch (ModeValue)
+ {
+ case ReferenceMode.Raw:
+ RawReferenceValue = value;
+ UnityReferenceProperty.objectReferenceValue = null;
+ break;
+ case ReferenceMode.Unity:
+ UnityReferenceProperty.objectReferenceValue = GetUnityObject((Object)value);
+ RawReferenceValue = null;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ Property.serializedObject.ApplyModifiedProperties();
+ }
+ }
+
+ protected ReferenceDrawer(SerializedProperty property, Type genericType, FieldInfo fieldInfo)
{
Property = property;
GenericType = genericType;
+ this.fieldInfo = fieldInfo;
CustomObjectDrawer = new CustomObjectDrawer();
CustomObjectDrawer.ButtonClicked += OnButtonClicked;
@@ -66,56 +129,35 @@ private void OnButtonClicked(Rect position)
private void OnClicked()
{
- switch ((ReferenceMode)ReferenceModeProperty.enumValueIndex)
- {
- case ReferenceMode.Raw:
- // No support for pinging raw objects for now (I guess this would ping the MonoScript?)
- break;
- case ReferenceMode.Unity:
- EditorGUIUtility.PingObject(UnityReferenceProperty.objectReferenceValue);
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
+ PingObject();
}
private void OnDeletePressed()
{
- RawReferenceProperty.managedReferenceValue = null;
- UnityReferenceProperty.objectReferenceValue = null;
- Property.serializedObject.ApplyModifiedProperties();
+ PropertyValue = null;
}
private void OnItemSelected(ReferenceMode mode, object reference)
{
- ReferenceModeProperty.enumValueIndex = (int)mode;
-
- switch (mode)
- {
- case ReferenceMode.Raw:
- RawReferenceProperty.managedReferenceValue = reference;
- break;
- case ReferenceMode.Unity:
- UnityReferenceProperty.objectReferenceValue = (Object)reference;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
- }
-
- Property.serializedObject.ApplyModifiedProperties();
+ ModeValue = mode;
+ PropertyValue = reference;
}
protected abstract void OnPropertiesClicked();
protected void HandleDragAndDrop(Rect position)
{
+ if (!position.Contains(Event.current.mousePosition))
+ return;
+
if (Event.current.type == EventType.DragPerform)
{
+ HandleDragUpdated();
HandleDragPerform();
}
else if (Event.current.type == EventType.DragUpdated)
{
- HandleDragUpdated(position);
+ HandleDragUpdated();
}
}
@@ -134,11 +176,8 @@ private void SetDragAndDropMode(bool success, DragAndDropMode? successMode = nul
}
}
- private void HandleDragUpdated(Rect position)
+ private void HandleDragUpdated()
{
- if (!position.Contains(Event.current.mousePosition))
- return;
-
if (DragAndDrop.objectReferences.Length > 1)
{
SetDragAndDropMode(false);
@@ -156,12 +195,12 @@ private void HandleDragUpdated(Rect position)
{
Type scriptType = monoScript.GetClass();
- if (scriptType.IsSubclassOf(typeof(UnityEngine.Object)))
+ if (scriptType.IsSubclassOf(typeof(Object)))
{
SetDragAndDropMode(false);
return;
}
-
+
if (!GenericType.IsAssignableFrom(scriptType))
{
SetDragAndDropMode(false);
@@ -182,18 +221,26 @@ private void HandleDragPerform()
switch (dragAndDropMode)
{
case DragAndDropMode.Raw:
- RawReferenceProperty.managedReferenceValue =
- Activator.CreateInstance(((MonoScript)DragAndDrop.objectReferences[0]).GetClass());
- ReferenceModeProperty.enumValueIndex = (int)ReferenceMode.Raw;
+ ModeValue = ReferenceMode.Raw;
+ PropertyValue = Activator.CreateInstance(((MonoScript)DragAndDrop.objectReferences[0]).GetClass());
break;
case DragAndDropMode.Unity:
- UnityReferenceProperty.objectReferenceValue = DragAndDrop.objectReferences[0];
- ReferenceModeProperty.enumValueIndex = (int)ReferenceMode.Unity;
+ ModeValue = ReferenceMode.Unity;
+ PropertyValue = DragAndDrop.objectReferences[0];
break;
case DragAndDropMode.None:
default:
throw new ArgumentOutOfRangeException();
}
}
+
+ private Object GetUnityObject(Object objectReference)
+ {
+ if(objectReference is GameObject gameObject)
+ return gameObject.GetComponent(GenericType);
+ return objectReference;
+ }
+
+ protected abstract void PingObject();
}
}
diff --git a/Editor/Drawers/UnityReferenceDrawer.cs b/Editor/Drawers/UnityReferenceDrawer.cs
index b409799..8592c49 100644
--- a/Editor/Drawers/UnityReferenceDrawer.cs
+++ b/Editor/Drawers/UnityReferenceDrawer.cs
@@ -1,4 +1,5 @@
using System;
+using System.Reflection;
using TNRD.Utilities;
using UnityEditor;
using UnityEngine;
@@ -10,8 +11,8 @@ internal class UnityReferenceDrawer : ReferenceDrawer, IReferenceDrawer
{
private readonly GUIContent label;
- public UnityReferenceDrawer(SerializedProperty property, GUIContent label, Type genericType)
- : base(property, genericType)
+ public UnityReferenceDrawer(SerializedProperty property, GUIContent label, Type genericType, FieldInfo fieldInfo)
+ : base(property, genericType, fieldInfo)
{
this.label = label;
}
@@ -30,6 +31,11 @@ public void OnGUI(Rect position)
HandleDragAndDrop(position);
}
+ protected override void PingObject()
+ {
+ EditorGUIUtility.PingObject((Object)PropertyValue);
+ }
+
protected override void OnPropertiesClicked()
{
PropertyEditorUtility.Show(UnityReferenceProperty.objectReferenceValue);
diff --git a/Editor/Items/NoneDropdownItem.cs b/Editor/Items/NoneDropdownItem.cs
new file mode 100644
index 0000000..ca05cdc
--- /dev/null
+++ b/Editor/Items/NoneDropdownItem.cs
@@ -0,0 +1,17 @@
+using UnityEditor.IMGUI.Controls;
+
+namespace TNRD.Items
+{
+ public class NoneDropdownItem : AdvancedDropdownItem, IDropdownItem
+ {
+ private ReferenceMode mode => ReferenceMode.Raw;
+ public NoneDropdownItem() : base("None") { }
+
+ ReferenceMode IDropdownItem.Mode => mode;
+
+ public object GetValue()
+ {
+ return null;
+ }
+ }
+}
diff --git a/Editor/Items/NoneDropdownItem.cs.meta b/Editor/Items/NoneDropdownItem.cs.meta
new file mode 100644
index 0000000..2813776
--- /dev/null
+++ b/Editor/Items/NoneDropdownItem.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: a7015062205d46cbb9cb01b0b88fff55
+timeCreated: 1657572673
\ No newline at end of file
diff --git a/Editor/SerializableInterfacePropertyDrawer.cs b/Editor/SerializableInterfacePropertyDrawer.cs
index 7ce4953..72d84cc 100644
--- a/Editor/SerializableInterfacePropertyDrawer.cs
+++ b/Editor/SerializableInterfacePropertyDrawer.cs
@@ -16,10 +16,7 @@ internal sealed class SerializableInterfacePropertyDrawer : PropertyDrawer
private IReferenceDrawer activeDrawer;
///
- public override bool CanCacheInspectorGUI(SerializedProperty property)
- {
- return false;
- }
+ public override bool CanCacheInspectorGUI(SerializedProperty property) => false;
private void Initialize(SerializedProperty property)
{
@@ -102,7 +99,7 @@ GUIContent label
case ReferenceMode.Unity:
return original is UnityReferenceDrawer
? original
- : new UnityReferenceDrawer(property, label, genericType);
+ : new UnityReferenceDrawer(property, label, genericType, fieldInfo);
default:
throw new ArgumentOutOfRangeException();
}
diff --git a/Editor/Utilities/SerializableInterfaceAdvancedDropdown.cs b/Editor/Utilities/SerializableInterfaceAdvancedDropdown.cs
index af82ecd..a485c08 100644
--- a/Editor/Utilities/SerializableInterfaceAdvancedDropdown.cs
+++ b/Editor/Utilities/SerializableInterfaceAdvancedDropdown.cs
@@ -48,6 +48,11 @@ protected override AdvancedDropdownItem BuildRoot()
.AddChild(new ClassesItemBuilder(interfaceType).Build())
.AddChild(new SceneItemBuilder(interfaceType, relevantScene).Build());
+ foreach (var dropdownItem in item.children)
+ {
+ dropdownItem.AddChild(new NoneDropdownItem());
+ }
+
if (canSort)
{
sortChildrenMethod.Invoke(item,
@@ -62,6 +67,12 @@ protected override AdvancedDropdownItem BuildRoot()
private int Sort(AdvancedDropdownItem a, AdvancedDropdownItem b)
{
+ // For aesthetic reasons. Always puts the None first
+ if (a is NoneDropdownItem)
+ return -1;
+ if (b is NoneDropdownItem)
+ return 1;
+
int childrenA = a.children.Count();
int childrenB = b.children.Count();