Skip to content
Closed
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
18 changes: 14 additions & 4 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -85722,10 +85722,10 @@ bool flecs_query_trav_fixed_src_up_fixed_second(

/* Check if table has transitive relationship by traversing upwards */
ecs_table_record_t *tr = NULL;
ecs_search_relation(ctx->world, table, 0,
ecs_pair(trav, second), trav, EcsSelf|EcsUp, NULL, NULL, &tr);
const int32_t index = ecs_search_relation(ctx->world, table, 0,
ecs_pair(trav, second), trav, EcsSelf| EcsUp, NULL, NULL, &tr);

if (!tr) {
if (index == -1 || !tr) {
if (op->match_flags & EcsTermReflexive) {
return flecs_query_trav_fixed_src_reflexive(op, ctx,
&range, trav, second);
Expand All @@ -85734,7 +85734,17 @@ bool flecs_query_trav_fixed_src_up_fixed_second(
}
}

flecs_query_set_trav_match(op, tr, trav, second, ctx);
ecs_id_t matched = ecs_pair(trav, second);
if (trav == EcsIsA) {
matched = table->type.array[index];
}

if (op->field_index != -1) {
ecs_iter_t *it = ctx->it;
it->ids [op->field_index] = matched;
flecs_query_it_set_tr(it, op->field_index, tr);
}
flecs_query_set_vars(op, matched, ctx);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion docs/Docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- [Getting Started with Unreal Engine](https://github.com/PreyK/Unreal-Minimum-Viable-Flecs)
- [Unreal-Flecs (Unreal Engine Flecs plugin)](https://github.com/Reddy-dev/Unreal-Flecs)
- [Godot-flecs-sample (example)](https://github.com/paulfigiel/godot-flecs-sample)
- [Flecs-Godot (GDExtension)](https://github.com/VoxInteractive/Godot-Flecs)
- [Stagehand (GDExtension)](https://github.com/VerdantInteractive/Stagehand)
- [Godot-turbo (engine module)](https://github.com/callmefloof/godot-turbo/) ([demo project](https://github.com/callmefloof/godot_turbo_demo_projects))
- [Getting Started with Raylib](https://github.com/kranzky/raylib-flecs-starter-kit)
- [Getting Started with SDL3, ImGui, Sqlite](https://github.com/ilyas-taouaou/CodotakuCMakeRepo) ([video](https://www.youtube.com/watch?v=T32B7nf6B-8))
Expand Down
18 changes: 14 additions & 4 deletions src/query/engine/eval_trav.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ bool flecs_query_trav_fixed_src_up_fixed_second(

/* Check if table has transitive relationship by traversing upwards */
ecs_table_record_t *tr = NULL;
ecs_search_relation(ctx->world, table, 0,
ecs_pair(trav, second), trav, EcsSelf|EcsUp, NULL, NULL, &tr);
const int32_t index = ecs_search_relation(ctx->world, table, 0,
ecs_pair(trav, second), trav, EcsSelf| EcsUp, NULL, NULL, &tr);

if (!tr) {
if (index == -1 || !tr) {
if (op->match_flags & EcsTermReflexive) {
return flecs_query_trav_fixed_src_reflexive(op, ctx,
&range, trav, second);
Expand All @@ -108,7 +108,17 @@ bool flecs_query_trav_fixed_src_up_fixed_second(
}
}

flecs_query_set_trav_match(op, tr, trav, second, ctx);
ecs_id_t matched = ecs_pair(trav, second);
if (trav == EcsIsA) {
matched = table->type.array[index];
}

if (op->field_index != -1) {
ecs_iter_t *it = ctx->it;
it->ids [op->field_index] = matched;
flecs_query_it_set_tr(it, op->field_index, tr);
}
flecs_query_set_vars(op, matched, ctx);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion test/query/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,8 @@
"this_or_w_self_up_childof",
"this_or_w_self_up_childof_2",
"this_or_w_self_up_childof_w_tag",
"this_written_or_w_self_up_childof"
"this_written_or_w_self_up_childof",
"this_written_up_isa_trav_id_n_lvl"
]
}, {
"id": "Cascade",
Expand Down
46 changes: 46 additions & 0 deletions test/query/src/Traversal.c
Original file line number Diff line number Diff line change
Expand Up @@ -13160,3 +13160,49 @@ void Traversal_this_written_or_w_self_up_childof(void) {

ecs_fini(world);
}

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

ECS_COMPONENT(world, Position);
ecs_add_pair(world, ecs_id(Position), EcsOnInstantiate, EcsInherit);

/* Setup: instance --(IsA)--> troll --(IsA)--> enemy
* Position is on troll and inherited by instance.
* Querying (IsA, enemy) on this should match instance and report
* the field ID as (IsA, troll) — the actual pair in the archetype —
* not (IsA, enemy) which was incorrectly reconstructed from arguments
* before the fix in flecs_query_trav_fixed_src_up_fixed_second. */
ecs_entity_t enemy = ecs_new_w_id(world, EcsPrefab);
ecs_entity_t troll = ecs_new_w_id(world, EcsPrefab);
ecs_add_pair(world, troll, EcsIsA, enemy);
ecs_set(world, troll, Position, {10, 20});

ecs_entity_t instance = ecs_new_w_pair(world, EcsIsA, troll);

ecs_query_t *q = ecs_query(world, {
.terms = {
{ ecs_id(Position) }, /* constrains 'this' to tables with Position */
{ .id = ecs_pair(EcsIsA, enemy) } /* transitive IsA check */
},
.cache_kind = cache_kind
});

test_assert(q != NULL);

ecs_iter_t it = ecs_query_iter(world, q);
test_bool(true, ecs_query_next(&it));
test_int(1, it.count);
test_uint(instance, it.entities[0]);
test_uint(ecs_id(Position), ecs_field_id(&it, 0));
test_uint(troll, ecs_field_src(&it, 0));
/* The field ID for the (IsA, enemy) term must be the actual pair stored
* in the instance's archetype: (IsA, troll), not the query target. */
test_uint(ecs_pair(EcsIsA, troll), ecs_field_id(&it, 1));

test_bool(false, ecs_query_next(&it));

ecs_query_fini(q);

ecs_fini(world);
}
Loading