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

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 (264) 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/npm-publish.yml +1 -1
  15. package/.github/workflows/prettier-autofix.yml +195 -0
  16. package/.github/workflows/update-dotnet-tools.yml +80 -0
  17. package/.github/workflows/yaml-format-lint.yml +41 -0
  18. package/.lychee.toml +4 -4
  19. package/.markdownlint.jsonc +21 -0
  20. package/.pre-commit-config.yaml +11 -3
  21. package/.yamllint.yaml +31 -0
  22. package/AGENTS.md +5 -1
  23. package/Docs/CHANGELOG.md +11 -0
  24. package/Docs/CONTRIBUTING.md +49 -0
  25. package/Docs/CONTRIBUTING.md.meta +7 -0
  26. package/{EDITOR_TOOLS_GUIDE.md → Docs/EDITOR_TOOLS_GUIDE.md} +4 -0
  27. package/Docs/EFFECTS_SYSTEM.md +1316 -0
  28. package/{EFFECTS_SYSTEM_TUTORIAL.md → Docs/EFFECTS_SYSTEM_TUTORIAL.md} +1 -1
  29. package/{GETTING_STARTED.md → Docs/GETTING_STARTED.md} +50 -64
  30. package/{GLOSSARY.md → Docs/GLOSSARY.md} +4 -4
  31. package/Docs/HELPER_UTILITIES.md +885 -0
  32. package/Docs/HELPER_UTILITIES.md.meta +7 -0
  33. package/{INDEX.md → Docs/INDEX.md} +107 -62
  34. package/Docs/MATH_AND_EXTENSIONS.md +1039 -0
  35. package/{RANDOM_PERFORMANCE.md → Docs/RANDOM_PERFORMANCE.md} +15 -15
  36. package/{RELATIONAL_COMPONENTS.md → Docs/RELATIONAL_COMPONENTS.md} +111 -84
  37. package/{SERIALIZATION.md → Docs/SERIALIZATION.md} +15 -0
  38. package/{SPATIAL_TREES_2D_GUIDE.md → Docs/SPATIAL_TREES_2D_GUIDE.md} +2 -2
  39. package/{SPATIAL_TREES_3D_GUIDE.md → Docs/SPATIAL_TREES_3D_GUIDE.md} +1 -1
  40. package/Docs/SPATIAL_TREE_2D_PERFORMANCE.md +241 -0
  41. package/Docs/SPATIAL_TREE_3D_PERFORMANCE.md +243 -0
  42. package/{THIRD_PARTY_NOTICES.md → Docs/THIRD_PARTY_NOTICES.md} +1 -1
  43. package/Docs/UTILITY_COMPONENTS.md +906 -0
  44. package/Docs/UTILITY_COMPONENTS.md.meta +7 -0
  45. package/Docs/VISUAL_COMPONENTS.md +337 -0
  46. package/Docs/VISUAL_COMPONENTS.md.meta +7 -0
  47. package/Editor/AnimationEventEditor.cs +337 -160
  48. package/Editor/Core/Helper/AnimationEventHelpers.cs +178 -152
  49. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +20 -11
  50. package/Editor/CustomEditors/TexturePlatformOverrideEntryDrawer.cs +11 -2
  51. package/Editor/FitTextureSizeWindow.cs +43 -19
  52. package/Editor/PersistentDirectorySettings.cs +64 -12
  53. package/Editor/PrefabChecker.cs +72 -5
  54. package/Editor/Sprites/AnimationCopier.cs +131 -55
  55. package/Editor/Sprites/AnimationCreator.cs +63 -22
  56. package/Editor/Sprites/AnimationViewerWindow.cs +42 -6
  57. package/Editor/Sprites/TexturePlatformNameHelper.cs +50 -39
  58. package/Editor/Sprites/TextureResizerWizard.cs +23 -1
  59. package/Editor/Sprites/TextureSettingsApplierWindow.cs +148 -85
  60. package/Editor/Tools/ImageBlurTool.cs +81 -10
  61. package/Editor/Utils/EditorUi.cs +1 -1
  62. package/Editor/Utils/ScriptableObjectSingletonCreator.cs +1 -1
  63. package/README.md +428 -2433
  64. package/Runtime/AssemblyInfo.cs +4 -0
  65. package/Runtime/Core/Attributes/NotNullAttribute.cs +1 -3
  66. package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +50 -5
  67. package/Runtime/Core/DataStructure/CyclicBuffer.cs +0 -1
  68. package/Runtime/Core/DataStructure/KDTree3D.cs +1 -1
  69. package/Runtime/Core/DataStructure/OctTree3D.cs +1 -1
  70. package/Runtime/Core/Extension/AsyncOperationExtensions.cs +122 -0
  71. package/Runtime/Core/Extension/RandomExtensions.cs +68 -0
  72. package/Runtime/Core/Extension/WallstopStudiosLogger.cs +16 -0
  73. package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -1
  74. package/Runtime/Core/Helper/ReflectionHelpers.cs +21 -10
  75. package/Runtime/Core/Helper/SpriteHelpers.cs +3 -1
  76. package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +45 -1
  77. package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +13 -5
  78. package/Runtime/Core/Serialization/JsonConverters/ResolutionConverter.cs +1 -1
  79. package/Runtime/Core/Serialization/JsonConverters/TypeConverter.cs +1 -1
  80. package/Runtime/Core/Serialization/ProtobufUnitySurrogates.cs +24 -29
  81. package/Runtime/Core/Serialization/Serializer.cs +101 -0
  82. package/Runtime/Integrations/Reflex/AssemblyInfo.cs +7 -0
  83. package/Runtime/Integrations/Reflex/AssemblyInfo.cs.meta +11 -0
  84. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs +198 -0
  85. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs.meta +11 -0
  86. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs +86 -0
  87. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs.meta +11 -0
  88. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs +316 -0
  89. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs.meta +11 -0
  90. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs +86 -0
  91. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs.meta +11 -0
  92. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef +20 -0
  93. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef.meta +7 -0
  94. package/Runtime/Integrations/Reflex.meta +8 -0
  95. package/Runtime/Integrations/VContainer/AssemblyInfo.cs +9 -0
  96. package/Runtime/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  97. package/Runtime/Integrations/VContainer/ObjectResolverRelationalExtensions.cs +96 -0
  98. package/Runtime/Integrations/VContainer/RelationalComponentEntryPoint.cs +90 -10
  99. package/Runtime/Integrations/VContainer/RelationalComponentsBuilderExtensions.cs +13 -1
  100. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs +114 -0
  101. package/Runtime/Integrations/VContainer/RelationalObjectPools.cs.meta +11 -0
  102. package/Runtime/Integrations/VContainer/RelationalSceneAssignmentOptions.cs +16 -4
  103. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs +241 -0
  104. package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs.meta +11 -0
  105. package/Runtime/Integrations/Zenject/AssemblyInfo.cs +9 -0
  106. package/Runtime/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  107. package/Runtime/Integrations/Zenject/DiContainerRelationalExtensions.cs +69 -2
  108. package/Runtime/Integrations/Zenject/RelationalComponentSceneInitializer.cs +89 -12
  109. package/Runtime/Integrations/Zenject/RelationalComponentsInstaller.cs +23 -1
  110. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs +44 -0
  111. package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs.meta +11 -0
  112. package/Runtime/Integrations/Zenject/RelationalSceneAssignmentOptions.cs +16 -10
  113. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs +243 -0
  114. package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs.meta +11 -0
  115. package/Runtime/Tags/AttributeMetadataCache.cs +1 -4
  116. package/Runtime/Utils/Buffers.cs +4 -4
  117. package/Runtime/Utils/ScriptableObjectSingleton.cs +1 -2
  118. package/Runtime/Utils/SetTextureImportData.cs +3 -1
  119. package/Runtime/Utils/TextureScale.cs +10 -2
  120. package/Runtime/Visuals/UGUI/EnhancedImage.cs +6 -0
  121. package/Runtime/Visuals/UIToolkit/LayeredImage.cs +4 -1
  122. package/Samples~/DI - Reflex/README.md +527 -0
  123. package/Samples~/DI - Reflex/README.md.meta +7 -0
  124. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs +36 -0
  125. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs.meta +11 -0
  126. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs +79 -0
  127. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs.meta +11 -0
  128. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs +30 -0
  129. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs.meta +11 -0
  130. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs +79 -0
  131. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs.meta +11 -0
  132. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef +26 -0
  133. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef.meta +9 -0
  134. package/Samples~/DI - Reflex/Scripts.meta +8 -0
  135. package/Samples~/DI - Reflex.meta +8 -0
  136. package/Samples~/DI - VContainer/README.md +238 -56
  137. package/Samples~/DI - VContainer/Scripts/GameLifetimeScope.cs +22 -4
  138. package/Samples~/DI - VContainer/Scripts/RelationalConsumer.cs +5 -2
  139. package/Samples~/DI - VContainer/Scripts/Spawner.cs +113 -4
  140. package/Samples~/DI - Zenject/README.md +223 -58
  141. package/Samples~/DI - Zenject/Scripts/RelationalConsumer.cs +3 -0
  142. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs +37 -0
  143. package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs.meta +12 -0
  144. package/Samples~/DI - Zenject/Scripts/SpawnerZenject.cs +74 -3
  145. package/Samples~/Random - PRNG/README.md +2 -1
  146. package/Samples~/Relational Components - Basic/README.md +3 -1
  147. package/Samples~/Serialization - JSON/README.md +2 -1
  148. package/Samples~/Spatial Structures - 2D and 3D/README.md +2 -1
  149. package/Samples~/UGUI - EnhancedImage/README.md +2 -1
  150. package/Samples~/UI Toolkit - MultiFile Selector (Editor)/README.md +2 -1
  151. package/Tests/Editor/Attributes/AnimationEventHelpersTests.cs +16 -0
  152. package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +32 -34
  153. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs +41 -0
  154. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs.meta +11 -0
  155. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef +27 -0
  156. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef.meta +7 -0
  157. package/Tests/Editor/Integrations/Reflex.meta +8 -0
  158. package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +21 -18
  159. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +164 -0
  160. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs.meta +11 -0
  161. package/Tests/Editor/Integrations/VContainer/WallstopStudios.UnityHelpers.Tests.Editor.VContainer.asmdef +2 -1
  162. package/Tests/Editor/Integrations/Zenject/WallstopStudios.UnityHelpers.Tests.Editor.Zenject.asmdef +3 -2
  163. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +127 -0
  164. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs.meta +11 -0
  165. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +25 -23
  166. package/Tests/Editor/PersistentDirectorySettingsTests.cs +58 -0
  167. package/Tests/Editor/PersistentDirectorySettingsTests.cs.meta +11 -0
  168. package/Tests/Editor/PrefabCheckerReportTests.cs +32 -0
  169. package/Tests/Editor/PrefabCheckerReportTests.cs.meta +11 -0
  170. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +63 -0
  171. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs.meta +11 -0
  172. package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +1 -1
  173. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +38 -0
  174. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs.meta +11 -0
  175. package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +1 -1
  176. package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +12 -12
  177. package/Tests/Editor/Sprites/SpriteCropperTests.cs +9 -9
  178. package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +3 -3
  179. package/Tests/Editor/Sprites/TexturePlatformNameHelperTests.cs +18 -0
  180. package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +5 -5
  181. package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +3 -3
  182. package/Tests/Editor/Sprites/TextureSettingsApplierWizardAdditionalTests.cs +4 -4
  183. package/Tests/Editor/Sprites/TextureSettingsApplierWizardTests.cs +4 -4
  184. package/Tests/Editor/Tools/ImageBlurToolTests.cs +22 -110
  185. package/Tests/Editor/Utils/CommonTestBase.cs +60 -1
  186. package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +6 -6
  187. package/Tests/Editor/Windows/FitTextureSizeWindowTests.cs +66 -74
  188. package/Tests/Runtime/Attributes/RelationalComponentInitializerTests.cs +4 -15
  189. package/Tests/Runtime/DataStructures/SpatialTree3DBoundsConsistencyTests.cs +29 -29
  190. package/Tests/Runtime/Extensions/AsyncOperationExtensionsTests.cs +179 -0
  191. package/Tests/Runtime/Extensions/RandomExtensionTests.cs +55 -0
  192. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +445 -0
  193. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs.meta +11 -0
  194. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef +28 -0
  195. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef.meta +7 -0
  196. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  197. package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +257 -221
  198. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +91 -0
  199. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs.meta +11 -0
  200. package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +251 -233
  201. package/Tests/Runtime/Performance/RandomPerformanceTests.cs +1 -1
  202. package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +6 -1
  203. package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +4 -1
  204. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs +30 -0
  205. package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs.meta +11 -0
  206. package/Tests/Runtime/Serialization/JsonConverterTests.cs +8 -12
  207. package/Tests/Runtime/Serialization/JsonRoundtripComprehensiveTests.cs +4 -9
  208. package/Tests/Runtime/Serialization/JsonSerializationTest.cs +16 -5
  209. package/Tests/Runtime/Serialization/ProtoRoundtripComprehensiveTests.cs +13 -13
  210. package/Tests/Runtime/Serialization/SerializerAdditionalTests.cs +12 -0
  211. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs +105 -0
  212. package/Tests/Runtime/Serialization/SerializerFileIoTests.cs.meta +11 -0
  213. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs +247 -0
  214. package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs.meta +11 -0
  215. package/Tests/Runtime/TestUtils/CommonTestBase.cs +99 -0
  216. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs +111 -0
  217. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs.meta +12 -0
  218. package/Tests/Runtime/Utils/CoroutineHandlerTests.cs +1 -1
  219. package/Tests/Runtime/Utils/LZMAComprehensiveTests.cs +1 -1
  220. package/Tests/Runtime/Utils/LZMATests.cs +1 -1
  221. package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +5 -5
  222. package/Tests/Runtime/Visuals/EnhancedImageTests.cs +25 -56
  223. package/Tests/Runtime/Visuals/VisualsTestHelpers.cs +1 -8
  224. package/Tests/TestUtils.meta +8 -0
  225. package/package-lock.json.meta +7 -0
  226. package/package.json +13 -4
  227. package/scripts/check-eol.ps1 +4 -5
  228. package/scripts/lint-tests.ps1 +156 -0
  229. package/scripts/lint-tests.ps1.meta +7 -0
  230. package/scripts/normalize-eol.ps1 +6 -9
  231. package/.github/workflows/csharpier.yml +0 -135
  232. package/CHANGELOG.md +0 -0
  233. package/EFFECTS_SYSTEM.md +0 -242
  234. package/MATH_AND_EXTENSIONS.md +0 -316
  235. package/SPATIAL_TREE_2D_PERFORMANCE.md +0 -238
  236. package/SPATIAL_TREE_3D_PERFORMANCE.md +0 -240
  237. /package/{CHANGELOG.md.meta → Docs/CHANGELOG.md.meta} +0 -0
  238. /package/{DATA_STRUCTURES.md → Docs/DATA_STRUCTURES.md} +0 -0
  239. /package/{DATA_STRUCTURES.md.meta → Docs/DATA_STRUCTURES.md.meta} +0 -0
  240. /package/{EDITOR_TOOLS_GUIDE.md.meta → Docs/EDITOR_TOOLS_GUIDE.md.meta} +0 -0
  241. /package/{EFFECTS_SYSTEM.md.meta → Docs/EFFECTS_SYSTEM.md.meta} +0 -0
  242. /package/{EFFECTS_SYSTEM_TUTORIAL.md.meta → Docs/EFFECTS_SYSTEM_TUTORIAL.md.meta} +0 -0
  243. /package/{GETTING_STARTED.md.meta → Docs/GETTING_STARTED.md.meta} +0 -0
  244. /package/{GLOSSARY.md.meta → Docs/GLOSSARY.md.meta} +0 -0
  245. /package/{HULLS.md → Docs/HULLS.md} +0 -0
  246. /package/{HULLS.md.meta → Docs/HULLS.md.meta} +0 -0
  247. /package/{INDEX.md.meta → Docs/INDEX.md.meta} +0 -0
  248. /package/{LICENSE.md → Docs/LICENSE.md} +0 -0
  249. /package/{LICENSE.md.meta → Docs/LICENSE.md.meta} +0 -0
  250. /package/{MATH_AND_EXTENSIONS.md.meta → Docs/MATH_AND_EXTENSIONS.md.meta} +0 -0
  251. /package/{RANDOM_PERFORMANCE.md.meta → Docs/RANDOM_PERFORMANCE.md.meta} +0 -0
  252. /package/{REFLECTION_HELPERS.md → Docs/REFLECTION_HELPERS.md} +0 -0
  253. /package/{REFLECTION_HELPERS.md.meta → Docs/REFLECTION_HELPERS.md.meta} +0 -0
  254. /package/{RELATIONAL_COMPONENTS.md.meta → Docs/RELATIONAL_COMPONENTS.md.meta} +0 -0
  255. /package/{SERIALIZATION.md.meta → Docs/SERIALIZATION.md.meta} +0 -0
  256. /package/{SINGLETONS.md → Docs/SINGLETONS.md} +0 -0
  257. /package/{SINGLETONS.md.meta → Docs/SINGLETONS.md.meta} +0 -0
  258. /package/{SPATIAL_TREES_2D_GUIDE.md.meta → Docs/SPATIAL_TREES_2D_GUIDE.md.meta} +0 -0
  259. /package/{SPATIAL_TREES_3D_GUIDE.md.meta → Docs/SPATIAL_TREES_3D_GUIDE.md.meta} +0 -0
  260. /package/{SPATIAL_TREE_2D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_2D_PERFORMANCE.md.meta} +0 -0
  261. /package/{SPATIAL_TREE_3D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_3D_PERFORMANCE.md.meta} +0 -0
  262. /package/{SPATIAL_TREE_SEMANTICS.md → Docs/SPATIAL_TREE_SEMANTICS.md} +0 -0
  263. /package/{SPATIAL_TREE_SEMANTICS.md.meta → Docs/SPATIAL_TREE_SEMANTICS.md.meta} +0 -0
  264. /package/{THIRD_PARTY_NOTICES.md.meta → Docs/THIRD_PARTY_NOTICES.md.meta} +0 -0
