예제 #1
0
        public static void ReplicateManagedObjects(
            ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcIndex,
            ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstBaseIndex,
            int count, Entity srcEntity, Entity *dstEntities, int entityCount)
        {
            object[] companionGameObjectInstances = null;

            var srcI = 0;
            var dstI = 0;

            while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount)
            {
                if (srcArch->Types[srcI] < dstArch->Types[dstI])
                {
                    ++srcI;
                }
                else if (srcArch->Types[srcI] > dstArch->Types[dstI])
                {
                    ++dstI;
                }
                else
                {
                    if (srcArch->IsManaged(srcI))
                    {
                        var componentType = srcArch->Types[srcI];
                        var typeInfo      = TypeManager.GetTypeInfo(componentType.TypeIndex);
                        var obj           = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcIndex);

                        if (typeInfo.Category == TypeManager.TypeCategory.Class)
                        {
                            // If we're dealing with a class based type, we will defer the execution to InstantiateHybridComponent (if dependency injection was made), this method will
                            // - Determine if the object should be cloned (true is returned) or referenced (false is returned)
                            // - Clone the GameObject and its components (as many times as we have in 'count'), and make it a Companion Game Object by adding a CompanionLink component to it
                            // - Add the Cloned Hybrid Component to the instantiated entities (again 'count' times)
                            if (InstantiateHybridComponent == null || !InstantiateHybridComponent(obj, srcStore, dstArch, dstStore, dstManagedArrayIndex, dstChunkCapacity, srcEntity, dstEntities, entityCount, dstI, dstBaseIndex, ref companionGameObjectInstances))
                            {
                                // We end up here if we have to reference the object and not cloning it
                                for (var i = 0; i < count; ++i)
                                {
                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                                }
                            }
                        }
                        else
                        {
#if NET_DOTS
                            for (var i = 0; i < count; ++i)
                            {
                                // Until DOTS Runtime supports Properties just perform a simple shallow copy
                                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                            }
#else
                            if (obj == null)
                            {
                                // If we are dealing with a Class/GameObject types just perform a shallow copy
                                for (var i = 0; i < count; ++i)
                                {
                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj);
                                }
                            }
                            else
                            {
                                // Unless we want to enforce managed components to implement an IDeepClonable interface
                                // we instead generate a binary stream of an object and then use that to instantiate our new deep copy
                                var type   = TypeManager.GetType(componentType.TypeIndex);
                                var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp);
                                var writer = new PropertiesBinaryWriter(&buffer);
                                BoxedProperties.WriteBoxedType(obj, writer);

                                for (var i = 0; i < count; ++i)
                                {
                                    var    readBuffer = buffer.AsReader();
                                    var    reader     = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable());
                                    object newObj     = BoxedProperties.ReadBoxedClass(type, reader);

                                    dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, newObj);
                                }
                                buffer.Dispose();
                            }
#endif
                        }
                    }

                    ++srcI;
                    ++dstI;
                }
            }
        }
