/// <summary> /// Fix-up the chunk to refer to a different (but layout compatible) archetype. /// - Should only be called by Move(chunk) /// </summary> void ChangeArchetypeInPlace(Chunk *srcChunk, ref ArchetypeChunkFilter dstArchetypeChunkFilter) { var dstArchetype = dstArchetypeChunkFilter.Archetype; fixed(int *sharedComponentValues = dstArchetypeChunkFilter.SharedComponentValues) { var srcArchetype = srcChunk->Archetype; ChunkDataUtility.AssertAreLayoutCompatible(srcArchetype, dstArchetype); var fixupSharedComponentReferences = (srcArchetype->NumSharedComponents > 0) || (dstArchetype->NumSharedComponents > 0); if (fixupSharedComponentReferences) { int srcFirstShared = srcArchetype->FirstSharedComponent; int dstFirstShared = dstArchetype->FirstSharedComponent; int srcCount = srcArchetype->NumSharedComponents; int dstCount = dstArchetype->NumSharedComponents; int o = 0; int n = 0; for (; n < dstCount && o < srcCount;) { int srcType = srcArchetype->Types[o + srcFirstShared].TypeIndex; int dstType = dstArchetype->Types[n + dstFirstShared].TypeIndex; if (srcType == dstType) { var srcSharedComponentDataIndex = srcChunk->SharedComponentValues[o]; var dstSharedComponentDataIndex = sharedComponentValues[n]; if (srcSharedComponentDataIndex != dstSharedComponentDataIndex) { ManagedChangesTracker.RemoveReference(srcSharedComponentDataIndex); ManagedChangesTracker.AddReference(dstSharedComponentDataIndex); } n++; o++; } else if (dstType > srcType) // removed from dstArchetype { var sharedComponentDataIndex = srcChunk->SharedComponentValues[o]; ManagedChangesTracker.RemoveReference(sharedComponentDataIndex); o++; } else // added to dstArchetype { var sharedComponentDataIndex = sharedComponentValues[n]; ManagedChangesTracker.AddReference(sharedComponentDataIndex); n++; } } for (; n < dstCount; n++) // added to dstArchetype { var sharedComponentDataIndex = sharedComponentValues[n]; ManagedChangesTracker.AddReference(sharedComponentDataIndex); } for (; o < srcCount; o++) // removed from dstArchetype { var sharedComponentDataIndex = srcChunk->SharedComponentValues[o]; ManagedChangesTracker.RemoveReference(sharedComponentDataIndex); } } var fixupManagedComponents = (srcArchetype->NumManagedArrays > 0) || (dstArchetype->NumManagedArrays > 0); if (fixupManagedComponents) { if (dstArchetype->NumManagedArrays == 0) // removed all { ManagedChangesTracker.DeallocateManagedArrayStorage(srcChunk->ManagedArrayIndex); m_ManagedArrayFreeIndex.Add(srcChunk->ManagedArrayIndex); srcChunk->ManagedArrayIndex = -1; } else { // We have changed the managed array order + size so allocate a new managed array // copy the unchanged values into it int dstManagedArrayIndex; if (!m_ManagedArrayFreeIndex.IsEmpty) { dstManagedArrayIndex = m_ManagedArrayFreeIndex.Pop <int>(); } else { dstManagedArrayIndex = m_ManagedArrayIndex; m_ManagedArrayIndex++; } ManagedChangesTracker.AllocateManagedArrayStorage(dstManagedArrayIndex, dstArchetype->NumManagedArrays * srcChunk->Capacity); int srcManagedArrayIndex = srcChunk->ManagedArrayIndex; srcChunk->ManagedArrayIndex = dstManagedArrayIndex; if (srcManagedArrayIndex != -1) { ManagedChangesTracker.MoveChunksManagedObjects(srcArchetype, srcManagedArrayIndex, dstArchetype, dstManagedArrayIndex, srcChunk->Capacity, srcChunk->Count); ManagedChangesTracker.DeallocateManagedArrayStorage(srcManagedArrayIndex); m_ManagedArrayFreeIndex.Add(srcManagedArrayIndex); } } } var count = srcChunk->Count; bool hasEmptySlots = count < srcChunk->Capacity; if (hasEmptySlots) { srcArchetype->EmptySlotTrackingRemoveChunk(srcChunk); } int chunkIndexInSrcArchetype = srcChunk->ListIndex; var dstTypes = dstArchetype->Types; var srcTypes = srcArchetype->Types; //Change version is overriden below dstArchetype->AddToChunkList(srcChunk, sharedComponentValues, 0); int chunkIndexInDstArchetype = srcChunk->ListIndex; //Copy change versions from src to dst archetype for (int isrcType = srcArchetype->TypesCount - 1, idstType = dstArchetype->TypesCount - 1; idstType >= 0; --idstType) { var dstType = dstTypes[idstType]; while (srcTypes[isrcType] > dstType) { --isrcType; } var version = srcTypes[isrcType] == dstType ? srcArchetype->Chunks.GetChangeVersion(isrcType, chunkIndexInSrcArchetype) : GlobalSystemVersion; dstArchetype->Chunks.SetChangeVersion(idstType, chunkIndexInDstArchetype, version); } srcChunk->ListIndex = chunkIndexInSrcArchetype; srcArchetype->RemoveFromChunkList(srcChunk); srcChunk->ListIndex = chunkIndexInDstArchetype; if (hasEmptySlots) { dstArchetype->EmptySlotTrackingAddChunk(srcChunk); } SetArchetype(srcChunk, dstArchetype); srcArchetype->EntityCount -= count; dstArchetype->EntityCount += count; if (srcArchetype->MetaChunkArchetype != dstArchetype->MetaChunkArchetype) { if (srcArchetype->MetaChunkArchetype == null) { CreateMetaEntityForChunk(srcChunk); } else if (dstArchetype->MetaChunkArchetype == null) { DestroyMetaChunkEntity(srcChunk->metaChunkEntity); srcChunk->metaChunkEntity = Entity.Null; } else { var metaChunk = GetChunk(srcChunk->metaChunkEntity); var archetypeChunkFilter = new ArchetypeChunkFilter(dstArchetype->MetaChunkArchetype, metaChunk->SharedComponentValues); Move(srcChunk->metaChunkEntity, ref archetypeChunkFilter); } } } }