Skip to content

Commit b43c49b

Browse files
committed
add some tryout to fix dupicating Collections
1 parent 33f4d64 commit b43c49b

File tree

7 files changed

+336
-60
lines changed

7 files changed

+336
-60
lines changed

Scripts/Editor/CustomEditors/CollectionCustomEditor.cs

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -626,10 +626,10 @@ private bool IsAddressableAsset(ScriptableObject target)
626626
#endif
627627
}
628628

629-
private ScriptableObject AddNewItemOfType(Type targetType, bool autoFocusForRename = true)
629+
private ScriptableObject AddNewItemOfType(Type targetType,string assetName = "", bool autoFocusForRename = true)
630630
{
631631
Undo.IncrementCurrentGroup();
632-
ScriptableObject newItem = collection.AddNew(targetType);
632+
ScriptableObject newItem = collection.AddNew(targetType, assetName);
633633
Undo.RegisterCreatedObjectUndo(newItem, "Create New Item");
634634
Undo.RecordObject(collection, "Add New Item");
635635
Undo.SetCurrentGroupName($"Created new item {newItem.name}");
@@ -792,10 +792,12 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
792792
{
793793
DuplicateItem(item, false);
794794
}
795+
ReloadFilteredItems();
795796
}
796797
else
797798
{
798799
DuplicateItem(targetIndex);
800+
ReloadFilteredItems();
799801
}
800802
}
801803
);
@@ -825,6 +827,7 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
825827
{
826828
RemoveItemAtIndex(collection.IndexOf(item), result == 2);
827829
}
830+
ReloadFilteredItems();
828831
}
829832
else
830833
{
@@ -837,6 +840,7 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
837840
}
838841

839842
RemoveItemAtIndex(filteredItems.Count - 1, result == 2);
843+
ReloadFilteredItems();
840844
}
841845
}
842846
);
@@ -872,19 +876,20 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
872876

873877
foreach (ScriptableObject item in moveItems)
874878
{
875-
MoveItem(item, scriptableObjectCollection);
879+
SOCItemUtility.MoveItem(item as ISOCItem, scriptableObjectCollection);
876880
}
881+
ReloadFilteredItems();
877882

878883
}
879884
else
880885
{
881-
if (!EditorUtility.DisplayDialog($"Move Item",
886+
if (!EditorUtility.DisplayDialog("Move Item",
882887
$"Are you sure you want to move {filteredItems[^1].name}, from {AssetDatabase.GetAssetPath(collection)} to {AssetDatabase.GetAssetPath(scriptableObject)}", "Yes", "No"))
883888
{
884889
return;
885890
}
886-
887-
MoveItem(filteredItems[targetIndex], scriptableObjectCollection);
891+
SOCItemUtility.MoveItem(filteredItems[targetIndex], scriptableObjectCollection);
892+
ReloadFilteredItems();
888893
}
889894
}
890895
);
@@ -923,38 +928,6 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
923928
menu.ShowAsContext();
924929
}
925930

926-
private void MoveItem(ScriptableObject item, ScriptableObjectCollection targetCollection)
927-
{
928-
Undo.RecordObject(collection, "Move Item");
929-
Undo.RecordObject(targetCollection, "Move Item");
930-
931-
collection.Remove(item);
932-
targetCollection.Add(item);
933-
934-
string itemPath = AssetDatabase.GetAssetPath(item);
935-
string targetCollectionPath = AssetDatabase.GetAssetPath(targetCollection);
936-
937-
if (!string.IsNullOrEmpty(itemPath) && !string.IsNullOrEmpty(targetCollectionPath))
938-
{
939-
string directory = Path.GetDirectoryName(targetCollectionPath);
940-
941-
string itemsFolderPath = Path.Combine(directory, "Items");
942-
bool hasItemsFolder = AssetDatabase.IsValidFolder(itemsFolderPath);
943-
944-
string finalDirectory = hasItemsFolder ? itemsFolderPath : directory;
945-
string fileName = Path.GetFileName(itemPath);
946-
947-
string newPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(finalDirectory, fileName));
948-
949-
AssetDatabase.MoveAsset(itemPath, newPath);
950-
}
951-
952-
AssetDatabase.SaveAssets();
953-
AssetDatabase.Refresh();
954-
955-
ReloadFilteredItems();
956-
}
957-
958931
private List<ScriptableObjectCollection> GetPossibleAnotherCollections()
959932
{
960933
CollectionsRegistry.Instance.TryGetCollectionsOfItemType(collection.GetItemType(), out List<ScriptableObjectCollection> collections);
@@ -980,7 +953,14 @@ private void DuplicateItem(int index, bool showRenameAfter = true)
980953
private void DuplicateItem(ScriptableObject source, bool showRenameAfter)
981954
{
982955
CopyCollectionItemUtility.SetSource(source);
983-
ScriptableObject newItem = AddNewItemOfType(source.GetType(), false);
956+
957+
string path = AssetDatabase.GetAssetPath(source);
958+
string directory = Path.GetDirectoryName(path);
959+
string fileName = $"{source.name} (Clone)";
960+
961+
fileName = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(directory, $"{fileName}.asset"));
962+
963+
ScriptableObject newItem = AddNewItemOfType(source.GetType(), Path.GetFileNameWithoutExtension(fileName), false);
984964
CopyCollectionItemUtility.ApplySourceToTarget(newItem);
985965

986966
if (showRenameAfter)
@@ -990,7 +970,6 @@ private void DuplicateItem(ScriptableObject source, bool showRenameAfter)
990970
}
991971
else
992972
{
993-
AssetDatabaseUtils.RenameAsset(newItem, $"{source.name} (Copy)");
994973
AssetDatabase.SaveAssetIfDirty(newItem);
995974
ReloadFilteredItems();
996975
}

