예제 #1
0
        static Chunk *DeallocateDataEntitiesInChunk(EntityDataManager *entityDataManager, Entity *entities,
                                                    int count, out int indexInChunk, out int batchCount)
        {
            /// This is optimized for the case where the array of entities are allocated contigously in the chunk
            /// Thus the compacting of other elements can be batched

            // Calculate baseEntityIndex & chunk
            var baseEntityIndex = entities[0].Index;

            var chunk = entityDataManager->m_Entities[baseEntityIndex].Chunk;

            indexInChunk = entityDataManager->m_Entities[baseEntityIndex].IndexInChunk;
            batchCount   = 0;

            var freeIndex   = entityDataManager->m_EntitiesFreeIndex;
            var entityDatas = entityDataManager->m_Entities;

            while (batchCount < count)
            {
                var entityIndex = entities[batchCount].Index;
                var data        = entityDatas + entityIndex;

                if (data->Chunk != chunk || data->IndexInChunk != indexInChunk + batchCount)
                {
                    break;
                }

                data->Chunk = null;
                data->Version++;
                data->IndexInChunk = freeIndex;
                freeIndex          = entityIndex;

                batchCount++;
            }

            entityDataManager->m_EntitiesFreeIndex = freeIndex;

            // We can just chop-off the end, no need to copy anything
            if (chunk->Count == indexInChunk + batchCount)
            {
                return(chunk);
            }

            // updates EntitityData->indexInChunk to point to where the components will be moved to
            //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0);
            var movedEntities = (Entity *)(chunk->Buffer) + (chunk->Count - batchCount);

            for (var i = 0; i != batchCount; i++)
            {
                entityDataManager->m_Entities[movedEntities[i].Index].IndexInChunk = indexInChunk + i;
            }

            // Move component data from the end to where we deleted components
            ChunkDataUtility.Copy(chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount);

            return(chunk);
        }
예제 #2
0
        public void SetArchetype(ArchetypeManager typeMan, Entity entity, Archetype *archetype,
                                 int *sharedComponentDataIndices)
        {
            var chunk      = typeMan.GetChunkWithEmptySlots(archetype, sharedComponentDataIndices);
            var chunkIndex = typeMan.AllocateIntoChunk(chunk);

            var oldArchetype  = m_Entities[entity.Index].Archetype;
            var oldChunk      = m_Entities[entity.Index].Chunk;
            var oldChunkIndex = m_Entities[entity.Index].IndexInChunk;

            ChunkDataUtility.Convert(oldChunk, oldChunkIndex, chunk, chunkIndex);
            if (chunk->ManagedArrayIndex >= 0 && oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, chunk, chunkIndex, 1);
            }

            m_Entities[entity.Index].Archetype    = archetype;
            m_Entities[entity.Index].Chunk        = chunk;
            m_Entities[entity.Index].IndexInChunk = chunkIndex;

            var lastIndex = oldChunk->Count - 1;

            // No need to replace with ourselves
            if (lastIndex != oldChunkIndex)
            {
                var lastEntity = (Entity *)ChunkDataUtility.GetComponentData(oldChunk, lastIndex, 0);
                m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex;

                ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                if (oldChunk->ManagedArrayIndex >= 0)
                {
                    ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                }
            }

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1);
            }

            --oldArchetype->EntityCount;
            typeMan.SetChunkCount(oldChunk, lastIndex);
        }
예제 #3
0
        internal void DeallocateDataEntitiesInChunk(Chunk *chunk, int indexInChunk, int batchCount)
        {
            DeallocateBuffers(chunk, indexInChunk, batchCount);
            DeallocateManagedComponents(chunk, indexInChunk, batchCount);

            var freeIndex = m_NextFreeEntityIndex;
            var entities  = (Entity *)chunk->Buffer + indexInChunk;

            for (var i = batchCount - 1; i >= 0; --i)
            {
                var entityIndex = entities[i].Index;

                m_EntityInChunkByEntity[entityIndex].Chunk = null;
                m_VersionByEntity[entityIndex]++;
                m_EntityInChunkByEntity[entityIndex].IndexInChunk = freeIndex;
#if UNITY_EDITOR
                m_NameByEntity[entityIndex] = new NumberedWords();
#endif
                freeIndex = entityIndex;
            }

            m_NextFreeEntityIndex = freeIndex;
            m_EntityCreateDestroyVersion++;

            // Compute the number of things that need to moved and patched.
            int patchCount = Math.Min(batchCount, chunk->Count - indexInChunk - batchCount);

            if (0 == patchCount)
            {
                return;
            }

            // updates indexInChunk to point to where the components will be moved to
            //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0);
            var movedEntities = (Entity *)chunk->Buffer + (chunk->Count - patchCount);
            for (var i = 0; i != patchCount; i++)
            {
                m_EntityInChunkByEntity[movedEntities[i].Index].IndexInChunk = indexInChunk + i;
            }

            // Move component data from the end to where we deleted components
            ChunkDataUtility.Copy(chunk, chunk->Count - patchCount, chunk, indexInChunk, patchCount);
        }
예제 #4
0
        public void MoveEntityToChunk(ArchetypeManager typeMan, Entity entity, Chunk *newChunk, int newChunkIndex)
        {
            var oldChunk = m_Entities[entity.Index].Chunk;

            Assert.IsTrue(oldChunk->Archetype == newChunk->Archetype);

            var oldChunkIndex = m_Entities[entity.Index].IndexInChunk;

            ChunkDataUtility.Copy(oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1);

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1);
            }

            m_Entities[entity.Index].Chunk        = newChunk;
            m_Entities[entity.Index].IndexInChunk = newChunkIndex;

            var lastIndex = oldChunk->Count - 1;

            // No need to replace with ourselves
            if (lastIndex != oldChunkIndex)
            {
                var lastEntity = (Entity *)ChunkDataUtility.GetComponentData(oldChunk, lastIndex, 0);
                m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex;

                ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                if (oldChunk->ManagedArrayIndex >= 0)
                {
                    ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                }
            }

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1);
            }

            newChunk->Archetype->EntityCount--;
            typeMan.SetChunkCount(oldChunk, oldChunk->Count - 1);
        }
