#+private package ecs import "core:log" ComponentManager :: struct { component_ids: map[typeid]ComponentID, component_pools: map[typeid]^ComponentPool(any), next_component_id: ComponentID, component_pool_destroy_entity_cbs: map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID), component_pool_delete_cbs: map[typeid]proc(pool: ^ComponentPool(any)), } component_manager_init :: proc(component_manager: ^ComponentManager) { component_manager.component_ids = make(map[typeid]ComponentID, context.allocator) component_manager.component_pools = make(map[typeid]^ComponentPool(any), context.allocator) component_manager.component_pool_destroy_entity_cbs = make(map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID), context.allocator) component_manager.component_pool_delete_cbs = make(map[typeid]proc(pool: ^ComponentPool(any)), context.allocator) component_manager.next_component_id = 0 } component_manager_register_component :: proc($Component: typeid, component_manager: ^ComponentManager) { log.assertf(Component not_in component_manager.component_ids, "Registering component more than once") component_manager.component_ids[Component] = component_manager.next_component_id component_pool := new(ComponentPool(Component), context.allocator) component_pool_init(component_pool) component_manager.component_pools[Component] = cast(^ComponentPool(any))component_pool component_manager.component_pool_destroy_entity_cbs[Component] = proc(any_component_pool: ^ComponentPool(any), entity_id: EntityID) { typed_component_pool := cast(^ComponentPool(Component))any_component_pool if entity_id in typed_component_pool.entity_to_index { component_pool_remove_data(typed_component_pool, entity_id) } } component_manager.component_pool_delete_cbs[Component] = proc(any_component_pool: ^ComponentPool(any)) { typed_component_pool := cast(^ComponentPool(Component))any_component_pool component_pool_delete(typed_component_pool) free(typed_component_pool) } component_manager.next_component_id += 1 } component_manager_get_component_id :: proc(component_manager: ^ComponentManager, $Component: typeid) -> ComponentID { log.assertf(Component in component_manager.component_ids, "Component not registered before use") return component_manager.component_ids[Component] } component_manager_add_component :: proc(component_manager: ^ComponentManager, component: $Component, entity_id: EntityID) { component_pool := cast(^ComponentPool(Component))component_manager.component_pools[Component] component_pool_insert_data(component_pool, entity_id, component) } component_manager_remove_component :: proc(component_manager: ^ComponentManager, $Component: typeid, entity_id: EntityID) { component_pool := cast(^ComponentPool(Component))component_manager.component_pools[Component] component_pool_remove_data(component_pool, entity_id) } component_manager_get_component :: proc(component_manager: ^ComponentManager, $Component: typeid, entity_id: EntityID) -> ^Component { component_pool := cast(^ComponentPool(Component)) component_manager.component_pools[Component] return component_pool_get(component_pool, entity_id) } component_manager_destroy_entity :: proc(component_manager: ^ComponentManager, entity_id: EntityID) { for Component, component_pool in component_manager.component_pools { component_manager.component_pool_destroy_entity_cbs[Component](component_pool, entity_id) } } component_manager_delete :: proc(component_manager: ^ComponentManager) { for Component, &component_pool in component_manager.component_pools { component_manager.component_pool_delete_cbs[Component](component_pool) } delete(component_manager.component_pools) delete(component_manager.component_ids) delete(component_manager.component_pool_destroy_entity_cbs) delete(component_manager.component_pool_delete_cbs) }