예제 #2
0
        public void PatchEntitiesForPrefab(ManagedComponentStore managedComponentStore, Archetype *archetype, Chunk *chunk, int indexInChunk, int entityCount,
                                           EntityRemapUtility.SparseEntityRemapInfo *remapping, int remappingCount, Allocator allocator)
        {
#if !NET_DOTS
            var managedPatches    = archetype->ManagedEntityPatches;
            var managedPatchCount = archetype->ManagedEntityPatchCount;

            // Patch managed components with entity references.
            for (int p = 0; p < managedPatchCount; p++)
            {
                var componentType = managedPatches[p].Type;

                for (int e = 0; e != entityCount; e++)
                {
                    var obj = managedComponentStore.GetManagedObject(chunk, componentType, e + indexInChunk);

                    EntityRemapUtility.PatchEntityForPrefabInBoxedType(obj, remapping + e * remappingCount, remappingCount);
                }
            }
            UnsafeUtility.Free(remapping, allocator);
#endif
        }
        public static void AssertArchetypeDoesNotRemoveSystemStateComponents(Archetype *src, Archetype *dst)
        {
            int o = 0;
            int n = 0;

            for (; n < src->TypesCount && o < dst->TypesCount;)
            {
                int srcType = src->Types[o].TypeIndex;
                int dstType = dst->Types[n].TypeIndex;
                if (srcType == dstType)
                {
                    o++;
                    n++;
                }
                else if (dstType > srcType)
                {
                    if (src->Types[o].IsSystemStateComponent)
                    {
                        throw new System.ArgumentException(
                                  $"SystemState components may not be removed via SetArchetype: {src->Types[o]}");
                    }
                    o++;
                }
                else
                {
                    n++;
                }
            }

            for (; o < src->TypesCount; o++)
            {
                if (src->Types[o].IsSystemStateComponent)
                {
                    throw new System.ArgumentException($"SystemState components may not be removed via SetArchetype: {src->Types[o]}");
                }
            }
        }
            private void AddComponentData(
                Chunk *afterChunk,
                Archetype *afterArchetype,
                ComponentTypeInArchetype afterTypeInArchetype,
                int afterIndexInTypeArray,
                int afterEntityIndexInChunk,
                EntityGuid entityGuid,
                int typeIndex,
                TypeInfo typeInfo
                )
            {
                var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash);

                AddComponents.Add(packedComponent);

                if (afterTypeInArchetype.IsSharedComponent)
                {
                    var offset = afterIndexInTypeArray - afterChunk->Archetype->FirstSharedComponent;
                    var sharedComponentIndex = afterChunk->GetSharedComponentValue(offset);

                    // No managed objects in burst land. Do what we can a defer the actual unpacking until later.
                    ComponentDataStream.SetSharedComponentDataDeferred(entityGuid, afterTypeInArchetype.TypeIndex, sharedComponentIndex);
                    return;
                }

                // IMPORTANT This means `IsZeroSizedInChunk` which is always true for shared components.
                // Always check shared components first.
                if (afterTypeInArchetype.IsZeroSized)
                {
                    // Zero sized components have no data to copy.
                    return;
                }

                if (afterTypeInArchetype.IsBuffer)
                {
                    var sizeOf = afterArchetype->SizeOfs[afterIndexInTypeArray];
                    var buffer = (BufferHeader *)(ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterEntityIndexInChunk * sizeOf);
                    var length = buffer->Length;

                    if (length == 0)
                    {
                        return;
                    }

                    var elementPtr = BufferHeader.GetElementPointer(buffer);

                    if (afterTypeInArchetype.TypeIndex == TypeInfoStream.LinkedEntityGroupTypeIndex)
                    {
                        // Magic in AddComponent already put a self-reference at the top of the buffer, so there's no need for us to add it.
                        // The rest of the elements should be interpreted as LinkedEntityGroupAdditions.
                        for (var elementIndex = 1; elementIndex < length; elementIndex++)
                        {
                            var childEntity = ((Entity *)elementPtr)[elementIndex];
                            if (!AfterEntityToEntityGuid.TryGetValue(childEntity, out var childEntityGuid))
                            {
                                // If the child entity doesn't have a guid, there's no way for us to communicate its identity to the destination world.
                                throw new Exception("LinkedEntityGroup child is missing an EntityGuid component.");
                            }

                            LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange
                            {
                                RootEntityGuid  = entityGuid,
                                ChildEntityGuid = childEntityGuid
                            });
                        }
                    }
                    else
                    {
                        ComponentDataStream.SetComponentData(packedComponent, elementPtr, typeInfo.ElementSize * length);
                        ExtractEntityReferencePatches(typeInfo, packedComponent, elementPtr, length);
                    }
                }
                else
                {
                    var sizeOf = afterArchetype->SizeOfs[afterIndexInTypeArray];
                    var ptr    = ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterEntityIndexInChunk * sizeOf;
                    ComponentDataStream.SetComponentData(packedComponent, ptr, sizeOf);
                    ExtractEntityReferencePatches(typeInfo, packedComponent, ptr, 1);
                }
            }
예제 #5
0
 public bool Contains(Archetype *value)
 {
     return(IndexOf(value) != -1);
 }
예제 #6
0
 static bool RequiresBuildingResidueSharedComponentIndices(Archetype *srcArchetype,
                                                           Archetype *dstArchetype)
 {
     return(dstArchetype->NumSharedComponents > 0 &&
            dstArchetype->NumSharedComponents != srcArchetype->NumSharedComponents);
 }
예제 #7
0
 public bool Contains(Archetype *value)
 {
     return(ListData.Contains(value));
 }
