Skip to content
Closed
155 changes: 115 additions & 40 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2718,18 +2718,33 @@ void flecs_enqueue(
#ifndef FLECS_ENTITY_H
#define FLECS_ENTITY_H

#ifdef FLECS_SAFETY_LOCKS
#define FLECS_SI_INIT(cr_, table_, col_) \
.si = (ecs_safety_info_t){ .cr = (cr_), .table = (table_), .column_index = (int16_t)(col_) },
#else
#define FLECS_SI_INIT(cr_, table_, col_) /* nothing */
#endif

#define ecs_get_low_id(table, r, id)\
ecs_assert(table->component_map != NULL, ECS_INTERNAL_ERROR, NULL);\
int16_t column_index = table->component_map[id];\
if (column_index > 0) {\
ecs_column_t *column = &table->data.columns[column_index - 1];\
return ECS_ELEM(column->data, column->ti->size, \
--column_index;\
ecs_column_t *column = &table->data.columns[column_index];\
void *ptr = ECS_ELEM(column->data, column->ti->size, \
ECS_RECORD_TO_ROW(r->row));\
return (ecs_get_ptr_t){\
.component_ptr = ptr,\
FLECS_SI_INIT(NULL, table, column_index)\
};\
}

typedef struct {
const ecs_type_info_t *ti;
void *ptr;
#ifdef FLECS_SAFETY_LOCKS
ecs_safety_info_t si;
#endif
} flecs_component_ptr_t;

flecs_component_ptr_t flecs_ensure(
Expand Down Expand Up @@ -2805,7 +2820,7 @@ int32_t flecs_relation_depth(
const ecs_table_t *table);

/* Get component from base entity (follows IsA relationship) */
void* flecs_get_base_component(
ecs_get_ptr_t flecs_get_base_component(
const ecs_world_t *world,
ecs_table_t *table,
ecs_id_t id,
Expand Down Expand Up @@ -5510,7 +5525,7 @@ void* flecs_defer_ensure(
void *base = NULL;
if (table && (table->flags & EcsTableHasIsA)) {
ecs_component_record_t *cr = flecs_components_get(world, id);
base = flecs_get_base_component(world, table, id, cr, 0);
base = flecs_get_base_component(world, table, id, cr, 0).component_ptr;
}

if (!base) {
Expand Down Expand Up @@ -7281,7 +7296,8 @@ flecs_component_ptr_t flecs_table_get_component(
ecs_column_t *column = &table->data.columns[column_index];
return (flecs_component_ptr_t){
.ti = column->ti,
.ptr = ECS_ELEM(column->data, column->ti->size, row)
.ptr = ECS_ELEM(column->data, column->ti->size, row),
FLECS_SI_INIT(NULL, table, column_index)
};
}

Expand All @@ -7301,7 +7317,8 @@ flecs_component_ptr_t flecs_get_component_ptr(
ecs_entity_t entity = ecs_table_entities(table)[row];
return (flecs_component_ptr_t){
.ti = cr->type_info,
.ptr = flecs_component_sparse_get(world, cr, table, entity)
.ptr = flecs_component_sparse_get(world, cr, table, entity),
FLECS_SI_INIT(cr, NULL, -1)
};
}

Expand All @@ -7322,7 +7339,7 @@ void* flecs_get_component(
return flecs_get_component_ptr(world, table, row, cr).ptr;
}

void* flecs_get_base_component(
ecs_get_ptr_t flecs_get_base_component(
const ecs_world_t *world,
ecs_table_t *table,
ecs_id_t component,
Expand All @@ -7334,16 +7351,16 @@ void* flecs_get_base_component(

/* Table (and thus entity) does not have component, look for base */
if (!(table->flags & EcsTableHasIsA)) {
return NULL;
return (ecs_get_ptr_t){0};
}

if (!(cr->flags & EcsIdOnInstantiateInherit)) {
return NULL;
return (ecs_get_ptr_t){0};
}

/* Exclude Name */
if (component == ecs_pair(ecs_id(EcsIdentifier), EcsName)) {
return NULL;
return (ecs_get_ptr_t){0};
}

/* Table should always be in the table index for (IsA, *), otherwise the
Expand All @@ -7355,7 +7372,7 @@ void* flecs_get_base_component(
ecs_type_t type = table->type;
ecs_id_t *ids = type.array;
int32_t i = tr_isa->index, end = tr_isa->count + tr_isa->index;
void *ptr = NULL;
ecs_get_ptr_t ptr = {0};

do {
ecs_id_t pair = ids[i ++];
Expand All @@ -7370,26 +7387,39 @@ void* flecs_get_base_component(
const ecs_table_record_t *tr = flecs_component_get_table(cr, table);
if (!tr) {
if (cr->flags & EcsIdDontFragment) {
ptr = flecs_component_sparse_get(world, cr, table, base);
void *sparse_ptr = flecs_component_sparse_get(world, cr, table, base);
ptr = (ecs_get_ptr_t){
.component_ptr = sparse_ptr,
FLECS_SI_INIT(cr, NULL, -1)
};
}

if (!ptr) {
if (!ptr.component_ptr) {
ptr = flecs_get_base_component(world, table, component, cr,
recur_depth + 1);
}
} else {
if (cr->flags & EcsIdIsSparse) {
return flecs_component_sparse_get(world, cr, table, base);
void *sparse_ptr = flecs_component_sparse_get(world, cr, table, base);
return (ecs_get_ptr_t){
.component_ptr = sparse_ptr,
FLECS_SI_INIT(cr, NULL, -1)
};
} else {
int32_t row = ECS_RECORD_TO_ROW(r->row);
return flecs_table_get_component(table, tr->column, row).ptr;
int16_t column = tr->column;
void *get_ptr = flecs_table_get_component(table, column, row).ptr;
return (ecs_get_ptr_t){
.component_ptr = get_ptr,
FLECS_SI_INIT(NULL, table, column)
};
}
}
} while (!ptr && (i < end));
} while (!ptr.component_ptr && (i < end));

return ptr;
error:
return NULL;
return (ecs_get_ptr_t){0};
}

ecs_entity_t flecs_new_id(
Expand Down Expand Up @@ -9143,40 +9173,40 @@ ecs_entity_t ecs_clone(
return 0;
}

const void* ecs_get_id(
ecs_get_ptr_t flecs_get_id_from_record(
const ecs_world_t *world,
ecs_entity_t entity,
const ecs_record_t *r,
ecs_id_t component)
{
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);
flecs_assert_entity_valid(world, entity, "get");
ecs_assert(r != NULL, ECS_INVALID_PARAMETER, NULL);
ecs_check(ecs_id_is_valid(world, component) || ecs_id_is_wildcard(component),
ECS_INVALID_PARAMETER, NULL);

world = ecs_get_world(world);

ecs_record_t *r = flecs_entities_get(world, entity);
ecs_assert(r != NULL, ECS_INVALID_PARAMETER, NULL);

ecs_table_t *table = r->table;
ecs_assert(table != NULL, ECS_INTERNAL_ERROR, NULL);

if (component < FLECS_HI_COMPONENT_ID) {
if (!world->non_trivial_lookup[component]) {
ecs_get_low_id(table, r, component);
return NULL;
return (ecs_get_ptr_t){0};
}
}

ecs_component_record_t *cr = flecs_components_get(world, component);
if (!cr) {
return NULL;
return (ecs_get_ptr_t){0};
}

if (cr->flags & EcsIdDontFragment) {
void *ptr = flecs_component_sparse_get(world, cr, table, entity);
if (ptr) {
return ptr;
return (ecs_get_ptr_t){
.component_ptr = ptr,
FLECS_SI_INIT(cr, NULL, -1)
};
}
}

Expand All @@ -9185,15 +9215,40 @@ const void* ecs_get_id(
return flecs_get_base_component(world, table, component, cr, 0);
} else {
if (cr->flags & EcsIdIsSparse) {
return flecs_component_sparse_get(world, cr, table, entity);
void *sparse_ptr = flecs_component_sparse_get(world, cr, table, entity);
return (ecs_get_ptr_t){
.component_ptr = sparse_ptr,
FLECS_SI_INIT(cr, NULL, -1)
};
}
ecs_check(tr->column != -1, ECS_INVALID_PARAMETER,
"component '%s' passed to get() is a tag/zero sized",
flecs_errstr(ecs_id_str(world, component)));
}

int32_t row = ECS_RECORD_TO_ROW(r->row);
return flecs_table_get_component(table, tr->column, row).ptr;
int32_t column_index = tr->column;
void *get_ptr = flecs_table_get_component(table, column_index, row).ptr;
return (ecs_get_ptr_t){
.component_ptr = get_ptr,
FLECS_SI_INIT(NULL, table, column_index)
};
error:
return (ecs_get_ptr_t){0};
}

const void* ecs_get_id(
const ecs_world_t *world,
ecs_entity_t entity,
ecs_id_t component)
{
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);

world = ecs_get_world(world);

ecs_record_t *r = flecs_entities_get(world, entity);

return flecs_get_id_from_record(world, entity, r, component).component_ptr;
error:
return NULL;
}
Expand All @@ -9215,37 +9270,57 @@ bool flecs_component_has_on_replace(
}
#endif

void* ecs_get_mut_id(
ecs_get_ptr_t flecs_get_mut_id_from_record(
const ecs_world_t *world,
ecs_entity_t entity,
const ecs_record_t *r,
ecs_id_t component)
{
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);
flecs_assert_entity_valid(world, entity, "get_mut");
flecs_assert_component_valid(world, entity, component, "get_mut");
flecs_poly_assert(world, ecs_world_t);
ecs_assert(r != NULL, ECS_INVALID_PARAMETER, NULL);
ecs_dbg_assert(!flecs_component_has_on_replace(world, component, "get_mut"),
ECS_INVALID_PARAMETER,
"cannot call get_mut() for component '%s' which has an on_replace hook "
"(use set()/assign())",
flecs_errstr(ecs_id_str(world, component)));

world = ecs_get_world(world);

flecs_check_exclusive_world_access_write(world);

ecs_record_t *r = flecs_entities_get(world, entity);
ecs_assert(r != NULL, ECS_INVALID_PARAMETER, NULL);

if (component < FLECS_HI_COMPONENT_ID) {
if (!world->non_trivial_lookup[component]) {
ecs_get_low_id(r->table, r, component);
return NULL;
return (ecs_get_ptr_t){0};
}
}

ecs_component_record_t *cr = flecs_components_get(world, component);
int32_t row = ECS_RECORD_TO_ROW(r->row);
return flecs_get_component_ptr(world, r->table, row, cr).ptr;
flecs_component_ptr_t component_ptr = flecs_get_component_ptr(world, r->table, row, cr);
return (ecs_get_ptr_t) {
.component_ptr = component_ptr.ptr
#ifdef FLECS_SAFETY_LOCKS
, .si = component_ptr.si
#endif
};
error:
return (ecs_get_ptr_t){0};
}

void* ecs_get_mut_id(
const ecs_world_t *world,
ecs_entity_t entity,
ecs_id_t component)
{
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);
flecs_assert_entity_valid(world, entity, "get_mut");
flecs_assert_component_valid(world, entity, component, "get_mut");

world = ecs_get_world(world);

ecs_record_t *r = flecs_entities_get(world, entity);

return flecs_get_mut_id_from_record(world, r, component).component_ptr;

error:
return NULL;
}
Expand Down Expand Up @@ -9841,7 +9916,7 @@ bool ecs_has_id(
return true;
} else {
return flecs_get_base_component(
world, table, component, cr, 0) != NULL;
world, table, component, cr, 0).component_ptr != NULL;
}
}

Expand Down
Loading
Loading