internal void DestroyEntity(MatchingArchetypeList archetypeList, EntityQueryFilter filter)
        {
            Profiler.BeginSample("DestroyEntity(EntityQuery entityQueryFilter)");

            Profiler.BeginSample("GetAllMatchingChunks");
            var jobHandle = new JobHandle();

            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                Profiler.EndSample();

                if (chunks.Length != 0)
                {
                    BeforeStructuralChange();

                    Profiler.BeginSample("EditorOnlyChecks");
                    EntityComponentStore->AssertCanDestroy(chunks);
                    EntityComponentStore->AssertWillDestroyAllInLinkedEntityGroup(chunks, GetArchetypeChunkBufferType <LinkedEntityGroup>(false));
                    Profiler.EndSample();

                    Profiler.BeginSample("DeleteChunks");
                    EntityManagerCreateDestroyEntitiesUtility.DestroyEntities(chunks, EntityComponentStore, ManagedComponentStore);
                    Profiler.EndSample();
                }
            }

            Profiler.EndSample();
        }
        internal void AddComponent(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter, ComponentType componentType)
        {
            var jobHandle = new JobHandle();

            //@TODO: Missing EntityQuery.SyncFilter
            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                if (chunks.Length == 0)
                {
                    return;
                }

                BeforeStructuralChange();
                var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

                EntityComponentStore->AssertCanAddComponent(chunks, componentType);

                using (var entityBatchList = m_EntityComponentStore->CreateEntityBatchList(chunks))
                {
                    EntityComponentStore->AddComponentFromMainThread(entityBatchList, componentType, 0);
                }

                var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
                EntityQueryManager.AddAdditionalArchetypes(changedArchetypes);
                ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            }
        }
Beispiel #3
0
        internal void RemoveComponent(MatchingArchetypeList archetypeList, EntityQueryFilter filter,
                                      ComponentType componentType)
        {
            var jobHandle = new JobHandle();

            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                if (chunks.Length == 0)
                {
                    return;
                }

                BeforeStructuralChange();
                var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

                EntityComponentStore->AssertCanRemoveComponent(chunks, componentType);
                EntityManagerChangeArchetypeUtility.RemoveComponent(chunks, componentType,
                                                                    EntityComponentStore,
                                                                    ManagedComponentStore);

                var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
                EntityGroupManager.AddAdditionalArchetypes(changedArchetypes);
            }
        }
Beispiel #4
0
        internal void AddComponent(MatchingArchetypeList archetypeList, EntityQueryFilter filter,
                                   ComponentType componentType)
        {
            var jobHandle = new JobHandle();

            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                if (chunks.Length == 0)
                {
                    return;
                }

                BeforeStructuralChange();
                EntityComponentStore->AssertCanAddComponent(chunks, componentType);

                using (var entityBatchList = m_EntityComponentStore->CreateEntityBatchList(chunks))
                {
                    EntityManagerChangeArchetypeUtility.AddComponent(entityBatchList, componentType, 0,
                                                                     EntityComponentStore,
                                                                     ManagedComponentStore,
                                                                     EntityGroupManager);
                }
            }
        }
 internal EntityQuery(EntityQueryData *queryData, ComponentJobSafetyManager *safetyManager, EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore)
 {
     m_QueryData             = queryData;
     m_Filter                = default(EntityQueryFilter);
     m_SafetyManager         = safetyManager;
     m_EntityComponentStore  = entityComponentStore;
     m_ManagedComponentStore = managedComponentStore;
 }
Beispiel #6
0
 internal EntityQuery(EntityGroupData *groupData, ComponentJobSafetyManager *safetyManager, ArchetypeManager typeManager, EntityDataManager *entityDataManager)
 {
     m_GroupData         = groupData;
     m_EntityDataManager = entityDataManager;
     m_Filter            = default(EntityQueryFilter);
     m_SafetyManager     = safetyManager;
     ArchetypeManager    = typeManager;
     EntityDataManager   = entityDataManager;
 }
        /// <summary>
        ///     Sets this EntityQuery's filter while preserving its version number.
        /// </summary>
        /// <param name="filter">EntityQueryFilter to use all data but RequiredChangeVersion from.</param>
        void SetFilter(ref EntityQueryFilter filter)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            filter.AssertValid();
