com.wallstop-studios.unity-helpers 2.0.0-rc81.9 → 2.0.0

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 (168) hide show
  1. package/.editorconfig +1 -1
  2. package/.gitattributes +1 -1
  3. package/.githooks/pre-commit +31 -5
  4. package/.githooks/pre-push +50 -0
  5. package/.github/dependabot.yml +24 -2
  6. package/.github/scripts/check-markdown-links.ps1 +77 -0
  7. package/.github/scripts/check_markdown_links.py +89 -0
  8. package/.github/scripts/check_markdown_url_encoding.py +74 -0
  9. package/.github/scripts/validate_markdown_links.py +194 -0
  10. package/.github/workflows/csharpier-autofix.yml +152 -0
  11. package/.github/workflows/format-on-demand.yml +305 -0
  12. package/.github/workflows/lint-doc-links.yml +8 -5
  13. package/.github/workflows/markdown-json.yml +6 -2
  14. package/.github/workflows/prettier-autofix.yml +195 -0
  15. package/.github/workflows/update-dotnet-tools.yml +80 -0
  16. package/.github/workflows/yaml-format-lint.yml +41 -0
  17. package/.lychee.toml +4 -4
  18. package/.markdownlint.jsonc +21 -0
  19. package/.pre-commit-config.yaml +11 -3
  20. package/.yamllint.yaml +31 -0
  21. package/AGENTS.md +5 -1
  22. package/CHANGELOG.md +11 -0
  23. package/CONTRIBUTING.md +49 -0
  24. package/CONTRIBUTING.md.meta +7 -0
  25. package/EDITOR_TOOLS_GUIDE.md +4 -0
  26. package/Editor/AnimationEventEditor.cs +337 -160
  27. package/Editor/Core/Helper/AnimationEventHelpers.cs +178 -152
  28. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +20 -11
  29. package/Editor/CustomEditors/TexturePlatformOverrideEntryDrawer.cs +11 -2
  30. package/Editor/FitTextureSizeWindow.cs +43 -19
  31. package/Editor/PersistentDirectorySettings.cs +64 -12
  32. package/Editor/PrefabChecker.cs +72 -5
  33. package/Editor/Sprites/AnimationCopier.cs +132 -56
  34. package/Editor/Sprites/AnimationCreator.cs +63 -22
  35. package/Editor/Sprites/AnimationViewerWindow.cs +42 -6
  36. package/Editor/Sprites/TexturePlatformNameHelper.cs +50 -39
  37. package/Editor/Sprites/TextureResizerWizard.cs +23 -1
  38. package/Editor/Sprites/TextureSettingsApplierWindow.cs +148 -85
  39. package/Editor/Tools/ImageBlurTool.cs +81 -10
  40. package/Editor/Utils/EditorUi.cs +1 -1
  41. package/Editor/Utils/ScriptableObjectSingletonCreator.cs +1 -1
  42. package/GETTING_STARTED.md +40 -56
  43. package/RANDOM_PERFORMANCE.md +12 -12
  44. package/README.md +395 -2407
  45. package/RELATIONAL_COMPONENTS.md +92 -83
  46. package/Runtime/AssemblyInfo.cs +2 -0
  47. package/Runtime/Core/Attributes/NotNullAttribute.cs +1 -3
  48. package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +50 -5
  49. package/Runtime/Core/DataStructure/CyclicBuffer.cs +0 -1
  50. package/Runtime/Core/Extension/RandomExtensions.cs +68 -0
  51. package/Runtime/Core/Extension/WallstopStudiosLogger.cs +16 -0
  52. package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -1
  53. package/Runtime/Core/Helper/ReflectionHelpers.cs +21 -10
  54. package/Runtime/Core/Helper/SpriteHelpers.cs +3 -1
  55. package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +45 -1
  56. package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +13 -5
  57. package/Runtime/Core/Serialization/JsonConverters/ResolutionConverter.cs +1 -1
  58. package/Runtime/Core/Serialization/JsonConverters/TypeConverter.cs +1 -1
  59. package/Runtime/Core/Serialization/Serializer.cs +101 -0
  60. package/Runtime/Integrations/VContainer/AssemblyInfo.cs +9 -0
  61. package/Runtime/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  62. package/Runtime/Integrations/VContainer/ObjectResolverRelationalExtensions.cs +96 -0
  63. package/Runtime/Integrations/VContainer/RelationalComponentEntryPoint.cs +90 -10
  64. package/Runtime/Integrations/VContainer/RelationalComponentsBuilderExtensions.cs +13 -1
  65. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs +114 -0
  66. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs.meta +11 -0
  67. package/Runtime/Integrations/VContainer/RelationalSceneAssignmentOptions.cs +16 -4
  68. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs +241 -0
  69. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs.meta +11 -0
  70. package/Runtime/Integrations/Zenject/AssemblyInfo.cs +9 -0
  71. package/Runtime/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  72. package/Runtime/Integrations/Zenject/DiContainerRelationalExtensions.cs +69 -2
  73. package/Runtime/Integrations/Zenject/RelationalComponentSceneInitializer.cs +89 -12
  74. package/Runtime/Integrations/Zenject/RelationalComponentsInstaller.cs +23 -1
  75. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs +44 -0
  76. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs.meta +11 -0
  77. package/Runtime/Integrations/Zenject/RelationalSceneAssignmentOptions.cs +16 -10
  78. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs +243 -0
  79. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs.meta +11 -0
  80. package/Runtime/Tags/AttributeMetadataCache.cs +1 -4
  81. package/Runtime/Utils/Buffers.cs +4 -4
  82. package/Runtime/Utils/ScriptableObjectSingleton.cs +0 -1
  83. package/Runtime/Utils/SetTextureImportData.cs +3 -1
  84. package/Runtime/Utils/TextureScale.cs +10 -2
  85. package/Runtime/Visuals/UGUI/EnhancedImage.cs +6 -0
  86. package/Runtime/Visuals/UIToolkit/LayeredImage.cs +4 -1
  87. package/SERIALIZATION.md +15 -0
  88. package/SPATIAL_TREE_2D_PERFORMANCE.md +85 -82
  89. package/SPATIAL_TREE_3D_PERFORMANCE.md +94 -91
  90. package/Samples~/DI - VContainer/README.md +232 -51
  91. package/Samples~/DI - VContainer/Scripts/GameLifetimeScope.cs +22 -4
  92. package/Samples~/DI - VContainer/Scripts/RelationalConsumer.cs +5 -2
  93. package/Samples~/DI - VContainer/Scripts/Spawner.cs +113 -4
  94. package/Samples~/DI - Zenject/README.md +217 -53
  95. package/Samples~/DI - Zenject/Scripts/RelationalConsumer.cs +3 -0
  96. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs +37 -0
  97. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs.meta +12 -0
  98. package/Samples~/DI - Zenject/Scripts/SpawnerZenject.cs +74 -3
  99. package/Samples~/Random - PRNG/README.md +2 -1
  100. package/Samples~/Relational Components - Basic/README.md +3 -1
  101. package/Samples~/Serialization - JSON/README.md +2 -1
  102. package/Samples~/Spatial Structures - 2D and 3D/README.md +2 -1
  103. package/Samples~/UGUI - EnhancedImage/README.md +2 -1
  104. package/Samples~/UI Toolkit - MultiFile Selector (Editor)/README.md +2 -1
  105. package/THIRD_PARTY_NOTICES.md +1 -1
  106. package/Tests/Editor/Attributes/AnimationEventHelpersTests.cs +16 -0
  107. package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +3 -3
  108. package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +6 -2
  109. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +170 -0
  110. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs.meta +11 -0
  111. package/Tests/Editor/Integrations/VContainer/WallstopStudios.UnityHelpers.Tests.Editor.VContainer.asmdef +2 -1
  112. package/Tests/Editor/Integrations/Zenject/WallstopStudios.UnityHelpers.Tests.Editor.Zenject.asmdef +3 -2
  113. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +131 -0
  114. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs.meta +11 -0
  115. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +6 -2
  116. package/Tests/Editor/PersistentDirectorySettingsTests.cs +59 -0
  117. package/Tests/Editor/PersistentDirectorySettingsTests.cs.meta +11 -0
  118. package/Tests/Editor/PrefabCheckerReportTests.cs +32 -0
  119. package/Tests/Editor/PrefabCheckerReportTests.cs.meta +11 -0
  120. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +64 -0
  121. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs.meta +11 -0
  122. package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +1 -1
  123. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +38 -0
  124. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs.meta +11 -0
  125. package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +1 -1
  126. package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +12 -12
  127. package/Tests/Editor/Sprites/SpriteCropperTests.cs +9 -9
  128. package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +3 -3
  129. package/Tests/Editor/Sprites/TexturePlatformNameHelperTests.cs +18 -0
  130. package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +5 -5
  131. package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +3 -3
  132. package/Tests/Editor/Sprites/TextureSettingsApplierWizardAdditionalTests.cs +4 -4
  133. package/Tests/Editor/Sprites/TextureSettingsApplierWizardTests.cs +4 -4
  134. package/Tests/Editor/Tools/ImageBlurToolTests.cs +22 -110
  135. package/Tests/Editor/Utils/CommonTestBase.cs +43 -1
  136. package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +5 -5
  137. package/Tests/Editor/Windows/FitTextureSizeWindowTests.cs +66 -74
  138. package/Tests/Runtime/Attributes/RelationalComponentInitializerTests.cs +4 -15
  139. package/Tests/Runtime/DataStructures/SpatialTree3DBoundsConsistencyTests.cs +29 -29
  140. package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +259 -218
  141. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +86 -0
  142. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs.meta +11 -0
  143. package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +255 -227
  144. package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +5 -0
  145. package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +3 -0
  146. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs +30 -0
  147. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs.meta +11 -0
  148. package/Tests/Runtime/Serialization/JsonConverterTests.cs +8 -12
  149. package/Tests/Runtime/Serialization/JsonSerializationTest.cs +16 -5
  150. package/Tests/Runtime/Serialization/SerializerAdditionalTests.cs +12 -0
  151. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs +105 -0
  152. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs.meta +11 -0
  153. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs +247 -0
  154. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs.meta +11 -0
  155. package/Tests/Runtime/TestUtils/CommonTestBase.cs +88 -0
  156. package/Tests/Runtime/Utils/CoroutineHandlerTests.cs +1 -1
  157. package/Tests/Runtime/Utils/LZMAComprehensiveTests.cs +1 -1
  158. package/Tests/Runtime/Utils/LZMATests.cs +1 -1
  159. package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +1 -1
  160. package/Tests/Runtime/Visuals/EnhancedImageTests.cs +25 -56
  161. package/Tests/Runtime/Visuals/VisualsTestHelpers.cs +1 -8
  162. package/package-lock.json.meta +7 -0
  163. package/package.json +8 -4
  164. package/scripts/check-eol.ps1 +4 -5
  165. package/scripts/lint-tests.ps1 +156 -0
  166. package/scripts/lint-tests.ps1.meta +7 -0
  167. package/scripts/normalize-eol.ps1 +6 -9
  168. package/.github/workflows/csharpier.yml +0 -135
