private static unsafe Entity GetEntityFromEntityInChunk(EntityInChunk entityInChunk)
        {
            var chunk     = entityInChunk.Chunk;
            var archetype = chunk->Archetype;
            var buffer    = ChunkUtility.GetBuffer(chunk) + archetype->Offsets[0] + entityInChunk.IndexInChunk * archetype->SizeOfs[0];

            return(*(Entity *)buffer);
        }
Esempio n. 2
0
            public unsafe void Execute(int index)
            {
                var chunk     = Chunks[index].m_Chunk;
                var archetype = chunk->Archetype;
                var entities  = (Entity *)(ChunkUtility.GetBuffer(chunk) + archetype->Offsets[0]);
                var componentTypeIndexInArchetype = ChunkDataUtility.GetIndexInTypeArray(archetype, ComponentTypeIndex);
                var componentBuffer = (TComponentData *)(ChunkUtility.GetBuffer(chunk) + archetype->Offsets[componentTypeIndexInArchetype]);

                for (var i = 0; i < chunk->Count; ++i)
                {
                    ComponentDataToEntity.Add(componentBuffer[i], entities[i]);
                }
            }
Esempio n. 3
0
            public void Execute(int index)
            {
                var chunk     = Chunks[index].m_Chunk;
                var archetype = chunk->Archetype;

                for (var typeIndexInArchetype = 0; typeIndexInArchetype < archetype->TypesCount; typeIndexInArchetype++)
                {
                    var componentTypeInArchetype = archetype->Types[typeIndexInArchetype];
                    var typeInfo = TypeInfoStream.GetTypeInfo(componentTypeInArchetype.TypeIndex);

                    if (typeInfo.EntityOffsetCount == 0)
                    {
                        // This type has no entity references. Skip.
                        continue;
                    }

                    if (componentTypeInArchetype.IsSharedComponent || componentTypeInArchetype.IsZeroSized)
                    {
                        // @TODO Should we handle shared components with references? Is that a thing?
                        continue;
                    }

                    var typeInChunkPtr = ChunkUtility.GetBuffer(chunk) + archetype->Offsets[typeIndexInArchetype];
                    var typeSizeOf     = archetype->SizeOfs[typeIndexInArchetype];

                    var changed = false;

                    for (var entityIndexInChunk = 0; entityIndexInChunk < Chunks[index].Count; entityIndexInChunk++)
                    {
                        var componentDataPtr = typeInChunkPtr + typeSizeOf * entityIndexInChunk;

                        if (componentTypeInArchetype.IsBuffer)
                        {
                            var bufferHeader = (BufferHeader *)componentDataPtr;
                            var bufferLength = bufferHeader->Length;
                            var bufferPtr    = BufferHeader.GetElementPointer(bufferHeader);
                            changed |= SetMissingEntityReferencesToNullForComponent(typeInfo, bufferPtr, bufferLength);
                        }
                        else
                        {
                            changed |= SetMissingEntityReferencesToNullForComponent(typeInfo, componentDataPtr, 1);
                        }
                    }

                    if (changed)
                    {
                        chunk->SetChangeVersion(typeIndexInArchetype, GlobalSystemVersion);
                    }
                }
            }
            public unsafe void Execute(int index)
            {
                var chunk            = Chunks[index].m_Chunk;
                var chunkChangeFlags = ChunkChangeFlags[index];
                var baseIndex        = Offsets[index];

                var archetype = chunk->Archetype;
                var componentIndexInArchetype = ChunkDataUtility.GetIndexInTypeArray(archetype, ComponentTypeIndex);
                var componentBuffer           = (TComponent *)(ChunkUtility.GetBuffer(chunk) + archetype->Offsets[componentIndexInArchetype]);

                for (var i = 0; i < chunk->Count; ++i)
                {
                    Entities[baseIndex + i] = new EntityInChunkWithComponent <TComponent>
                    {
                        EntityInChunk = new EntityInChunk {
                            Chunk = chunk, IndexInChunk = i
                        },
                        Component        = componentBuffer[i],
                        ChunkChangeFlags = chunkChangeFlags
                    };
                }
            }
            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);
                    }
                }
            }
            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);
                }
            }