@snaptrude/plugin-core 0.0.0-dev-20260911064951 → 0.0.0-dev-20260921132444
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 +4 -0
- package/CHANGELOG.md +35 -1
- package/dist/api/core/mode/index.d.ts +19 -7
- package/dist/api/core/mode/index.d.ts.map +1 -1
- package/dist/api/core/tags.d.ts +81 -0
- package/dist/api/core/tags.d.ts.map +1 -1
- package/dist/api/design/create/grids.d.ts +132 -0
- package/dist/api/design/create/grids.d.ts.map +1 -0
- package/dist/api/design/create/index.d.ts +109 -1
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +73 -5
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/grids.d.ts +237 -0
- package/dist/api/design/grids.d.ts.map +1 -0
- package/dist/api/design/index.d.ts +4 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/query/grids.d.ts +287 -0
- package/dist/api/design/query/grids.d.ts.map +1 -0
- package/dist/api/design/query/index.d.ts +29 -0
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/update/index.d.ts +74 -0
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/program/departments.d.ts +58 -2
- package/dist/api/program/departments.d.ts.map +1 -1
- package/dist/api/program/index.d.ts +16 -6
- package/dist/api/program/index.d.ts.map +1 -1
- package/dist/api/program/labels.d.ts +355 -0
- package/dist/api/program/labels.d.ts.map +1 -0
- package/dist/api/program/metadata.d.ts +328 -0
- package/dist/api/program/metadata.d.ts.map +1 -0
- package/dist/api/program/spreadsheet.d.ts +263 -0
- package/dist/api/program/spreadsheet.d.ts.map +1 -1
- package/dist/api/workspace/index.d.ts +49 -2
- package/dist/api/workspace/index.d.ts.map +1 -1
- package/dist/index.cjs +2365 -1908
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2294 -1908
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/core/mode/index.ts +19 -7
- package/src/api/core/tags.ts +76 -0
- package/src/api/design/create/grids.ts +137 -0
- package/src/api/design/create/index.ts +131 -0
- package/src/api/design/family.ts +51 -4
- package/src/api/design/grids.ts +237 -0
- package/src/api/design/index.ts +5 -0
- package/src/api/design/query/grids.ts +197 -0
- package/src/api/design/query/index.ts +27 -0
- package/src/api/design/update/index.ts +53 -0
- package/src/api/program/departments.ts +54 -2
- package/src/api/program/index.ts +16 -6
- package/src/api/program/labels.ts +332 -0
- package/src/api/program/metadata.ts +364 -0
- package/src/api/program/spreadsheet.ts +282 -0
- package/src/api/workspace/index.ts +51 -2
package/package.json
CHANGED
|
@@ -29,10 +29,14 @@ export interface PluginCoreModeSetResult {
|
|
|
29
29
|
* Not to be confused with the viewport's 2D/3D camera mode
|
|
30
30
|
* (`core.camera.setMode`) or saved presentation views (`presentation.views`).
|
|
31
31
|
*
|
|
32
|
-
* `set` covers `design`, `bim`, and `present` — in-page switches
|
|
33
|
-
* `program
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
* `set` covers `design`, `bim`, and `present` — in-page switches — and
|
|
33
|
+
* `program`, which opens the Program tab (a paired browser window) through the
|
|
34
|
+
* same path as the top bar's Program button. Because the open happens outside a
|
|
35
|
+
* user gesture the browser may block the pop-up; the editor then shows its
|
|
36
|
+
* "Allow pop-up to continue" modal and the tab opens when the user confirms.
|
|
37
|
+
* `get()` reports `"program"` only for code running in the Program tab itself.
|
|
38
|
+
* Prefer {@linkcode PluginWorkspaceApi.openProgramMode} when you need to know
|
|
39
|
+
* the tab is ready before calling `program.spreadsheet.*`.
|
|
36
40
|
*/
|
|
37
41
|
export abstract class PluginCoreModeApi {
|
|
38
42
|
constructor() {}
|
|
@@ -74,16 +78,24 @@ export abstract class PluginCoreModeApi {
|
|
|
74
78
|
* Switch the editor to another application mode — the same action as
|
|
75
79
|
* clicking that tab in the top menu bar.
|
|
76
80
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
81
|
+
* `"design"`, `"bim"` and `"present"` switch in place. `"program"` opens
|
|
82
|
+
* the Program tab (a paired browser window) exactly as the top bar's Program
|
|
83
|
+
* button does, and resolves once that tab has connected to the editor (up to
|
|
84
|
+
* ~90s — the browser may block the pop-up, in which case the editor shows an
|
|
85
|
+
* "Allow pop-up to continue" modal and waits for the user to confirm).
|
|
86
|
+
* Idempotent when the Program tab is already open. Note `get()` in the model
|
|
87
|
+
* tab keeps reporting the model tab's own mode afterwards; the Program tab is
|
|
88
|
+
* a separate window.
|
|
80
89
|
*
|
|
81
90
|
* @param mode - Target mode token from {@linkcode PluginAppMode}
|
|
82
91
|
* @returns The committed `{ mode }` after the switch.
|
|
92
|
+
* @throws `PRECONDITION_FAILED` for `"program"` when the user dismisses the
|
|
93
|
+
* pop-up modal or the tab does not connect within the timeout.
|
|
83
94
|
*
|
|
84
95
|
* @examplePrompt Switch to present mode
|
|
85
96
|
* @examplePrompt Open BIM mode
|
|
86
97
|
* @examplePrompt Go back to design mode
|
|
98
|
+
* @examplePrompt Open program mode
|
|
87
99
|
*
|
|
88
100
|
* # Example
|
|
89
101
|
* ```ts
|
package/src/api/core/tags.ts
CHANGED
|
@@ -163,6 +163,40 @@ export abstract class PluginCoreTagsApi {
|
|
|
163
163
|
componentId: ComponentHandle,
|
|
164
164
|
): PluginApiReturn<PluginCoreTagsGetTagsForComponentResult>
|
|
165
165
|
|
|
166
|
+
/**
|
|
167
|
+
* List the tags carried by many components in one call.
|
|
168
|
+
*
|
|
169
|
+
* The plural of {@linkcode PluginCoreTagsApi.listForComponent}: pass
|
|
170
|
+
* `componentIds` to read specific components (unknown ids are skipped), or
|
|
171
|
+
* omit it to read **every** taggable component (Mass/Floor space) in the
|
|
172
|
+
* project. Each entry carries the component id and its tags — one per tagged
|
|
173
|
+
* category, with the tag's `color` — so a plugin can color every space by a
|
|
174
|
+
* chosen category's tag in a single round-trip.
|
|
175
|
+
*
|
|
176
|
+
* @param componentIds - Optional `Component.id`s to read; omit for all spaces.
|
|
177
|
+
* @returns A {@linkcode PluginCoreTagsListForComponentsResult} with a
|
|
178
|
+
* `components` array, one entry per component (in input order when
|
|
179
|
+
* `componentIds` is given).
|
|
180
|
+
*
|
|
181
|
+
* @performance One round-trip for any number of components — use this instead of a `listForComponent` loop.
|
|
182
|
+
*
|
|
183
|
+
* @examplePrompt Get the tags of every space with their colors
|
|
184
|
+
* @examplePrompt List the tags on all rooms so I can color them by Occupancy
|
|
185
|
+
* @examplePrompt Which tag does each selected space carry?
|
|
186
|
+
*
|
|
187
|
+
* # Example
|
|
188
|
+
* ```ts
|
|
189
|
+
* const { components } = await snaptrude.core.tags.listForComponents()
|
|
190
|
+
* for (const c of components) {
|
|
191
|
+
* const occupancy = c.tags.find((t) => t.categoryName === "Occupancy")
|
|
192
|
+
* if (occupancy) paint(c.componentId, occupancy.color)
|
|
193
|
+
* }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
public abstract listForComponents(
|
|
197
|
+
componentIds?: ComponentHandle[],
|
|
198
|
+
): PluginApiReturn<PluginCoreTagsListForComponentsResult>
|
|
199
|
+
|
|
166
200
|
/**
|
|
167
201
|
* List the components carrying a given tag or category.
|
|
168
202
|
*
|
|
@@ -588,6 +622,48 @@ export type PluginCoreTagsGetTagsForComponentResult = z.infer<
|
|
|
588
622
|
typeof PluginCoreTagsGetTagsForComponentResult
|
|
589
623
|
>
|
|
590
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Arguments for {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
627
|
+
*
|
|
628
|
+
* | Property | Type | Description |
|
|
629
|
+
* |---|---|---|
|
|
630
|
+
* | `componentIds` | `ComponentHandle[]?` | Components to read; omit for every taggable component |
|
|
631
|
+
*/
|
|
632
|
+
export const PluginCoreTagsListForComponentsArgs = z.object({
|
|
633
|
+
componentIds: z.array(ComponentHandle).optional(),
|
|
634
|
+
})
|
|
635
|
+
export type PluginCoreTagsListForComponentsArgs = z.infer<
|
|
636
|
+
typeof PluginCoreTagsListForComponentsArgs
|
|
637
|
+
>
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* One component's tags, for {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
641
|
+
*
|
|
642
|
+
* | Property | Type | Description |
|
|
643
|
+
* |---|---|---|
|
|
644
|
+
* | `componentId` | `ComponentHandle` | The component's id |
|
|
645
|
+
* | `tags` | {@linkcode PluginCoreComponentTag}`[]` | Its tags, one per tagged category (empty when none) |
|
|
646
|
+
*/
|
|
647
|
+
export const PluginCoreComponentTags = z.object({
|
|
648
|
+
componentId: ComponentHandle,
|
|
649
|
+
tags: z.array(PluginCoreComponentTag),
|
|
650
|
+
})
|
|
651
|
+
export type PluginCoreComponentTags = z.infer<typeof PluginCoreComponentTags>
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Result of {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
655
|
+
*
|
|
656
|
+
* | Property | Type | Description |
|
|
657
|
+
* |---|---|---|
|
|
658
|
+
* | `components` | {@linkcode PluginCoreComponentTags}`[]` | One entry per component |
|
|
659
|
+
*/
|
|
660
|
+
export const PluginCoreTagsListForComponentsResult = z.object({
|
|
661
|
+
components: z.array(PluginCoreComponentTags),
|
|
662
|
+
})
|
|
663
|
+
export type PluginCoreTagsListForComponentsResult = z.infer<
|
|
664
|
+
typeof PluginCoreTagsListForComponentsResult
|
|
665
|
+
>
|
|
666
|
+
|
|
591
667
|
/**
|
|
592
668
|
* Arguments for {@linkcode PluginCoreTagsApi.listComponents}. Provide exactly one
|
|
593
669
|
* of `tagId`, `categoryId`. `untagged` is valid only with `categoryId`.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { ComponentHandle, CurveHandle, Vec3Handle } from "../../../handles"
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Shared grid style vocabulary
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Grid line style (mirrors the engine `LineMode` values verbatim — the same
|
|
10
|
+
* vocabulary as {@linkcode PluginReferenceLineStyle}).
|
|
11
|
+
*/
|
|
12
|
+
export const PluginGridLineStyle = z.enum(["SOLID", "DASHED", "DOT_DASH"])
|
|
13
|
+
export type PluginGridLineStyle = z.infer<typeof PluginGridLineStyle>
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Optional visual styling shared by every grid creator (and reused as the
|
|
17
|
+
* patch shape by `design.update.grid`). All fields optional; engine defaults
|
|
18
|
+
* apply when omitted.
|
|
19
|
+
*
|
|
20
|
+
* | Property | Type | Description |
|
|
21
|
+
* |---|---|---|
|
|
22
|
+
* | `style` | {@linkcode PluginGridLineStyle}? | Line style |
|
|
23
|
+
* | `weight` | `number`? | Line weight (> 0) |
|
|
24
|
+
* | `color` | `string`? | Line color as a `#rrggbb` hex string |
|
|
25
|
+
* | `showStart` | `boolean`? | Show the start-end tag bubble |
|
|
26
|
+
* | `showEnd` | `boolean`? | Show the end-end tag bubble |
|
|
27
|
+
*/
|
|
28
|
+
export const PluginGridStyleOptions = z.object({
|
|
29
|
+
style: PluginGridLineStyle.optional(),
|
|
30
|
+
weight: z.number().positive().optional(),
|
|
31
|
+
color: z
|
|
32
|
+
.string()
|
|
33
|
+
.regex(/^#[0-9a-fA-F]{6}$/, "color must be a #rrggbb hex string")
|
|
34
|
+
.optional(),
|
|
35
|
+
showStart: z.boolean().optional(),
|
|
36
|
+
showEnd: z.boolean().optional(),
|
|
37
|
+
})
|
|
38
|
+
export type PluginGridStyleOptions = z.infer<typeof PluginGridStyleOptions>
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// create.grid — free rectangular grid
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Arguments for {@linkcode PluginDesignCreateApi.grid}.
|
|
46
|
+
*
|
|
47
|
+
* | Property | Type | Description |
|
|
48
|
+
* |---|---|---|
|
|
49
|
+
* | `linesX` | `number` | Line count of the first family (integer ≥ 1) |
|
|
50
|
+
* | `linesY` | `number` | Line count of the second family (integer ≥ 1) |
|
|
51
|
+
* | `spacingX` | `number` | Spacing of the first family (Snaptrude units, > 0) |
|
|
52
|
+
* | `spacingY` | `number` | Spacing of the second family (Snaptrude units, > 0) |
|
|
53
|
+
* | `angle` | `number`? | Rotation in degrees, CCW about +Y (default 0) |
|
|
54
|
+
* | `center` | {@linkcode Vec3Handle}? | Placement centre; defaults to the native viewport-centre behavior |
|
|
55
|
+
* | …style | {@linkcode PluginGridStyleOptions} | Optional line styling |
|
|
56
|
+
*/
|
|
57
|
+
export const PluginDesignCreateGridArgs = z
|
|
58
|
+
.object({
|
|
59
|
+
linesX: z.number().int().min(1),
|
|
60
|
+
linesY: z.number().int().min(1),
|
|
61
|
+
spacingX: z.number().positive().finite(),
|
|
62
|
+
spacingY: z.number().positive().finite(),
|
|
63
|
+
angle: z.number().finite().optional(),
|
|
64
|
+
center: Vec3Handle.optional(),
|
|
65
|
+
})
|
|
66
|
+
.merge(PluginGridStyleOptions)
|
|
67
|
+
export type PluginDesignCreateGridArgs = z.infer<typeof PluginDesignCreateGridArgs>
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// create.gridFromCurve — single-curve grid
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Arguments for {@linkcode PluginDesignCreateApi.gridFromCurve}.
|
|
75
|
+
*
|
|
76
|
+
* | Property | Type | Description |
|
|
77
|
+
* |---|---|---|
|
|
78
|
+
* | `curve` | {@linkcode CurveHandle} | The grid line's geometry — a line or arc (circles are rejected) |
|
|
79
|
+
* | `tag` | `string`? | The line's grid tag (defaults to the draw tool's next tag) |
|
|
80
|
+
* | …style | {@linkcode PluginGridStyleOptions} | Optional line styling |
|
|
81
|
+
*/
|
|
82
|
+
export const PluginDesignCreateGridFromCurveArgs = z
|
|
83
|
+
.object({
|
|
84
|
+
curve: CurveHandle,
|
|
85
|
+
tag: z.string().min(1).optional(),
|
|
86
|
+
})
|
|
87
|
+
.merge(PluginGridStyleOptions)
|
|
88
|
+
export type PluginDesignCreateGridFromCurveArgs = z.infer<
|
|
89
|
+
typeof PluginDesignCreateGridFromCurveArgs
|
|
90
|
+
>
|
|
91
|
+
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// create.gridsFromMasses — fitted grids
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Arguments for {@linkcode PluginDesignCreateApi.gridsFromMasses}.
|
|
98
|
+
*
|
|
99
|
+
* | Property | Type | Description |
|
|
100
|
+
* |---|---|---|
|
|
101
|
+
* | `masses` | {@linkcode ComponentHandle}`[]` | Masses whose footprints seat the grids |
|
|
102
|
+
* | `spacingX` | `number` | First-family spacing (Snaptrude units, > 0) |
|
|
103
|
+
* | `spacingY` | `number` | Second-family spacing (Snaptrude units, > 0) |
|
|
104
|
+
* | …style | {@linkcode PluginGridStyleOptions} | Optional line styling |
|
|
105
|
+
*/
|
|
106
|
+
export const PluginDesignCreateGridsFromMassesArgs = z
|
|
107
|
+
.object({
|
|
108
|
+
masses: z.array(ComponentHandle).min(1),
|
|
109
|
+
spacingX: z.number().positive().finite(),
|
|
110
|
+
spacingY: z.number().positive().finite(),
|
|
111
|
+
})
|
|
112
|
+
.merge(PluginGridStyleOptions)
|
|
113
|
+
export type PluginDesignCreateGridsFromMassesArgs = z.infer<
|
|
114
|
+
typeof PluginDesignCreateGridsFromMassesArgs
|
|
115
|
+
>
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// create.columnsFromGrids — columns at line intersections
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Arguments for {@linkcode PluginDesignCreateApi.columnsFromGrids}.
|
|
123
|
+
*
|
|
124
|
+
* | Property | Type | Description |
|
|
125
|
+
* |---|---|---|
|
|
126
|
+
* | `grids` | {@linkcode ComponentHandle}`[]` | Grid groups whose line intersections seat the columns |
|
|
127
|
+
* | `width` | `number` | Column width (Snaptrude units, > 0) |
|
|
128
|
+
* | `depth` | `number` | Column depth (Snaptrude units, > 0) |
|
|
129
|
+
*/
|
|
130
|
+
export const PluginDesignCreateColumnsFromGridsArgs = z.object({
|
|
131
|
+
grids: z.array(ComponentHandle).min(1),
|
|
132
|
+
width: z.number().positive().finite(),
|
|
133
|
+
depth: z.number().positive().finite(),
|
|
134
|
+
})
|
|
135
|
+
export type PluginDesignCreateColumnsFromGridsArgs = z.infer<
|
|
136
|
+
typeof PluginDesignCreateColumnsFromGridsArgs
|
|
137
|
+
>
|
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
BrepHandle,
|
|
5
5
|
ComponentHandle,
|
|
6
6
|
ContourHandle,
|
|
7
|
+
CurveHandle,
|
|
7
8
|
ProfileHandle,
|
|
8
9
|
Vec3Handle,
|
|
9
10
|
} from "../../../handles"
|
|
11
|
+
import { PluginGridStyleOptions } from "./grids"
|
|
10
12
|
import {
|
|
11
13
|
PluginSpaceType,
|
|
12
14
|
PluginMassType,
|
|
@@ -628,6 +630,134 @@ export abstract class PluginDesignCreateApi {
|
|
|
628
630
|
gridTag?: string,
|
|
629
631
|
): PluginApiReturn<ComponentHandle[]>
|
|
630
632
|
|
|
633
|
+
/**
|
|
634
|
+
* Create a free rectangular **structural grid** — one grid group with two
|
|
635
|
+
* perpendicular line families (`linesX` lines spaced `spacingX` apart, and
|
|
636
|
+
* `linesY` lines spaced `spacingY` apart) on the active storey. One undoable
|
|
637
|
+
* creation.
|
|
638
|
+
*
|
|
639
|
+
* Units: spacings in Snaptrude units; `angle` in degrees (CCW about +Y,
|
|
640
|
+
* default 0). Without `center` the grid is centred on the current viewport
|
|
641
|
+
* (the native tool's behavior) — pass `center` for deterministic placement.
|
|
642
|
+
*
|
|
643
|
+
* @param linesX - Line count of the first family (integer ≥ 1)
|
|
644
|
+
* @param linesY - Line count of the second family (integer ≥ 1)
|
|
645
|
+
* @param spacingX - First-family spacing (Snaptrude units, > 0)
|
|
646
|
+
* @param spacingY - Second-family spacing (Snaptrude units, > 0)
|
|
647
|
+
* @param options - `angle`, `center`, and {@linkcode PluginGridStyleOptions}
|
|
648
|
+
* @returns the created grid group's {@linkcode ComponentHandle}
|
|
649
|
+
*
|
|
650
|
+
* @examplePrompt Create a 5 by 8 structural grid with 6 metre spacing
|
|
651
|
+
* @examplePrompt Add a column grid rotated 30 degrees
|
|
652
|
+
* @examplePrompt Set up a structural grid at the site origin
|
|
653
|
+
*
|
|
654
|
+
* # Example
|
|
655
|
+
* ```ts
|
|
656
|
+
* const centre = await snaptrude.core.math.vec3.new(0, 0, 0)
|
|
657
|
+
* const grid = await snaptrude.design.create.grid(5, 8, 6, 6, { center: centre })
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
public abstract grid(
|
|
661
|
+
linesX: number,
|
|
662
|
+
linesY: number,
|
|
663
|
+
spacingX: number,
|
|
664
|
+
spacingY: number,
|
|
665
|
+
options?: {
|
|
666
|
+
angle?: number
|
|
667
|
+
center?: Vec3Handle
|
|
668
|
+
} & PluginGridStyleOptions,
|
|
669
|
+
): PluginApiReturn<ComponentHandle>
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Create a **structural grid from a single curve** — one grid group holding
|
|
673
|
+
* one wing with one line (the draw tool's output). The curve may be a line
|
|
674
|
+
* or an arc; circles are rejected with `VALIDATION`. Undoable.
|
|
675
|
+
*
|
|
676
|
+
* @param curve - The grid line's geometry ({@linkcode CurveHandle}, world space)
|
|
677
|
+
* @param options - `tag` (defaults to the draw tool's next tag) and
|
|
678
|
+
* {@linkcode PluginGridStyleOptions}
|
|
679
|
+
* @returns the created grid group's {@linkcode ComponentHandle}
|
|
680
|
+
*
|
|
681
|
+
* @examplePrompt Draw a grid line from A to B
|
|
682
|
+
* @examplePrompt Add a curved grid line through these points
|
|
683
|
+
* @examplePrompt Create grid line "C" along this wall
|
|
684
|
+
*
|
|
685
|
+
* # Example
|
|
686
|
+
* ```ts
|
|
687
|
+
* const { vec3 } = snaptrude.core.math
|
|
688
|
+
* const from = await vec3.new(0, 0, 0)
|
|
689
|
+
* const to = await vec3.new(30, 0, 0)
|
|
690
|
+
* const curve = await snaptrude.core.geom.create.line(from, to)
|
|
691
|
+
* const grid = await snaptrude.design.create.gridFromCurve(curve, { tag: "A" })
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
694
|
+
public abstract gridFromCurve(
|
|
695
|
+
curve: CurveHandle,
|
|
696
|
+
options?: {
|
|
697
|
+
tag?: string
|
|
698
|
+
} & PluginGridStyleOptions,
|
|
699
|
+
): PluginApiReturn<ComponentHandle>
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Generate **structural grids fitted to mass footprints** — one grid group
|
|
703
|
+
* per footprint cluster, with counts and orientation derived from each
|
|
704
|
+
* footprint's geometry and the given spacings. All created groups commit as
|
|
705
|
+
* ONE undoable unit.
|
|
706
|
+
*
|
|
707
|
+
* Lenient like the native tool: masses without an extractable footprint
|
|
708
|
+
* (no B-rep, degenerate top face) are skipped; throws `VALIDATION` only when
|
|
709
|
+
* NONE of the given masses yields a footprint.
|
|
710
|
+
*
|
|
711
|
+
* @param masses - Masses whose footprints seat the grids
|
|
712
|
+
* @param spacingX - First-family spacing (Snaptrude units, > 0)
|
|
713
|
+
* @param spacingY - Second-family spacing (Snaptrude units, > 0)
|
|
714
|
+
* @param options - {@linkcode PluginGridStyleOptions}
|
|
715
|
+
* @returns the created grid groups' {@linkcode ComponentHandle}`[]`
|
|
716
|
+
*
|
|
717
|
+
* @examplePrompt Generate grids for the selected masses
|
|
718
|
+
* @examplePrompt Auto-generate a 6m structural grid on this building
|
|
719
|
+
* @examplePrompt Fit column grids to every mass on this storey
|
|
720
|
+
*
|
|
721
|
+
* # Example
|
|
722
|
+
* ```ts
|
|
723
|
+
* const masses = await snaptrude.design.query.listMasses({ storeys: [1] })
|
|
724
|
+
* const grids = await snaptrude.design.create.gridsFromMasses(masses, 6, 6)
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
public abstract gridsFromMasses(
|
|
728
|
+
masses: ComponentHandle[],
|
|
729
|
+
spacingX: number,
|
|
730
|
+
spacingY: number,
|
|
731
|
+
options?: PluginGridStyleOptions,
|
|
732
|
+
): PluginApiReturn<ComponentHandle[]>
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Create **columns at every grid-line intersection** of the given grid
|
|
736
|
+
* groups, sized `width` × `depth` and oriented to the grid axes, on the
|
|
737
|
+
* grids' storey. All columns commit as ONE undoable unit.
|
|
738
|
+
*
|
|
739
|
+
* @param grids - Grid groups whose intersections seat the columns
|
|
740
|
+
* @param width - Column width (Snaptrude units, > 0)
|
|
741
|
+
* @param depth - Column depth (Snaptrude units, > 0)
|
|
742
|
+
* @returns the created columns' {@linkcode ComponentHandle}`[]`
|
|
743
|
+
* @throws `VALIDATION` when an id does not resolve to a grid group;
|
|
744
|
+
* `OPERATION_FAILED` when the grids have no line intersections
|
|
745
|
+
*
|
|
746
|
+
* @examplePrompt Generate columns on this grid
|
|
747
|
+
* @examplePrompt Place 450mm square columns at every grid intersection
|
|
748
|
+
*
|
|
749
|
+
* # Example
|
|
750
|
+
* ```ts
|
|
751
|
+
* const grids = await snaptrude.design.query.listGrids()
|
|
752
|
+
* const columns = await snaptrude.design.create.columnsFromGrids(grids, 0.45, 0.45)
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
public abstract columnsFromGrids(
|
|
756
|
+
grids: ComponentHandle[],
|
|
757
|
+
width: number,
|
|
758
|
+
depth: number,
|
|
759
|
+
): PluginApiReturn<ComponentHandle[]>
|
|
760
|
+
|
|
631
761
|
/**
|
|
632
762
|
* Place a **furniture** item from the project library at a world position.
|
|
633
763
|
*
|
|
@@ -1821,3 +1951,4 @@ export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>
|
|
|
1821
1951
|
|
|
1822
1952
|
export * from "./opening-fields"
|
|
1823
1953
|
export * from "./bulk-items"
|
|
1954
|
+
export * from "./grids"
|
package/src/api/design/family.ts
CHANGED
|
@@ -25,7 +25,8 @@ import { ComponentHandle, Vec3Components } from "../../handles"
|
|
|
25
25
|
* ## Read getReference() first
|
|
26
26
|
*
|
|
27
27
|
* The spec DSL is a closed expression language with its own op set, coordinate
|
|
28
|
-
* convention (**+Y up,
|
|
28
|
+
* convention (**+Y up, Snaptrude units** — the scene's own unit, 1 SU = 254 mm;
|
|
29
|
+
* literals may carry a unit suffix such as `600mm` or `2ft`)
|
|
29
30
|
* and part-naming law. It is deliberately NOT duplicated in these types:
|
|
30
31
|
* {@linkcode PluginDesignFamilyApi.getReference} returns the whole reference,
|
|
31
32
|
* generated from a family that is actually registered in the host, so the
|
|
@@ -278,11 +279,11 @@ export interface PluginFamilyBundle {
|
|
|
278
279
|
deps?: Record<string, Record<string, unknown>>
|
|
279
280
|
}
|
|
280
281
|
|
|
281
|
-
/** Axis-aligned extents of a built family.
|
|
282
|
+
/** Axis-aligned extents of a built family. Snaptrude units (1 SU = 254 mm), +Y up. */
|
|
282
283
|
export interface PluginFamilyBBox {
|
|
283
284
|
min: [number, number, number]
|
|
284
285
|
max: [number, number, number]
|
|
285
|
-
/** `[width, height, depth]` in
|
|
286
|
+
/** `[width, height, depth]` in Snaptrude units — convert with `core.units.convert` for display. */
|
|
286
287
|
size: [number, number, number]
|
|
287
288
|
}
|
|
288
289
|
|
|
@@ -322,6 +323,7 @@ export interface PluginFamilyDiagnostic {
|
|
|
322
323
|
| "unbounded-repeat"
|
|
323
324
|
| "depth"
|
|
324
325
|
| "bad-dimension"
|
|
326
|
+
| "proportion"
|
|
325
327
|
message: string
|
|
326
328
|
hint?: string
|
|
327
329
|
}
|
|
@@ -335,7 +337,7 @@ export interface PluginFamilyPrepareResult {
|
|
|
335
337
|
label?: string
|
|
336
338
|
/** How many parts the family built. Sanity-check against intent. */
|
|
337
339
|
partCount?: number
|
|
338
|
-
/** Extents in
|
|
340
|
+
/** Extents in Snaptrude units. Sanity-check against intent. */
|
|
339
341
|
bbox?: PluginFamilyBBox
|
|
340
342
|
evalMs?: number
|
|
341
343
|
parameters?: PluginFamilyParameter[]
|
|
@@ -343,6 +345,8 @@ export interface PluginFamilyPrepareResult {
|
|
|
343
345
|
takeoff?: Record<string, number | string>
|
|
344
346
|
/** The first few part names — enough to check the naming came out right. */
|
|
345
347
|
sampleParts?: string[]
|
|
348
|
+
/** Present when `snapshot` was asked for. */
|
|
349
|
+
snapshot?: PluginFamilySnapshot
|
|
346
350
|
errors: PluginFamilyDiagnostic[]
|
|
347
351
|
warnings: PluginFamilyDiagnostic[]
|
|
348
352
|
/** Set when the bundle validated but threw while building. */
|
|
@@ -372,6 +376,10 @@ export interface PluginFamilyFlexResult {
|
|
|
372
376
|
evalMs?: number
|
|
373
377
|
changed?: PluginFamilyChangeBuckets
|
|
374
378
|
takeoff?: Record<string, number | string>
|
|
379
|
+
/** Proportion warnings at the flexed values (code `proportion`): a part thinner than 0.5 mm, a part or family over 50 m, a family under 10 mm — the signature of a unit slip. */
|
|
380
|
+
warnings?: PluginFamilyDiagnostic[]
|
|
381
|
+
/** Present when `snapshot` was asked for. */
|
|
382
|
+
snapshot?: PluginFamilySnapshot
|
|
375
383
|
error?: string
|
|
376
384
|
}
|
|
377
385
|
|
|
@@ -421,6 +429,8 @@ export interface PluginFamilyInstanceParameters {
|
|
|
421
429
|
values: Record<string, number | string>
|
|
422
430
|
/** The sheet: what each key means, its bounds, and whether it moves geometry. */
|
|
423
431
|
parameters: PluginFamilyParameter[]
|
|
432
|
+
/** Present when `getParameters` was asked for a `snapshot`. */
|
|
433
|
+
snapshot?: PluginFamilySnapshot
|
|
424
434
|
}
|
|
425
435
|
|
|
426
436
|
/** What `create` reports. */
|
|
@@ -455,13 +465,46 @@ export const PluginFamilyBundleSchema = z.object({
|
|
|
455
465
|
* |---|---|---|
|
|
456
466
|
* | `bundle` | {@linkcode PluginFamilyBundle} | The family spec bundle |
|
|
457
467
|
* | `spec` | {@linkcode PluginFamilyBundle} | Alias for `bundle` |
|
|
468
|
+
* | `snapshot` | {@linkcode PluginFamilySnapshotOption} | Also return a picture of the built family |
|
|
458
469
|
*
|
|
459
470
|
* Exactly one of `bundle` / `spec` is required. A bare `FamilySpec` (no `root`
|
|
460
471
|
* wrapper) is also accepted by the host and wrapped for the caller.
|
|
461
472
|
*/
|
|
473
|
+
/**
|
|
474
|
+
* Ask for a picture with the result: `true` for the default sheet (iso, front,
|
|
475
|
+
* right and top tiles with a dimension line), or an object to choose views and
|
|
476
|
+
* tile size. The picture is an isolated offscreen render of the family alone —
|
|
477
|
+
* the viewport is not moved — and comes back as a PNG data URL in the result's
|
|
478
|
+
* `snapshot.image`. Through the agent's `run_worker`, return the result and the
|
|
479
|
+
* image reaches the model as an image.
|
|
480
|
+
*/
|
|
481
|
+
export const PluginFamilySnapshotOption = z.union([
|
|
482
|
+
z.boolean(),
|
|
483
|
+
z.object({
|
|
484
|
+
views: z.array(z.enum(["iso", "front", "right", "top"])).optional(),
|
|
485
|
+
/** Pixels per tile (square), 64–2048; default 512. */
|
|
486
|
+
tileSize: z.number().optional(),
|
|
487
|
+
}),
|
|
488
|
+
])
|
|
489
|
+
export type PluginFamilySnapshotOption = z.infer<typeof PluginFamilySnapshotOption>
|
|
490
|
+
|
|
491
|
+
/** The picture block on prepare / flex / getParameters results when `snapshot` was asked for. */
|
|
492
|
+
export interface PluginFamilySnapshot {
|
|
493
|
+
ok: boolean
|
|
494
|
+
/** PNG data URL of the composed sheet. */
|
|
495
|
+
image?: string
|
|
496
|
+
views?: ("iso" | "front" | "right" | "top")[]
|
|
497
|
+
/** [width, height, depth] in Snaptrude units. */
|
|
498
|
+
size?: [number, number, number]
|
|
499
|
+
ms?: number
|
|
500
|
+
/** Set when the picture could not be taken (e.g. the legacy renderer); the call itself still succeeded. */
|
|
501
|
+
error?: string
|
|
502
|
+
}
|
|
503
|
+
|
|
462
504
|
export const PluginDesignFamilyPrepareArgs = z.object({
|
|
463
505
|
bundle: PluginFamilyBundleSchema.optional(),
|
|
464
506
|
spec: PluginFamilyBundleSchema.optional(),
|
|
507
|
+
snapshot: PluginFamilySnapshotOption.optional(),
|
|
465
508
|
})
|
|
466
509
|
export type PluginDesignFamilyPrepareArgs = z.infer<typeof PluginDesignFamilyPrepareArgs>
|
|
467
510
|
|
|
@@ -471,9 +514,11 @@ export type PluginDesignFamilyPrepareArgs = z.infer<typeof PluginDesignFamilyPre
|
|
|
471
514
|
* | Property | Type | Description |
|
|
472
515
|
* |---|---|---|
|
|
473
516
|
* | `values` | `Record<string, number \| string>` | Parameter values to change (partial) |
|
|
517
|
+
* | `snapshot` | {@linkcode PluginFamilySnapshotOption} | Also return a picture of the flexed family |
|
|
474
518
|
*/
|
|
475
519
|
export const PluginDesignFamilyFlexArgs = z.object({
|
|
476
520
|
values: z.record(z.string(), z.union([z.number(), z.string()])),
|
|
521
|
+
snapshot: PluginFamilySnapshotOption.optional(),
|
|
477
522
|
})
|
|
478
523
|
export type PluginDesignFamilyFlexArgs = z.infer<typeof PluginDesignFamilyFlexArgs>
|
|
479
524
|
|
|
@@ -522,6 +567,8 @@ export type PluginDesignFamilyPlaceArgs = z.infer<typeof PluginDesignFamilyPlace
|
|
|
522
567
|
*/
|
|
523
568
|
export const PluginDesignFamilyGetParametersArgs = z.object({
|
|
524
569
|
component: ComponentHandle,
|
|
570
|
+
/** Also return a picture of this instance (its recipe re-run at its values, with its paint). */
|
|
571
|
+
snapshot: PluginFamilySnapshotOption.optional(),
|
|
525
572
|
})
|
|
526
573
|
export type PluginDesignFamilyGetParametersArgs = z.infer<
|
|
527
574
|
typeof PluginDesignFamilyGetParametersArgs
|