@@ -0,0 +1,243 @@
1
+ #if ZENJECT_PRESENT
2
+ namespace WallstopStudios.UnityHelpers.Integrations.Zenject
3
+ {
4
+ using System;
5
+ using System.Collections.Generic;
6
+ using global::Zenject;
7
+ using UnityEngine;
8
+ using UnityEngine.SceneManagement;
9
+ using WallstopStudios.UnityHelpers.Core.Attributes;
10
+ using WallstopStudios.UnityHelpers.Tags;
11
+ using WallstopStudios.UnityHelpers.Utils;
12
+
13
+ /// <summary>
14
+ /// Listens for additive scene loads and assigns relational fields within the newly loaded scene.
15
+ /// </summary>
16
+ public sealed class RelationalSceneLoadListener : IInitializable, IDisposable
17
+ {
18
+ private readonly IRelationalComponentAssigner _assigner;
19
+ private readonly AttributeMetadataCache _metadataCache;
20
+ private readonly RelationalSceneAssignmentOptions _options;
21
+
22
+ public RelationalSceneLoadListener(
23
+ IRelationalComponentAssigner assigner,
24
+ AttributeMetadataCache metadataCache,
25
+ RelationalSceneAssignmentOptions options
26
+ )
27
+ {
28
+ _assigner = assigner ?? throw new ArgumentNullException(nameof(assigner));
29
+ _metadataCache = metadataCache;
30
+ _options = options;
31
+ }
32
+
33
+ public void Initialize()
34
+ {
35
+ SceneManager.sceneLoaded += OnSceneLoaded;
36
+ }
37
+
38
+ public void Dispose()
39
+ {
40
+ SceneManager.sceneLoaded -= OnSceneLoaded;
41
+ }
42
+
43
+ internal void OnSceneLoaded(Scene scene, LoadSceneMode mode)
44
+ {
45
+ if (!scene.IsValid())
46
+ {
47
+ return;
48
+ }
49
+
50
+ AttributeMetadataCache cache = _metadataCache ?? AttributeMetadataCache.Instance;
51
+ if (cache == null)
52
+ {
53
+ return;
54
+ }
55
+
56
+ using PooledResource<List<Type>> pooledTypes = Buffers<Type>.List.Get(
57
+ out List<Type> relationalTypes
58
+ );
59
+ cache.CollectRelationalComponentTypes(relationalTypes);
60
+
61
+ if (relationalTypes.Count == 0)
62
+ {
63
+ // Fallback: scan all components in new scene and assign when type has relational fields
64
+ bool includeInactiveAll = _options.IncludeInactive;
65
+ Component[] all = includeInactiveAll
66
+ ? UnityEngine.Object.FindObjectsOfType<Component>(true)
67
+ : UnityEngine.Object.FindObjectsOfType<Component>(false);
68
+
69
+ for (int i = 0; i < all.Length; i++)
70
+ {
71
+ Component c = all[i];
72
+ if (c == null || c.gameObject.scene != scene)
73
+ {
74
+ continue;
75
+ }
76
+
77
+ if (_assigner.HasRelationalAssignments(c.GetType()))
78
+ {
79
+ _assigner.Assign(c);
80
+ }
81
+ }
82
+ return;
83
+ }
84
+
85
+ bool includeInactive = _options.IncludeInactive;
86
+
87
+ if (_options.UseSinglePassScan)
88
+ {
89
+ AssignBySinglePass(scene, relationalTypes, includeInactive);
90
+ }
91
+ else
92
+ {
93
+ AssignByTypePass(scene, relationalTypes, includeInactive);
94
+ }
95
+
96
+ // Safety net in Editor/tests: also walk scene roots
97
+ #if UNITY_EDITOR
98
+ if (!Application.isPlaying)
99
+ {
100
+ AssignBySceneRoots(scene, includeInactive);
101
+
102
+ // In EditMode, some components may be registered on the following editor tick.
103
+ // Schedule a delayed pass to ensure complete hydration in tests/tools.
104
+ UnityEditor.EditorApplication.delayCall += () =>
105
+ {
106
+ if (scene.IsValid())
107
+ {
108
+ AssignBySceneRoots(scene, includeInactive);
109
+ }
110
+ };
111
+ }
112
+ #endif
113
+ }
114
+
115
+ private void AssignByTypePass(
116
+ Scene target,
117
+ List<Type> relationalTypes,
118
+ bool includeInactive
119
+ )
120
+ {
121
+ using PooledResource<List<GameObject>> rootGoBuffer = Buffers<GameObject>.List.Get(
122
+ out List<GameObject> roots
123
+ );
124
+ target.GetRootGameObjects(roots);
125
+ if (roots.Count == 0)
126
+ {
127
+ return;
128
+ }
129
+
130
+ using PooledResource<HashSet<Type>> typeSetPool = Buffers<Type>.HashSet.Get(
131
+ out HashSet<Type> relationalSet
132
+ );
133
+ for (int i = 0; i < relationalTypes.Count; i++)
134
+ {
135
+ Type type = relationalTypes[i];
136
+ if (type != null)
137
+ {
138
+ relationalSet.Add(type);
139
+ }
140
+ }
141
+
142
+ using PooledResource<List<Component>> componentBuffer = Buffers<Component>.List.Get(
143
+ out List<Component> components
144
+ );
145
+
146
+ for (int i = 0; i < roots.Count; i++)
147
+ {
148
+ GameObject root = roots[i];
149
+ if (root == null)
150
+ {
151
+ continue;
152
+ }
153
+
154
+ root.GetComponentsInChildren(includeInactive, components);
155
+ for (int j = 0; j < components.Count; j++)
156
+ {
157
+ Component component = components[j];
158
+ if (component == null || component.gameObject.scene != target)
159
+ {
160
+ continue;
161
+ }
162
+
163
+ Type current = component.GetType();
164
+ while (current != null && typeof(Component).IsAssignableFrom(current))
165
+ {
166
+ if (relationalSet.Contains(current))
167
+ {
168
+ _assigner.Assign(component);
169
+ break;
170
+ }
171
+ current = current.BaseType;
172
+ }
173
+ }
174
+
175
+ components.Clear();
176
+ }
177
+ }
178
+
179
+ private void AssignBySinglePass(
180
+ Scene target,
181
+ List<Type> relationalTypes,
182
+ bool includeInactive
183
+ )
184
+ {
185
+ using PooledResource<HashSet<Type>> pooledSet = Buffers<Type>.HashSet.Get(
186
+ out HashSet<Type> relationalSet
187
+ );
188
+ for (int i = 0; i < relationalTypes.Count; i++)
189
+ {
190
+ if (relationalTypes[i] != null)
191
+ {
192
+ relationalSet.Add(relationalTypes[i]);
193
+ }
194
+ }
195
+
196
+ Component[] all = includeInactive
197
+ ? UnityEngine.Object.FindObjectsOfType<Component>(true)
198
+ : UnityEngine.Object.FindObjectsOfType<Component>(false);
199
+
200
+ for (int i = 0; i < all.Length; i++)
201
+ {
202
+ Component component = all[i];
203
+ if (component == null || component.gameObject.scene != target)
204
+ {
205
+ continue;
206
+ }
207
+
208
+ Type t = component.GetType();
209
+ while (t != null && typeof(Component).IsAssignableFrom(t))
210
+ {
211
+ if (relationalSet.Contains(t))
212
+ {
213
+ _assigner.Assign(component);
214
+ break;
215
+ }
216
+ t = t.BaseType;
217
+ }
218
+ }
219
+ }
220
+
221
+ private void AssignBySceneRoots(Scene target, bool includeInactive)
222
+ {
223
+ int rootCount = target.rootCount;
224
+ if (rootCount == 0)
225
+ {
226
+ return;
227
+ }
228
+ using PooledResource<List<GameObject>> rootGoBuffer = Buffers<GameObject>.List.Get(
229
+ out List<GameObject> roots
230
+ );
231
+ target.GetRootGameObjects(roots);
232
+ foreach (GameObject root in roots)
233
+ {
234
+ if (root == null)
235
+ {
236
+ continue;
237
+ }
238
+ _assigner.AssignHierarchy(root, includeInactive);
239
+ }
240
+ }
241
+ }
242
+ }
243
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: b0eebbf7839d3134e84389f53f242abe
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -227,10 +227,7 @@ namespace WallstopStudios.UnityHelpers.Tags
227
227
  if (inst != null && inst._prewarmRelationalOnLoad)
