com.wallstop-studios.unity-helpers 2.0.0-rc73.18 → 2.0.0-rc73.2

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 (78) hide show
  1. package/Editor/{Sprites/AnimationCopier.cs → AnimationCopier.cs} +209 -84
  2. package/Editor/{Sprites/AnimationCreator.cs → AnimationCreator.cs} +100 -29
  3. package/Editor/AnimationEventEditor.cs +23 -10
  4. package/Editor/CustomEditors/MatchColliderToSpriteEditor.cs +1 -1
  5. package/Editor/FitTextureSizeWindow.cs +53 -14
  6. package/Editor/PrefabChecker.cs +18 -11
  7. package/Editor/SpriteAtlasGenerator.cs +914 -0
  8. package/Editor/SpriteAtlasGenerator.cs.meta +3 -0
  9. package/Editor/{Sprites/SpriteCropper.cs → SpriteCropper.cs} +143 -172
  10. package/Editor/{Sprites/SpriteSettingsApplier.cs → SpriteSettingsApplier.cs} +77 -12
  11. package/Editor/{Sprites/TextureResizerWizard.cs → TextureResizerWizard.cs} +1 -1
  12. package/Editor/{Sprites/TextureSettingsApplier.cs → TextureSettingsApplier.cs} +1 -1
  13. package/Editor/Utils/DxReadOnlyPropertyDrawer.cs +1 -1
  14. package/Editor/Utils/GUIHorizontalScope.cs +20 -0
  15. package/Editor/Utils/GUIHorizontalScope.cs.meta +3 -0
  16. package/Runtime/Core/DataStructure/Circle.cs +1 -1
  17. package/Runtime/Core/DataStructure/QuadTree.cs +4 -4
  18. package/Runtime/Core/Extension/ColorExtensions.cs +5 -5
  19. package/Runtime/Core/Extension/IEnumerableExtensions.cs +1 -1
  20. package/Runtime/Core/Extension/UnityExtensions.cs +14 -14
  21. package/Runtime/Core/Helper/DirectoryHelper.cs +0 -64
  22. package/Runtime/Core/Helper/Helpers.cs +9 -9
  23. package/Runtime/Core/Helper/Logging/UnityLogTagFormatter.cs +8 -31
  24. package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -5
  25. package/Runtime/Core/Helper/PathHelper.cs +1 -2
  26. package/Runtime/Core/Random/DotNetRandom.cs +1 -1
  27. package/Runtime/Core/Random/SplitMix64.cs +1 -1
  28. package/Runtime/Core/Random/SquirrelRandom.cs +7 -7
  29. package/Runtime/Core/Random/ThreadLocalRandom.cs +1 -1
  30. package/Runtime/Core/Random/WyRandom.cs +1 -1
  31. package/Runtime/Tags/AttributeEffect.cs +0 -1
  32. package/Runtime/Tags/EffectHandler.cs +1 -1
  33. package/Runtime/UI/LayeredImage.cs +161 -309
  34. package/Runtime/Utils/AnimatorEnumStateMachine.cs +1 -1
  35. package/Runtime/Utils/SetTextureImportData.cs +1 -1
  36. package/Runtime/Utils/TextureScale.cs +4 -4
  37. package/Styles/Elements/{Progress/CircularProgressBar.cs → CircularProgressBar.cs} +55 -56
  38. package/Styles/Elements/{Progress/RegularProgressBar.cs → RegularProgressBar.cs} +13 -24
  39. package/Styles/UXML/CircularProgressBar.uxml +11 -0
  40. package/Styles/UXML/CircularProgressBar.uxml.meta +10 -0
  41. package/Styles/UXML/RegularProgressBar.uxml +22 -0
  42. package/Styles/UXML/RegularProgressBar.uxml.meta +10 -0
  43. package/Styles/UXML.meta +3 -0
  44. package/package.json +1 -17
  45. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +0 -796
  46. package/Editor/CustomEditors/PersistentDirectoryGUI.cs.meta +0 -3
  47. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +0 -275
  48. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs.meta +0 -3
  49. package/Editor/PersistentDirectorySettings.cs +0 -248
  50. package/Editor/PersistentDirectorySettings.cs.meta +0 -3
  51. package/Editor/Sprites/ScriptableSpriteAtlas.cs +0 -95
  52. package/Editor/Sprites/ScriptableSpriteAtlas.cs.meta +0 -3
  53. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +0 -960
  54. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs.meta +0 -3
  55. package/Editor/Sprites.meta +0 -3
  56. package/Styles/Elements/Progress/ArcedProgressBar.cs +0 -345
  57. package/Styles/Elements/Progress/ArcedProgressBar.cs.meta +0 -3
  58. package/Styles/Elements/Progress/GlitchProgressBar.cs +0 -416
  59. package/Styles/Elements/Progress/GlitchProgressBar.cs.meta +0 -3
  60. package/Styles/Elements/Progress/LiquidProgressBar.cs +0 -632
  61. package/Styles/Elements/Progress/LiquidProgressBar.cs.meta +0 -3
  62. package/Styles/Elements/Progress/MarchingAntsProgressBar.cs +0 -722
  63. package/Styles/Elements/Progress/MarchingAntsProgressBar.cs.meta +0 -3
  64. package/Styles/Elements/Progress/WigglyProgressBar.cs +0 -837
  65. package/Styles/Elements/Progress/WigglyProgressBar.cs.meta +0 -3
  66. package/Styles/Elements/Progress.meta +0 -3
  67. package/Styles/USS/ArcedProgressBar.uss +0 -19
  68. package/Styles/USS/ArcedProgressBar.uss.meta +0 -3
  69. package/Styles/USS/WigglyProgressBar.uss +0 -17
  70. package/Styles/USS/WigglyProgressBar.uss.meta +0 -3
  71. /package/Editor/{Sprites/AnimationCopier.cs.meta → AnimationCopier.cs.meta} +0 -0
  72. /package/Editor/{Sprites/AnimationCreator.cs.meta → AnimationCreator.cs.meta} +0 -0
  73. /package/Editor/{Sprites/SpriteCropper.cs.meta → SpriteCropper.cs.meta} +0 -0
  74. /package/Editor/{Sprites/SpriteSettingsApplier.cs.meta → SpriteSettingsApplier.cs.meta} +0 -0
  75. /package/Editor/{Sprites/TextureResizerWizard.cs.meta → TextureResizerWizard.cs.meta} +0 -0
  76. /package/Editor/{Sprites/TextureSettingsApplier.cs.meta → TextureSettingsApplier.cs.meta} +0 -0
  77. /package/Styles/Elements/{Progress/CircularProgressBar.cs.meta → CircularProgressBar.cs.meta} +0 -0
  78. /package/Styles/Elements/{Progress/RegularProgressBar.cs.meta → RegularProgressBar.cs.meta} +0 -0
