Skip to content

Commit e498e57

Browse files
committed
Fix issue where observer was not always called for deferred set of DontFragment component
1 parent b189eae commit e498e57

File tree

8 files changed

+151
-6
lines changed

8 files changed

+151
-6
lines changed

distr/flecs.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,6 +2813,7 @@ typedef enum ecs_cmd_kind_t {
28132813
EcsCmdAdd,
28142814
EcsCmdRemove,
28152815
EcsCmdSet,
2816+
EcsCmdSetDontFragment,
28162817
EcsCmdEmplace,
28172818
EcsCmdEnsure,
28182819
EcsCmdModified,
@@ -6086,7 +6087,9 @@ void* flecs_defer_set(
60866087
}
60876088

60886089
if (!ptr.ptr) {
6089-
cmd->kind = EcsCmdSet;
6090+
bool is_dont_fragment =
6091+
flecs_component_get_flags(world, id) & EcsIdDontFragment;
6092+
cmd->kind = is_dont_fragment ? EcsCmdSetDontFragment : EcsCmdSet;
60906093
cmd->is._1.size = size;
60916094
ptr.ptr = cmd->is._1.value =
60926095
flecs_stack_alloc(&stage->cmd->stack, size, ti->alignment);
@@ -6159,7 +6162,9 @@ void* flecs_defer_cpp_set(
61596162
}
61606163

61616164
if (!ptr.ptr) {
6162-
cmd->kind = EcsCmdSet;
6165+
bool is_dont_fragment =
6166+
flecs_component_get_flags(world, id) & EcsIdDontFragment;
6167+
cmd->kind = is_dont_fragment ? EcsCmdSetDontFragment : EcsCmdSet;
61636168
cmd->is._1.size = size;
61646169
ptr.ptr = cmd->is._1.value =
61656170
flecs_stack_alloc(&stage->cmd->stack, size, ti->alignment);
@@ -6431,6 +6436,9 @@ void flecs_cmd_batch_for_entity(
64316436

64326437
if (cr && cr->flags & EcsIdDontFragment) {
64336438
/* Nothing to batch for non-fragmenting components */
6439+
if (cmd->kind == EcsCmdSet) {
6440+
cmd->kind = EcsCmdSetDontFragment;
6441+
}
64346442
continue;
64356443
}
64366444

@@ -6504,6 +6512,7 @@ void flecs_cmd_batch_for_entity(
65046512
case EcsCmdSkip:
65056513
case EcsCmdModifiedNoHook:
65066514
case EcsCmdModified:
6515+
case EcsCmdSetDontFragment:
65076516
break;
65086517
}
65096518
} while ((cur = next_for_entity));
@@ -6611,6 +6620,7 @@ void flecs_cmd_batch_for_entity(
66116620
case EcsCmdModified:
66126621
case EcsCmdModifiedNoHook:
66136622
case EcsCmdAddModified:
6623+
case EcsCmdSetDontFragment:
66146624
case EcsCmdPath:
66156625
case EcsCmdDelete:
66166626
case EcsCmdClear:
@@ -6779,6 +6789,7 @@ bool flecs_defer_end(
67796789
world->info.cmd.other_count ++;
67806790
break;
67816791
case EcsCmdSet:
6792+
case EcsCmdSetDontFragment:
67826793
flecs_set_id_move(world, dst_stage, e,
67836794
cmd->id, flecs_itosize(cmd->is._1.size),
67846795
cmd->is._1.value, kind);
@@ -10209,6 +10220,9 @@ void flecs_set_id_move(
1020910220
flecs_notify_on_set_ids(
1021010221
world, table, ECS_RECORD_TO_ROW(r->row), 1, &ids);
1021110222
}
10223+
} else if (cmd_kind == EcsCmdSetDontFragment) {
10224+
flecs_notify_on_set(
10225+
world, r->table, ECS_RECORD_TO_ROW(r->row), component, true);
1021210226
}
1021310227

1021410228
flecs_defer_end(world, stage);
@@ -30019,6 +30033,7 @@ const char* flecs_rest_cmd_kind_to_str(
3001930033
case EcsCmdBulkNew: return "BulkNew";
3002030034
case EcsCmdAdd: return "Add";
3002130035
case EcsCmdRemove: return "Remove";
30036+
case EcsCmdSetDontFragment:
3002230037
case EcsCmdSet: return "Set";
3002330038
case EcsCmdEmplace: return "Emplace";
3002430039
case EcsCmdEnsure: return "Ensure";
@@ -30052,6 +30067,7 @@ bool flecs_rest_cmd_has_id(
3005230067
case EcsCmdAdd:
3005330068
case EcsCmdRemove:
3005430069
case EcsCmdSet:
30070+
case EcsCmdSetDontFragment:
3005530071
case EcsCmdEmplace:
3005630072
case EcsCmdEnsure:
3005730073
case EcsCmdModified:

src/addons/rest.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,7 @@ const char* flecs_rest_cmd_kind_to_str(
17181718
case EcsCmdBulkNew: return "BulkNew";
17191719
case EcsCmdAdd: return "Add";
17201720
case EcsCmdRemove: return "Remove";
1721+
case EcsCmdSetDontFragment:
17211722
case EcsCmdSet: return "Set";
17221723
case EcsCmdEmplace: return "Emplace";
17231724
case EcsCmdEnsure: return "Ensure";
@@ -1751,6 +1752,7 @@ bool flecs_rest_cmd_has_id(
17511752
case EcsCmdAdd:
17521753
case EcsCmdRemove:
17531754
case EcsCmdSet:
1755+
case EcsCmdSetDontFragment:
17541756
case EcsCmdEmplace:
17551757
case EcsCmdEnsure:
17561758
case EcsCmdModified:

src/commands.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ void* flecs_defer_set(
503503
}
504504

505505
if (!ptr.ptr) {
506-
cmd->kind = EcsCmdSet;
506+
bool is_dont_fragment =
507+
flecs_component_get_flags(world, id) & EcsIdDontFragment;
508+
cmd->kind = is_dont_fragment ? EcsCmdSetDontFragment : EcsCmdSet;
507509
cmd->is._1.size = size;
508510
ptr.ptr = cmd->is._1.value =
509511
flecs_stack_alloc(&stage->cmd->stack, size, ti->alignment);
@@ -576,7 +578,9 @@ void* flecs_defer_cpp_set(
576578
}
577579

578580
if (!ptr.ptr) {
579-
cmd->kind = EcsCmdSet;
581+
bool is_dont_fragment =
582+
flecs_component_get_flags(world, id) & EcsIdDontFragment;
583+
cmd->kind = is_dont_fragment ? EcsCmdSetDontFragment : EcsCmdSet;
580584
cmd->is._1.size = size;
581585
ptr.ptr = cmd->is._1.value =
582586
flecs_stack_alloc(&stage->cmd->stack, size, ti->alignment);
@@ -848,6 +852,9 @@ void flecs_cmd_batch_for_entity(
848852

849853
if (cr && cr->flags & EcsIdDontFragment) {
850854
/* Nothing to batch for non-fragmenting components */
855+
if (cmd->kind == EcsCmdSet) {
856+
cmd->kind = EcsCmdSetDontFragment;
857+
}
851858
continue;
852859
}
853860

@@ -921,6 +928,7 @@ void flecs_cmd_batch_for_entity(
921928
case EcsCmdSkip:
922929
case EcsCmdModifiedNoHook:
923930
case EcsCmdModified:
931+
case EcsCmdSetDontFragment:
924932
break;
925933
}
926934
} while ((cur = next_for_entity));
@@ -1028,6 +1036,7 @@ void flecs_cmd_batch_for_entity(
10281036
case EcsCmdModified:
10291037
case EcsCmdModifiedNoHook:
10301038
case EcsCmdAddModified:
1039+
case EcsCmdSetDontFragment:
10311040
case EcsCmdPath:
10321041
case EcsCmdDelete:
10331042
case EcsCmdClear:
@@ -1196,6 +1205,7 @@ bool flecs_defer_end(
11961205
world->info.cmd.other_count ++;
11971206
break;
11981207
case EcsCmdSet:
1208+
case EcsCmdSetDontFragment:
11991209
flecs_set_id_move(world, dst_stage, e,
12001210
cmd->id, flecs_itosize(cmd->is._1.size),
12011211
cmd->is._1.value, kind);

src/commands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ typedef enum ecs_cmd_kind_t {
1313
EcsCmdAdd,
1414
EcsCmdRemove,
1515
EcsCmdSet,
16+
EcsCmdSetDontFragment,
1617
EcsCmdEmplace,
1718
EcsCmdEnsure,
1819
EcsCmdModified,

src/entity.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,9 @@ void flecs_set_id_move(
23412341
flecs_notify_on_set_ids(
23422342
world, table, ECS_RECORD_TO_ROW(r->row), 1, &ids);
23432343
}
2344+
} else if (cmd_kind == EcsCmdSetDontFragment) {
2345+
flecs_notify_on_set(
2346+
world, r->table, ECS_RECORD_TO_ROW(r->row), component, true);
23442347
}
23452348

23462349
flecs_defer_end(world, stage);

test/core/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,9 @@
740740
"child_of_component_w_sparse_exclusive",
741741
"create_entity_in_on_remove",
742742
"defer_add_two_sparse_w_observer",
743-
"defer_remove_two_sparse_w_observer"
743+
"defer_remove_two_sparse_w_observer",
744+
"defer_set_batch_two_sparse_w_observer",
745+
"defer_set_w_sparse_w_observer"
744746
]
745747
}, {
746748
"id": "NonFragmentingChildOf",

test/core/src/Sparse.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7232,6 +7232,10 @@ static int OnAddTagA_invoked = 0;
72327232
static int OnAddTagB_invoked = 0;
72337233
static int OnRemoveTagA_invoked = 0;
72347234
static int OnRemoveTagB_invoked = 0;
7235+
static int DataOnSet_invoked = 0;
7236+
static int DataOnAdd_invoked = 0;
7237+
static int RegularOnAdd_invoked = 0;
7238+
static int DataOnSet_value = -1;
72357239

72367240
static void OnAddTagA(ecs_iter_t *it) {
72377241
OnAddTagA_invoked += it->count;
@@ -7249,6 +7253,25 @@ static void OnRemoveTagB(ecs_iter_t *it) {
72497253
OnRemoveTagB_invoked += it->count;
72507254
}
72517255

7256+
static void DataOnAdd(ecs_iter_t* it)
7257+
{
7258+
DataOnAdd_invoked++;
7259+
}
7260+
7261+
static void DataOnSet(ecs_iter_t* it)
7262+
{
7263+
DataOnSet_invoked++;
7264+
Velocity* d = ecs_field_at(it, Velocity, 0, 0);
7265+
if (d) {
7266+
DataOnSet_value = d->x;
7267+
}
7268+
}
7269+
7270+
static void RegularOnAdd(ecs_iter_t* it)
7271+
{
7272+
RegularOnAdd_invoked++;
7273+
}
7274+
72527275
void Sparse_defer_add_two_sparse_w_observer(void) {
72537276
ecs_world_t *world = ecs_mini();
72547277

@@ -7324,3 +7347,81 @@ void Sparse_defer_remove_two_sparse_w_observer(void) {
73247347

73257348
ecs_fini(world);
73267349
}
7350+
7351+
void Sparse_defer_set_batch_two_sparse_w_observer(void) {
7352+
ecs_world_t* world = ecs_mini();
7353+
7354+
ECS_COMPONENT(world, Position);
7355+
ECS_COMPONENT(world, Velocity);
7356+
7357+
ecs_add_id(world, ecs_id(Velocity), EcsSparse);
7358+
if (!fragment) ecs_add_id(world, ecs_id(Velocity), EcsDontFragment);
7359+
7360+
ecs_observer(world, {
7361+
.query.terms = {{.id = ecs_id(Position) }},
7362+
.events = { EcsOnAdd },
7363+
.callback = RegularOnAdd
7364+
});
7365+
7366+
ecs_observer(world, {
7367+
.query.terms = {{.id = ecs_id(Velocity) }},
7368+
.events = { EcsOnAdd },
7369+
.callback = DataOnAdd
7370+
});
7371+
7372+
ecs_observer(world, {
7373+
.query.terms = {{.id = ecs_id(Velocity) }},
7374+
.events = { EcsOnSet },
7375+
.callback = DataOnSet
7376+
});
7377+
7378+
ecs_entity_t e = ecs_new(world);
7379+
7380+
ecs_defer_begin(world);
7381+
ecs_set(world, e, Position, {42});
7382+
ecs_set(world, e, Velocity, {99});
7383+
ecs_defer_end(world);
7384+
7385+
test_int(RegularOnAdd_invoked, 1);
7386+
test_int(DataOnAdd_invoked, 1);
7387+
test_int(DataOnSet_invoked, 1);
7388+
test_int(DataOnSet_value, 99);
7389+
test_assert(ecs_has(world, e, Velocity));
7390+
test_assert(ecs_get(world, e, Velocity)->x == 99);
7391+
7392+
ecs_fini(world);
7393+
}
7394+
7395+
void Sparse_defer_set_w_sparse_w_observer(void) {
7396+
ecs_world_t *world = ecs_mini();
7397+
7398+
ECS_COMPONENT(world, Velocity);
7399+
ecs_add_id(world, ecs_id(Velocity), EcsSparse);
7400+
if (!fragment) ecs_add_id(world, ecs_id(Velocity), EcsDontFragment);
7401+
7402+
ecs_observer(world, {
7403+
.query.terms = {{ .id = ecs_id(Velocity) }},
7404+
.events = { EcsOnAdd },
7405+
.callback = DataOnAdd
7406+
});
7407+
7408+
ecs_observer(world, {
7409+
.query.terms = {{ .id = ecs_id(Velocity) }},
7410+
.events = { EcsOnSet },
7411+
.callback = DataOnSet
7412+
});
7413+
7414+
ecs_entity_t e = ecs_new(world);
7415+
7416+
ecs_defer_begin(world);
7417+
ecs_set(world, e, Velocity, {77});
7418+
ecs_defer_end(world);
7419+
7420+
test_int(DataOnAdd_invoked, 1);
7421+
test_int(DataOnSet_invoked, 1);
7422+
test_int(DataOnSet_value, 77);
7423+
test_assert(ecs_has(world, e, Velocity));
7424+
test_assert(ecs_get(world, e, Velocity)->x == 77);
7425+
7426+
ecs_fini(world);
7427+
}

test/core/src/main.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,8 @@ void Sparse_child_of_component_w_sparse_exclusive(void);
711711
void Sparse_create_entity_in_on_remove(void);
712712
void Sparse_defer_add_two_sparse_w_observer(void);
713713
void Sparse_defer_remove_two_sparse_w_observer(void);
714+
void Sparse_defer_set_batch_two_sparse_w_observer(void);
715+
void Sparse_defer_set_w_sparse_w_observer(void);
714716

715717
// Testsuite 'NonFragmentingChildOf'
716718
void NonFragmentingChildOf_set_parent_no_ordered_children(void);
@@ -5975,6 +5977,14 @@ bake_test_case Sparse_testcases[] = {
59755977
{
59765978
"defer_remove_two_sparse_w_observer",
59775979
Sparse_defer_remove_two_sparse_w_observer
5980+
},
5981+
{
5982+
"defer_set_batch_two_sparse_w_observer",
5983+
Sparse_defer_set_batch_two_sparse_w_observer
5984+
},
5985+
{
5986+
"defer_set_w_sparse_w_observer",
5987+
Sparse_defer_set_w_sparse_w_observer
59785988
}
59795989
};
59805990

@@ -15901,7 +15911,7 @@ static bake_test_suite suites[] = {
1590115911
"Sparse",
1590215912
Sparse_setup,
1590315913
NULL,
15904-
221,
15914+
223,
1590515915
Sparse_testcases,
1590615916
1,
1590715917
Sparse_params

0 commit comments

Comments
 (0)