Let a value be a bundle of named fields

PropertyValue was number | string | boolean | list. A struct joins it, which
costs two things the typechecker found rather than I did.

An object on a data edge used to mean a live entity, so asEntity would have
taken a struct for one and asString would have read .name off it. EntityHandle
now carries a symbol brand – a symbol so no field name can impersonate it, and
it never serializes, which suits a thing that exists only while the game runs.
It is built in exactly one place.

String(value) would have written a struct as [object Object] at 39 call sites.
They go through textOf(), which is identical for primitives.

normalizeGraph dropped everything but primitives from node params, so the List
node lost its value on every save ([3,1,4] round-tripped to undefined).
Variables were spared: they have a schema, params have none.
This commit is contained in:
root committed 2026-09-10 08:14:18 +02:00
1 parent 3b3f374e10
commit 2cf788eedd
34 files changed
+284 -82

No files matched your search

+5 -3
View File
@@ -14,7 +14,7 @@ import {
} from '../../core/graph';
import type { BehaviorAsset } from '../../core/model/Asset';
import type { Project } from '../../core/model/Project';
import { isList, type PropertyValue } from '../../core/model/Properties';
import { isList, type PropertyValue, textOf } from '../../core/model/Properties';
import { assetRefLabel } from '../../core/properties/assetRef';
import type { PropertyDef } from '../../core/properties/PropertySchema';
import { formatNumber, Theme, textStyle, type TextStyleToken, truncate, Widget } from '../../ui';
@@ -60,6 +60,8 @@ export function portColor(type: PortType): number {
return c.portObject;
case 'list':
return c.portList;
case 'struct':
return c.portStruct;
case 'any':
return c.portAny;
}
@@ -296,8 +298,8 @@ function formatParam(
project: Project | null,
): string {
if (value === undefined || value === '') return '—';
if (param.kind === 'key') return keyLabel(String(value));
if (param.kind === 'asset') return assetRefLabel(project, String(value));
if (param.kind === 'key') return keyLabel(textOf(value));
if (param.kind === 'asset') return assetRefLabel(project, textOf(value));
if (
param.kind === 'enum' &&
param.key === 'variable' &&