Skip to content

Update

Edit existing scene entities — properties and geometry. Accessed via snaptrude.design.update.

Migrated from the removed entity.space.{update, updateGeometryFromProfile, bulkUpdate}. Only provided fields change; each call is undoable. Failures throw (the RPC rejects).

Performance

Editing many spaces? Use the plural spaces(items) — one host round-trip for the whole batch — rather than looping space. See Performance.

Types

PluginSpacePropertyUpdates

Sparse property changes for a space (all optional).

PropertyTypeDescription
room_typestringRoom label
massTypePluginMassTypeMass type
spaceTypePluginSpaceTypeSpace type
areaClassPluginAreaClassArea class (NET / GROSS / EXCLUDED)
departmentIdPluginDepartmentIdDepartment

PluginSpaceGeometryUpdate

Geometry replacement — re-extrude a profile.

PropertyTypeDescription
profileProfileHandleNew footprint profile
extrudeHeightnumberNew extrude height

PluginUpdateSpaceItem

One space to update via spaces. { space: ComponentHandle; properties?: PluginSpacePropertyUpdates; geometry?: PluginSpaceGeometryUpdate }.

PluginStaircaseParamUpdates

Sparse parametric changes for a staircase (all optional) — the same fields the staircase properties panel exposes. Dimensions are in Snaptrude (engine) units. See design.query.getStaircaseParams for the paired read.

PropertyTypeDescription
staircaseHeightnumberTotal rise
stepsnumberStep count
risernumberRiser height
treadnumberTread depth
widthnumberFlight width
depthnumberFlight depth
baseOffsetnumberBase offset from the storey
storeyHeightnumberStorey height (when decoupled)
wellSizenumberWell size (well-based presets)
landingWidthnumberLanding width (landing-based presets)
flightStartDistAfterTurnnumberFlight start distance after a turn
isStoreyHeightUnlockedbooleanDecouple height from the storey
isStaircaseHeightUnlockedbooleanDecouple height from steps × riser

PluginWallUpdates

Sparse changes for a wall (all optional; at least one required). Dimensions are in Snaptrude (engine) units and must be > 0.

PropertyTypeDescription
thicknessnumberWall thickness
heightnumberWall height
typestringConvert the wall to another wall type — a name, label, or wall:-prefixed id from design.types.list("wall")

PluginSlabUpdates

Sparse changes for a slab-family element — slab / floor / roof / ceiling. Values are in Snaptrude (engine) units; thickness must be > 0.