228
228
  {
229
229
  RelationalComponentInitializer.Report report =
230
- Core.Attributes.RelationalComponentInitializer.Initialize(
231
- types: null,
232
- logSummary: false
233
- );
230
+ RelationalComponentInitializer.Initialize(types: null, logSummary: false);
234
231
  Debug.Log(
235
232
  $"AttributeMetadataCache: Relational prewarm enabled. TypesWarmed={report.TypesWarmed}, FieldsWarmed={report.FieldsWarmed}, Warnings={report.Warnings}, Errors={report.Errors}."
236
233
  );
@@ -1113,21 +1113,21 @@ namespace WallstopStudios.UnityHelpers.Utils
1113
1113
  /// This struct implements IDisposable to enable automatic resource return via 'using' statements.
1114
1114
  /// The resource is returned to its pool when Dispose is called, typically at the end of a 'using' block.
1115
1115
  /// </remarks>
1116
- public readonly struct PooledResource<T> : IDisposable
1116
+ public struct PooledResource<T> : IDisposable
1117
1117
  {
1118
1118
  /// <summary>
1119
1119
  /// The pooled resource instance. Access this to use the resource.
1120
1120
  /// </summary>
1121
1121
  public readonly T resource;
1122
1122
  private readonly Action<T> _onDispose;
1123
- private readonly bool _initialized;
1123
+ private bool _initialized;
1124
1124
 
1125
1125
  /// <summary>
1126
1126
  /// Creates a new PooledResource wrapping the specified resource with a disposal action.
1127
1127
  /// </summary>
1128
1128
  /// <param name="resource">The resource to wrap.</param>
1129
1129
  /// <param name="onDispose">The action to invoke when disposing, typically returning the resource to a pool.</param>
1130
- internal PooledResource(T resource, Action<T> onDispose)
1130
+ public PooledResource(T resource, Action<T> onDispose)
1131
1131
  {
1132
1132
  _initialized = true;
1133
1133
  this.resource = resource;
@@ -1144,7 +1144,7 @@ namespace WallstopStudios.UnityHelpers.Utils
1144
1144
  {
1145
1145
  return;
1146
1146
  }
1147
-
1147
+ _initialized = false;
1148
1148
  _onDispose(resource);
1149
1149
  }
1150
1150
  }
@@ -1,7 +1,6 @@
1
1
  namespace WallstopStudios.UnityHelpers.Utils
2
2
  {
3
3
  using System;
4
- using System.Linq;
5
4
  using UnityEngine;
6
5
  using WallstopStudios.UnityHelpers.Core.Attributes;
7
6
  using WallstopStudios.UnityHelpers.Core.Helper;
@@ -1,7 +1,9 @@
1
1
  namespace WallstopStudios.UnityHelpers.Utils
2
2
  {
3
- using UnityEditor;
4
3
  using UnityEngine;
4
+ #if UNITY_EDITOR
5
+ using UnityEditor;
6
+ #endif
5
7
 
6
8
  public static class SetTextureImportData
7
9
  {
@@ -36,10 +36,14 @@ namespace WallstopStudios.UnityHelpers.Utils
36
36
  /// This method modifies the texture in-place. Point sampling provides fast, sharp scaling
37
37
  /// but may produce pixelated results. Use Bilinear for smoother results.
38
38
  /// </remarks>
39
- public static void Point(Texture2D tex, int newWidth, int newHeight)
39
+ public static void Point(Texture2D tex, int newWidth, int newHeight, bool apply = false)
40
40
  {
41
41
  ValidateInputs(tex, newWidth, newHeight);
42
42
  ThreadedScale(tex, newWidth, newHeight, false);
43
+ if (apply)
44
+ {
45
+ tex.Apply(updateMipmaps: false, makeNoLongerReadable: false);
46
+ }
43
47
  }
44
48
 
45
49
  /// <summary>
@@ -55,10 +59,14 @@ namespace WallstopStudios.UnityHelpers.Utils
55
59
  /// This method modifies the texture in-place. Bilinear interpolation provides smooth scaling
56
60
  /// with better visual quality than point sampling, at a slight performance cost.
57
61
  /// </remarks>
58
- public static void Bilinear(Texture2D tex, int newWidth, int newHeight)
62
+ public static void Bilinear(Texture2D tex, int newWidth, int newHeight, bool apply = false)
59
63
  {
60
64
  ValidateInputs(tex, newWidth, newHeight);
61
65
  ThreadedScale(tex, newWidth, newHeight, true);
66
+ if (apply)
67
+ {
68
+ tex.Apply(updateMipmaps: false, makeNoLongerReadable: false);
69
+ }
62
70
  }
63
71
 
64
72
  private static void ValidateInputs(Texture2D tex, int newWidth, int newHeight)
@@ -70,6 +70,7 @@ namespace WallstopStudios.UnityHelpers.Visuals.UGUI
70
70
  /// Stores the dedicated material instance produced by <see cref="UpdateMaterialInstance"/>.
71
71
  /// </summary>
72
72
  private Material _cachedMaterialInstance;
73
+ internal Material CachedMaterialInstanceForTests => _cachedMaterialInstance;
73
74
 
74
75
  /// <summary>
75
76
  /// HDR-capable tint applied to the instantiated material. Values above 1 keep their intensity instead of being clamped.
@@ -214,5 +215,10 @@ namespace WallstopStudios.UnityHelpers.Visuals.UGUI
214
215
  _cachedMaterialInstance = null;
215
216
  }
216
217
  }
218
+
219
+ // Test helpers to avoid reflection
220
+ internal void InvokeStartForTests() => Start();
221
+
222
+ internal void InvokeOnDestroyForTests() => OnDestroy();
217
223
  }
218
224
  }
