Skip to content

Commit c646f92

Browse files
#2004 Fix issue where observers were not always called for deferred DontFragment operations
1 parent 16fc517 commit c646f92

File tree

5 files changed

+123
-8
lines changed

5 files changed

+123
-8
lines changed

distr/flecs.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6526,8 +6526,11 @@ void flecs_cmd_batch_for_entity(
65266526
/* If destination table has new sparse components, make sure they're created
65276527
* for the entity. */
65286528
if ((table_diff.added_flags & (EcsTableHasSparse|EcsTableHasDontFragment)) && added.count) {
6529-
flecs_sparse_on_add(
6530-
world, table, ECS_RECORD_TO_ROW(r->row), 1, &added, true);
6529+
if (flecs_sparse_on_add(
6530+
world, table, ECS_RECORD_TO_ROW(r->row), 1, &added, true))
6531+
{
6532+
table_diff.added_flags |= EcsTableHasOnAdd;
6533+
}
65316534
}
65326535

65336536
/* If the batch contains set commands, copy the component value from the
@@ -6626,7 +6629,7 @@ void flecs_cmd_batch_for_entity(
66266629
if (added.count) {
66276630
ecs_table_diff_t add_diff = ECS_TABLE_DIFF_INIT;
66286631
add_diff.added = added;
6629-
add_diff.added_flags = diff->added_flags;
6632+
add_diff.added_flags = table_diff.added_flags;
66306633

66316634
if (r->row & EcsEntityIsTraversable) {
66326635
/* Update monitors since we didn't do this in flecs_commit. Do this

src/commands.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -943,8 +943,11 @@ void flecs_cmd_batch_for_entity(
943943
/* If destination table has new sparse components, make sure they're created
944944
* for the entity. */
945945
if ((table_diff.added_flags & (EcsTableHasSparse|EcsTableHasDontFragment)) && added.count) {
946-
flecs_sparse_on_add(
947-
world, table, ECS_RECORD_TO_ROW(r->row), 1, &added, true);
946+
if (flecs_sparse_on_add(
947+
world, table, ECS_RECORD_TO_ROW(r->row), 1, &added, true))
948+
{
949+
table_diff.added_flags |= EcsTableHasOnAdd;
950+
}
948951
}
949952

950953
/* If the batch contains set commands, copy the component value from the
@@ -1043,7 +1046,7 @@ void flecs_cmd_batch_for_entity(
10431046
if (added.count) {
10441047
ecs_table_diff_t add_diff = ECS_TABLE_DIFF_INIT;
10451048
add_diff.added = added;
1046-
add_diff.added_flags = diff->added_flags;
1049+
add_diff.added_flags = table_diff.added_flags;
10471050

10481051
if (r->row & EcsEntityIsTraversable) {
10491052
/* Update monitors since we didn't do this in flecs_commit. Do this

test/core/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,9 @@
738738
"check_regular_exclusive_target_in_sparse_observer",
739739
"child_of_component_w_sparse",
740740
"child_of_component_w_sparse_exclusive",
741-
"create_entity_in_on_remove"
741+
"create_entity_in_on_remove",
742+
"defer_add_two_sparse_w_observer",
743+
"defer_remove_two_sparse_w_observer"
742744
]
743745
}, {
744746
"id": "NonFragmentingChildOf",

test/core/src/Sparse.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7227,3 +7227,100 @@ void Sparse_create_entity_in_on_remove(void) {
72277227

72287228
ecs_fini(world);
72297229
}
7230+
7231+
static int OnAddTagA_invoked = 0;
7232+
static int OnAddTagB_invoked = 0;
7233+
static int OnRemoveTagA_invoked = 0;
7234+
static int OnRemoveTagB_invoked = 0;
7235+
7236+
static void OnAddTagA(ecs_iter_t *it) {
7237+
OnAddTagA_invoked += it->count;
7238+
}
7239+
7240+
static void OnAddTagB(ecs_iter_t *it) {
7241+
OnAddTagB_invoked += it->count;
7242+
}
7243+
7244+
static void OnRemoveTagA(ecs_iter_t *it) {
7245+
OnRemoveTagA_invoked += it->count;
7246+
}
7247+
7248+
static void OnRemoveTagB(ecs_iter_t *it) {
7249+
OnRemoveTagB_invoked += it->count;
7250+
}
7251+
7252+
void Sparse_defer_add_two_sparse_w_observer(void) {
7253+
ecs_world_t *world = ecs_mini();
7254+
7255+
ecs_entity_t DontFragA = ecs_entity(world, { .name = "DontFragA" });
7256+
if (!fragment) ecs_add_id(world, DontFragA, EcsDontFragment);
7257+
7258+
ecs_entity_t DontFragB = ecs_entity(world, { .name = "DontFragB" });
7259+
if (!fragment) ecs_add_id(world, DontFragB, EcsDontFragment);
7260+
7261+
ecs_observer(world, {
7262+
.query.terms = {{ .id = DontFragA }},
7263+
.events = { EcsOnAdd },
7264+
.callback = OnAddTagA
7265+
});
7266+
7267+
ecs_observer(world, {
7268+
.query.terms = {{ .id = DontFragB }},
7269+
.events = { EcsOnAdd },
7270+
.callback = OnAddTagB
7271+
});
7272+
7273+
OnAddTagA_invoked = 0;
7274+
OnAddTagB_invoked = 0;
7275+
7276+
ecs_entity_t e = ecs_new(world);
7277+
7278+
ecs_defer_begin(world);
7279+
ecs_add_id(world, e, DontFragA);
7280+
ecs_add_id(world, e, DontFragB);
7281+
ecs_defer_end(world);
7282+
7283+
test_int(OnAddTagA_invoked, 1);
7284+
test_int(OnAddTagB_invoked, 1);
7285+
7286+
ecs_fini(world);
7287+
}
7288+
7289+
void Sparse_defer_remove_two_sparse_w_observer(void) {
7290+
ecs_world_t *world = ecs_mini();
7291+
7292+
ecs_entity_t DontFragA = ecs_entity(world, { .name = "DontFragA" });
7293+
if (!fragment) ecs_add_id(world, DontFragA, EcsDontFragment);
7294+
7295+
ecs_entity_t DontFragB = ecs_entity(world, { .name = "DontFragB" });
7296+
if (!fragment) ecs_add_id(world, DontFragB, EcsDontFragment);
7297+
7298+
ecs_observer(world, {
7299+
.query.terms = {{ .id = DontFragA }},
7300+
.events = { EcsOnRemove },
7301+
.callback = OnRemoveTagA
7302+
});
7303+
7304+
ecs_observer(world, {
7305+
.query.terms = {{ .id = DontFragB }},
7306+
.events = { EcsOnRemove },
7307+
.callback = OnRemoveTagB
7308+
});
7309+
7310+
OnRemoveTagA_invoked = 0;
7311+
OnRemoveTagB_invoked = 0;
7312+
7313+
ecs_entity_t e = ecs_new(world);
7314+
ecs_add_id(world, e, DontFragA);
7315+
ecs_add_id(world, e, DontFragB);
7316+
7317+
ecs_defer_begin(world);
7318+
ecs_remove_id(world, e, DontFragA);
7319+
ecs_remove_id(world, e, DontFragB);
7320+
ecs_defer_end(world);
7321+
7322+
test_int(OnRemoveTagA_invoked, 1);
7323+
test_int(OnRemoveTagB_invoked, 1);
7324+
7325+
ecs_fini(world);
7326+
}

test/core/src/main.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,8 @@ void Sparse_check_regular_exclusive_target_in_sparse_observer(void);
709709
void Sparse_child_of_component_w_sparse(void);
710710
void Sparse_child_of_component_w_sparse_exclusive(void);
711711
void Sparse_create_entity_in_on_remove(void);
712+
void Sparse_defer_add_two_sparse_w_observer(void);
713+
void Sparse_defer_remove_two_sparse_w_observer(void);
712714

713715
// Testsuite 'NonFragmentingChildOf'
714716
void NonFragmentingChildOf_set_parent_no_ordered_children(void);
@@ -5961,6 +5963,14 @@ bake_test_case Sparse_testcases[] = {
59615963
{
59625964
"create_entity_in_on_remove",
59635965
Sparse_create_entity_in_on_remove
5966+
},
5967+
{
5968+
"defer_add_two_sparse_w_observer",
5969+
Sparse_defer_add_two_sparse_w_observer
5970+
},
5971+
{
5972+
"defer_remove_two_sparse_w_observer",
5973+
Sparse_defer_remove_two_sparse_w_observer
59645974
}
59655975
};
59665976

@@ -15871,7 +15881,7 @@ static bake_test_suite suites[] = {
1587115881
"Sparse",
1587215882
Sparse_setup,
1587315883
NULL,
15874-
219,
15884+
221,
1587515885
Sparse_testcases,
1587615886
1,
1587715887
Sparse_params

0 commit comments

Comments
 (0)