예제 #8
0
 public bool Contains(Archetype *value)
 {
     return(this.ListData().Contains(value));
 }
        internal void MoveChunksFromFiltered(
            NativeArray <ArchetypeChunk> chunks,
            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping,
            EntityComponentStore *srcEntityComponentStore,
            ManagedComponentStore srcManagedComponentStore)
        {
            var access = GetCheckedEntityDataAccess();
            var ecs    = access->EntityComponentStore;
            var mcs    = access->ManagedComponentStore;

            new MoveChunksJob
            {
                srcEntityComponentStore = srcEntityComponentStore,
                dstEntityComponentStore = ecs,
                entityRemapping         = entityRemapping,
                chunks = chunks
            }.Run();

            int chunkCount  = chunks.Length;
            var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob);

            Archetype *previousSrcArchetypee = null;
            Archetype *dstArchetype          = null;
            int        managedComponentCount = 0;

            NativeList <IntPtr> managedChunks = new NativeList <IntPtr>(0, Allocator.TempJob);

            for (int i = 0; i < chunkCount; ++i)
            {
                var chunk     = chunks[i].m_Chunk;
                var archetype = chunk->Archetype;

                // Move Chunk World. ChangeVersion:Yes OrderVersion:Yes
                if (previousSrcArchetypee != archetype)
                {
                    dstArchetype = ecs->GetOrCreateArchetype(archetype->Types, archetype->TypesCount);
                }

                remapChunks[i] = new RemapChunk {
                    chunk = chunk, dstArchetype = dstArchetype
                };

                if (dstArchetype->NumManagedComponents > 0)
                {
                    managedComponentCount += chunk->Count * dstArchetype->NumManagedComponents;
                    managedChunks.Add((IntPtr)chunk);
                }

                if (archetype->MetaChunkArchetype != null)
                {
                    Entity srcEntity = chunk->metaChunkEntity;
                    Entity dstEntity;

                    ecs->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1);

                    var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity);
                    var dstEntityInChunk = ecs->GetEntityInChunk(dstEntity);

                    ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1,
                                                    srcEntityComponentStore->GlobalSystemVersion, ecs->GlobalSystemVersion);
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity);

                    srcEntityComponentStore->DestroyEntities(&srcEntity, 1);
                }
            }

            NativeArray <int> srcManagedIndices = default;
            NativeArray <int> dstManagedIndices = default;
            int nonNullManagedComponentCount    = 0;

            if (managedComponentCount > 0)
            {
                srcManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob);
                dstManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob);
                new
                GatherManagedComponentIndicesInChunkJob()
                {
                    SrcEntityComponentStore = srcEntityComponentStore,
                    DstEntityComponentStore = ecs,
                    SrcManagedIndices       = srcManagedIndices,
                    DstManagedIndices       = dstManagedIndices,
                    Chunks       = managedChunks,
                    NonNullCount = &nonNullManagedComponentCount
                }.Run();
            }

            mcs.Playback(ref ecs->ManagedChangesTracker);
            srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker);

            k_ProfileMoveSharedComponents.Begin();
            var remapShared = access->MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob);

            k_ProfileMoveSharedComponents.End();

            if (managedComponentCount > 0)
            {
                k_ProfileMoveManagedComponents.Begin();
                mcs.MoveManagedComponentsFromDifferentWorld(srcManagedIndices, dstManagedIndices, nonNullManagedComponentCount, srcManagedComponentStore);
                srcEntityComponentStore->m_ManagedComponentFreeIndex.Add(srcManagedIndices.GetUnsafeReadOnlyPtr(), sizeof(int) * srcManagedIndices.Length);
                k_ProfileMoveManagedComponents.End();
            }

            new ChunkPatchEntities
            {
                RemapChunks          = remapChunks,
                EntityRemapping      = entityRemapping,
                EntityComponentStore = ecs
            }.Run();

            var remapChunksJob = new RemapChunksFilteredJob
            {
                dstEntityComponentStore = ecs,
                remapChunks             = remapChunks,
                entityRemapping         = entityRemapping,
                chunkHeaderType         = TypeManager.GetTypeIndex <ChunkHeader>()
            }.Schedule(remapChunks.Length, 1);

            var moveChunksBetweenArchetypeJob = new MoveFilteredChunksBetweenArchetypexJob
            {
                RemapChunks         = remapChunks,
                RemapShared         = remapShared,
                GlobalSystemVersion = ecs->GlobalSystemVersion
            }.Schedule(remapChunksJob);

            moveChunksBetweenArchetypeJob.Complete();

            mcs.Playback(ref ecs->ManagedChangesTracker);

            if (managedComponentCount > 0)
            {
                srcManagedIndices.Dispose();
                dstManagedIndices.Dispose();
            }
            managedChunks.Dispose();
            remapShared.Dispose();
            remapChunks.Dispose();
        }
예제 #10
0
 public int IndexOf(Archetype *value)
 {
     return(ListData.IndexOf(value));
 }
