Skip to content
Merged
Show file tree
Hide file tree
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
143 changes: 87 additions & 56 deletions Scripts/Editor/Core/CollectionItemIndirectReferencePropertyDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,73 +9,93 @@ namespace BrunoMikoski.ScriptableObjectCollections
public sealed class CollectionItemIndirectReferencePropertyDrawer : PropertyDrawer
{
private const string COLLECTION_ITEM_GUID_PROPERTY_PATH = "collectionItemGUID";
private const string COLLECTION_GUID_PROPERTY_PATh = "collectionGUID";
private const string COLLECTION_GUID_PROPERTY_PATH = "collectionGUID";

private Type collectionItemType;
private CollectionItemItemPropertyDrawer collectionItemPropertyDrawer;
private CollectionItemPropertyDrawer collectionItemPropertyDrawer;

private SerializedProperty drawingProperty;
private SerializedProperty itemGUIDSerializedProperty;
private SerializedProperty collectionGUIDSerializedProperty;

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (collectionItemType == null)
{
Type arrayOrListType = fieldInfo.FieldType.GetArrayOrListType();
Type properFieldType = arrayOrListType ?? fieldInfo.FieldType;
collectionItemType = GetGenericItemType(properFieldType).GetGenericArguments().First();
}
if(collectionItemType == null) SetCollectionItemType();
if (collectionItemPropertyDrawer == null) CreateCollectionItemPropertyDrawer(property);

if (collectionItemPropertyDrawer == null)
{
collectionItemPropertyDrawer = new CollectionItemItemPropertyDrawer();
collectionItemPropertyDrawer.Initialize(collectionItemType, null);
}

SerializedProperty collectionItemGUIDSerializedProperty = property.FindPropertyRelative(COLLECTION_ITEM_GUID_PROPERTY_PATH);
SerializedProperty collectionGUIDSerializedProperty = property.FindPropertyRelative(COLLECTION_GUID_PROPERTY_PATh);

ScriptableObjectCollectionItem collectionItem = null;

if (!string.IsNullOrEmpty(collectionItemGUIDSerializedProperty.stringValue)
&& !string.IsNullOrEmpty(collectionGUIDSerializedProperty.stringValue))
drawingProperty = property;
itemGUIDSerializedProperty = property.FindPropertyRelative(COLLECTION_ITEM_GUID_PROPERTY_PATH);
collectionGUIDSerializedProperty = property.FindPropertyRelative(COLLECTION_GUID_PROPERTY_PATH);

var itemGUID = itemGUIDSerializedProperty.stringValue;
var collectionItem = GetCollectionItem(itemGUID, collectionGUIDSerializedProperty.stringValue);

int indexOfArrayPart = property.propertyPath.IndexOf('[');
if (indexOfArrayPart > -1)
{
if (CollectionsRegistry.Instance.TryGetCollectionByGUID(collectionGUIDSerializedProperty.stringValue,
out ScriptableObjectCollection collection))
if (string.Equals(label.text, itemGUID, StringComparison.Ordinal))
{
if (collection.TryGetItemByGUID(collectionItemGUIDSerializedProperty.stringValue,
out ScriptableObjectCollectionItem resultCollection))
{
collectionItem = resultCollection;
}
label.text = $"Element {property.propertyPath.Substring(indexOfArrayPart + 1, 1)}";
}
}

int indexOfArrayPart = property.propertyPath.IndexOf('[');
if (collectionItemPropertyDrawer.OptionsAttribute.DrawType == DrawType.Dropdown)
{
DrawItemDrawer(position, label, collectionItem);
return;
}

if (indexOfArrayPart > -1)
EditorGUI.PropertyField(position, property, label, true);
}

private void DrawItemDrawer(
Rect position, GUIContent label, ScriptableObjectCollectionItem collectionItem
)
{
collectionItemPropertyDrawer.DrawCollectionItemDrawer(ref position, collectionItem, label, item =>
{
if (string.Equals(label.text, collectionItemGUIDSerializedProperty.stringValue, StringComparison.Ordinal))
{
label.text = $"Element {property.propertyPath.Substring(indexOfArrayPart+1, 1)}";
}
SetSerializedPropertyGUIDs(item);
drawingProperty.serializedObject.ApplyModifiedProperties();
});
}

private void SetSerializedPropertyGUIDs(ScriptableObjectCollectionItem item)
{
if (item == null)
{
itemGUIDSerializedProperty.stringValue = string.Empty;
collectionGUIDSerializedProperty.stringValue = string.Empty;
}

collectionItemPropertyDrawer.DrawCollectionItemDrawer(
ref position, collectionItem, label,
item =>
{
string collectionItemGUID = string.Empty;
string collectionGUID = string.Empty;
if (item != null)
{
collectionItemGUID = item.GUID;
collectionGUID = item.Collection.GUID;
}

collectionItemGUIDSerializedProperty.stringValue = collectionItemGUID;
collectionGUIDSerializedProperty.stringValue = collectionGUID;
collectionItem = item;
property.serializedObject.ApplyModifiedProperties();
}
);
else
{
itemGUIDSerializedProperty.stringValue = item.GUID;
collectionGUIDSerializedProperty.stringValue = item.Collection.GUID;
}
}