@@ -5,3 +5,7 @@ using System.Runtime.CompilerServices;
5
5
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Editor")]
6
6
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.Zenject")]
7
7
  [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.VContainer")]
8
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.Reflex")]
9
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.VContainer")]
10
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.Zenject")]
11
+ [assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.Reflex")]
@@ -13,9 +13,7 @@ namespace WallstopStudios.UnityHelpers.Core.Attributes
13
13
  {
14
14
  #if UNITY_EDITOR
15
15
  IEnumerable<FieldInfo> properties =
16
- WallstopStudios.UnityHelpers.Core.Helper.ReflectionHelpers.GetFieldsWithAttribute<NotNullAttribute>(
17
- o.GetType()
18
- );
16
+ Helper.ReflectionHelpers.GetFieldsWithAttribute<NotNullAttribute>(o.GetType());
19
17
 
20
18
  foreach (FieldInfo field in properties)
21
19
  {
@@ -2,6 +2,7 @@ namespace WallstopStudios.UnityHelpers.Core.Attributes
2
2
  {
3
3
  using System;
4
4
  using System.Collections.Generic;
5
+ using System.Linq;
5
6
  using Tags;
6
7
  using UnityEngine;
7
8
  using WallstopStudios.UnityHelpers.Utils;
@@ -39,14 +40,58 @@ namespace WallstopStudios.UnityHelpers.Core.Attributes
39
40
  AttributeMetadataCache cache = _metadataCache ?? AttributeMetadataCache.Instance;
40
41
  if (cache == null)
41
42
  {
42
- return false;
43
+ // Fallback to reflection-based discovery when no cache is available
44
+ return HasRelationalAttributesViaReflection(componentType);
43
45
  }
44
46
 
45
- return cache.TryGetRelationalFields(
46
- componentType,
47
- out AttributeMetadataCache.RelationalFieldMetadata[] fields
47
+ Type current = componentType;
48
+ while (current != null && typeof(Component).IsAssignableFrom(current))
49
+ {
50
+ if (
51
+ cache.TryGetRelationalFields(
52
+ current,
53
+ out AttributeMetadataCache.RelationalFieldMetadata[] fields
54
+ )
55
+ && fields.Length > 0
48
56
  )
49
- && fields.Length > 0;
57
+ {
58
+ return true;
59
+ }
60
+ current = current.BaseType;
61
+ }
62
+
63
+ // Fallback: inspect fields via reflection to detect relational attributes
64
+ return HasRelationalAttributesViaReflection(componentType);
65
+ }
66
+
67
+ private static bool HasRelationalAttributesViaReflection(Type componentType)
68
+ {
69
+ Type current = componentType;
70
+ while (current != null && typeof(Component).IsAssignableFrom(current))
71
+ {
72
+ // Prefer ReflectionHelpers so Editor TypeCache can accelerate lookups
73
+ bool has =
74
+ Helper
75
+ .ReflectionHelpers.GetFieldsWithAttribute<ParentComponentAttribute>(current)
76
+ .Any()
77
+ || Helper
78
+ .ReflectionHelpers.GetFieldsWithAttribute<ChildComponentAttribute>(current)
79
+ .Any()
80
+ || Helper
81
+ .ReflectionHelpers.GetFieldsWithAttribute<SiblingComponentAttribute>(
82
+ current
83
+ )
84
+ .Any();
85
+
86
+ if (has)
87
+ {
88
+ return true;
89
+ }
90
+
91
+ current = current.BaseType;
92
+ }
93
+
94
+ return false;
50
95
  }
51
96
 
52
97
  /// <inheritdoc />
@@ -4,7 +4,6 @@ namespace WallstopStudios.UnityHelpers.Core.DataStructure
4
4
  using System.Collections;
5
5
  using System.Collections.Generic;
6
6
  using System.Runtime.CompilerServices;
7
- using Extension;
8
7
  using Helper;
9
8
  using ProtoBuf;
10
9
  using UnityEngine;
@@ -17,7 +17,7 @@ namespace WallstopStudios.UnityHelpers.Core.DataStructure
17
17
  /// <para>Semantics: Due to algorithmic choices (axis-aligned splitting, half-open containment checks,
18
18
  /// minimum node-size enforcement, and tie-handling on split planes), KdTree3D (balanced and unbalanced)
19
19
  /// may return different edge-case results compared to OctTree3D for identical inputs/queries—especially for
20
- /// points lying exactly on query boundaries or split planes. See SPATIAL_TREE_SEMANTICS.md for details.</para>
20
+ /// points lying exactly on query boundaries or split planes. See Docs/SPATIAL_TREE_SEMANTICS.md for details.</para>
21
21
  /// </remarks>
22
22
  [Serializable]
23
23
  public sealed class KdTree3D<T> : ISpatialTree3D<T>
@@ -16,7 +16,7 @@ namespace WallstopStudios.UnityHelpers.Core.DataStructure
16
16
  /// <para>Cons: Immutable structure by design; rebuild when positions change frequently.</para>
17
17
  /// <para>Semantics: OctTree3D uses octant subdivision and inclusive half-open containment checks with internal
18
18
  /// fast-paths when nodes are fully contained. These choices can lead to different results from KdTree3D for points
19
- /// on boundaries or when numeric precision interacts with minimum node-size adjustments. See SPATIAL_TREE_SEMANTICS.md.</para>
19
+ /// on boundaries or when numeric precision interacts with minimum node-size adjustments. See Docs/SPATIAL_TREE_SEMANTICS.md.</para>
20
20
  /// </remarks>
21
21
  [Serializable]
22
22
  public sealed class OctTree3D<T> : ISpatialTree3D<T>
@@ -271,6 +271,67 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
271
271
  onResult?.Invoke(task.Result);
272
272
  }
273
273
 
274
+ /// <summary>
275
+ /// Converts a Task returning a tuple with two elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
276
+ /// </summary>
277
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
278
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
279
+ /// <param name="task">The task to convert.</param>
280
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
281
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
282
+ /// <remarks>
283
+ /// <para>Null handling: Task cannot be null. onResult can be null.</para>
284
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
285
+ /// <para>Performance: Delegates work to the generic Task overload. O(1) per iteration.</para>
286
+ /// <para>Allocations: Iterator allocation only.</para>
287
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
288
+ /// </remarks>
289
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
290
+ public static IEnumerator AsCoroutine<T1, T2>(
291
+ this Task<(T1 First, T2 Second)> task,
292
+ Action<T1, T2> onResult = null
293
+ )
294
+ {
295
+ return task.AsCoroutine(tuple =>
296
+ {
297
+ if (onResult != null)
298
+ {
299
+ onResult(tuple.First, tuple.Second);
300
+ }
301
+ });
302
+ }
303
+
304
+ /// <summary>
305
+ /// Converts a Task returning a tuple with three elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
306
+ /// </summary>
307
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
308
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
309
+ /// <typeparam name="T3">The type of the third tuple element.</typeparam>
310
+ /// <param name="task">The task to convert.</param>
311
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
312
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
313
+ /// <remarks>
314
+ /// <para>Null handling: Task cannot be null. onResult can be null.</para>
315
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
316
+ /// <para>Performance: Delegates work to the generic Task overload. O(1) per iteration.</para>
317
+ /// <para>Allocations: Iterator allocation only.</para>
318
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
319
+ /// </remarks>
320
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
321
+ public static IEnumerator AsCoroutine<T1, T2, T3>(
322
+ this Task<(T1 First, T2 Second, T3 Third)> task,
323
+ Action<T1, T2, T3> onResult = null
324
+ )
325
+ {
326
+ return task.AsCoroutine(tuple =>
327
+ {
328
+ if (onResult != null)
329
+ {
330
+ onResult(tuple.First, tuple.Second, tuple.Third);
331
+ }
332
+ });
333
+ }
334
+
274
335
  /// <summary>
275
336
  /// Converts a ValueTask to a Unity coroutine (IEnumerator).
276
337
  /// </summary>
@@ -348,6 +409,67 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
348
409
  onResult?.Invoke(innerTask.Result);
349
410
  }
350
411
 
412
+ /// <summary>
413
+ /// Converts a ValueTask returning a tuple with two elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
414
+ /// </summary>
415
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
416
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
417
+ /// <param name="task">The ValueTask to convert.</param>
418
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
419
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
420
+ /// <remarks>
421
+ /// <para>Null handling: ValueTask is a value type and cannot be null. onResult can be null.</para>
422
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
423
+ /// <para>Performance: Delegates work to the generic ValueTask overload. O(1) per iteration.</para>
424
+ /// <para>Allocations: Iterator allocation only.</para>
425
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
426
+ /// </remarks>
427
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
428
+ public static IEnumerator AsCoroutine<T1, T2>(
429
+ this ValueTask<(T1 First, T2 Second)> task,
430
+ Action<T1, T2> onResult = null
431
+ )
432
+ {
433
+ return task.AsCoroutine(tuple =>
434
+ {
435
+ if (onResult != null)
436
+ {
437
+ onResult(tuple.First, tuple.Second);
438
+ }
439
+ });
440
+ }
441
+
442
+ /// <summary>
443
+ /// Converts a ValueTask returning a tuple with three elements to a Unity coroutine (IEnumerator), optionally invoking a callback with the tuple elements.
444
+ /// </summary>
445
+ /// <typeparam name="T1">The type of the first tuple element.</typeparam>
446
+ /// <typeparam name="T2">The type of the second tuple element.</typeparam>
447
+ /// <typeparam name="T3">The type of the third tuple element.</typeparam>
448
+ /// <param name="task">The ValueTask to convert.</param>
449
+ /// <param name="onResult">Optional callback invoked with the tuple elements. Can be null.</param>
450
+ /// <returns>An IEnumerator that can be used with StartCoroutine.</returns>
451
+ /// <remarks>
452
+ /// <para>Null handling: ValueTask is a value type and cannot be null. onResult can be null.</para>
453
+ /// <para>Thread safety: Must be iterated on Unity main thread. No Unity main thread requirement for task execution.</para>
454
+ /// <para>Performance: Delegates work to the generic ValueTask overload. O(1) per iteration.</para>
455
+ /// <para>Allocations: Iterator allocation only.</para>
456
+ /// <para>Edge cases: Returns immediately if task is complete. Propagates task exceptions.</para>
457
+ /// </remarks>
458
+ /// <exception cref="Exception">Throws the task's exception if the task is faulted.</exception>
459
+ public static IEnumerator AsCoroutine<T1, T2, T3>(
460
+ this ValueTask<(T1 First, T2 Second, T3 Third)> task,
461
+ Action<T1, T2, T3> onResult = null
462
+ )
463
+ {
464
+ return task.AsCoroutine(tuple =>
465
+ {
466
+ if (onResult != null)
467
+ {
468
+ onResult(tuple.First, tuple.Second, tuple.Third);
469
+ }
470
+ });
471
+ }
472
+
351
473
  // IEnumerator to Task/ValueTask conversions
352
474
  /// <summary>
353
475
  /// Converts a Unity coroutine (IEnumerator) to a Task.
@@ -17,6 +17,74 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
17
17
  /// </remarks>
18
18
  public static class RandomExtensions
19
19
  {
20
+ /// <summary>
21
+ /// Returns an index sampled from the provided weights (unnormalized). Negative weights are treated as zero.
22
+ /// </summary>
23
+ public static int NextWeightedIndex(this IRandom random, IReadOnlyList<float> weights)
24
+ {
25
+ if (weights == null)
26
+ {
27
+ throw new ArgumentNullException(nameof(weights));
28
+ }
29
+ if (weights.Count == 0)
30
+ {
31
+ throw new ArgumentException("Weights cannot be empty", nameof(weights));
32
+ }
33
+ double total = 0;
34
+ for (int i = 0; i < weights.Count; i++)
35
+ {
36
+ if (weights[i] > 0)
37
+ {
38
+ total += weights[i];
39
+ }
40
+ }
41
+ if (total <= 0)
42
+ {
43
+ throw new ArgumentException("Sum of weights must be > 0", nameof(weights));
44
+ }
45
+ double r = random.NextDouble() * total;
46
+ double acc = 0;
47
+ for (int i = 0; i < weights.Count; i++)
48
+ {
49
+ float w = weights[i];
50
+ if (w <= 0)
51
+ {
52
+ continue;
53
+ }
54
+ acc += w;
55
+ if (r <= acc)
56
+ {
57
+ return i;
58
+ }
59
+ }
60
+ return weights.Count - 1;
61
+ }
62
+
63
+ /// <summary>
64
+ /// Returns an element sampled according to the given weights list. Throws if lengths mismatch.
65
+ /// </summary>
66
+ public static T NextWeightedElement<T>(
67
+ this IRandom random,
68
+ IReadOnlyList<T> items,
69
+ IReadOnlyList<float> weights
70
+ )
71
+ {
72
+ if (items == null)
73
+ {
74
+ throw new ArgumentNullException(nameof(items));
75
+ }
76
+ if (weights == null)
77
+ {
78
+ throw new ArgumentNullException(nameof(weights));
79
+ }
80
+ if (items.Count != weights.Count)
81
+ {
82
+ throw new ArgumentException("Items and weights length must match.");
83
+ }
84
+ int idx = random.NextWeightedIndex(weights);
85
+ return items[idx];
86
+ }
87
+
20
88
  /// <summary>
21
89
  /// Generates a random 2D vector with components in the range [-amplitude, amplitude].
22
90
  /// </summary>
@@ -74,6 +74,22 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
74
74
  LoggingEnabled = false;
75
75
  }
76
76
 
77
+ /// <summary>
78
+ /// Gets whether global logging is enabled.
79
+ /// </summary>
80
+ public static bool IsGlobalLoggingEnabled()
81
+ {
82
+ return LoggingEnabled;
83
+ }
84
+
85
+ /// <summary>
86
+ /// Sets global logging enabled/disabled without requiring an Object instance.
87
+ /// </summary>
88
+ public static void SetGlobalLoggingEnabled(bool enabled)
89
+ {
90
+ LoggingEnabled = enabled;
91
+ }
92
+
77
93
  public static void EnableLogging(this Object component)
78
94
  {
79
95
  Disabled.Remove(component);
@@ -3,11 +3,14 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3
3
  using System;
4
4
  using System.Collections.Generic;
5
5
  using Extension;
6
- using UnityEditor;
7
6
  using UnityEngine;
8
7
  using UnityEngine.SceneManagement;
9
8
  using WallstopStudios.UnityHelpers.Utils;
10
9
  using Object = UnityEngine.Object;
10
+ #if UNITY_EDITOR
11
+ using UnityEditor;
12
+ #endif
13
+
11
14
  #if UNITY_EDITOR
12
15
  using UnityEditor.SceneManagement;
13
16
  #endif
@@ -12,7 +12,9 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
12
12
  using System.Linq.Expressions;
13
13
  using System.Reflection;
14
14
  using System.Runtime.CompilerServices;
15
+ #if UNITY_EDITOR
15
16
  using UnityEditor;
17
+ #endif
16
18
  #if EMIT_DYNAMIC_IL
17
19
  using System.Reflection.Emit;
18
20
  #endif
@@ -50,10 +52,9 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
50
52
  {
51
53
  // Cache for type resolution by name
52
54
  #if !SINGLE_THREADED
53
- private static readonly System.Collections.Concurrent.ConcurrentDictionary<
54
- string,
55
- Type
56
- > TypeResolutionCache = new(StringComparer.Ordinal);
55
+ private static readonly ConcurrentDictionary<string, Type> TypeResolutionCache = new(
56
+ StringComparer.Ordinal
57
+ );
57
58
  #else
58
59
  private static readonly Dictionary<string, Type> TypeResolutionCache = new(
59
60
  StringComparer.Ordinal
@@ -383,6 +384,17 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
383
384
  return ListCreators.GetOrAdd(elementType, type => GetListCreator(type)).Invoke();
384
385
  }
385
386
 
387
+ // Test helpers to avoid reflection in tests when asserting cache state
388
+ internal static bool IsFieldGetterCached(FieldInfo field)
389
+ {
390
+ return field != null && FieldGetterCache.ContainsKey(field);
391
+ }
392
+
393
+ internal static bool IsFieldSetterCached(FieldInfo field)
394
+ {
395
+ return field != null && FieldSetterCache.ContainsKey(field);
396
+ }
397
+
386
398
  /// <summary>
387
399
  /// Builds a cached delegate that returns the value of a field as <see cref="object"/>.
388
400
  /// Supports instance and static fields.
@@ -3713,7 +3725,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3713
3725
  #if UNITY_EDITOR
3714
3726
  try
3715
3727
  {
3716
- TypeCache.TypeCollection list = UnityEditor.TypeCache.GetTypesDerivedFrom<T>();
3728
+ TypeCache.TypeCollection list = TypeCache.GetTypesDerivedFrom<T>();
3717
3729
  return list.Where(t =>
3718
3730
  t != null && (includeAbstract || (t.IsClass && !t.IsAbstract))
3719
3731
  );
@@ -3747,7 +3759,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3747
3759
  #if UNITY_EDITOR
3748
3760
  try
3749
3761
  {
3750
- TypeCache.TypeCollection list = UnityEditor.TypeCache.GetTypesDerivedFrom(baseType);
3762
+ TypeCache.TypeCollection list = TypeCache.GetTypesDerivedFrom(baseType);
3751
3763
  return list.Where(t =>
3752
3764
  t != null && (includeAbstract || (t.IsClass && !t.IsAbstract))
3753
3765
  );
@@ -3799,8 +3811,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3799
3811
  #if UNITY_EDITOR
3800
3812
  try
3801
3813
  {
3802
- TypeCache.TypeCollection types =
3803
- UnityEditor.TypeCache.GetTypesWithAttribute<TAttribute>();
3814
+ TypeCache.TypeCollection types = TypeCache.GetTypesWithAttribute<TAttribute>();
3804
3815
  return types.Where(t =>
3805
3816
  t != null && (includeAbstract || (t.IsClass && !t.IsAbstract))
3806
3817
  );
@@ -3855,7 +3866,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3855
3866
  try
3856
3867
  {
3857
3868
  TypeCache.MethodCollection methods =
3858
- UnityEditor.TypeCache.GetMethodsWithAttribute<TAttribute>();
3869
+ TypeCache.GetMethodsWithAttribute<TAttribute>();
3859
3870
  IEnumerable<MethodInfo> filtered = methods;
3860
3871
  if (within != null)
3861
3872
  {
@@ -3892,7 +3903,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
3892
3903
  try
3893
3904
  {
3894
3905
  TypeCache.FieldInfoCollection fields =
3895
- UnityEditor.TypeCache.GetFieldsWithAttribute<TAttribute>();
3906
+ TypeCache.GetFieldsWithAttribute<TAttribute>();
3896
3907
  IEnumerable<FieldInfo> filtered = fields;
3897
3908
  if (within != null)
3898
3909
  {
@@ -1,8 +1,10 @@
1
1
  namespace WallstopStudios.UnityHelpers.Core.Helper
2
2
  {
3
3
  using Extension;
4
- using UnityEditor;
5
4
  using UnityEngine;
5
+ #if UNITY_EDITOR
6
+ using UnityEditor;
7
+ #endif
6
8
 
7
9
  /// <summary>
8
10
  /// Sprite and texture utilities for editor workflows.
@@ -2,9 +2,11 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
2
2
  {
3
3
  using System;
4
4
  using System.Collections.Concurrent;
5
- using UnityEditor;
6
5
  using UnityEngine;
7
6
  using Utils;
7
+ #if UNITY_EDITOR
8
+ using UnityEditor;
9
+ #endif
8
10
 
9
11
  /// <summary>
10
12
  /// Thread-safe dispatcher that enqueues work to run on Unity's main thread.
@@ -96,5 +98,47 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
96
98
  }
97
99
  }
98
100
  }
101
+
102
+ /// <summary>
103
+ /// Posts an action to run on the main thread and returns a Task that completes after execution.
104
+ /// </summary>
105
+ public System.Threading.Tasks.Task RunAsync(Action action)
106
+ {
107
+ var tcs = new System.Threading.Tasks.TaskCompletionSource<bool>();
108
+ RunOnMainThread(() =>
109
+ {
110
+ try
111
+ {
112
+ action();
113
+ tcs.SetResult(true);
114
+ }
115
+ catch (Exception ex)
116
+ {
117
+ tcs.SetException(ex);
118
+ }
119
+ });
120
+ return tcs.Task;
121
+ }
122
+
123
+ /// <summary>
124
+ /// Posts a function to run on the main thread and returns its result via Task.
125
+ /// </summary>
126
+ public System.Threading.Tasks.Task<T> Post<T>(Func<T> func)
127
+ {
128
+ var tcs = new System.Threading.Tasks.TaskCompletionSource<T>();
129
+ RunOnMainThread(() =>
130
+ {
131
+ try
132
+ {
133
+ T result = func();
134
+ tcs.SetResult(result);
135
+ }
136
+ catch (Exception ex)
137
+ {
138
+ tcs.SetException(ex);
139
+ }
140
+ });
141
+ return tcs.Task;
142
+ }
99
143
  }
100
144
  }
@@ -26,11 +26,19 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization.JsonConverters
26
26
  JsonSerializerOptions options
27
27
  )
28
28
  {
29
- writer.WriteStringValue(
30
- value == null
31
- ? "{}"
32
- : new { name = value.name, type = value.GetType().FullName }.ToString()
33
- );
29
+ if (value == null)
30
+ {
31
+ writer.WriteNullValue();
32
+ return;
33
+ }
34
+
35
+ writer.WriteStartObject();
36
+ writer.WriteString("name", value.name);
37
+ // Use AssemblyQualifiedName to disambiguate type for diagnostics
38
+ writer.WriteString("type", value.GetType().AssemblyQualifiedName);
39
+ // Emit the actual Unity instance ID without transformation for correctness.
40
+ writer.WriteNumber("instanceId", value.GetInstanceID());
41
+ writer.WriteEndObject();
34
42
  }
35
43
  }
36
44
  }
@@ -141,7 +141,7 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization.JsonConverters
141
141
  #if UNITY_2022_2_OR_NEWER
142
142
  uint num = value.refreshRateRatio.numerator;
143
143
  uint den = value.refreshRateRatio.denominator;
144
- int hz = den != 0 ? (int)System.Math.Round((double)num / den) : 0;
144
+ int hz = den != 0 ? (int)Math.Round((double)num / den) : 0;
145
145
  writer.WriteNumber(RefreshRateProp, hz);
146
146
  writer.WritePropertyName(RefreshRatioProp);
147
147
  writer.WriteStartObject();
@@ -19,7 +19,7 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization.JsonConverters
19
19
  string typeName = reader.GetString();
20
20
  return string.IsNullOrWhiteSpace(typeName)
21
21
  ? null
22
- : Core.Helper.ReflectionHelpers.TryResolveType(typeName);
22
+ : Helper.ReflectionHelpers.TryResolveType(typeName);
23
23
  }
24
24
 
25
25
  public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)