예제 #11
0
        public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager)
        {
            var type = GetExistingArchetype(types, count);

            if (type != null)
            {
                return(type);
            }

            AssertArchetypeComponents(types, count);

            // This is a new archetype, allocate it and add it to the hash map
            type              = (Archetype *)m_ArchetypeChunkAllocator.Allocate(sizeof(Archetype), 8);
            type->TypesCount  = count;
            type->Types       = (ComponentTypeInArchetype *)m_ArchetypeChunkAllocator.Construct(sizeof(ComponentTypeInArchetype) * count, 4, types);
            type->EntityCount = 0;

            type->NumSharedComponents   = 0;
            type->SharedComponentOffset = null;

            for (var i = 0; i < count; ++i)
            {
                if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.ISharedComponentData)
                {
                    ++type->NumSharedComponents;
                }
            }

            var chunkDataSize = Chunk.GetChunkBufferSize(type->NumSharedComponents);

            // FIXME: proper alignment
            type->Offsets = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4);
            type->SizeOfs = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4);

            var bytesPerInstance = 0;

            for (var i = 0; i < count; ++i)
            {
                var cType  = TypeManager.GetComponentType(types[i].TypeIndex);
                var sizeOf = cType.SizeInChunk * types[i].FixedArrayLengthMultiplier;
                type->SizeOfs[i] = sizeOf;

                bytesPerInstance += sizeOf;
            }

            type->ChunkCapacity = chunkDataSize / bytesPerInstance;
            Assert.IsTrue(Chunk.kMaximumEntitiesPerChunk >= type->ChunkCapacity);
            var usedBytes = 0;

            for (var i = 0; i < count; ++i)
            {
                var sizeOf = type->SizeOfs[i];

                type->Offsets[i] = usedBytes;

                usedBytes += sizeOf * type->ChunkCapacity;
            }
            type->NumManagedArrays   = 0;
            type->ManagedArrayOffset = null;

            for (var i = 0; i < count; ++i)
            {
                if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.Class)
                {
                    ++type->NumManagedArrays;
                }
            }

            if (type->NumManagedArrays > 0)
            {
                type->ManagedArrayOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4);
                var mi = 0;
                for (var i = 0; i < count; ++i)
                {
                    var cType = TypeManager.GetComponentType(types[i].TypeIndex);
                    if (cType.Category == TypeManager.TypeCategory.Class)
                    {
                        type->ManagedArrayOffset[i] = mi++;
                    }
                    else
                    {
                        type->ManagedArrayOffset[i] = -1;
                    }
                }
            }

            if (type->NumSharedComponents > 0)
            {
                type->SharedComponentOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4);
                var mi = 0;
                for (var i = 0; i < count; ++i)
                {
                    var cType = TypeManager.GetComponentType(types[i].TypeIndex);
                    if (cType.Category == TypeManager.TypeCategory.ISharedComponentData)
                    {
                        type->SharedComponentOffset[i] = mi++;
                    }
                    else
                    {
                        type->SharedComponentOffset[i] = -1;
                    }
                }
            }

            // Update the list of all created archetypes
            type->PrevArchetype = m_LastArchetype;
            m_LastArchetype     = type;

            UnsafeLinkedListNode.InitializeList(&type->ChunkList);
            UnsafeLinkedListNode.InitializeList(&type->ChunkListWithEmptySlots);

            m_TypeLookup.Add(GetHash(types, count), (IntPtr)type);

            groupManager.OnArchetypeAdded(type);

            return(type);
        }
        public void Move(Entity entity, Archetype *archetype, SharedComponentValues sharedComponentValues)
        {
            var archetypeChunkFilter = new ArchetypeChunkFilter(archetype, sharedComponentValues);

            Move(entity, ref archetypeChunkFilter);
        }
            private void SetComponentData(
                Chunk *afterChunk,
                Archetype *afterArchetype,
                ComponentTypeInArchetype afterTypeInArchetype,
                int afterIndexInTypeArray,
                int afterEntityIndexInChunk,
                Chunk *beforeChunk,
                Archetype *beforeArchetype,
                int beforeIndexInTypeArray,
                int beforeEntityIndexInChunk,
                EntityGuid entityGuid,
                int typeIndex,
                TypeInfo typeInfo)
            {
                if (afterTypeInArchetype.IsSharedComponent)
                {
                    var beforeOffset = beforeIndexInTypeArray - beforeChunk->Archetype->FirstSharedComponent;
                    var beforeSharedComponentIndex = beforeChunk->GetSharedComponentValue(beforeOffset);

                    var afterOffset = afterIndexInTypeArray - afterChunk->Archetype->FirstSharedComponent;
                    var afterSharedComponentIndex = afterChunk->GetSharedComponentValue(afterOffset);

                    // No managed objects in burst land. Do what we can and defer the actual unpacking until later.
                    ComponentDataStream.SetSharedComponentDataDeferred(entityGuid, afterTypeInArchetype.TypeIndex, afterSharedComponentIndex, beforeSharedComponentIndex);
                    return;
                }

                // IMPORTANT This means `IsZeroSizedInChunk` which is always true for shared components.
                // Always check shared components first.
                if (afterTypeInArchetype.IsZeroSized)
                {
                    return;
                }

                if (afterTypeInArchetype.IsBuffer)
                {
                    var beforeBuffer = (BufferHeader *)(ChunkUtility.GetBuffer(beforeChunk) + beforeArchetype->Offsets[beforeIndexInTypeArray] +
                                                        beforeEntityIndexInChunk * beforeArchetype->SizeOfs[beforeIndexInTypeArray]);
                    var beforeElementPtr = BufferHeader.GetElementPointer(beforeBuffer);
                    var beforeLength     = beforeBuffer->Length;

                    var afterBuffer = (BufferHeader *)(ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] +
                                                       afterEntityIndexInChunk * afterArchetype->SizeOfs[afterIndexInTypeArray]);
                    var afterElementPtr = BufferHeader.GetElementPointer(afterBuffer);
                    var afterLength     = afterBuffer->Length;

                    if (afterTypeInArchetype.TypeIndex == TypeInfoStream.LinkedEntityGroupTypeIndex)
                    {
                        var beforeLinkedEntityGroups = (LinkedEntityGroup *)beforeElementPtr;
                        var afterLinkedEntityGroups  = (LinkedEntityGroup *)afterElementPtr;

                        // Using is not supported by burst.
                        var beforeLinkedEntityGroupEntityGuids = new NativeArray <EntityGuid>(beforeLength, Allocator.Temp);
                        var afterLinkedEntityGroupEntityGuids  = new NativeArray <EntityGuid>(afterLength, Allocator.Temp);
                        {
                            for (var i = 0; i < beforeLength; i++)
                            {
                                if (!BeforeEntityToEntityGuid.TryGetValue(beforeLinkedEntityGroups[i].Value, out var beforeEntityGuid))
                                {
                                    throw new Exception("LinkedEntityGroup child is missing an EntityGuid component.");
                                }

                                beforeLinkedEntityGroupEntityGuids[i] = beforeEntityGuid;
                            }

                            for (var i = 0; i < afterLength; i++)
                            {
                                if (!AfterEntityToEntityGuid.TryGetValue(afterLinkedEntityGroups[i].Value, out var afterEntityGuid))
                                {
                                    throw new Exception("LinkedEntityGroup child is missing an EntityGuid component.");
                                }

                                afterLinkedEntityGroupEntityGuids[i] = afterEntityGuid;
                            }

                            beforeLinkedEntityGroupEntityGuids.Sort();
                            afterLinkedEntityGroupEntityGuids.Sort();

                            var beforeIndex = 0;
                            var afterIndex  = 0;

                            while (beforeIndex < beforeLength && afterIndex < afterLength)
                            {
                                var beforeEntityGuid = beforeLinkedEntityGroupEntityGuids[beforeIndex];
                                var afterEntityGuid  = afterLinkedEntityGroupEntityGuids[afterIndex];

                                var comparison = beforeEntityGuid.CompareTo(afterEntityGuid);

                                if (comparison == 0)
                                {
                                    // If the entity is in both "before" and "after", then there is no change.
                                    beforeIndex++;
                                    afterIndex++;
                                }
                                else if (comparison > 0)
                                {
                                    // If the entity is in "before" but not "after", it's been removed.
                                    LinkedEntityGroupRemovals.Add(new LinkedEntityGroupChange {
                                        RootEntityGuid = entityGuid, ChildEntityGuid = beforeEntityGuid
                                    });
                                    beforeIndex++;
                                }
                                else if (comparison < 0)
                                {
                                    // If the entity is in "after" but not "before", it's been added.
                                    LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange {
                                        RootEntityGuid = entityGuid, ChildEntityGuid = afterEntityGuid
                                    });
                                    afterIndex++;
                                }
                            }

                            while (beforeIndex < beforeLength)
                            {
                                // If the entity is in "before" but not "after", it's been removed.
                                LinkedEntityGroupRemovals.Add(new LinkedEntityGroupChange
                                {
                                    RootEntityGuid = entityGuid, ChildEntityGuid = beforeLinkedEntityGroupEntityGuids[beforeIndex++]
                                });
                            }

                            while (afterIndex < afterLength)
                            {
                                // If the entity is in "after" but not "before", it's been added.
                                LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange
                                {
                                    RootEntityGuid = entityGuid, ChildEntityGuid = afterLinkedEntityGroupEntityGuids[afterIndex++]
                                });
                            }
                        }
                    }
                    else
                    {
                        if (afterLength != beforeLength ||
                            UnsafeUtility.MemCmp(beforeElementPtr, afterElementPtr, afterLength * typeInfo.ElementSize) != 0)
                        {
                            var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash);
                            ComponentDataStream.SetComponentData(packedComponent, afterElementPtr, typeInfo.ElementSize * afterLength);
                            ExtractEntityReferencePatches(typeInfo, packedComponent, afterElementPtr, afterLength);
                        }
                    }
                }
                else
                {
                    if (beforeArchetype->SizeOfs[beforeIndexInTypeArray] != afterArchetype->SizeOfs[afterIndexInTypeArray])
                    {
                        throw new Exception("Archetype->SizeOfs do not match");
                    }

                    var beforeAddress = ChunkUtility.GetBuffer(beforeChunk) + beforeArchetype->Offsets[beforeIndexInTypeArray] +
                                        beforeArchetype->SizeOfs[beforeIndexInTypeArray] * beforeEntityIndexInChunk;
                    var afterAddress = ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterArchetype->SizeOfs[afterIndexInTypeArray] * afterEntityIndexInChunk;

                    if (UnsafeUtility.MemCmp(beforeAddress, afterAddress, beforeArchetype->SizeOfs[beforeIndexInTypeArray]) != 0)
                    {
                        var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash);
                        ComponentDataStream.SetComponentData(packedComponent, afterAddress, beforeArchetype->SizeOfs[beforeIndexInTypeArray]);
                        ExtractEntityReferencePatches(typeInfo, packedComponent, afterAddress, 1);
                    }
                }
            }
