Skip to content

Commit

Permalink
#1413 Fix issue where (OnInstantiate, Override) would not trigger OnSet
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Nov 4, 2024
1 parent 08da32a commit f906a4d
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 7 deletions.
46 changes: 43 additions & 3 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13802,6 +13802,7 @@ void flecs_emit(
int32_t ider_i, ider_count = 0;
bool is_pair = ECS_IS_PAIR(id);
void *override_ptr = NULL;
bool override_base_added = false;
ecs_table_record_t *base_tr = NULL;
ecs_entity_t base = 0;
bool id_can_override = can_override;
Expand Down Expand Up @@ -13873,6 +13874,26 @@ void flecs_emit(
override_ptr = base_table->data.columns[base_column].data;
override_ptr = ECS_ELEM(override_ptr, ti->size, base_row);
}

/* For ids with override policy, check if base was added
* in same operation. This will determine later on
* whether we need to emit an OnSet event. */
if (!(idr->flags &
(EcsIdOnInstantiateInherit|EcsIdOnInstantiateDontInherit))) {
int32_t base_i;
for (base_i = 0; base_i < id_count; base_i ++) {
ecs_id_t base_id = id_array[base_i];
if (!ECS_IS_PAIR(base_id)) {
continue;
}
if (ECS_PAIR_FIRST(base_id) != EcsIsA) {
continue;
}
if (ECS_PAIR_SECOND(base_id) == (uint32_t)base) {
override_base_added = true;
}
}
}
}
}
}
Expand Down Expand Up @@ -13928,7 +13949,7 @@ void flecs_emit(
ptr = ECS_ELEM(c->data, size, offset);
}

/* safe, owned by observer */
/* Safe, owned by observer */
ECS_CONST_CAST(int32_t*, it.sizes)[0] = size;

if (override_ptr) {
Expand All @@ -13937,6 +13958,26 @@ void flecs_emit(
* with the value of the overridden component. */
flecs_override_copy(world, table, tr, ti, ptr,
override_ptr, offset, count);

/* If the base for this component got added in the same
* operation, generate an OnSet event as this is the
* first time this value is observed for the entity. */
if (override_base_added) {
ecs_event_id_record_t *iders_set[5] = {0};
int32_t ider_set_i, ider_set_count =
flecs_event_observers_get(er_onset, id, iders_set);
for (ider_set_i = 0; ider_set_i < ider_set_count; ider_set_i ++) {
ecs_event_id_record_t *ider = iders_set[ider_set_i];
flecs_observers_invoke(
world, &ider->self, &it, table, 0);
ecs_assert(it.event_cur == evtx,
ECS_INTERNAL_ERROR, NULL);
flecs_observers_invoke(
world, &ider->self_up, &it, table, 0);
ecs_assert(it.event_cur == evtx,
ECS_INTERNAL_ERROR, NULL);
}
}
} else if (er_onset && it.other_table) {
/* If an override was removed, this re-exposes the
* overridden component. Because this causes the actual
Expand Down Expand Up @@ -14519,8 +14560,7 @@ void flecs_observers_invoke(
while (ecs_map_next(&oit)) {
ecs_observer_t *o = ecs_map_ptr(&oit);
ecs_assert(it->table == table, ECS_INTERNAL_ERROR, NULL);
flecs_uni_observer_invoke(
world, o, it, table, trav);
flecs_uni_observer_invoke(world, o, it, table, trav);
}

ecs_table_unlock(it->world, table);
Expand Down
43 changes: 42 additions & 1 deletion src/observable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,7 @@ void flecs_emit(
int32_t ider_i, ider_count = 0;
bool is_pair = ECS_IS_PAIR(id);
void *override_ptr = NULL;
bool override_base_added = false;
ecs_table_record_t *base_tr = NULL;
ecs_entity_t base = 0;
bool id_can_override = can_override;
Expand Down Expand Up @@ -1307,6 +1308,26 @@ void flecs_emit(
override_ptr = base_table->data.columns[base_column].data;
override_ptr = ECS_ELEM(override_ptr, ti->size, base_row);
}

/* For ids with override policy, check if base was added
* in same operation. This will determine later on
* whether we need to emit an OnSet event. */
if (!(idr->flags &
(EcsIdOnInstantiateInherit|EcsIdOnInstantiateDontInherit))) {
int32_t base_i;
for (base_i = 0; base_i < id_count; base_i ++) {
ecs_id_t base_id = id_array[base_i];
if (!ECS_IS_PAIR(base_id)) {
continue;
}
if (ECS_PAIR_FIRST(base_id) != EcsIsA) {
continue;
}
if (ECS_PAIR_SECOND(base_id) == (uint32_t)base) {
override_base_added = true;
}
}
}
}
}
}
Expand Down Expand Up @@ -1362,7 +1383,7 @@ void flecs_emit(
ptr = ECS_ELEM(c->data, size, offset);
}

/* safe, owned by observer */
/* Safe, owned by observer */
ECS_CONST_CAST(int32_t*, it.sizes)[0] = size;