@@ -18,13 +18,13 @@
18
18
  {
19
19
  public const float FrameRate = 12f;
20
20
 
21
- public readonly Vector2[] perFramePixelOffsets;
21
+ public readonly Vector2[] offsets;
22
22
  public readonly Sprite[] frames;
23
23
  public readonly float alpha;
24
24
 
25
25
  public AnimatedSpriteLayer(
26
26
  IEnumerable<Sprite> sprites,
27
- IEnumerable<Vector2> worldSpaceOffsets = null,
27
+ IEnumerable<Vector2> offsets,
28
28
  float alpha = 1
29
29
  )
30
30
  {
@@ -37,45 +37,21 @@
37
37
  }
38
38
 
39
39
  frame.texture.MakeReadable();
40
- try
41
- {
42
- frame.texture.GetPixel(0, 0);
43
- }
44
- catch (UnityException e)
45
- {
46
- Debug.LogError(
47
- $"Texture '{frame.texture.name}' for sprite '{frame.name}' is not readable. Please enable Read/Write in its import settings. Error: {e.Message}"
48
- );
49
- }
50
- }
51
-
52
- if (worldSpaceOffsets != null && frames is { Length: > 0 })
53
- {
54
- perFramePixelOffsets = worldSpaceOffsets
55
- .Zip(
56
- frames,
57
- (offset, frame) =>
58
- frame != null && frame.pixelsPerUnit > 0
59
- ? frame.pixelsPerUnit * offset
60
- : Vector2.zero
61
- )
62
- .ToArray();
63
- Debug.Assert(
64
- perFramePixelOffsets.Length == frames.Length,
65
- $"Expected {frames.Length} sprite frames to match {perFramePixelOffsets.Length} offsets after processing."
66
- );
67
- }
68
- else
69
- {
70
- perFramePixelOffsets = null;
71
40
  }