예제 #14
0
        private void AddArchetypeIfMatching(Archetype *archetype, EntityGroupData *group)
        {
            // If the group has more actually required types than the archetype it can never match, so early out as an optimization
            if (group->RequiredComponentsCount - group->SubtractiveComponentsCount > archetype->TypesCount)
            {
                return;
            }
            var typeI             = 0;
            var prevTypeI         = 0;
            var disabledIndex     = TypeManager.GetTypeIndex <Disabled>();
            var prefabIndex       = TypeManager.GetTypeIndex <Prefab>();
            var requestedDisabled = false;
            var requestedPrefab   = false;

            for (var i = 0; i < group->RequiredComponentsCount; ++i, ++typeI)
            {
                while (archetype->Types[typeI].TypeIndex < group->RequiredComponents[i].TypeIndex &&
                       typeI < archetype->TypesCount)
                {
                    ++typeI;
                }

                if (group->RequiredComponents[i].TypeIndex == disabledIndex)
                {
                    requestedDisabled = true;
                }
                if (group->RequiredComponents[i].TypeIndex == prefabIndex)
                {
                    requestedPrefab = true;
                }

                var hasComponent = !(typeI >= archetype->TypesCount);

                // Type mismatch
                if (hasComponent && archetype->Types[typeI].TypeIndex != group->RequiredComponents[i].TypeIndex)
                {
                    hasComponent = false;
                }

                if (hasComponent && group->RequiredComponents[i].AccessModeType == ComponentType.AccessMode.Subtractive)
                {
                    return;
                }
                if (!hasComponent &&
                    group->RequiredComponents[i].AccessModeType != ComponentType.AccessMode.Subtractive)
                {
                    return;
                }
                if (hasComponent)
                {
                    prevTypeI = typeI;
                }
                else
                {
                    typeI = prevTypeI;
                }
            }

            if (archetype->Disabled && (!requestedDisabled))
            {
                return;
            }
            if (archetype->Prefab && (!requestedPrefab))
            {
                return;
            }

            var match = (MatchingArchetypes *)m_GroupDataChunkAllocator.Allocate(
                MatchingArchetypes.GetAllocationSize(group->RequiredComponentsCount), 8);

            match->Archetype = archetype;
            var typeIndexInArchetypeArray = match->IndexInArchetype;

            if (group->LastMatchingArchetype == null)
            {
                group->LastMatchingArchetype = match;
            }

            match->Next = group->FirstMatchingArchetype;
            group->FirstMatchingArchetype = match;

            for (var component = 0; component < group->RequiredComponentsCount; ++component)
            {
                var typeComponentIndex = -1;
                if (group->RequiredComponents[component].AccessModeType != ComponentType.AccessMode.Subtractive)
                {
                    typeComponentIndex =
                        ChunkDataUtility.GetIndexInTypeArray(archetype, group->RequiredComponents[component].TypeIndex);
                    Assert.AreNotEqual(-1, typeComponentIndex);
                }

                typeIndexInArchetypeArray[component] = typeComponentIndex;
            }
        }
