Show a placed object's struct the way its asset does

The instance inspector drew its own, flatter version of a struct: one row per
field, no bundle head. It now draws the same block as the asset side, because
there is only one implementation left - both call buildStructBlock. What the
instance does not get is everything that touches the shape: renaming a field,
'+ Field', and the per-field '×'. The shape belongs to the asset; a placed
object overrides values. The revert and override marks sit on the head rather
than on a field, since an override covers the whole bundle at once.

Underneath this, editing a single field of an unoverridden struct used to blank
its siblings: structFieldsOf filled the untouched fields from spec.read, which
is object.overrides[key] and therefore undefined until something is overridden.
structOf then handed back the empty shape. PreviewedValue carries 'current' now
- the resolved value the row actually shows - and the fields come from that.
Without it the old path stays, which is right for the asset side, whose prop
bag is dense.
This commit is contained in:
root committed 2026-09-10 23:05:02 +02:00
1 parent 14f542365e
commit 9f482573e5
9 files changed
+606 -207

No files matched your search

+28 -19
View File
@@ -105,26 +105,10 @@ export function labelledRow(text: string): { row: HStack; label: Label } {
}
/**
* Maps one PropertySchema entry to a labelled row containing the matching widget.
* The inspector is entirely generated through this function: adding a new property
* kind means adding a case here, adding a property means adding a schema line.
*
* A row shows its actions at the right: ↺ resets to the base value, ↑ applies the value to
* its source, `extra` adds row-specific ones. Each group is asked on every refresh: no entry
* means no button, one entry means a direct button, several mean a menu (↺ ▾ / ↑ ▾).
* Adds the trailing ↺/↑/extra buttons to a row and returns the refresh that re-evaluates them.
* Separate from `createFieldRow` because a struct block wears the same buttons on its head row.
*/
export function createFieldRow(
ctx: FieldContext,
def: PropertyDef,
value: PropertyValue,
handlers: FieldHandlers,
rowActions: RowActions = {},
): FieldRow {
const { row, label } = labelledRow(def.label);
const field = createField(ctx, def, value, handlers);
row.add(field.widget, field.grow ? 1 : 0);
if (!field.grow) row.add(new Spacer(), 1);
export function attachRowActions(row: HStack, rowActions: RowActions): () => void {
const actions: { button: Button; glyph: string; available: FieldActions }[] = [];
const addActions = (glyph: string, available: FieldActions): void => {
// A floor, not a width: the same button also carries the two-glyph menu form "↺ ▾".
@@ -163,6 +147,31 @@ export function createFieldRow(
if (changed) row.relayout();
};
refreshActions();
return refreshActions;
}
/**
* Maps one PropertySchema entry to a labelled row containing the matching widget.
* The inspector is entirely generated through this function: adding a new property
* kind means adding a case here, adding a property means adding a schema line.
*
* A row shows its actions at the right: ↺ resets to the base value, ↑ applies the value to
* its source, `extra` adds row-specific ones. Each group is asked on every refresh: no entry
* means no button, one entry means a direct button, several mean a menu (↺ ▾ / ↑ ▾).
*/
export function createFieldRow(
ctx: FieldContext,
def: PropertyDef,
value: PropertyValue,
handlers: FieldHandlers,
rowActions: RowActions = {},
): FieldRow {
const { row, label } = labelledRow(def.label);
const field = createField(ctx, def, value, handlers);
row.add(field.widget, field.grow ? 1 : 0);
if (!field.grow) row.add(new Spacer(), 1);
const refreshActions = attachRowActions(row, rowActions);
return {
row,