com.wallstop-studios.unity-helpers 2.0.0-rc73.13 → 2.0.0-rc73.15
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/AnimationEventEditor.cs +4 -5
- package/Editor/CustomEditors/MatchColliderToSpriteEditor.cs +1 -1
- package/Editor/CustomEditors/PersistentDirectoryGUI.cs +590 -0
- package/Editor/CustomEditors/PersistentDirectoryGUI.cs.meta +3 -0
- package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +298 -0
- package/Editor/CustomEditors/SourceFolderEntryDrawer.cs.meta +3 -0
- package/Editor/FitTextureSizeWindow.cs +5 -44
- package/Editor/PersistentDirectorySettings.cs +248 -0
- package/Editor/PersistentDirectorySettings.cs.meta +3 -0
- package/Editor/PrefabChecker.cs +1 -2
- package/Editor/{AnimationCopier.cs → Sprites/AnimationCopier.cs} +33 -166
- package/Editor/{AnimationCreator.cs → Sprites/AnimationCreator.cs} +9 -80
- package/Editor/Sprites/ScriptableSpriteAtlas.cs +95 -0
- package/Editor/Sprites/ScriptableSpriteAtlas.cs.meta +3 -0
- package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +938 -0
- package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs.meta +3 -0
- package/Editor/{SpriteCropper.cs → Sprites/SpriteCropper.cs} +68 -66
- package/Editor/{SpriteSettingsApplier.cs → Sprites/SpriteSettingsApplier.cs} +9 -76
- package/Editor/{TextureResizerWizard.cs → Sprites/TextureResizerWizard.cs} +1 -1
- package/Editor/{TextureSettingsApplier.cs → Sprites/TextureSettingsApplier.cs} +1 -1
- package/Editor/Sprites.meta +3 -0
- package/Editor/Utils/DxReadOnlyPropertyDrawer.cs +1 -1
- package/Runtime/Core/Helper/DirectoryHelper.cs +64 -0
- package/package.json +3 -1
- package/Editor/SpriteAtlasGenerator.cs +0 -895
- package/Editor/SpriteAtlasGenerator.cs.meta +0 -3
- package/Editor/Utils/GUIHorizontalScope.cs +0 -20
- package/Editor/Utils/GUIHorizontalScope.cs.meta +0 -3
- package/Editor/Utils/GUIIndentScope.cs +0 -20
- package/Editor/Utils/GUIIndentScope.cs.meta +0 -3
- /package/Editor/{AnimationCopier.cs.meta → Sprites/AnimationCopier.cs.meta} +0 -0
- /package/Editor/{AnimationCreator.cs.meta → Sprites/AnimationCreator.cs.meta} +0 -0
- /package/Editor/{SpriteCropper.cs.meta → Sprites/SpriteCropper.cs.meta} +0 -0
- /package/Editor/{SpriteSettingsApplier.cs.meta → Sprites/SpriteSettingsApplier.cs.meta} +0 -0
- /package/Editor/{TextureResizerWizard.cs.meta → Sprites/TextureResizerWizard.cs.meta} +0 -0
- /package/Editor/{TextureSettingsApplier.cs.meta → Sprites/TextureSettingsApplier.cs.meta} +0 -0
|
@@ -0,0 +1,938 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
2
|
+
{
|
|
3
|
+
#if UNITY_EDITOR
|
|
4
|
+
using System;
|
|
5
|
+
using System.Collections.Generic;
|
|
6
|
+
using System.IO;
|
|
7
|
+
using System.Linq;
|
|
8
|
+
using System.Text.RegularExpressions;
|
|
9
|
+
using Core.Extension;
|
|
10
|
+
using Core.Helper;
|
|
11
|
+
using UnityEditor;
|
|
12
|
+
using UnityEditor.U2D;
|
|
13
|
+
using UnityEngine;
|
|
14
|
+
using UnityEngine.U2D;
|
|
15
|
+
using Object = UnityEngine.Object;
|
|
16
|
+
|
|
17
|
+
public sealed class ScriptableSpriteAtlasEditor : EditorWindow
|
|
18
|
+
{
|
|
19
|
+
private List<ScriptableSpriteAtlas> _atlasConfigs = new();
|
|
20
|
+
private Vector2 _scrollPosition;
|
|
21
|
+
|
|
22
|
+
private sealed class ScanResult
|
|
23
|
+
{
|
|
24
|
+
public List<Sprite> spritesToAdd = new();
|
|
25
|
+
public List<Sprite> spritesToRemove = new();
|
|
26
|
+
public bool hasScanned;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private readonly Dictionary<ScriptableSpriteAtlas, ScanResult> _scanResultsCache = new();
|
|
30
|
+
private readonly Dictionary<ScriptableSpriteAtlas, bool> _foldoutStates = new();
|
|
31
|
+
|
|
32
|
+
private const string NewAtlasConfigDirectory = "Assets/Data";
|
|
33
|
+
|
|
34
|
+
[MenuItem("Tools/Wallstop Studios/Unity Helpers/Sprite Atlas Generator")]
|
|
35
|
+
public static void ShowWindow()
|
|
36
|
+
{
|
|
37
|
+
GetWindow<ScriptableSpriteAtlasEditor>("Sprite Atlas Generator");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private void OnEnable()
|
|
41
|
+
{
|
|
42
|
+
LoadAtlasConfigs();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private void OnFocus()
|
|
46
|
+
{
|
|
47
|
+
LoadAtlasConfigs();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private void OnProjectChange()
|
|
51
|
+
{
|
|
52
|
+
LoadAtlasConfigs();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private void LoadAtlasConfigs()
|
|
56
|
+
{
|
|
57
|
+
_atlasConfigs.Clear();
|
|
58
|
+
Dictionary<ScriptableSpriteAtlas, ScanResult> existingScanCache = new(
|
|
59
|
+
_scanResultsCache
|
|
60
|
+
);
|
|
61
|
+
_scanResultsCache.Clear();
|
|
62
|
+
|
|
63
|
+
string[] guids = AssetDatabase.FindAssets("t:ScriptableSpriteAtlas");
|
|
64
|
+
foreach (string guid in guids)
|
|
65
|
+
{
|
|
66
|
+
string path = AssetDatabase.GUIDToAssetPath(guid);
|
|
67
|
+
ScriptableSpriteAtlas config = AssetDatabase.LoadAssetAtPath<ScriptableSpriteAtlas>(
|
|
68
|
+
path
|
|
69
|
+
);
|
|
70
|
+
if (config != null)
|
|
71
|
+
{
|
|
72
|
+
_atlasConfigs.Add(config);
|
|
73
|
+
if (existingScanCache.TryGetValue(config, out ScanResult cachedResult))
|
|
74
|
+
{
|
|
75
|
+
_scanResultsCache[config] = cachedResult;
|
|
76
|
+
}
|
|
77
|
+
else if (!_scanResultsCache.ContainsKey(config))
|
|
78
|
+
{
|
|
79
|
+
_scanResultsCache[config] = new ScanResult();
|
|
80
|
+
}
|
|
81
|
+
_foldoutStates.TryAdd(config, true);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
_atlasConfigs = _atlasConfigs.OrderBy(c => c.name).ToList();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private void OnGUI()
|
|
88
|
+
{
|
|
89
|
+
EditorGUILayout.LabelField("Sprite Atlas Generation Tool", EditorStyles.boldLabel);
|
|
90
|
+
EditorGUILayout.Space();
|
|
91
|
+
|
|
92
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
93
|
+
{
|
|
94
|
+
if (GUILayout.Button("Refresh Config List", GUILayout.Height(30)))
|
|
95
|
+
{
|
|
96
|
+
LoadAtlasConfigs();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (
|
|
100
|
+
GUILayout.Button(
|
|
101
|
+
$"Create New Config in '{NewAtlasConfigDirectory}'",
|
|
102
|
+
GUILayout.Height(30)
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
{
|
|
106
|
+
CreateNewScriptableSpriteAtlas();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
EditorGUILayout.Space();
|
|
111
|
+
|
|
112
|
+
if (GUILayout.Button("Generate/Update All .spriteatlas Assets", GUILayout.Height(40)))
|
|
113
|
+
{
|
|
114
|
+
if (
|
|
115
|
+
EditorUtility.DisplayDialog(
|
|
116
|
+
"Generate All Atlases",
|
|
117
|
+
"This will create or update .spriteatlas assets based on all loaded configurations. Continue?",
|
|
118
|
+
"Yes",
|
|
119
|
+
"No"
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
{
|
|
123
|
+
GenerateAllAtlases();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (GUILayout.Button("Pack All Generated Sprite Atlases", GUILayout.Height(40)))
|
|
128
|
+
{
|
|
129
|
+
if (
|
|
130
|
+
EditorUtility.DisplayDialog(
|
|
131
|
+
"Pack All Atlases",
|
|
132
|
+
"This will pack all .spriteatlas assets in the project into textures. This can take some time. Continue?",
|
|
133
|
+
"Yes",
|
|
134
|
+
"No"
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
{
|
|
138
|
+
PackAllProjectAtlases();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
EditorGUILayout.Space(20);
|
|
142
|
+
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
|
143
|
+
if (_atlasConfigs.Count == 0)
|
|
144
|
+
{
|
|
145
|
+
EditorGUILayout.HelpBox(
|
|
146
|
+
"No ScriptableSpriteAtlas configurations found. Use the 'Create New Config' button above or create one via Assets > Create > Wallstop Studios > Unity Helpers > Scriptable Sprite Atlas Config.",
|
|
147
|
+
MessageType.Info
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
foreach (ScriptableSpriteAtlas config in _atlasConfigs)
|
|
152
|
+
{
|
|
153
|
+
if (config == null)
|
|
154
|
+
{
|
|
155
|
+
LoadAtlasConfigs();
|
|
156
|
+
Repaint();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
161
|
+
string foldoutLabel =
|
|
162
|
+
$"{config.name} (Output: {config.FullOutputPath ?? "Path Not Set"})";
|
|
163
|
+
if (AssetDatabase.Contains(config))
|
|
164
|
+
{
|
|
165
|
+
foldoutLabel += $" - Path: {AssetDatabase.GetAssetPath(config)}";
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
_foldoutStates[config] = EditorGUILayout.Foldout(
|
|
169
|
+
_foldoutStates[config],
|
|
170
|
+
foldoutLabel,
|
|
171
|
+
true,
|
|
172
|
+
EditorStyles.foldoutHeader
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (_foldoutStates[config])
|
|
176
|
+
{
|
|
177
|
+
using EditorGUI.IndentLevelScope indentScope = new();
|
|
178
|
+
SerializedObject serializedConfig = new(config);
|
|
179
|
+
serializedConfig.Update();
|
|
180
|
+
EditorGUI.BeginChangeCheck();
|
|
181
|
+
SerializedProperty scriptProperty = serializedConfig.FindProperty("m_Script");
|
|
182
|
+
if (scriptProperty != null)
|
|
183
|
+
{
|
|
184
|
+
GUI.enabled = false;
|
|
185
|
+
EditorGUILayout.PropertyField(scriptProperty);
|
|
186
|
+
GUI.enabled = true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
SerializedProperty property = serializedConfig.GetIterator();
|
|
190
|
+
bool enterChildren = true;
|
|
191
|
+
while (property.NextVisible(enterChildren))
|
|
192
|
+
{
|
|
193
|
+
enterChildren = false;
|
|
194
|
+
if (property.name == "m_Script")
|
|
195
|
+
{
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
EditorGUILayout.PropertyField(property, true);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (EditorGUI.EndChangeCheck())
|
|
203
|
+
{
|
|
204
|
+
serializedConfig.ApplyModifiedProperties();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
EditorGUILayout.Space();
|
|
208
|
+
if (GUILayout.Button("Add New Source Folder Entry"))
|
|
209
|
+
{
|
|
210
|
+
string folderPath = EditorUtility.OpenFolderPanel(
|
|
211
|
+
"Select Source Folder",
|
|
212
|
+
Application.dataPath,
|
|
213
|
+
""
|
|
214
|
+
);
|
|
215
|
+
if (!string.IsNullOrWhiteSpace(folderPath))
|
|
216
|
+
{
|
|
217
|
+
if (folderPath.StartsWith(Application.dataPath))
|
|
218
|
+
{
|
|
219
|
+
string relativePath =
|
|
220
|
+
"Assets" + folderPath.Substring(Application.dataPath.Length);
|
|
221
|
+
relativePath = relativePath.SanitizePath();
|
|
222
|
+
SerializedProperty sourceFolderEntriesProp =
|
|
223
|
+
serializedConfig.FindProperty(
|
|
224
|
+
nameof(ScriptableSpriteAtlas.sourceFolderEntries)
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
bool pathExists = false;
|
|
228
|
+
for (int j = 0; j < sourceFolderEntriesProp.arraySize; j++)
|
|
229
|
+
{
|
|
230
|
+
SerializedProperty entryProp =
|
|
231
|
+
sourceFolderEntriesProp.GetArrayElementAtIndex(j);
|
|
232
|
+
SerializedProperty pathProp = entryProp.FindPropertyRelative(
|
|
233
|
+
"folderPath"
|
|
234
|
+
);
|
|
235
|
+
if (
|
|
236
|
+
string.Equals(
|
|
237
|
+
pathProp.stringValue,
|
|
238
|
+
relativePath,
|
|
239
|
+
StringComparison.Ordinal
|
|
240
|
+
)
|
|
241
|
+
)
|
|
242
|
+
{
|
|
243
|
+
pathExists = true;
|
|
244
|
+
this.LogWarn(
|
|
245
|
+
$"Folder path '{relativePath}' already exists in an entry for '{config.name}'."
|
|
246
|
+
);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (!pathExists)
|
|
252
|
+
{
|
|
253
|
+
sourceFolderEntriesProp.InsertArrayElementAtIndex(
|
|
254
|
+
sourceFolderEntriesProp.arraySize
|
|
255
|
+
);
|
|
256
|
+
SerializedProperty newEntryProp =
|
|
257
|
+
sourceFolderEntriesProp.GetArrayElementAtIndex(
|
|
258
|
+
sourceFolderEntriesProp.arraySize - 1
|
|
259
|
+
);
|
|
260
|
+
newEntryProp.FindPropertyRelative("folderPath").stringValue =
|
|
261
|
+
relativePath;
|
|
262
|
+
|
|
263
|
+
serializedConfig.ApplyModifiedProperties();
|
|
264
|
+
this.Log(
|
|
265
|
+
$"Added new source folder entry for '{relativePath}' to '{config.name}'. You can add regexes to it below."
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else
|
|
270
|
+
{
|
|
271
|
+
EditorUtility.DisplayDialog(
|
|
272
|
+
"Invalid Folder",
|
|
273
|
+
"The selected folder must be within the project's 'Assets' directory.",
|
|
274
|
+
"OK"
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
EditorGUILayout.Space();
|
|
281
|
+
EditorGUILayout.LabelField("Analysis & Actions", EditorStyles.boldLabel);
|
|
282
|
+
|
|
283
|
+
if (GUILayout.Button($"Scan Folders for '{config.name}'"))
|
|
284
|
+
{
|
|
285
|
+
ScanFoldersForConfig(config);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
ScanResult result = _scanResultsCache[config];
|
|
289
|
+
if (result.hasScanned)
|
|
290
|
+
{
|
|
291
|
+
EditorGUILayout.LabelField(
|
|
292
|
+
$"Current manually added sprites: {config.spritesToPack.Count(s => s != null)}"
|
|
293
|
+
);
|
|
294
|
+
EditorGUILayout.LabelField(
|
|
295
|
+
"Sprites found by scan (not yet added/removed):"
|
|
296
|
+
);
|
|
297
|
+
using EditorGUI.IndentLevelScope nextIndentScope = new();
|
|
298
|
+
|
|
299
|
+
if (result.spritesToAdd.Count > 0)
|
|
300
|
+
{
|
|
301
|
+
EditorGUILayout.LabelField(
|
|
302
|
+
$"To Add: {result.spritesToAdd.Count} sprites."
|
|
303
|
+
);
|
|
304
|
+
if (
|
|
305
|
+
GUILayout.Button(
|
|
306
|
+
$"Add {result.spritesToAdd.Count} Sprites to '{config.name}' List"
|
|
307
|
+
)
|
|
308
|
+
)
|
|
309
|
+
{
|
|
310
|
+
AddScannedSprites(config, result);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
else
|
|
314
|
+
{
|
|
315
|
+
EditorGUILayout.LabelField(
|
|
316
|
+
"To Add: 0 sprites.",
|
|
317
|
+
EditorStyles.miniLabel
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (result.spritesToRemove.Count > 0)
|
|
322
|
+
{
|
|
323
|
+
EditorGUILayout.LabelField(
|
|
324
|
+
$"To Remove: {result.spritesToRemove.Count} sprites (currently in list but not found by scan)."
|
|
325
|
+
);
|
|
326
|
+
if (
|
|
327
|
+
GUILayout.Button(
|
|
328
|
+
$"Remove {result.spritesToRemove.Count} Sprites from '{config.name}' List"
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
{
|
|
332
|
+
RemoveUnfoundSprites(config, result);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else
|
|
336
|
+
{
|
|
337
|
+
EditorGUILayout.LabelField(
|
|
338
|
+
"To Remove: 0 sprites.",
|
|
339
|
+
EditorStyles.miniLabel
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else
|
|
344
|
+
{
|
|
345
|
+
EditorGUILayout.HelpBox(
|
|
346
|
+
"Scan to see potential changes from folder sources.",
|
|
347
|
+
MessageType.None
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
EditorGUILayout.Space();
|
|
352
|
+
EditorGUILayout.LabelField("Source Sprite Utilities", EditorStyles.boldLabel);
|
|
353
|
+
|
|
354
|
+
int validSpriteCount = config.spritesToPack.Count(s => s != null);
|
|
355
|
+
EditorGUI.BeginDisabledGroup(validSpriteCount == 0);
|
|
356
|
+
if (
|
|
357
|
+
GUILayout.Button(
|
|
358
|
+
$"Force Uncompressed for {validSpriteCount} Source Sprites in '{config.name}'"
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
{
|
|
362
|
+
if (
|
|
363
|
+
EditorUtility.DisplayDialog(
|
|
364
|
+
"Force Uncompressed Source Sprites",
|
|
365
|
+
$"This will modify the import settings of {validSpriteCount} source sprites currently in the '{config.name}' list.\n\n"
|
|
366
|
+
+ "- Crunch compression will be disabled.\n"
|
|
367
|
+
+ "- Texture format for the 'Default' platform will be set to uncompressed (RGBA32 or RGB24).\n\n"
|
|
368
|
+
+ "This action modifies source asset import settings and may require re-packing atlases. Are you sure?",
|
|
369
|
+
"Yes, Modify Source Sprites",
|
|
370
|
+
"Cancel"
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
{
|
|
374
|
+
ForceUncompressedSourceSprites(config);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
EditorGUI.EndDisabledGroup();
|
|
378
|
+
|
|
379
|
+
EditorGUILayout.Space();
|
|
380
|
+
if (
|
|
381
|
+
GUILayout.Button(
|
|
382
|
+
$"Generate/Update '{config.outputSpriteAtlasName}.spriteatlas' ONLY"
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
{
|
|
386
|
+
if (
|
|
387
|
+
EditorUtility.DisplayDialog(
|
|
388
|
+
$"Generate Atlas: {config.name}",
|
|
389
|
+
$"This will create or update '{config.outputSpriteAtlasName}.spriteatlas'. Continue?",
|
|
390
|
+
"Yes",
|
|
391
|
+
"No"
|
|
392
|
+
)
|
|
393
|
+
)
|
|
394
|
+
{
|
|
395
|
+
GenerateSingleAtlas(config);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
EditorGUILayout.EndVertical();
|
|
400
|
+
EditorGUILayout.Space();
|
|
401
|
+
}
|
|
402
|
+
EditorGUILayout.EndScrollView();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private void CreateNewScriptableSpriteAtlas()
|
|
406
|
+
{
|
|
407
|
+
if (!Directory.Exists(NewAtlasConfigDirectory))
|
|
408
|
+
{
|
|
409
|
+
Directory.CreateDirectory(NewAtlasConfigDirectory);
|
|
410
|
+
AssetDatabase.Refresh();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
ScriptableSpriteAtlas newAtlasConfig = CreateInstance<ScriptableSpriteAtlas>();
|
|
414
|
+
newAtlasConfig.outputSpriteAtlasDirectory = "Assets/GeneratedSpriteAtlases";
|
|
415
|
+
newAtlasConfig.outputSpriteAtlasName = "NewlyCreatedAtlas";
|
|
416
|
+
|
|
417
|
+
string path = AssetDatabase.GenerateUniqueAssetPath(
|
|
418
|
+
Path.Combine(NewAtlasConfigDirectory, "NewScriptableSpriteAtlas.asset")
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
AssetDatabase.CreateAsset(newAtlasConfig, path);
|
|
422
|
+
AssetDatabase.SaveAssets();
|
|
423
|
+
AssetDatabase.Refresh();
|
|
424
|
+
|
|
425
|
+
EditorUtility.FocusProjectWindow();
|
|
426
|
+
Selection.activeObject = newAtlasConfig;
|
|
427
|
+
|
|
428
|
+
this.Log($"Created new ScriptableSpriteAtlas at: {path}");
|
|
429
|
+
LoadAtlasConfigs();
|
|
430
|
+
Repaint();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private void ScanFoldersForConfig(ScriptableSpriteAtlas config)
|
|
434
|
+
{
|
|
435
|
+
if (config.sourceFolderEntries == null || config.sourceFolderEntries.Count == 0)
|
|
436
|
+
{
|
|
437
|
+
this.LogWarn(
|
|
438
|
+
$"'{config.name}': No source folder entries defined. Scan will find nothing from folders."
|
|
439
|
+
);
|
|
440
|
+
_scanResultsCache[config] = new ScanResult { hasScanned = true };
|
|
441
|
+
Repaint();
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
ScanResult currentScan = new();
|
|
446
|
+
HashSet<Sprite> foundSpritesInFolders = new();
|
|
447
|
+
|
|
448
|
+
foreach (SourceFolderEntry entry in config.sourceFolderEntries)
|
|
449
|
+
{
|
|
450
|
+
if (
|
|
451
|
+
string.IsNullOrWhiteSpace(entry.folderPath)
|
|
452
|
+
|| !AssetDatabase.IsValidFolder(entry.folderPath)
|
|
453
|
+
)
|
|
454
|
+
{
|
|
455
|
+
this.LogWarn(
|
|
456
|
+
$"'{config.name}': Invalid or empty folder path '{entry.folderPath}' in an entry. Skipping this entry."
|
|
457
|
+
);
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
string[] textureGuids = AssetDatabase.FindAssets(
|
|
462
|
+
"t:Texture2D",
|
|
463
|
+
new[] { entry.folderPath }
|
|
464
|
+
);
|
|
465
|
+
foreach (string guid in textureGuids)
|
|
466
|
+
{
|
|
467
|
+
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
468
|
+
string fileName = Path.GetFileName(assetPath);
|
|
469
|
+
|
|
470
|
+
bool matchesAllRegexesInEntry;
|
|
471
|
+
List<string> activeRegexPatterns = entry
|
|
472
|
+
.regexes.Where(r => !string.IsNullOrWhiteSpace(r))
|
|
473
|
+
.ToList();
|
|
474
|
+
|
|
475
|
+
if (activeRegexPatterns.Count == 0)
|
|
476
|
+
{
|
|
477
|
+
matchesAllRegexesInEntry = true;
|
|
478
|
+
}
|
|
479
|
+
else
|
|
480
|
+
{
|
|
481
|
+
matchesAllRegexesInEntry = true;
|
|
482
|
+
foreach (string regexPattern in activeRegexPatterns)
|
|
483
|
+
{
|
|
484
|
+
try
|
|
485
|
+
{
|
|
486
|
+
if (!Regex.IsMatch(fileName, regexPattern, RegexOptions.IgnoreCase))
|
|
487
|
+
{
|
|
488
|
+
matchesAllRegexesInEntry = false;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (ArgumentException ex)
|
|
493
|
+
{
|
|
494
|
+
this.LogError(
|
|
495
|
+
$"'{config.name}', Folder '{entry.folderPath}': Invalid Regex pattern '{regexPattern}': {ex.Message}. File '{fileName}' will not be matched by this entry due to this error."
|
|
496
|
+
);
|
|
497
|
+
matchesAllRegexesInEntry = false;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (matchesAllRegexesInEntry)
|
|
504
|
+
{
|
|
505
|
+
Object[] assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
|
|
506
|
+
foreach (Object asset in assets)
|
|
507
|
+
{
|
|
508
|
+
if (asset is Sprite spriteAsset && spriteAsset != null)
|
|
509
|
+
{
|
|
510
|
+
foundSpritesInFolders.Add(spriteAsset);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
List<Sprite> validSpritesInConfigList = config
|
|
518
|
+
.spritesToPack.Where(s => s != null)
|
|
519
|
+
.ToList();
|
|
520
|
+
|
|
521
|
+
currentScan.spritesToAdd = foundSpritesInFolders
|
|
522
|
+
.Except(validSpritesInConfigList)
|
|
523
|
+
.ToList();
|
|
524
|
+
|
|
525
|
+
currentScan.spritesToRemove = validSpritesInConfigList
|
|
526
|
+
.Except(foundSpritesInFolders)
|
|
527
|
+
.ToList();
|
|
528
|
+
|
|
529
|
+
currentScan.hasScanned = true;
|
|
530
|
+
_scanResultsCache[config] = currentScan;
|
|
531
|
+
this.Log(
|
|
532
|
+
$"'{config.name}': Scan complete. Total unique sprites found across all folder entries: {foundSpritesInFolders.Count}. Potential to add: {currentScan.spritesToAdd.Count}, Potential to remove: {currentScan.spritesToRemove.Count}."
|
|
533
|
+
);
|
|
534
|
+
Repaint();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
private void AddScannedSprites(ScriptableSpriteAtlas config, ScanResult result)
|
|
538
|
+
{
|
|
539
|
+
if (result.spritesToAdd.Count <= 0)
|
|
540
|
+
{
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
SerializedObject so = new(config);
|
|
545
|
+
SerializedProperty spritesListProp = so.FindProperty(
|
|
546
|
+
nameof(ScriptableSpriteAtlas.spritesToPack)
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
Undo.RecordObject(config, "Add Scanned Sprites to Atlas Config");
|
|
550
|
+
|
|
551
|
+
int addedCount = 0;
|
|
552
|
+
foreach (Sprite sprite in result.spritesToAdd)
|
|
553
|
+
{
|
|
554
|
+
bool alreadyExists = false;
|
|
555
|
+
for (int i = 0; i < spritesListProp.arraySize; i++)
|
|
556
|
+
{
|
|
557
|
+
if (spritesListProp.GetArrayElementAtIndex(i).objectReferenceValue == sprite)
|
|
558
|
+
{
|
|
559
|
+
alreadyExists = true;
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (!alreadyExists)
|
|
564
|
+
{
|
|
565
|
+
spritesListProp.InsertArrayElementAtIndex(spritesListProp.arraySize);
|
|
566
|
+
spritesListProp
|
|
567
|
+
.GetArrayElementAtIndex(spritesListProp.arraySize - 1)
|
|
568
|
+
.objectReferenceValue = sprite;
|
|
569
|
+
addedCount++;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (addedCount > 0)
|
|
574
|
+
{
|
|
575
|
+
so.ApplyModifiedProperties();
|
|
576
|
+
this.Log($"'{config.name}': Added {addedCount} sprites.");
|
|
577
|
+
}
|
|
578
|
+
else
|
|
579
|
+
{
|
|
580
|
+
this.Log(
|
|
581
|
+
$"'{config.name}': No new sprites to add (all found sprites might already be in the list)."
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
result.spritesToAdd.Clear();
|
|
586
|
+
ScanFoldersForConfig(config);
|
|
587
|
+
Repaint();
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
private void RemoveUnfoundSprites(ScriptableSpriteAtlas config, ScanResult result)
|
|
591
|
+
{
|
|
592
|
+
if (result.spritesToRemove.Count <= 0)
|
|
593
|
+
{
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
SerializedObject so = new(config);
|
|
598
|
+
SerializedProperty spritesListProp = so.FindProperty("spritesToPack");
|
|
599
|
+
|
|
600
|
+
Undo.RecordObject(config, "Remove Unfound Sprites from Atlas Config");
|
|
601
|
+
|
|
602
|
+
int countRemoved = 0;
|
|
603
|
+
List<Sprite> spritesActuallyToRemove = new(result.spritesToRemove);
|
|
604
|
+
|
|
605
|
+
for (int i = spritesListProp.arraySize - 1; i >= 0; i--)
|
|
606
|
+
{
|
|
607
|
+
SerializedProperty element = spritesListProp.GetArrayElementAtIndex(i);
|
|
608
|
+
if (
|
|
609
|
+
element.objectReferenceValue != null
|
|
610
|
+
&& spritesActuallyToRemove.Contains(element.objectReferenceValue as Sprite)
|
|
611
|
+
)
|
|
612
|
+
{
|
|
613
|
+
element.objectReferenceValue = null;
|
|
614
|
+
spritesListProp.DeleteArrayElementAtIndex(i);
|
|
615
|
+
countRemoved++;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (countRemoved > 0)
|
|
620
|
+
{
|
|
621
|
+
so.ApplyModifiedProperties();
|
|
622
|
+
this.Log(
|
|
623
|
+
$"'{config.name}': Removed {countRemoved} sprites that were no longer found by scan."
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
result.spritesToRemove.Clear();
|
|
627
|
+
ScanFoldersForConfig(config);
|
|
628
|
+
Repaint();
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private void GenerateAllAtlases()
|
|
632
|
+
{
|
|
633
|
+
if (_atlasConfigs.Count == 0)
|
|
634
|
+
{
|
|
635
|
+
EditorUtility.DisplayDialog(
|
|
636
|
+
"No Configurations",
|
|
637
|
+
"No ScriptableSpriteAtlas configurations found to generate.",
|
|
638
|
+
"OK"
|
|
639
|
+
);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
int totalConfigs = _atlasConfigs.Count;
|
|
644
|
+
int currentConfig = 0;
|
|
645
|
+
|
|
646
|
+
AssetDatabase.StartAssetEditing();
|
|
647
|
+
try
|
|
648
|
+
{
|
|
649
|
+
foreach (ScriptableSpriteAtlas config in _atlasConfigs)
|
|
650
|
+
{
|
|
651
|
+
if (config == null)
|
|
652
|
+
{
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
currentConfig++;
|
|
657
|
+
float progress = (float)currentConfig / totalConfigs;
|
|
658
|
+
EditorUtility.DisplayProgressBar(
|
|
659
|
+
"Generating Sprite Atlases",
|
|
660
|
+
$"Processing: {config.name}",
|
|
661
|
+
progress
|
|
662
|
+
);
|
|
663
|
+
GenerateSingleAtlas(config, false);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
finally
|
|
667
|
+
{
|
|
668
|
+
AssetDatabase.StopAssetEditing();
|
|
669
|
+
EditorUtility.ClearProgressBar();
|
|
670
|
+
AssetDatabase.SaveAssets();
|
|
671
|
+
AssetDatabase.Refresh();
|
|
672
|
+
EditorUtility.DisplayDialog(
|
|
673
|
+
"Generation Complete",
|
|
674
|
+
$"Processed {totalConfigs} atlas configurations.",
|
|
675
|
+
"OK"
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
private void GenerateSingleAtlas(
|
|
681
|
+
ScriptableSpriteAtlas config,
|
|
682
|
+
bool refreshAssetsImmediately = true
|
|
683
|
+
)
|
|
684
|
+
{
|
|
685
|
+
if (config == null)
|
|
686
|
+
{
|
|
687
|
+
this.LogError($"Attempted to generate atlas from a null config.");
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
string outputPath = config.FullOutputPath;
|
|
691
|
+
if (string.IsNullOrWhiteSpace(outputPath))
|
|
692
|
+
{
|
|
693
|
+
this.LogError(
|
|
694
|
+
$"'{config.name}': Output path or name is not set. Cannot generate atlas."
|
|
695
|
+
);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
string directory = Path.GetDirectoryName(outputPath);
|
|
700
|
+
if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
|
|
701
|
+
{
|
|
702
|
+
Directory.CreateDirectory(directory);
|
|
703
|
+
AssetDatabase.Refresh();
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(outputPath);
|
|
707
|
+
bool newAtlas = false;
|
|
708
|
+
if (atlas == null)
|
|
709
|
+
{
|
|
710
|
+
atlas = new SpriteAtlas();
|
|
711
|
+
newAtlas = true;
|
|
712
|
+
this.Log($"'{config.name}': Creating new SpriteAtlas at {outputPath}");
|
|
713
|
+
}
|
|
714
|
+
else
|
|
715
|
+
{
|
|
716
|
+
this.Log($"'{config.name}': Updating existing SpriteAtlas at {outputPath}");
|
|
717
|
+
atlas.Remove(atlas.GetPackables());
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
SpriteAtlasPackingSettings packingSettings = atlas.GetPackingSettings();
|
|
721
|
+
packingSettings.enableRotation = config.enableRotation;
|
|
722
|
+
packingSettings.padding = config.padding;
|
|
723
|
+
atlas.SetPackingSettings(packingSettings);
|
|
724
|
+
|
|
725
|
+
SpriteAtlasTextureSettings textureSettings = atlas.GetTextureSettings();
|
|
726
|
+
textureSettings.readable = config.readWriteEnabled;
|
|
727
|
+
atlas.SetTextureSettings(textureSettings);
|
|
728
|
+
|
|
729
|
+
TextureImporterPlatformSettings platformSettings = atlas.GetPlatformSettings(
|
|
730
|
+
"DefaultTexturePlatform"
|
|
731
|
+
);
|
|
732
|
+
if (string.IsNullOrWhiteSpace(platformSettings.name))
|
|
733
|
+
{
|
|
734
|
+
platformSettings.name = "DefaultTexturePlatform";
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
platformSettings.overridden = true;
|
|
738
|
+
platformSettings.maxTextureSize = config.maxTextureSize;
|
|
739
|
+
|
|
740
|
+
if (config.useCrunchCompression)
|
|
741
|
+
{
|
|
742
|
+
platformSettings.format = TextureImporterFormat.DXT5Crunched;
|
|
743
|
+
platformSettings.crunchedCompression = true;
|
|
744
|
+
platformSettings.compressionQuality = config.crunchCompressionLevel;
|
|
745
|
+
}
|
|
746
|
+
else
|
|
747
|
+
{
|
|
748
|
+
platformSettings.crunchedCompression = false;
|
|
749
|
+
platformSettings.format = TextureImporterFormat.Automatic;
|
|
750
|
+
}
|
|
751
|
+
platformSettings.textureCompression = config.compression;
|
|
752
|
+
atlas.SetPlatformSettings(platformSettings);
|
|
753
|
+
|
|
754
|
+
Object[] spritesToAdd = config.spritesToPack.Where(s => s != null).ToArray<Object>();
|
|
755
|
+
if (spritesToAdd.Length > 0)
|
|
756
|
+
{
|
|
757
|
+
atlas.Add(spritesToAdd);
|
|
758
|
+
}
|
|
759
|
+
else
|
|
760
|
+
{
|
|
761
|
+
this.LogWarn(
|
|
762
|
+
$"'{config.name}': No sprites in the 'spritesToPack' list. Atlas will be empty."
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (newAtlas)
|
|
767
|
+
{
|
|
768
|
+
AssetDatabase.CreateAsset(atlas, outputPath);
|
|
769
|
+
}
|
|
770
|
+
else
|
|
771
|
+
{
|
|
772
|
+
EditorUtility.SetDirty(atlas);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (refreshAssetsImmediately)
|
|
776
|
+
{
|
|
777
|
+
AssetDatabase.SaveAssets();
|
|
778
|
+
AssetDatabase.Refresh();
|
|
779
|
+
}
|
|
780
|
+
this.Log(
|
|
781
|
+
$"'{config.name}': Successfully generated/updated at {outputPath}. Sprites included: {spritesToAdd.Length}."
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private void PackAllProjectAtlases()
|
|
786
|
+
{
|
|
787
|
+
this.Log(
|
|
788
|
+
$"Starting to pack all Sprite Atlases in the project for target: {EditorUserBuildSettings.activeBuildTarget}"
|
|
789
|
+
);
|
|
790
|
+
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
|
|
791
|
+
this.Log($"Finished packing all Sprite Atlases.");
|
|
792
|
+
AssetDatabase.Refresh();
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
private void ForceUncompressedSourceSprites(ScriptableSpriteAtlas config)
|
|
796
|
+
{
|
|
797
|
+
if (config == null)
|
|
798
|
+
{
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
List<Sprite> spritesToProcess = config
|
|
803
|
+
.spritesToPack.Where(s => s != null && s.texture != null)
|
|
804
|
+
.ToList();
|
|
805
|
+
if (spritesToProcess.Count == 0)
|
|
806
|
+
{
|
|
807
|
+
this.LogWarn(
|
|
808
|
+
$"'{config.name}': No valid sprites with textures in the list to modify."
|
|
809
|
+
);
|
|
810
|
+
EditorUtility.DisplayDialog(
|
|
811
|
+
"No Sprites",
|
|
812
|
+
"No valid sprites found in the configuration's list to process.",
|
|
813
|
+
"OK"
|
|
814
|
+
);
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
int modifiedCount = 0;
|
|
819
|
+
int errorCount = 0;
|
|
820
|
+
HashSet<string> processedAssetPaths = new();
|
|
821
|
+
|
|
822
|
+
AssetDatabase.StartAssetEditing();
|
|
823
|
+
try
|
|
824
|
+
{
|
|
825
|
+
for (int i = 0; i < spritesToProcess.Count; i++)
|
|
826
|
+
{
|
|
827
|
+
Sprite sprite = spritesToProcess[i];
|
|
828
|
+
EditorUtility.DisplayProgressBar(
|
|
829
|
+
"Modifying Source Sprite Import Settings",
|
|
830
|
+
$"Processing: {sprite.name} ({i + 1}/{spritesToProcess.Count})",
|
|
831
|
+
(float)(i + 1) / spritesToProcess.Count
|
|
832
|
+
);
|
|
833
|
+
|
|
834
|
+
string assetPath = AssetDatabase.GetAssetPath(sprite.texture);
|
|
835
|
+
if (string.IsNullOrWhiteSpace(assetPath))
|
|
836
|
+
{
|
|
837
|
+
this.LogWarn(
|
|
838
|
+
$"Could not find asset path for sprite's texture: {sprite.name}. Skipping."
|
|
839
|
+
);
|
|
840
|
+
errorCount++;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
if (!processedAssetPaths.Add(assetPath))
|
|
845
|
+
{
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
TextureImporter importer =
|
|
850
|
+
AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
|
851
|
+
if (importer == null)
|
|
852
|
+
{
|
|
853
|
+
this.LogWarn(
|
|
854
|
+
$"Could not get TextureImporter for asset: {assetPath} (from sprite: {sprite.name}). Skipping."
|
|
855
|
+
);
|
|
856
|
+
errorCount++;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
bool settingsActuallyModified = false;
|
|
861
|
+
|
|
862
|
+
if (importer.crunchedCompression)
|
|
863
|
+
{
|
|
864
|
+
importer.crunchedCompression = false;
|
|
865
|
+
settingsActuallyModified = true;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
if (importer.textureCompression != TextureImporterCompression.Uncompressed)
|
|
869
|
+
{
|
|
870
|
+
importer.textureCompression = TextureImporterCompression.Uncompressed;
|
|
871
|
+
settingsActuallyModified = true;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
TextureImporterPlatformSettings platformSettings =
|
|
875
|
+
importer.GetDefaultPlatformTextureSettings();
|
|
876
|
+
bool platformSettingsChangedThisTime = false;
|
|
877
|
+
TextureImporterFormat targetFormat = importer.DoesSourceTextureHaveAlpha()
|
|
878
|
+
? TextureImporterFormat.RGBA32
|
|
879
|
+
: TextureImporterFormat.RGB24;
|
|
880
|
+
|
|
881
|
+
if (platformSettings.format != targetFormat)
|
|
882
|
+
{
|
|
883
|
+
platformSettings.format = targetFormat;
|
|
884
|
+
platformSettingsChangedThisTime = true;
|
|
885
|
+
}
|
|
886
|
+
if (platformSettings.crunchedCompression)
|
|
887
|
+
{
|
|
888
|
+
platformSettings.crunchedCompression = false;
|
|
889
|
+
platformSettingsChangedThisTime = true;
|
|
890
|
+
}
|
|
891
|
+
if (platformSettings.compressionQuality != 100)
|
|
892
|
+
{
|
|
893
|
+
platformSettings.compressionQuality = 100;
|
|
894
|
+
platformSettingsChangedThisTime = true;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (platformSettingsChangedThisTime || !platformSettings.overridden)
|
|
898
|
+
{
|
|
899
|
+
platformSettings.overridden = true;
|
|
900
|
+
importer.SetPlatformTextureSettings(platformSettings);
|
|
901
|
+
settingsActuallyModified = true;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (settingsActuallyModified)
|
|
905
|
+
{
|
|
906
|
+
importer.SaveAndReimport();
|
|
907
|
+
modifiedCount++;
|
|
908
|
+
this.Log(
|
|
909
|
+
$"Set import settings for texture: {assetPath} (from sprite: {sprite.name}) to uncompressed ({targetFormat})."
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
finally
|
|
915
|
+
{
|
|
916
|
+
AssetDatabase.StopAssetEditing();
|
|
917
|
+
EditorUtility.ClearProgressBar();
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
if (modifiedCount > 0 || errorCount > 0)
|
|
921
|
+
{
|
|
922
|
+
AssetDatabase.Refresh();
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
string summaryMessage =
|
|
926
|
+
$"Finished processing source sprite textures for '{config.name}'.\n"
|
|
927
|
+
+ $"Successfully modified importers for: {modifiedCount} textures.\n"
|
|
928
|
+
+ $"Errors/Skipped duplicates: {errorCount + (spritesToProcess.Count - processedAssetPaths.Count)}.";
|
|
929
|
+
EditorUtility.DisplayDialog(
|
|
930
|
+
"Source Sprite Modification Complete",
|
|
931
|
+
summaryMessage,
|
|
932
|
+
"OK"
|
|
933
|
+
);
|
|
934
|
+
this.Log($"{summaryMessage}");
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
#endif
|
|
938
|
+
}
|