Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
02fb8a9
Update SerializableInterfacePropertyDrawer.cs
marc-antoine-girard Jul 9, 2022
c69d2e1
Clean up SerializableInterfacePropertyDrawer.cs
marc-antoine-girard Jul 9, 2022
ba10941
Update SerializableInterfacePropertyDrawer.cs
marc-antoine-girard Jul 9, 2022
d6e8d0b
Update SerializableInterfacePropertyDrawer.cs
marc-antoine-girard Jul 9, 2022
ae0f89f
Moved changes to RawReferenceDrawer
marc-antoine-girard Jul 9, 2022
0a43f4e
Forgot a managedReferenceValue
marc-antoine-girard Jul 9, 2022
9fd9c18
Added changes requested
marc-antoine-girard Jul 10, 2022
8730e50
Added null check in RawReferenceDrawer
marc-antoine-girard Jul 11, 2022
5b8bc58
Added NoneDropdownItem
marc-antoine-girard Jul 11, 2022
4f98193
Small cleanup before PR
marc-antoine-girard Jul 11, 2022
17040d0
Added proper properties in ReferenceDrawer.cs
marc-antoine-girard Jul 12, 2022
b3a5ccb
Merge branch '#24-Add-None-Option-CustomDrawers' into Merging
marc-antoine-girard Jul 12, 2022
b92d5ae
Merge branch '#21-Fix-NullReferenceException-RawReferenceDrawer' into…
marc-antoine-girard Jul 12, 2022
e3ecc45
Merge branch '#25-Fix-Setter-ReferenceDrawer' into Merging
marc-antoine-girard Jul 12, 2022
5495d00
Fixed Drag and Drop behaviour
marc-antoine-girard Jul 12, 2022
2199452
Merge branch '#22-Fix-DragAndDrop-ReferenceDrawer' into Merging
marc-antoine-girard Jul 12, 2022
693da10
Update RawReferenceDrawer.cs
marc-antoine-girard Jul 12, 2022
64c42a4
Update ReferenceDrawer.cs
marc-antoine-girard Jul 12, 2022
5c45251
Forgot to set a ModeValue
marc-antoine-girard Jul 12, 2022
a400f57
Update ReferenceDrawer.cs PropertyValue setter
marc-antoine-girard Jul 14, 2022
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
1 change: 1 addition & 0 deletions Editor/Drawers/CustomObjectDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
66 changes: 49 additions & 17 deletions Editor/Drawers/RawReferenceDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <inheritdoc />
public RawReferenceDrawer(SerializedProperty property, GUIContent label, Type genericType, FieldInfo fieldInfo)
: base(property, genericType)
: base(property, genericType, fieldInfo)
{
this.label = label;
this.fieldInfo = fieldInfo;
}

/// <inheritdoc />
Expand All @@ -47,6 +34,8 @@ public float GetHeight()
/// <inheritdoc />
public void OnGUI(Rect position)
{
AvoidDuplicateReferencesInArray();

Rect objectFieldRect = new Rect(position)
{
height = EditorGUIUtility.singleLineHeight
Expand All @@ -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;

Expand All @@ -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?)
}

/// <inheritdoc />
protected override void OnPropertiesClicked()
{
if (RawReferenceValue == null)
return;

Type type = RawReferenceValue.GetType();
string typeName = type.Name;

Expand All @@ -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;
}
}
}
131 changes: 89 additions & 42 deletions Editor/Drawers/ReferenceDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Reflection;
using TNRD.Utilities;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
Expand Down Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property mirrors the behaviour of SerializableInterface.Value, but in the PropertyDrawer.

{
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;
Expand Down Expand Up @@ -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();
}
}

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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();
}
}
10 changes: 8 additions & 2 deletions Editor/Drawers/UnityReferenceDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using TNRD.Utilities;
using UnityEditor;
using UnityEngine;
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down
17 changes: 17 additions & 0 deletions Editor/Items/NoneDropdownItem.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
3 changes: 3 additions & 0 deletions Editor/Items/NoneDropdownItem.cs.meta

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

7 changes: 2 additions & 5 deletions Editor/SerializableInterfacePropertyDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ internal sealed class SerializableInterfacePropertyDrawer : PropertyDrawer
private IReferenceDrawer activeDrawer;

/// <inheritdoc />
public override bool CanCacheInspectorGUI(SerializedProperty property)
{
return false;
}
public override bool CanCacheInspectorGUI(SerializedProperty property) => false;

private void Initialize(SerializedProperty property)
{
Expand Down Expand Up @@ -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();
}
Expand Down
Loading