Skip to content

Commit 45a2586

Browse files
committed
add: more tweaks
1 parent 56f21b7 commit 45a2586

8 files changed

Lines changed: 323 additions & 95 deletions

File tree

Scripts/Editor/Core/SOCSettings.cs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@ public static SOCSettings Instance
6565
[SerializeField]
6666
private string generatedScriptsDefaultFilePath = @"Assets\Generated\Scripts";
6767
public string GeneratedScriptsDefaultFilePath => generatedScriptsDefaultFilePath;
68-
6968

69+
[SerializeField]
70+
private List<LongGuid> useCustomEditorDrawer = new List<LongGuid>();
71+
72+
7073
private static readonly GUIContent namespacePrefixGUIContent = new GUIContent(
7174
"Prefix",
7275
"When using the Create New Collection wizard," +
@@ -156,12 +159,37 @@ public void SetGeneratedScriptsDefaultFilePath(string assetPath)
156159
generatedScriptsDefaultFilePath = assetPath;
157160
Save();
158161
}
159-
162+
160163
public void Save()
161164
{
162165
string json = EditorJsonUtility.ToJson(this, prettyPrint: true);
163166
File.WriteAllText(STORAGE_PATH, json);
164167
}
165168

169+
170+
public bool ShouldDrawUsingCustomEditor(ScriptableObjectCollection collection)
171+
{
172+
return useCustomEditorDrawer.Contains(collection.GUID);
173+
}
174+
175+
public void SetUseCustomEditor(ScriptableObjectCollection collection, bool useCustomEditor)
176+
{
177+
if (useCustomEditor)
178+
{
179+
if (!useCustomEditorDrawer.Contains(collection.GUID))
180+
{
181+
useCustomEditorDrawer.Add(collection.GUID);
182+
Save();
183+
}
184+
}
185+
else
186+
{
187+
if (useCustomEditorDrawer.Contains(collection.GUID))
188+
{
189+
useCustomEditorDrawer.Remove(collection.GUID);
190+
Save();
191+
}
192+
}
193+
}
166194
}
167195
}

