com.wallstop-studios.unity-helpers 2.0.0-rc81.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +1 -1
- package/.gitattributes +1 -1
- package/.githooks/pre-commit +31 -5
- package/.githooks/pre-push +50 -0
- package/.github/dependabot.yml +24 -2
- package/.github/scripts/check-markdown-links.ps1 +77 -0
- package/.github/scripts/check_markdown_links.py +89 -0
- package/.github/scripts/check_markdown_url_encoding.py +74 -0
- package/.github/scripts/validate_markdown_links.py +194 -0
- package/.github/workflows/csharpier-autofix.yml +152 -0
- package/.github/workflows/format-on-demand.yml +305 -0
- package/.github/workflows/lint-doc-links.yml +8 -5
- package/.github/workflows/markdown-json.yml +6 -2
- package/.github/workflows/prettier-autofix.yml +195 -0
- package/.github/workflows/update-dotnet-tools.yml +80 -0
- package/.github/workflows/yaml-format-lint.yml +41 -0
- package/.lychee.toml +4 -4
- package/.markdownlint.jsonc +21 -0
- package/.pre-commit-config.yaml +11 -3
- package/.yamllint.yaml +31 -0
- package/AGENTS.md +5 -1
- package/CHANGELOG.md +11 -0
- package/CONTRIBUTING.md +49 -0
- package/CONTRIBUTING.md.meta +7 -0
- package/EDITOR_TOOLS_GUIDE.md +4 -0
- package/Editor/AnimationEventEditor.cs +337 -160
- package/Editor/Core/Helper/AnimationEventHelpers.cs +178 -152
- package/Editor/CustomEditors/PersistentDirectoryGUI.cs +20 -11
- package/Editor/CustomEditors/TexturePlatformOverrideEntryDrawer.cs +11 -2
- package/Editor/FitTextureSizeWindow.cs +43 -19
- package/Editor/PersistentDirectorySettings.cs +64 -12
- package/Editor/PrefabChecker.cs +72 -5
- package/Editor/Sprites/AnimationCopier.cs +132 -56
- package/Editor/Sprites/AnimationCreator.cs +63 -22
- package/Editor/Sprites/AnimationViewerWindow.cs +42 -6
- package/Editor/Sprites/TexturePlatformNameHelper.cs +50 -39
- package/Editor/Sprites/TextureResizerWizard.cs +23 -1
- package/Editor/Sprites/TextureSettingsApplierWindow.cs +148 -85
- package/Editor/Tools/ImageBlurTool.cs +81 -10
- package/Editor/Utils/EditorUi.cs +1 -1
- package/Editor/Utils/ScriptableObjectSingletonCreator.cs +1 -1
- package/GETTING_STARTED.md +40 -56
- package/RANDOM_PERFORMANCE.md +12 -12
- package/README.md +395 -2407
- package/RELATIONAL_COMPONENTS.md +92 -83
- package/Runtime/AssemblyInfo.cs +2 -0
- package/Runtime/Core/Attributes/NotNullAttribute.cs +1 -3
- package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +50 -5
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +0 -1
- package/Runtime/Core/Extension/RandomExtensions.cs +68 -0
- package/Runtime/Core/Extension/WallstopStudiosLogger.cs +16 -0
- package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -1
- package/Runtime/Core/Helper/ReflectionHelpers.cs +21 -10
- package/Runtime/Core/Helper/SpriteHelpers.cs +3 -1
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +45 -1
- package/Runtime/Core/Serialization/JsonConverters/GameObjectConverter.cs +13 -5
- package/Runtime/Core/Serialization/JsonConverters/ResolutionConverter.cs +1 -1
- package/Runtime/Core/Serialization/JsonConverters/TypeConverter.cs +1 -1
- package/Runtime/Core/Serialization/Serializer.cs +101 -0
- package/Runtime/Integrations/VContainer/AssemblyInfo.cs +9 -0
- package/Runtime/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Integrations/VContainer/ObjectResolverRelationalExtensions.cs +96 -0
- package/Runtime/Integrations/VContainer/RelationalComponentEntryPoint.cs +90 -10
- package/Runtime/Integrations/VContainer/RelationalComponentsBuilderExtensions.cs +13 -1
- package/Runtime/Integrations/VContainer/RelationalObjectPools.cs +114 -0
- package/Runtime/Integrations/VContainer/RelationalObjectPools.cs.meta +11 -0
- package/Runtime/Integrations/VContainer/RelationalSceneAssignmentOptions.cs +16 -4
- package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs +241 -0
- package/Runtime/Integrations/VContainer/RelationalSceneLoadListener.cs.meta +11 -0
- package/Runtime/Integrations/Zenject/AssemblyInfo.cs +9 -0
- package/Runtime/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
- package/Runtime/Integrations/Zenject/DiContainerRelationalExtensions.cs +69 -2
- package/Runtime/Integrations/Zenject/RelationalComponentSceneInitializer.cs +89 -12
- package/Runtime/Integrations/Zenject/RelationalComponentsInstaller.cs +23 -1
- package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs +44 -0
- package/Runtime/Integrations/Zenject/RelationalMemoryPools.cs.meta +11 -0
- package/Runtime/Integrations/Zenject/RelationalSceneAssignmentOptions.cs +16 -10
- package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs +243 -0
- package/Runtime/Integrations/Zenject/RelationalSceneLoadListener.cs.meta +11 -0
- package/Runtime/Tags/AttributeMetadataCache.cs +1 -4
- package/Runtime/Utils/Buffers.cs +4 -4
- package/Runtime/Utils/ScriptableObjectSingleton.cs +0 -1
- package/Runtime/Utils/SetTextureImportData.cs +3 -1
- package/Runtime/Utils/TextureScale.cs +10 -2
- package/Runtime/Visuals/UGUI/EnhancedImage.cs +6 -0
- package/Runtime/Visuals/UIToolkit/LayeredImage.cs +4 -1
- package/SERIALIZATION.md +15 -0
- package/SPATIAL_TREE_2D_PERFORMANCE.md +85 -82
- package/SPATIAL_TREE_3D_PERFORMANCE.md +94 -91
- package/Samples~/DI - VContainer/README.md +232 -51
- package/Samples~/DI - VContainer/Scripts/GameLifetimeScope.cs +22 -4
- package/Samples~/DI - VContainer/Scripts/RelationalConsumer.cs +5 -2
- package/Samples~/DI - VContainer/Scripts/Spawner.cs +113 -4
- package/Samples~/DI - Zenject/README.md +217 -53
- package/Samples~/DI - Zenject/Scripts/RelationalConsumer.cs +3 -0
- package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs +37 -0
- package/Samples~/DI - Zenject/Scripts/RelationalConsumerPool.cs.meta +12 -0
- package/Samples~/DI - Zenject/Scripts/SpawnerZenject.cs +74 -3
- package/Samples~/Random - PRNG/README.md +2 -1
- package/Samples~/Relational Components - Basic/README.md +3 -1
- package/Samples~/Serialization - JSON/README.md +2 -1
- package/Samples~/Spatial Structures - 2D and 3D/README.md +2 -1
- package/Samples~/UGUI - EnhancedImage/README.md +2 -1
- package/Samples~/UI Toolkit - MultiFile Selector (Editor)/README.md +2 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/Tests/Editor/Attributes/AnimationEventHelpersTests.cs +16 -0
- package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +3 -3
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +6 -2
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +170 -0
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs.meta +11 -0
- package/Tests/Editor/Integrations/VContainer/WallstopStudios.UnityHelpers.Tests.Editor.VContainer.asmdef +2 -1
- package/Tests/Editor/Integrations/Zenject/WallstopStudios.UnityHelpers.Tests.Editor.Zenject.asmdef +3 -2
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +131 -0
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs.meta +11 -0
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +6 -2
- package/Tests/Editor/PersistentDirectorySettingsTests.cs +59 -0
- package/Tests/Editor/PersistentDirectorySettingsTests.cs.meta +11 -0
- package/Tests/Editor/PrefabCheckerReportTests.cs +32 -0
- package/Tests/Editor/PrefabCheckerReportTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +64 -0
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +1 -1
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +38 -0
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs.meta +11 -0
- package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +1 -1
- package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +12 -12
- package/Tests/Editor/Sprites/SpriteCropperTests.cs +9 -9
- package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +3 -3
- package/Tests/Editor/Sprites/TexturePlatformNameHelperTests.cs +18 -0
- package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +5 -5
- package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +3 -3
- package/Tests/Editor/Sprites/TextureSettingsApplierWizardAdditionalTests.cs +4 -4
- package/Tests/Editor/Sprites/TextureSettingsApplierWizardTests.cs +4 -4
- package/Tests/Editor/Tools/ImageBlurToolTests.cs +22 -110
- package/Tests/Editor/Utils/CommonTestBase.cs +43 -1
- package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +5 -5
- package/Tests/Editor/Windows/FitTextureSizeWindowTests.cs +66 -74
- package/Tests/Runtime/Attributes/RelationalComponentInitializerTests.cs +4 -15
- package/Tests/Runtime/DataStructures/SpatialTree3DBoundsConsistencyTests.cs +29 -29
- package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +259 -218
- package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +86 -0
- package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +255 -227
- package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +5 -0
- package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +3 -0
- package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs +30 -0
- package/Tests/Runtime/Serialization/JsonConverterAdditionalTests.cs.meta +11 -0
- package/Tests/Runtime/Serialization/JsonConverterTests.cs +8 -12
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +16 -5
- package/Tests/Runtime/Serialization/SerializerAdditionalTests.cs +12 -0
- package/Tests/Runtime/Serialization/SerializerFileIoTests.cs +105 -0
- package/Tests/Runtime/Serialization/SerializerFileIoTests.cs.meta +11 -0
- package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs +247 -0
- package/Tests/Runtime/Serialization/UnityEngineObjectJsonTests.cs.meta +11 -0
- package/Tests/Runtime/TestUtils/CommonTestBase.cs +88 -0
- package/Tests/Runtime/Utils/CoroutineHandlerTests.cs +1 -1
- package/Tests/Runtime/Utils/LZMAComprehensiveTests.cs +1 -1
- package/Tests/Runtime/Utils/LZMATests.cs +1 -1
- package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +1 -1
- package/Tests/Runtime/Visuals/EnhancedImageTests.cs +25 -56
- package/Tests/Runtime/Visuals/VisualsTestHelpers.cs +1 -8
- package/package-lock.json.meta +7 -0
- package/package.json +8 -4
- package/scripts/check-eol.ps1 +4 -5
- package/scripts/lint-tests.ps1 +156 -0
- package/scripts/lint-tests.ps1.meta +7 -0
- package/scripts/normalize-eol.ps1 +6 -9
- package/.github/workflows/csharpier.yml +0 -135
|
@@ -277,6 +277,10 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
277
277
|
None = 0,
|
|
278
278
|
|
|
279
279
|
/// <summary>Legacy .NET BinaryFormatter. Trusted/ephemeral data only.</summary>
|
|
280
|
+
[Obsolete(
|
|
281
|
+
"BinaryFormatter is obsolete and unsafe for untrusted data. "
|
|
282
|
+
+ "Prefer Json or Protobuf for new code."
|
|
283
|
+
)]
|
|
280
284
|
SystemBinary = 1,
|
|
281
285
|
|
|
282
286
|
/// <summary>protobuf-net compact binary. Best for networking and high-performance.</summary>
|
|
@@ -608,7 +612,9 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
608
612
|
{
|
|
609
613
|
switch (serializationType)
|
|
610
614
|
{
|
|
615
|
+
#pragma warning disable CS0618 // Type or member is obsolete
|
|
611
616
|
case SerializationType.SystemBinary:
|
|
617
|
+
#pragma warning restore CS0618 // Type or member is obsolete
|
|
612
618
|
{
|
|
613
619
|
return BinaryDeserialize<T>(serialized);
|
|
614
620
|
}
|
|
@@ -650,7 +656,9 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
650
656
|
{
|
|
651
657
|
switch (serializationType)
|
|
652
658
|
{
|
|
659
|
+
#pragma warning disable CS0618 // Type or member is obsolete
|
|
653
660
|
case SerializationType.SystemBinary:
|
|
661
|
+
#pragma warning restore CS0618 // Type or member is obsolete
|
|
654
662
|
{
|
|
655
663
|
return BinarySerialize(instance);
|
|
656
664
|
}
|
|
@@ -689,7 +697,9 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
689
697
|
{
|
|
690
698
|
switch (serializationType)
|
|
691
699
|
{
|
|
700
|
+
#pragma warning disable CS0618 // Type or member is obsolete
|
|
692
701
|
case SerializationType.SystemBinary:
|
|
702
|
+
#pragma warning restore CS0618 // Type or member is obsolete
|
|
693
703
|
{
|
|
694
704
|
return BinarySerialize(instance, ref buffer);
|
|
695
705
|
}
|
|
@@ -1494,6 +1504,35 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
1494
1504
|
return JsonDeserialize<T>(settingsAsBytes);
|
|
1495
1505
|
}
|
|
1496
1506
|
|
|
1507
|
+
/// <summary>
|
|
1508
|
+
/// Asynchronously reads JSON with cancellation.
|
|
1509
|
+
/// </summary>
|
|
1510
|
+
public static async Task<T> ReadFromJsonFileAsync<T>(
|
|
1511
|
+
string path,
|
|
1512
|
+
System.Threading.CancellationToken cancellationToken
|
|
1513
|
+
)
|
|
1514
|
+
{
|
|
1515
|
+
using FileStream fs = new(
|
|
1516
|
+
path,
|
|
1517
|
+
FileMode.Open,
|
|
1518
|
+
FileAccess.Read,
|
|
1519
|
+
FileShare.Read,
|
|
1520
|
+
4096,
|
|
1521
|
+
useAsync: true
|
|
1522
|
+
);
|
|
1523
|
+
using Utils.PooledResource<PooledBufferStream> lease = PooledBufferStream.Rent(
|
|
1524
|
+
out PooledBufferStream stream
|
|
1525
|
+
);
|
|
1526
|
+
byte[] buffer = new byte[8192];
|
|
1527
|
+
int read;
|
|
1528
|
+
while ((read = await fs.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
|
|
1529
|
+
{
|
|
1530
|
+
stream.Write(buffer, 0, read);
|
|
1531
|
+
}
|
|
1532
|
+
ArraySegment<byte> seg = stream.GetWrittenSegment();
|
|
1533
|
+
return JsonDeserialize<T>(seg.Array.AsSpan(0, seg.Count).ToArray());
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1497
1536
|
/// <summary>
|
|
1498
1537
|
/// Writes an instance to a JSON file (UTF‑8).
|
|
1499
1538
|
/// </summary>
|
|
@@ -1520,6 +1559,29 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
1520
1559
|
await File.WriteAllTextAsync(path, jsonAsText);
|
|
1521
1560
|
}
|
|
1522
1561
|
|
|
1562
|
+
/// <summary>
|
|
1563
|
+
/// Asynchronously writes an instance to a JSON file (UTF‑8) with cancellation.
|
|
1564
|
+
/// </summary>
|
|
1565
|
+
public static async Task WriteToJsonFileAsync<T>(
|
|
1566
|
+
T input,
|
|
1567
|
+
string path,
|
|
1568
|
+
bool pretty,
|
|
1569
|
+
System.Threading.CancellationToken cancellationToken
|
|
1570
|
+
)
|
|
1571
|
+
{
|
|
1572
|
+
string jsonAsText = JsonStringify(input, pretty);
|
|
1573
|
+
byte[] bytes = SerializerEncoding.Encoding.GetBytes(jsonAsText);
|
|
1574
|
+
using FileStream fs = new(
|
|
1575
|
+
path,
|
|
1576
|
+
FileMode.Create,
|
|
1577
|
+
FileAccess.Write,
|
|
1578
|
+
FileShare.None,
|
|
1579
|
+
4096,
|
|
1580
|
+
useAsync: true
|
|
1581
|
+
);
|
|
1582
|
+
await fs.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1523
1585
|
/// <summary>
|
|
1524
1586
|
/// Writes an instance to a JSON file (UTF‑8) using the provided <paramref name="options"/>.
|
|
1525
1587
|
/// </summary>
|
|
@@ -1549,6 +1611,45 @@ namespace WallstopStudios.UnityHelpers.Core.Serialization
|
|
|
1549
1611
|
string jsonAsText = JsonStringify(input, options);
|
|
1550
1612
|
await File.WriteAllTextAsync(path, jsonAsText);
|
|
1551
1613
|
}
|
|
1614
|
+
|
|
1615
|
+
/// <summary>
|
|
1616
|
+
/// Attempts to read JSON into an instance, returns false if file missing or invalid.
|
|
1617
|
+
/// </summary>
|
|
1618
|
+
public static bool TryReadFromJsonFile<T>(string path, out T value)
|
|
1619
|
+
{
|
|
1620
|
+
try
|
|
1621
|
+
{
|
|
1622
|
+
if (!File.Exists(path))
|
|
1623
|
+
{
|
|
1624
|
+
value = default;
|
|
1625
|
+
return false;
|
|
1626
|
+
}
|
|
1627
|
+
string json = File.ReadAllText(path);
|
|
1628
|
+
value = JsonDeserialize<T>(json);
|
|
1629
|
+
return true;
|
|
1630
|
+
}
|
|
1631
|
+
catch
|
|
1632
|
+
{
|
|
1633
|
+
value = default;
|
|
1634
|
+
return false;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/// <summary>
|
|
1639
|
+
/// Attempts to write JSON to a file, returns false on failure.
|
|
1640
|
+
/// </summary>
|
|
1641
|
+
public static bool TryWriteToJsonFile<T>(T input, string path, bool pretty = true)
|
|
1642
|
+
{
|
|
1643
|
+
try
|
|
1644
|
+
{
|
|
1645
|
+
WriteToJsonFile(input, path, pretty);
|
|
1646
|
+
return true;
|
|
1647
|
+
}
|
|
1648
|
+
catch
|
|
1649
|
+
{
|
|
1650
|
+
return false;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1552
1653
|
}
|
|
1553
1654
|
|
|
1554
1655
|
// Internal pooled, growable write stream backed by ArrayPool<byte> to reduce allocations
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
using System.Runtime.CompilerServices;
|
|
2
|
+
|
|
3
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor")]
|
|
4
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime")]
|
|
5
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Editor")]
|
|
6
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.Zenject")]
|
|
7
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Runtime.VContainer")]
|
|
8
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.VContainer")]
|
|
9
|
+
[assembly: InternalsVisibleTo("WallstopStudios.UnityHelpers.Tests.Editor.Zenject")]
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#if VCONTAINER_PRESENT
|
|
2
2
|
namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
3
3
|
{
|
|
4
|
+
using System;
|
|
4
5
|
using System.Collections.Generic;
|
|
5
6
|
using global::VContainer;
|
|
7
|
+
using global::VContainer.Unity;
|
|
6
8
|
using UnityEngine;
|
|
7
9
|
using WallstopStudios.UnityHelpers.Core.Attributes;
|
|
8
10
|
using WallstopStudios.UnityHelpers.Utils;
|
|
@@ -56,6 +58,27 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
56
58
|
/// </example>
|
|
57
59
|
public static class ObjectResolverRelationalExtensions
|
|
58
60
|
{
|
|
61
|
+
/// <summary>
|
|
62
|
+
/// Injects <paramref name="component"/> with VContainer and assigns its relational fields.
|
|
63
|
+
/// </summary>
|
|
64
|
+
/// <typeparam name="T">The component type.</typeparam>
|
|
65
|
+
/// <param name="resolver">The VContainer object resolver.</param>
|
|
66
|
+
/// <param name="component">The component instance to inject and hydrate.</param>
|
|
67
|
+
/// <returns>The same component instance.</returns>
|
|
68
|
+
public static T InjectWithRelations<T>(this IObjectResolver resolver, T component)
|
|
69
|
+
where T : Component
|
|
70
|
+
{
|
|
71
|
+
if (component == null)
|
|
72
|
+
{
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Use Inject for compatibility with VContainer 1.16.x
|
|
77
|
+
resolver?.Inject(component);
|
|
78
|
+
resolver.AssignRelationalComponents(component);
|
|
79
|
+
return component;
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
/// <summary>
|
|
60
83
|
/// Assigns all relational fields on a component using the container's registered
|
|
61
84
|
/// <see cref="IRelationalComponentAssigner"/> if present, with a safe fallback to the
|
|
@@ -167,6 +190,79 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
167
190
|
return component;
|
|
168
191
|
}
|
|
169
192
|
|
|
193
|
+
/// <summary>
|
|
194
|
+
/// Instantiates a prefab that has component <typeparamref name="T"/> on the root, injects it
|
|
195
|
+
/// using VContainer and assigns relational fields.
|
|
196
|
+
/// </summary>
|
|
197
|
+
/// <typeparam name="T">Component type on the prefab root.</typeparam>
|
|
198
|
+
/// <param name="resolver">The VContainer object resolver.</param>
|
|
199
|
+
/// <param name="prefab">Prefab that contains <typeparamref name="T"/>.</param>
|
|
200
|
+
/// <param name="parent">Optional parent transform for the new instance.</param>
|
|
201
|
+
/// <returns>The instantiated component with DI and relational fields populated.</returns>
|
|
202
|
+
public static T InstantiateComponentWithRelations<T>(
|
|
203
|
+
this IObjectResolver resolver,
|
|
204
|
+
T prefab,
|
|
205
|
+
Transform parent = null
|
|
206
|
+
)
|
|
207
|
+
where T : Component
|
|
208
|
+
{
|
|
209
|
+
if (prefab == null)
|
|
210
|
+
{
|
|
211
|
+
throw new ArgumentNullException(nameof(prefab));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
T instance = UnityEngine.Object.Instantiate(prefab, parent);
|
|
215
|
+
return resolver.BuildUpWithRelations(instance);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// <summary>
|
|
219
|
+
/// Instantiates a GameObject prefab, injects its hierarchy with VContainer, then assigns
|
|
220
|
+
/// relational fields for all components beneath the root.
|
|
221
|
+
/// </summary>
|
|
222
|
+
/// <param name="resolver">The VContainer object resolver.</param>
|
|
223
|
+
/// <param name="prefab">GameObject prefab to instantiate.</param>
|
|
224
|
+
/// <param name="parent">Optional parent transform.</param>
|
|
225
|
+
/// <param name="includeInactiveChildren">Whether to include inactive children when assigning.</param>
|
|
226
|
+
/// <returns>The instantiated GameObject.</returns>
|
|
227
|
+
public static GameObject InstantiateGameObjectWithRelations(
|
|
228
|
+
this IObjectResolver resolver,
|
|
229
|
+
GameObject prefab,
|
|
230
|
+
Transform parent = null,
|
|
231
|
+
bool includeInactiveChildren = true
|
|
232
|
+
)
|
|
233
|
+
{
|
|
234
|
+
if (prefab == null)
|
|
235
|
+
{
|
|
236
|
+
throw new ArgumentNullException(nameof(prefab));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
GameObject instance = UnityEngine.Object.Instantiate(prefab, parent);
|
|
240
|
+
resolver.InjectGameObjectWithRelations(instance, includeInactiveChildren);
|
|
241
|
+
return instance;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// <summary>
|
|
245
|
+
/// Injects all components on <paramref name="root"/> and its children, then assigns
|
|
246
|
+
/// relational fields for the hierarchy.
|
|
247
|
+
/// </summary>
|
|
248
|
+
/// <param name="resolver">The VContainer object resolver.</param>
|
|
249
|
+
/// <param name="root">Root GameObject to inject and hydrate.</param>
|
|
250
|
+
/// <param name="includeInactiveChildren">Whether to include inactive children when assigning.</param>
|
|
251
|
+
public static void InjectGameObjectWithRelations(
|
|
252
|
+
this IObjectResolver resolver,
|
|
253
|
+
GameObject root,
|
|
254
|
+
bool includeInactiveChildren = true
|
|
255
|
+
)
|
|
256
|
+
{
|
|
257
|
+
if (root == null)
|
|
258
|
+
{
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
resolver?.InjectGameObject(root);
|
|
263
|
+
resolver.AssignRelationalHierarchy(root, includeInactiveChildren);
|
|
264
|
+
}
|
|
265
|
+
|
|
170
266
|
private static bool TryResolveAssigner(
|
|
171
267
|
IObjectResolver resolver,
|
|
172
268
|
out IRelationalComponentAssigner assigner
|
|
@@ -9,6 +9,7 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
9
9
|
using WallstopStudios.UnityHelpers.Core.Attributes;
|
|
10
10
|
using WallstopStudios.UnityHelpers.Tags;
|
|
11
11
|
using WallstopStudios.UnityHelpers.Utils;
|
|
12
|
+
using Object = UnityEngine.Object;
|
|
12
13
|
|
|
13
14
|
/// <summary>
|
|
14
15
|
/// Entry point registered with VContainer to hydrate relational attributes once the container is
|
|
@@ -71,38 +72,117 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
71
72
|
|
|
72
73
|
if (relationalTypes.Count == 0)
|
|
73
74
|
{
|
|
75
|
+
// Fallback: scan all components once and assign when type has relational fields
|
|
76
|
+
bool includeInactiveAll = _options.IncludeInactive;
|
|
77
|
+
Component[] allComponents = includeInactiveAll
|
|
78
|
+
? Object.FindObjectsOfType<Component>(true)
|
|
79
|
+
: Object.FindObjectsOfType<Component>(false);
|
|
80
|
+
|
|
81
|
+
for (int i = 0; i < allComponents.Length; i++)
|
|
82
|
+
{
|
|
83
|
+
Component c = allComponents[i];
|
|
84
|
+
if (c == null || c.gameObject.scene != SceneManager.GetActiveScene())
|
|
85
|
+
{
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (_assigner.HasRelationalAssignments(c.GetType()))
|
|
90
|
+
{
|
|
91
|
+
_assigner.Assign(c);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
74
94
|
return;
|
|
75
95
|
}
|
|
76
96
|
|
|
77
97
|
bool includeInactive = _options.IncludeInactive;
|
|
78
98
|
Scene activeScene = SceneManager.GetActiveScene();
|
|
79
99
|
|
|
80
|
-
|
|
100
|
+
if (_options.UseSinglePassScan)
|
|
81
101
|
{
|
|
82
|
-
|
|
102
|
+
using PooledResource<HashSet<Type>> pooledSet = Buffers<Type>.HashSet.Get(
|
|
103
|
+
out HashSet<Type> relationalSet
|
|
104
|
+
);
|
|
105
|
+
for (int i = 0; i < relationalTypes.Count; i++)
|
|
83
106
|
{
|
|
84
|
-
|
|
107
|
+
Type t = relationalTypes[i];
|
|
108
|
+
if (t != null)
|
|
109
|
+
{
|
|
110
|
+
relationalSet.Add(t);
|
|
111
|
+
}
|
|
85
112
|
}
|
|
86
113
|
|
|
87
|
-
|
|
88
|
-
?
|
|
89
|
-
:
|
|
114
|
+
Component[] all = includeInactive
|
|
115
|
+
? Object.FindObjectsOfType<Component>(true)
|
|
116
|
+
: Object.FindObjectsOfType<Component>(false);
|
|
90
117
|
|
|
91
|
-
|
|
118
|
+
for (int i = 0; i < all.Length; i++)
|
|
92
119
|
{
|
|
93
|
-
|
|
120
|
+
Component c = all[i];
|
|
121
|
+
if (c == null || c.gameObject.scene != activeScene)
|
|
94
122
|
{
|
|
95
123
|
continue;
|
|
96
124
|
}
|
|
97
125
|
|
|
98
|
-
|
|
126
|
+
Type t = c.GetType();
|
|
127
|
+
while (t != null && typeof(Component).IsAssignableFrom(t))
|
|
128
|
+
{
|
|
129
|
+
if (relationalSet.Contains(t))
|
|
130
|
+
{
|
|
131
|
+
_assigner.Assign(c);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
t = t.BaseType;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else
|
|
139
|
+
{
|
|
140
|
+
foreach (Type componentType in relationalTypes)
|
|
141
|
+
{
|
|
142
|
+
if (componentType == null)
|
|
99
143
|
{
|
|
100
144
|
continue;
|
|
101
145
|
}
|
|
102
146
|
|
|
103
|
-
|
|
147
|
+
Object[] located = includeInactive
|
|
148
|
+
? Object.FindObjectsOfType(componentType, true)
|
|
149
|
+
: Object.FindObjectsOfType(componentType, false);
|
|
150
|
+
|
|
151
|
+
foreach (Object t in located)
|
|
152
|
+
{
|
|
153
|
+
if (t is not Component component)
|
|
154
|
+
{
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (component.gameObject.scene != activeScene)
|
|
159
|
+
{
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_assigner.Assign(component);
|
|
164
|
+
}
|
|
104
165
|
}
|
|
105
166
|
}
|
|
167
|
+
|
|
168
|
+
// Safety net in Editor/tests: also walk scene roots to catch any missed
|
|
169
|
+
#if UNITY_EDITOR
|
|
170
|
+
if (!Application.isPlaying)
|
|
171
|
+
{
|
|
172
|
+
using PooledResource<List<GameObject>> rootGoBuffer = Buffers<GameObject>.List.Get(
|
|
173
|
+
out List<GameObject> roots
|
|
174
|
+
);
|
|
175
|
+
activeScene.GetRootGameObjects(roots);
|
|
176
|
+
foreach (GameObject root in roots)
|
|
177
|
+
{
|
|
178
|
+
if (root == null)
|
|
179
|
+
{
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
_assigner.AssignHierarchy(root, includeInactive);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
#endif
|
|
106
186
|
}
|
|
107
187
|
}
|
|
108
188
|
}
|
|
@@ -14,6 +14,8 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
14
14
|
/// <remarks>
|
|
15
15
|
/// Registers the shared <see cref="IRelationalComponentAssigner"/> as a singleton and schedules a
|
|
16
16
|
/// scene-wide entry point that hydrates all relational fields after the container has been built.
|
|
17
|
+
/// Optionally wires <see cref="RelationalSceneLoadListener"/> so future additive scenes receive
|
|
18
|
+
/// the same treatment.
|
|
17
19
|
/// </remarks>
|
|
18
20
|
public static class RelationalComponentsBuilderExtensions
|
|
19
21
|
{
|
|
@@ -26,6 +28,10 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
26
28
|
/// Optional settings to control how the active scene is scanned (e.g., include inactive
|
|
27
29
|
/// objects). When <c>null</c>, <see cref="RelationalSceneAssignmentOptions.Default"/> is used.
|
|
28
30
|
/// </param>
|
|
31
|
+
/// <param name="enableAdditiveSceneListener">
|
|
32
|
+
/// When true registers <see cref="RelationalSceneLoadListener"/> so additively loaded scenes
|
|
33
|
+
/// are hydrated with the same options. Disable when you manage additive scenes manually.
|
|
34
|
+
/// </param>
|
|
29
35
|
/// <example>
|
|
30
36
|
/// <code>
|
|
31
37
|
/// using VContainer;
|
|
@@ -49,7 +55,8 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
49
55
|
/// </example>
|
|
50
56
|
public static void RegisterRelationalComponents(
|
|
51
57
|
this IContainerBuilder builder,
|
|
52
|
-
RelationalSceneAssignmentOptions? options = null
|
|
58
|
+
RelationalSceneAssignmentOptions? options = null,
|
|
59
|
+
bool enableAdditiveSceneListener = true
|
|
53
60
|
)
|
|
54
61
|
{
|
|
55
62
|
if (builder == null)
|
|
@@ -72,6 +79,11 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
72
79
|
.AsSelf();
|
|
73
80
|
|
|
74
81
|
builder.RegisterEntryPoint<RelationalComponentEntryPoint>().WithParameter(resolved);
|
|
82
|
+
|
|
83
|
+
if (enableAdditiveSceneListener)
|
|
84
|
+
{
|
|
85
|
+
builder.RegisterEntryPoint<RelationalSceneLoadListener>().WithParameter(resolved);
|
|
86
|
+
}
|
|
75
87
|
}
|
|
76
88
|
}
|
|
77
89
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#if VCONTAINER_PRESENT
|
|
2
|
+
namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
3
|
+
{
|
|
4
|
+
using System;
|
|
5
|
+
using global::VContainer;
|
|
6
|
+
using global::VContainer.Unity;
|
|
7
|
+
using UnityEngine;
|
|
8
|
+
using UnityEngine.Pool;
|
|
9
|
+
|
|
10
|
+
/// <summary>
|
|
11
|
+
/// Helpers for creating UnityEngine.Pool object pools plus extensions that hydrate pooled items
|
|
12
|
+
/// through VContainer when you rent them via <see cref="GetWithRelations{T}(ObjectPool{T},IObjectResolver)"/>.
|
|
13
|
+
/// </summary>
|
|
14
|
+
public static class RelationalObjectPools
|
|
15
|
+
{
|
|
16
|
+
/// <summary>
|
|
17
|
+
/// Creates a component pool to be combined with <see cref="GetWithRelations{T}(ObjectPool{T},IObjectResolver)"/>
|
|
18
|
+
/// so items are injected and hydrated on rental time.
|
|
19
|
+
/// </summary>
|
|
20
|
+
public static ObjectPool<T> CreatePoolWithRelations<T>(
|
|
21
|
+
Func<T> createFunc,
|
|
22
|
+
Action<T> actionOnGet = null,
|
|
23
|
+
Action<T> actionOnRelease = null,
|
|
24
|
+
Action<T> actionOnDestroy = null,
|
|
25
|
+
bool collectionCheck = true,
|
|
26
|
+
int defaultCapacity = 10,
|
|
27
|
+
int maxSize = 10000
|
|
28
|
+
)
|
|
29
|
+
where T : Component
|
|
30
|
+
{
|
|
31
|
+
if (createFunc == null)
|
|
32
|
+
{
|
|
33
|
+
throw new ArgumentNullException(nameof(createFunc));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return new ObjectPool<T>(
|
|
37
|
+
createFunc,
|
|
38
|
+
actionOnGet: actionOnGet,
|
|
39
|
+
actionOnRelease: actionOnRelease,
|
|
40
|
+
actionOnDestroy: actionOnDestroy,
|
|
41
|
+
collectionCheck: collectionCheck,
|
|
42
|
+
defaultCapacity: defaultCapacity,
|
|
43
|
+
maxSize: maxSize
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// <summary>
|
|
48
|
+
/// Creates a GameObject pool to be combined with
|
|
49
|
+
/// <see cref="GetWithRelations(ObjectPool{GameObject},IObjectResolver)"/> so hierarchies are
|
|
50
|
+
/// injected and hydrated on rental time.
|
|
51
|
+
/// </summary>
|
|
52
|
+
public static ObjectPool<GameObject> CreateGameObjectPoolWithRelations(
|
|
53
|
+
GameObject prefab,
|
|
54
|
+
Transform parent = null,
|
|
55
|
+
Action<GameObject> actionOnGet = null,
|
|
56
|
+
Action<GameObject> actionOnRelease = null,
|
|
57
|
+
Action<GameObject> actionOnDestroy = null,
|
|
58
|
+
bool collectionCheck = true,
|
|
59
|
+
int defaultCapacity = 10,
|
|
60
|
+
int maxSize = 10000
|
|
61
|
+
)
|
|
62
|
+
{
|
|
63
|
+
if (prefab == null)
|
|
64
|
+
{
|
|
65
|
+
throw new ArgumentNullException(nameof(prefab));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Func<GameObject> create = () => UnityEngine.Object.Instantiate(prefab, parent);
|
|
69
|
+
|
|
70
|
+
return new ObjectPool<GameObject>(
|
|
71
|
+
create,
|
|
72
|
+
actionOnGet: actionOnGet,
|
|
73
|
+
actionOnRelease: actionOnRelease,
|
|
74
|
+
actionOnDestroy: actionOnDestroy,
|
|
75
|
+
collectionCheck: collectionCheck,
|
|
76
|
+
defaultCapacity: defaultCapacity,
|
|
77
|
+
maxSize: maxSize
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// <summary>
|
|
82
|
+
/// Rents an item from the pool, injects and assigns relational fields.
|
|
83
|
+
/// </summary>
|
|
84
|
+
public static T GetWithRelations<T>(this ObjectPool<T> pool, IObjectResolver resolver)
|
|
85
|
+
where T : Component
|
|
86
|
+
{
|
|
87
|
+
T item = pool.Get();
|
|
88
|
+
if (item != null)
|
|
89
|
+
{
|
|
90
|
+
resolver?.Inject(item);
|
|
91
|
+
resolver.AssignRelationalComponents(item);
|
|
92
|
+
}
|
|
93
|
+
return item;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// <summary>
|
|
97
|
+
/// Rents a GameObject from the pool, injects the hierarchy and assigns relational fields.
|
|
98
|
+
/// </summary>
|
|
99
|
+
public static GameObject GetWithRelations(
|
|
100
|
+
this ObjectPool<GameObject> pool,
|
|
101
|
+
IObjectResolver resolver
|
|
102
|
+
)
|
|
103
|
+
{
|
|
104
|
+
GameObject go = pool.Get();
|
|
105
|
+
if (go != null)
|
|
106
|
+
{
|
|
107
|
+
resolver?.InjectGameObject(go);
|
|
108
|
+
resolver.AssignRelationalHierarchy(go, includeInactiveChildren: true);
|
|
109
|
+
}
|
|
110
|
+
return go;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
#endif
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
3
3
|
{
|
|
4
4
|
using System;
|
|
5
|
+
using WallstopStudios.UnityHelpers.Core.Helper;
|
|
5
6
|
|
|
6
7
|
/// <summary>
|
|
7
8
|
/// Controls how the VContainer integration applies relational component assignment.
|
|
@@ -24,25 +25,36 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
24
25
|
/// When true the entry point will scan inactive scene objects so that relational fields are
|
|
25
26
|
/// populated even for disabled hierarchies. Defaults to <c>true</c>.
|
|
26
27
|
/// </param>
|
|
27
|
-
|
|
28
|
+
/// <param name="useSinglePassScan">
|
|
29
|
+
/// When true uses a single-pass scene scan for performance (recommended). Defaults to
|
|
30
|
+
/// <c>true</c>.
|
|
31
|
+
/// </param>
|
|
32
|
+
public RelationalSceneAssignmentOptions(bool includeInactive, bool useSinglePassScan = true)
|
|
28
33
|
{
|
|
29
34
|
IncludeInactive = includeInactive;
|
|
35
|
+
UseSinglePassScan = useSinglePassScan;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
/// <summary>
|
|
33
39
|
/// Options used when no explicit configuration is supplied.
|
|
34
40
|
/// </summary>
|
|
35
|
-
public static RelationalSceneAssignmentOptions Default => new(
|
|
41
|
+
public static RelationalSceneAssignmentOptions Default => new(true, true);
|
|
36
42
|
|
|
37
43
|
/// <summary>
|
|
38
44
|
/// Gets whether inactive GameObjects should be included when scanning the scene.
|
|
39
45
|
/// </summary>
|
|
40
46
|
public bool IncludeInactive { get; }
|
|
41
47
|
|
|
48
|
+
/// <summary>
|
|
49
|
+
/// Gets whether to use a single-pass scene scan to locate relational components.
|
|
50
|
+
/// </summary>
|
|
51
|
+
public bool UseSinglePassScan { get; }
|
|
52
|
+
|
|
42
53
|
/// <inheritdoc />
|
|
43
54
|
public bool Equals(RelationalSceneAssignmentOptions other)
|
|
44
55
|
{
|
|
45
|
-
return IncludeInactive == other.IncludeInactive
|
|
56
|
+
return IncludeInactive == other.IncludeInactive
|
|
57
|
+
&& UseSinglePassScan == other.UseSinglePassScan;
|
|
46
58
|
}
|
|
47
59
|
|
|
48
60
|
/// <inheritdoc />
|
|
@@ -54,7 +66,7 @@ namespace WallstopStudios.UnityHelpers.Integrations.VContainer
|
|
|
54
66
|
/// <inheritdoc />
|
|
55
67
|
public override int GetHashCode()
|
|
56
68
|
{
|
|
57
|
-
return
|
|
69
|
+
return Objects.HashCode(IncludeInactive, UseSinglePassScan);
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
/// <summary>
|