public static void PatchEntitiesForPrefab(EntityPatchInfo *scalarPatches, int scalarPatchCount, BufferEntityPatchInfo *bufferPatches, int bufferPatchCount, byte *data, int indexInChunk, int entityCount, SparseEntityRemapInfo *remapping, int remappingCount) { // Patch scalars (single components) with entity references. for (int p = 0; p < scalarPatchCount; p++) { byte *entityData = data + scalarPatches[p].Offset; for (int e = 0; e != entityCount; e++) { Entity *entity = (Entity *)(entityData + scalarPatches[p].Stride * (e + indexInChunk)); * entity = RemapEntityForPrefab(remapping + e * remappingCount, remappingCount, *entity); } } // Patch buffers that contain entity references for (int p = 0; p < bufferPatchCount; ++p) { byte *bufferData = data + bufferPatches[p].BufferOffset; for (int e = 0; e != entityCount; e++) { BufferHeader *header = (BufferHeader *)(bufferData + bufferPatches[p].BufferStride * (e + indexInChunk)); byte *elemsBase = BufferHeader.GetElementPointer(header) + bufferPatches[p].ElementOffset; int elemCount = header->Length; for (int k = 0; k != elemCount; ++k) { Entity *entityPtr = (Entity *)elemsBase; * entityPtr = RemapEntityForPrefab(remapping + e * remappingCount, remappingCount, *entityPtr); elemsBase += bufferPatches[p].ElementStride; } } } }
//cm internal void AddBufferRaw(Entity entity, int componentTypeIndex, BufferHeader *tempBuffer) { EntityComponentStore->AssertEntityHasComponent(entity, componentTypeIndex); ComponentJobSafetyManager->CompleteReadAndWriteDependency(componentTypeIndex); var bufferHeader = (BufferHeader *)EntityComponentStore->GetComponentDataWithTypeRW(entity, componentTypeIndex, EntityComponentStore->GlobalSystemVersion); var typeInfo = TypeManager.GetTypeInfo(componentTypeIndex); var elementSize = typeInfo.ElementSize; var alignment = typeInfo.AlignmentInBytes; var total = bufferHeader->Length + tempBuffer->Length; if (total > bufferHeader->Capacity) { BufferHeader.EnsureCapacity(bufferHeader, total, elementSize, alignment, BufferHeader.TrashMode.RetainOldData); } UnsafeUtility.MemCpy( BufferHeader.GetElementPointer(bufferHeader) + bufferHeader->Length * elementSize, BufferHeader.GetElementPointer(tempBuffer), tempBuffer->Length * elementSize); bufferHeader->Length = total; }
// After cloning two worlds have access to the same malloc'ed buffer pointer leading to double deallocate etc. // So after cloning, just allocate all malloc based buffers and copy the data. public static void PatchAfterCloningChunkForDiff(Chunk *chunk) { for (int i = 0; i < chunk->Archetype->TypesCount; ++i) { var type = chunk->Archetype->Types[i]; if (!type.IsBuffer) { continue; } var ti = TypeManager.GetTypeInfo(type.TypeIndex); var sizeOf = chunk->Archetype->SizeOfs[i]; var offset = chunk->Archetype->Offsets[i]; for (var j = 0; j < chunk->Count; ++j) { var offsetOfBuffer = offset + sizeOf * j; var header = (BufferHeader *)(chunk->Buffer + offsetOfBuffer); if (header->Pointer != null) // hoo boy, it's a malloc { BufferHeader newHeader = *header; var bytesToAllocate = header->Capacity * ti.ElementSize; var bytesToCopy = header->Length * ti.ElementSize; newHeader.Pointer = (byte *)UnsafeUtility.Malloc(bytesToAllocate, 16, Allocator.Persistent); UnsafeUtility.MemCpy(newHeader.Pointer, header->Pointer, bytesToCopy); *header = newHeader; } } } }
private static unsafe void ApplySetComponents( EntityManager entityManager, NativeArray <PackedComponentDataChange> changes, NativeArray <byte> payload, NativeArray <EntityGuid> packedEntityGuids, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes, NativeMultiHashMap <EntityGuid, Entity> entityGuidToEntity, NativeHashMap <Entity, EntityGuid> entityToEntityGuid) { var entityGuidTypeIndex = TypeManager.GetTypeIndex <EntityGuid>(); var offset = 0L; for (var i = 0; i < changes.Length; i++) { var packedComponentDataChange = changes[i]; var packedComponent = packedComponentDataChange.Component; var component = packedTypes[packedComponent.PackedTypeIndex]; var size = packedComponentDataChange.Size; var data = (byte *)payload.GetUnsafeReadOnlyPtr() + offset; var componentTypeInArchetype = new ComponentTypeInArchetype(component); if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator)) { do { if (!entityManager.Exists(entity)) { Debug.LogWarning($"SetComponent<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity does not exist."); } else if (!entityManager.HasComponent(entity, component)) { Debug.LogWarning($"SetComponent<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component does not exist."); } else { if (componentTypeInArchetype.IsZeroSized) { // Nothing to set. } else if (componentTypeInArchetype.IsBuffer) { var typeInfo = TypeManager.GetTypeInfo(componentTypeInArchetype.TypeIndex); var elementSize = typeInfo.ElementSize; var lengthInElements = size / elementSize; var header = (BufferHeader *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex); BufferHeader.Assign(header, data, lengthInElements, elementSize, 16); } else { var target = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex); // Perform incremental updates on the entityGuidToEntity map to avoid a full rebuild. if (componentTypeInArchetype.TypeIndex == entityGuidTypeIndex) { EntityGuid entityGuid; UnsafeUtility.MemCpy(&entityGuid, target, sizeof(EntityGuid)); if (!entityGuid.Equals(default))
public static void InitializeComponents(Chunk *dstChunk, int dstIndex, int count) { var arch = dstChunk->Archetype; var offsets = arch->Offsets; var sizeOfs = arch->SizeOfs; var dstBuffer = dstChunk->Buffer; var typesCount = arch->TypesCount; var types = arch->Types; for (var t = 1; t != typesCount; t++) { var offset = offsets[t]; var sizeOf = sizeOfs[t]; var dst = dstBuffer + (offset + sizeOf * dstIndex); if (types[t].IsBuffer) { for (var i = 0; i < count; ++i) { BufferHeader.Initialize((BufferHeader *)dst, types[t].BufferCapacity); dst += sizeOf; } } else { UnsafeUtility.MemClear(dst, sizeOf * count); } } }
public static unsafe void InitializeComponents(Chunk *dstChunk, int dstIndex, int count) { Archetype *archetype = dstChunk.Archetype; int * offsets = archetype->Offsets; int * sizeOfs = archetype->SizeOfs; byte * numPtr3 = &dstChunk.Buffer.FixedElementField; int typesCount = archetype->TypesCount; ComponentTypeInArchetype *types = archetype->Types; for (int i = 1; i != typesCount; i++) { int num3 = offsets[i]; int num4 = sizeOfs[i]; byte *numPtr4 = numPtr3 + (num3 + (num4 * dstIndex)); if (!(types + i).IsBuffer) { UnsafeUtility.MemClear((void *)numPtr4, (long)(num4 * count)); } else { int num5 = 0; while (true) { if (num5 >= count) { break; } BufferHeader.Initialize((BufferHeader *)numPtr4, types[i].BufferCapacity); numPtr4 += num4; num5++; } } } }
void DeallocateBuffers(Entity *entities, Chunk *chunk, int batchCount) { var archetype = chunk->Archetype; for (var ti = 0; ti < archetype->TypesCount; ++ti) { var type = archetype->Types[ti]; if (!type.IsBuffer) { continue; } var basePtr = chunk->Buffer + archetype->Offsets[ti]; var stride = archetype->SizeOfs[ti]; for (int i = 0; i < batchCount; ++i) { Entity e = entities[i]; int indexInChunk = m_EntityInChunkByEntity[e.Index].IndexInChunk; byte * bufferPtr = basePtr + stride * indexInChunk; BufferHeader.Destroy((BufferHeader *)bufferPtr); } } }
public static void InitializeBuffersInChunk(byte *p, int count, int stride, int bufferCapacity) { for (int i = 0; i < count; i++) { BufferHeader.Initialize((BufferHeader *)p, bufferCapacity); p += stride; } }
public static void ReplicateComponents(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstBaseIndex, int count) { var srcArchetype = srcChunk->Archetype; var srcBuffer = srcChunk->Buffer; var dstBuffer = dstChunk->Buffer; var dstArchetype = dstChunk->Archetype; var srcOffsets = srcArchetype->Offsets; var srcSizeOfs = srcArchetype->SizeOfs; var srcBufferCapacities = srcArchetype->BufferCapacities; var srcTypesCount = srcArchetype->TypesCount; var srcTypes = srcArchetype->Types; var dstTypes = dstArchetype->Types; var dstOffsets = dstArchetype->Offsets; var dstTypeIndex = 1; // type[0] is always Entity, and will be patched up later, so just skip for (var srcTypeIndex = 1; srcTypeIndex != srcTypesCount; srcTypeIndex++) { var srcType = srcTypes[srcTypeIndex]; var dstType = dstTypes[dstTypeIndex]; // Type does not exist in destination. Skip it. if (srcType.TypeIndex != dstType.TypeIndex) { continue; } var srcOffset = srcOffsets[srcTypeIndex]; var srcSizeOf = srcSizeOfs[srcTypeIndex]; var dstOffset = dstOffsets[dstTypeIndex]; var src = srcBuffer + (srcOffset + srcSizeOf * srcIndex); var dst = dstBuffer + (dstOffset + srcSizeOf * dstBaseIndex); if (!srcType.IsBuffer) { UnsafeUtility.MemCpyReplicate(dst, src, srcSizeOf, count); } else { var srcBufferCapacity = srcBufferCapacities[srcTypeIndex]; var alignment = 8; // TODO: Need a way to compute proper alignment for arbitrary non-generic types in TypeManager var elementSize = TypeManager.GetTypeInfo(srcType.TypeIndex).ElementSize; for (int i = 0; i < count; ++i) { BufferHeader *srcHdr = (BufferHeader *)src; BufferHeader *dstHdr = (BufferHeader *)dst; BufferHeader.Initialize(dstHdr, srcBufferCapacity); BufferHeader.Assign(dstHdr, BufferHeader.GetElementPointer(srcHdr), srcHdr->Length, elementSize, alignment); dst += srcSizeOf; } } dstTypeIndex++; } }
public void Execute(int index) { var srcChunk = Chunks[index].m_Chunk; var dstChunk = ClonedChunks[index].m_Chunk; var copySize = Chunk.GetChunkBufferSize(); UnsafeUtility.MemCpy((byte *)dstChunk + Chunk.kBufferOffset, (byte *)srcChunk + Chunk.kBufferOffset, copySize); BufferHeader.PatchAfterCloningChunk(dstChunk); }
public static unsafe void PatchEntities(EntityPatchInfo *scalarPatches, int scalarPatchCount, BufferEntityPatchInfo *bufferPatches, int bufferPatchCount, byte *data, int count, ref NativeArray <EntityRemapInfo> remapping) { int index = 0; while (true) { if (index >= scalarPatchCount) { int num3 = 0; while (num3 < bufferPatchCount) { byte *numPtr2 = data + bufferPatches[num3].BufferOffset; int num4 = 0; while (true) { if (num4 == count) { num3++; break; } BufferHeader *header = (BufferHeader *)numPtr2; byte * numPtr3 = BufferHeader.GetElementPointer(header) + bufferPatches[num3].ElementOffset; int length = header->Length; int num6 = 0; while (true) { if (num6 == length) { numPtr2 += bufferPatches[num3].BufferStride; num4++; break; } Entity *entityPtr2 = (Entity *)numPtr3; entityPtr2[0] = RemapEntity(ref remapping, entityPtr2[0]); numPtr3 += bufferPatches[num3].ElementStride; num6++; } } } return; } byte *numPtr = data + scalarPatches[index].Offset; int num2 = 0; while (true) { if (num2 == count) { index++; break; } Entity *entityPtr = (Entity *)numPtr; entityPtr[0] = RemapEntity(ref remapping, entityPtr[0]); numPtr += scalarPatches[index].Stride; num2++; } } }
public unsafe void AddRange(NativeArray <T> newElems) { this.CheckWriteAccess(); int num = UnsafeUtility.SizeOf <T>(); int length = this.Length; this.ResizeUninitialized(length + newElems.Length); UnsafeUtility.MemCpy((void *)(BufferHeader.GetElementPointer(this.m_Buffer) + (length * num)), newElems.GetUnsafeReadOnlyPtr <T>(), (long)(num * newElems.Length)); }
public void Reserve(int length) { CheckWriteAccessAndInvalidateArrayAliases(); #if ENABLE_UNITY_COLLECTIONS_CHECKS BufferHeader.EnsureCapacity(m_Buffer, length, UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), BufferHeader.TrashMode.RetainOldData, m_useMemoryInitPattern, m_memoryInitPattern); #else BufferHeader.EnsureCapacity(m_Buffer, length, UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), BufferHeader.TrashMode.RetainOldData, false, 0); #endif }
internal unsafe void SetBufferRaw(Entity entity, int componentTypeIndex, BufferHeader *tempBuffer, int sizeInChunk) { this.Entities.AssertEntityHasComponent(entity, componentTypeIndex); this.ComponentJobSafetyManager.CompleteReadAndWriteDependency(componentTypeIndex); byte *numPtr = ref this.Entities.GetComponentDataWithTypeRW(entity, componentTypeIndex, this.Entities.GlobalSystemVersion); BufferHeader.Destroy((BufferHeader *)numPtr); UnsafeUtility.MemCpy((void *)numPtr, (void *)tempBuffer, (long)sizeInChunk); }
public static void InstantiateEntities(Entity srcEntity, Entity *outputEntities, int instanceCount, EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore, EntityGroupManager entityGroupManager) { var linkedType = TypeManager.GetTypeIndex <LinkedEntityGroup>(); if (entityComponentStore->HasComponent(srcEntity, linkedType)) { var header = (BufferHeader *)entityComponentStore->GetComponentDataWithTypeRO(srcEntity, linkedType); var entityPtr = (Entity *)BufferHeader.GetElementPointer(header); var entityCount = header->Length; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (entityCount == 0 || entityPtr[0] != srcEntity) { throw new ArgumentException("LinkedEntityGroup[0] must always be the Entity itself."); } for (int i = 0; i < entityCount; i++) { if (!entityComponentStore->Exists(entityPtr[i])) { throw new ArgumentException( "The srcEntity's LinkedEntityGroup references an entity that is invalid. (Entity at index {i} on the LinkedEntityGroup.)"); } var archetype = entityComponentStore->GetArchetype(entityPtr[i]); if (archetype->InstantiableArchetype == null) { throw new ArgumentException( "The srcEntity's LinkedEntityGroup references an entity that has already been destroyed. (Entity at index {i} on the LinkedEntityGroup. Only system state components are left on the entity)"); } } #endif InstantiateEntitiesGroup(entityPtr, entityCount, outputEntities, instanceCount, entityComponentStore, managedComponentStore, entityGroupManager); } else { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!entityComponentStore->Exists(srcEntity)) { throw new ArgumentException("srcEntity is not a valid entity"); } var srcArchetype = entityComponentStore->GetArchetype(srcEntity); if (srcArchetype->InstantiableArchetype == null) { throw new ArgumentException( "srcEntity is not instantiable because it has already been destroyed. (Only system state components are left on it)"); } #endif InstantiateEntitiesOne(srcEntity, outputEntities, instanceCount, null, 0, entityComponentStore, managedComponentStore, entityGroupManager); } }
public void AddRange(NativeArray<T> newElems) { CheckWriteAccess(); int elemSize = UnsafeUtility.SizeOf<T>(); int oldLength = Length; ResizeUninitialized(oldLength + newElems.Length); byte* basePtr = BufferHeader.GetElementPointer(m_Buffer); UnsafeUtility.MemCpy(basePtr + oldLength * elemSize, newElems.GetUnsafeReadOnlyPtr<T>(), elemSize * newElems.Length); }
internal void *GetBufferRawRW(Entity entity, int typeIndex) { Entities->AssertEntityHasComponent(entity, typeIndex); ComponentJobSafetyManager.CompleteReadAndWriteDependency(typeIndex); BufferHeader *header = (BufferHeader *)Entities->GetComponentDataWithTypeRW(entity, typeIndex, Entities->GlobalSystemVersion); return(BufferHeader.GetElementPointer(header)); }
public void Insert(int index, T elem) { CheckWriteAccess(); int length = Length; ResizeUninitialized(length + 1); CheckBounds(index); //CheckBounds after ResizeUninitialized since index == length is allowed int elemSize = UnsafeUtility.SizeOf<T>(); byte* basePtr = BufferHeader.GetElementPointer(m_Buffer); UnsafeUtility.MemMove(basePtr + (index + 1) * elemSize, basePtr + index * elemSize, elemSize * (length - index)); this[index] = elem; }
/// <summary> /// Removes the specified number of elements, starting with the element at the specified index. /// </summary> /// <remarks>The buffer capacity remains unchanged.</remarks> /// <example> /// <code source="../../DocCodeSamples.Tests/DynamicBufferExamples.cs" language="csharp" region="dynamicbuffer.removerange"/> /// </example> /// <param name="index">The first element to remove.</param> /// <param name="count">How many elements tot remove.</param> public void RemoveRange(int index, int count) { CheckWriteAccess(); CheckBounds(index + count - 1); int elemSize = UnsafeUtility.SizeOf <T>(); byte *basePtr = BufferHeader.GetElementPointer(m_Buffer); UnsafeUtility.MemMove(basePtr + index * elemSize, basePtr + (index + count) * elemSize, (long)elemSize * (Length - count - index)); m_Buffer->Length -= count; }
public unsafe void RemoveRange(int index, int count) { this.CheckWriteAccess(); this.CheckBounds((index + count) - 1); int num = UnsafeUtility.SizeOf <T>(); byte *elementPointer = BufferHeader.GetElementPointer(this.m_Buffer); UnsafeUtility.MemMove((void *)(elementPointer + (index * num)), (void *)(elementPointer + ((index + count) * num)), (long)(num * ((this.Length - count) - index))); int *numPtr1 = (int *)ref this.m_Buffer.Length; numPtr1[0] -= count; }
static Chunk *CloneChunkWithoutAllocatingEntities(EntityManager dstEntityManager, Chunk *srcChunk, ManagedComponentStore srcManagedComponentStore) { var dstEntityComponentStore = dstEntityManager.EntityComponentStore; var dstManagedComponentStore = dstEntityManager.ManagedComponentStore; // Copy shared component data var dstSharedIndices = stackalloc int[srcChunk->Archetype->NumSharedComponents]; srcChunk->SharedComponentValues.CopyTo(dstSharedIndices, 0, srcChunk->Archetype->NumSharedComponents); dstManagedComponentStore.CopySharedComponents(srcManagedComponentStore, dstSharedIndices, srcChunk->Archetype->NumSharedComponents); // @TODO: Why don't we memcpy the whole chunk. So we include all extra fields??? // Allocate a new chunk var srcArchetype = srcChunk->Archetype; var dstArchetype = dstEntityComponentStore->GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount); var dstChunk = dstEntityComponentStore->GetCleanChunkNoMetaChunk(dstArchetype, dstSharedIndices); dstManagedComponentStore.Playback(ref dstEntityComponentStore->ManagedChangesTracker); dstChunk->metaChunkEntity = srcChunk->metaChunkEntity; // Release any references obtained by GetCleanChunk & CopySharedComponents for (var i = 0; i < srcChunk->Archetype->NumSharedComponents; i++) { dstManagedComponentStore.RemoveReference(dstSharedIndices[i]); } dstEntityComponentStore->SetChunkCountKeepMetaChunk(dstChunk, srcChunk->Count); dstManagedComponentStore.Playback(ref dstEntityComponentStore->ManagedChangesTracker); dstChunk->Archetype->EntityCount += srcChunk->Count; var copySize = Chunk.GetChunkBufferSize(); UnsafeUtility.MemCpy((byte *)dstChunk + Chunk.kBufferOffset, (byte *)srcChunk + Chunk.kBufferOffset, copySize); var numManagedComponents = dstChunk->Archetype->NumManagedComponents; for (int t = 0; t < numManagedComponents; ++t) { int type = t + dstChunk->Archetype->FirstManagedComponent; var offset = dstChunk->Archetype->Offsets[type]; var a = (int *)(dstChunk->Buffer + offset); dstManagedComponentStore.CloneManagedComponentsFromDifferentWorld(a, dstChunk->Count, srcManagedComponentStore, ref *dstEntityManager.EntityComponentStore); } BufferHeader.PatchAfterCloningChunk(dstChunk); dstChunk->SequenceNumber = srcChunk->SequenceNumber; return(dstChunk); }
internal void SetBufferRaw(Entity entity, int componentTypeIndex, BufferHeader *tempBuffer, int sizeInChunk) { Entities->AssertEntityHasComponent(entity, componentTypeIndex); ComponentJobSafetyManager.CompleteReadAndWriteDependency(componentTypeIndex); var ptr = Entities->GetComponentDataWithTypeRW(entity, componentTypeIndex, Entities->GlobalSystemVersion); BufferHeader.Destroy((BufferHeader *)ptr); UnsafeUtility.MemCpy(ptr, tempBuffer, sizeInChunk); }
void GatherBlobAssetsMemoryOrdered(Archetype *archetype, Chunk *chunk, int typeIndexInArchetype, int entityCount) { var componentTypeInArchetype = archetype->Types[typeIndexInArchetype]; if (componentTypeInArchetype.IsZeroSized || componentTypeInArchetype.IsSharedComponent) { return; } var typeInfo = TypeInfo[componentTypeInArchetype.TypeIndex & TypeManager.ClearFlagsMask]; var blobAssetRefCount = typeInfo.BlobAssetRefOffsetCount; if (blobAssetRefCount == 0) { return; } var blobAssetRefOffsets = BlobAssetRefOffsets + typeInfo.BlobAssetRefOffsetStartIndex; var chunkBuffer = chunk->Buffer; var subArrayOffset = archetype->Offsets[typeIndexInArchetype]; var componentArrayStart = chunkBuffer + subArrayOffset; if (componentTypeInArchetype.IsBuffer) { var header = (BufferHeader *)componentArrayStart; var strideSize = archetype->SizeOfs[typeIndexInArchetype]; var elementSize = typeInfo.ElementSize; for (var entityIndex = 0; entityIndex < entityCount; entityIndex++) { var bufferStart = BufferHeader.GetElementPointer(header); var bufferEnd = bufferStart + header->Length * elementSize; for (var componentData = bufferStart; componentData < bufferEnd; componentData += elementSize) { AddBlobAssets(componentData, blobAssetRefOffsets, blobAssetRefCount); } header = (BufferHeader *)(((byte *)header) + strideSize); } } else { var componentSize = archetype->SizeOfs[typeIndexInArchetype]; var end = componentArrayStart + componentSize * entityCount; for (var componentData = componentArrayStart; componentData < end; componentData += componentSize) { AddBlobAssets(componentData, blobAssetRefOffsets, blobAssetRefCount); } } }
public unsafe void Insert(int index, T elem) { this.CheckWriteAccess(); int length = this.Length; this.ResizeUninitialized(length + 1); this.CheckBounds(index); int num2 = UnsafeUtility.SizeOf <T>(); byte *elementPointer = BufferHeader.GetElementPointer(this.m_Buffer); UnsafeUtility.MemMove((void *)(elementPointer + ((index + 1) * num2)), (void *)(elementPointer + (index * num2)), (long)(num2 * (length - index))); this.set_Item(index, elem); }
internal void *GetBufferRawRO(Entity entity, int typeIndex) { var access = GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; ecs->AssertEntityHasComponent(entity, typeIndex); access->DependencyManager->CompleteReadAndWriteDependency(typeIndex); BufferHeader *header = (BufferHeader *)ecs->GetComponentDataWithTypeRO(entity, typeIndex); return(BufferHeader.GetElementPointer(header)); }