Skip to content

Commit 9eca097

Browse files
authored
Merge pull request #153 from brunomikoski/feature/fix-item-picker-editor-usage
Feature/fix item picker editor usage
2 parents 75087cc + 7295c20 commit 9eca097

File tree

6 files changed

+169
-27
lines changed

6 files changed

+169
-27
lines changed

CHANGELOG.MD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
## [2.3.4]
89
## Changed
910
- Update PickerPropertyDrawer to use PopupList from property path cache to avoid issue when rendered inside a List/Array
1011
- Update CollectionRegistry to search for the ScriptableObjectCollection using the `AssetDatabase.FindAssets` instead of the `TypeCache` first
1112
- Added confirmation popup for deleting items from the Collection
1213
- Fixed issue while renaming one asset could be canceled on arrow keys press
14+
- Fix removing wrong usages of ApplyModifiedProperties
15+
- Fixed issue with the CollectionItemPicker not updating the collection properly on editor mode
1316

1417
## [2.3.3]
1518
## Added
@@ -577,6 +580,7 @@ public bool IsValidConsumable(Consumable consumable)
577580
### Added
578581
- First initial working version
579582

583+
[2.3.4]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.4
580584
[2.3.3]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.3
581585
[2.3.2]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.2
582586
[2.3.1]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.1

Scripts/Editor/Extensions/SerializedPropertyExtensions.cs

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
25
using System.Reflection;
36
using UnityEditor;
47
using UnityEngine;
8+
using Object = UnityEngine.Object;
59

610
namespace BrunoMikoski.ScriptableObjectCollections
711
{
@@ -108,5 +112,143 @@ public static void SetValue(this SerializedProperty serializedProperty, object v
108112
break;
109113
}
110114
}
115+
116+
public static T GetActualObject<T>(this SerializedProperty property, FieldInfo fieldInfo)
117+
where T : class
118+
{
119+
string label = string.Empty;
120+
return property.GetActualObjectForSerializedProperty<T>(fieldInfo, ref label);
121+
}
122+
123+
/// <summary>
124+
/// Used to extract the target object from a serialized property.
125+
/// NOTE: This implementation comes from Unity's own Addressables package.
126+
/// </summary>
127+
/// <typeparam name="T">The type of the object to extract.</typeparam>
128+
/// <param name="property">The property containing the object.</param>
129+
/// <param name="field">The field data.</param>
130+
/// <param name="label">The label name.</param>
131+
/// <returns>Returns the target object type.</returns>
132+
public static T GetActualObjectForSerializedProperty<T>(
133+
this SerializedProperty property, FieldInfo field, ref string label)
134+
{
135+
try
136+
{
137+
if (property == null || field == null)
138+
return default;
139+
140+
SerializedObject serializedObject = property.serializedObject;
141+
if (serializedObject == null)
142+
return default;
143+
144+
Object targetObject = serializedObject.targetObject;
145+
146+
if (property.depth > 0)
147+
{
148+
List<string> slicedName = property.propertyPath.Split('.').ToList();
149+
List<int> arrayCounts = new List<int>();
150+
for (int index = 0; index < slicedName.Count; index++)
151+
{
152+
arrayCounts.Add(-1);
153+
string currName = slicedName[index];
154+
if (currName.EndsWith("]"))
155+
{
156+
string[] arraySlice = currName.Split('[', ']');
157+
if (arraySlice.Length >= 2)
158+
{
159+
arrayCounts[index - 2] = Convert.ToInt32(arraySlice[1]);
160+
slicedName[index] = string.Empty;
161+
slicedName[index - 1] = string.Empty;
162+
}
163+
}
164+
}
165+
166+
while (string.IsNullOrEmpty(slicedName.Last()))
167+
{
168+
int i = slicedName.Count - 1;
169+
slicedName.RemoveAt(i);
170+
arrayCounts.RemoveAt(i);
171+
}
172+
173+
if (property.propertyPath.EndsWith("]"))
174+
{
175+
string[] slice = property.propertyPath.Split('[', ']');
176+
if (slice.Length >= 2)
177+
label = "Element " + slice[slice.Length - 2];
178+
}
179+
180+
return DescendHierarchy<T>(targetObject, slicedName, arrayCounts, 0);
181+
}
182+
183+
object obj = field.GetValue(targetObject);
184+
return (T)obj;
185+
}
186+
catch
187+
{
188+
return default;
189+
}
190+
}
191+
192+
static T DescendHierarchy<T>(object targetObject, List<string> splitName, List<int> splitCounts, int depth)
193+
{
194+
if (depth >= splitName.Count)
195+
return default;
196+
197+
string currName = splitName[depth];
198+
199+
if (string.IsNullOrEmpty(currName))
200+
return DescendHierarchy<T>(targetObject, splitName, splitCounts, depth + 1);
201+
202+
int arrayIndex = splitCounts[depth];
203+
204+
FieldInfo newField = targetObject.GetType().GetField(
205+
currName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
206+
207+
if (newField == null)
208+
{
209+
Type baseType = targetObject.GetType().BaseType;
210+
while (baseType != null && newField == null)
211+
{
212+
newField = baseType.GetField(
213+
currName,
214+
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
215+
baseType = baseType.BaseType;
216+
}
217+
}
218+
219+
object newObj = newField.GetValue(targetObject);
220+
if (depth == splitName.Count - 1)
221+
{
222+
T actualObject = default(T);
223+
if (arrayIndex >= 0)
224+
{
225+
if (newObj.GetType().IsArray && ((Array)newObj).Length > arrayIndex)
226+
actualObject = (T)((Array)newObj).GetValue(arrayIndex);
227+
228+
if (newObj is IList newObjList && newObjList.Count > arrayIndex)
229+
{
230+
actualObject = (T)newObjList[arrayIndex];
231+
232+
//if (actualObject == null)
233+
// actualObject = new T();
234+
}
235+
}
236+
else
237+
{
238+
actualObject = (T)newObj;
239+
}
240+
241+
return actualObject;
242+
}
243+
else if (arrayIndex >= 0)
244+
{
245+
if (newObj is IList list)
246+
newObj = list[arrayIndex];
247+
else if (newObj is Array a)
248+
newObj = a.GetValue(arrayIndex);
249+
}
250+
251+
return DescendHierarchy<T>(newObj, splitName, splitCounts, depth + 1);
252+
}
111253
}
112-
}
254+
}