Scripts/Editor/Processors/CollectionAssetsModificationProcessor.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public static AssetDeleteResult OnWillDeleteAsset(string targetAssetPath, Remove
2424
if (socItem == null)
2525
return AssetDeleteResult.DidNotDelete;
2626

27+
if (socItem.Collection == null)
28+
return AssetDeleteResult.DidNotDelete;
29+
2730
socItem.Collection.Remove(collectionItem);
2831
return AssetDeleteResult.DidNotDelete;
2932
}
@@ -42,4 +45,4 @@ public static AssetDeleteResult OnWillDeleteAsset(string targetAssetPath, Remove
4245
}
4346

4447
}
45-
}
48+
}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
using System.Collections.Generic;
2+
using UnityEditor;
3+
using UnityEngine;
4+
5+
namespace BrunoMikoski.ScriptableObjectCollections
6+
{
7+
public static class SOCollectionsProjectContextMenus
8+
{
9+
// ================================
10+
// ISOCItem (ScriptableObjectCollectionItem) commands
11+
// ================================
12+
13+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Move to Different Collection", true)]
14+
private static bool ValidateMoveToDifferentCollection()
15+
{
16+
Object[] selectedObjects = Selection.objects;
17+
if (selectedObjects == null || selectedObjects.Length == 0)
18+
return false;
19+
// Check that every selected object implements ISOCItem.
20+
foreach (Object obj in selectedObjects)
21+
{
22+
ISOCItem socItem = obj as ISOCItem;
23+
if (socItem == null)
24+
return false;
25+
}
26+
return true;
27+
}
28+
29+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Move to Different Collection")]
30+
private static void MoveToDifferentCollection()
31+
{
32+
Object[] selectedObjects = Selection.objects;
33+
List<ISOCItem> items = new List<ISOCItem>();
34+
foreach (Object obj in selectedObjects)
35+
{
36+
if (obj is ISOCItem item)
37+
items.Add(item);
38+
}
39+
if (items.Count == 0)
40+
return;
41+
42+
// Get available collections for the item type.
43+
List<ScriptableObjectCollection> possibleCollections =
44+
CollectionsRegistry.Instance.GetCollectionsByItemType(items[0].GetType());
45+
if (possibleCollections == null || possibleCollections.Count == 0)
46+
{
47+
EditorUtility.DisplayDialog("Move to Different Collection", "No collections available.", "OK");
48+
return;
49+
}
50+
// Exclude the current collection of the first item.
51+
ScriptableObjectCollection currentCollection = items[0].Collection;
52+
List<ScriptableObjectCollection> filteredCollections = new List<ScriptableObjectCollection>();
53+
foreach (ScriptableObjectCollection collection in possibleCollections)
54+
{
55+
if (collection != currentCollection)
56+
filteredCollections.Add(collection);
57+
}
58+
if (filteredCollections.Count == 0)
59+
{
60+
EditorUtility.DisplayDialog("Move to Different Collection", "No other collections available.", "OK");
61+
return;
62+
}
63+
// Present a GenericMenu so the user can choose a new collection.
64+
GenericMenu menu = new GenericMenu();
65+
foreach (ScriptableObjectCollection collection in filteredCollections)
66+
{
67+
menu.AddItem(new GUIContent(collection.name), false, delegate
68+
{
69+
foreach (ISOCItem item in items)
70+
{
71+
SOCItemUtility.MoveItem(item, collection);
72+
}
73+
EditorUtility.SetDirty(collection);
74+
});
75+
}
76+
menu.ShowAsContext();
77+
}
78+
79+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Select Collection", true)]
80+
private static bool ValidateSelectCollection()
81+
{
82+
Object[] selectedObjects = Selection.objects;
83+
if (selectedObjects == null || selectedObjects.Length != 1)
84+
return false;
85+
ISOCItem socItem = selectedObjects[0] as ISOCItem;
86+
return socItem != null && socItem.Collection != null;
87+
}
88+
89+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Select Collection")]
90+
private static void SelectCollection()
91+
{
92+
Object[] selectedObjects = Selection.objects;
93+
if (selectedObjects == null || selectedObjects.Length != 1)
94+
return;
95+
ISOCItem socItem = selectedObjects[0] as ISOCItem;
96+
if (socItem != null && socItem.Collection != null)
97+
Selection.activeObject = socItem.Collection;
98+
}
99+
100+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Duplicate", true)]
101+
private static bool ValidateDuplicateItem()
102+
{
103+
Object[] selectedObjects = Selection.objects;
104+
if (selectedObjects == null || selectedObjects.Length == 0)
105+
return false;
106+
foreach (Object obj in selectedObjects)
107+
{
108+
if (!(obj is ScriptableObject))
109+
return false;
110+
}
111+
return true;
112+
}
113+
114+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Duplicate")]
115+
private static void DuplicateItem()
116+
{
117+
Object[] selectedObjects = Selection.objects;
118+
foreach (Object obj in selectedObjects)
119+
{
120+
string assetPath = AssetDatabase.GetAssetPath(obj);
121+
if (string.IsNullOrEmpty(assetPath))
122+
continue;
123+
string newPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
124+
bool copySuccess = AssetDatabase.CopyAsset(assetPath, newPath);
125+
if (copySuccess)
126+
AssetDatabase.Refresh();
127+
}
128+
}
129+
130+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Delete", true)]
131+
private static bool ValidateDeleteItem()
132+
{
133+
Object[] selectedObjects = Selection.objects;
134+
if (selectedObjects == null || selectedObjects.Length == 0)
135+
return false;
136+
foreach (Object obj in selectedObjects)
137+
{
138+
if (!(obj is ScriptableObject))
139+
return false;
140+
}
141+
return true;
142+
}
143+
144+
[MenuItem("Assets/ScriptableObjectCollections/ISOCItem/Delete")]
145+
private static void DeleteItem()
146+
{
147+
Object[] selectedObjects = Selection.objects;
148+
if (EditorUtility.DisplayDialog("Delete Item",
149+
"Are you sure you want to delete the selected item(s)?", "Yes", "No"))
150+
{
151+
List<ScriptableObjectCollection> objectCollections = new List<ScriptableObjectCollection>();
152+
foreach (Object obj in selectedObjects)
153+
{
154+
string assetPath = AssetDatabase.GetAssetPath(obj);
155+
if(obj is ISOCItem socItem)
156+
objectCollections.Add(socItem.Collection);
157+
158+
if (!string.IsNullOrEmpty(assetPath))
159+
AssetDatabase.DeleteAsset(assetPath);
160+
}
161+
162+
foreach (ScriptableObjectCollection objectCollection in objectCollections)
163+
{
164+
objectCollection.RefreshCollection();
165+
}
166+
167+
AssetDatabase.Refresh();
168+
}
169+
}
170+
171+
// ================================
172+
// ScriptableObjectCollection commands
173+
// ================================
174+
175+
[MenuItem("Assets/ScriptableObjectCollections/ScriptableObjectCollection/Duplicate Collection", true)]
176+
private static bool ValidateDuplicateCollection()
177+
{
178+
Object[] selectedObjects = Selection.objects;
179+
if (selectedObjects == null || selectedObjects.Length != 1)
180+
return false;
181+
return selectedObjects[0] is ScriptableObjectCollection;
182+
}
183+
184+
[MenuItem("Assets/ScriptableObjectCollections/ScriptableObjectCollection/Duplicate Collection")]
185+
private static void DuplicateCollection()
186+
{
187+
Object[] selectedObjects = Selection.objects;
188+
if (selectedObjects == null || selectedObjects.Length != 1)
189+
return;
190+
ScriptableObjectCollection originalCollection = selectedObjects[0] as ScriptableObjectCollection;
191+
if (originalCollection == null)
192+
return;
193+
string assetPath = AssetDatabase.GetAssetPath(originalCollection);
194+
if (string.IsNullOrEmpty(assetPath))
195+
return;
196+
string newPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
197+
bool copySuccess = AssetDatabase.CopyAsset(assetPath, newPath);
198+
if (copySuccess)
199+
{
200+
AssetDatabase.Refresh();
201+
CollectionsRegistry.Instance.ValidateCollections();
202+
EditorUtility.DisplayDialog("Duplicate Collection",
203+
"Collection duplicated successfully at:\n" + newPath, "OK");
204+
}
205+
else
206+
{
207+
EditorUtility.DisplayDialog("Duplicate Collection",
208+
"Failed to duplicate collection.", "OK");
209+
}
210+
}
211+
}
212+
}

Scripts/Editor/Utils/SOCollectionsContextMenuItems.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)