com.wallstop-studios.unity-helpers 2.0.0-rc69 → 2.0.0-rc70

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.
Files changed (45) hide show
  1. package/Editor/AnimationCopier.cs +875 -93
  2. package/Editor/AnimationCreator.cs +840 -137
  3. package/Editor/AnimationEventEditor.cs +4 -4
  4. package/Editor/AnimatorControllerCopier.cs +3 -3
  5. package/Editor/Extensions/UnityExtensions.cs +26 -0
  6. package/Editor/Extensions/UnityExtensions.cs.meta +3 -0
  7. package/Editor/Extensions.meta +3 -0
  8. package/Editor/FitTextureSizeWindow.cs +371 -0
  9. package/Editor/PrefabChecker.cs +716 -0
  10. package/Editor/SpriteAtlasGenerator.cs +598 -0
  11. package/Editor/SpriteAtlasGenerator.cs.meta +3 -0
  12. package/Editor/SpriteCropper.cs +407 -0
  13. package/Editor/SpriteCropper.cs.meta +3 -0
  14. package/Editor/SpriteSettingsApplier.cs +756 -92
  15. package/Editor/TextureResizerWizard.cs +3 -3
  16. package/Editor/TextureSettingsApplier.cs +9 -9
  17. package/Editor/WShowIfPropertyDrawer.cs +2 -2
  18. package/Runtime/Core/Attributes/EnumDisplayNameAttribute.cs +15 -0
  19. package/Runtime/Core/Attributes/EnumDisplayNameAttribute.cs.meta +3 -0
  20. package/Runtime/Core/Extension/EnumExtensions.cs +176 -1
  21. package/Runtime/Core/Extension/UnityExtensions.cs +1 -1
  22. package/Runtime/Tags/AttributeUtilities.cs +8 -7
  23. package/Runtime/Tags/EffectHandler.cs +2 -1
  24. package/Tests/Runtime/DataStructures/BalancedKDTreeTests.cs +1 -1
  25. package/Tests/Runtime/DataStructures/CyclicBufferTests.cs +1 -1
  26. package/Tests/Runtime/DataStructures/QuadTreeTests.cs +1 -1
  27. package/Tests/Runtime/DataStructures/UnbalancedKDTreeTests.cs +1 -1
  28. package/Tests/Runtime/Extensions/DictionaryExtensionTests.cs +1 -1
  29. package/Tests/Runtime/Extensions/EnumExtensionTests.cs +1 -1
  30. package/Tests/Runtime/Extensions/IListExtensionTests.cs +1 -1
  31. package/Tests/Runtime/Extensions/LoggingExtensionTests.cs +1 -1
  32. package/Tests/Runtime/Extensions/RandomExtensionTests.cs +1 -1
  33. package/Tests/Runtime/Extensions/StringExtensionTests.cs +1 -1
  34. package/Tests/Runtime/Helper/WallMathTests.cs +1 -1
  35. package/Tests/Runtime/Performance/KDTreePerformanceTests.cs +1 -1
  36. package/Tests/Runtime/Performance/QuadTreePerformanceTests.cs +1 -1
  37. package/Tests/Runtime/Performance/SpatialTreePerformanceTest.cs +1 -1
  38. package/Tests/Runtime/Performance/UnbalancedKDTreeTests.cs +1 -1
  39. package/Tests/Runtime/Random/RandomTestBase.cs +2 -2
  40. package/Tests/Runtime/Serialization/JsonSerializationTest.cs +1 -1
  41. package/package.json +1 -1
  42. package/Editor/FitTextureSizeWizard.cs +0 -147
  43. package/Editor/PrefabCheckWizard.cs +0 -167
  44. /package/Editor/{FitTextureSizeWizard.cs.meta → FitTextureSizeWindow.cs.meta} +0 -0
  45. /package/Editor/{PrefabCheckWizard.cs.meta → PrefabChecker.cs.meta} +0 -0
@@ -7,8 +7,8 @@
7
7
  using System.Reflection;
8
8
  using UnityEditor;
9
9
  using UnityEngine;
