Skip to content

Commit 5f517b3

Browse files
committed
Implement event forwarding/propagation for Parent component
1 parent 24e3591 commit 5f517b3

File tree

12 files changed

+1554
-17
lines changed

12 files changed

+1554
-17
lines changed

distr/flecs.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4810,6 +4810,9 @@ ecs_table_t* flecs_bootstrap_component_table(
48104810
world->cr_childof_0 = flecs_components_ensure(world,
48114811
ecs_pair(EcsChildOf, 0));
48124812

4813+
cr = flecs_components_ensure(world, ecs_id(EcsParent));
4814+
cr->flags |= EcsIdHasOnSet;
4815+
48134816
/* Initialize root table */
48144817
flecs_init_root_table(world);
48154818

@@ -7345,8 +7348,7 @@ void flecs_notify_on_set(
73457348
ecs_iter_action_t on_set = ti->hooks.on_set;
73467349
if (on_set) {
73477350
ecs_table_record_t dummy_tr;
7348-
const ecs_table_record_t *tr =
7349-
flecs_component_get_table(cr, table);
7351+
const ecs_table_record_t *tr = flecs_component_get_table(cr, table);
73507352
if (!tr) {
73517353
dummy_tr.hdr.cr = cr;
73527354
dummy_tr.hdr.table = table;
@@ -7370,7 +7372,6 @@ void flecs_notify_on_set(
73707372
}
73717373
}
73727374

7373-
/* Run OnSet notifications */
73747375
if ((dont_fragment || table->flags & EcsTableHasOnSet)) {
73757376
ecs_type_t ids = { .array = &id, .count = 1 };
73767377
flecs_emit(world, world, &(ecs_event_desc_t) {
@@ -15531,15 +15532,15 @@ void flecs_emit(
1553115532
* event) this will cause the components of the target entity to be
1553215533
* propagated to the source entity. This makes it possible for observers to
1553315534
* get notified of any new reachable components though the relationship. */
15534-
bool can_forward = event != EcsOnSet;
15535+
bool can_forward = true;
1553515536

1553615537
/* Does table has observed entities */
1553715538
bool has_observed = table_flags & EcsTableHasTraversable;
1553815539

1553915540
ecs_event_id_record_t *iders[5] = {0};
1554015541
ecs_table_record_t dummy_tr;
1554115542

15542-
if (count && can_forward && has_observed) {
15543+
if (count && has_observed) {
1554315544
flecs_emit_propagate_invalidate(world, table, offset, count);
1554415545
}
1554515546

@@ -15567,14 +15568,27 @@ void flecs_emit(
1556715568
continue;
1556815569
}
1556915570

15571+
// if (id == ecs_id(EcsParent)) {
15572+
15573+
// ecs_event_desc_t pdesc = *desc;
15574+
// EcsParent *parents = ecs_table_get_column(table,
15575+
// table->component_map[ecs_id(EcsParent)], it.offset);
15576+
// int32_t i, count = pdesc.count;
15577+
15578+
// for (i = 0; i < count; i ++) {
15579+
// ecs_entity_t parent =
15580+
15581+
// }
15582+
// }
15583+
1557015584
int32_t ider_i, ider_count = 0;
1557115585
ecs_component_record_t *cr = flecs_components_get(world, id);
1557215586
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
1557315587
ecs_flags32_t cr_flags = cr->flags;
1557415588

1557515589
/* Check if this id is a pair of an traversable relationship. If so, we
1557615590
* may have to forward ids from the pair's target. */
15577-
if (can_forward && (cr_flags & EcsIdTraversable)) {
15591+
if (can_forward && ECS_IS_PAIR(id) && (cr_flags & EcsIdTraversable)) {
1557815592
const ecs_event_record_t *er_fwd = NULL;
1557915593
if (ECS_PAIR_FIRST(id) == EcsIsA) {
1558015594
if (event == EcsOnAdd) {
@@ -15609,6 +15623,7 @@ void flecs_emit(
1560915623

1561015624
/* Forward events for components from pair target */
1561115625
flecs_emit_forward(world, er, er_fwd, ids, &it, table, cr);
15626+
1561215627
ecs_assert(it.event_cur == evtx, ECS_INTERNAL_ERROR, NULL);
1561315628
}
1561415629

@@ -38152,6 +38167,10 @@ ecs_flags32_t flecs_component_get_flags_intern(
3815238167
result |= EcsIdSingleton;
3815338168
}
3815438169

38170+
if (id == ecs_id(EcsParent)) {
38171+
result |= EcsIdTraversable;
38172+
}
38173+
3815538174
ecs_entity_t on_delete_kind = ecs_table_get_target(world, table, EcsOnDelete, 0);
3815638175
if (on_delete_kind == EcsRemove) {
3815738176
result |= EcsIdOnDeleteRemove;

src/bootstrap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,9 @@ ecs_table_t* flecs_bootstrap_component_table(
690690
world->cr_childof_0 = flecs_components_ensure(world,
691691
ecs_pair(EcsChildOf, 0));
692692

693+
cr = flecs_components_ensure(world, ecs_id(EcsParent));
694+
cr->flags |= EcsIdHasOnSet;
695+
693696
/* Initialize root table */
694697
flecs_init_root_table(world);
695698

src/component_actions.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,7 @@ void flecs_notify_on_set(
496496
ecs_iter_action_t on_set = ti->hooks.on_set;
497497
if (on_set) {
498498
ecs_table_record_t dummy_tr;
499-
const ecs_table_record_t *tr =
500-
flecs_component_get_table(cr, table);
499+
const ecs_table_record_t *tr = flecs_component_get_table(cr, table);
501500
if (!tr) {
502501
dummy_tr.hdr.cr = cr;
503502
dummy_tr.hdr.table = table;
@@ -521,7 +520,6 @@ void flecs_notify_on_set(
521520
}
522521
}
523522

524-
/* Run OnSet notifications */
525523
if ((dont_fragment || table->flags & EcsTableHasOnSet)) {
526524
ecs_type_t ids = { .array = &id, .count = 1 };
527525
flecs_emit(world, world, &(ecs_event_desc_t) {

src/observable.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,15 +1256,15 @@ void flecs_emit(
12561256
* event) this will cause the components of the target entity to be
12571257
* propagated to the source entity. This makes it possible for observers to
12581258
* get notified of any new reachable components though the relationship. */
1259-
bool can_forward = event != EcsOnSet;
1259+
bool can_forward = true;
12601260

12611261
/* Does table has observed entities */
12621262
bool has_observed = table_flags & EcsTableHasTraversable;
12631263

12641264
ecs_event_id_record_t *iders[5] = {0};
12651265
ecs_table_record_t dummy_tr;
12661266

1267-
if (count && can_forward && has_observed) {
1267+
if (count && has_observed) {
12681268
flecs_emit_propagate_invalidate(world, table, offset, count);
12691269
}
12701270

@@ -1292,14 +1292,27 @@ void flecs_emit(
12921292
continue;
12931293
}
12941294

1295+
// if (id == ecs_id(EcsParent)) {
1296+
1297+
// ecs_event_desc_t pdesc = *desc;
1298+
// EcsParent *parents = ecs_table_get_column(table,
1299+
// table->component_map[ecs_id(EcsParent)], it.offset);
1300+
// int32_t i, count = pdesc.count;
1301+
1302+
// for (i = 0; i < count; i ++) {
1303+
// ecs_entity_t parent =
1304+
1305+
// }
1306+
// }
1307+
12951308
int32_t ider_i, ider_count = 0;
12961309
ecs_component_record_t *cr = flecs_components_get(world, id);
12971310
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
12981311
ecs_flags32_t cr_flags = cr->flags;
12991312

13001313
/* Check if this id is a pair of an traversable relationship. If so, we
13011314
* may have to forward ids from the pair's target. */
1302-
if (can_forward && (cr_flags & EcsIdTraversable)) {
1315+
if (can_forward && ECS_IS_PAIR(id) && (cr_flags & EcsIdTraversable)) {
13031316
const ecs_event_record_t *er_fwd = NULL;
13041317
if (ECS_PAIR_FIRST(id) == EcsIsA) {
13051318
if (event == EcsOnAdd) {
@@ -1334,6 +1347,7 @@ void flecs_emit(
13341347

13351348
/* Forward events for components from pair target */
13361349
flecs_emit_forward(world, er, er_fwd, ids, &it, table, cr);
1350+
13371351
ecs_assert(it.event_cur == evtx, ECS_INTERNAL_ERROR, NULL);
13381352
}
13391353

src/storage/component_index.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ ecs_flags32_t flecs_component_get_flags_intern(
328328
result |= EcsIdSingleton;
329329
}
330330

331+
if (id == ecs_id(EcsParent)) {
332+
result |= EcsIdTraversable;
333+
}
334+
331335
ecs_entity_t on_delete_kind = ecs_table_get_target(world, table, EcsOnDelete, 0);
332336
if (on_delete_kind == EcsRemove) {
333337
result |= EcsIdOnDeleteRemove;

test/core/project.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,8 @@
817817
"target_for_wildcard_3_lvls_childof_childof",
818818
"target_for_wildcard_3_lvls_childof_parent",
819819
"target_for_wildcard_3_lvls_parent_childof",
820-
"target_for_wildcard_3_lvls_parent_parent"
820+
"target_for_wildcard_3_lvls_parent_parent",
821+
"parent_has_traversable_flag"
821822
]
822823
}, {
823824
"id": "Hierarchies",
@@ -2067,6 +2068,14 @@
20672068
"1_on_set_overridden_term_field_size_w_tag",
20682069
"2_on_set_overridden_terms_field_size_w_tag",
20692070
"create_observer_in_observer",
2071+
"up_forward_w_parent_component",
2072+
"up_propagate_w_parent_component",
2073+
"self_up_forward_w_parent_component",
2074+
"self_up_propagate_w_parent_component",
2075+
"up_forward_w_parent_component_reparent",
2076+
"up_propagate_w_parent_component_reparent",
2077+
"self_up_forward_w_parent_component_reparent",
2078+
"self_up_propagate_w_parent_component_reparent",
20702079
"cache_test_1",
20712080
"cache_test_2",
20722081
"cache_test_3",

test/core/src/NonFragmentingChildOf.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,3 +2160,22 @@ void NonFragmentingChildOf_target_for_wildcard_3_lvls_parent_parent(void) {
21602160

21612161
ecs_fini(world);
21622162
}
2163+
2164+
void NonFragmentingChildOf_parent_has_traversable_flag(void) {
2165+
ecs_world_t *world = ecs_mini();
2166+
2167+
ecs_entity_t parent = ecs_new(world);
2168+
2169+
ecs_record_t *r = ecs_record_find(world, parent);
2170+
test_assert(r != NULL);
2171+
test_bool(false, r->row & EcsEntityIsTraversable);
2172+
2173+
ecs_entity_t child = ecs_insert(world, ecs_value(EcsParent, {parent}));
2174+
test_bool(true, r->row & EcsEntityIsTraversable);
2175+
2176+
ecs_record_t *child_r = ecs_record_find(world, child);
2177+
test_assert(child_r != NULL);
2178+
test_bool(false, child_r->row & EcsEntityIsTraversable);
2179+
2180+
ecs_fini(world);
2181+
}

test/core/src/Observer.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11750,3 +11750,63 @@ void Observer_create_observer_in_observer(void) {
1175011750

1175111751
ecs_fini(world);
1175211752
}
11753+
11754+
void Observer_up_forward_w_parent_component(void) {
11755+
ecs_world_t *world = ecs_mini();
11756+
11757+
ECS_COMPONENT(world, Position);
11758+
11759+
Probe ctx = {0};
11760+
11761+
ecs_entity_t o = ecs_observer(world, {
11762+
.query.terms = {{ ecs_id(Position), .src.id = EcsUp }},
11763+
.events = { EcsOnAdd },
11764+
.callback = Observer_w_value_1,
11765+
.ctx = &ctx
11766+
});
11767+
11768+
ecs_entity_t parent = ecs_insert(world, ecs_value(Position, {10, 20}));
11769+
test_int(ctx.invoked, 0);
11770+
11771+
printf("---\n");
11772+
11773+
ecs_entity_t e = ecs_insert(world, ecs_value(EcsParent, {parent}));
11774+
// ecs_entity_t e = ecs_new_w_pair(world, EcsChildOf, parent);
11775+
test_int(ctx.invoked, 1);
11776+
test_int(ctx.count, 1);
11777+
test_int(ctx.system, o);
11778+
test_int(ctx.event, EcsOnAdd);
11779+
test_uint(ctx.e[0], e);
11780+
11781+
printf("---\n");
11782+
11783+
ecs_fini(world);
11784+
}
11785+
11786+
void Observer_up_propagate_w_parent_component(void) {
11787+
// Implement testcase
11788+
}
11789+
11790+
void Observer_self_up_forward_w_parent_component(void) {
11791+
// Implement testcase
11792+
}
11793+
11794+
void Observer_self_up_propagate_w_parent_component(void) {
11795+
// Implement testcase
11796+
}
11797+
11798+
void Observer_up_forward_w_parent_component_reparent(void) {
11799+
// Implement testcase
11800+
}
11801+
11802+
void Observer_up_propagate_w_parent_component_reparent(void) {
11803+
// Implement testcase
11804+
}
11805+
11806+
void Observer_self_up_forward_w_parent_component_reparent(void) {
11807+
// Implement testcase
11808+
}
11809+
11810+
void Observer_self_up_propagate_w_parent_component_reparent(void) {
11811+
// Implement testcase
11812+
}

test/core/src/main.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ void NonFragmentingChildOf_target_for_wildcard_3_lvls_childof_childof(void);
786786
void NonFragmentingChildOf_target_for_wildcard_3_lvls_childof_parent(void);
787787
void NonFragmentingChildOf_target_for_wildcard_3_lvls_parent_childof(void);
788788
void NonFragmentingChildOf_target_for_wildcard_3_lvls_parent_parent(void);
789+
void NonFragmentingChildOf_parent_has_traversable_flag(void);
789790

790791
// Testsuite 'Hierarchies'
791792
void Hierarchies_setup(void);
@@ -2000,6 +2001,14 @@ void Observer_2_singleton_terms_field_size_w_tag(void);
20002001
void Observer_1_on_set_overridden_term_field_size_w_tag(void);
20012002
void Observer_2_on_set_overridden_terms_field_size_w_tag(void);
20022003
void Observer_create_observer_in_observer(void);
2004+
void Observer_up_forward_w_parent_component(void);
2005+
void Observer_up_propagate_w_parent_component(void);
2006+
void Observer_self_up_forward_w_parent_component(void);
2007+
void Observer_self_up_propagate_w_parent_component(void);
2008+
void Observer_up_forward_w_parent_component_reparent(void);
2009+
void Observer_up_propagate_w_parent_component_reparent(void);
2010+
void Observer_self_up_forward_w_parent_component_reparent(void);
2011+
void Observer_self_up_propagate_w_parent_component_reparent(void);
20032012
void Observer_cache_test_1(void);
20042013
void Observer_cache_test_2(void);
20052014
void Observer_cache_test_3(void);
@@ -6015,6 +6024,10 @@ bake_test_case NonFragmentingChildOf_testcases[] = {
60156024
{
60166025
"target_for_wildcard_3_lvls_parent_parent",
60176026
NonFragmentingChildOf_target_for_wildcard_3_lvls_parent_parent
6027+
},
6028+
{
6029+
"parent_has_traversable_flag",
6030+
NonFragmentingChildOf_parent_has_traversable_flag
60186031
}
60196032
};
60206033

@@ -10763,6 +10776,38 @@ bake_test_case Observer_testcases[] = {
1076310776
"create_observer_in_observer",
1076410777
Observer_create_observer_in_observer
1076510778
},
10779+
{
10780+
"up_forward_w_parent_component",
10781+
Observer_up_forward_w_parent_component
10782+
},
10783+
{
10784+
"up_propagate_w_parent_component",
10785+
Observer_up_propagate_w_parent_component
10786+
},
10787+
{
10788+
"self_up_forward_w_parent_component",
10789+
Observer_self_up_forward_w_parent_component
10790+
},
10791+
{
10792+
"self_up_propagate_w_parent_component",
10793+
Observer_self_up_propagate_w_parent_component
10794+
},
10795+
{
10796+
"up_forward_w_parent_component_reparent",
10797+
Observer_up_forward_w_parent_component_reparent
10798+
},
10799+
{
10800+
"up_propagate_w_parent_component_reparent",
10801+
Observer_up_propagate_w_parent_component_reparent
10802+
},
10803+
{
10804+
"self_up_forward_w_parent_component_reparent",
10805+
Observer_self_up_forward_w_parent_component_reparent
10806+
},
10807+
{
10808+
"self_up_propagate_w_parent_component_reparent",
10809+
Observer_self_up_propagate_w_parent_component_reparent
10810+
},
1076610811
{
1076710812
"cache_test_1",
1076810813
Observer_cache_test_1
@@ -14635,7 +14680,7 @@ static bake_test_suite suites[] = {
1463514680
"NonFragmentingChildOf",
1463614681
NULL,
1463714682
NULL,
14638-
88,
14683+
89,
1463914684
NonFragmentingChildOf_testcases
1464014685
},
1464114686
{
@@ -14754,7 +14799,7 @@ static bake_test_suite suites[] = {
1475414799
"Observer",
1475514800
NULL,
1475614801
NULL,
14757-
294,
14802+
302,
1475814803
Observer_testcases
1475914804
},
1476014805
{

0 commit comments

Comments
 (0)