Scripts/Editor/CustomEditors/CollectionCustomEditor.cs

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ private void OnClickToAddNewItem(Rect buttonRect, ReorderableList list)
130130
private float GetCollectionItemHeight(int index)
131131
{
132132
if (itemHidden == null || itemHidden.Length == 0 || itemHidden[index] || index > itemHidden.Length - 1)
133-
return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
133+
return 0;
134134

135135
return Mathf.Max(
136136
heights[index],
@@ -169,6 +169,9 @@ private void DrawCollectionItemAtIndex(Rect rect, int index, bool isActive, bool
169169
if (Event.current.alt)
170170
SetAllExpanded(false);
171171
}
172+
173+
if(wasExpanded != collectionItemSerializedProperty.isExpanded)
174+
itemIndexToRect.Clear();
172175

173176
using (EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope())
174177
{
@@ -208,52 +211,91 @@ private void DrawCollectionItemAtIndex(Rect rect, int index, bool isActive, bool
208211

209212
if (collectionItemSerializedProperty.isExpanded)
210213
{
211-
rect.y += EditorGUIUtility.standardVerticalSpacing;
214+
rect.y += EditorGUIUtility.standardVerticalSpacing;
215+
216+
if (SOCSettings.Instance.ShouldDrawUsingCustomEditor(collection))
217+
DrawCustomEditor(ref rect, index, collectionItemSerializedProperty);
218+
else
219+
DrawProperties(ref rect, index, collectionItemSerializedProperty);
220+
}
212221

213-
if (itemIndexToRect.TryGetValue(index, out Rect actualRect) && reorderableListYPosition.HasValue)
222+
CheckForContextInputOnItem(collectionItemSerializedProperty, index, originY, rect);
223+
224+
heights[index] = rect.y - originY;
225+
}
226+
227+
private void DrawProperties(ref Rect rect, int index, SerializedProperty collectionItemSerializedProperty)
228+
{
229+
EditorGUI.indentLevel++;
230+
231+
SerializedObject collectionItemSerializedObject = new SerializedObject(collectionItemSerializedProperty.objectReferenceValue);
232+
SerializedProperty iterator = collectionItemSerializedObject.GetIterator();
233+
234+
using (EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope())
235+
{
236+
for (bool enterChildren = true; iterator.NextVisible(enterChildren); enterChildren = false)
214237
{
215-
actualRect.y = rect.y + reorderableListYPosition.Value + reorderableList.headerHeight;
238+
bool guiEnabled = GUI.enabled;
239+
if (iterator.displayName.Equals("Script"))
240+
GUI.enabled = false;
216241

217-
// Have to indent the rect here because otherwise it overlaps with the drag handle
218-
EditorGUI.indentLevel++;
219-
actualRect = EditorGUI.IndentedRect(actualRect);
220-
EditorGUI.indentLevel--;
242+
EditorGUI.PropertyField(rect, iterator, true);
243+
GUI.enabled = guiEnabled;
244+
245+
rect.y += EditorGUI.GetPropertyHeight(iterator, true) +
246+
EditorGUIUtility.standardVerticalSpacing;
247+
}
221248

222-
GUILayout.BeginArea(actualRect);
223-
EditorGUI.indentLevel++;
249+
if (changeCheck.changed)
250+
iterator.serializedObject.ApplyModifiedProperties();
251+
}
252+
EditorGUI.indentLevel--;
253+
}
224254

225-
Editor editor = EditorCache.GetOrCreateEditorForObject(collectionItemSerializedProperty.objectReferenceValue);
226-
editor.OnInspectorGUI();
255+
private void DrawCustomEditor(ref Rect rect, int index, SerializedProperty collectionItemSerializedProperty)
256+
{
257+
Editor editor = EditorCache.GetOrCreateEditorForObject(collectionItemSerializedProperty.objectReferenceValue);
227258

228-
EditorGUI.indentLevel--;
229-
GUILayout.EndArea();
259+
if (itemIndexToRect.TryGetValue(index, out Rect actualRect) && reorderableListYPosition.HasValue)
260+
{
261+
actualRect.y = rect.y + reorderableListYPosition.Value + reorderableList.headerHeight;
262+
263+
// Have to indent the rect here because otherwise it overlaps with the drag handle
264+
EditorGUI.indentLevel++;
265+
actualRect = EditorGUI.IndentedRect(actualRect);
266+
EditorGUI.indentLevel--;
267+
268+
GUILayout.BeginArea(actualRect);
269+
EditorGUI.indentLevel++;
230270

271+
EditorGUI.BeginChangeCheck();
272+
editor.OnInspectorGUI();
273+
274+
EditorGUI.indentLevel--;
275+
GUILayout.EndArea();
276+
277+
if (EditorGUI.EndChangeCheck())
278+
{
231279
collectionItemSerializedProperty.serializedObject.ApplyModifiedProperties();
232-
rect.y += actualRect.height;
233280
}
234-
else
235-
{
236-
Rect verticalRect = EditorGUILayout.BeginVertical();
237-
238-
Editor editor = EditorCache.GetOrCreateEditorForObject(collectionItemSerializedProperty.objectReferenceValue);
239-
editor.OnInspectorGUI();
240281

241-
EditorGUILayout.EndVertical();
282+
rect.y += actualRect.height;
283+
}
284+
else
285+
{
286+
Rect verticalRect = EditorGUILayout.BeginVertical();
242287

243-
if (Event.current.type == EventType.Repaint)
244-
{
245-
itemIndexToRect[index] = verticalRect;
246-
}
288+
editor.OnInspectorGUI();
289+
290+
EditorGUILayout.EndVertical();
291+
292+
if (Event.current.type == EventType.Repaint)
293+
{
294+
itemIndexToRect[index] = verticalRect;
247295
}
248296
}
249-
250-
CheckForContextInputOnItem(collectionItemSerializedProperty, index, originY, rect);
251-
252-
heights[index] = rect.y - originY;
253297
}
254298

255-
256-
257299
private void SetAllExpanded(bool expanded)
258300
{
259301
for (int i = 0; i < reorderableList.count; i++)
@@ -670,6 +712,8 @@ private void DrawSettings()
670712
DrawUseBaseClassToggle();
671713
DrawGeneratedFileName();
672714
DrawGeneratedFileNamespace();
715+
DrawDrawOptions();
716+
673717
GUILayout.Space(10);
674718
DrawDeleteCollection();
675719

@@ -678,6 +722,16 @@ private void DrawSettings()
678722
}
679723
}
680724

725+
private void DrawDrawOptions()
726+
{
727+
using EditorGUI.ChangeCheckScope changeCheck = new EditorGUI.ChangeCheckScope();
728+
bool drawUsingCustomEditor = EditorGUILayout.Toggle("Use Custom Editor", SOCSettings.Instance.ShouldDrawUsingCustomEditor(collection));
729+
if (changeCheck.changed)
730+
{
731+
SOCSettings.Instance.SetUseCustomEditor(collection, drawUsingCustomEditor);
732+
}
733+
}
734+
681735
private void DrawDeleteCollection()
682736
{
683737
Color backgroundColor = GUI.backgroundColor;

Scripts/Editor/PropertyDrawers/CollectionItemPickerPropertyDrawer.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ namespace BrunoMikoski.ScriptableObjectCollections.Picker
1111
[CustomPropertyDrawer(typeof(CollectionItemPicker<>), true)]
1212
public class CollectionItemPickerPropertyDrawer : PropertyDrawer
1313
{
14-
private const string LONG_GUID_VALUE_1_PROPERTY_PATH = "value1";
15-
private const string LONG_GUID_VALUE_2_PROPERTY_PATH = "value2";
14+
private const string COLLECTION_ITEM_GUID_VALUE_A = "collectionItemGUIDValueA";
15+
private const string COLLECTION_ITEM_GUID_VALUE_B = "collectionItemGUIDValueB";
1616

17-
private const string ITEMS_PROPERTY_NAME = "itemsGuids";
17+
private const string COLLECTION_GUID_VALUE_A = "collectionGUIDValueA";
18+
private const string COLLECTION_GUID_VALUE_B = "collectionGUIDValueB";
19+
20+
private const string ITEMS_PROPERTY_NAME = "cachedIndirectReferences";
1821

1922
private bool initialized;
2023
private PopupList<PopupItem> popupList = new PopupList<PopupItem>();
@@ -174,14 +177,16 @@ private void GetValuesFromPopup(SerializedProperty property)
174177

175178
private void AssignItemGUIDToProperty(ScriptableObject scriptableObject, SerializedProperty newProperty)
176179
{
177-
SerializedProperty itemGUIDValueASerializedProperty = newProperty.FindPropertyRelative(LONG_GUID_VALUE_1_PROPERTY_PATH);
178-
SerializedProperty itemGUIDValueBSerializedProperty = newProperty.FindPropertyRelative(LONG_GUID_VALUE_2_PROPERTY_PATH);
179-
180180
if (scriptableObject is ISOCItem item)
181181
{
182-
(long, long) values = item.GUID.GetRawValues();
183-
itemGUIDValueASerializedProperty.longValue = values.Item1;
184-
itemGUIDValueBSerializedProperty.longValue = values.Item2;
182+
(long, long) itemValues = item.GUID.GetRawValues();
183+
(long, long) collectionValues = item.Collection.GUID.GetRawValues();
184+
185+
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_A).longValue = itemValues.Item1;
186+
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_B).longValue = itemValues.Item2;
187+
188+
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_A).longValue = collectionValues.Item1;
189+
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_B).longValue = collectionValues.Item2;
185190
}
186191
}
187192

@@ -198,7 +203,6 @@ private void SetSelectedValuesOnPopup(SerializedProperty property)
198203

199204
LongGuid socItemGUID = GetGUIDFromProperty(elementProperty);
200205

201-
202206
ScriptableObject foundItem = availableItems.FirstOrDefault(so =>
203207
{
204208
if (so is ISOCItem item)
@@ -232,8 +236,8 @@ private void SetSelectedValuesOnPopup(SerializedProperty property)
232236

233237
private LongGuid GetGUIDFromProperty(SerializedProperty property)
234238
{
235-
SerializedProperty itemGUIDValueASerializedProperty = property.FindPropertyRelative(LONG_GUID_VALUE_1_PROPERTY_PATH);
236-
SerializedProperty itemGUIDValueBSerializedProperty = property.FindPropertyRelative(LONG_GUID_VALUE_2_PROPERTY_PATH);
239+
SerializedProperty itemGUIDValueASerializedProperty = property.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_A);
240+
SerializedProperty itemGUIDValueBSerializedProperty = property.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_B);
237241

238242
return new LongGuid(itemGUIDValueASerializedProperty.longValue, itemGUIDValueBSerializedProperty.longValue);
239243
}

Scripts/Editor/Utils/CopyCollectionItemUtility.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
24
using UnityEditor;
35
using UnityEngine;
6+
using Object = UnityEngine.Object;
47

58
namespace BrunoMikoski.ScriptableObjectCollections
69
{
710
public static class EditorCache
811
{
912
private static Dictionary<object, Editor> typeToEditorCache = new();
1013

14+
private static Dictionary<Type, bool> typeToHasCustomEditorCache = new();
15+
1116
public static Editor GetOrCreateEditorForObject(Object targetObject)
1217
{
1318
if (typeToEditorCache.TryGetValue(targetObject, out Editor editor))
@@ -18,7 +23,41 @@ public static Editor GetOrCreateEditorForObject(Object targetObject)
1823
return editor;
1924
}
2025

26+
public static bool HasCustomEditor(Object objectReferenceValue)
27+
{
28+
Type objectType = objectReferenceValue.GetType();
29+
if(typeToHasCustomEditorCache.TryGetValue(objectType, out bool hasCustomEditor))
30+
return hasCustomEditor;
31+
32+
TypeCache.TypeCollection customEditors = TypeCache.GetTypesWithAttribute<CustomEditor>();
33+
34+
foreach (var type in customEditors)
35+
{
36+
object[] attributes = type.GetCustomAttributes(typeof(CustomEditor), true);
37+
foreach (var attribute in attributes)
38+
{
39+
Type attributeType = attribute.GetType();
40+
41+
// Access the `m_InspectedType` field using reflection
42+
FieldInfo fieldInfo = attributeType.GetField("m_InspectedType", BindingFlags.NonPublic | BindingFlags.Instance);
43+
44+
if (fieldInfo != null)
45+
{
46+
Type inspectedType = fieldInfo.GetValue(attribute) as Type;
47+
48+
if (inspectedType == objectType || inspectedType.IsSubclassOf(objectType))
49+
{
50+
typeToHasCustomEditorCache.Add(objectType, true);
51+
return true;
52+
}
53+
}
54+
}
55+
}
56+
typeToHasCustomEditorCache.Add(objectType, false);
57+
return false;
58+
}
2159
}
60+
2261
public static class CopyCollectionItemUtility
2362
{
2463
private static ScriptableObject source;

0 commit comments

Comments
 (0)