10
- using WallstopStudios.UnityHelpers.Core.Attributes;
11
- using WallstopStudios.UnityHelpers.Core.Helper;
10
+ using Core.Attributes;
11
+ using Core.Helper;
12
12
  using WallstopStudios.UnityHelpers.Utils;
13
13
 
14
14
  // https://gist.githubusercontent.com/yujen/5e1cd78e2a341260b38029de08a449da/raw/ac60c1002e0e14375de5b2b0a167af00df3f74b4/SeniaAnimationEventEditor.cs
@@ -38,7 +38,7 @@
38
38
  TypesToMethods = typesToMethods;
39
39
  }
40
40
 
41
- [MenuItem("Tools/Unity Helpers/AnimationEvent Editor")]
41
+ [MenuItem("Tools/Wallstop Studios/Unity Helpers/AnimationEvent Editor")]
42
42
  private static void AnimationEventEditorMenu()
43
43
  {
44
44
  GetWindow(typeof(AnimationEventEditor));
@@ -76,7 +76,7 @@
76
76
  private Animator _sourceAnimator;
77
77
  private AnimationClip _currentClip;
78
78
  private bool _explicitMode = true;
79
- private bool _controlFrameTime = false;
79
+ private bool _controlFrameTime;
80
80
  private string _animationSearchString = string.Empty;
81
81
  private List<ObjectReferenceKeyframe> _referenceCurve;
82
82
 
@@ -6,8 +6,8 @@
6
6
  using UnityEditor;
7
7
  using UnityEngine;
8
8
  using Utils;
9
- using WallstopStudios.UnityHelpers.Core.Attributes;
10
- using WallstopStudios.UnityHelpers.Core.Extension;
9
+ using Core.Attributes;
10
+ using Core.Extension;
11
11
 
12
12
  public sealed class AnimatorControllerCopier : ScriptableWizard
13
13
  {
@@ -20,7 +20,7 @@
20
20
  [DxReadOnly]
21
21
  public string controllerDestinationPath;
22
22
 
23
- [MenuItem("Tools/Unity Helpers/Animator Controller Copier")]
23
+ [MenuItem("Tools/Wallstop Studios/Unity Helpers/Animator Controller Copier")]
24
24
  public static void CopyAnimations()
25
25
  {
26
26
  _ = DisplayWizard<AnimatorControllerCopier>("Animator Controller Copier", "Copy");
@@ -0,0 +1,26 @@
1
+ namespace WallstopStudios.UnityHelpers.Editor.Extensions
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System.Linq;
5
+ using System.Reflection;
6
+ using Core.Helper;
7
+ using UnityEditor.U2D;
8
+ using UnityEngine;
9
+ using UnityEngine.U2D;
10
+
11
+ public static class UnityExtensions
12
+ {
13
+ public static Texture2D GetPreviewTexture(this SpriteAtlas spriteAtlas)
14
+ {
15
+ MethodInfo method = typeof(SpriteAtlasExtensions).GetMethod(
16
+ "GetPreviewTextures",
17
+ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public
18
+ );
19
+ object obj = method?.Invoke(null, new object[] { spriteAtlas });
20
+ return obj is not Texture2D[] { Length: > 0 } textures
21
+ ? null
22
+ : textures.Where(Objects.NotNull).FirstOrDefault();
23
+ }
24
+ }
25
+ #endif
26
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 838d412b343447f994b8c81ee00ae405
3
+ timeCreated: 1746466463
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 5ccafdb3b4ea4a90970b596a9e0b3ace
3
+ timeCreated: 1746466455
@@ -0,0 +1,371 @@
1
+ namespace WallstopStudios.UnityHelpers.Editor
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System.Collections.Generic;
5
+ using System.IO;
6
+ using System.Linq;
7
+ using UnityEditor;
8
+ using UnityEngine;
9
+ using Core.Extension;
10
+ using Object = UnityEngine.Object;
11
+
12
+ public enum FitMode
13
+ {
14
+ GrowAndShrink = 0,
15
+ GrowOnly = 1,
16
+ ShrinkOnly = 2,
17
+ }
18
+
19
+ public sealed class FitTextureSizeWindow : EditorWindow
20
+ {
21
+ private FitMode _fitMode = FitMode.GrowAndShrink;
22
+
23
+ [SerializeField]
24
+ private List<Object> _textureSourcePaths = new();
25
+ private Vector2 _scrollPosition = Vector2.zero;
26
+ private SerializedObject _serializedObject;
27
+ private SerializedProperty _textureSourcePathsProperty;
28
+ private int _potentialChangeCount = -1;
29
+
30
+ [MenuItem("Tools/Wallstop Studios/Unity Helpers/Fit Texture Size", priority = -1)]
31
+ public static void ShowWindow()
32
+ {
33
+ GetWindow<FitTextureSizeWindow>("Fit Texture Size");
34
+ }
35
+
36
+ private void OnEnable()
37
+ {
38
+ _serializedObject = new SerializedObject(this);
39
+ _textureSourcePathsProperty = _serializedObject.FindProperty(
40
+ nameof(_textureSourcePaths)
41
+ );
42
+
43
+ if (_textureSourcePaths != null && _textureSourcePaths.Count != 0)
44
+ {
45
+ return;
46
+ }
47
+
48
+ _textureSourcePaths = new List<Object>();
49
+ Object defaultFolder = AssetDatabase.LoadAssetAtPath<Object>("Assets/Sprites");
50
+ if (defaultFolder == null)
51
+ {
52
+ return;
53
+ }
54
+
55
+ _textureSourcePaths.Add(defaultFolder);
56
+ _serializedObject.Update();
57
+ }
58
+
59
+ private void OnGUI()
60
+ {
61
+ _serializedObject.Update();
62
+ _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
63
+
64
+ EditorGUILayout.LabelField("Configuration", EditorStyles.boldLabel);
65
+ _fitMode = (FitMode)EditorGUILayout.EnumPopup("Fit Mode", _fitMode);
66
+
67
+ EditorGUILayout.Space();
68
+ EditorGUILayout.LabelField("Source Folders", EditorStyles.boldLabel);
69
+
70
+ if (GUILayout.Button("Add Source Directory"))
71
+ {
72
+ string path = EditorUtility.OpenFolderPanel(
73
+ "Select Texture Source Directory",
74
+ "Assets",
75
+ ""
76
+ );
77
+ if (!string.IsNullOrWhiteSpace(path))
78
+ {
79
+ if (path.StartsWith(Application.dataPath))
80
+ {
81
+ string relativePath =
82
+ "Assets" + path.Substring(Application.dataPath.Length);
83
+ Object folderObject = AssetDatabase.LoadAssetAtPath<Object>(relativePath);
84
+ if (folderObject != null)
85
+ {
86
+ _textureSourcePaths ??= new List<Object>();
87
+ if (!_textureSourcePaths.Contains(folderObject))
88
+ {
89
+ _textureSourcePaths.Add(folderObject);
90
+ _potentialChangeCount = -1;
91
+ }
92
+ else
93
+ {
94
+ this.LogWarn($"Directory '{relativePath}' is already in the list.");
95
+ }
96
+ }
97
+ else
98
+ {
99
+ this.LogError($"Could not load asset at path: '{relativePath}'");
100
+ }
101
+ }
102
+ else
103
+ {
104
+ this.LogError(
105
+ $"Selected path is outside the project's Assets folder: '{path}'"
106
+ );
107
+ }
108
+ }
109
+ }
110
+
111
+ EditorGUILayout.PropertyField(_textureSourcePathsProperty, true);
112
+ EditorGUILayout.Space();
113
+ EditorGUILayout.LabelField("Actions", EditorStyles.boldLabel);
114
+
115
+ if (GUILayout.Button("Calculate Potential Changes"))
116
+ {
117
+ _potentialChangeCount = CalculateTextureChanges(applyChanges: false);
118
+ string message =
119
+ _potentialChangeCount >= 0
120
+ ? $"Calculation complete. {_potentialChangeCount} textures would be modified."
121
+ : "Calculation failed.";
122
+ this.Log($"{message}");
123
+ }
124
+
125
+ if (_potentialChangeCount >= 0)
126
+ {
127
+ EditorGUILayout.HelpBox(
128
+ $"{_potentialChangeCount} textures would be modified with the current settings.",
129
+ MessageType.Info
130
+ );
131
+ }
132
+
133
+ if (GUILayout.Button("Run Fit Texture Size"))
134
+ {
135
+ int actualChanges = CalculateTextureChanges(applyChanges: true);
136
+ _potentialChangeCount = -1;
137
+ string message =
138
+ actualChanges >= 0
139
+ ? $"Operation complete. {actualChanges} textures were modified."
140
+ : "Operation failed.";
141
+ this.Log($"{message}");
142
+ }
143
+
144
+ EditorGUILayout.EndScrollView();
145
+ _serializedObject.ApplyModifiedProperties();
146
+ }
147
+
148
+ private List<Texture2D> CollectTextures()
149
+ {
150
+ _textureSourcePaths ??= new List<Object>();
151
+ HashSet<string> uniqueAssetPaths = new();
152
+ List<string> searchPaths = new();
153
+
154
+ foreach (Object sourceObject in _textureSourcePaths)
155
+ {
156
+ if (sourceObject == null)
157
+ {
158
+ continue;
159
+ }
160
+
161
+ string assetPath = AssetDatabase.GetAssetPath(sourceObject);
162
+ if (string.IsNullOrWhiteSpace(assetPath))
163
+ {
164
+ continue;
165
+ }
166
+
167
+ if (AssetDatabase.IsValidFolder(assetPath))
168
+ {
169
+ _ = uniqueAssetPaths.Add(assetPath);
170
+ }
171
+ else
172
+ {
173
+ this.LogWarn($"Skipping non-folder object: '{assetPath}'");
174
+ }
175
+ }
176
+
177
+ if (!uniqueAssetPaths.Any())
178
+ {
179
+ if (_textureSourcePaths.Any(o => o != null))
180
+ {
181
+ this.LogWarn($"No valid source folders found in the list.");
182
+ }
183
+ else
184
+ {
185
+ this.Log($"No source folders specified. Searching entire 'Assets' folder.");
186
+ searchPaths.Add("Assets");
187
+ }
188
+ }
189
+ else
190
+ {
191
+ searchPaths.AddRange(uniqueAssetPaths);
192
+ }
193
+
194
+ List<Texture2D> foundTextures = new();
195
+ if (!searchPaths.Any())
196
+ {
197
+ return foundTextures.Distinct().OrderBy(texture => texture.name).ToList();
198
+ }
199
+
200
+ string[] guids = AssetDatabase.FindAssets("t:texture2D", searchPaths.ToArray());
201
+ foreach (string assetGuid in guids)
202
+ {
203
+ string path = AssetDatabase.GUIDToAssetPath(assetGuid);
204
+ if (string.IsNullOrWhiteSpace(path))
205
+ {
206
+ continue;
207
+ }
208
+
209
+ Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
210
+ if (texture != null)
211
+ {
212
+ foundTextures.Add(texture);
213
+ }
214
+ }
215
+
216
+ return foundTextures.Distinct().OrderBy(texture => texture.name).ToList();
217
+ }
218
+
219
+ private int CalculateTextureChanges(bool applyChanges)
220
+ {
221
+ List<Texture2D> texturesToProcess = CollectTextures();
222
+
223
+ if (texturesToProcess.Count <= 0)
224
+ {
225
+ this.Log($"No textures found in the specified paths.");
226
+ return 0;
227
+ }
228
+
229
+ int changedCount = 0;
230
+ List<TextureImporter> updatedImporters = new();
231
+ if (applyChanges)
232
+ {
233
+ AssetDatabase.StartAssetEditing();
234
+ }
235
+ try
236
+ {
237
+ float totalAssets = texturesToProcess.Count;
238
+ for (int i = 0; i < texturesToProcess.Count; i++)
239
+ {
240
+ Texture2D texture = texturesToProcess[i];
241
+ string assetPath = AssetDatabase.GetAssetPath(texture);
242
+ float progress = (i + 1) / totalAssets;
243
+ string progressBarTitle = applyChanges
244
+ ? "Fitting Texture Size"
245
+ : "Calculating Changes";
246
+ bool cancel = EditorUtility.DisplayCancelableProgressBar(
247
+ progressBarTitle,
248
+ $"Checking: {Path.GetFileName(assetPath)} ({i + 1}/{texturesToProcess.Count})",
249
+ progress
250
+ );
251
+
252
+ if (cancel)
253
+ {
254
+ this.LogWarn($"Operation cancelled by user.");
255
+ return -1;
256
+ }
257
+
258
+ if (string.IsNullOrWhiteSpace(assetPath))
259
+ {
260
+ continue;
261
+ }
262
+
263
+ TextureImporter textureImporter =
264
+ AssetImporter.GetAtPath(assetPath) as TextureImporter;
265
+ if (textureImporter == null)
266
+ {
267
+ continue;
268
+ }
269
+
270
+ textureImporter.GetSourceTextureWidthAndHeight(out int width, out int height);
271
+
272
+ float size = Mathf.Max(width, height);
273
+ int currentTextureSize = textureImporter.maxTextureSize;
274
+ int targetTextureSize = currentTextureSize;
275
+ bool needsChange = false;
276
+
277
+ if (_fitMode is FitMode.GrowAndShrink or FitMode.GrowOnly)
278
+ {
279
+ int tempSize = targetTextureSize;
280
+ while (tempSize < size)
281
+ {
282
+ tempSize <<= 1;
283
+ }
284
+ if (tempSize != targetTextureSize)
285
+ {
286
+ targetTextureSize = tempSize;
287
+ needsChange = true;
288
+ }
289
+ }
290
+
291
+ if (_fitMode is FitMode.GrowAndShrink or FitMode.ShrinkOnly)
292
+ {
293
+ int tempSize = targetTextureSize;
294
+ while (0 < tempSize >> 1 && size <= tempSize >> 1)
295
+ {
296
+ tempSize >>= 1;
297
+ }
298
+ if (tempSize != targetTextureSize)
299
+ {
300
+ targetTextureSize = tempSize;
301
+ needsChange = true;
302
+ }
303
+ else if (!needsChange && tempSize != currentTextureSize)
304
+ {
305
+ targetTextureSize = tempSize;
306
+ needsChange = true;
307
+ }
308
+ }
309
+
310
+ if (!needsChange || currentTextureSize == targetTextureSize)
311
+ {
312
+ continue;
313
+ }
314
+
315
+ changedCount++;
316
+ if (!applyChanges)
317
+ {
318
+ continue;
319
+ }
320
+
321
+ textureImporter.maxTextureSize = targetTextureSize;
322
+ updatedImporters.Add(textureImporter);
323
+
324
+ if (textureImporter.maxTextureSize == targetTextureSize)
325
+ {
326
+ continue;
327
+ }
328
+
329
+ this.LogError(
330
+ $"Failed to update {texture.name} to {targetTextureSize}, importer set size to {textureImporter.maxTextureSize}. Path: '{assetPath}'."
331
+ );
332
+
333
+ if (currentTextureSize == textureImporter.maxTextureSize)
334
+ {
335
+ changedCount--;
336
+ _ = updatedImporters.Remove(textureImporter);
337
+ }
338
+ }
339
+
340
+ if (applyChanges)
341
+ {
342
+ foreach (TextureImporter importer in updatedImporters)
343
+ {
344
+ importer.SaveAndReimport();
345
+ }
346
+
347
+ if (changedCount != 0)
348
+ {
349
+ this.Log($"Updated {changedCount} textures.");
350
+ AssetDatabase.SaveAssets();
351
+ AssetDatabase.Refresh();
352
+ }
353
+ else
354
+ {
355
+ this.Log($"No textures updated.");
356
+ }
357
+ }
358
+ }
359
+ finally
360
+ {
361
+ if (applyChanges)
362
+ {
363
+ AssetDatabase.StopAssetEditing();
364
+ }
365
+ EditorUtility.ClearProgressBar();
366
+ }
367
+ return changedCount;
368
+ }
369
+ }
370
+ #endif
371
+ }