#endif
            var version = m_Filter.RequiredChangeVersion;
            ResetFilter();
            m_Filter = filter;
            m_Filter.RequiredChangeVersion = version;
        }
        /// <summary>
        /// Filters out entities in chunks for which the specified component has not changed.
        /// </summary>
        /// <remarks>
        ///     Saves a given ComponentType's index in RequiredComponents in this group's Changed filter.
        /// </remarks>
        /// <param name="componentType">ComponentType to mark as changed on this EntityQuery's filter.</param>
        public void SetFilterChanged(ComponentType componentType)
        {
            var filter = new EntityQueryFilter();

            filter.Type          = FilterType.Changed;
            filter.Changed.Count = 1;
            filter.Changed.IndexInEntityQuery[0] = GetIndexInEntityQuery(componentType.TypeIndex);

            SetFilter(ref filter);
        }
Beispiel #9
0
        /// <summary>
        /// Creates a NativeArray with all the chunks in a given archetype filtered by the provided EntityQueryFilter.
        /// This function will sync the needed types in the EntityQueryFilter.
        /// </summary>
        /// <param name="matchingArchetypes">List of matching archetypes.</param>
        /// <param name="allocator">Allocator to use for the array.</param>
        /// <param name="jobHandle">Handle to the GatherChunks job used to fill the output array.</param>
        /// <param name="filter">Filter used to filter the resulting chunks</param>
        /// <param name="dependencyManager">The ComponentDependencyManager belonging to this world</param>
        /// <param name="dependsOn">All jobs spawned will depend on this JobHandle</param>

        /// <returns>NativeArray of all the chunks in the matchingArchetypes list.</returns>
        public static NativeArray <ArchetypeChunk> CreateArchetypeChunkArray(
            UnsafeMatchingArchetypePtrList matchingArchetypes, Allocator allocator,
            ref EntityQueryFilter filter, ComponentDependencyManager *dependencyManager)
        {
            EntityQuery.SyncFilterTypes(ref matchingArchetypes, ref filter, dependencyManager);
            var chunks = CreateArchetypeChunkArrayWithoutSync(matchingArchetypes, allocator, out var jobHandle, ref filter);

            jobHandle.Complete();
            return(chunks);
        }
        internal void RemoveComponent(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter, ComponentType componentType)
        {
            //@TODO: Missing EntityQuery.SyncFilter
            var jobHandle = new JobHandle();

            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                RemoveComponent(chunks, componentType);
            }
        }
Beispiel #11
0
 internal ArchetypeChunkIterator(UnsafeMatchingArchetypePtrList match, ComponentJobSafetyManager *safetyManager, uint globalSystemVersion,
                                 ref EntityQueryFilter filter)
 {
     m_MatchingArchetypeList               = match;
     m_CurrentArchetypeIndex               = 0;
     m_CurrentChunkInArchetypeIndex        = -1;
     m_CurrentChunkFirstEntityIndexInQuery = 0;
     m_PreviousMatchingChunk               = null;
     m_Filter = filter;
     m_GlobalSystemVersion = globalSystemVersion;
     m_SafetyManager       = safetyManager;
 }
