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
@@ -281,6 +281,91 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
281
281
  Assert.IsTrue(exceptionThrown);
282
282
  }
283
283
 
284
+ [UnityTest]
285
+ public IEnumerator TaskTupleAsCoroutineCompletesSuccessfully()
286
+ {
287
+ Task<(int, string)> task = CreateDelayedTask(() => (7, "lucky"));
288
+
289
+ int first = 0;
290
+ string second = null;
291
+ yield return task.AsCoroutine(
292
+ (value, label) =>
293
+ {
294
+ first = value;
295
+ second = label;
296
+ }
297
+ );
298
+
299
+ Assert.AreEqual(7, first);
300
+ Assert.AreEqual("lucky", second);
301
+ }
302
+
303
+ [UnityTest]
304
+ public IEnumerator TaskTupleAsCoroutineWorksWithoutCallback()
305
+ {
306
+ Task<(int, string)> task = CreateDelayedTask(() => (5, "five"));
307
+
308
+ yield return task.AsCoroutine();
309
+
310
+ Assert.AreEqual((5, "five"), task.Result);
311
+ }
312
+
313
+ [UnityTest]
314
+ public IEnumerator TaskTupleAsCoroutineThrowsOnFaultedTask()
315
+ {
316
+ Task<(int, string)> task = CreateFaultedTask<(int, string)>();
317
+
318
+ bool exceptionThrown = false;
319
+ IEnumerator coroutine = task.AsCoroutine((_, _) => { });
320
+
321
+ while (true)
322
+ {
323
+ try
324
+ {
325
+ if (!coroutine.MoveNext())
326
+ {
327
+ break;
328
+ }
329
+ }
330
+ catch (InvalidOperationException)
331
+ {
332
+ exceptionThrown = true;
333
+ break;
334
+ }
335
+ catch (AggregateException e)
336
+ {
337
+ exceptionThrown = e.Flatten()
338
+ .InnerExceptions.Any(inner => inner is InvalidOperationException);
339
+ break;
340
+ }
341
+ yield return null;
342
+ }
343
+
344
+ Assert.IsTrue(exceptionThrown);
345
+ }
346
+
347
+ [UnityTest]
348
+ public IEnumerator TaskTripleAsCoroutineCompletesSuccessfully()
349
+ {
350
+ Task<(int, string, bool)> task = CreateDelayedTask(() => (1, "one", true));
351
+
352
+ int first = 0;
353
+ string second = null;
354
+ bool third = false;
355
+ yield return task.AsCoroutine(
356
+ (value, label, flag) =>
357
+ {
358
+ first = value;
359
+ second = label;
360
+ third = flag;
361
+ }
362
+ );
363
+
364
+ Assert.AreEqual(1, first);
365
+ Assert.AreEqual("one", second);
366
+ Assert.IsTrue(third);
367
+ }
368
+
284
369
  // Tests for ValueTask.AsCoroutine()
285
370
  [UnityTest]
286
371
  public IEnumerator ValueTaskAsCoroutineCompletesSuccessfully()
@@ -400,6 +485,100 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
400
485
  Assert.IsTrue(exceptionThrown);
401
486
  }
402
487
 
