From 7936e90e6ed09e6d74d95309ae30383333e02d46 Mon Sep 17 00:00:00 2001 From: Sebastiano Mandala Date: Sun, 7 Jan 2024 22:21:41 +0000 Subject: [PATCH] update Svelto.ECS to 3.5.1 --- com.sebaslab.svelto.ecs/CHANGELOG.md | 13 ++ .../Core/CheckEntityUtilities.cs | 1 + ...EnginesRoot.DoubleBufferedEntitiesToAdd.cs | 8 +- .../Core/EnginesRoot.Engines.cs | 12 +- .../Core/EnginesRoot.Entities.cs | 8 +- .../Core/EntitiesOperations.cs | 11 +- .../Core/EntitySubmissionScheduler.cs | 34 ++++- .../Core/Filters/EntityFilterCollection.cs | 6 +- .../ExclusiveBuildGroupExtensions.cs | 117 ++++++++++++++++++ .../ExclusiveGroupStructExtensions.cs | 60 +++++++++ .../Core/Groups/EntitiesDB.FindGroups.cs | 7 ++ .../Core/Groups/ExclusiveGroup.cs | 8 +- .../Core/Groups/GroupHashMap.cs | 31 +++-- com.sebaslab.svelto.ecs/Core/IEngine.cs | 1 + .../Core/SimpleEntitiesSubmissionScheduler.cs | 35 +----- .../DOTS/UECS/SveltoOnDOTSEnginesGroup.cs | 8 +- .../SveltoOnDOTSEntitiesSubmissionGroup.cs | 4 +- .../Extensions/Unity/MonoScheduler.cs | 35 ------ .../Unity/UnityEntitiesSubmissionScheduler.cs | 52 -------- com.sebaslab.svelto.ecs/package.json | 4 +- com.sebaslab.svelto.ecs/version.json | 2 +- 21 files changed, 295 insertions(+), 162 deletions(-) create mode 100644 com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveBuildGroupExtensions.cs create mode 100644 com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveGroupStructExtensions.cs delete mode 100644 com.sebaslab.svelto.ecs/Extensions/Unity/MonoScheduler.cs delete mode 100644 com.sebaslab.svelto.ecs/Extensions/Unity/UnityEntitiesSubmissionScheduler.cs diff --git a/com.sebaslab.svelto.ecs/CHANGELOG.md b/com.sebaslab.svelto.ecs/CHANGELOG.md index 20b8fbe..fbe3a17 100644 --- a/com.sebaslab.svelto.ecs/CHANGELOG.md +++ b/com.sebaslab.svelto.ecs/CHANGELOG.md @@ -1,6 +1,19 @@ # Svelto.ECS Changelog All notable changes to this project will be documented in this file. Changes are listed in random order of importance. +## [3.5.1] - 01-2024 + +* Remove UnityEntitySubmissionScheduler, it was never needed, the user can use the standard EntitySubmissionScheduler and tick it manually +* Dropped the idea to specialise EntitiesSubmissionScheduler. In hindsight it was never necessary. +* Added better support for range exclusive groups, now they are correctly registered in the group hash map +* Removed announg Group compound/tag {type} is not sealed warning +* Merged Cuyi's workaround to be able to query compound groups in abstract engine. Never had the time to implement a better solution +* It is now possible again to add an entity multiple times inside a filter (it will be overriden) +* Fixed issue https://github.com/sebas77/Svelto.ECS/issues/123 +* Fixed issue https://github.com/sebas77/Svelto.ECS/issues/122 +* Fixed issue https://github.com/sebas77/Svelto.ECS/issues/121 +* AddEngine now adds engines contained in a GroupEngine to the EnginesGroup optionally~~~~ + ## [3.5.0] - 09-2023 * Introduced Serialization namespace for the serialization code diff --git a/com.sebaslab.svelto.ecs/Core/CheckEntityUtilities.cs b/com.sebaslab.svelto.ecs/Core/CheckEntityUtilities.cs index b4431e8..e196930 100644 --- a/com.sebaslab.svelto.ecs/Core/CheckEntityUtilities.cs +++ b/com.sebaslab.svelto.ecs/Core/CheckEntityUtilities.cs @@ -76,6 +76,7 @@ namespace Svelto.ECS bool isAllowed = false; if (_multipleOperationOnSameEGIDChecker.TryGetValue(egid, out var operationType) == true) { + //remove supersedes swap and remove operations, this means remove is allowed if the previous operation was swap or remove on the same submission isAllowed = operationType == OperationType.Remove || operationType == OperationType.SwapFrom; if (isAllowed) diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs index c3495b6..5e2fa62 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs @@ -152,13 +152,17 @@ namespace Svelto.ECS void PreallocateDictionaries (FasterDictionary> dic) { + //get the set of entities in the group ID var group = dic.GetOrAdd( groupID, () => new FasterDictionary()); + //for each component of the entities in the group foreach (var componentBuilder in entityComponentsToBuild) { - var safeDictionary = group.GetOrAdd(componentBuilder.getComponentID, () => componentBuilder.CreateDictionary(numberOfEntities)); - componentBuilder.Preallocate(safeDictionary, numberOfEntities); + //get the dictionary of entities for the component type + var components = group.GetOrAdd(componentBuilder.getComponentID, () => componentBuilder.CreateDictionary(numberOfEntities)); + + componentBuilder.Preallocate(components, numberOfEntities); } } diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs index 410ee83..f0c368b 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs @@ -92,6 +92,11 @@ namespace Svelto.ECS #endif } + /// + ///Ready is a callback that can be used to signal that an engine is ready to be used because the entitiesDB is now available + ///usually engines are ready to be used when they are added to the enginesRoot, but in some special cases, it is possible to + ///wait for the user input to signal that engines are ready to be used + /// protected EnginesRoot(EntitiesSubmissionScheduler entitiesComponentScheduler, EnginesReadyOption enginesWaitForReady): this(entitiesComponentScheduler) { @@ -116,7 +121,7 @@ namespace Svelto.ECS return _isDisposed == false; } - public void AddEngine(IEngine engine) + public void AddEngine(IEngine engine, bool addSubEngines = true) { var type = engine.GetType(); var refWrapper = new RefWrapperType(type); @@ -174,6 +179,7 @@ namespace Svelto.ECS if (engine is IReactOnSubmissionStarted submissionEngineStarted) _reactiveEnginesSubmissionStarted.Add(submissionEngineStarted); + if (addSubEngines) if (engine is IGroupEngine stepGroupEngine) foreach (var stepEngine in stepGroupEngine.engines) AddEngine(stepEngine); @@ -187,6 +193,7 @@ namespace Svelto.ECS if (engine is IQueryingEntitiesEngine queryableEntityComponentEngine) queryableEntityComponentEngine.entitiesDB = _entitiesDB; + //Ready is a callback that can be used to signal that the engine is ready to be used because the entitiesDB is now available if (_enginesWaitForReady == EnginesReadyOption.ReadyAsAdded && engine is IGetReadyEngine getReadyEngine) getReadyEngine.Ready(); } @@ -432,6 +439,9 @@ namespace Svelto.ECS bool _isDisposed; } + //Ready is a callback that can be used to signal that an engine is ready to be used because the entitiesDB is now available + //usually engines are ready to be used when they are added to the enginesRoot, but in some special cases, it is possible to + //wait for the user input to signal that the engine is ready to be used public enum EnginesReadyOption { ReadyAsAdded, diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs index 0c680d6..ce42128 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs @@ -90,14 +90,16 @@ namespace Svelto.ECS var entityComponentBuilder = entityComponentsToBuild[index]; var entityComponentType = entityComponentBuilder.getComponentID; - var dbList = group.GetOrAdd(entityComponentType, () => entityComponentBuilder.CreateDictionary(size)); - entityComponentBuilder.Preallocate(dbList, size); + var components = group.GetOrAdd(entityComponentType, () => entityComponentBuilder.CreateDictionary(size)); + if (components.count != 0) + throw new ECSException("Entity already created in this group, cannot preallocate"); + entityComponentBuilder.Preallocate(components, size); if (_groupsPerEntity.TryGetValue(entityComponentType, out var groupedGroup) == false) groupedGroup = _groupsPerEntity[entityComponentType] = new FasterDictionary(); - groupedGroup[groupID] = dbList; + groupedGroup[groupID] = components; } } diff --git a/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs b/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs index a00beaa..f49d7b0 100644 --- a/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs +++ b/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs @@ -33,8 +33,15 @@ namespace Svelto.ECS public void QueueRemoveOperation(EGID fromEgid, IComponentBuilder[] componentBuilders, string caller) { + // Check if the entity is already queued for removal + if (_thisSubmissionInfo._entitiesRemoved.Contains(fromEgid)) + { + // If it is, skip the rest of the function + return; + } + _thisSubmissionInfo._entitiesRemoved.Add(fromEgid); - RevertSwapOperation(fromEgid); + RevertSwapOperationIfPreviouslyQueued(fromEgid); //todo: limit the number of dictionaries that can be cached //recycle or create dictionaries of components per group @@ -49,7 +56,7 @@ namespace Svelto.ECS .Add((fromEgid.entityID, caller)); } - void RevertSwapOperation(EGID fromEgid) + void RevertSwapOperationIfPreviouslyQueued(EGID fromEgid) { if (_thisSubmissionInfo._entitiesSwapped.Remove(fromEgid, out (EGID fromEgid, EGID toEgid) val)) //Remove supersedes swap, check comment in IEntityFunctions.cs { diff --git a/com.sebaslab.svelto.ecs/Core/EntitySubmissionScheduler.cs b/com.sebaslab.svelto.ecs/Core/EntitySubmissionScheduler.cs index a7d97eb..beeedab 100644 --- a/com.sebaslab.svelto.ecs/Core/EntitySubmissionScheduler.cs +++ b/com.sebaslab.svelto.ecs/Core/EntitySubmissionScheduler.cs @@ -1,14 +1,38 @@ namespace Svelto.ECS.Schedulers { - public abstract class EntitiesSubmissionScheduler + public class EntitiesSubmissionScheduler { - protected internal abstract EnginesRoot.EntitiesSubmitter onTick { set; } - - public abstract void Dispose(); - public bool paused { get; set; } public uint iteration { get; protected internal set; } internal bool isRunning; + + protected internal EnginesRoot.EntitiesSubmitter onTick + { + set + { + DBC.ECS.Check.Require(_entitiesSubmitter == null, "a scheduler can be exclusively used by one enginesRoot only"); + + _entitiesSubmitter = value; + } + } + + public void Dispose() { } + + public void SubmitEntities() + { + try + { + _entitiesSubmitter.Value.SubmitEntities(); + } + catch + { + paused = true; + + throw; + } + } + + EnginesRoot.EntitiesSubmitter? _entitiesSubmitter; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Filters/EntityFilterCollection.cs b/com.sebaslab.svelto.ecs/Core/Filters/EntityFilterCollection.cs index 1d959a8..de742d1 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/EntityFilterCollection.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/EntityFilterCollection.cs @@ -217,12 +217,12 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(uint entityId, uint indexInComponentArray) + public bool Add(uint entityId, uint indexInComponentArray) { - //TODO: check what happens (unit test) if adding the same entityID twice + //it's a TryAdd because there is no reason to not replace the index if the entity is already there //TODO: when sentinels are finished, we need to add AsWriter here //cannot write in parallel - _entityIDToDenseIndex.Add(entityId, indexInComponentArray); + return _entityIDToDenseIndex.TryAdd(entityId, indexInComponentArray, out _); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveBuildGroupExtensions.cs b/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveBuildGroupExtensions.cs new file mode 100644 index 0000000..e964ef4 --- /dev/null +++ b/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveBuildGroupExtensions.cs @@ -0,0 +1,117 @@ +using System; +using Svelto.Common; +using Svelto.DataStructures; + +namespace Svelto.ECS +{ + //Hi! I've been following your discussion on discord and have just a few questions on how to use this snippet properly: + // + //Did I get the idea right: this snippet allows us to swap group tags (from current to target) even if target combination of tags not declared in groups class (like GameGroups.cs in Doofuses iteration 3 example)? If so: + //On discord you wrote: + //The specialized engines define the swaps like this: + //GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + //GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + // + //And any engine can do this: + //var targetGroup = egid.groupID.GetSwapTag(); + //_functions.SwapEntityGroup(egid, targetGroup); + // + //by specialized / any did you mean not abstract / abstract or something else? + // + //When _removeTransitions, _addTransitions, _swapTransitions should be filled? + //@jlreymendez + //Author + //jlreymendez commented on Aug 10, 2020 + //Hey! + // + //1- Yeah, it would allow you to swap to targets that are not directly declared in a group class. In reality you are declaring them when you declare the SetTagSwap, SetTagAddition and SetTagRemoval. + // + //2- Yes, correct by specialized I mean something not abstract, an engine that knows all the tags that apply to an entity. Thus it would allow you to create a comprehensive list of the swaps like you see in that code. Remember that when you do SetTagSwap the reverse will also be declared automatically. + // + //This is the latest from that code you shared: + // + // + // // Register possible transitions. + // GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + // GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + // GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + // + // GroupCompound.BuildGroup.SetTagSwap(GroupCompound.BuildGroup); + // + //3- You would fill them at initialization time, I did it in the Ready() of the engine before entering the game loop. But you could do it in the constructor of the engine. Wherever you find it appropriate before you need to start swapping or changing tags. + + public static class ExclusiveBuildGroupExtensions + { + internal static FasterDictionary, ExclusiveBuildGroup>> + _removeTransitions = + new FasterDictionary, ExclusiveBuildGroup>>(); + + internal static FasterDictionary, ExclusiveBuildGroup>> + _addTransitions = + new FasterDictionary, ExclusiveBuildGroup>>(); + + internal static FasterDictionary, ExclusiveBuildGroup>> + _swapTransitions = + new FasterDictionary, ExclusiveBuildGroup>>(); + + public static void SetTagAddition + (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true) where T : GroupTag + { + if (_addTransitions.TryGetValue(@group, out var transitions) == false) + { + transitions = new FasterDictionary, ExclusiveBuildGroup>(); + _addTransitions[@group] = transitions; + } + + var type = new RefWrapper(typeof(T)); + transitions[type] = target; + + if (setReverse) + { + SetTagRemoval(target, group, false); + } + } + + public static void SetTagRemoval + (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true) where T : GroupTag + { + if (_removeTransitions.TryGetValue(@group, out var transitions) == false) + { + transitions = new FasterDictionary, ExclusiveBuildGroup>(); + _removeTransitions[@group] = transitions; + } + + var type = new RefWrapper(typeof(T)); + transitions[type] = target; + + if (setReverse) + { + SetTagAddition(target, group, false); + } + } + + public static void SetTagSwap + (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true) + where TRemove : GroupTag where TAdd : GroupTag + { + if (_swapTransitions.TryGetValue(@group, out var transitions) == false) + { + transitions = new FasterDictionary, ExclusiveBuildGroup>(); + _swapTransitions[group] = transitions; + } + + var type = new RefWrapper(typeof(TAdd)); + transitions[type] = target; + + // To avoid needing to check if the group already has the tag when swapping (prevent ecs exceptions). + // The current groups adds the removed tag pointing to itself. + type = new RefWrapper(typeof(TRemove)); + transitions[type] = group; + + if (setReverse) + { + SetTagSwap(target, group, false); + } + } + } +} \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveGroupStructExtensions.cs b/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveGroupStructExtensions.cs new file mode 100644 index 0000000..c4069d2 --- /dev/null +++ b/com.sebaslab.svelto.ecs/Core/Groups/AbstractEnginesGroupSwapSupport/ExclusiveGroupStructExtensions.cs @@ -0,0 +1,60 @@ +using System; +using Svelto.DataStructures; + +namespace Svelto.ECS +{ + public static class ExclusiveGroupStructExtensions + { + public static ExclusiveBuildGroup RemoveTag(this ExclusiveGroupStruct group) where T : GroupTag + { + if (ExclusiveBuildGroupExtensions._removeTransitions.TryGetValue(@group, out var transitions)) + { + var type = new RefWrapper(typeof(T)); + if (transitions.TryGetValue(type, out var result)) + { + return result; + } + } + + throw new ECSException("No remove transition found for type " + .FastConcat(typeof(T).ToString()) + .FastConcat(" in group ").FastConcat(@group.ToString()) + ); + } + + public static ExclusiveBuildGroup AddTag(this ExclusiveGroupStruct group) where T : GroupTag + { + if (ExclusiveBuildGroupExtensions._addTransitions.TryGetValue(group, out var transitions)) + { + var type = new RefWrapper(typeof(T)); + if (transitions.TryGetValue(type, out var result)) + { + return result; + } + } + + throw new ECSException("No add transition found for type " + .FastConcat(typeof(T).ToString()) + .FastConcat(" in group ").FastConcat(@group.ToString()) + ); + } + + public static ExclusiveBuildGroup SwapTag(this ExclusiveGroupStruct group) + where TTarget : GroupTag + { + var type = new RefWrapper(typeof(TTarget)); + if (ExclusiveBuildGroupExtensions._swapTransitions.TryGetValue(@group, out var transitions)) + { + if (transitions.TryGetValue(type, out var result)) + { + return result; + } + } + + throw new ECSException("No swap transition found for type " + .FastConcat(typeof(TTarget).ToString()) + .FastConcat(" in group ").FastConcat(@group.ToString()) + ); + } + } +} \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs b/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs index 397b21d..ebbf191 100644 --- a/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs +++ b/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs @@ -7,6 +7,10 @@ namespace Svelto.ECS { public partial class EntitiesDB { + /// + /// Return all the groups where the entity component is found. It's a linear operation, but usually the number of groups are very low + /// By default Groups marked as disabled are not returned, however this can be overridden using the ignoreDisabledBit parameter + /// public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) where T1 : struct, _IInternalEntityComponent { FasterList result = localgroups.Value.groupArray; @@ -123,6 +127,7 @@ namespace Svelto.ECS if (localGroups.count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); + groupData = localArray[++startIndex % 3]; localGroups.Intersect(groupData); @@ -180,11 +185,13 @@ namespace Svelto.ECS if (localGroups.count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); + groupData = localArray[++startIndex & 3]; localGroups.Intersect(groupData); if (localGroups.count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); + groupData = localArray[++startIndex & 3]; localGroups.Intersect(groupData); diff --git a/com.sebaslab.svelto.ecs/Core/Groups/ExclusiveGroup.cs b/com.sebaslab.svelto.ecs/Core/Groups/ExclusiveGroup.cs index bb3527f..956e7e0 100644 --- a/com.sebaslab.svelto.ecs/Core/Groups/ExclusiveGroup.cs +++ b/com.sebaslab.svelto.ecs/Core/Groups/ExclusiveGroup.cs @@ -42,9 +42,8 @@ namespace Svelto.ECS public ExclusiveGroup(ushort range) { _group = ExclusiveGroupStruct.GenerateWithRange(range); -#if DEBUG && !PROFILE_SVELTO + _range = range; -#endif } public ExclusiveGroup(ushort range, ExclusiveGroupBitmask bitmask) @@ -90,9 +89,8 @@ namespace Svelto.ECS static readonly Dictionary _knownGroups = new Dictionary(); -#if DEBUG && !PROFILE_SVELTO - readonly ushort _range; -#endif + internal readonly ushort _range; + readonly ExclusiveGroupStruct _group; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs b/com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs index 3bd4896..d653cfa 100644 --- a/com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs +++ b/com.sebaslab.svelto.ecs/Core/Groups/GroupHashMap.cs @@ -52,10 +52,12 @@ namespace Svelto.ECS { uint groupIDAndBitMask; + int range = 0; if (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType)) { var group = (ExclusiveGroup)field.GetValue(null); groupIDAndBitMask = ((ExclusiveGroupStruct)@group).ToIDAndBitmask(); + range = @group._range; } else if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType)) { @@ -73,13 +75,24 @@ namespace Svelto.ECS var groupID = groupIDAndBitMask & 0xFFFFFF; ExclusiveGroupStruct group = new ExclusiveGroupStruct(groupID, bitMask); #if DEBUG && !PROFILE_SVELTO - if (GroupNamesMap.idToName.ContainsKey(@group) == false) - GroupNamesMap.idToName[@group] = - $"{type.FullName}.{field.Name} {@group.id})"; + if (GroupNamesMap.idToName.ContainsKey(@group) == false) + GroupNamesMap.idToName[@group] = + $"{type.FullName}.{field.Name} id: {@group.id}"; #endif //The hashname is independent from the actual group ID. this is fundamental because it is want //guarantees the hash to be the same across different machines RegisterGroup(@group, $"{type.FullName}.{field.Name}"); + + for (uint i = 1; i < range; i++) + { + var exclusiveGroupStruct = group + i; +#if DEBUG && !PROFILE_SVELTO + if (GroupNamesMap.idToName.ContainsKey(exclusiveGroupStruct) == false) + GroupNamesMap.idToName[exclusiveGroupStruct] = + $"{type.FullName}.{field.Name} id: {@group.id + i}"; +#endif + RegisterGroup(exclusiveGroupStruct, $"{type.FullName}.{field.Name} id: {@group.id + i}"); + } } } } @@ -102,15 +115,7 @@ namespace Svelto.ECS // Check if the current type has a static constructor // type.TypeInitializer.Invoke(null, null); //calling Invoke will force the static constructor to be called even if already called, this is a problem because GroupTag and Compound throw an exception if called multiple times RuntimeHelpers.RunClassConstructor(type.TypeHandle); //this will call the static constructor only once - -#if DEBUG && !PROFILE_SVELTO - if (type.GetInterfaces().Contains(type) == false) - { - if (type.IsSealed == false) - Svelto.Console.LogWarning( - $"Group compound/tag {type} is not sealed. GroupCompounds and Tags cannot be inherited, consider marking it sealed"); - } -#endif + // Recursively check the base types Type baseType = type.BaseType; if (baseType != null && baseType != typeof(object)) //second if means we got the the end of the hierarchy @@ -121,7 +126,7 @@ namespace Svelto.ECS } /// - /// The hashname is independent from the actual group ID. this is fundamental because it is want + /// The hashname is independent from the actual group ID. this is fundamental because it /// guarantees the hash to be the same across different machines /// /// diff --git a/com.sebaslab.svelto.ecs/Core/IEngine.cs b/com.sebaslab.svelto.ecs/Core/IEngine.cs index d76b666..4e3ff36 100644 --- a/com.sebaslab.svelto.ecs/Core/IEngine.cs +++ b/com.sebaslab.svelto.ecs/Core/IEngine.cs @@ -60,6 +60,7 @@ namespace Svelto.ECS public interface IGetReadyEngine : IEngine { + //Ready is a callback that can be used to signal that the engine is ready to be used because the entitiesDB is now available void Ready(); } diff --git a/com.sebaslab.svelto.ecs/Core/SimpleEntitiesSubmissionScheduler.cs b/com.sebaslab.svelto.ecs/Core/SimpleEntitiesSubmissionScheduler.cs index 8388622..6189cd3 100644 --- a/com.sebaslab.svelto.ecs/Core/SimpleEntitiesSubmissionScheduler.cs +++ b/com.sebaslab.svelto.ecs/Core/SimpleEntitiesSubmissionScheduler.cs @@ -1,33 +1,8 @@ -namespace Svelto.ECS.Schedulers +using System; + +namespace Svelto.ECS.Schedulers { + [Obsolete("SimpleEntitiesSubmissionScheduler is obsolete, use EntitiesSubmissionScheduler instead")] public sealed class SimpleEntitiesSubmissionScheduler : EntitiesSubmissionScheduler - { - protected internal override EnginesRoot.EntitiesSubmitter onTick - { - set - { - DBC.ECS.Check.Require(_entitiesSubmitter == null, "a scheduler can be exclusively used by one enginesRoot only"); - - _entitiesSubmitter = value; - } - } - - public override void Dispose() { } - - public void SubmitEntities() - { - try - { - _entitiesSubmitter.Value.SubmitEntities(); - } - catch - { - paused = true; - - throw; - } - } - - EnginesRoot.EntitiesSubmitter? _entitiesSubmitter; - } + { } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEnginesGroup.cs b/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEnginesGroup.cs index 132b39d..3846521 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEnginesGroup.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEnginesGroup.cs @@ -29,11 +29,7 @@ namespace Svelto.ECS.SveltoOnDOTS { public SveltoOnDOTSEnginesGroup(EnginesRoot enginesRoot) { - DBC.ECS.Check.Require( - enginesRoot.scheduler is SimpleEntitiesSubmissionScheduler - , "The Engines root must use a EntitiesSubmissionScheduler scheduler implementation"); - - CreateUnityECSWorldForSvelto(enginesRoot.scheduler as SimpleEntitiesSubmissionScheduler, enginesRoot); + CreateUnityECSWorldForSvelto(enginesRoot.scheduler, enginesRoot); } /// @@ -121,7 +117,7 @@ namespace Svelto.ECS.SveltoOnDOTS world.Dispose(); } - void CreateUnityECSWorldForSvelto(SimpleEntitiesSubmissionScheduler scheduler, EnginesRoot enginesRoot) + void CreateUnityECSWorldForSvelto(EntitiesSubmissionScheduler scheduler, EnginesRoot enginesRoot) { world = new World("Svelto<>DOTS world"); diff --git a/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs b/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs index 21c3f74..1342ffa 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs @@ -26,7 +26,7 @@ namespace Svelto.ECS.SveltoOnDOTS [DisableAutoCreation] public sealed partial class SveltoOnDOTSEntitiesSubmissionGroup: SystemBase, IQueryingEntitiesEngine, ISveltoOnDOTSSubmission { - public SveltoOnDOTSEntitiesSubmissionGroup(SimpleEntitiesSubmissionScheduler submissionScheduler) + public SveltoOnDOTSEntitiesSubmissionGroup(EntitiesSubmissionScheduler submissionScheduler) { _submissionScheduler = submissionScheduler; _structuralEngines = new FasterList(); @@ -106,7 +106,7 @@ namespace Svelto.ECS.SveltoOnDOTS } readonly FasterList _structuralEngines; - readonly SimpleEntitiesSubmissionScheduler _submissionScheduler; + readonly EntitiesSubmissionScheduler _submissionScheduler; DOTSOperationsForSvelto _dotsOperationsForSvelto; bool _isReady; unsafe JobHandle* _jobHandle; diff --git a/com.sebaslab.svelto.ecs/Extensions/Unity/MonoScheduler.cs b/com.sebaslab.svelto.ecs/Extensions/Unity/MonoScheduler.cs deleted file mode 100644 index c0b50bc..0000000 --- a/com.sebaslab.svelto.ecs/Extensions/Unity/MonoScheduler.cs +++ /dev/null @@ -1,35 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using System.Collections; -using UnityEngine; - -namespace Svelto.ECS.Schedulers.Unity -{ - class MonoScheduler : MonoBehaviour - { - public MonoScheduler() - { - _coroutine = Coroutine(); - } - - void Update() - { - _coroutine.MoveNext(); - } - - IEnumerator Coroutine() - { - while (true) - { - yield return _wait; - - onTick(); - } - } - - readonly WaitForEndOfFrame _wait = new WaitForEndOfFrame(); - readonly IEnumerator _coroutine; - - internal System.Action onTick; - } -} -#endif \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Extensions/Unity/UnityEntitiesSubmissionScheduler.cs b/com.sebaslab.svelto.ecs/Extensions/Unity/UnityEntitiesSubmissionScheduler.cs deleted file mode 100644 index df771cc..0000000 --- a/com.sebaslab.svelto.ecs/Extensions/Unity/UnityEntitiesSubmissionScheduler.cs +++ /dev/null @@ -1,52 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using System; -using Object = UnityEngine.Object; -using UnityEngine; - -namespace Svelto.ECS.Schedulers.Unity -{ - //The EntitySubmissionScheduler has been introduced to make the entity components submission logic platform independent - //You can customize the scheduler if you wish - public class UnityEntitiesSubmissionScheduler : EntitiesSubmissionScheduler - { - public UnityEntitiesSubmissionScheduler(string name) - { - _scheduler = new GameObject(name).AddComponent(); - GameObject.DontDestroyOnLoad(_scheduler.gameObject); - _scheduler.onTick = SubmitEntities; - } - - public override void Dispose() - { - if (_scheduler != null && _scheduler.gameObject != null) - { - Object.Destroy(_scheduler.gameObject); - } - } - - void SubmitEntities() - { - try - { - _onTick.SubmitEntities(); - } - catch (Exception e) - { - paused = true; - - Svelto.Console.LogException(e); - - throw; - } - } - - protected internal override EnginesRoot.EntitiesSubmitter onTick - { - set => _onTick = value; - } - - readonly MonoScheduler _scheduler; - EnginesRoot.EntitiesSubmitter _onTick; - } -} -#endif \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/package.json b/com.sebaslab.svelto.ecs/package.json index 98d0215..682368a 100644 --- a/com.sebaslab.svelto.ecs/package.json +++ b/com.sebaslab.svelto.ecs/package.json @@ -11,7 +11,7 @@ "url": "https://github.com/sebas77/Svelto.ECS.git" }, "dependencies": { - "com.sebaslab.svelto.common": "3.5.0" + "com.sebaslab.svelto.common": "3.5.1" }, "keywords": [ "svelto", @@ -19,7 +19,7 @@ "svelto.ecs" ], "name": "com.sebaslab.svelto.ecs", - "version": "3.5.0", + "version": "3.5.1", "type": "library", "unity": "2020.3" } diff --git a/com.sebaslab.svelto.ecs/version.json b/com.sebaslab.svelto.ecs/version.json index 4fdc669..a48434f 100644 --- a/com.sebaslab.svelto.ecs/version.json +++ b/com.sebaslab.svelto.ecs/version.json @@ -1,3 +1,3 @@ { - "version": "3.5.0-pre" + "version": "3.5.1" }