예제 #5
0
        private static void DeallocateDataEntitiesInChunk(EntityDataManager *entityDataManager, Entity *entities,
                                                          Chunk *chunk, int indexInChunk, int batchCount)
        {
            DeallocateBuffers(entityDataManager, entities, chunk, batchCount);

            var freeIndex   = entityDataManager->m_EntitiesFreeIndex;
            var entityDatas = entityDataManager->m_Entities;

            for (var i = batchCount - 1; i >= 0; --i)
            {
                var entityIndex = entities[i].Index;
                var data        = entityDatas + entityIndex;

                data->Chunk = null;
                data->Version++;
                data->IndexInChunk = freeIndex;
                freeIndex          = entityIndex;
            }

            entityDataManager->m_EntitiesFreeIndex = freeIndex;

            // Compute the number of things that need to moved and patched.
            int patchCount = Math.Min(batchCount, chunk->Count - indexInChunk - batchCount);

            if (0 == patchCount)
            {
                return;
            }

            // updates EntitityData->indexInChunk to point to where the components will be moved to
            //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0);
            var movedEntities = (Entity *)chunk->Buffer + (chunk->Count - patchCount);

            for (var i = 0; i != patchCount; i++)
            {
                entityDataManager->m_Entities[movedEntities[i].Index].IndexInChunk = indexInChunk + i;
            }

            // Move component data from the end to where we deleted components
            ChunkDataUtility.Copy(chunk, chunk->Count - patchCount, chunk, indexInChunk, patchCount);
        }
예제 #6
0
        // ----------------------------------------------------------------------------------------------------------
        // Core, self-contained functions to change chunks. No other functions should actually move data from
        // one Chunk to another, or otherwise change the structure of a Chunk after creation.
        // ----------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Move subset of chunk data into another chunk.
        /// - Chunks can be of same archetype (but differ by shared component values)
        /// - Returns number moved. Caller handles if less than indicated in srcBatch.
        /// </summary>
        /// <returns></returns>
        int Move(EntityBatchInChunk srcBatch, Chunk *dstChunk)
        {
            var srcChunk      = srcBatch.Chunk;
            var srcChunkIndex = srcBatch.StartIndex;
            var srcCount      = srcBatch.Count;
            var srcArchetype  = srcChunk->Archetype;
            var dstArchetype  = dstChunk->Archetype;

            // Note (srcArchetype == dstArchetype) is valid
            // Archetypes can the the same, but chunks still differ because filter is different (e.g. shared component)

            int dstChunkIndex;
            var dstCount = AllocateIntoChunk(dstChunk, srcCount, out dstChunkIndex);

            // If can only move partial batch, move from the end so that remainder of batch isn't affected.
            srcChunkIndex = srcChunkIndex + srcCount - dstCount;

            ChunkDataUtility.Convert(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount);

            if (dstChunk->ManagedArrayIndex >= 0 && srcChunk->ManagedArrayIndex >= 0)
            {
                ManagedChangesTracker.CopyManagedObjects(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount);
            }

            var dstEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(dstChunk, dstChunkIndex, 0);

            for (int i = 0; i < dstCount; i++)
            {
                var entity = dstEntities[i];

                SetArchetype(entity, dstArchetype);
                SetEntityInChunk(entity, new EntityInChunk {
                    Chunk = dstChunk, IndexInChunk = dstChunkIndex + i
                });
            }

            // Fill in moved component data from the end.
            var srcTailIndex = srcChunkIndex + dstCount;
            var srcTailCount = srcChunk->Count - srcTailIndex;
            var fillCount    = math.min(dstCount, srcTailCount);

            if (fillCount > 0)
            {
                var fillStartIndex = srcChunk->Count - fillCount;

                ChunkDataUtility.Copy(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount);

                var fillEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(srcChunk, srcChunkIndex, 0);
                for (int i = 0; i < fillCount; i++)
                {
                    var entity = fillEntities[i];
                    SetEntityInChunk(entity, new EntityInChunk {
                        Chunk = srcChunk, IndexInChunk = srcChunkIndex + i
                    });
                }

                if (srcChunk->ManagedArrayIndex >= 0)
                {
                    ManagedChangesTracker.CopyManagedObjects(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount);
                }
            }

            if (srcChunk->ManagedArrayIndex >= 0)
            {
                ManagedChangesTracker.ClearManagedObjects(srcChunk, srcChunk->Count - dstCount, dstCount);
            }

            srcArchetype->EntityCount -= dstCount;

            dstChunk->SetAllChangeVersions(GlobalSystemVersion);
            srcChunk->SetAllChangeVersions(GlobalSystemVersion);

            ManagedChangesTracker.IncrementComponentOrderVersion(srcArchetype, srcChunk->SharedComponentValues);
            IncrementComponentTypeOrderVersion(srcArchetype);

            ManagedChangesTracker.IncrementComponentOrderVersion(dstArchetype, dstChunk->SharedComponentValues);
            IncrementComponentTypeOrderVersion(dstArchetype);

            SetChunkCount(srcChunk, srcChunk->Count - dstCount);

            // Cannot DestroyEntities unless SystemStateCleanupComplete on the entity chunk.
            if (dstChunk->Archetype->SystemStateCleanupComplete)
            {
                DestroyEntities(dstEntities, dstCount);
            }

            return(dstCount);
        }