Skip to content

Commit e385364

Browse files
authored
Merge branch 'SanderMertens:master' into master
2 parents 28a5b72 + 4069f83 commit e385364

8 files changed

Lines changed: 201 additions & 16 deletions

File tree

distr/flecs.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6648,8 +6648,7 @@ void flecs_cmd_batch_for_entity(
66486648
* monitors since queries will have correctly matched them. */
66496649
ecs_component_record_t *cr = flecs_components_get(
66506650
world, ecs_pair(EcsWildcard, entity));
6651-
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
6652-
if (ecs_map_count(&cr->cache.index)) {
6651+
if (cr && ecs_map_count(&cr->cache.index)) {
66536652
flecs_update_component_monitors(world, &added, NULL);
66546653
}
66556654
}
@@ -40180,10 +40179,19 @@ void flecs_component_delete_sparse(
4018040179
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
4018140180
ecs_assert(cr->flags & EcsIdSparse, ECS_INTERNAL_ERROR, NULL);
4018240181
int32_t i, count = flecs_sparse_count(cr->sparse);
40182+
if (!count) {
40183+
return;
40184+
}
40185+
4018340186
const uint64_t *entities = flecs_sparse_ids(cr->sparse);
40187+
ecs_entity_t *to_delete = ecs_os_malloc_n(ecs_entity_t, count);
40188+
ecs_os_memcpy_n(to_delete, entities, ecs_entity_t, count);
40189+
4018440190
for (i = 0; i < count; i ++) {
40185-
ecs_delete(world, entities[i]);
40191+
ecs_delete(world, to_delete[i]);
4018640192
}
40193+
40194+
ecs_os_free(to_delete);
4018740195
}
4018840196

4018940197
ecs_component_record_t* flecs_component_first_next(
@@ -40281,7 +40289,7 @@ void flecs_entities_update_childof_depth(
4028140289
ecs_component_record_t *tgt_cr = flecs_components_get(
4028240290
world, ecs_childof(tgt));
4028340291
if (!tgt_cr) {
40284-
return;
40292+
continue;
4028540293
}
4028640294

4028740295
flecs_component_update_childof_depth(world, tgt_cr, tgt, r);
@@ -40305,7 +40313,7 @@ void flecs_entities_update_childof_depth(
4030540313
ecs_component_record_t *tgt_cr = flecs_components_get(
4030640314
world, ecs_childof(tgt));
4030740315
if (!tgt_cr) {
40308-
return;
40316+
continue;
4030940317
}
4031040318

4031140319
ecs_record_t *r = flecs_entities_get(world, tgt);
@@ -41159,7 +41167,7 @@ void flecs_non_fragmenting_childof_reparent(
4115941167

4116041168
const ecs_entity_t *entities = ecs_table_entities(dst);
4116141169
int32_t i = row, end = i + count;
41162-
for (i = 0; i < end; i ++) {
41170+
for (; i < end; i ++) {
4116341171
ecs_entity_t e = entities[i];
4116441172
ecs_component_record_t *cr = flecs_components_get(
4116541173
world, ecs_childof(e));
@@ -41204,7 +41212,7 @@ void flecs_non_fragmenting_childof_unparent(
4120441212

4120541213
const ecs_entity_t *entities = ecs_table_entities(src);
4120641214
int32_t i = row, end = i + count;
41207-
for (i = 0; i < end; i ++) {
41215+
for (; i < end; i ++) {
4120841216
ecs_entity_t e = entities[i];
4120941217
ecs_component_record_t *cr = flecs_components_get(
4121041218
world, ecs_childof(e));

src/commands.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,8 +1055,7 @@ void flecs_cmd_batch_for_entity(
10551055
* monitors since queries will have correctly matched them. */
10561056
ecs_component_record_t *cr = flecs_components_get(
10571057
world, ecs_pair(EcsWildcard, entity));
1058-
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
1059-
if (ecs_map_count(&cr->cache.index)) {
1058+
if (cr && ecs_map_count(&cr->cache.index)) {
10601059
flecs_update_component_monitors(world, &added, NULL);
10611060
}
10621061
}

src/storage/component_index.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,10 +1035,19 @@ void flecs_component_delete_sparse(
10351035
ecs_assert(cr != NULL, ECS_INTERNAL_ERROR, NULL);
10361036
ecs_assert(cr->flags & EcsIdSparse, ECS_INTERNAL_ERROR, NULL);
10371037
int32_t i, count = flecs_sparse_count(cr->sparse);
1038+
if (!count) {
1039+
return;
1040+
}
1041+
10381042
const uint64_t *entities = flecs_sparse_ids(cr->sparse);
1043+
ecs_entity_t *to_delete = ecs_os_malloc_n(ecs_entity_t, count);
1044+
ecs_os_memcpy_n(to_delete, entities, ecs_entity_t, count);
1045+
10391046
for (i = 0; i < count; i ++) {
1040-
ecs_delete(world, entities[i]);
1047+
ecs_delete(world, to_delete[i]);
10411048
}
1049+
1050+
ecs_os_free(to_delete);
10421051
}
10431052

10441053
ecs_component_record_t* flecs_component_first_next(
@@ -1136,7 +1145,7 @@ void flecs_entities_update_childof_depth(
11361145
ecs_component_record_t *tgt_cr = flecs_components_get(
11371146
world, ecs_childof(tgt));
11381147
if (!tgt_cr) {
1139-
return;
1148+
continue;
11401149
}
11411150

11421151
flecs_component_update_childof_depth(world, tgt_cr, tgt, r);
@@ -1160,7 +1169,7 @@ void flecs_entities_update_childof_depth(
11601169
ecs_component_record_t *tgt_cr = flecs_components_get(
11611170
world, ecs_childof(tgt));
11621171
if (!tgt_cr) {
1163-
return;
1172+
continue;
11641173
}
11651174

11661175
ecs_record_t *r = flecs_entities_get(world, tgt);

src/storage/non_fragmenting_childof.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ void flecs_non_fragmenting_childof_reparent(
365365

366366
const ecs_entity_t *entities = ecs_table_entities(dst);
367367
int32_t i = row, end = i + count;
368-
for (i = 0; i < end; i ++) {
368+
for (; i < end; i ++) {
369369
ecs_entity_t e = entities[i];
370370
ecs_component_record_t *cr = flecs_components_get(
371371
world, ecs_childof(e));
@@ -410,7 +410,7 @@ void flecs_non_fragmenting_childof_unparent(
410410

411411
const ecs_entity_t *entities = ecs_table_entities(src);
412412
int32_t i = row, end = i + count;
413-
for (i = 0; i < end; i ++) {
413+
for (; i < end; i ++) {
414414
ecs_entity_t e = entities[i];
415415
ecs_component_record_t *cr = flecs_components_get(
416416
world, ecs_childof(e));

test/core/project.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@
689689
"on_delete_sparse_panic",
690690
"on_delete_target_sparse_remove",
691691
"on_delete_target_sparse_delete",
692+
"component_delete_sparse_multiple_entities",
692693
"on_delete_target_sparse_panic",
693694
"delete_relationship",
694695
"delete_parent_of_relationship",
@@ -791,6 +792,8 @@
791792
"depth_after_parent_remove",
792793
"depth_after_parent_set_parent",
793794
"depth_after_parent_remove_parent",
795+
"depth_after_parent_remove_other_sibling_parent",
796+
"depth_after_parent_set_parent_sibling_traversable_no_children",
794797
"depth_after_parent_reparent",
795798
"depth_after_parent_reparent_different_depth",
796799
"depth_after_parent_set_parent_nested",
@@ -902,6 +905,7 @@
902905
"delete_tree_4",
903906
"delete_tree_5",
904907
"delete_tree_6",
908+
"delete_tree_7",
905909
"add_parent_to_childof_child",
906910
"add_childof_to_parent_child",
907911
"add_parent_to_childof_child_same_parent",

test/core/src/NonFragmentingChildOf.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,6 +1582,76 @@ void NonFragmentingChildOf_depth_after_parent_remove_parent(void) {
15821582
ecs_fini(world);
15831583
}
15841584

1585+
void NonFragmentingChildOf_depth_after_parent_remove_other_sibling_parent(void) {
1586+
ecs_world_t *world = ecs_mini();
1587+
1588+
ecs_entity_t base = ecs_new_w_id(world, EcsPrefab);
1589+
ecs_insert(world, ecs_value(EcsParent, {base}));
1590+
1591+
ecs_entity_t p = ecs_new(world);
1592+
1593+
ecs_entity_t c1 = ecs_new_w_pair(world, EcsIsA, base);
1594+
ecs_add_pair(world, c1, EcsChildOf, p);
1595+
ecs_entities_t c1_children = ecs_get_ordered_children(world, c1);
1596+
test_int(c1_children.count, 1);
1597+
ecs_entity_t gc1 = c1_children.ids[0];
1598+
1599+
ecs_entity_t c2 = ecs_new_w_pair(world, EcsIsA, base);
1600+
ecs_add_pair(world, c2, EcsChildOf, p);
1601+
ecs_entities_t c2_children = ecs_get_ordered_children(world, c2);
1602+
test_int(c2_children.count, 1);
1603+
ecs_entity_t gc2 = c2_children.ids[0];
1604+
1605+
test_assert(ecs_has_id(world, gc1, ecs_value_pair(EcsParentDepth, 2)));
1606+
test_assert(ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 2)));
1607+
1608+
ecs_remove_pair(world, c2, EcsChildOf, EcsWildcard);
1609+
1610+
test_assert(ecs_has_id(world, gc1, ecs_value_pair(EcsParentDepth, 2)));
1611+
test_assert(!ecs_has_id(world, gc1, ecs_value_pair(EcsParentDepth, 1)));
1612+
1613+
test_assert(ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 1)));
1614+
test_assert(!ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 2)));
1615+
1616+
ecs_fini(world);
1617+
}
1618+
1619+
void NonFragmentingChildOf_depth_after_parent_set_parent_sibling_traversable_no_children(void) {
1620+
ecs_world_t *world = ecs_mini();
1621+
1622+
ecs_entity_t root = ecs_new(world);
1623+
ecs_entity_t p = ecs_new(world);
1624+
ecs_entity_t c1 = ecs_insert(world, ecs_value(EcsParent, {p}));
1625+
ecs_entity_t c2 = ecs_insert(world, ecs_value(EcsParent, {p}));
1626+
ecs_add_id(world, c2, EcsOrderedChildren);
1627+
ecs_entity_t gc2 = ecs_insert(world, ecs_value(EcsParent, {c2}));
1628+
1629+
/* Make first sibling traversable without creating ChildOf record for it. */
1630+
ecs_new_w_pair(world, EcsIsA, c1);
1631+
1632+
ecs_entities_t children = ecs_get_ordered_children(world, p);
1633+
test_int(children.count, 2);
1634+
test_uint(children.ids[0], c1);
1635+
test_uint(children.ids[1], c2);
1636+
1637+
test_assert(ecs_has_id(world, c1, ecs_value_pair(EcsParentDepth, 1)));
1638+
test_assert(ecs_has_id(world, c2, ecs_value_pair(EcsParentDepth, 1)));
1639+
test_assert(ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 2)));
1640+
1641+
ecs_set(world, p, EcsParent, {root});
1642+
1643+
test_assert(ecs_has_id(world, c1, ecs_value_pair(EcsParentDepth, 2)));
1644+
test_assert(!ecs_has_id(world, c1, ecs_value_pair(EcsParentDepth, 1)));
1645+
1646+
test_assert(ecs_has_id(world, c2, ecs_value_pair(EcsParentDepth, 2)));
1647+
test_assert(!ecs_has_id(world, c2, ecs_value_pair(EcsParentDepth, 1)));
1648+
1649+
test_assert(ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 3)));
1650+
test_assert(!ecs_has_id(world, gc2, ecs_value_pair(EcsParentDepth, 2)));
1651+
1652+
ecs_fini(world);
1653+
}
1654+
15851655
void NonFragmentingChildOf_depth_after_parent_reparent(void) {
15861656
ecs_world_t *world = ecs_mini();
15871657

@@ -4361,6 +4431,55 @@ void NonFragmentingChildOf_delete_tree_6(void) {
43614431
ecs_fini(world);
43624432
}
43634433

4434+
static ECS_TAG_DECLARE(Foo);
4435+
static ECS_TAG_DECLARE(Bar);
4436+
4437+
static void observer_on_remove_position_up(ecs_iter_t *it) {
4438+
if (it->sources[0] != 0) {
4439+
ecs_entity_t src = it->sources[0];
4440+
if (ecs_is_alive(it->world, src) && !ecs_has(it->world, src, Foo)) {
4441+
ecs_add(it->world, src, Bar);
4442+
}
4443+
}
4444+
}
4445+
4446+
void NonFragmentingChildOf_delete_tree_7(void) {
4447+
ecs_world_t *world = ecs_mini();
4448+
4449+
ECS_COMPONENT_DEFINE(world, Position);
4450+
ECS_TAG_DEFINE(world, Foo);
4451+
ECS_TAG_DEFINE(world, Bar);
4452+
4453+
ecs_observer(world, {
4454+
.query.terms = {{
4455+
.id = ecs_id(Position),
4456+
.src.id = EcsUp,
4457+
.trav = EcsChildOf
4458+
}},
4459+
.events = { EcsOnRemove },
4460+
.callback = observer_on_remove_position_up
4461+
});
4462+
4463+
ecs_entity_t G = ecs_new_w(world, Position);
4464+
ecs_entity_t Q = ecs_new_w_parent(world, G, NULL);
4465+
ecs_entity_t P = ecs_new_w_parent(world, G, NULL);
4466+
4467+
ecs_add(world, P, Position);
4468+
4469+
ecs_entity_t C1 = ecs_new(world);
4470+
ecs_add_pair(world, C1, EcsChildOf, P);
4471+
ecs_add(world, C1, Bar);
4472+
4473+
ecs_delete(world, G);
4474+
4475+
test_assert(!ecs_is_alive(world, G));
4476+
test_assert(!ecs_is_alive(world, Q));
4477+
test_assert(!ecs_is_alive(world, P));
4478+
test_assert(!ecs_is_alive(world, C1));
4479+
4480+
ecs_fini(world);
4481+
}
4482+
43644483
void NonFragmentingChildOf_add_parent_to_childof_child(void) {
43654484
ecs_world_t* world = ecs_mini();
43664485

test/core/src/Sparse.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5690,6 +5690,32 @@ void Sparse_on_delete_sparse_delete(void) {
56905690
ecs_fini(world);
56915691
}
56925692

5693+
void Sparse_component_delete_sparse_multiple_entities(void) {
5694+
ecs_world_t *world = ecs_mini();
5695+
5696+
ECS_COMPONENT(world, Position);
5697+
5698+
ecs_add_id(world, ecs_id(Position), EcsSparse);
5699+
ecs_add_id(world, ecs_id(Position), EcsDontFragment);
5700+
ecs_add_pair(world, ecs_id(Position), EcsOnDelete, EcsDelete);
5701+
5702+
ecs_entity_t e1 = ecs_new_w(world, Position);
5703+
ecs_entity_t e2 = ecs_new_w(world, Position);
5704+
test_assert(ecs_has(world, e1, Position));
5705+
test_assert(ecs_has(world, e2, Position));
5706+
5707+
ecs_defer_begin(world);
5708+
ecs_defer_suspend(world);
5709+
ecs_delete_with(world, ecs_id(Position));
5710+
ecs_defer_resume(world);
5711+
ecs_defer_end(world);
5712+
5713+
test_assert(!ecs_is_alive(world, e1));
5714+
test_assert(!ecs_is_alive(world, e2));
5715+
5716+
ecs_fini(world);
5717+
}
5718+
56935719
void Sparse_on_delete_sparse_panic(void) {
56945720
install_test_abort();
56955721

0 commit comments

Comments
 (0)