488
+ [UnityTest]
489
+ public IEnumerator ValueTaskTupleAsCoroutineCompletesSuccessfully()
490
+ {
491
+ ValueTask<(int, string)> task = new(CreateDelayedTask(() => (2, "two")));
492
+
493
+ int first = 0;
494
+ string second = null;
495
+ yield return task.AsCoroutine(
496
+ (value, label) =>
497
+ {
498
+ first = value;
499
+ second = label;
500
+ }
501
+ );
502
+
503
+ Assert.AreEqual(2, first);
504
+ Assert.AreEqual("two", second);
505
+ }
506
+
507
+ [UnityTest]
508
+ public IEnumerator ValueTaskTupleAsCoroutineCompletesImmediatelyWhenAlreadyDone()
509
+ {
510
+ ValueTask<(int, string)> task = new((3, "three"));
511
+
512
+ int first = 0;
513
+ string second = null;
514
+ yield return task.AsCoroutine(
515
+ (value, label) =>
516
+ {
517
+ first = value;
518
+ second = label;
519
+ }
520
+ );
521
+
522
+ Assert.AreEqual(3, first);
523
+ Assert.AreEqual("three", second);
524
+ }
525
+
526
+ [UnityTest]
527
+ public IEnumerator ValueTaskTupleAsCoroutineThrowsOnFaultedTask()
528
+ {
529
+ ValueTask<(int, string)> task = new(CreateFaultedTask<(int, string)>());
530
+
531
+ bool exceptionThrown = false;
532
+ IEnumerator coroutine = task.AsCoroutine((_, _) => { });
533
+
534
+ while (true)
535
+ {
536
+ try
537
+ {
538
+ if (!coroutine.MoveNext())
539
+ {
540
+ break;
541
+ }
542
+ }
543
+ catch (InvalidOperationException)
544
+ {
545
+ exceptionThrown = true;
546
+ break;
547
+ }
548
+ catch (AggregateException e)
549
+ {
550
+ exceptionThrown = e.Flatten()
551
+ .InnerExceptions.Any(inner => inner is InvalidOperationException);
552
+ break;
553
+ }
554
+ yield return null;
555
+ }
556
+
557
+ Assert.IsTrue(exceptionThrown);
558
+ }
559
+
560
+ [UnityTest]
561
+ public IEnumerator ValueTaskTripleAsCoroutineCompletesSuccessfully()
562
+ {
563
+ ValueTask<(int, string, bool)> task = new(CreateDelayedTask(() => (4, "four", true)));
564
+
565
+ int first = 0;
566
+ string second = null;
567
+ bool third = false;
568
+ yield return task.AsCoroutine(
569
+ (value, label, flag) =>
570
+ {
571
+ first = value;
572
+ second = label;
573
+ third = flag;
574
+ }
575
+ );
576
+
577
+ Assert.AreEqual(4, first);
578
+ Assert.AreEqual("four", second);
579
+ Assert.IsTrue(third);
580
+ }
581
+
403
582
  // Tests for IEnumerator.AsTask()
404
583
  [UnityTest]
405
584
  public IEnumerator IEnumeratorAsTaskCompletesSuccessfully()
@@ -445,6 +445,61 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
445
445
  }
446
446
  }
447
447
 
448
+ [Test]
449
+ public void NextWeightedElement()
450
+ {
451
+ List<string> items = new() { "rare", "common" };
452
+ List<float> weights = new() { 1f, 99f };
453
+ HashSet<string> seen = new();
454
+ int commonCount = 0;
455
+ int rareCount = 0;
456
+ for (int i = 0; i < 1000; ++i)
457
+ {
458
+ string result = PRNG.Instance.NextWeightedElement(items, weights);
459
+ seen.Add(result);
460
+ if (result == "common")
461
+ {
462
+ commonCount++;
463
+ }
464
+ else if (result == "rare")
465
+ {
466
+ rareCount++;
467
+ }
468
+ }
469
+
470
+ Assert.AreEqual(2, seen.Count);
471
+ Assert.Greater(commonCount, rareCount);
472
+ Assert.Greater(commonCount, 900);
473
+ }
474
+
475
+ [Test]
476
+ public void NextWeightedElementThrowsOnNullItems()
477
+ {
478
+ List<float> weights = new() { 1f };
479
+ Assert.Throws<ArgumentNullException>(() =>
480
+ PRNG.Instance.NextWeightedElement<string>(null, weights)
481
+ );
482
+ }
483
+
484
+ [Test]
485
+ public void NextWeightedElementThrowsOnNullWeights()
486
+ {
487
+ List<string> items = new() { "item" };
488
+ Assert.Throws<ArgumentNullException>(() =>
489
+ PRNG.Instance.NextWeightedElement(items, (IReadOnlyList<float>)null)
490
+ );
491
+ }
492
+
493
+ [Test]
494
+ public void NextWeightedElementThrowsOnMismatchedCounts()
495
+ {
496
+ List<string> items = new() { "item" };
497
+ List<float> weights = new() { 1f, 2f };
498
+ Assert.Throws<ArgumentException>(() =>
499
+ PRNG.Instance.NextWeightedElement(items, weights)
500
+ );
501
+ }
502
+
448
503
  [Test]
449
504
  public void NextWeighted()
