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 Archetype *GetArchetypeWithAddedComponentType(Archetype *archetype, ComponentType addedComponentType, EntityComponentStore *entityComponentStore, int *indexInTypeArray = null) { var componentType = new ComponentTypeInArchetype(addedComponentType); ComponentTypeInArchetype *newTypes = stackalloc ComponentTypeInArchetype[archetype->TypesCount + 1]; var t = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { newTypes[t] = archetype->Types[t]; ++t; } if (indexInTypeArray != null) { *indexInTypeArray = t; } if (archetype->Types[t] == componentType) { Assert.IsTrue(addedComponentType.IgnoreDuplicateAdd, $"{addedComponentType} is already part of the archetype."); // Tag component type is already there, no new archetype required. return(null); } newTypes[t] = componentType; while (t < archetype->TypesCount) { newTypes[t + 1] = archetype->Types[t]; ++t; } return(GetOrCreateArchetype(newTypes, archetype->TypesCount + 1, entityComponentStore)); }
public static Archetype *GetArchetypeWithRemovedComponentType(Archetype *archetype, ComponentType addedComponentType, EntityComponentStore *entityComponentStore, int *indexInOldTypeArray = null) { var componentType = new ComponentTypeInArchetype(addedComponentType); ComponentTypeInArchetype *newTypes = stackalloc ComponentTypeInArchetype[archetype->TypesCount]; var removedTypes = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { if (indexInOldTypeArray != null) { *indexInOldTypeArray = t; } ++removedTypes; } else { newTypes[t - removedTypes] = archetype->Types[t]; } } return(GetOrCreateArchetype(newTypes, archetype->TypesCount - removedTypes, entityComponentStore)); }
int PopulatedCachedTypeInArchetypeArray(ComponentType[] requiredComponents) { m_CachedComponentTypeInArchetypeArray[0] = new ComponentTypeInArchetype(ComponentType.Create <Entity>()); for (var i = 0; i < requiredComponents.Length; ++i) { SortingUtilities.InsertSorted(m_CachedComponentTypeInArchetypeArray, i + 1, requiredComponents[i]); } return(requiredComponents.Length + 1); }
private int PopulatedCachedTypeInArchetypeArray(ComponentType *requiredComponents, int count) { m_CachedComponentTypeInArchetypeArray[0] = new ComponentTypeInArchetype(ComponentType.Create <Entity>()); for (var i = 0; i < count; ++i) { SortingUtilities.InsertSorted(m_CachedComponentTypeInArchetypeArray, i + 1, requiredComponents[i]); } return(count + 1); }
public static unsafe void InsertSorted(ComponentTypeInArchetype *data, int length, ComponentType newValue) { var newVal = new ComponentTypeInArchetype(newValue); while (length > 0 && newVal < data[length - 1]) { data[length] = data[length - 1]; --length; } data[length] = newVal; }
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 EntityArchetype GetEntityOnlyArchetype() { if (!m_EntityOnlyArchetype.Valid) { ComponentTypeInArchetype entityType = new ComponentTypeInArchetype(ComponentType.ReadWrite <Entity>()); var archetype = EntityManagerCreateArchetypeUtility.GetOrCreateArchetype(&entityType, 1, EntityComponentStore, EntityGroupManager); m_EntityOnlyArchetype = new EntityArchetype { Archetype = archetype }; } return(m_EntityOnlyArchetype); }
public static unsafe void InsertSorted(ComponentTypeInArchetype *data, int length, ComponentType newValue) { ComponentTypeInArchetype archetype = new ComponentTypeInArchetype(newValue); while (true) { if ((length <= 0) || (archetype >= data[length - 1])) { data[length] = archetype; return; } data[length] = data[length - 1]; length--; } }
private int PopulatedCachedTypeInArchetypeArray(ComponentType *requiredComponents, int count) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (count + 1 > m_CachedComponentTypeInArchetypeArrayLength) { throw new System.ArgumentException($"Archetypes can't hold more than {m_CachedComponentTypeInArchetypeArrayLength}"); } #endif m_CachedComponentTypeInArchetypeArray[0] = new ComponentTypeInArchetype(ComponentType.Create <Entity>()); for (var i = 0; i < count; ++i) { SortingUtilities.InsertSorted(m_CachedComponentTypeInArchetypeArray, i + 1, requiredComponents[i]); } return(count + 1); }
public EntityArchetype GetEntityOnlyArchetype() { if (!m_EntityOnlyArchetype.Valid) { var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking(); ComponentTypeInArchetype entityType = new ComponentTypeInArchetype(ComponentType.ReadWrite <Entity>()); var archetype = EntityComponentStore->GetOrCreateArchetype(&entityType, 1); m_EntityOnlyArchetype = new EntityArchetype { Archetype = archetype }; var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges); EntityQueryManager.AddAdditionalArchetypes(changedArchetypes); } return(m_EntityOnlyArchetype); }
public void AddComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var t = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { componentTypeInArchetypeArray[t] = archetype->Types[t]; ++t; } var indexInTypeArray = t; componentTypeInArchetypeArray[t] = componentType; while (t < archetype->TypesCount) { componentTypeInArchetypeArray[t + 1] = archetype->Types[t]; ++t; } var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount + 1, groupManager); int *sharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; if ((newType->NumSharedComponents > 0) && (newType->NumSharedComponents != archetype->NumSharedComponents)) { var oldSharedComponentDataIndices = sharedComponentDataIndices; int *stackAlloced = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = stackAlloced; int indexOfNewSharedComponent = newType->SharedComponentOffset[indexInTypeArray]; UnsafeUtility.MemCpy(sharedComponentDataIndices, oldSharedComponentDataIndices, indexOfNewSharedComponent * sizeof(int)); sharedComponentDataIndices[indexOfNewSharedComponent] = 0; UnsafeUtility.MemCpy(sharedComponentDataIndices + indexOfNewSharedComponent + 1, oldSharedComponentDataIndices + indexOfNewSharedComponent, (archetype->NumSharedComponents - indexOfNewSharedComponent) * sizeof(int)); } SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); IncrementComponentOrderVersion(newType, GetComponentChunk(entity), sharedComponentDataManager); }
public void RemoveComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var removedTypes = 0; int indexInOldTypeArray = -1; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { indexInOldTypeArray = t; ++removedTypes; } else { componentTypeInArchetypeArray[t - removedTypes] = archetype->Types[t]; } } var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount - removedTypes, groupManager); int *sharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; if ((newType->NumSharedComponents > 0) && (newType->NumSharedComponents != archetype->NumSharedComponents)) { var oldSharedComponentDataIndices = sharedComponentDataIndices; int *tempAlloc = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = tempAlloc; int indexOfRemovedSharedComponent = archetype->SharedComponentOffset[indexInOldTypeArray]; UnsafeUtility.MemCpy(sharedComponentDataIndices, oldSharedComponentDataIndices, indexOfRemovedSharedComponent * sizeof(int)); UnsafeUtility.MemCpy(sharedComponentDataIndices + indexOfRemovedSharedComponent, oldSharedComponentDataIndices + indexOfRemovedSharedComponent + 1, (newType->NumSharedComponents - indexOfRemovedSharedComponent) * sizeof(int)); } IncrementComponentOrderVersion(archetype, GetComponentChunk(entity), sharedComponentDataManager); SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); }
public Archetype *GetExistingArchetype(ComponentTypeInArchetype *types, int count) { IntPtr typePtr; NativeMultiHashMapIterator <uint> it; if (!m_TypeLookup.TryGetFirstValue(GetHash(types, count), out typePtr, out it)) { return(null); } do { var type = (Archetype *)typePtr; if (ComponentTypeInArchetype.CompareArray(type->Types, type->TypesCount, types, count)) { return(type); } } while (m_TypeLookup.TryGetNextValue(out typePtr, ref it)); return(null); }
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); } }
// ---------------------------------------------------------------------------------------------------------- // PUBLIC // ---------------------------------------------------------------------------------------------------------- public static Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *inTypesSorted, int count, EntityComponentStore *entityComponentStore) { var srcArchetype = entityComponentStore->GetExistingArchetype(inTypesSorted, count); if (srcArchetype != null) { return(srcArchetype); } srcArchetype = entityComponentStore->CreateArchetype(inTypesSorted, count); var types = stackalloc ComponentTypeInArchetype[count + 1]; // Setup Instantiable archetype { UnsafeUtility.MemCpy(types, inTypesSorted, sizeof(ComponentTypeInArchetype) * count); var hasCleanup = false; var removedTypes = 0; var prefabTypeIndex = TypeManager.GetTypeIndex <Prefab>(); var cleanupTypeIndex = TypeManager.GetTypeIndex <CleanupEntity>(); for (var t = 0; t < srcArchetype->TypesCount; ++t) { var type = srcArchetype->Types[t]; hasCleanup |= type.TypeIndex == cleanupTypeIndex; var skip = type.IsSystemStateComponent || type.TypeIndex == prefabTypeIndex; if (skip) { ++removedTypes; } else { types[t - removedTypes] = srcArchetype->Types[t]; } } // Entity has already been destroyed, so it shouldn't be instantiated anymore if (hasCleanup) { srcArchetype->InstantiableArchetype = null; } else if (removedTypes > 0) { var instantiableArchetype = GetOrCreateArchetype(types, count - removedTypes, entityComponentStore); srcArchetype->InstantiableArchetype = instantiableArchetype; Assert.IsTrue(instantiableArchetype->InstantiableArchetype == instantiableArchetype); Assert.IsTrue(instantiableArchetype->SystemStateResidueArchetype == null); } else { srcArchetype->InstantiableArchetype = srcArchetype; } } // Setup System state cleanup archetype if (srcArchetype->SystemStateCleanupNeeded) { var cleanupEntityType = new ComponentTypeInArchetype(ComponentType.ReadWrite <CleanupEntity>()); bool cleanupAdded = false; types[0] = inTypesSorted[0]; var newTypeCount = 1; for (var t = 1; t < srcArchetype->TypesCount; ++t) { var type = srcArchetype->Types[t]; if (type.IsSystemStateComponent) { if (!cleanupAdded && (cleanupEntityType < srcArchetype->Types[t])) { types[newTypeCount++] = cleanupEntityType; cleanupAdded = true; } types[newTypeCount++] = srcArchetype->Types[t]; } } if (!cleanupAdded) { types[newTypeCount++] = cleanupEntityType; } var systemStateResidueArchetype = GetOrCreateArchetype(types, newTypeCount, entityComponentStore); srcArchetype->SystemStateResidueArchetype = systemStateResidueArchetype; Assert.IsTrue(systemStateResidueArchetype->SystemStateResidueArchetype == systemStateResidueArchetype); Assert.IsTrue(systemStateResidueArchetype->InstantiableArchetype == null); } // Setup meta chunk archetype if (count > 1) { types[0] = new ComponentTypeInArchetype(typeof(Entity)); int metaArchetypeTypeCount = 1; for (int i = 1; i < count; ++i) { var t = inTypesSorted[i]; ComponentType typeToInsert; if (inTypesSorted[i].IsChunkComponent) { typeToInsert = new ComponentType { TypeIndex = TypeManager.ChunkComponentToNormalTypeIndex(t.TypeIndex) }; SortingUtilities.InsertSorted(types, metaArchetypeTypeCount++, typeToInsert); } } if (metaArchetypeTypeCount > 1) { SortingUtilities.InsertSorted(types, metaArchetypeTypeCount++, new ComponentType(typeof(ChunkHeader))); srcArchetype->MetaChunkArchetype = GetOrCreateArchetype(types, metaArchetypeTypeCount, entityComponentStore); } } return(srcArchetype); }
// ---------------------------------------------------------------------------------------------------------- // PUBLIC // ---------------------------------------------------------------------------------------------------------- public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *inTypesSorted, int count) { var srcArchetype = GetExistingArchetype(inTypesSorted, count); if (srcArchetype != null) { return(srcArchetype); } srcArchetype = CreateArchetype(inTypesSorted, count); var types = stackalloc ComponentTypeInArchetype[count + 1]; srcArchetype->InstantiateArchetype = CreateInstanceArchetype(inTypesSorted, count, types, srcArchetype, true); srcArchetype->CopyArchetype = CreateInstanceArchetype(inTypesSorted, count, types, srcArchetype, false); if (srcArchetype->InstantiateArchetype != null) { Assert.IsTrue(srcArchetype->InstantiateArchetype->InstantiateArchetype == srcArchetype->InstantiateArchetype); Assert.IsTrue(srcArchetype->InstantiateArchetype->SystemStateResidueArchetype == null); } if (srcArchetype->CopyArchetype != null) { Assert.IsTrue(srcArchetype->CopyArchetype->CopyArchetype == srcArchetype->CopyArchetype); Assert.IsTrue(srcArchetype->CopyArchetype->SystemStateResidueArchetype == null); } // Setup System state cleanup archetype if (srcArchetype->SystemStateCleanupNeeded) { var cleanupEntityType = new ComponentTypeInArchetype(ComponentType.FromTypeIndex(m_CleanupEntityType)); bool cleanupAdded = false; types[0] = inTypesSorted[0]; var newTypeCount = 1; for (var t = 1; t < srcArchetype->TypesCount; ++t) { var type = srcArchetype->Types[t]; if (type.IsSystemStateComponent) { if (!cleanupAdded && (cleanupEntityType < srcArchetype->Types[t])) { types[newTypeCount++] = cleanupEntityType; cleanupAdded = true; } types[newTypeCount++] = srcArchetype->Types[t]; } } if (!cleanupAdded) { types[newTypeCount++] = cleanupEntityType; } var systemStateResidueArchetype = GetOrCreateArchetype(types, newTypeCount); srcArchetype->SystemStateResidueArchetype = systemStateResidueArchetype; Assert.IsTrue(systemStateResidueArchetype->SystemStateResidueArchetype == systemStateResidueArchetype); Assert.IsTrue(systemStateResidueArchetype->InstantiateArchetype == null); Assert.IsTrue(systemStateResidueArchetype->CopyArchetype == null); } // Setup meta chunk archetype if (count > 1) { types[0] = new ComponentTypeInArchetype(m_EntityComponentType); int metaArchetypeTypeCount = 1; for (int i = 1; i < count; ++i) { var t = inTypesSorted[i]; ComponentType typeToInsert; if (inTypesSorted[i].IsChunkComponent) { typeToInsert = new ComponentType { TypeIndex = ChunkComponentToNormalTypeIndex(t.TypeIndex) }; SortingUtilities.InsertSorted(types, metaArchetypeTypeCount++, typeToInsert); } } if (metaArchetypeTypeCount > 1) { SortingUtilities.InsertSorted(types, metaArchetypeTypeCount++, m_ChunkHeaderComponentType); srcArchetype->MetaChunkArchetype = GetOrCreateArchetype(types, metaArchetypeTypeCount); } } return(srcArchetype); }
public void RemoveComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var removedTypes = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { ++removedTypes; } else { componentTypeInArchetypeArray[t - removedTypes] = archetype->Types[t]; } } Assert.AreNotEqual(-1, removedTypes); var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount - removedTypes, groupManager); int *sharedComponentDataIndices = null; if (newType->NumSharedComponents > 0) { var oldSharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; var removedComponentIsShared = TypeManager.TypeCategory.ISharedComponentData == TypeManager.GetComponentType(type.TypeIndex).Category; removedTypes = 0; if (removedComponentIsShared) { int *tempAlloc = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = tempAlloc; int srcIndex = 0; int dstIndex = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->SharedComponentOffset[t] != -1) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { srcIndex++; } else { sharedComponentDataIndices[dstIndex] = oldSharedComponentDataIndices[srcIndex]; srcIndex++; dstIndex++; } } } } else { // reuse old sharedComponentDataIndices sharedComponentDataIndices = oldSharedComponentDataIndices; } } IncrementComponentOrderVersion(archetype, GetComponentChunk(entity), sharedComponentDataManager); SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); }
public void AddComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var t = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { componentTypeInArchetypeArray[t] = archetype->Types[t]; ++t; } componentTypeInArchetypeArray[t] = componentType; while (t < archetype->TypesCount) { componentTypeInArchetypeArray[t + 1] = archetype->Types[t]; ++t; } var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount + 1, groupManager); int *sharedComponentDataIndices = null; if (newType->NumSharedComponents > 0) { var oldSharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; var newComponentIsShared = (TypeManager.TypeCategory.ISharedComponentData == TypeManager.GetComponentType(type.TypeIndex).Category); if (newComponentIsShared) { int *stackAlloced = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = stackAlloced; if (archetype->SharedComponentOffset == null) { sharedComponentDataIndices[0] = 0; } else { t = 0; var sharedIndex = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { if (archetype->SharedComponentOffset[t] != -1) { sharedComponentDataIndices[sharedIndex] = oldSharedComponentDataIndices[sharedIndex]; ++sharedIndex; } ++t; } sharedComponentDataIndices[sharedIndex] = 0; while (t < archetype->TypesCount) { if (archetype->SharedComponentOffset[t] != -1) { sharedComponentDataIndices[sharedIndex + 1] = oldSharedComponentDataIndices[sharedIndex]; ++sharedIndex; } ++t; } } } else { // reuse old sharedComponentDataIndices sharedComponentDataIndices = oldSharedComponentDataIndices; } } SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); IncrementComponentOrderVersion(newType, GetComponentChunk(entity), sharedComponentDataManager); }
public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager) { var srcArchetype = GetExistingArchetype(types, count); if (srcArchetype != null) { return(srcArchetype); } srcArchetype = CreateArchetypeInternal(types, count, groupManager); var removedTypes = 0; var prefabTypeIndex = TypeManager.GetTypeIndex <Prefab>(); for (var t = 0; t < srcArchetype->TypesCount; ++t) { var type = srcArchetype->Types[t]; var skip = type.IsSystemStateComponent || type.IsSystemStateSharedComponent || (type.TypeIndex == prefabTypeIndex); if (skip) { ++removedTypes; } else { types[t - removedTypes] = srcArchetype->Types[t]; } } srcArchetype->InstantiableArchetype = srcArchetype; if (removedTypes > 0) { var instantiableArchetype = GetOrCreateArchetypeInternal(types, count - removedTypes, groupManager); srcArchetype->InstantiableArchetype = instantiableArchetype; instantiableArchetype->InstantiableArchetype = instantiableArchetype; instantiableArchetype->SystemStateResidueArchetype = null; } if (!srcArchetype->SystemStateCleanupNeeded) { return(srcArchetype); } var cleanupEntityType = new ComponentTypeInArchetype(ComponentType.Create <CleanupEntity>()); bool cleanupAdded = false; var newTypeCount = 1; for (var t = 1; t < srcArchetype->TypesCount; ++t) { var type = srcArchetype->Types[t]; if (type.IsSystemStateComponent || type.IsSystemStateSharedComponent) { if (!cleanupAdded && (cleanupEntityType < srcArchetype->Types[t])) { types[newTypeCount++] = cleanupEntityType; cleanupAdded = true; } types[newTypeCount++] = srcArchetype->Types[t]; } } if (!cleanupAdded) { types[newTypeCount++] = cleanupEntityType; } var systemStateResidueArchetype = GetOrCreateArchetype(types, newTypeCount, groupManager); systemStateResidueArchetype->SystemStateResidueArchetype = systemStateResidueArchetype; systemStateResidueArchetype->InstantiableArchetype = GetEntityOnlyArchetype(types, groupManager); srcArchetype->SystemStateResidueArchetype = systemStateResidueArchetype; return(srcArchetype); }
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); } } }
public void TryRemoveEntityId(Entity *entities, int count, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var entityIndex = 0; while (entityIndex != count) { int indexInChunk; int batchCount; fixed(EntityDataManager *manager = &this) { var chunk = EntityChunkBatch(manager, entities + entityIndex, count - entityIndex, out indexInChunk, out batchCount); var archetype = GetArchetype(entities[entityIndex]); if (!archetype->SystemStateCleanupNeeded) { DeallocateDataEntitiesInChunk(manager, entities + entityIndex, chunk, indexInChunk, batchCount); IncrementComponentOrderVersion(chunk->Archetype, chunk, sharedComponentDataManager); if (chunk->ManagedArrayIndex >= 0) { // We can just chop-off the end, no need to copy anything if (chunk->Count != indexInChunk + batchCount) { ChunkDataUtility.CopyManagedObjects(archetypeManager, chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount); } ChunkDataUtility.ClearManagedObjects(archetypeManager, chunk, chunk->Count - batchCount, batchCount); } chunk->Archetype->EntityCount -= batchCount; archetypeManager.SetChunkCount(chunk, chunk->Count - batchCount); } else { for (var batchEntityIndex = 0; batchEntityIndex < batchCount; batchEntityIndex++) { var entity = entities[entityIndex + batchEntityIndex]; var removedTypes = 0; var removedComponentIsShared = false; for (var t = 1; t < archetype->TypesCount; ++t) { var type = archetype->Types[t]; if (!(type.IsSystemStateComponent || type.IsSystemStateSharedComponent)) { ++removedTypes; removedComponentIsShared |= type.IsSharedComponent; } else { componentTypeInArchetypeArray[t - removedTypes] = archetype->Types[t]; } } componentTypeInArchetypeArray[archetype->TypesCount - removedTypes] = new ComponentTypeInArchetype(ComponentType.Create <CleanupEntity>()); var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount - removedTypes + 1, groupManager); int *sharedComponentDataIndices = null; if (newType->NumSharedComponents > 0) { var oldSharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; if (removedComponentIsShared) { int *tempAlloc = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = tempAlloc; var srcIndex = 0; var dstIndex = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->SharedComponentOffset[t] != -1) { var typeIndex = archetype->Types[t].TypeIndex; var systemStateType = typeof(ISystemStateComponentData).IsAssignableFrom(TypeManager.GetType(typeIndex)); var systemStateSharedType = typeof(ISystemStateSharedComponentData).IsAssignableFrom(TypeManager.GetType(typeIndex)); if (!(systemStateType || systemStateSharedType)) { srcIndex++; } else { sharedComponentDataIndices[dstIndex] = oldSharedComponentDataIndices[srcIndex]; srcIndex++; dstIndex++; } } } } else { // reuse old sharedComponentDataIndices sharedComponentDataIndices = oldSharedComponentDataIndices; } } IncrementComponentOrderVersion(archetype, GetComponentChunk(entity), sharedComponentDataManager); SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); } } } entityIndex += batchCount; } }