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