if (override_ptr) {
Expand All @@ -1371,6 +1392,26 @@ void flecs_emit(
* with the value of the overridden component. */
flecs_override_copy(world, table, tr, ti, ptr,
override_ptr, offset, count);

/* If the base for this component got added in the same
* operation, generate an OnSet event as this is the
* first time this value is observed for the entity. */
if (override_base_added) {
ecs_event_id_record_t *iders_set[5] = {0};
int32_t ider_set_i, ider_set_count =
flecs_event_observers_get(er_onset, id, iders_set);
for (ider_set_i = 0; ider_set_i < ider_set_count; ider_set_i ++) {
ecs_event_id_record_t *ider = iders_set[ider_set_i];
flecs_observers_invoke(
world, &ider->self, &it, table, 0);
ecs_assert(it.event_cur == evtx,
ECS_INTERNAL_ERROR, NULL);
flecs_observers_invoke(
world, &ider->self_up, &it, table, 0);
ecs_assert(it.event_cur == evtx,
ECS_INTERNAL_ERROR, NULL);
}
}
} else if (er_onset && it.other_table) {
/* If an override was removed, this re-exposes the
* overridden component. Because this causes the actual
Expand Down
3 changes: 1 addition & 2 deletions src/observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,7 @@ void flecs_observers_invoke(
while (ecs_map_next(&oit)) {
ecs_observer_t *o = ecs_map_ptr(&oit);
ecs_assert(it->table == table, ECS_INTERNAL_ERROR, NULL);
flecs_uni_observer_invoke(
world, o, it, table, trav);
flecs_uni_observer_invoke(world, o, it, table, trav);
}

ecs_table_unlock(it->world, table);
Expand Down
3 changes: 3 additions & 0 deletions test/core/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,9 @@
"on_set_self_auto_override",
"on_set_self_superset_auto_override",
"on_set_superset_auto_override",
"on_set_self_on_instantiate_override",
"on_set_self_up_on_instantiate_override",
"on_set_up_on_instantiate_override",
"not_only",
"not_only_w_base",
"not_only_w_base_no_match",
Expand Down
87 changes: 87 additions & 0 deletions test/core/src/Trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -4654,6 +4654,93 @@ void Trigger_on_set_superset_auto_override(void) {
ecs_fini(world);
}

void Trigger_on_set_self_on_instantiate_override(void) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t base = ecs_insert(world, ecs_value(Position, {10, 20}));

Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.query.terms[0] = {
.id = ecs_id(Position),
.src.id = EcsSelf
},
.events = {EcsOnSet},
.callback = Trigger_w_value,
.ctx = &ctx
});

ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( ecs_has(world, inst, Position));
test_assert( ecs_owns(world, inst, Position));

test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.e[0], inst);
test_int(ctx.s[0][0], 0);

ecs_fini(world);
}

void Trigger_on_set_self_up_on_instantiate_override(void) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t base = ecs_insert(world, ecs_value(Position, {10, 20}));

Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.query.terms[0] = {
.id = ecs_id(Position),
.src.id = EcsSelf|EcsUp
},
.events = {EcsOnSet},
.callback = Trigger_w_value,
.ctx = &ctx
});

ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( ecs_has(world, inst, Position));
test_assert( ecs_owns(world, inst, Position));

test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.e[0], inst);
test_int(ctx.s[0][0], 0);

ecs_fini(world);
}

void Trigger_on_set_up_on_instantiate_override(void) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t base = ecs_insert(world, ecs_value(Position, {10, 20}));

Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.query.terms[0] = {
.id = ecs_id(Position),
.src.id = EcsUp
},
.events = {EcsOnSet},
.callback = Trigger_w_value,
.ctx = &ctx
});

ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( ecs_has(world, inst, Position));
test_assert( ecs_owns(world, inst, Position));

test_int(ctx.invoked, 0);

ecs_fini(world);
}

void Trigger_not_only(void) {
ecs_world_t *world = ecs_mini();

Expand Down
17 changes: 16 additions & 1 deletion test/core/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,9 @@ void Trigger_on_set_self_superset_from_child_base_of_prefab(void);
void Trigger_on_set_self_auto_override(void);
void Trigger_on_set_self_superset_auto_override(void);
void Trigger_on_set_superset_auto_override(void);
void Trigger_on_set_self_on_instantiate_override(void);
void Trigger_on_set_self_up_on_instantiate_override(void);
void Trigger_on_set_up_on_instantiate_override(void);
void Trigger_not_only(void);
void Trigger_not_only_w_base(void);
void Trigger_not_only_w_base_no_match(void);
Expand Down Expand Up @@ -7595,6 +7598,18 @@ bake_test_case Trigger_testcases[] = {
"on_set_superset_auto_override",
Trigger_on_set_superset_auto_override
},
{
"on_set_self_on_instantiate_override",
Trigger_on_set_self_on_instantiate_override
},
{
"on_set_self_up_on_instantiate_override",
Trigger_on_set_self_up_on_instantiate_override
},
{
"on_set_up_on_instantiate_override",
Trigger_on_set_up_on_instantiate_override
},
{
"not_only",
Trigger_not_only
Expand Down Expand Up @@ -11298,7 +11313,7 @@ static bake_test_suite suites[] = {
"Trigger",
NULL,
NULL,
117,
120,
Trigger_testcases
},
{
Expand Down

0 comments on commit f906a4d

Please sign in to comment.