예제 #15
0
 public void Add(Archetype *value)
 {
     ListData.Add(value);
 }
예제 #16
0
 public int IndexOf(Archetype *value)
 {
     return(this.ListData().IndexOf(value));
 }
예제 #17
0
        Archetype *CreateInstanceArchetype(ComponentTypeInArchetype *inTypesSorted, int count, ComponentTypeInArchetype *types, Archetype *srcArchetype, bool removePrefab)
        {
            UnsafeUtility.MemCpy(types, inTypesSorted, sizeof(ComponentTypeInArchetype) * count);

            var hasCleanup   = false;
            var removedTypes = 0;

            for (var t = 0; t < srcArchetype->TypesCount; ++t)
            {
                var type = srcArchetype->Types[t];

                hasCleanup |= type.TypeIndex == m_CleanupEntityType;

                var skip = type.IsSystemStateComponent || (removePrefab && type.TypeIndex == m_PrefabType);
                if (skip)
                {
                    ++removedTypes;
                }
                else
                {
                    types[t - removedTypes] = srcArchetype->Types[t];
                }
            }

            // Entity has already been destroyed, so it shouldn't be instantiated anymore
            if (hasCleanup)
            {
                return(null);
            }
            else if (removedTypes > 0)
            {
                return(GetOrCreateArchetype(types, count - removedTypes));
            }
            else
            {
                return(srcArchetype);
            }
        }
예제 #18
0
 public void Add(Archetype *value)
 {
     this.ListData().Add(value);
 }
예제 #19
0
        ArchetypeChunkFilter GetArchetypeChunkFilterWithChangedArchetype(Chunk *srcChunk, Archetype *dstArchetype)
        {
            var srcArchetype = srcChunk->Archetype;

            var archetypeChunkFilter = new ArchetypeChunkFilter();

            archetypeChunkFilter.Archetype = dstArchetype;
            BuildSharedComponentIndicesWithChangedArchetype(srcArchetype, dstArchetype, srcChunk->SharedComponentValues, archetypeChunkFilter.SharedComponentValues);
            return(archetypeChunkFilter);
        }
예제 #20
0
 public void AddNoResize(Archetype *value)
 {
     Writer.AddNoResize(value);
 }