Beispiel #12
0
        public bool MatchesFilter(MatchingArchetype *match, ref EntityQueryFilter filter)
        {
            if ((filter.Type & FilterType.SharedComponent) != 0)
            {
                var sharedComponentsInChunk = SharedComponentValues;
                var filteredCount           = filter.Shared.Count;

                fixed(int *indexInEntityQueryPtr = filter.Shared.IndexInEntityQuery, sharedComponentIndexPtr =
                      filter.Shared.SharedComponentIndex)
                {
                    for (var i = 0; i < filteredCount; ++i)
                    {
                        var indexInEntityQuery        = indexInEntityQueryPtr[i];
                        var sharedComponentIndex      = sharedComponentIndexPtr[i];
                        var componentIndexInArcheType = match->IndexInArchetype[indexInEntityQuery];
                        var componentIndexInChunk     = componentIndexInArcheType - match->Archetype->FirstSharedComponent;
                        if (sharedComponentsInChunk[componentIndexInChunk] != sharedComponentIndex)
                        {
                            return(false);
                        }
                    }
                }

                return(true);
            }

            if ((filter.Type & FilterType.Changed) != 0)
            {
                var changedCount = filter.Changed.Count;

                var requiredVersion = filter.RequiredChangeVersion;
                fixed(int *indexInEntityQueryPtr = filter.Changed.IndexInEntityQuery)
                {
                    for (var i = 0; i < changedCount; ++i)
                    {
                        var indexInArchetype = match->IndexInArchetype[indexInEntityQueryPtr[i]];

                        var changeVersion = GetChangeVersion(indexInArchetype);
                        if (ChangeVersionUtility.DidChange(changeVersion, requiredVersion))
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }

            return(true);
        }
 public ComponentChunkIterator(MatchingArchetypeList match, uint globalSystemVersion,
                               ref EntityQueryFilter filter)
 {
     m_MatchingArchetypeList         = match;
     m_CurrentMatchingArchetypeIndex = match.Count - 1;
     IndexInEntityQuery                = -1;
     m_CurrentChunk                    = null;
     m_CurrentArchetypeIndex           =
         m_CurrentArchetypeEntityIndex =
             int.MaxValue; // This will trigger UpdateCacheResolvedIndex to update the cache on first access
     m_CurrentChunkIndex   = m_CurrentChunkEntityIndex = 0;
     m_GlobalSystemVersion = globalSystemVersion;
     m_Filter = filter;
 }
        /// <summary>
        /// Filters this EntityQuery so that it only selects entities with shared component values
        /// matching the values specified by the `sharedComponent1` parameter.
        /// </summary>
        /// <param name="sharedComponent1">The shared component values on which to filter.</param>
        /// <typeparam name="SharedComponent1">The type of shared component. (The type must also be
        /// one of the types used to create the EntityQuery.</typeparam>
        public void SetFilter <SharedComponent1>(SharedComponent1 sharedComponent1)
            where SharedComponent1 : struct, ISharedComponentData
        {
            var sm = ManagedComponentStore;

            var filter = new EntityQueryFilter();

            filter.Type         = FilterType.SharedComponent;
            filter.Shared.Count = 1;
            filter.Shared.IndexInEntityQuery[0]   = GetIndexInEntityQuery(TypeManager.GetTypeIndex <SharedComponent1>());
            filter.Shared.SharedComponentIndex[0] = sm.InsertSharedComponent(sharedComponent1);

            SetFilter(ref filter);
        }
Beispiel #15
0
        public static void GatherEntitiesToArray(EntityQueryData *queryData, ref EntityQueryFilter filter, out EntityQuery.GatherEntitiesResult result)
        {
            if (s_EntityQueryResultBuffer == null)
            {
                s_EntityQueryResultBuffer = (Entity *)UnsafeUtility.Malloc(k_EntityQueryResultBufferSize * sizeof(Entity), 64, Allocator.Persistent);
            }

            var buffer    = s_EntityQueryResultBuffer;
            var curOffset = currentOffsetInResultBuffer;

            // Main method that copies the entities of each chunk of a matching archetype to the buffer
            bool AddArchetype(MatchingArchetype *matchingArchetype, ref EntityQueryFilter queryFilter)
            {
                var archetype = matchingArchetype->Archetype;
                var entityCountInArchetype = archetype->EntityCount;

                if (entityCountInArchetype == 0)
                {
                    return(true);
                }

                var chunkCount = archetype->Chunks.Count;
                var chunks     = archetype->Chunks.p;
                var counts     = archetype->Chunks.GetChunkEntityCountArray();

                for (int i = 0; i < chunkCount; ++i)
                {
                    // Ignore the chunk if the query uses filter and the chunk doesn't comply
                    if (queryFilter.RequiresMatchesFilter && (chunks[i]->MatchesFilter(matchingArchetype, ref queryFilter) == false))
                    {
                        continue;
                    }
                    var entityCountInChunk = counts[i];

                    if ((curOffset + entityCountInChunk) > k_EntityQueryResultBufferSize)
                    {
                        return(false);
                    }

                    UnsafeUtility.MemCpy(buffer + curOffset, chunks[i]->Buffer, entityCountInChunk * sizeof(Entity));
                    curOffset += entityCountInChunk;
                }

                return(true);
            }

            // Parse all the matching archetypes and add the entities that fits the query and its filter
            bool    success            = true;
            ref var matchingArchetypes = ref queryData->MatchingArchetypes;
        public static void CopyFromComponentDataArray <T>(MatchingArchetypeList matchingArchetypes,
                                                          NativeArray <T> componentDataArray,
                                                          ArchetypeChunkComponentType <T> type,
                                                          EntityQuery entityQuery,
                                                          ref EntityQueryFilter filter,
                                                          out JobHandle jobHandle,
                                                          JobHandle dependsOn)
            where T : struct, IComponentData
        {
            var job = new CopyComponentArrayToChunks <T>
            {
                ComponentData = componentDataArray,
                ComponentType = type
            };

            jobHandle = job.Schedule(entityQuery, dependsOn);
        }
Beispiel #17
0
        /// <summary>
        /// Filters this EntityQuery based on the values of two separate shared components.
        /// </summary>
        /// <remarks>
        /// The filter only selects entities for which both shared component values
        /// specified by the `sharedComponent1` and `sharedComponent2` parameters match.
        /// </remarks>
        /// <param name="sharedComponent1">Shared component values on which to filter.</param>
        /// <param name="sharedComponent2">Shared component values on which to filter.</param>
        /// <typeparam name="SharedComponent1">The type of shared component. (The type must also be
        /// one of the types used to create the EntityQuery.</typeparam>
        /// <typeparam name="SharedComponent2">The type of shared component. (The type must also be
        /// one of the types used to create the EntityQuery.</typeparam>
        public void SetFilter <SharedComponent1, SharedComponent2>(SharedComponent1 sharedComponent1,
                                                                   SharedComponent2 sharedComponent2)
            where SharedComponent1 : struct, ISharedComponentData
            where SharedComponent2 : struct, ISharedComponentData
        {
            var sm = ArchetypeManager.GetSharedComponentDataManager();

            var filter = new EntityQueryFilter();

            filter.Type         = FilterType.SharedComponent;
            filter.Shared.Count = 2;
            filter.Shared.IndexInEntityQuery[0]   = GetIndexInEntityQuery(TypeManager.GetTypeIndex <SharedComponent1>());
            filter.Shared.SharedComponentIndex[0] = sm.InsertSharedComponent(sharedComponent1);

            filter.Shared.IndexInEntityQuery[1]   = GetIndexInEntityQuery(TypeManager.GetTypeIndex <SharedComponent2>());
            filter.Shared.SharedComponentIndex[1] = sm.InsertSharedComponent(sharedComponent2);

            SetFilter(ref filter);
        }
        public bool ChunkMatchesFilter(int chunkIndex, ref EntityQueryFilter filter)
        {
            var chunks = Archetype->Chunks;

            // Must match ALL shared component data
            for (int i = 0; i < filter.Shared.Count; ++i)
            {
                var indexInEntityQuery    = filter.Shared.IndexInEntityQuery[i];
                var sharedComponentIndex  = filter.Shared.SharedComponentIndex[i];
                var componentIndexInChunk = IndexInArchetype[indexInEntityQuery] - Archetype->FirstSharedComponent;
                var sharedComponents      = chunks.GetSharedComponentValueArrayForType(componentIndexInChunk);

                // if we don't have a match, we can early out
                if (sharedComponents[chunkIndex] != sharedComponentIndex)
                {
                    return(false);
                }
            }

            if (filter.Changed.Count == 0)
            {
                return(true);
            }

            // Must have AT LEAST ONE type have changed
            for (int i = 0; i < filter.Changed.Count; ++i)
            {
                var indexInEntityQuery    = filter.Changed.IndexInEntityQuery[i];
                var componentIndexInChunk = IndexInArchetype[indexInEntityQuery];
                var changeVersions        = chunks.GetChangeVersionArrayForType(componentIndexInChunk);

                var requiredVersion = filter.RequiredChangeVersion;

                if (ChangeVersionUtility.DidChange(changeVersions[chunkIndex], requiredVersion))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #19
0
        /// <summary>
        ///     Creates a NativeArray containing the entities in a given EntityQuery.
        /// </summary>
        /// <param name="matchingArchetypes">List of matching archetypes.</param>
        /// <param name="allocator">Allocator to use for the array.</param>
        /// <param name="type">An atomic safety handle required by GatherEntitiesJob so it can call GetNativeArray() on chunks.</param>
        /// <param name="entityQuery">EntityQuery to gather entities from.</param>
        /// <param name="filter">EntityQueryFilter for calculating the length of the output array.</param>
        /// <param name="jobHandle">Handle to the GatherEntitiesJob job used to fill the output array.</param>
        /// <param name="dependsOn">Handle to a job this GatherEntitiesJob must wait on.</param>
        /// <returns>NativeArray of the entities in a given EntityQuery.</returns>
        public static NativeArray <Entity> CreateEntityArray(UnsafeMatchingArchetypePtrList matchingArchetypes,
                                                             Allocator allocator,
                                                             ArchetypeChunkEntityType type,
                                                             EntityQuery entityQuery,
                                                             ref EntityQueryFilter filter,
                                                             out JobHandle jobHandle,
                                                             JobHandle dependsOn)

        {
            var entityCount = CalculateEntityCount(matchingArchetypes, ref filter);

            var job = new GatherEntitiesJob
            {
                EntityType = type,
                Entities   = new NativeArray <Entity>(entityCount, allocator)
            };

            jobHandle = job.Schedule(entityQuery, dependsOn);

            return(job.Entities);
        }
Beispiel #20
0
        public static NativeArray <T> CreateComponentDataArray <T>(UnsafeMatchingArchetypePtrList matchingArchetypes,
                                                                   Allocator allocator,
                                                                   ArchetypeChunkComponentType <T> type,
                                                                   EntityQuery entityQuery,
                                                                   ref EntityQueryFilter filter,
                                                                   out JobHandle jobHandle,
                                                                   JobHandle dependsOn)
            where T : struct, IComponentData
        {
            var entityCount = CalculateEntityCount(matchingArchetypes, ref filter);

            var job = new GatherComponentDataJob <T>
            {
                ComponentData = new NativeArray <T>(entityCount, allocator),
                ComponentType = type
            };

            jobHandle = job.Schedule(entityQuery, dependsOn);

            return(job.ComponentData);
        }
        internal void DestroyEntity(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter)
        {
            Profiler.BeginSample("DestroyEntity(EntityQuery entityQueryFilter)");

            Profiler.BeginSample("GetAllMatchingChunks");
            var jobHandle = new JobHandle();

            // @TODO: Missing EntityQuery.SyncFilter
            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                Profiler.EndSample();

                if (chunks.Length != 0)
                {
                    BeforeStructuralChange();

                    Profiler.BeginSample("EditorOnlyChecks");
                    EntityComponentStore->AssertCanDestroy(chunks);
                    EntityComponentStore->AssertWillDestroyAllInLinkedEntityGroup(chunks, GetArchetypeChunkBufferType <LinkedEntityGroup>(false));
                    Profiler.EndSample();

                    // #todo @macton DestroyEntities should support IJobChunk. But internal writes need to be handled.
                    Profiler.BeginSample("DeleteChunks");
                    new DestroyChunks {
                        EntityComponentStore = EntityComponentStore, Chunks = chunks
                    }.Run();
                    Profiler.EndSample();

                    Profiler.BeginSample("Managed Playback");
                    ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
                    Profiler.EndSample();
                }
            }

            Profiler.EndSample();
        }
        /// <summary>
        /// Filters out entities in chunks for which the specified components have not changed.
        /// </summary>
        /// <remarks>
        ///     Saves given ComponentTypes' indices in RequiredComponents in this group's Changed filter.
        /// </remarks>
        /// <param name="componentType">Array of up to two ComponentTypes to mark as changed on this EntityQuery's filter.</param>
        public void SetFilterChanged(ComponentType[] componentType)
        {
            if (componentType.Length > EntityQueryFilter.ChangedFilter.Capacity)
            {
                throw new ArgumentException(
                          $"EntityQuery.SetFilterChanged accepts a maximum of {EntityQueryFilter.ChangedFilter.Capacity} component array length");
            }
            if (componentType.Length <= 0)
            {
                throw new ArgumentException(
                          $"EntityQuery.SetFilterChanged component array length must be larger than 0");
            }

            var filter = new EntityQueryFilter();

            filter.Type          = FilterType.Changed;
            filter.Changed.Count = componentType.Length;
            for (var i = 0; i != componentType.Length; i++)
            {
                filter.Changed.IndexInEntityQuery[i] = GetIndexInEntityQuery(componentType[i].TypeIndex);
            }

            SetFilter(ref filter);
        }
        /// <summary>
        /// Creates a NativeArray with all the chunks in a given archetype filtered by the provided EntityQueryFilter.
        /// This function will not sync the needed types in the EntityQueryFilter so they have to be synced manually before calling this function.
        /// </summary>
        /// <param name="matchingArchetypes">List of matching archetypes.</param>
        /// <param name="allocator">Allocator to use for the array.</param>
        /// <param name="jobHandle">Handle to the GatherChunks job used to fill the output array.</param>
        /// <param name="filter">Filter used to filter the resulting chunks</param>
        /// <param name="dependsOn">All jobs spawned will depend on this JobHandle</param>
        /// <returns>NativeArray of all the chunks in the matchingArchetypes list.</returns>
        public static NativeArray <ArchetypeChunk> CreateArchetypeChunkArrayAsync(UnsafeMatchingArchetypePtrList matchingArchetypes,
                                                                                  Allocator allocator, out JobHandle jobHandle, ref EntityQueryFilter filter,
                                                                                  JobHandle dependsOn = default(JobHandle))
        {
            var archetypeCount = matchingArchetypes.Length;

            var offsets =
                new NativeArray <int>(archetypeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var chunkCount = 0;

            {
                for (int i = 0; i < matchingArchetypes.Length; ++i)
                {
                    var archetype = matchingArchetypes.Ptr[i]->Archetype;
                    offsets[i]  = chunkCount;
                    chunkCount += archetype->Chunks.Count;
                }
            }

            if (!filter.RequiresMatchesFilter)
            {
                var chunks          = new NativeArray <ArchetypeChunk>(chunkCount, allocator, NativeArrayOptions.UninitializedMemory);
                var gatherChunksJob = new GatherChunksJob
                {
                    MatchingArchetypes   = matchingArchetypes.Ptr,
                    entityComponentStore = matchingArchetypes.entityComponentStore,
                    Offsets = offsets,
                    Chunks  = chunks
                };
                jobHandle = gatherChunksJob.Schedule(archetypeCount, 1, dependsOn);

                return(chunks);
            }
            else
            {
                var filteredCounts  = new NativeArray <int>(archetypeCount + 1, Allocator.TempJob);
                var sparseChunks    = new NativeArray <ArchetypeChunk>(chunkCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var gatherChunksJob = new GatherChunksWithFilteringJob
                {
                    MatchingArchetypes   = matchingArchetypes.Ptr,
                    Filter               = filter,
                    Offsets              = offsets,
                    FilteredCounts       = filteredCounts,
                    SparseChunks         = sparseChunks,
                    entityComponentStore = matchingArchetypes.entityComponentStore
                };
                gatherChunksJob.Schedule(archetypeCount, 1, dependsOn).Complete();

                // accumulated filtered counts: filteredCounts[i] becomes the destination offset
                int totalChunks = 0;
                for (int i = 0; i < archetypeCount; ++i)
                {
                    int currentCount = filteredCounts[i];
                    filteredCounts[i] = totalChunks;
                    totalChunks      += currentCount;
                }
                filteredCounts[archetypeCount] = totalChunks;

                var joinedChunks = new NativeArray <ArchetypeChunk>(totalChunks, allocator, NativeArrayOptions.UninitializedMemory);

                jobHandle = new JoinChunksJob
                {
                    DestinationOffsets = filteredCounts,
                    SparseChunks       = sparseChunks,
                    Offsets            = offsets,
                    JoinedChunks       = joinedChunks
                }.Schedule(archetypeCount, 1);

                return(joinedChunks);
            }
        }
Beispiel #24
0
        void DestroyEntity(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter)
        {
            var access = GetCheckedEntityDataAccess();

            access->DestroyEntity(archetypeList, filter);
        }
Beispiel #25
0
 public bool MatchesFilter(MatchingArchetype *match, ref EntityQueryFilter filter)
 {
     return(match->ChunkMatchesFilter(ListIndex, ref filter));
 }
        /// <summary>
        ///     Total number of entities contained in a given MatchingArchetype list.
        /// </summary>
        /// <param name="matchingArchetypes">List of matching archetypes.</param>
        /// <param name="filter">EntityQueryFilter to use when calculating total number of entities.</param>
        /// <returns>Number of entities</returns>
        public static int CalculateLength(MatchingArchetypeList matchingArchetypes, ref EntityQueryFilter filter)
        {
            var filterCopy = filter; // Necessary to avoid a nasty compiler error cause by fixed buffer types

            var length = 0;

            if (!filter.RequiresMatchesFilter)
            {
                for (var m = matchingArchetypes.Count - 1; m >= 0; --m)
                {
                    var match = matchingArchetypes.p[m];
                    length += match->Archetype->EntityCount;
                }
            }
            else
            {
                for (var m = matchingArchetypes.Count - 1; m >= 0; --m)
                {
                    var match = matchingArchetypes.p[m];
                    if (match->Archetype->EntityCount <= 0)
                    {
                        continue;
                    }

                    int filteredCount         = 0;
                    var archetype             = match->Archetype;
                    int chunkCount            = archetype->Chunks.Count;
                    var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray();

                    if (filter.Type == FilterType.SharedComponent)
                    {
                        var indexInEntityQuery0    = filterCopy.Shared.IndexInEntityQuery[0];
                        var sharedComponentIndex0  = filterCopy.Shared.SharedComponentIndex[0];
                        var componentIndexInChunk0 =
                            match->IndexInArchetype[indexInEntityQuery0] - archetype->FirstSharedComponent;
                        var sharedComponents0 =
                            archetype->Chunks.GetSharedComponentValueArrayForType(componentIndexInChunk0);

                        if (filter.Shared.Count == 1)
                        {
                            for (var i = 0; i < chunkCount; ++i)
                            {
                                if (sharedComponents0[i] == sharedComponentIndex0)
                                {
                                    filteredCount += chunkEntityCountArray[i];
                                }
                            }
                        }
                        else
                        {
                            var indexInEntityQuery1    = filterCopy.Shared.IndexInEntityQuery[1];
                            var sharedComponentIndex1  = filterCopy.Shared.SharedComponentIndex[1];
                            var componentIndexInChunk1 =
                                match->IndexInArchetype[indexInEntityQuery1] - archetype->FirstSharedComponent;
                            var sharedComponents1 =
                                archetype->Chunks.GetSharedComponentValueArrayForType(componentIndexInChunk1);

                            for (var i = 0; i < chunkCount; ++i)
                            {
                                if (sharedComponents0[i] == sharedComponentIndex0 &&
                                    sharedComponents1[i] == sharedComponentIndex1)
                                {
                                    filteredCount += chunkEntityCountArray[i];
                                }
                            }
                        }
                    }
                    else
                    {
                        var indexInEntityQuery0    = filterCopy.Changed.IndexInEntityQuery[0];
                        var componentIndexInChunk0 = match->IndexInArchetype[indexInEntityQuery0];
                        var changeVersions0        = archetype->Chunks.GetChangeVersionArrayForType(componentIndexInChunk0);

                        var requiredVersion = filter.RequiredChangeVersion;
                        if (filter.Changed.Count == 1)
                        {
                            for (var i = 0; i < chunkCount; ++i)
                            {
                                if (ChangeVersionUtility.DidChange(changeVersions0[i], requiredVersion))
                                {
                                    filteredCount += chunkEntityCountArray[i];
                                }
                            }
                        }
                        else
                        {
                            var indexInEntityQuery1    = filterCopy.Changed.IndexInEntityQuery[1];
                            var componentIndexInChunk1 = match->IndexInArchetype[indexInEntityQuery1];
                            var changeVersions1        =
                                archetype->Chunks.GetChangeVersionArrayForType(componentIndexInChunk1);

                            for (var i = 0; i < chunkCount; ++i)
                            {
                                if (ChangeVersionUtility.DidChange(changeVersions0[i], requiredVersion) ||
                                    ChangeVersionUtility.DidChange(changeVersions1[i], requiredVersion))
                                {
                                    filteredCount += chunkEntityCountArray[i];
                                }
                            }
                        }
                    }

                    length += filteredCount;
                }
            }

            return(length);
        }
        internal static JobHandle PreparePrefilteredChunkLists(int unfilteredChunkCount, MatchingArchetypeList archetypes, EntityQueryFilter filter, JobHandle dependsOn, ScheduleMode mode, out NativeArray <byte> prefilterDataArray, out void *deferredCountData)
        {
            // Allocate one buffer for all prefilter data and distribute it
            // We keep the full buffer as a "dummy array" so we can deallocate it later with [DeallocateOnJobCompletion]
            var sizeofChunkArray  = sizeof(ArchetypeChunk) * unfilteredChunkCount;
            var sizeofIndexArray  = sizeof(int) * unfilteredChunkCount;
            var prefilterDataSize = sizeofChunkArray + sizeofIndexArray + sizeof(int);

            var prefilterData = (byte *)UnsafeUtility.Malloc(prefilterDataSize, 64, Allocator.TempJob);

            prefilterDataArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(prefilterData, prefilterDataSize, Allocator.TempJob);

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref prefilterDataArray, AtomicSafetyHandle.Create());
#endif

            JobHandle prefilterHandle = default(JobHandle);

            if (filter.RequiresMatchesFilter)
            {
                var prefilteringJob = new GatherChunksAndOffsetsWithFilteringJob
                {
                    Archetypes           = archetypes,
                    Filter               = filter,
                    PrefilterData        = prefilterData,
                    UnfilteredChunkCount = unfilteredChunkCount
                };
                if (mode == ScheduleMode.Batched)
                {
                    prefilterHandle = prefilteringJob.Schedule(dependsOn);
                }
                else
                {
                    prefilteringJob.Run();
                }
            }
            else
            {
                var gatherJob = new GatherChunksAndOffsetsJob
                {
                    Archetypes           = archetypes,
                    PrefilterData        = prefilterData,
                    UnfilteredChunkCount = unfilteredChunkCount
                };
                if (mode == ScheduleMode.Batched)
                {
                    prefilterHandle = gatherJob.Schedule(dependsOn);
                }
                else
                {
                    gatherJob.Run();
                }
            }

            // ScheduleParallelForDeferArraySize expects a ptr to a structure with a void* and a count.
            // It only uses the count, so this is safe to fudge
            deferredCountData = prefilterData + sizeofChunkArray + sizeofIndexArray;
            deferredCountData = (byte *)deferredCountData - sizeof(void *);

            return(prefilterHandle);
        }
Beispiel #28
0
 void DestroyEntity(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter)
 {
     m_EntityDataAccess.DestroyEntity(archetypeList, filter);
 }
Beispiel #29
0
        public void RemoveComponentWithValidation(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter,
                                                  ComponentType componentType, ComponentDependencyManager *dependencyManager)
        {
            var chunks = ChunkIterationUtility.CreateArchetypeChunkArray(archetypeList, Collections.Allocator.TempJob, ref filter, dependencyManager);

            RemoveComponentWithValidation(chunks, componentType);
            chunks.Dispose();
        }
Beispiel #30
0
        public void AddComponentWithValidation(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter,
                                               ComponentType componentType, ComponentDependencyManager *dependencyManager)
        {
            AssertCanAddComponent(archetypeList, componentType);

            var chunks = ChunkIterationUtility.CreateArchetypeChunkArray(archetypeList, Collections.Allocator.TempJob, ref filter, dependencyManager);

            if (chunks.Length > 0)
            {
                //@TODO the fast path for a chunk that contains a single entity is only possible if the chunk doesn't have a Locked Entity Order
                //but we should still be allowed to add zero sized components to chunks with a Locked Entity Order, even ones that only contain a single entity

                /*
                 * if ((chunks.Length == 1) && (chunks[0].Count == 1))
                 * {
                 *  var entityPtr = (Entity*) chunks[0].m_Chunk->Buffer;
                 *  StructuralChange.AddComponentEntity(EntityComponentStore, entityPtr, componentType.TypeIndex);
                 * }
                 * else
                 * {
                 */
                AddComponent((ArchetypeChunk *)NativeArrayUnsafeUtility.GetUnsafePtr(chunks), chunks.Length, componentType);

                /*
                 * }
                 */
            }

            chunks.Dispose();
        }