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); }
// ---------------------------------------------------------------------------------------------------------- // 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); }