예제 #21
0
        internal object GetManagedObject(Archetype *archetype, int managedArrayIndex, int chunkCapacity, int type, int index)
        {
            var managedStart = archetype->ManagedArrayOffset[type] * chunkCapacity;

            return(m_ManagedArrays[managedArrayIndex].ManagedArray[index + managedStart]);
        }
        internal void MoveChunksFromFiltered(
            NativeArray <ArchetypeChunk> chunks,
            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping,
            EntityComponentStore *srcEntityComponentStore,
            ManagedComponentStore srcManagedComponentStore)
        {
            new MoveChunksJob
            {
                srcEntityComponentStore = srcEntityComponentStore,
                dstEntityComponentStore = EntityComponentStore,
                entityRemapping         = entityRemapping,
                chunks = chunks
            }.Run();

            var managedArrayChunks = new NativeList <IntPtr>(Allocator.Temp);

            int chunkCount  = chunks.Length;
            var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob);

            Archetype *previousSrcArchetypee = null;
            Archetype *dstArchetype          = null;

            for (int i = 0; i < chunkCount; ++i)
            {
                var chunk     = chunks[i].m_Chunk;
                var archetype = chunk->Archetype;

                if (previousSrcArchetypee != archetype)
                {
                    dstArchetype = EntityComponentStore->GetOrCreateArchetype(archetype->Types, archetype->TypesCount);
                    EntityComponentStore->IncrementComponentTypeOrderVersion(dstArchetype);
                }

                remapChunks[i] = new RemapChunk {
                    chunk = chunk, dstArchetype = dstArchetype
                };

                if (archetype->NumManagedArrays > 0)
                {
                    managedArrayChunks.Add((IntPtr)chunk);
                }

                if (archetype->MetaChunkArchetype != null)
                {
                    Entity srcEntity = chunk->metaChunkEntity;
                    Entity dstEntity;

                    EntityComponentStore->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1);

                    var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity);
                    var dstEntityInChunk = EntityComponentStore->GetEntityInChunk(dstEntity);

                    ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1,
                                                    srcEntityComponentStore->GlobalSystemVersion, EntityComponentStore->GlobalSystemVersion);
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity);

                    srcEntityComponentStore->DestroyEntities(&srcEntity, 1);
                }
            }

            var managedArrayDstIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob);
            var managedArraySrcIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob);

            EntityComponentStore->ReserveManagedObjectArrays(managedArrayDstIndices);

            var remapManaged = new RemapManagedArraysJob
            {
                chunks     = managedArrayChunks,
                dstIndices = managedArrayDstIndices,
                srcIndices = managedArraySrcIndices,
            }.Schedule(managedArrayChunks.Length, 64);

            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker);

            k_ProfileMoveObjectComponents.Begin();
            remapManaged.Complete();
            m_ManagedComponentStore.MoveManagedObjectArrays(managedArraySrcIndices, managedArrayDstIndices, srcManagedComponentStore);
            k_ProfileMoveObjectComponents.End();

            managedArrayDstIndices.Dispose();
            managedArraySrcIndices.Dispose();
            managedArrayChunks.Dispose();

            k_ProfileMoveSharedComponents.Begin();
            var remapShared =
                ManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob);

            k_ProfileMoveSharedComponents.End();

            new ChunkPatchEntities
            {
                RemapChunks          = remapChunks,
                EntityRemapping      = entityRemapping,
                EntityComponentStore = EntityComponentStore
            }.Run();

            var remapChunksJob = new RemapChunksFilteredJob
            {
                dstEntityComponentStore = EntityComponentStore,
                remapChunks             = remapChunks,
                entityRemapping         = entityRemapping
            }.Schedule(remapChunks.Length, 1);

            var moveChunksBetweenArchetypeJob = new MoveFilteredChunksBetweenArchetypexJob
            {
                remapChunks         = remapChunks,
                remapShared         = remapShared,
                globalSystemVersion = EntityComponentStore->GlobalSystemVersion
            }.Schedule(remapChunksJob);

            moveChunksBetweenArchetypeJob.Complete();

            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);

            remapShared.Dispose();
            remapChunks.Dispose();
        }
예제 #23
0
        public void SetManagedObject(Archetype *archetype, int managedArrayIndex, int chunkCapacity, int type, int index, object val)
        {
            var managedStart = archetype->ManagedArrayOffset[type] * chunkCapacity;

            m_ManagedArrays[managedArrayIndex].ManagedArray[index + managedStart] = val;
        }
