@snaptrude/plugin-core 0.9.17 → 0.9.18-edgesetbacks-20261021.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +231 -231
- package/CHANGELOG.md +408 -408
- package/CLAUDE.md +11 -11
- package/api-manifest.json +1428 -712
- package/dist/api/analysis/daylight.d.ts +5 -5
- package/dist/api/analysis/solar.d.ts +2 -2
- package/dist/api/core/camera/index.d.ts +29 -0
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +7 -1
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +8 -2
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/storeys/index.d.ts +5 -2
- package/dist/api/core/storeys/index.d.ts.map +1 -1
- package/dist/api/core/zoom/index.d.ts +13 -0
- package/dist/api/core/zoom/index.d.ts.map +1 -1
- package/dist/api/design/bim.d.ts +299 -0
- package/dist/api/design/bim.d.ts.map +1 -0
- package/dist/api/design/boolean/index.d.ts +2 -0
- package/dist/api/design/boolean/index.d.ts.map +1 -1
- package/dist/api/design/catalog.d.ts +320 -0
- package/dist/api/design/catalog.d.ts.map +1 -0
- package/dist/api/design/create/bulk-items.d.ts +65 -25
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +299 -100
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +13 -12
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +1 -0
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +18 -24
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +813 -35
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +16 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/networks.d.ts +1703 -0
- package/dist/api/design/networks.d.ts.map +1 -0
- package/dist/api/design/query/grids.d.ts +2 -2
- package/dist/api/design/query/index.d.ts +42 -32
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/selection/index.d.ts +10 -10
- package/dist/api/design/types/index.d.ts +40 -24
- package/dist/api/design/types/index.d.ts.map +1 -1
- package/dist/api/design/update/index.d.ts +111 -6
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/design/windows/index.d.ts +8 -8
- package/dist/api/design/windows/index.d.ts.map +1 -1
- package/dist/api/entity/buildableEnvelope.d.ts +84 -2
- package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
- package/dist/api/presentation/aiInspiration.d.ts +10 -10
- package/dist/api/presentation/annotate.d.ts +38 -22
- package/dist/api/presentation/annotate.d.ts.map +1 -1
- package/dist/api/presentation/drawingContract.d.ts +32 -0
- package/dist/api/presentation/drawingContract.d.ts.map +1 -0
- package/dist/api/presentation/drawings.d.ts +3523 -0
- package/dist/api/presentation/drawings.d.ts.map +1 -0
- package/dist/api/presentation/export.d.ts +23 -5
- package/dist/api/presentation/export.d.ts.map +1 -1
- package/dist/api/presentation/index.d.ts +32 -12
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +106 -6
- package/dist/api/presentation/placedViews.d.ts.map +1 -1
- package/dist/api/presentation/shapes.d.ts +2 -2
- package/dist/api/presentation/sheets.d.ts +175 -19
- package/dist/api/presentation/sheets.d.ts.map +1 -1
- package/dist/api/presentation/viewPresets.d.ts +222 -0
- package/dist/api/presentation/viewPresets.d.ts.map +1 -0
- package/dist/api/presentation/views.d.ts +141 -8
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/api/presentation/walkthroughs.d.ts +6 -6
- package/dist/errors/codes.d.ts +3 -1
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/index.cjs +3831 -2444
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3705 -2444
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-dist-fresh.mjs +22 -22
- package/scripts/generate-manifest.mjs +243 -238
- package/scripts/generate-manifest.test.mjs +303 -303
- package/src/api/analysis/daylight.ts +470 -470
- package/src/api/analysis/heatmaps.ts +683 -683
- package/src/api/analysis/illuminance.ts +155 -155
- package/src/api/analysis/index.ts +61 -61
- package/src/api/analysis/shadows.ts +183 -183
- package/src/api/analysis/solar.ts +237 -237
- package/src/api/analysis/sunlightHours.ts +211 -211
- package/src/api/analysis/sunpath.ts +83 -83
- package/src/api/analysis/weather.ts +179 -179
- package/src/api/core/buildings.ts +485 -485
- package/src/api/core/camera/index.ts +696 -667
- package/src/api/core/comment/index.ts +376 -376
- package/src/api/core/geom/create/index.ts +2139 -2133
- package/src/api/core/geom/delete/index.ts +84 -84
- package/src/api/core/geom/index.ts +35 -35
- package/src/api/core/geom/query/arc.ts +169 -169
- package/src/api/core/geom/query/brep.ts +621 -621
- package/src/api/core/geom/query/circle.ts +404 -404
- package/src/api/core/geom/query/contour.ts +540 -540
- package/src/api/core/geom/query/curve.ts +1102 -1102
- package/src/api/core/geom/query/edge.ts +130 -130
- package/src/api/core/geom/query/face.ts +508 -508
- package/src/api/core/geom/query/halfedge.ts +210 -210
- package/src/api/core/geom/query/index.ts +63 -63
- package/src/api/core/geom/query/profile.ts +473 -473
- package/src/api/core/geom/query/vertex.ts +205 -205
- package/src/api/core/geom/update/contour.ts +323 -317
- package/src/api/core/geom/update/curve.ts +209 -209
- package/src/api/core/geom/update/index.ts +29 -29
- package/src/api/core/geom/update/profile.ts +379 -379
- package/src/api/core/groups.ts +521 -521
- package/src/api/core/handles/index.ts +234 -234
- package/src/api/core/history/index.ts +84 -84
- package/src/api/core/index.ts +99 -99
- package/src/api/core/io/export/index.ts +126 -126
- package/src/api/core/io/import/index.ts +504 -504
- package/src/api/core/io/index.ts +42 -42
- package/src/api/core/io/job/index.ts +140 -140
- package/src/api/core/io/query/index.ts +71 -71
- package/src/api/core/io/terrain/index.ts +360 -360
- package/src/api/core/io/underlay/index.ts +705 -705
- package/src/api/core/layers.ts +540 -540
- package/src/api/core/math/index.ts +20 -20
- package/src/api/core/math/quat.ts +172 -172
- package/src/api/core/math/vec3.ts +179 -179
- package/src/api/core/mode/index.ts +108 -108
- package/src/api/core/project/index.ts +479 -479
- package/src/api/core/proposals/index.ts +570 -570
- package/src/api/core/storeys/index.ts +311 -308
- package/src/api/core/storeys/layers.ts +339 -339
- package/src/api/core/tags.ts +911 -911
- package/src/api/core/units/index.ts +164 -164
- package/src/api/core/user.ts +46 -46
- package/src/api/core/zoom/index.ts +64 -51
- package/src/api/design/bim.ts +210 -0
- package/src/api/design/boolean/index.ts +181 -179
- package/src/api/design/catalog.ts +203 -0
- package/src/api/design/create/bulk-items.ts +294 -254
- package/src/api/design/create/grids.ts +137 -137
- package/src/api/design/create/index.ts +2178 -1980
- package/src/api/design/create/opening-fields.ts +40 -37
- package/src/api/design/delete/index.ts +75 -74
- package/src/api/design/dimensions.ts +453 -453
- package/src/api/design/doors/index.ts +516 -500
- package/src/api/design/edit/index.ts +54 -54
- package/src/api/design/erase/index.ts +151 -151
- package/src/api/design/family.ts +1342 -704
- package/src/api/design/furniture/index.ts +319 -319
- package/src/api/design/grids.ts +237 -237
- package/src/api/design/index.ts +304 -274
- package/src/api/design/lock.ts +69 -69
- package/src/api/design/materials/index.ts +608 -608
- package/src/api/design/networks.ts +607 -0
- package/src/api/design/query/geometry/index.ts +319 -319
- package/src/api/design/query/grids.ts +197 -197
- package/src/api/design/query/index.ts +1236 -1226
- package/src/api/design/query/referenceLines.ts +52 -52
- package/src/api/design/query/spaces.ts +275 -275
- package/src/api/design/selection/index.ts +273 -273
- package/src/api/design/shared.ts +40 -40
- package/src/api/design/transform/index.ts +254 -254
- package/src/api/design/types/index.ts +163 -156
- package/src/api/design/update/index.ts +1096 -983
- package/src/api/design/visibility.ts +143 -143
- package/src/api/design/windows/index.ts +351 -333
- package/src/api/entity/buildableEnvelope.ts +397 -322
- package/src/api/entity/index.ts +30 -30
- package/src/api/entity/referenceLine.ts +235 -235
- package/src/api/entity/space.ts +612 -612
- package/src/api/entity/story.ts +517 -517
- package/src/api/index.ts +47 -47
- package/src/api/presentation/aiInspiration.ts +1116 -1116
- package/src/api/presentation/annotate.ts +417 -385
- package/src/api/presentation/camera.ts +289 -289
- package/src/api/presentation/diagrams.ts +194 -194
- package/src/api/presentation/drawingContract.ts +70 -0
- package/src/api/presentation/drawings.ts +1179 -0
- package/src/api/presentation/export.ts +134 -108
- package/src/api/presentation/import.ts +159 -159
- package/src/api/presentation/index.ts +160 -135
- package/src/api/presentation/placedViews.ts +1211 -1120
- package/src/api/presentation/sections.ts +420 -420
- package/src/api/presentation/shapes.ts +274 -274
- package/src/api/presentation/sheets.ts +746 -585
- package/src/api/presentation/slideshow.ts +134 -134
- package/src/api/presentation/tables.ts +84 -84
- package/src/api/presentation/viewPresets.ts +241 -0
- package/src/api/presentation/views.ts +742 -673
- package/src/api/presentation/walkthroughs.ts +1201 -1201
- package/src/api/program/adjacency.ts +164 -164
- package/src/api/program/areas.ts +408 -408
- package/src/api/program/classification.ts +138 -138
- package/src/api/program/cores.ts +83 -83
- package/src/api/program/departments.ts +517 -517
- package/src/api/program/index.ts +73 -73
- package/src/api/program/labels.ts +332 -332
- package/src/api/program/layout.ts +422 -422
- package/src/api/program/metadata.ts +364 -364
- package/src/api/program/metrics.ts +120 -120
- package/src/api/program/site.ts +748 -748
- package/src/api/program/spreadsheet.ts +2698 -2698
- package/src/api/workspace/index.ts +612 -612
- package/src/errors/codes.ts +143 -136
- package/src/errors/envelope.ts +75 -75
- package/src/errors/index.ts +21 -21
- package/src/errors/plugin-error.ts +134 -134
- package/src/handles.ts +297 -297
- package/src/host-utils.ts +67 -67
- package/src/index.ts +7 -7
- package/src/massParameters.ops.ts +246 -246
- package/src/massParameters.ts +427 -427
- package/src/types.ts +16 -16
- package/test/drawingContract.test.mjs +288 -0
- package/test/errors.test.mjs +185 -184
- package/test/massParameters.test.mjs +952 -952
- package/test/presentationViewSettings.test.mjs +85 -0
- package/tsconfig.json +22 -22
- package/tsup.config.ts +12 -12
|
@@ -1,273 +1,273 @@
|
|
|
1
|
-
import * as z from "zod"
|
|
2
|
-
import { PluginApiReturn } from "../../../types"
|
|
3
|
-
import { ComponentHandle } from "../../../handles"
|
|
4
|
-
import { PluginDesignChangeResult } from "../lock"
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* The entity kinds {@linkcode PluginDesignSelectionApi.setByFilter} can select —
|
|
8
|
-
* the union of the editor's "Filter selection" menus (Design tab + BIM tab).
|
|
9
|
-
* Tokens mirror {@linkcode PluginEntityType} where a kind exists on the query
|
|
10
|
-
* surface; the rest are selection-only kinds the query surface cannot reach
|
|
11
|
-
* (layer-backed and annotation objects).
|
|
12
|
-
*
|
|
13
|
-
* | Value | Entity (menu label) |
|
|
14
|
-
* |---|---|
|
|
15
|
-
* | `"wall"` | Wall |
|
|
16
|
-
* | `"slab"` | Floor slab |
|
|
17
|
-
* | `"floor"` | Flooring |
|
|
18
|
-
* | `"door"` | Door |
|
|
19
|
-
* | `"window"` | Window |
|
|
20
|
-
* | `"beam"` | Beam |
|
|
21
|
-
* | `"column"` | Column |
|
|
22
|
-
* | `"ceiling"` | Ceiling |
|
|
23
|
-
* | `"roof"` | Roof |
|
|
24
|
-
* | `"staircase"` | Staircase |
|
|
25
|
-
* | `"furniture"` | Furniture |
|
|
26
|
-
* | `"pergola"` | Pergola |
|
|
27
|
-
* | `"sunshade"` | Sunshade |
|
|
28
|
-
* | `"referenceLine"` | Reference line |
|
|
29
|
-
* | `"space"` | Space (room mass) |
|
|
30
|
-
* | `"site"` | Site |
|
|
31
|
-
* | `"terrain"` | Terrain |
|
|
32
|
-
* | `"cad"` | CAD import |
|
|
33
|
-
* | `"pdf"` | PDF import |
|
|
34
|
-
* | `"image"` | Image import |
|
|
35
|
-
* | `"dimensionLine"` | Dimension line |
|
|
36
|
-
* | `"model3d"` | Imported 3D model |
|
|
37
|
-
* | `"neighborhoodBuilding"` | Neighborhood building |
|
|
38
|
-
* | `"programBlock"` | Program block (department mass) |
|
|
39
|
-
*/
|
|
40
|
-
export const PluginSelectionEntityType = z.enum([
|
|
41
|
-
"wall",
|
|
42
|
-
"slab",
|
|
43
|
-
"floor",
|
|
44
|
-
"door",
|
|
45
|
-
"window",
|
|
46
|
-
"beam",
|
|
47
|
-
"column",
|
|
48
|
-
"ceiling",
|
|
49
|
-
"roof",
|
|
50
|
-
"staircase",
|
|
51
|
-
"furniture",
|
|
52
|
-
"pergola",
|
|
53
|
-
"sunshade",
|
|
54
|
-
"referenceLine",
|
|
55
|
-
"space",
|
|
56
|
-
"site",
|
|
57
|
-
"terrain",
|
|
58
|
-
"cad",
|
|
59
|
-
"pdf",
|
|
60
|
-
"image",
|
|
61
|
-
"dimensionLine",
|
|
62
|
-
"model3d",
|
|
63
|
-
"neighborhoodBuilding",
|
|
64
|
-
"programBlock",
|
|
65
|
-
])
|
|
66
|
-
export type PluginSelectionEntityType = z.infer<typeof PluginSelectionEntityType>
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* The filter for {@linkcode PluginDesignSelectionApi.setByFilter}. At least one
|
|
70
|
-
* field must be non-empty (to empty the selection use
|
|
71
|
-
* {@linkcode PluginDesignSelectionApi.clear}). Fields **AND**-combine; values
|
|
72
|
-
* within a field **OR**-combine — `{ storeys: [2], types: ["furniture"] }`
|
|
73
|
-
* selects only the furniture on storey 2.
|
|
74
|
-
*
|
|
75
|
-
* | Field | Type | Selects entities where |
|
|
76
|
-
* |---|---|---|
|
|
77
|
-
* | `storeys` | `number[]` | storey/floor level ∈ `storeys` (negative = basement) |
|
|
78
|
-
* | `types` | {@linkcode PluginSelectionEntityType}`[]` | entity kind ∈ `types` |
|
|
79
|
-
*/
|
|
80
|
-
export const PluginSelectionFilter = z
|
|
81
|
-
.object({
|
|
82
|
-
storeys: z.array(z.number()).optional(),
|
|
83
|
-
types: z.array(PluginSelectionEntityType).optional(),
|
|
84
|
-
})
|
|
85
|
-
.refine((f) => (f.storeys?.length ?? 0) + (f.types?.length ?? 0) > 0, {
|
|
86
|
-
message:
|
|
87
|
-
"PluginSelectionFilter requires at least one non-empty field (storeys or types); use design.selection.clear() to deselect everything",
|
|
88
|
-
})
|
|
89
|
-
export type PluginSelectionFilter = z.infer<typeof PluginSelectionFilter>
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* `snaptrude.design.selection` — read and mutate the current scene selection.
|
|
93
|
-
*
|
|
94
|
-
* Selection targets are {@linkcode ComponentHandle}s. `get` is the one sanctioned
|
|
95
|
-
* `get`-returns-array accessor (§4.1(3)). The mutators (`set`/`add`/`remove`/`clear`)
|
|
96
|
-
* change the live selection and return the resulting selection snapshot — they are
|
|
97
|
-
* **not undoable** (the engine fires a selection listener, no command), so the
|
|
98
|
-
* returned {@linkcode PluginDesignChangeResult} is a committed-state snapshot.
|
|
99
|
-
*/
|
|
100
|
-
export abstract class PluginDesignSelectionApi {
|
|
101
|
-
constructor() {}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Read the current scene selection — the entities the user (or a previous
|
|
105
|
-
* call) has selected, returned as handles you can pass straight into other
|
|
106
|
-
* API calls.
|
|
107
|
-
*
|
|
108
|
-
* @returns The selection as {@linkcode ComponentHandle}`[]` (`[]` when nothing is selected)
|
|
109
|
-
*
|
|
110
|
-
* @examplePrompt What do I have selected right now?
|
|
111
|
-
* @examplePrompt List the currently selected objects
|
|
112
|
-
* @examplePrompt Which rooms are selected in the scene?
|
|
113
|
-
* @examplePrompt Get the ids of everything I've selected
|
|
114
|
-
* @examplePrompt Is anything selected?
|
|
115
|
-
*
|
|
116
|
-
* # Example
|
|
117
|
-
* ```ts
|
|
118
|
-
* // Selection handles feed straight into other API calls
|
|
119
|
-
* const selection = await snaptrude.design.selection.get()
|
|
120
|
-
* if (selection.length > 0) {
|
|
121
|
-
* const props = await snaptrude.design.query.getProperties(selection[0])
|
|
122
|
-
* }
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
public abstract get(): PluginApiReturn<ComponentHandle[]>
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Replace the selection with exactly the given entities — anything
|
|
129
|
-
* previously selected is deselected first, so afterwards only these
|
|
130
|
-
* entities are selected.
|
|
131
|
-
*
|
|
132
|
-
* @param components The entities to select
|
|
133
|
-
* @returns The resulting selection snapshot
|
|
134
|
-
*
|
|
135
|
-
* @examplePrompt Select these three walls
|
|
136
|
-
* @examplePrompt Select only the kitchen and deselect everything else
|
|
137
|
-
* @examplePrompt Change the selection to just these rooms
|
|
138
|
-
* @examplePrompt Highlight the spaces on the second storey
|
|
139
|
-
*
|
|
140
|
-
* # Example
|
|
141
|
-
* ```ts
|
|
142
|
-
* // Select only the ground-storey walls (replaces the previous selection)
|
|
143
|
-
* const walls = await snaptrude.design.query.listWalls({ storeys: [1] })
|
|
144
|
-
* const { affected } = await snaptrude.design.selection.set(walls)
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
|
-
public abstract set(components: ComponentHandle[]): PluginApiReturn<PluginDesignChangeResult>
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Add entities to the current selection without deselecting anything — the
|
|
151
|
-
* selection grows to include the given entities alongside whatever was
|
|
152
|
-
* already selected.
|
|
153
|
-
*
|
|
154
|
-
* @param components The entities to add to the selection
|
|
155
|
-
* @returns The resulting selection snapshot
|
|
156
|
-
*
|
|
157
|
-
* @examplePrompt Add the corridor to my current selection
|
|
158
|
-
* @examplePrompt Select these columns too, keeping what's already selected
|
|
159
|
-
* @examplePrompt Also select the roof
|
|
160
|
-
* @examplePrompt Extend the selection to include all the doors on this floor
|
|
161
|
-
*
|
|
162
|
-
* # Example
|
|
163
|
-
* ```ts
|
|
164
|
-
* // Grow the selection to include every roof, keeping what's already selected
|
|
165
|
-
* const roofs = await snaptrude.design.query.listRoofs()
|
|
166
|
-
* await snaptrude.design.selection.add(roofs)
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
public abstract add(components: ComponentHandle[]): PluginApiReturn<PluginDesignChangeResult>
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Remove entities from the current selection — the given entities are
|
|
173
|
-
* deselected while everything else stays selected.
|
|
174
|
-
*
|
|
175
|
-
* @param components The entities to remove from the selection
|
|
176
|
-
* @returns The resulting selection snapshot
|
|
177
|
-
*
|
|
178
|
-
* @examplePrompt Deselect the stair core but keep the rest selected
|
|
179
|
-
* @examplePrompt Remove these walls from my selection
|
|
180
|
-
* @examplePrompt Take the furniture out of the current selection
|
|
181
|
-
* @examplePrompt Unselect the two smaller rooms
|
|
182
|
-
*
|
|
183
|
-
* # Example
|
|
184
|
-
* ```ts
|
|
185
|
-
* // Deselect the furniture while keeping everything else selected
|
|
186
|
-
* const furniture = await snaptrude.design.query.listFurniture({ isSelected: true })
|
|
187
|
-
* await snaptrude.design.selection.remove(furniture)
|
|
188
|
-
* ```
|
|
189
|
-
*/
|
|
190
|
-
public abstract remove(
|
|
191
|
-
components: ComponentHandle[]
|
|
192
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Clear the selection so nothing is selected (equivalent to `set([])`).
|
|
196
|
-
*
|
|
197
|
-
* @returns The resulting (empty) selection snapshot
|
|
198
|
-
*
|
|
199
|
-
* @examplePrompt Deselect everything
|
|
200
|
-
* @examplePrompt Clear my current selection
|
|
201
|
-
* @examplePrompt Unselect all objects in the scene
|
|
202
|
-
* @examplePrompt Make sure nothing is selected before we start
|
|
203
|
-
*
|
|
204
|
-
* # Example
|
|
205
|
-
* ```ts
|
|
206
|
-
* const { affected } = await snaptrude.design.selection.clear()
|
|
207
|
-
* // affected is the resulting selection — always [] here
|
|
208
|
-
* ```
|
|
209
|
-
*/
|
|
210
|
-
public abstract clear(): PluginApiReturn<PluginDesignChangeResult>
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Replace the selection with every visible entity of the active building that
|
|
214
|
-
* matches the filter — the programmatic equivalent of the editor's
|
|
215
|
-
* **Story selection** (`storeys`) and **Filter selection** (`types`) menus
|
|
216
|
-
* under the select tool, including their combination (fields AND, values
|
|
217
|
-
* within a field OR). Reaches selection-only kinds the query surface cannot
|
|
218
|
-
* (sites, terrain, CAD/PDF/image imports, dimension lines, 3D models,
|
|
219
|
-
* neighborhood buildings) and selects whole groups the way the editor does.
|
|
220
|
-
*
|
|
221
|
-
* This is a one-shot bulk select, not a persistent mode: the user's next
|
|
222
|
-
* canvas click resets the underlying filter state (the selection it made
|
|
223
|
-
* stays until changed). Results honor the ambient view — active building,
|
|
224
|
-
* hidden objects/buckets, and in 2D the active storey.
|
|
225
|
-
*
|
|
226
|
-
* @param filter Which entities to select — {@linkcode PluginSelectionFilter};
|
|
227
|
-
* at least one field must be non-empty
|
|
228
|
-
* @returns The resulting selection snapshot
|
|
229
|
-
*
|
|
230
|
-
* @examplePrompt Select everything on storey 2
|
|
231
|
-
* @examplePrompt Select all the walls and doors
|
|
232
|
-
* @examplePrompt Story selection: select the ground floor and first floor
|
|
233
|
-
* @examplePrompt Filter selection: select all furniture in the model
|
|
234
|
-
* @examplePrompt Select only the furniture on the second storey
|
|
235
|
-
* @examplePrompt Select all the spaces so I can recolor them
|
|
236
|
-
*
|
|
237
|
-
* # Example
|
|
238
|
-
* ```ts
|
|
239
|
-
* // "Story selection": everything on storeys 1 and 2
|
|
240
|
-
* await snaptrude.design.selection.setByFilter({ storeys: [1, 2] })
|
|
241
|
-
*
|
|
242
|
-
* // "Filter selection": all walls and doors
|
|
243
|
-
* await snaptrude.design.selection.setByFilter({ types: ["wall", "door"] })
|
|
244
|
-
*
|
|
245
|
-
* // Combined: only the furniture on storey 2
|
|
246
|
-
* const { affected } = await snaptrude.design.selection.setByFilter({
|
|
247
|
-
* storeys: [2],
|
|
248
|
-
* types: ["furniture"],
|
|
249
|
-
* })
|
|
250
|
-
* ```
|
|
251
|
-
*/
|
|
252
|
-
public abstract setByFilter(
|
|
253
|
-
filter: PluginSelectionFilter
|
|
254
|
-
): PluginApiReturn<PluginDesignChangeResult>
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Arguments for {@linkcode PluginDesignSelectionApi.set}.
|
|
259
|
-
*
|
|
260
|
-
* | Property | Type | Description |
|
|
261
|
-
* |---|---|---|
|
|
262
|
-
* | `components` | {@linkcode ComponentHandle}`[]` | The entities to select |
|
|
263
|
-
*/
|
|
264
|
-
export const PluginDesignSelectionSetArgs = z.object({
|
|
265
|
-
components: z.array(ComponentHandle),
|
|
266
|
-
})
|
|
267
|
-
export type PluginDesignSelectionSetArgs = z.infer<typeof PluginDesignSelectionSetArgs>
|
|
268
|
-
|
|
269
|
-
export const PluginDesignSelectionAddArgs = PluginDesignSelectionSetArgs
|
|
270
|
-
export type PluginDesignSelectionAddArgs = z.infer<typeof PluginDesignSelectionAddArgs>
|
|
271
|
-
|
|
272
|
-
export const PluginDesignSelectionRemoveArgs = PluginDesignSelectionSetArgs
|
|
273
|
-
export type PluginDesignSelectionRemoveArgs = z.infer<typeof PluginDesignSelectionRemoveArgs>
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../../types"
|
|
3
|
+
import { ComponentHandle } from "../../../handles"
|
|
4
|
+
import { PluginDesignChangeResult } from "../lock"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The entity kinds {@linkcode PluginDesignSelectionApi.setByFilter} can select —
|
|
8
|
+
* the union of the editor's "Filter selection" menus (Design tab + BIM tab).
|
|
9
|
+
* Tokens mirror {@linkcode PluginEntityType} where a kind exists on the query
|
|
10
|
+
* surface; the rest are selection-only kinds the query surface cannot reach
|
|
11
|
+
* (layer-backed and annotation objects).
|
|
12
|
+
*
|
|
13
|
+
* | Value | Entity (menu label) |
|
|
14
|
+
* |---|---|
|
|
15
|
+
* | `"wall"` | Wall |
|
|
16
|
+
* | `"slab"` | Floor slab |
|
|
17
|
+
* | `"floor"` | Flooring |
|
|
18
|
+
* | `"door"` | Door |
|
|
19
|
+
* | `"window"` | Window |
|
|
20
|
+
* | `"beam"` | Beam |
|
|
21
|
+
* | `"column"` | Column |
|
|
22
|
+
* | `"ceiling"` | Ceiling |
|
|
23
|
+
* | `"roof"` | Roof |
|
|
24
|
+
* | `"staircase"` | Staircase |
|
|
25
|
+
* | `"furniture"` | Furniture |
|
|
26
|
+
* | `"pergola"` | Pergola |
|
|
27
|
+
* | `"sunshade"` | Sunshade |
|
|
28
|
+
* | `"referenceLine"` | Reference line |
|
|
29
|
+
* | `"space"` | Space (room mass) |
|
|
30
|
+
* | `"site"` | Site |
|
|
31
|
+
* | `"terrain"` | Terrain |
|
|
32
|
+
* | `"cad"` | CAD import |
|
|
33
|
+
* | `"pdf"` | PDF import |
|
|
34
|
+
* | `"image"` | Image import |
|
|
35
|
+
* | `"dimensionLine"` | Dimension line |
|
|
36
|
+
* | `"model3d"` | Imported 3D model |
|
|
37
|
+
* | `"neighborhoodBuilding"` | Neighborhood building |
|
|
38
|
+
* | `"programBlock"` | Program block (department mass) |
|
|
39
|
+
*/
|
|
40
|
+
export const PluginSelectionEntityType = z.enum([
|
|
41
|
+
"wall",
|
|
42
|
+
"slab",
|
|
43
|
+
"floor",
|
|
44
|
+
"door",
|
|
45
|
+
"window",
|
|
46
|
+
"beam",
|
|
47
|
+
"column",
|
|
48
|
+
"ceiling",
|
|
49
|
+
"roof",
|
|
50
|
+
"staircase",
|
|
51
|
+
"furniture",
|
|
52
|
+
"pergola",
|
|
53
|
+
"sunshade",
|
|
54
|
+
"referenceLine",
|
|
55
|
+
"space",
|
|
56
|
+
"site",
|
|
57
|
+
"terrain",
|
|
58
|
+
"cad",
|
|
59
|
+
"pdf",
|
|
60
|
+
"image",
|
|
61
|
+
"dimensionLine",
|
|
62
|
+
"model3d",
|
|
63
|
+
"neighborhoodBuilding",
|
|
64
|
+
"programBlock",
|
|
65
|
+
])
|
|
66
|
+
export type PluginSelectionEntityType = z.infer<typeof PluginSelectionEntityType>
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The filter for {@linkcode PluginDesignSelectionApi.setByFilter}. At least one
|
|
70
|
+
* field must be non-empty (to empty the selection use
|
|
71
|
+
* {@linkcode PluginDesignSelectionApi.clear}). Fields **AND**-combine; values
|
|
72
|
+
* within a field **OR**-combine — `{ storeys: [2], types: ["furniture"] }`
|
|
73
|
+
* selects only the furniture on storey 2.
|
|
74
|
+
*
|
|
75
|
+
* | Field | Type | Selects entities where |
|
|
76
|
+
* |---|---|---|
|
|
77
|
+
* | `storeys` | `number[]` | storey/floor level ∈ `storeys` (negative = basement) |
|
|
78
|
+
* | `types` | {@linkcode PluginSelectionEntityType}`[]` | entity kind ∈ `types` |
|
|
79
|
+
*/
|
|
80
|
+
export const PluginSelectionFilter = z
|
|
81
|
+
.object({
|
|
82
|
+
storeys: z.array(z.number()).optional(),
|
|
83
|
+
types: z.array(PluginSelectionEntityType).optional(),
|
|
84
|
+
})
|
|
85
|
+
.refine((f) => (f.storeys?.length ?? 0) + (f.types?.length ?? 0) > 0, {
|
|
86
|
+
message:
|
|
87
|
+
"PluginSelectionFilter requires at least one non-empty field (storeys or types); use design.selection.clear() to deselect everything",
|
|
88
|
+
})
|
|
89
|
+
export type PluginSelectionFilter = z.infer<typeof PluginSelectionFilter>
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* `snaptrude.design.selection` — read and mutate the current scene selection.
|
|
93
|
+
*
|
|
94
|
+
* Selection targets are {@linkcode ComponentHandle}s. `get` is the one sanctioned
|
|
95
|
+
* `get`-returns-array accessor (§4.1(3)). The mutators (`set`/`add`/`remove`/`clear`)
|
|
96
|
+
* change the live selection and return the resulting selection snapshot — they are
|
|
97
|
+
* **not undoable** (the engine fires a selection listener, no command), so the
|
|
98
|
+
* returned {@linkcode PluginDesignChangeResult} is a committed-state snapshot.
|
|
99
|
+
*/
|
|
100
|
+
export abstract class PluginDesignSelectionApi {
|
|
101
|
+
constructor() {}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Read the current scene selection — the entities the user (or a previous
|
|
105
|
+
* call) has selected, returned as handles you can pass straight into other
|
|
106
|
+
* API calls.
|
|
107
|
+
*
|
|
108
|
+
* @returns The selection as {@linkcode ComponentHandle}`[]` (`[]` when nothing is selected)
|
|
109
|
+
*
|
|
110
|
+
* @examplePrompt What do I have selected right now?
|
|
111
|
+
* @examplePrompt List the currently selected objects
|
|
112
|
+
* @examplePrompt Which rooms are selected in the scene?
|
|
113
|
+
* @examplePrompt Get the ids of everything I've selected
|
|
114
|
+
* @examplePrompt Is anything selected?
|
|
115
|
+
*
|
|
116
|
+
* # Example
|
|
117
|
+
* ```ts
|
|
118
|
+
* // Selection handles feed straight into other API calls
|
|
119
|
+
* const selection = await snaptrude.design.selection.get()
|
|
120
|
+
* if (selection.length > 0) {
|
|
121
|
+
* const props = await snaptrude.design.query.getProperties(selection[0])
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
public abstract get(): PluginApiReturn<ComponentHandle[]>
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Replace the selection with exactly the given entities — anything
|
|
129
|
+
* previously selected is deselected first, so afterwards only these
|
|
130
|
+
* entities are selected.
|
|
131
|
+
*
|
|
132
|
+
* @param components The entities to select
|
|
133
|
+
* @returns The resulting selection snapshot
|
|
134
|
+
*
|
|
135
|
+
* @examplePrompt Select these three walls
|
|
136
|
+
* @examplePrompt Select only the kitchen and deselect everything else
|
|
137
|
+
* @examplePrompt Change the selection to just these rooms
|
|
138
|
+
* @examplePrompt Highlight the spaces on the second storey
|
|
139
|
+
*
|
|
140
|
+
* # Example
|
|
141
|
+
* ```ts
|
|
142
|
+
* // Select only the ground-storey walls (replaces the previous selection)
|
|
143
|
+
* const walls = await snaptrude.design.query.listWalls({ storeys: [1] })
|
|
144
|
+
* const { affected } = await snaptrude.design.selection.set(walls)
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
public abstract set(components: ComponentHandle[]): PluginApiReturn<PluginDesignChangeResult>
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Add entities to the current selection without deselecting anything — the
|
|
151
|
+
* selection grows to include the given entities alongside whatever was
|
|
152
|
+
* already selected.
|
|
153
|
+
*
|
|
154
|
+
* @param components The entities to add to the selection
|
|
155
|
+
* @returns The resulting selection snapshot
|
|
156
|
+
*
|
|
157
|
+
* @examplePrompt Add the corridor to my current selection
|
|
158
|
+
* @examplePrompt Select these columns too, keeping what's already selected
|
|
159
|
+
* @examplePrompt Also select the roof
|
|
160
|
+
* @examplePrompt Extend the selection to include all the doors on this floor
|
|
161
|
+
*
|
|
162
|
+
* # Example
|
|
163
|
+
* ```ts
|
|
164
|
+
* // Grow the selection to include every roof, keeping what's already selected
|
|
165
|
+
* const roofs = await snaptrude.design.query.listRoofs()
|
|
166
|
+
* await snaptrude.design.selection.add(roofs)
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
public abstract add(components: ComponentHandle[]): PluginApiReturn<PluginDesignChangeResult>
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove entities from the current selection — the given entities are
|
|
173
|
+
* deselected while everything else stays selected.
|
|
174
|
+
*
|
|
175
|
+
* @param components The entities to remove from the selection
|
|
176
|
+
* @returns The resulting selection snapshot
|
|
177
|
+
*
|
|
178
|
+
* @examplePrompt Deselect the stair core but keep the rest selected
|
|
179
|
+
* @examplePrompt Remove these walls from my selection
|
|
180
|
+
* @examplePrompt Take the furniture out of the current selection
|
|
181
|
+
* @examplePrompt Unselect the two smaller rooms
|
|
182
|
+
*
|
|
183
|
+
* # Example
|
|
184
|
+
* ```ts
|
|
185
|
+
* // Deselect the furniture while keeping everything else selected
|
|
186
|
+
* const furniture = await snaptrude.design.query.listFurniture({ isSelected: true })
|
|
187
|
+
* await snaptrude.design.selection.remove(furniture)
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
public abstract remove(
|
|
191
|
+
components: ComponentHandle[]
|
|
192
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Clear the selection so nothing is selected (equivalent to `set([])`).
|
|
196
|
+
*
|
|
197
|
+
* @returns The resulting (empty) selection snapshot
|
|
198
|
+
*
|
|
199
|
+
* @examplePrompt Deselect everything
|
|
200
|
+
* @examplePrompt Clear my current selection
|
|
201
|
+
* @examplePrompt Unselect all objects in the scene
|
|
202
|
+
* @examplePrompt Make sure nothing is selected before we start
|
|
203
|
+
*
|
|
204
|
+
* # Example
|
|
205
|
+
* ```ts
|
|
206
|
+
* const { affected } = await snaptrude.design.selection.clear()
|
|
207
|
+
* // affected is the resulting selection — always [] here
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
public abstract clear(): PluginApiReturn<PluginDesignChangeResult>
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Replace the selection with every visible entity of the active building that
|
|
214
|
+
* matches the filter — the programmatic equivalent of the editor's
|
|
215
|
+
* **Story selection** (`storeys`) and **Filter selection** (`types`) menus
|
|
216
|
+
* under the select tool, including their combination (fields AND, values
|
|
217
|
+
* within a field OR). Reaches selection-only kinds the query surface cannot
|
|
218
|
+
* (sites, terrain, CAD/PDF/image imports, dimension lines, 3D models,
|
|
219
|
+
* neighborhood buildings) and selects whole groups the way the editor does.
|
|
220
|
+
*
|
|
221
|
+
* This is a one-shot bulk select, not a persistent mode: the user's next
|
|
222
|
+
* canvas click resets the underlying filter state (the selection it made
|
|
223
|
+
* stays until changed). Results honor the ambient view — active building,
|
|
224
|
+
* hidden objects/buckets, and in 2D the active storey.
|
|
225
|
+
*
|
|
226
|
+
* @param filter Which entities to select — {@linkcode PluginSelectionFilter};
|
|
227
|
+
* at least one field must be non-empty
|
|
228
|
+
* @returns The resulting selection snapshot
|
|
229
|
+
*
|
|
230
|
+
* @examplePrompt Select everything on storey 2
|
|
231
|
+
* @examplePrompt Select all the walls and doors
|
|
232
|
+
* @examplePrompt Story selection: select the ground floor and first floor
|
|
233
|
+
* @examplePrompt Filter selection: select all furniture in the model
|
|
234
|
+
* @examplePrompt Select only the furniture on the second storey
|
|
235
|
+
* @examplePrompt Select all the spaces so I can recolor them
|
|
236
|
+
*
|
|
237
|
+
* # Example
|
|
238
|
+
* ```ts
|
|
239
|
+
* // "Story selection": everything on storeys 1 and 2
|
|
240
|
+
* await snaptrude.design.selection.setByFilter({ storeys: [1, 2] })
|
|
241
|
+
*
|
|
242
|
+
* // "Filter selection": all walls and doors
|
|
243
|
+
* await snaptrude.design.selection.setByFilter({ types: ["wall", "door"] })
|
|
244
|
+
*
|
|
245
|
+
* // Combined: only the furniture on storey 2
|
|
246
|
+
* const { affected } = await snaptrude.design.selection.setByFilter({
|
|
247
|
+
* storeys: [2],
|
|
248
|
+
* types: ["furniture"],
|
|
249
|
+
* })
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
public abstract setByFilter(
|
|
253
|
+
filter: PluginSelectionFilter
|
|
254
|
+
): PluginApiReturn<PluginDesignChangeResult>
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Arguments for {@linkcode PluginDesignSelectionApi.set}.
|
|
259
|
+
*
|
|
260
|
+
* | Property | Type | Description |
|
|
261
|
+
* |---|---|---|
|
|
262
|
+
* | `components` | {@linkcode ComponentHandle}`[]` | The entities to select |
|
|
263
|
+
*/
|
|
264
|
+
export const PluginDesignSelectionSetArgs = z.object({
|
|
265
|
+
components: z.array(ComponentHandle),
|
|
266
|
+
})
|
|
267
|
+
export type PluginDesignSelectionSetArgs = z.infer<typeof PluginDesignSelectionSetArgs>
|
|
268
|
+
|
|
269
|
+
export const PluginDesignSelectionAddArgs = PluginDesignSelectionSetArgs
|
|
270
|
+
export type PluginDesignSelectionAddArgs = z.infer<typeof PluginDesignSelectionAddArgs>
|
|
271
|
+
|
|
272
|
+
export const PluginDesignSelectionRemoveArgs = PluginDesignSelectionSetArgs
|
|
273
|
+
export type PluginDesignSelectionRemoveArgs = z.infer<typeof PluginDesignSelectionRemoveArgs>
|
package/src/api/design/shared.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import * as z from "zod"
|
|
2
|
-
import { ComponentHandle } from "../../handles"
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Shared `design.*` operation return records (LLD Part A.3).
|
|
6
|
-
*
|
|
7
|
-
* `PluginDesignChangeResult` (`{ affected }`) is NOT here — it already lives in
|
|
8
|
-
* `./lock` and is reused verbatim by the transform/delete mutators.
|
|
9
|
-
*
|
|
10
|
-
* NOTE: `PluginMirrorAxis` currently lives in `./doors`; its relocation into this
|
|
11
|
-
* shared module is deferred to the transform wave (avoids a doors edit + a
|
|
12
|
-
* double-export while `design.transform` is unwired).
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Result of a CSG boolean op (`design.boolean.union/subtract/intersect`). Grounded
|
|
17
|
-
* in the engine `Boolean3dOperation.resultComponents { toCreate; toDelete }`:
|
|
18
|
-
* `created` are the result masses, `deleted` is every consumed input (for
|
|
19
|
-
* `subtract` this includes BOTH the target AND the tools). Errors throw (RPC
|
|
20
|
-
* rejects); no `Result<>` crosses the boundary.
|
|
21
|
-
*/
|
|
22
|
-
export const BooleanOutcome = z.object({
|
|
23
|
-
created: z.array(ComponentHandle),
|
|
24
|
-
deleted: z.array(ComponentHandle),
|
|
25
|
-
})
|
|
26
|
-
export type BooleanOutcome = z.infer<typeof BooleanOutcome>
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Result of `design.edit.offsetSplit` (migrated from `tools.offset`). `createdIds`
|
|
30
|
-
* are the components the offset produced; `deletedIds` are those a split-style
|
|
31
|
-
* offset removed. `offsetValue` is the engine's POST-clamp / post-sign applied
|
|
32
|
-
* distance — the only way a caller learns the actually-applied clamped distance
|
|
33
|
-
* (the shipped `tools.offset` result dropped it).
|
|
34
|
-
*/
|
|
35
|
-
export const OffsetSplitOutcome = z.object({
|
|
36
|
-
createdIds: z.array(ComponentHandle),
|
|
37
|
-
deletedIds: z.array(ComponentHandle),
|
|
38
|
-
offsetValue: z.number(),
|
|
39
|
-
})
|
|
40
|
-
export type OffsetSplitOutcome = z.infer<typeof OffsetSplitOutcome>
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { ComponentHandle } from "../../handles"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared `design.*` operation return records (LLD Part A.3).
|
|
6
|
+
*
|
|
7
|
+
* `PluginDesignChangeResult` (`{ affected }`) is NOT here — it already lives in
|
|
8
|
+
* `./lock` and is reused verbatim by the transform/delete mutators.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: `PluginMirrorAxis` currently lives in `./doors`; its relocation into this
|
|
11
|
+
* shared module is deferred to the transform wave (avoids a doors edit + a
|
|
12
|
+
* double-export while `design.transform` is unwired).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Result of a CSG boolean op (`design.boolean.union/subtract/intersect`). Grounded
|
|
17
|
+
* in the engine `Boolean3dOperation.resultComponents { toCreate; toDelete }`:
|
|
18
|
+
* `created` are the result masses, `deleted` is every consumed input (for
|
|
19
|
+
* `subtract` this includes BOTH the target AND the tools). Errors throw (RPC
|
|
20
|
+
* rejects); no `Result<>` crosses the boundary.
|
|
21
|
+
*/
|
|
22
|
+
export const BooleanOutcome = z.object({
|
|
23
|
+
created: z.array(ComponentHandle),
|
|
24
|
+
deleted: z.array(ComponentHandle),
|
|
25
|
+
})
|
|
26
|
+
export type BooleanOutcome = z.infer<typeof BooleanOutcome>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Result of `design.edit.offsetSplit` (migrated from `tools.offset`). `createdIds`
|
|
30
|
+
* are the components the offset produced; `deletedIds` are those a split-style
|
|
31
|
+
* offset removed. `offsetValue` is the engine's POST-clamp / post-sign applied
|
|
32
|
+
* distance — the only way a caller learns the actually-applied clamped distance
|
|
33
|
+
* (the shipped `tools.offset` result dropped it).
|
|
34
|
+
*/
|
|
35
|
+
export const OffsetSplitOutcome = z.object({
|
|
36
|
+
createdIds: z.array(ComponentHandle),
|
|
37
|
+
deletedIds: z.array(ComponentHandle),
|
|
38
|
+
offsetValue: z.number(),
|
|
39
|
+
})
|
|
40
|
+
export type OffsetSplitOutcome = z.infer<typeof OffsetSplitOutcome>
|