@@ -6,11 +6,13 @@ namespace WallstopStudios.UnityHelpers.Visuals.UIToolkit
6
6
  using System.Linq;
7
7
  using System.Runtime.CompilerServices;
8
8
  using System.Threading.Tasks;
9
- using UnityEditor;
10
9
  using UnityEngine;
11
10
  using UnityEngine.UIElements;
12
11
  using WallstopStudios.UnityHelpers.Core.Helper;
13
12
  using WallstopStudios.UnityHelpers.Utils;
13
+ #if UNITY_EDITOR
14
+ using UnityEditor;
15
+ #endif
14
16
 
15
17
  public sealed class LayeredImage : VisualElement
16
18
  {
@@ -68,6 +70,7 @@ namespace WallstopStudios.UnityHelpers.Visuals.UIToolkit
68
70
 
69
71
  private readonly AnimatedSpriteLayer[] _layers;
70
72
  private readonly Texture2D[] _computed;
73
+ internal Texture2D[] ComputedTexturesForTests => _computed;
71
74
  private readonly Color _backgroundColor;
72
75
  private readonly Rect? _largestArea;
73
76
  private readonly Stopwatch _timer;
package/SERIALIZATION.md CHANGED
@@ -646,3 +646,18 @@ References
646
646
  - Replace direct `System.Text.Json.JsonSerializer` calls in app code with `Serializer.JsonSerialize/JsonDeserialize/JsonStringify`, or with `Serializer.Serialize/Deserialize` + `SerializationType.Json` to centralize options and Unity converters.
647
647
  - Replace any custom protobuf helpers with `Serializer.ProtoSerialize/ProtoDeserialize` or the generic `Serializer.Serialize/Deserialize` APIs. Ensure models are annotated with `[ProtoContract]` and stable `[ProtoMember(n)]` tags.
648
648
  - For existing binary saves using BinaryFormatter, prefer migrating to Json or Protobuf. If you must keep BinaryFormatter, scope it to trusted, same-version caches only.
649
+
650
+ ## 2.0 changes
651
+
652
+ - BinaryFormatter (`SerializationType.SystemBinary`) is deprecated but remains functional for trusted/legacy scenarios. Prefer:
653
+ - `SerializationType.Json` (System.Text.Json with Unity-aware converters) for readable, diffable content.
654
+ - `SerializationType.Protobuf` (protobuf-net) for compact, high-performance binary payloads.
655
+
656
+ ## IL2CPP / AOT guidance
657
+
658
+ System.Text.Json can require extra care under AOT (e.g., IL2CPP):
659
+
660
+ - Prefer explicit `JsonSerializerOptions` and concrete generic APIs over `object`-based serialization to reduce reflection.
661
+ - For hot POCO models, consider adding a source-generated context (JsonSerializerContext) in your game assembly and pass it to `JsonSerializer` calls.
662
+ - If you rely on many custom converters, ensure they are referenced by code so the linker doesn't strip them. The UnityHelpers converters are referenced via options by default.
663
+ - Avoid deserializing `System.Type` from untrusted input (see `TypeConverter`); this is intended for trusted configs/tools.