Ejemplo n.º 1
0
        /// <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);
                    }
                }
            }
        }