diff --git a/com.sebaslab.svelto.ecs/Core/ComponentBuilder.CheckFields.cs b/com.sebaslab.svelto.ecs/Core/ComponentBuilder.CheckFields.cs index 57faef5..9e76063 100644 --- a/com.sebaslab.svelto.ecs/Core/ComponentBuilder.CheckFields.cs +++ b/com.sebaslab.svelto.ecs/Core/ComponentBuilder.CheckFields.cs @@ -4,6 +4,7 @@ using System.Diagnostics; #endif using System; using System.Reflection; +using System.Runtime.CompilerServices; using Svelto.ECS.Hybrid; namespace Svelto.ECS @@ -153,5 +154,13 @@ namespace Svelto.ECS static readonly Type STRINGBUILDERTYPE = typeof(System.Text.StringBuilder); internal static readonly Type ENTITY_INFO_COMPONENT = typeof(EntityInfoComponent); + public static ComponentID ENTITY_INFO_COMPONENT_ID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ComponentTypeID.id; + } + } } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs b/com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs index 3b38b38..2ccafdc 100644 --- a/com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs +++ b/com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Threading; using DBC.ECS; using Svelto.Common; @@ -28,14 +30,42 @@ namespace Svelto.ECS { public static int counter; } - - public class ComponentID where T : struct, _IInternalEntityComponent + + static public class ComponentTypeMap + { + static readonly FasterDictionary, ComponentID> _componentTypeMap = new FasterDictionary, ComponentID>(); + static readonly FasterDictionary _reverseComponentTypeMap = new FasterDictionary(); + + public static void Add(Type type, ComponentID idData) + { + _componentTypeMap.Add(type, idData); + _reverseComponentTypeMap.Add(idData, type); + } + + public static ComponentID FetchID(Type type) + { + return _componentTypeMap[type]; + } + + public static Type FetchType(ComponentID id) + { + return _reverseComponentTypeMap[id]; + } + } + + public class ComponentTypeID where T : struct, _IInternalEntityComponent { - public static readonly SharedStaticWrapper> id; + static readonly SharedStaticWrapper> _id; + + public static ComponentID id + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _id.Data; + } //todo: any reason to not do this? If I don't, I cannot Create filters in ready functions and //I have to remove the CreateFilter method - static ComponentID() + static ComponentTypeID() { Init(); } @@ -46,10 +76,52 @@ namespace Svelto.ECS #endif static void Init() { - id.Data = Interlocked.Increment(ref BurstCompatibleCounter.counter); - - Check.Ensure(id.Data < ushort.MaxValue, "too many types registered, HOW :)"); + _id.Data = Interlocked.Increment(ref BurstCompatibleCounter.counter); + ComponentTypeMap.Add(typeof(T), id); + } + } + + sealed class ComponentIDDebugProxy + { + public ComponentIDDebugProxy(ComponentID id) + { + this._id = id; + } + + public Type type => ComponentTypeMap.FetchType(_id); + + readonly ComponentID _id; + } + + [DebuggerTypeProxy(typeof(ComponentIDDebugProxy))] + public struct ComponentID: IEquatable + { + public static implicit operator int(ComponentID id) + { + return id._id; + } + + public static implicit operator uint(ComponentID id) + { + return (uint)id._id; + } + + public static implicit operator ComponentID(int id) + { + return new ComponentID() {_id = id}; + } + + public bool Equals(ComponentID other) + { + return _id == other._id; + } + + public override int GetHashCode() + { + return _id; } + + int _id; } public class ComponentBuilder : IComponentBuilder where T : struct, _IInternalEntityComponent @@ -57,7 +129,6 @@ namespace Svelto.ECS internal static readonly Type ENTITY_COMPONENT_TYPE; internal static readonly bool IS_ENTITY_VIEW_COMPONENT; - static readonly T DEFAULT_IT; static readonly string ENTITY_COMPONENT_NAME; static readonly bool IS_UNMANAGED; #if SLOW_SVELTO_SUBMISSION @@ -68,7 +139,6 @@ namespace Svelto.ECS static ComponentBuilder() { ENTITY_COMPONENT_TYPE = typeof(T); - DEFAULT_IT = default; IS_ENTITY_VIEW_COMPONENT = typeof(IEntityViewComponent).IsAssignableFrom(ENTITY_COMPONENT_TYPE); #if SLOW_SVELTO_SUBMISSION HAS_EGID = typeof(INeedEGID).IsAssignableFrom(ENTITY_COMPONENT_TYPE); @@ -100,7 +170,7 @@ namespace Svelto.ECS public ComponentBuilder() { - _initializer = DEFAULT_IT; + _initializer = default; } public ComponentBuilder(in T initializer) : this() @@ -109,6 +179,7 @@ namespace Svelto.ECS } public bool isUnmanaged => IS_UNMANAGED; + public ComponentID getComponentID => ComponentTypeID.id; static readonly ThreadLocal _localCache = new ThreadLocal(() => new EntityViewComponentCache()); diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs index 0acf4fc..c3495b6 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.DoubleBufferedEntitiesToAdd.cs @@ -1,4 +1,5 @@ -using Svelto.DataStructures; +using System; +using Svelto.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS @@ -18,9 +19,9 @@ namespace Svelto.ECS var entitiesCreatedPerGroupA = new FasterDictionary(); var entitiesCreatedPerGroupB = new FasterDictionary(); var entityComponentsToAddBufferA = - new FasterDictionary>(); + new FasterDictionary>(); var entityComponentsToAddBufferB = - new FasterDictionary>(); + new FasterDictionary>(); _currentNumberEntitiesCreatedPerGroup = entitiesCreatedPerGroupA; _lastNumberEntitiesCreatedPerGroup = entitiesCreatedPerGroupB; @@ -149,17 +150,14 @@ namespace Svelto.ECS (ExclusiveGroupStruct groupID, uint numberOfEntities, IComponentBuilder[] entityComponentsToBuild) { void PreallocateDictionaries - (FasterDictionary> dic) + (FasterDictionary> dic) { var group = dic.GetOrAdd( - groupID, () => new FasterDictionary()); + groupID, () => new FasterDictionary()); foreach (var componentBuilder in entityComponentsToBuild) { - var entityComponentType = componentBuilder.GetEntityComponentType(); - var safeDictionary = group.GetOrAdd(new RefWrapperType(entityComponentType) - , () => componentBuilder - .CreateDictionary(numberOfEntities)); + var safeDictionary = group.GetOrAdd(componentBuilder.getComponentID, () => componentBuilder.CreateDictionary(numberOfEntities)); componentBuilder.Preallocate(safeDictionary, numberOfEntities); } } @@ -191,10 +189,10 @@ namespace Svelto.ECS //Before I tried for the third time to use a SparseSet instead of FasterDictionary, remember that //while group indices are sequential, they may not be used in a sequential order. Sparseset needs //entities to be created sequentially (the index cannot be managed externally) - internal FasterDictionary> + internal FasterDictionary> currentComponentsToAddPerGroup; - FasterDictionary> + FasterDictionary> lastComponentsToAddPerGroup; /// @@ -212,7 +210,7 @@ namespace Svelto.ECS struct OtherComponentsToAddPerGroupEnumerator { public OtherComponentsToAddPerGroupEnumerator - (FasterDictionary> + (FasterDictionary> lastComponentsToAddPerGroup , FasterDictionary otherNumberEntitiesCreatedPerGroup) { @@ -246,7 +244,7 @@ namespace Svelto.ECS public GroupInfo Current { get; private set; } //cannot be read only as they will be modified by MoveNext - readonly FasterDictionary> + readonly FasterDictionary> _lastComponentsToAddPerGroup; SveltoDictionaryKeyValueEnumerator components; + public FasterDictionary components; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs index a25c40c..e196789 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Engines.cs @@ -16,6 +16,7 @@ namespace Svelto.ECS { static EnginesRoot() { + EntityDescriptorsWarmup.Init(); GroupHashMap.Init(); //SharedDictonary.Init(); SerializationDescriptorMap.Init(); @@ -50,19 +51,21 @@ namespace Svelto.ECS _nativeAddOperationQueue = new AtomicNativeBags(Allocator.Persistent); #endif _serializationDescriptorMap = new SerializationDescriptorMap(); - _reactiveEnginesAdd = new FasterDictionary>>(); + _reactiveEnginesAdd = new FasterDictionary>>(); _reactiveEnginesAddEx = - new FasterDictionary>>(); + new FasterDictionary>>(); _reactiveEnginesRemove = - new FasterDictionary>>(); + new FasterDictionary>>(); _reactiveEnginesRemoveEx = - new FasterDictionary>>(); + new FasterDictionary>>(); _reactiveEnginesSwap = - new FasterDictionary>>(); + new FasterDictionary>>(); _reactiveEnginesSwapEx = - new FasterDictionary>>(); + new FasterDictionary>>(); _reactiveEnginesDispose = - new FasterDictionary>>(); + new FasterDictionary>>(); + _reactiveEnginesDisposeEx = + new FasterDictionary>>(); _reactiveEnginesSubmission = new FasterList(); _reactiveEnginesSubmissionStarted = new FasterList(); @@ -71,14 +74,14 @@ namespace Svelto.ECS _disposableEngines = new FasterList(); _groupEntityComponentsDB = - new FasterDictionary>(); + new FasterDictionary>(); _groupsPerEntity = - new FasterDictionary>(); + new FasterDictionary>(); _groupedEntityToAdd = new DoubleBufferedEntitiesToAdd(); _entityStreams = EntitiesStreams.Create(); #if SVELTO_LEGACY_FILTERS _groupFilters = - new FasterDictionary>(); + new FasterDictionary>(); #endif _entityLocator.InitEntityReferenceMap(); _entitiesDB = new EntitiesDB(this, _entityLocator); @@ -150,6 +153,10 @@ namespace Svelto.ECS if (engine is IReactOnDispose viewEngineDispose) CheckReactEngineComponents( typeof(IReactOnDispose<>), viewEngineDispose, _reactiveEnginesDispose, type.Name); + + if (engine is IReactOnDisposeEx viewEngineDisposeEx) + CheckReactEngineComponents( + typeof(IReactOnDisposeEx<>), viewEngineDisposeEx, _reactiveEnginesDisposeEx, type.Name); if (engine is IReactOnSwap viewEngineSwap) #pragma warning disable CS0612 @@ -198,18 +205,19 @@ namespace Svelto.ECS } static void AddEngineToList(T engine, Type[] entityComponentTypes, - FasterDictionary>> engines, string typeName) + FasterDictionary>> engines, string typeName) where T : class, IReactEngine { for (var i = 0; i < entityComponentTypes.Length; i++) { var type = entityComponentTypes[i]; - if (engines.TryGetValue(new RefWrapperType(type), out var list) == false) + var componentID = ComponentTypeMap.FetchID(type); + if (engines.TryGetValue(componentID, out var list) == false) { list = new FasterList>(); - engines.Add(new RefWrapperType(type), list); + engines.Add(componentID, list); } list.Add(new ReactEngineContainer(engine, typeName)); @@ -217,7 +225,7 @@ namespace Svelto.ECS } void CheckReactEngineComponents(Type genericDefinition, T engine, - FasterDictionary>> engines, string typeName) + FasterDictionary>> engines, string typeName) where T : class, IReactEngine { var interfaces = engine.GetType().GetInterfaces(); @@ -226,7 +234,7 @@ namespace Svelto.ECS { if (interf.IsGenericTypeEx() && interf.GetGenericTypeDefinition() == genericDefinition) { - var genericArguments = interf.GetGenericArgumentsEx(); + Type[] genericArguments = interf.GetGenericArgumentsEx(); AddEngineToList(engine, genericArguments, engines, typeName); } @@ -261,7 +269,7 @@ namespace Svelto.ECS ITypeSafeDictionary typeSafeDictionary = entityList.value; typeSafeDictionary.ExecuteEnginesDisposeCallbacks_Group( - _reactiveEnginesDispose, groups.key, + _reactiveEnginesDispose, _reactiveEnginesDisposeEx, groups.key, profiler); } catch (Exception e) @@ -298,6 +306,7 @@ namespace Svelto.ECS _reactiveEnginesAdd.Clear(); _reactiveEnginesRemove.Clear(); _reactiveEnginesDispose.Clear(); + _reactiveEnginesDisposeEx.Clear(); _reactiveEnginesSubmission.Clear(); _reactiveEnginesSubmissionStarted.Clear(); @@ -401,13 +410,14 @@ namespace Svelto.ECS readonly HashSet _enginesTypeSet; readonly EnginesReadyOption _enginesWaitForReady; - readonly FasterDictionary>> _reactiveEnginesAdd; - readonly FasterDictionary>> _reactiveEnginesAddEx; - readonly FasterDictionary>> _reactiveEnginesRemove; - readonly FasterDictionary>> _reactiveEnginesRemoveEx; - readonly FasterDictionary>> _reactiveEnginesSwap; - readonly FasterDictionary>> _reactiveEnginesSwapEx; - readonly FasterDictionary>> _reactiveEnginesDispose; + readonly FasterDictionary>> _reactiveEnginesAdd; + readonly FasterDictionary>> _reactiveEnginesAddEx; + readonly FasterDictionary>> _reactiveEnginesRemove; + readonly FasterDictionary>> _reactiveEnginesRemoveEx; + readonly FasterDictionary>> _reactiveEnginesSwap; + readonly FasterDictionary>> _reactiveEnginesSwapEx; + readonly FasterDictionary>> _reactiveEnginesDispose; + readonly FasterDictionary>> _reactiveEnginesDisposeEx; readonly FasterList _reactiveEnginesSubmission; readonly FasterList _reactiveEnginesSubmissionStarted; diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs index c7242a4..0c25bc8 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Entities.cs @@ -62,19 +62,18 @@ namespace Svelto.ECS void PreallocateDBGroup() { var numberOfEntityComponents = entityComponentsToBuild.Length; - FasterDictionary group = GetOrAddDBGroup(groupID); + FasterDictionary group = GetOrAddDBGroup(groupID); for (var index = 0; index < numberOfEntityComponents; index++) { var entityComponentBuilder = entityComponentsToBuild[index]; - var entityComponentType = entityComponentBuilder.GetEntityComponentType(); + var entityComponentType = entityComponentBuilder.getComponentID; - var refWrapper = new RefWrapperType(entityComponentType); - var dbList = group.GetOrAdd(refWrapper, () => entityComponentBuilder.CreateDictionary(size)); + var dbList = group.GetOrAdd(entityComponentType, () => entityComponentBuilder.CreateDictionary(size)); entityComponentBuilder.Preallocate(dbList, size); - if (_groupsPerEntity.TryGetValue(refWrapper, out var groupedGroup) == false) - groupedGroup = _groupsPerEntity[refWrapper] = + if (_groupsPerEntity.TryGetValue(entityComponentType, out var groupedGroup) == false) + groupedGroup = _groupsPerEntity[entityComponentType] = new FasterDictionary(); groupedGroup[groupID] = dbList; @@ -87,27 +86,27 @@ namespace Svelto.ECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - FasterDictionary GetDBGroup(ExclusiveGroupStruct fromIdGroupId) + FasterDictionary GetDBGroup(ExclusiveGroupStruct fromIdGroupId) { if (_groupEntityComponentsDB.TryGetValue(fromIdGroupId, - out FasterDictionary fromGroup) == false) + out FasterDictionary fromGroup) == false) throw new ECSException("Group doesn't exist: ".FastConcat(fromIdGroupId.ToName())); return fromGroup; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - FasterDictionary GetOrAddDBGroup(ExclusiveGroupStruct toGroupId) + FasterDictionary GetOrAddDBGroup(ExclusiveGroupStruct toGroupId) { return _groupEntityComponentsDB.GetOrAdd(toGroupId, - () => new FasterDictionary()); + () => new FasterDictionary()); } IComponentBuilder[] FindRealComponents(EGID fromEntityGID) where T : IEntityDescriptor, new() { var fromGroup = GetDBGroup(fromEntityGID.groupID); - if (fromGroup.TryGetValue(new RefWrapperType(ComponentBuilderUtilities.ENTITY_INFO_COMPONENT), + if (fromGroup.TryGetValue(ComponentBuilderUtilities.ENTITY_INFO_COMPONENT_ID, out var entityInfoDic) // && ((ITypeSafeDictionary)entityInfoDic).TryGetValue(fromEntityGID.entityID, out var entityInfo)) //there could be multiple entity descriptors registered in the same group, so it's necessary to check if the entity registered in the group has entityInfoComponent @@ -129,14 +128,14 @@ namespace Svelto.ECS return entityInfo.componentsToBuild; } - return EntityDescriptorTemplate.descriptor.componentsToBuild; + return EntityDescriptorTemplate.realDescriptor.componentsToBuild; } IComponentBuilder[] FindRealComponents(EGID fromEntityGID, IComponentBuilder[] baseComponents) { var fromGroup = GetDBGroup(fromEntityGID.groupID); - if (fromGroup.TryGetValue(new RefWrapperType(ComponentBuilderUtilities.ENTITY_INFO_COMPONENT), + if (fromGroup.TryGetValue(ComponentBuilderUtilities.ENTITY_INFO_COMPONENT_ID, out var entityInfoDic) // && ((ITypeSafeDictionary)entityInfoDic).TryGetValue(fromEntityGID.entityID, out var entityInfo)) //there could be multiple entity descriptors registered in the same group, so it's necessary to check if the entity registered in the group has entityInfoComponent @@ -168,18 +167,18 @@ namespace Svelto.ECS //ID. This ID doesn't need to be the EGID, it can be just the entityID //for each group id, save a dictionary indexed by entity type of entities indexed by id // group EntityComponentType entityID, EntityComponent - internal readonly FasterDictionary> + internal readonly FasterDictionary> _groupEntityComponentsDB; //for each entity view type, return the groups (dictionary of entities indexed by entity id) where they are //found indexed by group id. TypeSafeDictionary are never created, they instead point to the ones hold //by _groupEntityComponentsDB // >> - internal readonly FasterDictionary> + internal readonly FasterDictionary> _groupsPerEntity; #if SVELTO_LEGACY_FILTERS //The filters stored for each component and group - internal readonly FasterDictionary> + internal readonly FasterDictionary> _groupFilters; #endif diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs index f3d3d32..8577dff 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs @@ -20,7 +20,7 @@ namespace Svelto.ECS , [CallerMemberName] string caller = null) where T : IEntityDescriptor, new() { return _enginesRoot.Target.BuildEntity(new EGID(entityID, groupStructId) - , EntityDescriptorTemplate.descriptor.componentsToBuild + , EntityDescriptorTemplate.realDescriptor.componentsToBuild , TypeCache.type, implementors, caller); } @@ -29,7 +29,7 @@ namespace Svelto.ECS (EGID egid, IEnumerable implementors = null , [CallerMemberName] string caller = null) where T : IEntityDescriptor, new() { - return _enginesRoot.Target.BuildEntity(egid, EntityDescriptorTemplate.descriptor.componentsToBuild + return _enginesRoot.Target.BuildEntity(egid, EntityDescriptorTemplate.realDescriptor.componentsToBuild , TypeCache.type, implementors, caller); } @@ -65,7 +65,7 @@ namespace Svelto.ECS where T : IEntityDescriptor, new() { _enginesRoot.Target.Preallocate(groupStructId, numberOfEntities - , EntityDescriptorTemplate.descriptor.componentsToBuild); + , EntityDescriptorTemplate.realDescriptor.componentsToBuild); } #if UNITY_NATIVE diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFunctions.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFunctions.cs index 2e780c5..2c03ed1 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFunctions.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFunctions.cs @@ -48,7 +48,7 @@ namespace Svelto.ECS { if (_enginesRoot.Target._groupEntityComponentsDB.TryGetValue( fromGroupID.group - , out FasterDictionary entitiesInGroupPerType) == true) + , out FasterDictionary entitiesInGroupPerType) == true) { #if DEBUG && !PROFILE_SVELTO ITypeSafeDictionary dictionary = entitiesInGroupPerType.unsafeValues[0]; diff --git a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Submission.cs b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Submission.cs index bf3c91a..d267c48 100644 --- a/com.sebaslab.svelto.ecs/Core/EnginesRoot.Submission.cs +++ b/com.sebaslab.svelto.ecs/Core/EnginesRoot.Submission.cs @@ -46,7 +46,7 @@ namespace Svelto.ECS } static void RemoveEntities( - FasterDictionary>> + FasterDictionary>> removeOperations, FasterList entitiesRemoved, EnginesRoot enginesRoot) { using (var sampler = new PlatformProfiler("remove Entities")) @@ -94,7 +94,7 @@ namespace Svelto.ECS foreach (var groupedEntitiesToRemove in entitiesToRemove.value) { - RefWrapperType componentType = groupedEntitiesToRemove.key; + ComponentID componentType = groupedEntitiesToRemove.key; ITypeSafeDictionary fromComponentsDictionary = fromGroupDictionary[componentType]; FasterList<(uint, string)> entityIDsToRemove = groupedEntitiesToRemove.value; @@ -161,7 +161,7 @@ namespace Svelto.ECS } } - static void SwapEntities(FasterDictionary>>> swapEntitiesOperations, FasterList<(EGID, EGID)> entitiesIDSwaps, EnginesRoot enginesRoot) { @@ -262,7 +262,7 @@ namespace Svelto.ECS //get all the engines linked to TValue if (!enginesRoot._reactiveEnginesSwap.TryGetValue( - new RefWrapperType(componentType), + componentType, out var entityComponentsEngines)) continue; @@ -304,8 +304,7 @@ namespace Svelto.ECS //get all the engines linked to TValue if (!enginesRoot._reactiveEnginesSwapEx.TryGetValue( - new RefWrapperType(componentType), - out var entityComponentsEngines)) + componentType, out var entityComponentsEngines)) continue; ExclusiveGroupStruct toGroup = entitiesInfoToSwap.key; @@ -354,9 +353,8 @@ namespace Svelto.ECS { var type = entityComponentsToSubmit.key; var fromDictionary = entityComponentsToSubmit.value; - var wrapper = new RefWrapperType(type); - - var toDictionary = GetOrAddTypeSafeDictionary(groupID, groupDB, wrapper, fromDictionary); + + var toDictionary = GetOrAddTypeSafeDictionary(groupID, groupDB, type, fromDictionary); //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 @@ -385,9 +383,8 @@ namespace Svelto.ECS foreach (var entityComponentsToSubmit in groupToSubmit.components) { var type = entityComponentsToSubmit.key; - var wrapper = new RefWrapperType(type); - - var toDictionary = GetTypeSafeDictionary(groupID, groupDB, wrapper); + + var toDictionary = GetTypeSafeDictionary(groupID, groupDB, type); enumerator.MoveNext(); toDictionary.ExecuteEnginesAddEntityCallbacksFast(_reactiveEnginesAddEx, groupID, enumerator.Current, in sampler); } @@ -465,15 +462,15 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] void SwapEntitiesBetweenGroups(ExclusiveGroupStruct fromGroupId, ExclusiveGroupStruct toGroupId, PlatformProfiler platformProfiler) { - FasterDictionary fromGroup = GetDBGroup(fromGroupId); - FasterDictionary toGroup = GetOrAddDBGroup(toGroupId); + FasterDictionary fromGroup = GetDBGroup(fromGroupId); + FasterDictionary toGroup = GetOrAddDBGroup(toGroupId); _entityLocator.UpdateAllGroupReferenceLocators(fromGroupId, toGroupId); //remove entities from dictionaries foreach (var dictionaryOfEntities in fromGroup) { - RefWrapperType refWrapperType = dictionaryOfEntities.key; + var refWrapperType = dictionaryOfEntities.key; ITypeSafeDictionary fromDictionary = dictionaryOfEntities.value; ITypeSafeDictionary toDictionary = GetOrAddTypeSafeDictionary(toGroupId, toGroup, refWrapperType, fromDictionary); @@ -488,7 +485,7 @@ namespace Svelto.ECS //Call all the callbacks foreach (var dictionaryOfEntities in fromGroup) { - RefWrapperType refWrapperType = dictionaryOfEntities.key; + var refWrapperType = dictionaryOfEntities.key; ITypeSafeDictionary fromDictionary = dictionaryOfEntities.value; ITypeSafeDictionary toDictionary = GetTypeSafeDictionary(toGroupId, toGroup, refWrapperType); @@ -509,20 +506,20 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] ITypeSafeDictionary GetOrAddTypeSafeDictionary(ExclusiveGroupStruct groupId, - FasterDictionary groupPerComponentType, RefWrapperType type, + FasterDictionary groupPerComponentType, ComponentID typeID, ITypeSafeDictionary fromDictionary) { //be sure that the TypeSafeDictionary for the entity Type exists - if (groupPerComponentType.TryGetValue(type, out ITypeSafeDictionary toEntitiesDictionary) == false) + if (groupPerComponentType.TryGetValue(typeID, out ITypeSafeDictionary toEntitiesDictionary) == false) { toEntitiesDictionary = fromDictionary.Create(); - groupPerComponentType.Add(type, toEntitiesDictionary); + groupPerComponentType.Add(typeID, toEntitiesDictionary); } { //update GroupsPerEntity - if (_groupsPerEntity.TryGetValue(type, out var groupedGroup) == false) - groupedGroup = _groupsPerEntity[type] = + if (_groupsPerEntity.TryGetValue(typeID, out var groupedGroup) == false) + groupedGroup = _groupsPerEntity[typeID] = new FasterDictionary(); groupedGroup[groupId] = toEntitiesDictionary; @@ -533,7 +530,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] static ITypeSafeDictionary GetTypeSafeDictionary(ExclusiveGroupStruct groupID, - FasterDictionary @group, RefWrapperType refWrapper) + FasterDictionary @group, ComponentID refWrapper) { if (@group.TryGetValue(refWrapper, out ITypeSafeDictionary fromTypeSafeDictionary) == false) { @@ -553,12 +550,12 @@ namespace Svelto.ECS //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< static readonly - Action>>>, FasterList<(EGID, EGID)> , EnginesRoot> _swapEntities; static readonly Action< - FasterDictionary>>, + FasterDictionary>>, FasterList, EnginesRoot> _removeEntities; static readonly Action _removeGroup; diff --git a/com.sebaslab.svelto.ecs/Core/EntitiesDB.cs b/com.sebaslab.svelto.ecs/Core/EntitiesDB.cs index 7d13aa8..e271f1d 100644 --- a/com.sebaslab.svelto.ecs/Core/EntitiesDB.cs +++ b/com.sebaslab.svelto.ecs/Core/EntitiesDB.cs @@ -19,7 +19,7 @@ namespace Svelto.ECS } EntityCollection InternalQueryEntities - (FasterDictionary entitiesInGroupPerType) + (FasterDictionary entitiesInGroupPerType) where T : struct, _IInternalEntityComponent { uint count = 0; @@ -236,7 +236,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; } @@ -265,17 +265,17 @@ namespace Svelto.ECS return (int)typeSafeDictionary.count; } - public bool FoundInGroups() where T1 : _IInternalEntityComponent + public bool FoundInGroups() where T : struct, _IInternalEntityComponent { - return groupsPerComponent.ContainsKey(TypeRefWrapper.wrapper); + return groupsPerComponent.ContainsKey(ComponentTypeID.id); } [MethodImpl(MethodImplOptions.AggressiveInlining)] bool SafeQueryEntityDictionary (out ITypeSafeDictionary typeSafeDictionary - , FasterDictionary entitiesInGroupPerType) where T : _IInternalEntityComponent + , FasterDictionary entitiesInGroupPerType) where T : struct, _IInternalEntityComponent { - if (entitiesInGroupPerType.TryGetValue(new RefWrapperType(TypeCache.type), out var safeDictionary) + if (entitiesInGroupPerType.TryGetValue(ComponentTypeID.id, out var safeDictionary) == false) { typeSafeDictionary = default; @@ -290,9 +290,9 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool SafeQueryEntityDictionary - (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : _IInternalEntityComponent + (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : struct, _IInternalEntityComponent { - if (UnsafeQueryEntityDictionary(group, TypeCache.type, out var safeDictionary) == false) + if (UnsafeQueryEntityDictionary(group, ComponentTypeID.id, out var safeDictionary) == false) { typeSafeDictionary = default; return false; @@ -306,7 +306,7 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool UnsafeQueryEntityDictionary - (ExclusiveGroupStruct group, Type type, out ITypeSafeDictionary typeSafeDictionary) + (ExclusiveGroupStruct group, ComponentID id, out ITypeSafeDictionary typeSafeDictionary) { //search for the group if (groupEntityComponentsDB.TryGetValue(group, out var entitiesInGroupPerType) == false) @@ -316,7 +316,7 @@ namespace Svelto.ECS } //search for the indexed entities in the group - return entitiesInGroupPerType.TryGetValue(new RefWrapperType(type), out typeSafeDictionary); + return entitiesInGroupPerType.TryGetValue(id, out typeSafeDictionary); } static readonly FasterDictionary _emptyDictionary = @@ -330,14 +330,14 @@ namespace Svelto.ECS //group, then indexable per type, then indexable per EGID. however the TypeSafeDictionary can return an array of //values directly, that can be iterated over, so that is possible to iterate over all the entity components of //a specific type inside a specific group. - FasterDictionary> + FasterDictionary> groupEntityComponentsDB => _enginesRoot._groupEntityComponentsDB; //for each entity view type, return the groups (dictionary of entities indexed by entity id) where they are //found indexed by group id. TypeSafeDictionary are never created, they instead point to the ones hold //by _groupEntityComponentsDB // >> - FasterDictionary> groupsPerComponent => + FasterDictionary> groupsPerComponent => _enginesRoot._groupsPerEntity; EnginesRoot.EntityReferenceMap _entityReferencesMap; diff --git a/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs b/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs index 7da09db..f6364cf 100644 --- a/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs +++ b/com.sebaslab.svelto.ecs/Core/EntitiesOperations.cs @@ -43,7 +43,7 @@ namespace Svelto.ECS foreach (var operation in componentBuilders) { removedComponentsPerType //recycle or create dictionaries per component type - .RecycleOrAdd(new RefWrapperType(operation.GetEntityComponentType()), _newList, _clearList) + .RecycleOrAdd(operation.getComponentID, _newList, _clearList) //add entity to remove .Add((entityEgid.entityID, caller)); } @@ -72,7 +72,7 @@ namespace Svelto.ECS //Get the dictionary for each component that holds the list of entities to swap swappedComponentsPerType //recycle or create dictionaries per component type - .RecycleOrAdd(new RefWrapperType(operation.GetEntityComponentType()), _newGroupDictionary, _recycleDicitionaryWithCaller) + .RecycleOrAdd(operation.getComponentID, _newGroupDictionary, _recycleDicitionaryWithCaller) //recycle or create list of entities to swap .RecycleOrAdd(toID.groupID, _newListWithCaller, _clearListWithCaller) //add entity to swap @@ -86,9 +86,9 @@ namespace Svelto.ECS return _thisSubmissionInfo.AnyOperationQueued(); } - public void ExecuteRemoveAndSwappingOperations(Action>>>, FasterList<(EGID, EGID)>, - EnginesRoot> swapEntities, Action>>, + EnginesRoot> swapEntities, Action>>, FasterList, EnginesRoot> removeEntities, Action removeGroup, Action swapGroup, EnginesRoot enginesRoot) { @@ -137,12 +137,12 @@ namespace Svelto.ECS _lastSubmittedInfo.Clear(); } - FasterDictionary> NewGroupsDictionary() + FasterDictionary> NewGroupsDictionary() { - return new FasterDictionary>(); + return new FasterDictionary>(); } - void RecycleDictionary(ref FasterDictionary> recycled) + void RecycleDictionary(ref FasterDictionary> recycled) { recycled.Recycle(); } @@ -172,13 +172,13 @@ namespace Svelto.ECS return new FasterList<(uint, uint, string)>(); } - FasterDictionary>> NewGroupsDictionaryWithCaller() + FasterDictionary>> NewGroupsDictionaryWithCaller() { - return new FasterDictionary>>(); } - void RecycleGroupDictionaryWithCaller(ref FasterDictionary>> recycled) + void RecycleGroupDictionaryWithCaller(ref FasterDictionary>> recycled) { recycled.Recycle(); } @@ -191,13 +191,13 @@ namespace Svelto.ECS struct Info { //from group //actual component type - internal FasterDictionary>>> _currentSwapEntitiesOperations; internal FasterDictionary>> _currentRemoveEntitiesOperations; + FasterDictionary>> _currentRemoveEntitiesOperations; internal FasterList<(EGID, EGID)> _entitiesSwapped; internal FasterList _entitiesRemoved; @@ -229,11 +229,11 @@ namespace Svelto.ECS _groupsToSwap = new FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)>(); _currentSwapEntitiesOperations = - new FasterDictionary>>>(); _currentRemoveEntitiesOperations = new FasterDictionary>>(); + FasterDictionary>>(); } } @@ -241,12 +241,12 @@ namespace Svelto.ECS Info _thisSubmissionInfo; readonly Func>> _newGroupDictionary; - readonly Func>> _newGroupsDictionary; - readonly ActionRef>> _recycleDictionary; + readonly Func>> _newGroupsDictionary; + readonly ActionRef>> _recycleDictionary; readonly Func> _newList; readonly ActionRef> _clearList; - readonly Func>>> _newGroupsDictionaryWithCaller; - readonly ActionRef>>> _recycleGroupDictionaryWithCaller; + readonly Func>>> _newGroupsDictionaryWithCaller; + readonly ActionRef>>> _recycleGroupDictionaryWithCaller; readonly ActionRef>> _recycleDicitionaryWithCaller; readonly Func> _newListWithCaller; readonly ActionRef> _clearListWithCaller; diff --git a/com.sebaslab.svelto.ecs/Core/EntityCollection.cs b/com.sebaslab.svelto.ecs/Core/EntityCollection.cs index fd6a5ff..1875918 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityCollection.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityCollection.cs @@ -17,8 +17,8 @@ namespace Svelto.ECS public uint count { get; } - internal readonly IBufferBase _buffer; - internal readonly IEntityIDs _entityIDs; + public readonly IBufferBase _buffer; + public readonly IEntityIDs _entityIDs; } public readonly ref struct EntityCollection where T1 : struct, _IInternalEntityComponent diff --git a/com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs b/com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs index 3d42ace..ea65ef8 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs @@ -16,7 +16,7 @@ namespace Svelto.ECS { internal DynamicEntityDescriptor(bool isExtendible) : this() { - var defaultEntities = EntityDescriptorTemplate.descriptor.componentsToBuild; + var defaultEntities = EntityDescriptorTemplate.realDescriptor.componentsToBuild; var length = defaultEntities.Length; if (FetchEntityInfoComponent(defaultEntities) == -1) @@ -56,7 +56,7 @@ namespace Svelto.ECS public void ExtendWith() where T : IEntityDescriptor, new() { - var extraEntities = EntityDescriptorTemplate.descriptor.componentsToBuild; + var extraEntities = EntityDescriptorTemplate.realDescriptor.componentsToBuild; _componentsToBuild = Construct(extraEntities.Length, extraEntities); } diff --git a/com.sebaslab.svelto.ecs/Core/EntityDescriptor/IEntityDescriptor.cs b/com.sebaslab.svelto.ecs/Core/EntityDescriptor/IEntityDescriptor.cs index 45674f2..490df42 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityDescriptor/IEntityDescriptor.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityDescriptor/IEntityDescriptor.cs @@ -1,5 +1,20 @@ namespace Svelto.ECS { + /// + /// When implementing IEntityDescriptor directly the pattern to use is the following: + /// + /// class DoofusEntityDescriptor: IEntityDescriptor +/// { +/// public IComponentBuilder[] componentsToBuild { get; } = +/// { +/// new ComponentBuilder() +/// , new ComponentBuilder() +/// , new ComponentBuilder() +/// , new ComponentBuilder() +/// , ... +/// }; +/// } + /// public interface IEntityDescriptor { IComponentBuilder[] componentsToBuild { get; } diff --git a/com.sebaslab.svelto.ecs/Core/EntityFactory.cs b/com.sebaslab.svelto.ecs/Core/EntityFactory.cs index ff86957..4fd4d89 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityFactory.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityFactory.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Svelto.DataStructures; @@ -5,7 +6,7 @@ namespace Svelto.ECS.Internal { static class EntityFactory { - public static FasterDictionary BuildGroupedEntities + public static FasterDictionary BuildGroupedEntities (EGID egid, EnginesRoot.DoubleBufferedEntitiesToAdd groupEntitiesToAdd, IComponentBuilder[] componentsToBuild , IEnumerable implementors #if DEBUG && !PROFILE_SVELTO @@ -14,7 +15,7 @@ namespace Svelto.ECS.Internal ) { var group = groupEntitiesToAdd.currentComponentsToAddPerGroup.GetOrAdd( - egid.groupID, () => new FasterDictionary()); + egid.groupID, () => new FasterDictionary()); //track the number of entities created so far in the group. groupEntitiesToAdd.IncrementEntityCount(egid.groupID); @@ -29,7 +30,7 @@ namespace Svelto.ECS.Internal } static void BuildEntitiesAndAddToGroup - (EGID entityID, FasterDictionary @group + (EGID entityID, FasterDictionary @group , IComponentBuilder[] componentBuilders, IEnumerable implementors #if DEBUG && !PROFILE_SVELTO , System.Type descriptorType @@ -64,12 +65,10 @@ namespace Svelto.ECS.Internal } } - static void BuildEntity - (EGID entityID, FasterDictionary group - , IComponentBuilder componentBuilder, IEnumerable implementors) + static void BuildEntity(EGID entityID, FasterDictionary group, + IComponentBuilder componentBuilder, IEnumerable implementors) { - var entityComponentType = componentBuilder.GetEntityComponentType(); - ITypeSafeDictionary safeDictionary = group.GetOrAdd(new RefWrapperType(entityComponentType) + ITypeSafeDictionary safeDictionary = group.GetOrAdd(componentBuilder.getComponentID , (ref IComponentBuilder cb) => cb.CreateDictionary(1) , ref componentBuilder); diff --git a/com.sebaslab.svelto.ecs/Core/EntityInfoView.cs b/com.sebaslab.svelto.ecs/Core/EntityInfoView.cs index b6d2852..cb5ef3e 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityInfoView.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityInfoView.cs @@ -1,5 +1,4 @@ using Svelto.ECS.Hybrid; -using Svelto.ECS.Internal; namespace Svelto.ECS { diff --git a/com.sebaslab.svelto.ecs/Core/EntityInitializer.cs b/com.sebaslab.svelto.ecs/Core/EntityInitializer.cs index 0bf812a..f50c49d 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityInitializer.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityInitializer.cs @@ -6,7 +6,7 @@ namespace Svelto.ECS { public readonly ref struct EntityInitializer { - public EntityInitializer(EGID id, FasterDictionary group, + public EntityInitializer(EGID id, FasterDictionary group, in EntityReference reference) { _group = group; @@ -20,7 +20,7 @@ namespace Svelto.ECS public void Init(T initializer) where T : struct, _IInternalEntityComponent { if (_group.TryGetValue( - new RefWrapperType(TypeCache.type), + ComponentTypeID.id, out var typeSafeDictionary) == false) return; @@ -34,10 +34,10 @@ namespace Svelto.ECS dictionary.GetDirectValueByRef(findElementIndex) = initializer; } - internal ref T GetOrAdd() where T : unmanaged, IEntityComponent + internal ref T GetOrAdd() where T : struct, _IInternalEntityComponent { ref var entityDictionary = ref _group.GetOrAdd( - new RefWrapperType(ComponentBuilder.ENTITY_COMPONENT_TYPE), + ComponentTypeID.id, () => new UnmanagedTypeSafeDictionary(1)); var dictionary = (ITypeSafeDictionary)entityDictionary; @@ -46,14 +46,14 @@ namespace Svelto.ECS public ref T Get() where T : struct, _IInternalEntityComponent { - return ref (_group[new RefWrapperType(TypeCache.type)] as ITypeSafeDictionary) + return ref (_group[ComponentTypeID.id] as ITypeSafeDictionary) .GetValueByRef(_ID.entityID); } public bool Has() where T : struct, _IInternalEntityComponent { if (_group.TryGetValue( - new RefWrapperType(TypeCache.type), + ComponentTypeID.id, out var typeSafeDictionary)) { var dictionary = (ITypeSafeDictionary)typeSafeDictionary; @@ -66,6 +66,6 @@ namespace Svelto.ECS } readonly EGID _ID; - readonly FasterDictionary _group; + readonly FasterDictionary _group; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs b/com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs index 175a3f0..dfa9f60 100644 --- a/com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs +++ b/com.sebaslab.svelto.ecs/Core/EntityReference/EnginesRoot.LocatorMap.cs @@ -1,5 +1,4 @@ -using System; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using Svelto.Common; using Svelto.DataStructures; using Svelto.DataStructures.Native; diff --git a/com.sebaslab.svelto.ecs/Core/Filters/CombinedFilterID.cs b/com.sebaslab.svelto.ecs/Core/Filters/CombinedFilterID.cs index 27508bc..2196c31 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/CombinedFilterID.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/CombinedFilterID.cs @@ -1,15 +1,30 @@ -namespace Svelto.ECS +using System; +using System.Runtime.CompilerServices; +using Svelto.ECS.Internal; + +namespace Svelto.ECS { public readonly struct CombinedFilterID { - internal readonly long id; - - public FilterContextID contextID => new FilterContextID((uint)((id & 0xFFFF0000) >> 16)); - public uint filterID => (uint)(id >> 32); + //filter (32) | contextID (16) | component type (16) + readonly long id; + + //a context ID is 16bit + public FilterContextID contextID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new FilterContextID((ushort)((id & 0xFFFF0000) >> 16)); + } + + public uint filterID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => (uint)(id >> 32); + } public CombinedFilterID(int filterID, FilterContextID contextID) { - id = (long)filterID << 32 | (uint)contextID.id << 16; + id = (long)filterID << 32 | (long)contextID.id << 16; } public static implicit operator CombinedFilterID((int filterID, FilterContextID contextID) data) @@ -17,4 +32,72 @@ return new CombinedFilterID(data.filterID, data.contextID); } } + + readonly struct CombinedFilterComponentID: IEquatable + { + //filter (32) | contextID (16) | component type (16) + internal readonly long id; + + //a context ID is 16bit + public FilterContextID contextID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return new FilterContextID((ushort)((id & 0xFFFF0000) >> 16)); + } + } + + public uint filterID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return (uint)(id >> 32); + } + } + + public uint contextComponentID + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return (uint)(id & 0xFFFF); + } + } + + public CombinedFilterComponentID(int filterID, FilterContextID contextID) + { + id = (long)filterID << 32 | (uint)contextID.id << 16; + } + + public CombinedFilterComponentID(uint filterIdFilterId, FilterContextID filterIdContextId, ComponentID componentid) + { + id = (long)filterIdFilterId << 32 | (long)filterIdContextId.id << 16 | (long)(uint)componentid; + } + + public bool Equals(CombinedFilterComponentID other) + { + return id == other.id; + } + + public override int GetHashCode() + { + return id.GetHashCode(); + } + } + + public static class CombinedFilterIDExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static CombinedFilterComponentID CombineComponent(this CombinedFilterID filterID) + where T : struct, _IInternalEntityComponent + { + var componentid = ComponentTypeID.id; + + DBC.ECS.Check.Require(componentid < ushort.MaxValue, "too many component types registered, HOW :)"); + + return new CombinedFilterComponentID(filterID.filterID, filterID.contextID, componentid); + } + } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Filters/EnginesRoot.Filters.cs b/com.sebaslab.svelto.ecs/Core/Filters/EnginesRoot.Filters.cs index 71ae6ed..305f329 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/EnginesRoot.Filters.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/EnginesRoot.Filters.cs @@ -8,10 +8,12 @@ namespace Svelto.ECS { void InitFilters() { - _transientEntityFilters = new SharedSveltoDictionaryNative(0); - _persistentEntityFilters = new SharedSveltoDictionaryNative(0); + _transientEntityFilters = new SharedSveltoDictionaryNative(0); + _persistentEntityFilters = new SharedSveltoDictionaryNative(0); _indicesOfPersistentFiltersUsedByThisComponent = - new SharedSveltoDictionaryNative>(0); + new SharedSveltoDictionaryNative>(0); + _indicesOfTransientFiltersUsedByThisComponent = + new SharedSveltoDictionaryNative>(0); } void DisposeFilters() @@ -20,7 +22,12 @@ namespace Svelto.ECS { filter.value.Dispose(); } - + + foreach (var filter in _indicesOfTransientFiltersUsedByThisComponent) + { + filter.value.Dispose(); + } + foreach (var filter in _persistentEntityFilters) { filter.value.Dispose(); @@ -34,6 +41,7 @@ namespace Svelto.ECS _transientEntityFilters.Dispose(); _persistentEntityFilters.Dispose(); _indicesOfPersistentFiltersUsedByThisComponent.Dispose(); + _indicesOfTransientFiltersUsedByThisComponent.Dispose(); } void ClearTransientFilters() @@ -54,12 +62,12 @@ namespace Svelto.ECS /// /// void RemoveEntitiesFromPersistentFilters - (FasterList<(uint entityID, string)> entityIDsRemoved, ExclusiveGroupStruct fromGroup, RefWrapperType refWrapperType + (FasterList<(uint entityID, string)> entityIDsRemoved, ExclusiveGroupStruct fromGroup, ComponentID refWrapperType , ITypeSafeDictionary fromDic, FasterList entityIDsLeftAndAffectedByRemoval) { //is there any filter used by this component? if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue( - new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast listOfFilters) == true) + refWrapperType, out NativeDynamicArrayCast listOfFilters) == true) { var numberOfFilters = listOfFilters.count; var filters = _persistentEntityFilters.unsafeValues; @@ -117,11 +125,11 @@ namespace Svelto.ECS void SwapEntityBetweenPersistentFilters (FasterList<(uint, uint, string)> fromEntityToEntityIDs, ITypeSafeDictionary fromDic , ITypeSafeDictionary toDic, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup - , RefWrapperType refWrapperType, FasterList entityIDsLeftAndAffectedByRemoval) + , ComponentID refWrapperType, FasterList entityIDsLeftAndAffectedByRemoval) { //is there any filter used by this component? if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue( - new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast listOfFilters) == true) + refWrapperType, out NativeDynamicArrayCast listOfFilters) == true) { DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?"); var numberOfFilters = listOfFilters.count; @@ -181,10 +189,10 @@ namespace Svelto.ECS } } - internal SharedSveltoDictionaryNative _transientEntityFilters; - internal SharedSveltoDictionaryNative _persistentEntityFilters; + internal SharedSveltoDictionaryNative _transientEntityFilters; + internal SharedSveltoDictionaryNative _persistentEntityFilters; - internal SharedSveltoDictionaryNative> - _indicesOfPersistentFiltersUsedByThisComponent; + internal SharedSveltoDictionaryNative> _indicesOfPersistentFiltersUsedByThisComponent; + public SharedSveltoDictionaryNative> _indicesOfTransientFiltersUsedByThisComponent; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/Filters/EntitiesDB.Filters.cs b/com.sebaslab.svelto.ecs/Core/Filters/EntitiesDB.Filters.cs index 8baae31..4a81f21 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/EntitiesDB.Filters.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/EntitiesDB.Filters.cs @@ -13,15 +13,12 @@ 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) + //ComponentTypeID + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static CombinedFilterComponentID CombineFilterIDWithComponentID(CombinedFilterID combinedFilterID) where T : struct, _IInternalEntityComponent { - var id = (uint)ComponentID.id.Data; - - var combineFilterIDs = (long)combinedFilterID.id | id; - - return combineFilterIDs; + return combinedFilterID.CombineComponent(); } } @@ -31,7 +28,9 @@ namespace Svelto.ECS { return new SveltoFilters( _enginesRoot._persistentEntityFilters, - _enginesRoot._indicesOfPersistentFiltersUsedByThisComponent, _enginesRoot._transientEntityFilters); + _enginesRoot._indicesOfPersistentFiltersUsedByThisComponent, + _enginesRoot._transientEntityFilters, + _enginesRoot._indicesOfTransientFiltersUsedByThisComponent); } /// @@ -47,45 +46,45 @@ namespace Svelto.ECS #endif public static FilterContextID GetNewContextID() { - return new FilterContextID((uint)Interlocked.Increment(ref uniqueContextID.Data)); + return new FilterContextID((ushort)Interlocked.Increment(ref uniqueContextID.Data)); } - public SveltoFilters(SharedSveltoDictionaryNative persistentEntityFilters, - SharedSveltoDictionaryNative> - indicesOfPersistentFiltersUsedByThisComponent, - SharedSveltoDictionaryNative transientEntityFilters) + internal SveltoFilters(SharedSveltoDictionaryNative persistentEntityFilters, + SharedSveltoDictionaryNative> indicesOfPersistentFiltersUsedByThisComponent, + SharedSveltoDictionaryNative transientEntityFilters, + SharedSveltoDictionaryNative> indicesOfTransientFiltersUsedByThisComponent) { _persistentEntityFilters = persistentEntityFilters; _indicesOfPersistentFiltersUsedByThisComponent = indicesOfPersistentFiltersUsedByThisComponent; _transientEntityFilters = transientEntityFilters; + _indicesOfTransientFiltersUsedByThisComponent = indicesOfTransientFiltersUsedByThisComponent; } -#if UNITY_BURST //the following methods do not make sense without burst as they are workaround for burst - public ref EntityFilterCollection GetOrCreatePersistentFilter(int filterID, - FilterContextID filterContextId, NativeRefWrapperType typeRef) - where T : unmanaged, IEntityComponent + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref EntityFilterCollection GetOrCreatePersistentFilter(int filterID, FilterContextID filterContextId) + where T : struct, _IInternalEntityComponent { - return ref GetOrCreatePersistentFilter(new CombinedFilterID(filterID, filterContextId), typeRef); + return ref GetOrCreatePersistentFilter(new CombinedFilterID(filterID, filterContextId)); } - public ref EntityFilterCollection GetOrCreatePersistentFilter(CombinedFilterID filterID, - NativeRefWrapperType typeRef) - where T : unmanaged, IEntityComponent + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref EntityFilterCollection GetOrCreatePersistentFilter(CombinedFilterID filterID) where T : struct, _IInternalEntityComponent { - long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(filterID); - if (_persistentEntityFilters.TryFindIndex(combineFilterIDs, out var index) == true) + if (_persistentEntityFilters.TryFindIndex(componentAndFilterID, out var index) == true) return ref _persistentEntityFilters.GetDirectValueByRef(index); - _persistentEntityFilters.Add(combineFilterIDs, new EntityFilterCollection(filterID)); + _persistentEntityFilters.Add(componentAndFilterID, new EntityFilterCollection(filterID)); var lastIndex = _persistentEntityFilters.count - 1; - if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex(typeRef, out var getIndex) == false) + var componentId = ComponentTypeID.id; + if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex(componentId, out var getIndex) == false) { var newArray = new NativeDynamicArrayCast(1, Allocator.Persistent); newArray.Add(lastIndex); - _indicesOfPersistentFiltersUsedByThisComponent.Add(typeRef, newArray); + _indicesOfPersistentFiltersUsedByThisComponent.Add(componentId, newArray); } else { @@ -95,7 +94,6 @@ namespace Svelto.ECS return ref _persistentEntityFilters.GetDirectValueByRef((uint)lastIndex); } -#endif /// /// Create a persistent filter. Persistent filters are not deleted after each submission, @@ -104,57 +102,26 @@ namespace Svelto.ECS /// /// /// + #if UNITY_BURST && UNITY_COLLECTIONS - [Unity.Burst.BurstDiscard] //not burst compatible because of TypeRefWrapper.wrapper; + [Unity.Burst.BurstDiscard] //not burst compatible because of ComponentTypeID.id and GetOrAdd callback; #endif [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref EntityFilterCollection GetOrCreatePersistentFilter(int filterID, - FilterContextID filterContextId) - where T : unmanaged, _IInternalEntityComponent - { - return ref GetOrCreatePersistentFilter(new CombinedFilterID(filterID, filterContextId)); - } -#if UNITY_BURST && UNITY_COLLECTIONS - [Unity.Burst.BurstDiscard] //not burst compatible because of TypeRefWrapper.wrapper and GetOrAdd callback; -#endif - public ref EntityFilterCollection GetOrCreatePersistentFilter(CombinedFilterID filterID) - where T : unmanaged, _IInternalEntityComponent - { - long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); - - if (_persistentEntityFilters.TryFindIndex(combineFilterIDs, out var index) == true) - return ref _persistentEntityFilters.GetDirectValueByRef(index); - - var typeRef = TypeRefWrapper.wrapper; - var filterCollection = new EntityFilterCollection(filterID); - - _persistentEntityFilters.Add(combineFilterIDs, filterCollection); - - var lastIndex = _persistentEntityFilters.count - 1; - - _indicesOfPersistentFiltersUsedByThisComponent.GetOrAdd(new NativeRefWrapperType(typeRef), _builder).Add(lastIndex); - - return ref _persistentEntityFilters.GetDirectValueByRef((uint)lastIndex); - } -#if UNITY_BURST && UNITY_COLLECTIONS - [Unity.Burst.BurstDiscard] //not burst compatible because of TypeRefWrapper.wrapper and GetOrAdd callback; -#endif public ref EntityFilterCollection CreatePersistentFilter(CombinedFilterID filterID) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(filterID); - if (_persistentEntityFilters.TryFindIndex(combineFilterIDs, out var index) == true) + if (_persistentEntityFilters.TryFindIndex(componentAndFilterID, out var index) == true) throw new ECSException("filter already exists"); - var typeRef = TypeRefWrapper.wrapper; var filterCollection = new EntityFilterCollection(filterID); - _persistentEntityFilters.Add(combineFilterIDs, filterCollection); + _persistentEntityFilters.Add(componentAndFilterID, filterCollection); var lastIndex = _persistentEntityFilters.count - 1; - _indicesOfPersistentFiltersUsedByThisComponent.GetOrAdd(new NativeRefWrapperType(typeRef), _builder).Add(lastIndex); + _indicesOfPersistentFiltersUsedByThisComponent.GetOrAdd(ComponentTypeID.id, _builder).Add(lastIndex); return ref _persistentEntityFilters.GetDirectValueByRef((uint)lastIndex); } @@ -166,18 +133,18 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref EntityFilterCollection GetPersistentFilter(int filterID, FilterContextID filterContextId) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { return ref GetPersistentFilter(new CombinedFilterID(filterID, filterContextId)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref EntityFilterCollection GetPersistentFilter(CombinedFilterID filterID) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(filterID); - if (_persistentEntityFilters.TryFindIndex(combineFilterIDs, out var index) == true) + if (_persistentEntityFilters.TryFindIndex(componentAndFilterID, out var index) == true) return ref _persistentEntityFilters.GetDirectValueByRef(index); throw new ECSException("filter not found"); @@ -186,11 +153,11 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetPersistentFilter(CombinedFilterID combinedFilterID, out EntityFilterCollection entityCollection) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - long combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(combinedFilterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(combinedFilterID); - if (_persistentEntityFilters.TryFindIndex(combineFilterIDs, out var index) == true) + if (_persistentEntityFilters.TryFindIndex(componentAndFilterID, out var index) == true) { entityCollection = _persistentEntityFilters.GetDirectValueByRef(index); return true; @@ -200,12 +167,15 @@ namespace Svelto.ECS return false; } + /// + /// Svelto.ECS tracks the filters linked to each + /// component. This allows to iterate over all the filters of a given filter context linked to a component. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityFilterCollectionsEnumerator GetPersistentFilters() - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex( - new NativeRefWrapperType(new RefWrapperType(typeof(T))), out var index) == true) + if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) return new EntityFilterCollectionsEnumerator( _indicesOfPersistentFiltersUsedByThisComponent.GetDirectValueByRef(index), _persistentEntityFilters); @@ -215,9 +185,9 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityFilterCollectionsWithContextEnumerator GetPersistentFilters(FilterContextID filterContextId) + where T : struct, _IInternalEntityComponent { - if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex( - new NativeRefWrapperType(new RefWrapperType(typeof(T))), out var index) == true) + if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) return new EntityFilterCollectionsWithContextEnumerator( _indicesOfPersistentFiltersUsedByThisComponent.GetDirectValueByRef(index), _persistentEntityFilters, filterContextId); @@ -228,13 +198,12 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetPersistentFilters(FilterContextID filterContextId, out EntityFilterCollectionsWithContextEnumerator enumerator) + where T : struct, _IInternalEntityComponent { - if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex( - new NativeRefWrapperType(new RefWrapperType(typeof(T))), out var index) == true) + if (_indicesOfPersistentFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) { - enumerator = new EntityFilterCollectionsWithContextEnumerator( - _indicesOfPersistentFiltersUsedByThisComponent.GetDirectValueByRef(index), - _persistentEntityFilters, filterContextId); + ref var filterIndices = ref _indicesOfPersistentFiltersUsedByThisComponent.GetDirectValueByRef(index); + enumerator = new EntityFilterCollectionsWithContextEnumerator(filterIndices, _persistentEntityFilters, filterContextId); return true; } @@ -245,32 +214,49 @@ namespace Svelto.ECS /// /// Creates a transient filter. Transient filters are deleted after each submission + /// transient filters are identified by filterID and Context and can be linked to several groups. + /// So for each group there can be as many as necessary transient filters with different ID and contextID /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref EntityFilterCollection GetOrCreateTransientFilter(CombinedFilterID filterID) - where T : unmanaged, _IInternalEntityComponent + public ref EntityFilterCollection GetOrCreateTransientFilter(CombinedFilterID combinedFilterID, bool trackFilter = false) + where T : struct, _IInternalEntityComponent { - var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(combinedFilterID); - if (_transientEntityFilters.TryFindIndex(combineFilterIDs, out var index)) + if (_transientEntityFilters.TryFindIndex(componentAndFilterID, out var index)) return ref _transientEntityFilters.GetDirectValueByRef(index); - var filterCollection = new EntityFilterCollection(filterID); + return ref InternalCreateTransientFilter(combinedFilterID, componentAndFilterID, trackFilter); + } - _transientEntityFilters.Add(combineFilterIDs, filterCollection); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref EntityFilterCollection GetOrCreateTransientFilter(int filterID, FilterContextID filterContextId) + where T : struct, _IInternalEntityComponent + { + return ref GetOrCreateTransientFilter(new CombinedFilterID(filterID, filterContextId)); + } - return ref _transientEntityFilters.GetDirectValueByRef((uint)(_transientEntityFilters.count - 1)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref EntityFilterCollection CreateTransientFilter(CombinedFilterID combinedFilterID, bool trackFilter = false) + where T : struct, _IInternalEntityComponent + { + CombinedFilterComponentID componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(combinedFilterID); +#if DEBUG && !PROFILE_SVELTO + if (_transientEntityFilters.TryFindIndex(componentAndFilterID, out _)) + throw new ECSException($"filter already exists {TypeCache.name}"); +#endif + return ref InternalCreateTransientFilter(combinedFilterID, componentAndFilterID, trackFilter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetTransientFilter(CombinedFilterID filterID, out EntityFilterCollection entityCollection) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(filterID); - if (_transientEntityFilters.TryFindIndex(combineFilterIDs, out var index)) + if (_transientEntityFilters.TryFindIndex(componentAndFilterID, out var index)) { entityCollection = _transientEntityFilters.GetDirectValueByRef(index); return true; @@ -279,37 +265,89 @@ namespace Svelto.ECS entityCollection = default; return false; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref EntityFilterCollection GetTransientFilter(CombinedFilterID filterID) - where T : unmanaged, _IInternalEntityComponent + where T : struct, _IInternalEntityComponent { - var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); + var componentAndFilterID = Internal_FilterHelper.CombineFilterIDWithComponentID(filterID); - if (_transientEntityFilters.TryFindIndex(combineFilterIDs, out var index)) + if (_transientEntityFilters.TryFindIndex(componentAndFilterID, out var index)) { return ref _transientEntityFilters.GetDirectValueByRef(index); } - + throw new ECSException($"no filters associated with the type {TypeCache.name}"); } - - public void CreateTransientFilter(CombinedFilterID filterID) + + /// + /// Svelto.ECS tracks the filters linked to each + /// component. This allows to iterate over all the filters of a given filter context linked to a component. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public EntityFilterCollectionsEnumerator GetTransientFilters() + where T : struct, _IInternalEntityComponent + { + if (_indicesOfTransientFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) + return new EntityFilterCollectionsEnumerator( + _indicesOfTransientFiltersUsedByThisComponent.GetDirectValueByRef(index), + _transientEntityFilters); + + throw new ECSException($"no filters associated with the type {TypeCache.name}"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public EntityFilterCollectionsWithContextEnumerator GetTransientFilters(FilterContextID filterContextId) + where T : struct, _IInternalEntityComponent + { + if (_indicesOfTransientFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) + return new EntityFilterCollectionsWithContextEnumerator( + _indicesOfTransientFiltersUsedByThisComponent.GetDirectValueByRef(index), + _transientEntityFilters, filterContextId); + + throw new ECSException($"no filters associated with the type {TypeCache.name}"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryGetTransientFilters(FilterContextID filterContextId, out EntityFilterCollectionsWithContextEnumerator enumerator) + where T : struct, _IInternalEntityComponent + { + if (_indicesOfTransientFiltersUsedByThisComponent.TryFindIndex(ComponentTypeID.id, out var index) == true) + { + enumerator = new EntityFilterCollectionsWithContextEnumerator( + _indicesOfTransientFiltersUsedByThisComponent.GetDirectValueByRef(index), + _transientEntityFilters, filterContextId); + + return true; + } + + enumerator = default; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + ref EntityFilterCollection InternalCreateTransientFilter(CombinedFilterID filterID, CombinedFilterComponentID componentAndFilterID, + bool trackFilter) where T : struct, _IInternalEntityComponent { - var combineFilterIDs = Internal_FilterHelper.CombineFilterIDs(filterID); -#if DEBUG && !PROFILE_SVELTO - if (_transientEntityFilters.TryFindIndex(combineFilterIDs, out _)) - throw new ECSException($"filter already exists {TypeCache.name}"); -#endif var filterCollection = new EntityFilterCollection(filterID); - _transientEntityFilters.Add(combineFilterIDs, filterCollection); + _transientEntityFilters.Add(componentAndFilterID, filterCollection); + + if (trackFilter) + { + var typeRef = ComponentTypeID.id; + var lastIndex = _transientEntityFilters.count - 1; + _indicesOfTransientFiltersUsedByThisComponent.GetOrAdd(ComponentTypeID.id, _builder).Add(lastIndex); + } + + return ref _transientEntityFilters.GetDirectValueByRef((uint)(_transientEntityFilters.count - 1)); } - + public struct EntityFilterCollectionsEnumerator { - public EntityFilterCollectionsEnumerator(NativeDynamicArrayCast getDirectValueByRef, - SharedSveltoDictionaryNative sharedSveltoDictionaryNative): this() + internal EntityFilterCollectionsEnumerator(NativeDynamicArrayCast getDirectValueByRef, + SharedSveltoDictionaryNative sharedSveltoDictionaryNative): this() { _getDirectValueByRef = getDirectValueByRef; _sharedSveltoDictionaryNative = sharedSveltoDictionaryNative; @@ -336,24 +374,24 @@ namespace Svelto.ECS public ref EntityFilterCollection Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_currentIndex - 1); - } + get => ref _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_currentIndex - 1); } readonly NativeDynamicArrayCast _getDirectValueByRef; - readonly SharedSveltoDictionaryNative _sharedSveltoDictionaryNative; + readonly SharedSveltoDictionaryNative _sharedSveltoDictionaryNative; int _currentIndex; } + /// + /// TODO: ABSOLUTELY UNIT TEST THIS AS THE CODE WAS WRONG!!! + /// public struct EntityFilterCollectionsWithContextEnumerator { - public EntityFilterCollectionsWithContextEnumerator(NativeDynamicArrayCast getDirectValueByRef, - SharedSveltoDictionaryNative sharedSveltoDictionaryNative, + internal EntityFilterCollectionsWithContextEnumerator(NativeDynamicArrayCast filterIndices, + SharedSveltoDictionaryNative sharedSveltoDictionaryNative, FilterContextID filterContextId): this() { - _getDirectValueByRef = getDirectValueByRef; + _filterIndices = filterIndices; _sharedSveltoDictionaryNative = sharedSveltoDictionaryNative; _filterContextId = filterContextId; } @@ -366,11 +404,11 @@ namespace Svelto.ECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { - while (_currentIndex++ < _getDirectValueByRef.count && - _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_currentIndex - 1).combinedFilterID - .contextID.id != _filterContextId.id) ; + while (_currentIndex++ < _filterIndices.count && + _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_filterIndices[(uint)_currentIndex - 1]).combinedFilterID + .contextID.id != _filterContextId.id); - if (_currentIndex - 1 < _getDirectValueByRef.count) + if (_currentIndex - 1 < _filterIndices.count) return true; return false; @@ -379,24 +417,25 @@ namespace Svelto.ECS public ref EntityFilterCollection Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_currentIndex - 1); - } + get => ref _sharedSveltoDictionaryNative.GetDirectValueByRef((uint)_filterIndices[(uint)_currentIndex - 1]); } - readonly NativeDynamicArrayCast _getDirectValueByRef; - readonly SharedSveltoDictionaryNative _sharedSveltoDictionaryNative; + readonly NativeDynamicArrayCast _filterIndices; + readonly SharedSveltoDictionaryNative _sharedSveltoDictionaryNative; readonly FilterContextID _filterContextId; int _currentIndex; } - readonly SharedSveltoDictionaryNative _persistentEntityFilters; + readonly SharedSveltoDictionaryNative _persistentEntityFilters; - readonly SharedSveltoDictionaryNative> + readonly SharedSveltoDictionaryNative> _indicesOfPersistentFiltersUsedByThisComponent; - readonly SharedSveltoDictionaryNative _transientEntityFilters; + readonly SharedSveltoDictionaryNative _transientEntityFilters; + + readonly SharedSveltoDictionaryNative> + _indicesOfTransientFiltersUsedByThisComponent; + static readonly Func> _builder = Builder; } } diff --git a/com.sebaslab.svelto.ecs/Core/Filters/FilterContextID.cs b/com.sebaslab.svelto.ecs/Core/Filters/FilterContextID.cs index 2f286bc..abf051b 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/FilterContextID.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/FilterContextID.cs @@ -2,9 +2,9 @@ { public struct FilterContextID { - public readonly uint id; + public readonly ushort id; - internal FilterContextID(uint id) + internal FilterContextID(ushort id) { DBC.ECS.Check.Require(id < ushort.MaxValue, "too many types registered, HOW :)"); diff --git a/com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs b/com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs index 2a48772..bc2e74f 100644 --- a/com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs +++ b/com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs @@ -16,7 +16,7 @@ namespace Svelto.ECS /// public partial class EntitiesDB { - FasterDictionary> _filters => + FasterDictionary> _filters => _enginesRoot._groupFilters; public LegacyFilters GetLegacyFilters() @@ -27,7 +27,7 @@ namespace Svelto.ECS public readonly struct LegacyFilters { public LegacyFilters( - FasterDictionary> + FasterDictionary> filtersLegacy) { _filtersLegacy = filtersLegacy; @@ -36,14 +36,14 @@ namespace Svelto.ECS public ref LegacyFilterGroup CreateOrGetFilterForGroup(int filterID, ExclusiveGroupStruct groupID) where T : struct, _IInternalEntityComponent { - var refWrapper = TypeRefWrapper.wrapper; + var refWrapper = ComponentTypeID.id; return ref CreateOrGetFilterForGroup(filterID, groupID, refWrapper); } public bool HasFiltersForGroup(ExclusiveGroupStruct groupID) where T : struct, _IInternalEntityComponent { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary) == false) return false; return fasterDictionary.ContainsKey(groupID); @@ -52,7 +52,7 @@ namespace Svelto.ECS public bool HasFilterForGroup(int filterID, ExclusiveGroupStruct groupID) where T : struct, _IInternalEntityComponent { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary) == false) return false; if (fasterDictionary.TryGetValue(groupID, out var result)) @@ -64,7 +64,7 @@ namespace Svelto.ECS public ref LegacyGroupFilters CreateOrGetFiltersForGroup(ExclusiveGroupStruct groupID) where T : struct, _IInternalEntityComponent { - var fasterDictionary = _filtersLegacy.GetOrAdd(TypeRefWrapper.wrapper, + var fasterDictionary = _filtersLegacy.GetOrAdd(ComponentTypeID.id, () => new FasterDictionary()); return ref fasterDictionary.GetOrAdd(groupID, @@ -75,27 +75,27 @@ namespace Svelto.ECS where T : struct, _IInternalEntityComponent { #if DEBUG && !PROFILE_SVELTO - if (_filtersLegacy.ContainsKey(TypeRefWrapper.wrapper) == false) + if (_filtersLegacy.ContainsKey(ComponentTypeID.id) == false) throw new ECSException($"trying to fetch not existing filters, type {typeof(T)}"); - if (_filtersLegacy[TypeRefWrapper.wrapper].ContainsKey(groupID) == false) + if (_filtersLegacy[ComponentTypeID.id].ContainsKey(groupID) == false) throw new ECSException( $"trying to fetch not existing filters, type {typeof(T)} group {groupID.ToName()}"); #endif - return ref _filtersLegacy[TypeRefWrapper.wrapper].GetValueByRef(groupID); + return ref _filtersLegacy[ComponentTypeID.id].GetValueByRef(groupID); } public ref LegacyFilterGroup GetFilterForGroup(int filterId, ExclusiveGroupStruct groupID) where T : struct, _IInternalEntityComponent { #if DEBUG && !PROFILE_SVELTO - if (_filtersLegacy.ContainsKey(TypeRefWrapper.wrapper) == false) + if (_filtersLegacy.ContainsKey(ComponentTypeID.id) == false) throw new ECSException($"trying to fetch not existing filters, type {typeof(T)}"); - if (_filtersLegacy[TypeRefWrapper.wrapper].ContainsKey(groupID) == false) + if (_filtersLegacy[ComponentTypeID.id].ContainsKey(groupID) == false) throw new ECSException( $"trying to fetch not existing filters, type {typeof(T)} group {groupID.ToName()}"); #endif - return ref _filtersLegacy[TypeRefWrapper.wrapper][groupID].GetFilter(filterId); + return ref _filtersLegacy[ComponentTypeID.id][groupID].GetFilter(filterId); } public bool TryGetFilterForGroup(int filterId, ExclusiveGroupStruct groupID, @@ -103,7 +103,7 @@ namespace Svelto.ECS { groupLegacyFilter = default; - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary) == false) return false; if (fasterDictionary.TryGetValue(groupID, out var groupFilters) == false) @@ -120,7 +120,7 @@ namespace Svelto.ECS { legacyGroupFilters = default; - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary) == false) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary) == false) return false; return fasterDictionary.TryGetValue(groupID, out legacyGroupFilters); @@ -128,7 +128,7 @@ namespace Svelto.ECS public void ClearFilter(int filterID, ExclusiveGroupStruct exclusiveGroupStruct) { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary)) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary)) { Check.Require(fasterDictionary.ContainsKey(exclusiveGroupStruct), $"trying to clear filter not present in group {exclusiveGroupStruct}"); @@ -139,14 +139,14 @@ namespace Svelto.ECS public void ClearFilters(int filterID) { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary)) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary)) foreach (var filtersPerGroup in fasterDictionary) filtersPerGroup.value.ClearFilter(filterID); } public void DisposeFilters(ExclusiveGroupStruct exclusiveGroupStruct) { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary)) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary)) { fasterDictionary[exclusiveGroupStruct].DisposeFilters(); fasterDictionary.Remove(exclusiveGroupStruct); @@ -155,16 +155,16 @@ namespace Svelto.ECS public void DisposeFilters() { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary)) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary)) foreach (var filtersPerGroup in fasterDictionary) filtersPerGroup.value.DisposeFilters(); - _filtersLegacy.Remove(TypeRefWrapper.wrapper); + _filtersLegacy.Remove(ComponentTypeID.id); } public void DisposeFilterForGroup(int resetFilterID, ExclusiveGroupStruct group) { - if (_filtersLegacy.TryGetValue(TypeRefWrapper.wrapper, out var fasterDictionary)) + if (_filtersLegacy.TryGetValue(ComponentTypeID.id, out var fasterDictionary)) fasterDictionary[@group].DisposeFilter(resetFilterID); } @@ -205,7 +205,7 @@ namespace Svelto.ECS return ref filters.CreateOrGetFilter(filterID); } - readonly FasterDictionary> + readonly FasterDictionary> _filtersLegacy; } } diff --git a/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs b/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs index 23adf1a..397b21d 100644 --- a/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs +++ b/com.sebaslab.svelto.ecs/Core/Groups/EntitiesDB.FindGroups.cs @@ -7,11 +7,11 @@ namespace Svelto.ECS { public partial class EntitiesDB { - public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) where T1 : _IInternalEntityComponent + public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) where T1 : struct, _IInternalEntityComponent { FasterList result = localgroups.Value.groupArray; result.Clear(); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(ComponentTypeID.id , out FasterDictionary result1) == false) return result; @@ -31,15 +31,15 @@ namespace Svelto.ECS } public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) - where T1 : _IInternalEntityComponent where T2 : _IInternalEntityComponent + where T1 : struct, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent { FasterList result = localgroups.Value.groupArray; result.Clear(); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(ComponentTypeID.id , out FasterDictionary result1) == false) return result; - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper + if (groupsPerComponent.TryGetValue(ComponentTypeID.id , out FasterDictionary result2) == false) return result; @@ -82,18 +82,18 @@ namespace Svelto.ECS /// /// public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) - where T1 : _IInternalEntityComponent where T2 : _IInternalEntityComponent where T3 : _IInternalEntityComponent + where T1 : struct, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent where T3 : struct, _IInternalEntityComponent { FasterList> localArray = localgroups.Value.listOfGroups; - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[0]) == false || localArray[0].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[1]) == false || localArray[1].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[2]) == false || localArray[2].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); @@ -131,24 +131,24 @@ namespace Svelto.ECS } public LocalFasterReadOnlyList FindGroups(bool ignoreDisabledBit = false) - where T1 : _IInternalEntityComponent - where T2 : _IInternalEntityComponent - where T3 : _IInternalEntityComponent - where T4 : _IInternalEntityComponent + where T1 : struct, _IInternalEntityComponent + where T2 : struct, _IInternalEntityComponent + where T3 : struct, _IInternalEntityComponent + where T4 : struct, _IInternalEntityComponent { FasterList> localArray = localgroups.Value.listOfGroups; - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[0]) == false || localArray[0].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[0]) == false || localArray[0].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[1]) == false || localArray[1].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[1]) == false || localArray[1].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[2]) == false || localArray[2].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[2]) == false || localArray[2].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); - if (groupsPerComponent.TryGetValue(TypeRefWrapper.wrapper, out localArray[3]) == false || localArray[3].count == 0) + if (groupsPerComponent.TryGetValue(ComponentTypeID.id, out localArray[3]) == false || localArray[3].count == 0) return new LocalFasterReadOnlyList( FasterReadOnlyList.DefaultEmptyList); @@ -192,12 +192,12 @@ namespace Svelto.ECS , (uint) localGroups.count); } - internal FasterDictionary FindGroups_INTERNAL(Type type) + internal FasterDictionary FindGroups_INTERNAL(ComponentID type) { - if (groupsPerComponent.ContainsKey(new RefWrapperType(type)) == false) + if (groupsPerComponent.ContainsKey(type) == false) return _emptyDictionary; - return groupsPerComponent[new RefWrapperType(type)]; + return groupsPerComponent[type]; } struct GroupsList diff --git a/com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs b/com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs new file mode 100644 index 0000000..7125bfb --- /dev/null +++ b/com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Svelto.ECS +{ + public static class EntityDescriptorsWarmup + { + /// + /// c# Static constructors are guaranteed to be thread safe + /// Warmup all EntityDescriptors and ComponentTypeID classes to avoid huge overheads when they are first used + /// + internal static void Init() + { + List assemblies = AssemblyUtility.GetCompatibleAssemblies(); + foreach (Assembly assembly in assemblies) + { + var typeOfEntityDescriptors = typeof(IEntityDescriptor); + + foreach (Type type in AssemblyUtility.GetTypesSafe(assembly)) + { + if (typeOfEntityDescriptors.IsAssignableFrom(type)) //IsClass and IsSealed and IsAbstract means only static classes + { + var warmup = typeof(EntityDescriptorTemplate<>).MakeGenericType(type); + try + { + System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup.TypeHandle); + } + catch + { + continue; + } + + PropertyInfo field = warmup.GetProperty("descriptor", BindingFlags.Static | BindingFlags.Public); + object value = field.GetValue(null); // pass null because the field is static + +// cast the value to your descriptor type + IEntityDescriptor descriptor = (IEntityDescriptor)value; + foreach (IComponentBuilder component in descriptor.componentsToBuild) + { + var typeArguments = component.GetEntityComponentType(); + var warmup2 = typeof(ComponentTypeID<>).MakeGenericType(typeArguments); + System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup2.TypeHandle); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/IComponentBuilder.cs b/com.sebaslab.svelto.ecs/Core/IComponentBuilder.cs index a1fb0db..ce1f4de 100644 --- a/com.sebaslab.svelto.ecs/Core/IComponentBuilder.cs +++ b/com.sebaslab.svelto.ecs/Core/IComponentBuilder.cs @@ -12,5 +12,6 @@ namespace Svelto.ECS Type GetEntityComponentType(); bool isUnmanaged { get; } + ComponentID getComponentID { get; } } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Core/IEngine.cs b/com.sebaslab.svelto.ecs/Core/IEngine.cs index 271e26c..c622fc1 100644 --- a/com.sebaslab.svelto.ecs/Core/IEngine.cs +++ b/com.sebaslab.svelto.ecs/Core/IEngine.cs @@ -40,6 +40,10 @@ namespace Svelto.ECS.Internal public interface IReactOnSwapEx : IReactEngine { } + + public interface IReactOnDisposeEx : IReactEngine + { + } public interface IReactOnDispose : IReactEngine { @@ -132,6 +136,12 @@ namespace Svelto.ECS void MovedTo((uint start, uint end) rangeOfEntities, in EntityCollection entities, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup); } + + public interface IReactOnDisposeEx : IReactOnDisposeEx where T : struct, _IInternalEntityComponent + { + void Remove((uint start, uint end) rangeOfEntities, in EntityCollection entities, + ExclusiveGroupStruct groupID); + } /// /// Interface to mark an Engine as reacting after each entities submission phase diff --git a/com.sebaslab.svelto.ecs/Core/Streams/EntitiesStreams.cs b/com.sebaslab.svelto.ecs/Core/Streams/EntitiesStreams.cs index cd93291..7129a62 100644 --- a/com.sebaslab.svelto.ecs/Core/Streams/EntitiesStreams.cs +++ b/com.sebaslab.svelto.ecs/Core/Streams/EntitiesStreams.cs @@ -18,25 +18,29 @@ namespace Svelto.ECS internal Consumer GenerateConsumer(string name, uint capacity) where T : unmanaged, _IInternalEntityComponent { - if (_streams.ContainsKey(TypeRefWrapper.wrapper) == false) - _streams[TypeRefWrapper.wrapper] = new EntityStream(); + var componentId = ComponentTypeID.id; + + if (_streams.ContainsKey(componentId) == false) + _streams[componentId] = new EntityStream(); - return (_streams[TypeRefWrapper.wrapper] as EntityStream).GenerateConsumer(name, capacity); + return (_streams[componentId] as EntityStream).GenerateConsumer(name, capacity); } public Consumer GenerateConsumer(ExclusiveGroupStruct group, string name, uint capacity) where T : unmanaged, _IInternalEntityComponent { - if (_streams.ContainsKey(TypeRefWrapper.wrapper) == false) - _streams[TypeRefWrapper.wrapper] = new EntityStream(); + var componentId = ComponentTypeID.id; + + if (_streams.ContainsKey(componentId) == false) + _streams[componentId] = new EntityStream(); - var typeSafeStream = (EntityStream) _streams[TypeRefWrapper.wrapper]; + var typeSafeStream = (EntityStream) _streams[componentId]; return typeSafeStream.GenerateConsumer(group, name, capacity); } internal void PublishEntity(ref T entity, EGID egid) where T : unmanaged, _IInternalEntityComponent { - if (_streams.TryGetValue(TypeRefWrapper.wrapper, out var typeSafeStream)) + if (_streams.TryGetValue(ComponentTypeID.id, out var typeSafeStream)) (typeSafeStream as EntityStream).PublishEntity(ref entity, egid); else Console.LogDebug($"No Consumers are waiting for this entity to change {typeof(T)}"); @@ -51,11 +55,11 @@ namespace Svelto.ECS public static EntitiesStreams Create() { var stream = new EntitiesStreams(); - stream._streams = FasterDictionary.Construct(); + stream._streams = FasterDictionary.Construct(); return stream; } - FasterDictionary _streams; + FasterDictionary _streams; } } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/DataStructures/ITypeSafeDictionary.cs b/com.sebaslab.svelto.ecs/DataStructures/ITypeSafeDictionary.cs index 2a9fb81..5ad6fb5 100644 --- a/com.sebaslab.svelto.ecs/DataStructures/ITypeSafeDictionary.cs +++ b/com.sebaslab.svelto.ecs/DataStructures/ITypeSafeDictionary.cs @@ -39,11 +39,11 @@ namespace Svelto.ECS.Internal //This is now obsolete, but I cannot mark it as such because it's heavily used by legacy projects void ExecuteEnginesAddCallbacks - (FasterDictionary>> entityComponentEnginesDb + (FasterDictionary>> entityComponentEnginesDb , ITypeSafeDictionary destinationDatabase, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler); //Version to use void ExecuteEnginesAddEntityCallbacksFast( - FasterDictionary>> reactiveEnginesAdd, + FasterDictionary>> reactiveEnginesAdd, ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler); //------------ @@ -61,7 +61,7 @@ namespace Svelto.ECS.Internal //This is now obsolete, but I cannot mark it as such because it's heavily used by legacy projects void ExecuteEnginesRemoveCallbacks(FasterList<(uint, string)> infosToProcess, - FasterDictionary>> reactiveEnginesRemove, + FasterDictionary>> reactiveEnginesRemove, ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler); //Version to use void ExecuteEnginesRemoveCallbacksFast(FasterList> reactiveEnginesRemoveEx, @@ -71,17 +71,18 @@ namespace Svelto.ECS.Internal //------------ void ExecuteEnginesSwapCallbacks_Group( - FasterDictionary>> reactiveEnginesSwap, - FasterDictionary>> reactiveEnginesSwapEx, + FasterDictionary>> reactiveEnginesSwap, + FasterDictionary>> reactiveEnginesSwapEx, ITypeSafeDictionary toEntitiesDictionary, ExclusiveGroupStruct fromGroupId, ExclusiveGroupStruct toGroupId, in PlatformProfiler platformProfiler); void ExecuteEnginesRemoveCallbacks_Group( - FasterDictionary>> engines, - FasterDictionary>> reactiveEnginesRemoveEx, + FasterDictionary>> reactiveEnginesRemove, + FasterDictionary>> reactiveEnginesRemoveEx, ExclusiveGroupStruct @group, in PlatformProfiler profiler); void ExecuteEnginesDisposeCallbacks_Group - (FasterDictionary>> engines - , ExclusiveGroupStruct group, in PlatformProfiler profiler); + (FasterDictionary>> reactiveEnginesDispose, + FasterDictionary>> reactiveEnginesDisposeEx, + ExclusiveGroupStruct group, in PlatformProfiler profiler); void IncreaseCapacityBy(uint size); void EnsureCapacity(uint size); diff --git a/com.sebaslab.svelto.ecs/DataStructures/ManagedTypeSafeDictionary.cs b/com.sebaslab.svelto.ecs/DataStructures/ManagedTypeSafeDictionary.cs index 1d7b272..1581585 100644 --- a/com.sebaslab.svelto.ecs/DataStructures/ManagedTypeSafeDictionary.cs +++ b/com.sebaslab.svelto.ecs/DataStructures/ManagedTypeSafeDictionary.cs @@ -9,13 +9,13 @@ namespace Svelto.ECS.Internal sealed class ManagedTypeSafeDictionary : ITypeSafeDictionary where TValue : struct, _IInternalEntityComponent { + //todo: would this be better to not be static to avoid overhead? static readonly ThreadLocal cachedEntityIDM = new ThreadLocal(() => new ManagedEntityIDs()); public ManagedTypeSafeDictionary(uint size) { - implMgd = - new SveltoDictionary>, ManagedStrategy, + implMgd = new SveltoDictionary>, ManagedStrategy, ManagedStrategy>(size, Allocator.Managed); } @@ -181,7 +181,7 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddCallbacks - (FasterDictionary>> entityComponentEnginesDB + (FasterDictionary>> entityComponentEnginesDB , ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddCallbacks(ref implMgd, (ITypeSafeDictionary)toDic @@ -207,7 +207,7 @@ namespace Svelto.ECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks (FasterList<(uint, string)> infosToProcess - , FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemove , ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks(infosToProcess, ref implMgd, reactiveEnginesRemove @@ -219,7 +219,7 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddEntityCallbacksFast - (FasterDictionary>> reactiveEnginesAdd + (FasterDictionary>> reactiveEnginesAdd , ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddEntityCallbacksFast( @@ -257,14 +257,14 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesSwapCallbacks_Group - (FasterDictionary>> reactiveEnginesSwap - , FasterDictionary>> reactiveEnginesSwapEx + (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); + ref implMgd, (ITypeSafeDictionary)toDictionary, toGroup, fromGroup, reactiveEnginesSwap + , reactiveEnginesSwapEx, entityIDs, in profiler); } /// @@ -273,12 +273,12 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks_Group - (FasterDictionary>> reactiveEnginesRemove - , FasterDictionary>> reactiveEnginesRemoveEx + (FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemoveEx , ExclusiveGroupStruct group, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks_Group( - ref implMgd, this, reactiveEnginesRemove, reactiveEnginesRemoveEx, count, entityIDs, group + ref implMgd, reactiveEnginesRemove, reactiveEnginesRemoveEx, entityIDs, group , in profiler); } @@ -287,10 +287,12 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesDisposeCallbacks_Group - (FasterDictionary>> engines - , ExclusiveGroupStruct group, in PlatformProfiler profiler) + (FasterDictionary>> reactiveEnginesDispose, + FasterDictionary>> reactiveEnginesDisposeEx, + ExclusiveGroupStruct group, in PlatformProfiler profiler) { - TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group(ref implMgd, engines, group, in profiler); + TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group( + ref implMgd, reactiveEnginesDispose, reactiveEnginesDisposeEx, entityIDs, group, in profiler); } SveltoDictionary>, ManagedStrategy, diff --git a/com.sebaslab.svelto.ecs/DataStructures/TypeSafeDictionaryMethods.cs b/com.sebaslab.svelto.ecs/DataStructures/TypeSafeDictionaryMethods.cs index 10ccded..b58844c 100644 --- a/com.sebaslab.svelto.ecs/DataStructures/TypeSafeDictionaryMethods.cs +++ b/com.sebaslab.svelto.ecs/DataStructures/TypeSafeDictionaryMethods.cs @@ -57,7 +57,7 @@ namespace Svelto.ECS.Internal public static void ExecuteEnginesAddCallbacks( ref SveltoDictionary fromDictionary , ITypeSafeDictionary todic, ExclusiveGroupStruct togroup - , FasterDictionary>> entitycomponentenginesdb + , FasterDictionary>> entitycomponentenginesdb , in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> where Strategy2 : struct, IBufferStrategy @@ -65,7 +65,7 @@ namespace Svelto.ECS.Internal where TValue : struct, _IInternalEntityComponent { if (entitycomponentenginesdb.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var entityComponentsEngines)) { if (entityComponentsEngines.count == 0) @@ -101,14 +101,15 @@ namespace Svelto.ECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ExecuteEnginesDisposeCallbacks_Group( ref SveltoDictionary fromDictionary - , FasterDictionary>> allEngines - , ExclusiveGroupStruct inGroup, in PlatformProfiler sampler) + , FasterDictionary>> reactiveEnginesDispose + , FasterDictionary>> reactiveEnginesDisposeEx + , IEntityIDs entityids, ExclusiveGroupStruct group, in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> where Strategy2 : struct, IBufferStrategy where Strategy3 : struct, IBufferStrategy where TValue : struct, _IInternalEntityComponent { - if (allEngines.TryGetValue(new RefWrapperType(TypeCache.type), out var entityComponentsEngines) + if (reactiveEnginesDispose.TryGetValue(ComponentTypeID.id, out var entityComponentsEngines) == false) return; @@ -120,7 +121,7 @@ namespace Svelto.ECS.Internal foreach (var value in fromDictionary) { ref var entity = ref value.value; - var egid = new EGID(value.key, inGroup); + var egid = new EGID(value.key, group); var reactOnRemove = (IReactOnDispose)entityComponentsEngines[i].engine; reactOnRemove.Remove(ref entity, egid); } @@ -132,12 +133,41 @@ namespace Svelto.ECS.Internal throw; } + + + var count = fromDictionary.count; + + if (reactiveEnginesDisposeEx.TryGetValue( + ComponentTypeID.id + , out var reactiveEnginesDisposeExPerType)) + { + var enginesCount = reactiveEnginesDisposeExPerType.count; + + for (var i = 0; i < enginesCount; i++) + try + { + using (sampler.Sample(reactiveEnginesDisposeExPerType[i].name)) + { + ((IReactOnDisposeEx)reactiveEnginesDisposeExPerType[i].engine).Remove( + (0, (uint)count) + , new EntityCollection( + fromDictionary.UnsafeGetValues(out _), entityids + , (uint)count), group); + } + } + catch + { + Console.LogError("Code crashed inside Remove callback ".FastConcat(reactiveEnginesDisposeExPerType[i].name)); + + throw; + } + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ExecuteEnginesRemoveCallbacks(FasterList<(uint, string)> infostoprocess , ref SveltoDictionary fromDictionary - , FasterDictionary>> reactiveenginesremove + , FasterDictionary>> reactiveenginesremove , ExclusiveGroupStruct fromgroup, in PlatformProfiler profiler) where Strategy1 : struct, IBufferStrategy> where Strategy2 : struct, IBufferStrategy @@ -145,7 +175,7 @@ namespace Svelto.ECS.Internal where TValue : struct, _IInternalEntityComponent { if (reactiveenginesremove.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var entityComponentsEngines)) { if (entityComponentsEngines.count == 0) @@ -185,17 +215,16 @@ namespace Svelto.ECS.Internal [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) + , FasterDictionary>> reactiveenginesremove + , FasterDictionary>> reactiveenginesremoveex + , IEntityIDs entityids, ExclusiveGroupStruct group, in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> where Strategy2 : struct, IBufferStrategy where Strategy3 : struct, IBufferStrategy where TValue : struct, _IInternalEntityComponent { if (reactiveenginesremove.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var reactiveEnginesRemovePerType)) { var enginesCount = reactiveEnginesRemovePerType.count; @@ -226,9 +255,10 @@ namespace Svelto.ECS.Internal } if (reactiveenginesremoveex.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var reactiveEnginesRemoveExPerType)) { + var count = fromDictionary.count; var enginesCount = reactiveEnginesRemoveExPerType.count; for (var i = 0; i < enginesCount; i++) @@ -239,7 +269,7 @@ namespace Svelto.ECS.Internal ((IReactOnRemoveEx)reactiveEnginesRemoveExPerType[i].engine).Remove( (0, (uint)count) , new EntityCollection( - typeSafeDictionary.GetValues(out _), entityids + fromDictionary.UnsafeGetValues(out _), entityids , (uint)count), group); } } @@ -300,10 +330,9 @@ namespace Svelto.ECS.Internal 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) + , FasterDictionary>> reactiveenginesswap + , FasterDictionary>> reactiveenginesswapex + , IEntityIDs entityids, in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy> where Strategy2 : struct, IBufferStrategy where Strategy3 : struct, IBufferStrategy @@ -311,7 +340,7 @@ namespace Svelto.ECS.Internal { //get all the engines linked to TValue if (!reactiveenginesswap.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var reactiveEnginesSwapPerType)) return; @@ -342,10 +371,11 @@ namespace Svelto.ECS.Internal } if (reactiveenginesswapex.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var reactiveEnginesRemoveExPerType)) { var enginesCount = reactiveEnginesRemoveExPerType.count; + var count = fromDictionary.count; for (var i = 0; i < enginesCount; i++) try @@ -355,7 +385,7 @@ namespace Svelto.ECS.Internal ((IReactOnSwapEx)reactiveEnginesRemoveExPerType[i].engine).MovedTo( (0, (uint)count) , new EntityCollection( - typeSafeDictionary.GetValues(out _), entityids + fromDictionary.UnsafeGetValues(out _), entityids , (uint)count), fromgroup, togroup); } } @@ -467,14 +497,14 @@ namespace Svelto.ECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ExecuteEnginesAddEntityCallbacksFast( - FasterDictionary>> fasterDictionary + FasterDictionary>> fasterDictionary , ExclusiveGroupStruct groupId, (uint, uint) rangeTuple, IEntityIDs entityids , ITypeSafeDictionary typeSafeDictionary, PlatformProfiler profiler) where TValue : struct, _IInternalEntityComponent { //get all the engines linked to TValue if (!fasterDictionary.TryGetValue( - new RefWrapperType(TypeCache.type) + ComponentTypeID.id , out var entityComponentsEngines)) return; diff --git a/com.sebaslab.svelto.ecs/DataStructures/UnmanagedTypeSafeDictionary.cs b/com.sebaslab.svelto.ecs/DataStructures/UnmanagedTypeSafeDictionary.cs index ea50b28..2a2ae60 100644 --- a/com.sebaslab.svelto.ecs/DataStructures/UnmanagedTypeSafeDictionary.cs +++ b/com.sebaslab.svelto.ecs/DataStructures/UnmanagedTypeSafeDictionary.cs @@ -22,13 +22,13 @@ namespace Svelto.ECS.Internal sealed class UnmanagedTypeSafeDictionary : ITypeSafeDictionary where TValue : struct, _IInternalEntityComponent { + //todo: would this be better to not be static to avoid overhead? static readonly ThreadLocal cachedEntityIDN = new ThreadLocal(() => new NativeEntityIDs()); public UnmanagedTypeSafeDictionary(uint size) { - implUnmgd = - new SharedSveltoDictionaryNative(size, Allocator.Persistent); + implUnmgd = new SharedSveltoDictionaryNative(size, Allocator.Persistent); } public IEntityIDs entityIDs @@ -193,7 +193,7 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddCallbacks - (FasterDictionary>> entityComponentEnginesDB + (FasterDictionary>> entityComponentEnginesDB , ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddCallbacks(ref implUnmgd.dictionary, (ITypeSafeDictionary)toDic @@ -219,7 +219,7 @@ namespace Svelto.ECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks (FasterList<(uint, string)> infosToProcess - , FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemove , ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks(infosToProcess, ref implUnmgd.dictionary @@ -231,7 +231,7 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddEntityCallbacksFast - (FasterDictionary>> reactiveEnginesAdd + (FasterDictionary>> reactiveEnginesAdd , ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddEntityCallbacksFast( @@ -269,14 +269,14 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesSwapCallbacks_Group - (FasterDictionary>> reactiveEnginesSwap - , FasterDictionary>> reactiveEnginesSwapEx + (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); + ref implUnmgd.dictionary, (ITypeSafeDictionary)toDictionary, toGroup, fromGroup + , reactiveEnginesSwap, reactiveEnginesSwapEx, entityIDs, in profiler); } /// @@ -285,12 +285,12 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks_Group - (FasterDictionary>> reactiveEnginesRemove - , FasterDictionary>> reactiveEnginesRemoveEx + (FasterDictionary>> reactiveEnginesRemove + , FasterDictionary>> reactiveEnginesRemoveEx , ExclusiveGroupStruct group, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks_Group( - ref implUnmgd.dictionary, this, reactiveEnginesRemove, reactiveEnginesRemoveEx, count, entityIDs, group + ref implUnmgd.dictionary, reactiveEnginesRemove, reactiveEnginesRemoveEx, entityIDs, group , in profiler); } @@ -299,11 +299,12 @@ namespace Svelto.ECS.Internal /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesDisposeCallbacks_Group - (FasterDictionary>> engines + ( FasterDictionary>> reactiveEnginesDispose + , FasterDictionary>> reactiveEnginesDisposeEx , ExclusiveGroupStruct group, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group( - ref implUnmgd.dictionary, engines, group, in profiler); + ref implUnmgd.dictionary, reactiveEnginesDispose, reactiveEnginesDisposeEx, entityIDs, group, in profiler); } internal SharedSveltoDictionaryNative implUnmgd; diff --git a/com.sebaslab.svelto.ecs/Extensions/Native/EnginesRoot.NativeOperation.cs b/com.sebaslab.svelto.ecs/Extensions/Native/EnginesRoot.NativeOperation.cs index 79b1a7c..a838428 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Native/EnginesRoot.NativeOperation.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Native/EnginesRoot.NativeOperation.cs @@ -143,9 +143,9 @@ namespace Svelto.ECS var typeID = buffer.Dequeue(); - IFiller entityBuilder = EntityComponentIDMap.GetTypeFromID(typeID); + IFiller componentBuilder = EntityComponentIDMap.GetBuilderFromID(typeID); //after the typeID, I expect the serialized component - entityBuilder.FillFromByteArray(init, buffer); + componentBuilder.FillFromByteArray(init, buffer); } } } diff --git a/com.sebaslab.svelto.ecs/Core/GlobalTypeID.cs b/com.sebaslab.svelto.ecs/Extensions/Native/NativeComponentFiller.cs similarity index 66% rename from com.sebaslab.svelto.ecs/Core/GlobalTypeID.cs rename to com.sebaslab.svelto.ecs/Extensions/Native/NativeComponentFiller.cs index 1285ce6..2b860c7 100644 --- a/com.sebaslab.svelto.ecs/Core/GlobalTypeID.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Native/NativeComponentFiller.cs @@ -1,19 +1,9 @@ -using System.Threading; using Svelto.Common; using Svelto.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS { - public class GlobalTypeID - { - internal static uint NextID() { return (uint) (Interlocked.Increment(ref value) - 1); } - - static GlobalTypeID() { value = 0; } - - static int value; - } - interface IFiller { void FillFromByteArray(EntityInitializer init, NativeBag buffer); @@ -36,12 +26,6 @@ namespace Svelto.ECS } #if UNITY_NATIVE //at the moment I am still considering NativeOperations useful only for Unity - static class EntityComponentID - { - internal static readonly Unity.Burst.SharedStatic ID = - Unity.Burst.SharedStatic.GetOrCreate(); - } - static class EntityComponentIDMap { static readonly Svelto.DataStructures.FasterList TYPE_IDS; @@ -53,11 +37,11 @@ namespace Svelto.ECS internal static void Register(IFiller entityBuilder) where T : struct, _IInternalEntityComponent { - var location = EntityComponentID.ID.Data = GlobalTypeID.NextID(); + ComponentID location = ComponentTypeID.id; TYPE_IDS.AddAt(location, entityBuilder); } - internal static IFiller GetTypeFromID(uint typeId) { return TYPE_IDS[typeId]; } + internal static IFiller GetBuilderFromID(uint typeId) { return TYPE_IDS[typeId]; } } #endif } \ No newline at end of file diff --git a/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityFactory.cs b/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityFactory.cs index f8ce312..46f4888 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityFactory.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityFactory.cs @@ -32,8 +32,7 @@ namespace Svelto.ECS.Native EntityReference reference = _entityLocator.ClaimReference(); NativeBag bagPerEntityPerThread = _addOperationQueue.GetBag(threadIndex + 1); - bagPerEntityPerThread.Enqueue( - _operationIndex); //each native operation is stored in an array, each request to perform a native operation in a queue. _index is the index of the operation in the array that will be dequeued later + bagPerEntityPerThread.Enqueue(_operationIndex); //each native operation is stored in an array, each request to perform a native operation in a queue. _index is the index of the operation in the array that will be dequeued later bagPerEntityPerThread.Enqueue(new EGID(eindex, exclusiveBuildGroup)); bagPerEntityPerThread.Enqueue(reference); diff --git a/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityInitializer.cs b/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityInitializer.cs index 4e72dcd..d013a45 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityInitializer.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Native/NativeEntityInitializer.cs @@ -20,7 +20,7 @@ namespace Svelto.ECS.Native [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Init(in T component) where T : unmanaged, IEntityComponent { - uint componentID = EntityComponentID.ID.Data; + uint componentID = ComponentTypeID.id; _unsafeBuffer.AccessReserved(_componentsToInitializeCounterRef)++; //increase the number of components that have been initialised by the user diff --git a/com.sebaslab.svelto.ecs/Extensions/Svelto/AllGroupsEnumerable.cs b/com.sebaslab.svelto.ecs/Extensions/Svelto/AllGroupsEnumerable.cs index ebf231e..4214679 100644 --- a/com.sebaslab.svelto.ecs/Extensions/Svelto/AllGroupsEnumerable.cs +++ b/com.sebaslab.svelto.ecs/Extensions/Svelto/AllGroupsEnumerable.cs @@ -35,7 +35,7 @@ namespace Svelto.ECS { public GroupsIterator(EntitiesDB db) : this() { - _db = db.FindGroups_INTERNAL(TypeCache.type).GetEnumerator(); + _db = db.FindGroups_INTERNAL(ComponentTypeID.id).GetEnumerator(); } public bool MoveNext() diff --git a/com.sebaslab.svelto.ecs/Serialization/EnginesRoot.GenericEntitySerialization.cs b/com.sebaslab.svelto.ecs/Serialization/EnginesRoot.GenericEntitySerialization.cs index 8e1c8d8..cb47353 100644 --- a/com.sebaslab.svelto.ecs/Serialization/EnginesRoot.GenericEntitySerialization.cs +++ b/com.sebaslab.svelto.ecs/Serialization/EnginesRoot.GenericEntitySerialization.cs @@ -1,7 +1,6 @@ using System; using System.Runtime.CompilerServices; using Svelto.DataStructures; -using Svelto.ECS.Internal; using Svelto.ECS.Serialization; namespace Svelto.ECS @@ -208,7 +207,7 @@ namespace Svelto.ECS ISerializationData serializationData, int serializationType) { ExclusiveGroupStruct groupId = entityGID.groupID; - Type entityType = componentBuilder.GetEntityComponentType(); + var entityType = componentBuilder.getComponentID; if (!_enginesRoot._entitiesDB.UnsafeQueryEntityDictionary(groupId, entityType, out var safeDictionary)) { throw new Exception("Entity Serialization failed"); @@ -230,7 +229,7 @@ namespace Svelto.ECS foreach (var serializableEntityBuilder in entityDescriptor.componentsToSerialize) { entitiesInGroupPerType.TryGetValue( - new RefWrapperType(serializableEntityBuilder.GetEntityComponentType()), out var safeDictionary); + serializableEntityBuilder.getComponentID, out var safeDictionary); serializationData.BeginNextEntityComponent(); serializableEntityBuilder.Deserialize(egid.entityID, safeDictionary, serializationData, diff --git a/com.sebaslab.svelto.ecs/Serialization/IEntitySerialization.cs b/com.sebaslab.svelto.ecs/Serialization/IEntitySerialization.cs index 08b68b7..c1bf424 100644 --- a/com.sebaslab.svelto.ecs/Serialization/IEntitySerialization.cs +++ b/com.sebaslab.svelto.ecs/Serialization/IEntitySerialization.cs @@ -1,5 +1,4 @@ using System.Runtime.CompilerServices; -using Svelto.ECS.Internal; namespace Svelto.ECS.Serialization { diff --git a/com.sebaslab.svelto.ecs/Serialization/SerializableEntityDescriptor.cs b/com.sebaslab.svelto.ecs/Serialization/SerializableEntityDescriptor.cs index 7878d4b..b0613f3 100644 --- a/com.sebaslab.svelto.ecs/Serialization/SerializableEntityDescriptor.cs +++ b/com.sebaslab.svelto.ecs/Serialization/SerializableEntityDescriptor.cs @@ -16,7 +16,7 @@ namespace Svelto.ECS.Serialization { static SerializableEntityDescriptor() { - IComponentBuilder[] defaultEntities = EntityDescriptorTemplate.descriptor.componentsToBuild; + IComponentBuilder[] defaultEntities = EntityDescriptorTemplate.realDescriptor.componentsToBuild; var hashNameAttribute = Type.GetCustomAttribute(); if (hashNameAttribute == null) @@ -49,13 +49,12 @@ namespace Svelto.ECS.Serialization ///// var entitiesToSerialize = new FasterList(); - EntityComponentsToSerializeMap = new FasterDictionary(); + EntityComponentsToSerializeMap = new FasterDictionary(); foreach (IComponentBuilder e in defaultEntities) { if (e is ISerializableComponentBuilder serializableEntityBuilder) { - var entityType = serializableEntityBuilder.GetEntityComponentType(); - EntityComponentsToSerializeMap[new RefWrapperType(entityType)] = serializableEntityBuilder; + EntityComponentsToSerializeMap[serializableEntityBuilder.getComponentID] = serializableEntityBuilder; entitiesToSerialize.Add(serializableEntityBuilder); } } @@ -99,7 +98,7 @@ namespace Svelto.ECS.Serialization public ISerializableComponentBuilder[] componentsToSerialize => EntitiesToSerialize; static readonly IComponentBuilder[] ComponentsToBuild; - static readonly FasterDictionary EntityComponentsToSerializeMap; + static readonly FasterDictionary EntityComponentsToSerializeMap; static readonly ISerializableComponentBuilder[] EntitiesToSerialize; static readonly uint Hash; diff --git a/com.sebaslab.svelto.ecs/Svelto.ECS.csproj b/com.sebaslab.svelto.ecs/Svelto.ECS.csproj index f68ec94..87fa700 100644 --- a/com.sebaslab.svelto.ecs/Svelto.ECS.csproj +++ b/com.sebaslab.svelto.ecs/Svelto.ECS.csproj @@ -1,11 +1,11 @@  Svelto.ECS - 9 + 10 netstandard2.1 Svelto - 3.4.3 - 3.4.3 + 3.4 + true Debug;Release;SlowSubmissionRelease;SlowSubmissionDebug AnyCPU diff --git a/com.sebaslab.svelto.ecs/package.json b/com.sebaslab.svelto.ecs/package.json index 0ad09cd..8cc7fb1 100644 --- a/com.sebaslab.svelto.ecs/package.json +++ b/com.sebaslab.svelto.ecs/package.json @@ -11,7 +11,7 @@ "url": "https://github.com/sebas77/Svelto.ECS.git" }, "dependencies": { - "com.sebaslab.svelto.common": "3.4.1" + "com.sebaslab.svelto.common": "3.4.2" }, "keywords": [ "svelto", @@ -19,7 +19,7 @@ "svelto.ecs" ], "name": "com.sebaslab.svelto.ecs", - "version": "3.4.3", + "version": "3.4.4", "type": "library", "unity": "2020.3" } diff --git a/com.sebaslab.svelto.ecs/version.json b/com.sebaslab.svelto.ecs/version.json index 4c49bb1..28ff4ef 100644 --- a/com.sebaslab.svelto.ecs/version.json +++ b/com.sebaslab.svelto.ecs/version.json @@ -1,3 +1,3 @@ { - "version": "3.4.3" + "version": "3.4.4" }