Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 38 additions & 26 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,7 +2610,8 @@ void flecs_invoke_replace_hook(
ecs_id_t id,
const void *old_ptr,
const void *new_ptr,
const ecs_type_info_t *ti);
const ecs_type_info_t *ti,
ecs_table_t *prev_table);

/* Add action for sparse components. */
bool flecs_sparse_on_add(
Expand Down Expand Up @@ -5995,7 +5996,7 @@ void* flecs_defer_set(
/* Call on_replace hook before copying the new value. */
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ti);
world, r->table, entity, id, ptr.ptr, value, ti, r->table);
}

flecs_type_info_copy(ptr.ptr, value, 1, ti);
Expand Down Expand Up @@ -6071,7 +6072,7 @@ void* flecs_defer_cpp_set(
/* Call on_replace hook before copying the new value. */
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ti);
world, r->table, entity, id, ptr.ptr, value, ti, r->table);
}
}

Expand Down Expand Up @@ -6105,7 +6106,7 @@ void* flecs_defer_cpp_assign(
ecs_iter_action_t on_replace = ptr.ti->hooks.on_replace;
if (on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ptr.ti);
world, r->table, entity, id, ptr.ptr, value, ptr.ti, r->table);
}

ecs_cmd_t *cmd = flecs_cmd_new(stage);
Expand Down Expand Up @@ -6474,9 +6475,8 @@ void flecs_cmd_batch_for_entity(
void *ptr = cmd->is._1.value;
const ecs_type_info_t *ti = dst.ti;
if (ti->hooks.on_replace) {
ecs_table_t *prev_table = r->table;
flecs_invoke_replace_hook(world, prev_table, entity,
cmd->id, dst.ptr, ptr, ti);
flecs_invoke_replace_hook(world, r->table, entity,
cmd->id, dst.ptr, ptr, ti, start_table);
if (!r->table) {
/* Entity was deleted */
goto done;
Expand Down Expand Up @@ -6996,7 +6996,8 @@ void flecs_invoke_replace_hook(
ecs_id_t id,
const void *old_ptr,
const void *new_ptr,
const ecs_type_info_t *ti)
const ecs_type_info_t *ti,
ecs_table_t *prev_table)
{
int32_t defer = world->stages[0]->defer;
if (defer < 0) {
Expand Down Expand Up @@ -7029,6 +7030,8 @@ void flecs_invoke_replace_hook(
it.count = 1;
it.offset = 0; /* Don't set row because we don't want to offset ptrs */
it.flags = EcsIterIsValid;
it.other_table = prev_table;
it.set_fields = (1 << 2) - 1;

ti->hooks.on_replace(&it);

Expand Down Expand Up @@ -8697,15 +8700,11 @@ void flecs_copy_id(
const void *src_ptr,
const ecs_type_info_t *ti)
{
(void)entity;
ecs_assert(dst_ptr != NULL, ECS_INTERNAL_ERROR, NULL);
ecs_assert(src_ptr != NULL, ECS_INTERNAL_ERROR, NULL);
(void)size;

if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst_ptr, src_ptr, ti);
}

flecs_type_info_copy(dst_ptr, src_ptr, 1, ti);

flecs_table_mark_dirty(world, r->table, component);
Expand Down Expand Up @@ -8845,9 +8844,9 @@ int flecs_traverse_add(
}

/* Find existing table */
ecs_table_t *src_table = NULL, *table = NULL;
ecs_table_t *src_table = NULL, *table = NULL, *init_table = NULL;
ecs_record_t *r = flecs_entities_get(world, result);
table = r->table;
init_table = table = r->table;

/* Add components from the 'add' array */
if (desc->add) {
Expand Down Expand Up @@ -8925,7 +8924,11 @@ int flecs_traverse_add(
flecs_errstr_2(ecs_get_path(world, result)));

const ecs_type_info_t *ti = cr->type_info;
flecs_copy_id(world, result, r, v->type,
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, result, v->type, ptr.ptr, v->ptr, ti, init_table);
}
flecs_copy_id(world, result, r, v->type,
flecs_itosize(ti->size), ptr.ptr, v->ptr, ti);
}

Expand Down Expand Up @@ -10179,6 +10182,7 @@ void flecs_set_id_move(
}

ecs_record_t *r = flecs_entities_get(world, entity);
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_ensure(
world, entity, component, r, flecs_uto(int32_t, size));
ecs_check(dst.ptr != NULL, ECS_INVALID_PARAMETER, NULL);
Expand All @@ -10188,7 +10192,7 @@ void flecs_set_id_move(

if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst.ptr, ptr, ti);
world, r->table, entity, component, dst.ptr, ptr, ti, prev_table);
}

if (cmd_kind != EcsCmdEmplace) {
Expand Down Expand Up @@ -10250,7 +10254,8 @@ void ecs_set_id(
}

ecs_record_t *r = flecs_entities_get(world, entity);
flecs_component_ptr_t dst = flecs_ensure(world, entity, component, r,
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_ensure(world, entity, component, r,
flecs_uto(int32_t, size));

if (component < FLECS_HI_COMPONENT_ID) {
Expand All @@ -10260,6 +10265,11 @@ void ecs_set_id(
}
}

if (dst.ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst.ptr, ptr, dst.ti, prev_table);
}

flecs_copy_id(world, entity, r, component, size, dst.ptr, ptr, dst.ti);

done:
Expand Down Expand Up @@ -26285,9 +26295,10 @@ ecs_cpp_get_mut_t ecs_cpp_set(
}

ecs_record_t *r = flecs_entities_get(world, entity);
flecs_component_ptr_t dst = flecs_ensure(world, entity, id, r,
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_ensure(world, entity, id, r,
flecs_uto(int32_t, size));

result.ptr = dst.ptr;
result.world = world;
result.stage = stage;
Expand All @@ -26304,10 +26315,10 @@ ecs_cpp_get_mut_t ecs_cpp_set(

if (dst.ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, dst.ptr, new_ptr, dst.ti);
world, r->table, entity, id, dst.ptr, new_ptr, dst.ti, prev_table);
}

done:
done:
return result;
error:
return (ecs_cpp_get_mut_t){0};
Expand Down Expand Up @@ -26336,12 +26347,13 @@ ecs_cpp_get_mut_t ecs_cpp_assign(
}

ecs_record_t *r = flecs_entities_get(world, entity);
flecs_component_ptr_t dst = flecs_get_mut(world, entity, id, r,
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_get_mut(world, entity, id, r,
flecs_uto(int32_t, size));

ecs_assert(dst.ptr != NULL, ECS_INVALID_OPERATION,
ecs_assert(dst.ptr != NULL, ECS_INVALID_OPERATION,
"entity does not have component, use set() instead");

result.ptr = dst.ptr;
result.world = world;
result.stage = stage;
Expand All @@ -26358,7 +26370,7 @@ ecs_cpp_get_mut_t ecs_cpp_assign(

if (dst.ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, dst.ptr, new_ptr, dst.ti);
world, r->table, entity, id, dst.ptr, new_ptr, dst.ti, prev_table);
}

done:
Expand Down
5 changes: 4 additions & 1 deletion distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -4659,7 +4659,10 @@ struct ecs_type_hooks_t {
/** Callback that is invoked with the existing and new value before the
* value is assigned. Invoked after on_add and before on_set. Registering
* an on_replace hook prevents using operations that return a mutable
* pointer to the component, like get_mut(), ensure(), and emplace(). */
* pointer to the component, like get_mut(), ensure(), and emplace().
* The iterator's other_table field is set to the table of the entity
* before the operation. To find out whether the component existed before
* the operation, call ecs_table_has_id() on other_table. */
ecs_iter_action_t on_replace;

/** Callback that is invoked before the on_set/OnSet hooks and observers are
Expand Down
46 changes: 28 additions & 18 deletions distr/flecs_no_addons.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,7 +2610,8 @@ void flecs_invoke_replace_hook(
ecs_id_t id,
const void *old_ptr,
const void *new_ptr,
const ecs_type_info_t *ti);
const ecs_type_info_t *ti,
ecs_table_t *prev_table);

/* Add action for sparse components. */
bool flecs_sparse_on_add(
Expand Down Expand Up @@ -5930,7 +5931,7 @@ void* flecs_defer_set(
/* Call on_replace hook before copying the new value. */
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ti);
world, r->table, entity, id, ptr.ptr, value, ti, r->table);
}

flecs_type_info_copy(ptr.ptr, value, 1, ti);
Expand Down Expand Up @@ -6006,7 +6007,7 @@ void* flecs_defer_cpp_set(
/* Call on_replace hook before copying the new value. */
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ti);
world, r->table, entity, id, ptr.ptr, value, ti, r->table);
}
}