72
41
 
42
+ this.offsets =
43
+ offsets?.Zip(frames, (offset, frame) => frame.pixelsPerUnit * offset).ToArray()
44
+ ?? Array.Empty<Vector2>();
45
+ Debug.Assert(
46
+ this.offsets.Length == frames.Length,
47
+ $"Expected {frames.Length} to match {this.offsets.Length}"
48
+ );
73
49
  this.alpha = Mathf.Clamp01(alpha);
74
50
  }
75
51
 
76
52
  public AnimatedSpriteLayer(
77
53
  AnimationClip clip,
78
- IEnumerable<Vector2> worldSpaceOffsets = null,
54
+ IEnumerable<Vector2> offsets,
79
55
  float alpha = 1
80
56
  )
81
57
  : this(
@@ -84,7 +60,7 @@
84
60
  #else
85
61
  Enumerable.Empty<Sprite>(),
86
62
  #endif
87
- worldSpaceOffsets, alpha) { }
63
+ offsets, alpha) { }
88
64
  }
89
65
 
90
66
  public sealed class LayeredImage : VisualElement
@@ -92,6 +68,7 @@
92
68
  private readonly AnimatedSpriteLayer[] _layers;
93
69
  private readonly Texture2D[] _computed;
94
70
  private readonly Color _backgroundColor;
71
+
95
72
  private readonly Rect? _largestArea;
96
73
 
