@snaptrude/plugin-core 0.7.1 → 0.9.0

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.
Files changed (193) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/api-manifest.full.json +7703 -0
  3. package/api-manifest.json +2946 -259
  4. package/dist/api/analysis/daylight.d.ts +603 -0
  5. package/dist/api/analysis/daylight.d.ts.map +1 -0
  6. package/dist/api/analysis/heatmaps.d.ts +438 -14
  7. package/dist/api/analysis/heatmaps.d.ts.map +1 -1
  8. package/dist/api/analysis/index.d.ts +15 -0
  9. package/dist/api/analysis/index.d.ts.map +1 -1
  10. package/dist/api/analysis/solar.d.ts +249 -0
  11. package/dist/api/analysis/solar.d.ts.map +1 -0
  12. package/dist/api/analysis/weather.d.ts +193 -0
  13. package/dist/api/analysis/weather.d.ts.map +1 -0
  14. package/dist/api/core/camera/index.d.ts +245 -0
  15. package/dist/api/core/camera/index.d.ts.map +1 -0
  16. package/dist/api/core/comment/index.d.ts +105 -2
  17. package/dist/api/core/comment/index.d.ts.map +1 -1
  18. package/dist/api/core/geom/create/index.d.ts +331 -14
  19. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  20. package/dist/api/core/geom/delete/index.d.ts +8 -2
  21. package/dist/api/core/geom/delete/index.d.ts.map +1 -1
  22. package/dist/api/core/geom/query/arc.d.ts +5 -5
  23. package/dist/api/core/geom/query/brep.d.ts +18 -18
  24. package/dist/api/core/geom/query/circle.d.ts +18 -18
  25. package/dist/api/core/geom/query/contour.d.ts +20 -20
  26. package/dist/api/core/geom/query/curve.d.ts +49 -49
  27. package/dist/api/core/geom/query/edge.d.ts +5 -5
  28. package/dist/api/core/geom/query/face.d.ts +16 -16
  29. package/dist/api/core/geom/query/halfedge.d.ts +8 -8
  30. package/dist/api/core/geom/query/profile.d.ts +19 -19
  31. package/dist/api/core/geom/query/vertex.d.ts +8 -8
  32. package/dist/api/core/geom/update/contour.d.ts +14 -14
  33. package/dist/api/core/geom/update/curve.d.ts +7 -7
  34. package/dist/api/core/geom/update/profile.d.ts +16 -16
  35. package/dist/api/core/handles/index.d.ts +210 -0
  36. package/dist/api/core/handles/index.d.ts.map +1 -0
  37. package/dist/api/core/index.d.ts +24 -0
  38. package/dist/api/core/index.d.ts.map +1 -1
  39. package/dist/api/core/io/export/index.d.ts +134 -0
  40. package/dist/api/core/io/export/index.d.ts.map +1 -0
  41. package/dist/api/core/io/import/index.d.ts +62 -1
  42. package/dist/api/core/io/import/index.d.ts.map +1 -1
  43. package/dist/api/core/io/index.d.ts +5 -0
  44. package/dist/api/core/io/index.d.ts.map +1 -1
  45. package/dist/api/core/layers.d.ts +7 -7
  46. package/dist/api/core/mode/index.d.ts +99 -0
  47. package/dist/api/core/mode/index.d.ts.map +1 -0
  48. package/dist/api/core/proposals/index.d.ts +65 -9
  49. package/dist/api/core/proposals/index.d.ts.map +1 -1
  50. package/dist/api/core/storeys/index.d.ts +251 -0
  51. package/dist/api/core/storeys/index.d.ts.map +1 -0
  52. package/dist/api/core/tags.d.ts +24 -0
  53. package/dist/api/core/tags.d.ts.map +1 -1
  54. package/dist/api/core/user.d.ts +44 -0
  55. package/dist/api/core/user.d.ts.map +1 -0
  56. package/dist/api/core/zoom/index.d.ts +4 -0
  57. package/dist/api/core/zoom/index.d.ts.map +1 -1
  58. package/dist/api/design/boolean/index.d.ts +4 -4
  59. package/dist/api/design/create/index.d.ts +253 -47
  60. package/dist/api/design/create/index.d.ts.map +1 -1
  61. package/dist/api/design/delete/index.d.ts +3 -0
  62. package/dist/api/design/delete/index.d.ts.map +1 -1
  63. package/dist/api/design/doors/index.d.ts +36 -0
  64. package/dist/api/design/doors/index.d.ts.map +1 -1
  65. package/dist/api/design/edit/index.d.ts +1 -1
  66. package/dist/api/design/erase/index.d.ts +2 -2
  67. package/dist/api/design/furniture/index.d.ts +114 -3
  68. package/dist/api/design/furniture/index.d.ts.map +1 -1
  69. package/dist/api/design/index.d.ts +10 -0
  70. package/dist/api/design/index.d.ts.map +1 -1
  71. package/dist/api/design/materials/index.d.ts +111 -14
  72. package/dist/api/design/materials/index.d.ts.map +1 -1
  73. package/dist/api/design/query/geometry/index.d.ts +112 -0
  74. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  75. package/dist/api/design/query/index.d.ts +35 -1
  76. package/dist/api/design/query/index.d.ts.map +1 -1
  77. package/dist/api/design/query/referenceLines.d.ts +45 -0
  78. package/dist/api/design/query/referenceLines.d.ts.map +1 -0
  79. package/dist/api/design/query/spaces.d.ts +178 -5
  80. package/dist/api/design/query/spaces.d.ts.map +1 -1
  81. package/dist/api/design/transform/index.d.ts +95 -14
  82. package/dist/api/design/transform/index.d.ts.map +1 -1
  83. package/dist/api/design/types/index.d.ts +181 -0
  84. package/dist/api/design/types/index.d.ts.map +1 -0
  85. package/dist/api/design/update/index.d.ts +385 -2
  86. package/dist/api/design/update/index.d.ts.map +1 -1
  87. package/dist/api/design/visibility.d.ts +98 -0
  88. package/dist/api/design/visibility.d.ts.map +1 -0
  89. package/dist/api/entity/buildableEnvelope.d.ts +4 -0
  90. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  91. package/dist/api/entity/referenceLine.d.ts +10 -2
  92. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  93. package/dist/api/entity/space.d.ts +19 -19
  94. package/dist/api/entity/story.d.ts +148 -15
  95. package/dist/api/entity/story.d.ts.map +1 -1
  96. package/dist/api/index.d.ts +5 -0
  97. package/dist/api/index.d.ts.map +1 -1
  98. package/dist/api/presentation/annotate.d.ts +448 -0
  99. package/dist/api/presentation/annotate.d.ts.map +1 -0
  100. package/dist/api/presentation/diagrams.d.ts +49 -8
  101. package/dist/api/presentation/diagrams.d.ts.map +1 -1
  102. package/dist/api/presentation/export.d.ts +108 -0
  103. package/dist/api/presentation/export.d.ts.map +1 -0
  104. package/dist/api/presentation/import.d.ts +6 -0
  105. package/dist/api/presentation/import.d.ts.map +1 -1
  106. package/dist/api/presentation/index.d.ts +47 -0
  107. package/dist/api/presentation/index.d.ts.map +1 -1
  108. package/dist/api/presentation/placedViews.d.ts +370 -0
  109. package/dist/api/presentation/placedViews.d.ts.map +1 -0
  110. package/dist/api/presentation/shapes.d.ts +481 -0
  111. package/dist/api/presentation/shapes.d.ts.map +1 -0
  112. package/dist/api/presentation/sheets.d.ts +410 -13
  113. package/dist/api/presentation/sheets.d.ts.map +1 -1
  114. package/dist/api/presentation/views.d.ts +165 -10
  115. package/dist/api/presentation/views.d.ts.map +1 -1
  116. package/dist/api/program/areas.d.ts +63 -3
  117. package/dist/api/program/areas.d.ts.map +1 -1
  118. package/dist/api/program/cores.d.ts +3 -99
  119. package/dist/api/program/cores.d.ts.map +1 -1
  120. package/dist/api/program/index.d.ts +2 -2
  121. package/dist/api/program/index.d.ts.map +1 -1
  122. package/dist/api/program/layout.d.ts +172 -12
  123. package/dist/api/program/layout.d.ts.map +1 -1
  124. package/dist/api/program/site.d.ts +105 -8
  125. package/dist/api/program/site.d.ts.map +1 -1
  126. package/dist/api/program/spreadsheet.d.ts +365 -41
  127. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  128. package/dist/api/workspace/index.d.ts +460 -0
  129. package/dist/api/workspace/index.d.ts.map +1 -0
  130. package/dist/handles.d.ts +64 -25
  131. package/dist/handles.d.ts.map +1 -1
  132. package/dist/index.cjs +3210 -1671
  133. package/dist/index.cjs.map +1 -1
  134. package/dist/index.js +3008 -1666
  135. package/dist/index.js.map +1 -1
  136. package/package.json +3 -2
  137. package/scripts/generate-manifest.mjs +45 -0
  138. package/src/api/analysis/daylight.ts +470 -0
  139. package/src/api/analysis/heatmaps.ts +444 -17
  140. package/src/api/analysis/index.ts +15 -0
  141. package/src/api/analysis/solar.ts +237 -0
  142. package/src/api/analysis/weather.ts +179 -0
  143. package/src/api/core/camera/index.ts +251 -0
  144. package/src/api/core/comment/index.ts +120 -2
  145. package/src/api/core/geom/create/index.ts +344 -1
  146. package/src/api/core/geom/delete/index.ts +6 -0
  147. package/src/api/core/handles/index.ts +233 -0
  148. package/src/api/core/index.ts +24 -0
  149. package/src/api/core/io/export/index.ts +126 -0
  150. package/src/api/core/io/import/index.ts +64 -0
  151. package/src/api/core/io/index.ts +5 -0
  152. package/src/api/core/mode/index.ts +96 -0
  153. package/src/api/core/proposals/index.ts +71 -11
  154. package/src/api/core/storeys/index.ts +279 -0
  155. package/src/api/core/tags.ts +27 -0
  156. package/src/api/core/user.ts +46 -0
  157. package/src/api/core/zoom/index.ts +4 -0
  158. package/src/api/design/create/index.ts +303 -36
  159. package/src/api/design/delete/index.ts +3 -0
  160. package/src/api/design/doors/index.ts +40 -0
  161. package/src/api/design/furniture/index.ts +127 -3
  162. package/src/api/design/index.ts +10 -0
  163. package/src/api/design/materials/index.ts +157 -30
  164. package/src/api/design/query/geometry/index.ts +125 -3
  165. package/src/api/design/query/index.ts +37 -7
  166. package/src/api/design/query/referenceLines.ts +52 -0
  167. package/src/api/design/query/spaces.ts +143 -0
  168. package/src/api/design/transform/index.ts +101 -12
  169. package/src/api/design/types/index.ts +156 -0
  170. package/src/api/design/update/index.ts +467 -6
  171. package/src/api/design/visibility.ts +109 -0
  172. package/src/api/entity/buildableEnvelope.ts +4 -0
  173. package/src/api/entity/referenceLine.ts +8 -0
  174. package/src/api/entity/story.ts +161 -15
  175. package/src/api/index.ts +5 -0
  176. package/src/api/presentation/annotate.ts +360 -0
  177. package/src/api/presentation/diagrams.ts +53 -8
  178. package/src/api/presentation/export.ts +108 -0
  179. package/src/api/presentation/import.ts +6 -0
  180. package/src/api/presentation/index.ts +55 -0
  181. package/src/api/presentation/placedViews.ts +363 -0
  182. package/src/api/presentation/shapes.ts +274 -0
  183. package/src/api/presentation/sheets.ts +346 -13
  184. package/src/api/presentation/views.ts +164 -12
  185. package/src/api/program/areas.ts +57 -6
  186. package/src/api/program/cores.ts +3 -91
  187. package/src/api/program/index.ts +2 -2
  188. package/src/api/program/layout.ts +182 -12
  189. package/src/api/program/site.ts +106 -8
  190. package/src/api/program/spreadsheet.ts +376 -35
  191. package/src/api/workspace/index.ts +516 -0
  192. package/src/handles.ts +77 -13
  193. package/tsconfig.json +7 -2
