com.wallstop-studios.unity-helpers 2.0.0-rc76.6 → 2.0.0-rc76.8
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/SourceFolderEntryDrawer.cs +182 -57
- package/Editor/Extensions/SerializedPropertyExtensions.cs +11 -0
- package/Editor/Sprites/ScriptableSpriteAtlas.cs +71 -1
- package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +91 -40
- package/Editor/Sprites/SpriteSheetAnimationCreator.cs +421 -102
- package/Runtime/Core/Attributes/WShowIfAttribute.cs +9 -1
- package/Runtime/Core/Helper/Helpers.cs +31 -3
- package/Runtime/Core/Helper/StringInList.cs +22 -3
- 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;
|
|
@@ -44,11 +45,6 @@
|
|
|
44
45
|
LoadAtlasConfigs();
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
private void OnFocus()
|
|
48
|
-
{
|
|
49
|
-
LoadAtlasConfigs();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
48
|
private void OnProjectChange()
|
|
53
49
|
{
|
|
54
50
|
LoadAtlasConfigs();
|
|
@@ -67,6 +63,10 @@
|
|
|
67
63
|
foreach (string guid in guids)
|
|
68
64
|
{
|
|
69
65
|
string path = AssetDatabase.GUIDToAssetPath(guid);
|
|
66
|
+
if (string.IsNullOrWhiteSpace(path))
|
|
67
|
+
{
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
70
|
ScriptableSpriteAtlas config = AssetDatabase.LoadAssetAtPath<ScriptableSpriteAtlas>(
|
|
71
71
|
path
|
|
72
72
|
);
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
{
|
|
78
78
|
_scanResultsCache[config] = cachedResult;
|
|
79
79
|
}
|
|
80
|
-
else
|
|
80
|
+
else
|
|
81
81
|
{
|
|
82
|
-
_scanResultsCache
|
|
82
|
+
_scanResultsCache.TryAdd(config, _ => new ScanResult());
|
|
83
83
|
}
|
|
84
84
|
_serializedConfigs.TryAdd(config, newConfig => new SerializedObject(newConfig));
|
|
85
85
|
_foldoutStates.TryAdd(config, true);
|
|
@@ -376,22 +376,18 @@
|
|
|
376
376
|
GUILayout.Button(
|
|
377
377
|
$"Force Uncompressed for {validSpriteCount} Source Sprites in '{config.name}'"
|
|
378
378
|
)
|
|
379
|
+
&& EditorUtility.DisplayDialog(
|
|
380
|
+
"Force Uncompressed Source Sprites",
|
|
381
|
+
$"This will modify the import settings of {validSpriteCount} source sprites currently in the '{config.name}' list.\n\n"
|
|
382
|
+
+ "- Crunch compression will be disabled.\n"
|
|
383
|
+
+ "- Texture format for the 'Default' platform will be set to uncompressed (RGBA32 or RGB24).\n\n"
|
|
384
|
+
+ "This action modifies source asset import settings and may require re-packing atlases. Are you sure?",
|
|
385
|
+
"Yes, Modify Source Sprites",
|
|
386
|
+
"Cancel"
|
|
387
|
+
)
|
|
379
388
|
)
|
|
380
389
|
{
|
|
381
|
-
|
|
382
|
-
EditorUtility.DisplayDialog(
|
|
383
|
-
"Force Uncompressed Source Sprites",
|
|
384
|
-
$"This will modify the import settings of {validSpriteCount} source sprites currently in the '{config.name}' list.\n\n"
|
|
385
|
-
+ "- Crunch compression will be disabled.\n"
|
|
386
|
-
+ "- Texture format for the 'Default' platform will be set to uncompressed (RGBA32 or RGB24).\n\n"
|
|
387
|
-
+ "This action modifies source asset import settings and may require re-packing atlases. Are you sure?",
|
|
388
|
-
"Yes, Modify Source Sprites",
|
|
389
|
-
"Cancel"
|
|
390
|
-
)
|
|
391
|
-
)
|
|
392
|
-
{
|
|
393
|
-
ForceUncompressedSourceSprites(config);
|
|
394
|
-
}
|
|
390
|
+
ForceUncompressedSourceSprites(config);
|
|
395
391
|
}
|
|
396
392
|
EditorGUI.EndDisabledGroup();
|
|
397
393
|
|
|
@@ -400,19 +396,15 @@
|
|
|
400
396
|
GUILayout.Button(
|
|
401
397
|
$"Generate/Update '{config.outputSpriteAtlasName}.spriteatlas' ONLY"
|
|
402
398
|
)
|
|
399
|
+
&& EditorUtility.DisplayDialog(
|
|
400
|
+
$"Generate Atlas: {config.name}",
|
|
401
|
+
$"This will create or update '{config.outputSpriteAtlasName}.spriteatlas'. Continue?",
|
|
402
|
+
"Yes",
|
|
403
|
+
"No"
|
|
404
|
+
)
|
|
403
405
|
)
|
|
404
406
|
{
|
|
405
|
-
|
|
406
|
-
EditorUtility.DisplayDialog(
|
|
407
|
-
$"Generate Atlas: {config.name}",
|
|
408
|
-
$"This will create or update '{config.outputSpriteAtlasName}.spriteatlas'. Continue?",
|
|
409
|
-
"Yes",
|
|
410
|
-
"No"
|
|
411
|
-
)
|
|
412
|
-
)
|
|
413
|
-
{
|
|
414
|
-
GenerateSingleAtlas(config);
|
|
415
|
-
}
|
|
407
|
+
GenerateSingleAtlas(config);
|
|
416
408
|
}
|
|
417
409
|
}
|
|
418
410
|
EditorGUILayout.EndVertical();
|
|
@@ -478,18 +470,16 @@
|
|
|
478
470
|
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
479
471
|
string fileName = Path.GetFileName(assetPath);
|
|
480
472
|
|
|
481
|
-
bool matchesAllRegexesInEntry;
|
|
473
|
+
bool matchesAllRegexesInEntry = true;
|
|
482
474
|
List<string> activeRegexPatterns = entry
|
|
483
475
|
.regexes.Where(r => !string.IsNullOrWhiteSpace(r))
|
|
484
476
|
.ToList();
|
|
485
477
|
|
|
486
|
-
if (
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
else
|
|
478
|
+
if (
|
|
479
|
+
entry.selectionMode.HasFlagNoAlloc(SpriteSelectionMode.Regex)
|
|
480
|
+
&& activeRegexPatterns is { Count: > 0 }
|
|
481
|
+
)
|
|
491
482
|
{
|
|
492
|
-
matchesAllRegexesInEntry = true;
|
|
493
483
|
foreach (string regexPattern in activeRegexPatterns)
|
|
494
484
|
{
|
|
495
485
|
try
|
|
@@ -511,7 +501,68 @@
|
|
|
511
501
|
}
|
|
512
502
|
}
|
|
513
503
|
|
|
514
|
-
|
|
504
|
+
bool matchesAllTagsInEntry = true;
|
|
505
|
+
if (
|
|
506
|
+
entry.selectionMode.HasFlagNoAlloc(SpriteSelectionMode.Labels)
|
|
507
|
+
&& entry.labels is { Count: > 0 }
|
|
508
|
+
)
|
|
509
|
+
{
|
|
510
|
+
Object mainAsset = AssetDatabase.LoadMainAssetAtPath(assetPath);
|
|
511
|
+
if (mainAsset != null)
|
|
512
|
+
{
|
|
513
|
+
string[] labels = AssetDatabase.GetLabels(mainAsset);
|
|
514
|
+
switch (entry.labelSelectionMode)
|
|
515
|
+
{
|
|
516
|
+
case LabelSelectionMode.All:
|
|
517
|
+
{
|
|
518
|
+
matchesAllTagsInEntry = labels.All(label =>
|
|
519
|
+
entry.labels.Contains(label)
|
|
520
|
+
);
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
case LabelSelectionMode.AnyOf:
|
|
524
|
+
{
|
|
525
|
+
matchesAllTagsInEntry = labels.Any(label =>
|
|
526
|
+
entry.labels.Contains(label)
|
|
527
|
+
);
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
default:
|
|
531
|
+
{
|
|
532
|
+
throw new InvalidEnumArgumentException(
|
|
533
|
+
nameof(entry.labelSelectionMode),
|
|
534
|
+
(int)entry.labelSelectionMode,
|
|
535
|
+
typeof(LabelSelectionMode)
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
bool allMatch;
|
|
543
|
+
switch (entry.regexAndTagLogic)
|
|
544
|
+
{
|
|
545
|
+
case SpriteSelectionBooleanLogic.And:
|
|
546
|
+
{
|
|
547
|
+
allMatch = matchesAllRegexesInEntry && matchesAllTagsInEntry;
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
case SpriteSelectionBooleanLogic.Or:
|
|
551
|
+
{
|
|
552
|
+
allMatch = matchesAllRegexesInEntry || matchesAllTagsInEntry;
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
default:
|
|
556
|
+
{
|
|
557
|
+
throw new InvalidEnumArgumentException(
|
|
558
|
+
nameof(entry.regexAndTagLogic),
|
|
559
|
+
(int)entry.regexAndTagLogic,
|
|
560
|
+
typeof(SpriteSelectionBooleanLogic)
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (allMatch)
|
|
515
566
|
{
|
|
516
567
|
Object[] assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
|
|
517
568
|
foreach (Object asset in assets)
|