@snaptrude/plugin-core 0.9.17 → 0.9.18-edgesetbacks-20261021.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +231 -231
- package/CHANGELOG.md +408 -408
- package/CLAUDE.md +11 -11
- package/api-manifest.json +1428 -712
- package/dist/api/analysis/daylight.d.ts +5 -5
- package/dist/api/analysis/solar.d.ts +2 -2
- package/dist/api/core/camera/index.d.ts +29 -0
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +7 -1
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +8 -2
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/storeys/index.d.ts +5 -2
- package/dist/api/core/storeys/index.d.ts.map +1 -1
- package/dist/api/core/zoom/index.d.ts +13 -0
- package/dist/api/core/zoom/index.d.ts.map +1 -1
- package/dist/api/design/bim.d.ts +299 -0
- package/dist/api/design/bim.d.ts.map +1 -0
- package/dist/api/design/boolean/index.d.ts +2 -0
- package/dist/api/design/boolean/index.d.ts.map +1 -1
- package/dist/api/design/catalog.d.ts +320 -0
- package/dist/api/design/catalog.d.ts.map +1 -0
- package/dist/api/design/create/bulk-items.d.ts +65 -25
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +299 -100
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +13 -12
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +1 -0
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +18 -24
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +813 -35
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +16 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/networks.d.ts +1703 -0
- package/dist/api/design/networks.d.ts.map +1 -0
- package/dist/api/design/query/grids.d.ts +2 -2
- package/dist/api/design/query/index.d.ts +42 -32
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/selection/index.d.ts +10 -10
- package/dist/api/design/types/index.d.ts +40 -24
- package/dist/api/design/types/index.d.ts.map +1 -1
- package/dist/api/design/update/index.d.ts +111 -6
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/design/windows/index.d.ts +8 -8
- package/dist/api/design/windows/index.d.ts.map +1 -1
- package/dist/api/entity/buildableEnvelope.d.ts +84 -2
- package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
- package/dist/api/presentation/aiInspiration.d.ts +10 -10
- package/dist/api/presentation/annotate.d.ts +38 -22
- package/dist/api/presentation/annotate.d.ts.map +1 -1
- package/dist/api/presentation/drawingContract.d.ts +32 -0
- package/dist/api/presentation/drawingContract.d.ts.map +1 -0
- package/dist/api/presentation/drawings.d.ts +3523 -0
- package/dist/api/presentation/drawings.d.ts.map +1 -0
- package/dist/api/presentation/export.d.ts +23 -5
- package/dist/api/presentation/export.d.ts.map +1 -1
- package/dist/api/presentation/index.d.ts +32 -12
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +106 -6
- package/dist/api/presentation/placedViews.d.ts.map +1 -1
- package/dist/api/presentation/shapes.d.ts +2 -2
- package/dist/api/presentation/sheets.d.ts +175 -19
- package/dist/api/presentation/sheets.d.ts.map +1 -1
- package/dist/api/presentation/viewPresets.d.ts +222 -0
- package/dist/api/presentation/viewPresets.d.ts.map +1 -0
- package/dist/api/presentation/views.d.ts +141 -8
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/api/presentation/walkthroughs.d.ts +6 -6
- package/dist/errors/codes.d.ts +3 -1
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/index.cjs +3831 -2444
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3705 -2444
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-dist-fresh.mjs +22 -22
- package/scripts/generate-manifest.mjs +243 -238
- package/scripts/generate-manifest.test.mjs +303 -303
- package/src/api/analysis/daylight.ts +470 -470
- package/src/api/analysis/heatmaps.ts +683 -683
- package/src/api/analysis/illuminance.ts +155 -155
- package/src/api/analysis/index.ts +61 -61
- package/src/api/analysis/shadows.ts +183 -183
- package/src/api/analysis/solar.ts +237 -237
- package/src/api/analysis/sunlightHours.ts +211 -211
- package/src/api/analysis/sunpath.ts +83 -83
- package/src/api/analysis/weather.ts +179 -179
- package/src/api/core/buildings.ts +485 -485
- package/src/api/core/camera/index.ts +696 -667
- package/src/api/core/comment/index.ts +376 -376
- package/src/api/core/geom/create/index.ts +2139 -2133
- package/src/api/core/geom/delete/index.ts +84 -84
- package/src/api/core/geom/index.ts +35 -35
- package/src/api/core/geom/query/arc.ts +169 -169
- package/src/api/core/geom/query/brep.ts +621 -621
- package/src/api/core/geom/query/circle.ts +404 -404
- package/src/api/core/geom/query/contour.ts +540 -540
- package/src/api/core/geom/query/curve.ts +1102 -1102
- package/src/api/core/geom/query/edge.ts +130 -130
- package/src/api/core/geom/query/face.ts +508 -508
- package/src/api/core/geom/query/halfedge.ts +210 -210
- package/src/api/core/geom/query/index.ts +63 -63
- package/src/api/core/geom/query/profile.ts +473 -473
- package/src/api/core/geom/query/vertex.ts +205 -205
- package/src/api/core/geom/update/contour.ts +323 -317
- package/src/api/core/geom/update/curve.ts +209 -209
- package/src/api/core/geom/update/index.ts +29 -29
- package/src/api/core/geom/update/profile.ts +379 -379
- package/src/api/core/groups.ts +521 -521
- package/src/api/core/handles/index.ts +234 -234
- package/src/api/core/history/index.ts +84 -84
- package/src/api/core/index.ts +99 -99
- package/src/api/core/io/export/index.ts +126 -126
- package/src/api/core/io/import/index.ts +504 -504
- package/src/api/core/io/index.ts +42 -42
- package/src/api/core/io/job/index.ts +140 -140
- package/src/api/core/io/query/index.ts +71 -71
- package/src/api/core/io/terrain/index.ts +360 -360
- package/src/api/core/io/underlay/index.ts +705 -705
- package/src/api/core/layers.ts +540 -540
- package/src/api/core/math/index.ts +20 -20
- package/src/api/core/math/quat.ts +172 -172
- package/src/api/core/math/vec3.ts +179 -179
- package/src/api/core/mode/index.ts +108 -108
- package/src/api/core/project/index.ts +479 -479
- package/src/api/core/proposals/index.ts +570 -570
- package/src/api/core/storeys/index.ts +311 -308
- package/src/api/core/storeys/layers.ts +339 -339
- package/src/api/core/tags.ts +911 -911
- package/src/api/core/units/index.ts +164 -164
- package/src/api/core/user.ts +46 -46
- package/src/api/core/zoom/index.ts +64 -51
- package/src/api/design/bim.ts +210 -0
- package/src/api/design/boolean/index.ts +181 -179
- package/src/api/design/catalog.ts +203 -0
- package/src/api/design/create/bulk-items.ts +294 -254
- package/src/api/design/create/grids.ts +137 -137
- package/src/api/design/create/index.ts +2178 -1980
- package/src/api/design/create/opening-fields.ts +40 -37
- package/src/api/design/delete/index.ts +75 -74
- package/src/api/design/dimensions.ts +453 -453
- package/src/api/design/doors/index.ts +516 -500
- package/src/api/design/edit/index.ts +54 -54
- package/src/api/design/erase/index.ts +151 -151
- package/src/api/design/family.ts +1342 -704
- package/src/api/design/furniture/index.ts +319 -319
- package/src/api/design/grids.ts +237 -237
- package/src/api/design/index.ts +304 -274
- package/src/api/design/lock.ts +69 -69
- package/src/api/design/materials/index.ts +608 -608
- package/src/api/design/networks.ts +607 -0
- package/src/api/design/query/geometry/index.ts +319 -319
- package/src/api/design/query/grids.ts +197 -197
- package/src/api/design/query/index.ts +1236 -1226
- package/src/api/design/query/referenceLines.ts +52 -52
- package/src/api/design/query/spaces.ts +275 -275
- package/src/api/design/selection/index.ts +273 -273
- package/src/api/design/shared.ts +40 -40
- package/src/api/design/transform/index.ts +254 -254
- package/src/api/design/types/index.ts +163 -156
- package/src/api/design/update/index.ts +1096 -983
- package/src/api/design/visibility.ts +143 -143
- package/src/api/design/windows/index.ts +351 -333
- package/src/api/entity/buildableEnvelope.ts +397 -322
- package/src/api/entity/index.ts +30 -30
- package/src/api/entity/referenceLine.ts +235 -235
- package/src/api/entity/space.ts +612 -612
- package/src/api/entity/story.ts +517 -517
- package/src/api/index.ts +47 -47
- package/src/api/presentation/aiInspiration.ts +1116 -1116
- package/src/api/presentation/annotate.ts +417 -385
- package/src/api/presentation/camera.ts +289 -289
- package/src/api/presentation/diagrams.ts +194 -194
- package/src/api/presentation/drawingContract.ts +70 -0
- package/src/api/presentation/drawings.ts +1179 -0
- package/src/api/presentation/export.ts +134 -108
- package/src/api/presentation/import.ts +159 -159
- package/src/api/presentation/index.ts +160 -135
- package/src/api/presentation/placedViews.ts +1211 -1120
- package/src/api/presentation/sections.ts +420 -420
- package/src/api/presentation/shapes.ts +274 -274
- package/src/api/presentation/sheets.ts +746 -585
- package/src/api/presentation/slideshow.ts +134 -134
- package/src/api/presentation/tables.ts +84 -84
- package/src/api/presentation/viewPresets.ts +241 -0
- package/src/api/presentation/views.ts +742 -673
- package/src/api/presentation/walkthroughs.ts +1201 -1201
- package/src/api/program/adjacency.ts +164 -164
- package/src/api/program/areas.ts +408 -408
- package/src/api/program/classification.ts +138 -138
- package/src/api/program/cores.ts +83 -83
- package/src/api/program/departments.ts +517 -517
- package/src/api/program/index.ts +73 -73
- package/src/api/program/labels.ts +332 -332
- package/src/api/program/layout.ts +422 -422
- package/src/api/program/metadata.ts +364 -364
- package/src/api/program/metrics.ts +120 -120
- package/src/api/program/site.ts +748 -748
- package/src/api/program/spreadsheet.ts +2698 -2698
- package/src/api/workspace/index.ts +612 -612
- package/src/errors/codes.ts +143 -136
- package/src/errors/envelope.ts +75 -75
- package/src/errors/index.ts +21 -21
- package/src/errors/plugin-error.ts +134 -134
- package/src/handles.ts +297 -297
- package/src/host-utils.ts +67 -67
- package/src/index.ts +7 -7
- package/src/massParameters.ops.ts +246 -246
- package/src/massParameters.ts +427 -427
- package/src/types.ts +16 -16
- package/test/drawingContract.test.mjs +288 -0
- package/test/errors.test.mjs +185 -184
- package/test/massParameters.test.mjs +952 -952
- package/test/presentationViewSettings.test.mjs +85 -0
- package/tsconfig.json +22 -22
- package/tsup.config.ts +12 -12
|
@@ -1,254 +1,254 @@
|
|
|
1
|
-
import * as z from "zod"
|
|
2
|
-
import { PluginApiReturn } from "../../../types"
|
|
3
|
-
import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
4
|
-
import { PluginDesignChangeResult } from "../lock"
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* `snaptrude.design.transform` — rigid transforms on scene entities.
|
|
8
|
-
*
|
|
9
|
-
* `move` / `rotate` migrated from the removed `tools.transform.*`; `align` snaps a
|
|
10
|
-
* set of components' bounding-box edges to each other (or to a reference); `mirror`
|
|
11
|
-
* flips components in place about a horizontal axis. All ops are undoable and return
|
|
12
|
-
* {@linkcode PluginDesignChangeResult} `{ affected }`; failures throw (RPC rejects).
|
|
13
|
-
*
|
|
14
|
-
* `getPosition` / `setPosition` (and `scale`, an engine gap) are NOT in this surface
|
|
15
|
-
* yet — they are a later pass.
|
|
16
|
-
*/
|
|
17
|
-
export abstract class PluginDesignTransformApi {
|
|
18
|
-
constructor() {}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Translate entities by a **relative** displacement vector (added to the first
|
|
22
|
-
* component's absolute position as the anchor). Undoable.
|
|
23
|
-
*
|
|
24
|
-
* @param components - Entities to move
|
|
25
|
-
* @param displacement - Relative translation as a {@linkcode Vec3Handle}
|
|
26
|
-
* @param options - `is2D`, `trackParentChange`
|
|
27
|
-
* @returns {@linkcode PluginDesignChangeResult}
|
|
28
|
-
*
|
|
29
|
-
* @examplePrompt Move the selected room 5 metres to the right
|
|
30
|
-
* @examplePrompt Shift these walls 3m along the x axis
|
|
31
|
-
* @examplePrompt Nudge this space 500mm north
|
|
32
|
-
* @examplePrompt Translate the furniture block by (10, 0, 5)
|
|
33
|
-
* @examplePrompt Move these masses up one storey
|
|
34
|
-
*
|
|
35
|
-
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
36
|
-
* single call; never loop `design.transform.move` per entity.
|
|
37
|
-
*
|
|
38
|
-
* # Example
|
|
39
|
-
* ```ts
|
|
40
|
-
* const { vec3 } = snaptrude.core.math
|
|
41
|
-
* await snaptrude.design.transform.move(["space-id"], vec3.new(10, 0, 0))
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
public abstract move(
|
|
45
|
-
components: ComponentHandle[],
|
|
46
|
-
displacement: Vec3Handle,
|
|
47
|
-
options?: { is2D?: boolean; trackParentChange?: boolean },
|
|
48
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Rotate entities by a **signed angle in DEGREES** (positive = CCW about +Y).
|
|
52
|
-
* The pivot defaults to the combined bounding-box centre; pass `options.pivot`
|
|
53
|
-
* to rotate about an explicit world-space point instead. NOTE: unlike the
|
|
54
|
-
* removed `tools.transform.rotate` (radians), this canonical form takes
|
|
55
|
-
* DEGREES. Undoable.
|
|
56
|
-
*
|
|
57
|
-
* @param components - Entities to rotate
|
|
58
|
-
* @param angleInDegrees - Signed rotation angle in degrees
|
|
59
|
-
* @param options - `axis` (defaults to world +Y), `pivot` (world-space rotation
|
|
60
|
-
* centre as a {@linkcode Vec3Handle}; defaults to the combined bbox centre),
|
|
61
|
-
* `is2D`
|
|
62
|
-
* @returns {@linkcode PluginDesignChangeResult}
|
|
63
|
-
*
|
|
64
|
-
* @examplePrompt Rotate the selected building 90 degrees
|
|
65
|
-
* @examplePrompt Turn this room 45 degrees clockwise
|
|
66
|
-
* @examplePrompt Spin the furniture block 180 degrees about its centre
|
|
67
|
-
* @examplePrompt Rotate these masses 30 degrees around the vertical axis
|
|
68
|
-
* @examplePrompt Rotate these walls 90 degrees about the origin
|
|
69
|
-
*
|
|
70
|
-
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
71
|
-
* single call; never loop `design.transform.rotate` per entity.
|
|
72
|
-
*
|
|
73
|
-
* # Example
|
|
74
|
-
* ```ts
|
|
75
|
-
* await snaptrude.design.transform.rotate(["space-id"], 90)
|
|
76
|
-
* // …or rotate about an explicit pivot point
|
|
77
|
-
* const { vec3 } = snaptrude.core.math
|
|
78
|
-
* await snaptrude.design.transform.rotate(["space-id"], 90, { pivot: vec3.new(0, 0, 0) })
|
|
79
|
-
* ```
|
|
80
|
-
*/
|
|
81
|
-
public abstract rotate(
|
|
82
|
-
components: ComponentHandle[],
|
|
83
|
-
angleInDegrees: number,
|
|
84
|
-
options?: { axis?: Vec3Handle; pivot?: Vec3Handle; is2D?: boolean },
|
|
85
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Align a set of components by snapping one bounding-box edge to a common value
|
|
89
|
-
* — the classic Left/Center/Right/Top/Middle/Bottom align. Purely **world-axis**
|
|
90
|
-
* (deterministic and headless — the UI's camera-relative remap is bypassed):
|
|
91
|
-
*
|
|
92
|
-
* - `left` / `right` / `center` → world **X** min / max / mid
|
|
93
|
-
* - `top` / `bottom` / `middle` → world **Z** max / min / mid
|
|
94
|
-
*
|
|
95
|
-
* There is **no vertical (Y) alignment** in v1 (the UI only reaches it via a
|
|
96
|
-
* side-elevation camera remap, which this API does not replicate). Doors and
|
|
97
|
-
* windows are **rejected** in v1 — if any component in `components` (or the
|
|
98
|
-
* `reference`) is a door or window, the whole call **throws**; nothing is
|
|
99
|
-
* silently dropped. A group aligns as **one rigid body** (its whole-group
|
|
100
|
-
* bounding box moves together). Undoable.
|
|
101
|
-
*
|
|
102
|
-
* Requires **at least 2 components** unless a `reference` is supplied; with a
|
|
103
|
-
* reference, every component aligns to that reference's edge (the reference does
|
|
104
|
-
* not move) and a single component is allowed. Y (height) is preserved.
|
|
105
|
-
*
|
|
106
|
-
* @param components - Entities to align (≥2 without a `reference`)
|
|
107
|
-
* @param edge - Which bounding-box edge to snap ({@linkcode PluginAlignEdge})
|
|
108
|
-
* @param options - `reference`: a component whose edge is the fixed target
|
|
109
|
-
* @returns {@linkcode PluginDesignChangeResult}
|
|
110
|
-
*
|
|
111
|
-
* @examplePrompt Align the selected rooms to the left
|
|
112
|
-
* @examplePrompt Line up these masses along their top edges
|
|
113
|
-
* @examplePrompt Center these columns horizontally
|
|
114
|
-
* @examplePrompt Align all the walls to the left edge of this reference wall
|
|
115
|
-
* @examplePrompt Snap the bottom edges of these spaces together
|
|
116
|
-
*
|
|
117
|
-
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
118
|
-
* single call; never loop `design.transform.align` per entity.
|
|
119
|
-
*
|
|
120
|
-
* # Example
|
|
121
|
-
* ```ts
|
|
122
|
-
* const rooms = await snaptrude.design.selection.get()
|
|
123
|
-
* // align every room's left (world -X) edge to a common minimum
|
|
124
|
-
* await snaptrude.design.transform.align(rooms, "left")
|
|
125
|
-
* // …or align them to a fixed reference component's left edge
|
|
126
|
-
* const [anchor] = await snaptrude.design.query.listWalls({ storeys: [1] })
|
|
127
|
-
* await snaptrude.design.transform.align(rooms, "left", { reference: anchor })
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
public abstract align(
|
|
131
|
-
components: ComponentHandle[],
|
|
132
|
-
edge: PluginAlignEdge,
|
|
133
|
-
options?: { reference?: ComponentHandle },
|
|
134
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Mirror components **in place** about a horizontal axis, flipping their geometry
|
|
138
|
-
* across that axis through the combined bounding-box centre (the mesh's
|
|
139
|
-
* world-matrix flip + brep inversion + CAD/dimension-line/parametric handling
|
|
140
|
-
* commit atomically). Nothing moves off-centre — this is the toolbar "flip", not
|
|
141
|
-
* a translate-and-reflect. Undoable.
|
|
142
|
-
*
|
|
143
|
-
* `axis` names the axis the geometry mirrors **across** (world axes, Y is up):
|
|
144
|
-
* - `'x'` — mirror across world X (a front↔back flip in plan; reflects the Z coord)
|
|
145
|
-
* - `'z'` — mirror across world Z (a left↔right flip in plan; reflects the X coord)
|
|
146
|
-
*
|
|
147
|
-
* Vertical (`'y'`) mirroring is intentionally not exposed. Locked, bucket-locked
|
|
148
|
-
* and ineligible entries (terrain, plinths, reference/dimension lines,
|
|
149
|
-
* neighbourhood buildings) are **silently dropped**; the call only throws if
|
|
150
|
-
* nothing mirrorable remains. `affected` echoes the supplied handles.
|
|
151
|
-
*
|
|
152
|
-
* @param components - Entities to mirror (≥1)
|
|
153
|
-
* @param axis - Axis to mirror across ({@linkcode PluginTransformMirrorAxis})
|
|
154
|
-
* @returns {@linkcode PluginDesignChangeResult}
|
|
155
|
-
*
|
|
156
|
-
* @examplePrompt Mirror the selected building across the x axis
|
|
157
|
-
* @examplePrompt Flip these rooms left to right
|
|
158
|
-
* @examplePrompt Mirror this furniture block horizontally
|
|
159
|
-
* @examplePrompt Flip the selected walls front to back
|
|
160
|
-
* @examplePrompt Create a mirror image of these masses about the z axis
|
|
161
|
-
*
|
|
162
|
-
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
163
|
-
* single call; never loop `design.transform.mirror` per entity.
|
|
164
|
-
*
|
|
165
|
-
* # Example
|
|
166
|
-
* ```ts
|
|
167
|
-
* const rooms = await snaptrude.design.selection.get()
|
|
168
|
-
* await snaptrude.design.transform.mirror(rooms, "x")
|
|
169
|
-
* ```
|
|
170
|
-
*/
|
|
171
|
-
public abstract mirror(
|
|
172
|
-
components: ComponentHandle[],
|
|
173
|
-
axis: PluginTransformMirrorAxis,
|
|
174
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* The horizontal axis a {@linkcode PluginDesignTransformApi.mirror} flips **across**
|
|
179
|
-
* (world axes, Y up): `'x'` mirrors across world X (front↔back in plan; reflects Z),
|
|
180
|
-
* `'z'` mirrors across world Z (left↔right in plan; reflects X). Vertical (`'y'`)
|
|
181
|
-
* mirroring is not exposed.
|
|
182
|
-
*/
|
|
183
|
-
export const PluginTransformMirrorAxis = z.enum(["x", "z"])
|
|
184
|
-
export type PluginTransformMirrorAxis = z.infer<
|
|
185
|
-
typeof PluginTransformMirrorAxis
|
|
186
|
-
>
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* The bounding-box edge an {@linkcode PluginDesignTransformApi.align} snaps to.
|
|
190
|
-
* Mirrors the engine's align `DirectionType`. World-axis mapping: `left`/`right`/`center`
|
|
191
|
-
* → world X min/max/mid; `top`/`bottom`/`middle` → world Z max/min/mid.
|
|
192
|
-
*/
|
|
193
|
-
export const PluginAlignEdge = z.enum([
|
|
194
|
-
"left",
|
|
195
|
-
"right",
|
|
196
|
-
"center",
|
|
197
|
-
"top",
|
|
198
|
-
"bottom",
|
|
199
|
-
"middle",
|
|
200
|
-
])
|
|
201
|
-
export type PluginAlignEdge = z.infer<typeof PluginAlignEdge>
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Arguments for {@linkcode PluginDesignTransformApi.move} (options flattened).
|
|
205
|
-
*/
|
|
206
|
-
export const PluginDesignMoveArgs = z.object({
|
|
207
|
-
components: z.array(ComponentHandle).min(1),
|
|
208
|
-
displacement: Vec3Handle,
|
|
209
|
-
is2D: z.boolean().optional(),
|
|
210
|
-
trackParentChange: z.boolean().optional(),
|
|
211
|
-
})
|
|
212
|
-
export type PluginDesignMoveArgs = z.infer<typeof PluginDesignMoveArgs>
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Arguments for {@linkcode PluginDesignTransformApi.rotate} (options flattened).
|
|
216
|
-
*/
|
|
217
|
-
export const PluginDesignRotateArgs = z.object({
|
|
218
|
-
components: z.array(ComponentHandle).min(1),
|
|
219
|
-
angleInDegrees: z.number(),
|
|
220
|
-
axis: Vec3Handle.optional(),
|
|
221
|
-
is2D: z.boolean().optional(),
|
|
222
|
-
pivot: Vec3Handle.optional(),
|
|
223
|
-
})
|
|
224
|
-
export type PluginDesignRotateArgs = z.infer<typeof PluginDesignRotateArgs>
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Arguments for {@linkcode PluginDesignTransformApi.align} (options flattened).
|
|
228
|
-
*
|
|
229
|
-
* | Property | Type | Description |
|
|
230
|
-
* |---|---|---|
|
|
231
|
-
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to align (≥2 unless `reference` is set — host-enforced) |
|
|
232
|
-
* | `edge` | {@linkcode PluginAlignEdge} | Which bounding-box edge to snap |
|
|
233
|
-
* | `reference` | {@linkcode ComponentHandle} | A fixed component whose edge is the target (optional) |
|
|
234
|
-
*/
|
|
235
|
-
export const PluginDesignAlignArgs = z.object({
|
|
236
|
-
components: z.array(ComponentHandle).min(1),
|
|
237
|
-
edge: PluginAlignEdge,
|
|
238
|
-
reference: ComponentHandle.optional(),
|
|
239
|
-
})
|
|
240
|
-
export type PluginDesignAlignArgs = z.infer<typeof PluginDesignAlignArgs>
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Arguments for {@linkcode PluginDesignTransformApi.mirror}.
|
|
244
|
-
*
|
|
245
|
-
* | Property | Type | Description |
|
|
246
|
-
* |---|---|---|
|
|
247
|
-
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to mirror (≥1) |
|
|
248
|
-
* | `axis` | {@linkcode PluginTransformMirrorAxis} | Horizontal axis to mirror across (`'x'` \| `'z'`) |
|
|
249
|
-
*/
|
|
250
|
-
export const PluginDesignMirrorArgs = z.object({
|
|
251
|
-
components: z.array(ComponentHandle).min(1),
|
|
252
|
-
axis: PluginTransformMirrorAxis,
|
|
253
|
-
})
|
|
254
|
-
export type PluginDesignMirrorArgs = z.infer<typeof PluginDesignMirrorArgs>
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../../types"
|
|
3
|
+
import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
4
|
+
import { PluginDesignChangeResult } from "../lock"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `snaptrude.design.transform` — rigid transforms on scene entities.
|
|
8
|
+
*
|
|
9
|
+
* `move` / `rotate` migrated from the removed `tools.transform.*`; `align` snaps a
|
|
10
|
+
* set of components' bounding-box edges to each other (or to a reference); `mirror`
|
|
11
|
+
* flips components in place about a horizontal axis. All ops are undoable and return
|
|
12
|
+
* {@linkcode PluginDesignChangeResult} `{ affected }`; failures throw (RPC rejects).
|
|
13
|
+
*
|
|
14
|
+
* `getPosition` / `setPosition` (and `scale`, an engine gap) are NOT in this surface
|
|
15
|
+
* yet — they are a later pass.
|
|
16
|
+
*/
|
|
17
|
+
export abstract class PluginDesignTransformApi {
|
|
18
|
+
constructor() {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Translate entities by a **relative** displacement vector (added to the first
|
|
22
|
+
* component's absolute position as the anchor). Undoable.
|
|
23
|
+
*
|
|
24
|
+
* @param components - Entities to move
|
|
25
|
+
* @param displacement - Relative translation as a {@linkcode Vec3Handle}
|
|
26
|
+
* @param options - `is2D`, `trackParentChange`
|
|
27
|
+
* @returns {@linkcode PluginDesignChangeResult}
|
|
28
|
+
*
|
|
29
|
+
* @examplePrompt Move the selected room 5 metres to the right
|
|
30
|
+
* @examplePrompt Shift these walls 3m along the x axis
|
|
31
|
+
* @examplePrompt Nudge this space 500mm north
|
|
32
|
+
* @examplePrompt Translate the furniture block by (10, 0, 5)
|
|
33
|
+
* @examplePrompt Move these masses up one storey
|
|
34
|
+
*
|
|
35
|
+
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
36
|
+
* single call; never loop `design.transform.move` per entity.
|
|
37
|
+
*
|
|
38
|
+
* # Example
|
|
39
|
+
* ```ts
|
|
40
|
+
* const { vec3 } = snaptrude.core.math
|
|
41
|
+
* await snaptrude.design.transform.move(["space-id"], vec3.new(10, 0, 0))
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
public abstract move(
|
|
45
|
+
components: ComponentHandle[],
|
|
46
|
+
displacement: Vec3Handle,
|
|
47
|
+
options?: { is2D?: boolean; trackParentChange?: boolean },
|
|
48
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Rotate entities by a **signed angle in DEGREES** (positive = CCW about +Y).
|
|
52
|
+
* The pivot defaults to the combined bounding-box centre; pass `options.pivot`
|
|
53
|
+
* to rotate about an explicit world-space point instead. NOTE: unlike the
|
|
54
|
+
* removed `tools.transform.rotate` (radians), this canonical form takes
|
|
55
|
+
* DEGREES. Undoable.
|
|
56
|
+
*
|
|
57
|
+
* @param components - Entities to rotate
|
|
58
|
+
* @param angleInDegrees - Signed rotation angle in degrees
|
|
59
|
+
* @param options - `axis` (defaults to world +Y), `pivot` (world-space rotation
|
|
60
|
+
* centre as a {@linkcode Vec3Handle}; defaults to the combined bbox centre),
|
|
61
|
+
* `is2D`
|
|
62
|
+
* @returns {@linkcode PluginDesignChangeResult}
|
|
63
|
+
*
|
|
64
|
+
* @examplePrompt Rotate the selected building 90 degrees
|
|
65
|
+
* @examplePrompt Turn this room 45 degrees clockwise
|
|
66
|
+
* @examplePrompt Spin the furniture block 180 degrees about its centre
|
|
67
|
+
* @examplePrompt Rotate these masses 30 degrees around the vertical axis
|
|
68
|
+
* @examplePrompt Rotate these walls 90 degrees about the origin
|
|
69
|
+
*
|
|
70
|
+
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
71
|
+
* single call; never loop `design.transform.rotate` per entity.
|
|
72
|
+
*
|
|
73
|
+
* # Example
|
|
74
|
+
* ```ts
|
|
75
|
+
* await snaptrude.design.transform.rotate(["space-id"], 90)
|
|
76
|
+
* // …or rotate about an explicit pivot point
|
|
77
|
+
* const { vec3 } = snaptrude.core.math
|
|
78
|
+
* await snaptrude.design.transform.rotate(["space-id"], 90, { pivot: vec3.new(0, 0, 0) })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
public abstract rotate(
|
|
82
|
+
components: ComponentHandle[],
|
|
83
|
+
angleInDegrees: number,
|
|
84
|
+
options?: { axis?: Vec3Handle; pivot?: Vec3Handle; is2D?: boolean },
|
|
85
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Align a set of components by snapping one bounding-box edge to a common value
|
|
89
|
+
* — the classic Left/Center/Right/Top/Middle/Bottom align. Purely **world-axis**
|
|
90
|
+
* (deterministic and headless — the UI's camera-relative remap is bypassed):
|
|
91
|
+
*
|
|
92
|
+
* - `left` / `right` / `center` → world **X** min / max / mid
|
|
93
|
+
* - `top` / `bottom` / `middle` → world **Z** max / min / mid
|
|
94
|
+
*
|
|
95
|
+
* There is **no vertical (Y) alignment** in v1 (the UI only reaches it via a
|
|
96
|
+
* side-elevation camera remap, which this API does not replicate). Doors and
|
|
97
|
+
* windows are **rejected** in v1 — if any component in `components` (or the
|
|
98
|
+
* `reference`) is a door or window, the whole call **throws**; nothing is
|
|
99
|
+
* silently dropped. A group aligns as **one rigid body** (its whole-group
|
|
100
|
+
* bounding box moves together). Undoable.
|
|
101
|
+
*
|
|
102
|
+
* Requires **at least 2 components** unless a `reference` is supplied; with a
|
|
103
|
+
* reference, every component aligns to that reference's edge (the reference does
|
|
104
|
+
* not move) and a single component is allowed. Y (height) is preserved.
|
|
105
|
+
*
|
|
106
|
+
* @param components - Entities to align (≥2 without a `reference`)
|
|
107
|
+
* @param edge - Which bounding-box edge to snap ({@linkcode PluginAlignEdge})
|
|
108
|
+
* @param options - `reference`: a component whose edge is the fixed target
|
|
109
|
+
* @returns {@linkcode PluginDesignChangeResult}
|
|
110
|
+
*
|
|
111
|
+
* @examplePrompt Align the selected rooms to the left
|
|
112
|
+
* @examplePrompt Line up these masses along their top edges
|
|
113
|
+
* @examplePrompt Center these columns horizontally
|
|
114
|
+
* @examplePrompt Align all the walls to the left edge of this reference wall
|
|
115
|
+
* @examplePrompt Snap the bottom edges of these spaces together
|
|
116
|
+
*
|
|
117
|
+
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
118
|
+
* single call; never loop `design.transform.align` per entity.
|
|
119
|
+
*
|
|
120
|
+
* # Example
|
|
121
|
+
* ```ts
|
|
122
|
+
* const rooms = await snaptrude.design.selection.get()
|
|
123
|
+
* // align every room's left (world -X) edge to a common minimum
|
|
124
|
+
* await snaptrude.design.transform.align(rooms, "left")
|
|
125
|
+
* // …or align them to a fixed reference component's left edge
|
|
126
|
+
* const [anchor] = await snaptrude.design.query.listWalls({ storeys: [1] })
|
|
127
|
+
* await snaptrude.design.transform.align(rooms, "left", { reference: anchor })
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
public abstract align(
|
|
131
|
+
components: ComponentHandle[],
|
|
132
|
+
edge: PluginAlignEdge,
|
|
133
|
+
options?: { reference?: ComponentHandle },
|
|
134
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Mirror components **in place** about a horizontal axis, flipping their geometry
|
|
138
|
+
* across that axis through the combined bounding-box centre (the mesh's
|
|
139
|
+
* world-matrix flip + brep inversion + CAD/dimension-line/parametric handling
|
|
140
|
+
* commit atomically). Nothing moves off-centre — this is the toolbar "flip", not
|
|
141
|
+
* a translate-and-reflect. Undoable.
|
|
142
|
+
*
|
|
143
|
+
* `axis` names the axis the geometry mirrors **across** (world axes, Y is up):
|
|
144
|
+
* - `'x'` — mirror across world X (a front↔back flip in plan; reflects the Z coord)
|
|
145
|
+
* - `'z'` — mirror across world Z (a left↔right flip in plan; reflects the X coord)
|
|
146
|
+
*
|
|
147
|
+
* Vertical (`'y'`) mirroring is intentionally not exposed. Locked, bucket-locked
|
|
148
|
+
* and ineligible entries (terrain, plinths, reference/dimension lines,
|
|
149
|
+
* neighbourhood buildings) are **silently dropped**; the call only throws if
|
|
150
|
+
* nothing mirrorable remains. `affected` echoes the supplied handles.
|
|
151
|
+
*
|
|
152
|
+
* @param components - Entities to mirror (≥1)
|
|
153
|
+
* @param axis - Axis to mirror across ({@linkcode PluginTransformMirrorAxis})
|
|
154
|
+
* @returns {@linkcode PluginDesignChangeResult}
|
|
155
|
+
*
|
|
156
|
+
* @examplePrompt Mirror the selected building across the x axis
|
|
157
|
+
* @examplePrompt Flip these rooms left to right
|
|
158
|
+
* @examplePrompt Mirror this furniture block horizontally
|
|
159
|
+
* @examplePrompt Flip the selected walls front to back
|
|
160
|
+
* @examplePrompt Create a mirror image of these masses about the z axis
|
|
161
|
+
*
|
|
162
|
+
* @performance Array API — one host round-trip for the whole set. Pass every target in a
|
|
163
|
+
* single call; never loop `design.transform.mirror` per entity.
|
|
164
|
+
*
|
|
165
|
+
* # Example
|
|
166
|
+
* ```ts
|
|
167
|
+
* const rooms = await snaptrude.design.selection.get()
|
|
168
|
+
* await snaptrude.design.transform.mirror(rooms, "x")
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
public abstract mirror(
|
|
172
|
+
components: ComponentHandle[],
|
|
173
|
+
axis: PluginTransformMirrorAxis,
|
|
174
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The horizontal axis a {@linkcode PluginDesignTransformApi.mirror} flips **across**
|
|
179
|
+
* (world axes, Y up): `'x'` mirrors across world X (front↔back in plan; reflects Z),
|
|
180
|
+
* `'z'` mirrors across world Z (left↔right in plan; reflects X). Vertical (`'y'`)
|
|
181
|
+
* mirroring is not exposed.
|
|
182
|
+
*/
|
|
183
|
+
export const PluginTransformMirrorAxis = z.enum(["x", "z"])
|
|
184
|
+
export type PluginTransformMirrorAxis = z.infer<
|
|
185
|
+
typeof PluginTransformMirrorAxis
|
|
186
|
+
>
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The bounding-box edge an {@linkcode PluginDesignTransformApi.align} snaps to.
|
|
190
|
+
* Mirrors the engine's align `DirectionType`. World-axis mapping: `left`/`right`/`center`
|
|
191
|
+
* → world X min/max/mid; `top`/`bottom`/`middle` → world Z max/min/mid.
|
|
192
|
+
*/
|
|
193
|
+
export const PluginAlignEdge = z.enum([
|
|
194
|
+
"left",
|
|
195
|
+
"right",
|
|
196
|
+
"center",
|
|
197
|
+
"top",
|
|
198
|
+
"bottom",
|
|
199
|
+
"middle",
|
|
200
|
+
])
|
|
201
|
+
export type PluginAlignEdge = z.infer<typeof PluginAlignEdge>
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Arguments for {@linkcode PluginDesignTransformApi.move} (options flattened).
|
|
205
|
+
*/
|
|
206
|
+
export const PluginDesignMoveArgs = z.object({
|
|
207
|
+
components: z.array(ComponentHandle).min(1),
|
|
208
|
+
displacement: Vec3Handle,
|
|
209
|
+
is2D: z.boolean().optional(),
|
|
210
|
+
trackParentChange: z.boolean().optional(),
|
|
211
|
+
})
|
|
212
|
+
export type PluginDesignMoveArgs = z.infer<typeof PluginDesignMoveArgs>
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Arguments for {@linkcode PluginDesignTransformApi.rotate} (options flattened).
|
|
216
|
+
*/
|
|
217
|
+
export const PluginDesignRotateArgs = z.object({
|
|
218
|
+
components: z.array(ComponentHandle).min(1),
|
|
219
|
+
angleInDegrees: z.number(),
|
|
220
|
+
axis: Vec3Handle.optional(),
|
|
221
|
+
is2D: z.boolean().optional(),
|
|
222
|
+
pivot: Vec3Handle.optional(),
|
|
223
|
+
})
|
|
224
|
+
export type PluginDesignRotateArgs = z.infer<typeof PluginDesignRotateArgs>
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Arguments for {@linkcode PluginDesignTransformApi.align} (options flattened).
|
|
228
|
+
*
|
|
229
|
+
* | Property | Type | Description |
|
|
230
|
+
* |---|---|---|
|
|
231
|
+
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to align (≥2 unless `reference` is set — host-enforced) |
|
|
232
|
+
* | `edge` | {@linkcode PluginAlignEdge} | Which bounding-box edge to snap |
|
|
233
|
+
* | `reference` | {@linkcode ComponentHandle} | A fixed component whose edge is the target (optional) |
|
|
234
|
+
*/
|
|
235
|
+
export const PluginDesignAlignArgs = z.object({
|
|
236
|
+
components: z.array(ComponentHandle).min(1),
|
|
237
|
+
edge: PluginAlignEdge,
|
|
238
|
+
reference: ComponentHandle.optional(),
|
|
239
|
+
})
|
|
240
|
+
export type PluginDesignAlignArgs = z.infer<typeof PluginDesignAlignArgs>
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Arguments for {@linkcode PluginDesignTransformApi.mirror}.
|
|
244
|
+
*
|
|
245
|
+
* | Property | Type | Description |
|
|
246
|
+
* |---|---|---|
|
|
247
|
+
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to mirror (≥1) |
|
|
248
|
+
* | `axis` | {@linkcode PluginTransformMirrorAxis} | Horizontal axis to mirror across (`'x'` \| `'z'`) |
|
|
249
|
+
*/
|
|
250
|
+
export const PluginDesignMirrorArgs = z.object({
|
|
251
|
+
components: z.array(ComponentHandle).min(1),
|
|
252
|
+
axis: PluginTransformMirrorAxis,
|
|
253
|
+
})
|
|
254
|
+
export type PluginDesignMirrorArgs = z.infer<typeof PluginDesignMirrorArgs>
|