From a73101ad50e3d843effd880701a6f6f00315be4b Mon Sep 17 00:00:00 2001 From: GitHub Date: Sat, 4 Jun 2022 11:30:28 +0000 Subject: [PATCH] UPM package version 3.3.2 --- CHANGELOG.md | 15 +- Core/BT.cs | 88 ++ Core/BT.cs.meta | 11 + Core/ComponentBuilder.cs | 29 +- Core/EGIDMapper.cs | 2 +- Core/EnginesRoot.Engines.cs | 7 +- Core/EnginesRoot.Submission.cs | 207 ++--- Core/EntitiesDB.cs | 123 ++- Core/EntitiesOperations.cs | 12 +- Core/EntityCollection.cs | 171 +--- .../DynamicEntityDescriptor.cs | 10 +- .../ExtendibleEntityDescriptor.cs | 6 +- .../GenericEntityDescriptor.cs | 18 +- Core/EntityInfoView.cs | 2 +- Core/EntityInitializer.cs | 8 +- Core/EntityViewUtility.cs | 41 +- Core/Filters/EnginesRoot.Filters.cs | 184 ++-- Core/Filters/EntitiesDB.Filters.cs | 24 +- Core/Filters/EntitiesDB.LegacyFilters.cs | 20 +- Core/Filters/EntityFilterCollection.cs | 87 +- Core/Filters/NativeEntityFilterCollection.cs | 2 +- Core/Filters/NativeEntityFilterIterator.cs | 2 +- Core/GlobalTypeID.cs | 4 +- Core/{ => Groups}/EntitiesDB.FindGroups.cs | 38 +- .../EntitiesDB.FindGroups.cs.meta | 2 +- .../EntityGroupNotFoundException.cs | 0 .../EntityGroupNotFoundException.cs.meta | 2 +- Core/{ => Groups}/GroupHashMap.cs | 0 Core/{ => Groups}/GroupHashMap.cs.meta | 2 +- Core/{ => Groups}/GroupNamesMap.cs | 0 Core/{ => Groups}/GroupNamesMap.cs.meta | 2 +- Core/{ => Groups}/QueryGroups.cs | 4 +- Core/{ => Groups}/QueryGroups.cs.meta | 2 +- Core/Hybrid/IEntityViewComponent.cs | 2 +- Core/IBaseEntityComponent.cs | 11 + Core/IBaseEntityComponent.cs.meta | 11 + Core/IEngine.cs | 20 +- Core/IEntityComponent.cs | 7 - Core/IEntityComponent.cs.meta | 11 - Core/SetEGIDWithoutBoxing.cs | 6 +- .../DoubleIterationEnumerator.cs | 20 +- Core/Streams/Consumer.cs | 2 +- Core/Streams/EnginesRoot.Streams.cs | 4 +- Core/Streams/EntitiesDB.Streams.cs | 2 +- Core/Streams/EntitiesStreams.cs | 6 +- Core/Streams/EntityStream.cs | 2 +- .../GenericentityStreamConsumerFactory.cs | 8 +- Core/TypeSafeDictionaryFactory.cs | 19 +- .../EntityIDs.meta | 2 +- DataStructures/EntityIDs/IEntityIDs.cs | 4 + DataStructures/EntityIDs/IEntityIDs.cs.meta | 11 + DataStructures/EntityIDs/ManagedEntityIDs.cs | 22 + .../EntityIDs/ManagedEntityIDs.cs.meta | 11 + DataStructures/EntityIDs/NativeEntityIDs.cs | 22 + .../EntityIDs/NativeEntityIDs.cs.meta | 11 + DataStructures/ITypeSafeDictionary.cs | 18 +- DataStructures/ManagedTypeSafeDictionary.cs | 305 +++++++ .../ManagedTypeSafeDictionary.cs.meta | 11 + DataStructures/TypeSafeDictionary.cs | 800 ------------------ DataStructures/TypeSafeDictionary.cs.meta | 11 - DataStructures/TypeSafeDictionaryMethods.cs | 539 ++++++++++++ .../TypeSafeDictionaryMethods.cs.meta | 11 + DataStructures/TypeSafeDictionaryUtilities.cs | 2 +- .../Unmanaged/SharedDisposableNative.cs | 47 + .../Unmanaged/SharedDisposableNative.cs.meta | 11 + DataStructures/Unmanaged/SharedNativeInt.cs | 42 - DataStructures/UnmanagedTypeSafeDictionary.cs | 312 +++++++ .../UnmanagedTypeSafeDictionary.cs.meta | 11 + Extensions/Native/NativeEGIDMapper.cs | 31 +- Extensions/Native/NativeEGIDMultiMapper.cs | 26 +- .../Native/UnityNativeEntityDBExtensions.cs | 20 +- Extensions/Svelto/AllGroupsEnumerable.cs | 6 +- Extensions/Svelto/EGIDMultiMapper.cs | 2 +- .../Svelto/EntityCollectionExtension.cs | 278 ++++-- .../Svelto/EntityManagedDBExtensions.cs | 2 +- Extensions/Svelto/GroupsEnumerable.cs | 18 +- .../SveltoOnDOTSEntitiesSubmissionGroup.cs | 2 +- .../UECS/SveltoOnDOTSHandleLifeTimeEngine.cs | 4 +- .../GameObjects/AbstractionLayer/GOManager.cs | 31 - .../AbstractionLayer/GOManager.cs.meta | 11 - .../Unity/GameObjects/Implementors.meta | 8 - .../EntityReferenceHolderImplementor.cs | 13 - .../EntityReferenceHolderImplementor.cs.meta | 11 - .../GameObjects/Implementors/IECSManager.cs | 6 - .../Implementors/IECSManager.cs.meta | 11 - .../IUseMultipleResourceManagerImplementor.cs | 9 - ...MultipleResourceManagerImplementor.cs.meta | 11 - .../IUseResourceManagerImplementor.cs | 9 - .../IUseResourceManagerImplementor.cs.meta | 11 - .../Unity/GameObjects/ListToPopupDrawer.cs | 11 +- Serialization/ComposedComponentSerializer.cs | 2 +- Serialization/DefaultSerializer.cs | 2 +- Serialization/DefaultSerializerUtils.cs | 4 +- Serialization/DontSerialize.cs | 2 +- .../EnginesRoot.GenericEntitySerialization.cs | 2 +- Serialization/IComponentSerializer.cs | 2 +- Serialization/IEntitySerialization.cs | 2 +- Serialization/PartialSerializer.cs | 2 +- Serialization/SerializableComponentBuilder.cs | 4 +- Serialization/SerializerExt.cs | 4 +- Svelto.ECS.nuspec | 2 + package.json | 4 +- 102 files changed, 2279 insertions(+), 1743 deletions(-) create mode 100644 Core/BT.cs create mode 100644 Core/BT.cs.meta rename Core/{ => Groups}/EntitiesDB.FindGroups.cs (83%) rename Core/{ => Groups}/EntitiesDB.FindGroups.cs.meta (83%) rename Core/{ => Groups}/EntityGroupNotFoundException.cs (100%) rename Core/{ => Groups}/EntityGroupNotFoundException.cs.meta (83%) rename Core/{ => Groups}/GroupHashMap.cs (100%) rename Core/{ => Groups}/GroupHashMap.cs.meta (83%) rename Core/{ => Groups}/GroupNamesMap.cs (100%) rename Core/{ => Groups}/GroupNamesMap.cs.meta (83%) rename Core/{ => Groups}/QueryGroups.cs (99%) rename Core/{ => Groups}/QueryGroups.cs.meta (83%) create mode 100644 Core/IBaseEntityComponent.cs create mode 100644 Core/IBaseEntityComponent.cs.meta delete mode 100644 Core/IEntityComponent.cs delete mode 100644 Core/IEntityComponent.cs.meta rename Extensions/Unity/GameObjects/AbstractionLayer.meta => DataStructures/EntityIDs.meta (77%) create mode 100644 DataStructures/EntityIDs/IEntityIDs.cs create mode 100644 DataStructures/EntityIDs/IEntityIDs.cs.meta create mode 100644 DataStructures/EntityIDs/ManagedEntityIDs.cs create mode 100644 DataStructures/EntityIDs/ManagedEntityIDs.cs.meta create mode 100644 DataStructures/EntityIDs/NativeEntityIDs.cs create mode 100644 DataStructures/EntityIDs/NativeEntityIDs.cs.meta create mode 100644 DataStructures/ManagedTypeSafeDictionary.cs create mode 100644 DataStructures/ManagedTypeSafeDictionary.cs.meta delete mode 100644 DataStructures/TypeSafeDictionary.cs delete mode 100644 DataStructures/TypeSafeDictionary.cs.meta create mode 100644 DataStructures/TypeSafeDictionaryMethods.cs create mode 100644 DataStructures/TypeSafeDictionaryMethods.cs.meta create mode 100644 DataStructures/Unmanaged/SharedDisposableNative.cs create mode 100644 DataStructures/Unmanaged/SharedDisposableNative.cs.meta create mode 100644 DataStructures/UnmanagedTypeSafeDictionary.cs create mode 100644 DataStructures/UnmanagedTypeSafeDictionary.cs.meta delete mode 100644 Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs delete mode 100644 Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs.meta delete mode 100644 Extensions/Unity/GameObjects/Implementors.meta delete mode 100644 Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs delete mode 100644 Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs.meta delete mode 100644 Extensions/Unity/GameObjects/Implementors/IECSManager.cs delete mode 100644 Extensions/Unity/GameObjects/Implementors/IECSManager.cs.meta delete mode 100644 Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs delete mode 100644 Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs.meta delete mode 100644 Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs delete mode 100644 Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c8756b..5038a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,22 @@ # Changelog All notable changes to this project will be documented in this file. Changes are listed in random order of importance. -## [3.3.1] - 26-2022 +## [3.3.2] - 04-06-2022 + +* Internal refactoring to support future features. Currently it may translate to a small performance boost +* IEntityComponent and IEntityViewComponent now implements IBaseEntityComponent. This shouldn't affect existing code +* Improve thread-safety of entity building +* Fixed serious bug that affected the integrity of the EntityIDs values during RemoveEX callbacks +* The point above may result in a performance boost in the Filters updates during submission +* Code is again 2019 compatible (this may have been broken for a while) +* Fix a crash wit the EntityCollection deconstruction while trying to deconstruct an empty collection + + +## [3.3.1] - 26-04-2022 * Fixed serious bug that would affect the new IReactOnRemoveEx callbacks -## [3.3.0] - 04-2022 +## [3.3.0] - 11-04-2022 * INeedEGID and INeedEntityReference interfaces are not deprecated, but still available for backwards compatibility through the define SLOW_SVELTO_SUBMISSION * There are some minor breaking changes, you may need to rename a bunch of methods calls diff --git a/Core/BT.cs b/Core/BT.cs new file mode 100644 index 0000000..164eedd --- /dev/null +++ b/Core/BT.cs @@ -0,0 +1,88 @@ +namespace Svelto.ECS +{ + public readonly struct BT + { + public readonly BufferT1 buffer1; + public readonly BufferT2 buffer2; + public readonly BufferT3 buffer3; + public readonly BufferT4 buffer4; + public readonly int count; + + BT(in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, BufferT4 bufferT4, int count) buffer) : + this() + { + buffer1 = buffer.bufferT1; + buffer2 = buffer.bufferT2; + buffer3 = buffer.bufferT3; + buffer4 = buffer.bufferT4; + count = buffer.count; + } + + public static implicit operator BT( + in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, BufferT4 bufferT4, int count) buffer) + { + return new BT(buffer); + } + } + + public readonly struct BT + { + public readonly BufferT1 buffer1; + public readonly BufferT2 buffer2; + public readonly BufferT3 buffer3; + public readonly int count; + + BT(in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, int count) buffer) : this() + { + buffer1 = buffer.bufferT1; + buffer2 = buffer.bufferT2; + buffer3 = buffer.bufferT3; + count = buffer.count; + } + + public static implicit operator BT( + in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, int count) buffer) + { + return new BT(buffer); + } + } + + public readonly struct BT + { + public readonly BufferT1 buffer; + public readonly int count; + + BT(in (BufferT1 bufferT1, int count) buffer) : this() + { + this.buffer = buffer.bufferT1; + count = buffer.count; + } + + public static implicit operator BT(in (BufferT1 bufferT1, int count) buffer) + { + return new BT(buffer); + } + + public static implicit operator BufferT1(BT t) => t.buffer; + } + + public readonly struct BT + { + public readonly BufferT1 buffer1; + public readonly BufferT2 buffer2; + public readonly int count; + + BT(in (BufferT1 bufferT1, BufferT2 bufferT2, int count) buffer) : this() + { + buffer1 = buffer.bufferT1; + buffer2 = buffer.bufferT2; + count = buffer.count; + } + + public static implicit operator BT( + in (BufferT1 bufferT1, BufferT2 bufferT2, int count) buffer) + { + return new BT(buffer); + } + } +} \ No newline at end of file diff --git a/Core/BT.cs.meta b/Core/BT.cs.meta new file mode 100644 index 0000000..9a5c6e4 --- /dev/null +++ b/Core/BT.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fdd14e4ea613ca68e260dea894f844f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Core/ComponentBuilder.cs b/Core/ComponentBuilder.cs index bf2eaf1..75742ce 100644 --- a/Core/ComponentBuilder.cs +++ b/Core/ComponentBuilder.cs @@ -29,7 +29,7 @@ namespace Svelto.ECS public static int counter; } - public class ComponentID where T : struct, IEntityComponent + public class ComponentID where T : struct, IBaseEntityComponent { public static readonly SharedStaticWrapper> id; @@ -45,7 +45,7 @@ namespace Svelto.ECS } } - public class ComponentBuilder : IComponentBuilder where T : struct, IEntityComponent + public class ComponentBuilder : IComponentBuilder where T : struct, IBaseEntityComponent { internal static readonly Type ENTITY_COMPONENT_TYPE; internal static readonly bool IS_ENTITY_VIEW_COMPONENT; @@ -104,6 +104,8 @@ namespace Svelto.ECS public bool isUnmanaged => IS_UNMANAGED; + static ThreadLocal _localCache = new ThreadLocal(() => new EntityViewComponentCache()); + public void BuildEntityAndAddToList(ITypeSafeDictionary dictionary, EGID egid, IEnumerable implementors) { var castedDic = dictionary as ITypeSafeDictionary; @@ -115,8 +117,7 @@ namespace Svelto.ECS Check.Require(castedDic.ContainsKey(egid.entityID) == false, $"building an entity with already used entity id! id: '{(ulong)egid}', {ENTITY_COMPONENT_NAME}"); - this.SetEntityViewComponentImplementors(ref entityComponent, EntityViewComponentCache.cachedFields, - implementors, EntityViewComponentCache.implementorsByType, EntityViewComponentCache.cachedTypes); + this.SetEntityViewComponentImplementors(ref entityComponent, implementors, _localCache.Value); castedDic.Add(egid.entityID, entityComponent); } @@ -156,22 +157,18 @@ namespace Svelto.ECS readonly T _initializer; - /// - /// Note: this static class will hold forever the references of the entities implementors. These references - /// are not even cleared when the engines root is destroyed, as they are static references. - /// It must be seen as an application-wide cache system. Honestly, I am not sure if this may cause leaking - /// issues in some kind of applications. To remember. - /// - static class EntityViewComponentCache + internal class EntityViewComponentCache { - internal static readonly FasterList>> cachedFields; - internal static readonly Dictionary cachedTypes; + internal readonly FasterList>> cachedFields; + internal readonly Dictionary cachedTypes; + + //this is just a local static cache that is cleared after every use #if DEBUG && !PROFILE_SVELTO - internal static readonly Dictionary> implementorsByType; + internal readonly Dictionary> implementorsByType; #else - internal static readonly Dictionary implementorsByType; + internal readonly Dictionary implementorsByType; #endif - static EntityViewComponentCache() + internal EntityViewComponentCache() { cachedFields = new FasterList>>(); diff --git a/Core/EGIDMapper.cs b/Core/EGIDMapper.cs index a1c7f2d..a0a4c54 100644 --- a/Core/EGIDMapper.cs +++ b/Core/EGIDMapper.cs @@ -8,7 +8,7 @@ namespace Svelto.ECS /// /// /// - public readonly struct EGIDMapper : IEGIDMapper where T : struct, IEntityComponent + public readonly struct EGIDMapper : IEGIDMapper where T : struct, IBaseEntityComponent { public int count => _map.count; public ExclusiveGroupStruct groupID { get; } diff --git a/Core/EnginesRoot.Engines.cs b/Core/EnginesRoot.Engines.cs index c48f2af..d297e77 100644 --- a/Core/EnginesRoot.Engines.cs +++ b/Core/EnginesRoot.Engines.cs @@ -21,7 +21,6 @@ namespace Svelto.ECS SharedDictonary.Init(); SerializationDescriptorMap.Init(); - _swapEntities = SwapEntities; _removeEntities = RemoveEntities; _removeGroup = RemoveGroup; @@ -41,8 +40,9 @@ namespace Svelto.ECS _entitiesOperations = new EntitiesOperations(); _idChecker = new FasterDictionary>(); - _cachedRangeOfSubmittedIndices = new FasterList<(uint, uint)>(); - _cachedIndicesToSwapBeforeSubmissionForFilters = new FasterDictionary(); + _cachedRangeOfSubmittedIndices = new FasterList<(uint, uint)>(); + _transientEntityIDsLeftAndAffectedByRemoval = new FasterList(); + _transientEntityIDsLeftWithoutDuplicates = new FasterDictionary(); _multipleOperationOnSameEGIDChecker = new FasterDictionary(); #if UNITY_NATIVE //because of the thread count, ATM this is only for unity @@ -62,7 +62,6 @@ namespace Svelto.ECS new FasterDictionary>>(); _reactiveEnginesSwapEx = new FasterDictionary>>(); - _reactiveEnginesDispose = new FasterDictionary>>(); diff --git a/Core/EnginesRoot.Submission.cs b/Core/EnginesRoot.Submission.cs index 442e311..821c1ad 100644 --- a/Core/EnginesRoot.Submission.cs +++ b/Core/EnginesRoot.Submission.cs @@ -2,7 +2,6 @@ using System.Runtime.CompilerServices; using Svelto.Common; using Svelto.DataStructures; -using Svelto.ECS.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS @@ -14,8 +13,8 @@ namespace Svelto.ECS { ClearDebugChecks(); //this must be done first as I need the carry the last states after the submission - _entitiesOperations.ExecuteRemoveAndSwappingOperations(_swapEntities, _removeEntities, _removeGroup, - _swapGroup, this); + _entitiesOperations.ExecuteRemoveAndSwappingOperations(_swapEntities, _removeEntities, _removeGroup + , _swapGroup, this); AddEntities(profiler); } @@ -38,9 +37,9 @@ namespace Svelto.ECS } } - static void RemoveEntities( - FasterDictionary>> - removeOperations, FasterList entitiesRemoved, EnginesRoot enginesRoot) + static void RemoveEntities + (FasterDictionary>> + removeOperations, FasterList entitiesRemoved, EnginesRoot enginesRoot) { using (var sampler = new PlatformProfiler("remove Entities")) { @@ -67,8 +66,8 @@ namespace Svelto.ECS FasterList<(uint, string)> infosToProcess = groupedEntitiesToRemove.value; - fromComponentsDictionary.ExecuteEnginesRemoveCallbacks(infosToProcess, - enginesRoot._reactiveEnginesRemove, group, in sampler); + fromComponentsDictionary.ExecuteEnginesRemoveCallbacks( + infosToProcess, enginesRoot._reactiveEnginesRemove, group, in sampler); } } } @@ -89,20 +88,34 @@ namespace Svelto.ECS FasterList<(uint, string)> entityIDsToRemove = groupedEntitiesToRemove.value; - enginesRoot.RemoveEntityFromPersistentFilters(entityIDsToRemove, fromGroup, - componentType, fromComponentsDictionary); - - fromComponentsDictionary.RemoveEntitiesFromDictionary(entityIDsToRemove); - - //store new count after the entities are removed, plus the number of entities removed + enginesRoot._transientEntityIDsLeftAndAffectedByRemoval.FastClear(); + + fromComponentsDictionary.RemoveEntitiesFromDictionary( + entityIDsToRemove, enginesRoot._transientEntityIDsLeftAndAffectedByRemoval); + + //important: remove from the filter must happen after remove from the dictionary + //as we need to read the new indices linked to entities after the removal + enginesRoot.RemoveEntitiesFromPersistentFilters( + entityIDsToRemove, fromGroup, componentType, fromComponentsDictionary + , enginesRoot._transientEntityIDsLeftAndAffectedByRemoval); + + //store new database count after the entities are removed from the datatabase, plus the number of entities removed enginesRoot._cachedRangeOfSubmittedIndices.Add(((uint, uint))( - fromComponentsDictionary.count, - fromComponentsDictionary.count + entityIDsToRemove.count)); + fromComponentsDictionary.count + , fromComponentsDictionary.count + + entityIDsToRemove.count)); } } } - + var rangeEnumerator = enginesRoot._cachedRangeOfSubmittedIndices.GetEnumerator(); + //Note, very important: This is exploiting a trick of the removal operation (RemoveEntitiesFromDictionary) + //You may wonder: how can the remove callbacks iterate entities that have been just removed + //from the database? This works just because during a remove, entities are put at the end of the + //array and not actually removed. The entities are not iterated anymore in future just because + //the count of the array decreases. This means that at the end of the array, after the remove + //operations, we will find the collection of entities just removed. The remove callbacks are + //going to iterate the array from the new count to the new count + the number of entities removed using (sampler.Sample("Execute remove Callbacks Fast")) { foreach (var entitiesToRemove in removeOperations) @@ -113,27 +126,27 @@ namespace Svelto.ECS foreach (var groupedEntitiesToRemove in entitiesToRemove.value) { rangeEnumerator.MoveNext(); - + var componentType = groupedEntitiesToRemove.key; ITypeSafeDictionary fromComponentsDictionary = fromGroupDictionary[componentType]; //get all the engines linked to TValue - if (!enginesRoot._reactiveEnginesRemoveEx.TryGetValue(new RefWrapperType(componentType), - out var entityComponentsEngines)) + if (!enginesRoot._reactiveEnginesRemoveEx.TryGetValue( + componentType, out var entityComponentsEngines)) continue; - - fromComponentsDictionary.ExecuteEnginesRemoveCallbacksFast(entityComponentsEngines, - group, rangeEnumerator.Current, in sampler); + + fromComponentsDictionary.ExecuteEnginesRemoveCallbacksFast( + entityComponentsEngines, group, rangeEnumerator.Current, in sampler); } } } } } - static void SwapEntities( - FasterDictionary>>> swapEntitiesOperations, - FasterList<(EGID, EGID)> entitiesIDSwaps, EnginesRoot enginesRoot) + static void SwapEntities + (FasterDictionary>>> swapEntitiesOperations + , FasterList<(EGID, EGID)> entitiesIDSwaps, EnginesRoot enginesRoot) { using (var sampler = new PlatformProfiler("Swap entities between groups")) { @@ -151,6 +164,7 @@ namespace Svelto.ECS using (sampler.Sample("Swap Entities")) { enginesRoot._cachedRangeOfSubmittedIndices.FastClear(); + //Entities to swap are organised in order to minimise the amount of dictionary lookups. //swapEntitiesOperations iterations happen in the following order: //for each fromGroup, get all the entities to swap for each component type. @@ -172,52 +186,39 @@ namespace Svelto.ECS { ExclusiveGroupStruct toGroup = entitiesInfoToSwap.key; ITypeSafeDictionary toComponentsDictionary = - enginesRoot.GetOrAddTypeSafeDictionary(toGroup, - enginesRoot.GetOrAddDBGroup(toGroup), componentType, fromComponentsDictionary); + enginesRoot.GetOrAddTypeSafeDictionary( + toGroup, enginesRoot.GetOrAddDBGroup(toGroup), componentType + , fromComponentsDictionary); - DBC.ECS.Check.Assert(toComponentsDictionary != null, - "something went wrong with the creation of dictionaries"); + DBC.ECS.Check.Assert(toComponentsDictionary != null + , "something went wrong with the creation of dictionaries"); //this list represents the set of entities that come from fromGroup and need //to be swapped to toGroup. Most of the times will be 1 of few units. FasterList<(uint, uint, string)> fromEntityToEntityIDs = entitiesInfoToSwap.value; - int fromDictionaryCountBeforeSubmission = -1; - - if (enginesRoot._indicesOfPersistentFiltersUsedByThisComponent.TryGetValue( - new NativeRefWrapperType(componentType), - out NativeDynamicArrayCast listOfFilters)) - { - enginesRoot._cachedIndicesToSwapBeforeSubmissionForFilters.FastClear(); - - fromDictionaryCountBeforeSubmission = fromComponentsDictionary.count - 1; - - //add the index of the entities in the component array for each entityID - //BEFORE the submission, as after that the ID will be different - foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs) - enginesRoot._cachedIndicesToSwapBeforeSubmissionForFilters.Add(fromEntityID, - fromComponentsDictionary.GetIndex(fromEntityID)); - } - - //ensure that to dictionary has enough room to store the new entities` - toComponentsDictionary.EnsureCapacity((uint)(toComponentsDictionary.count + - (uint)fromEntityToEntityIDs.count)); + //ensure that to dictionary has enough room to store the new entities + toComponentsDictionary.EnsureCapacity( + (uint)(toComponentsDictionary.count + (uint)fromEntityToEntityIDs.count)); //fortunately swap means that entities are added at the end of each destination //dictionary list, so we can just iterate the list using the indices ranges added in the //_cachedIndices enginesRoot._cachedRangeOfSubmittedIndices.Add(((uint, uint))( - toComponentsDictionary.count, - toComponentsDictionary.count + fromEntityToEntityIDs.count)); + toComponentsDictionary.count + , toComponentsDictionary.count + + fromEntityToEntityIDs.count)); - fromComponentsDictionary.SwapEntitiesBetweenDictionaries(fromEntityToEntityIDs, - fromGroup, toGroup, toComponentsDictionary); + enginesRoot._transientEntityIDsLeftAndAffectedByRemoval.FastClear(); - if (fromDictionaryCountBeforeSubmission != -1) //this if skips the swap if there are no filters linked to the component - enginesRoot.SwapEntityBetweenPersistentFilters(fromEntityToEntityIDs, - enginesRoot._cachedIndicesToSwapBeforeSubmissionForFilters, - toComponentsDictionary, fromGroup, toGroup, - (uint)fromDictionaryCountBeforeSubmission, listOfFilters); + fromComponentsDictionary.SwapEntitiesBetweenDictionaries( + fromEntityToEntityIDs, fromGroup, toGroup, toComponentsDictionary + , enginesRoot._transientEntityIDsLeftAndAffectedByRemoval); + + //important: this must happen after the entities are swapped in the database + enginesRoot.SwapEntityBetweenPersistentFilters( + fromEntityToEntityIDs, fromComponentsDictionary, toComponentsDictionary, fromGroup + , toGroup, componentType, enginesRoot._transientEntityIDsLeftAndAffectedByRemoval); } } } @@ -234,20 +235,20 @@ namespace Svelto.ECS var componentType = groupedEntitiesToSwap.key; //get all the engines linked to TValue - if (!enginesRoot._reactiveEnginesSwap.TryGetValue(new RefWrapperType(componentType), - out var entityComponentsEngines)) + if (!enginesRoot._reactiveEnginesSwap.TryGetValue( + new RefWrapperType(componentType), out var entityComponentsEngines)) continue; foreach (var entitiesInfoToSwap in groupedEntitiesToSwap.value) { ExclusiveGroupStruct toGroup = entitiesInfoToSwap.key; - ITypeSafeDictionary toComponentsDictionary = GetTypeSafeDictionary(toGroup, - enginesRoot.GetDBGroup(toGroup), componentType); + ITypeSafeDictionary toComponentsDictionary = + GetTypeSafeDictionary(toGroup, enginesRoot.GetDBGroup(toGroup), componentType); var infosToProcess = entitiesInfoToSwap.value; - toComponentsDictionary.ExecuteEnginesSwapCallbacks(infosToProcess, - entityComponentsEngines, fromGroup, toGroup, in sampler); + toComponentsDictionary.ExecuteEnginesSwapCallbacks( + infosToProcess, entityComponentsEngines, fromGroup, toGroup, in sampler); } } } @@ -269,16 +270,16 @@ namespace Svelto.ECS rangeEnumerator.MoveNext(); //get all the engines linked to TValue - if (!enginesRoot._reactiveEnginesSwapEx.TryGetValue(new RefWrapperType(componentType), - out var entityComponentsEngines)) + if (!enginesRoot._reactiveEnginesSwapEx.TryGetValue( + new RefWrapperType(componentType), out var entityComponentsEngines)) continue; ExclusiveGroupStruct toGroup = entitiesInfoToSwap.key; - ITypeSafeDictionary toComponentsDictionary = GetTypeSafeDictionary(toGroup, - enginesRoot.GetDBGroup(toGroup), componentType); + ITypeSafeDictionary toComponentsDictionary = + GetTypeSafeDictionary(toGroup, enginesRoot.GetDBGroup(toGroup), componentType); - toComponentsDictionary.ExecuteEnginesSwapCallbacksFast(entityComponentsEngines, - fromGroup, toGroup, rangeEnumerator.Current, in sampler); + toComponentsDictionary.ExecuteEnginesSwapCallbacksFast( + entityComponentsEngines, fromGroup, toGroup, rangeEnumerator.Current, in sampler); } } } @@ -320,10 +321,14 @@ namespace Svelto.ECS //all the new entities are added at the end of each dictionary list, so we can //just iterate the list using the indices ranges added in the _cachedIndices - _cachedRangeOfSubmittedIndices.Add(((uint, uint))(toDictionary.count, - toDictionary.count + fromDictionary.count)); + _cachedRangeOfSubmittedIndices.Add( + ((uint, uint))(toDictionary.count, toDictionary.count + fromDictionary.count)); //Fill the DB with the entity components generated this frame. - fromDictionary.AddEntitiesToDictionary(toDictionary, groupID, entityLocator); + fromDictionary.AddEntitiesToDictionary(toDictionary, groupID +#if SLOW_SVELTO_SUBMISSION + , entityLocator +#endif + ); } } } @@ -345,8 +350,8 @@ namespace Svelto.ECS var toDictionary = GetTypeSafeDictionary(groupID, groupDB, wrapper); enumerator.MoveNext(); - toDictionary.ExecuteEnginesAddEntityCallbacksFast(_reactiveEnginesAddEx, groupID, - enumerator.Current, in sampler); + toDictionary.ExecuteEnginesAddEntityCallbacksFast( + _reactiveEnginesAddEx, groupID, enumerator.Current, in sampler); } } } @@ -373,8 +378,8 @@ namespace Svelto.ECS //this contains the total number of components ever submitted in the DB ITypeSafeDictionary toDictionary = GetTypeSafeDictionary(groupID, groupDB, type); - fromDictionary.ExecuteEnginesAddCallbacks(_reactiveEnginesAdd, toDictionary, - groupID, in sampler); + fromDictionary.ExecuteEnginesAddCallbacks( + _reactiveEnginesAdd, toDictionary, groupID, in sampler); } } } @@ -396,6 +401,7 @@ namespace Svelto.ECS return _groupedEntityToAdd.AnyEntityCreated() || _entitiesOperations.AnyOperationQueued(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] void RemoveEntitiesFromGroup(ExclusiveGroupStruct groupID, in PlatformProfiler profiler) { _entityLocator.RemoveAllGroupReferenceLocators(groupID); @@ -405,8 +411,8 @@ namespace Svelto.ECS foreach (var dictionaryOfEntities in dictionariesOfEntities) { //RemoveEX happens inside - dictionaryOfEntities.value.ExecuteEnginesRemoveCallbacks_Group(_reactiveEnginesRemove, - _reactiveEnginesRemoveEx, groupID, profiler); + dictionaryOfEntities.value.ExecuteEnginesRemoveCallbacks_Group( + _reactiveEnginesRemove, _reactiveEnginesRemoveEx, groupID, profiler); } foreach (var dictionaryOfEntities in dictionariesOfEntities) @@ -418,8 +424,9 @@ namespace Svelto.ECS } } - void SwapEntitiesBetweenGroups(ExclusiveGroupStruct fromGroupId, ExclusiveGroupStruct toGroupId, - PlatformProfiler platformProfiler) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SwapEntitiesBetweenGroups + (ExclusiveGroupStruct fromGroupId, ExclusiveGroupStruct toGroupId, PlatformProfiler platformProfiler) { FasterDictionary fromGroup = GetDBGroup(fromGroupId); FasterDictionary toGroup = GetOrAddDBGroup(toGroupId); @@ -435,7 +442,11 @@ namespace Svelto.ECS ITypeSafeDictionary toDictionary = GetOrAddTypeSafeDictionary(toGroupId, toGroup, refWrapperType, fromDictionary); - fromDictionary.AddEntitiesToDictionary(toDictionary, toGroupId, this.entityLocator); + fromDictionary.AddEntitiesToDictionary(toDictionary, toGroupId +#if SLOW_SVELTO_SUBMISSION + , this.entityLocator +#endif + ); } //Call all the callbacks @@ -447,8 +458,9 @@ namespace Svelto.ECS ITypeSafeDictionary toDictionary = GetTypeSafeDictionary(toGroupId, toGroup, refWrapperType); //SwapEX happens inside - fromDictionary.ExecuteEnginesSwapCallbacks_Group(_reactiveEnginesSwap, - _reactiveEnginesSwapEx, toDictionary, fromGroupId, toGroupId, platformProfiler); + fromDictionary.ExecuteEnginesSwapCallbacks_Group(_reactiveEnginesSwap, _reactiveEnginesSwapEx + , toDictionary, fromGroupId, toGroupId + , platformProfiler); } //remove entities from dictionaries @@ -461,9 +473,9 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - ITypeSafeDictionary GetOrAddTypeSafeDictionary(ExclusiveGroupStruct groupId, - FasterDictionary groupPerComponentType, RefWrapperType type, - ITypeSafeDictionary fromDictionary) + ITypeSafeDictionary GetOrAddTypeSafeDictionary + (ExclusiveGroupStruct groupId, FasterDictionary groupPerComponentType + , RefWrapperType type, ITypeSafeDictionary fromDictionary) { //be sure that the TypeSafeDictionary for the entity Type exists if (groupPerComponentType.TryGetValue(type, out ITypeSafeDictionary toEntitiesDictionary) == false) @@ -485,8 +497,9 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - static ITypeSafeDictionary GetTypeSafeDictionary(ExclusiveGroupStruct groupID, - FasterDictionary @group, RefWrapperType refWrapper) + static ITypeSafeDictionary GetTypeSafeDictionary + (ExclusiveGroupStruct groupID, FasterDictionary @group + , RefWrapperType refWrapper) { if (@group.TryGetValue(refWrapper, out ITypeSafeDictionary fromTypeSafeDictionary) == false) { @@ -496,10 +509,14 @@ namespace Svelto.ECS return fromTypeSafeDictionary; } - readonly DoubleBufferedEntitiesToAdd _groupedEntityToAdd; - readonly EntitiesOperations _entitiesOperations; - readonly FasterList<(uint, uint)> _cachedRangeOfSubmittedIndices; - readonly FasterDictionary _cachedIndicesToSwapBeforeSubmissionForFilters; + readonly DoubleBufferedEntitiesToAdd _groupedEntityToAdd; + readonly EntitiesOperations _entitiesOperations; + + //transient caches>>>>>>>>>>>>>>>>>>>>> + readonly FasterList<(uint, uint)> _cachedRangeOfSubmittedIndices; + readonly FasterDictionary _transientEntityIDsLeftWithoutDuplicates; + readonly FasterList _transientEntityIDsLeftAndAffectedByRemoval; + //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< static readonly Action InternalQueryEntities (FasterDictionary entitiesInGroupPerType) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { uint count = 0; IBuffer buffer; - EntityIDs ids = default; + IEntityIDs ids = default; if (SafeQueryEntityDictionary(out var typeSafeDictionary, entitiesInGroupPerType) == false) - buffer = RetrieveEmptyEntityComponentArray(); + buffer = default; else { ITypeSafeDictionary safeDictionary = (typeSafeDictionary as ITypeSafeDictionary); @@ -34,7 +34,7 @@ namespace Svelto.ECS ids = safeDictionary.entityIDs; } - return new EntityCollection(buffer, count, ids); + return new EntityCollection(buffer, ids, count); } /// @@ -46,25 +46,24 @@ namespace Svelto.ECS /// /// public EntityCollection QueryEntities(ExclusiveGroupStruct groupStructId) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { if (groupEntityComponentsDB.TryGetValue(groupStructId, out var entitiesInGroupPerType) == false) { - var buffer = RetrieveEmptyEntityComponentArray(); - return new EntityCollection(buffer, 0); + return new EntityCollection(default, default, 0); } return InternalQueryEntities(entitiesInGroupPerType); } public EntityCollection QueryEntities(ExclusiveGroupStruct groupStruct) - where T1 : struct, IEntityComponent where T2 : struct, IEntityComponent + where T1 : struct, IBaseEntityComponent where T2 : struct, IBaseEntityComponent { if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false) { - return new EntityCollection(new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection( - RetrieveEmptyEntityComponentArray(), 0)); + return new EntityCollection( + new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0)); } var T1entities = InternalQueryEntities(entitiesInGroupPerType); @@ -81,16 +80,18 @@ namespace Svelto.ECS return new EntityCollection(T1entities, T2entities); } - + public EntityCollection QueryEntities(ExclusiveGroupStruct groupStruct) - where T1 : struct, IEntityComponent where T2 : struct, IEntityComponent where T3 : struct, IEntityComponent + where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent { if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false) { return new EntityCollection( - new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection(RetrieveEmptyEntityComponentArray(), 0)); + new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0)); } var T1entities = InternalQueryEntities(entitiesInGroupPerType); @@ -111,18 +112,18 @@ namespace Svelto.ECS } public EntityCollection QueryEntities(ExclusiveGroupStruct groupStruct) - where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent - where T4 : struct, IEntityComponent + where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent + where T4 : struct, IBaseEntityComponent { if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false) { return new EntityCollection( - new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection(RetrieveEmptyEntityComponentArray(), 0) - , new EntityCollection(RetrieveEmptyEntityComponentArray(), 0)); + new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0) + , new EntityCollection(default, default, 0)); } var T1entities = InternalQueryEntities(entitiesInGroupPerType); @@ -147,7 +148,7 @@ namespace Svelto.ECS } public GroupsEnumerable QueryEntities - (in LocalFasterReadOnlyList groups) where T : struct, IEntityComponent + (in LocalFasterReadOnlyList groups) where T : struct, IBaseEntityComponent { return new GroupsEnumerable(this, groups); } @@ -158,32 +159,31 @@ namespace Svelto.ECS /// /// public GroupsEnumerable QueryEntities(in LocalFasterReadOnlyList groups) - where T1 : struct, IEntityComponent where T2 : struct, IEntityComponent + where T1 : struct, IBaseEntityComponent where T2 : struct, IBaseEntityComponent { return new GroupsEnumerable(this, groups); } - public GroupsEnumerable QueryEntities - (in LocalFasterReadOnlyList groups) - where T1 : struct, IEntityComponent where T2 : struct, IEntityComponent where T3 : struct, IEntityComponent + (in LocalFasterReadOnlyList groups) where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent { return new GroupsEnumerable(this, groups); } public GroupsEnumerable QueryEntities - (in LocalFasterReadOnlyList groups) - where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent - where T4 : struct, IEntityComponent + (in LocalFasterReadOnlyList groups) where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent + where T4 : struct, IBaseEntityComponent { return new GroupsEnumerable(this, groups); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public EGIDMapper QueryMappedEntities(ExclusiveGroupStruct groupStructId) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { if (SafeQueryEntityDictionary(groupStructId, out var typeSafeDictionary) == false) throw new EntityGroupNotFoundException(typeof(T), groupStructId.ToName()); @@ -193,7 +193,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryQueryMappedEntities - (ExclusiveGroupStruct groupStructId, out EGIDMapper mapper) where T : struct, IEntityComponent + (ExclusiveGroupStruct groupStructId, out EGIDMapper mapper) where T : struct, IBaseEntityComponent { mapper = default; if (SafeQueryEntityDictionary(groupStructId, out var typeSafeDictionary) == false @@ -206,7 +206,7 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Exists(EGID entityGID) where T : struct, IEntityComponent + public bool Exists(EGID entityGID) where T : struct, IBaseEntityComponent { if (SafeQueryEntityDictionary(entityGID.groupID, out var casted) == false) return false; @@ -215,7 +215,7 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Exists(uint id, ExclusiveGroupStruct group) where T : struct, IEntityComponent + public bool Exists(uint id, ExclusiveGroupStruct group) where T : struct, IBaseEntityComponent { if (SafeQueryEntityDictionary(group, out var casted) == false) return false; @@ -227,7 +227,7 @@ namespace Svelto.ECS public bool ExistsAndIsNotEmpty(ExclusiveGroupStruct gid) { if (groupEntityComponentsDB.TryGetValue( - gid, out FasterDictionary group) == true) + gid, out FasterDictionary group) == true) { return group.count > 0; } @@ -236,23 +236,23 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasAny(ExclusiveGroupStruct groupStruct) where T : struct, IEntityComponent + public bool HasAny(ExclusiveGroupStruct groupStruct) where T : struct, IBaseEntityComponent { return Count(groupStruct) > 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count(ExclusiveGroupStruct groupStruct) where T : struct, IEntityComponent + public int Count(ExclusiveGroupStruct groupStruct) where T : struct, IBaseEntityComponent { if (SafeQueryEntityDictionary(groupStruct, out var typeSafeDictionary) == false) return 0; - return (int) typeSafeDictionary.count; + return (int)typeSafeDictionary.count; } - public bool FoundInGroups() where T1 : IEntityComponent + public bool FoundInGroups() where T1 : IBaseEntityComponent { - return groupsPerEntity.ContainsKey(TypeRefWrapper.wrapper); + return groupsPerComponent.ContainsKey(TypeRefWrapper.wrapper); } public bool IsDisposing => _enginesRoot._isDisposing; @@ -260,7 +260,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] bool SafeQueryEntityDictionary (out ITypeSafeDictionary typeSafeDictionary - , FasterDictionary entitiesInGroupPerType) where T : IEntityComponent + , FasterDictionary entitiesInGroupPerType) where T : IBaseEntityComponent { if (entitiesInGroupPerType.TryGetValue(new RefWrapperType(TypeCache.type), out var safeDictionary) == false) @@ -277,7 +277,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool SafeQueryEntityDictionary - (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : IEntityComponent + (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : IBaseEntityComponent { if (UnsafeQueryEntityDictionary(group, TypeCache.type, out var safeDictionary) == false) { @@ -306,33 +306,6 @@ namespace Svelto.ECS return entitiesInGroupPerType.TryGetValue(new RefWrapperType(type), out typeSafeDictionary); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IBuffer RetrieveEmptyEntityComponentArray() where T : struct, IEntityComponent - { - return EmptyList.emptyArray; - } - - static class EmptyList where T : struct, IEntityComponent - { - internal static readonly IBuffer emptyArray; - - static EmptyList() - { - if (ComponentBuilder.IS_ENTITY_VIEW_COMPONENT) - { - MB b = default; - - emptyArray = b; - } - else - { - NB b = default; - - emptyArray = b; - } - } - } - static readonly FasterDictionary _emptyDictionary = new FasterDictionary(); @@ -351,7 +324,7 @@ namespace Svelto.ECS //found indexed by group id. TypeSafeDictionary are never created, they instead point to the ones hold //by _groupEntityComponentsDB // >> - FasterDictionary> groupsPerEntity => + FasterDictionary> groupsPerComponent => _enginesRoot._groupsPerEntity; EnginesRoot.EntityReferenceMap _entityReferencesMap; diff --git a/Core/EntitiesOperations.cs b/Core/EntitiesOperations.cs index ef37ec0..4772102 100644 --- a/Core/EntitiesOperations.cs +++ b/Core/EntitiesOperations.cs @@ -82,16 +82,8 @@ namespace Svelto.ECS { (_thisSubmissionInfo, _lastSubmittedInfo) = (_lastSubmittedInfo, _thisSubmissionInfo); - ///todo: we found a case where entities with reference to other entities were removed - /// in the same frame where the referenced entities are remove too. - /// the callback of the referencing entities were assuming that the reference at that point - /// would be invalid. However since the callbacks were called before the groups are removed - /// the reference were still valid, which was not expected. - /// If the referenced entities were removed one by one instead that with the group, by chance - /// it instead worked because the entities were removed before the callbacks were called. - /// this is why RemoveGroup is happeing before RemoveEntities, however the real fix - /// should be to update all the references before removing the entities from the dictionaries - /// and call the callbacks + /// todo: entity references should be updated before calling all the methods to avoid callbacks handling + /// references that should be marked as invalid. foreach (var (group, caller) in _lastSubmittedInfo._groupsToRemove) { try diff --git a/Core/EntityCollection.cs b/Core/EntityCollection.cs index 35c2a58..0ee2430 100644 --- a/Core/EntityCollection.cs +++ b/Core/EntityCollection.cs @@ -4,49 +4,25 @@ using Svelto.ECS.Internal; namespace Svelto.ECS { - public readonly ref struct EntityCollection where T : struct, IEntityComponent + public readonly ref struct EntityCollection where T : struct, IBaseEntityComponent { - static readonly bool IsUnmanaged = TypeSafeDictionary.isUnmanaged; - - public EntityCollection(IBuffer buffer, uint count, EntityIDs entityIDs) : this() - { - DBC.ECS.Check.Require(count == 0 || buffer.isValid, "Buffer is found in impossible state"); - if (IsUnmanaged) - { - _nativedBuffer = (NB)buffer; - _nativedIndices = entityIDs.nativeIDs; - } - else - { - _managedBuffer = (MB)buffer; - _managedIndices = entityIDs.managedIDs; - } - - this.count = count; - } - - public EntityCollection(IBuffer buffer, uint count) : this() + public EntityCollection(IBuffer buffer, IEntityIDs entityIDs, uint count) : this() { DBC.ECS.Check.Require(count == 0 || buffer.isValid, "Buffer is found in impossible state"); - if (IsUnmanaged) - _nativedBuffer = (NB)buffer; - else - _managedBuffer = (MB)buffer; + _buffer = buffer; + _entityIDs = entityIDs; this.count = count; } public uint count { get; } - internal readonly MB _managedBuffer; - internal readonly NB _nativedBuffer; - - internal readonly NativeEntityIDs _nativedIndices; - internal readonly ManagedEntityIDs _managedIndices; + internal readonly IBufferBase _buffer; + internal readonly IEntityIDs _entityIDs; } - public readonly ref struct EntityCollection where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent + public readonly ref struct EntityCollection where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent { internal EntityCollection(in EntityCollection array1, in EntityCollection array2) { @@ -56,59 +32,60 @@ namespace Svelto.ECS public int count => (int)buffer1.count; - internal EntityCollection buffer2 + public EntityCollection buffer2 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer1 + public EntityCollection buffer1 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } } - public readonly ref struct EntityCollection where T3 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T1 : struct, IEntityComponent + public readonly ref struct EntityCollection where T3 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T1 : struct, IBaseEntityComponent { - internal EntityCollection(in EntityCollection array1, in EntityCollection array2, - in EntityCollection array3) + internal EntityCollection + (in EntityCollection array1, in EntityCollection array2, in EntityCollection array3) { buffer1 = array1; buffer2 = array2; buffer3 = array3; } - internal EntityCollection buffer1 + public EntityCollection buffer1 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer2 + public EntityCollection buffer2 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer3 + public EntityCollection buffer3 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal int count => (int)buffer1.count; + public int count => (int)buffer1.count; } - public readonly ref struct EntityCollection where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent - where T4 : struct, IEntityComponent + public readonly ref struct EntityCollection where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent + where T4 : struct, IBaseEntityComponent { - internal EntityCollection(in EntityCollection array1, in EntityCollection array2, - in EntityCollection array3, in EntityCollection array4) + internal EntityCollection + (in EntityCollection array1, in EntityCollection array2, in EntityCollection array3 + , in EntityCollection array4) { buffer1 = array1; buffer2 = array2; @@ -116,116 +93,30 @@ namespace Svelto.ECS buffer4 = array4; } - internal EntityCollection buffer1 + public EntityCollection buffer1 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer2 + public EntityCollection buffer2 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer3 + public EntityCollection buffer3 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal EntityCollection buffer4 + public EntityCollection buffer4 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; } - internal int count => (int)buffer1.count; - } - - public readonly struct BT - { - public readonly BufferT1 buffer1; - public readonly BufferT2 buffer2; - public readonly BufferT3 buffer3; - public readonly BufferT4 buffer4; - public readonly int count; - - BT(in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, BufferT4 bufferT4, int count) buffer) : - this() - { - buffer1 = buffer.bufferT1; - buffer2 = buffer.bufferT2; - buffer3 = buffer.bufferT3; - buffer4 = buffer.bufferT4; - count = buffer.count; - } - - public static implicit operator BT( - in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, BufferT4 bufferT4, int count) buffer) - { - return new BT(buffer); - } - } - - public readonly struct BT - { - public readonly BufferT1 buffer1; - public readonly BufferT2 buffer2; - public readonly BufferT3 buffer3; - public readonly int count; - - BT(in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, int count) buffer) : this() - { - buffer1 = buffer.bufferT1; - buffer2 = buffer.bufferT2; - buffer3 = buffer.bufferT3; - count = buffer.count; - } - - public static implicit operator BT( - in (BufferT1 bufferT1, BufferT2 bufferT2, BufferT3 bufferT3, int count) buffer) - { - return new BT(buffer); - } - } - - public readonly struct BT - { - public readonly BufferT1 buffer; - public readonly int count; - - BT(in (BufferT1 bufferT1, int count) buffer) : this() - { - this.buffer = buffer.bufferT1; - count = buffer.count; - } - - public static implicit operator BT(in (BufferT1 bufferT1, int count) buffer) - { - return new BT(buffer); - } - - public static implicit operator BufferT1(BT t) => t.buffer; - } - - public readonly struct BT - { - public readonly BufferT1 buffer1; - public readonly BufferT2 buffer2; - public readonly int count; - - BT(in (BufferT1 bufferT1, BufferT2 bufferT2, int count) buffer) : this() - { - buffer1 = buffer.bufferT1; - buffer2 = buffer.bufferT2; - count = buffer.count; - } - - public static implicit operator BT( - in (BufferT1 bufferT1, BufferT2 bufferT2, int count) buffer) - { - return new BT(buffer); - } + public int count => (int)buffer1.count; } } \ No newline at end of file diff --git a/Core/EntityDescriptor/DynamicEntityDescriptor.cs b/Core/EntityDescriptor/DynamicEntityDescriptor.cs index daa2c98..a5eab81 100644 --- a/Core/EntityDescriptor/DynamicEntityDescriptor.cs +++ b/Core/EntityDescriptor/DynamicEntityDescriptor.cs @@ -70,21 +70,21 @@ namespace Svelto.ECS _componentsToBuild = Construct(extraEntities.count, extraEntities.ToArrayFast(out _)); } - public void Add() where T : struct, IEntityComponent + public void Add() where T : struct, IBaseEntityComponent { IComponentBuilder[] extraEntities = { new ComponentBuilder() }; _componentsToBuild = Construct(extraEntities.Length, extraEntities); } - public void Add() where T : struct, IEntityComponent where U : struct, IEntityComponent + public void Add() where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent { IComponentBuilder[] extraEntities = { new ComponentBuilder(), new ComponentBuilder() }; _componentsToBuild = Construct(extraEntities.Length, extraEntities); } - public void Add() where T : struct, IEntityComponent - where U : struct, IEntityComponent - where V : struct, IEntityComponent + public void Add() where T : struct, IBaseEntityComponent + where U : struct, IBaseEntityComponent + where V : struct, IBaseEntityComponent { IComponentBuilder[] extraEntities = { diff --git a/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs b/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs index 11e8633..f70f9ce 100644 --- a/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs +++ b/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs @@ -53,15 +53,15 @@ namespace Svelto.ECS return this; } - protected void Add() where T : struct, IEntityComponent + protected void Add() where T : struct, IBaseEntityComponent { _dynamicDescriptor.Add(); } - protected void Add() where T : struct, IEntityComponent where U : struct, IEntityComponent + protected void Add() where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent { _dynamicDescriptor.Add(); } - protected void Add() where T : struct, IEntityComponent where U : struct, IEntityComponent where V : struct, IEntityComponent + protected void Add() where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent where V : struct, IBaseEntityComponent { _dynamicDescriptor.Add(); } diff --git a/Core/EntityDescriptor/GenericEntityDescriptor.cs b/Core/EntityDescriptor/GenericEntityDescriptor.cs index a10a149..0ae3cda 100644 --- a/Core/EntityDescriptor/GenericEntityDescriptor.cs +++ b/Core/EntityDescriptor/GenericEntityDescriptor.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS { - public abstract class GenericEntityDescriptor : IEntityDescriptor where T : struct, IEntityComponent + public abstract class GenericEntityDescriptor : IEntityDescriptor where T : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; static GenericEntityDescriptor() { _componentBuilders = new IComponentBuilder[] {new ComponentBuilder()}; } @@ -9,7 +9,7 @@ } public abstract class GenericEntityDescriptor : IEntityDescriptor - where T : struct, IEntityComponent where U : struct, IEntityComponent + where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; @@ -22,7 +22,7 @@ } public abstract class GenericEntityDescriptor : IEntityDescriptor - where T : struct, IEntityComponent where U : struct, IEntityComponent where V : struct, IEntityComponent + where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent where V : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; @@ -40,8 +40,8 @@ } public abstract class GenericEntityDescriptor : IEntityDescriptor - where T : struct, IEntityComponent where U : struct, IEntityComponent where V : struct, IEntityComponent - where W : struct, IEntityComponent + where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent where V : struct, IBaseEntityComponent + where W : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; @@ -60,8 +60,8 @@ } public abstract class GenericEntityDescriptor : IEntityDescriptor - where T : struct, IEntityComponent where U : struct, IEntityComponent where V : struct, IEntityComponent - where W : struct, IEntityComponent where X : struct, IEntityComponent + where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent where V : struct, IBaseEntityComponent + where W : struct, IBaseEntityComponent where X : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; @@ -81,8 +81,8 @@ } public abstract class GenericEntityDescriptor : IEntityDescriptor - where T : struct, IEntityComponent where U : struct, IEntityComponent where V : struct, IEntityComponent - where W : struct, IEntityComponent where X : struct, IEntityComponent where Y : struct, IEntityComponent + where T : struct, IBaseEntityComponent where U : struct, IBaseEntityComponent where V : struct, IBaseEntityComponent + where W : struct, IBaseEntityComponent where X : struct, IBaseEntityComponent where Y : struct, IBaseEntityComponent { static readonly IComponentBuilder[] _componentBuilders; diff --git a/Core/EntityInfoView.cs b/Core/EntityInfoView.cs index edbb968..50f0003 100644 --- a/Core/EntityInfoView.cs +++ b/Core/EntityInfoView.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS { - struct EntityInfoComponent: IEntityComponent + struct EntityInfoComponent: IBaseEntityComponent { public IComponentBuilder[] componentsToBuild; } diff --git a/Core/EntityInitializer.cs b/Core/EntityInitializer.cs index 3ce726f..ba8845c 100644 --- a/Core/EntityInitializer.cs +++ b/Core/EntityInitializer.cs @@ -16,7 +16,7 @@ namespace Svelto.ECS public EGID EGID => _ID; public readonly EntityReference reference; - public void Init(T initializer) where T : struct, IEntityComponent + public void Init(T initializer) where T : struct, IBaseEntityComponent { if (_group.TryGetValue(new RefWrapperType(ComponentBuilder.ENTITY_COMPONENT_TYPE), out var typeSafeDictionary) == false) @@ -32,7 +32,7 @@ namespace Svelto.ECS dictionary.GetDirectValueByRef(findElementIndex) = initializer; } - public ref T GetOrAdd() where T : struct, IEntityComponent + public ref T GetOrAdd() where T : struct, IBaseEntityComponent { ref var entityDictionary = ref _group.GetOrAdd( new RefWrapperType(ComponentBuilder.ENTITY_COMPONENT_TYPE), TypeSafeDictionaryFactory.Create); @@ -41,13 +41,13 @@ namespace Svelto.ECS return ref dictionary.GetOrAdd(_ID.entityID); } - public ref T Get() where T : struct, IEntityComponent + public ref T Get() where T : struct, IBaseEntityComponent { return ref (_group[new RefWrapperType(ComponentBuilder.ENTITY_COMPONENT_TYPE)] as ITypeSafeDictionary) .GetValueByRef(_ID.entityID); } - public bool Has() where T : struct, IEntityComponent + public bool Has() where T : struct, IBaseEntityComponent { if (_group.TryGetValue(new RefWrapperType(ComponentBuilder.ENTITY_COMPONENT_TYPE), out var typeSafeDictionary)) diff --git a/Core/EntityViewUtility.cs b/Core/EntityViewUtility.cs index a990550..0023296 100644 --- a/Core/EntityViewUtility.cs +++ b/Core/EntityViewUtility.cs @@ -13,7 +13,7 @@ namespace Svelto.ECS public ECSTuple(T1 implementor, T2 v) { - instance = implementor; + instance = implementor; numberOfImplementations = v; } } @@ -22,31 +22,28 @@ namespace Svelto.ECS static class EntityComponentUtility { const string DUPLICATE_IMPLEMENTOR_ERROR = - "Svelto.ECS the same component is implemented with more than one implementor. This is " - + "considered an error and MUST be fixed. "; + "Svelto.ECS the same component is implemented with more than one implementor. This is " + + "considered an error and MUST be fixed. "; const string NULL_IMPLEMENTOR_ERROR = - "Svelto.ECS Null implementor, please be careful about the implementors passed to avoid " - + "performance loss "; + "Svelto.ECS Null implementor, please be careful about the implementors passed to avoid " + + "performance loss "; const string NOT_FOUND_EXCEPTION = "Svelto.ECS Implementor not found for an EntityComponent. "; - public static void SetEntityViewComponentImplementors - (this IComponentBuilder componentBuilder, ref T entityComponent - , FasterList>> entityComponentBlazingFastReflection - , IEnumerable implementors -#if DEBUG && !PROFILE_SVELTO - ,Dictionary> implementorsByType -#else - , Dictionary implementorsByType -#endif - , Dictionary cachedTypeInterfaces) + internal static void SetEntityViewComponentImplementors(this IComponentBuilder componentBuilder, + ref T entityComponent, IEnumerable implementors, + ComponentBuilder.EntityViewComponentCache localCache) where T : struct, IBaseEntityComponent { - DBC.ECS.Check.Require(implementors != null, NULL_IMPLEMENTOR_ERROR.FastConcat(" entityComponent " - , componentBuilder - .GetEntityComponentType().ToString())); + DBC.ECS.Check.Require(implementors != null, + NULL_IMPLEMENTOR_ERROR.FastConcat(" entityComponent ", + componentBuilder.GetEntityComponentType().ToString())); + var cachedTypeInterfaces = localCache.cachedTypes; + var implementorsByType = localCache.implementorsByType; + var entityComponentBlazingFastReflection = localCache.cachedFields; + foreach (var implementor in implementors) { DBC.ECS.Check.Require(implementor != null, "invalid null implementor used to build an entity"); @@ -95,16 +92,16 @@ namespace Svelto.ECS if (implementorsByType.TryGetValue(fieldType, out implementor) == false) { - var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name - + " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name); + var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + + " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name); throw e; } #if DEBUG && !PROFILE_SVELTO if (implementor.numberOfImplementations > 1) throw new ECSException(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat( - "Component Type: ", fieldType.Name, " implementor: ", implementor.instance.ToString()) + - " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name); + "Component Type: ", fieldType.Name, " implementor: ", implementor.instance.ToString()) + + " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name); #endif #if DEBUG && !PROFILE_SVELTO fieldSetter.Value(ref entityComponent, implementor.instance); diff --git a/Core/Filters/EnginesRoot.Filters.cs b/Core/Filters/EnginesRoot.Filters.cs index 979cfab..c8148c6 100644 --- a/Core/Filters/EnginesRoot.Filters.cs +++ b/Core/Filters/EnginesRoot.Filters.cs @@ -1,4 +1,5 @@ -using Svelto.DataStructures; +using System.Collections.Generic; +using Svelto.DataStructures; using Svelto.DataStructures.Native; using Svelto.ECS.DataStructures; using Svelto.ECS.Internal; @@ -45,33 +46,69 @@ namespace Svelto.ECS } } - void RemoveEntityFromPersistentFilters(FasterList<(uint, string)> entityIDs, ExclusiveGroupStruct fromGroup, - RefWrapperType refWrapperType, ITypeSafeDictionary fromDic) + /// + /// Persistent filters are automatically updated by the framework. If entities are removed from the database + /// the filters are updated consequentially. + /// + /// + /// + /// + /// + /// + void RemoveEntitiesFromPersistentFilters + (FasterList<(uint entityID, string)> entityIDsRemoved, ExclusiveGroupStruct fromGroup, RefWrapperType refWrapperType + , ITypeSafeDictionary fromDic, FasterList entityIDsLeftAndAffectedByRemoval) { //is there any filter used by this component? - if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue(new NativeRefWrapperType(refWrapperType), - out NativeDynamicArrayCast listOfFilters)) + if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue( + new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast listOfFilters) == true) { var numberOfFilters = listOfFilters.count; + var filters = _persistentEntityFilters.unsafeValues; + + //remove duplicates + _transientEntityIDsLeftWithoutDuplicates.FastClear(); + var entityAffectedCount = entityIDsLeftAndAffectedByRemoval.count; + for (int i = 0; i < entityAffectedCount; i++) + { + _transientEntityIDsLeftWithoutDuplicates[entityIDsLeftAndAffectedByRemoval[i]] = -1; + } + for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex) { - //we are going to remove multiple entities, this means that the dictionary count would decrease - //for each entity removed from each filter - //we need to keep a copy to reset to the original count for each filter - var currentLastIndex = (uint)fromDic.count - 1; - var filters = _persistentEntityFilters.unsafeValues; - var persistentFilter = filters[listOfFilters[filterIndex]]._filtersPerGroup; - - if (persistentFilter.TryGetValue(fromGroup, out var groupFilter)) + //foreach filter linked to this component + var persistentFiltersPerGroup = filters[listOfFilters[filterIndex]]._filtersPerGroup; + + //get the filter linked to this group + if (persistentFiltersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter)) { - var entitiesCount = entityIDs.count; - + var entitiesCount = entityIDsRemoved.count; + + //foreach entity to remove, remove it from the filter (if present) for (int entityIndex = 0; entityIndex < entitiesCount; ++entityIndex) { - uint fromentityID = entityIDs[entityIndex].Item1; - var fromIndex = fromDic.GetIndex(fromentityID); + //the current entity id to remove + uint fromEntityID = entityIDsRemoved[entityIndex].entityID; + + fromGroupFilter.Remove(fromEntityID); //Remove works even if the ID is not found (just returns false) + } - groupFilter.RemoveWithSwapBack(fromentityID, fromIndex, currentLastIndex--); + //when a component is removed from a component array, a remove swap back happens. This means + //that not only we have to remove the index of the component of the entity deleted from the array + //but we need also to update the index of the component that has been swapped in the cell + //of the deleted component + //entityIDsAffectedByRemoval tracks all the entitiesID of the components that need to be updated + //in the filters because their indices in the array changed. + foreach (var entity in _transientEntityIDsLeftWithoutDuplicates) + { + var entityId = entity.key; + if (fromGroupFilter.Exists(entityId)) //does the entityID that has been swapped exist in the filter? + { + if (entity.value == -1) + entity.value = (int)fromDic.GetIndex(entityId); //let's find the index of the entityID in the dictionary only once + + fromGroupFilter._entityIDToDenseIndex[entityId] = (uint) entity.value; //update the index in the filter of the component that has been swapped + } } } } @@ -79,73 +116,68 @@ namespace Svelto.ECS } //this method is called by the framework only if listOfFilters.count > 0 - void SwapEntityBetweenPersistentFilters(FasterList<(uint, uint, string)> fromEntityToEntityIDs, - FasterDictionary beforeSubmissionFromIDs, ITypeSafeDictionary toComponentsDictionary, - ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, uint fromDictionaryCount, - NativeDynamicArrayCast listOfFilters) + void SwapEntityBetweenPersistentFilters + (FasterList<(uint, uint, string)> fromEntityToEntityIDs, ITypeSafeDictionary fromDic + , ITypeSafeDictionary toDic, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup + , RefWrapperType refWrapperType, FasterList entityIDsLeftAndAffectedByRemoval) { - DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?"); - var numberOfFilters = listOfFilters.count; - - /// fromEntityToEntityIDs are the ID of the entities to swap from the from group to the to group. - /// for this component type. for each component type, there is only one set of fromEntityToEntityIDs - /// per from/to group. - /// The complexity of this function is that the ToDictionary is already updated, so the toIndex - /// is actually correct and guaranteed to be valid. However the beforeSubmissionFromIDs are the - /// indices of the entities in the FromDictionary BEFORE the submission happens, so before the - /// entities are actually removed from the dictionary. - for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex) + //is there any filter used by this component? + if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue( + new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast listOfFilters) == true) { - //we are going to remove multiple entities, this means that the dictionary count would decrease - //for each entity removed from each filter - //we need to keep a copy to reset to the original count for each filter - var currentLastIndex = fromDictionaryCount; - - //if the group has a filter linked: - EntityFilterCollection persistentFilter = - _persistentEntityFilters.unsafeValues[listOfFilters[filterIndex]]; - if (persistentFilter._filtersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter)) + DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?"); + var numberOfFilters = listOfFilters.count; + + //remove duplicates + _transientEntityIDsLeftWithoutDuplicates.FastClear(); + var entityAffectedCount = entityIDsLeftAndAffectedByRemoval.count; + for (int i = 0; i < entityAffectedCount; i++) { - EntityFilterCollection.GroupFilters groupFilterTo = default; + _transientEntityIDsLeftWithoutDuplicates[entityIDsLeftAndAffectedByRemoval[i]] = -1; + } - foreach (var (fromEntityID, toEntityID, _) in fromEntityToEntityIDs) + /// fromEntityToEntityIDs are the IDs of the entities to swap from the from group to the to group. + /// for this component type. for each component type, there is only one set of fromEntityToEntityIDs + /// per from/to group. + for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex) + { + //if the group has a filter linked: + EntityFilterCollection persistentFilter = + _persistentEntityFilters.unsafeValues[listOfFilters[filterIndex]]; + + if (persistentFilter._filtersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter)) { - //if there is an entity, it must be moved to the to filter - if (fromGroupFilter.Exists(fromEntityID) == true) - { - var toIndex = toComponentsDictionary.GetIndex(toEntityID); + EntityFilterCollection.GroupFilters groupFilterTo = default; - if (groupFilterTo.isValid == false) - groupFilterTo = persistentFilter.GetGroupFilter(toGroup); - - groupFilterTo.Add(toEntityID, toIndex); + foreach (var (fromEntityID, toEntityID, _) in fromEntityToEntityIDs) + { + var toIndex = toDic.GetIndex(toEntityID); //todo: optimize this should be calculated only once and not once per filter + //if there is an entity, it must be moved to the to filter + if (fromGroupFilter.Exists(fromEntityID) == true) + { + if (groupFilterTo.isValid == false) + groupFilterTo = persistentFilter.GetOrCreateGroupFilter(toGroup); + + groupFilterTo.Add(toEntityID, toIndex); + } } - } - - foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs) - { - //fromIndex is the same of the index in the filter if the entity is in the filter, but - //we need to update the entity index of the last entity swapped from the dictionary even - //in the case when the fromEntity is not present in the filter. - uint fromIndex; //index in the from dictionary - if (fromGroupFilter.Exists(fromEntityID)) - fromIndex = fromGroupFilter._entityIDToDenseIndex[fromEntityID]; - else - fromIndex = beforeSubmissionFromIDs[fromEntityID]; - - //Removing an entity from the dictionary may affect the index of the last entity in the - //values dictionary array, so we need to to update the indices of the affected entities. - //must be outside because from may not be present in the filter, but last index is - - //for each entity removed from the from group, I have to update it's index in the - //from filter. An entity removed from the DB is always swapped back, which means - //it's current position is taken by the last entity in the dictionary array. - - //this means that the index of the last entity will change to the index of the - //replaced entity + foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs) + { + fromGroupFilter.Remove(fromEntityID); //Remove works even if the ID is not found (just returns false) + } - fromGroupFilter.RemoveWithSwapBack(fromEntityID, fromIndex, currentLastIndex--); + foreach (var entity in _transientEntityIDsLeftWithoutDuplicates) + { + var entityId = entity.key; + if (fromGroupFilter.Exists(entityId)) + { + if (entity.value == -1) + entity.value = (int)fromDic.GetIndex(entityId); + + fromGroupFilter._entityIDToDenseIndex[entityId] = (uint) entity.value; + } + } } } } diff --git a/Core/Filters/EntitiesDB.Filters.cs b/Core/Filters/EntitiesDB.Filters.cs index 161d36c..0037fbc 100644 --- a/Core/Filters/EntitiesDB.Filters.cs +++ b/Core/Filters/EntitiesDB.Filters.cs @@ -5,7 +5,6 @@ using Svelto.DataStructures; using Svelto.DataStructures.Native; using Svelto.ECS.DataStructures; - namespace Svelto.ECS { public struct FilterContextID @@ -18,6 +17,11 @@ namespace Svelto.ECS this.id = id; } + + public static FilterContextID GetNewContextID() + { + return EntitiesDB.SveltoFilters.GetNewContextID(); + } } public readonly struct CombinedFilterID @@ -44,7 +48,7 @@ namespace Svelto.ECS //since the user can choose their own filterID, in order to avoid collisions between //filters of the same type, the FilterContext is provided. The type is identified through //TypeCounter - public static long CombineFilterIDs(CombinedFilterID combinedFilterID) where T: struct, IEntityComponent + public static long CombineFilterIDs(CombinedFilterID combinedFilterID) where T: struct, IBaseEntityComponent { var id = (uint)ComponentID.id.Data; @@ -134,7 +138,7 @@ namespace Svelto.ECS [Unity.Collections.NotBurstCompatible] #endif public ref EntityFilterCollection GetOrCreatePersistentFilter(int filterID, FilterContextID filterContextId) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { return ref GetOrCreatePersistentFilter(new CombinedFilterID(filterID, filterContextId)); } @@ -142,7 +146,7 @@ namespace Svelto.ECS [Unity.Collections.NotBurstCompatible] #endif public ref EntityFilterCollection GetOrCreatePersistentFilter(CombinedFilterID filterID) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); @@ -163,13 +167,13 @@ namespace Svelto.ECS } public ref EntityFilterCollection GetPersistentFilter(int filterID, FilterContextID filterContextId) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { return ref GetPersistentFilter(new CombinedFilterID(filterID, filterContextId)); } public ref EntityFilterCollection GetPersistentFilter(CombinedFilterID filterID) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); @@ -180,7 +184,7 @@ namespace Svelto.ECS } public bool TryGetPersistentFilter(CombinedFilterID combinedFilterID, out EntityFilterCollection entityCollection) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(combinedFilterID); @@ -194,7 +198,7 @@ namespace Svelto.ECS return false; } - public EntityFilterCollectionsEnumerator GetPersistentFilters() where T : unmanaged, IEntityComponent + public EntityFilterCollectionsEnumerator GetPersistentFilters() where T : unmanaged, IBaseEntityComponent { if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex( new NativeRefWrapperType(new RefWrapperType(typeof(T))), out var index) == true) @@ -309,7 +313,7 @@ namespace Svelto.ECS /// /// public ref EntityFilterCollection GetOrCreateTransientFilter(CombinedFilterID filterID) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); @@ -324,7 +328,7 @@ namespace Svelto.ECS } public bool TryGetTransientFilter(CombinedFilterID filterID, out EntityFilterCollection entityCollection) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); diff --git a/Core/Filters/EntitiesDB.LegacyFilters.cs b/Core/Filters/EntitiesDB.LegacyFilters.cs index 2cb913b..b7e14ac 100644 --- a/Core/Filters/EntitiesDB.LegacyFilters.cs +++ b/Core/Filters/EntitiesDB.LegacyFilters.cs @@ -32,14 +32,14 @@ namespace Svelto.ECS } public ref LegacyFilterGroup CreateOrGetFilterForGroup(int filterID, ExclusiveGroupStruct groupID) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { var refWrapper = TypeRefWrapper.wrapper; return ref CreateOrGetFilterForGroup(filterID, groupID, refWrapper); } - public bool HasFiltersForGroup(ExclusiveGroupStruct groupID) where T : struct, IEntityComponent + public bool HasFiltersForGroup(ExclusiveGroupStruct groupID) where T : struct, IBaseEntityComponent { if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) return false; @@ -48,7 +48,7 @@ namespace Svelto.ECS } public bool HasFilterForGroup(int filterID, ExclusiveGroupStruct groupID) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) return false; @@ -60,7 +60,7 @@ namespace Svelto.ECS } public ref LegacyGroupFilters CreateOrGetFiltersForGroup(ExclusiveGroupStruct groupID) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { var fasterDictionary = _filtersLegacy.GetOrAdd(TypeRefWrapper.wrapper, () => new FasterDictionary()); @@ -70,7 +70,7 @@ namespace Svelto.ECS } public ref LegacyGroupFilters GetFiltersForGroup(ExclusiveGroupStruct groupID) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { #if DEBUG && !PROFILE_SVELTO if (_filtersLegacy.ContainsKey(TypeRefWrapper.wrapper) == false) @@ -84,7 +84,7 @@ namespace Svelto.ECS } public ref LegacyFilterGroup GetFilterForGroup(int filterId, ExclusiveGroupStruct groupID) - where T : struct, IEntityComponent + where T : struct, IBaseEntityComponent { #if DEBUG && !PROFILE_SVELTO if (_filtersLegacy.ContainsKey(TypeRefWrapper.wrapper) == false) @@ -97,7 +97,7 @@ namespace Svelto.ECS } public bool TryGetFilterForGroup(int filterId, ExclusiveGroupStruct groupID, - out LegacyFilterGroup groupLegacyFilter) where T : struct, IEntityComponent + out LegacyFilterGroup groupLegacyFilter) where T : struct, IBaseEntityComponent { groupLegacyFilter = default; @@ -114,7 +114,7 @@ namespace Svelto.ECS } public bool TryGetFiltersForGroup(ExclusiveGroupStruct groupID, - out LegacyGroupFilters legacyGroupFilters) where T : struct, IEntityComponent + out LegacyGroupFilters legacyGroupFilters) where T : struct, IBaseEntityComponent { legacyGroupFilters = default; @@ -166,7 +166,7 @@ namespace Svelto.ECS fasterDictionary[@group].DisposeFilter(resetFilterID); } - public bool TryRemoveEntityFromFilter(int filtersID, EGID egid) where T : struct, IEntityComponent + public bool TryRemoveEntityFromFilter(int filtersID, EGID egid) where T : struct, IBaseEntityComponent { if (TryGetFilterForGroup(filtersID, egid.groupID, out var filter)) return filter.TryRemove(egid.entityID); @@ -174,7 +174,7 @@ namespace Svelto.ECS return false; } - public void RemoveEntityFromFilter(int filtersID, EGID egid) where T : struct, IEntityComponent + public void RemoveEntityFromFilter(int filtersID, EGID egid) where T : struct, IBaseEntityComponent { ref var filter = ref GetFilterForGroup(filtersID, egid.groupID); diff --git a/Core/Filters/EntityFilterCollection.cs b/Core/Filters/EntityFilterCollection.cs index b20828b..aa673c2 100644 --- a/Core/Filters/EntityFilterCollection.cs +++ b/Core/Filters/EntityFilterCollection.cs @@ -1,4 +1,5 @@ -using System.Runtime.CompilerServices; +using System; +using System.Runtime.CompilerServices; using Svelto.Common; using Svelto.DataStructures.Native; using Svelto.ECS.Native; @@ -21,14 +22,14 @@ namespace Svelto.ECS public EntityFilterIterator GetEnumerator() => new EntityFilterIterator(this); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Add(EGID egid, NativeEGIDMapper mmap) where T : unmanaged, IEntityComponent + public bool Add(EGID egid, NativeEGIDMapper mmap) where T : unmanaged, IBaseEntityComponent { DBC.ECS.Check.Require(mmap.groupID == egid.groupID, "not compatible NativeEgidMapper used"); return Add(egid, mmap.GetIndex(egid.entityID)); } - public bool Add(EGID egid, NativeEGIDMultiMapper mmap) where T : unmanaged, IEntityComponent + public bool Add(EGID egid, NativeEGIDMultiMapper mmap) where T : unmanaged, IBaseEntityComponent { return Add(egid, mmap.GetIndex(egid)); } @@ -36,7 +37,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Add(EGID egid, uint toIndex) { - return GetGroupFilter(egid.groupID).Add(egid.entityID, toIndex); + return GetOrCreateGroupFilter(egid.groupID).Add(egid.entityID, toIndex); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -50,15 +51,31 @@ namespace Svelto.ECS { _filtersPerGroup[egid.groupID].Remove(egid.entityID); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Remove(uint entityID, ExclusiveGroupStruct groupID) + { + _filtersPerGroup[groupID].Remove(entityID); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Exists(EGID egid) { - return GetGroupFilter(egid.groupID).Exists(egid.entityID); + if (TryGetGroupFilter(egid.groupID, out var groupFilter)) + { + return groupFilter.Exists(egid.entityID); + } + return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public GroupFilters GetGroupFilter(ExclusiveGroupStruct group) + public bool TryGetGroupFilter(ExclusiveGroupStruct group, out GroupFilters groupFilter) + { + return _filtersPerGroup.TryGetValue(group, out groupFilter); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public GroupFilters GetOrCreateGroupFilter(ExclusiveGroupStruct group) { if (_filtersPerGroup.TryGetValue(group, out var groupFilter) == false) { @@ -68,6 +85,15 @@ namespace Svelto.ECS return groupFilter; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public GroupFilters GetGroupFilter(ExclusiveGroupStruct group) + { + if (_filtersPerGroup.TryGetValue(group, out var groupFilter) == true) + return groupFilter; + + throw new Exception($"no filter linked to group {group}"); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() @@ -116,32 +142,28 @@ namespace Svelto.ECS internal GroupFilters(ExclusiveGroupStruct group) : this() { _entityIDToDenseIndex = new SharedSveltoDictionaryNative(1); - _indexToEntityId = new SharedSveltoDictionaryNative(1); _group = group; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Add(uint entityId, uint entityIndex) { //TODO: when sentinels are finished, we need to add AsWriter here - if (_entityIDToDenseIndex.TryAdd(entityId, entityIndex, out _)) - { - _indexToEntityId[entityIndex] = entityId; - return true; - } - - return false; + return _entityIDToDenseIndex.TryAdd(entityId, entityIndex, out _); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Exists(uint entityId) => _entityIDToDenseIndex.ContainsKey(entityId); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Remove(uint entityId) { - _indexToEntityId.Remove(_entityIDToDenseIndex[entityId]); _entityIDToDenseIndex.Remove(entityId); } public EntityFilterIndices indices { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { var values = _entityIDToDenseIndex.GetValues(out var count); @@ -149,50 +171,31 @@ namespace Svelto.ECS } } + public uint this[uint entityId] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _entityIDToDenseIndex[entityId]; + } + public int count => _entityIDToDenseIndex.count; public bool isValid => _entityIDToDenseIndex.isValid; [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void RemoveWithSwapBack(uint entityId, uint entityIndex, uint lastIndex) - { - // Check if the last index is part of the filter as an entity, in that case - //we need to update the filter - if (entityIndex != lastIndex && _indexToEntityId.TryGetValue(lastIndex, out var lastEntityID)) - { - _entityIDToDenseIndex[lastEntityID] = entityIndex; - _indexToEntityId[entityIndex] = lastEntityID; - - _indexToEntityId.Remove(lastIndex); - } - else - { - // We don't need to check if the entityIndex is a part of the dictionary. - // The Remove function will check for us. - _indexToEntityId.Remove(entityIndex); - } - - // We don't need to check if the entityID is part of the dictionary. - // The Remove function will check for us. - _entityIDToDenseIndex.Remove(entityId); - } - internal void Clear() { - _indexToEntityId.FastClear(); _entityIDToDenseIndex.FastClear(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void Dispose() { _entityIDToDenseIndex.Dispose(); - _indexToEntityId.Dispose(); } internal ExclusiveGroupStruct group => _group; - SharedSveltoDictionaryNative _indexToEntityId; internal SharedSveltoDictionaryNative _entityIDToDenseIndex; readonly ExclusiveGroupStruct _group; } } -} \ No newline at end of file +} diff --git a/Core/Filters/NativeEntityFilterCollection.cs b/Core/Filters/NativeEntityFilterCollection.cs index b54ea0f..d2e0a10 100644 --- a/Core/Filters/NativeEntityFilterCollection.cs +++ b/Core/Filters/NativeEntityFilterCollection.cs @@ -4,7 +4,7 @@ using Svelto.ECS.Native; namespace Svelto.ECS { - public struct NativeEntityFilterCollection where T : unmanaged, IEntityComponent + public struct NativeEntityFilterCollection where T : unmanaged, IBaseEntityComponent { internal NativeEntityFilterCollection(NativeEGIDMultiMapper mmap) { diff --git a/Core/Filters/NativeEntityFilterIterator.cs b/Core/Filters/NativeEntityFilterIterator.cs index db9d75a..151b882 100644 --- a/Core/Filters/NativeEntityFilterIterator.cs +++ b/Core/Filters/NativeEntityFilterIterator.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS { - public readonly ref struct NativeEntityFilterIterator where T : unmanaged, IEntityComponent + public readonly ref struct NativeEntityFilterIterator where T : unmanaged, IBaseEntityComponent { internal NativeEntityFilterIterator(NativeEntityFilterCollection filter) { diff --git a/Core/GlobalTypeID.cs b/Core/GlobalTypeID.cs index 0633a19..b59c894 100644 --- a/Core/GlobalTypeID.cs +++ b/Core/GlobalTypeID.cs @@ -18,7 +18,7 @@ namespace Svelto.ECS void FillFromByteArray(EntityInitializer init, NativeBag buffer); } - class Filler : IFiller where T : struct, IEntityComponent + class Filler : IFiller where T : struct, IBaseEntityComponent { static Filler() { @@ -50,7 +50,7 @@ namespace Svelto.ECS TYPE_IDS = new Svelto.DataStructures.FasterList(); } - internal static void Register(IFiller entityBuilder) where T : struct, IEntityComponent + internal static void Register(IFiller entityBuilder) where T : struct, IBaseEntityComponent { var location = EntityComponentID.ID.Data = GlobalTypeID.NextID(); TYPE_IDS.AddAt(location, entityBuilder); diff --git a/Core/EntitiesDB.FindGroups.cs b/Core/Groups/EntitiesDB.FindGroups.cs similarity index 83% rename from Core/EntitiesDB.FindGroups.cs rename to Core/Groups/EntitiesDB.FindGroups.cs index 41186fd..824750a 100644 --- a/Core/EntitiesDB.FindGroups.cs +++ b/Core/Groups/EntitiesDB.FindGroups.cs @@ -7,11 +7,11 @@ namespace Svelto.ECS { public partial class EntitiesDB { - public LocalFasterReadOnlyList FindGroups() where T1 : IEntityComponent + public LocalFasterReadOnlyList FindGroups() where T1 : IBaseEntityComponent { FasterList result = localgroups.Value.groupArray; result.FastClear(); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper , out FasterDictionary result1) == false) return result; @@ -32,15 +32,15 @@ namespace Svelto.ECS } public LocalFasterReadOnlyList FindGroups() - where T1 : IEntityComponent where T2 : IEntityComponent + where T1 : IBaseEntityComponent where T2 : IBaseEntityComponent { FasterList result = localgroups.Value.groupArray; result.FastClear(); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper , out FasterDictionary result1) == false) return result; - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper , out FasterDictionary result2) == false) return result; @@ -83,18 +83,18 @@ namespace Svelto.ECS /// /// public LocalFasterReadOnlyList FindGroups() - where T1 : IEntityComponent where T2 : IEntityComponent where T3 : IEntityComponent + where T1 : IBaseEntityComponent where T2 : IBaseEntityComponent where T3 : IBaseEntityComponent { FasterList> localArray = localgroups.Value.listOfGroups; - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); @@ -133,24 +133,24 @@ namespace Svelto.ECS } public LocalFasterReadOnlyList FindGroups() - where T1 : IEntityComponent - where T2 : IEntityComponent - where T3 : IEntityComponent - where T4 : IEntityComponent + where T1 : IBaseEntityComponent + where T2 : IBaseEntityComponent + where T3 : IBaseEntityComponent + where T4 : IBaseEntityComponent { FasterList> localArray = localgroups.Value.listOfGroups; - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerEntity.TryGetValue(TypeRefWrapper.wrapper, out localArray[3]) == false || localArray[3].count == 0) + if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[3]) == false || localArray[3].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); @@ -195,10 +195,10 @@ namespace Svelto.ECS internal FasterDictionary FindGroups_INTERNAL(Type type) { - if (groupsPerEntity.ContainsKey(new RefWrapperType(type)) == false) + if (groupsPerComponent.ContainsKey(new RefWrapperType(type)) == false) return _emptyDictionary; - return groupsPerEntity[new RefWrapperType(type)]; + return groupsPerComponent[new RefWrapperType(type)]; } struct GroupsList diff --git a/Core/EntitiesDB.FindGroups.cs.meta b/Core/Groups/EntitiesDB.FindGroups.cs.meta similarity index 83% rename from Core/EntitiesDB.FindGroups.cs.meta rename to Core/Groups/EntitiesDB.FindGroups.cs.meta index f80c63f..76312de 100644 --- a/Core/EntitiesDB.FindGroups.cs.meta +++ b/Core/Groups/EntitiesDB.FindGroups.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3a9f8fa92212370fb4baed7ca10e1404 +guid: c002b07122073225abc2acecbf2da276 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Core/EntityGroupNotFoundException.cs b/Core/Groups/EntityGroupNotFoundException.cs similarity index 100% rename from Core/EntityGroupNotFoundException.cs rename to Core/Groups/EntityGroupNotFoundException.cs diff --git a/Core/EntityGroupNotFoundException.cs.meta b/Core/Groups/EntityGroupNotFoundException.cs.meta similarity index 83% rename from Core/EntityGroupNotFoundException.cs.meta rename to Core/Groups/EntityGroupNotFoundException.cs.meta index 1168d44..073b61e 100644 --- a/Core/EntityGroupNotFoundException.cs.meta +++ b/Core/Groups/EntityGroupNotFoundException.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f5290f4d2cdc30d4bb27969f6f41d052 +guid: c20e19ea059133b29403f51e40968d24 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Core/GroupHashMap.cs b/Core/Groups/GroupHashMap.cs similarity index 100% rename from Core/GroupHashMap.cs rename to Core/Groups/GroupHashMap.cs diff --git a/Core/GroupHashMap.cs.meta b/Core/Groups/GroupHashMap.cs.meta similarity index 83% rename from Core/GroupHashMap.cs.meta rename to Core/Groups/GroupHashMap.cs.meta index 8dabe15..3b4b2eb 100644 --- a/Core/GroupHashMap.cs.meta +++ b/Core/Groups/GroupHashMap.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: dd3f86070a8934a18ace9dfe566d9784 +guid: 8f261a3fa27635799ac4429a7992099d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Core/GroupNamesMap.cs b/Core/Groups/GroupNamesMap.cs similarity index 100% rename from Core/GroupNamesMap.cs rename to Core/Groups/GroupNamesMap.cs diff --git a/Core/GroupNamesMap.cs.meta b/Core/Groups/GroupNamesMap.cs.meta similarity index 83% rename from Core/GroupNamesMap.cs.meta rename to Core/Groups/GroupNamesMap.cs.meta index 20602e9..b034b8d 100644 --- a/Core/GroupNamesMap.cs.meta +++ b/Core/Groups/GroupNamesMap.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1b34885b789f32b99d3dc9131491f56f +guid: cf2312faeca534e1be55d9b538b0eb6a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Core/QueryGroups.cs b/Core/Groups/QueryGroups.cs similarity index 99% rename from Core/QueryGroups.cs rename to Core/Groups/QueryGroups.cs index 98654c6..99c4bad 100644 --- a/Core/QueryGroups.cs +++ b/Core/Groups/QueryGroups.cs @@ -210,7 +210,7 @@ namespace Svelto.ECS.Experimental readonly FasterReadOnlyList _group; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count(EntitiesDB entitiesDB) where T : struct, IEntityComponent + public int Count(EntitiesDB entitiesDB) where T : struct, IBaseEntityComponent { var count = 0; @@ -220,7 +220,7 @@ namespace Svelto.ECS.Experimental return count; } - public int Max(EntitiesDB entitiesDB) where T : struct, IEntityComponent + public int Max(EntitiesDB entitiesDB) where T : struct, IBaseEntityComponent { var max = 0; diff --git a/Core/QueryGroups.cs.meta b/Core/Groups/QueryGroups.cs.meta similarity index 83% rename from Core/QueryGroups.cs.meta rename to Core/Groups/QueryGroups.cs.meta index d5911b4..c12f1d1 100644 --- a/Core/QueryGroups.cs.meta +++ b/Core/Groups/QueryGroups.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e3063c92835c3dcfb72ee2221375b2c0 +guid: 1bdd444089d63f6db21d58c77747faad MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Core/Hybrid/IEntityViewComponent.cs b/Core/Hybrid/IEntityViewComponent.cs index 10c248b..2b5c642 100644 --- a/Core/Hybrid/IEntityViewComponent.cs +++ b/Core/Hybrid/IEntityViewComponent.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS.Hybrid { - public interface IManagedComponent:IEntityComponent + public interface IManagedComponent:IBaseEntityComponent {} public interface IEntityViewComponent:IManagedComponent diff --git a/Core/IBaseEntityComponent.cs b/Core/IBaseEntityComponent.cs new file mode 100644 index 0000000..669c9f9 --- /dev/null +++ b/Core/IBaseEntityComponent.cs @@ -0,0 +1,11 @@ +namespace Svelto.ECS +{ + ///Entity Components MUST implement IEntityComponent + public interface IBaseEntityComponent + { + } + + public interface IEntityComponent:IBaseEntityComponent + { + } +} \ No newline at end of file diff --git a/Core/IBaseEntityComponent.cs.meta b/Core/IBaseEntityComponent.cs.meta new file mode 100644 index 0000000..af4e986 --- /dev/null +++ b/Core/IBaseEntityComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8677309fad563a32bd517e93d87296af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Core/IEngine.cs b/Core/IEngine.cs index ca28804..74c0c35 100644 --- a/Core/IEngine.cs +++ b/Core/IEngine.cs @@ -65,12 +65,12 @@ namespace Svelto.ECS /// Interface to mark an Engine as reacting on entities added /// /// - public interface IReactOnAdd : IReactOnAdd where T : IEntityComponent + public interface IReactOnAdd : IReactOnAdd where T : IBaseEntityComponent { void Add(ref T entityComponent, EGID egid); } - public interface IReactOnAddEx : IReactOnAddEx where T : struct, IEntityComponent + public interface IReactOnAddEx : IReactOnAddEx where T : struct, IBaseEntityComponent { void Add((uint start, uint end) rangeOfEntities, in EntityCollection collection, ExclusiveGroupStruct groupID); @@ -80,18 +80,22 @@ namespace Svelto.ECS /// Interface to mark an Engine as reacting on entities removed /// /// - public interface IReactOnRemove : IReactOnRemove where T : IEntityComponent + public interface IReactOnRemove : IReactOnRemove where T : IBaseEntityComponent { void Remove(ref T entityComponent, EGID egid); } + + public interface IReactOnAddAndRemoveEx : IReactOnAddEx, IReactOnRemoveEx where T : struct, IBaseEntityComponent + { + } - public interface IReactOnRemoveEx : IReactOnRemoveEx where T : struct, IEntityComponent + public interface IReactOnRemoveEx : IReactOnRemoveEx where T : struct, IBaseEntityComponent { void Remove((uint start, uint end) rangeOfEntities, in EntityCollection collection, ExclusiveGroupStruct groupID); } - public interface IReactOnAddAndRemove : IReactOnAdd, IReactOnRemove where T : IEntityComponent + public interface IReactOnAddAndRemove : IReactOnAdd, IReactOnRemove where T : IBaseEntityComponent { } @@ -100,7 +104,7 @@ namespace Svelto.ECS /// It can work together with IReactOnRemove which normally is not called on enginesroot disposed /// /// - public interface IReactOnDispose : IReactOnDispose where T : IEntityComponent + public interface IReactOnDispose : IReactOnDispose where T : IBaseEntityComponent { void Remove(ref T entityComponent, EGID egid); } @@ -109,12 +113,12 @@ namespace Svelto.ECS /// Interface to mark an Engine as reacting to entities swapping group /// /// - public interface IReactOnSwap : IReactOnSwap where T : IEntityComponent + public interface IReactOnSwap : IReactOnSwap where T : IBaseEntityComponent { void MovedTo(ref T entityComponent, ExclusiveGroupStruct previousGroup, EGID egid); } - public interface IReactOnSwapEx : IReactOnSwapEx where T : struct, IEntityComponent + public interface IReactOnSwapEx : IReactOnSwapEx where T : struct, IBaseEntityComponent { void MovedTo((uint start, uint end) rangeOfEntities, in EntityCollection collection, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup); diff --git a/Core/IEntityComponent.cs b/Core/IEntityComponent.cs deleted file mode 100644 index cf4d06c..0000000 --- a/Core/IEntityComponent.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Svelto.ECS -{ - ///Entity Components MUST implement IEntityComponent - public interface IEntityComponent - { - } -} \ No newline at end of file diff --git a/Core/IEntityComponent.cs.meta b/Core/IEntityComponent.cs.meta deleted file mode 100644 index 183eaf3..0000000 --- a/Core/IEntityComponent.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 25bd99235be530aaa1f75f0d01aaa408 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Core/SetEGIDWithoutBoxing.cs b/Core/SetEGIDWithoutBoxing.cs index 34e7607..0daf562 100644 --- a/Core/SetEGIDWithoutBoxing.cs +++ b/Core/SetEGIDWithoutBoxing.cs @@ -1,10 +1,10 @@ #if SLOW_SVELTO_SUBMISSION namespace Svelto.ECS.Internal { - delegate void SetEGIDWithoutBoxingActionCast(ref T target, EGID egid) where T : struct, IEntityComponent; - delegate void SetReferenceWithoutBoxingActionCast(ref T target, EntityReference egid) where T : struct, IEntityComponent; + delegate void SetEGIDWithoutBoxingActionCast(ref T target, EGID egid) where T : struct, IBaseEntityComponent; + delegate void SetReferenceWithoutBoxingActionCast(ref T target, EntityReference egid) where T : struct, IBaseEntityComponent; - static class SetEGIDWithoutBoxing where T : struct, IEntityComponent + static class SetEGIDWithoutBoxing where T : struct, IBaseEntityComponent { public static readonly SetEGIDWithoutBoxingActionCast SetIDWithoutBoxing = MakeSetter(); public static readonly SetReferenceWithoutBoxingActionCast SetRefWithoutBoxing = MakeSetterReference(); diff --git a/Core/SpecialEnumerators/DoubleIterationEnumerator.cs b/Core/SpecialEnumerators/DoubleIterationEnumerator.cs index 18afdab..9918bfb 100644 --- a/Core/SpecialEnumerators/DoubleIterationEnumerator.cs +++ b/Core/SpecialEnumerators/DoubleIterationEnumerator.cs @@ -2,7 +2,7 @@ using System; namespace Svelto.ECS { - public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IEntityComponent + public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IBaseEntityComponent { public DoubleEntitiesEnumerator(GroupsEnumerable groupsEnumerable) { _groupsEnumerable = groupsEnumerable; } @@ -130,8 +130,8 @@ namespace Svelto.ECS } } - public readonly ref struct DoubleIterationEnumerator where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent + public readonly ref struct DoubleIterationEnumerator where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent { public DoubleIterationEnumerator(GroupsEnumerable groupsEnumerable) { @@ -268,9 +268,9 @@ namespace Svelto.ECS /// /// /// - public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent + public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent { public DoubleEntitiesEnumerator(GroupsEnumerable groupsEnumerable) { @@ -409,10 +409,10 @@ namespace Svelto.ECS /// /// /// - public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent - where T4 : struct, IEntityComponent + public readonly ref struct DoubleEntitiesEnumerator where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent + where T4 : struct, IBaseEntityComponent { public DoubleEntitiesEnumerator(GroupsEnumerable groupsEnumerable) { diff --git a/Core/Streams/Consumer.cs b/Core/Streams/Consumer.cs index 8c79dcf..561acd4 100644 --- a/Core/Streams/Consumer.cs +++ b/Core/Streams/Consumer.cs @@ -4,7 +4,7 @@ using Svelto.DataStructures; namespace Svelto.ECS { - public struct Consumer : IDisposable where T : unmanaged, IEntityComponent + public struct Consumer : IDisposable where T : unmanaged, IBaseEntityComponent { internal Consumer(string name, uint capacity) : this() { diff --git a/Core/Streams/EnginesRoot.Streams.cs b/Core/Streams/EnginesRoot.Streams.cs index c1d369d..5d1ec94 100644 --- a/Core/Streams/EnginesRoot.Streams.cs +++ b/Core/Streams/EnginesRoot.Streams.cs @@ -5,14 +5,14 @@ namespace Svelto.ECS public partial class EnginesRoot { [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, IEntityComponent + internal Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, IBaseEntityComponent { return _entityStreams.GenerateConsumer(name, capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Consumer GenerateConsumer(ExclusiveGroupStruct group, string name, uint capacity) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { return _entityStreams.GenerateConsumer(@group, name, capacity); } diff --git a/Core/Streams/EntitiesDB.Streams.cs b/Core/Streams/EntitiesDB.Streams.cs index 609d1fb..9603ce1 100644 --- a/Core/Streams/EntitiesDB.Streams.cs +++ b/Core/Streams/EntitiesDB.Streams.cs @@ -5,7 +5,7 @@ namespace Svelto.ECS public partial class EntitiesDB { [MethodImpl(MethodImplOptions.AggressiveInlining)] - //Todo I should rename this method to reflect it's original intention + //Todo I should rename this method to reflect its original intention public void PublishEntityChange(EGID egid) where T : unmanaged, IEntityComponent { //Note: it is correct to publish the EGID at the moment of the publishing, as the responsibility of diff --git a/Core/Streams/EntitiesStreams.cs b/Core/Streams/EntitiesStreams.cs index 41b3ae2..933d0f8 100644 --- a/Core/Streams/EntitiesStreams.cs +++ b/Core/Streams/EntitiesStreams.cs @@ -15,7 +15,7 @@ namespace Svelto.ECS struct EntitiesStreams : IDisposable { internal Consumer GenerateConsumer(string name, uint capacity) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { if (_streams.ContainsKey(TypeRefWrapper.wrapper) == false) _streams[TypeRefWrapper.wrapper] = new EntityStream(); @@ -24,7 +24,7 @@ namespace Svelto.ECS } public Consumer GenerateConsumer(ExclusiveGroupStruct group, string name, uint capacity) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { if (_streams.ContainsKey(TypeRefWrapper.wrapper) == false) _streams[TypeRefWrapper.wrapper] = new EntityStream(); @@ -33,7 +33,7 @@ namespace Svelto.ECS return typeSafeStream.GenerateConsumer(group, name, capacity); } - internal void PublishEntity(ref T entity, EGID egid) where T : unmanaged, IEntityComponent + internal void PublishEntity(ref T entity, EGID egid) where T : unmanaged, IBaseEntityComponent { if (_streams.TryGetValue(TypeRefWrapper.wrapper, out var typeSafeStream)) (typeSafeStream as EntityStream).PublishEntity(ref entity, egid); diff --git a/Core/Streams/EntityStream.cs b/Core/Streams/EntityStream.cs index def2e1c..6f0fd0c 100644 --- a/Core/Streams/EntityStream.cs +++ b/Core/Streams/EntityStream.cs @@ -7,7 +7,7 @@ namespace Svelto.ECS void Dispose(); } - public class EntityStream : ITypeSafeStream where T : unmanaged, IEntityComponent + public class EntityStream : ITypeSafeStream where T : unmanaged, IBaseEntityComponent { readonly ThreadSafeFasterList> _consumers; diff --git a/Core/Streams/GenericentityStreamConsumerFactory.cs b/Core/Streams/GenericentityStreamConsumerFactory.cs index 05c7f13..e2e7ae3 100644 --- a/Core/Streams/GenericentityStreamConsumerFactory.cs +++ b/Core/Streams/GenericentityStreamConsumerFactory.cs @@ -12,14 +12,14 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public Consumer GenerateConsumer(string name, uint capacity) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { return _enginesRoot.Target.GenerateConsumer(name, capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Consumer GenerateConsumer(ExclusiveGroupStruct @group, string name, uint capacity) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { return _enginesRoot.Target.GenerateConsumer(group, name, capacity); } @@ -31,9 +31,9 @@ namespace Svelto.ECS public interface IEntityStreamConsumerFactory { - Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, IEntityComponent; + Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, IBaseEntityComponent; Consumer GenerateConsumer(ExclusiveGroupStruct @group, string name, uint capacity) - where T : unmanaged, IEntityComponent; + where T : unmanaged, IBaseEntityComponent; } } \ No newline at end of file diff --git a/Core/TypeSafeDictionaryFactory.cs b/Core/TypeSafeDictionaryFactory.cs index 7b2c550..47b472d 100644 --- a/Core/TypeSafeDictionaryFactory.cs +++ b/Core/TypeSafeDictionaryFactory.cs @@ -1,17 +1,28 @@ +using Svelto.Common; +using Svelto.ECS.Hybrid; using Svelto.ECS.Internal; namespace Svelto.ECS { - static class TypeSafeDictionaryFactory where T : struct, IEntityComponent + static class TypeSafeDictionaryFactory where T : struct, IBaseEntityComponent { + static readonly bool isUnmanaged = typeof(T).IsUnmanagedEx() + && typeof(IEntityViewComponent).IsAssignableFrom(typeof(T)) == false; + public static ITypeSafeDictionary Create() { - return new TypeSafeDictionary(1); + if (isUnmanaged) + return new UnmanagedTypeSafeDictionary(1); + + return new ManagedTypeSafeDictionary(1); } - + public static ITypeSafeDictionary Create(uint size) { - return new TypeSafeDictionary(size); + if (isUnmanaged) + return new UnmanagedTypeSafeDictionary(size); + + return new ManagedTypeSafeDictionary(size); } } } \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/AbstractionLayer.meta b/DataStructures/EntityIDs.meta similarity index 77% rename from Extensions/Unity/GameObjects/AbstractionLayer.meta rename to DataStructures/EntityIDs.meta index 5b6ac3f..44b5e8e 100644 --- a/Extensions/Unity/GameObjects/AbstractionLayer.meta +++ b/DataStructures/EntityIDs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0c4bbc498c0e37a9964adcc0511d8e73 +guid: 8066f1c47da83e12ac2b132ceaccaf04 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/DataStructures/EntityIDs/IEntityIDs.cs b/DataStructures/EntityIDs/IEntityIDs.cs new file mode 100644 index 0000000..629eec9 --- /dev/null +++ b/DataStructures/EntityIDs/IEntityIDs.cs @@ -0,0 +1,4 @@ +namespace Svelto.ECS.Internal +{ + public interface IEntityIDs { } +} \ No newline at end of file diff --git a/DataStructures/EntityIDs/IEntityIDs.cs.meta b/DataStructures/EntityIDs/IEntityIDs.cs.meta new file mode 100644 index 0000000..47f71cd --- /dev/null +++ b/DataStructures/EntityIDs/IEntityIDs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 774b2b8912f13957b877e14c99137edf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/EntityIDs/ManagedEntityIDs.cs b/DataStructures/EntityIDs/ManagedEntityIDs.cs new file mode 100644 index 0000000..d8acf71 --- /dev/null +++ b/DataStructures/EntityIDs/ManagedEntityIDs.cs @@ -0,0 +1,22 @@ +using Svelto.DataStructures; + +namespace Svelto.ECS.Internal +{ + public struct ManagedEntityIDs: IEntityIDs + { + public ManagedEntityIDs(MB> managed) + { + _managed = managed; + } + + public void Update(MB> managed) + { + _managed = managed; + } + + public uint this[uint index] => _managed[index].key; + public uint this[int index] => _managed[index].key; + + MB> _managed; + } +} \ No newline at end of file diff --git a/DataStructures/EntityIDs/ManagedEntityIDs.cs.meta b/DataStructures/EntityIDs/ManagedEntityIDs.cs.meta new file mode 100644 index 0000000..39cdaa2 --- /dev/null +++ b/DataStructures/EntityIDs/ManagedEntityIDs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad8b3dc156e23dadb8116e89155f70ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/EntityIDs/NativeEntityIDs.cs b/DataStructures/EntityIDs/NativeEntityIDs.cs new file mode 100644 index 0000000..be68fcd --- /dev/null +++ b/DataStructures/EntityIDs/NativeEntityIDs.cs @@ -0,0 +1,22 @@ +using Svelto.DataStructures; + +namespace Svelto.ECS.Internal +{ + public struct NativeEntityIDs: IEntityIDs + { + public NativeEntityIDs(NB> native) + { + _native = native; + } + + public void Update(in NB> unsafeKeys) + { + _native = unsafeKeys; + } + + public uint this[uint index] => _native[index].key; + public uint this[int index] => _native[index].key; + + NB> _native; + } +} \ No newline at end of file diff --git a/DataStructures/EntityIDs/NativeEntityIDs.cs.meta b/DataStructures/EntityIDs/NativeEntityIDs.cs.meta new file mode 100644 index 0000000..054cd7f --- /dev/null +++ b/DataStructures/EntityIDs/NativeEntityIDs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 679f27762d9d3068b5204bdcd3ce3b1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/ITypeSafeDictionary.cs b/DataStructures/ITypeSafeDictionary.cs index 9c95c9f..d0c9850 100644 --- a/DataStructures/ITypeSafeDictionary.cs +++ b/DataStructures/ITypeSafeDictionary.cs @@ -4,7 +4,7 @@ using Svelto.DataStructures; namespace Svelto.ECS.Internal { - public interface ITypeSafeDictionary : ITypeSafeDictionary where TValue : IEntityComponent + public interface ITypeSafeDictionary : ITypeSafeDictionary where TValue : IBaseEntityComponent { void Add(uint egidEntityId, in TValue entityComponent); @@ -14,7 +14,7 @@ namespace Svelto.ECS.Internal IBuffer GetValues(out uint count); ref TValue GetDirectValueByRef(uint key); ref TValue GetValueByRef(uint key); - EntityIDs entityIDs { get; } + IEntityIDs entityIDs { get; } } public interface ITypeSafeDictionary : IDisposable @@ -24,10 +24,16 @@ namespace Svelto.ECS.Internal ITypeSafeDictionary Create(); void AddEntitiesToDictionary - (ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId, in EnginesRoot.EntityReferenceMap entityLocator); - void RemoveEntitiesFromDictionary(FasterList<(uint, string)> infosToProcess); - void SwapEntitiesBetweenDictionaries(FasterList<(uint, uint, string)> infosToProcess, - ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary); + (ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId +#if SLOW_SVELTO_SUBMISSION + , in EnginesRoot.EntityReferenceMap entityLocator +#endif + ); + void RemoveEntitiesFromDictionary + (FasterList<(uint, string)> infosToProcess, FasterList entityIDsAffectedByRemoval); + void SwapEntitiesBetweenDictionaries + (FasterList<(uint, uint, string)> infosToProcess, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup + , ITypeSafeDictionary toComponentsDictionary, FasterList entityIDsAffectedByRemoval); //------------ diff --git a/DataStructures/ManagedTypeSafeDictionary.cs b/DataStructures/ManagedTypeSafeDictionary.cs new file mode 100644 index 0000000..5c29251 --- /dev/null +++ b/DataStructures/ManagedTypeSafeDictionary.cs @@ -0,0 +1,305 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using Svelto.Common; +using Svelto.DataStructures; +using Svelto.ECS.Hybrid; + +namespace Svelto.ECS.Internal +{ + public sealed class ManagedTypeSafeDictionary : ITypeSafeDictionary + where TValue : struct, IBaseEntityComponent + { + static readonly Type _type = typeof(TValue); +#if SLOW_SVELTO_SUBMISSION + static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type); + static readonly bool _hasReference = typeof(INeedEntityReference).IsAssignableFrom(_type); +#endif + static readonly ThreadLocal cachedEntityIDM = + new ThreadLocal(() => new ManagedEntityIDs()); + + public ManagedTypeSafeDictionary(uint size) + { + implMgd = + new SveltoDictionary>, ManagedStrategy, + ManagedStrategy>(size, Allocator.Managed); + } + + public IEntityIDs entityIDs + { + get + { + ref var unboxed = ref Unsafe.Unbox(cachedEntityIDM.Value); + + unboxed.Update(implMgd.unsafeKeys.ToRealBuffer()); + + return cachedEntityIDM.Value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ContainsKey(uint egidEntityId) + { + return implMgd.ContainsKey(egidEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint GetIndex(uint valueEntityId) + { + return implMgd.GetIndex(valueEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref TValue GetOrAdd(uint idEntityId) + { + return ref implMgd.GetOrAdd(idEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IBuffer GetValues(out uint count) + { + return implMgd.UnsafeGetValues(out count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref TValue GetDirectValueByRef(uint key) + { + return ref implMgd.GetDirectValueByRef(key); + } + + public ref TValue GetValueByRef(uint key) + { + return ref implMgd.GetValueByRef(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Has(uint key) + { + return implMgd.ContainsKey(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryFindIndex(uint entityId, out uint index) + { + return implMgd.TryFindIndex(entityId, out index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryGetValue(uint entityId, out TValue item) + { + return implMgd.TryGetValue(entityId, out item); + } + + public int count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => implMgd.count; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ITypeSafeDictionary Create() + { + return TypeSafeDictionaryFactory.Create(1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + implMgd.Clear(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void EnsureCapacity(uint size) + { + implMgd.EnsureCapacity(size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void IncreaseCapacityBy(uint size) + { + implMgd.IncreaseCapacityBy(size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Trim() + { + implMgd.Trim(); + } + + public void KeysEvaluator(Action action) + { + foreach (var key in implMgd.keys) + action(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(uint egidEntityId, in TValue entityComponent) + { + implMgd.Add(egidEntityId, entityComponent); + } + + public void Dispose() + { + implMgd.Dispose(); + + GC.SuppressFinalize(this); + } + + /// ********************************* + /// the following methods are executed during the submission of entities + /// ********************************* + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void AddEntitiesToDictionary + (ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId +#if SLOW_SVELTO_SUBMISSION + , in EnginesRoot.EntityReferenceMap entityLocator +#endif + ) + { + TypeSafeDictionaryMethods.AddEntitiesToDictionary(implMgd, toDictionary as ITypeSafeDictionary +#if SLOW_SVELTO_SUBMISSION +, entityLocator +#endif + , groupId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RemoveEntitiesFromDictionary + (FasterList<(uint, string)> infosToProcess, FasterList entityIDsAffectedByRemoval) + { + TypeSafeDictionaryMethods.RemoveEntitiesFromDictionary(infosToProcess, ref implMgd, entityIDsAffectedByRemoval); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SwapEntitiesBetweenDictionaries + (FasterList<(uint, uint, string)> infosToProcess, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary + , FasterList entityIDsAffectedByRemoval) + { + TypeSafeDictionaryMethods.SwapEntitiesBetweenDictionaries(infosToProcess, ref implMgd + , toComponentsDictionary as + ITypeSafeDictionary, fromGroup + , toGroup, entityIDsAffectedByRemoval); + } + + /// + /// Execute all the engine IReactOnAdd callbacks linked to components added this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesAddCallbacks + (FasterDictionary>> entityComponentEnginesDB + , ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesAddCallbacks(ref implMgd, (ITypeSafeDictionary)toDic + , toGroup, entityComponentEnginesDB, in profiler); + } + + /// + /// Execute all the engine IReactOnSwap callbacks linked to components swapped this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacks + (FasterList<(uint, uint, string)> infosToProcess + , FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks(infosToProcess, ref implMgd, reactiveEnginesSwap + , toGroup, fromGroup, in profiler); + } + + /// + /// Execute all the engine IReactOnREmove callbacks linked to components removed this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacks + (FasterList<(uint, string)> infosToProcess + , FasterDictionary>> reactiveEnginesRemove + , ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks(infosToProcess, ref implMgd, reactiveEnginesRemove + , fromGroup, in sampler); + } + + /// + /// Execute all the engine IReactOnAddEx callbacks linked to components added this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesAddEntityCallbacksFast + (FasterDictionary>> reactiveEnginesAdd + , ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesAddEntityCallbacksFast( + reactiveEnginesAdd, groupID, rangeOfSubmittedEntitiesIndicies, entityIDs, this, profiler); + } + + /// + /// Execute all the engine IReactOnSwapEx callbacks linked to components swapped this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacksFast + (FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacksFast(reactiveEnginesSwap, fromGroup, toGroup, entityIDs + , this, rangeOfSubmittedEntitiesIndicies, sampler); + } + + /// + /// Execute all the engine IReactOnRemoveEx callbacks linked to components removed this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacksFast + (FasterList> reactiveEnginesRemoveEx, ExclusiveGroupStruct fromGroup + , (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacksFast(reactiveEnginesRemoveEx, fromGroup + , rangeOfSubmittedEntitiesIndicies, entityIDs + , this, sampler); + } + + /// + /// Execute all the engine IReactOnSwap and IReactOnSwapEx callbacks linked to components swapped between + /// whole groups swapped during this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacks_Group + (FasterDictionary>> reactiveEnginesSwap + , FasterDictionary>> reactiveEnginesSwapEx + , ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup + , in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks_Group( + ref implMgd, (ITypeSafeDictionary)toDictionary, toGroup, fromGroup, this, reactiveEnginesSwap + , reactiveEnginesSwapEx, count, entityIDs, in profiler); + } + + /// + /// Execute all the engine IReactOnRemove and IReactOnRemoveEx callbacks linked to components remove from + /// whole groups removed during this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacks_Group + (FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemoveEx + , ExclusiveGroupStruct group, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks_Group( + ref implMgd, this, reactiveEnginesRemove, reactiveEnginesRemoveEx, count, entityIDs, group + , in profiler); + } + + /// + /// Execute all the engine IReactOnDispose for eahc component registered in the DB when it's disposed of + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesDisposeCallbacks_Group + (FasterDictionary>> engines + , ExclusiveGroupStruct group, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group(ref implMgd, engines, group, in profiler); + } + + SveltoDictionary>, ManagedStrategy, + ManagedStrategy> implMgd; + } +} \ No newline at end of file diff --git a/DataStructures/ManagedTypeSafeDictionary.cs.meta b/DataStructures/ManagedTypeSafeDictionary.cs.meta new file mode 100644 index 0000000..de7b368 --- /dev/null +++ b/DataStructures/ManagedTypeSafeDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6bf2d50adc2436bf94eff49ba715cace +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/TypeSafeDictionary.cs b/DataStructures/TypeSafeDictionary.cs deleted file mode 100644 index 39a0fdc..0000000 --- a/DataStructures/TypeSafeDictionary.cs +++ /dev/null @@ -1,800 +0,0 @@ -#if DEBUG && !PROFILE_SVELTO -//#define PARANOID_CHECK -#endif - -using System; -using System.Runtime.CompilerServices; -using DBC.ECS; -using Svelto.Common; -using Svelto.DataStructures; -using Svelto.DataStructures.Native; -using Svelto.ECS.DataStructures; -using Svelto.ECS.Hybrid; - -namespace Svelto.ECS.Internal -{ - public readonly struct NativeEntityIDs - { - public NativeEntityIDs(NB> native) - { - _native = native; - } - - public uint this[uint index] => _native[index].key; - public uint this[int index] => _native[index].key; - - readonly NB> _native; - } - - public readonly struct ManagedEntityIDs - { - public ManagedEntityIDs(MB> managed) - { - _managed = managed; - } - - public uint this[uint index] => _managed[index].key; - public uint this[int index] => _managed[index].key; - - readonly MB> _managed; - } - - public readonly struct EntityIDs - { - readonly NB> _native; - readonly MB> _managed; - - public EntityIDs(NativeStrategy> unmanagedKeys) : this() - { - _native = unmanagedKeys.ToRealBuffer(); - } - - public EntityIDs(ManagedStrategy> managedKeys) : this() - { - _managed = managedKeys.ToRealBuffer(); - } - - public NativeEntityIDs nativeIDs => new NativeEntityIDs(_native); - public ManagedEntityIDs managedIDs => new ManagedEntityIDs(_managed); - } - - public sealed class TypeSafeDictionary : ITypeSafeDictionary where TValue : struct, IEntityComponent - { - static readonly Type _type = typeof(TValue); -#if SLOW_SVELTO_SUBMISSION - static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type); - static readonly bool _hasReference = typeof(INeedEntityReference).IsAssignableFrom(_type); -#endif - internal static readonly bool isUnmanaged = - _type.IsUnmanagedEx() && typeof(IEntityViewComponent).IsAssignableFrom(_type) == false; - - public TypeSafeDictionary(uint size) - { - if (isUnmanaged) - implUnmgd = - new SharedNative>, - NativeStrategy, NativeStrategy>>( - new SveltoDictionary>, - NativeStrategy, NativeStrategy>(size, Allocator.Persistent)); - else - implMgd = - new SveltoDictionary>, - ManagedStrategy, ManagedStrategy>(size, Allocator.Managed); - } - - public EntityIDs entityIDs - { - get - { - if (isUnmanaged) - return new EntityIDs(implUnmgd.value.unsafeKeys); - - return new EntityIDs(implMgd.unsafeKeys); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool ContainsKey(uint egidEntityId) - { - return isUnmanaged ? implUnmgd.value.ContainsKey(egidEntityId) : implMgd.ContainsKey(egidEntityId); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public uint GetIndex(uint valueEntityId) - { - return isUnmanaged ? implUnmgd.value.GetIndex(valueEntityId) : implMgd.GetIndex(valueEntityId); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TValue GetOrAdd(uint idEntityId) - { - return ref isUnmanaged ? ref implUnmgd.value.GetOrAdd(idEntityId) : ref implMgd.GetOrAdd(idEntityId); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IBuffer GetValues(out uint count) - { - return isUnmanaged ? implUnmgd.value.UnsafeGetValues(out count) : implMgd.UnsafeGetValues(out count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TValue GetDirectValueByRef(uint key) - { - return ref isUnmanaged - ? ref implUnmgd.value.GetDirectValueByRef(key) - : ref implMgd.GetDirectValueByRef(key); - } - - public ref TValue GetValueByRef(uint key) - { - return ref isUnmanaged ? ref implUnmgd.value.GetValueByRef(key) : ref implMgd.GetValueByRef(key); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(uint key) - { - return isUnmanaged ? implUnmgd.value.ContainsKey(key) : implMgd.ContainsKey(key); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryFindIndex(uint entityId, out uint index) - { - return isUnmanaged - ? implUnmgd.value.TryFindIndex(entityId, out index) - : implMgd.TryFindIndex(entityId, out index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetValue(uint entityId, out TValue item) - { - return isUnmanaged - ? implUnmgd.value.TryGetValue(entityId, out item) - : implMgd.TryGetValue(entityId, out item); - } - - public int count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => isUnmanaged ? implUnmgd.value.count : implMgd.count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ITypeSafeDictionary Create() - { - return TypeSafeDictionaryFactory.Create(1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() - { - if (isUnmanaged) - implUnmgd.value.FastClear(); - else - implMgd.Clear(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void EnsureCapacity(uint size) - { - if (isUnmanaged) - implUnmgd.value.EnsureCapacity(size); - else - implMgd.EnsureCapacity(size); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void IncreaseCapacityBy(uint size) - { - if (isUnmanaged) - implUnmgd.value.IncreaseCapacityBy(size); - else - implMgd.IncreaseCapacityBy(size); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Trim() - { - if (isUnmanaged) - implUnmgd.value.Trim(); - else - implMgd.Trim(); - } - - public void KeysEvaluator(Action action) - { - if (isUnmanaged) - foreach (var key in implUnmgd.value.keys) - action(key); - else - foreach (var key in implMgd.keys) - action(key); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(uint egidEntityId, in TValue entityComponent) - { - if (isUnmanaged) - implUnmgd.value.Add(egidEntityId, entityComponent); - else - implMgd.Add(egidEntityId, entityComponent); - } - - public void Dispose() - { - if (isUnmanaged) - implUnmgd.Dispose(); - else - implMgd.Dispose(); - - GC.SuppressFinalize(this); - } - - public void AddEntitiesToDictionary(ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId, - in EnginesRoot.EntityReferenceMap entityLocator) - { - void SharedAddEntitiesFromDictionary( - in SveltoDictionary fromDictionary, - ITypeSafeDictionary toDic, in EnginesRoot.EntityReferenceMap locator, - ExclusiveGroupStruct toGroupID) where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - foreach (var tuple in fromDictionary) - { -#if SLOW_SVELTO_SUBMISSION - var egid = new EGID(tuple.key, toGroupID); - - if (_hasEgid) - SetEGIDWithoutBoxing.SetIDWithoutBoxing(ref tuple.value, egid); - - //todo: temporary code that will eventually be removed - if (_hasReference) - SetEGIDWithoutBoxing.SetRefWithoutBoxing(ref tuple.value, - locator.GetEntityReference(egid)); -#endif - try - { - toDic.Add(tuple.key, tuple.value); - } - catch (Exception e) - { - Console.LogException(e, - "trying to add an EntityComponent with the same ID more than once Entity: " - .FastConcat(typeof(TValue).ToString()).FastConcat(", group ") - .FastConcat(toGroupID.ToName()).FastConcat(", id ").FastConcat(tuple.key)); - - throw; - } -#if PARANOID_CHECK && SLOW_SVELTO_SUBMISSION - DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)fromDictionary[egid.entityID]).ID == egid, "impossible situation happened during swap"); -#endif - } - } - - var destinationDictionary = toDictionary as ITypeSafeDictionary; - - if (isUnmanaged) - SharedAddEntitiesFromDictionary(implUnmgd.value, destinationDictionary, entityLocator, groupId); - else - SharedAddEntitiesFromDictionary(implMgd, destinationDictionary, entityLocator, groupId); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RemoveEntitiesFromDictionary(FasterList<(uint, string)> infosToProcess) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary) - where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - var iterations = infosToProcess.count; - - for (var i = 0; i < iterations; i++) - { - var (id, trace) = infosToProcess[i]; - - try - { - if (fromDictionary.Remove(id, out var value)) - //Note I am doing this to be able to use a range of values even with the - //remove Ex callbacks. Basically I am copying back the deleted value - //at the end of the array, so I can use as range - //count, count + number of deleted entities - fromDictionary.GetDirectValueByRef((uint)fromDictionary.count) = value; - } - catch - { - var str = "Crash while executing Remove Entity operation on ".FastConcat(TypeCache.name) - .FastConcat(" from : ", trace); - - Console.LogError(str); - - throw; - } - } - } - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value); - else - AgnosticMethod(ref implMgd); - } - - public void SwapEntitiesBetweenDictionaries(FasterList<(uint, uint, string)> infosToProcess, - ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary) - { - void SharedSwapEntityInDictionary( - ref SveltoDictionary fromDictionary, - ITypeSafeDictionary toDictionary) - where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - var iterations = infosToProcess.count; - - for (var i = 0; i < iterations; i++) - { - var (fromID, toID, trace) = infosToProcess[i]; - - try - { - var fromEntityGid = new EGID(fromID, fromGroup); - var toEntityEgid = new EGID(toID, toGroup); - - Check.Require(toGroup.isInvalid == false, "Invalid To Group"); - - var isFound = fromDictionary.Remove(fromEntityGid.entityID, out var entity); - Check.Assert(isFound, "Swapping an entity that doesn't exist"); -#if SLOW_SVELTO_SUBMISSION - if (_hasEgid) - SetEGIDWithoutBoxing.SetIDWithoutBoxing(ref entity, toEntityEgid); -#endif - - toDictionary.Add(toEntityEgid.entityID, entity); - -#if PARANOID_CHECK - DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)toGroupCasted[toEntityEGID.entityID]).ID == toEntityEGID, "impossible situation happened during swap"); -#endif - } - catch - { - var str = "Crash while executing Swap Entity operation on ".FastConcat(TypeCache.name) - .FastConcat(" from : ", trace); - - Console.LogError(str); - - throw; - } - } - } - - var toGroupCasted = toComponentsDictionary as ITypeSafeDictionary; - - if (isUnmanaged) - SharedSwapEntityInDictionary(ref implUnmgd.value, toGroupCasted); - else - SharedSwapEntityInDictionary(ref implMgd, toGroupCasted); - } - - public void ExecuteEnginesAddCallbacks( - FasterDictionary>> entityComponentEnginesDB, - ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary, - ITypeSafeDictionary todic, in PlatformProfiler sampler) - where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - if (entityComponentEnginesDB.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines)) - { - if (entityComponentsEngines.count == 0) return; - - var dictionaryKeyEnumerator = fromDictionary.unsafeKeys; - var count = fromDictionary.count; - - for (var i = 0; i < count; ++i) - try - { - var key = dictionaryKeyEnumerator[i].key; - ref var entity = ref todic.GetValueByRef(key); - var egid = new EGID(key, toGroup); - //get all the engines linked to TValue - for (var j = 0; j < entityComponentsEngines.count; j++) - using (sampler.Sample(entityComponentsEngines[j].name)) - { - ((IReactOnAdd)entityComponentsEngines[j].engine).Add(ref entity, egid); - } - } - catch (Exception e) - { - Console.LogException(e, - "Code crashed inside Add callback with Type ".FastConcat(TypeCache.name)); - - throw; - } - } - } - - var toDictionary = (ITypeSafeDictionary)toDic; - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value, toDictionary, in profiler); - else - AgnosticMethod(ref implMgd, toDictionary, in profiler); - } - - public void ExecuteEnginesSwapCallbacks(FasterList<(uint, uint, string)> infosToProcess, - FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup, - ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary, - in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - if (reactiveEnginesSwap.count == 0) return; - - var iterations = infosToProcess.count; - - for (var i = 0; i < iterations; i++) - { - var (fromEntityID, toEntityID, trace) = infosToProcess[i]; - - try - { - ref var entityComponent = ref fromDictionary.GetValueByRef(fromEntityID); - var newEgid = new EGID(toEntityID, toGroup); - for (var j = 0; j < reactiveEnginesSwap.count; j++) - using (sampler.Sample(reactiveEnginesSwap[j].name)) - { - ((IReactOnSwap)reactiveEnginesSwap[j].engine).MovedTo(ref entityComponent, - fromGroup, newEgid); - } - } - catch - { - var str = "Crash while executing Swap Entity callback on ".FastConcat(TypeCache.name) - .FastConcat(" from : ", trace); - - Console.LogError(str); - - throw; - } - } - } - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value, in profiler); - else - AgnosticMethod(ref implMgd, in profiler); - } - - public void ExecuteEnginesRemoveCallbacks(FasterList<(uint, string)> infosToProcess, - FasterDictionary>> reactiveEnginesRemove, - ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary, - in PlatformProfiler profiler) where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - if (reactiveEnginesRemove.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines)) - { - if (entityComponentsEngines.count == 0) return; - - var iterations = infosToProcess.count; - - for (var i = 0; i < iterations; i++) - { - var (entityID, trace) = infosToProcess[i]; - try - { - ref var entity = ref fromDictionary.GetValueByRef(entityID); - var egid = new EGID(entityID, fromGroup); - - for (var j = 0; j < entityComponentsEngines.count; j++) - using (profiler.Sample(entityComponentsEngines[j].name)) - { - ((IReactOnRemove)entityComponentsEngines[j].engine).Remove(ref entity, - egid); - } - } - catch - { - var str = "Crash while executing Remove Entity callback on " - .FastConcat(TypeCache.name).FastConcat(" from : ", trace); - - Console.LogError(str); - - throw; - } - } - } - } - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value, in sampler); - else - AgnosticMethod(ref implMgd, in sampler); - } - - public void ExecuteEnginesAddEntityCallbacksFast( - FasterDictionary>> reactiveEnginesAdd, - ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) - { - //get all the engines linked to TValue - if (!reactiveEnginesAdd.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines)) - return; - - for (var i = 0; i < entityComponentsEngines.count; i++) - try - { - using (profiler.Sample(entityComponentsEngines[i].name)) - { - ((IReactOnAddEx)entityComponentsEngines[i].engine).Add(rangeOfSubmittedEntitiesIndicies, - new EntityCollection(GetValues(out var count), count, entityIDs), groupID); - } - } - catch (Exception e) - { - Console.LogException(e, - "Code crashed inside Add callback ".FastConcat(entityComponentsEngines[i].name)); - - throw; - } - } - - public void ExecuteEnginesSwapCallbacksFast( - FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup, - ExclusiveGroupStruct toGroup, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) - { - for (var i = 0; i < reactiveEnginesSwap.count; i++) - try - { - using (sampler.Sample(reactiveEnginesSwap[i].name)) - { - ((IReactOnSwapEx)reactiveEnginesSwap[i].engine).MovedTo( - rangeOfSubmittedEntitiesIndicies, - new EntityCollection(GetValues(out var count), count, entityIDs), fromGroup, - toGroup); - } - } - catch (Exception e) - { - Console.LogException(e, - "Code crashed inside Add callback ".FastConcat(reactiveEnginesSwap[i].name)); - - throw; - } - } - - public void ExecuteEnginesRemoveCallbacksFast( - FasterList> reactiveEnginesRemoveEx, ExclusiveGroupStruct fromGroup, - (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) - { - for (var i = 0; i < reactiveEnginesRemoveEx.count; i++) - try - { - using (sampler.Sample(reactiveEnginesRemoveEx[i].name)) - { - ((IReactOnRemoveEx)reactiveEnginesRemoveEx[i].engine).Remove( - rangeOfSubmittedEntitiesIndicies, - new EntityCollection(GetValues(out var count), count, entityIDs), fromGroup); - } - } - catch (Exception e) - { - Console.LogException(e, - "Code crashed inside Add callback ".FastConcat(reactiveEnginesRemoveEx[i].name)); - - throw; - } - } - - public void ExecuteEnginesSwapCallbacks_Group( - FasterDictionary>> reactiveEnginesSwap, - FasterDictionary>> reactiveEnginesSwapEx, - ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, - in PlatformProfiler profiler) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary, - ITypeSafeDictionary toDic, in PlatformProfiler sampler) - where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - //get all the engines linked to TValue - if (!reactiveEnginesSwap.TryGetValue(new RefWrapperType(_type), out var reactiveEnginesSwapPerType)) - return; - - var componentsEnginesCount = reactiveEnginesSwapPerType.count; - - for (var i = 0; i < componentsEnginesCount; i++) - try - { - foreach (var value in fromDictionary) - { - ref var entityComponent = ref toDic.GetValueByRef(value.key); - var newEgid = new EGID(value.key, toGroup); - - - using (sampler.Sample(reactiveEnginesSwapPerType[i].name)) - { - ((IReactOnSwap)reactiveEnginesSwapPerType[i].engine).MovedTo( - ref entityComponent, fromGroup, newEgid); - } - } - } - catch (Exception) - { - Console.LogError( - "Code crashed inside MoveTo callback ".FastConcat(reactiveEnginesSwapPerType[i].name)); - - throw; - } - - if (reactiveEnginesSwapEx.TryGetValue(new RefWrapperType(_type), - out var reactiveEnginesRemoveExPerType)) - { - var enginesCount = reactiveEnginesRemoveExPerType.count; - - for (var i = 0; i < enginesCount; i++) - try - { - using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name)) - { - ((IReactOnSwapEx)reactiveEnginesRemoveExPerType[i].engine).MovedTo( - (0, (uint)count), - new EntityCollection(GetValues(out _), (uint)count, entityIDs), fromGroup, - toGroup); - } - } - catch - { - Console.LogError( - "Code crashed inside Remove callback ".FastConcat( - reactiveEnginesRemoveExPerType[i].name)); - - throw; - } - } - } - - var toEntitiesDictionary = (ITypeSafeDictionary)toDictionary; - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value, toEntitiesDictionary, in profiler); - else - AgnosticMethod(ref implMgd, toEntitiesDictionary, in profiler); - } - - public void ExecuteEnginesRemoveCallbacks_Group( - FasterDictionary>> reactiveEnginesRemove, - FasterDictionary>> - reactiveEnginesRemoveEx, ExclusiveGroupStruct group, in PlatformProfiler profiler) - { - void AgnosticMethod( - ref SveltoDictionary fromDictionary, - in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - if (reactiveEnginesRemove.TryGetValue(new RefWrapperType(_type), out var reactiveEnginesRemovePerType)) - { - var enginesCount = reactiveEnginesRemovePerType.count; - - for (var i = 0; i < enginesCount; i++) - try - { - foreach (var value in fromDictionary) - { - ref var entity = ref value.value; - var egid = new EGID(value.key, group); - - - using (sampler.Sample(reactiveEnginesRemovePerType[i].name)) - { - ((IReactOnRemove)reactiveEnginesRemovePerType[i].engine).Remove(ref entity, - egid); - } - } - } - catch - { - Console.LogError( - "Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemovePerType[i] - .name)); - - throw; - } - } - - if (reactiveEnginesRemoveEx.TryGetValue(new RefWrapperType(_type), - out var reactiveEnginesRemoveExPerType)) - { - var enginesCount = reactiveEnginesRemoveExPerType.count; - - for (var i = 0; i < enginesCount; i++) - try - { - using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name)) - { - ((IReactOnRemoveEx)reactiveEnginesRemoveExPerType[i].engine).Remove( - (0, (uint)count), - new EntityCollection(GetValues(out _), (uint)count, entityIDs), group); - } - } - catch - { - Console.LogError( - "Code crashed inside Remove callback ".FastConcat( - reactiveEnginesRemoveExPerType[i].name)); - - throw; - } - } - } - - if (isUnmanaged) - AgnosticMethod(ref implUnmgd.value, in profiler); - else - AgnosticMethod(ref implMgd, in profiler); - } - - public void ExecuteEnginesDisposeCallbacks_Group( - FasterDictionary>> engines, - ExclusiveGroupStruct group, in PlatformProfiler profiler) - { - void ExecuteEnginesDisposeEntityCallback( - ref SveltoDictionary fromDictionary, - FasterDictionary>> allEngines, - in PlatformProfiler sampler, ExclusiveGroupStruct inGroup) - where Strategy1 : struct, IBufferStrategy> - where Strategy2 : struct, IBufferStrategy - where Strategy3 : struct, IBufferStrategy - { - if (allEngines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines) == false) - return; - - for (var i = 0; i < entityComponentsEngines.count; i++) - try - { - using (sampler.Sample(entityComponentsEngines[i].name)) - { - foreach (var value in fromDictionary) - { - ref var entity = ref value.value; - var egid = new EGID(value.key, inGroup); - var reactOnRemove = ((IReactOnDispose)entityComponentsEngines[i].engine); - reactOnRemove.Remove(ref entity, egid); - } - } - } - catch - { - Console.LogError( - "Code crashed inside Remove callback ".FastConcat(entityComponentsEngines[i].name)); - - throw; - } - } - - if (isUnmanaged) - ExecuteEnginesDisposeEntityCallback(ref implUnmgd.value, engines, in profiler, @group); - else - ExecuteEnginesDisposeEntityCallback(ref implMgd, engines, in profiler, @group); - } - - SveltoDictionary>, ManagedStrategy, - ManagedStrategy> implMgd; - - internal SharedNative>, - NativeStrategy, NativeStrategy>> implUnmgd; - } -} \ No newline at end of file diff --git a/DataStructures/TypeSafeDictionary.cs.meta b/DataStructures/TypeSafeDictionary.cs.meta deleted file mode 100644 index ef8ffbe..0000000 --- a/DataStructures/TypeSafeDictionary.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8c01d337f0c8331598400db7e9bdcc1e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/TypeSafeDictionaryMethods.cs b/DataStructures/TypeSafeDictionaryMethods.cs new file mode 100644 index 0000000..8d55495 --- /dev/null +++ b/DataStructures/TypeSafeDictionaryMethods.cs @@ -0,0 +1,539 @@ +using System; +using System.Runtime.CompilerServices; +using DBC.ECS; +using Svelto.Common; +using Svelto.DataStructures; + +namespace Svelto.ECS.Internal +{ + public static class TypeSafeDictionaryMethods + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AddEntitiesToDictionary + (in SveltoDictionary fromDictionary + , ITypeSafeDictionary toDic +#if SLOW_SVELTO_SUBMISSION +, in EnginesRoot.EntityReferenceMap entityLocator +#endif + , ExclusiveGroupStruct toGroupID) where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + foreach (var tuple in fromDictionary) + { +#if SLOW_SVELTO_SUBMISSION + var egid = new EGID(tuple.key, toGroupID); + + if (SlowSubmissionInfo.hasEgid) + SetEGIDWithoutBoxing.SetIDWithoutBoxing(ref tuple.value, egid); + + if (SlowSubmissionInfo.hasReference) + SetEGIDWithoutBoxing.SetRefWithoutBoxing(ref tuple.value, + entityLocator.GetEntityReference(egid)); +#endif + try + { + toDic.Add(tuple.key, tuple.value); + } + catch (Exception e) + { + Console.LogException( + e, "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString()).FastConcat(", group ").FastConcat(toGroupID.ToName()).FastConcat(", id ").FastConcat(tuple.key)); + + throw; + } +#if PARANOID_CHECK && SLOW_SVELTO_SUBMISSION + DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)fromDictionary[egid.entityID]).ID == egid, "impossible situation happened during swap"); +#endif + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesAddCallbacks + (ref SveltoDictionary fromDictionary + , ITypeSafeDictionary todic, ExclusiveGroupStruct togroup + , FasterDictionary>> entitycomponentenginesdb + , in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + if (entitycomponentenginesdb.TryGetValue(new RefWrapperType(TypeCache.type) + , out var entityComponentsEngines)) + { + if (entityComponentsEngines.count == 0) + return; + + var dictionaryKeyEnumerator = fromDictionary.unsafeKeys; + var count = fromDictionary.count; + + for (var i = 0; i < count; ++i) + try + { + var key = dictionaryKeyEnumerator[i].key; + ref var entity = ref todic.GetValueByRef(key); + var egid = new EGID(key, togroup); + //get all the engines linked to TValue + for (var j = 0; j < entityComponentsEngines.count; j++) + using (sampler.Sample(entityComponentsEngines[j].name)) + { + ((IReactOnAdd)entityComponentsEngines[j].engine).Add(ref entity, egid); + } + } + catch (Exception e) + { + Console.LogException( + e, "Code crashed inside Add callback with Type ".FastConcat(TypeCache.name)); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesDisposeCallbacks_Group + (ref SveltoDictionary fromDictionary + , FasterDictionary>> allEngines + , ExclusiveGroupStruct inGroup, in PlatformProfiler sampler) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + if (allEngines.TryGetValue(new RefWrapperType(TypeCache.type), out var entityComponentsEngines) + == false) + return; + + for (var i = 0; i < entityComponentsEngines.count; i++) + try + { + using (sampler.Sample(entityComponentsEngines[i].name)) + { + foreach (var value in fromDictionary) + { + ref var entity = ref value.value; + var egid = new EGID(value.key, inGroup); + var reactOnRemove = (IReactOnDispose)entityComponentsEngines[i].engine; + reactOnRemove.Remove(ref entity, egid); + } + } + } + catch + { + Console.LogError( + "Code crashed inside Remove callback ".FastConcat(entityComponentsEngines[i].name)); + + throw; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesRemoveCallbacks + (FasterList<(uint, string)> infostoprocess + , ref SveltoDictionary fromDictionary + , FasterDictionary>> reactiveenginesremove + , ExclusiveGroupStruct fromgroup, in PlatformProfiler profiler) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + if (reactiveenginesremove.TryGetValue(new RefWrapperType(TypeCache.type) + , out var entityComponentsEngines)) + { + if (entityComponentsEngines.count == 0) + return; + + var iterations = infostoprocess.count; + + for (var i = 0; i < iterations; i++) + { + var (entityID, trace) = infostoprocess[i]; + try + { + ref var entity = ref fromDictionary.GetValueByRef(entityID); + var egid = new EGID(entityID, fromgroup); + + for (var j = 0; j < entityComponentsEngines.count; j++) + using (profiler.Sample(entityComponentsEngines[j].name)) + { + ((IReactOnRemove)entityComponentsEngines[j].engine).Remove(ref entity, egid); + } + } + catch + { + var str = "Crash while executing Remove Entity callback on ".FastConcat(TypeCache.name) + .FastConcat(" from : ", trace); + + Console.LogError(str); + + throw; + } + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesRemoveCallbacks_Group + (ref SveltoDictionary fromDictionary + , ITypeSafeDictionary typeSafeDictionary + , FasterDictionary>> reactiveenginesremove + , FasterDictionary>> reactiveenginesremoveex + , int count, IEntityIDs entityids, ExclusiveGroupStruct group, in PlatformProfiler sampler) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + if (reactiveenginesremove.TryGetValue(new RefWrapperType(TypeCache.type) + , out var reactiveEnginesRemovePerType)) + { + var enginesCount = reactiveEnginesRemovePerType.count; + + for (var i = 0; i < enginesCount; i++) + try + { + foreach (var value in fromDictionary) + { + ref var entity = ref value.value; + var egid = new EGID(value.key, group); + + using (sampler.Sample(reactiveEnginesRemovePerType[i].name)) + { + ((IReactOnRemove)reactiveEnginesRemovePerType[i].engine).Remove( + ref entity, egid); + } + } + } + catch + { + Console.LogError( + "Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemovePerType[i].name)); + + throw; + } + } + + if (reactiveenginesremoveex.TryGetValue(new RefWrapperType(TypeCache.type) + , out var reactiveEnginesRemoveExPerType)) + { + var enginesCount = reactiveEnginesRemoveExPerType.count; + + for (var i = 0; i < enginesCount; i++) + try + { + using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name)) + { + ((IReactOnRemoveEx)reactiveEnginesRemoveExPerType[i].engine).Remove( + (0, (uint)count) + , new EntityCollection(typeSafeDictionary.GetValues(out _), entityids + , (uint)count), group); + } + } + catch + { + Console.LogError( + "Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemoveExPerType[i].name)); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesSwapCallbacks + (FasterList<(uint, uint, string)> infostoprocess + , ref SveltoDictionary fromDictionary + , FasterList> reactiveenginesswap, ExclusiveGroupStruct togroup + , ExclusiveGroupStruct fromgroup, in PlatformProfiler sampler) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + if (reactiveenginesswap.count == 0) + return; + + var iterations = infostoprocess.count; + + for (var i = 0; i < iterations; i++) + { + var (fromEntityID, toEntityID, trace) = infostoprocess[i]; + + try + { + ref var entityComponent = ref fromDictionary.GetValueByRef(fromEntityID); + var newEgid = new EGID(toEntityID, togroup); + for (var j = 0; j < reactiveenginesswap.count; j++) + using (sampler.Sample(reactiveenginesswap[j].name)) + { + ((IReactOnSwap)reactiveenginesswap[j].engine).MovedTo( + ref entityComponent, fromgroup, newEgid); + } + } + catch + { + var str = "Crash while executing Swap Entity callback on ".FastConcat(TypeCache.name) + .FastConcat(" from : ", trace); + + Console.LogError(str); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesSwapCallbacks_Group + (ref SveltoDictionary fromDictionary + , ITypeSafeDictionary toDic, ExclusiveGroupStruct togroup, ExclusiveGroupStruct fromgroup + , ITypeSafeDictionary typeSafeDictionary + , FasterDictionary>> reactiveenginesswap + , FasterDictionary>> reactiveenginesswapex + , int count, IEntityIDs entityids, in PlatformProfiler sampler) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + //get all the engines linked to TValue + if (!reactiveenginesswap.TryGetValue(new RefWrapperType(TypeCache.type) + , out var reactiveEnginesSwapPerType)) + return; + + var componentsEnginesCount = reactiveEnginesSwapPerType.count; + + for (var i = 0; i < componentsEnginesCount; i++) + try + { + foreach (var value in fromDictionary) + { + ref var entityComponent = ref toDic.GetValueByRef(value.key); + var newEgid = new EGID(value.key, togroup); + + using (sampler.Sample(reactiveEnginesSwapPerType[i].name)) + { + ((IReactOnSwap)reactiveEnginesSwapPerType[i].engine).MovedTo( + ref entityComponent, fromgroup, newEgid); + } + } + } + catch (Exception) + { + Console.LogError( + "Code crashed inside MoveTo callback ".FastConcat(reactiveEnginesSwapPerType[i].name)); + + throw; + } + + if (reactiveenginesswapex.TryGetValue(new RefWrapperType(TypeCache.type) + , out var reactiveEnginesRemoveExPerType)) + { + var enginesCount = reactiveEnginesRemoveExPerType.count; + + for (var i = 0; i < enginesCount; i++) + try + { + using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name)) + { + ((IReactOnSwapEx)reactiveEnginesRemoveExPerType[i].engine).MovedTo( + (0, (uint)count) + , new EntityCollection(typeSafeDictionary.GetValues(out _), entityids + , (uint)count), fromgroup, togroup); + } + } + catch + { + Console.LogError( + "Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemoveExPerType[i].name)); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RemoveEntitiesFromDictionary + (FasterList<(uint, string)> infostoprocess + , ref SveltoDictionary fromDictionary + , FasterList entityIDsAffectedByRemoval) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + var iterations = infostoprocess.count; + + for (var i = 0; i < iterations; i++) + { + var (id, trace) = infostoprocess[i]; + + try + { + if (fromDictionary.Remove(id, out var index, out var value)) + { + //Note I am doing this to be able to use a range of values even with the + //remove Ex callbacks. Basically I am copying back the deleted value + //at the end of the array, so I can use as range count, count + number of deleted entities + //I need to swap the keys too to have matching EntityIDs + fromDictionary.unsafeValues[(uint)fromDictionary.count] = value; + fromDictionary.unsafeKeys[(uint)fromDictionary.count] = new SveltoDictionaryNode(ref id, 0); + //when a component is removed from a component array, a remove swap back happens. This means + //that not only we have to remove the index of the component of the entity deleted from the array + //but we need also to update the index of the component that has been swapped in the cell + //of the deleted component + //entityIDsAffectedByRemoval tracks all the entitiesID of the components that need to be updated + //in the filters because their indices in the array changed. + entityIDsAffectedByRemoval.Add(fromDictionary.unsafeKeys[index].key); + } + } + catch + { + var str = "Crash while executing Remove Entity operation on ".FastConcat(TypeCache.name) + .FastConcat(" from : ", trace); + + Console.LogError(str); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SwapEntitiesBetweenDictionaries + (FasterList<(uint, uint, string)> infostoprocess + , ref SveltoDictionary fromDictionary + , ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromgroup, ExclusiveGroupStruct togroup + , FasterList entityIDsAffectedByRemoval) + where Strategy1 : struct, IBufferStrategy> + where Strategy2 : struct, IBufferStrategy + where Strategy3 : struct, IBufferStrategy + where TValue : struct, IBaseEntityComponent + { + var iterations = infostoprocess.count; + + for (var i = 0; i < iterations; i++) + { + var (fromID, toID, trace) = infostoprocess[i]; + + try + { + var fromEntityGid = new EGID(fromID, fromgroup); + var toEntityEgid = new EGID(toID, togroup); + + Check.Require(togroup.isInvalid == false, "Invalid To Group"); + + if (fromDictionary.Remove(fromEntityGid.entityID, out var index, out var value)) + entityIDsAffectedByRemoval.Add(fromDictionary.unsafeKeys[index].key); + else + Check.Assert(false, "Swapping an entity that doesn't exist"); + +#if SLOW_SVELTO_SUBMISSION + if (SlowSubmissionInfo.hasEgid) + SetEGIDWithoutBoxing.SetIDWithoutBoxing(ref value, toEntityEgid); +#endif + + toDictionary.Add(toEntityEgid.entityID, value); + +#if PARANOID_CHECK + DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)toGroupCasted[toEntityEGID.entityID]).ID == toEntityEGID, "impossible situation happened during swap"); +#endif + } + catch + { + var str = "Crash while executing Swap Entity operation on ".FastConcat(TypeCache.name) + .FastConcat(" from : ", trace); + + Console.LogError(str); + + throw; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesAddEntityCallbacksFast + (FasterDictionary>> fasterDictionary + , ExclusiveGroupStruct groupId, (uint, uint) valueTuple, IEntityIDs entityids + , ITypeSafeDictionary typeSafeDictionary, PlatformProfiler profiler) + where TValue : struct, IBaseEntityComponent + { + //get all the engines linked to TValue + if (!fasterDictionary.TryGetValue(new RefWrapperType(TypeCache.type) + , out var entityComponentsEngines)) + return; + + for (var i = 0; i < entityComponentsEngines.count; i++) + try + { + using (profiler.Sample(entityComponentsEngines[i].name)) + { + ((IReactOnAddEx)entityComponentsEngines[i].engine).Add( + valueTuple + , new EntityCollection(typeSafeDictionary.GetValues(out var count), entityids, count) + , groupId); + } + } + catch (Exception e) + { + Console.LogException( + e, "Code crashed inside Add callback ".FastConcat(entityComponentsEngines[i].name)); + + throw; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesSwapCallbacksFast + (FasterList> fasterList, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, IEntityIDs entityids, ITypeSafeDictionary typeSafeDictionary + , (uint, uint) rangeofsubmittedentitiesindicies, PlatformProfiler sampler) + where TValue : struct, IBaseEntityComponent + { + for (var i = 0; i < fasterList.count; i++) + try + { + using (sampler.Sample(fasterList[i].name)) + { + ((IReactOnSwapEx)fasterList[i].engine).MovedTo(rangeofsubmittedentitiesindicies + , new EntityCollection( + typeSafeDictionary.GetValues( + out var count), entityids, count) + , fromGroup, toGroup); + } + } + catch (Exception e) + { + Console.LogException(e, "Code crashed inside Add callback ".FastConcat(fasterList[i].name)); + + throw; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ExecuteEnginesRemoveCallbacksFast + (FasterList> fasterList, ExclusiveGroupStruct exclusiveGroupStruct + , (uint, uint) valueTuple, IEntityIDs entityids, ITypeSafeDictionary typeSafeDictionary + , PlatformProfiler sampler) where TValue : struct, IBaseEntityComponent + { + for (var i = 0; i < fasterList.count; i++) + try + { + using (sampler.Sample(fasterList[i].name)) + { + ((IReactOnRemoveEx)fasterList[i].engine).Remove( + valueTuple + , new EntityCollection(typeSafeDictionary.GetValues(out var count), entityids, count) + , exclusiveGroupStruct); + } + } + catch (Exception e) + { + Console.LogException(e, "Code crashed inside Add callback ".FastConcat(fasterList[i].name)); + + throw; + } + } + } +} \ No newline at end of file diff --git a/DataStructures/TypeSafeDictionaryMethods.cs.meta b/DataStructures/TypeSafeDictionaryMethods.cs.meta new file mode 100644 index 0000000..ade97df --- /dev/null +++ b/DataStructures/TypeSafeDictionaryMethods.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6dbd1dab66c230c2a64f6ad0695fd852 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/TypeSafeDictionaryUtilities.cs b/DataStructures/TypeSafeDictionaryUtilities.cs index 57af0d1..716b755 100644 --- a/DataStructures/TypeSafeDictionaryUtilities.cs +++ b/DataStructures/TypeSafeDictionaryUtilities.cs @@ -3,7 +3,7 @@ namespace Svelto.ECS.Internal static class TypeSafeDictionaryUtilities { internal static EGIDMapper ToEGIDMapper(this ITypeSafeDictionary dic, - ExclusiveGroupStruct groupStructId) where T:struct, IEntityComponent + ExclusiveGroupStruct groupStructId) where T:struct, IBaseEntityComponent { var mapper = new EGIDMapper(groupStructId, dic); diff --git a/DataStructures/Unmanaged/SharedDisposableNative.cs b/DataStructures/Unmanaged/SharedDisposableNative.cs new file mode 100644 index 0000000..42a2fa5 --- /dev/null +++ b/DataStructures/Unmanaged/SharedDisposableNative.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.CompilerServices; +using Svelto.Common; + +namespace Svelto.ECS.DataStructures +{ + public struct SharedDisposableNative : IDisposable where T : unmanaged, IDisposable + { +#if UNITY_COLLECTIONS || (UNITY_JOBS || UNITY_BURST) + [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] +#endif + unsafe IntPtr ptr; + + public SharedDisposableNative(in T value) + { + unsafe + { + ptr = MemoryUtilities.Alloc(1, Allocator.Persistent); + Unsafe.Write((void*)ptr, value); + } + } + + public void Dispose() + { + unsafe + { + Unsafe.AsRef((void*)ptr).Dispose(); + + MemoryUtilities.Free((IntPtr)ptr, Allocator.Persistent); + ptr = IntPtr.Zero; + } + } + + public ref T value + { + get + { + unsafe + { + DBC.ECS.Check.Require(ptr != null, "SharedNative has not been initialized"); + + return ref Unsafe.AsRef((void*)ptr); + } + } + } + } +} \ No newline at end of file diff --git a/DataStructures/Unmanaged/SharedDisposableNative.cs.meta b/DataStructures/Unmanaged/SharedDisposableNative.cs.meta new file mode 100644 index 0000000..eebef6b --- /dev/null +++ b/DataStructures/Unmanaged/SharedDisposableNative.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4cd887ae843386d9d234a799e3bee7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DataStructures/Unmanaged/SharedNativeInt.cs b/DataStructures/Unmanaged/SharedNativeInt.cs index f7103cd..04d09fc 100644 --- a/DataStructures/Unmanaged/SharedNativeInt.cs +++ b/DataStructures/Unmanaged/SharedNativeInt.cs @@ -1,51 +1,9 @@ using System; -using System.Runtime.CompilerServices; using System.Threading; using Svelto.Common; namespace Svelto.ECS.DataStructures { - public struct SharedNative : IDisposable where T : struct, IDisposable - { -#if UNITY_COLLECTIONS || (UNITY_JOBS || UNITY_BURST) - [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] -#endif - unsafe IntPtr ptr; - - public SharedNative(in T value) - { - unsafe - { - ptr = MemoryUtilities.Alloc(1, Allocator.Persistent); - Unsafe.Write((void*)ptr, value); - } - } - - public void Dispose() - { - unsafe - { - Unsafe.AsRef((void*)ptr).Dispose(); - - MemoryUtilities.Free((IntPtr)ptr, Allocator.Persistent); - ptr = IntPtr.Zero; - } - } - - public ref T value - { - get - { - unsafe - { - DBC.ECS.Check.Require(ptr != null, "SharedNative has not been initialized"); - - return ref Unsafe.AsRef((void*)ptr); - } - } - } - } - public struct SharedNativeInt: IDisposable { #if UNITY_COLLECTIONS || (UNITY_JOBS || UNITY_BURST) diff --git a/DataStructures/UnmanagedTypeSafeDictionary.cs b/DataStructures/UnmanagedTypeSafeDictionary.cs new file mode 100644 index 0000000..83656b3 --- /dev/null +++ b/DataStructures/UnmanagedTypeSafeDictionary.cs @@ -0,0 +1,312 @@ +#if DEBUG && !PROFILE_SVELTO +//#define PARANOID_CHECK +#endif + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using Svelto.Common; +using Svelto.DataStructures; +using Svelto.DataStructures.Native; +using Svelto.ECS.DataStructures; + +namespace Svelto.ECS.Internal +{ +#if SLOW_SVELTO_SUBMISSION + static class SlowSubmissionInfo + { + internal static readonly bool hasEgid = typeof(INeedEGID).IsAssignableFrom(TypeCache.type); + internal static readonly bool hasReference = typeof(INeedEntityReference).IsAssignableFrom(TypeCache.type); + } +#endif + + public sealed class UnmanagedTypeSafeDictionary : ITypeSafeDictionary + where TValue : struct, IBaseEntityComponent + { + static readonly ThreadLocal cachedEntityIDN = + new ThreadLocal(() => new NativeEntityIDs()); + + public UnmanagedTypeSafeDictionary(uint size) + { + implUnmgd = + new SharedSveltoDictionaryNative(size, Allocator.Persistent); + } + + public IEntityIDs entityIDs + { + get + { + ref var unboxed = ref Unsafe.Unbox(cachedEntityIDN.Value); + + unboxed.Update(implUnmgd.dictionary.unsafeKeys.ToRealBuffer()); + + return cachedEntityIDN.Value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ContainsKey(uint egidEntityId) + { + return implUnmgd.dictionary.ContainsKey(egidEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint GetIndex(uint valueEntityId) + { + return implUnmgd.dictionary.GetIndex(valueEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref TValue GetOrAdd(uint idEntityId) + { + return ref implUnmgd.dictionary.GetOrAdd(idEntityId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IBuffer GetValues(out uint count) + { + return implUnmgd.dictionary.UnsafeGetValues(out count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref TValue GetDirectValueByRef(uint key) + { + return ref implUnmgd.dictionary.GetDirectValueByRef(key); + } + + public ref TValue GetValueByRef(uint key) + { + return ref implUnmgd.dictionary.GetValueByRef(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Has(uint key) + { + return implUnmgd.dictionary.ContainsKey(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryFindIndex(uint entityId, out uint index) + { + return implUnmgd.dictionary.TryFindIndex(entityId, out index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryGetValue(uint entityId, out TValue item) + { + return implUnmgd.dictionary.TryGetValue(entityId, out item); + } + + public int count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => implUnmgd.dictionary.count; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ITypeSafeDictionary Create() + { + return TypeSafeDictionaryFactory.Create(1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + implUnmgd.dictionary.FastClear(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void EnsureCapacity(uint size) + { + implUnmgd.dictionary.EnsureCapacity(size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void IncreaseCapacityBy(uint size) + { + implUnmgd.dictionary.IncreaseCapacityBy(size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Trim() + { + implUnmgd.dictionary.Trim(); + } + + public void KeysEvaluator(Action action) + { + foreach (var key in implUnmgd.dictionary.keys) + action(key); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(uint egidEntityId, in TValue entityComponent) + { + implUnmgd.dictionary.Add(egidEntityId, entityComponent); + } + + public void Dispose() + { + implUnmgd.Dispose(); //SharedDisposableNative already calls the dispose of the underlying value + + GC.SuppressFinalize(this); + } + + /// ********************************* + /// the following methods are executed during the submission of entities + /// ********************************* + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void AddEntitiesToDictionary + (ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId +#if SLOW_SVELTO_SUBMISSION + , in EnginesRoot.EntityReferenceMap entityLocator +#endif + ) + + { + TypeSafeDictionaryMethods.AddEntitiesToDictionary(implUnmgd.dictionary + , toDictionary as ITypeSafeDictionary +#if SLOW_SVELTO_SUBMISSION + , entityLocator +#endif + , groupId); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RemoveEntitiesFromDictionary + (FasterList<(uint, string)> infosToProcess, FasterList entityIDsAffectedByRemoval) + { + TypeSafeDictionaryMethods.RemoveEntitiesFromDictionary(infosToProcess, ref implUnmgd.dictionary + , entityIDsAffectedByRemoval); + } + + public void SwapEntitiesBetweenDictionaries + (FasterList<(uint, uint, string)> infosToProcess, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary + , FasterList entityIDsAffectedByRemoval) + { + TypeSafeDictionaryMethods.SwapEntitiesBetweenDictionaries(infosToProcess, ref implUnmgd.dictionary + ,toComponentsDictionary as ITypeSafeDictionary, fromGroup, toGroup, entityIDsAffectedByRemoval); + } + + /// + /// Execute all the engine IReactOnAdd callbacks linked to components added this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesAddCallbacks + (FasterDictionary>> entityComponentEnginesDB + , ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesAddCallbacks(ref implUnmgd.dictionary, (ITypeSafeDictionary)toDic + , toGroup, entityComponentEnginesDB, in profiler); + } + + /// + /// Execute all the engine IReactOnSwap callbacks linked to components swapped this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacks + (FasterList<(uint, uint, string)> infosToProcess + , FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks(infosToProcess, ref implUnmgd.dictionary + , reactiveEnginesSwap, toGroup, fromGroup, in profiler); + } + + /// + /// Execute all the engine IReactOnREmove callbacks linked to components removed this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacks + (FasterList<(uint, string)> infosToProcess + , FasterDictionary>> reactiveEnginesRemove + , ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks(infosToProcess, ref implUnmgd.dictionary + , reactiveEnginesRemove, fromGroup, in sampler); + } + + /// + /// Execute all the engine IReactOnAddEx callbacks linked to components added this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesAddEntityCallbacksFast + (FasterDictionary>> reactiveEnginesAdd + , ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesAddEntityCallbacksFast( + reactiveEnginesAdd, groupID, rangeOfSubmittedEntitiesIndicies, entityIDs, this, profiler); + } + + /// + /// Execute all the engine IReactOnSwapEx callbacks linked to components swapped this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacksFast + (FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup + , ExclusiveGroupStruct toGroup, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacksFast(reactiveEnginesSwap, fromGroup, toGroup, entityIDs + , this, rangeOfSubmittedEntitiesIndicies, sampler); + } + + /// + /// Execute all the engine IReactOnRemoveEx callbacks linked to components removed this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacksFast + (FasterList> reactiveEnginesRemoveEx, ExclusiveGroupStruct fromGroup + , (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacksFast(reactiveEnginesRemoveEx, fromGroup + , rangeOfSubmittedEntitiesIndicies, entityIDs + , this, sampler); + } + + /// + /// Execute all the engine IReactOnSwap and IReactOnSwapEx callbacks linked to components swapped between + /// whole groups swapped during this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesSwapCallbacks_Group + (FasterDictionary>> reactiveEnginesSwap + , FasterDictionary>> reactiveEnginesSwapEx + , ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup + , in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks_Group( + ref implUnmgd.dictionary, (ITypeSafeDictionary)toDictionary, toGroup, fromGroup, this + , reactiveEnginesSwap, reactiveEnginesSwapEx, count, entityIDs, in profiler); + } + + /// + /// Execute all the engine IReactOnRemove and IReactOnRemoveEx callbacks linked to components remove from + /// whole groups removed during this submit + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesRemoveCallbacks_Group + (FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemoveEx + , ExclusiveGroupStruct group, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks_Group( + ref implUnmgd.dictionary, this, reactiveEnginesRemove, reactiveEnginesRemoveEx, count, entityIDs, group + , in profiler); + } + + /// + /// Execute all the engine IReactOnDispose for eahc component registered in the DB when it's disposed of + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEnginesDisposeCallbacks_Group + (FasterDictionary>> engines + , ExclusiveGroupStruct group, in PlatformProfiler profiler) + { + TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group( + ref implUnmgd.dictionary, engines, group, in profiler); + } + + internal SharedSveltoDictionaryNative implUnmgd; + } +} \ No newline at end of file diff --git a/DataStructures/UnmanagedTypeSafeDictionary.cs.meta b/DataStructures/UnmanagedTypeSafeDictionary.cs.meta new file mode 100644 index 0000000..456e67e --- /dev/null +++ b/DataStructures/UnmanagedTypeSafeDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a28862edbc6f37d9864b84cef119b96e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Extensions/Native/NativeEGIDMapper.cs b/Extensions/Native/NativeEGIDMapper.cs index f8ccd7d..f90e3cf 100644 --- a/Extensions/Native/NativeEGIDMapper.cs +++ b/Extensions/Native/NativeEGIDMapper.cs @@ -13,30 +13,26 @@ namespace Svelto.ECS.Native /// that a job can use it as long as nothing else is modifying the entities database and the NativeEGIDMapper /// is disposed right after the use. /// - public readonly struct NativeEGIDMapper : IEGIDMapper where T : unmanaged, IEntityComponent + public readonly struct NativeEGIDMapper : IEGIDMapper where T : unmanaged, IBaseEntityComponent { public static readonly NativeEGIDMapper empty = new NativeEGIDMapper - (default, new SharedNative>, - NativeStrategy, NativeStrategy>>( - new SveltoDictionary>, - NativeStrategy, NativeStrategy>(0, Allocator.Persistent))); + (default, new SharedSveltoDictionaryNative(0, Allocator.Persistent)); public NativeEGIDMapper(ExclusiveGroupStruct groupStructId, - in SharedNative>, NativeStrategy, - NativeStrategy>> toNative) : this() + in SharedSveltoDictionaryNative toDisposableNative) : this() { groupID = groupStructId; - _map = toNative; + _map = toDisposableNative; } - public int count => _map.value.count; + public int count => _map.dictionary.count; public Type entityType => TypeCache.type; public ExclusiveGroupStruct groupID { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Entity(uint entityID) { - var sveltoDictionary = _map.value; + var sveltoDictionary = _map.dictionary; #if DEBUG && !PROFILE_SVELTO if (sveltoDictionary.TryFindIndex(entityID, out var findIndex) == false) @@ -50,7 +46,7 @@ namespace Svelto.ECS.Native [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetEntity(uint entityID, out T value) { - var sveltoDictionary = _map.value; + var sveltoDictionary = _map.dictionary; if (sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(entityID, out var index)) { var values = sveltoDictionary.unsafeValues.ToRealBuffer(); @@ -65,7 +61,7 @@ namespace Svelto.ECS.Native [MethodImpl(MethodImplOptions.AggressiveInlining)] public NB GetArrayAndEntityIndex(uint entityID, out uint index) { - var sveltoDictionary = _map.value; + var sveltoDictionary = _map.dictionary; if (sveltoDictionary.TryFindIndex(entityID, out index)) return sveltoDictionary.unsafeValues.ToRealBuffer(); @@ -80,7 +76,7 @@ namespace Svelto.ECS.Native public bool TryGetArrayAndEntityIndex(uint entityID, out uint index, out NB array) { index = 0; - var sveltoDictionary = _map.value; + var sveltoDictionary = _map.dictionary; if (sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(entityID, out index)) { @@ -95,23 +91,22 @@ namespace Svelto.ECS.Native [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Exists(uint idEntityId) { - var sveltoDictionary = _map.value; + var sveltoDictionary = _map.dictionary; return sveltoDictionary.count > 0 && sveltoDictionary.TryFindIndex(idEntityId, out _); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint GetIndex(uint entityID) { - return _map.value.GetIndex(entityID); + return _map.dictionary.GetIndex(entityID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool FindIndex(uint valueKey, out uint index) { - return _map.value.TryFindIndex(valueKey, out index); + return _map.dictionary.TryFindIndex(valueKey, out index); } - readonly SharedNative>, NativeStrategy, - NativeStrategy>> _map; + readonly SharedSveltoDictionaryNative _map; } } \ No newline at end of file diff --git a/Extensions/Native/NativeEGIDMultiMapper.cs b/Extensions/Native/NativeEGIDMultiMapper.cs index 4941076..f525db0 100644 --- a/Extensions/Native/NativeEGIDMultiMapper.cs +++ b/Extensions/Native/NativeEGIDMultiMapper.cs @@ -14,17 +14,9 @@ namespace Svelto.ECS.Native ///WARNING: REMEMBER THIS MUST BE DISPOSED OF, AS IT USES NATIVE MEMORY. IT WILL LEAK MEMORY OTHERWISE /// /// - public struct NativeEGIDMultiMapper : IDisposable where T : unmanaged, IEntityComponent + public struct NativeEGIDMultiMapper : IDisposable where T : unmanaged, IBaseEntityComponent { - public NativeEGIDMultiMapper(in SveltoDictionary< - /*key */ExclusiveGroupStruct, - /*value*/ - SharedNative>, NativeStrategy, - NativeStrategy>>, - /*strategy to store the key*/ NativeStrategy>, - /*strategy to store the value*/ - NativeStrategy>, - NativeStrategy, NativeStrategy>>>, NativeStrategy> dictionary) + public NativeEGIDMultiMapper(in SveltoDictionaryNative> dictionary) { _dic = dictionary; } @@ -43,7 +35,7 @@ namespace Svelto.ECS.Native throw new Exception($"NativeEGIDMultiMapper: Entity not found {entity}"); #endif ref var sveltoDictionary = ref _dic.GetValueByRef(entity.groupID); - return ref sveltoDictionary.value.GetValueByRef(entity.entityID); + return ref sveltoDictionary.dictionary.GetValueByRef(entity.entityID); } public uint GetIndex(EGID entity) @@ -53,26 +45,22 @@ namespace Svelto.ECS.Native throw new Exception($"NativeEGIDMultiMapper: Entity not found {entity}"); #endif ref var sveltoDictionary = ref _dic.GetValueByRef(entity.groupID); - return sveltoDictionary.value.GetIndex(entity.entityID); + return sveltoDictionary.dictionary.GetIndex(entity.entityID); } public bool Exists(EGID entity) { return _dic.TryFindIndex(entity.groupID, out var index) && - _dic.GetDirectValueByRef(index).value.ContainsKey(entity.entityID); + _dic.GetDirectValueByRef(index).dictionary.ContainsKey(entity.entityID); } public bool TryGetEntity(EGID entity, out T component) { component = default; return _dic.TryFindIndex(entity.groupID, out var index) && - _dic.GetDirectValueByRef(index).value.TryGetValue(entity.entityID, out component); + _dic.GetDirectValueByRef(index).dictionary.TryGetValue(entity.entityID, out component); } - SveltoDictionary>, NativeStrategy, - NativeStrategy>>, NativeStrategy>, NativeStrategy< - SharedNative>, NativeStrategy, - NativeStrategy>>>, NativeStrategy> _dic; + SveltoDictionaryNative> _dic; } } \ No newline at end of file diff --git a/Extensions/Native/UnityNativeEntityDBExtensions.cs b/Extensions/Native/UnityNativeEntityDBExtensions.cs index 0254f4a..1da6269 100644 --- a/Extensions/Native/UnityNativeEntityDBExtensions.cs +++ b/Extensions/Native/UnityNativeEntityDBExtensions.cs @@ -9,7 +9,7 @@ namespace Svelto.ECS.Native { public static class UnityNativeEntityDBExtensions { - static NativeEGIDMapper ToNativeEGIDMapper(this TypeSafeDictionary dic, + static NativeEGIDMapper ToNativeEGIDMapper(this UnmanagedTypeSafeDictionary dic, ExclusiveGroupStruct groupStructId) where T : unmanaged, IEntityComponent { var mapper = new NativeEGIDMapper(groupStructId, dic.implUnmgd); @@ -24,7 +24,7 @@ namespace Svelto.ECS.Native if (entitiesDb.SafeQueryEntityDictionary(groupStructId, out var typeSafeDictionary) == false) throw new EntityGroupNotFoundException(typeof(T), groupStructId.ToName()); - return (typeSafeDictionary as TypeSafeDictionary).ToNativeEGIDMapper(groupStructId); + return (typeSafeDictionary as UnmanagedTypeSafeDictionary).ToNativeEGIDMapper(groupStructId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -37,7 +37,7 @@ namespace Svelto.ECS.Native typeSafeDictionary.count == 0) return false; - mapper = (typeSafeDictionary as TypeSafeDictionary).ToNativeEGIDMapper(groupStructId); + mapper = (typeSafeDictionary as UnmanagedTypeSafeDictionary).ToNativeEGIDMapper(groupStructId); return true; } @@ -45,24 +45,20 @@ namespace Svelto.ECS.Native [MethodImpl(MethodImplOptions.AggressiveInlining)] ///Note: if I use a SharedNativeSveltoDictionary for implUnmg, I may be able to cache NativeEGIDMultiMapper /// and reuse it + /// TODO: the ability to retain a NativeEGIDMultiMapper thanks to the use of shareable arrays + /// must be unit tested! public static NativeEGIDMultiMapper QueryNativeMappedEntities(this EntitiesDB entitiesDb, LocalFasterReadOnlyList groups, Allocator allocator) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { - var dictionary = new SveltoDictionary< - /*key */ExclusiveGroupStruct, - /*value*/SharedNative>, NativeStrategy, NativeStrategy>>, - /*strategy to store the key*/ NativeStrategy>, - /*strategy to store the value*/NativeStrategy< - SharedNative>, NativeStrategy, NativeStrategy>>> - , NativeStrategy> + var dictionary = new SveltoDictionaryNative> ((uint) groups.count, allocator); foreach (var group in groups) { if (entitiesDb.SafeQueryEntityDictionary(group, out var typeSafeDictionary) == true) //if (typeSafeDictionary.count > 0) - dictionary.Add(group, ((TypeSafeDictionary)typeSafeDictionary).implUnmgd); + dictionary.Add(group, ((UnmanagedTypeSafeDictionary)typeSafeDictionary).implUnmgd); } return new NativeEGIDMultiMapper(dictionary); diff --git a/Extensions/Svelto/AllGroupsEnumerable.cs b/Extensions/Svelto/AllGroupsEnumerable.cs index 7961fc7..14f31b7 100644 --- a/Extensions/Svelto/AllGroupsEnumerable.cs +++ b/Extensions/Svelto/AllGroupsEnumerable.cs @@ -9,7 +9,7 @@ namespace Svelto.ECS /// that can be burstifiable /// /// - public readonly struct AllGroupsEnumerable where T1 : struct, IEntityComponent + public readonly struct AllGroupsEnumerable where T1 : struct, IBaseEntityComponent { public ref struct GroupCollection { @@ -45,8 +45,8 @@ namespace Svelto.ECS if (typeSafeDictionary.count == 0) continue; - _array.collection = new EntityCollection(typeSafeDictionary.GetValues(out var count), count, - typeSafeDictionary.entityIDs); + _array.collection = new EntityCollection(typeSafeDictionary.GetValues(out var count), + typeSafeDictionary.entityIDs, count); _array.@group = group.key; return true; } diff --git a/Extensions/Svelto/EGIDMultiMapper.cs b/Extensions/Svelto/EGIDMultiMapper.cs index 8469b27..55468ed 100644 --- a/Extensions/Svelto/EGIDMultiMapper.cs +++ b/Extensions/Svelto/EGIDMultiMapper.cs @@ -9,7 +9,7 @@ namespace Svelto.ECS { namespace Native { - public struct EGIDMultiMapper where T : unmanaged, IEntityComponent + public struct EGIDMultiMapper where T : unmanaged, IBaseEntityComponent { public EGIDMultiMapper (SveltoDictionary(in this EntityCollection ec, out NB buffer, out int count) where T1 : unmanaged, IEntityComponent { - buffer = ec._nativedBuffer; + if (ec._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer = default; + count = 0; + return; + } + + buffer = (NB)ec._buffer; count = (int)ec.count; } @@ -19,9 +26,17 @@ namespace Svelto.ECS public static void Deconstruct(in this EntityCollection ec, out NB buffer, out NativeEntityIDs entityIDs, out int count) where T1 : unmanaged, IEntityComponent { - buffer = ec._nativedBuffer; + if (ec._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer = default; + count = 0; + entityIDs = default; + return; + } + + buffer = (NB)ec._buffer; count = (int)ec.count; - entityIDs = ec._nativedIndices; + entityIDs = (NativeEntityIDs)ec._entityIDs; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -29,10 +44,19 @@ namespace Svelto.ECS out NB buffer2, out NativeEntityIDs entityIDs, out int count) where T1 : unmanaged, IEntityComponent where T2 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + count = 0; + entityIDs = default; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; count = ec.count; - entityIDs = ec.buffer1._nativedIndices; + entityIDs = (NativeEntityIDs)ec.buffer1._entityIDs; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -40,8 +64,16 @@ namespace Svelto.ECS out NB buffer2, out int count) where T1 : unmanaged, IEntityComponent where T2 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; count = (int)ec.count; } @@ -51,9 +83,18 @@ namespace Svelto.ECS where T2 : unmanaged, IEntityComponent where T3 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._nativedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (NB)ec.buffer3._buffer; count = (int)ec.count; } @@ -64,11 +105,21 @@ namespace Svelto.ECS where T2 : unmanaged, IEntityComponent where T3 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._nativedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + count = 0; + entityIDs = default; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (NB)ec.buffer3._buffer; count = (int)ec.count; - entityIDs = ec.buffer1._nativedIndices; + entityIDs = (NativeEntityIDs)ec.buffer1._entityIDs; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -79,10 +130,20 @@ namespace Svelto.ECS where T3 : unmanaged, IEntityComponent where T4 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._nativedBuffer; - buffer4 = ec.buffer4._nativedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + buffer4 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (NB)ec.buffer3._buffer; + buffer4 = (NB)ec.buffer4._buffer; count = (int)ec.count; } @@ -94,11 +155,22 @@ namespace Svelto.ECS where T3 : unmanaged, IEntityComponent where T4 : unmanaged, IEntityComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._nativedBuffer; - buffer4 = ec.buffer4._nativedBuffer; - entityIDs = ec.buffer1._nativedIndices; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + buffer4 = default; + count = 0; + entityIDs = default; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (NB)ec.buffer3._buffer; + buffer4 = (NB)ec.buffer4._buffer; + entityIDs = (NativeEntityIDs)ec.buffer1._entityIDs; count = (int)ec.count; } } @@ -109,7 +181,14 @@ namespace Svelto.ECS public static void Deconstruct(in this EntityCollection ec, out MB buffer, out int count) where T1 : struct, IEntityViewComponent { - buffer = ec._managedBuffer; + if (ec._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer = default; + count = 0; + return; + } + + buffer = (MB)ec._buffer; count = (int)ec.count; } @@ -117,9 +196,16 @@ namespace Svelto.ECS public static void Deconstruct(in this EntityCollection ec, out MB buffer, out ManagedEntityIDs entityIDs, out int count) where T1 : struct, IEntityViewComponent { - buffer = ec._managedBuffer; + if (ec._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer = default; + count = 0; + entityIDs = default; + return; + } + buffer = (MB)ec._buffer; count = (int)ec.count; - entityIDs = ec._managedIndices; + entityIDs = (ManagedEntityIDs)ec._entityIDs; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -127,8 +213,16 @@ namespace Svelto.ECS out MB buffer2, out int count) where T1 : struct, IEntityViewComponent where T2 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._managedBuffer; - buffer2 = ec.buffer2._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + count = 0; + return; + } + + buffer1 = (MB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; count = (int)ec.count; } @@ -137,10 +231,19 @@ namespace Svelto.ECS out MB buffer2, out ManagedEntityIDs entityIDs, out int count) where T1 : struct, IEntityViewComponent where T2 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._managedBuffer; - buffer2 = ec.buffer2._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + count = 0; + entityIDs = default; + return; + } + + buffer1 = (MB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; count = (int)ec.count; - entityIDs = ec.buffer1._managedIndices; + entityIDs = (ManagedEntityIDs)ec.buffer1._entityIDs; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -149,9 +252,18 @@ namespace Svelto.ECS where T2 : struct, IEntityViewComponent where T3 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._managedBuffer; - buffer2 = ec.buffer2._managedBuffer; - buffer3 = ec.buffer3._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + count = 0; + return; + } + + buffer1 = (MB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; + buffer3 = (MB)ec.buffer3._buffer; count = (int)ec.count; } @@ -162,11 +274,21 @@ namespace Svelto.ECS where T2 : struct, IEntityViewComponent where T3 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._managedBuffer; - buffer2 = ec.buffer2._managedBuffer; - buffer3 = ec.buffer3._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + entityIDs = default; + count = 0; + return; + } + + buffer1 = (MB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; + buffer3 = (MB)ec.buffer3._buffer; count = (int)ec.count; - entityIDs = ec.buffer1._managedIndices; + entityIDs = (ManagedEntityIDs)ec.buffer1._entityIDs; } } @@ -177,8 +299,16 @@ namespace Svelto.ECS out MB buffer2, out int count) where T1 : unmanaged, IEntityComponent where T2 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; count = (int)ec.count; } @@ -188,9 +318,18 @@ namespace Svelto.ECS where T2 : struct, IEntityViewComponent where T3 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._managedBuffer; - buffer3 = ec.buffer3._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + count = 0; + return; + + } + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (MB)ec.buffer2._buffer; + buffer3 = (MB)ec.buffer3._buffer; count = (int)ec.count; } @@ -202,10 +341,20 @@ namespace Svelto.ECS where T3 : unmanaged, IEntityComponent where T4 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._nativedBuffer; - buffer4 = ec.buffer4._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + buffer4 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (NB)ec.buffer3._buffer; + buffer4 = (MB)ec.buffer4._buffer; count = (int)ec.count; } } @@ -218,9 +367,18 @@ namespace Svelto.ECS where T2 : unmanaged, IEntityComponent where T3 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (MB)ec.buffer3._buffer; count = (int)ec.count; } @@ -232,10 +390,20 @@ namespace Svelto.ECS where T3 : struct, IEntityViewComponent where T4 : struct, IEntityViewComponent { - buffer1 = ec.buffer1._nativedBuffer; - buffer2 = ec.buffer2._nativedBuffer; - buffer3 = ec.buffer3._managedBuffer; - buffer4 = ec.buffer4._managedBuffer; + if (ec.buffer1._buffer == null) //I cannot test 0, as buffer can be valid and processed by removeEx with count 0 + { + buffer1 = default; + buffer2 = default; + buffer3 = default; + buffer4 = default; + count = 0; + return; + } + + buffer1 = (NB)ec.buffer1._buffer; + buffer2 = (NB)ec.buffer2._buffer; + buffer3 = (MB)ec.buffer3._buffer; + buffer4 = (MB)ec.buffer4._buffer; count = (int)ec.count; } } diff --git a/Extensions/Svelto/EntityManagedDBExtensions.cs b/Extensions/Svelto/EntityManagedDBExtensions.cs index a3483e1..28eb6c4 100644 --- a/Extensions/Svelto/EntityManagedDBExtensions.cs +++ b/Extensions/Svelto/EntityManagedDBExtensions.cs @@ -119,7 +119,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public static AllGroupsEnumerable QueryEntities(this EntitiesDB db) - where T1 :struct, IEntityComponent + where T1 :struct, IBaseEntityComponent { return new AllGroupsEnumerable(db); } diff --git a/Extensions/Svelto/GroupsEnumerable.cs b/Extensions/Svelto/GroupsEnumerable.cs index 31d986b..38661a3 100644 --- a/Extensions/Svelto/GroupsEnumerable.cs +++ b/Extensions/Svelto/GroupsEnumerable.cs @@ -11,10 +11,10 @@ namespace Svelto.ECS /// /// /// - public readonly ref struct GroupsEnumerable where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent - where T4 : struct, IEntityComponent + public readonly ref struct GroupsEnumerable where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent + where T4 : struct, IBaseEntityComponent { public GroupsEnumerable(EntitiesDB db, in LocalFasterReadOnlyList groups) { @@ -92,9 +92,9 @@ namespace Svelto.ECS } } - public readonly ref struct GroupsEnumerable where T1 : struct, IEntityComponent - where T2 : struct, IEntityComponent - where T3 : struct, IEntityComponent + public readonly ref struct GroupsEnumerable where T1 : struct, IBaseEntityComponent + where T2 : struct, IBaseEntityComponent + where T3 : struct, IBaseEntityComponent { public GroupsEnumerable(EntitiesDB db, in LocalFasterReadOnlyList groups) { @@ -175,7 +175,7 @@ namespace Svelto.ECS } public readonly ref struct GroupsEnumerable - where T1 : struct, IEntityComponent where T2 : struct, IEntityComponent + where T1 : struct, IBaseEntityComponent where T2 : struct, IBaseEntityComponent { public GroupsEnumerable(EntitiesDB db, in LocalFasterReadOnlyList groups) { @@ -253,7 +253,7 @@ namespace Svelto.ECS } } - public readonly ref struct GroupsEnumerable where T1 : struct, IEntityComponent + public readonly ref struct GroupsEnumerable where T1 : struct, IBaseEntityComponent { public GroupsEnumerable(EntitiesDB db, in LocalFasterReadOnlyList groups) { diff --git a/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs b/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs index 237c433..2a41d1e 100644 --- a/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs +++ b/Extensions/Unity/DOTS/UECS/SveltoOnDOTSEntitiesSubmissionGroup.cs @@ -99,7 +99,7 @@ namespace Svelto.ECS.SveltoOnDOTS void PreSubmissionPhase(ref JobHandle jobHandle, PlatformProfiler profiler) { - using (profiler.Sample("Complete All Pending Jobs")) jobHandle.Complete(); + using (profiler.Sample("Complete All Pending Jobs")) jobHandle.Complete(); //sync-point _entityCommandBuffer = new EntityCommandBuffer((Allocator)Common.Allocator.TempJob); diff --git a/Extensions/Unity/DOTS/UECS/SveltoOnDOTSHandleLifeTimeEngine.cs b/Extensions/Unity/DOTS/UECS/SveltoOnDOTSHandleLifeTimeEngine.cs index 696c5c5..8832d68 100644 --- a/Extensions/Unity/DOTS/UECS/SveltoOnDOTSHandleLifeTimeEngine.cs +++ b/Extensions/Unity/DOTS/UECS/SveltoOnDOTSHandleLifeTimeEngine.cs @@ -26,11 +26,11 @@ namespace Svelto.ECS.SveltoOnDOTS public void MovedTo((uint start, uint end) rangeOfEntities, in EntityCollection collection, ExclusiveGroupStruct _, ExclusiveGroupStruct toGroup) { - var (buffer, entityIDs, _) = collection; + var (entities, entityIDs, _) = collection; for (uint i = rangeOfEntities.start; i < rangeOfEntities.end; i++) { - ref var entityComponent = ref buffer[i]; + ref var entityComponent = ref entities[i]; ECB.SetSharedComponent(entityComponent.dotsEntity, new DOTSSveltoGroupID(toGroup)); ECB.SetComponent(entityComponent.dotsEntity, new DOTSSveltoEGID diff --git a/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs b/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs deleted file mode 100644 index 5fbcf47..0000000 --- a/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs +++ /dev/null @@ -1,31 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using Svelto.DataStructures; -using UnityEngine; - -namespace Svelto.ECS.Extensions.Unity -{ - ///The class that wrap the OOP library must be known by the package only as much as possible. - ///what cannot be use through the package, is exposed through a public interface. Note though that this may - ///be considered a work around to better design. In this case, no methods are exposed. - public class GOManager - { - public uint RegisterEntity(PrimitiveType type) - { - var cubeObject = GameObject.CreatePrimitive(type); - - objects.Add(cubeObject.transform); - - return (uint) (objects.count - 1); - } - - public void SetParent(uint index, in uint parent) - { - objects[index].SetParent(objects[parent], false); - } - - public void SetPosition(uint index, in Vector3 position) { objects[index].localPosition = position; } - - readonly FasterList objects = new FasterList(); - } -} -#endif \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs.meta b/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs.meta deleted file mode 100644 index afdf7d4..0000000 --- a/Extensions/Unity/GameObjects/AbstractionLayer/GOManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 83928a155e5a36c3821f33fcc9ea7a83 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/Implementors.meta b/Extensions/Unity/GameObjects/Implementors.meta deleted file mode 100644 index 2a8414e..0000000 --- a/Extensions/Unity/GameObjects/Implementors.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f60f2aa405cf349fb3e8739522027cf1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs b/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs deleted file mode 100644 index 2957acf..0000000 --- a/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs +++ /dev/null @@ -1,13 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using Svelto.ECS.Hybrid; -using UnityEngine; - -namespace Svelto.ECS.Extensions.Unity -{ - [DisallowMultipleComponent] - public class EntityReferenceHolderImplementor : MonoBehaviour, IImplementor - { - public EntityReference reference { get; set; } - } -} -#endif \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs.meta b/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs.meta deleted file mode 100644 index 4e31f24..0000000 --- a/Extensions/Unity/GameObjects/Implementors/EntityReferenceHolderImplementor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4d6a79e76dce399eb4dbb2ddf9c62b9e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/Implementors/IECSManager.cs b/Extensions/Unity/GameObjects/Implementors/IECSManager.cs deleted file mode 100644 index 52b96c4..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IECSManager.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Svelto.ECS.Extensions.Unity -{ - public interface IECSManager - { - } -} \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/Implementors/IECSManager.cs.meta b/Extensions/Unity/GameObjects/Implementors/IECSManager.cs.meta deleted file mode 100644 index bf01e30..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IECSManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 44451edf88f83b1cbcb2dcca24ba4247 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs b/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs deleted file mode 100644 index e68e6c9..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Svelto.ECS.Hybrid; - -namespace Svelto.ECS.Extensions.Unity -{ - public interface IUseMultipleResourceManagerImplementor: IImplementor - { - IECSManager[] resourceManager { set; } - } -} \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs.meta b/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs.meta deleted file mode 100644 index d95726c..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IUseMultipleResourceManagerImplementor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3810177bdb7830ebb282423234dd21c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs b/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs deleted file mode 100644 index 2b2efea..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Svelto.ECS.Hybrid; - -namespace Svelto.ECS.Extensions.Unity -{ - public interface IUseResourceManagerImplementor: IImplementor - { - IECSManager resourceManager { set; } - } -} \ No newline at end of file diff --git a/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs.meta b/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs.meta deleted file mode 100644 index 69f7ec6..0000000 --- a/Extensions/Unity/GameObjects/Implementors/IUseResourceManagerImplementor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e06a9044584f39b5ab92135cc185c312 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Extensions/Unity/GameObjects/ListToPopupDrawer.cs b/Extensions/Unity/GameObjects/ListToPopupDrawer.cs index 0351ef1..214862d 100644 --- a/Extensions/Unity/GameObjects/ListToPopupDrawer.cs +++ b/Extensions/Unity/GameObjects/ListToPopupDrawer.cs @@ -18,14 +18,17 @@ public class ListToPopupDrawer : PropertyDrawer if (atb.classType.GetField(atb.listName, BindingFlags.Static | BindingFlags.NonPublic) != null) { - stringList = atb.classType.GetField(atb.listName, BindingFlags.Static | BindingFlags.NonPublic).GetValue(atb.classType) as List; + stringList = + atb.classType.GetField(atb.listName, BindingFlags.Static | BindingFlags.NonPublic) + .GetValue(atb.classType) as List; } if (stringList != null && stringList.Count != 0) { - int selectedIndex = Mathf.Max(0, stringList.FindIndex(t => t.Name == property.stringValue)); - - selectedIndex = EditorGUI.Popup(position, property.name, selectedIndex, stringList.Select(t => t.Name).ToArray()); + int selectedIndex = Mathf.Max(0, stringList.FindIndex(t => t.Name == property.stringValue)); + + selectedIndex = EditorGUI.Popup(position, property.name, selectedIndex + , stringList.Select(t => t.Name).ToArray()); property.stringValue = stringList[selectedIndex].Name; (property.serializedObject.targetObject as EntityDescriptorHolder).type = diff --git a/Serialization/ComposedComponentSerializer.cs b/Serialization/ComposedComponentSerializer.cs index ca3bbb3..ba82b64 100644 --- a/Serialization/ComposedComponentSerializer.cs +++ b/Serialization/ComposedComponentSerializer.cs @@ -3,7 +3,7 @@ using System; namespace Svelto.ECS.Serialization { public class ComposedComponentSerializer : IComponentSerializer - where T : unmanaged, IEntityComponent where X : class, IComponentSerializer, new() + where T : unmanaged, IBaseEntityComponent where X : class, IComponentSerializer, new() where Y : class, IComponentSerializer, new() { public ComposedComponentSerializer() diff --git a/Serialization/DefaultSerializer.cs b/Serialization/DefaultSerializer.cs index 9532aeb..22fa0f2 100644 --- a/Serialization/DefaultSerializer.cs +++ b/Serialization/DefaultSerializer.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS.Serialization { - public class DefaultSerializer : IComponentSerializer where T : unmanaged, IEntityComponent + public class DefaultSerializer : IComponentSerializer where T : unmanaged, IBaseEntityComponent { static readonly uint SIZEOFT = SerializableComponentBuilder.SIZE; diff --git a/Serialization/DefaultSerializerUtils.cs b/Serialization/DefaultSerializerUtils.cs index c0f8cdd..0d5e6a9 100644 --- a/Serialization/DefaultSerializerUtils.cs +++ b/Serialization/DefaultSerializerUtils.cs @@ -3,7 +3,7 @@ using Svelto.ECS; public static class DefaultSerializerUtils { - public static unsafe void CopyToByteArray(in T src, byte[] data, uint offsetDst) where T : unmanaged, IEntityComponent + public static unsafe void CopyToByteArray(in T src, byte[] data, uint offsetDst) where T : unmanaged, IBaseEntityComponent { #if DEBUG && !PROFILE_SVELTO if (data.Length - offsetDst < sizeof(T)) @@ -29,7 +29,7 @@ public static class DefaultSerializerUtils } } - public static unsafe T CopyFromByteArray(byte[] data, uint offsetSrc) where T : unmanaged, IEntityComponent + public static unsafe T CopyFromByteArray(byte[] data, uint offsetSrc) where T : unmanaged, IBaseEntityComponent { T dst = default; diff --git a/Serialization/DontSerialize.cs b/Serialization/DontSerialize.cs index 414e16a..38f5b02 100644 --- a/Serialization/DontSerialize.cs +++ b/Serialization/DontSerialize.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS.Serialization { - public class DontSerialize : IComponentSerializer where T : unmanaged, IEntityComponent + public class DontSerialize : IComponentSerializer where T : unmanaged, IBaseEntityComponent { public uint size => 0; diff --git a/Serialization/EnginesRoot.GenericEntitySerialization.cs b/Serialization/EnginesRoot.GenericEntitySerialization.cs index 1b2ff8d..c7a1765 100644 --- a/Serialization/EnginesRoot.GenericEntitySerialization.cs +++ b/Serialization/EnginesRoot.GenericEntitySerialization.cs @@ -89,7 +89,7 @@ namespace Svelto.ECS /// public T DeserializeEntityComponent(ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { var readPos = serializationData.dataPos; T entityComponent = default; diff --git a/Serialization/IComponentSerializer.cs b/Serialization/IComponentSerializer.cs index a3bcff4..48e2c1d 100644 --- a/Serialization/IComponentSerializer.cs +++ b/Serialization/IComponentSerializer.cs @@ -2,7 +2,7 @@ #endif namespace Svelto.ECS.Serialization { - public interface IComponentSerializer where T : unmanaged, IEntityComponent + public interface IComponentSerializer where T : unmanaged, IBaseEntityComponent { bool Serialize(in T value, ISerializationData serializationData); bool Deserialize(ref T value, ISerializationData serializationData); diff --git a/Serialization/IEntitySerialization.cs b/Serialization/IEntitySerialization.cs index c1bf424..f2d39ce 100644 --- a/Serialization/IEntitySerialization.cs +++ b/Serialization/IEntitySerialization.cs @@ -84,6 +84,6 @@ namespace Svelto.ECS.Serialization T DeserializeEntityComponent(ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType) - where T : unmanaged, IEntityComponent; + where T : unmanaged, IBaseEntityComponent; } } \ No newline at end of file diff --git a/Serialization/PartialSerializer.cs b/Serialization/PartialSerializer.cs index 063f983..4653925 100644 --- a/Serialization/PartialSerializer.cs +++ b/Serialization/PartialSerializer.cs @@ -11,7 +11,7 @@ namespace Svelto.ECS.Serialization {} public class PartialSerializer : IComponentSerializer - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { static PartialSerializer() { diff --git a/Serialization/SerializableComponentBuilder.cs b/Serialization/SerializableComponentBuilder.cs index bcc4baa..7db46b4 100644 --- a/Serialization/SerializableComponentBuilder.cs +++ b/Serialization/SerializableComponentBuilder.cs @@ -12,7 +12,7 @@ namespace Svelto.ECS.Serialization } public class SerializableComponentBuilder : ComponentBuilder, ISerializableComponentBuilder - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { public static readonly uint SIZE = (uint) MemoryUtilities.SizeOf(); @@ -77,7 +77,7 @@ namespace Svelto.ECS.Serialization } public class SerializableComponentBuilder : SerializableComponentBuilder - where T : unmanaged, IEntityComponent where SerializationType : Enum + where T : unmanaged, IBaseEntityComponent where SerializationType : Enum { static SerializableComponentBuilder() { } diff --git a/Serialization/SerializerExt.cs b/Serialization/SerializerExt.cs index c7d455d..1487488 100644 --- a/Serialization/SerializerExt.cs +++ b/Serialization/SerializerExt.cs @@ -4,7 +4,7 @@ namespace Svelto.ECS.Serialization { public static bool SerializeSafe (this IComponentSerializer componentSerializer, in T value, ISerializationData serializationData) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { #if DEBUG && !PROFILE_SVELTO uint posBefore = serializationData.dataPos; @@ -24,7 +24,7 @@ namespace Svelto.ECS.Serialization public static bool DeserializeSafe (this IComponentSerializer componentSerializer, ref T value, ISerializationData serializationData) - where T : unmanaged, IEntityComponent + where T : unmanaged, IBaseEntityComponent { #if DEBUG && !PROFILE_SVELTO uint posBefore = serializationData.dataPos; diff --git a/Svelto.ECS.nuspec b/Svelto.ECS.nuspec index b7d7bf8..cbbeac1 100644 --- a/Svelto.ECS.nuspec +++ b/Svelto.ECS.nuspec @@ -11,10 +11,12 @@ + docs/README.md + diff --git a/package.json b/package.json index b7bdbb6..425687c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "url": "https://github.com/sebas77/Svelto.ECS.git" }, "dependencies": { - "com.sebaslab.svelto.common": "3.3.0" + "com.sebaslab.svelto.common": "3.3.2" }, "keywords": [ "svelto", @@ -19,7 +19,7 @@ "svelto.ecs" ], "name": "com.sebaslab.svelto.ecs", - "version": "3.3.1", + "version": "3.3.2", "type": "library", "unity": "2019.3" } \ No newline at end of file