private static ScriptableObjectCollectionItem GetCollectionItem(string itemGUID, string collectionGUID)
{
if (string.IsNullOrEmpty(itemGUID)) return null;
if (string.IsNullOrEmpty(collectionGUID)) return null;
if (!CollectionsRegistry.Instance.TryGetCollectionByGUID(collectionGUID,
out ScriptableObjectCollection collection))
return null;
if (!collection.TryGetItemByGUID(itemGUID, out ScriptableObjectCollectionItem resultCollection))
return null;
return resultCollection;
}

private void CreateCollectionItemPropertyDrawer(SerializedProperty serializedProperty)
{
collectionItemPropertyDrawer = new CollectionItemPropertyDrawer();
collectionItemPropertyDrawer.Initialize(collectionItemType, GetOptionsAttribute());
}

private void SetCollectionItemType()
{
Type arrayOrListType = fieldInfo.FieldType.GetArrayOrListType();
Type properFieldType = arrayOrListType ?? fieldInfo.FieldType;
collectionItemType = GetGenericItemType(properFieldType).GetGenericArguments().First();
}

private Type GetGenericItemType(Type targetType)
Expand All @@ -84,12 +104,23 @@ private Type GetGenericItemType(Type targetType)

while (baseType != null)
{
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(CollectionItemIndirectReference<>))
if (baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == typeof(CollectionItemIndirectReference<>))
return baseType;
baseType = baseType.BaseType;
}

return null;
}
}
}

