com.wallstop-studios.unity-helpers 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/.github/workflows/format-on-demand.yml +2 -2
  2. package/.github/workflows/markdown-json.yml +1 -1
  3. package/.github/workflows/npm-publish.yml +1 -1
  4. package/.github/workflows/prettier-autofix.yml +4 -4
  5. package/.github/workflows/yaml-format-lint.yml +1 -1
  6. package/Docs/EFFECTS_SYSTEM.md +1316 -0
  7. package/{EFFECTS_SYSTEM_TUTORIAL.md → Docs/EFFECTS_SYSTEM_TUTORIAL.md} +1 -1
  8. package/{GETTING_STARTED.md → Docs/GETTING_STARTED.md} +10 -8
  9. package/{GLOSSARY.md → Docs/GLOSSARY.md} +4 -4
  10. package/Docs/HELPER_UTILITIES.md +885 -0
  11. package/Docs/HELPER_UTILITIES.md.meta +7 -0
  12. package/{INDEX.md → Docs/INDEX.md} +107 -62
  13. package/Docs/MATH_AND_EXTENSIONS.md +1039 -0
  14. package/{RANDOM_PERFORMANCE.md → Docs/RANDOM_PERFORMANCE.md} +15 -15
  15. package/{RELATIONAL_COMPONENTS.md → Docs/RELATIONAL_COMPONENTS.md} +21 -3
  16. package/{SPATIAL_TREES_2D_GUIDE.md → Docs/SPATIAL_TREES_2D_GUIDE.md} +2 -2
  17. package/{SPATIAL_TREES_3D_GUIDE.md → Docs/SPATIAL_TREES_3D_GUIDE.md} +1 -1
  18. package/{SPATIAL_TREE_2D_PERFORMANCE.md → Docs/SPATIAL_TREE_2D_PERFORMANCE.md} +64 -64
  19. package/{SPATIAL_TREE_3D_PERFORMANCE.md → Docs/SPATIAL_TREE_3D_PERFORMANCE.md} +64 -64
  20. package/Docs/UTILITY_COMPONENTS.md +906 -0
  21. package/Docs/UTILITY_COMPONENTS.md.meta +7 -0
  22. package/Docs/VISUAL_COMPONENTS.md +337 -0
  23. package/Docs/VISUAL_COMPONENTS.md.meta +7 -0
  24. package/Editor/Sprites/AnimationCopier.cs +3 -3
  25. package/README.md +69 -62
  26. package/Runtime/AssemblyInfo.cs +2 -0
  27. package/Runtime/Core/DataStructure/KDTree3D.cs +1 -1
  28. package/Runtime/Core/DataStructure/OctTree3D.cs +1 -1
  29. package/Runtime/Core/Extension/AsyncOperationExtensions.cs +122 -0
  30. package/Runtime/Core/Helper/Logging/UnityLogTagFormatter.cs +76 -90
  31. package/Runtime/Core/Serialization/ProtobufUnitySurrogates.cs +24 -29
  32. package/Runtime/Integrations/Reflex/AssemblyInfo.cs +7 -0
  33. package/Runtime/Integrations/Reflex/AssemblyInfo.cs.meta +11 -0
  34. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs +198 -0
  35. package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs.meta +11 -0
  36. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs +86 -0
  37. package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs.meta +11 -0
  38. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs +316 -0
  39. package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs.meta +11 -0
  40. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs +86 -0
  41. package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs.meta +11 -0
  42. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef +20 -0
  43. package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef.meta +7 -0
  44. package/Runtime/Integrations/Reflex.meta +8 -0
  45. package/Runtime/Utils/ScriptableObjectSingleton.cs +1 -1
  46. package/Samples~/DI - Reflex/README.md +527 -0
  47. package/Samples~/DI - Reflex/README.md.meta +7 -0
  48. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs +36 -0
  49. package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs.meta +11 -0
  50. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs +79 -0
  51. package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs.meta +11 -0
  52. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs +30 -0
  53. package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs.meta +11 -0
  54. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs +79 -0
  55. package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs.meta +11 -0
  56. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef +26 -0
  57. package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef.meta +9 -0
  58. package/Samples~/DI - Reflex/Scripts.meta +8 -0
  59. package/Samples~/DI - Reflex.meta +8 -0
  60. package/Samples~/DI - VContainer/README.md +6 -5
  61. package/Samples~/DI - Zenject/README.md +6 -5
  62. package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +29 -31
  63. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs +41 -0
  64. package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs.meta +11 -0
  65. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef +27 -0
  66. package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef.meta +7 -0
  67. package/Tests/Editor/Integrations/Reflex.meta +8 -0
  68. package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +15 -16
  69. package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +7 -13
  70. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +7 -11
  71. package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +19 -21
  72. package/Tests/Editor/PersistentDirectorySettingsTests.cs +0 -1
  73. package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +0 -1
  74. package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +2 -2
  75. package/Tests/Editor/Tools/ImageBlurToolTests.cs +1 -1
  76. package/Tests/Editor/Utils/CommonTestBase.cs +17 -0
  77. package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +1 -1
  78. package/Tests/Runtime/Extensions/AsyncOperationExtensionsTests.cs +179 -0
  79. package/Tests/Runtime/Extensions/RandomExtensionTests.cs +55 -0
  80. package/Tests/Runtime/Extensions/UnityLogTagFormatterEdgeTests.cs +84 -0
  81. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +445 -0
  82. package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs.meta +11 -0
  83. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef +28 -0
  84. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef.meta +7 -0
  85. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  86. package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +24 -29
  87. package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +8 -3
  88. package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +10 -20
  89. package/Tests/Runtime/Performance/RandomPerformanceTests.cs +1 -1
  90. package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +1 -1
  91. package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +1 -1
  92. package/Tests/Runtime/Serialization/JsonRoundtripComprehensiveTests.cs +4 -9
  93. package/Tests/Runtime/Serialization/ProtoRoundtripComprehensiveTests.cs +13 -13
  94. package/Tests/Runtime/TestUtils/CommonTestBase.cs +11 -0
  95. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs +111 -0
  96. package/Tests/Runtime/TestUtils/ReflexTestSupport.cs.meta +12 -0
  97. package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +4 -4
  98. package/Tests/TestUtils.meta +8 -0
  99. package/package.json +6 -1
  100. package/EFFECTS_SYSTEM.md +0 -242
  101. package/MATH_AND_EXTENSIONS.md +0 -316
  102. /package/{CHANGELOG.md → Docs/CHANGELOG.md} +0 -0
  103. /package/{CHANGELOG.md.meta → Docs/CHANGELOG.md.meta} +0 -0
  104. /package/{CONTRIBUTING.md → Docs/CONTRIBUTING.md} +0 -0
  105. /package/{CONTRIBUTING.md.meta → Docs/CONTRIBUTING.md.meta} +0 -0
  106. /package/{DATA_STRUCTURES.md → Docs/DATA_STRUCTURES.md} +0 -0
  107. /package/{DATA_STRUCTURES.md.meta → Docs/DATA_STRUCTURES.md.meta} +0 -0
  108. /package/{EDITOR_TOOLS_GUIDE.md → Docs/EDITOR_TOOLS_GUIDE.md} +0 -0
  109. /package/{EDITOR_TOOLS_GUIDE.md.meta → Docs/EDITOR_TOOLS_GUIDE.md.meta} +0 -0
  110. /package/{EFFECTS_SYSTEM.md.meta → Docs/EFFECTS_SYSTEM.md.meta} +0 -0
  111. /package/{EFFECTS_SYSTEM_TUTORIAL.md.meta → Docs/EFFECTS_SYSTEM_TUTORIAL.md.meta} +0 -0
  112. /package/{GETTING_STARTED.md.meta → Docs/GETTING_STARTED.md.meta} +0 -0
  113. /package/{GLOSSARY.md.meta → Docs/GLOSSARY.md.meta} +0 -0
  114. /package/{HULLS.md → Docs/HULLS.md} +0 -0
  115. /package/{HULLS.md.meta → Docs/HULLS.md.meta} +0 -0
  116. /package/{INDEX.md.meta → Docs/INDEX.md.meta} +0 -0
  117. /package/{LICENSE.md → Docs/LICENSE.md} +0 -0
  118. /package/{LICENSE.md.meta → Docs/LICENSE.md.meta} +0 -0
  119. /package/{MATH_AND_EXTENSIONS.md.meta → Docs/MATH_AND_EXTENSIONS.md.meta} +0 -0
  120. /package/{RANDOM_PERFORMANCE.md.meta → Docs/RANDOM_PERFORMANCE.md.meta} +0 -0
  121. /package/{REFLECTION_HELPERS.md → Docs/REFLECTION_HELPERS.md} +0 -0
  122. /package/{REFLECTION_HELPERS.md.meta → Docs/REFLECTION_HELPERS.md.meta} +0 -0
  123. /package/{RELATIONAL_COMPONENTS.md.meta → Docs/RELATIONAL_COMPONENTS.md.meta} +0 -0
  124. /package/{SERIALIZATION.md → Docs/SERIALIZATION.md} +0 -0
  125. /package/{SERIALIZATION.md.meta → Docs/SERIALIZATION.md.meta} +0 -0
  126. /package/{SINGLETONS.md → Docs/SINGLETONS.md} +0 -0
  127. /package/{SINGLETONS.md.meta → Docs/SINGLETONS.md.meta} +0 -0
  128. /package/{SPATIAL_TREES_2D_GUIDE.md.meta → Docs/SPATIAL_TREES_2D_GUIDE.md.meta} +0 -0
  129. /package/{SPATIAL_TREES_3D_GUIDE.md.meta → Docs/SPATIAL_TREES_3D_GUIDE.md.meta} +0 -0
  130. /package/{SPATIAL_TREE_2D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_2D_PERFORMANCE.md.meta} +0 -0
  131. /package/{SPATIAL_TREE_3D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_3D_PERFORMANCE.md.meta} +0 -0
  132. /package/{SPATIAL_TREE_SEMANTICS.md → Docs/SPATIAL_TREE_SEMANTICS.md} +0 -0
  133. /package/{SPATIAL_TREE_SEMANTICS.md.meta → Docs/SPATIAL_TREE_SEMANTICS.md.meta} +0 -0
  134. /package/{THIRD_PARTY_NOTICES.md → Docs/THIRD_PARTY_NOTICES.md} +0 -0
  135. /package/{THIRD_PARTY_NOTICES.md.meta → Docs/THIRD_PARTY_NOTICES.md.meta} +0 -0
