diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 9227b99..1432dc1 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [2.0.3] +### Changed + - Collection now uses the appropriated Editor for each CollectionItem when displayed on the Collection + - Fixed expanded state not being saved on the Collection ## [2.0.2] ### Changed @@ -424,6 +428,7 @@ public bool IsValidConsumable(Consumable consumable) ### Added - First initial working version +[2.0.3]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.0.3 [2.0.2]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.0.2 [2.0.1]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.0.1 [2.0.0]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.0.0 diff --git a/Scripts/Editor/Core/CustomEditors/CollectionCustomEditor.cs b/Scripts/Editor/Core/CustomEditors/CollectionCustomEditor.cs index 795fe49..8aed837 100644 --- a/Scripts/Editor/Core/CustomEditors/CollectionCustomEditor.cs +++ b/Scripts/Editor/Core/CustomEditors/CollectionCustomEditor.cs @@ -28,6 +28,8 @@ public sealed class CollectionCustomEditor : Editor private ReorderableList reorderableList; private SerializedProperty itemsSerializedProperty; private int lastCheckedForValidItemsArraySize; + private readonly Dictionary itemIndexToRect = new(); + private float? reorderableListYPosition; private static bool IsWaitingForNewTypeBeCreated { @@ -185,39 +187,50 @@ private void DrawCollectionItemAtIndex(Rect rect, int index, bool isActive, bool { rect.y += EditorGUIUtility.standardVerticalSpacing; - SerializedObject collectionItemSerializedObject = new SerializedObject(collectionItemSerializedProperty.objectReferenceValue); - - EditorGUI.indentLevel++; - - SerializedProperty iterator = collectionItemSerializedObject.GetIterator(); - - using (EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope()) + if (itemIndexToRect.TryGetValue(index, out Rect actualRect) && reorderableListYPosition.HasValue) { - for (bool enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false) - { - bool guiEnabled = GUI.enabled; - if (iterator.displayName.Equals("Script")) - GUI.enabled = false; + actualRect.y = rect.y + reorderableListYPosition.Value + reorderableList.headerHeight; + + // Have to indent the rect here because otherwise it overlaps with the drag handle + EditorGUI.indentLevel++; + actualRect = EditorGUI.IndentedRect(actualRect); + EditorGUI.indentLevel--; + + GUILayout.BeginArea(actualRect); + EditorGUI.indentLevel++; - EditorGUI.PropertyField(rect, iterator, true); - GUI.enabled = guiEnabled; + Editor editor = EditorCache.GetOrCreateEditorForObject(collectionItemSerializedProperty.objectReferenceValue); + editor.OnInspectorGUI(); - rect.y += EditorGUI.GetPropertyHeight(iterator, true) + - EditorGUIUtility.standardVerticalSpacing; - } + EditorGUI.indentLevel--; + GUILayout.EndArea(); - if (changeCheck.changed) - iterator.serializedObject.ApplyModifiedProperties(); + collectionItemSerializedProperty.serializedObject.ApplyModifiedProperties(); + rect.y += actualRect.height; } + else + { + Rect verticalRect = EditorGUILayout.BeginVertical(); + + Editor editor = EditorCache.GetOrCreateEditorForObject(collectionItemSerializedProperty.objectReferenceValue); + editor.OnInspectorGUI(); - EditorGUI.indentLevel--; + EditorGUILayout.EndVertical(); + + if (Event.current.type == EventType.Repaint) + { + itemIndexToRect[index] = verticalRect; + } + } } CheckForContextInputOnItem(collectionItemSerializedProperty, index, originY, rect); - + heights[index] = rect.y - originY; } + + private void SetAllExpanded(bool expanded) { for (int i = 0; i < reorderableList.count; i++) @@ -344,6 +357,10 @@ public override void OnInspectorGUI() DrawSearchField(); DrawSynchronizeButton(); reorderableList.DoLayoutList(); + if (Event.current.type == EventType.Repaint) + { + reorderableListYPosition = GUILayoutUtility.GetLastRect().y; + } DrawBottomMenu(); } DrawSettings(); diff --git a/Scripts/Editor/Core/PropertyDrawers/SOCItemPropertyDrawer.cs b/Scripts/Editor/Core/PropertyDrawers/SOCItemPropertyDrawer.cs index 8ac63e8..9f558df 100644 --- a/Scripts/Editor/Core/PropertyDrawers/SOCItemPropertyDrawer.cs +++ b/Scripts/Editor/Core/PropertyDrawers/SOCItemPropertyDrawer.cs @@ -103,7 +103,7 @@ private void DrawEditorPreview(ref Rect rect, ScriptableObject scriptableObject) if (scriptableObject == null) return; - if (!CollectionUtility.IsFoldoutOpen(scriptableObject, currentObject)) + if (!CollectionUtility.IsCollectionItemExpanded((ISOCItem) scriptableObject)) return; rect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; @@ -111,13 +111,13 @@ private void DrawEditorPreview(ref Rect rect, ScriptableObject scriptableObject) rect.y += 10; float beginPositionY = rect.y; - SerializedObject collectionItemSerializedObject = new SerializedObject(scriptableObject); + SerializedObject collectionItemSerializedObject = new(scriptableObject); EditorGUI.indentLevel++; rect = EditorGUI.IndentedRect(rect); SerializedProperty iterator = collectionItemSerializedObject.GetIterator(); - using (EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope()) + using (EditorGUI.ChangeCheckScope changeCheck = new()) { for (bool enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false) { @@ -225,7 +225,7 @@ private void DrawGotoButton(ref Rect popupRect, ScriptableObject collectionItem) if (GUI.Button(buttonRect, CollectionEditorGUI.ARROW_RIGHT_CHAR)) { Selection.activeObject = socItem.Collection; - CollectionUtility.SetFoldoutOpen(true, collectionItem, socItem.Collection); + CollectionUtility.SetOnlyCollectionItemExpanded((ISOCItem) collectionItem, socItem.Collection); } } @@ -241,12 +241,14 @@ private void DrawEditFoldoutButton(ref Rect popupRect, ScriptableObject targetIt buttonRect.x += popupRect.width; GUIContent guiContent = CollectionEditorGUI.EditGUIContent; - if (CollectionUtility.IsFoldoutOpen(targetItem, currentObject)) + + if (CollectionUtility.IsCollectionItemExpanded((ISOCItem) targetItem)) guiContent = CollectionEditorGUI.CloseGUIContent; if (GUI.Button(buttonRect, guiContent)) { - CollectionUtility.SetFoldoutOpen(!CollectionUtility.IsFoldoutOpen(targetItem, currentObject), targetItem, currentObject); + CollectionUtility.SetCollectionItemExpanded(!CollectionUtility.IsCollectionItemExpanded((ISOCItem) targetItem), (ISOCItem) targetItem); + ObjectUtility.SetDirty(targetItem); } } diff --git a/Scripts/Editor/Core/Utility/CopyCollectionItemUtility.cs b/Scripts/Editor/Core/Utility/CopyCollectionItemUtility.cs index 24581b0..07a9c7c 100644 --- a/Scripts/Editor/Core/Utility/CopyCollectionItemUtility.cs +++ b/Scripts/Editor/Core/Utility/CopyCollectionItemUtility.cs @@ -1,8 +1,24 @@ -using UnityEditor; +using System.Collections.Generic; +using UnityEditor; using UnityEngine; namespace BrunoMikoski.ScriptableObjectCollections { + public static class EditorCache + { + private static Dictionary typeToEditorCache = new(); + + public static Editor GetOrCreateEditorForObject(Object targetObject) + { + if (typeToEditorCache.TryGetValue(targetObject, out Editor editor)) + return editor; + + editor = Editor.CreateEditor(targetObject); + typeToEditorCache.Add(targetObject, editor); + return editor; + } + + } public static class CopyCollectionItemUtility { private static ScriptableObject source; diff --git a/Scripts/Editor/Utils/CollectionUtility.cs b/Scripts/Editor/Utils/CollectionUtility.cs index 1134711..ef708c7 100644 --- a/Scripts/Editor/Utils/CollectionUtility.cs +++ b/Scripts/Editor/Utils/CollectionUtility.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using UnityEditor; +using UnityEngine; using Object = UnityEngine.Object; namespace BrunoMikoski.ScriptableObjectCollections @@ -36,12 +38,54 @@ public static bool IsFoldoutOpen(params Object[] objects) return value; } + - public static void SetFoldoutOpen(bool value, params Object[] objects) + public static void SetCollectionItemExpanded(bool isExpanded, ISOCItem targetItem) { - int hashCount = GetHasCount(objects); + ScriptableObjectCollection collection = targetItem.Collection; + SetCollectionItemExpanded(isExpanded, targetItem, collection); + } + + public static bool IsCollectionItemExpanded(ISOCItem targetItem) + { + SerializedObject collectionSerializedObject = new SerializedObject(targetItem.Collection); + SerializedProperty itemsProperty = collectionSerializedObject.FindProperty("items"); + for (int i = 0; i < itemsProperty.arraySize; i++) + { + SerializedProperty itemProperty = itemsProperty.GetArrayElementAtIndex(i); + if (itemProperty.objectReferenceValue == (Object) targetItem) + { + return itemProperty.isExpanded; + } + } + + return false; + } - objectToFoldOut[hashCount] = value; + public static void SetCollectionItemExpanded(bool isExpanded, ISOCItem collectionItem, ScriptableObjectCollection collection) + { + SerializedObject collectionSerializedObject = new SerializedObject(collection); + SerializedProperty itemsProperty = collectionSerializedObject.FindProperty("items"); + for (int i = 0; i < itemsProperty.arraySize; i++) + { + SerializedProperty itemProperty = itemsProperty.GetArrayElementAtIndex(i); + if (itemProperty.objectReferenceValue == (Object) collectionItem) + { + itemProperty.isExpanded = isExpanded; + break; + } + } + } + + public static void SetOnlyCollectionItemExpanded(ISOCItem collectionItem, ScriptableObjectCollection collection) + { + SerializedObject collectionSerializedObject = new SerializedObject(collection); + SerializedProperty itemsProperty = collectionSerializedObject.FindProperty("items"); + for (int i = 0; i < itemsProperty.arraySize; i++) + { + SerializedProperty itemProperty = itemsProperty.GetArrayElementAtIndex(i); + itemProperty.isExpanded = itemProperty.objectReferenceValue == (Object) collectionItem; + } } } } diff --git a/package.json b/package.json index a0ffa61..a907550 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.brunomikoski.scriptableobjectcollection", "displayName": "Scriptable Object Collection", - "version": "2.0.2", + "version": "2.0.3", "unity": "2021.2", "description": "A library to help improve the usability of Unity3D Scriptable Objects by grouping then into a collection and exposing then by code or nice inspectors!", "keywords": [