450
505
  {
@@ -0,0 +1,445 @@
1
+ #if REFLEX_PRESENT
2
+ namespace WallstopStudios.UnityHelpers.Tests.Integrations.Reflex
3
+ {
4
+ using System;
5
+ using System.Collections.Generic;
6
+ using global::Reflex.Core;
7
+ using NUnit.Framework;
8
+ using UnityEngine;
9
+ using UnityEngine.SceneManagement;
10
+ using UnityEngine.TestTools;
11
+ using WallstopStudios.UnityHelpers.Core.Attributes;
12
+ using WallstopStudios.UnityHelpers.Integrations.Reflex;
13
+ using WallstopStudios.UnityHelpers.Tags;
14
+ using WallstopStudios.UnityHelpers.Tests.TestUtils;
15
+
16
+ public sealed class RelationalComponentsReflexTests : CommonTestBase
17
+ {
18
+ [Test]
19
+ public void ContainerExtensionsUseBoundAssigner()
20
+ {
21
+ ContainerBuilder builder = new();
22
+ RecordingAssigner assigner = new();
23
+ builder.AddSingleton(assigner, typeof(IRelationalComponentAssigner));
24
+ builder.AddSingleton(CreateCacheFor(typeof(ReflexRelationalTester)));
25
+ Container container = builder.Build();
26
+
27
+ ReflexRelationalTester tester = CreateHierarchy();
28
+
29
+ container.AssignRelationalComponents(tester);
30
+
31
+ Assert.That(assigner.CallCount, Is.EqualTo(1), "Assigner should be invoked once.");
32
+ Assert.That(
33
+ assigner.LastComponent,
34
+ Is.SameAs(tester),
35
+ "Assigner should target the supplied component."
36
+ );
37
+ Assert.IsTrue(tester.parentBody != null, "ParentComponent field should be assigned.");
38
+ Assert.IsTrue(tester.childCollider != null, "ChildComponent field should be assigned.");
39
+ }
40
+
41
+ [Test]
42
+ public void ContainerExtensionsFallbackWithoutAssigner()
43
+ {
44
+ Container container = new ContainerBuilder().Build();
45
+
46
+ ReflexRelationalTester tester = CreateHierarchy();
47
+
48
+ container.AssignRelationalComponents(tester);
49
+
50
+ Assert.IsTrue(
51
+ tester.parentBody != null,
52
+ "Fallback path should assign parentBody using reflection."
53
+ );
54
+ Assert.IsTrue(
55
+ tester.childCollider != null,
56
+ "Fallback path should assign childCollider using reflection."
57
+ );
58
+ }
59
+
60
+ [UnityTest]
61
+ public System.Collections.IEnumerator AssignSceneHydratesComponents()
62
+ {
63
+ AttributeMetadataCache cache = CreateCacheFor(typeof(ReflexRelationalTester));
64
+ RecordingAssigner assigner = new();
65
+ Scene scene = CreateTempScene("ReflexAssignScene");
66
+ ReflexRelationalTester tester = CreateHierarchy();
67
+ GameObject root = tester.transform.root.gameObject;
68
+ SceneManager.MoveGameObjectToScene(root, scene);
69
+ yield return null;
70
+
71
+ RelationalReflexSceneBootstrapper.AssignScene(
72
+ scene,
73
+ assigner,
74
+ cache,
75
+ RelationalSceneAssignmentOptions.Default
76
+ );
77
+
78
+ Assert.That(assigner.CallCount, Is.EqualTo(1), "AssignScene should use the assigner.");
79
+ Assert.That(
80
+ assigner.LastComponent,
81
+ Is.SameAs(tester),
82
+ "AssignScene should hydrate relational tester component."
83
+ );
84
+ Assert.IsTrue(tester.parentBody != null, "ParentBody should be assigned after scan.");
85
+ Assert.IsTrue(
86
+ tester.childCollider != null,
87
+ "ChildCollider should be assigned after scan."
88
+ );
89
+ }
90
+
91
+ [UnityTest]
92
+ public System.Collections.IEnumerator InstallerBindsAssignerAndOptions()
93
+ {
94
+ AttributeMetadataCache cache = CreateCacheFor(typeof(ReflexRelationalTester));
95
+ System.Lazy<AttributeMetadataCache> previousLazy = AttributeMetadataCache.LazyInstance;
96
+ AttributeMetadataCache.LazyInstance = new System.Lazy<AttributeMetadataCache>(() =>
97
+ cache
98
+ );
99
+
100
+ Scene scene = CreateTempScene("ReflexInstallerScene");
101
+ GameObject installerObject = Track(new GameObject("ReflexInstaller"));
102
+ RelationalComponentsInstaller installer =
103
+ installerObject.AddComponent<RelationalComponentsInstaller>();
104
+ SceneManager.MoveGameObjectToScene(installerObject, scene);
105
+
106
+ ReflexRelationalTester tester = CreateHierarchy();
107
+ GameObject root = tester.transform.root.gameObject;
108
+ SceneManager.MoveGameObjectToScene(root, scene);
109
+ yield return null;
110
+
111
+ ContainerBuilder builder = new();
112
+ builder.SetName("ReflexTesterContainer");
113
+ installer.InstallBindings(builder);
114
+ try
115
+ {
116
+ Container container = builder.Build();
117
+ yield return null;
118
+
119
+ Assert.IsTrue(
120
+ container.HasBinding<IRelationalComponentAssigner>(),
121
+ "Installer should bind IRelationalComponentAssigner."
122
+ );
123
+
124
+ Assert.IsTrue(
125
+ tester.parentBody != null,
126
+ "Installer should hydrate parentBody via scene assignment."
127
+ );
128
+ Assert.IsTrue(
129
+ tester.childCollider != null,
130
+ "Installer should hydrate childCollider via scene assignment."
131
+ );
132
+ }
133
+ finally
134
+ {
135
+ AttributeMetadataCache.LazyInstance = previousLazy;
136
+ }
137
+ }
138
+
139
+ [UnityTest]
140
+ public System.Collections.IEnumerator InstantiateComponentWithRelationsUsesAssigner()
141
+ {
142
+ ContainerBuilder builder = new();
143
+ RecordingAssigner assigner = new();
144
+ builder.AddSingleton(assigner, typeof(IRelationalComponentAssigner));
145
+ builder.AddSingleton(CreateCacheFor(typeof(ReflexRelationalTester)));
146
+ Container container = builder.Build();
147
+
148
+ GameObject parent = Track(new GameObject("ReflexComponentParent"));
149
+ Rigidbody parentBody = parent.AddComponent<Rigidbody>();
150
+ parentBody.useGravity = false;
151
+
152
+ ReflexRelationalTester prefab = CreateComponentPrefabTester();
153
+ ReflexRelationalTester instance = container.InstantiateComponentWithRelations(
154
+ prefab,
155
+ parent.transform
156
+ );
157
+ Track(instance.gameObject);
158
+ instance.gameObject.SetActive(true);
159
+
160
+ yield return null;
161
+
162
+ Assert.That(
163
+ assigner.CallCount,
164
+ Is.GreaterThanOrEqualTo(1),
165
+ "InstantiateComponentWithRelations should invoke the assigner."
166
+ );
167
+ Assert.That(
168
+ assigner.AssignedComponents,
169
+ Does.Contain(instance),
170
+ "Assigner should receive the instantiated component."
171
+ );
172
+ Assert.That(
173
+ instance.parentBody,
174
+ Is.SameAs(parentBody),
175
+ "ParentComponent attribute should resolve the injected parent Rigidbody."
176
+ );
177
+ Assert.IsNotNull(
178
+ instance.childCollider,
179
+ "ChildComponent attribute should resolve the child collider on instantiation."
180
+ );
181
+ }
182
+
183
+ [UnityTest]
184
+ public System.Collections.IEnumerator InstantiateComponentWithRelationsFallsBackWithoutAssigner()
185
+ {
186
+ Container container = new ContainerBuilder().Build();
187
+
188
+ GameObject parent = Track(new GameObject("ReflexComponentParentFallback"));
189
+ Rigidbody parentBody = parent.AddComponent<Rigidbody>();
190
+ parentBody.useGravity = false;
191
+
192
+ ReflexRelationalTester prefab = CreateComponentPrefabTester();
193
+ ReflexRelationalTester instance = container.InstantiateComponentWithRelations(
194
+ prefab,
195
+ parent.transform
196
+ );
197
+ Track(instance.gameObject);
198
+ instance.gameObject.SetActive(true);
199
+
200
+ yield return null;
201
+
202
+ Assert.That(
203
+ instance.parentBody,
204
+ Is.SameAs(parentBody),
205
+ "Fallback path should assign the parent Rigidbody."
206
+ );
207
+ Assert.IsNotNull(
208
+ instance.childCollider,
209
+ "Fallback path should assign the child collider."
210
+ );
211
+ }
212
+
213
+ [UnityTest]
214
+ public System.Collections.IEnumerator InstantiateGameObjectWithRelationsUsesAssigner()
215
+ {
216
+ ContainerBuilder builder = new();
217
+ RecordingAssigner assigner = new();
218
+ builder.AddSingleton(assigner, typeof(IRelationalComponentAssigner));
219
+ builder.AddSingleton(CreateCacheFor(typeof(ReflexRelationalTester)));
220
+ Container container = builder.Build();
221
+
222
+ GameObject parent = Track(new GameObject("ReflexGameObjectParent"));
223
+ Rigidbody parentBody = parent.AddComponent<Rigidbody>();
224
+ parentBody.useGravity = false;
225
+
226
+ GameObject prefabRoot = CreateGameObjectPrefab();
227
+ GameObject instanceRoot = container.InstantiateGameObjectWithRelations(
228
+ prefabRoot,
229
+ parent.transform,
230
+ includeInactiveChildren: true
231
+ );
232
+ Track(instanceRoot);
233
+ instanceRoot.SetActive(true);
234
+
235
+ yield return null;
236
+
237
+ ReflexRelationalTester instanceTester =
238
+ instanceRoot.GetComponentInChildren<ReflexRelationalTester>(true);
239
+ Assert.NotNull(
240
+ instanceTester,
241
+ "Instantiated hierarchy should include the tester component."
242
+ );
243
+
244
+ Assert.That(
245
+ assigner.CallCount,
246
+ Is.GreaterThanOrEqualTo(1),
247
+ "InstantiateGameObjectWithRelations should invoke the assigner for hierarchy hydration."
248
+ );
249
+ Assert.That(
250
+ assigner.AssignedComponents,
251
+ Does.Contain(instanceTester),
252
+ "Assigner should hydrate the tester component inside the instantiated hierarchy."
253
+ );
254
+ Assert.That(
255
+ instanceTester.parentBody,
256
+ Is.SameAs(parentBody),
257
+ "ParentComponent attribute should bind to the supplied parent hierarchy."
258
+ );
259
+ Assert.IsNotNull(
260
+ instanceTester.childCollider,
261
+ "ChildComponent attribute should bind to the prefab child after instantiation."
262
+ );
263
+ }
264
+
265
+ [UnityTest]
266
+ public System.Collections.IEnumerator InstantiateGameObjectWithRelationsFallsBackWithoutAssigner()
267
+ {
268
+ Container container = new ContainerBuilder().Build();
269
+
270
+ GameObject parent = Track(new GameObject("ReflexGameObjectParentFallback"));
271
+ Rigidbody parentBody = parent.AddComponent<Rigidbody>();
272
+ parentBody.useGravity = false;
273
+
274
+ GameObject prefabRoot = CreateGameObjectPrefab();
275
+ GameObject instanceRoot = container.InstantiateGameObjectWithRelations(
276
+ prefabRoot,
277
+ parent.transform,
278
+ includeInactiveChildren: true
279
+ );
280
+ Track(instanceRoot);
281
+ instanceRoot.SetActive(true);
282
+
283
+ yield return null;
284
+
285
+ ReflexRelationalTester instanceTester =
286
+ instanceRoot.GetComponentInChildren<ReflexRelationalTester>(true);
287
+ Assert.NotNull(
288
+ instanceTester,
289
+ "Instantiated hierarchy should include the tester component."
290
+ );
291
+ Assert.That(
292
+ instanceTester.parentBody,
293
+ Is.SameAs(parentBody),
294
+ "Fallback path should assign the parent Rigidbody inside the instantiated hierarchy."
295
+ );
296
+ Assert.IsNotNull(
297
+ instanceTester.childCollider,
298
+ "Fallback path should assign the child collider inside the instantiated hierarchy."
299
+ );
300
+ }
301
+
302
+ private ReflexRelationalTester CreateHierarchy()
303
+ {
304
+ GameObject parent = Track(new GameObject("ReflexParent"));
305
+ Rigidbody parentBody = parent.AddComponent<Rigidbody>();
306
+ parentBody.useGravity = false;
307
+
308
+ GameObject middle = Track(new GameObject("ReflexMiddle"));
309
+ middle.transform.SetParent(parent.transform);
310
+ ReflexRelationalTester tester = middle.AddComponent<ReflexRelationalTester>();
311
+
312
+ GameObject child = Track(new GameObject("ReflexChild"));
313
+ child.transform.SetParent(middle.transform);
314
+ child.AddComponent<CapsuleCollider>();
315
+
316
+ return tester;
317
+ }
318
+
319
+ private ReflexRelationalTester CreateComponentPrefabTester()
320
+ {
321
+ GameObject root = Track(new GameObject("ReflexComponentPrefab"));
322
+ ReflexRelationalTester tester = root.AddComponent<ReflexRelationalTester>();
323
+
324
+ GameObject child = new GameObject("ReflexComponentPrefabChild");
325
+ child.AddComponent<CapsuleCollider>();
326
+ child.transform.SetParent(root.transform, false);
327
+
328
+ root.SetActive(false);
329
+ return tester;
330
+ }
331
+
332
+ private GameObject CreateGameObjectPrefab()
333
+ {
334
+ GameObject root = Track(new GameObject("ReflexGameObjectPrefab"));
335
+ root.AddComponent<ReflexRelationalTester>();
336
+
337
+ GameObject child = new GameObject("ReflexGameObjectPrefabChild");
338
+ child.AddComponent<CapsuleCollider>();
339
+ child.transform.SetParent(root.transform, false);
340
+
341
+ root.SetActive(false);
342
+ return root;
343
+ }
344
+
345
+ private AttributeMetadataCache CreateCacheFor(Type componentType)
346
+ {
347
+ AttributeMetadataCache cache = Track(
348
+ ScriptableObject.CreateInstance<AttributeMetadataCache>()
349
+ );
350
+
351
+ AttributeMetadataCache.RelationalFieldMetadata[] fields =
352
+ {
353
+ new(
354
+ nameof(ReflexRelationalTester.parentBody),
355
+ AttributeMetadataCache.RelationalAttributeKind.Parent,
356
+ AttributeMetadataCache.FieldKind.Single,
357
+ typeof(Rigidbody).AssemblyQualifiedName,
358
+ false
359
+ ),
360
+ new(
361
+ nameof(ReflexRelationalTester.childCollider),
362
+ AttributeMetadataCache.RelationalAttributeKind.Child,
363
+ AttributeMetadataCache.FieldKind.Single,
364
+ typeof(CapsuleCollider).AssemblyQualifiedName,
365
+ false
366
+ ),
367
+ };
368
+
369
+ AttributeMetadataCache.RelationalTypeMetadata[] relationalTypes =
370
+ {
371
+ new(componentType.AssemblyQualifiedName, fields),
372
+ };
373
+
374
+ cache._relationalTypeMetadata = relationalTypes;
375
+ cache.ForceRebuildForTests();
376
+ return cache;
377
+ }
378
+
379
+ private sealed class RecordingAssigner : IRelationalComponentAssigner
380
+ {
381
+ private readonly List<Component> _assignedComponents = new();
382
+
383
+ public int CallCount { get; private set; }
384
+
385
+ public Component LastComponent { get; private set; }
386
+
387
+ public IReadOnlyList<Component> AssignedComponents => _assignedComponents;
388
+
389
+ public bool HasRelationalAssignments(Type componentType)
390
+ {
391
+ return true;
392
+ }
393
+
394
+ public void Assign(Component component)
395
+ {
396
+ LastComponent = component;
397
+ CallCount++;
398
+ if (component != null)
399
+ {
400
+ _assignedComponents.Add(component);
401
+ }
402
+ component?.AssignRelationalComponents();
403
+ }
404
+
405
+ public void Assign(IEnumerable<Component> components)
406
+ {
407
+ if (components == null)
408
+ {
409
+ return;
410
+ }
411
+
412
+ foreach (Component component in components)
413
+ {
414
+ Assign(component);
415
+ }
416
+ }
417
+
418
+ public void AssignHierarchy(GameObject root, bool includeInactiveChildren = true)
419
+ {
420
+ if (root == null)
421
+ {
422
+ return;
423
+ }
424
+
425
+ Component[] components = root.GetComponentsInChildren<Component>(
426
+ includeInactiveChildren
427
+ );
428
+ for (int i = 0; i < components.Length; i++)
429
+ {
430
+ Assign(components[i]);
431
+ }
432
+ }
433
+ }
434
+
435
+ private sealed class ReflexRelationalTester : MonoBehaviour
436
+ {
437
+ [ParentComponent(OnlyAncestors = true)]
438
+ public Rigidbody parentBody;
439
+
440
+ [ChildComponent(OnlyDescendants = true)]
441
+ public CapsuleCollider childCollider;
442
+ }
443
+ }
444
+ }
445
+ #endif