@@ -50322,6 +50322,7 @@ typedef struct ecs_expr_initializer_t {
5032250322 const ecs_type_info_t *type_info;
5032350323 bool is_collection;
5032450324 bool is_dynamic;
50325+ bool is_partial;
5032550326} ecs_expr_initializer_t;
5032650327
5032750328typedef struct ecs_expr_variable_t {
@@ -66830,6 +66831,15 @@ void FlecsScriptMathPerlinImport(
6683066831 case '\n':\
6683166832 case '\0'
6683266833
66834+ static
66835+ void flecs_script_initializer_set_full(
66836+ ecs_expr_node_t *node)
66837+ {
66838+ if (node->kind == EcsExprInitializer) {
66839+ ((ecs_expr_initializer_t*)node)->is_partial = false;
66840+ }
66841+ }
66842+
6683366843/* Parse scope (statements inside {}) */
6683466844static
6683566845const char* flecs_script_scope(
@@ -66942,6 +66952,7 @@ const char* flecs_script_with_expr(
6694266952 flecs_script_insert_component(parser, Token(0));
6694366953 component->node.kind = EcsAstWithComponent;
6694466954 component->expr = INITIALIZER;
66955+ flecs_script_initializer_set_full(component->expr);
6694566956 EndOfRule;
6694666957 )
6694766958 )
@@ -66970,10 +66981,11 @@ const char* flecs_script_with_expr(
6697066981 // (Eats, Apples) ( expr )
6697166982 Initializer(')',
6697266983 ecs_script_component_t *component =
66973- flecs_script_insert_pair_component(parser,
66984+ flecs_script_insert_pair_component(parser,
6697466985 Token(1), Token(3));
6697566986 component->node.kind = EcsAstWithComponent;
6697666987 component->expr = INITIALIZER;
66988+ flecs_script_initializer_set_full(component->expr);
6697766989 EndOfRule;
6697866990 )
6697966991 )
@@ -67038,10 +67050,11 @@ const char* flecs_script_paren_expr(
6703867050 Initializer(')',
6703967051 entity->kind_w_expr = true;
6704067052
67041- Scope(entity->scope,
67042- ecs_script_component_t *component =
67053+ Scope(entity->scope,
67054+ ecs_script_component_t *component =
6704367055 flecs_script_insert_component(parser, kind);
6704467056 component->expr = INITIALIZER;
67057+ flecs_script_initializer_set_full(component->expr);
6704567058 )
6704667059
6704767060 Parse(
@@ -67980,10 +67993,11 @@ identifier_paren: {
6798067993 ecs_script_entity_t *entity = flecs_script_insert_entity(
6798167994 parser, NULL);
6798267995
67983- Scope(entity->scope,
67984- ecs_script_component_t *comp =
67985- flecs_script_insert_component(parser, Token(0));
67996+ Scope(entity->scope,
67997+ ecs_script_component_t *comp =
67998+ flecs_script_insert_component(parser, Token(0));
6798667999 comp->expr = INITIALIZER;
68000+ flecs_script_initializer_set_full(comp->expr);
6798768001 )
6798868002
6798968003 EndOfRule;
@@ -67994,10 +68008,11 @@ identifier_paren: {
6799468008 ecs_script_entity_t *entity = flecs_script_insert_entity(
6799568009 parser, NULL);
6799668010
67997- Scope(entity->scope,
67998- ecs_script_component_t *comp =
67999- flecs_script_insert_component(parser, Token(0));
68011+ Scope(entity->scope,
68012+ ecs_script_component_t *comp =
68013+ flecs_script_insert_component(parser, Token(0));
6800068014 comp->expr = INITIALIZER;
68015+ flecs_script_initializer_set_full(comp->expr);
6800168016 )
6800268017
6800368018 return flecs_script_scope(parser, entity->scope, pos);
@@ -71822,25 +71837,44 @@ int flecs_script_eval_component(
7182271837 }
7182371838
7182471839 bool needs_set = ti->hooks.on_replace != NULL;
71825- ecs_record_t *r = flecs_entities_get(v->world, src);
71826- ecs_assert(r != NULL, ECS_INTERNAL_ERROR, NULL);
71827- ecs_table_t *table = r->table;
71828-
71840+
71841+ bool partial = false;
71842+ if (node->expr->kind == EcsExprInitializer) {
71843+ partial = ((ecs_expr_initializer_t*)node->expr)->is_partial;
71844+ }
71845+
71846+ const void *existing = NULL;
71847+ if (partial) {
71848+ existing = ecs_get_id(v->world, src, node->id.eval);
71849+ }
71850+
7182971851 ecs_value_t value = {
71830- .ptr = needs_set
71831- ? ecs_os_alloca(ti->size)
71832- : ecs_ensure_id(v->world, src, node->id.eval,
71852+ .ptr = needs_set
71853+ ? ecs_os_alloca(ti->size)
71854+ : ecs_ensure_id(v->world, src, node->id.eval,
7183371855 flecs_ito(size_t, ti->size)),
7183471856 .type = ti->component
7183571857 };
7183671858
71837- /* Assign entire value, including members not set by expression. This
71838- * prevents uninitialized or unexpected values. */
71839- if (needs_set || (r->table != table)) {
71859+ /* For full assignments, assign entire value including members not set
71860+ * by expression. This prevents uninitialized or unexpected values. For
71861+ * partial assignments, members not set by the expression keep the
71862+ * existing component value. */
71863+ if (needs_set) {
7184071864 if (!ti->hooks.ctor) {
7184171865 ecs_os_memset(value.ptr, 0, ti->size);
7184271866 } else {
71843- if (!needs_set && ti->hooks.dtor) {
71867+ flecs_type_info_ctor(value.ptr, 1, ti);
71868+ }
71869+
71870+ if (existing) {
71871+ ecs_value_copy_w_type_info(v->world, ti, value.ptr, existing);
71872+ }
71873+ } else if (!existing) {
71874+ if (!ti->hooks.ctor) {
71875+ ecs_os_memset(value.ptr, 0, ti->size);
71876+ } else {
71877+ if (ti->hooks.dtor) {
7184471878 flecs_type_info_dtor(value.ptr, 1, ti);
7184571879 }
7184671880 flecs_type_info_ctor(value.ptr, 1, ti);
@@ -71972,12 +72006,33 @@ int flecs_script_eval_default_component(
7197272006 return -1;
7197372007 }
7197472008
72009+ bool partial = false;
72010+ if (node->expr->kind == EcsExprInitializer) {
72011+ partial = ((ecs_expr_initializer_t*)node->expr)->is_partial;
72012+ }
72013+
72014+ const void *existing = NULL;
72015+ if (partial) {
72016+ existing = ecs_get_id(v->world, v->entity->eval, default_type);
72017+ }
72018+
7197572019 ecs_value_t value = {
71976- .ptr = ecs_ensure_id(v->world, v->entity->eval, default_type,
72020+ .ptr = ecs_ensure_id(v->world, v->entity->eval, default_type,
7197772021 flecs_ito(size_t, ti->size)),
7197872022 .type = default_type
7197972023 };
7198072024
72025+ if (!existing) {
72026+ if (!ti->hooks.ctor) {
72027+ ecs_os_memset(value.ptr, 0, ti->size);
72028+ } else {
72029+ if (ti->hooks.dtor) {
72030+ flecs_type_info_dtor(value.ptr, 1, ti);
72031+ }
72032+ flecs_type_info_ctor(value.ptr, 1, ti);
72033+ }
72034+ }
72035+
7198172036 if (flecs_script_eval_expr(v, &node->expr, &value)) {
7198272037 return -1;
7198372038 }
@@ -93044,6 +93099,16 @@ const char* flecs_script_parse_initializer(
9304493099 goto error;
9304593100 }
9304693101
93102+ if (elem->member) {
93103+ node->is_partial = true;
93104+ }
93105+
93106+ if (elem->value && elem->value->kind == EcsExprInitializer &&
93107+ ((ecs_expr_initializer_t*)elem->value)->is_partial)
93108+ {
93109+ node->is_partial = true;
93110+ }
93111+
9304793112 {
9304893113 /* Parse next element or end of initializer */
9304993114 LookAhead(
@@ -93053,7 +93118,7 @@ const char* flecs_script_parse_initializer(
9305393118 }
9305493119
9305593120 case ')':
93056- case '}':
93121+ case '}':
9305793122 /* Return last character of initializer */
9305893123 pos = lookahead - 1;
9305993124
@@ -93108,6 +93173,12 @@ const char* flecs_script_parse_collection_initializer(
9310893173 goto error;
9310993174 }
9311093175
93176+ if (elem->value && elem->value->kind == EcsExprInitializer &&
93177+ ((ecs_expr_initializer_t*)elem->value)->is_partial)
93178+ {
93179+ node->is_partial = true;
93180+ }
93181+
9311193182 {
9311293183 /* Parse next element or end of initializer */
9311393184 LookAhead(
@@ -95907,6 +95978,10 @@ int flecs_expr_initializer_visit_fold(
9590795978
9590895979 ecs_expr_initializer_t *node = (ecs_expr_initializer_t*)*node_ptr;
9590995980
95981+ if (node->is_partial) {
95982+ can_fold = false;
95983+ }
95984+
9591095985 if (flecs_expr_initializer_pre_fold(script, node, desc, &can_fold)) {
9591195986 goto error;
9591295987 }
0 commit comments