From 6d43f30c09f614131155d046b73929095e3a055b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=A5rdbrink?= Date: Tue, 26 Aug 2025 22:01:28 +0200 Subject: [PATCH] Fix component pool entity removal --- ecs/component_manager.odin | 22 ++++++++++++++++------ ecs/component_pool.odin | 12 ++++++------ ecs/constants.odin | 2 +- ecs/physics_system.odin | 13 +++++++++++++ ecs/render_system.odin | 17 ++++++++++++----- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/ecs/component_manager.odin b/ecs/component_manager.odin index 562bb14..3eb8e0f 100644 --- a/ecs/component_manager.odin +++ b/ecs/component_manager.odin @@ -5,6 +5,7 @@ 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, } @@ -25,6 +26,15 @@ component_manager_register_component :: proc($T: typeid, component_manager: ^Com 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 } @@ -35,22 +45,22 @@ component_manager_get_component_type :: proc($T: typeid, component_manager: ^Com 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(T, component_pool, entity_id, 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_pool_remove_data(T, component_pool, entity_id) + 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(T, component_pool, entity_id) + 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 _, component_pool in component_manager.component_pools { - component_pool_destroy_entity(component_pool, entity_id) + for T, component_pool in component_manager.component_pools { + component_manager.destroy_procs[T](component_pool, entity_id) } } diff --git a/ecs/component_pool.odin b/ecs/component_pool.odin index 80efcb9..dc96a8a 100644 --- a/ecs/component_pool.odin +++ b/ecs/component_pool.odin @@ -2,7 +2,7 @@ package ecs import "core:log" -ComponentPool :: struct($T: typeid) { +ComponentPool :: struct(T: typeid) { data: []T, entity_to_index: map[EntityID]uintptr, index_to_entity: map[uintptr]EntityID, @@ -20,7 +20,7 @@ component_pool_create :: proc($T: typeid) -> ComponentPool(T) { return component_pool } -component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID, component: T) { +component_pool_insert_data :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID, component: T) { log.assertf(entity_id not_in component_pool.entity_to_index, "Component already added to entity") new_idx := component_pool.size @@ -31,7 +31,7 @@ component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T) component_pool.size += 1 } -component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) { +component_pool_remove_data :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) { log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component") removed_entity_idx := component_pool.entity_to_index[entity_id] @@ -48,20 +48,20 @@ component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_i component_pool.size -= 1 } -component_pool_get :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID) -> ^T { +component_pool_get :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) -> ^T { log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component") idx := component_pool.entity_to_index[entity_id] return &component_pool.data[idx] } -component_pool_destroy_entity :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) { +component_pool_destroy_entity :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) { if entity_id in component_pool.entity_to_index { component_pool_remove_data(component_pool, entity_id) } } -component_pool_destroy :: proc(component_pool: ^ComponentPool(any)) { +component_pool_destroy :: proc(component_pool: ^ComponentPool($T)) { delete(component_pool.entity_to_index) delete(component_pool.index_to_entity) delete(component_pool.data) diff --git a/ecs/constants.odin b/ecs/constants.odin index c0c3af9..95380d6 100644 --- a/ecs/constants.odin +++ b/ecs/constants.odin @@ -6,4 +6,4 @@ COMPONENT_MAX :: 32 ID :: u32 EntityID :: ID -ComponentType :: u8 +ComponentType :: u16 diff --git a/ecs/physics_system.odin b/ecs/physics_system.odin index 4bee026..f75affb 100644 --- a/ecs/physics_system.odin +++ b/ecs/physics_system.odin @@ -1,10 +1,15 @@ package ecs +import "core:log" + PhysicsSystem :: struct { using base: SystemBase, } physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coordinator, dt: f32) { + entities_to_delete := make([dynamic]EntityID) + defer delete(entities_to_delete) + for entity in physics_system.entities { rigid_body := coordinator_get_component(RigidBodyComponent, coordinator, entity) transform := coordinator_get_component(TransformComponent, coordinator, entity) @@ -12,5 +17,13 @@ physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coor transform.position += rigid_body.velocity * dt rigid_body.velocity += gravity.force * dt + + if transform.position.y < -15 { + append(&entities_to_delete, entity) + } + } + + for entity in entities_to_delete { + coordinator_destroy_entity(coordinator, entity) } } diff --git a/ecs/render_system.odin b/ecs/render_system.odin index 5c53c8c..fded7c3 100644 --- a/ecs/render_system.odin +++ b/ecs/render_system.odin @@ -218,7 +218,6 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin for entity in render_system.entities { transform := coordinator_get_component(TransformComponent, coordinator, entity) - color := coordinator_get_component(ColorComponent, coordinator, entity) mesh_id := coordinator_get_component(MeshComponent, coordinator, entity).mesh_id mesh := render_system.meshes[mesh_id] @@ -226,9 +225,17 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin material_id := coordinator_get_component(MaterialComponent, coordinator, entity).material_id material := render_system.materials[material_id] + color := coordinator_get_component(ColorComponent, coordinator, entity) + + scale_mat := linalg.matrix4_scale_f32(transform.scale) + rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32( + transform.rotation.y, + transform.rotation.x, + transform.rotation.z + ) pos_mat := linalg.matrix4_translate_f32(transform.position) - rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(transform.rotation.y, transform.rotation.x, transform.rotation.z) - model := pos_mat * rot_mat + model := pos_mat * rot_mat * scale_mat + mvp := proj * view * model sg.apply_pipeline(material.pipeline) sg.apply_bindings({ @@ -240,8 +247,8 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin }) sg.apply_uniforms(shaders.UB_VsParams, sg_range(&shaders.Vsparams{ - mvp = proj * view * model, - col = color.color + mvp = mvp, + col = color.color, })) sg.draw(0, 36, 1)