#include #include #include #include #include #include #include #include EntityID EntityManager::ID = 0; void InitEntityManager(NonNullPtr world) { EntityManager* newManager = ArenaPushStruct(world->WorldArena); world->EntityManager = newManager; newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities")); ArenaParams by_type_params{ .ReserveSize = Kilobytes(1), .CommitSize = Kilobytes(1), .Name = "" JULIET_DEBUG_ONLY(, .CanReserveMore = false) }; for (uint8 i = 0; i < ENTITY(Count); ++i) { by_type_params.Name = kEntity_type_names[i]; newManager->by_type[i].arena = ArenaAllocate(by_type_params); newManager->by_type[i].array = nullptr; } } void ShutdownEntityManager() { auto& manager = GetEntityManager(); for (typed_entity_array& type : manager.by_type) { ArenaRelease(type.arena); } manager.Entities.Destroy(); } EntityManager& GetEntityManager() { NonNullPtr entityManager = GetGameState()->World->EntityManager; return *entityManager; } EntityTemplate* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity) { base->ID = EntityManager::ID++; base->derived = entity; manager.Entities.PushBack(*base); auto* ptr = (EntityTemplate*)ArenaPushSize(manager.by_type[base->derived_kind->kind].arena, base->derived_kind->size_of, base->derived_kind->alignment, false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind])); MemCopy(ptr, entity, base->derived_kind->size_of); manager.by_type[base->derived_kind->kind].count += 1; ptr->base = manager.Entities.Back(); if (manager.by_type[base->derived_kind->kind].array == nullptr) { manager.by_type[base->derived_kind->kind].array = ptr; } return ptr; } Entity* allocate_entity(EntityManager& manager, NonNullPtr derived_type_class) { Assert(derived_type_class->kind < ENTITY(Count)); Assert(derived_type_class->size_of >= sizeof(EntityTemplate)); Assert(derived_type_class->alignment > 0); Assert(derived_type_class->initialize_fct); Entity base_template = {}; base_template.derived_kind = derived_type_class; base_template.is_dirty = true; manager.Entities.PushBack(base_template); Entity* base_ptr = manager.Entities.Back(); Assert(base_ptr); typed_entity_array& typed_array = manager.by_type[derived_type_class->kind]; Assert(typed_array.arena); void* derived = ArenaPushSize(typed_array.arena, derived_type_class->size_of, derived_type_class->alignment, false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind])); Assert(derived); derived_type_class->initialize_fct(derived); auto* derived_template = (EntityTemplate*)derived; base_ptr->derived = derived; derived_template->base = base_ptr; if (typed_array.array == nullptr) { typed_array.array = derived_template; } typed_array.count += 1; return base_ptr; } void UpdateEntityManager(EntityManager& manager) { // Todo : inert by definition dont move, but this is for test auto& by_type = manager.by_type[ENTITY(Inert)]; for (index_t i = 0; i < by_type.count; ++i) { Inert* inert = reinterpret_cast(by_type.array) + i; if (inert->MeshInstance != indexMax) { SetMeshInstanceTransform(inert->MeshInstance, MatrixTranslation(inert->base->position.x, inert->base->position.y, inert->base->position.z)); } } } Entity* deserialize_entity(Archive& ar, EntityManager& manager) { Assert(ar.loading); String class_name; SERIALIZE(ar, Class, class_name); NonNullPtr class_ptr = find_class_by_name(class_name); NonNullPtr entity_base = allocate_entity(manager, class_ptr); serialize(ar, entity_base); if (entity_base->ID >= EntityManager::ID) { EntityManager::ID = entity_base->ID + 1; } entity_base->is_dirty = false; return entity_base; }