Expand Down Expand Up @@ -6040,7 +6041,7 @@ void* flecs_defer_cpp_assign(
ecs_iter_action_t on_replace = ptr.ti->hooks.on_replace;
if (on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, id, ptr.ptr, value, ptr.ti);
world, r->table, entity, id, ptr.ptr, value, ptr.ti, r->table);
}

ecs_cmd_t *cmd = flecs_cmd_new(stage);
Expand Down Expand Up @@ -6409,9 +6410,8 @@ void flecs_cmd_batch_for_entity(
void *ptr = cmd->is._1.value;
const ecs_type_info_t *ti = dst.ti;
if (ti->hooks.on_replace) {
ecs_table_t *prev_table = r->table;
flecs_invoke_replace_hook(world, prev_table, entity,
cmd->id, dst.ptr, ptr, ti);
flecs_invoke_replace_hook(world, r->table, entity,
cmd->id, dst.ptr, ptr, ti, start_table);
if (!r->table) {
/* Entity was deleted */
goto done;
Expand Down Expand Up @@ -6931,7 +6931,8 @@ void flecs_invoke_replace_hook(
ecs_id_t id,
const void *old_ptr,
const void *new_ptr,
const ecs_type_info_t *ti)
const ecs_type_info_t *ti,
ecs_table_t *prev_table)
{
int32_t defer = world->stages[0]->defer;
if (defer < 0) {
Expand Down Expand Up @@ -6964,6 +6965,8 @@ void flecs_invoke_replace_hook(
it.count = 1;
it.offset = 0; /* Don't set row because we don't want to offset ptrs */
it.flags = EcsIterIsValid;
it.other_table = prev_table;
it.set_fields = (1 << 2) - 1;

ti->hooks.on_replace(&it);

Expand Down Expand Up @@ -8602,15 +8605,11 @@ void flecs_copy_id(
const void *src_ptr,
const ecs_type_info_t *ti)
{
(void)entity;
ecs_assert(dst_ptr != NULL, ECS_INTERNAL_ERROR, NULL);
ecs_assert(src_ptr != NULL, ECS_INTERNAL_ERROR, NULL);
(void)size;

if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst_ptr, src_ptr, ti);
}

flecs_type_info_copy(dst_ptr, src_ptr, 1, ti);

flecs_table_mark_dirty(world, r->table, component);
Expand Down Expand Up @@ -8710,9 +8709,9 @@ int flecs_traverse_add(
}

/* Find existing table */
ecs_table_t *src_table = NULL, *table = NULL;
ecs_table_t *src_table = NULL, *table = NULL, *init_table = NULL;
ecs_record_t *r = flecs_entities_get(world, result);
table = r->table;
init_table = table = r->table;

/* Add components from the 'add' array */
if (desc->add) {
Expand Down Expand Up @@ -8790,7 +8789,11 @@ int flecs_traverse_add(
flecs_errstr_2(ecs_get_path(world, result)));

const ecs_type_info_t *ti = cr->type_info;
flecs_copy_id(world, result, r, v->type,
if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, result, v->type, ptr.ptr, v->ptr, ti, init_table);
}
flecs_copy_id(world, result, r, v->type,
flecs_itosize(ti->size), ptr.ptr, v->ptr, ti);
}

Expand Down Expand Up @@ -10044,6 +10047,7 @@ void flecs_set_id_move(
}

ecs_record_t *r = flecs_entities_get(world, entity);
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_ensure(
world, entity, component, r, flecs_uto(int32_t, size));
ecs_check(dst.ptr != NULL, ECS_INVALID_PARAMETER, NULL);
Expand All @@ -10053,7 +10057,7 @@ void flecs_set_id_move(

if (ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst.ptr, ptr, ti);
world, r->table, entity, component, dst.ptr, ptr, ti, prev_table);
}

if (cmd_kind != EcsCmdEmplace) {
Expand Down Expand Up @@ -10115,7 +10119,8 @@ void ecs_set_id(
}

ecs_record_t *r = flecs_entities_get(world, entity);
flecs_component_ptr_t dst = flecs_ensure(world, entity, component, r,
ecs_table_t *prev_table = r->table;
flecs_component_ptr_t dst = flecs_ensure(world, entity, component, r,
flecs_uto(int32_t, size));

if (component < FLECS_HI_COMPONENT_ID) {
Expand All @@ -10125,6 +10130,11 @@ void ecs_set_id(
}
}

if (dst.ti->hooks.on_replace) {
flecs_invoke_replace_hook(
world, r->table, entity, component, dst.ptr, ptr, dst.ti, prev_table);
}

flecs_copy_id(world, entity, r, component, size, dst.ptr, ptr, dst.ti);

done:
Expand Down
5 changes: 4 additions & 1 deletion distr/flecs_no_addons.h
Original file line number Diff line number Diff line change
Expand Up @@ -4632,7 +4632,10 @@ struct ecs_type_hooks_t {
/** Callback that is invoked with the existing and new value before the
* value is assigned. Invoked after on_add and before on_set. Registering
* an on_replace hook prevents using operations that return a mutable
* pointer to the component, like get_mut(), ensure(), and emplace(). */
* pointer to the component, like get_mut(), ensure(), and emplace().
* The iterator's other_table field is set to the table of the entity
* before the operation. To find out whether the component existed before
* the operation, call ecs_table_has_id() on other_table. */
ecs_iter_action_t on_replace;

/** Callback that is invoked before the on_set/OnSet hooks and observers are
Expand Down
5 changes: 4 additions & 1 deletion include/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,10 @@ struct ecs_type_hooks_t {
/** Callback that is invoked with the existing and new value before the
* value is assigned. Invoked after on_add and before on_set. Registering
* an on_replace hook prevents using operations that return a mutable
* pointer to the component, like get_mut(), ensure(), and emplace(). */
* pointer to the component, like get_mut(), ensure(), and emplace().
* The iterator's other_table field is set to the table of the entity
* before the operation. To find out whether the component existed before
* the operation, call ecs_table_has_id() on other_table. */
ecs_iter_action_t on_replace;

/** Callback that is invoked before the on_set/OnSet hooks and observers are
Expand Down
Loading
Loading