Skip to content

Commit c857648

Browse files
authored
Merge pull request #156 from brunomikoski/feature/qol-asset-manipulation
Feature/qol asset manipulation
2 parents d91f267 + b163350 commit c857648

File tree

4 files changed

+153
-29
lines changed

4 files changed

+153
-29
lines changed

CHANGELOG.MD

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ 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.6]
9+
## Changed
10+
- Updated ListView to allow for multiple selection
11+
- Updated Context Menu functionality to support multiple selection (Copy/Paste/Duplicate/Delete)
12+
813
## [2.3.5]
914
## Changed
1015
- Added `ApplyModifiedProperties()` to property drawers again, since was causing issues with the shareable picker. This was removed on [2.3.4]
1116

12-
1317
## [2.3.4]
1418
## Changed
1519
- Update PickerPropertyDrawer to use PopupList from property path cache to avoid issue when rendered inside a List/Array
@@ -587,7 +591,8 @@ public bool IsValidConsumable(Consumable consumable)
587591
### Added
588592
- First initial working version
589593

590-
[2.3.5]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.5~~~~
594+
[2.3.6]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.6
595+
[2.3.5]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.5
591596
[2.3.4]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.4
592597
[2.3.3]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.3
593598
[2.3.2]: https://github.com/badawe/ScriptableObjectCollection/releases/tag/v2.3.2

Editor/UXML/CollectionCustomEditorTreeAsset.uxml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<AttributeOverrides element-name="Label" text="Items" />
77
<uie:ToolbarSearchField name="ToolbarSearchField" style="width: auto; margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding-bottom: 0; top: -18px; left: 200px; right: 30px; position: absolute;" />
88
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" name="expand-button" tooltip="Expand / Collapse Items" text="▸◂" enable-rich-text="false" style="width: 18px; height: 18px; position: absolute; right: 0; top: -20px;" />
9-
<ui:ListView virtualization-method="DynamicHeight" show-border="false" show-alternating-row-backgrounds="All" reorderable="true" show-foldout-header="false" header-title="Items" show-add-remove-footer="false" reorder-mode="Animated" show-bound-collection-size="false" name="items-list-view" horizontal-scrolling="false" selection-type="Single" view-data-key="collection-item-list-view" style="display: flex;" />
9+
<ui:ListView virtualization-method="DynamicHeight" show-border="false" show-alternating-row-backgrounds="All" reorderable="true" show-foldout-header="false" header-title="Items" show-add-remove-footer="false" reorder-mode="Animated" show-bound-collection-size="false" name="items-list-view" horizontal-scrolling="false" selection-type="Multiple" view-data-key="collection-item-list-view" style="display: flex;" />
1010
</ui:Instance>
1111
<ui:VisualElement name="unity-list-view__footer" class="unity-list-view__footer">
1212
<ui:Button name="unity-list-view__remove-button" text="-" class="unity-text-element unity-button" />

Scripts/Editor/CustomEditors/CollectionCustomEditor.cs

