void Move(Chunk *srcChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { if (archetypeChunkFilter.Archetype->SystemStateCleanupComplete) { ChunkDataUtility.Deallocate(srcChunk); return; } var srcArchetype = srcChunk->Archetype; if (ChunkDataUtility.AreLayoutCompatible(srcArchetype, archetypeChunkFilter.Archetype)) { fixed(int *sharedComponentValues = archetypeChunkFilter.SharedComponentValues) { ChunkDataUtility.ChangeArchetypeInPlace(srcChunk, archetypeChunkFilter.Archetype, sharedComponentValues); } return; } var entityBatch = new EntityBatchInChunk { Chunk = srcChunk, Count = srcChunk->Count, StartIndex = 0 }; Move(entityBatch, ref archetypeChunkFilter); }
void Move(Entity entity, ref ArchetypeChunkFilter archetypeChunkFilter) { var srcEntityInChunk = GetEntityInChunk(entity); var entityBatch = new EntityBatchInChunk { Chunk = srcEntityInChunk.Chunk, Count = 1, StartIndex = srcEntityInChunk.IndexInChunk }; Move(entityBatch, ref archetypeChunkFilter); }
// ---------------------------------------------------------------------------------------------------------- // INTERNAL // ---------------------------------------------------------------------------------------------------------- void Move(Entity entity, Chunk *dstChunk) { var srcEntityInChunk = GetEntityInChunk(entity); var srcChunk = srcEntityInChunk.Chunk; var srcChunkIndex = srcEntityInChunk.IndexInChunk; var entityBatch = new EntityBatchInChunk { Chunk = srcChunk, Count = 1, StartIndex = srcChunkIndex }; Move(entityBatch, dstChunk); }
bool AddComponent(EntityBatchInChunk entityBatchInChunk, ComponentType componentType, int sharedComponentIndex = 0) { var srcChunk = entityBatchInChunk.Chunk; var archetypeChunkFilter = GetArchetypeChunkFilterWithAddedComponent(srcChunk, componentType, sharedComponentIndex); if (archetypeChunkFilter.Archetype == null) { return(false); } Move(entityBatchInChunk, ref archetypeChunkFilter); return(true); }
bool RemoveComponent(EntityBatchInChunk entityBatchInChunk, ComponentType componentType) { var srcChunk = entityBatchInChunk.Chunk; var archetypeChunkFilter = GetArchetypeChunkFilterWithRemovedComponent(srcChunk, componentType); if (archetypeChunkFilter.Archetype == null) { return(false); } Move(entityBatchInChunk, ref archetypeChunkFilter); return(true); }
bool AddComponents(EntityBatchInChunk entityBatchInChunk, ComponentTypes componentTypes) { var srcChunk = entityBatchInChunk.Chunk; var dstArchetype = GetArchetypeWithAddedComponents(srcChunk->Archetype, componentTypes); if (dstArchetype == srcChunk->Archetype) // none were added { return(false); } var archetypeChunkFilter = GetArchetypeChunkFilterWithAddedComponents(srcChunk, dstArchetype); if (archetypeChunkFilter.Archetype == null) { return(false); } Move(entityBatchInChunk, ref archetypeChunkFilter); return(true); }
void Move(Chunk *srcChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { if (archetypeChunkFilter.Archetype->SystemStateCleanupComplete) { DeleteChunk(srcChunk); return; } var srcArchetype = srcChunk->Archetype; if (ChunkDataUtility.AreLayoutCompatible(srcArchetype, archetypeChunkFilter.Archetype)) { ChangeArchetypeInPlace(srcChunk, ref archetypeChunkFilter); return; } var entityBatch = new EntityBatchInChunk { Chunk = srcChunk, Count = srcChunk->Count, StartIndex = 0 }; Move(entityBatch, ref archetypeChunkFilter); }
void Move(EntityBatchInChunk entityBatchInChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { var systemStateCleanupComplete = archetypeChunkFilter.Archetype->SystemStateCleanupComplete; var srcChunk = entityBatchInChunk.Chunk; var srcRemainingCount = entityBatchInChunk.Count; var startIndex = entityBatchInChunk.StartIndex; if ((srcRemainingCount == srcChunk->Count) && systemStateCleanupComplete) { ChunkDataUtility.Deallocate(srcChunk); return; } while (srcRemainingCount > 0) { var dstChunk = GetChunkWithEmptySlots(ref archetypeChunkFilter); var dstCount = Move(new EntityBatchInChunk { Chunk = srcChunk, Count = srcRemainingCount, StartIndex = startIndex }, dstChunk); srcRemainingCount -= dstCount; } }
// ---------------------------------------------------------------------------------------------------------- // 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); }