overhang is only available on slabs and roofs (the panels' Overhang slider) — floors and ceilings reject it with PRECONDITION_FAILED.

PropertyTypeDescription
thicknessnumberElement thickness
overhangnumberAbsolute overhang offset (negative insets the edge) — slab / roof only

Functions

space(space, options)

Update ONE space — sparse properties and/or a geometry re-extrude. Undoable.

  • Parameters:
    • space: ComponentHandle — The space to update
    • options: { properties?: PluginSpacePropertyUpdates; geometry?: PluginSpaceGeometryUpdate }
  • Returns: the updated space's echoed PluginSpaceUpdateResult
  • Throws: for an unknown/forged handle or an engine failure
ts
await snaptrude.design.update.space("space-id", { properties: { room_type: "Office" } });

spaces(items)

Update many spaces in one host round-trip (bulk plural of space) — always prefer this over looping space; it also commits as a single undoable operation. Validate-all-or-throw; one command.

  • Parameters:
    • items: PluginUpdateSpaceItem[]
  • Returns: one PluginSpaceUpdateResult per item, in input order
ts
await snaptrude.design.update.spaces([
  { space: "s1", properties: { spaceType: "Room" } },
  { space: "s2", geometry: { profile, extrudeHeight: 4 } }
]);

setLabel(component, label)

Set a component's Label — the same editable Label field the properties panel shows (doors, windows, furniture, spaces, and every other labelled component). The paired read is design.query.getLabel. Undoable; the canvas label text updates immediately.

Strictly per component: labelling one door of a placed family never touches its sibling doors (the panel's Label edit, by contrast, applies to the whole family). On legacy masses without a space type, panel parity applies — a label matching a room-type preset with a height (e.g. "Water Body") can also adjust the mass's height and material, exactly like typing it in the panel.

  • Parameters:
    • component: ComponentHandle — The component to relabel
    • label: string — New label text (non-empty; leading/trailing whitespace trimmed)
  • Returns: true once the label is applied
  • Throws: when the component is locked, the handle is gone/forged, the label is empty, or the component has no mesh to label.
ts
// Door tag numbering: label every door as D-<storey>-<n>, numbered per storey
await snaptrude.design.selection.setByFilter({ types: ["door"] });
const doors = await snaptrude.design.selection.get();
const counts = {};
for (const door of doors) {
  const { storey = 0 } = await snaptrude.design.query.getProperties(door);
  counts[storey] = (counts[storey] ?? 0) + 1;
  await snaptrude.design.update.setLabel(
    door,
    `D-${storey}-${String(counts[storey]).padStart(2, "0")}`
  );
}

staircase(staircases, params)

Update the parametric fields of one or more preset staircases — riser, tread, width, depth, step count, height, base offset, and the type-specific well/landing/flight fields. Values are Snaptrude (engine) units; the engine round-trips each dimension through the panel's display representation, so a plugin read → write returns the staircase to the exact panel values.

Presets-only: this edits the parameters of an existing preset staircase; it does not re-type it. staircaseHeight / steps / riser are coupled (height = steps × riser) and governed by the two lock booleans — the locks are applied first so the coupled recompute sees them. Every field rebuilds the geometry, and every edit across every staircase commits as one undo batch. A locked or non-staircase handle rejects the whole call before any geometry is rebuilt.

ts
const [stair] = await snaptrude.design.query.listStaircases();
await snaptrude.design.update.staircase([stair], { steps: 16, width });

wall(component, updates)

Edit a wall — its thickness and/or height (the same command the properties panel's Thickness/Height fields drive) and/or its wall type (the panel's Wall Types dropdown: converts the wall to another type, rebuilding its layer stack and materials, stacked-wall conversions included). Sparse and undoable; the geometry rebuilds, dimension lines refresh, and stacked-wall companions and hosted fenestration are handled exactly as the panel does. Dimensions are in Snaptrude (engine) units and must be > 0.

type accepts the tokens design.types.list("wall") returns — the type name, its label, or the wall:<name> id. When combined with dimensions the type conversion is applied first, so an explicit thickness/height wins over the new type's defaults. Re-applying the wall's current type is a no-op.

  • Parameters:
  • Returns: PluginDesignChangeResult — the affected wall
  • Throws: for a non-wall handle, a locked wall, an unknown/forged handle, an unknown wall type, a conversion the engine rejects (e.g. a curved wall thinner than the new type's minimum thickness), or no field supplied

Rebuilds replace the wall — re-bind from affected

A type conversion (and a thickness edit on a parametric wall) rebuilds the wall, replacing it with a new component. Your input handle is then dead (further calls throw HANDLE_INVALID); affected[0] carries the replacement's handle — use it for any follow-up calls.

ts
const walls = await snaptrude.design.query.listWalls({ storeys: [1] });
for (const wall of walls) await snaptrude.design.update.wall(wall, { thickness: 230 });

// Convert a wall to another type from the panel's Wall Types dropdown.
// The conversion rebuilds the wall — keep working with the handle it returns.
const [wallType] = await snaptrude.design.types.list("wall");
const { affected } = await snaptrude.design.update.wall(walls[0], { type: wallType.id });
const converted = affected[0]; // NOT walls[0] — that handle is dead after the rebuild

slab(component, updates) · floor · roof · ceiling

Edit a slab-family element — its thickness (the same command the properties panel's Thickness field drives), and on slabs and roofs also its overhang (the panels' Overhang slider). One method per kind (slab, floor, roof, ceiling); they share the underlying commands and each rejects a handle of the wrong kind. Sparse and undoable; the element rebuilds and dimension lines refresh. Values are in Snaptrude (engine) units; thickness must be > 0.

overhang is an absolute offset (not a delta): re-applying the current value is a no-op, 0 removes the overhang, and a negative value insets the edge. Plinth/basement slabs and elements whose overhang is disabled have no Overhang control — setting overhang on them (or on any floor/ceiling) throws PRECONDITION_FAILED. When both fields are given, thickness applies first, then overhang (each is its own undo entry, exactly like two panel edits).

  • Parameters:
  • Returns: PluginDesignChangeResult — the affected element
  • Throws: for a wrong-kind handle, a locked element, an unknown/forged handle, an overhang on an element without one, or no field supplied
ts
const [slab] = await snaptrude.design.query.listSlabs();
await snaptrude.design.update.slab(slab, { thickness: 250, overhang: 200 });

const [roof] = await snaptrude.design.query.listRoofs();
await snaptrude.design.update.roof(roof, { overhang: 600 });

setElevation(component, elevation)

Set a component's absolute world elevation — moves it vertically so its base (the bounding-box bottom, world Y) lands at elevation. Composed over the canonical command-backed move machinery, so it is undoable and persisted exactly like dragging the element up or down; per-type invariants (e.g. a staircase's base offset) stay in sync. elevation is in Snaptrude (engine) units. Re-applying the current elevation is a no-op.

  • Parameters:
    • component: ComponentHandle — The component to move vertically
    • elevation: number — Target world elevation of the component's base
  • Returns: PluginDesignChangeResult — the affected component
  • Throws: for a locked component or an unknown/forged handle
ts
const [roof] = await snaptrude.design.query.listRoofs();
await snaptrude.design.update.setElevation(roof, 3000);

setBaseOffset(component, offset)

Set a component's base offset — its vertical distance above its own storey's base level. Moves the component so its base lands at storeyBase + offset, composed over the same command-backed move machinery as setElevation (undoable, persisted, per-type invariants kept in sync). Use this when you want an offset relative to the storey rather than an absolute world height. offset is in Snaptrude (engine) units; 0 sits the base flush with the storey base. Re-applying the current offset is a no-op.

  • Parameters:
    • component: ComponentHandle — The component to offset
    • offset: number — Distance of the component's base above its storey base
  • Returns: PluginDesignChangeResult — the affected component
  • Throws: for a locked component, a component with no storey, or an unknown/forged handle
ts
const [stair] = await snaptrude.design.query.listStaircases();
await snaptrude.design.update.setBaseOffset(stair, 0);

setStorey(components, storey)

Reassign one or more components to another storey — the same operation as the properties panel's Story dropdown, working across element kinds exactly like the panel (walls, slabs, masses, furniture, staircases, ...). Each component moves vertically to the target storey's level (per-kind placement rules — a slab sits at the storey base, a wall on it), its storey assignment and children update, stale canvas labels are removed, and storey visibility flags re-apply. All moves commit as one undoable operation; parametric walls/floors are made non-parametric first, exactly as the panel does.

storey is an integer storey number in the entity.story convention (1 ground, -1 first basement; 0 does not exist) and must already exist in each component's building — this call never creates storeys (use entity.story.create first; the panel's dropdown likewise only offers existing storeys). Components already on the target storey are skipped as no-ops (their custom elevation is preserved) and are not echoed in affected.

All guards run up front (all-or-nothing): a locked component, a missing storey, or a bad handle rejects the whole call before anything moves.

  • Parameters:
    • components: ComponentHandle[] — The components to reassign
    • storey: number — Target storey number (integer, entity.story convention)
  • Returns: PluginDesignChangeResult — the components actually reassigned
  • Throws: for a non-existent target storey, a locked component, or an unknown/forged handle
ts
// Move the current selection up to storey 2
const selection = await snaptrude.design.selection.get();
const { affected } = await snaptrude.design.update.setStorey(selection, 2);
console.log("moved", affected.length, "components");

Errors

Failed calls reject with a typed PluginError — see Error Handling. Conditions specific to this namespace:

CodeThrown byWhendetails
VALIDATIONspace, spacesgeometry.extrudeHeight is zero or negative (must be > 0)extrudeHeight — the offending value
VALIDATIONwall, slab, floor, roof, ceilingNo field supplied, or a thickness/height that is zero or negative (must be > 0)
HANDLE_INVALIDspace, spacesAn id does not resolve to a live space/mass (not-found and wrong-kind collapse to the one code); the geometry.profile handle cannot be resolved
HANDLE_INVALIDall element editorsThe component id is gone or forged
PRECONDITION_FAILEDwall, slab, floor, roof, ceilingThe handle is not of the expected kind, or the element is locked
PRECONDITION_FAILEDwalltype names an unknown wall type (see design.types.list("wall"))type — the offending token
PRECONDITION_FAILEDslab, floor, roof, ceilingoverhang set on an element without one: any floor/ceiling, a plinth/basement slab, or an element whose overhang is disabled
PRECONDITION_FAILEDsetStoreyThe target storey does not exist in a component's building, or a component is lockedstorey — the missing value
PRECONDITION_FAILEDsetElevation, setBaseOffsetThe component is locked; setBaseOffset also throws when the component has no storey
OPERATION_FAILEDspace, spaces, setElevation, setBaseOffsetThe engine cannot apply the geometry/property update, or the vertical move is rejected (hosted/constrained)
OPERATION_FAILEDwallThe engine rejected a type conversion without applying it (e.g. a curved/non-orthogonal wall thinner than the new type's minimum thickness)type — the requested type name
OPERATION_FAILEDslab, roofThe engine could not rebuild the overhang geometry (e.g. a slanted slab whose thickness varies, or a profile that cannot be offset)engineMessage — the engine's reason

spaces validates every item before anything is applied, so one bad item rejects the whole call with no partial updates (all-or-nothing) — the same guarantee space gets as a batch of one.