@@ -0,0 +1,86 @@
1
+ #if REFLEX_PRESENT
2
+ namespace WallstopStudios.UnityHelpers.Integrations.Reflex
3
+ {
4
+ using global::Reflex.Core;
5
+ using UnityEngine;
6
+ using UnityEngine.SceneManagement;
7
+ using WallstopStudios.UnityHelpers.Core.Attributes;
8
+ using WallstopStudios.UnityHelpers.Tags;
9
+
10
+ /// <summary>
11
+ /// Reflex installer that binds relational component services and optionally hydrates scenes.
12
+ /// </summary>
13
+ [AddComponentMenu("Wallstop Studios/Relational Components/Reflex Installer")]
14
+ public sealed class RelationalComponentsInstaller : MonoBehaviour, IInstaller
15
+ {
16
+ [SerializeField]
17
+ [Tooltip(
18
+ "When enabled, relational fields within the scene are assigned immediately after the container is built."
19
+ )]
20
+ private bool _assignSceneOnInitialize = true;
21
+
22
+ [SerializeField]
23
+ [Tooltip("Include inactive GameObjects when scanning for relational assignments.")]
24
+ private bool _includeInactiveObjects = true;
25
+
26
+ [SerializeField]
27
+ [Tooltip(
28
+ "Registers an additive scene listener that hydrates relational fields for scenes loaded additively."
29
+ )]
30
+ private bool _listenForAdditiveScenes = true;
31
+
32
+ [SerializeField]
33
+ [Tooltip(
34
+ "Use a single-pass scan when assigning relational fields for improved performance."
35
+ )]
36
+ private bool _useSinglePassScan = true;
37
+
38
+ /// <inheritdoc />
39
+ public void InstallBindings(ContainerBuilder builder)
40
+ {
41
+ AttributeMetadataCache cacheInstance = AttributeMetadataCache.Instance;
42
+ if (cacheInstance != null && !builder.HasBinding(typeof(AttributeMetadataCache)))
43
+ {
44
+ builder.AddSingleton(cacheInstance, typeof(AttributeMetadataCache));
45
+ }
46
+
47
+ if (!builder.HasBinding(typeof(IRelationalComponentAssigner)))
48
+ {
49
+ builder.AddSingleton(
50
+ typeof(RelationalComponentAssigner),
51
+ typeof(IRelationalComponentAssigner),
52
+ typeof(RelationalComponentAssigner)
53
+ );
54
+ }
55
+
56
+ RelationalSceneAssignmentOptions options = new(
57
+ _includeInactiveObjects,
58
+ _useSinglePassScan
59
+ );
60
+ if (!builder.HasBinding(typeof(RelationalSceneAssignmentOptions)))
61
+ {
62
+ builder.AddSingleton(options);
63
+ }
64
+
65
+ Scene installerScene = gameObject.scene;
66
+
67
+ builder.OnContainerBuilt += container =>
68
+ {
69
+ RelationalSceneAssignmentOptions assignmentOptions = options;
70
+ if (container.HasBinding<RelationalSceneAssignmentOptions>())
71
+ {
72
+ assignmentOptions = container.Resolve<RelationalSceneAssignmentOptions>();
73
+ }
74
+
75
+ RelationalReflexSceneBootstrapper.ConfigureScene(
76
+ container,
77
+ installerScene,
78
+ assignmentOptions,
79
+ _assignSceneOnInitialize,
80
+ _listenForAdditiveScenes
81
+ );
82
+ };
83
+ }
84
+ }
85
+ }
86
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 21805c62e51942dc9d0763c610f7809f
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,316 @@
1
+ #if REFLEX_PRESENT
2
+ namespace WallstopStudios.UnityHelpers.Integrations.Reflex
3
+ {
4
+ using System;
5
+ using System.Collections.Generic;
6
+ using global::Reflex.Core;
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
+ internal static class RelationalReflexSceneBootstrapper
14
+ {
15
+ public static void ConfigureScene(
16
+ Container container,
17
+ Scene scene,
18
+ RelationalSceneAssignmentOptions options,
19
+ bool assignSceneOnInitialize,
20
+ bool listenForAdditiveScenes
21
+ )
22
+ {
23
+ if (container == null)
24
+ {
25
+ return;
26
+ }
27
+
28
+ IRelationalComponentAssigner assigner = ResolveAssigner(container);
29
+ if (assigner == null)
30
+ {
31
+ return;
32
+ }
33
+
34
+ AttributeMetadataCache metadataCache = ResolveMetadata(container);
35
+
36
+ if (assignSceneOnInitialize)
37
+ {
38
+ AssignScene(scene, assigner, metadataCache, options);
39
+ }
40
+
41
+ if (listenForAdditiveScenes)
42
+ {
43
+ RelationalSceneLoadListener listener = new(assigner, metadataCache, options, scene);
44
+ listener.Activate();
45
+ }
46
+ }
47
+
48
+ internal static void AssignScene(
49
+ Scene scene,
50
+ IRelationalComponentAssigner assigner,
51
+ AttributeMetadataCache metadataCache,
52
+ RelationalSceneAssignmentOptions options
53
+ )
54
+ {
55
+ if (!scene.IsValid() || assigner == null)
56
+ {
57
+ return;
58
+ }
59
+
60
+ AttributeMetadataCache cache = metadataCache ?? AttributeMetadataCache.Instance;
61
+ if (cache == null)
62
+ {
63
+ AssignBySceneRoots(scene, assigner, options.IncludeInactive);
64
+ return;
65
+ }
66
+
67
+ using PooledResource<List<Type>> typeBuffer = Buffers<Type>.List.Get(
68
+ out List<Type> relationalTypes
69
+ );
70
+ cache.CollectRelationalComponentTypes(relationalTypes);
71
+
72
+ if (relationalTypes.Count == 0)
73
+ {
74
+ AssignBySceneRoots(scene, assigner, options.IncludeInactive);
75
+ return;
76
+ }
77
+
78
+ if (options.UseSinglePassScan)
79
+ {
80
+ AssignBySinglePass(scene, assigner, relationalTypes, options.IncludeInactive);
81
+ }
82
+ else
83
+ {
84
+ AssignByTypePass(scene, assigner, relationalTypes, options.IncludeInactive);
85
+ }
86
+
87
+ #if UNITY_EDITOR
88
+ if (!Application.isPlaying)
89
+ {
90
+ AssignBySceneRoots(scene, assigner, options.IncludeInactive);
91
+ UnityEditor.EditorApplication.delayCall += () =>
92
+ {
93
+ if (scene.IsValid())
94
+ {
95
+ AssignBySceneRoots(scene, assigner, options.IncludeInactive);
96
+ }
97
+ };
98
+ }
99
+ #endif
100
+ }
101
+
102
+ private static void AssignByTypePass(
103
+ Scene target,
104
+ IRelationalComponentAssigner assigner,
105
+ List<Type> relationalTypes,
106
+ bool includeInactive
107
+ )
108
+ {
109
+ using PooledResource<List<GameObject>> rootBuffer = Buffers<GameObject>.List.Get(
110
+ out List<GameObject> roots
111
+ );
112
+ target.GetRootGameObjects(roots);
113
+ if (roots.Count == 0)
114
+ {
115
+ return;
116
+ }
117
+
118
+ using PooledResource<HashSet<Type>> typeSetPool = Buffers<Type>.HashSet.Get(
119
+ out HashSet<Type> relationalSet
120
+ );
121
+ for (int i = 0; i < relationalTypes.Count; i++)
122
+ {
123
+ Type type = relationalTypes[i];
124
+ if (type != null)
125
+ {
126
+ relationalSet.Add(type);
127
+ }
128
+ }
129
+
130
+ using PooledResource<List<Component>> componentBuffer = Buffers<Component>.List.Get(
131
+ out List<Component> components
132
+ );
133
+
134
+ for (int i = 0; i < roots.Count; i++)
135
+ {
136
+ GameObject root = roots[i];
137
+ if (root == null)
138
+ {
139
+ continue;
140
+ }
141
+
142
+ root.GetComponentsInChildren(includeInactive, components);
143
+ for (int j = 0; j < components.Count; j++)
144
+ {
145
+ Component component = components[j];
146
+ if (component == null || component.gameObject.scene != target)
147
+ {
148
+ continue;
149
+ }
150
+
151
+ Type current = component.GetType();
152
+ while (current != null && typeof(Component).IsAssignableFrom(current))
153
+ {
154
+ if (relationalSet.Contains(current))
155
+ {
156
+ assigner.Assign(component);
157
+ break;
158
+ }
159
+ current = current.BaseType;
160
+ }
161
+ }
162
+
163
+ components.Clear();
164
+ }
165
+ }
166
+
167
+ private static void AssignBySinglePass(
168
+ Scene target,
169
+ IRelationalComponentAssigner assigner,
170
+ List<Type> relationalTypes,
171
+ bool includeInactive
172
+ )
173
+ {
174
+ using PooledResource<HashSet<Type>> pooledSet = Buffers<Type>.HashSet.Get(
175
+ out HashSet<Type> relationalSet
176
+ );
177
+ for (int i = 0; i < relationalTypes.Count; i++)
178
+ {
179
+ Type type = relationalTypes[i];
180
+ if (type != null)
181
+ {
182
+ relationalSet.Add(type);
183
+ }
184
+ }
185
+
186
+ Component[] allComponents = includeInactive
187
+ ? UnityEngine.Object.FindObjectsOfType<Component>(true)
188
+ : UnityEngine.Object.FindObjectsOfType<Component>(false);
189
+
190
+ for (int i = 0; i < allComponents.Length; i++)
191
+ {
192
+ Component component = allComponents[i];
193
+ if (component == null || component.gameObject.scene != target)
194
+ {
195
+ continue;
196
+ }
197
+
198
+ Type current = component.GetType();
199
+ while (current != null && typeof(Component).IsAssignableFrom(current))
200
+ {
201
+ if (relationalSet.Contains(current))
202
+ {
203
+ assigner.Assign(component);
204
+ break;
205
+ }
206
+ current = current.BaseType;
207
+ }
208
+ }
209
+ }
210
+
211
+ private static void AssignBySceneRoots(
212
+ Scene target,
213
+ IRelationalComponentAssigner assigner,
214
+ bool includeInactive
215
+ )
216
+ {
217
+ if (!target.IsValid())
218
+ {
219
+ return;
220
+ }
221
+
222
+ using PooledResource<List<GameObject>> rootBuffer = Buffers<GameObject>.List.Get(
223
+ out List<GameObject> roots
224
+ );
225
+ target.GetRootGameObjects(roots);
226
+ for (int i = 0; i < roots.Count; i++)
227
+ {
228
+ GameObject root = roots[i];
229
+ if (root == null)
230
+ {
231
+ continue;
232
+ }
233
+
234
+ assigner.AssignHierarchy(root, includeInactive);
235
+ }
236
+ }
237
+
238
+ private static IRelationalComponentAssigner ResolveAssigner(Container container)
239
+ {
240
+ if (container.HasBinding<IRelationalComponentAssigner>())
241
+ {
242
+ return container.Resolve<IRelationalComponentAssigner>();
243
+ }
244
+ return null;
245
+ }
246
+
247
+ private static AttributeMetadataCache ResolveMetadata(Container container)
248
+ {
249
+ if (container.HasBinding<AttributeMetadataCache>())
250
+ {
251
+ return container.Resolve<AttributeMetadataCache>();
252
+ }
253
+ return AttributeMetadataCache.Instance;
254
+ }
255
+
256
+ private sealed class RelationalSceneLoadListener
257
+ {
258
+ private readonly IRelationalComponentAssigner _assigner;
259
+ private readonly AttributeMetadataCache _metadataCache;
260
+ private readonly RelationalSceneAssignmentOptions _options;
261
+ private readonly Scene _originScene;
262
+ private bool _isActive;
263
+
264
+ public RelationalSceneLoadListener(
265
+ IRelationalComponentAssigner assigner,
266
+ AttributeMetadataCache metadataCache,
267
+ RelationalSceneAssignmentOptions options,
268
+ Scene originScene
269
+ )
270
+ {
271
+ _assigner = assigner;
272
+ _metadataCache = metadataCache;
273
+ _options = options;
274
+ _originScene = originScene;
275
+ }
276
+
277
+ public void Activate()
278
+ {
279
+ if (_isActive)
280
+ {
281
+ return;
282
+ }
283
+
284
+ SceneManager.sceneLoaded += OnSceneLoaded;
285
+ SceneManager.sceneUnloaded += OnSceneUnloaded;
286
+ _isActive = true;
287
+ }
288
+
289
+ private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
290
+ {
291
+ if (mode != LoadSceneMode.Additive || !_isActive)
292
+ {
293
+ return;
294
+ }
295
+
296
+ AssignScene(scene, _assigner, _metadataCache, _options);
297
+ }
298
+
299
+ private void OnSceneUnloaded(Scene scene)
300
+ {
301
+ if (!_isActive)
302
+ {
303
+ return;
304
+ }
305
+
306
+ if (scene == _originScene)
307
+ {
308
+ SceneManager.sceneLoaded -= OnSceneLoaded;
309
+ SceneManager.sceneUnloaded -= OnSceneUnloaded;
310
+ _isActive = false;
311
+ }
312
+ }
313
+ }
314
+ }
315
+ }
316
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: d7743a9acbb348aeae8ae6eafc00ae4e
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,86 @@
1
+ #if REFLEX_PRESENT
2
+ namespace WallstopStudios.UnityHelpers.Integrations.Reflex
3
+ {
4
+ using System;
5
+ using WallstopStudios.UnityHelpers.Core.Helper;
6
+
7
+ /// <summary>
8
+ /// Controls how the Reflex integration performs relational component assignment across scenes.
9
+ /// </summary>
10
+ public readonly struct RelationalSceneAssignmentOptions
11
+ : IEquatable<RelationalSceneAssignmentOptions>
12
+ {
13
+ /// <summary>
14
+ /// Initializes a new instance of the <see cref="RelationalSceneAssignmentOptions"/> struct.
15
+ /// </summary>
16
+ /// <param name="includeInactive">
17
+ /// When true, relational assignment scans include inactive GameObjects. Defaults to true.
18
+ /// </param>
19
+ /// <param name="useSinglePassScan">
20
+ /// When true, performs a single-pass scan for relational types to maximize performance.
21
+ /// Defaults to true.
22
+ /// </param>
23
+ public RelationalSceneAssignmentOptions(bool includeInactive, bool useSinglePassScan = true)
24
+ {
25
+ IncludeInactive = includeInactive;
26
+ UseSinglePassScan = useSinglePassScan;
27
+ }
28
+
29
+ /// <summary>
30
+ /// Gets default options (include inactive objects, single-pass scan).
31
+ /// </summary>
32
+ public static RelationalSceneAssignmentOptions Default => new(true, true);
33
+
34
+ /// <summary>
35
+ /// Gets whether inactive GameObjects are included during scans.
36
+ /// </summary>
37
+ public bool IncludeInactive { get; }
38
+
39
+ /// <summary>
40
+ /// Gets whether to use a single-pass scan strategy.
41
+ /// </summary>
42
+ public bool UseSinglePassScan { get; }
43
+
44
+ /// <inheritdoc />
45
+ public bool Equals(RelationalSceneAssignmentOptions other)
46
+ {
47
+ return IncludeInactive == other.IncludeInactive
48
+ && UseSinglePassScan == other.UseSinglePassScan;
49
+ }
50
+
51
+ /// <inheritdoc />
52
+ public override bool Equals(object obj)
53
+ {
54
+ return obj is RelationalSceneAssignmentOptions other && Equals(other);
55
+ }
56
+
57
+ /// <inheritdoc />
58
+ public override int GetHashCode()
59
+ {
60
+ return Objects.HashCode(IncludeInactive, UseSinglePassScan);
61
+ }
62
+
63
+ /// <summary>
64
+ /// Equality operator.
65
+ /// </summary>
66
+ public static bool operator ==(
67
+ RelationalSceneAssignmentOptions left,
68
+ RelationalSceneAssignmentOptions right
69
+ )
70
+ {
71
+ return left.Equals(right);
72
+ }
73
+
74
+ /// <summary>
75
+ /// Inequality operator.
76
+ /// </summary>
77
+ public static bool operator !=(
78
+ RelationalSceneAssignmentOptions left,
79
+ RelationalSceneAssignmentOptions right
80
+ )
81
+ {
82
+ return !left.Equals(right);
83
+ }
84
+ }
85
+ }
86
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 5a36274d1b4047a2bd4fb40329223f91
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "WallstopStudios.UnityHelpers.Integration.Reflex",
3
+ "rootNamespace": "WallstopStudios.UnityHelpers.Integrations.Reflex",
4
+ "references": ["WallstopStudios.UnityHelpers", "Reflex"],
5
+ "includePlatforms": [],
6
+ "excludePlatforms": [],
7
+ "allowUnsafeCode": false,
8
+ "overrideReferences": false,
9
+ "precompiledReferences": [],
10
+ "autoReferenced": true,
11
+ "defineConstraints": ["REFLEX_PRESENT"],
12
+ "versionDefines": [
13
+ {
14
+ "name": "com.gustavopsantos.reflex",
15
+ "expression": "0.0.1",
16
+ "define": "REFLEX_PRESENT"
17
+ }
18
+ ],
19
+ "noEngineReferences": false
20
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: a97bece904584fe29a1cb15c14637610
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: ad38057b5632441999deda0a7c20a633
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -24,7 +24,7 @@ namespace WallstopStudios.UnityHelpers.Utils
24
24
  ///
25
25
  /// If multiple assets are found, a warning is logged and the first result ordered by name is returned.
26
26
  /// The editor utility “ScriptableObject Singleton Creator” automatically creates and relocates assets to
27
- /// the correct path on editor load — see EDITOR_TOOLS_GUIDE.md#scriptableobject-singleton-creator.
27
+ /// the correct path on editor load — see Docs/EDITOR_TOOLS_GUIDE.md#scriptableobject-singleton-creator.
28
28
  ///
29
29
  /// ODIN compatibility: When the <c>ODIN_INSPECTOR</c> symbol is defined, this class derives from
30
30
  /// <c>Sirenix.OdinInspector.SerializedScriptableObject</c>; otherwise it derives from <see cref="ScriptableObject"/>.