From f9eed7e42110616a1dc0e70afed613ceabe53558 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Wed, 28 Aug 2024 11:08:06 -0700 Subject: [PATCH] Fix ecs_new_w_table issue with observers/sparse components --- distr/flecs.c | 6 ++- src/entity.c | 6 ++- test/core/project.json | 11 ++++- test/core/src/ComponentLifecycle.c | 52 +++++++++++++++++++++++ test/core/src/New.c | 66 ++++++++++++++++++++++++++++++ test/core/src/Observer.c | 39 ++++++++++++++++++ test/core/src/main.c | 41 +++++++++++++++++-- 7 files changed, 214 insertions(+), 7 deletions(-) diff --git a/distr/flecs.c b/distr/flecs.c index 4c4fe2a951..d6f1bf3b2a 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -6448,12 +6448,16 @@ ecs_entity_t ecs_new_w_table( ecs_table_t *table) { ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_check(table != NULL, ECS_INVALID_PARAMETER, NULL); flecs_stage_from_world(&world); ecs_entity_t entity = ecs_new(world); ecs_record_t *r = flecs_entities_get(world, entity); - ecs_table_diff_t table_diff = { .added = table->type }; + ecs_table_diff_t table_diff = { + .added = table->type, + .added_flags = table->flags & EcsTableAddEdgeFlags + }; flecs_new_entity(world, entity, r, table, &table_diff, true, 0); return entity; error: diff --git a/src/entity.c b/src/entity.c index cb025b303e..b56aa711f6 100644 --- a/src/entity.c +++ b/src/entity.c @@ -1485,12 +1485,16 @@ ecs_entity_t ecs_new_w_table( ecs_table_t *table) { ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_check(table != NULL, ECS_INVALID_PARAMETER, NULL); flecs_stage_from_world(&world); ecs_entity_t entity = ecs_new(world); ecs_record_t *r = flecs_entities_get(world, entity); - ecs_table_diff_t table_diff = { .added = table->type }; + ecs_table_diff_t table_diff = { + .added = table->type, + .added_flags = table->flags & EcsTableAddEdgeFlags + }; flecs_new_entity(world, entity, r, table, &table_diff, true, 0); return entity; error: diff --git a/test/core/project.json b/test/core/project.json index 5136a1ff92..2f4b539e9b 100644 --- a/test/core/project.json +++ b/test/core/project.json @@ -355,7 +355,11 @@ "new_w_id_w_with_defer", "new_w_id_w_with_defer_w_scope", "new_w_type_w_with_defer", - "new_w_type_w_with_defer_w_scope" + "new_w_type_w_with_defer_w_scope", + "new_w_table", + "new_w_null_table", + "new_w_table_component", + "new_w_table_sparse_component" ] }, { "id": "New_w_Count", @@ -1144,7 +1148,9 @@ "batched_set_new_component_w_lifecycle", "batched_ensure_new_component_w_lifecycle", "on_nested_prefab_copy_test_invokes_copy_count", - "no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor" + "no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor", + "new_w_table_ctor", + "new_w_table_on_add_hook" ] }, { "id": "Pairs", @@ -1581,6 +1587,7 @@ "register_run_after_callback", "register_callback_after_run_ctx", "register_run_after_callback_ctx", + "on_add_after_new_w_table", "cache_test_1", "cache_test_2", "cache_test_3", diff --git a/test/core/src/ComponentLifecycle.c b/test/core/src/ComponentLifecycle.c index 17e9886b4d..e49d16472e 100644 --- a/test/core/src/ComponentLifecycle.c +++ b/test/core/src/ComponentLifecycle.c @@ -3369,3 +3369,55 @@ void ComponentLifecycle_no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor( ecs_fini(world); } + +void ComponentLifecycle_new_w_table_ctor(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + ECS_TAG(world, Bar); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position) + }); + + ecs_table_t *table = ecs_table_add_id(world, NULL, ecs_id(Position)); + table = ecs_table_add_id(world, table, Bar); + + test_int(ctor_position, 0); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Position)); + test_assert(ecs_has(world, e, Bar)); + test_assert(ecs_get(world, e, Position) != NULL); + test_assert(table == ecs_get_table(world, e)); + test_int(ctor_position, 1); + + ecs_fini(world); +} + +void ComponentLifecycle_new_w_table_on_add_hook(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + ECS_TAG(world, Bar); + + ecs_set_hooks(world, Position, { + .on_add = ecs_on_add(Position) + }); + + ecs_table_t *table = ecs_table_add_id(world, NULL, ecs_id(Position)); + table = ecs_table_add_id(world, table, Bar); + + test_int(ctor_position, 0); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Position)); + test_assert(ecs_has(world, e, Bar)); + test_assert(ecs_get(world, e, Position) != NULL); + test_assert(table == ecs_get_table(world, e)); + test_int(on_add_position, 1); + + ecs_fini(world); +} diff --git a/test/core/src/New.c b/test/core/src/New.c index 1041338e00..38817d75ae 100644 --- a/test/core/src/New.c +++ b/test/core/src/New.c @@ -463,3 +463,69 @@ void New_new_w_type_w_with_defer_w_scope(void) { ecs_fini(world); } + +void New_new_w_table(void) { + ecs_world_t *world = ecs_mini(); + + ECS_TAG(world, Foo); + ECS_TAG(world, Bar); + + ecs_table_t *table = ecs_table_add_id(world, NULL, Foo); + table = ecs_table_add_id(world, table, Bar); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Foo)); + test_assert(ecs_has(world, e, Bar)); + test_assert(table == ecs_get_table(world, e)); + + ecs_fini(world); +} + +void New_new_w_null_table(void) { + install_test_abort(); + ecs_world_t *world = ecs_mini(); + + test_expect_abort(); + ecs_new_w_table(world, NULL); +} + +void New_new_w_table_component(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + ECS_TAG(world, Bar); + + ecs_table_t *table = ecs_table_add_id(world, NULL, ecs_id(Position)); + table = ecs_table_add_id(world, table, Bar); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Position)); + test_assert(ecs_has(world, e, Bar)); + test_assert(ecs_get(world, e, Position) != NULL); + test_assert(table == ecs_get_table(world, e)); + + ecs_fini(world); +} + +void New_new_w_table_sparse_component(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + ECS_TAG(world, Bar); + + ecs_add_id(world, ecs_id(Position), EcsSparse); + + ecs_table_t *table = ecs_table_add_id(world, NULL, ecs_id(Position)); + table = ecs_table_add_id(world, table, Bar); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Position)); + test_assert(ecs_has(world, e, Bar)); + test_assert(ecs_get(world, e, Position) != NULL); + test_assert(table == ecs_get_table(world, e)); + + ecs_fini(world); +} diff --git a/test/core/src/Observer.c b/test/core/src/Observer.c index 7c0ef2768f..701bd37381 100644 --- a/test/core/src/Observer.c +++ b/test/core/src/Observer.c @@ -7157,6 +7157,45 @@ void Observer_register_run_after_callback_ctx(void) { test_int(run_ctx, 1); } +void Observer_on_add_after_new_w_table(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + ECS_TAG(world, Bar); + + Probe ctx = {0}; + + ecs_observer(world, { + .query.terms = { + { .id = ecs_id(Position) } + }, + .callback = Observer, + .events = { EcsOnAdd }, + .ctx = &ctx + }); + + ecs_table_t *table = ecs_table_add_id(world, NULL, ecs_id(Position)); + table = ecs_table_add_id(world, table, Bar); + + test_int(ctx.invoked, 0); + + ecs_entity_t e = ecs_new_w_table(world, table); + test_assert(e != 0); + test_assert(ecs_has(world, e, Position)); + test_assert(ecs_has(world, e, Bar)); + test_assert(ecs_get(world, e, Position) != NULL); + test_assert(table == ecs_get_table(world, e)); + + test_int(ctx.invoked, 1); + test_int(ctx.count, 1); + test_int(ctx.e[0], e); + test_int(ctx.s[0][0], 0); + test_int(ctx.c[0][0], ecs_id(Position)); + test_int(ctx.event, EcsOnAdd); + + ecs_fini(world); +} + void Observer_cache_test_1(void) { ecs_world_t *world = ecs_mini(); diff --git a/test/core/src/main.c b/test/core/src/main.c index c6b18c90ba..cc394f3149 100644 --- a/test/core/src/main.c +++ b/test/core/src/main.c @@ -339,6 +339,10 @@ void New_new_w_id_w_with_defer(void); void New_new_w_id_w_with_defer_w_scope(void); void New_new_w_type_w_with_defer(void); void New_new_w_type_w_with_defer_w_scope(void); +void New_new_w_table(void); +void New_new_w_null_table(void); +void New_new_w_table_component(void); +void New_new_w_table_sparse_component(void); // Testsuite 'New_w_Count' void New_w_Count_empty(void); @@ -1089,6 +1093,8 @@ void ComponentLifecycle_batched_set_new_component_w_lifecycle(void); void ComponentLifecycle_batched_ensure_new_component_w_lifecycle(void); void ComponentLifecycle_on_nested_prefab_copy_test_invokes_copy_count(void); void ComponentLifecycle_no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor(void); +void ComponentLifecycle_new_w_table_ctor(void); +void ComponentLifecycle_new_w_table_on_add_hook(void); // Testsuite 'Pairs' void Pairs_type_w_one_pair(void); @@ -1519,6 +1525,7 @@ void Observer_register_callback_after_run(void); void Observer_register_run_after_callback(void); void Observer_register_callback_after_run_ctx(void); void Observer_register_run_after_callback_ctx(void); +void Observer_on_add_after_new_w_table(void); void Observer_cache_test_1(void); void Observer_cache_test_2(void); void Observer_cache_test_3(void); @@ -3452,6 +3459,22 @@ bake_test_case New_testcases[] = { { "new_w_type_w_with_defer_w_scope", New_new_w_type_w_with_defer_w_scope + }, + { + "new_w_table", + New_new_w_table + }, + { + "new_w_null_table", + New_new_w_null_table + }, + { + "new_w_table_component", + New_new_w_table_component + }, + { + "new_w_table_sparse_component", + New_new_w_table_sparse_component } }; @@ -6333,6 +6356,14 @@ bake_test_case ComponentLifecycle_testcases[] = { { "no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor", ComponentLifecycle_no_move_no_move_ctor_with_move_dtor_with_ctor_move_dtor + }, + { + "new_w_table_ctor", + ComponentLifecycle_new_w_table_ctor + }, + { + "new_w_table_on_add_hook", + ComponentLifecycle_new_w_table_on_add_hook } }; @@ -8039,6 +8070,10 @@ bake_test_case Observer_testcases[] = { "register_run_after_callback_ctx", Observer_register_run_after_callback_ctx }, + { + "on_add_after_new_w_table", + Observer_on_add_after_new_w_table + }, { "cache_test_1", Observer_cache_test_1 @@ -10556,7 +10591,7 @@ static bake_test_suite suites[] = { "New", New_setup, NULL, - 24, + 28, New_testcases }, { @@ -10689,7 +10724,7 @@ static bake_test_suite suites[] = { "ComponentLifecycle", ComponentLifecycle_setup, NULL, - 92, + 94, ComponentLifecycle_testcases }, { @@ -10710,7 +10745,7 @@ static bake_test_suite suites[] = { "Observer", NULL, NULL, - 198, + 199, Observer_testcases }, {