Appearance
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).
| Property | Type | Description |
|---|---|---|
room_type | string | Room label |
massType | PluginMassType | Mass type |
spaceType | PluginSpaceType | Space type |
areaClass | PluginAreaClass | Area class (NET / GROSS / EXCLUDED) |
departmentId | PluginDepartmentId | Department |
PluginSpaceGeometryUpdate
Geometry replacement — re-extrude a profile.
| Property | Type | Description |
|---|---|---|
profile | ProfileHandle | New footprint profile |
extrudeHeight | number | New 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.
| Property | Type | Description |
|---|---|---|
staircaseHeight | number | Total rise |
steps | number | Step count |
riser | number | Riser height |
tread | number | Tread depth |
width | number | Flight width |
depth | number | Flight depth |
baseOffset | number | Base offset from the storey |
storeyHeight | number | Storey height (when decoupled) |
wellSize | number | Well size (well-based presets) |
landingWidth | number | Landing width (landing-based presets) |
flightStartDistAfterTurn | number | Flight start distance after a turn |
isStoreyHeightUnlocked | boolean | Decouple height from the storey |
isStaircaseHeightUnlocked | boolean | Decouple 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.
| Property | Type | Description |
|---|---|---|
thickness | number | Wall thickness |
height | number | Wall height |
type | string | Convert 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.
| Property | Type | Description |
|---|---|---|
thickness | number | Element thickness |
overhang | number | Absolute 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 updateoptions:{ 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
PluginSpaceUpdateResultper 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 relabellabel:string— New label text (non-empty; leading/trailing whitespace trimmed)
- Returns:
trueonce 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.
- Parameters:
staircases:ComponentHandle[]— The staircases to updateparams:PluginStaircaseParamUpdates— Sparse field changes
- Returns:
PluginDesignChangeResult— the affected staircases - Throws: for a locked or non-staircase handle, an unknown/forged handle, or an out-of-range value
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:
component:ComponentHandle— The wall to editupdates:PluginWallUpdates— Sparse thickness/height/type (≥ 1 field)
- 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 rebuildslab(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:
component:ComponentHandle— The slab / floor / roof / ceiling to editupdates:PluginSlabUpdates—thicknessand/oroverhang(≥ 1 field)
- Returns:
PluginDesignChangeResult— the affected element - Throws: for a wrong-kind handle, a locked element, an unknown/forged handle, an
overhangon 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 verticallyelevation: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 offsetoffset: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 reassignstorey:number— Target storey number (integer,entity.storyconvention)
- 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:
| Code | Thrown by | When | details |
|---|---|---|---|
VALIDATION | space, spaces | geometry.extrudeHeight is zero or negative (must be > 0) | extrudeHeight — the offending value |
VALIDATION | wall, slab, floor, roof, ceiling | No field supplied, or a thickness/height that is zero or negative (must be > 0) | — |
HANDLE_INVALID | space, spaces | An 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_INVALID | all element editors | The component id is gone or forged | — |
PRECONDITION_FAILED | wall, slab, floor, roof, ceiling | The handle is not of the expected kind, or the element is locked | — |
PRECONDITION_FAILED | wall | type names an unknown wall type (see design.types.list("wall")) | type — the offending token |
PRECONDITION_FAILED | slab, floor, roof, ceiling | overhang set on an element without one: any floor/ceiling, a plinth/basement slab, or an element whose overhang is disabled | — |
PRECONDITION_FAILED | setStorey | The target storey does not exist in a component's building, or a component is locked | storey — the missing value |
PRECONDITION_FAILED | setElevation, setBaseOffset | The component is locked; setBaseOffset also throws when the component has no storey | — |
OPERATION_FAILED | space, spaces, setElevation, setBaseOffset | The engine cannot apply the geometry/property update, or the vertical move is rejected (hosted/constrained) | — |
OPERATION_FAILED | wall | The 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_FAILED | slab, roof | The 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.