package ecs import "core:log" ComponentManager :: struct { component_types: map[typeid]ComponentType, component_pools: map[typeid]^ComponentPool(any), destroy_procs: map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID), next_component_type: ComponentType, } component_manager_create :: proc() -> ComponentManager { component_manager := ComponentManager { component_types = make(map[typeid]ComponentType, context.allocator), component_pools = make(map[typeid]^ComponentPool(any), context.allocator), next_component_type = 0 } return component_manager } component_manager_register_component :: proc($T: typeid, component_manager: ^ComponentManager) { log.assertf(T not_in component_manager.component_types, "Registering component more than once") component_manager.component_types[T] = component_manager.next_component_type component_pool := new(ComponentPool(T), context.allocator) component_pool^ = component_pool_create(T) component_manager.component_pools[T] = cast(^ComponentPool(any))component_pool component_manager.destroy_procs[T] = proc(component_pool: ^ComponentPool(any), id: EntityID) { typed_component_pool := cast(^ComponentPool(T))component_pool if id in typed_component_pool.entity_to_index { component_pool_remove_data(typed_component_pool, id) } } component_manager.next_component_type += 1 } component_manager_get_component_type :: proc($T: typeid, component_manager: ^ComponentManager) -> ComponentType { log.assertf(T in component_manager.component_types, "Component not registered before use") return component_manager.component_types[T] } component_manager_add_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID, component: T) { component_pool := cast(^ComponentPool(T))component_manager.component_pools[T] component_pool_insert_data(component_pool, entity_id, component) } component_manager_remove_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) { component_pool := cast(^ComponentPool(T))component_manager.component_pools[T] component_pool_remove_data(component_pool, entity_id) } component_manager_get_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) -> ^T { component_pool := cast(^ComponentPool(T)) component_manager.component_pools[T] return component_pool_get(component_pool, entity_id) } component_manager_destroy_entity :: proc(component_manager: ^ComponentManager, entity_id: EntityID) { for T, component_pool in component_manager.component_pools { component_manager.destroy_procs[T](component_pool, entity_id) } } component_manager_destroy :: proc(component_manager: ^ComponentManager) { for _, &component_pool in component_manager.component_pools { component_pool_destroy(component_pool) free(component_pool) } delete(component_manager.component_pools) delete(component_manager.component_types) }