ecs-test/ecs/component_manager.odin

88 lines
3.9 KiB
Odin

#+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)
}