@@ -1,6 +1,7 @@
1
1
  import * as z from "zod"
2
2
  import { PluginApiReturn } from "../../../types"
3
3
  import {
4
+ BrepHandle,
4
5
  ComponentHandle,
5
6
  ContourHandle,
6
7
  ProfileHandle,
@@ -11,6 +12,12 @@ import {
11
12
  PluginMassType,
12
13
  PluginDepartmentId,
13
14
  } from "../../entity/space"
15
+ import {
16
+ PluginBuildableEnvelopePolygonVertex,
17
+ PluginBuildableEnvelopeSetbackTier,
18
+ PluginBuildableEnvelopeVerticalCap,
19
+ PluginBuildableEnvelopeCreateResult,
20
+ } from "../../entity/buildableEnvelope"
14
21
 
15
22
  /**
16
23
  * `design.create.*` — author new scene-committed BIM entities.
@@ -50,14 +57,25 @@ export abstract class PluginDesignCreateApi {
50
57
  * @param spaceType - Space-type classification (default `Room`)
51
58
  * @param massType - Mass-type classification (default `Room`)
52
59
  * @param departmentId - Department assignment (default department)
60
+ * @param storey - Target storey number to place the space on — the same integer
61
+ * `entity.story` uses (`1` ground, `2` first floor, `-1` basement). Default:
62
+ * the active storey. Folds a `core.storeys.setActive` call into the create,
63
+ * placing the space at that storey's floor elevation (any `position` offset is
64
+ * applied on top). Throws if no storey has that value.
53
65
  * @returns the {@linkcode ComponentHandle} of the created space
54
- * @throws if the contour is invalid or the height is not positive
66
+ * @throws if the contour is invalid, the height is not positive, or the target
67
+ * storey does not exist
55
68
  *
56
69
  * @examplePrompt Create a room called Living Room that's 3m tall from this outline
57
70
  * @examplePrompt Add a new space on the current storey using this footprint
58
71
  * @examplePrompt Make a bedroom here and assign it to the Residential department
59
72
  * @examplePrompt Extrude this closed outline into a 10 foot high room
60
73
  * @examplePrompt Can you create a Kitchen space from the sketch I just drew?
74
+ * @examplePrompt Create a bedroom on the second floor from this outline
75
+ *
76
+ * @performance For MORE THAN ONE space, call `design.create.spaces(items[])` — the whole
77
+ * batch is one host round-trip. Looping this single-space creator is N round-trips (slow,
78
+ * and a large loop can trip the plugin rate limit).
61
79
  *
62
80
  * # Example
63
81
  * ```ts
@@ -70,6 +88,10 @@ export abstract class PluginDesignCreateApi {
70
88
  * ])
71
89
  * const contour = await snaptrude.core.geom.create.contourFromProfile(outer)
72
90
  * const space = await snaptrude.design.create.space(contour, 3, "Living")
91
+ * // …place one directly on the second floor (no setActive dance):
92
+ * const upstairs = await snaptrude.design.create.space(
93
+ * contour, 3, "Bedroom", undefined, undefined, undefined, undefined, 2,
94
+ * )
73
95
  * ```
74
96
  */
75
97
  public abstract space(
@@ -80,6 +102,7 @@ export abstract class PluginDesignCreateApi {
80
102
  spaceType?: PluginSpaceType,
81
103
  massType?: PluginMassType,
82
104
  departmentId?: PluginDepartmentId,
105
+ storey?: number,
83
106
  ): PluginApiReturn<ComponentHandle>
84
107
 
85
108
  /**
@@ -114,6 +137,51 @@ export abstract class PluginDesignCreateApi {
114
137
  massType?: PluginMassType,
115
138
  ): PluginApiReturn<ComponentHandle>
116
139
 
140
+ /**
141
+ * Create a **mass** from a custom solid built with a `core.geom.create` brep
142
+ * constructor (`brepFromFaces`, `brepFromExtrusion`, `brepFromLoft`,
143
+ * `brepFromMesh`, or a brep boolean) — the free-form counterpart of
144
+ * {@linkcode PluginDesignCreateApi.mass}, for solids that are not simple
145
+ * footprint extrusions (pyramids, wedges, faceted volumes).
146
+ *
147
+ * Only accepts breps **minted by a `core.geom.create` brep constructor** —
148
+ * scene-derived breps from `design.query.geometry.getBrep` are read-only and
149
+ * throw. The mass is created as a generic mass (`massType` "Generic mass") at
150
+ * the exact coordinates the solid was authored in, committed as a single
151
+ * undo step, and synced to collaborators like any other creator.
152
+ *
153
+ * @param brep - A solid from a `core.geom.create` brep constructor
154
+ * @param label - Label (maps to `room_type`)
155
+ * @returns the {@linkcode ComponentHandle} of the created mass
156
+ * @throws if the brep handle is invalid, or the brep was not created by a
157
+ * `core.geom.create` brep constructor
158
+ *
159
+ * @examplePrompt Create a mass from these faces
160
+ * @examplePrompt Turn this custom brep into a scene mass
161
+ * @examplePrompt Add a pyramid-shaped mass to the model
162
+ *
163
+ * # Example
164
+ * ```ts
165
+ * const apex = { x: 0, y: 4, z: 0 }
166
+ * const a = { x: -2, y: 0, z: -2 }
167
+ * const b = { x: 2, y: 0, z: -2 }
168
+ * const c = { x: 2, y: 0, z: 2 }
169
+ * const d = { x: -2, y: 0, z: 2 }
170
+ * const brep = await snaptrude.core.geom.create.brepFromFaces([
171
+ * [a, d, c, b],
172
+ * [a, b, apex],
173
+ * [b, c, apex],
174
+ * [c, d, apex],
175
+ * [d, a, apex],
176
+ * ])
177
+ * const pyramid = await snaptrude.design.create.massFromBrep(brep, "Pavilion")
178
+ * ```
179
+ */
180
+ public abstract massFromBrep(
181
+ brep: BrepHandle,
182
+ label?: string,
183
+ ): PluginApiReturn<ComponentHandle>
184
+
117
185
  /**
118
186
  * Create a **slab** by extruding a footprint contour by `thickness`
119
187
  * (default direction: down).
@@ -229,14 +297,17 @@ export abstract class PluginDesignCreateApi {
229
297
 
230
298
  /**
231
299
  * Create a **column** by extruding a cross-section contour upward by `height`
232
- * from a base `position`.
300
+ * from a base `position`. The column is built to EXACTLY `height` — unlike
301
+ * the interactive draw tool, no slab-thickness deduction is applied.
233
302
  *
234
303
  * @param position - Base point
235
304
  * @param crossSection - Column cross-section footprint
236
- * @param height - Column height (> 0)
237
- * @param directionUp - Up axis (default world up)
305
+ * @param height - Column height (> 0), built exactly
306
+ * @param directionUp - Up axis (default world up); normalized by the host, so
307
+ * magnitude does not scale the height
238
308
  * @returns the {@linkcode ComponentHandle} of the created column
239
- * @throws if the cross-section is invalid or the height is not positive
309
+ * @throws if the cross-section is invalid, the height is not positive, or the
310
+ * direction is zero / lies in the cross-section plane (degenerate extrusion)
240
311
  *
241
312
  * @examplePrompt Add a 3m tall column at this point
242
313
  * @examplePrompt Place a column at the grid intersection
@@ -260,13 +331,30 @@ export abstract class PluginDesignCreateApi {
260
331
 
261
332
  /**
262
333
  * Create a **beam** by extruding a cross-section contour along `direction` by
263
- * `length`.
334
+ * `length`. Matches the Snaptrude beam tool's semantics: the beam body hangs
335
+ * BELOW the plane the section is authored on.
336
+ *
337
+ * For a **horizontal** `direction` (the common spanning beam), author the
338
+ * section as an axis-aligned plan rectangle: its X extent is the beam's
339
+ * width, its Z extent is the beam's depth (the vertical drop). The beam runs
340
+ * `length` along `direction` starting at the section's centre, hanging below
341
+ * the authoring plane by its depth — exactly like an interactively drawn
342
+ * beam. Only axis-aligned rectangular sections are supported horizontally.
343
+ *
344
+ * For a **vertical** `direction` (the default), the section itself is
345
+ * extruded by `length`, again hanging below the authoring plane. Diagonal
346
+ * directions are rejected.
264
347
  *
265
- * @param section - Beam cross-section footprint
266
- * @param length - Beam length along `direction` (> 0)
267
- * @param direction - Extrusion axis (default world up)
348
+ * @param section - Beam cross-section, an axis-aligned rectangle in plan
349
+ * (X extent = width, Z extent = depth)
350
+ * @param length - Beam length along `direction` (> 0); direction is
351
+ * normalized by the host, so magnitude does not scale the length
352
+ * @param direction - Beam axis: horizontal for a spanning beam, or vertical
353
+ * (default world up). Diagonal directions throw.
268
354
  * @returns the {@linkcode ComponentHandle} of the created beam
269
- * @throws if the section is invalid or the length is not positive
355
+ * @throws if the section is invalid (horizontal beams: not an axis-aligned
356
+ * plan rectangle), the length is not positive, or the direction is zero or
357
+ * diagonal
270
358
  *
271
359
  * @examplePrompt Add a beam spanning 6 metres between the columns
272
360
  * @examplePrompt Create a horizontal beam along the X axis
@@ -293,15 +381,25 @@ export abstract class PluginDesignCreateApi {
293
381
  *
294
382
  * @param profile - Ordered curve chain (wall centerlines)
295
383
  * @param height - Wall height (default engine default)
296
- * @param thickness - Wall thickness (default engine default)
384
+ * @param thickness - Wall thickness (default: the `wallType`'s total layer
385
+ * thickness when `wallType` is given, else the engine default)
386
+ * @param wallType - Wall type to build with — the same searchable list the
387
+ * Draw tab's Wall Type dropdown offers. Pass a name from
388
+ * `design.types.list("wall")` (the summary's `label`, or its `"wall:…"` id).
389
+ * Drives the wall's construction layers and default material, and — when
390
+ * `thickness` is omitted — its total layer thickness. Default: the engine's
391
+ * generic wall.
297
392
  * @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
298
- * @throws if the profile is empty or wall creation fails
393
+ * @throws if the profile is empty, `wallType` names no wall type in the
394
+ * project, or wall creation fails
299
395
  *
300
396
  * @examplePrompt Draw walls along this centerline
301
397
  * @examplePrompt Create 3m high, 200mm thick walls from these points
302
398
  * @examplePrompt Build a wall run around the room outline
303
399
  * @examplePrompt Turn this polyline sketch into walls
304
400
  * @examplePrompt Add walls with mitred corners along the path
401
+ * @examplePrompt Draw brick walls with plaster along this outline
402
+ * @examplePrompt Build the perimeter in exposed concrete walls
305
403
  *
306
404
  * # Example
307
405
  * ```ts
@@ -312,12 +410,18 @@ export abstract class PluginDesignCreateApi {
312
410
  * await v.new(8, 0, 6),
313
411
  * ])
314
412
  * const walls = await snaptrude.design.create.walls(centerlines, 3, 0.2)
413
+ * // …built as a specific wall type (layers/material/thickness from the type):
414
+ * const [brick] = await snaptrude.design.types.list("wall")
415
+ * const brickWalls = await snaptrude.design.create.walls(
416
+ * centerlines, 3, undefined, brick.label,
417
+ * )
315
418
  * ```
316
419
  */
317
420
  public abstract walls(
318
421
  profile: ProfileHandle,
319
422
  height?: number,
320
423
  thickness?: number,
424
+ wallType?: string,
321
425
  ): PluginApiReturn<ComponentHandle[]>
322
426
 
323
427
  /**
@@ -408,14 +512,19 @@ export abstract class PluginDesignCreateApi {
408
512
  * with {@linkcode PluginDesignFurnitureApi.listCatalog}. Placement is asynchronous
409
513
  * (the source mesh is fetched if not cached) and creates one undo entry.
410
514
  *
411
- * Placed at the item's default rotation; rotate afterward via `design.transform.rotate`
412
- * on the returned handle (planned namespace).
515
+ * Placed at the item's default rotation unless `angleInDegrees` is given, which
516
+ * rotates it about the vertical axis at creation time (baked into the same undo
517
+ * entry). To rotate an existing instance instead, use `design.transform.rotate`.
413
518
  *
414
519
  * @param catalogId - Library id: team `_id` or general `fullName`
415
520
  * @param position - Absolute world placement point
416
521
  * @param options - Optional placement options: `label` — instance name
417
522
  * (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
418
523
  * source-mesh creation command (default `true`)
524
+ * @param angleInDegrees - Optional signed rotation about the vertical axis, in
525
+ * degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
526
+ * Applied at creation time so it is part of the placement's single undo entry.
527
+ * Default: the item's own (unrotated) orientation.
419
528
  * @returns the {@linkcode ComponentHandle} of the placed furniture instance
420
529
  * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
421
530
  *
@@ -424,6 +533,7 @@ export abstract class PluginDesignCreateApi {
424
533
  * @examplePrompt Drop a desk into the scene at 3, 0, 5
425
534
  * @examplePrompt Insert the uploaded bed model in the bedroom
426
535
  * @examplePrompt Put a table from my project library here and name it Table-01
536
+ * @examplePrompt Place a chair here rotated 90 degrees
427
537
  *
428
538
  * # Example
429
539
  * ```ts
@@ -432,12 +542,20 @@ export abstract class PluginDesignCreateApi {
432
542
  * await snaptrude.core.math.vec3.new(3, 0, 5),
433
543
  * { label: "Chair-01" },
434
544
  * )
545
+ * // …placed already turned 90° about the vertical axis:
546
+ * const turned = await snaptrude.design.create.furniture(
547
+ * "6620f1a…",
548
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
549
+ * undefined,
550
+ * 90,
551
+ * )
435
552
  * ```
436
553
  */
437
554
  public abstract furniture(
438
555
  catalogId: string,
439
556
  position: Vec3Handle,
440
557
  options?: { label?: string; createNewSourceMesh?: boolean },
558
+ angleInDegrees?: number,
441
559
  ): PluginApiReturn<ComponentHandle>
442
560
 
443
561
  /**
@@ -454,6 +572,11 @@ export abstract class PluginDesignCreateApi {
454
572
  * @param hostWall - The wall to host the door
455
573
  * @param position - World point projected onto the wall to locate the opening
456
574
  * @param options - Optional placement options: `label` — instance name
575
+ * @param facing - World point selecting which side of the wall the door faces
576
+ * (the room it opens into) — the same convention as approaching the wall
577
+ * from that side with the cursor in the interactive tool. Any point clearly
578
+ * on that side works (e.g. the room's center). Default: the engine picks a
579
+ * side (nondeterministic when `position` sits on the wall centerline).
457
580
  * @returns the {@linkcode ComponentHandle} of the placed door
458
581
  * @throws if the catalog id is unknown, the host is not a wall, the source
459
582
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -463,6 +586,7 @@ export abstract class PluginDesignCreateApi {
463
586
  * @examplePrompt Put a door from the catalog at this point on the wall
464
587
  * @examplePrompt Insert the entrance door into this wall
465
588
  * @examplePrompt Add a door to the wall and call it Entry-01
589
+ * @examplePrompt Add a door that opens into the living room
466
590
  *
467
591
  * # Example
468
592
  * ```ts
@@ -474,6 +598,14 @@ export abstract class PluginDesignCreateApi {
474
598
  * await snaptrude.core.math.vec3.new(3, 0, 5),
475
599
  * { label: "Entry-01" },
476
600
  * )
601
+ * // …facing a specific side of the wall (pass a point inside that room):
602
+ * const intoKitchen = await snaptrude.design.create.door(
603
+ * entry.id,
604
+ * wall,
605
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
606
+ * undefined,
607
+ * await snaptrude.core.math.vec3.new(3, 0, 9),
608
+ * )
477
609
  * ```
478
610
  */
479
611
  public abstract door(
@@ -481,6 +613,7 @@ export abstract class PluginDesignCreateApi {
481
613
  hostWall: ComponentHandle,
482
614
  position: Vec3Handle,
483
615
  options?: { label?: string },
616
+ facing?: Vec3Handle,
484
617
  ): PluginApiReturn<ComponentHandle>
485
618
 
486
619
  /**
@@ -497,6 +630,10 @@ export abstract class PluginDesignCreateApi {
497
630
  * @param hostWall - The wall to host the window
498
631
  * @param position - World point projected onto the wall to locate the opening
499
632
  * @param options - Optional placement options: `label` — instance name
633
+ * @param facing - World point selecting which side of the wall the window
634
+ * faces (matters for asymmetric windows, e.g. casement swing) — same
635
+ * convention as {@linkcode PluginDesignCreateApi.door}. Default: the engine
636
+ * picks a side (nondeterministic when `position` sits on the centerline).
500
637
  * @returns the {@linkcode ComponentHandle} of the placed window
501
638
  * @throws if the catalog id is unknown, the host is not a wall, the source
502
639
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -506,6 +643,7 @@ export abstract class PluginDesignCreateApi {
506
643
  * @examplePrompt Put a window from the catalog at this point on the wall
507
644
  * @examplePrompt Insert a window into the living room wall
508
645
  * @examplePrompt Add a window to the wall and name it Win-01
646
+ * @examplePrompt Add a casement window opening toward the garden side
509
647
  *
510
648
  * # Example
511
649
  * ```ts
@@ -524,6 +662,7 @@ export abstract class PluginDesignCreateApi {
524
662
  hostWall: ComponentHandle,
525
663
  position: Vec3Handle,
526
664
  options?: { label?: string },
665
+ facing?: Vec3Handle,
527
666
  ): PluginApiReturn<ComponentHandle>
528
667
 
529
668
  /**
@@ -602,6 +741,11 @@ export abstract class PluginDesignCreateApi {
602
741
  * @examplePrompt Array these walls with a 3m offset
603
742
  * @examplePrompt Clone the desk as a unique copy, not an instance
604
743
  *
744
+ * @performance To place N repeats of the same geometry, bulk-create the seed(s) once then
745
+ * call this ONCE with `{ count: N - 1 }` — one host round-trip for all copies. Never
746
+ * reproduce geometry by looping `design.create.*` N times. Copy only after the create
747
+ * that mints the seed ids.
748
+ *
605
749
  * # Example
606
750
  * ```ts
607
751
  * const { vec3 } = snaptrude.core.math
@@ -619,15 +763,24 @@ export abstract class PluginDesignCreateApi {
619
763
  * Migrated from the removed `entity.space.bulkCreate`. Each item extrudes a contour
620
764
  * footprint up `height`. Validate-all-or-throw; one command. For a rectangular
621
765
  * (box) space, build the footprint with `core.geom.create.profileRect` →
622
- * `contourFromProfile`, then pass it as an item.
766
+ * `contourFromProfile`, then pass it as an item. Each item may carry its own
767
+ * `storey` (see {@linkcode PluginCreateSpaceItem}) so a single call can populate
768
+ * several floors at once.
623
769
  *
624
770
  * @param items - One {@linkcode PluginCreateSpaceItem} per space to create (≥1)
625
771
  * @returns the created spaces as {@linkcode ComponentHandle}`[]`, in input order
772
+ * @throws if any item's contour is invalid, its height is not positive, or its
773
+ * target `storey` does not exist (all-or-nothing — nothing is created)
626
774
  *
627
775
  * @examplePrompt Create several rooms at once from these footprints
628
776
  * @examplePrompt Generate all the bedrooms in one operation
629
777
  * @examplePrompt Bulk create the spaces for this floor plan
630
778
  * @examplePrompt Add three rooms with different heights in a single undo step
779
+ * @examplePrompt Create one room on the ground floor and one on the first floor
780
+ *
781
+ * @performance Bulk creator — the whole batch is ONE host round-trip. Always prefer this
782
+ * over calling `design.create.space` in a loop: build the full `items[]` array first
783
+ * (all per-item math and geometry up front), then make one call.
631
784
  *
632
785
  * # Example
633
786
  * ```ts
@@ -639,7 +792,61 @@ export abstract class PluginDesignCreateApi {
639
792
  * ])
640
793
  * ```
641
794
  */
642
- public abstract spaces(items: PluginCreateSpaceItem[]): PluginApiReturn<ComponentHandle[]>
795
+ public abstract spaces(
796
+ items: PluginCreateSpaceItem[],
797
+ ): PluginApiReturn<ComponentHandle[]>
798
+
799
+ /**
800
+ * Create a new parametric buildable envelope — the zoning-regulated volume a
801
+ * building may occupy — generated from a site polygon, tiered setbacks, a
802
+ * height or floor-count cap, and optional FAR and lot-coverage limits. The host
803
+ * mints the envelope id and returns it. Canonical home of the create formerly
804
+ * at `entity.buildableEnvelope.create` (now deprecated).
805
+ *
806
+ * @param sitePolygon - Site polygon vertices in `lengthUnit`; minimum 3 vertices.
807
+ * @param lengthUnit - Unit used by all length fields (`"ft" | "m"`).
808
+ * @param setbacks - Setback profile, ground tier first; minimum 1 tier.
809
+ * @param verticalCap - Maximum height or floor count.
810
+ * @param floorToFloor - Required floor-to-floor height in `lengthUnit`.
811
+ * @param farRatio - Optional FAR value, positive when provided.
812
+ * @param lotCoverageMaxPct - Optional lot coverage cap, `0..100`.
813
+ * @returns A {@linkcode PluginBuildableEnvelopeCreateResult} with the
814
+ * `buildableEnvelopeId` of the created envelope.
815
+ * @throws If validation fails or generation produces no renderable geometry.
816
+ *
817
+ * @examplePrompt Create a buildable envelope for my site
818
+ * @examplePrompt Generate the zoning envelope with 10ft front setbacks
819
+ * @examplePrompt Show the maximum buildable volume with a 150ft height limit
820
+ * @examplePrompt Create a zoning envelope capped at 12 floors with FAR 3
821
+ *
822
+ * # Example
823
+ * ```ts
824
+ * const { buildableEnvelopeId } = await snaptrude.design.create.buildableEnvelope(
825
+ * [
826
+ * { x: 0, z: 0 },
827
+ * { x: 100, z: 0 },
828
+ * { x: 100, z: 80 },
829
+ * { x: 0, z: 80 },
830
+ * ],
831
+ * "ft",
832
+ * [
833
+ * { aboveHeight: 0, front: 10, side: 5, rear: 10 },
834
+ * { aboveHeight: 100, front: 20, side: 10, rear: 20 },
835
+ * ],
836
+ * { kind: "max_height", maxHeight: 150 },
837
+ * 12,
838
+ * )
839
+ * ```
840
+ */
841
+ public abstract buildableEnvelope(
842
+ sitePolygon: PluginBuildableEnvelopePolygonVertex[],
843
+ lengthUnit: "ft" | "m",
844
+ setbacks: PluginBuildableEnvelopeSetbackTier[],
845
+ verticalCap: PluginBuildableEnvelopeVerticalCap,
846
+ floorToFloor: number,
847
+ farRatio?: number,
848
+ lotCoverageMaxPct?: number,
849
+ ): PluginApiReturn<PluginBuildableEnvelopeCreateResult>
643
850
  }
644
851
 
645
852
  // ---------------------------------------------------------------------------
@@ -717,6 +924,7 @@ export type PluginStaircasePreset = z.infer<typeof PluginStaircasePreset>
717
924
  * | `spaceType` | {@linkcode PluginSpaceType}? | Space-type classification (default `Room`) |
718
925
  * | `massType` | {@linkcode PluginMassType}? | Mass-type classification (default `Room`) |
719
926
  * | `departmentId` | {@linkcode PluginDepartmentId}? | Department assignment (default department) |
927
+ * | `storey` | `number`? (int) | Target storey number (default active storey) |
720
928
  */
721
929
  export const PluginDesignCreateSpaceArgs = z.object({
722
930
  contour: ContourHandle,
@@ -726,8 +934,13 @@ export const PluginDesignCreateSpaceArgs = z.object({
726
934
  spaceType: PluginSpaceType.optional(),
727
935
  massType: PluginMassType.optional(),
728
936
  departmentId: PluginDepartmentId.optional(),
937
+ storey: z.number().int().optional(),
729
938
  })
730
- export type PluginDesignCreateSpaceArgs = z.infer<typeof PluginDesignCreateSpaceArgs>
939
+ export type PluginDesignCreateSpaceArgs = z.infer<
940
+ typeof PluginDesignCreateSpaceArgs
941
+ >
942
+ // TRANSPORT: positional signature shipped — storey is the trailing 8th arg:
943
+ // space(contour, height, label?, position?, spaceType?, massType?, departmentId?, storey?)
731
944
 
732
945
  // ---------------------------------------------------------------------------
733
946
  // mass
@@ -751,7 +964,29 @@ export const PluginDesignCreateMassArgs = z.object({
751
964
  position: Vec3Handle.optional(),
752
965
  massType: PluginMassType.optional(),
753
966
  })
754
- export type PluginDesignCreateMassArgs = z.infer<typeof PluginDesignCreateMassArgs>
967
+ export type PluginDesignCreateMassArgs = z.infer<
968
+ typeof PluginDesignCreateMassArgs
969
+ >
970
+
971
+ // ---------------------------------------------------------------------------
972
+ // massFromBrep
973
+ // ---------------------------------------------------------------------------
974
+
975
+ /**
976
+ * Arguments for {@linkcode PluginDesignCreateApi.massFromBrep}.
977
+ *
978
+ * | Property | Type | Description |
979
+ * |---|---|---|
980
+ * | `brep` | {@linkcode BrepHandle} | A solid from a `core.geom.create` brep constructor |
981
+ * | `label` | `string`? | Label (maps to `room_type`) |
982
+ */
983
+ export const PluginDesignCreateMassFromBrepArgs = z.object({
984
+ brep: BrepHandle,
985
+ label: z.string().optional(),
986
+ })
987
+ export type PluginDesignCreateMassFromBrepArgs = z.infer<
988
+ typeof PluginDesignCreateMassFromBrepArgs
989
+ >
755
990
 
756
991
  // ---------------------------------------------------------------------------
757
992
  // slab
@@ -773,7 +1008,9 @@ export const PluginDesignCreateSlabArgs = z.object({
773
1008
  direction: z.enum(["up", "down"]).optional(),
774
1009
  slabType: PluginSlabType.optional(),
775
1010
  })
776
- export type PluginDesignCreateSlabArgs = z.infer<typeof PluginDesignCreateSlabArgs>
1011
+ export type PluginDesignCreateSlabArgs = z.infer<
1012
+ typeof PluginDesignCreateSlabArgs
1013
+ >
777
1014
 
778
1015
  // ---------------------------------------------------------------------------
779
1016
  // floor
@@ -793,7 +1030,9 @@ export const PluginDesignCreateFloorArgs = z.object({
793
1030
  thickness: z.number(),
794
1031
  position: Vec3Handle.optional(),
795
1032
  })
796
- export type PluginDesignCreateFloorArgs = z.infer<typeof PluginDesignCreateFloorArgs>
1033
+ export type PluginDesignCreateFloorArgs = z.infer<
1034
+ typeof PluginDesignCreateFloorArgs
1035
+ >
797
1036
 
798
1037
  // ---------------------------------------------------------------------------
799
1038
  // roof
@@ -811,7 +1050,9 @@ export const PluginDesignCreateRoofArgs = z.object({
811
1050
  contour: ContourHandle,
812
1051
  thickness: z.number(),
813
1052
  })
814
- export type PluginDesignCreateRoofArgs = z.infer<typeof PluginDesignCreateRoofArgs>
1053
+ export type PluginDesignCreateRoofArgs = z.infer<
1054
+ typeof PluginDesignCreateRoofArgs
1055
+ >
815
1056
 
816
1057
  // ---------------------------------------------------------------------------
817
1058
  // ceiling
@@ -831,7 +1072,9 @@ export const PluginDesignCreateCeilingArgs = z.object({
831
1072
  thickness: z.number(),
832
1073
  heightFromFloor: z.number().optional(),
833
1074
  })
834
- export type PluginDesignCreateCeilingArgs = z.infer<typeof PluginDesignCreateCeilingArgs>
1075
+ export type PluginDesignCreateCeilingArgs = z.infer<
1076
+ typeof PluginDesignCreateCeilingArgs
1077
+ >
835
1078
 
836
1079
  // ---------------------------------------------------------------------------
837
1080
  // column
@@ -853,7 +1096,9 @@ export const PluginDesignCreateColumnArgs = z.object({
853
1096
  height: z.number(),
854
1097
  directionUp: Vec3Handle.optional(),
855
1098
  })
856
- export type PluginDesignCreateColumnArgs = z.infer<typeof PluginDesignCreateColumnArgs>
1099
+ export type PluginDesignCreateColumnArgs = z.infer<
1100
+ typeof PluginDesignCreateColumnArgs
1101
+ >
857
1102
 
858
1103
  // ---------------------------------------------------------------------------
859
1104
  // beam
@@ -873,7 +1118,9 @@ export const PluginDesignCreateBeamArgs = z.object({
873
1118
  length: z.number(),
874
1119
  direction: Vec3Handle.optional(),
875
1120
  })
876
- export type PluginDesignCreateBeamArgs = z.infer<typeof PluginDesignCreateBeamArgs>
1121
+ export type PluginDesignCreateBeamArgs = z.infer<
1122
+ typeof PluginDesignCreateBeamArgs
1123
+ >
877
1124
 
878
1125
  // ---------------------------------------------------------------------------
879
1126
  // walls
@@ -886,14 +1133,20 @@ export type PluginDesignCreateBeamArgs = z.infer<typeof PluginDesignCreateBeamAr
886
1133
  * |---|---|---|
887
1134
  * | `profile` | {@linkcode ProfileHandle} | Ordered curve chain (wall centerlines) |
888
1135
  * | `height` | `number`? | Wall height (default engine default) |
889
- * | `thickness` | `number`? | Wall thickness (default engine default) |
1136
+ * | `thickness` | `number`? | Wall thickness (default: `wallType`'s total layer thickness when given, else engine default) |
1137
+ * | `wallType` | `string`? | Wall type name from `design.types.list("wall")` — layers/material/thickness defaults (default generic) |
890
1138
  */
891
1139
  export const PluginDesignCreateWallsArgs = z.object({
892
1140
  profile: ProfileHandle,
893
1141
  height: z.number().optional(),
894
1142
  thickness: z.number().optional(),
1143
+ wallType: z.string().min(1).optional(),
895
1144
  })
896
- export type PluginDesignCreateWallsArgs = z.infer<typeof PluginDesignCreateWallsArgs>
1145
+ export type PluginDesignCreateWallsArgs = z.infer<
1146
+ typeof PluginDesignCreateWallsArgs
1147
+ >
1148
+ // TRANSPORT: positional signature shipped — wallType is the trailing 4th arg:
1149
+ // walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string)
897
1150
 
898
1151
  // ---------------------------------------------------------------------------
899
1152
  // staircase
@@ -934,18 +1187,20 @@ export type PluginDesignCreateStaircaseArgs = z.infer<
934
1187
  * | `position` | {@linkcode Vec3Handle} | Absolute world placement point |
935
1188
  * | `label` | `string`? | Instance name (default auto `${name}Ins${n}`) |
936
1189
  * | `createNewSourceMesh` | `boolean`? | Emit a source-mesh creation command (default `true`) |
1190
+ * | `angleInDegrees` | `number`? | Rotation about the vertical axis, in degrees (default unrotated) |
937
1191
  */
938
1192
  export const PluginDesignCreateFurnitureArgs = z.object({
939
1193
  catalogId: z.string().min(1),
940
1194
  position: Vec3Handle,
941
1195
  label: z.string().optional(),
942
1196
  createNewSourceMesh: z.boolean().optional(),
1197
+ angleInDegrees: z.number().optional(),
943
1198
  })
944
1199
  export type PluginDesignCreateFurnitureArgs = z.infer<
945
1200
  typeof PluginDesignCreateFurnitureArgs
946
1201
  >
947
- // TRANSPORT: positional signature shipped —
948
- // furniture(catalogId: string, position: Vec3Handle, options?: { label?, createNewSourceMesh? })
1202
+ // TRANSPORT: positional signature shipped — angleInDegrees is the trailing 4th arg:
1203
+ // furniture(catalogId: string, position: Vec3Handle, options?: { label?, createNewSourceMesh? }, angleInDegrees?: number)
949
1204
 
950
1205
  // ---------------------------------------------------------------------------
951
1206
  // door
@@ -960,16 +1215,20 @@ export type PluginDesignCreateFurnitureArgs = z.infer<
960
1215
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
961
1216
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
962
1217
  * | `label` | `string`? | Instance name (optional) |
1218
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door faces (default engine-chosen) |
963
1219
  */
964
1220
  export const PluginDesignCreateDoorArgs = z.object({
965
1221
  catalogId: z.string().min(1),
966
1222
  hostWall: ComponentHandle,
967
1223
  position: Vec3Handle,
968
1224
  label: z.string().optional(),
1225
+ facing: Vec3Handle.optional(),
969
1226
  })
970
- export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorArgs>
971
- // TRANSPORT: positional signature shipped —
972
- // door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? })
1227
+ export type PluginDesignCreateDoorArgs = z.infer<
1228
+ typeof PluginDesignCreateDoorArgs
1229
+ >
1230
+ // TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
1231
+ // door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
973
1232
 
974
1233
  // ---------------------------------------------------------------------------
975
1234
  // window
@@ -984,16 +1243,20 @@ export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorAr
984
1243
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
985
1244
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
986
1245
  * | `label` | `string`? | Instance name (optional) |
1246
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window faces (default engine-chosen) |
987
1247
  */
988
1248
  export const PluginDesignCreateWindowArgs = z.object({
989
1249
  catalogId: z.string().min(1),
990
1250
  hostWall: ComponentHandle,
991
1251
  position: Vec3Handle,
992
1252
  label: z.string().optional(),
1253
+ facing: Vec3Handle.optional(),
993
1254
  })
994
- export type PluginDesignCreateWindowArgs = z.infer<typeof PluginDesignCreateWindowArgs>
995
- // TRANSPORT: positional signature shipped —
996
- // window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? })
1255
+ export type PluginDesignCreateWindowArgs = z.infer<
1256
+ typeof PluginDesignCreateWindowArgs
1257
+ >
1258
+ // TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
1259
+ // window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
997
1260
 
998
1261
  // ---------------------------------------------------------------------------
999
1262
  // smartLayout
@@ -1019,7 +1282,7 @@ export const PluginSmartLayoutArgs = z
1019
1282
  })
1020
1283
  .refine(
1021
1284
  (v) =>
1022
- (v.templateGroup != null) !== ((v.templateComponents?.length ?? 0) > 0),
1285
+ (v.templateGroup != null) !== (v.templateComponents?.length ?? 0) > 0,
1023
1286
  {
1024
1287
  message:
1025
1288
  "Provide exactly one template source: templateGroup or a non-empty templateComponents",
@@ -1110,7 +1373,9 @@ export const PluginDesignCreateCopyArgs = z.object({
1110
1373
  count: z.number().int().positive().optional(),
1111
1374
  mode: PluginCopyMode.optional(),
1112
1375
  })
1113
- export type PluginDesignCreateCopyArgs = z.infer<typeof PluginDesignCreateCopyArgs>
1376
+ export type PluginDesignCreateCopyArgs = z.infer<
1377
+ typeof PluginDesignCreateCopyArgs
1378
+ >
1114
1379
  // TRANSPORT: positional signature shipped —
1115
1380
  // copy(components: ComponentHandle[], displacement: Vec3Handle, options?: { count?, mode? })
1116
1381
 
@@ -1131,6 +1396,7 @@ export type PluginDesignCreateCopyArgs = z.infer<typeof PluginDesignCreateCopyAr
1131
1396
  * | `spaceType` | `PluginSpaceType`? | Space type |
1132
1397
  * | `massType` | `PluginMassType`? | Mass type |
1133
1398
  * | `departmentId` | `PluginDepartmentId`? | Department |
1399
+ * | `storey` | `number`? (int) | Target storey number (default active storey) |
1134
1400
  */
1135
1401
  export const PluginCreateSpaceItem = z.object({
1136
1402
  contour: ContourHandle,
@@ -1140,5 +1406,6 @@ export const PluginCreateSpaceItem = z.object({
1140
1406
  spaceType: PluginSpaceType.optional(),
1141
1407
  massType: PluginMassType.optional(),
1142
1408
  departmentId: PluginDepartmentId.optional(),
1409
+ storey: z.number().int().optional(),
1143
1410
  })
1144
1411
  export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>