@snaptrude/plugin-core 0.9.9 → 0.9.11
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 +26 -0
- package/api-manifest.json +76 -390
- package/dist/api/core/mode/index.d.ts +19 -7
- package/dist/api/core/mode/index.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/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/workspace/index.d.ts +49 -2
- package/dist/api/workspace/index.d.ts.map +1 -1
- package/dist/index.cjs +2163 -1968
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2143 -1973
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/api/core/mode/index.ts +19 -7
- package/src/api/design/create/grids.ts +137 -0
- package/src/api/design/create/index.ts +131 -0
- 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/workspace/index.ts +51 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snaptrude/plugin-core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -16,17 +16,6 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"check-types": "tsc --noEmit",
|
|
21
|
-
"build": "tsup --clean",
|
|
22
|
-
"dev": "tsup --watch",
|
|
23
|
-
"clean-dist": "rm -rf dist",
|
|
24
|
-
"test": "node --test test/*.test.mjs",
|
|
25
|
-
"generate:manifest": "node scripts/generate-manifest.mjs",
|
|
26
|
-
"generate:manifest:check": "node scripts/generate-manifest.mjs --check",
|
|
27
|
-
"generate:manifest:all": "node scripts/generate-manifest.mjs --all",
|
|
28
|
-
"generate:manifest:all:check": "node scripts/generate-manifest.mjs --all --check"
|
|
29
|
-
},
|
|
30
19
|
"devDependencies": {
|
|
31
20
|
"ts-morph": "^28.0.0",
|
|
32
21
|
"tsup": "^8.5.1",
|
|
@@ -37,5 +26,16 @@
|
|
|
37
26
|
},
|
|
38
27
|
"peerDependencies": {
|
|
39
28
|
"zod": "^3.25.0 || ^4.0.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"check-types": "tsc --noEmit",
|
|
32
|
+
"build": "tsup --clean",
|
|
33
|
+
"dev": "tsup --watch",
|
|
34
|
+
"clean-dist": "rm -rf dist",
|
|
35
|
+
"test": "node --test test/*.test.mjs",
|
|
36
|
+
"generate:manifest": "node scripts/generate-manifest.mjs",
|
|
37
|
+
"generate:manifest:check": "node scripts/generate-manifest.mjs --check",
|
|
38
|
+
"generate:manifest:all": "node scripts/generate-manifest.mjs --all",
|
|
39
|
+
"generate:manifest:all:check": "node scripts/generate-manifest.mjs --all --check"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|
|
@@ -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
|
|
@@ -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"
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../types"
|
|
3
|
+
import { ComponentHandle } from "../../handles"
|
|
4
|
+
import { PluginGridStyleOptions } from "./create/grids"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tag policy for structural line removal (mirrors the engine
|
|
8
|
+
* `GridLineTagPolicy` values verbatim): `"rewrite"` renumbers each affected
|
|
9
|
+
* wing's tag sequence after removal; `"preserve"` keeps the surviving lines'
|
|
10
|
+
* tags unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export const PluginGridLineTagPolicy = z.enum(["rewrite", "preserve"])
|
|
13
|
+
export type PluginGridLineTagPolicy = z.infer<typeof PluginGridLineTagPolicy>
|
|
14
|
+
|
|
15
|
+
/** A positional grid-line address — indices into `design.query.grids.get`'s `wings` arrays. */
|
|
16
|
+
export const PluginGridLineAddress = z.object({
|
|
17
|
+
wing: z.number().int().nonnegative(),
|
|
18
|
+
line: z.number().int().nonnegative(),
|
|
19
|
+
})
|
|
20
|
+
export type PluginGridLineAddress = z.infer<typeof PluginGridLineAddress>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* One per-wing entry of {@linkcode PluginDesignGridsApi.updateWings} —
|
|
24
|
+
* addressed by wing index. `spanMin`/`spanMax` move the family's length
|
|
25
|
+
* handles (Snaptrude units).
|
|
26
|
+
*/
|
|
27
|
+
export const PluginGridWingEntry = z.object({
|
|
28
|
+
wing: z.number().int().nonnegative(),
|
|
29
|
+
spacing: z.number().positive().finite().optional(),
|
|
30
|
+
count: z.number().int().min(1).optional(),
|
|
31
|
+
spanMin: z.number().finite().optional(),
|
|
32
|
+
spanMax: z.number().finite().optional(),
|
|
33
|
+
})
|
|
34
|
+
export type PluginGridWingEntry = z.infer<typeof PluginGridWingEntry>
|
|
35
|
+
|
|
36
|
+
/** Arguments for {@linkcode PluginDesignGridsApi.updateWings}. */
|
|
37
|
+
export const PluginDesignGridsUpdateWingsArgs = z.object({
|
|
38
|
+
grid: ComponentHandle,
|
|
39
|
+
wings: z.array(PluginGridWingEntry).min(1),
|
|
40
|
+
})
|
|
41
|
+
export type PluginDesignGridsUpdateWingsArgs = z.infer<
|
|
42
|
+
typeof PluginDesignGridsUpdateWingsArgs
|
|
43
|
+
>
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* One per-line entry of {@linkcode PluginDesignGridsApi.updateLines} —
|
|
47
|
+
* addressed positionally by `{ wing, line }` indices (invalidated by
|
|
48
|
+
* structural edits; re-query after mutating). `distanceToPrevious` /
|
|
49
|
+
* `distanceToNext` set the typed distance to the adjacent line on that side
|
|
50
|
+
* and are mutually exclusive.
|
|
51
|
+
*
|
|
52
|
+
* `visible` is **hide-only** (`false`), mirroring the product: per-line show
|
|
53
|
+
* does not exist — showing the GROUP (`design.visibility.show`) restores all
|
|
54
|
+
* of its lines, exactly like the native Show All.
|
|
55
|
+
*/
|
|
56
|
+
export const PluginGridLineEntry = z
|
|
57
|
+
.object({
|
|
58
|
+
wing: z.number().int().nonnegative(),
|
|
59
|
+
line: z.number().int().nonnegative(),
|
|
60
|
+
tag: z.string().min(1).optional(),
|
|
61
|
+
distanceToPrevious: z.number().positive().finite().optional(),
|
|
62
|
+
distanceToNext: z.number().positive().finite().optional(),
|
|
63
|
+
props: PluginGridStyleOptions.optional(),
|
|
64
|
+
visible: z.literal(false).optional(),
|
|
65
|
+
})
|
|
66
|
+
.superRefine((entry, ctx) => {
|
|
67
|
+
if (entry.distanceToPrevious !== undefined && entry.distanceToNext !== undefined) {
|
|
68
|
+
ctx.addIssue({
|
|
69
|
+
code: z.ZodIssueCode.custom,
|
|
70
|
+
message:
|
|
71
|
+
"distanceToPrevious and distanceToNext are mutually exclusive on one line entry",
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
export type PluginGridLineEntry = z.infer<typeof PluginGridLineEntry>
|
|
76
|
+
|
|
77
|
+
/** Arguments for {@linkcode PluginDesignGridsApi.updateLines}. */
|
|
78
|
+
export const PluginDesignGridsUpdateLinesArgs = z.object({
|
|
79
|
+
grid: ComponentHandle,
|
|
80
|
+
lines: z.array(PluginGridLineEntry).min(1),
|
|
81
|
+
})
|
|
82
|
+
export type PluginDesignGridsUpdateLinesArgs = z.infer<
|
|
83
|
+
typeof PluginDesignGridsUpdateLinesArgs
|
|
84
|
+
>
|
|
85
|
+
|
|
86
|
+
/** Arguments for {@linkcode PluginDesignGridsApi.addLine}. */
|
|
87
|
+
export const PluginDesignGridsAddLineArgs = z.object({
|
|
88
|
+
grid: ComponentHandle,
|
|
89
|
+
wing: z.number().int().nonnegative(),
|
|
90
|
+
position: z.number().finite(),
|
|
91
|
+
})
|
|
92
|
+
export type PluginDesignGridsAddLineArgs = z.infer<typeof PluginDesignGridsAddLineArgs>
|
|
93
|
+
|
|
94
|
+
/** Arguments for {@linkcode PluginDesignGridsApi.removeLines}. */
|
|
95
|
+
export const PluginDesignGridsRemoveLinesArgs = z.object({
|
|
96
|
+
grid: ComponentHandle,
|
|
97
|
+
lines: z.array(PluginGridLineAddress).min(1),
|
|
98
|
+
tagPolicy: PluginGridLineTagPolicy.optional(),
|
|
99
|
+
})
|
|
100
|
+
export type PluginDesignGridsRemoveLinesArgs = z.infer<
|
|
101
|
+
typeof PluginDesignGridsRemoveLinesArgs
|
|
102
|
+
>
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* `design.grids.*` — structural edits on a grid's line structure (the
|
|
106
|
+
* entity-family home for grid-specific operations, like `design.doors`).
|
|
107
|
+
*
|
|
108
|
+
* Lines are addressed positionally as `{ wing, line }` index pairs into the
|
|
109
|
+
* `wings` arrays returned by `design.query.grids.get`. Adding, removing, or
|
|
110
|
+
* re-counting lines re-indexes the wing — re-query after every structural edit.
|
|
111
|
+
*
|
|
112
|
+
* Group-level edits (default styling, angle, storey visibility) live on
|
|
113
|
+
* `design.update.grid`; creation lives on `design.create.grid*`.
|
|
114
|
+
*
|
|
115
|
+
* Accessed via `snaptrude.design.grids`.
|
|
116
|
+
*/
|
|
117
|
+
export abstract class PluginDesignGridsApi {
|
|
118
|
+
constructor() {}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Update one or more **wings** of a grid with sparse per-wing entries —
|
|
122
|
+
* `spacing` (uniform re-space), `count` (grow/truncate + tag renumber),
|
|
123
|
+
* `spanMin`/`spanMax` (family length handles). Every change routes through
|
|
124
|
+
* the exact setters the native panel uses — each changed field commits its
|
|
125
|
+
* own undoable command, identical to editing that field in the panel.
|
|
126
|
+
*
|
|
127
|
+
* A `count` change re-indexes the wing's lines — positional `{ wing, line }`
|
|
128
|
+
* addresses held from before the call are stale afterwards; re-query.
|
|
129
|
+
*
|
|
130
|
+
* @param grid - The grid group
|
|
131
|
+
* @param wings - Sparse {@linkcode PluginGridWingEntry} entries (≥ 1)
|
|
132
|
+
* @returns `true` once applied
|
|
133
|
+
*
|
|
134
|
+
* @examplePrompt Change this grid's spacing to 8 metres
|
|
135
|
+
* @examplePrompt Make this grid 10 by 12 lines
|
|
136
|
+
*
|
|
137
|
+
* # Example
|
|
138
|
+
* ```ts
|
|
139
|
+
* await snaptrude.design.grids.updateWings(grid, [{ wing: 0, spacing: 8, count: 10 }])
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
public abstract updateWings(
|
|
143
|
+
grid: ComponentHandle,
|
|
144
|
+
wings: PluginGridWingEntry[],
|
|
145
|
+
): PluginApiReturn<boolean>
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Update one or more **lines** of a grid with sparse per-line entries —
|
|
149
|
+
* `tag`, `distanceToPrevious`/`distanceToNext` (typed distance to the
|
|
150
|
+
* neighbour on that side; mutually exclusive), `props` (per-line style
|
|
151
|
+
* overrides), and `visible: false` (hide). Every change routes through the
|
|
152
|
+
* exact setters the native panel uses — each changed field commits its own
|
|
153
|
+
* undoable command, identical to editing that field in the panel.
|
|
154
|
+
*
|
|
155
|
+
* Visibility mirrors the product exactly: `visible` accepts only `false` —
|
|
156
|
+
* per-line show does not exist. Hiding lines that would leave NO visible
|
|
157
|
+
* line hides the whole GROUP instead (the native last-line rule; those line
|
|
158
|
+
* flags stay untouched). To bring hidden lines back, show the group
|
|
159
|
+
* (`design.visibility.show([grid])`) — it restores ALL of its lines, like
|
|
160
|
+
* the native Show All.
|
|
161
|
+
*
|
|
162
|
+
* @param grid - The grid group
|
|
163
|
+
* @param lines - Sparse {@linkcode PluginGridLineEntry} entries (≥ 1)
|
|
164
|
+
* @returns `true` once applied
|
|
165
|
+
*
|
|
166
|
+
* @examplePrompt Rename grid line 2 to "B"
|
|
167
|
+
* @examplePrompt Move this grid line 4 metres from its neighbour
|
|
168
|
+
* @examplePrompt Hide grid line 3 on this grid
|
|
169
|
+
*
|
|
170
|
+
* # Example
|
|
171
|
+
* ```ts
|
|
172
|
+
* await snaptrude.design.grids.updateLines(grid, [
|
|
173
|
+
* { wing: 0, line: 1, tag: "B", distanceToPrevious: 4 },
|
|
174
|
+
* ])
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
public abstract updateLines(
|
|
178
|
+
grid: ComponentHandle,
|
|
179
|
+
lines: PluginGridLineEntry[],
|
|
180
|
+
): PluginApiReturn<boolean>
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Insert a parallel grid line into a wing at an explicit position along the
|
|
184
|
+
* wing's spacing axis (Snaptrude units, wing-local — line 0's position can
|
|
185
|
+
* be read from its curve). Sibling lines do not shift; the wing's tag
|
|
186
|
+
* sequence is renumbered. Undoable.
|
|
187
|
+
*
|
|
188
|
+
* @param grid - The grid group
|
|
189
|
+
* @param wing - Wing index
|
|
190
|
+
* @param position - Position along the wing's spacing axis (Snaptrude units)
|
|
191
|
+
* @returns `true` once inserted
|
|
192
|
+
* @throws `VALIDATION` on a bad wing index or non-finite position
|
|
193
|
+
*
|
|
194
|
+
* @examplePrompt Add a grid line between lines 2 and 3
|
|
195
|
+
* @examplePrompt Insert an extra grid line 4 metres from line A
|
|
196
|
+
*
|
|
197
|
+
* # Example
|
|
198
|
+
* ```ts
|
|
199
|
+
* await snaptrude.design.grids.addLine(grid, 0, 12.5)
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
public abstract addLine(
|
|
203
|
+
grid: ComponentHandle,
|
|
204
|
+
wing: number,
|
|
205
|
+
position: number,
|
|
206
|
+
): PluginApiReturn<boolean>
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Remove grid lines by positional address, as ONE undoable step. With
|
|
210
|
+
* `tagPolicy: "rewrite"` (default) each affected wing renumbers its tag
|
|
211
|
+
* sequence; `"preserve"` keeps surviving tags unchanged. A wing emptied of
|
|
212
|
+
* lines is dropped from the group.
|
|
213
|
+
*
|
|
214
|
+
* Removing EVERY line of the group is rejected — delete the group instead
|
|
215
|
+
* (`design.delete.entities`).
|
|
216
|
+
*
|
|
217
|
+
* @param grid - The grid group
|
|
218
|
+
* @param lines - Positional addresses to remove (see `design.query.grids.get`)
|
|
219
|
+
* @param tagPolicy - `"rewrite"` (default) or `"preserve"`
|
|
220
|
+
* @returns `true` once removed
|
|
221
|
+
* @throws `VALIDATION` on out-of-range addresses; `OPERATION_FAILED` when the
|
|
222
|
+
* removal would delete the group's last line
|
|
223
|
+
*
|
|
224
|
+
* @examplePrompt Delete grid line B
|
|
225
|
+
* @examplePrompt Remove the last two lines of this grid without renumbering
|
|
226
|
+
*
|
|
227
|
+
* # Example
|
|
228
|
+
* ```ts
|
|
229
|
+
* await snaptrude.design.grids.removeLines(grid, [{ wing: 0, line: 2 }], "preserve")
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
public abstract removeLines(
|
|
233
|
+
grid: ComponentHandle,
|
|
234
|
+
lines: PluginGridLineAddress[],
|
|
235
|
+
tagPolicy?: PluginGridLineTagPolicy,
|
|
236
|
+
): PluginApiReturn<boolean>
|
|
237
|
+
}
|
package/src/api/design/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { PluginDesignUpdateApi } from "./update"
|
|
|
16
16
|
import { PluginDesignVisibilityApi } from "./visibility"
|
|
17
17
|
import { PluginDesignDimensionsApi } from "./dimensions"
|
|
18
18
|
import { PluginDesignTypesApi } from "./types"
|
|
19
|
+
import { PluginDesignGridsApi } from "./grids"
|
|
19
20
|
import { PluginDesignChangeResult } from "./lock"
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -72,6 +73,9 @@ export abstract class PluginDesignApi {
|
|
|
72
73
|
/** Read-only building type / assembly reference. See {@linkcode PluginDesignTypesApi}. */
|
|
73
74
|
public abstract types: PluginDesignTypesApi
|
|
74
75
|
|
|
76
|
+
/** Structural edits on a grid's line structure. See {@linkcode PluginDesignGridsApi}. */
|
|
77
|
+
public abstract grids: PluginDesignGridsApi
|
|
78
|
+
|
|
75
79
|
/**
|
|
76
80
|
* Lock entities so they cannot be edited. Undoable. Cascades to void/door/window
|
|
77
81
|
* children, stacked-wall companions, and terrain neighborhood; skips
|
|
@@ -262,3 +266,4 @@ export * from "./update"
|
|
|
262
266
|
export * from "./visibility"
|
|
263
267
|
export * from "./dimensions"
|
|
264
268
|
export * from "./types"
|
|
269
|
+
export * from "./grids"
|