+144-25
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
namespace BrunoMikoski.ScriptableObjectCollections
2020
{
21+
2122
[CustomEditor(typeof(ScriptableObjectCollection), true)]
2223
public class CollectionCustomEditor : Editor
2324
{
@@ -290,9 +291,9 @@ private void BindCollectionItemListItem(VisualElement targetElement, int targetI
290291
Editor editor = EditorCache.GetOrCreateEditorForObject(targetItem);
291292

292293
Label titleLabel = foldout.Q<Label>();
293-
titleLabel.RegisterCallback<MouseDownEvent, int>(RenameItemAtIndex, targetIndex);
294+
titleLabel.RegisterCallback<MouseDownEvent, int>(RenameItemAtIndex, targetIndex, TrickleDown.TrickleDown);
294295

295-
targetElement.RegisterCallback<MouseUpEvent, int>(ShowOptionsForIndex, targetIndex);
296+
targetElement.parent.parent.RegisterCallback<MouseUpEvent, int>(ShowOptionsForIndex, targetIndex);
296297

297298
imguiContainer.onGUIHandler = () =>
298299
{
@@ -435,15 +436,35 @@ private void OnClickGenerateStaticFile(MouseUpEvent evt)
435436

436437
private void OnClickRemoveSelectedItems(MouseUpEvent evt)
437438
{
439+
440+
438441
if (!collectionItemListView.selectedIndices.Any())
439442
{
443+
if (!EditorUtility.DisplayDialog($"Delete Item",
444+
$"Are you sure you want to delete {filteredItems[^1].name}?", "Yes", "No"))
445+
{
446+
return;
447+
}
448+
440449
DeleteItemAtIndex(filteredItems.Count - 1);
441450
}
442451
else
443452
{
453+
if (!EditorUtility.DisplayDialog($"Delete {collectionItemListView.selectedIndices.Count()} Items",
454+
$"Are you sure you want to delete all {collectionItemListView.selectedIndices.Count()} items?", "Yes", "No"))
455+
{
456+
return;
457+
}
458+
459+
List<ScriptableObject> itemsToBeDuplicated = new List<ScriptableObject>();
444460
foreach (int selectedIndex in collectionItemListView.selectedIndices)
445461
{
446-
DeleteItemAtIndex(selectedIndex);
462+
itemsToBeDuplicated.Add(filteredItems[selectedIndex]);
463+
}
464+
465+
foreach (ScriptableObject item in itemsToBeDuplicated)
466+
{
467+
DeleteItemAtIndex(collection.IndexOf(item));
447468
}
448469
}
449470

@@ -657,12 +678,6 @@ protected void DeleteItemAtIndex(int selectedIndex)
657678
return;
658679
}
659680

660-
if (!EditorUtility.DisplayDialog($"Delete {scriptableObject.name}",
661-
$"Are you sure you want to delete {scriptableObject.name}?", "Yes", "No"))
662-
{
663-
return;
664-
}
665-
666681
Undo.RecordObject(collection, "Remove Item");
667682

668683
filteredItems.Remove(scriptableObject);
@@ -696,22 +711,47 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
696711
{
697712
if (evt.button != 1)
698713
return;
699-
714+
715+
int selectedItemsCount = collectionItemListView.selectedIndices.Count();
716+
bool singleItemSelected = selectedItemsCount == 1;
717+
700718
ScriptableObject scriptableObject = filteredItems[targetIndex];
701719

702720
GenericMenu menu = new GenericMenu();
703721

704-
menu.AddItem(
705-
new GUIContent("Copy Values"),
706-
false,
707-
() => { CopyCollectionItemUtility.SetSource(scriptableObject); }
708-
);
722+
if (singleItemSelected)
723+
{
724+
menu.AddItem(
725+
new GUIContent("Copy Values"),
726+
false,
727+
() => { CopyCollectionItemUtility.SetSource(scriptableObject); }
728+
);
729+
}
730+
else
731+
{
732+
menu.AddDisabledItem(
733+
new GUIContent("Copy Values"),
734+
false);
735+
}
709736
if (CopyCollectionItemUtility.CanPasteToTarget(scriptableObject))
710737
{
711738
menu.AddItem(
712739
new GUIContent("Paste Values"),
713740
false,
714-
() => { CopyCollectionItemUtility.ApplySourceToTarget(scriptableObject); }
741+
() =>
742+
{
743+
if (selectedItemsCount > 0)
744+
{
745+
foreach (int selectedIndex in collectionItemListView.selectedIndices)
746+
{
747+
CopyCollectionItemUtility.ApplySourceToTarget(filteredItems[selectedIndex]);
748+
}
749+
}
750+
else
751+
{
752+
CopyCollectionItemUtility.ApplySourceToTarget(scriptableObject);
753+
}
754+
}
715755
);
716756
}
717757
else
@@ -724,39 +764,118 @@ private void ShowOptionsForIndex(MouseUpEvent evt, int targetIndex)
724764
menu.AddItem(
725765
new GUIContent("Duplicate Item"),
726766
false,
727-
() => { DuplicateItem(targetIndex); }
767+
() =>
768+
{
769+
if (selectedItemsCount > 0)
770+
{
771+
List<ScriptableObject> itemsToBeDuplicated = new List<ScriptableObject>();
772+
foreach (int selectedIndex in collectionItemListView.selectedIndices)
773+
{
774+
itemsToBeDuplicated.Add(filteredItems[selectedIndex]);
775+
}
776+
777+
foreach (ScriptableObject item in itemsToBeDuplicated)
778+
{
779+
DuplicateItem(item, false);
780+
}
781+
}
782+
else
783+
{
784+
DuplicateItem(targetIndex);
785+
}
786+
}
728787
);
729788

730789
menu.AddItem(
731790
new GUIContent("Delete Item"),
732791
false,
733-
() => { DeleteItemAtIndex(targetIndex); }
792+
() =>
793+
{
794+
if (selectedItemsCount > 0)
795+
{
796+
if (!EditorUtility.DisplayDialog($"Delete {collectionItemListView.selectedIndices.Count()} Items",
797+
$"Are you sure you want to delete all {collectionItemListView.selectedIndices.Count()} items?", "Yes", "No"))
798+
{
799+
return;
800+
}
801+
802+
List<ScriptableObject> itemsToBeDuplicated = new List<ScriptableObject>();
803+
foreach (int selectedIndex in collectionItemListView.selectedIndices)
804+
{
805+
itemsToBeDuplicated.Add(filteredItems[selectedIndex]);
806+
}
807+
808+
foreach (ScriptableObject item in itemsToBeDuplicated)
809+
{
810+
DeleteItemAtIndex(collection.IndexOf(item));
811+
}
812+
}
813+
else
814+
{
815+
if (!EditorUtility.DisplayDialog($"Delete Item",
816+
$"Are you sure you want to delete {filteredItems[^1].name}?", "Yes", "No"))
817+
{
818+
return;
819+
}
820+
821+
DeleteItemAtIndex(targetIndex);
822+
}
823+
}
734824
);
735825

736826
menu.AddSeparator("");
737827
menu.AddItem(
738828
new GUIContent("Select Asset"),
739829
false,
740-
() => { SelectItemAtIndex(targetIndex); }
830+
() =>
831+
{
832+
if (selectedItemsCount > 0)
833+
{
834+
SelectItemAtIndex(collectionItemListView.selectedIndices.ToArray());
835+
}
836+
else
837+
{
838+
SelectItemAtIndex(targetIndex);
839+
}
840+
}
741841
);
742842

743843
menu.ShowAsContext();
744844
}
745845

746-
private void SelectItemAtIndex(int index)
846+
private void SelectItemAtIndex(params int[] index)
747847
{
748-
ScriptableObject collectionItem = filteredItems[index];
749-
Selection.objects = new Object[] { collectionItem };
848+
Object[] selectedObjects = new Object[index.Length];
849+
for (int i = 0; i < index.Length; i++)
850+
{
851+
selectedObjects[i] = filteredItems[index[i]];
852+
}
853+
Selection.objects = selectedObjects;
750854
}
751855

752-
private void DuplicateItem(int index)
856+
private void DuplicateItem(int index, bool showRenameAfter = true)
753857
{
754858
ScriptableObject source = filteredItems[index];
859+
DuplicateItem(source, showRenameAfter);
860+
}
861+
862+
private void DuplicateItem(ScriptableObject source, bool showRenameAfter)
863+
{
755864
CopyCollectionItemUtility.SetSource(source);
756865
ScriptableObject newItem = AddNewItemOfType(source.GetType(), false);
757866
CopyCollectionItemUtility.ApplySourceToTarget(newItem);
758-
int targetIndex = filteredItems.IndexOf(newItem);
759-
RenameItemAtIndex(targetIndex);
867+
868+
if (showRenameAfter)
869+
{
870+
int targetIndex = filteredItems.IndexOf(newItem);
871+
RenameItemAtIndex(targetIndex);
872+
}
873+
else
874+
{
875+
AssetDatabaseUtils.RenameAsset(newItem, $"{source.name} (Copy)");
876+
AssetDatabase.SaveAssetIfDirty(newItem);
877+
ReloadFilteredItems();
878+
}
760879
}
761880

762881
private void RenameItemAtIndex(MouseDownEvent evt, int targetIndex)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "com.brunomikoski.scriptableobjectcollection",
33
"displayName": "Scriptable Object Collection",
4-
"version": "2.3.4",
4+
"version": "2.3.6",
55
"unity": "2022.2",
66
"description": "A library to help improve the usability of Unity3D Scriptable Objects by grouping them into a collection and exposing them by code or nice inspectors!",
77
"keywords": [

0 commit comments

Comments
 (0)