Standardise and make ECS more robust

This commit is contained in:
Hugo Mårdbrink 2025-08-28 14:31:55 +02:00
parent b9aaeb62c9
commit 2ba1022f79
13 changed files with 245 additions and 232 deletions

View file

@ -1,76 +1,88 @@
#+private
package ecs
import "core:log"
ComponentManager :: struct {
component_types: map[typeid]ComponentType,
component_ids: map[typeid]ComponentID,
component_pools: map[typeid]^ComponentPool(any),
destroy_procs: map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID),
next_component_type: ComponentType,
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_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
}
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)
return component_manager
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($T: typeid, component_manager: ^ComponentManager) {
log.assertf(T not_in component_manager.component_types, "Registering component more than once")
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_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.component_ids[Component] = component_manager.next_component_id
component_manager.destroy_procs[T] = proc(component_pool: ^ComponentPool(any), id: EntityID) {
typed_component_pool := cast(^ComponentPool(T))component_pool
component_pool := new(ComponentPool(Component), context.allocator)
component_pool_init(component_pool)
if id in typed_component_pool.entity_to_index {
component_pool_remove_data(typed_component_pool, id)
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.next_component_type += 1
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_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_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($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID, component: T) {
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
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($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) {
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
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($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) -> ^T {
component_pool := cast(^ComponentPool(T)) component_manager.component_pools[T]
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 T, component_pool in component_manager.component_pools {
component_manager.destroy_procs[T](component_pool, entity_id)
for Component, component_pool in component_manager.component_pools {
component_manager.component_pool_destroy_entity_cbs[Component](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)
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_types)
delete(component_manager.component_ids)
delete(component_manager.component_pool_destroy_entity_cbs)
delete(component_manager.component_pool_delete_cbs)
}