Scripts/Editor/PropertyDrawers/CollectionItemIndirectReferencePropertyDrawer.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten
7373

7474
private void DrawItemDrawer(Rect position, SerializedProperty property, GUIContent label, ScriptableObject collectionItem)
7575
{
76-
collectionItemPropertyDrawer.DrawCollectionItemDrawer(ref position, property, collectionItem, label, item =>
77-
{
78-
SetSerializedPropertyGUIDs(item);
79-
drawingProperty.serializedObject.ApplyModifiedProperties();
80-
});
76+
collectionItemPropertyDrawer.DrawCollectionItemDrawer(ref position, property, collectionItem, label, SetSerializedPropertyGUIDs);
8177
}
8278

8379
private void SetSerializedPropertyGUIDs(ScriptableObject item)
@@ -156,4 +152,4 @@ private SOCItemEditorOptionsAttribute GetOptionsAttribute()
156152
return null;
157153
}
158154
}
159-
}
155+
}

Scripts/Editor/PropertyDrawers/CollectionItemPickerPropertyDrawer.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class CollectionItemPickerPropertyDrawer : PropertyDrawer
1717
private const string COLLECTION_GUID_VALUE_A = "collectionGUIDValueA";
1818
private const string COLLECTION_GUID_VALUE_B = "collectionGUIDValueB";
1919

20-
private const string ITEMS_PROPERTY_NAME = "cachedIndirectReferences";
20+
private const string ITEMS_PROPERTY_NAME = "indirectReferences";
2121

2222
private static GUIStyle labelStyle;
2323
private static GUIStyle buttonStyle;
@@ -158,7 +158,6 @@ private void CreatAndAddNewItems(SerializedProperty property)
158158
itemsProperty.arraySize++;
159159

160160
AssignItemGUIDToProperty(newItem, itemsProperty.GetArrayElementAtIndex(itemsProperty.arraySize - 1));
161-
itemsProperty.serializedObject.ApplyModifiedProperties();
162161
}
163162

