//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; }
/// <summary> /// Copies all the elements from an array. /// </summary> /// <example> /// <code source="../../DocCodeSamples.Tests/DynamicBufferExamples.cs" language="csharp" region="dynamicbuffer.copyfrom.array"/> /// </example> /// <param name="v">A C# array containing the elements to copy.</param> /// <exception cref="ArgumentNullException"></exception> public void CopyFrom(T[] v) { if (v == null) { throw new ArgumentNullException(nameof(v)); } #if NET_DOTS Clear(); foreach (var d in v) { Add(d); } #else ResizeUninitialized(v.Length); CheckWriteAccess(); GCHandle gcHandle = GCHandle.Alloc((object)v, GCHandleType.Pinned); IntPtr num = gcHandle.AddrOfPinnedObject(); UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(m_Buffer), (void *)num, Length * UnsafeUtility.SizeOf <T>()); gcHandle.Free(); #endif }
void AddToDestroyList(Chunk *chunk, int indexInChunk, int batchCount, int inputDestroyCount, ref UnsafeList entitiesList, ref int minBufferLength, ref int maxBufferLength) { int indexInArchetype = ChunkDataUtility.GetIndexInTypeArray(chunk->Archetype, m_LinkedGroupType); if (indexInArchetype != -1) { var baseHeader = ChunkDataUtility.GetComponentDataWithTypeRO(chunk, indexInChunk, m_LinkedGroupType); var stride = chunk->Archetype->SizeOfs[indexInArchetype]; for (int i = 0; i != batchCount; i++) { var header = (BufferHeader *)(baseHeader + stride * i); var entityGroupCount = header->Length - 1; if (entityGroupCount <= 0) { continue; } var entityGroupArray = (Entity *)BufferHeader.GetElementPointer(header) + 1; if (entitiesList.Capacity == 0) { entitiesList.SetCapacity <Entity>(inputDestroyCount * entityGroupCount /*, Allocator.TempJob*/); } entitiesList.AddRange <Entity>(entityGroupArray, entityGroupCount /*, Allocator.TempJob*/); minBufferLength = math.min(minBufferLength, entityGroupCount); maxBufferLength = math.max(maxBufferLength, entityGroupCount); } } }
public TElement this[int index] { get { CheckBounds(index); return(UnsafeUtility.ReadArrayElement <TElement>(BufferHeader.GetElementPointer(m_Buffer), index)); } set { // @FIXME // // In C# despite being `readonly` a list can have it's elements mutated, however for ECS data we have strict access writes. // For now we opt to silently skip until a proper fix is implemented. // // In order to properly fix this we need either: // // 1) A custom property bag for DynamicBufferContainer`1 which correctly sets IsReadOnly per element property. // * While this is a more elegant solution we lose the built in machinery around ListPropertyBag`1. e.g. UI would not be quite right. // // 2) A fix directly in ListPropertyBag`1 to allow controlling IsReadOnly per element. // * This is a best place to fix it but requires a package update of properties. // if (!m_IsReadOnly) { CheckBounds(index); UnsafeUtility.WriteArrayElement(BufferHeader.GetElementPointer(m_Buffer), index, value); } } }
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; } } } }
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 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 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 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); } }
internal void *GetBufferRawRO(Entity entity, int typeIndex) { EntityComponentStore->AssertEntityHasComponent(entity, typeIndex); ComponentJobSafetyManager->CompleteReadAndWriteDependency(typeIndex); BufferHeader *header = (BufferHeader *)EntityComponentStore->GetComponentDataWithTypeRO(entity, typeIndex); return(BufferHeader.GetElementPointer(header)); }
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); }
/// <summary> /// Copies all the elements from another dynamic buffer. /// </summary> /// <example> /// <code source="../../DocCodeSamples.Tests/DynamicBufferExamples.cs" language="csharp" region="dynamicbuffer.copyfrom.dynamicbuffer"/> /// </example> /// <param name="v">The dynamic buffer containing the elements to copy.</param> public void CopyFrom(DynamicBuffer <T> v) { ResizeUninitialized(v.Length); v.CheckReadAccess(); CheckWriteAccess(); UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(m_Buffer), BufferHeader.GetElementPointer(v.m_Buffer), Length * UnsafeUtility.SizeOf <T>()); }
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; }
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; }
/// <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; }
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); } } }
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)); }
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); }
public static unsafe void ReplicateComponents(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstBaseIndex, int count) { Archetype *archetypePtr = srcChunk.Archetype; byte * numPtr = &srcChunk.Buffer.FixedElementField; byte * numPtr2 = &dstChunk.Buffer.FixedElementField; Archetype *archetypePtr2 = dstChunk.Archetype; int * offsets = archetypePtr->Offsets; int * sizeOfs = archetypePtr->SizeOfs; int typesCount = archetypePtr->TypesCount; ComponentTypeInArchetype *types = archetypePtr->Types; ComponentTypeInArchetype *archetypePtr4 = archetypePtr2->Types; int *numPtr5 = archetypePtr2->Offsets; int index = 1; for (int i = 1; i != typesCount; i++) { ComponentTypeInArchetype archetype = types[i]; ComponentTypeInArchetype archetype2 = archetypePtr4[index]; if (archetype.TypeIndex == archetype2.TypeIndex) { int size = sizeOfs[i]; byte *numPtr6 = numPtr + (offsets[i] + (size * srcIndex)); byte *numPtr7 = numPtr2 + (numPtr5[index] + (size * dstBaseIndex)); if (!archetype.IsBuffer) { UnsafeUtility.MemCpyReplicate((void *)numPtr7, (void *)numPtr6, size, count); } else { int alignment = 8; int elementSize = TypeManager.GetTypeInfo(archetype.TypeIndex).ElementSize; int num9 = 0; while (true) { if (num9 >= count) { break; } BufferHeader *header = (BufferHeader *)numPtr6; BufferHeader *headerPtr2 = (BufferHeader *)numPtr7; BufferHeader.Initialize(headerPtr2, archetype.BufferCapacity); BufferHeader.Assign(headerPtr2, BufferHeader.GetElementPointer(header), header->Length, elementSize, alignment); numPtr7 += size; num9++; } } index++; } } }
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); } } }
/// <summary> /// Array-like indexing operator. /// </summary> /// <example> /// <code source="../../DocCodeSamples.Tests/DynamicBufferExamples.cs" language="csharp" region="dynamicbuffer.indexoperator"/> /// </example> /// <param name="index">The zero-based index.</param> public T this [int index] { get { CheckReadAccess(); CheckBounds(index); return(UnsafeUtility.ReadArrayElement <T>(BufferHeader.GetElementPointer(m_Buffer), index)); } set { CheckWriteAccess(); CheckBounds(index); UnsafeUtility.WriteArrayElement <T>(BufferHeader.GetElementPointer(m_Buffer), index, value); } }
public void InstantiateEntities(Entity srcEntity, Entity *outputEntities, int instanceCount) { if (HasComponent(srcEntity, m_LinkedGroupType)) { var header = (BufferHeader *)GetComponentDataWithTypeRO(srcEntity, m_LinkedGroupType); var entityPtr = (Entity *)BufferHeader.GetElementPointer(header); var entityCount = header->Length; InstantiateEntitiesGroup(entityPtr, entityCount, outputEntities, true, instanceCount, true); } else { InstantiateEntitiesOne(srcEntity, outputEntities, instanceCount, null, 0, true); } }
public void Execute(int index) { var chunk = Chunks[index].m_Chunk; var archetype = chunk->Archetype; var typesCount = archetype->TypesCount; var entityCount = Chunks[index].Count; for (var typeIndexInArchetype = 1; typeIndexInArchetype < typesCount; typeIndexInArchetype++) { var componentTypeInArchetype = archetype->Types[typeIndexInArchetype]; if (!componentTypeInArchetype.HasEntityReferences || componentTypeInArchetype.IsSharedComponent || componentTypeInArchetype.IsZeroSized) { continue; } var typeInfo = TypeInfo[componentTypeInArchetype.TypeIndex & TypeManager.ClearFlagsMask]; var typeInChunkPtr = GetChunkBuffer(chunk) + archetype->Offsets[typeIndexInArchetype]; var typeSizeOf = archetype->SizeOfs[typeIndexInArchetype]; var changed = false; if (componentTypeInArchetype.IsBuffer) { for (var entityIndexInChunk = 0; entityIndexInChunk < entityCount; entityIndexInChunk++) { var componentDataPtr = typeInChunkPtr + typeSizeOf * entityIndexInChunk; var bufferHeader = (BufferHeader *)componentDataPtr; var bufferLength = bufferHeader->Length; var bufferPtr = BufferHeader.GetElementPointer(bufferHeader); changed |= ClearEntityReferences(typeInfo, bufferPtr, bufferLength); } } else { for (var entityIndexInChunk = 0; entityIndexInChunk < entityCount; entityIndexInChunk++) { var componentDataPtr = typeInChunkPtr + typeSizeOf * entityIndexInChunk; changed |= ClearEntityReferences(typeInfo, componentDataPtr, 1); } } if (changed) { chunk->SetChangeVersion(typeIndexInArchetype, GlobalSystemVersion); } } }
public void AssertCanInstantiateEntities(Entity srcEntity, Entity *outputEntities, int instanceCount) { if (HasComponent(srcEntity, m_LinkedGroupType)) { var header = (BufferHeader *)GetComponentDataWithTypeRO(srcEntity, m_LinkedGroupType); var entityPtr = (Entity *)BufferHeader.GetElementPointer(header); var entityCount = header->Length; 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 (!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 = 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)"); } } } else { if (!Exists(srcEntity)) { throw new ArgumentException("srcEntity is not a valid entity"); } var srcArchetype = 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)"); } } }
public static void ReplicateComponents(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstBaseIndex, int count) { Assert.IsTrue(srcChunk->Archetype == dstChunk->Archetype); var arch = srcChunk->Archetype; var srcBuffer = srcChunk->Buffer; var dstBuffer = dstChunk->Buffer; var offsets = arch->Offsets; var sizeOfs = arch->SizeOfs; var typesCount = arch->TypesCount; var types = arch->Types; // type[0] is always Entity, and will be patched up later, so just skip for (var t = 1; t != typesCount; t++) { var type = types[t]; var offset = offsets[t]; var sizeOf = sizeOfs[t]; var src = srcBuffer + (offset + sizeOf * srcIndex); var dst = dstBuffer + (offset + sizeOf * dstBaseIndex); if (!type.IsBuffer) { UnsafeUtility.MemCpyReplicate(dst, src, sizeOf, count); } else { var alignment = 8; // TODO: Need a way to compute proper alignment for arbitrary non-generic types in TypeManager for (int i = 0; i < count; ++i) { BufferHeader *srcHdr = (BufferHeader *)src; BufferHeader *dstHdr = (BufferHeader *)dst; BufferHeader.Initialize(dstHdr, type.BufferCapacity); BufferHeader.Assign(dstHdr, BufferHeader.GetElementPointer(srcHdr), srcHdr->Length, sizeOf, alignment); src += sizeOf; dst += sizeOf; } } } }
unsafe object GetObject(void *pointer, Type type) { if (typeof(IBufferElementData).IsAssignableFrom(type)) { var listType = typeof(List <>); var constructedListType = listType.MakeGenericType(type); var instance = (IList)Activator.CreateInstance(constructedListType); var size = Marshal.SizeOf(type); BufferHeader *header = (BufferHeader *)pointer; var begin = BufferHeader.GetElementPointer(header); for (var i = 0; i < header->Length; ++i) { var item = begin + (size * i); instance.Add(Marshal.PtrToStructure((IntPtr)item, type)); } return(instance); } else { return(Marshal.PtrToStructure((IntPtr)pointer, type)); } }
public static void PatchEntities(EntityPatchInfo *scalarPatches, int scalarPatchCount, BufferEntityPatchInfo *bufferPatches, int bufferPatchCount, byte *chunkBuffer, int entityCount, ref NativeArray <EntityRemapInfo> remapping) { // Patch scalars (single components) with entity references. for (int p = 0; p < scalarPatchCount; p++) { byte *entityData = chunkBuffer + scalarPatches[p].Offset; for (int i = 0; i != entityCount; i++) { Entity *entity = (Entity *)entityData; * entity = RemapEntity(ref remapping, *entity); entityData += scalarPatches[p].Stride; } } // Patch buffers that contain entity references for (int p = 0; p < bufferPatchCount; ++p) { byte *bufferData = chunkBuffer + bufferPatches[p].BufferOffset; for (int i = 0; i != entityCount; ++i) { BufferHeader *header = (BufferHeader *)bufferData; byte *elemsBase = BufferHeader.GetElementPointer(header) + bufferPatches[p].ElementOffset; int elemCount = header->Length; for (int k = 0; k != elemCount; ++k) { Entity *entityPtr = (Entity *)elemsBase; * entityPtr = RemapEntity(ref remapping, *entityPtr); elemsBase += bufferPatches[p].ElementStride; } bufferData += bufferPatches[p].BufferStride; } } }
/// <summary> /// Return a native array that aliases the original buffer contents. /// </summary> /// <remarks>You can only access the native array as long as the /// the buffer memory has not been reallocated. Several dynamic buffer operations, /// such as <see cref="Add"/> and <see cref="TrimExcess"/> can result in /// buffer reallocation.</remarks> /// <example> /// <code source="../../DocCodeSamples.Tests/DynamicBufferExamples.cs" language="csharp" region="dynamicbuffer.asnativearray"/> /// </example> public NativeArray <T> AsNativeArray() { CheckReadAccess(); var shadow = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <T>(BufferHeader.GetElementPointer(m_Buffer), Length, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var handle = m_Safety1; AtomicSafetyHandle.UseSecondaryVersion(ref handle); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref shadow, handle); #endif return(shadow); }
/// <summary> /// Gets an <see langword="unsafe"/> pointer to the contents of the buffer. /// </summary> /// <remarks>This function can only be called in unsafe code contexts.</remarks> /// <returns>A typed, unsafe pointer to the first element in the buffer.</returns> public void *GetUnsafePtr() { CheckWriteAccess(); return(BufferHeader.GetElementPointer(m_Buffer)); }