97
74
  public LayeredImage(
@@ -104,74 +81,51 @@
104
81
  _backgroundColor = backgroundColor ?? Color.white;
105
82
  _computed = ComputeTextures().ToArray();
106
83
  _largestArea = null;
107
-
108
- foreach (Texture2D? computedTexture in _computed)
84
+ foreach (Texture2D computed in _computed)
109
85
  {
110
- if (computedTexture == null)
111
- {
112
- continue;
113
- }
114
-
115
86
  if (_largestArea == null)
116
87
  {
117
- _largestArea = new Rect(0, 0, computedTexture.width, computedTexture.height);
88
+ _largestArea = new Rect(0, 0, computed.width, computed.height);
118
89
  }
119
90
  else
120
91
  {
121
- Rect currentLargest = _largestArea.Value;
122
- currentLargest.width = Mathf.Max(currentLargest.width, computedTexture.width);
123
- currentLargest.height = Mathf.Max(
124
- currentLargest.height,
125
- computedTexture.height
126
- );
127
- _largestArea = currentLargest;
92
+ Rect largestArea = _largestArea.Value;
93
+ largestArea.width = Mathf.Max(largestArea.width, computed.width);
94
+ largestArea.height = Mathf.Max(largestArea.height, computed.height);
95
+ _largestArea = largestArea;
128
96
  }
129
97
  }
130
98
 
131
99
  Render(0);
132
-
133
- if (_computed.Length > 1 && fps > 0)
100
+ float fpsMs = 1000f / fps;
101
+ if (1 < _computed.Length)
134
102
  {
135
103
  #if UNITY_EDITOR
136
104
  if (!Application.isPlaying)
137
105
  {
138
106
  TimeSpan lastTick = TimeSpan.Zero;
139
- TimeSpan fpsSpan = TimeSpan.FromMilliseconds(1000f / fps);
107
+ TimeSpan fpsSpan = TimeSpan.FromMilliseconds(fpsMs);
140
108
  int index = 0;
141
109
  Stopwatch timer = Stopwatch.StartNew();
142
- EditorApplication.update += Tick;
143
- return;
144
-
145
- void Tick()
110
+ EditorApplication.update += () =>
146
111
  {
147
- if (panel == null)
148
- {
149
- EditorApplication.update -= Tick;
150
- return;
151
- }
152
112
  TimeSpan elapsed = timer.Elapsed;
153
- if (lastTick + fpsSpan >= elapsed)
113
+ if (lastTick + fpsSpan < elapsed)
154
114
  {
155
- return;
115
+ index = index.WrappedIncrement(_computed.Length);
116
+ lastTick = elapsed;
117
+ Render(index);
156
118
  }
157
-
158
- index = index.WrappedIncrement(_computed.Length);
159
- lastTick = elapsed;
160
- Render(index);
161
- }
119
+ };
120
+ return;
162
121
  }
122
+
163
123
  #endif
164
- if (Application.isPlaying && CoroutineHandler.Instance != null)
165
124
  {
166
125
  int index = 0;
167
126
  CoroutineHandler.Instance.StartFunctionAsCoroutine(
168
127
  () =>
169
128
  {
170
- if (panel == null)
171
- {
172
- return;
173
- }
174
-
175
129
  index = index.WrappedIncrement(_computed.Length);
176
130
  Render(index);
177
131
  },
@@ -183,11 +137,6 @@
183
137
 
184
138
  private void Render(int index)
185
139
  {
186
- if (index < 0 || index >= _computed.Length)
187
- {
188
- return;
189
- }
190
-
191
140
  Texture2D computed = _computed[index];
192
141
  if (computed != null)
193
142
  {
@@ -195,303 +144,205 @@
195
144
  style.width = computed.width;
196
145
  style.height = computed.height;
197
146
  }
198
- else
199
- {
200
- style.backgroundImage = null;
201
- style.width = _largestArea?.width ?? 0;
202
- style.height = _largestArea?.height ?? 0;
203
- }
204
147
 
205
148
  style.marginRight = 0;
206
149
  style.marginBottom = 0;
207
- if (_largestArea == null)
150
+ if (_largestArea != null)
208
151
  {
209
- return;
210
- }
211
-
212
- Rect largestAreaRect = _largestArea.Value;
213
- float currentWidth = computed != null ? computed.width : _largestArea?.width ?? 0;
214
- float currentHeight = computed != null ? computed.height : _largestArea?.height ?? 0;
152
+ Rect largestArea = _largestArea.Value;
153
+ if (style.width.value.value < largestArea.width)
154
+ {
155
+ style.marginRight = largestArea.width - style.width.value.value;
156
+ }
215
157
 
216
- if (currentWidth < largestAreaRect.width)
217
- {
218
- style.marginRight = largestAreaRect.width - currentWidth;
219
- }
220
- if (currentHeight < largestAreaRect.height)
221
- {
222
- style.marginBottom = largestAreaRect.height - currentHeight;
158
+ if (style.height.value.value < largestArea.height)
159
+ {
160
+ style.marginBottom = largestArea.height - style.height.value.value;
161
+ }
223
162
  }
224
163
  }
225
164
 
226
- private IEnumerable<Texture2D?> ComputeTextures()
165
+ private IEnumerable<Texture2D> ComputeTextures()
227
166
  {
228
167
  const float pixelCutoff = 0.01f;
229
- if (_layers is not { Length: > 0 })
230
- {
231
- yield break;
232
- }
233
-
234
- int frameCount = 0;
235
- foreach (AnimatedSpriteLayer layer in _layers)
236
- {
237
- if (layer.frames != null)
238
- {
239
- frameCount = Mathf.Max(frameCount, layer.frames.Length);
240
- }
241
- }
242
- if (frameCount == 0)
243
- {
244
- yield break;
245
- }
168
+ int frameCount = _layers.Select(layer => layer.frames.Length).Distinct().Single();
246
169
 
170
+ Color transparent = Color.clear;
247
171
  for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex)
248
172
  {
249
- float overallMinX = float.MaxValue;
250
- float overallMaxX = float.MinValue;
251
- float overallMinY = float.MaxValue;
252
- float overallMaxY = float.MinValue;
253
- bool hasVisibleSpriteThisFrame = false;
254
-
173
+ int minX = int.MaxValue;
174
+ int maxX = int.MinValue;
175
+ int minY = int.MaxValue;
176
+ int maxY = int.MinValue;
255
177
  foreach (AnimatedSpriteLayer layer in _layers)
256
178
  {
257
- if (layer.frames == null || frameIndex >= layer.frames.Length)
179
+ if (layer.frames.Length <= 0)
258
180
  {
259
181
  continue;
260
182
  }
261
183
 
262
184
  Sprite sprite = layer.frames[frameIndex];
263
- if (sprite == null)
264
- {
265
- continue;
266
- }
267
-
268
- hasVisibleSpriteThisFrame = true;
269
- Rect spriteGeomRect = sprite.rect;
270
- Vector2 pivot = sprite.pivot;
271
-
272
- Vector2 additionalPixelOffset = Vector2.zero;
273
- if (
274
- layer.perFramePixelOffsets != null
275
- && frameIndex < layer.perFramePixelOffsets.Length
276
- )
277
- {
278
- additionalPixelOffset = layer.perFramePixelOffsets[frameIndex];
279
- }
280
-
281
- float spriteWorldMinX = -pivot.x + additionalPixelOffset.x;
282
- float spriteWorldMaxX =
283
- spriteGeomRect.width - pivot.x + additionalPixelOffset.x;
284
- float spriteWorldMinY = -pivot.y + additionalPixelOffset.y;
285
- float spriteWorldMaxY =
286
- spriteGeomRect.height - pivot.y + additionalPixelOffset.y;
287
-
288
- overallMinX = Mathf.Min(overallMinX, spriteWorldMinX);
289
- overallMaxX = Mathf.Max(overallMaxX, spriteWorldMaxX);
290
- overallMinY = Mathf.Min(overallMinY, spriteWorldMinY);
291
- overallMaxY = Mathf.Max(overallMaxY, spriteWorldMaxY);
292
- }
293
-
294
- if (!hasVisibleSpriteThisFrame)
295
- {
296
- yield return null;
297
- continue;
185
+ Vector2 offset = layer.offsets[frameIndex];
186
+ Rect spriteRect = sprite.rect;
187
+
188
+ int left = Mathf.RoundToInt(offset.x + spriteRect.xMin);
189
+ int right = Mathf.RoundToInt(offset.x + spriteRect.xMax);
190
+ int bottom = Mathf.RoundToInt(offset.y + spriteRect.yMin);
191
+ int top = Mathf.RoundToInt(offset.y + spriteRect.yMax);
192
+
193
+ minX = Mathf.Min(minX, left);
194
+ maxX = Mathf.Max(maxX, right);
195
+ minY = Mathf.Min(minY, bottom);
196
+ maxY = Mathf.Max(maxY, top);
298
197
  }
299
198
 
300
- int compositeBufferOriginX = Mathf.FloorToInt(overallMinX);
301
- int compositeBufferOriginY = Mathf.FloorToInt(overallMinY);
302
- int compositeBufferWidth = Mathf.CeilToInt(overallMaxX) - compositeBufferOriginX;
303
- int compositeBufferHeight = Mathf.CeilToInt(overallMaxY) - compositeBufferOriginY;
304
-
305
- if (compositeBufferWidth <= 0 || compositeBufferHeight <= 0)
199
+ if (minX == int.MaxValue)
306
200
  {
307
- yield return null;
308
201
  continue;
309
202
  }
310
203
 
311
- Color[] bufferPixels = new Color[compositeBufferWidth * compositeBufferHeight];
204
+ // Calculate the width and height of the non-transparent region
205
+ int width = maxX - minX + 1;
206
+ int height = maxY - minY + 1;
312
207
 
313
- Array.Fill(bufferPixels, Color.clear);
208
+ Color[] pixels = new Color[width * height];
209
+ Array.Fill(pixels, Color.clear);
314
210
 
315
211
  foreach (AnimatedSpriteLayer layer in _layers)
316
212
  {
317
- if (layer.frames == null || frameIndex >= layer.frames.Length)
213
+ if (layer.frames.Length <= 0)
318
214
  {
319
215
  continue;
320
216
  }
321
217
 
322
218
  Sprite sprite = layer.frames[frameIndex];
323
- if (sprite == null)
324
- {
325
- continue;
326
- }
327
-
328
- float layerAlpha = layer.alpha;
329
- Texture2D spriteTexture = sprite.texture;
330
- Rect spriteGeomRect = sprite.rect;
331
- Vector2 pivot = sprite.pivot;
332
-
333
- Vector2 additionalPixelOffset = Vector2.zero;
334
- if (
335
- layer.perFramePixelOffsets != null
336
- && frameIndex < layer.perFramePixelOffsets.Length
337
- )
338
- {
339
- additionalPixelOffset = layer.perFramePixelOffsets[frameIndex];
340
- }
341
-
342
- int spriteRectX = Mathf.FloorToInt(spriteGeomRect.x);
343
- int spriteRectY = Mathf.FloorToInt(spriteGeomRect.y);
344
- int spriteRectWidth = Mathf.FloorToInt(spriteGeomRect.width);
345
- int spriteRectHeight = Mathf.FloorToInt(spriteGeomRect.height);
346
-
347
- if (spriteRectWidth <= 0 || spriteRectHeight <= 0)
348
- {
349
- continue;
350
- }
351
-
352
- Color[] spriteRawPixels = spriteTexture.GetPixels(
353
- spriteRectX,
354
- spriteRectY,
355
- spriteRectWidth,
356
- spriteRectHeight
219
+ Vector2 offset = layer.offsets[frameIndex];
220
+ float alpha = layer.alpha;
221
+ int offsetX = Mathf.RoundToInt(offset.x);
222
+ int offsetY = Mathf.RoundToInt(offset.y);
223
+ Texture2D texture = sprite.texture;
224
+ Rect spriteRect = sprite.rect;
225
+
226
+ int spriteX = Mathf.RoundToInt(spriteRect.xMin);
227
+ int spriteWidth = Mathf.RoundToInt(spriteRect.width);
228
+ int spriteY = Mathf.RoundToInt(spriteRect.yMin);
229
+ int spriteHeight = Mathf.RoundToInt(spriteRect.height);
230
+ Color[] spritePixels = texture.GetPixels(
231
+ spriteX,
232
+ spriteY,
233
+ spriteWidth,
234
+ spriteHeight
357
235
  );
358
236
 
359
237
  Parallel.For(
360
238
  0,
361
- spriteRectHeight,
362
- sySprite =>
239
+ spritePixels.Length,
240
+ inIndex =>
363
241
  {
364
- for (int sxSprite = 0; sxSprite < spriteRectWidth; ++sxSprite)
242
+ int x = inIndex % spriteWidth;
243
+ int y = inIndex / spriteWidth;
244
+
245
+ Color pixelColor = spritePixels[inIndex];
246
+ if (pixelColor.a < pixelCutoff)
365
247
  {
366
- Color spritePixelColor = spriteRawPixels[
367
- sySprite * spriteRectWidth + sxSprite
368
- ];
369
-
370
- if (spritePixelColor.a < pixelCutoff)
371
- {
372
- continue;
373
- }
374
-
375
- float pixelWorldX = sxSprite - pivot.x + additionalPixelOffset.x;
376
- float pixelWorldY = sySprite - pivot.y + additionalPixelOffset.y;
377
- int bufferX = Mathf.FloorToInt(
378
- pixelWorldX - compositeBufferOriginX
379
- );
380
- int bufferY = Mathf.FloorToInt(
381
- pixelWorldY - compositeBufferOriginY
382
- );
383
-
384
- if (
385
- bufferX < 0
386
- || bufferX >= compositeBufferWidth
387
- || bufferY < 0
388
- || bufferY >= compositeBufferHeight
389
- )
390
- {
391
- continue;
392
- }
393
-
394
- int bufferIndex = bufferY * compositeBufferWidth + bufferX;
395
- Color existingColor = bufferPixels[bufferIndex];
396
- if (existingColor.a < pixelCutoff)
397
- {
398
- existingColor = _backgroundColor;
399
- }
400
-
401
- Color blendedColor = Color.Lerp(
402
- existingColor,
403
- spritePixelColor,
404
- layerAlpha
405
- );
406
-
407
- bufferPixels[bufferIndex] = blendedColor;
248
+ return;
249
+ }
250
+
251
+ int textureX = (-1 * minX) + offsetX + x + spriteX;
252
+ int textureY = (-1 * minY) + offsetY + y + spriteY;
253
+ int index = textureY * width + textureX;
254
+
255
+ if (index < 0 || pixels.Length <= index)
256
+ {
257
+ return;
408
258
  }
259
+
260
+ Color existingColor = pixels[index];
261
+ if (existingColor == transparent)
262
+ {
263
+ existingColor = _backgroundColor;
264
+ }
265
+
266
+ Color blendedColor = Color.Lerp(existingColor, pixelColor, alpha);
267
+ pixels[index] = blendedColor;
409
268
  }
410
269
  );
411
270
  }
412
271
 
413
- int finalMinX = int.MaxValue,
414
- finalMaxX = int.MinValue;
415
- int finalMinY = int.MaxValue,
416
- finalMaxY = int.MinValue;
272
+ // Find the bounds of the non-transparent pixels in the temporary texture
273
+ int finalMinX = int.MaxValue;
274
+ int finalMaxX = int.MinValue;
275
+ int finalMinY = int.MaxValue;
276
+ int finalMaxY = int.MinValue;
417
277
 
418
278
  Parallel.For(
419
279
  0,
420
- compositeBufferHeight * compositeBufferWidth,
421
- bufferIndex =>
280
+ height * width,
281
+ inIndex =>
422
282
  {
423
- if (bufferPixels[bufferIndex].a >= pixelCutoff)
283
+ Color pixelColor = pixels[inIndex];
284
+ if (pixelColor.a < pixelCutoff)
424
285
  {
425
- int x = bufferIndex % compositeBufferWidth;
426
- int y = bufferIndex / compositeBufferWidth;
286
+ return;
287
+ }
427
288
 
428
- int currentVal;
429
- do
430
- {
431
- currentVal = Volatile.Read(ref finalMinX);
432
- } while (
433
- x < currentVal
434
- && Interlocked.CompareExchange(ref finalMinX, x, currentVal)
435
- != currentVal
436
- );
437
- do
438
- {
439
- currentVal = Volatile.Read(ref finalMaxX);
440
- } while (
441
- x > currentVal
442
- && Interlocked.CompareExchange(ref finalMaxX, x, currentVal)
443
- != currentVal
444
- );
445
- do
446
- {
447
- currentVal = Volatile.Read(ref finalMinY);
448
- } while (
449
- y < currentVal
450
- && Interlocked.CompareExchange(ref finalMinY, y, currentVal)
451
- != currentVal
452
- );
453
- do
454
- {
455
- currentVal = Volatile.Read(ref finalMaxY);
456
- } while (
457
- y > currentVal
458
- && Interlocked.CompareExchange(ref finalMaxY, y, currentVal)
459
- != currentVal
460
- );
289
+ int x = inIndex % width;
290
+ int y = inIndex / width;
291
+
292
+ int expectedX = finalMinX;
293
+ while (x < expectedX)
294
+ {
295
+ expectedX = Interlocked.CompareExchange(ref finalMinX, x, expectedX);
296
+ }
297
+
298
+ expectedX = finalMaxX;
299
+ while (expectedX < x)
300
+ {
301
+ expectedX = Interlocked.CompareExchange(ref finalMaxX, x, expectedX);
302
+ }
303
+
304
+ int expectedY = finalMinY;
305
+ while (y < expectedY)
306
+ {
307
+ expectedY = Interlocked.CompareExchange(ref finalMinY, y, expectedY);
308
+ }
309
+
310
+ expectedY = finalMaxY;
311
+ while (expectedY < y)
312
+ {
313
+ expectedY = Interlocked.CompareExchange(ref finalMaxY, y, expectedY);
461
314
  }
462
315
  }
463
316
  );
464
317
 
465
318
  if (finalMinX == int.MaxValue)
466
319
  {
467
- yield return null;
468
320
  continue;
469
321
  }
470
322
 
323
+ // Calculate the final width and height of the culled texture
471
324
  int finalWidth = finalMaxX - finalMinX + 1;
472
325
  int finalHeight = finalMaxY - finalMinY + 1;
473
326
 
474
327
  Color[] finalPixels = new Color[finalWidth * finalHeight];
475
-
476
328
  Array.Fill(finalPixels, _backgroundColor);
329
+
330
+ // Copy the non-transparent pixels from the temporary texture to the final texture
477
331
  Parallel.For(
478
332
  0,
479
- finalHeight,
480
- yFinal =>
333
+ finalWidth * finalHeight,
334
+ inIndex =>
481
335
  {
482
- for (int xFinal = 0; xFinal < finalWidth; ++xFinal)
336
+ int x = inIndex % finalWidth;
337
+ int y = inIndex / finalWidth;
338
+ int outerX = x + finalMinX;
339
+ int outerY = y + finalMinY;
340
+ Color pixelColor = pixels[outerY * width + outerX];
341
+ if (pixelColor.a < pixelCutoff)
483
342
  {
484
- int bufferX = finalMinX + xFinal;
485
- int bufferY = finalMinY + yFinal;
486
- Color pixelColor = bufferPixels[
487
- bufferY * compositeBufferWidth + bufferX
488
- ];
489
-
490
- if (pixelColor.a >= pixelCutoff)
491
- {
492
- finalPixels[yFinal * finalWidth + xFinal] = pixelColor;
493
- }
343
+ return;
494
344
  }
345
+ finalPixels[y * finalWidth + x] = pixelColor;
495
346
  }
496
347
  );
497
348
 
@@ -500,11 +351,12 @@
500
351
  finalHeight,
501
352
  TextureFormat.RGBA32,
502
353
  mipChain: false,
503
- linear: false
354
+ linear: false,
355
+ createUninitialized: true
504
356
  );
505
-
506
357
  finalTexture.SetPixels(finalPixels);
507
- finalTexture.Apply(updateMipmaps: false, makeNoLongerReadable: false);
358
+ finalTexture.Apply(false, false);
359
+
508
360
  yield return finalTexture;
509
361
  }
510
362
  }
@@ -21,7 +21,7 @@
21
21
 
22
22
  [JsonIgnore]
23
23
  [IgnoreDataMember]
24
- private readonly HashSet<string> _availableBools = new();
24
+ private readonly HashSet<string> _availableBools = new HashSet<string>();
25
25
 
26
26
  [JsonIgnore]
27
27
  [IgnoreDataMember]
@@ -53,7 +53,7 @@
53
53
 
54
54
  tImporter.isReadable = isReadable;
55
55
 
56
- TextureImporterPlatformSettings importerSettings = new()
56
+ TextureImporterPlatformSettings importerSettings = new TextureImporterPlatformSettings
57
57
  {
58
58
  resizeAlgorithm = TextureResizeAlgorithm.Bilinear,
59
59
  maxTextureSize = MaxTextureSize,