@snaptrude/plugin-core 0.9.13 → 0.9.15
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/CHANGELOG.md +61 -0
- package/api-manifest.full.json +8930 -0
- package/api-manifest.json +1002 -55
- package/dist/api/core/geom/create/index.d.ts +935 -100
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/brep.d.ts +59 -2
- package/dist/api/core/geom/query/brep.d.ts.map +1 -1
- package/dist/api/core/geom/query/curve.d.ts +59 -35
- package/dist/api/core/geom/query/curve.d.ts.map +1 -1
- package/dist/api/core/geom/query/edge.d.ts +2 -2
- package/dist/api/core/geom/query/face.d.ts +105 -0
- package/dist/api/core/geom/query/face.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +2 -0
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/geom/update/curve.d.ts +5 -5
- package/dist/api/core/geom/update/profile.d.ts +3 -1
- package/dist/api/core/geom/update/profile.d.ts.map +1 -1
- package/dist/api/core/handles/index.d.ts +4 -2
- package/dist/api/core/handles/index.d.ts.map +1 -1
- package/dist/api/core/index.d.ts +4 -4
- package/dist/api/core/index.d.ts.map +1 -1
- package/dist/api/core/layers.d.ts +377 -255
- package/dist/api/core/layers.d.ts.map +1 -1
- package/dist/api/core/proposals/index.d.ts +4 -3
- package/dist/api/core/proposals/index.d.ts.map +1 -1
- package/dist/api/core/storeys/index.d.ts +12 -0
- package/dist/api/core/storeys/index.d.ts.map +1 -1
- package/dist/api/core/storeys/layers.d.ts +408 -0
- package/dist/api/core/storeys/layers.d.ts.map +1 -0
- package/dist/api/core/tags.d.ts +3 -3
- package/dist/api/design/create/bulk-items.d.ts +44 -0
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/grids.d.ts +1 -1
- package/dist/api/design/create/index.d.ts +31 -3
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +67 -10
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/query/geometry/index.d.ts +33 -5
- package/dist/api/design/query/geometry/index.d.ts.map +1 -1
- package/dist/api/design/query/grids.d.ts +3 -3
- package/dist/api/design/query/index.d.ts +47 -0
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/query/spaces.d.ts +5 -5
- package/dist/api/design/selection/index.d.ts +2 -2
- package/dist/api/design/update/index.d.ts +172 -0
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/entity/referenceLine.d.ts +1 -1
- package/dist/api/entity/space.d.ts +4 -4
- package/dist/api/entity/story.d.ts +4 -4
- package/dist/api/presentation/aiInspiration.d.ts +13 -13
- package/dist/api/presentation/camera.d.ts +265 -0
- package/dist/api/presentation/camera.d.ts.map +1 -0
- package/dist/api/presentation/index.d.ts +5 -0
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +1 -1
- package/dist/api/presentation/views.d.ts +3 -1
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/api/program/site.d.ts +4 -4
- package/dist/api/program/spreadsheet.d.ts +4 -4
- package/dist/handles.d.ts +13 -3
- package/dist/handles.d.ts.map +1 -1
- package/dist/index.cjs +3638 -2958
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3558 -2955
- package/dist/index.js.map +1 -1
- package/dist/massParameters.d.ts +287 -0
- package/dist/massParameters.d.ts.map +1 -0
- package/dist/massParameters.ops.d.ts +138 -0
- package/dist/massParameters.ops.d.ts.map +1 -0
- package/package.json +2 -1
- package/scripts/check-dist-fresh.mjs +22 -0
- package/scripts/generate-manifest.test.mjs +14 -3
- package/src/api/core/geom/create/index.ts +1030 -101
- package/src/api/core/geom/query/brep.ts +60 -2
- package/src/api/core/geom/query/curve.ts +26 -2
- package/src/api/core/geom/query/edge.ts +2 -2
- package/src/api/core/geom/query/face.ts +109 -4
- package/src/api/core/geom/update/contour.ts +2 -0
- package/src/api/core/geom/update/profile.ts +2 -0
- package/src/api/core/handles/index.ts +3 -2
- package/src/api/core/index.ts +4 -4
- package/src/api/core/layers.ts +380 -173
- package/src/api/core/proposals/index.ts +4 -3
- package/src/api/core/storeys/index.ts +14 -0
- package/src/api/core/storeys/layers.ts +339 -0
- package/src/api/design/create/bulk-items.ts +68 -0
- package/src/api/design/create/index.ts +30 -4
- package/src/api/design/family.ts +68 -10
- package/src/api/design/query/geometry/index.ts +35 -4
- package/src/api/design/query/index.ts +50 -0
- package/src/api/design/update/index.ts +186 -1
- package/src/api/presentation/camera.ts +289 -0
- package/src/api/presentation/index.ts +5 -0
- package/src/api/presentation/views.ts +3 -1
- package/src/handles.ts +18 -3
- package/src/index.ts +2 -0
- package/src/massParameters.ops.ts +246 -0
- package/src/massParameters.ts +427 -0
- package/test/massParameters.test.mjs +952 -0
package/src/api/design/family.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../types"
|
|
3
|
-
import { ComponentHandle, Vec3Components } from "../../handles"
|
|
3
|
+
import { BrepHandle, ComponentHandle, Vec3Components } from "../../handles"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* `snaptrude.design.family.*` — author NATIVE parametric families from a JSON spec.
|
|
@@ -18,15 +18,21 @@ import { ComponentHandle, Vec3Components } from "../../handles"
|
|
|
18
18
|
* getReference() read the spec DSL once — grammar, ops, expressions, example
|
|
19
19
|
* prepare({ bundle }) validate + compile + show a live ghost; nothing committed
|
|
20
20
|
* flex({ values }) re-run at new values; returns the geometry delta
|
|
21
|
-
* place()
|
|
22
|
-
*
|
|
21
|
+
* place({ position }) put it in the model — saves the family as the first instance drops
|
|
22
|
+
* place() save the family, then arm placement — the USER clicks to drop it
|
|
23
|
+
* create({ teamId }) share with a team; a save with nothing placed also drops one instance
|
|
23
24
|
* ```
|
|
24
25
|
*
|
|
26
|
+
* `place` saves the prepared family to the user's personal library, so it
|
|
27
|
+
* survives reload with no extra step; finish on `place`, not on `create`.
|
|
28
|
+
*
|
|
25
29
|
* ## Read getReference() first
|
|
26
30
|
*
|
|
27
31
|
* The spec DSL is a closed expression language with its own op set, coordinate
|
|
28
|
-
* convention (**+Y up, Snaptrude units** — the scene's own unit, 1 SU = 254 mm
|
|
29
|
-
*
|
|
32
|
+
* convention (**+Y up, Snaptrude units** — the scene's own unit, 1 SU = 254 mm,
|
|
33
|
+
* the same unit `core.units.getBabylonType()` names and every geometry API
|
|
34
|
+
* takes; literals inside spec expressions may carry a unit suffix such as
|
|
35
|
+
* `600mm` or `2ft`)
|
|
30
36
|
* and part-naming law. It is deliberately NOT duplicated in these types:
|
|
31
37
|
* {@linkcode PluginDesignFamilyApi.getReference} returns the whole reference,
|
|
32
38
|
* generated from a family that is actually registered in the host, so the
|
|
@@ -41,6 +47,18 @@ import { ComponentHandle, Vec3Components } from "../../handles"
|
|
|
41
47
|
* leaves the previous good draft standing, so it costs nothing but the node you
|
|
42
48
|
* broke. Re-authoring from scratch throws away everything already correct.
|
|
43
49
|
*
|
|
50
|
+
* ## Curved parts are exact
|
|
51
|
+
*
|
|
52
|
+
* A part whose sketch has a curved edge — any `revolve`, or an `extrude` /
|
|
53
|
+
* `sweep` / `loft` with an arc or circle in its profile (or an arc in a sweep
|
|
54
|
+
* path) — is built by the exact geometry kernel, the same one behind curved
|
|
55
|
+
* masses. Straight-edged parts keep the fast mesh builder. `getParameters` on a
|
|
56
|
+
* placed component reports which built each part in `parts[].engine`, and a
|
|
57
|
+
* kernel part carries a `brep`: read it with `core.geom.query.brep.*` and
|
|
58
|
+
* `core.geom.query.face.getSurfaceKind` — the same face-kind check as for a
|
|
59
|
+
* curved mass. If the kernel is unavailable a part falls back to the mesh
|
|
60
|
+
* builder (`engine: "mesh"`) rather than failing the family.
|
|
61
|
+
*
|
|
44
62
|
* Accessed via `snaptrude.design.family`.
|
|
45
63
|
*/
|
|
46
64
|
export abstract class PluginDesignFamilyApi {
|
|
@@ -68,20 +86,25 @@ export abstract class PluginDesignFamilyApi {
|
|
|
68
86
|
|
|
69
87
|
/**
|
|
70
88
|
* Validate, compile and preview a family spec. Nothing is committed to the
|
|
71
|
-
* model or the library — call {@linkcode PluginDesignFamilyApi.place}
|
|
72
|
-
*
|
|
89
|
+
* model or the library — call {@linkcode PluginDesignFamilyApi.place} to put
|
|
90
|
+
* it in the model, which also saves it.
|
|
73
91
|
*
|
|
74
92
|
* Safe to call repeatedly while iterating. On success, check `partCount` and
|
|
75
93
|
* `bbox` against what you intended before treating the family as correct — a
|
|
76
94
|
* facade that built 3 parts, or a 3 m screen reporting 40 m of height, is a
|
|
77
95
|
* visible bug the validator cannot catch.
|
|
78
96
|
*
|
|
97
|
+
* Lengths — the spec's bare numbers, `bbox`, the sheet's `length` values — are
|
|
98
|
+
* Snaptrude units: the same 254 mm unit as the kernel's internal (`"babylon"`)
|
|
99
|
+
* unit. A unit suffix (`600mm`) is legal only inside a spec expression.
|
|
100
|
+
*
|
|
79
101
|
* @param args The spec bundle, as `{ bundle }` or `{ spec }`
|
|
80
102
|
* @returns Build report, or `{ ok: false, errors }` with JSON-pointer paths
|
|
81
103
|
*
|
|
82
104
|
* @examplePrompt Make a louvre screen with adjustable blade count and tilt
|
|
83
105
|
* @examplePrompt Design a curtain wall panel family with 8 bays
|
|
84
106
|
* @examplePrompt Create a railing family I can adjust
|
|
107
|
+
* @examplePrompt Make a pendant lamp family with a domed shade I can resize
|
|
85
108
|
*
|
|
86
109
|
* # Example
|
|
87
110
|
* ```ts
|
|
@@ -147,6 +170,9 @@ export abstract class PluginDesignFamilyApi {
|
|
|
147
170
|
* Put a family into the model — either the prepared draft or any family from
|
|
148
171
|
* {@linkcode PluginDesignFamilyApi.list}.
|
|
149
172
|
*
|
|
173
|
+
* Placing the prepared draft saves it to the user's personal library first,
|
|
174
|
+
* so its instances survive reload.
|
|
175
|
+
*
|
|
150
176
|
* Two modes, chosen by whether you pass `position`:
|
|
151
177
|
*
|
|
152
178
|
* **With `position`** the component is created there and then, undoably. Use
|
|
@@ -195,6 +221,9 @@ export abstract class PluginDesignFamilyApi {
|
|
|
195
221
|
* label the user says, and a Revit-imported family carries parameters that
|
|
196
222
|
* do not drive geometry at all.
|
|
197
223
|
*
|
|
224
|
+
* `length` values are Snaptrude units: the same 254 mm unit as the kernel's
|
|
225
|
+
* internal (`"babylon"`) unit — convert with `core.units.convert` to report.
|
|
226
|
+
*
|
|
198
227
|
* @param args The component to read
|
|
199
228
|
* @returns Its definition, current values, and the parameter sheet
|
|
200
229
|
*
|
|
@@ -220,6 +249,11 @@ export abstract class PluginDesignFamilyApi {
|
|
|
220
249
|
* that does not is accepted and stored (it round-trips to Revit) but nothing
|
|
221
250
|
* visible happens — say so rather than claiming a change the user cannot see.
|
|
222
251
|
*
|
|
252
|
+
* `length` values are Snaptrude units: the same 254 mm unit as the kernel's
|
|
253
|
+
* internal (`"babylon"`) unit — convert the user's number with
|
|
254
|
+
* `core.units.convert` first; a bare `400` is 400 SU, not 400 mm. Kernel part
|
|
255
|
+
* breps read before the edit are stale: re-read `getParameters`.
|
|
256
|
+
*
|
|
223
257
|
* @param args The component and the values to change
|
|
224
258
|
* @returns The values now in effect
|
|
225
259
|
*
|
|
@@ -236,8 +270,11 @@ export abstract class PluginDesignFamilyApi {
|
|
|
236
270
|
): PluginApiReturn<PluginFamilyInstanceParameters>
|
|
237
271
|
|
|
238
272
|
/**
|
|
239
|
-
*
|
|
240
|
-
*
|
|
273
|
+
* Save the prepared bundle to the library — the user's personal library
|
|
274
|
+
* unless `teamId` is given. {@linkcode PluginDesignFamilyApi.place} already
|
|
275
|
+
* saves, so `create` is for sharing with a team. When nothing of the family is
|
|
276
|
+
* in the model yet, one instance is also dropped at the centre of the current
|
|
277
|
+
* view on the active storey (`placed: true`), so a save is never invisible.
|
|
241
278
|
*
|
|
242
279
|
* @param args Optional library name and team scope
|
|
243
280
|
* @returns The catalogued definition's id and version
|
|
@@ -318,7 +355,7 @@ export interface PluginFamilyParameter {
|
|
|
318
355
|
key: string
|
|
319
356
|
label: string
|
|
320
357
|
type: "length" | "integer" | "enum" | "text" | "boolean"
|
|
321
|
-
/** Current value. `length
|
|
358
|
+
/** Current value. `length` (Snaptrude units) and `integer` are numbers; the rest are strings. */
|
|
322
359
|
value: string | number
|
|
323
360
|
default: string | number
|
|
324
361
|
/**
|
|
@@ -354,6 +391,25 @@ export interface PluginFamilyDiagnostic {
|
|
|
354
391
|
hint?: string
|
|
355
392
|
}
|
|
356
393
|
|
|
394
|
+
/**
|
|
395
|
+
* One placed part and which engine built it, from `getParameters`. `"kernel"` —
|
|
396
|
+
* a curved sketch built exactly; `"mesh"` — straight-edged, or the kernel
|
|
397
|
+
* fallback.
|
|
398
|
+
*/
|
|
399
|
+
export interface PluginFamilyPart {
|
|
400
|
+
name: string
|
|
401
|
+
engine: "kernel" | "mesh"
|
|
402
|
+
/**
|
|
403
|
+
* Kernel parts only: the part's exact solid, for `core.geom.query.brep.*` /
|
|
404
|
+
* `core.geom.query.face.getSurfaceKind`. READ-ONLY and PART-LOCAL — in the
|
|
405
|
+
* part's own frame, not where the component sits, so never pass it to a
|
|
406
|
+
* boolean or `design.create.massFromBrep` (a family changes only through
|
|
407
|
+
* `setParameters`). Valid until the next parameter change: re-read
|
|
408
|
+
* `getParameters` after `setParameters`.
|
|
409
|
+
*/
|
|
410
|
+
brep?: BrepHandle
|
|
411
|
+
}
|
|
412
|
+
|
|
357
413
|
/** What `prepare` reports. */
|
|
358
414
|
export interface PluginFamilyPrepareResult {
|
|
359
415
|
/** `false` means the spec was rejected — read `errors`, fix, re-prepare. */
|
|
@@ -455,6 +511,8 @@ export interface PluginFamilyInstanceParameters {
|
|
|
455
511
|
values: Record<string, number | string>
|
|
456
512
|
/** The sheet: what each key means, its bounds, and whether it moves geometry. */
|
|
457
513
|
parameters: PluginFamilyParameter[]
|
|
514
|
+
/** The placed parts; kernel parts carry their exact `brep`. */
|
|
515
|
+
parts?: PluginFamilyPart[]
|
|
458
516
|
/** Present when `getParameters` was asked for a `snapshot`. */
|
|
459
517
|
snapshot?: PluginFamilySnapshot
|
|
460
518
|
}
|
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
* {@linkcode PluginDesignQueryGeometryApi.getCenterline} mints a
|
|
20
20
|
* {@linkcode CurveHandle} for a wall's core curve.
|
|
21
21
|
* {@linkcode PluginDesignQueryGeometryApi.getTriangulatedMeshes} is the
|
|
22
|
-
* handle-free exception: it returns the triangulated render
|
|
23
|
-
* world-space arrays.
|
|
22
|
+
* handle-free exception: it returns `{ meshes }` — the triangulated render
|
|
23
|
+
* meshes as plain world-space arrays, wrapped in an object, never bare.
|
|
24
24
|
*
|
|
25
25
|
* Returned handles are session-ephemeral and go stale on undo/redo/re-topologize
|
|
26
26
|
* — re-fetch a fresh one after edits.
|
|
@@ -34,10 +34,26 @@ export abstract class PluginDesignQueryGeometryApi {
|
|
|
34
34
|
* scene entity, as a reusable {@linkcode BrepHandle} for the
|
|
35
35
|
* `core.geom.query.brep.*` reads.
|
|
36
36
|
*
|
|
37
|
+
* **Frame.** By default the brep comes back in the component's own LOCAL frame
|
|
38
|
+
* (its vertices are relative to the mesh origin, exactly as stored). This is
|
|
39
|
+
* the long-standing default, and existing callers rely on it. Pass
|
|
40
|
+
* `{ frame: "world" }` to get the same solid placed where it sits in the
|
|
41
|
+
* scene (world coordinates, like
|
|
42
|
+
* `getBottomContour` / `getTriangulatedMeshes` and every `design.query.measure`
|
|
43
|
+
* read). Use `"world"` whenever the handle will be COMBINED with other scene
|
|
44
|
+
* geometry or committed back beside its source: booleans between two scene
|
|
45
|
+
* masses, `brepFromFillet` / `brepFromShell` / `brepFromOffset` /
|
|
46
|
+
* `brepFromChamfer` on a scene mass followed by `massFromBrep`, or comparing
|
|
47
|
+
* its vertices with a bounding box. A world-frame handle from a parametrically
|
|
48
|
+
* live mass also carries that mass's recipe, so an operation result keeps an
|
|
49
|
+
* editable record.
|
|
50
|
+
*
|
|
37
51
|
* @param component - The scene component to read
|
|
38
|
-
* @
|
|
52
|
+
* @param options - `frame`: `"local"` (default, mesh-local coordinates) or `"world"` (scene coordinates)
|
|
53
|
+
* @returns The brep as a {@linkcode BrepHandle}, or `null` if the component has no brep geometry — also `null` for a parametric family: read `design.family.getParameters({ component }).parts[].brep`
|
|
39
54
|
*
|
|
40
55
|
* @examplePrompt Get the 3D solid geometry of the selected wall
|
|
56
|
+
* @examplePrompt Round the top rim of this column and put it back where it is
|
|
41
57
|
* @examplePrompt How many faces does this mass have?
|
|
42
58
|
* @examplePrompt Inspect the mesh of this slab so I can look at its faces and edges
|
|
43
59
|
* @examplePrompt Read the vertices of the selected column's geometry
|
|
@@ -48,10 +64,16 @@ export abstract class PluginDesignQueryGeometryApi {
|
|
|
48
64
|
* if (brep) {
|
|
49
65
|
* const faces = await snaptrude.core.geom.query.brep.listFaces(brep)
|
|
50
66
|
* }
|
|
67
|
+
*
|
|
68
|
+
* // Operate on a scene mass and commit the result where the mass sits:
|
|
69
|
+
* const placed = await snaptrude.design.query.geometry.getBrep(mass, { frame: "world" })
|
|
70
|
+
* const rounded = await snaptrude.core.geom.create.brepFromFillet(placed, edges, 0.2)
|
|
71
|
+
* await snaptrude.design.create.massFromBrep(rounded, "Rounded")
|
|
51
72
|
* ```
|
|
52
73
|
*/
|
|
53
74
|
public abstract getBrep(
|
|
54
75
|
component: ComponentHandle,
|
|
76
|
+
options?: PluginDesignQueryGeometryGetBrepOptions,
|
|
55
77
|
): PluginApiReturn<BrepHandle | null>
|
|
56
78
|
|
|
57
79
|
/**
|
|
@@ -126,7 +148,8 @@ export abstract class PluginDesignQueryGeometryApi {
|
|
|
126
148
|
* Get the **triangulated render meshes** of scene components as plain,
|
|
127
149
|
* serializable arrays — flat world-space vertex `positions` (`[x0, y0, z0,
|
|
128
150
|
* x1, …]`) and triangle `indices` (three per triangle), one record per
|
|
129
|
-
* requested component.
|
|
151
|
+
* requested component. The result is `{ meshes }`, not a bare array —
|
|
152
|
+
* destructure it before iterating.
|
|
130
153
|
*
|
|
131
154
|
* Unlike the other `geometry.*` reads this does NOT mint kernel handles — the
|
|
132
155
|
* raw arrays cross the boundary directly, ready for export, custom analysis,
|
|
@@ -189,8 +212,16 @@ export abstract class PluginDesignQueryGeometryApi {
|
|
|
189
212
|
* |---|---|---|
|
|
190
213
|
* | `component` | {@linkcode ComponentHandle} | The scene component to read |
|
|
191
214
|
*/
|
|
215
|
+
/** Options for {@linkcode PluginDesignQueryGeometryApi.getBrep}: `frame` defaults to `"local"`. */
|
|
216
|
+
export type PluginDesignQueryGeometryGetBrepOptions = { frame?: "local" | "world" }
|
|
217
|
+
export const PluginDesignQueryGeometryGetBrepOptions: z.ZodType<
|
|
218
|
+
PluginDesignQueryGeometryGetBrepOptions,
|
|
219
|
+
PluginDesignQueryGeometryGetBrepOptions
|
|
220
|
+
> = z.object({ frame: z.enum(["local", "world"]).optional() })
|
|
221
|
+
|
|
192
222
|
export const PluginDesignQueryGeometryGetBrepArgs = z.object({
|
|
193
223
|
component: ComponentHandle,
|
|
224
|
+
options: PluginDesignQueryGeometryGetBrepOptions.optional(),
|
|
194
225
|
})
|
|
195
226
|
|
|
196
227
|
export type PluginDesignQueryGeometryGetBrepArgs = z.infer<
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../../types"
|
|
3
3
|
import { ComponentHandle, BBoxComponents } from "../../../handles"
|
|
4
|
+
import type { MassParametersRecord } from "../../../massParameters"
|
|
4
5
|
import {
|
|
5
6
|
PluginSpaceType,
|
|
6
7
|
PluginMassType,
|
|
@@ -1040,6 +1041,55 @@ export abstract class PluginDesignQueryApi {
|
|
|
1040
1041
|
staircase: ComponentHandle,
|
|
1041
1042
|
): PluginApiReturn<PluginStaircaseParams | null>
|
|
1042
1043
|
|
|
1044
|
+
/**
|
|
1045
|
+
* Read a mass's creation-parameter record — the recipe it was built from
|
|
1046
|
+
* (`kind` plus the values that constructor was called with). Present on
|
|
1047
|
+
* masses committed from a `core.geom.create` brep constructor that carries a
|
|
1048
|
+
* recipe: {@linkcode MassParametersRecord} covers the four primitives
|
|
1049
|
+
* (sphere, cylinder, cone, torus), extrusions, revolutions, lofts and sweeps.
|
|
1050
|
+
*
|
|
1051
|
+
* A fillet, chamfer, shell or offset of a recorded solid keeps the record
|
|
1052
|
+
* too: `kind` stays the base constructor and the operation is appended to the
|
|
1053
|
+
* record's `operations` list. Edit any of it with `design.update.parameters`.
|
|
1054
|
+
*
|
|
1055
|
+
* `null` for everything else — drawn masses, imported geometry, booleans,
|
|
1056
|
+
* split parts, `brepFromFaces` / `brepFromMesh`, and results built on a
|
|
1057
|
+
* source that carried no record — and for a mass whose record no longer
|
|
1058
|
+
* matches what is on
|
|
1059
|
+
* screen (a later free-form edit dropped the recipe, or the mass carries a
|
|
1060
|
+
* baked scale). `null` too when the recipe was not recordable: the record
|
|
1061
|
+
* schema has its own caps (a sweep path of at most 512 points, a loft of at
|
|
1062
|
+
* most 32 sections, at most 8 chained `operations`, at most 256 curves in one
|
|
1063
|
+
* profile loop and 64 holes in one contour), and a mass built past one of
|
|
1064
|
+
* them — through a route that does not enforce the matching creator cap —
|
|
1065
|
+
* commits as ordinary geometry carrying no record. The `operations` cap is
|
|
1066
|
+
* the one an agent can walk into by accident: a 9th chained
|
|
1067
|
+
* fillet/chamfer/shell/offset drops the record silently, so the result
|
|
1068
|
+
* commits as ordinary geometry and reads back `null` here. A record is never
|
|
1069
|
+
* reported unless it is still the truth.
|
|
1070
|
+
*
|
|
1071
|
+
* Points and axes come back in **world** coordinates. Pure read — nothing is
|
|
1072
|
+
* created or modified.
|
|
1073
|
+
*
|
|
1074
|
+
* @param component - the mass's {@linkcode ComponentHandle}
|
|
1075
|
+
* @returns the {@linkcode MassParametersRecord}, or `null`
|
|
1076
|
+
*
|
|
1077
|
+
* @examplePrompt What radius is this sphere?
|
|
1078
|
+
* @examplePrompt Is this mass parametric?
|
|
1079
|
+
* @examplePrompt Read back the dome's creation parameters
|
|
1080
|
+
* @examplePrompt How tall was this cylinder made?
|
|
1081
|
+
*
|
|
1082
|
+
* # Example
|
|
1083
|
+
* ```ts
|
|
1084
|
+
* const [mass] = await snaptrude.design.query.listMasses({ isSelected: true })
|
|
1085
|
+
* const params = await snaptrude.design.query.getParameters(mass)
|
|
1086
|
+
* if (params?.kind === "sphere") console.log("radius:", params.values.radius)
|
|
1087
|
+
* ```
|
|
1088
|
+
*/
|
|
1089
|
+
public abstract getParameters(
|
|
1090
|
+
component: ComponentHandle,
|
|
1091
|
+
): PluginApiReturn<MassParametersRecord | null>
|
|
1092
|
+
|
|
1043
1093
|
/**
|
|
1044
1094
|
* Get the **union** axis-aligned bounding box enclosing a set of entities.
|
|
1045
1095
|
*
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
PluginSpaceUpdateResult,
|
|
10
10
|
} from "../../entity/space"
|
|
11
11
|
import { PluginDesignChangeResult } from "../lock"
|
|
12
|
+
import { MassParametersPatch, type MassParametersRecord } from "../../../massParameters"
|
|
12
13
|
import {
|
|
13
14
|
PluginBuildableEnvelopePolygonVertex,
|
|
14
15
|
PluginBuildableEnvelopeSetbackTier,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
PluginBuildableEnvelopeUpdateResult,
|
|
17
18
|
} from "../../entity/buildableEnvelope"
|
|
18
19
|
import { PluginGridStyleOptions } from "../create/grids"
|
|
20
|
+
import { PluginEntityType } from "../query"
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Sparse property updates for a space. Only provided fields change.
|
|
@@ -137,6 +139,22 @@ export type PluginDesignUpdateStaircaseArgs = z.infer<
|
|
|
137
139
|
typeof PluginDesignUpdateStaircaseArgs
|
|
138
140
|
>
|
|
139
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Arguments for {@linkcode PluginDesignUpdateApi.parameters}.
|
|
144
|
+
*
|
|
145
|
+
* | Property | Type | Description |
|
|
146
|
+
* |---|---|---|
|
|
147
|
+
* | `component` | {@linkcode ComponentHandle} | The parametric mass to edit |
|
|
148
|
+
* | `patch` | {@linkcode MassParametersPatch} | Partial `values` (+ optional `operations`), or the full edited record |
|
|
149
|
+
*/
|
|
150
|
+
export const PluginDesignUpdateParametersArgs = z.object({
|
|
151
|
+
component: ComponentHandle,
|
|
152
|
+
patch: MassParametersPatch,
|
|
153
|
+
})
|
|
154
|
+
export type PluginDesignUpdateParametersArgs = z.infer<
|
|
155
|
+
typeof PluginDesignUpdateParametersArgs
|
|
156
|
+
>
|
|
157
|
+
|
|
140
158
|
/**
|
|
141
159
|
* Sparse edits for a wall (all optional; at least one required). Only the
|
|
142
160
|
* fields you provide change. Dimensions are in **engine units** (the same
|
|
@@ -239,6 +257,34 @@ export type PluginDesignSetStoreyArgs = z.infer<
|
|
|
239
257
|
typeof PluginDesignSetStoreyArgs
|
|
240
258
|
>
|
|
241
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Object types {@linkcode PluginDesignUpdateApi.setObjectType} can turn a mass
|
|
262
|
+
* into — the `design.query` `type` vocabulary.
|
|
263
|
+
*/
|
|
264
|
+
export const PluginObjectType = PluginEntityType.extract([
|
|
265
|
+
"wall",
|
|
266
|
+
"roof",
|
|
267
|
+
"slab",
|
|
268
|
+
"floor",
|
|
269
|
+
])
|
|
270
|
+
export type PluginObjectType = z.infer<typeof PluginObjectType>
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Arguments for {@linkcode PluginDesignUpdateApi.setObjectType}.
|
|
274
|
+
*
|
|
275
|
+
* | Property | Type | Description |
|
|
276
|
+
* |---|---|---|
|
|
277
|
+
* | `components` | {@linkcode ComponentHandle}`[]` | The masses to convert (>= 1) |
|
|
278
|
+
* | `objectType` | {@linkcode PluginObjectType} | Target object type (`"wall"`, `"roof"`, `"slab"`, `"floor"`) |
|
|
279
|
+
*/
|
|
280
|
+
export const PluginDesignSetObjectTypeArgs = z.object({
|
|
281
|
+
components: z.array(ComponentHandle).min(1),
|
|
282
|
+
objectType: PluginObjectType,
|
|
283
|
+
})
|
|
284
|
+
export type PluginDesignSetObjectTypeArgs = z.infer<
|
|
285
|
+
typeof PluginDesignSetObjectTypeArgs
|
|
286
|
+
>
|
|
287
|
+
|
|
242
288
|
/**
|
|
243
289
|
* The sparse GROUP-LEVEL patch accepted by {@linkcode PluginDesignUpdateApi.grid}.
|
|
244
290
|
* Only provided fields change. Wing- and line-level updates live on the grids
|
|
@@ -258,7 +304,9 @@ export const PluginDesignUpdateGridArgs = z.object({
|
|
|
258
304
|
grid: ComponentHandle,
|
|
259
305
|
patch: PluginGridPatch,
|
|
260
306
|
})
|
|
261
|
-
export type PluginDesignUpdateGridArgs = z.infer<
|
|
307
|
+
export type PluginDesignUpdateGridArgs = z.infer<
|
|
308
|
+
typeof PluginDesignUpdateGridArgs
|
|
309
|
+
>
|
|
262
310
|
|
|
263
311
|
/**
|
|
264
312
|
* `snaptrude.design.update` — edit existing scene entities (properties + geometry).
|
|
@@ -462,6 +510,95 @@ export abstract class PluginDesignUpdateApi {
|
|
|
462
510
|
params: PluginStaircaseParamUpdates,
|
|
463
511
|
): PluginApiReturn<PluginDesignChangeResult>
|
|
464
512
|
|
|
513
|
+
/**
|
|
514
|
+
* Edit a parametric mass by patching its creation recipe and rebuilding the
|
|
515
|
+
* solid in place — the mass keeps its id, storey, materials, position and
|
|
516
|
+
* linked copies; only the geometry changes. Read the current record with
|
|
517
|
+
* `design.query.getParameters` first.
|
|
518
|
+
*
|
|
519
|
+
* `patch` is a partial of `record.values` — or the whole record you read
|
|
520
|
+
* back, edited. A key you leave out is unchanged (that includes
|
|
521
|
+
* `operations`). Each key you send replaces that value whole — a scalar, a
|
|
522
|
+
* point, a list or a record (`contour`, `profile`, `sections`, `path`,
|
|
523
|
+
* `options`, `operations`) alike — so send the complete value you read,
|
|
524
|
+
* edited (a partial `options` drops the switches it leaves out);
|
|
525
|
+
* `{ operations: [] }` drops every operation. An optional key
|
|
526
|
+
* the record does not carry yet may be patched in when the kind allows it:
|
|
527
|
+
* a straight extrusion acquires `twistInDegrees` or `topScale`, an
|
|
528
|
+
* options-less loft or sweep acquires `options` (`levels` is not one — send
|
|
529
|
+
* the angle, not the section count). A patch that changes nothing
|
|
530
|
+
* returns the current record and records no edit (no undo step). `kind` and
|
|
531
|
+
* `version` are immutable: to change the kind, build a new mass. Keys are the
|
|
532
|
+
* record's `values` keys for its `kind` (sphere: `centre`, `radius`;
|
|
533
|
+
* cylinder: `base`, `axis`, `radius`, `height`; torus: `centre`, `axis`,
|
|
534
|
+
* `majorRadius`, `minorRadius`; …) plus `operations`. To change a fillet
|
|
535
|
+
* radius, edit `operations[i].radius` in the record you read and send
|
|
536
|
+
* `{ operations }` back. Points and axes are WORLD coordinates in internal
|
|
537
|
+
* units, exactly as `getParameters` reports them.
|
|
538
|
+
*
|
|
539
|
+
* Rebuilds in memory first, then swaps onto the SAME component; every linked
|
|
540
|
+
* copy regenerates together. One undo step; saves and syncs to collaborators
|
|
541
|
+
* like any geometry edit. Kernel kinds (revolution, sweep, loft, primitives,
|
|
542
|
+
* any `operations`) run on OpenCascade — expect a short pause.
|
|
543
|
+
*
|
|
544
|
+
* @param component - a mass whose `getParameters` is non-null
|
|
545
|
+
* @param patch - partial `values` (+ optional `operations`), or the full edited record
|
|
546
|
+
* @returns the complete post-edit record, world coordinates (what
|
|
547
|
+
* `getParameters` now returns)
|
|
548
|
+
* @throws PRECONDITION_FAILED when the component is not a mass (a family
|
|
549
|
+
* instance: use `design.family.setParameters`).
|
|
550
|
+
* Also PRECONDITION_FAILED when the mass carries no live recipe — built
|
|
551
|
+
* from a boolean, split, `brepFromFaces`/`brepFromMesh` or drawn; edited
|
|
552
|
+
* free-form since (push/pull, move face, boolean); or scaled with the
|
|
553
|
+
* transform tool. `getParameters` returns `null` for exactly these.
|
|
554
|
+
* Do not retry — rebuild it with a recipe constructor and say so.
|
|
555
|
+
* A scaled mass is the exception: undo the scale and call again.
|
|
556
|
+
* Also PRECONDITION_FAILED when the mass (or a linked copy) is **locked**
|
|
557
|
+
* (the message says so). Locking is invisible to `getParameters` — a
|
|
558
|
+
* locked parametric mass still reads back a full record. Unlock it (and
|
|
559
|
+
* every linked copy) and call again; never rebuild it, the recipe is intact.
|
|
560
|
+
* Also PRECONDITION_FAILED when an `operations` entry's edge/face selectors
|
|
561
|
+
* no longer resolve on the rebuilt base (the message names the operation
|
|
562
|
+
* and edge): re-select the edges on the new shape and re-apply that
|
|
563
|
+
* operation.
|
|
564
|
+
* Also PRECONDITION_FAILED when the edit is the first twist or taper — or
|
|
565
|
+
* the straightening — of an extrusion that carries a shell, fillet or
|
|
566
|
+
* chamfer (the kernel numbers its faces differently): send the twist/taper
|
|
567
|
+
* keys with `operations: []` first (the message names them), re-select on
|
|
568
|
+
* the new shape, then send `{ operations }` back.
|
|
569
|
+
* @throws VALIDATION for a key the kind does not have (the message lists the
|
|
570
|
+
* kind's keys), `kind` or `version` in a partial patch, or a value outside
|
|
571
|
+
* the constructor's own rules (torus tube ≥ ring, revolution angle ∉
|
|
572
|
+
* (0, 360], a profile crossing its axis, a spline with fewer than
|
|
573
|
+
* degree + 1 poles).
|
|
574
|
+
* @throws OPERATION_FAILED when the kernel cannot build the edited recipe;
|
|
575
|
+
* the model is left unchanged.
|
|
576
|
+
*
|
|
577
|
+
* @examplePrompt Make the dome's radius 8 metres
|
|
578
|
+
* @examplePrompt Raise the podium to 5 m
|
|
579
|
+
* @examplePrompt Widen the vase — move its profile points 20 cm outward
|
|
580
|
+
* @examplePrompt Change the fillet on the rounded column to 300 mm
|
|
581
|
+
*
|
|
582
|
+
* # Example
|
|
583
|
+
* ```ts
|
|
584
|
+
* // { kind: "sphere", values: { centre, radius: 19.685 }, … }
|
|
585
|
+
* const before = await snaptrude.design.query.getParameters(dome)
|
|
586
|
+
* const after = await snaptrude.design.update.parameters(dome, { radius: 31.496 }) // 8 m in internal units
|
|
587
|
+
*
|
|
588
|
+
* // Fillet radius on a recorded result: read → edit → send the array back
|
|
589
|
+
* const rec = await snaptrude.design.query.getParameters(column)
|
|
590
|
+
* const operations = rec?.operations ?? []
|
|
591
|
+
* if (operations[0]?.op === "fillet") {
|
|
592
|
+
* operations[0].radius = 1.181
|
|
593
|
+
* await snaptrude.design.update.parameters(column, { operations })
|
|
594
|
+
* }
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
597
|
+
public abstract parameters(
|
|
598
|
+
component: ComponentHandle,
|
|
599
|
+
patch: MassParametersPatch,
|
|
600
|
+
): PluginApiReturn<MassParametersRecord>
|
|
601
|
+
|
|
465
602
|
/**
|
|
466
603
|
* Edit a **wall** — its thickness and/or height (the same command the
|
|
467
604
|
* properties panel's Thickness/Height fields drive) and/or its **wall type**
|
|
@@ -743,6 +880,54 @@ export abstract class PluginDesignUpdateApi {
|
|
|
743
880
|
storey: number,
|
|
744
881
|
): PluginApiReturn<PluginDesignChangeResult>
|
|
745
882
|
|
|
883
|
+
/**
|
|
884
|
+
* Change the **object type** of one or more masses — turn a mass into a real
|
|
885
|
+
* wall, roof, slab or floor: the properties panel's Object Type dropdown,
|
|
886
|
+
* headless. The geometry is kept exactly as it is (a wedge stays a wedge;
|
|
887
|
+
* nothing is flattened to a default thickness), so a sloped mass built with
|
|
888
|
+
* `design.create.massFromBrep` becomes a sloped roof or a raked wall. The
|
|
889
|
+
* component keeps its handle, label and storey; it gains the target type's
|
|
890
|
+
* construction layers and properties, and the type's default material when
|
|
891
|
+
* the mass still wore the default. One undoable operation for the whole
|
|
892
|
+
* list; undo turns them back into masses.
|
|
893
|
+
*
|
|
894
|
+
* Instances convert as a family: passing one instance (or the source) of an
|
|
895
|
+
* instanced mass converts its source and every sibling; `affected` echoes
|
|
896
|
+
* every visible member (the hidden instancing template converts too but is
|
|
897
|
+
* not listed). A converted component cannot be converted again (same rule
|
|
898
|
+
* as the panel). A converted wall has no parametric centerline: it hosts
|
|
899
|
+
* doors and windows and exports, but neighbours do not re-mitre against it.
|
|
900
|
+
*
|
|
901
|
+
* Throws before anything changes (all-or-nothing) when a component is not a
|
|
902
|
+
* mass, is a plinth, is locked or in a locked bucket, already had its type
|
|
903
|
+
* changed, or when a handle is gone/forged.
|
|
904
|
+
*
|
|
905
|
+
* @param components - The masses to convert
|
|
906
|
+
* @param objectType - Target type: `"wall"`, `"roof"`, `"slab"` or `"floor"`
|
|
907
|
+
* (the `design.query.getEntityType` vocabulary)
|
|
908
|
+
* @returns the visible components converted — the same handles, plus any
|
|
909
|
+
* instance siblings pulled in by family expansion
|
|
910
|
+
*
|
|
911
|
+
* @examplePrompt Convert this mass into a wall
|
|
912
|
+
* @examplePrompt Turn the sloped mass into a roof
|
|
913
|
+
* @examplePrompt Make these masses real slabs
|
|
914
|
+
* @examplePrompt Change the object type of the selection to wall
|
|
915
|
+
* @examplePrompt Convert the wedge I built into a raked wall
|
|
916
|
+
* @examplePrompt Turn this mass into a floor
|
|
917
|
+
*
|
|
918
|
+
* # Example
|
|
919
|
+
* ```ts
|
|
920
|
+
* const brep = await snaptrude.core.geom.create.brepFromFaces(wedgeFaces)
|
|
921
|
+
* const wedge = await snaptrude.design.create.massFromBrep(brep, "Gable end")
|
|
922
|
+
* const { affected } = await snaptrude.design.update.setObjectType([wedge], "wall")
|
|
923
|
+
* console.log(await snaptrude.design.query.getEntityType(affected[0])) // "wall"
|
|
924
|
+
* ```
|
|
925
|
+
*/
|
|
926
|
+
public abstract setObjectType(
|
|
927
|
+
components: ComponentHandle[],
|
|
928
|
+
objectType: PluginObjectType,
|
|
929
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
930
|
+
|
|
746
931
|
/**
|
|
747
932
|
* Update an existing parametric buildable envelope — regenerate the zoning
|
|
748
933
|
* volume from a revised site polygon, setbacks, vertical cap, or FAR and
|