From 2ff5dc720024bf56db329c89a3c5f8e067cadca8 Mon Sep 17 00:00:00 2001 From: Ashley Canning Date: Thu, 26 Oct 2023 09:57:42 +0100 Subject: [PATCH] Add unity package to SystemGroups so it can become a dependency of another package and be more easily debugged Signed-off-by: Ashley Canning --- Arch.SystemGroups/Arch.SystemGroups.asmdef | 13 + .../Builder/ArchSystemsWorldBuilder.cs | 487 +++++++++--------- .../ArchSystemsWorldBuilderExtensions.cs | 21 +- .../InitializationSystemGroup.cs | 27 +- .../DefaultSystemGroups/PhysicsSystemGroup.cs | 27 +- .../PostPhysicsSystemGroup.cs | 27 +- .../PostRenderingSystemGroup.cs | 27 +- .../PresentationSystemGroup.cs | 27 +- .../SimulationSystemGroup.cs | 27 +- .../DefaultSystemGroups/SystemGroupsUtils.cs | 29 +- Arch.SystemGroups/ExecutionNode.cs | 143 ++--- Arch.SystemGroups/Groups/CustomGroupBase.cs | 253 ++++----- Arch.SystemGroups/Groups/DefaultGroup.cs | 91 ++-- .../Groups/GroupNotFoundException.cs | 33 +- .../ISystemGroupExceptionHandler.cs | 51 +- Arch.SystemGroups/Metadata/AttributesInfo.cs | 49 +- .../Metadata/SystemGroupAttributesInfo.cs | 57 +- .../Aggregation/ISystemGroupAggregate.cs | 77 +-- .../ISystemGroupAggregateFactory.cs | 15 +- .../OrderedSystemGroupAggregate.cs | 95 ++-- .../Aggregation/SystemGroupAggregate.cs | 71 +-- .../Aggregation/SystemGroupAggregateCache.cs | 75 +-- .../PlayerLoopHelper/DebouncedComparer.cs | 25 +- .../PlayerLoopHelper/IPlayerLoop.cs | 43 +- .../PlayerLoopHelper/PlayerLoopAddMode.cs | 25 +- .../PlayerLoopHelper/PlayerLoopHelper.cs | 169 +++--- .../PlayerLoopHelper/UnityPlayerLoop.cs | 245 ++++----- Arch.SystemGroups/PlayerLoopSystem.cs | 33 +- Arch.SystemGroups/SystemGroup.cs | 203 ++++---- Arch.SystemGroups/SystemGroupWorld.cs | 69 +-- .../SystemsDependencies/ArchSystemsSorter.cs | 113 ++-- .../DisconnectedDependenciesFoundException.cs | 43 +- .../DisconnectedDependenciesInfo.cs | 65 +-- Arch.SystemGroups/SystemsUpdateOrder.cs | 93 ++-- .../Throttling/ISystemGroupThrottler.cs | 57 +- .../Throttling/ThrottlingEnabledAttribute.cs | 17 +- Arch.SystemGroups/UnityBridge/TimeProvider.cs | 133 ++--- Arch.SystemGroups/UpdateInGroupAttribute.cs | 47 +- Arch.SystemGroups/package.json | 28 + 39 files changed, 1606 insertions(+), 1524 deletions(-) create mode 100644 Arch.SystemGroups/Arch.SystemGroups.asmdef create mode 100644 Arch.SystemGroups/package.json diff --git a/Arch.SystemGroups/Arch.SystemGroups.asmdef b/Arch.SystemGroups/Arch.SystemGroups.asmdef new file mode 100644 index 0000000..3af8ccb --- /dev/null +++ b/Arch.SystemGroups/Arch.SystemGroups.asmdef @@ -0,0 +1,13 @@ +{ + "name": "Arch.SystemGroups", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Arch.SystemGroups/Builder/ArchSystemsWorldBuilder.cs b/Arch.SystemGroups/Builder/ArchSystemsWorldBuilder.cs index 17c244f..8a9c6b8 100644 --- a/Arch.SystemGroups/Builder/ArchSystemsWorldBuilder.cs +++ b/Arch.SystemGroups/Builder/ArchSystemsWorldBuilder.cs @@ -5,284 +5,289 @@ using Arch.SystemGroups.Throttling; using UnityEngine.Pool; -namespace Arch.SystemGroups; - -/// -/// The builder of systems attached to the Unity Player Loop -/// -/// -public readonly struct ArchSystemsWorldBuilder +namespace Arch.SystemGroups { - private struct GroupInfo - { - public Dictionary> Systems; - public Dictionary> Edges; - public List DisconnectedDependencies; - } - - private readonly Dictionary _groupsInfo; - private readonly Dictionary> _customGroups; - - private readonly IPlayerLoop _playerLoop; - - private readonly IFixedUpdateBasedSystemGroupThrottler _fixedUpdateBasedSystemGroupThrottler; - private readonly IUpdateBasedSystemGroupThrottler _updateBasedSystemGroupThrottler; - private readonly ISystemGroupExceptionHandler _exceptionHandler; - /// - /// Create a systems builder for the given world + /// The builder of systems attached to the Unity Player Loop /// - /// ECS World (Normally "Arch.Core.World") - /// Throttler for all Fixed Update based Systems - /// Throttler for all Update based Systems - /// Exception handler - public ArchSystemsWorldBuilder(T world, - IFixedUpdateBasedSystemGroupThrottler fixedUpdateBasedSystemGroupThrottler = null, - IUpdateBasedSystemGroupThrottler updateBasedSystemGroupThrottler = null, - ISystemGroupExceptionHandler exceptionHandler = null) : this(world, - UnityPlayerLoop.Instance, fixedUpdateBasedSystemGroupThrottler, updateBasedSystemGroupThrottler, - exceptionHandler) + /// + public readonly struct ArchSystemsWorldBuilder { - } + private struct GroupInfo + { + public Dictionary> Systems; + public Dictionary> Edges; + public List DisconnectedDependencies; + } - internal ArchSystemsWorldBuilder(T world, IPlayerLoop playerLoop, - IFixedUpdateBasedSystemGroupThrottler fixedUpdateBasedSystemGroupThrottler = null, - IUpdateBasedSystemGroupThrottler updateBasedSystemGroupThrottler = null, - ISystemGroupExceptionHandler exceptionHandler = null) - { - World = world; - _playerLoop = playerLoop; - _fixedUpdateBasedSystemGroupThrottler = fixedUpdateBasedSystemGroupThrottler; - _updateBasedSystemGroupThrottler = updateBasedSystemGroupThrottler; - _exceptionHandler = exceptionHandler; - - _groupsInfo = DictionaryPool.Get(); - _customGroups = DictionaryPool>.Get(); - } + private readonly Dictionary _groupsInfo; + private readonly Dictionary> _customGroups; + + private readonly IPlayerLoop _playerLoop; + + private readonly IFixedUpdateBasedSystemGroupThrottler _fixedUpdateBasedSystemGroupThrottler; + private readonly IUpdateBasedSystemGroupThrottler _updateBasedSystemGroupThrottler; + private readonly ISystemGroupExceptionHandler _exceptionHandler; + + /// + /// Create a systems builder for the given world + /// + /// ECS World (Normally "Arch.Core.World") + /// Throttler for all Fixed Update based Systems + /// Throttler for all Update based Systems + /// Exception handler + public ArchSystemsWorldBuilder(T world, + IFixedUpdateBasedSystemGroupThrottler fixedUpdateBasedSystemGroupThrottler = null, + IUpdateBasedSystemGroupThrottler updateBasedSystemGroupThrottler = null, + ISystemGroupExceptionHandler exceptionHandler = null) : this(world, + UnityPlayerLoop.Instance, fixedUpdateBasedSystemGroupThrottler, updateBasedSystemGroupThrottler, + exceptionHandler) + { + } - /// - /// Current World - /// - public T World { get; } + internal ArchSystemsWorldBuilder(T world, IPlayerLoop playerLoop, + IFixedUpdateBasedSystemGroupThrottler fixedUpdateBasedSystemGroupThrottler = null, + IUpdateBasedSystemGroupThrottler updateBasedSystemGroupThrottler = null, + ISystemGroupExceptionHandler exceptionHandler = null) + { + World = world; + _playerLoop = playerLoop; + _fixedUpdateBasedSystemGroupThrottler = fixedUpdateBasedSystemGroupThrottler; + _updateBasedSystemGroupThrottler = updateBasedSystemGroupThrottler; + _exceptionHandler = exceptionHandler; + + _groupsInfo = DictionaryPool.Get(); + _customGroups = DictionaryPool>.Get(); + } - /// - /// Creates Groups Automatically - /// - public ArchSystemsWorldBuilder TryCreateGroup(Type updateInGroupType, - Action>> addToEdges, - Action> validateDependencies, - bool throttlingEnabled) - where TGroup : CustomGroupBase, new() - { - if (_customGroups.ContainsKey(typeof(TGroup))) - return this; + /// + /// Current World + /// + public T World { get; } + + /// + /// Creates Groups Automatically + /// + public ArchSystemsWorldBuilder TryCreateGroup(Type updateInGroupType, + Action>> addToEdges, + Action> validateDependencies, + bool throttlingEnabled) + where TGroup : CustomGroupBase, new() + { + if (_customGroups.ContainsKey(typeof(TGroup))) + return this; - var newGroup = new TGroup(); + var newGroup = new TGroup(); - _customGroups[typeof(TGroup)] = newGroup; + _customGroups[typeof(TGroup)] = newGroup; - return AddToGroup(new ExecutionNode(newGroup, throttlingEnabled), updateInGroupType, typeof(TGroup), - addToEdges, validateDependencies); - } + return AddToGroup(new ExecutionNode(newGroup, throttlingEnabled), updateInGroupType, typeof(TGroup), + addToEdges, validateDependencies); + } - /// - /// Registers a group that is not created automatically - /// - public void TryRegisterGroup(Type updateInGroupType, Action>> addToEdges, - Action> validateDependencies, - bool throttlingEnabled) - where TGroup : CustomGroupBase - { - // Thr group should be injected in advance - if (!_customGroups.TryGetValue(typeof(TGroup), out var customGroup)) - throw new GroupNotFoundException(typeof(TGroup)); + /// + /// Registers a group that is not created automatically + /// + public void TryRegisterGroup(Type updateInGroupType, Action>> addToEdges, + Action> validateDependencies, + bool throttlingEnabled) + where TGroup : CustomGroupBase + { + // Thr group should be injected in advance + if (!_customGroups.TryGetValue(typeof(TGroup), out var customGroup)) + throw new GroupNotFoundException(typeof(TGroup)); - AddToGroup(new ExecutionNode(customGroup, throttlingEnabled), updateInGroupType, typeof(TGroup), - addToEdges, validateDependencies, false); - } + AddToGroup(new ExecutionNode(customGroup, throttlingEnabled), updateInGroupType, typeof(TGroup), + addToEdges, validateDependencies, false); + } - /// - /// Used by auto-generated code - /// - public ArchSystemsWorldBuilder AddToGroup(ISystem system, Type updateInGroupType, Type systemType, - Action>> addToEdges, Action> validateDependencies, - bool throttlingEnabled, bool assertGroupExists = true) - { - return AddToGroup(new ExecutionNode(system, throttlingEnabled), updateInGroupType, systemType, - addToEdges, - validateDependencies, - assertGroupExists); - } + /// + /// Used by auto-generated code + /// + public ArchSystemsWorldBuilder AddToGroup(ISystem system, Type updateInGroupType, Type systemType, + Action>> addToEdges, + Action> validateDependencies, + bool throttlingEnabled, bool assertGroupExists = true) + { + return AddToGroup(new ExecutionNode(system, throttlingEnabled), updateInGroupType, systemType, + addToEdges, + validateDependencies, + assertGroupExists); + } - private ArchSystemsWorldBuilder AddToGroup(ExecutionNode node, Type updateInGroupType, Type systemType, - Action>> addToEdges, Action> validateDependencies, - bool assertGroupExists = true) - { - if (!_groupsInfo.TryGetValue(updateInGroupType, out var group)) - _groupsInfo[updateInGroupType] = group = new GroupInfo + private ArchSystemsWorldBuilder AddToGroup(ExecutionNode node, Type updateInGroupType, Type systemType, + Action>> addToEdges, + Action> validateDependencies, + bool assertGroupExists = true) + { + if (!_groupsInfo.TryGetValue(updateInGroupType, out var group)) + _groupsInfo[updateInGroupType] = group = new GroupInfo + { + Systems = DictionaryPool>.Get(), + Edges = DictionaryPool>.Get(), + DisconnectedDependencies = ListPool.Get() + }; + + if (group.Systems.ContainsKey(systemType)) { - Systems = DictionaryPool>.Get(), - Edges = DictionaryPool>.Get(), - DisconnectedDependencies = ListPool.Get() - }; + if (assertGroupExists) + throw new InvalidOperationException( + $"System {systemType} is already added to the group {updateInGroupType}."); + return this; + } + + group.Systems[systemType] = node; + addToEdges(group.Edges); + validateDependencies(group.DisconnectedDependencies); - if (group.Systems.ContainsKey(systemType)) - { - if (assertGroupExists) - throw new InvalidOperationException( - $"System {systemType} is already added to the group {updateInGroupType}."); return this; } - group.Systems[systemType] = node; - addToEdges(group.Edges); - validateDependencies(group.DisconnectedDependencies); - - return this; - } + internal void AddCustomGroup(TGroup customGroup) where TGroup : CustomGroupBase + { + _customGroups.Add(typeof(TGroup), customGroup); + } - internal void AddCustomGroup(TGroup customGroup) where TGroup : CustomGroupBase - { - _customGroups.Add(typeof(TGroup), customGroup); - } + /// + /// Finalize the builder and create a systems world + /// + public SystemGroupWorld Finish() + { + return Finish(SystemGroupAggregate.Factory.Instance, default); + } - /// - /// Finalize the builder and create a systems world - /// - public SystemGroupWorld Finish() - { - return Finish(SystemGroupAggregate.Factory.Instance, default); - } + /// + /// Finalize the builder and create a systems world according to the custom aggregation mechanism + /// + /// factory for custom aggregation + /// data for custom aggregation + /// Type of aggregation data + /// + public SystemGroupWorld Finish(ISystemGroupAggregate.IFactory aggregateFactory, + TAggregationData aggregationData) + { + var initializationSystemGroup = InitializationSystemGroup.Empty; + var simulationSystemGroup = SimulationSystemGroup.Empty; + var presentationSystemGroup = PresentationSystemGroup.Empty; + var postRenderingSystemGroup = PostRenderingSystemGroup.Empty; + var physicsSystemGroup = PhysicsSystemGroup.Empty; + var postPhysicsSystemGroup = PostPhysicsSystemGroup.Empty; + + // detect detached dependencies + var disconnectedDependencies = ListPool.Get(); + + CreateSystemGroup(ref initializationSystemGroup, CreateInitializationSystemGroup, disconnectedDependencies); + CreateSystemGroup(ref simulationSystemGroup, CreateSimulationSystemGroup, disconnectedDependencies); + CreateSystemGroup(ref presentationSystemGroup, CreatePresentationSystemGroup, disconnectedDependencies); + CreateSystemGroup(ref postRenderingSystemGroup, CreatePostRenderingSystemGroup, disconnectedDependencies); + CreateSystemGroup(ref physicsSystemGroup, CreatePhysicsSystemGroup, disconnectedDependencies); + CreateSystemGroup(ref postPhysicsSystemGroup, CreatePostPhysicsSystemGroup, disconnectedDependencies); + + // All remaining groups are empty at the moment + // Fill them with systems + + foreach (var (systemType, groupInfo) in _groupsInfo) + { + if (!_customGroups.TryGetValue(systemType, out var customGroup)) + throw new GroupNotFoundException(systemType); + + // validate dependencies + if (groupInfo.DisconnectedDependencies.Count > 0) + disconnectedDependencies.Add(new DisconnectedDependenciesInfo(systemType, + new List(groupInfo.DisconnectedDependencies))); + + customGroup.SetSystems(ArchSystemsSorter.SortSystems(groupInfo.Systems, groupInfo.Edges)); + CleanUpGroupInfo(in groupInfo); + } + + // At this point we gather all information about wrong dependencies + if (disconnectedDependencies.Count > 0) + throw new DisconnectedDependenciesFoundException(disconnectedDependencies); + + ListPool.Release(disconnectedDependencies); + DictionaryPool.Release(_groupsInfo); + DictionaryPool>.Release(_customGroups); + + _playerLoop.AppendWorldToCurrentPlayerLoop( + aggregateFactory, + aggregationData, + initializationSystemGroup, + simulationSystemGroup, + presentationSystemGroup, + postRenderingSystemGroup, + physicsSystemGroup, + postPhysicsSystemGroup + ); + + return new SystemGroupWorld(new SystemGroup[] + { + initializationSystemGroup, + simulationSystemGroup, + presentationSystemGroup, + postRenderingSystemGroup, + physicsSystemGroup, + postPhysicsSystemGroup + }, _playerLoop, aggregateFactory); + } - /// - /// Finalize the builder and create a systems world according to the custom aggregation mechanism - /// - /// factory for custom aggregation - /// data for custom aggregation - /// Type of aggregation data - /// - public SystemGroupWorld Finish(ISystemGroupAggregate.IFactory aggregateFactory, - TAggregationData aggregationData) - { - var initializationSystemGroup = InitializationSystemGroup.Empty; - var simulationSystemGroup = SimulationSystemGroup.Empty; - var presentationSystemGroup = PresentationSystemGroup.Empty; - var postRenderingSystemGroup = PostRenderingSystemGroup.Empty; - var physicsSystemGroup = PhysicsSystemGroup.Empty; - var postPhysicsSystemGroup = PostPhysicsSystemGroup.Empty; - - // detect detached dependencies - var disconnectedDependencies = ListPool.Get(); - - CreateSystemGroup(ref initializationSystemGroup, CreateInitializationSystemGroup, disconnectedDependencies); - CreateSystemGroup(ref simulationSystemGroup, CreateSimulationSystemGroup, disconnectedDependencies); - CreateSystemGroup(ref presentationSystemGroup, CreatePresentationSystemGroup, disconnectedDependencies); - CreateSystemGroup(ref postRenderingSystemGroup, CreatePostRenderingSystemGroup, disconnectedDependencies); - CreateSystemGroup(ref physicsSystemGroup, CreatePhysicsSystemGroup, disconnectedDependencies); - CreateSystemGroup(ref postPhysicsSystemGroup, CreatePostPhysicsSystemGroup, disconnectedDependencies); - - // All remaining groups are empty at the moment - // Fill them with systems - - foreach (var (systemType, groupInfo) in _groupsInfo) + private PostPhysicsSystemGroup CreatePostPhysicsSystemGroup(List> list) { - if (!_customGroups.TryGetValue(systemType, out var customGroup)) - throw new GroupNotFoundException(systemType); - - // validate dependencies - if (groupInfo.DisconnectedDependencies.Count > 0) - disconnectedDependencies.Add(new DisconnectedDependenciesInfo(systemType, new List(groupInfo.DisconnectedDependencies))); - - customGroup.SetSystems(ArchSystemsSorter.SortSystems(groupInfo.Systems, groupInfo.Edges)); - CleanUpGroupInfo(in groupInfo); + return new PostPhysicsSystemGroup(list, _fixedUpdateBasedSystemGroupThrottler, _exceptionHandler); } - // At this point we gather all information about wrong dependencies - if (disconnectedDependencies.Count > 0) - throw new DisconnectedDependenciesFoundException(disconnectedDependencies); - - ListPool.Release(disconnectedDependencies); - DictionaryPool.Release(_groupsInfo); - DictionaryPool>.Release(_customGroups); - - _playerLoop.AppendWorldToCurrentPlayerLoop( - aggregateFactory, - aggregationData, - initializationSystemGroup, - simulationSystemGroup, - presentationSystemGroup, - postRenderingSystemGroup, - physicsSystemGroup, - postPhysicsSystemGroup - ); - - return new SystemGroupWorld(new SystemGroup[] + private PhysicsSystemGroup CreatePhysicsSystemGroup(List> list) { - initializationSystemGroup, - simulationSystemGroup, - presentationSystemGroup, - postRenderingSystemGroup, - physicsSystemGroup, - postPhysicsSystemGroup - }, _playerLoop, aggregateFactory); - } + return new PhysicsSystemGroup(list, _fixedUpdateBasedSystemGroupThrottler, _exceptionHandler); + } - private PostPhysicsSystemGroup CreatePostPhysicsSystemGroup(List> list) - { - return new PostPhysicsSystemGroup(list, _fixedUpdateBasedSystemGroupThrottler, _exceptionHandler); - } + private PostRenderingSystemGroup CreatePostRenderingSystemGroup(List> list) + { + return new PostRenderingSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); + } - private PhysicsSystemGroup CreatePhysicsSystemGroup(List> list) - { - return new PhysicsSystemGroup(list, _fixedUpdateBasedSystemGroupThrottler, _exceptionHandler); - } + private PresentationSystemGroup CreatePresentationSystemGroup(List> list) + { + return new PresentationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); + } - private PostRenderingSystemGroup CreatePostRenderingSystemGroup(List> list) - { - return new PostRenderingSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); - } + private SimulationSystemGroup CreateSimulationSystemGroup(List> list) + { + return new SimulationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); + } - private PresentationSystemGroup CreatePresentationSystemGroup(List> list) - { - return new PresentationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); - } + private InitializationSystemGroup CreateInitializationSystemGroup(List> list) + { + return new InitializationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); + } - private SimulationSystemGroup CreateSimulationSystemGroup(List> list) - { - return new SimulationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); - } + private void CreateSystemGroup(ref TGroup group, Func>, TGroup> constructor, + List disconnectedDependencies) + where TGroup : SystemGroup + { + if (_groupsInfo.TryGetValue(typeof(TGroup), out var groupsInfo)) + { + // validate dependencies + if (groupsInfo.DisconnectedDependencies.Count > 0) + disconnectedDependencies.Add(new DisconnectedDependenciesInfo(typeof(TGroup), + new List(groupsInfo.DisconnectedDependencies))); - private InitializationSystemGroup CreateInitializationSystemGroup(List> list) - { - return new InitializationSystemGroup(list, _updateBasedSystemGroupThrottler, _exceptionHandler); - } + group = constructor(ArchSystemsSorter.SortSystems(groupsInfo.Systems, groupsInfo.Edges)); - private void CreateSystemGroup(ref TGroup group, Func>, TGroup> constructor, - List disconnectedDependencies) - where TGroup : SystemGroup - { - if (_groupsInfo.TryGetValue(typeof(TGroup), out var groupsInfo)) - { - // validate dependencies - if (groupsInfo.DisconnectedDependencies.Count > 0) - disconnectedDependencies.Add(new DisconnectedDependenciesInfo(typeof(TGroup), new List(groupsInfo.DisconnectedDependencies))); - - group = constructor(ArchSystemsSorter.SortSystems(groupsInfo.Systems, groupsInfo.Edges)); - - CleanUpGroupInfo(in groupsInfo); - _groupsInfo.Remove(typeof(TGroup)); + CleanUpGroupInfo(in groupsInfo); + _groupsInfo.Remove(typeof(TGroup)); + } } - } - private void CleanUpGroupInfo(in GroupInfo groupInfo) - { - DictionaryPool>.Release(groupInfo.Systems); + private void CleanUpGroupInfo(in GroupInfo groupInfo) + { + DictionaryPool>.Release(groupInfo.Systems); - foreach (var (_, edges) in groupInfo.Edges) - ListPool.Release(edges); + foreach (var (_, edges) in groupInfo.Edges) + ListPool.Release(edges); - DictionaryPool>.Release(groupInfo.Edges); - ListPool.Release(groupInfo.DisconnectedDependencies); + DictionaryPool>.Release(groupInfo.Edges); + ListPool.Release(groupInfo.DisconnectedDependencies); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/Builder/ArchSystemsWorldBuilderExtensions.cs b/Arch.SystemGroups/Builder/ArchSystemsWorldBuilderExtensions.cs index 4aba55f..9ae9bc7 100644 --- a/Arch.SystemGroups/Builder/ArchSystemsWorldBuilderExtensions.cs +++ b/Arch.SystemGroups/Builder/ArchSystemsWorldBuilderExtensions.cs @@ -1,16 +1,17 @@ -namespace Arch.SystemGroups; - -/// -/// Publicly available extensions for the ArchSystemsWorldBuilder -/// -public static class ArchSystemsWorldBuilderExtensions +namespace Arch.SystemGroups { /// - /// Inject a custom group into the world. It allows to create a group with custom parameters. + /// Publicly available extensions for the ArchSystemsWorldBuilder /// - public static ref ArchSystemsWorldBuilder InjectCustomGroup(ref this ArchSystemsWorldBuilder builder, TGroup group) where TGroup : CustomGroupBase + public static class ArchSystemsWorldBuilderExtensions { - builder.AddCustomGroup(group); - return ref builder; + /// + /// Inject a custom group into the world. It allows to create a group with custom parameters. + /// + public static ref ArchSystemsWorldBuilder InjectCustomGroup(ref this ArchSystemsWorldBuilder builder, TGroup group) where TGroup : CustomGroupBase + { + builder.AddCustomGroup(group); + return ref builder; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/InitializationSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/InitializationSystemGroup.cs index af9fad1..23dd7ca 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/InitializationSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/InitializationSystemGroup.cs @@ -3,23 +3,24 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the end of the Initialization phase of the player loop -/// -public class InitializationSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal InitializationSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + /// + /// Updates at the end of the Initialization phase of the player loop + /// + public class InitializationSystemGroup : SystemGroup { - } + internal InitializationSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + { + } - internal static readonly InitializationSystemGroup Empty = new (null, null, null); + internal static readonly InitializationSystemGroup Empty = new (null, null, null); - public override void Update() - { - Update(TimeProvider.GetInfo()); - } + public override void Update() + { + Update(TimeProvider.GetInfo()); + } + } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/PhysicsSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/PhysicsSystemGroup.cs index c7b4cb2..5694654 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/PhysicsSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/PhysicsSystemGroup.cs @@ -4,22 +4,23 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the beginning of the FixedUpdate phase of the player loop -/// before all fixed updates -/// -public class PhysicsSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal PhysicsSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + /// + /// Updates at the beginning of the FixedUpdate phase of the player loop + /// before all fixed updates + /// + public class PhysicsSystemGroup : SystemGroup { - } + internal PhysicsSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + { + } - internal static readonly PhysicsSystemGroup Empty = new (null, null, null); + internal static readonly PhysicsSystemGroup Empty = new (null, null, null); - public override void Update() - { - Update(TimeProvider.GetFixedInfo()); + public override void Update() + { + Update(TimeProvider.GetFixedInfo()); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/PostPhysicsSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/PostPhysicsSystemGroup.cs index 78bd937..3798908 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/PostPhysicsSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/PostPhysicsSystemGroup.cs @@ -3,22 +3,23 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the end of the FixedUpdate phase of the player loop -/// -public class PostPhysicsSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal PostPhysicsSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, - [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + /// + /// Updates at the end of the FixedUpdate phase of the player loop + /// + public class PostPhysicsSystemGroup : SystemGroup { - } + internal PostPhysicsSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, + [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + { + } - internal static readonly PostPhysicsSystemGroup Empty = new(null, null, null); + internal static readonly PostPhysicsSystemGroup Empty = new(null, null, null); - public override void Update() - { - Update(TimeProvider.GetFixedInfo()); + public override void Update() + { + Update(TimeProvider.GetFixedInfo()); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/PostRenderingSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/PostRenderingSystemGroup.cs index 9f90758..e7d39d5 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/PostRenderingSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/PostRenderingSystemGroup.cs @@ -3,22 +3,23 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the end of the PostLateUpdate phase of the player loop. -/// -public class PostRenderingSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal PostRenderingSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, - [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + /// + /// Updates at the end of the PostLateUpdate phase of the player loop. + /// + public class PostRenderingSystemGroup : SystemGroup { - } + internal PostRenderingSystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, + [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(nodes, throttler, exceptionHandler) + { + } - internal static readonly PostRenderingSystemGroup Empty = new (null, null, null); + internal static readonly PostRenderingSystemGroup Empty = new (null, null, null); - public override void Update() - { - Update(TimeProvider.GetInfo()); + public override void Update() + { + Update(TimeProvider.GetInfo()); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/PresentationSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/PresentationSystemGroup.cs index 3a66694..415030a 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/PresentationSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/PresentationSystemGroup.cs @@ -4,22 +4,23 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the end of the PreLateUpdate phase of the player loop. -/// -public class PresentationSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal PresentationSystemGroup(List> systems, [CanBeNull] ISystemGroupThrottler throttler, - [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(systems, throttler, exceptionHandler) + /// + /// Updates at the end of the PreLateUpdate phase of the player loop. + /// + public class PresentationSystemGroup : SystemGroup { - } + internal PresentationSystemGroup(List> systems, [CanBeNull] ISystemGroupThrottler throttler, + [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(systems, throttler, exceptionHandler) + { + } - internal static readonly PresentationSystemGroup Empty = new (null, null, null); + internal static readonly PresentationSystemGroup Empty = new (null, null, null); - public override void Update() - { - Update(TimeProvider.GetInfo()); + public override void Update() + { + Update(TimeProvider.GetInfo()); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/SimulationSystemGroup.cs b/Arch.SystemGroups/DefaultSystemGroups/SimulationSystemGroup.cs index ed3e83f..7007ed0 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/SimulationSystemGroup.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/SimulationSystemGroup.cs @@ -3,22 +3,23 @@ using Arch.SystemGroups.UnityBridge; using JetBrains.Annotations; -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// Updates at the end of the Update phase of the player loop -/// -public class SimulationSystemGroup : SystemGroup +namespace Arch.SystemGroups.DefaultSystemGroups { - internal SimulationSystemGroup(List> systems, [CanBeNull] ISystemGroupThrottler throttler, - [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(systems, throttler, exceptionHandler) + /// + /// Updates at the end of the Update phase of the player loop + /// + public class SimulationSystemGroup : SystemGroup { - } + internal SimulationSystemGroup(List> systems, [CanBeNull] ISystemGroupThrottler throttler, + [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) : base(systems, throttler, exceptionHandler) + { + } - internal static readonly SimulationSystemGroup Empty = new (null, null, null); + internal static readonly SimulationSystemGroup Empty = new (null, null, null); - public override void Update() - { - Update(TimeProvider.GetInfo()); + public override void Update() + { + Update(TimeProvider.GetInfo()); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/DefaultSystemGroups/SystemGroupsUtils.cs b/Arch.SystemGroups/DefaultSystemGroups/SystemGroupsUtils.cs index 99a233c..d387edc 100644 --- a/Arch.SystemGroups/DefaultSystemGroups/SystemGroupsUtils.cs +++ b/Arch.SystemGroups/DefaultSystemGroups/SystemGroupsUtils.cs @@ -1,18 +1,19 @@ -namespace Arch.SystemGroups.DefaultSystemGroups; - -/// -/// System Groups Utility Functions -/// -public static class SystemGroupsUtils +namespace Arch.SystemGroups.DefaultSystemGroups { /// - /// The number of defined system groups: - /// - /// - /// - /// - /// - /// + /// System Groups Utility Functions /// - public const int Count = 6; + public static class SystemGroupsUtils + { + /// + /// The number of defined system groups: + /// + /// + /// + /// + /// + /// + /// + public const int Count = 6; + } } \ No newline at end of file diff --git a/Arch.SystemGroups/ExecutionNode.cs b/Arch.SystemGroups/ExecutionNode.cs index 89f9c78..1426409 100644 --- a/Arch.SystemGroups/ExecutionNode.cs +++ b/Arch.SystemGroups/ExecutionNode.cs @@ -1,96 +1,97 @@ using Arch.System; -namespace Arch.SystemGroups; - -internal readonly struct ExecutionNode +namespace Arch.SystemGroups { - public readonly bool ThrottlingEnabled; - public readonly bool IsGroup; - public readonly ISystem System; - public readonly CustomGroupBase CustomGroup; - - public ExecutionNode(ISystem system, bool throttlingEnabled) + internal readonly struct ExecutionNode { - ThrottlingEnabled = throttlingEnabled; - System = system; - CustomGroup = null; - IsGroup = false; - } + public readonly bool ThrottlingEnabled; + public readonly bool IsGroup; + public readonly ISystem System; + public readonly CustomGroupBase CustomGroup; - public ExecutionNode(CustomGroupBase customGroup, bool throttlingEnabled) - { - IsGroup = true; - ThrottlingEnabled = throttlingEnabled; - CustomGroup = customGroup; - System = null; - } - - public void Initialize() - { - if (IsGroup) + public ExecutionNode(ISystem system, bool throttlingEnabled) { - CustomGroup.Initialize(); + ThrottlingEnabled = throttlingEnabled; + System = system; + CustomGroup = null; + IsGroup = false; } - else + + public ExecutionNode(CustomGroupBase customGroup, bool throttlingEnabled) { - System.Initialize(); + IsGroup = true; + ThrottlingEnabled = throttlingEnabled; + CustomGroup = customGroup; + System = null; } - } - public void Dispose() - { - if (IsGroup) - { - CustomGroup.Dispose(); - } - else + public void Initialize() { - System.Dispose(); + if (IsGroup) + { + CustomGroup.Initialize(); + } + else + { + System.Initialize(); + } } - } - public void BeforeUpdate(in T t, bool throttle) - { - if (throttle && ThrottlingEnabled) - return; - - if (IsGroup) + public void Dispose() { - CustomGroup.BeforeUpdate(t, throttle); + if (IsGroup) + { + CustomGroup.Dispose(); + } + else + { + System.Dispose(); + } } - else - { - System.BeforeUpdate(t); - } - } - public void Update(in T t, bool throttle) - { - if (throttle && ThrottlingEnabled) - return; - - if (IsGroup) - { - CustomGroup.Update(t, throttle); - } - else + public void BeforeUpdate(in T t, bool throttle) { - System.Update(t); + if (throttle && ThrottlingEnabled) + return; + + if (IsGroup) + { + CustomGroup.BeforeUpdate(t, throttle); + } + else + { + System.BeforeUpdate(t); + } } - } - public void AfterUpdate(in T t, bool throttle) - { - if (throttle && ThrottlingEnabled) - return; - - if (IsGroup) + public void Update(in T t, bool throttle) { - CustomGroup.AfterUpdate(t, throttle); + if (throttle && ThrottlingEnabled) + return; + + if (IsGroup) + { + CustomGroup.Update(t, throttle); + } + else + { + System.Update(t); + } } - else + + public void AfterUpdate(in T t, bool throttle) { - System.AfterUpdate(t); + if (throttle && ThrottlingEnabled) + return; + + if (IsGroup) + { + CustomGroup.AfterUpdate(t, throttle); + } + else + { + System.AfterUpdate(t); + } } } } \ No newline at end of file diff --git a/Arch.SystemGroups/Groups/CustomGroupBase.cs b/Arch.SystemGroups/Groups/CustomGroupBase.cs index a0fc398..a3cac54 100644 --- a/Arch.SystemGroups/Groups/CustomGroupBase.cs +++ b/Arch.SystemGroups/Groups/CustomGroupBase.cs @@ -4,135 +4,136 @@ using Arch.SystemGroups.Metadata; using UnityEngine.Pool; -namespace Arch.SystemGroups; - -/// -/// The base class that can be used to provide custom behaviour for a group -/// -/// -public abstract class CustomGroupBase +namespace Arch.SystemGroups { /// - /// Creates an empty group - /// - protected CustomGroupBase() - { - } - - /// - /// Creates a group from the collection from which a pooled instance of the list will be created - /// - protected CustomGroupBase(IEnumerable> systems, bool throttlingEnabled) - { - Nodes = ListPool>.Get(); - AddRange(systems.Select(s => new ExecutionNode(s, throttlingEnabled))); - } - - internal List> Nodes { get; private set; } - - /// - /// Override to provide Dispose behaviour, you can use as the default implementation - /// - public abstract void Dispose(); - - /// - /// Override to provide initialization behaviour, you can use as the default - /// implementation - /// - public abstract void Initialize(); - - /// - /// Override to provide BeforeUpdate, you can use as the default implementation - /// - /// - /// Indicates that the current invocation is throttled - public abstract void BeforeUpdate(in T t, bool throttle); - - /// - /// Override to provide Update behaviour, you can use as the default implementation - /// - /// - /// Indicates that the current invocation is throttled - public abstract void Update(in T t, bool throttle); - - /// - /// Override to provide AfterUpdate behaviour, you can use as the default - /// implementation - /// - /// Indicates that the current invocation is throttled - /// - public abstract void AfterUpdate(in T t, bool throttle); - - /// - /// Adds systems to the group - /// - /// - internal void AddRange(IEnumerable> systems) - { - Nodes.AddRange(systems); - } - - internal void SetSystems(List> systems) - { - Nodes = systems; - } - - /// - /// Initialize all systems in the group - /// - protected void InitializeInternal() - { - foreach (var node in Nodes) - node.Initialize(); - } - - /// - /// Dispose all systems in the group - /// - protected void DisposeInternal() - { - foreach (var node in Nodes) - node.Dispose(); - - ListPool>.Release(Nodes); - } - - /// - /// Update all systems - /// - /// Delta time - /// Current update is throttled - protected void BeforeUpdateInternal(in T t, bool throttle) - { - for (var index = 0; index < Nodes.Count; ++index) - Nodes[index].BeforeUpdate(in t, throttle); - } - - /// - /// Update all systems + /// The base class that can be used to provide custom behaviour for a group /// - /// Delta time - /// Current update is throttled - protected void UpdateInternal(in T t, bool throttle) + /// + public abstract class CustomGroupBase { - for (var index = 0; index < Nodes.Count; ++index) - Nodes[index].Update(in t, throttle); - } - - /// - /// Update all systems - /// - /// Delta time - /// Current update is throttled - protected void AfterUpdateInternal(in T t, bool throttle) - { - for (var index = 0; index < Nodes.Count; ++index) - Nodes[index].AfterUpdate(in t, throttle); - } + /// + /// Creates an empty group + /// + protected CustomGroupBase() + { + } + + /// + /// Creates a group from the collection from which a pooled instance of the list will be created + /// + protected CustomGroupBase(IEnumerable> systems, bool throttlingEnabled) + { + Nodes = ListPool>.Get(); + AddRange(systems.Select(s => new ExecutionNode(s, throttlingEnabled))); + } + + internal List> Nodes { get; private set; } + + /// + /// Override to provide Dispose behaviour, you can use as the default implementation + /// + public abstract void Dispose(); + + /// + /// Override to provide initialization behaviour, you can use as the default + /// implementation + /// + public abstract void Initialize(); + + /// + /// Override to provide BeforeUpdate, you can use as the default implementation + /// + /// + /// Indicates that the current invocation is throttled + public abstract void BeforeUpdate(in T t, bool throttle); + + /// + /// Override to provide Update behaviour, you can use as the default implementation + /// + /// + /// Indicates that the current invocation is throttled + public abstract void Update(in T t, bool throttle); + + /// + /// Override to provide AfterUpdate behaviour, you can use as the default + /// implementation + /// + /// Indicates that the current invocation is throttled + /// + public abstract void AfterUpdate(in T t, bool throttle); + + /// + /// Adds systems to the group + /// + /// + internal void AddRange(IEnumerable> systems) + { + Nodes.AddRange(systems); + } + + internal void SetSystems(List> systems) + { + Nodes = systems; + } + + /// + /// Initialize all systems in the group + /// + protected void InitializeInternal() + { + foreach (var node in Nodes) + node.Initialize(); + } + + /// + /// Dispose all systems in the group + /// + protected void DisposeInternal() + { + foreach (var node in Nodes) + node.Dispose(); + + ListPool>.Release(Nodes); + } + + /// + /// Update all systems + /// + /// Delta time + /// Current update is throttled + protected void BeforeUpdateInternal(in T t, bool throttle) + { + for (var index = 0; index < Nodes.Count; ++index) + Nodes[index].BeforeUpdate(in t, throttle); + } + + /// + /// Update all systems + /// + /// Delta time + /// Current update is throttled + protected void UpdateInternal(in T t, bool throttle) + { + for (var index = 0; index < Nodes.Count; ++index) + Nodes[index].Update(in t, throttle); + } + + /// + /// Update all systems + /// + /// Delta time + /// Current update is throttled + protected void AfterUpdateInternal(in T t, bool throttle) + { + for (var index = 0; index < Nodes.Count; ++index) + Nodes[index].AfterUpdate(in t, throttle); + } - /// - /// The metadata of the group in an abstract form - /// - /// - protected abstract AttributesInfoBase GetMetadataInternal(); + /// + /// The metadata of the group in an abstract form + /// + /// + protected abstract AttributesInfoBase GetMetadataInternal(); + } } \ No newline at end of file diff --git a/Arch.SystemGroups/Groups/DefaultGroup.cs b/Arch.SystemGroups/Groups/DefaultGroup.cs index ef560e9..53ab734 100644 --- a/Arch.SystemGroups/Groups/DefaultGroup.cs +++ b/Arch.SystemGroups/Groups/DefaultGroup.cs @@ -1,56 +1,57 @@ -namespace Arch.SystemGroups; - -/// -/// Similar to `Arch.System.Group` but with better API that allows pooling -/// -/// -public abstract class DefaultGroup : CustomGroupBase +namespace Arch.SystemGroups { /// - /// Creates an empty group, for auto-generated code only, - /// Don't invoke it manually + /// Similar to `Arch.System.Group` but with better API that allows pooling /// - protected DefaultGroup() + /// + public abstract class DefaultGroup : CustomGroupBase { - } + /// + /// Creates an empty group, for auto-generated code only, + /// Don't invoke it manually + /// + protected DefaultGroup() + { + } - /// - /// Initialize all systems in the group - /// - public override void Initialize() - { - InitializeInternal(); - } + /// + /// Initialize all systems in the group + /// + public override void Initialize() + { + InitializeInternal(); + } - /// - /// Dispose all systems in the group - /// - public override void Dispose() - { - DisposeInternal(); - } + /// + /// Dispose all systems in the group + /// + public override void Dispose() + { + DisposeInternal(); + } - /// - /// To comply with Arch.System.ISystem - /// - public override void BeforeUpdate(in T t, bool throttle) - { - BeforeUpdateInternal(in t, throttle); - } + /// + /// To comply with Arch.System.ISystem + /// + public override void BeforeUpdate(in T t, bool throttle) + { + BeforeUpdateInternal(in t, throttle); + } - /// - /// To comply with Arch.System.ISystem - /// - public override void Update(in T t, bool throttle) - { - UpdateInternal(in t, throttle); - } + /// + /// To comply with Arch.System.ISystem + /// + public override void Update(in T t, bool throttle) + { + UpdateInternal(in t, throttle); + } - /// - /// To comply with Arch.System.ISystem - /// - public override void AfterUpdate(in T t, bool throttle) - { - AfterUpdateInternal(in t, throttle); + /// + /// To comply with Arch.System.ISystem + /// + public override void AfterUpdate(in T t, bool throttle) + { + AfterUpdateInternal(in t, throttle); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/Groups/GroupNotFoundException.cs b/Arch.SystemGroups/Groups/GroupNotFoundException.cs index 98136dd..364206b 100644 --- a/Arch.SystemGroups/Groups/GroupNotFoundException.cs +++ b/Arch.SystemGroups/Groups/GroupNotFoundException.cs @@ -1,22 +1,23 @@ using System; -namespace Arch.SystemGroups; - -/// -/// Indicates that the group was not injected into the builder -/// but there are systems included in it. -/// -public class GroupNotFoundException : Exception +namespace Arch.SystemGroups { - private readonly Type _type; - - internal GroupNotFoundException(Type type) - { - _type = type; - } - /// - /// + /// Indicates that the group was not injected into the builder + /// but there are systems included in it. /// - public override string Message => $"Group {_type} was not injected into the builder"; + public class GroupNotFoundException : Exception + { + private readonly Type _type; + + internal GroupNotFoundException(Type type) + { + _type = type; + } + + /// + /// + /// + public override string Message => $"Group {_type} was not injected into the builder"; + } } \ No newline at end of file diff --git a/Arch.SystemGroups/ISystemGroupExceptionHandler.cs b/Arch.SystemGroups/ISystemGroupExceptionHandler.cs index 90b34dd..cd5adcc 100644 --- a/Arch.SystemGroups/ISystemGroupExceptionHandler.cs +++ b/Arch.SystemGroups/ISystemGroupExceptionHandler.cs @@ -1,39 +1,40 @@ using System; -namespace Arch.SystemGroups; - -/// -/// Provides exceptions handling on the level of the -/// -public interface ISystemGroupExceptionHandler +namespace Arch.SystemGroups { /// - /// Action to tell the System Group how to behave after the exception + /// Provides exceptions handling on the level of the /// - public enum Action : byte + public interface ISystemGroupExceptionHandler { /// - /// Continue execution of the system + /// Action to tell the System Group how to behave after the exception /// - Continue, + public enum Action : byte + { + /// + /// Continue execution of the system + /// + Continue, - /// - /// Put the system group into the Error state and stops the execution - /// - Suspend, + /// + /// Put the system group into the Error state and stops the execution + /// + Suspend, + + /// + /// Dispose the system group and stops the execution + /// + Dispose + } /// - /// Dispose the system group and stops the execution + /// Handles the exception thrown by the system group, at some point the execution of the system group + /// should be suspended to prevent exceptions flood /// - Dispose + /// Exception + /// System Group Type + /// An action to tell the System Group how to behave after + Action Handle(Exception exception, Type systemGroupType); } - - /// - /// Handles the exception thrown by the system group, at some point the execution of the system group - /// should be suspended to prevent exceptions flood - /// - /// Exception - /// System Group Type - /// An action to tell the System Group how to behave after - Action Handle(Exception exception, Type systemGroupType); } \ No newline at end of file diff --git a/Arch.SystemGroups/Metadata/AttributesInfo.cs b/Arch.SystemGroups/Metadata/AttributesInfo.cs index f728f28..e81698e 100644 --- a/Arch.SystemGroups/Metadata/AttributesInfo.cs +++ b/Arch.SystemGroups/Metadata/AttributesInfo.cs @@ -1,34 +1,35 @@ using System; using System.Collections.Generic; -namespace Arch.SystemGroups.Metadata; - -/// -/// Generated attributes info, allows to avoid reflection if such access is needed -/// -public abstract class AttributesInfoBase +namespace Arch.SystemGroups.Metadata { /// - /// reflection, will be null for system groups + /// Generated attributes info, allows to avoid reflection if such access is needed /// - public abstract Type UpdateInGroup { get; } + public abstract class AttributesInfoBase + { + /// + /// reflection, will be null for system groups + /// + public abstract Type UpdateInGroup { get; } - /// - /// Metadata of the group this system belongs to, will be null for system groups - /// - public abstract AttributesInfoBase GroupMetadata { get; } + /// + /// Metadata of the group this system belongs to, will be null for system groups + /// + public abstract AttributesInfoBase GroupMetadata { get; } - /// - /// Get first attribute of type - /// - /// Type of attribute - /// Null if such attribute is not defined for the class - public abstract T GetAttribute() where T : Attribute; + /// + /// Get first attribute of type + /// + /// Type of attribute + /// Null if such attribute is not defined for the class + public abstract T GetAttribute() where T : Attribute; - /// - /// Get all attributes of type - /// - /// Type of attribute - /// An empty list if no attributes are found - public abstract IReadOnlyList GetAttributes() where T : Attribute; + /// + /// Get all attributes of type + /// + /// Type of attribute + /// An empty list if no attributes are found + public abstract IReadOnlyList GetAttributes() where T : Attribute; + } } \ No newline at end of file diff --git a/Arch.SystemGroups/Metadata/SystemGroupAttributesInfo.cs b/Arch.SystemGroups/Metadata/SystemGroupAttributesInfo.cs index 65991dd..9a4f666 100644 --- a/Arch.SystemGroups/Metadata/SystemGroupAttributesInfo.cs +++ b/Arch.SystemGroups/Metadata/SystemGroupAttributesInfo.cs @@ -1,39 +1,40 @@ using System; using System.Collections.Generic; -namespace Arch.SystemGroups.Metadata; - -/// -/// Dummy attributes info for system groups -/// -public class SystemGroupAttributesInfo : AttributesInfoBase +namespace Arch.SystemGroups.Metadata { /// - /// Instance shared between all System Groups as they provide no attributes data + /// Dummy attributes info for system groups /// - public static readonly SystemGroupAttributesInfo Instance = new(); + public class SystemGroupAttributesInfo : AttributesInfoBase + { + /// + /// Instance shared between all System Groups as they provide no attributes data + /// + public static readonly SystemGroupAttributesInfo Instance = new(); - /// - /// Returns null - /// - public override Type UpdateInGroup => null; + /// + /// Returns null + /// + public override Type UpdateInGroup => null; - /// - /// Returns null - /// - public override AttributesInfoBase GroupMetadata => null; + /// + /// Returns null + /// + public override AttributesInfoBase GroupMetadata => null; - /// - /// Returns null - /// - /// - /// - public override T GetAttribute() => null; + /// + /// Returns null + /// + /// + /// + public override T GetAttribute() => null; - /// - /// Returns an empty array - /// - /// - /// - public override IReadOnlyList GetAttributes() => Array.Empty(); + /// + /// Returns an empty array + /// + /// + /// + public override IReadOnlyList GetAttributes() => Array.Empty(); + } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregate.cs b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregate.cs index f7cdcb0..deeeead 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregate.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregate.cs @@ -1,54 +1,55 @@ using System; -namespace Arch.SystemGroups; - -/// -/// Non-generic interface for -/// -public interface ISystemGroupAggregate +namespace Arch.SystemGroups { /// - /// Count of system groups + /// Non-generic interface for /// - int Count { get; } + public interface ISystemGroupAggregate + { + /// + /// Count of system groups + /// + int Count { get; } - /// - /// This function is called from Unity Player Loop - /// - void TriggerUpdate(); + /// + /// This function is called from Unity Player Loop + /// + void TriggerUpdate(); - /// - /// Remove a system group from the aggregate - /// - void Remove(SystemGroup systemGroup); -} - -/// -/// Defines a way of aggregating system groups of the same type -/// Additional Data set per world basis -/// -public interface ISystemGroupAggregate : ISystemGroupAggregate -{ - /// - /// Add a system group to the aggregate - /// - void Add(in T data, SystemGroup systemGroup); + /// + /// Remove a system group from the aggregate + /// + void Remove(SystemGroup systemGroup); + } /// - /// Factory for SystemGroupAggregate + /// Defines a way of aggregating system groups of the same type + /// Additional Data set per world basis /// - interface IFactory : ISystemGroupAggregateFactory + public interface ISystemGroupAggregate : ISystemGroupAggregate { - ISystemGroupAggregate ISystemGroupAggregateFactory.Create(Type systemGroupType) - { - return Create(systemGroupType); - } + /// + /// Add a system group to the aggregate + /// + void Add(in T data, SystemGroup systemGroup); /// - /// Creates a new instance of SystemGroupAggregate. - /// Called once per type of SystemGroup + /// Factory for SystemGroupAggregate /// - /// - new ISystemGroupAggregate Create(Type systemGroupType); + interface IFactory : ISystemGroupAggregateFactory + { + ISystemGroupAggregate ISystemGroupAggregateFactory.Create(Type systemGroupType) + { + return Create(systemGroupType); + } + + /// + /// Creates a new instance of SystemGroupAggregate. + /// Called once per type of SystemGroup + /// + /// + new ISystemGroupAggregate Create(Type systemGroupType); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregateFactory.cs b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregateFactory.cs index 9a4484b..a5e0fe2 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregateFactory.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/ISystemGroupAggregateFactory.cs @@ -1,11 +1,12 @@ using System; -namespace Arch.SystemGroups; - -/// -/// Base interface for all system group aggregates -/// -public interface ISystemGroupAggregateFactory +namespace Arch.SystemGroups { - internal ISystemGroupAggregate Create(Type systemGroupType); + /// + /// Base interface for all system group aggregates + /// + public interface ISystemGroupAggregateFactory + { + internal ISystemGroupAggregate Create(Type systemGroupType); + } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/OrderedSystemGroupAggregate.cs b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/OrderedSystemGroupAggregate.cs index 7dee744..12ce80b 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/OrderedSystemGroupAggregate.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/OrderedSystemGroupAggregate.cs @@ -1,63 +1,64 @@ using System.Collections.Generic; -namespace Arch.SystemGroups; - -/// -/// Executes system groups in a specific order -/// -public class OrderedSystemGroupAggregate : ISystemGroupAggregate +namespace Arch.SystemGroups { - private readonly SortedList _sortedList; - /// - /// Creates a new instance of OrderedSystemGroupAggregate with the specified comparer + /// Executes system groups in a specific order /// - /// Comparer should never return 0 for different system groups as it is forbidden by . - /// Specify "debounceEqualValues" to force it - /// If True overrides the behaviour of comparer in a way that it never returns 0 - /// Initial capacity of the underlying collection - public OrderedSystemGroupAggregate(IComparer comparer, bool debounceEqualValues = false, int initialCapacity = 16) + public class OrderedSystemGroupAggregate : ISystemGroupAggregate { - if (debounceEqualValues) - comparer = new DebouncedComparer(comparer); + private readonly SortedList _sortedList; - _sortedList = new SortedList(initialCapacity, comparer); - } + /// + /// Creates a new instance of OrderedSystemGroupAggregate with the specified comparer + /// + /// Comparer should never return 0 for different system groups as it is forbidden by . + /// Specify "debounceEqualValues" to force it + /// If True overrides the behaviour of comparer in a way that it never returns 0 + /// Initial capacity of the underlying collection + public OrderedSystemGroupAggregate(IComparer comparer, bool debounceEqualValues = false, int initialCapacity = 16) + { + if (debounceEqualValues) + comparer = new DebouncedComparer(comparer); + + _sortedList = new SortedList(initialCapacity, comparer); + } - /// - /// - /// - public int Count => _sortedList.Count; + /// + /// + /// + public int Count => _sortedList.Count; - internal IList Values => _sortedList.Values; + internal IList Values => _sortedList.Values; - /// - /// - /// - public void TriggerUpdate() - { - for (var i = 0; i < _sortedList.Values.Count; i++) + /// + /// + /// + public void TriggerUpdate() { - var systemGroup = _sortedList.Values[i]; - systemGroup.Update(); + for (var i = 0; i < _sortedList.Values.Count; i++) + { + var systemGroup = _sortedList.Values[i]; + systemGroup.Update(); + } } - } - /// - /// - /// - public void Add(in T data, SystemGroup systemGroup) - { - _sortedList.Add(data, systemGroup); - } + /// + /// + /// + public void Add(in T data, SystemGroup systemGroup) + { + _sortedList.Add(data, systemGroup); + } - /// - /// - /// - public void Remove(SystemGroup systemGroup) - { - var index = _sortedList.Values.IndexOf(systemGroup); - if (index > -1) - _sortedList.RemoveAt(index); + /// + /// + /// + public void Remove(SystemGroup systemGroup) + { + var index = _sortedList.Values.IndexOf(systemGroup); + if (index > -1) + _sortedList.RemoveAt(index); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregate.cs b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregate.cs index 1f46e00..5853481 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregate.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregate.cs @@ -1,53 +1,54 @@ using System; using System.Collections.Generic; -namespace Arch.SystemGroups; - -/// -/// Contains the list of system groups of the same type -/// -internal class SystemGroupAggregate : ISystemGroupAggregate +namespace Arch.SystemGroups { - internal class Factory : ISystemGroupAggregate.IFactory + /// + /// Contains the list of system groups of the same type + /// + internal class SystemGroupAggregate : ISystemGroupAggregate { - internal static readonly Factory Instance = new(); + internal class Factory : ISystemGroupAggregate.IFactory + { + internal static readonly Factory Instance = new(); - public ISystemGroupAggregate Create(Type systemGroupType) => new SystemGroupAggregate(systemGroupType); - } + public ISystemGroupAggregate Create(Type systemGroupType) => new SystemGroupAggregate(systemGroupType); + } - private readonly List _systemGroups = new(16); + private readonly List _systemGroups = new(16); - /// - /// For debugging purpose only - /// - internal readonly Type GroupType; + /// + /// For debugging purpose only + /// + internal readonly Type GroupType; - public SystemGroupAggregate(Type groupType) - { - GroupType = groupType; - } + public SystemGroupAggregate(Type groupType) + { + GroupType = groupType; + } - public int Count => _systemGroups.Count; + public int Count => _systemGroups.Count; - public void TriggerUpdate() - { - for (var i = 0; i < _systemGroups.Count; i++) + public void TriggerUpdate() { - _systemGroups[i].Update(); + for (var i = 0; i < _systemGroups.Count; i++) + { + _systemGroups[i].Update(); + } } - } - public void Add(in None none, SystemGroup systemGroup) - { - _systemGroups.Add(systemGroup); - } + public void Add(in None none, SystemGroup systemGroup) + { + _systemGroups.Add(systemGroup); + } - public void Remove(SystemGroup systemGroup) - { - _systemGroups.Remove(systemGroup); - } + public void Remove(SystemGroup systemGroup) + { + _systemGroups.Remove(systemGroup); + } - internal struct None - { + internal struct None + { + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregateCache.cs b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregateCache.cs index f489d52..a69ffd5 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregateCache.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/Aggregation/SystemGroupAggregateCache.cs @@ -2,54 +2,55 @@ using System.Collections.Generic; using Arch.SystemGroups.DefaultSystemGroups; -namespace Arch.SystemGroups; - -/// -/// Caches the system group aggregates by type of system group, produced for each -/// -internal class SystemGroupAggregateCache +namespace Arch.SystemGroups { - private readonly Dictionary _aggregates = new (SystemGroupsUtils.Count); - - internal void GetAllAggregates(List results) where TAggregate : ISystemGroupAggregate + /// + /// Caches the system group aggregates by type of system group, produced for each + /// + internal class SystemGroupAggregateCache { - foreach (var aggregate in _aggregates.Values) - results.Add((TAggregate) aggregate); - } + private readonly Dictionary _aggregates = new (SystemGroupsUtils.Count); - public int Count => _aggregates.Count; + internal void GetAllAggregates(List results) where TAggregate : ISystemGroupAggregate + { + foreach (var aggregate in _aggregates.Values) + results.Add((TAggregate) aggregate); + } - public ISystemGroupAggregate Add(Type systemGroupType, ISystemGroupAggregate.IFactory factory) - { - var aggregate = factory.Create(systemGroupType); - _aggregates.Add(systemGroupType, aggregate); - return aggregate; - } + public int Count => _aggregates.Count; - public void Remove(IPlayerLoop playerLoop, Type systemGroupType, SystemGroup systemGroup) - { - if (_aggregates.TryGetValue(systemGroupType, out var aggregate)) + public ISystemGroupAggregate Add(Type systemGroupType, ISystemGroupAggregate.IFactory factory) { - aggregate.Remove(systemGroup); - if (aggregate.Count == 0) + var aggregate = factory.Create(systemGroupType); + _aggregates.Add(systemGroupType, aggregate); + return aggregate; + } + + public void Remove(IPlayerLoop playerLoop, Type systemGroupType, SystemGroup systemGroup) + { + if (_aggregates.TryGetValue(systemGroupType, out var aggregate)) { - _aggregates.Remove(systemGroupType); - playerLoop.RemoveAggregate(aggregate); + aggregate.Remove(systemGroup); + if (aggregate.Count == 0) + { + _aggregates.Remove(systemGroupType); + playerLoop.RemoveAggregate(aggregate); + } } - } - } + } - public bool TryGetValue(Type systemGroupType, out ISystemGroupAggregate aggregate) => _aggregates.TryGetValue(systemGroupType, out aggregate); + public bool TryGetValue(Type systemGroupType, out ISystemGroupAggregate aggregate) => _aggregates.TryGetValue(systemGroupType, out aggregate); - public bool TryGetValue(Type systemGroupType, out ISystemGroupAggregate aggregate) - { - if (_aggregates.TryGetValue(systemGroupType, out var value)) + public bool TryGetValue(Type systemGroupType, out ISystemGroupAggregate aggregate) { - aggregate = (ISystemGroupAggregate) value; - return true; - } + if (_aggregates.TryGetValue(systemGroupType, out var value)) + { + aggregate = (ISystemGroupAggregate) value; + return true; + } - aggregate = default; - return false; + aggregate = default; + return false; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/DebouncedComparer.cs b/Arch.SystemGroups/PlayerLoopHelper/DebouncedComparer.cs index 6995b5b..40fa2fc 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/DebouncedComparer.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/DebouncedComparer.cs @@ -1,19 +1,20 @@ using System.Collections.Generic; -namespace Arch.SystemGroups; - -internal class DebouncedComparer : IComparer +namespace Arch.SystemGroups { - private readonly IComparer _inner; - - public DebouncedComparer(IComparer inner) + internal class DebouncedComparer : IComparer { - _inner = inner; - } + private readonly IComparer _inner; + + public DebouncedComparer(IComparer inner) + { + _inner = inner; + } - public int Compare(T x, T y) - { - var result = _inner.Compare(x, y); - return result == 0 ? 1 : result; + public int Compare(T x, T y) + { + var result = _inner.Compare(x, y); + return result == 0 ? 1 : result; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/IPlayerLoop.cs b/Arch.SystemGroups/PlayerLoopHelper/IPlayerLoop.cs index 7d026fa..c15e5db 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/IPlayerLoop.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/IPlayerLoop.cs @@ -1,30 +1,31 @@ using System; -namespace Arch.SystemGroups; - -/// -/// Abstraction needed for Mocking or providing a custom implementation of injection into the Player Loop -/// -public interface IPlayerLoop +namespace Arch.SystemGroups { /// - /// Called before all other methods once for each world + /// Abstraction needed for Mocking or providing a custom implementation of injection into the Player Loop /// - void OnWorldStartAppending(); + public interface IPlayerLoop + { + /// + /// Called before all other methods once for each world + /// + void OnWorldStartAppending(); - /// - /// Called after all and - /// - void OnWorldEndAppending(); + /// + /// Called after all and + /// + void OnWorldEndAppending(); - /// - /// Adds an aggregate of system groups to the player loop. It is called only once upon the first mentioning of . - /// - void AddAggregate(Type systemGroupType, ISystemGroupAggregate aggregate); + /// + /// Adds an aggregate of system groups to the player loop. It is called only once upon the first mentioning of . + /// + void AddAggregate(Type systemGroupType, ISystemGroupAggregate aggregate); - /// - /// Removes the given system group from the Unity Player Loop. - /// - /// - void RemoveAggregate(ISystemGroupAggregate aggregate); + /// + /// Removes the given system group from the Unity Player Loop. + /// + /// + void RemoveAggregate(ISystemGroupAggregate aggregate); + } } diff --git a/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopAddMode.cs b/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopAddMode.cs index f46a246..c70a52e 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopAddMode.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopAddMode.cs @@ -1,17 +1,18 @@ -namespace Arch.SystemGroups; - -/// -/// Determines whether the system should be added to the beginning or the end of the step of the player loop -/// -internal enum PlayerLoopAddMode : byte +namespace Arch.SystemGroups { /// - /// Add the system to the beginning of the step + /// Determines whether the system should be added to the beginning or the end of the step of the player loop /// - Prepend, + internal enum PlayerLoopAddMode : byte + { + /// + /// Add the system to the beginning of the step + /// + Prepend, - /// - /// Add the system to the end of the step - /// - Append + /// + /// Add the system to the end of the step + /// + Append + } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopHelper.cs b/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopHelper.cs index e69ae2a..13af0fc 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopHelper.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/PlayerLoopHelper.cs @@ -1,106 +1,107 @@ using System.Collections.Generic; using Arch.SystemGroups.DefaultSystemGroups; -namespace Arch.SystemGroups; - -/// -/// Provides utilities to inject systems into the Unity Player Loop -/// -public static class PlayerLoopHelper +namespace Arch.SystemGroups { - internal static readonly Dictionary AggregatesCache = new (10); - /// - /// Retrieve all aggregates created from the given factory + /// Provides utilities to inject systems into the Unity Player Loop /// - /// - public static void GetAggregates(ISystemGroupAggregateFactory factory, List results) where TAggregate : ISystemGroupAggregate + public static class PlayerLoopHelper { - results.Clear(); - if (AggregatesCache.TryGetValue(factory, out var cache)) - cache.GetAllAggregates(results); - } + internal static readonly Dictionary AggregatesCache = new (10); - /// - /// Append ECS world to the provided player loop, supports custom system group aggregates - /// - public static void AppendWorldToCurrentPlayerLoop( - this IPlayerLoop playerLoop, - ISystemGroupAggregate.IFactory systemGroupAggregateFactory, - T data, - InitializationSystemGroup initializationSystemGroup, - SimulationSystemGroup simulationSystemGroup, - PresentationSystemGroup presentationSystemGroup, - PostRenderingSystemGroup postRenderingSystemGroup, - PhysicsSystemGroup physicsSystemGroup, - PostPhysicsSystemGroup postPhysicsSystemGroup) - { - playerLoop.OnWorldStartAppending(); + /// + /// Retrieve all aggregates created from the given factory + /// + /// + public static void GetAggregates(ISystemGroupAggregateFactory factory, List results) where TAggregate : ISystemGroupAggregate + { + results.Clear(); + if (AggregatesCache.TryGetValue(factory, out var cache)) + cache.GetAllAggregates(results); + } - playerLoop.AddSystemToPlayerLoop(data, initializationSystemGroup, systemGroupAggregateFactory); - playerLoop.AddSystemToPlayerLoop(data, simulationSystemGroup, systemGroupAggregateFactory); - playerLoop.AddSystemToPlayerLoop(data, presentationSystemGroup, systemGroupAggregateFactory); - playerLoop.AddSystemToPlayerLoop(data, postRenderingSystemGroup, systemGroupAggregateFactory); - playerLoop.AddSystemToPlayerLoop(data, physicsSystemGroup, systemGroupAggregateFactory); - playerLoop.AddSystemToPlayerLoop(data, postPhysicsSystemGroup, systemGroupAggregateFactory); + /// + /// Append ECS world to the provided player loop, supports custom system group aggregates + /// + public static void AppendWorldToCurrentPlayerLoop( + this IPlayerLoop playerLoop, + ISystemGroupAggregate.IFactory systemGroupAggregateFactory, + T data, + InitializationSystemGroup initializationSystemGroup, + SimulationSystemGroup simulationSystemGroup, + PresentationSystemGroup presentationSystemGroup, + PostRenderingSystemGroup postRenderingSystemGroup, + PhysicsSystemGroup physicsSystemGroup, + PostPhysicsSystemGroup postPhysicsSystemGroup) + { + playerLoop.OnWorldStartAppending(); + + playerLoop.AddSystemToPlayerLoop(data, initializationSystemGroup, systemGroupAggregateFactory); + playerLoop.AddSystemToPlayerLoop(data, simulationSystemGroup, systemGroupAggregateFactory); + playerLoop.AddSystemToPlayerLoop(data, presentationSystemGroup, systemGroupAggregateFactory); + playerLoop.AddSystemToPlayerLoop(data, postRenderingSystemGroup, systemGroupAggregateFactory); + playerLoop.AddSystemToPlayerLoop(data, physicsSystemGroup, systemGroupAggregateFactory); + playerLoop.AddSystemToPlayerLoop(data, postPhysicsSystemGroup, systemGroupAggregateFactory); - playerLoop.OnWorldEndAppending(); - } + playerLoop.OnWorldEndAppending(); + } - /// - /// Add an ECS system to a specific point in the Unity player loop, so that it is updated every frame. - /// The system groups are being inserted into their corresponding aggregate that is unique for each group type, - /// the execution order of the system groups inside the aggregate is not guaranteed and must be expected to be used for independent worlds - /// - /// - /// This function does not change the currently active player loop. If this behavior is desired, it's necessary - /// to call PlayerLoop.SetPlayerLoop(playerLoop) after the systems have been removed. - /// - /// Additional data per world - /// The ECS system to add to the player loop. - /// Existing player loop to modify (e.g. PlayerLoop.GetCurrentPlayerLoop()) - /// Factory of System Group Aggregates - private static void AddSystemToPlayerLoop(this IPlayerLoop playerLoop, in T data, SystemGroup systemGroup, - ISystemGroupAggregate.IFactory systemGroupAggregateFactory) - { - if (systemGroup == null) return; + /// + /// Add an ECS system to a specific point in the Unity player loop, so that it is updated every frame. + /// The system groups are being inserted into their corresponding aggregate that is unique for each group type, + /// the execution order of the system groups inside the aggregate is not guaranteed and must be expected to be used for independent worlds + /// + /// + /// This function does not change the currently active player loop. If this behavior is desired, it's necessary + /// to call PlayerLoop.SetPlayerLoop(playerLoop) after the systems have been removed. + /// + /// Additional data per world + /// The ECS system to add to the player loop. + /// Existing player loop to modify (e.g. PlayerLoop.GetCurrentPlayerLoop()) + /// Factory of System Group Aggregates + private static void AddSystemToPlayerLoop(this IPlayerLoop playerLoop, in T data, SystemGroup systemGroup, + ISystemGroupAggregate.IFactory systemGroupAggregateFactory) + { + if (systemGroup == null) return; - var systemGroupType = systemGroup.GetType(); + var systemGroupType = systemGroup.GetType(); - var aggregateCache = GetOrCreateAggregateCache(systemGroupAggregateFactory); + var aggregateCache = GetOrCreateAggregateCache(systemGroupAggregateFactory); - // If there is no aggregate yet, add it - if (!aggregateCache.TryGetValue(systemGroupType, out ISystemGroupAggregate aggregate)) - { - aggregate = aggregateCache.Add(systemGroupType, systemGroupAggregateFactory); - playerLoop.AddAggregate(systemGroupType, aggregate); - } + // If there is no aggregate yet, add it + if (!aggregateCache.TryGetValue(systemGroupType, out ISystemGroupAggregate aggregate)) + { + aggregate = aggregateCache.Add(systemGroupType, systemGroupAggregateFactory); + playerLoop.AddAggregate(systemGroupType, aggregate); + } - aggregate.Add(data, systemGroup); - } + aggregate.Add(data, systemGroup); + } - private static SystemGroupAggregateCache GetOrCreateAggregateCache(ISystemGroupAggregateFactory factory) - { - if (AggregatesCache.TryGetValue(factory, out var cache)) return cache; - AggregatesCache[factory] = cache = new SystemGroupAggregateCache(); - return cache; - } + private static SystemGroupAggregateCache GetOrCreateAggregateCache(ISystemGroupAggregateFactory factory) + { + if (AggregatesCache.TryGetValue(factory, out var cache)) return cache; + AggregatesCache[factory] = cache = new SystemGroupAggregateCache(); + return cache; + } - /// - /// Remove the system group from the player loop - /// - public static void RemoveFromPlayerLoop(this IPlayerLoop playerLoop, ISystemGroupAggregateFactory systemGroupAggregateFactory, SystemGroup systemGroup) - { - if (!AggregatesCache.TryGetValue(systemGroupAggregateFactory, out var cache)) - return; + /// + /// Remove the system group from the player loop + /// + public static void RemoveFromPlayerLoop(this IPlayerLoop playerLoop, ISystemGroupAggregateFactory systemGroupAggregateFactory, SystemGroup systemGroup) + { + if (!AggregatesCache.TryGetValue(systemGroupAggregateFactory, out var cache)) + return; - var systemGroupType = systemGroup.GetType(); - cache.Remove(playerLoop, systemGroupType, systemGroup); + var systemGroupType = systemGroup.GetType(); + cache.Remove(playerLoop, systemGroupType, systemGroup); - if (cache.Count > 0) - return; + if (cache.Count > 0) + return; - // Clean-up if there are no more system groups in the aggregate - AggregatesCache.Remove(systemGroupAggregateFactory); + // Clean-up if there are no more system groups in the aggregate + AggregatesCache.Remove(systemGroupAggregateFactory); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopHelper/UnityPlayerLoop.cs b/Arch.SystemGroups/PlayerLoopHelper/UnityPlayerLoop.cs index c1a1dda..17bdf75 100644 --- a/Arch.SystemGroups/PlayerLoopHelper/UnityPlayerLoop.cs +++ b/Arch.SystemGroups/PlayerLoopHelper/UnityPlayerLoop.cs @@ -4,165 +4,166 @@ using UnityEngine.LowLevel; using UnityEngine.PlayerLoop; -namespace Arch.SystemGroups; - -/// -/// Single-threaded wrapper over Unity's PlayerLoop -/// -public class UnityPlayerLoop : IPlayerLoop +namespace Arch.SystemGroups { /// - /// Singleton instance - /// - public static readonly UnityPlayerLoop Instance = new(); - - private PlayerLoopSystem _playerLoop; - - /// - /// + /// Single-threaded wrapper over Unity's PlayerLoop /// - public void OnWorldStartAppending() + public class UnityPlayerLoop : IPlayerLoop { - _playerLoop = PlayerLoop.GetCurrentPlayerLoop(); - } + /// + /// Singleton instance + /// + public static readonly UnityPlayerLoop Instance = new(); - /// - /// - /// - public void OnWorldEndAppending() - { - PlayerLoop.SetPlayerLoop(_playerLoop); - } + private PlayerLoopSystem _playerLoop; - /// - /// - /// - public void AddAggregate(Type systemGroupType, ISystemGroupAggregate aggregate) - { - var (playerLoopSystemType, addMode) = GetPlayerLoopSystemType(systemGroupType); + /// + /// + /// + public void OnWorldStartAppending() + { + _playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + } - if (!AppendToPlayerLoopList(systemGroupType, aggregate.TriggerUpdate, ref _playerLoop, playerLoopSystemType, - addMode)) - throw new ArgumentException($"Could not find PlayerLoopSystem with type={playerLoopSystemType}"); - } + /// + /// + /// + public void OnWorldEndAppending() + { + PlayerLoop.SetPlayerLoop(_playerLoop); + } - /// - /// - /// - /// - public void RemoveAggregate(ISystemGroupAggregate aggregate) - { - // If there are no more system groups in the aggregate remove the aggregate itself - var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + /// + /// + /// + public void AddAggregate(Type systemGroupType, ISystemGroupAggregate aggregate) + { + var (playerLoopSystemType, addMode) = GetPlayerLoopSystemType(systemGroupType); - if (RemoveFromPlayerLoopList(aggregate, ref playerLoop)) - PlayerLoop.SetPlayerLoop(playerLoop); - } + if (!AppendToPlayerLoopList(systemGroupType, aggregate.TriggerUpdate, ref _playerLoop, playerLoopSystemType, + addMode)) + throw new ArgumentException($"Could not find PlayerLoopSystem with type={playerLoopSystemType}"); + } - private static (Type, PlayerLoopAddMode) GetPlayerLoopSystemType(Type systemGroupType) - { - if (systemGroupType == typeof(InitializationSystemGroup)) - return (typeof(Initialization), PlayerLoopAddMode.Append); + /// + /// + /// + /// + public void RemoveAggregate(ISystemGroupAggregate aggregate) + { + // If there are no more system groups in the aggregate remove the aggregate itself + var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); - if (systemGroupType == typeof(SimulationSystemGroup)) - return (typeof(Update), PlayerLoopAddMode.Append); + if (RemoveFromPlayerLoopList(aggregate, ref playerLoop)) + PlayerLoop.SetPlayerLoop(playerLoop); + } - if (systemGroupType == typeof(PresentationSystemGroup)) - return (typeof(PreLateUpdate), PlayerLoopAddMode.Append); + private static (Type, PlayerLoopAddMode) GetPlayerLoopSystemType(Type systemGroupType) + { + if (systemGroupType == typeof(InitializationSystemGroup)) + return (typeof(Initialization), PlayerLoopAddMode.Append); - if (systemGroupType == typeof(PostRenderingSystemGroup)) - return (typeof(PostLateUpdate), PlayerLoopAddMode.Append); + if (systemGroupType == typeof(SimulationSystemGroup)) + return (typeof(Update), PlayerLoopAddMode.Append); - if (systemGroupType == typeof(PhysicsSystemGroup)) - return (typeof(FixedUpdate), PlayerLoopAddMode.Prepend); + if (systemGroupType == typeof(PresentationSystemGroup)) + return (typeof(PreLateUpdate), PlayerLoopAddMode.Append); - if (systemGroupType == typeof(PostPhysicsSystemGroup)) - return (typeof(FixedUpdate), PlayerLoopAddMode.Append); + if (systemGroupType == typeof(PostRenderingSystemGroup)) + return (typeof(PostLateUpdate), PlayerLoopAddMode.Append); - throw new ArgumentException($"Could not find PlayerLoopSystem for system group {systemGroupType}"); - } + if (systemGroupType == typeof(PhysicsSystemGroup)) + return (typeof(FixedUpdate), PlayerLoopAddMode.Prepend); - private static bool AppendToPlayerLoopList(Type updateType, PlayerLoopSystem.UpdateFunction updateFunction, - ref PlayerLoopSystem playerLoop, Type playerLoopSystemType, PlayerLoopAddMode addMode) - { - if (updateType == null || updateFunction == null || playerLoopSystemType == null) - return false; + if (systemGroupType == typeof(PostPhysicsSystemGroup)) + return (typeof(FixedUpdate), PlayerLoopAddMode.Append); + + throw new ArgumentException($"Could not find PlayerLoopSystem for system group {systemGroupType}"); + } - if (playerLoop.type == playerLoopSystemType) + private static bool AppendToPlayerLoopList(Type updateType, PlayerLoopSystem.UpdateFunction updateFunction, + ref PlayerLoopSystem playerLoop, Type playerLoopSystemType, PlayerLoopAddMode addMode) { - var oldListLength = playerLoop.subSystemList?.Length ?? 0; - var newSubsystemList = new PlayerLoopSystem[oldListLength + 1]; + if (updateType == null || updateFunction == null || playerLoopSystemType == null) + return false; - switch (addMode) + if (playerLoop.type == playerLoopSystemType) { - case PlayerLoopAddMode.Prepend: + var oldListLength = playerLoop.subSystemList?.Length ?? 0; + var newSubsystemList = new PlayerLoopSystem[oldListLength + 1]; + + switch (addMode) { - newSubsystemList[0] = new PlayerLoopSystem + case PlayerLoopAddMode.Prepend: { - type = updateType, - updateDelegate = updateFunction - }; - for (var i = 0; i < oldListLength; ++i) - newSubsystemList[i + 1] = playerLoop.subSystemList[i]; - break; - } - default: - { - for (var i = 0; i < oldListLength; ++i) - newSubsystemList[i] = playerLoop.subSystemList[i]; - newSubsystemList[oldListLength] = new PlayerLoopSystem + newSubsystemList[0] = new PlayerLoopSystem + { + type = updateType, + updateDelegate = updateFunction + }; + for (var i = 0; i < oldListLength; ++i) + newSubsystemList[i + 1] = playerLoop.subSystemList[i]; + break; + } + default: { - type = updateType, - updateDelegate = updateFunction - }; - break; + for (var i = 0; i < oldListLength; ++i) + newSubsystemList[i] = playerLoop.subSystemList[i]; + newSubsystemList[oldListLength] = new PlayerLoopSystem + { + type = updateType, + updateDelegate = updateFunction + }; + break; + } } + + playerLoop.subSystemList = newSubsystemList; + + return true; } - playerLoop.subSystemList = newSubsystemList; + if (playerLoop.subSystemList != null) + { + for (var i = 0; i < playerLoop.subSystemList.Length; ++i) + { + if (AppendToPlayerLoopList(updateType, updateFunction, ref playerLoop.subSystemList[i], + playerLoopSystemType, addMode)) + return true; + } + } - return true; + return false; } - if (playerLoop.subSystemList != null) + private static bool RemoveFromPlayerLoopList(ISystemGroupAggregate aggregate, ref PlayerLoopSystem playerLoop) { - for (var i = 0; i < playerLoop.subSystemList.Length; ++i) + static bool IsSystemGroup(ISystemGroupAggregate aggregate, ref PlayerLoopSystem playerLoopSystem) { - if (AppendToPlayerLoopList(updateType, updateFunction, ref playerLoop.subSystemList[i], - playerLoopSystemType, addMode)) - return true; + return playerLoopSystem.updateDelegate?.Target == aggregate; } - } - return false; - } - - private static bool RemoveFromPlayerLoopList(ISystemGroupAggregate aggregate, ref PlayerLoopSystem playerLoop) - { - static bool IsSystemGroup(ISystemGroupAggregate aggregate, ref PlayerLoopSystem playerLoopSystem) - { - return playerLoopSystem.updateDelegate?.Target == aggregate; - } + if (playerLoop.subSystemList == null || playerLoop.subSystemList.Length == 0) + return false; - if (playerLoop.subSystemList == null || playerLoop.subSystemList.Length == 0) - return false; + var result = false; + var newSubSystemList = new List(playerLoop.subSystemList.Length); + for (var i = 0; i < playerLoop.subSystemList.Length; ++i) + { + ref var playerLoopSubSystem = ref playerLoop.subSystemList[i]; + result |= RemoveFromPlayerLoopList(aggregate, ref playerLoopSubSystem); + if (!IsSystemGroup(aggregate, ref playerLoopSubSystem)) + newSubSystemList.Add(playerLoopSubSystem); + } - var result = false; - var newSubSystemList = new List(playerLoop.subSystemList.Length); - for (var i = 0; i < playerLoop.subSystemList.Length; ++i) - { - ref var playerLoopSubSystem = ref playerLoop.subSystemList[i]; - result |= RemoveFromPlayerLoopList(aggregate, ref playerLoopSubSystem); - if (!IsSystemGroup(aggregate, ref playerLoopSubSystem)) - newSubSystemList.Add(playerLoopSubSystem); - } + if (newSubSystemList.Count != playerLoop.subSystemList.Length) + { + playerLoop.subSystemList = newSubSystemList.ToArray(); + result = true; + } - if (newSubSystemList.Count != playerLoop.subSystemList.Length) - { - playerLoop.subSystemList = newSubSystemList.ToArray(); - result = true; + return result; } - - return result; } } \ No newline at end of file diff --git a/Arch.SystemGroups/PlayerLoopSystem.cs b/Arch.SystemGroups/PlayerLoopSystem.cs index f90bfad..d1dee07 100644 --- a/Arch.SystemGroups/PlayerLoopSystem.cs +++ b/Arch.SystemGroups/PlayerLoopSystem.cs @@ -1,25 +1,26 @@ using Arch.System; using Arch.SystemGroups.Metadata; -namespace Arch.SystemGroups; - -/// -/// The base system for all systems that are executed in the player loop -/// -/// -public abstract class PlayerLoopSystem : BaseSystem +namespace Arch.SystemGroups { /// - /// Default constructor for a player loop system + /// The base system for all systems that are executed in the player loop /// - /// - protected PlayerLoopSystem(TWorld world) : base(world) + /// + public abstract class PlayerLoopSystem : BaseSystem { - } + /// + /// Default constructor for a player loop system + /// + /// + protected PlayerLoopSystem(TWorld world) : base(world) + { + } - /// - /// The metadata of the system in an abstract form - /// - /// - protected abstract AttributesInfoBase GetMetadataInternal(); + /// + /// The metadata of the system in an abstract form + /// + /// + protected abstract AttributesInfoBase GetMetadataInternal(); + } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemGroup.cs b/Arch.SystemGroups/SystemGroup.cs index 7e67930..69ee390 100644 --- a/Arch.SystemGroups/SystemGroup.cs +++ b/Arch.SystemGroups/SystemGroup.cs @@ -6,138 +6,139 @@ using JetBrains.Annotations; using UnityEngine.Pool; -namespace Arch.SystemGroups; - -/// -/// Denotes a root group connected to a specific phase of the player loop. -/// By default updated by the scaled deltaTime. -/// If Unscaled delta time is needed consider using Time.unscaledXXX manually. -/// -public abstract class SystemGroup : IDisposable +namespace Arch.SystemGroups { /// - /// State of the system group + /// Denotes a root group connected to a specific phase of the player loop. + /// By default updated by the scaled deltaTime. + /// If Unscaled delta time is needed consider using Time.unscaledXXX manually. /// - public enum State : byte + public abstract class SystemGroup : IDisposable { /// - /// Initialized was not called yet + /// State of the system group /// - NotInitialized, - - /// - /// Up and Running - /// - Active, - - /// - /// The execution of update functions is suspended but the group is not disposed - /// - Suspended, + public enum State : byte + { + /// + /// Initialized was not called yet + /// + NotInitialized, + + /// + /// Up and Running + /// + Active, + + /// + /// The execution of update functions is suspended but the group is not disposed + /// + Suspended, + + /// + /// Disposed was executed + /// + Disposed + } /// - /// Disposed was executed + /// An empty shared instance of attributes metadata /// - Disposed - } - - /// - /// An empty shared instance of attributes metadata - /// - public static SystemGroupAttributesInfo Metadata = SystemGroupAttributesInfo.Instance; + public static SystemGroupAttributesInfo Metadata = SystemGroupAttributesInfo.Instance; - private readonly ISystemGroupExceptionHandler _exceptionHandler; + private readonly ISystemGroupExceptionHandler _exceptionHandler; - private readonly ISystemGroupThrottler _throttler; + private readonly ISystemGroupThrottler _throttler; - private readonly Type _type; + private readonly Type _type; - internal SystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, - [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) - { - Nodes = nodes; - _throttler = throttler; - _exceptionHandler = exceptionHandler; - _type = GetType(); - } - - internal State CurrentState { get; private set; } = State.NotInitialized; + internal SystemGroup(List> nodes, [CanBeNull] ISystemGroupThrottler throttler, + [CanBeNull] ISystemGroupExceptionHandler exceptionHandler) + { + Nodes = nodes; + _throttler = throttler; + _exceptionHandler = exceptionHandler; + _type = GetType(); + } - internal List> Nodes { get; } + internal State CurrentState { get; private set; } = State.NotInitialized; - /// - /// Dispose all systems and release the list allocated for them. - /// After the dispose is called the instance of the group is no longer usable. - /// - public void Dispose() - { - if (Nodes == null) return; - if (CurrentState == State.Disposed) return; + internal List> Nodes { get; } - foreach (var system in Nodes) - system.Dispose(); - ListPool>.Release(Nodes); - CurrentState = State.Disposed; - } + /// + /// Dispose all systems and release the list allocated for them. + /// After the dispose is called the instance of the group is no longer usable. + /// + public void Dispose() + { + if (Nodes == null) return; + if (CurrentState == State.Disposed) return; - /// - /// Update all nodes in the group - /// - public abstract void Update(); + foreach (var system in Nodes) + system.Dispose(); + ListPool>.Release(Nodes); + CurrentState = State.Disposed; + } - private protected void Update(in TimeProvider.Info timeInfo) - { - if (Nodes == null) return; + /// + /// Update all nodes in the group + /// + public abstract void Update(); - if (Nodes.Count == 0) return; + private protected void Update(in TimeProvider.Info timeInfo) + { + if (Nodes == null) return; - if (CurrentState != State.Active) return; + if (Nodes.Count == 0) return; - var throttle = _throttler != null && _throttler.ShouldThrottle(_type, in timeInfo); + if (CurrentState != State.Active) return; - try - { - foreach (var system in Nodes) - { - system.BeforeUpdate(in timeInfo.DeltaTime, throttle); - } + var throttle = _throttler != null && _throttler.ShouldThrottle(_type, in timeInfo); - foreach (var system in Nodes) + try { - system.Update(in timeInfo.DeltaTime, throttle); + foreach (var system in Nodes) + { + system.BeforeUpdate(in timeInfo.DeltaTime, throttle); + } + + foreach (var system in Nodes) + { + system.Update(in timeInfo.DeltaTime, throttle); + } + + foreach (var system in Nodes) + { + system.AfterUpdate(in timeInfo.DeltaTime, throttle); + } } - - foreach (var system in Nodes) + catch (Exception e) { - system.AfterUpdate(in timeInfo.DeltaTime, throttle); + if (_exceptionHandler == null) + throw; + + switch (_exceptionHandler.Handle(e, _type)) + { + case ISystemGroupExceptionHandler.Action.Suspend: + CurrentState = State.Suspended; + break; + case ISystemGroupExceptionHandler.Action.Dispose: + Dispose(); + break; + } } - } - catch (Exception e) - { - if (_exceptionHandler == null) - throw; - switch (_exceptionHandler.Handle(e, _type)) - { - case ISystemGroupExceptionHandler.Action.Suspend: - CurrentState = State.Suspended; - break; - case ISystemGroupExceptionHandler.Action.Dispose: - Dispose(); - break; - } + _throttler?.OnSystemGroupUpdateFinished(_type, throttle); } - _throttler?.OnSystemGroupUpdateFinished(_type, throttle); - } - - internal void Initialize() - { - if (Nodes == null) return; + internal void Initialize() + { + if (Nodes == null) return; - CurrentState = State.Active; + CurrentState = State.Active; - foreach (var system in Nodes) - system.Initialize(); + foreach (var system in Nodes) + system.Initialize(); + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemGroupWorld.cs b/Arch.SystemGroups/SystemGroupWorld.cs index 4ce5c67..c1aae90 100644 --- a/Arch.SystemGroups/SystemGroupWorld.cs +++ b/Arch.SystemGroups/SystemGroupWorld.cs @@ -1,49 +1,50 @@ using System; using System.Collections.Generic; -namespace Arch.SystemGroups; - -/// -/// An entry point to the systems connected to the Unity Player Loop. -/// -public class SystemGroupWorld : IDisposable +namespace Arch.SystemGroups { - private readonly IPlayerLoop _playerLoop; + /// + /// An entry point to the systems connected to the Unity Player Loop. + /// + public class SystemGroupWorld : IDisposable + { + private readonly IPlayerLoop _playerLoop; - // Aggregate factory is used to create the aggregate for each system group type, - // acts as a key in the SystemGroupAggregateCache - private readonly ISystemGroupAggregateFactory _aggregateFactory; + // Aggregate factory is used to create the aggregate for each system group type, + // acts as a key in the SystemGroupAggregateCache + private readonly ISystemGroupAggregateFactory _aggregateFactory; - internal IReadOnlyList SystemGroups { get; } + internal IReadOnlyList SystemGroups { get; } - internal SystemGroupWorld(IReadOnlyList systemGroups, IPlayerLoop playerLoop, ISystemGroupAggregateFactory aggregateFactory) - { - _playerLoop = playerLoop; - _aggregateFactory = aggregateFactory; - SystemGroups = systemGroups; - } + internal SystemGroupWorld(IReadOnlyList systemGroups, IPlayerLoop playerLoop, ISystemGroupAggregateFactory aggregateFactory) + { + _playerLoop = playerLoop; + _aggregateFactory = aggregateFactory; + SystemGroups = systemGroups; + } - /// - /// Recursively Initialize all systems in the world according to their execution order - /// - public void Initialize() - { - for (var i = 0; i < SystemGroups.Count; i++) + /// + /// Recursively Initialize all systems in the world according to their execution order + /// + public void Initialize() { - SystemGroups[i].Initialize(); + for (var i = 0; i < SystemGroups.Count; i++) + { + SystemGroups[i].Initialize(); + } } - } - /// - /// Recursively Dispose all systems in the world according to their execution order. - /// Remove all systems from the player loop - /// - public void Dispose() - { - for (var i = 0; i < SystemGroups.Count; i++) + /// + /// Recursively Dispose all systems in the world according to their execution order. + /// Remove all systems from the player loop + /// + public void Dispose() { - SystemGroups[i].Dispose(); - _playerLoop.RemoveFromPlayerLoop(_aggregateFactory, SystemGroups[i]); + for (var i = 0; i < SystemGroups.Count; i++) + { + SystemGroups[i].Dispose(); + _playerLoop.RemoveFromPlayerLoop(_aggregateFactory, SystemGroups[i]); + } } } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemsDependencies/ArchSystemsSorter.cs b/Arch.SystemGroups/SystemsDependencies/ArchSystemsSorter.cs index 60895d5..2dcc47d 100644 --- a/Arch.SystemGroups/SystemsDependencies/ArchSystemsSorter.cs +++ b/Arch.SystemGroups/SystemsDependencies/ArchSystemsSorter.cs @@ -3,80 +3,81 @@ using Arch.System; using UnityEngine.Pool; -namespace Arch.SystemGroups; - -/// -/// Sorts systems. Used by auto-generated code. Consider ignoring it -/// -public static class ArchSystemsSorter +namespace Arch.SystemGroups { /// - /// Adds a dependency edge to the graph. - /// Supports redundancies. - /// Circular dependencies will be resolved on the final stage of the graph traversal + /// Sorts systems. Used by auto-generated code. Consider ignoring it /// - /// System that should be updated before - /// System that should be updated after - /// Storage of edges - public static void AddEdge(Type from, Type to, Dictionary> edges) + public static class ArchSystemsSorter { - if (!edges.TryGetValue(from, out var list)) - edges[from] = list = ListPool.Get(); - list.Add(to); - } + /// + /// Adds a dependency edge to the graph. + /// Supports redundancies. + /// Circular dependencies will be resolved on the final stage of the graph traversal + /// + /// System that should be updated before + /// System that should be updated after + /// Storage of edges + public static void AddEdge(Type from, Type to, Dictionary> edges) + { + if (!edges.TryGetValue(from, out var list)) + edges[from] = list = ListPool.Get(); + list.Add(to); + } - /// - /// Called from auto-generated code, validate edges belong to the same group - /// - public static void ValidateEdge(List disconnectedDependencies, Type declaredOn, Type group, Type dependencyType, Type dependencyGroup) - { - if (group != dependencyGroup) - disconnectedDependencies.Add(new DisconnectedDependenciesInfo.WrongTypeBinding(dependencyType, declaredOn)); - } + /// + /// Called from auto-generated code, validate edges belong to the same group + /// + public static void ValidateEdge(List disconnectedDependencies, Type declaredOn, Type group, Type dependencyType, Type dependencyGroup) + { + if (group != dependencyGroup) + disconnectedDependencies.Add(new DisconnectedDependenciesInfo.WrongTypeBinding(dependencyType, declaredOn)); + } - internal static List> SortSystems(Dictionary> systems, Dictionary> edges) - { - var result = ListPool>.Get(); + internal static List> SortSystems(Dictionary> systems, Dictionary> edges) + { + var result = ListPool>.Get(); - var visited = HashSetPool.Get(); + var visited = HashSetPool.Get(); - foreach (var system in systems.Keys) - { - // Circular dependencies on the root will be found in the second cycle of the DFS Traversal - DFSTraversal(systems, system, visited, result, edges); - } + foreach (var system in systems.Keys) + { + // Circular dependencies on the root will be found in the second cycle of the DFS Traversal + DFSTraversal(systems, system, visited, result, edges); + } - HashSetPool.Release(visited); + HashSetPool.Release(visited); - result.Reverse(); + result.Reverse(); - return result; - } + return result; + } - private static Type DFSTraversal(Dictionary> systems, Type currentVertex, - HashSet visited, List> result, Dictionary> edges) - { - if (visited.Add(currentVertex)) + private static Type DFSTraversal(Dictionary> systems, Type currentVertex, + HashSet visited, List> result, Dictionary> edges) { - if (edges.TryGetValue(currentVertex, out var currentVertexEdges)) + if (visited.Add(currentVertex)) { - foreach (var vertex in currentVertexEdges) + if (edges.TryGetValue(currentVertex, out var currentVertexEdges)) { - // the current vertex may not belong to the current hierarchy - if (!systems.ContainsKey(vertex)) - continue; + foreach (var vertex in currentVertexEdges) + { + // the current vertex may not belong to the current hierarchy + if (!systems.ContainsKey(vertex)) + continue; - var circularDependency = DFSTraversal(systems, vertex, visited, result, edges); - if (circularDependency == currentVertex) - throw new InvalidOperationException($"Circular dependency detected on a path: {currentVertex} -> {vertex} -> ..."); + var circularDependency = DFSTraversal(systems, vertex, visited, result, edges); + if (circularDependency == currentVertex) + throw new InvalidOperationException($"Circular dependency detected on a path: {currentVertex} -> {vertex} -> ..."); + } } - } - // Instead of adding to the head (that is much more expensive) we add to the tail and reverse the list - result.Add(systems[currentVertex]); - } + // Instead of adding to the head (that is much more expensive) we add to the tail and reverse the list + result.Add(systems[currentVertex]); + } - // return the type that is a potential circular dependency - return currentVertex; + // return the type that is a potential circular dependency + return currentVertex; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesFoundException.cs b/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesFoundException.cs index 6672d30..6323bc4 100644 --- a/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesFoundException.cs +++ b/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesFoundException.cs @@ -2,32 +2,33 @@ using System.Collections.Generic; using System.Linq; -namespace Arch.SystemGroups; - -/// -/// Wrong dependencies were detected on traversal of the dependency graph -/// -public class DisconnectedDependenciesFoundException : Exception +namespace Arch.SystemGroups { - private readonly IReadOnlyList _disconnectedDependencies; - - internal DisconnectedDependenciesFoundException(IReadOnlyList disconnectedDependencies) + /// + /// Wrong dependencies were detected on traversal of the dependency graph + /// + public class DisconnectedDependenciesFoundException : Exception { - _disconnectedDependencies = disconnectedDependencies; - } + private readonly IReadOnlyList _disconnectedDependencies; - public override string Message => string.Join(Environment.NewLine, _disconnectedDependencies.Select(PrintDependencyInfo)); - - private static string PrintDependencyInfo(DisconnectedDependenciesInfo disconnectedDependenciesInfo) - { - static string PrintWrongBinding(DisconnectedDependenciesInfo.WrongTypeBinding wrongTypeBinding) + internal DisconnectedDependenciesFoundException(IReadOnlyList disconnectedDependencies) { - return wrongTypeBinding.DeclaredOn == null - ? $"{wrongTypeBinding.DependencyType.Name} (declared on a group)" - : $"{wrongTypeBinding.DependencyType.Name} (declared on {wrongTypeBinding.DeclaredOn.Name})"; + _disconnectedDependencies = disconnectedDependencies; } + + public override string Message => string.Join(Environment.NewLine, _disconnectedDependencies.Select(PrintDependencyInfo)); + + private static string PrintDependencyInfo(DisconnectedDependenciesInfo disconnectedDependenciesInfo) + { + static string PrintWrongBinding(DisconnectedDependenciesInfo.WrongTypeBinding wrongTypeBinding) + { + return wrongTypeBinding.DeclaredOn == null + ? $"{wrongTypeBinding.DependencyType.Name} (declared on a group)" + : $"{wrongTypeBinding.DependencyType.Name} (declared on {wrongTypeBinding.DeclaredOn.Name})"; + } - return $"The following dependencies don't belong to the group {disconnectedDependenciesInfo.GroupType.Name}: " + - $"{string.Join(", ", disconnectedDependenciesInfo.WrongDependencies.Select(PrintWrongBinding))}"; + return $"The following dependencies don't belong to the group {disconnectedDependenciesInfo.GroupType.Name}: " + + $"{string.Join(", ", disconnectedDependenciesInfo.WrongDependencies.Select(PrintWrongBinding))}"; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesInfo.cs b/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesInfo.cs index 6e6068c..72d55de 100644 --- a/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesInfo.cs +++ b/Arch.SystemGroups/SystemsDependencies/DisconnectedDependenciesInfo.cs @@ -2,49 +2,50 @@ using System.Collections.Generic; using JetBrains.Annotations; -namespace Arch.SystemGroups; - -/// -/// Contains information about the specified dependencies -/// which do not belong to the given hierarchy -/// -public readonly struct DisconnectedDependenciesInfo +namespace Arch.SystemGroups { /// - /// Denotes a pair of dependency type and the type it was declared on + /// Contains information about the specified dependencies + /// which do not belong to the given hierarchy /// - public readonly struct WrongTypeBinding + public readonly struct DisconnectedDependenciesInfo { /// - /// Type of the dependency + /// Denotes a pair of dependency type and the type it was declared on /// - public readonly Type DependencyType; + public readonly struct WrongTypeBinding + { + /// + /// Type of the dependency + /// + public readonly Type DependencyType; - /// - /// Type the dependency was declared on - /// - [CanBeNull] public readonly Type DeclaredOn; + /// + /// Type the dependency was declared on + /// + [CanBeNull] public readonly Type DeclaredOn; - internal WrongTypeBinding(Type dependencyType, Type declaredOn) - { - DependencyType = dependencyType; - DeclaredOn = declaredOn; + internal WrongTypeBinding(Type dependencyType, Type declaredOn) + { + DependencyType = dependencyType; + DeclaredOn = declaredOn; + } } - } - /// - /// Type of the group - /// - public readonly Type GroupType; + /// + /// Type of the group + /// + public readonly Type GroupType; - /// - /// - /// - public readonly IReadOnlyList WrongDependencies; + /// + /// + /// + public readonly IReadOnlyList WrongDependencies; - internal DisconnectedDependenciesInfo(Type groupType, IReadOnlyList wrongDependencies) - { - GroupType = groupType; - WrongDependencies = wrongDependencies; + internal DisconnectedDependenciesInfo(Type groupType, IReadOnlyList wrongDependencies) + { + GroupType = groupType; + WrongDependencies = wrongDependencies; + } } } \ No newline at end of file diff --git a/Arch.SystemGroups/SystemsUpdateOrder.cs b/Arch.SystemGroups/SystemsUpdateOrder.cs index 3be3e21..a89e9b3 100644 --- a/Arch.SystemGroups/SystemsUpdateOrder.cs +++ b/Arch.SystemGroups/SystemsUpdateOrder.cs @@ -1,60 +1,61 @@ using System; -namespace Arch.SystemGroups; - -// Interface used for constraining generic functions on Attributes -// which control system update, creation, or destruction order -internal interface ISystemOrderAttribute -{ - Type SystemType { get; } -} - -/// -/// Apply to a system to specify an update ordering constraint with another system in the same or . -/// -/// Updating before or after a system constrains the scheduler ordering of these systems within a ComponentSystemGroup. -/// Both the before and after systems must be a members of the same ComponentSystemGroup. -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] -public class UpdateBeforeAttribute : Attribute, ISystemOrderAttribute +namespace Arch.SystemGroups { - /// - /// Specify a system which the tagged system must update before. - /// - /// The target system which the tagged system must update before. This system must be - /// a member of the same or . - /// Thrown if the system type is empty. - public UpdateBeforeAttribute(Type systemType) + // Interface used for constraining generic functions on Attributes +// which control system update, creation, or destruction order + internal interface ISystemOrderAttribute { - SystemType = systemType ?? throw new ArgumentNullException(nameof(systemType)); + Type SystemType { get; } } /// - /// The type of the target system, which the tagged system must update before. + /// Apply to a system to specify an update ordering constraint with another system in the same or . /// - public Type SystemType { get; } -} - -/// -/// Apply to a system to specify an update ordering constraint with another system in the same or . -/// -/// Updating before or after a system constrains the scheduler ordering of these systems within a ComponentSystemGroup. -/// Both the before and after systems must be a members of the same ComponentSystemGroup. -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] -public class UpdateAfterAttribute : Attribute, ISystemOrderAttribute -{ - /// - /// Specify a system which the tagged system must update after. - /// - /// The target system which the tagged system must update after. This system must be - /// a member of the same or . - /// Thrown if the system type is empty. - public UpdateAfterAttribute(Type systemType) + /// Updating before or after a system constrains the scheduler ordering of these systems within a ComponentSystemGroup. + /// Both the before and after systems must be a members of the same ComponentSystemGroup. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] + public class UpdateBeforeAttribute : Attribute, ISystemOrderAttribute { - SystemType = systemType ?? throw new ArgumentNullException(nameof(systemType)); + /// + /// Specify a system which the tagged system must update before. + /// + /// The target system which the tagged system must update before. This system must be + /// a member of the same or . + /// Thrown if the system type is empty. + public UpdateBeforeAttribute(Type systemType) + { + SystemType = systemType ?? throw new ArgumentNullException(nameof(systemType)); + } + + /// + /// The type of the target system, which the tagged system must update before. + /// + public Type SystemType { get; } } /// - /// The type of the target system, which the tagged system must update after. + /// Apply to a system to specify an update ordering constraint with another system in the same or . /// - public Type SystemType { get; } + /// Updating before or after a system constrains the scheduler ordering of these systems within a ComponentSystemGroup. + /// Both the before and after systems must be a members of the same ComponentSystemGroup. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] + public class UpdateAfterAttribute : Attribute, ISystemOrderAttribute + { + /// + /// Specify a system which the tagged system must update after. + /// + /// The target system which the tagged system must update after. This system must be + /// a member of the same or . + /// Thrown if the system type is empty. + public UpdateAfterAttribute(Type systemType) + { + SystemType = systemType ?? throw new ArgumentNullException(nameof(systemType)); + } + + /// + /// The type of the target system, which the tagged system must update after. + /// + public Type SystemType { get; } + } } \ No newline at end of file diff --git a/Arch.SystemGroups/Throttling/ISystemGroupThrottler.cs b/Arch.SystemGroups/Throttling/ISystemGroupThrottler.cs index fb5f01a..842899e 100644 --- a/Arch.SystemGroups/Throttling/ISystemGroupThrottler.cs +++ b/Arch.SystemGroups/Throttling/ISystemGroupThrottler.cs @@ -1,38 +1,39 @@ using System; using Arch.SystemGroups.UnityBridge; -namespace Arch.SystemGroups.Throttling; - -/// -/// Provides a way to throttle systems in the root system group, reused for different system groups -/// -public interface ISystemGroupThrottler +namespace Arch.SystemGroups.Throttling { - /// - /// Called when the system group begins to update within the Unity Player Loop + /// - /// Type of the system group - /// Information about time - bool ShouldThrottle(Type systemGroupType, in TimeProvider.Info timeInfo); + public interface ISystemGroupThrottler + { + /// + /// Called when the system group begins to update within the Unity Player Loop + /// + /// Type of the system group + /// Information about time + bool ShouldThrottle(Type systemGroupType, in TimeProvider.Info timeInfo); + + /// + /// Called when the whole system group finishes its update, irrespective of whether it was throttled or not + /// + /// Type of the system group + /// The execution was throttled + void OnSystemGroupUpdateFinished(Type systemGroupType, bool wasThrottled); + } /// - /// Called when the whole system group finishes its update, irrespective of whether it was throttled or not + /// Throttler dedicated to the system groups based on non-fixed updates /// - /// Type of the system group - /// The execution was throttled - void OnSystemGroupUpdateFinished(Type systemGroupType, bool wasThrottled); -} - -/// -/// Throttler dedicated to the system groups based on non-fixed updates -/// -public interface IUpdateBasedSystemGroupThrottler : ISystemGroupThrottler -{ -} + public interface IUpdateBasedSystemGroupThrottler : ISystemGroupThrottler + { + } -/// -/// Throttler dedicated to the system groups based on fixed updates -/// -public interface IFixedUpdateBasedSystemGroupThrottler : ISystemGroupThrottler -{ + /// + /// Throttler dedicated to the system groups based on fixed updates + /// + public interface IFixedUpdateBasedSystemGroupThrottler : ISystemGroupThrottler + { + } } \ No newline at end of file diff --git a/Arch.SystemGroups/Throttling/ThrottlingEnabledAttribute.cs b/Arch.SystemGroups/Throttling/ThrottlingEnabledAttribute.cs index 3f9799e..7db3400 100644 --- a/Arch.SystemGroups/Throttling/ThrottlingEnabledAttribute.cs +++ b/Arch.SystemGroups/Throttling/ThrottlingEnabledAttribute.cs @@ -1,12 +1,13 @@ using System; -namespace Arch.SystemGroups.Throttling; - -/// -/// Indicates that the system or the group can throttle -/// If the group is marked by this attribute all its direct and transitive children will inherit it -/// -[AttributeUsage(AttributeTargets.Class)] -public class ThrottlingEnabledAttribute : Attribute +namespace Arch.SystemGroups.Throttling { + /// + /// Indicates that the system or the group can throttle + /// If the group is marked by this attribute all its direct and transitive children will inherit it + /// + [AttributeUsage(AttributeTargets.Class)] + public class ThrottlingEnabledAttribute : Attribute + { + } } \ No newline at end of file diff --git a/Arch.SystemGroups/UnityBridge/TimeProvider.cs b/Arch.SystemGroups/UnityBridge/TimeProvider.cs index 339f790..d64a751 100644 --- a/Arch.SystemGroups/UnityBridge/TimeProvider.cs +++ b/Arch.SystemGroups/UnityBridge/TimeProvider.cs @@ -1,132 +1,133 @@ using System.Runtime.InteropServices; -namespace Arch.SystemGroups.UnityBridge; - -/// -/// Can't call Unity API without Unity running -/// -public static class TimeProvider +namespace Arch.SystemGroups.UnityBridge { /// - /// Information about time, contains Fixed Time for Physics Systems Groups and Time for the rest + /// Can't call Unity API without Unity running /// - [StructLayout(LayoutKind.Sequential)] - public readonly struct Info + public static class TimeProvider { /// - /// or + /// Information about time, contains Fixed Time for Physics Systems Groups and Time for the rest /// - public readonly float DeltaTime; + [StructLayout(LayoutKind.Sequential)] + public readonly struct Info + { + /// + /// or + /// + public readonly float DeltaTime; - /// - /// or - /// - public readonly float CurrentUnscaledTime; + /// + /// or + /// + public readonly float CurrentUnscaledTime; - /// - /// or - /// - public readonly float CurrentScaledTime; + /// + /// or + /// + public readonly float CurrentScaledTime; - /// - /// - /// - public readonly float Realtime; + /// + /// + /// + public readonly float Realtime; - internal Info(float deltaTime, float currentUnscaledTime, float currentScaledTime, float realtime) - { - DeltaTime = deltaTime; - CurrentUnscaledTime = currentUnscaledTime; - CurrentScaledTime = currentScaledTime; - Realtime = realtime; + internal Info(float deltaTime, float currentUnscaledTime, float currentScaledTime, float realtime) + { + DeltaTime = deltaTime; + CurrentUnscaledTime = currentUnscaledTime; + CurrentScaledTime = currentScaledTime; + Realtime = realtime; + } } - } - internal static Info GetFixedInfo() => new (FixedDeltaTime, UnscaledFixedDeltaTime, ScaledFixedTime, Realtime); + internal static Info GetFixedInfo() => new (FixedDeltaTime, UnscaledFixedDeltaTime, ScaledFixedTime, Realtime); - internal static Info GetInfo() => new (DeltaTime, UnscaledDeltaTime, ScaledTime, Realtime); + internal static Info GetInfo() => new (DeltaTime, UnscaledDeltaTime, ScaledTime, Realtime); - internal static float DeltaTime - { - get + internal static float DeltaTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.deltaTime; + return UnityEngine.Time.deltaTime; #endif + } } - } - internal static float FixedDeltaTime - { - get + internal static float FixedDeltaTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.fixedDeltaTime; + return UnityEngine.Time.fixedDeltaTime; #endif + } } - } - internal static float ScaledTime - { - get + internal static float ScaledTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.time; + return UnityEngine.Time.time; #endif + } } - } - internal static float ScaledFixedTime - { - get + internal static float ScaledFixedTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.fixedTime; + return UnityEngine.Time.fixedTime; #endif + } } - } - internal static float UnscaledDeltaTime - { - get + internal static float UnscaledDeltaTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.unscaledDeltaTime; + return UnityEngine.Time.unscaledDeltaTime; #endif + } } - } - internal static float UnscaledFixedDeltaTime - { - get + internal static float UnscaledFixedDeltaTime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.fixedUnscaledDeltaTime; + return UnityEngine.Time.fixedUnscaledDeltaTime; #endif + } } - } - internal static float Realtime - { - get + internal static float Realtime { + get + { #if OUTSIDE_UNITY return 0; #else - return UnityEngine.Time.realtimeSinceStartup; + return UnityEngine.Time.realtimeSinceStartup; #endif + } } } } \ No newline at end of file diff --git a/Arch.SystemGroups/UpdateInGroupAttribute.cs b/Arch.SystemGroups/UpdateInGroupAttribute.cs index 7df05b6..55fdbae 100644 --- a/Arch.SystemGroups/UpdateInGroupAttribute.cs +++ b/Arch.SystemGroups/UpdateInGroupAttribute.cs @@ -1,33 +1,34 @@ using System; using Arch.System; -namespace Arch.SystemGroups; - -/// -/// The specified Type must be a SystemGroup. -/// Updating in a group means this system will be automatically updated by the specified ComponentSystemGroup when the group is updated. -/// The system may order itself relative to other systems in the group with UpdateBefore and UpdateAfter. This ordering takes -/// effect when the system group is sorted. -/// -[AttributeUsage(AttributeTargets.Class)] -public class UpdateInGroupAttribute : Attribute +namespace Arch.SystemGroups { /// - /// Specify the or which the tagged system should be added to. The tagged system - /// will be updated as part of this system group's Update() method. + /// The specified Type must be a SystemGroup. + /// Updating in a group means this system will be automatically updated by the specified ComponentSystemGroup when the group is updated. + /// The system may order itself relative to other systems in the group with UpdateBefore and UpdateAfter. This ordering takes + /// effect when the system group is sorted. /// - /// The type/ - /// Thrown id the group type is empty. - public UpdateInGroupAttribute(Type groupType) + [AttributeUsage(AttributeTargets.Class)] + public class UpdateInGroupAttribute : Attribute { - if (groupType == null) - throw new ArgumentNullException(nameof(groupType)); + /// + /// Specify the or which the tagged system should be added to. The tagged system + /// will be updated as part of this system group's Update() method. + /// + /// The type/ + /// Thrown id the group type is empty. + public UpdateInGroupAttribute(Type groupType) + { + if (groupType == null) + throw new ArgumentNullException(nameof(groupType)); - GroupType = groupType; - } + GroupType = groupType; + } - /// - /// Retrieve the type. - /// - public Type GroupType { get; } + /// + /// Retrieve the type. + /// + public Type GroupType { get; } + } } \ No newline at end of file diff --git a/Arch.SystemGroups/package.json b/Arch.SystemGroups/package.json new file mode 100644 index 0000000..bdb97e8 --- /dev/null +++ b/Arch.SystemGroups/package.json @@ -0,0 +1,28 @@ +{ + "name": "com.arch.systemgroups", + "displayName": "Arch.SystemGroups", + "version": "1.0.0", + "unity": "2022.3", + "description": "Aligns Arch systems with Unity updates", + "keywords": [ + "unity", + "unity3d", + "upm", + "utility", + "arch", + "ecs" + ], + "homepage": "https://github.com/mikhail-dcl/Arch.SystemGroups", + "bugs": { + "url": "https://github.com/mikhail-dcl/Arch.SystemGroups/issues" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mikhail-dcl/Arch.SystemGroups.git" + }, + "license": "APACHE 2.0", + "author": "mikhail-dcl (https://github.com/mikhail-dcl/)", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +}