Skip to content

Commit

Permalink
Fix flecs script issue with scope assignment inside with scope
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Sep 22, 2023
1 parent 5c29f9d commit e7a045b
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 30 deletions.
37 changes: 23 additions & 14 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31515,6 +31515,26 @@ ecs_entity_t plecs_lookup_action(
return plecs_lookup(world, path, ctx, 0, false);
}

static
void plecs_apply_with_frame(
ecs_world_t *world,
plecs_state_t *state,
ecs_entity_t e)
{
int32_t i, frame_count = state->with_frames[state->sp];
for (i = 0; i < frame_count; i ++) {
ecs_id_t id = state->with[i];
plecs_with_value_t *v = &state->with_value_frames[i];
if (v->value.type) {
void *ptr = ecs_get_mut_id(world, e, id);
ecs_value_copy(world, v->value.type, ptr, v->value.ptr);
ecs_modified_id(world, e, id);
} else {
ecs_add_id(world, e, id);
}
}
}

static
ecs_entity_t plecs_ensure_entity(
ecs_world_t *world,
Expand Down Expand Up @@ -31845,21 +31865,9 @@ int plecs_create_term(
}

state->with[state->with_frame ++] = id;

} else {
if (subj) {
int32_t i, frame_count = state->with_frames[state->sp];
for (i = 0; i < frame_count; i ++) {
ecs_id_t id = state->with[i];
plecs_with_value_t *v = &state->with_value_frames[i];
if (v->value.type) {
void *ptr = ecs_get_mut_id(world, subj, id);
ecs_value_copy(world, v->value.type, ptr, v->value.ptr);
ecs_modified_id(world, subj, id);
} else {
ecs_add_id(world, subj, id);
}
}
if (subj && !state->scope_assign_stmt) {
plecs_apply_with_frame(world, state, subj);
}
}

Expand Down Expand Up @@ -32623,6 +32631,7 @@ const char* plecs_parse_scope_open(
state->scope[state->sp] = state->scope[state->sp - 1];
state->default_scope_type[state->sp] =
state->default_scope_type[state->sp - 1];
state->assign_to = 0;
}

state->using_frames[state->sp] = state->using_frame;
Expand Down
37 changes: 23 additions & 14 deletions src/addons/plecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,26 @@ ecs_entity_t plecs_lookup_action(
return plecs_lookup(world, path, ctx, 0, false);
}

static
void plecs_apply_with_frame(
ecs_world_t *world,
plecs_state_t *state,
ecs_entity_t e)
{
int32_t i, frame_count = state->with_frames[state->sp];
for (i = 0; i < frame_count; i ++) {
ecs_id_t id = state->with[i];
plecs_with_value_t *v = &state->with_value_frames[i];
if (v->value.type) {
void *ptr = ecs_get_mut_id(world, e, id);
ecs_value_copy(world, v->value.type, ptr, v->value.ptr);
ecs_modified_id(world, e, id);
} else {
ecs_add_id(world, e, id);
}
}
}

static
ecs_entity_t plecs_ensure_entity(
ecs_world_t *world,
Expand Down Expand Up @@ -784,21 +804,9 @@ int plecs_create_term(
}

state->with[state->with_frame ++] = id;

} else {
if (subj) {
int32_t i, frame_count = state->with_frames[state->sp];
for (i = 0; i < frame_count; i ++) {
ecs_id_t id = state->with[i];
plecs_with_value_t *v = &state->with_value_frames[i];
if (v->value.type) {
void *ptr = ecs_get_mut_id(world, subj, id);
ecs_value_copy(world, v->value.type, ptr, v->value.ptr);
ecs_modified_id(world, subj, id);
} else {
ecs_add_id(world, subj, id);
}
}
if (subj && !state->scope_assign_stmt) {
plecs_apply_with_frame(world, state, subj);
}
}

Expand Down Expand Up @@ -1562,6 +1570,7 @@ const char* plecs_parse_scope_open(
state->scope[state->sp] = state->scope[state->sp - 1];
state->default_scope_type[state->sp] =
state->default_scope_type[state->sp - 1];
state->assign_to = 0;
}

state->using_frames[state->sp] = state->using_frame;
Expand Down
5 changes: 4 additions & 1 deletion test/addons/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,10 @@
"pair_w_rel_var",
"pair_w_tgt_var",
"assembly_w_pair_w_this_var",
"with_value_not_a_component"
"with_value_not_a_component",
"component_in_with_scope",
"component_in_with_scope_in_scope",
"assign_after_with_in_scope"
]
}, {
"id": "Doc",
Expand Down
116 changes: 116 additions & 0 deletions test/addons/src/Plecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7552,3 +7552,119 @@ void Plecs_with_value_not_a_component(void) {

ecs_fini(world);
}

void Plecs_component_in_with_scope(void) {
ecs_world_t *world = ecs_init();

ECS_COMPONENT(world, Position);

ecs_struct(world, {
.entity = ecs_id(Position),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
LINE "with Position{10, 20} {\n"
LINE " - Bar\n"
LINE "}\n"
LINE "\n";

ecs_log_set_level(-4);
test_assert(ecs_plecs_from_str(world, NULL, expr) != 0);

ecs_fini(world);
}

void Plecs_component_in_with_scope_in_scope(void) {
ecs_world_t *world = ecs_init();

ECS_COMPONENT(world, Position);

ecs_struct(world, {
.entity = ecs_id(Position),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
LINE "foo {\n"
LINE " - Position{10, 20}\n"
LINE " with Position{30, 40} {\n"
LINE " - Bar\n"
LINE " }\n"
LINE "}\n";

ecs_log_set_level(-4);
test_assert(ecs_plecs_from_str(world, NULL, expr) == 0);

ecs_entity_t foo = ecs_lookup_fullpath(world, "foo");
test_assert(foo != 0);
ecs_entity_t bar = ecs_lookup_fullpath(world, "Bar");
test_assert(bar != 0);

test_assert(ecs_has(world, foo, Position));
test_assert(ecs_has_id(world, foo, bar));

const Position *p = ecs_get(world, foo, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);

ecs_fini(world);
}

void Plecs_assign_after_with_in_scope(void) {
ecs_world_t *world = ecs_init();

ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);

ecs_struct(world, {
.entity = ecs_id(Position),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});
ecs_struct(world, {
.entity = ecs_id(Velocity),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
LINE "foo {\n"
LINE " - Position{10, 20}\n"
LINE " with Position{30, 40} {\n"
LINE " }\n"
LINE " - Velocity{1, 2}\n"
LINE "}\n";

ecs_log_set_level(-4);
test_assert(ecs_plecs_from_str(world, NULL, expr) == 0);

ecs_entity_t foo = ecs_lookup_fullpath(world, "foo");
test_assert(foo != 0);

test_assert(ecs_has(world, foo, Position));
test_assert(ecs_has(world, foo, Velocity));

const Position *p = ecs_get(world, foo, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);

const Velocity *v = ecs_get(world, foo, Velocity);
test_assert(v != NULL);
test_int(v->x, 1);
test_int(v->y, 2);

ecs_fini(world);
}
17 changes: 16 additions & 1 deletion test/addons/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,9 @@ void Plecs_pair_w_rel_var(void);
void Plecs_pair_w_tgt_var(void);
void Plecs_assembly_w_pair_w_this_var(void);
void Plecs_with_value_not_a_component(void);
void Plecs_component_in_with_scope(void);
void Plecs_component_in_with_scope_in_scope(void);
void Plecs_assign_after_with_in_scope(void);

// Testsuite 'Doc'
void Doc_get_set_name(void);
Expand Down Expand Up @@ -3356,6 +3359,18 @@ bake_test_case Plecs_testcases[] = {
{
"with_value_not_a_component",
Plecs_with_value_not_a_component
},
{
"component_in_with_scope",
Plecs_component_in_with_scope
},
{
"component_in_with_scope_in_scope",
Plecs_component_in_with_scope_in_scope
},
{
"assign_after_with_in_scope",
Plecs_assign_after_with_in_scope
}
};

Expand Down Expand Up @@ -7478,7 +7493,7 @@ static bake_test_suite suites[] = {
"Plecs",
NULL,
NULL,
228,
231,
Plecs_testcases
},
{
Expand Down

0 comments on commit e7a045b

Please sign in to comment.