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); }
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]); } }
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); } }