private CollectionItemEditorOptionsAttribute GetOptionsAttribute()
{
if (fieldInfo == null)
return null;
object[] attributes = fieldInfo.GetCustomAttributes(typeof(CollectionItemEditorOptionsAttribute), false);
if (attributes.Length > 0)
return attributes[0] as CollectionItemEditorOptionsAttribute;
return null;
}
}
}
3 changes: 0 additions & 3 deletions Scripts/Editor/Core/CollectionItemItemPropertyDrawer.cs.meta

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
Expand All @@ -7,25 +8,15 @@
namespace BrunoMikoski.ScriptableObjectCollections
{
[CustomPropertyDrawer(typeof(ScriptableObjectCollectionItem), true)]
public class CollectionItemItemPropertyDrawer : PropertyDrawer
public class CollectionItemPropertyDrawer : PropertyDrawer
{
private static readonly CollectionItemEditorOptionsAttribute DefaultAttribute
= new CollectionItemEditorOptionsAttribute(DrawType.Dropdown);

private CollectionItemEditorOptionsAttribute cachedOptionsAttribute;

private CollectionItemEditorOptionsAttribute OptionsAttribute
{
get
{
if (cachedOptionsAttribute == null)
cachedOptionsAttribute = GetOptionsAttribute();
return cachedOptionsAttribute;
}
}
internal CollectionItemEditorOptionsAttribute OptionsAttribute { get; private set; }

private bool initialized;

private Object currentObject;

private CollectionItemDropdown collectionItemDropdown;
Expand All @@ -36,8 +27,7 @@ private CollectionItemEditorOptionsAttribute GetOptionsAttribute()
{
if (fieldInfo == null)
return DefaultAttribute;
object[] attributes
= fieldInfo.GetCustomAttributes(typeof(CollectionItemEditorOptionsAttribute), false);
object[] attributes = fieldInfo.GetCustomAttributes(typeof(CollectionItemEditorOptionsAttribute), false);
if (attributes.Length > 0)
return attributes[0] as CollectionItemEditorOptionsAttribute;
return DefaultAttribute;
Expand All @@ -51,11 +41,11 @@ public override float GetPropertyHeight(SerializedProperty property, GUIContent
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Initialize(property);

if (OptionsAttribute.DrawType == DrawType.AsReference)
{
EditorGUI.PropertyField(position, property, label, true);
return;
return;
}

item = property.objectReferenceValue as ScriptableObjectCollectionItem;
Expand All @@ -80,9 +70,9 @@ internal void DrawCollectionItemDrawer(ref Rect position, ScriptableObjectCollec
{
if (currentObject == null)
currentObject = collectionItem;

DrawEditFoldoutButton(ref prefixPosition, collectionItem);
DrawGotoButton(ref prefixPosition);
DrawGotoButton(ref prefixPosition, collectionItem);
}

DrawCollectionItemDropDown(ref prefixPosition, collectionItem, callback);
Expand All @@ -95,7 +85,7 @@ private void DrawEditorPreview(ref Rect rect, ScriptableObjectCollectionItem scr
{
if (scriptableObjectCollectionItem == null)
return;

if (!CollectionUtility.IsFoldoutOpen(scriptableObjectCollectionItem, currentObject))
return;

Expand All @@ -107,7 +97,7 @@ private void DrawEditorPreview(ref Rect rect, ScriptableObjectCollectionItem scr
SerializedObject collectionItemSerializedObject = new SerializedObject(scriptableObjectCollectionItem);

EditorGUI.indentLevel++;
rect = EditorGUI.IndentedRect(rect);
rect = EditorGUI.IndentedRect(rect);
SerializedProperty iterator = collectionItemSerializedObject.GetIterator();

using (EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope())
Expand All @@ -134,7 +124,7 @@ private void DrawEditorPreview(ref Rect rect, ScriptableObjectCollectionItem scr

Rect boxPosition = rect;
boxPosition.y = beginPositionY - 5;
boxPosition.height = (rect.y - beginPositionY)+10;
boxPosition.height = (rect.y - beginPositionY) + 10;
boxPosition.width += 10;
boxPosition.x += 5;
rect.y += 10;
Expand All @@ -145,31 +135,56 @@ private void Initialize(SerializedProperty property)
{
if (initialized)
return;

Type itemType;
if (fieldInfo == null)
{
Type parentType = property.serializedObject.targetObject.GetType();
itemType = GetFieldViaPath(parentType, property.propertyPath).FieldType;
}
else
{
Type arrayOrListType = fieldInfo.FieldType.GetArrayOrListType();
itemType = arrayOrListType ?? fieldInfo.FieldType;
}

Type arrayOrListType = fieldInfo.FieldType.GetArrayOrListType();
Type itemType = arrayOrListType != null ? arrayOrListType : fieldInfo.FieldType;
Initialize(itemType, property.serializedObject.targetObject);
}

collectionItemDropdown = new CollectionItemDropdown(
new AdvancedDropdownState(),
itemType
);
public static System.Reflection.FieldInfo GetFieldViaPath(Type parentType, string path)
{
FieldInfo fieldInfo = parentType.GetField(path);
string[] perDot = path.Split('.');
foreach (string fieldName in perDot)
{
fieldInfo = parentType.GetField(fieldName);
if (fieldInfo == null) return null;
parentType = fieldInfo.FieldType;
}

currentObject = property.serializedObject.targetObject;
initialized = true;
return fieldInfo;
}

internal void Initialize(Type collectionItemType, CollectionItemEditorOptionsAttribute optionsAttribute)
{
Initialize(collectionItemType, (Object)null);
OptionsAttribute = optionsAttribute ?? GetOptionsAttribute();
}

internal void Initialize(Type collectionItemType, Object obj)
{
if (initialized)
return;

collectionItemDropdown = new CollectionItemDropdown(
new AdvancedDropdownState(),
collectionItemType
);

currentObject = obj;
initialized = true;

OptionsAttribute = GetOptionsAttribute();
}

private void DrawCollectionItemDropDown(ref Rect position, ScriptableObjectCollectionItem collectionItem,
Expand All @@ -179,29 +194,33 @@ private void DrawCollectionItemDropDown(ref Rect position, ScriptableObjectColle

if (collectionItem != null)
displayValue = new GUIContent(collectionItem.name);

if (GUI.Button(position, displayValue, EditorStyles.popup))
{
collectionItemDropdown.Show(position, callback.Invoke);
}
}

private void DrawGotoButton(ref Rect popupRect)
private void DrawGotoButton(ref Rect popupRect, ScriptableObjectCollectionItem collectionItem)
{
if (!OptionsAttribute.ShouldDrawGotoButton) return;

Rect buttonRect = popupRect;
buttonRect.width = 30;
buttonRect.height = 18;
popupRect.width -= buttonRect.width;
buttonRect.x += popupRect.width;
if (GUI.Button(buttonRect, CollectionEditorGUI.ARROW_RIGHT_CHAR))
{
Selection.activeObject = item.Collection;
CollectionUtility.SetFoldoutOpen(true, item, item.Collection);
Selection.activeObject = collectionItem.Collection;
CollectionUtility.SetFoldoutOpen(true, collectionItem, collectionItem.Collection);
}
}

private void DrawEditFoldoutButton(ref Rect popupRect, ScriptableObjectCollectionItem targetItem)
{
if (!OptionsAttribute.ShouldDrawPreviewButton) return;

Rect buttonRect = popupRect;
buttonRect.width = 30;
buttonRect.height = 18;
Expand All @@ -218,6 +237,5 @@ private void DrawEditFoldoutButton(ref Rect popupRect, ScriptableObjectCollectio
ObjectUtility.SetDirty(targetItem);
}
}

}
}
Loading