Skip to content

Commit 899ac1e

Browse files
authored
Merge pull request #179 from brunomikoski/feature/small-fixes
Feature/small fixes
2 parents dda8a84 + 1da9eec commit 899ac1e

File tree

6 files changed

+176
-39
lines changed

6 files changed

+176
-39
lines changed

Scripts/Editor/Browser/BrowserEditorWindow.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ private static void Init()
1919
private const float DIVIDER_MAXIMUM = 0.8f;
2020

2121
private BrowserTreeView treeView;
22+
#if UNITY_6000_0_OR_NEWER
23+
private TreeViewState<int> treeViewState;
24+
#else
2225
private TreeViewState treeViewState;
26+
#endif
2327
private Editor itemEditor;
2428
private Vector2 scrollPosition;
2529
private int separatorPosition = 250;
@@ -29,7 +33,11 @@ private static void Init()
2933

3034
private void OnEnable()
3135
{
36+
#if UNITY_6000_0_OR_NEWER
37+
treeViewState ??= new TreeViewState<int>();
38+
#else
3239
treeViewState ??= new TreeViewState();
40+
#endif
3341
treeView = new BrowserTreeView(treeViewState);
3442
treeView.ItemClicked += OnItemClicked;
3543

Scripts/Editor/Browser/BrowserTreeView.cs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
namespace BrunoMikoski.ScriptableObjectCollections.Browser
77
{
8+
#if UNITY_6000_0_OR_NEWER
9+
public class BrowserTreeView : TreeView<int>
10+
#else
811
public class BrowserTreeView : TreeView
12+
#endif
913
{
1014
public delegate void ItemClickedDelegate(BrowserTreeViewItem item);
1115

@@ -16,6 +20,19 @@ public class BrowserTreeView : TreeView
1620
private readonly GUIContent showHiddenCollectionsContent = new("Show Hidden Collections");
1721
private readonly GUIContent hideHiddenCollectionsContent = new("Hide Hidden Collections");
1822

23+
#if UNITY_6000_0_OR_NEWER
24+
public BrowserTreeView(TreeViewState<int> state)
25+
: base(state)
26+
{
27+
Initialize();
28+
}
29+
30+
public BrowserTreeView(TreeViewState<int> state, MultiColumnHeader multiColumnHeader)
31+
: base(state, multiColumnHeader)
32+
{
33+
Initialize();
34+
}
35+
#else
1936
public BrowserTreeView(TreeViewState state)
2037
: base(state)
2138
{
@@ -27,16 +44,18 @@ public BrowserTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader)
2744
{
2845
Initialize();
2946
}
47+
#endif
3048

3149
private void Initialize()
3250
{
3351
showAlternatingRowBackgrounds = true;
3452
Reload();
3553
}
3654

37-
protected override TreeViewItem BuildRoot()
55+
#if UNITY_6000_0_OR_NEWER
56+
protected override TreeViewItem<int> BuildRoot()
3857
{
39-
TreeViewItem root = new(0, -1);
58+
TreeViewItem<int> root = new(0, -1);
4059
int id = 1;
4160

4261
string[] scriptableObjectCollections = AssetDatabase.FindAssets("t:ScriptableObjectCollection");
@@ -63,10 +82,57 @@ protected override TreeViewItem BuildRoot()
6382
root.AddChild(parentItem);
6483
}
6584

85+
if (root.children == null)
86+
{
87+
root.children = new List<TreeViewItem<int>>();
88+
}
89+
90+
return root;
91+
}
92+
#else
93+
protected override TreeViewItem BuildRoot()
94+
{
95+
TreeViewItem root = new TreeViewItem(0, -1);
96+
int id = 1;
97+
98+
string[] scriptableObjectCollections = AssetDatabase.FindAssets("t:ScriptableObjectCollection");
99+
foreach (string guid in scriptableObjectCollections)
100+
{
101+
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
102+
ScriptableObjectCollection collection =
103+
AssetDatabase.LoadAssetAtPath<ScriptableObjectCollection>(assetPath);
104+
105+
if (BrowserSettings.Instance.IsHiddenCollection(collection.GetType()) &&
106+
!BrowserSettings.Instance.ShowHiddenCollections)
107+
{
108+
continue;
109+
}
110+
111+
BrowserTreeViewItem parentItem = new BrowserTreeViewItem(id++, 0, collection);
112+
113+
foreach (ScriptableObject item in collection)
114+
{
115+
BrowserTreeViewItem childItem = new BrowserTreeViewItem(id++, 1, item);
116+
parentItem.AddChild(childItem);
117+
}
118+
119+
root.AddChild(parentItem);
120+
}
121+
122+
if (root.children == null)
123+
{
124+
root.children = new List<TreeViewItem>();
125+
}
126+
66127
return root;
67128
}
129+
#endif
68130

131+
#if UNITY_6000_0_OR_NEWER
132+
protected override bool CanMultiSelect(TreeViewItem<int> item)
133+
#else
69134
protected override bool CanMultiSelect(TreeViewItem item)
135+
#endif
70136
{
71137
return false;
72138
}
@@ -76,7 +142,11 @@ protected override void SelectionChanged(IList<int> selectedIds)
76142
if (selectedIds.Count != 1)
77143
return;
78144

145+
#if UNITY_6000_0_OR_NEWER
146+
TreeViewItem<int> item = FindItem(selectedIds[0], rootItem);
147+
#else
79148
TreeViewItem item = FindItem(selectedIds[0], rootItem);
149+
#endif
80150

81151
if (item is BrowserTreeViewItem treeViewItem)
82152
{
@@ -86,7 +156,11 @@ protected override void SelectionChanged(IList<int> selectedIds)
86156

87157
protected override void SingleClickedItem(int id)
88158
{
159+
#if UNITY_6000_0_OR_NEWER
160+
TreeViewItem<int> item = FindItem(id, rootItem);
161+
#else
89162
TreeViewItem item = FindItem(id, rootItem);
163+
#endif
90164

91165
if (item is BrowserTreeViewItem treeViewItem)
92166
{
@@ -96,7 +170,11 @@ protected override void SingleClickedItem(int id)
96170

97171
protected override void DoubleClickedItem(int id)
98172
{
173+
#if UNITY_6000_0_OR_NEWER
174+
TreeViewItem<int> item = FindItem(id, rootItem);
175+
#else
99176
TreeViewItem item = FindItem(id, rootItem);
177+
#endif
100178

101179
if (item is BrowserTreeViewItem treeViewItem)
102180
{
@@ -106,7 +184,11 @@ protected override void DoubleClickedItem(int id)
106184

107185
protected override void ContextClickedItem(int id)
108186
{
187+
#if UNITY_6000_0_OR_NEWER
188+
TreeViewItem<int> item = FindItem(id, rootItem);
189+
#else
109190
TreeViewItem item = FindItem(id, rootItem);
191+
#endif
110192

111193
if (item is not BrowserTreeViewItem treeViewItem)
112194
return;

Scripts/Editor/Browser/BrowserTreeViewItem.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
namespace BrunoMikoski.ScriptableObjectCollections.Browser
55
{
6+
#if UNITY_6000_0_OR_NEWER
7+
public class BrowserTreeViewItem : TreeViewItem<int>
8+
#else
69
public class BrowserTreeViewItem : TreeViewItem
10+
#endif
711
{
812
public ScriptableObject ScriptableObject { get; private set; }
913

Scripts/Editor/CustomEditors/CollectionCustomEditor.cs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,10 @@ private void BindCollectionItemListItem(VisualElement targetElement, int targetI
293293

294294
imguiContainer.onGUIHandler = () =>
295295
{
296-
{
297-
editor.OnInspectorGUI();
298-
}
296+
if (editor == null || editor.target == null)
297+
return;
298+
299+
editor.OnInspectorGUI();
299300
};
300301
}
301302

@@ -345,19 +346,14 @@ private void OnKeyUpOnCollectionListView(KeyUpEvent evt)
345346
}
346347
}
347348

348-
private void OnCollectionItemOrderChanged(int fromIndex, int toIndex)
349+
private void OnCollectionItemOrderChanged(int oldIndex, int newIndex)
349350
{
350-
ScriptableObject sourceItem = filteredItems[fromIndex];
351-
ScriptableObject targetItem = filteredItems[toIndex];
352-
353-
int sourceIndex = collection.Items.IndexOf(sourceItem);
354-
int targetIndex = collection.Items.IndexOf(targetItem);
355-
356-
Undo.RecordObject(collection, "Reorder Item");
357-
collection.Items.RemoveAt(sourceIndex);
358-
collection.Items.Insert(targetIndex, sourceItem);
351+
ScriptableObject fromIndexItem = collection.Items[oldIndex];
352+
353+
collection.Items.RemoveAt(oldIndex);
354+
collection.Items.Insert(newIndex, fromIndexItem);
355+
359356
EditorUtility.SetDirty(collection);
360-
361357
ReloadFilteredItems();
362358
}
363359

@@ -1021,7 +1017,6 @@ private void OnFinishRenamingItem(int targetIndex)
10211017
else
10221018
{
10231019
ScriptableObject asset = filteredItems[targetIndex];
1024-
Undo.RecordObject(asset, "Rename Item");
10251020
AssetDatabaseUtils.RenameAsset(asset, targetNewName);
10261021
AssetDatabase.SaveAssetIfDirty(asset);
10271022
}

Scripts/Runtime/Core/ScriptableObjectCollection.cs

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public LongGuid GUID
4444
public bool IsReadOnly => false;
4545

4646
public virtual bool ShouldProtectItemOrder => false;
47+
48+
private Dictionary<string,ScriptableObject> itemNameToScriptableObject = new();
4749

4850
public ScriptableObject this[int index]
4951
{
@@ -258,7 +260,23 @@ public int IndexOf(ScriptableObject item)
258260

259261
public void Insert(int index, ScriptableObject item)
260262
{
261-
items.Insert(index, item);
263+
int existingIndex = items.IndexOf(item);
264+
if (existingIndex >= 0)
265+
{
266+
// If the item already exists in the list, move it to the new index instead of duplicating.
267+
if (existingIndex != index)
268+
{
269+
items.RemoveAt(existingIndex);
270+
if (index > existingIndex)
271+
index--; // Adjust index due to removal shift.
272+
items.Insert(index, item);
273+
}
274+
}
275+
else
276+
{
277+
items.Insert(index, item);
278+
}
279+
262280
if (item is ISOCItem socItem)
263281
socItem.SetCollection(this);
264282

@@ -390,6 +408,18 @@ public void RefreshCollection()
390408
Debug.Log($"Removing item at index {i} {scriptableObject} since it is not of type {GetItemType()}");
391409
}
392410

411+
HashSet<ScriptableObject> seen = new HashSet<ScriptableObject>();
412+
for (int i = items.Count - 1; i >= 0; i--)
413+
{
414+
ScriptableObject obj = items[i];
415+
if (!seen.Add(obj))
416+
{
417+
RemoveAt(i);
418+
Debug.Log($"Removing duplicated reference to item {obj} at index {i}");
419+
changed = true;
420+
}
421+
}
422+
393423
if (itemsFromOtherCollections.Any())
394424
{
395425
int result = EditorUtility.DisplayDialogComplex("Items from another collections",
@@ -435,20 +465,33 @@ public void RefreshCollection()
435465
#endif
436466
}
437467

438-
public bool TryGetItemByName(string targetItemName, out ScriptableObject scriptableObjectCollectionItem)
468+
public void CacheItemNames()
439469
{
470+
itemNameToScriptableObject.Clear();
440471
for (int i = 0; i < items.Count; i++)
441472
{
442473
ScriptableObject item = items[i];
443-
if (string.Equals(item.name, targetItemName, StringComparison.Ordinal))
474+
itemNameToScriptableObject.TryAdd(item.name, item);
475+
}
476+
}
477+
478+
public bool TryGetItemByName(string targetItemName, out ScriptableObject scriptableObjectCollectionItem, StringComparison stringComparison = StringComparison.Ordinal)
479+
{
480+
if (!itemNameToScriptableObject.TryGetValue(targetItemName, out scriptableObjectCollectionItem))
481+
{
482+
for (int i = 0; i < items.Count; i++)
444483
{
445-
scriptableObjectCollectionItem = item;
446-
return true;
484+
ScriptableObject item = items[i];
485+
if (string.Equals(item.name, targetItemName, stringComparison))
486+
{
487+
scriptableObjectCollectionItem = item;
488+
itemNameToScriptableObject[targetItemName] = item;
489+
break;
490+
}
447491
}
448492
}
449493

450-
scriptableObjectCollectionItem = null;
451-
return false;
494+
return scriptableObjectCollectionItem != null;
452495
}
453496

454497
public bool TryGetItemByGUID<T>(LongGuid itemGUID, out T scriptableObjectCollectionItem)
@@ -503,6 +546,8 @@ public static IReadOnlyList<TObjectType> Values
503546
get => (TObjectType)base[index];
504547
set => base[index] = value;
505548
}
549+
550+
private readonly Dictionary<Type, List<TObjectType>> typeToItems = new();
506551

507552

508553
public new IEnumerator<TObjectType> GetEnumerator()
@@ -578,17 +623,25 @@ public TObjectType GetItemByGUID(LongGuid targetGUID)
578623

579624
return null;
580625
}
626+
627+
public List<T> GetItemsByType<T>() where T : TObjectType
628+
{
629+
List<T> results = new List<T>();
630+
for (int i = 0; i < Items.Count; i++)
631+
{
632+
if (Items[i] is T t)
633+
results.Add(t);
634+
}
581635

582-
public bool TryGetItemByName<T>(string targetItemName, out T scriptableObjectCollectionItem) where T : TObjectType
636+
return results;
637+
}
638+
639+
public bool TryGetItemByName<T>(string targetItemName, out T scriptableObjectCollectionItem, StringComparison stringComparison = StringComparison.Ordinal) where T : TObjectType
583640
{
584-
for (int i = 0; i < items.Count; i++)
641+
if (base.TryGetItemByName(targetItemName, out ScriptableObject resultScriptableObject, stringComparison))
585642
{
586-
ScriptableObject item = items[i];
587-
if (string.Equals(item.name, targetItemName, StringComparison.Ordinal))
588-
{
589-
scriptableObjectCollectionItem = item as T;
590-
return scriptableObjectCollectionItem != null;
591-
}
643+
scriptableObjectCollectionItem = resultScriptableObject as T;
644+
return scriptableObjectCollectionItem != null;
592645
}
593646

594647
scriptableObjectCollectionItem = null;
@@ -658,4 +711,4 @@ protected override void ClearCachedValues()
658711
cachedValues = null;
659712
}
660713
}
661-
}
714+
}

0 commit comments

Comments
 (0)