예제 #24
0
        static unsafe void WriteChunkData(YamlWriter writer, EntityManager entityManager, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos, Chunk *initialChunk, Archetype *archetype, int archetypeIndex, bool dumpChunkRawData)
        {
            var    tempChunkMem = stackalloc byte[Chunk.kChunkSize];
            Chunk *tempChunk    = (Chunk *)tempChunkMem;

            if (dumpChunkRawData)
            {
                UnsafeUtility.MemCpy(tempChunk, initialChunk, Chunk.kChunkSize);

                byte *tempChunkBuffer = tempChunk->Buffer;

                BufferHeader.PatchAfterCloningChunk(tempChunk);
                EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);
                ClearChunkHeaderComponents(tempChunk);
                ChunkDataUtility.MemsetUnusedChunkData(tempChunk, 0);

                tempChunk->Archetype = (Archetype *)archetypeIndex;
            }

            using (writer.WriteCollection(k_ChunkDataCollectionTag))
            {
                using (writer.WriteCollection("Header"))
                {
                    WriteEntity(writer, nameof(Chunk.metaChunkEntity), initialChunk->metaChunkEntity);
                    writer.WriteKeyValue(nameof(Chunk.Capacity), initialChunk->Capacity);
                    writer.WriteKeyValue(nameof(Chunk.Count), initialChunk->Count);

                    if (dumpChunkRawData)
                    {
                        writer.WriteFormattedBinaryData("Header-RawData", tempChunk, Chunk.kBufferOffset);
                    }
                }

                // First pass to sort by component type
                var entitiesByChunkIndex   = new Dictionary <int, Entity>();
                var componentDataList      = new List <int>();
                var chunkComponentDataList = new List <int>();
                var chunkTypes             = archetype->Types;
                for (int typeI = 0; typeI < archetype->TypesCount; typeI++)
                {
                    var componentType         = &chunkTypes[typeI];
                    var type                  = TypeManager.GetType(componentType->TypeIndex);
                    ref readonly var typeInfo = ref TypeManager.GetTypeInfo(componentType->TypeIndex);
예제 #25
0
        static unsafe void WriteChunkData(YamlWriter writer, EntityManager entityManager, Chunk *initialChunk, Archetype *archetype, bool dumpChunkRawData)
        {
            using (writer.WriteCollection(k_ChunkDataCollectionTag))
            {
                using (writer.WriteCollection("Header"))
                {
                    WriteEntity(writer, nameof(Chunk.metaChunkEntity), initialChunk->metaChunkEntity);
                    writer.WriteKeyValue(nameof(Chunk.Capacity), initialChunk->Capacity)
                    .WriteKeyValue(nameof(Chunk.Count), initialChunk->Count);

                    if (dumpChunkRawData)
                    {
                        writer.WriteFormattedBinaryData("RawData", initialChunk, Chunk.kBufferOffset);
                    }
                }

                // First pass to sort by component type
                var entitiesByChunkIndex   = new Dictionary <int, Entity>();
                var componentDataList      = new List <int>();
                var chunkComponentDataList = new List <int>();
                var chunkTypes             = archetype->Types;
                for (int typeI = 0; typeI < archetype->TypesCount; typeI++)
                {
                    var componentType = &chunkTypes[typeI];
                    var type          = TypeManager.GetType(componentType->TypeIndex);
                    var typeInfo      = TypeManager.GetTypeInfo(componentType->TypeIndex);

                    if (componentType->IsChunkComponent)
                    {
                        chunkComponentDataList.Add(typeI);
                    }

                    // Is it a Component Data ?
                    else if (typeof(IComponentData).IsAssignableFrom(type) || typeof(Entity).IsAssignableFrom(type) || typeof(IBufferElementData).IsAssignableFrom(type))
                    {
                        // Ignore Tag Component, no data to dump
                        if (typeInfo.IsZeroSized)
                        {
                            continue;
                        }

                        if (typeof(Entity).IsAssignableFrom(type))
                        {
                            componentDataList.Insert(0, typeI);

                            for (int i = 0; i < initialChunk->Count;)
                            {
                                var entity = (Entity)Marshal.PtrToStructure((IntPtr)initialChunk->Buffer + archetype->SizeOfs[0] * i, type);
                                if (entityManager.Exists(entity))
                                {
                                    entitiesByChunkIndex.Add(i, entity);
                                    i++;
                                }
                            }
                        }
                        else
                        {
                            componentDataList.Add(typeI);
                        }
                    }
                }

                // Parse the Component Data for this chunk and store them
                using (writer.WriteCollection(k_ComponentDataCollectionTag))
                {
                    foreach (var typeI in componentDataList)
                    {
                        var componentTypeInArchetype = &chunkTypes[typeI];
                        var componentType            = TypeManager.GetType(componentTypeInArchetype->TypeIndex);
                        var componentTypeInfo        = TypeManager.GetTypeInfo(componentTypeInArchetype->TypeIndex);
                        var componentExtractedInfo   = TypeDataExtractor.GetTypeExtractedInfo(componentType);

                        using (writer.WriteCollection(k_ComponentDataTag))
                        {
                            writer.WriteInlineMap("info", new[]
                            {
                                new KeyValuePair <object, object>(nameof(Type), componentType.Name),
                                new KeyValuePair <object, object>(nameof(TypeManager.TypeInfo.SizeInChunk), componentTypeInfo.SizeInChunk)
                            });

                            using (writer.WriteCollection("Entities"))
                            {
                                var indexInTypeArray       = ChunkDataUtility.GetIndexInTypeArray(archetype, componentTypeInArchetype->TypeIndex);
                                var componentOffsetInChunk = archetype->Offsets[indexInTypeArray];
                                var componentSize          = archetype->SizeOfs[indexInTypeArray];
                                var componentsBuffer       = initialChunk->Buffer + componentOffsetInChunk;
                                var entityData             = new Dictionary <string, string>();

                                // Dump all entities in this chunk
                                foreach (var kvp in entitiesByChunkIndex)
                                {
                                    var entity = kvp.Value;
                                    entityData.Clear();

                                    // Get the location of the component data
                                    var compData = componentsBuffer + kvp.Key * componentSize;

                                    // If the component we are dumping is a Dynamic Buffer
                                    if (typeof(IBufferElementData).IsAssignableFrom(componentType))
                                    {
                                        var header = (BufferHeader *)compData;
                                        var begin  = BufferHeader.GetElementPointer(header);
                                        var size   = Marshal.SizeOf(componentType);

                                        using (writer.WriteCollection(entity.ToString()))
                                        {
                                            for (var it = 0; it < header->Length; it++)
                                            {
                                                var item = begin + (size * it);
                                                entityData.Clear();

                                                // Dump each field of the current entity's component data
                                                foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                                {
                                                    var compDataObject = Marshal.PtrToStructure((IntPtr)item + componentFieldInfo.Offset, componentFieldInfo.Type);
                                                    entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                                }
                                                writer.WriteInlineMap($"{it:0000}", entityData);
                                            }
                                        }
                                    }

                                    // If it's a Component Data
                                    else
                                    {
                                        // Dump each field of the current entity's component data
                                        foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                        {
                                            var compDataObject = Marshal.PtrToStructure((IntPtr)compData + componentFieldInfo.Offset, componentFieldInfo.Type);
                                            entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                        }
                                        writer.WriteInlineMap(entity.ToString(), entityData);
                                    }
                                }
                                if (dumpChunkRawData)
                                {
                                    var csize = EntityComponentStore.GetComponentArraySize(componentSize, archetype->ChunkCapacity);
                                    writer.WriteFormattedBinaryData("RawData", componentsBuffer, csize, componentOffsetInChunk + Chunk.kBufferOffset);
                                }
                            }
                        }
                    }
                }
            }
        }