164163
private void GetValuesFromPopup(PopupList<PopupItem> popupList, SerializedProperty property)
@@ -188,23 +187,21 @@ private void GetValuesFromPopup(PopupList<PopupItem> popupList, SerializedProper
188187
propertyArrayIndex++;
189188
}
190189
}
191-
192-
itemsProperty.serializedObject.ApplyModifiedProperties();
193190
}
194191

195192
private void AssignItemGUIDToProperty(ScriptableObject scriptableObject, SerializedProperty newProperty)
196193
{
197-
if (scriptableObject is ISOCItem item)
198-
{
199-
(long, long) itemValues = item.GUID.GetRawValues();
200-
(long, long) collectionValues = item.Collection.GUID.GetRawValues();
194+
if (scriptableObject is not ISOCItem item)
195+
return;
201196

202-
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_A).longValue = itemValues.Item1;
203-
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_B).longValue = itemValues.Item2;
197+
(long, long) itemValues = item.GUID.GetRawValues();
198+
(long, long) collectionValues = item.Collection.GUID.GetRawValues();
204199

205-
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_A).longValue = collectionValues.Item1;
206-
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_B).longValue = collectionValues.Item2;
207-
}
200+
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_A).longValue = itemValues.Item1;
201+
newProperty.FindPropertyRelative(COLLECTION_ITEM_GUID_VALUE_B).longValue = itemValues.Item2;
202+
203+
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_A).longValue = collectionValues.Item1;
204+
newProperty.FindPropertyRelative(COLLECTION_GUID_VALUE_B).longValue = collectionValues.Item2;
208205
}
209206

210207
private void SetSelectedValuesOnPopup(PopupList<PopupItem> popupList, SerializedProperty property)

Scripts/Editor/PropertyDrawers/CollectionItemPropertyDrawer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten
102102
newItem =>
103103
{
104104
property.objectReferenceValue = newItem;
105-
property.serializedObject.ApplyModifiedProperties();
106105
});
107106
}
108107
EditorGUI.EndProperty();

Scripts/Runtime/Core/CollectionItemPicker.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using UnityEngine;
5+
using UnityEngine.Serialization;
56

67
namespace BrunoMikoski.ScriptableObjectCollections.Picker
78
{
@@ -13,10 +14,8 @@ namespace BrunoMikoski.ScriptableObjectCollections.Picker
1314
public class CollectionItemPicker<TItemType> : IList<TItemType>, IEquatable<IList<TItemType>>, IEquatable<CollectionItemPicker<TItemType>>
1415
where TItemType : ScriptableObject, ISOCItem
1516
{
16-
[SerializeField]
17-
private List<CollectionItemIndirectReference<TItemType>> cachedIndirectReferences = new();
18-
19-
private List<CollectionItemIndirectReference<TItemType>> indirectReferences => cachedIndirectReferences;
17+
[SerializeField, FormerlySerializedAs("cachedIndirectReferences")]
18+
private List<CollectionItemIndirectReference<TItemType>> indirectReferences = new();
2019

2120
public event Action<TItemType> OnItemTypeAddedEvent;
2221
public event Action<TItemType> OnItemTypeRemovedEvent;
@@ -28,7 +27,7 @@ public List<TItemType> Items
2827
{
2928
get
3029
{
31-
if (isDirty)
30+
if (!Application.isPlaying || isDirty)
3231
{
3332
cachedItems.Clear();
3433

@@ -104,6 +103,11 @@ public bool HasNone(params TItemType[] itemTypes)
104103
//Implement mathematical operators
105104
#region Operators
106105

106+
public static implicit operator List<TItemType>(CollectionItemPicker<TItemType> targetPicker)
107+
{
108+
return targetPicker.Items;
109+
}
110+
107111
public static CollectionItemPicker<TItemType> operator +(CollectionItemPicker<TItemType> picker1,
108112
CollectionItemPicker<TItemType> picker2)
109113
{
@@ -261,7 +265,7 @@ public bool Remove(TItemType item)
261265

262266
public int IndexOf(TItemType item)
263267
{
264-
return indirectReferences.FindIndex(reference => reference.Ref.GUID== item.GUID);
268+
return indirectReferences.FindIndex(reference => reference.Ref.GUID == item.GUID);
265269
}
266270

267271
public void Insert(int index, TItemType item)

0 commit comments

Comments
 (0)