com.wallstop-studios.unity-helpers 2.0.0-rc76.5 → 2.0.0-rc76.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Editor/AssetProcessors/SpriteLabelProcessor.cs +133 -0
- package/Editor/AssetProcessors/SpriteLabelProcessor.cs.meta +3 -0
- package/Editor/AssetProcessors.meta +3 -0
- package/Editor/CustomDrawers/StringInListeDrawer.cs +104 -25
- package/Editor/CustomDrawers/WShowIfPropertyDrawer.cs +12 -4
- package/Editor/CustomEditors/PersistentDirectoryGUI.cs +4 -1
- package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +189 -52
- package/Editor/Extensions/SerializedPropertyExtensions.cs +11 -0
- package/Editor/Sprites/ScriptableSpriteAtlas.cs +71 -1
- package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +94 -34
- package/Editor/Sprites/SpriteSheetAnimationCreator.cs +1530 -0
- package/Editor/Sprites/SpriteSheetAnimationCreator.cs.meta +3 -0
- package/Runtime/Core/Attributes/WShowIfAttribute.cs +9 -1
- package/Runtime/Core/Extension/IListExtensions.cs +6 -0
- package/Runtime/Core/Helper/Helpers.cs +31 -3
- package/Runtime/Core/Helper/StringInList.cs +22 -3
- package/Runtime/Utils/UnityObjectNameComparer.cs +46 -1
- package/package.json +3 -1
|
@@ -1,23 +1,93 @@
|
|
|
1
1
|
namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
2
2
|
{
|
|
3
3
|
#if UNITY_EDITOR
|
|
4
|
+
using System;
|
|
4
5
|
using UnityEngine;
|
|
5
6
|
using System.Collections.Generic;
|
|
6
7
|
using Core.Attributes;
|
|
7
8
|
using Core.Helper;
|
|
8
9
|
using UnityEditor;
|
|
9
10
|
|
|
10
|
-
[
|
|
11
|
+
[Flags]
|
|
12
|
+
public enum SpriteSelectionMode
|
|
13
|
+
{
|
|
14
|
+
[Obsolete("Please select a valid value")]
|
|
15
|
+
None = 0,
|
|
16
|
+
Regex = 1 << 0,
|
|
17
|
+
Labels = 1 << 1,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public enum LabelSelectionMode
|
|
21
|
+
{
|
|
22
|
+
[Obsolete("Please select a valid value")]
|
|
23
|
+
None = 0,
|
|
24
|
+
All = 1 << 0,
|
|
25
|
+
AnyOf = 1 << 1,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public enum SpriteSelectionBooleanLogic
|
|
29
|
+
{
|
|
30
|
+
[Obsolete("Please select a valid value")]
|
|
31
|
+
None = 0,
|
|
32
|
+
And = 1 << 0,
|
|
33
|
+
Or = 1 << 1,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[Serializable]
|
|
11
37
|
public sealed class SourceFolderEntry
|
|
12
38
|
{
|
|
13
39
|
[Tooltip("Folder to scan for sprites. Path relative to Assets/.")]
|
|
14
40
|
public string folderPath = "Assets/Sprites/";
|
|
15
41
|
|
|
42
|
+
public SpriteSelectionMode selectionMode = SpriteSelectionMode.Regex;
|
|
43
|
+
|
|
44
|
+
[WShowIf(
|
|
45
|
+
nameof(selectionMode),
|
|
46
|
+
expectedValues = new object[]
|
|
47
|
+
{
|
|
48
|
+
SpriteSelectionMode.Regex,
|
|
49
|
+
SpriteSelectionMode.Regex | SpriteSelectionMode.Labels,
|
|
50
|
+
}
|
|
51
|
+
)]
|
|
16
52
|
[Tooltip(
|
|
17
53
|
"Regex patterns to match sprite file names within this specific folder. All regexes must match (AND logic). e.g., \"^icon_.*\\.png$\""
|
|
18
54
|
)]
|
|
19
55
|
public List<string> regexes = new();
|
|
20
56
|
|
|
57
|
+
[WShowIf(
|
|
58
|
+
nameof(selectionMode),
|
|
59
|
+
expectedValues = new object[]
|
|
60
|
+
{
|
|
61
|
+
SpriteSelectionMode.Regex | SpriteSelectionMode.Labels,
|
|
62
|
+
(SpriteSelectionMode)(-1),
|
|
63
|
+
}
|
|
64
|
+
)]
|
|
65
|
+
public SpriteSelectionBooleanLogic regexAndTagLogic = SpriteSelectionBooleanLogic.And;
|
|
66
|
+
|
|
67
|
+
[WShowIf(
|
|
68
|
+
nameof(selectionMode),
|
|
69
|
+
expectedValues = new object[]
|
|
70
|
+
{
|
|
71
|
+
SpriteSelectionMode.Labels,
|
|
72
|
+
SpriteSelectionMode.Regex | SpriteSelectionMode.Labels,
|
|
73
|
+
(SpriteSelectionMode)(-1),
|
|
74
|
+
}
|
|
75
|
+
)]
|
|
76
|
+
public LabelSelectionMode labelSelectionMode = LabelSelectionMode.All;
|
|
77
|
+
|
|
78
|
+
[WShowIf(
|
|
79
|
+
nameof(selectionMode),
|
|
80
|
+
expectedValues = new object[]
|
|
81
|
+
{
|
|
82
|
+
SpriteSelectionMode.Labels,
|
|
83
|
+
SpriteSelectionMode.Regex | SpriteSelectionMode.Labels,
|
|
84
|
+
(SpriteSelectionMode)(-1),
|
|
85
|
+
}
|
|
86
|
+
)]
|
|
87
|
+
[Tooltip("Asset labels to include in the folders.")]
|
|
88
|
+
[StringInList(typeof(Helpers), nameof(Helpers.GetAllSpriteLabelNames))]
|
|
89
|
+
public List<string> labels = new();
|
|
90
|
+
|
|
21
91
|
public SourceFolderEntry() { }
|
|
22
92
|
|
|
23
93
|
public SourceFolderEntry(string path)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#if UNITY_EDITOR
|
|
4
4
|
using System;
|
|
5
5
|
using System.Collections.Generic;
|
|
6
|
+
using System.ComponentModel;
|
|
6
7
|
using System.IO;
|
|
7
8
|
using System.Linq;
|
|
8
9
|
using System.Text.RegularExpressions;
|
|
@@ -16,6 +17,8 @@
|
|
|
16
17
|
|
|
17
18
|
public sealed class ScriptableSpriteAtlasEditor : EditorWindow
|
|
18
19
|
{
|
|
20
|
+
private readonly Dictionary<ScriptableSpriteAtlas, SerializedObject> _serializedConfigs =
|
|
21
|
+
new();
|
|
19
22
|
private List<ScriptableSpriteAtlas> _atlasConfigs = new();
|
|
20
23
|
private Vector2 _scrollPosition;
|
|
21
24
|
|
|
@@ -58,6 +61,7 @@
|
|
|
58
61
|
Dictionary<ScriptableSpriteAtlas, ScanResult> existingScanCache = new(
|
|
59
62
|
_scanResultsCache
|
|
60
63
|
);
|
|
64
|
+
_serializedConfigs.Clear();
|
|
61
65
|
_scanResultsCache.Clear();
|
|
62
66
|
|
|
63
67
|
string[] guids = AssetDatabase.FindAssets("t:ScriptableSpriteAtlas");
|
|
@@ -78,6 +82,7 @@
|
|
|
78
82
|
{
|
|
79
83
|
_scanResultsCache[config] = new ScanResult();
|
|
80
84
|
}
|
|
85
|
+
_serializedConfigs.TryAdd(config, newConfig => new SerializedObject(newConfig));
|
|
81
86
|
_foldoutStates.TryAdd(config, true);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
@@ -155,7 +160,10 @@
|
|
|
155
160
|
if (_foldoutStates[config])
|
|
156
161
|
{
|
|
157
162
|
using EditorGUI.IndentLevelScope indentScope = new();
|
|
158
|
-
SerializedObject serializedConfig =
|
|
163
|
+
SerializedObject serializedConfig = _serializedConfigs.GetOrAdd(
|
|
164
|
+
config,
|
|
165
|
+
newConfig => new SerializedObject(newConfig)
|
|
166
|
+
);
|
|
159
167
|
serializedConfig.Update();
|
|
160
168
|
EditorGUI.BeginChangeCheck();
|
|
161
169
|
|
|
@@ -169,6 +177,7 @@
|
|
|
169
177
|
);
|
|
170
178
|
if (EditorGUI.EndChangeCheck())
|
|
171
179
|
{
|
|
180
|
+
serializedConfig.ApplyModifiedProperties();
|
|
172
181
|
if (
|
|
173
182
|
!string.IsNullOrWhiteSpace(newAssetName)
|
|
174
183
|
&& newAssetName != currentAssetName
|
|
@@ -368,22 +377,18 @@
|
|
|
368
377
|
GUILayout.Button(
|
|
369
378
|
$"Force Uncompressed for {validSpriteCount} Source Sprites in '{config.name}'"
|
|
370
379
|
)
|
|
380
|
+
&& EditorUtility.DisplayDialog(
|
|
381
|
+
"Force Uncompressed Source Sprites",
|
|
382
|
+
$"This will modify the import settings of {validSpriteCount} source sprites currently in the '{config.name}' list.\n\n"
|
|
383
|
+
+ "- Crunch compression will be disabled.\n"
|
|
384
|
+
+ "- Texture format for the 'Default' platform will be set to uncompressed (RGBA32 or RGB24).\n\n"
|
|
385
|
+
+ "This action modifies source asset import settings and may require re-packing atlases. Are you sure?",
|
|
386
|
+
"Yes, Modify Source Sprites",
|
|
387
|
+
"Cancel"
|
|
388
|
+
)
|
|
371
389
|
)
|
|
372
390
|
{
|
|
373
|
-
|
|
374
|
-
EditorUtility.DisplayDialog(
|
|
375
|
-
"Force Uncompressed Source Sprites",
|
|
376
|
-
$"This will modify the import settings of {validSpriteCount} source sprites currently in the '{config.name}' list.\n\n"
|
|
377
|
-
+ "- Crunch compression will be disabled.\n"
|
|
378
|
-
+ "- Texture format for the 'Default' platform will be set to uncompressed (RGBA32 or RGB24).\n\n"
|
|
379
|
-
+ "This action modifies source asset import settings and may require re-packing atlases. Are you sure?",
|
|
380
|
-
"Yes, Modify Source Sprites",
|
|
381
|
-
"Cancel"
|
|
382
|
-
)
|
|
383
|
-
)
|
|
384
|
-
{
|
|
385
|
-
ForceUncompressedSourceSprites(config);
|
|
386
|
-
}
|
|
391
|
+
ForceUncompressedSourceSprites(config);
|
|
387
392
|
}
|
|
388
393
|
EditorGUI.EndDisabledGroup();
|
|
389
394
|
|
|
@@ -392,19 +397,15 @@
|
|
|
392
397
|
GUILayout.Button(
|
|
393
398
|
$"Generate/Update '{config.outputSpriteAtlasName}.spriteatlas' ONLY"
|
|
394
399
|
)
|
|
400
|
+
&& EditorUtility.DisplayDialog(
|
|
401
|
+
$"Generate Atlas: {config.name}",
|
|
402
|
+
$"This will create or update '{config.outputSpriteAtlasName}.spriteatlas'. Continue?",
|
|
403
|
+
"Yes",
|
|
404
|
+
"No"
|
|
405
|
+
)
|
|
395
406
|
)
|
|
396
407
|
{
|
|
397
|
-
|
|
398
|
-
EditorUtility.DisplayDialog(
|
|
399
|
-
$"Generate Atlas: {config.name}",
|
|
400
|
-
$"This will create or update '{config.outputSpriteAtlasName}.spriteatlas'. Continue?",
|
|
401
|
-
"Yes",
|
|
402
|
-
"No"
|
|
403
|
-
)
|
|
404
|
-
)
|
|
405
|
-
{
|
|
406
|
-
GenerateSingleAtlas(config);
|
|
407
|
-
}
|
|
408
|
+
GenerateSingleAtlas(config);
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
411
|
EditorGUILayout.EndVertical();
|
|
@@ -470,18 +471,16 @@
|
|
|
470
471
|
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
471
472
|
string fileName = Path.GetFileName(assetPath);
|
|
472
473
|
|
|
473
|
-
bool matchesAllRegexesInEntry;
|
|
474
|
+
bool matchesAllRegexesInEntry = true;
|
|
474
475
|
List<string> activeRegexPatterns = entry
|
|
475
476
|
.regexes.Where(r => !string.IsNullOrWhiteSpace(r))
|
|
476
477
|
.ToList();
|
|
477
478
|
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
else
|
|
479
|
+
if (
|
|
480
|
+
entry.selectionMode.HasFlagNoAlloc(SpriteSelectionMode.Regex)
|
|
481
|
+
&& activeRegexPatterns is { Count: > 0 }
|
|
482
|
+
)
|
|
483
483
|
{
|
|
484
|
-
matchesAllRegexesInEntry = true;
|
|
485
484
|
foreach (string regexPattern in activeRegexPatterns)
|
|
486
485
|
{
|
|
487
486
|
try
|
|
@@ -503,7 +502,68 @@
|
|
|
503
502
|
}
|
|
504
503
|
}
|
|
505
504
|
|
|
506
|
-
|
|
505
|
+
bool matchesAllTagsInEntry = true;
|
|
506
|
+
if (
|
|
507
|
+
entry.selectionMode.HasFlagNoAlloc(SpriteSelectionMode.Labels)
|
|
508
|
+
&& entry.labels is { Count: > 0 }
|
|
509
|
+
)
|
|
510
|
+
{
|
|
511
|
+
Object mainAsset = AssetDatabase.LoadMainAssetAtPath(assetPath);
|
|
512
|
+
if (mainAsset != null)
|
|
513
|
+
{
|
|
514
|
+
string[] labels = AssetDatabase.GetLabels(mainAsset);
|
|
515
|
+
switch (entry.labelSelectionMode)
|
|
516
|
+
{
|
|
517
|
+
case LabelSelectionMode.All:
|
|
518
|
+
{
|
|
519
|
+
matchesAllTagsInEntry = labels.All(label =>
|
|
520
|
+
entry.labels.Contains(label)
|
|
521
|
+
);
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
case LabelSelectionMode.AnyOf:
|
|
525
|
+
{
|
|
526
|
+
matchesAllTagsInEntry = labels.Any(label =>
|
|
527
|
+
entry.labels.Contains(label)
|
|
528
|
+
);
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
default:
|
|
532
|
+
{
|
|
533
|
+
throw new InvalidEnumArgumentException(
|
|
534
|
+
nameof(entry.labelSelectionMode),
|
|
535
|
+
(int)entry.labelSelectionMode,
|
|
536
|
+
typeof(LabelSelectionMode)
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
bool allMatch;
|
|
544
|
+
switch (entry.regexAndTagLogic)
|
|
545
|
+
{
|
|
546
|
+
case SpriteSelectionBooleanLogic.And:
|
|
547
|
+
{
|
|
548
|
+
allMatch = matchesAllRegexesInEntry && matchesAllTagsInEntry;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
case SpriteSelectionBooleanLogic.Or:
|
|
552
|
+
{
|
|
553
|
+
allMatch = matchesAllRegexesInEntry || matchesAllTagsInEntry;
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
default:
|
|
557
|
+
{
|
|
558
|
+
throw new InvalidEnumArgumentException(
|
|
559
|
+
nameof(entry.regexAndTagLogic),
|
|
560
|
+
(int)entry.regexAndTagLogic,
|
|
561
|
+
typeof(SpriteSelectionBooleanLogic)
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (allMatch)
|
|
507
567
|
{
|
|
508
568
|
Object[] assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
|
|
509
569
|
foreach (Object asset in assets)
|