@snaptrude/plugin-core 1.0.2-plainpoint-20261102.2 → 1.0.3
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 +17 -0
- package/CHANGELOG.md +6 -0
- package/api-manifest.json +35 -31
- package/dist/api/core/camera/index.d.ts +6 -16
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/comment/index.d.ts +3 -7
- package/dist/api/core/comment/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +21 -69
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/circle.d.ts +11 -31
- package/dist/api/core/geom/query/circle.d.ts.map +1 -1
- package/dist/api/core/geom/query/contour.d.ts +7 -19
- package/dist/api/core/geom/query/contour.d.ts.map +1 -1
- package/dist/api/core/geom/query/curve.d.ts +24 -72
- package/dist/api/core/geom/query/curve.d.ts.map +1 -1
- package/dist/api/core/geom/query/profile.d.ts +7 -19
- package/dist/api/core/geom/query/profile.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +12 -36
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/geom/update/curve.d.ts +5 -13
- package/dist/api/core/geom/update/curve.d.ts.map +1 -1
- package/dist/api/core/geom/update/profile.d.ts +12 -36
- package/dist/api/core/geom/update/profile.d.ts.map +1 -1
- package/dist/api/core/io/import/index.d.ts +3 -7
- package/dist/api/core/io/import/index.d.ts.map +1 -1
- package/dist/api/core/math/quat.d.ts +2 -2
- package/dist/api/core/math/quat.d.ts.map +1 -1
- package/dist/api/core/math/vec3.d.ts +15 -15
- package/dist/api/core/math/vec3.d.ts.map +1 -1
- package/dist/api/core/storeys/index.d.ts +0 -5
- package/dist/api/core/storeys/index.d.ts.map +1 -1
- package/dist/api/design/boolean/index.d.ts +4 -20
- package/dist/api/design/boolean/index.d.ts.map +1 -1
- package/dist/api/design/create/bulk-items.d.ts +20 -85
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +71 -134
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +6 -18
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +7 -14
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/dimensions.d.ts +4 -12
- package/dist/api/design/dimensions.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +37 -0
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/edit/index.d.ts +3 -7
- package/dist/api/design/edit/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +1 -5
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +1 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/lock.d.ts +0 -3
- package/dist/api/design/lock.d.ts.map +1 -1
- package/dist/api/design/opening-placement.d.ts +123 -0
- package/dist/api/design/opening-placement.d.ts.map +1 -0
- package/dist/api/design/transform/index.d.ts +8 -28
- package/dist/api/design/transform/index.d.ts.map +1 -1
- package/dist/api/design/windows/index.d.ts +23 -0
- package/dist/api/design/windows/index.d.ts.map +1 -1
- package/dist/api/entity/space.d.ts +6 -30
- package/dist/api/entity/space.d.ts.map +1 -1
- package/dist/api/entity/story.d.ts +0 -4
- package/dist/api/entity/story.d.ts.map +1 -1
- package/dist/api/presentation/drawings.d.ts +1 -1
- package/dist/api/presentation/views.d.ts +1 -5
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/handles.d.ts +0 -8
- package/dist/handles.d.ts.map +1 -1
- package/dist/index.cjs +2496 -2441
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2493 -2440
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/api/core/camera/index.ts +7 -9
- package/src/api/core/comment/index.ts +3 -3
- package/src/api/core/geom/create/index.ts +25 -25
- package/src/api/core/geom/query/circle.ts +11 -11
- package/src/api/core/geom/query/contour.ts +6 -7
- package/src/api/core/geom/query/curve.ts +25 -25
- package/src/api/core/geom/query/profile.ts +6 -7
- package/src/api/core/geom/update/contour.ts +11 -12
- package/src/api/core/geom/update/curve.ts +5 -5
- package/src/api/core/geom/update/profile.ts +11 -12
- package/src/api/core/io/import/index.ts +2 -3
- package/src/api/core/math/quat.ts +2 -2
- package/src/api/core/math/vec3.ts +16 -16
- package/src/api/core/storeys/index.ts +0 -5
- package/src/api/design/boolean/index.ts +2 -2
- package/src/api/design/create/bulk-items.ts +6 -8
- package/src/api/design/create/index.ts +58 -34
- package/src/api/design/create/opening-fields.ts +7 -7
- package/src/api/design/delete/index.ts +7 -14
- package/src/api/design/dimensions.ts +4 -5
- package/src/api/design/doors/index.ts +43 -0
- package/src/api/design/edit/index.ts +3 -3
- package/src/api/design/family.ts +1 -2
- package/src/api/design/index.ts +1 -0
- package/src/api/design/lock.ts +0 -6
- package/src/api/design/opening-placement.ts +79 -0
- package/src/api/design/transform/index.ts +7 -15
- package/src/api/design/windows/index.ts +29 -0
- package/src/api/entity/space.ts +4 -5
- package/src/api/entity/story.ts +0 -4
- package/src/api/presentation/views.ts +2 -7
- package/src/handles.ts +0 -11
- package/test/handles.test.mjs +0 -36
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
CurveHandle,
|
|
9
9
|
ProfileHandle,
|
|
10
10
|
Vec3Handle,
|
|
11
|
-
Vec3Input,
|
|
12
11
|
} from "../../../handles"
|
|
13
12
|
import { PluginGridStyleOptions } from "./grids"
|
|
14
13
|
import { PluginGraphicsLineStyleId } from "../../presentation/graphics"
|
|
@@ -131,7 +130,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
131
130
|
contour: ContourHandle,
|
|
132
131
|
height: number,
|
|
133
132
|
label?: string,
|
|
134
|
-
position?:
|
|
133
|
+
position?: Vec3Handle,
|
|
135
134
|
spaceType?: PluginSpaceType,
|
|
136
135
|
massType?: PluginMassType,
|
|
137
136
|
departmentId?: PluginDepartmentId,
|
|
@@ -166,7 +165,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
166
165
|
contour: ContourHandle,
|
|
167
166
|
height: number,
|
|
168
167
|
label?: string,
|
|
169
|
-
position?:
|
|
168
|
+
position?: Vec3Handle,
|
|
170
169
|
massType?: PluginMassType,
|
|
171
170
|
): PluginApiReturn<ComponentHandle>
|
|
172
171
|
|
|
@@ -289,7 +288,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
289
288
|
*/
|
|
290
289
|
public abstract floor(
|
|
291
290
|
...args:
|
|
292
|
-
| [contour: ContourHandle, thickness: number, position?:
|
|
291
|
+
| [contour: ContourHandle, thickness: number, position?: Vec3Handle]
|
|
293
292
|
| [contour: ContourHandle, options: PluginFamilyFloorOptions]
|
|
294
293
|
): PluginApiReturn<ComponentHandle[]>
|
|
295
294
|
|
|
@@ -423,10 +422,10 @@ export abstract class PluginDesignCreateApi {
|
|
|
423
422
|
public abstract column(
|
|
424
423
|
...args:
|
|
425
424
|
| [
|
|
426
|
-
position:
|
|
425
|
+
position: Vec3Handle,
|
|
427
426
|
crossSection: ContourHandle,
|
|
428
427
|
height: number,
|
|
429
|
-
directionUp?:
|
|
428
|
+
directionUp?: Vec3Handle,
|
|
430
429
|
]
|
|
431
430
|
| [axis: LineHandle, options: PluginFamilyPlacement]
|
|
432
431
|
): PluginApiReturn<ComponentHandle>
|
|
@@ -473,7 +472,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
473
472
|
*/
|
|
474
473
|
public abstract beam(
|
|
475
474
|
...args:
|
|
476
|
-
| [section: ContourHandle, length: number, direction?:
|
|
475
|
+
| [section: ContourHandle, length: number, direction?: Vec3Handle]
|
|
477
476
|
| [axis: LineHandle, options: PluginFamilyPlacement]
|
|
478
477
|
): PluginApiReturn<ComponentHandle>
|
|
479
478
|
|
|
@@ -497,10 +496,10 @@ export abstract class PluginDesignCreateApi {
|
|
|
497
496
|
* single undo entry. The storey must already exist
|
|
498
497
|
* (`core.storeys.create` first). Default: geometry-derived — a profile
|
|
499
498
|
* drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
|
|
500
|
-
* @param topProfiles -
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
499
|
+
* @param topProfiles - Optional top edge per curve of `profile` (same order):
|
|
500
|
+
* a {@linkcode PluginWallTopProfile} makes that wall raked / gabled; `null`
|
|
501
|
+
* or a missing entry keeps it flat at `height`. Straight curves only. Such
|
|
502
|
+
* walls are non-parametric (see {@linkcode PluginWallTopProfile}).
|
|
504
503
|
* @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
|
|
505
504
|
* @throws if the profile is empty, `wallType` names no wall type in the
|
|
506
505
|
* project, `storey` does not exist, `topProfiles` has more entries than the
|
|
@@ -514,6 +513,9 @@ export abstract class PluginDesignCreateApi {
|
|
|
514
513
|
* @examplePrompt Add walls with mitred corners along the path
|
|
515
514
|
* @examplePrompt Draw brick walls with plaster along this outline
|
|
516
515
|
* @examplePrompt Build the perimeter in exposed concrete walls
|
|
516
|
+
* @examplePrompt Create a raked wall that slopes from 3m to 5m
|
|
517
|
+
* @examplePrompt Build a gable end wall with the ridge in the middle
|
|
518
|
+
* @examplePrompt Draw a wall with a sloped top edge
|
|
517
519
|
*
|
|
518
520
|
* # Example
|
|
519
521
|
* ```ts
|
|
@@ -529,6 +531,13 @@ export abstract class PluginDesignCreateApi {
|
|
|
529
531
|
* const brickWalls = await snaptrude.design.create.walls(
|
|
530
532
|
* centerlines, 3, undefined, brick.label,
|
|
531
533
|
* )
|
|
534
|
+
* // …a raked wall (3m at the start, 5m at the end) on a single centerline:
|
|
535
|
+
* const run = await snaptrude.core.geom.create.profileFromCurves([
|
|
536
|
+
* await snaptrude.core.geom.create.line(await v.new(0, 0, 10), await v.new(8, 0, 10)),
|
|
537
|
+
* ])
|
|
538
|
+
* const [raked] = await snaptrude.design.create.walls(run, undefined, 0.2, undefined, undefined, [
|
|
539
|
+
* [{ along: 0, height: 3 }, { along: 1, height: 5 }],
|
|
540
|
+
* ])
|
|
532
541
|
* ```
|
|
533
542
|
*
|
|
534
543
|
* @performance For MORE THAN ONE run, call `design.create.wallRuns(items[])` — one
|
|
@@ -551,9 +560,8 @@ export abstract class PluginDesignCreateApi {
|
|
|
551
560
|
* item's profile chain, mitred at shared endpoints. Junctions resolve within a
|
|
552
561
|
* run, not between runs. Each item carries its own
|
|
553
562
|
* dimensions, `wallType` and `storey`, so a single call can build a whole
|
|
554
|
-
* floor plate or several storeys at once.
|
|
555
|
-
*
|
|
556
|
-
* names the item) and nothing is created. Validate-all-or-throw;
|
|
563
|
+
* floor plate or several storeys at once. Per-curve `topProfiles` make raked
|
|
564
|
+
* or gabled walls (see {@linkcode PluginWallTopProfile}). Validate-all-or-throw;
|
|
557
565
|
* one command.
|
|
558
566
|
*
|
|
559
567
|
* @param items - One {@linkcode PluginCreateWallRunItem} per run to create
|
|
@@ -574,6 +582,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
574
582
|
* @examplePrompt Bulk create wall runs from these centerlines
|
|
575
583
|
* @examplePrompt Create the walls for both storeys in a single undo step
|
|
576
584
|
* @examplePrompt Turn these polylines into 200mm brick walls together
|
|
585
|
+
* @examplePrompt Import these raked walls with their top profiles in one go
|
|
577
586
|
*
|
|
578
587
|
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
579
588
|
* entry. Always prefer this over calling `design.create.walls` in a loop: build the
|
|
@@ -594,6 +603,9 @@ export abstract class PluginDesignCreateApi {
|
|
|
594
603
|
* const [groundWalls, upperWalls] = await snaptrude.design.create.wallRuns([
|
|
595
604
|
* { profile: ground, height: 3, thickness: 0.2 },
|
|
596
605
|
* { profile: upper, height: 3, storey: 2 },
|
|
606
|
+
* // one gable wall: 3m at both ends, 5m ridge in the middle
|
|
607
|
+
* { profile: upper, thickness: 0.2, storey: 3,
|
|
608
|
+
* topProfiles: [[{ along: 0, height: 3 }, { along: 0.5, height: 5 }, { along: 1, height: 3 }]] },
|
|
597
609
|
* ])
|
|
598
610
|
* console.log(groundWalls.length, "walls on the ground floor")
|
|
599
611
|
* ```
|
|
@@ -637,7 +649,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
637
649
|
*/
|
|
638
650
|
public abstract staircase(
|
|
639
651
|
preset: PluginStaircasePreset,
|
|
640
|
-
position:
|
|
652
|
+
position: Vec3Handle,
|
|
641
653
|
label?: string,
|
|
642
654
|
structureId?: string,
|
|
643
655
|
level?: string,
|
|
@@ -728,7 +740,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
728
740
|
spacingY: number,
|
|
729
741
|
options?: {
|
|
730
742
|
angle?: number
|
|
731
|
-
center?:
|
|
743
|
+
center?: Vec3Handle
|
|
732
744
|
} & PluginGridStyleOptions,
|
|
733
745
|
): PluginApiReturn<ComponentHandle>
|
|
734
746
|
|
|
@@ -883,7 +895,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
883
895
|
*/
|
|
884
896
|
public abstract furniture(
|
|
885
897
|
catalogId: string,
|
|
886
|
-
position:
|
|
898
|
+
position: Vec3Handle,
|
|
887
899
|
options?: { label?: string; createNewSourceMesh?: boolean },
|
|
888
900
|
angleInDegrees?: number,
|
|
889
901
|
): PluginApiReturn<ComponentHandle>
|
|
@@ -996,14 +1008,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
996
1008
|
public abstract door(
|
|
997
1009
|
familyId: string,
|
|
998
1010
|
hostWall: ComponentHandle,
|
|
999
|
-
position:
|
|
1011
|
+
position: Vec3Handle,
|
|
1000
1012
|
options?: {
|
|
1001
1013
|
label?: string
|
|
1002
|
-
hinge?:
|
|
1014
|
+
hinge?: Vec3Handle
|
|
1003
1015
|
version?: number
|
|
1004
1016
|
values?: Record<string, number | string>
|
|
1005
1017
|
},
|
|
1006
|
-
facing?:
|
|
1018
|
+
facing?: Vec3Handle,
|
|
1007
1019
|
): PluginApiReturn<ComponentHandle>
|
|
1008
1020
|
|
|
1009
1021
|
/**
|
|
@@ -1035,6 +1047,12 @@ export abstract class PluginDesignCreateApi {
|
|
|
1035
1047
|
* @examplePrompt Put three doors on this wall in a single undo step
|
|
1036
1048
|
* @examplePrompt Add all the doors for this floor plan together
|
|
1037
1049
|
*
|
|
1050
|
+
* A width/height (top-level, or under the family's own keys in `values`) on a family that
|
|
1051
|
+
* takes its size from its Type while Custom Sizes is off is never dropped: the Type within
|
|
1052
|
+
* 25 mm is chosen, else Custom Sizes is turned on and that size is built, leaving the Type
|
|
1053
|
+
* label stale. `design.doors.checkPlacement` reports which as `sizing`; `customSizes: "No"`
|
|
1054
|
+
* with a size no Type matches is refused.
|
|
1055
|
+
*
|
|
1038
1056
|
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
1039
1057
|
* entry. Always prefer this over
|
|
1040
1058
|
* calling `design.create.door` in a loop: build the full `items[]` array first
|
|
@@ -1100,14 +1118,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
1100
1118
|
public abstract window(
|
|
1101
1119
|
familyId: string,
|
|
1102
1120
|
hostWall: ComponentHandle,
|
|
1103
|
-
position:
|
|
1121
|
+
position: Vec3Handle,
|
|
1104
1122
|
options?: {
|
|
1105
1123
|
label?: string
|
|
1106
|
-
hinge?:
|
|
1124
|
+
hinge?: Vec3Handle
|
|
1107
1125
|
version?: number
|
|
1108
1126
|
values?: Record<string, number | string>
|
|
1109
1127
|
},
|
|
1110
|
-
facing?:
|
|
1128
|
+
facing?: Vec3Handle,
|
|
1111
1129
|
): PluginApiReturn<ComponentHandle>
|
|
1112
1130
|
|
|
1113
1131
|
/**
|
|
@@ -1140,6 +1158,12 @@ export abstract class PluginDesignCreateApi {
|
|
|
1140
1158
|
* @examplePrompt Put four windows on this wall in a single undo step
|
|
1141
1159
|
* @examplePrompt Add all the windows with a 0.9m sill height together
|
|
1142
1160
|
*
|
|
1161
|
+
* A width/height (top-level, or under the family's own keys in `values`) on a family that
|
|
1162
|
+
* takes its size from its Type while Custom Sizes is off is never dropped: the Type within
|
|
1163
|
+
* 25 mm is chosen, else Custom Sizes is turned on and that size is built, leaving the Type
|
|
1164
|
+
* label stale. `design.windows.checkPlacement` reports which as `sizing`; `customSizes: "No"`
|
|
1165
|
+
* with a size no Type matches is refused.
|
|
1166
|
+
*
|
|
1143
1167
|
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
1144
1168
|
* entry. Always prefer this over
|
|
1145
1169
|
* calling `design.create.window` in a loop: build the full `items[]` array first
|
|
@@ -1434,7 +1458,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
1434
1458
|
*/
|
|
1435
1459
|
public abstract copy(
|
|
1436
1460
|
components: ComponentHandle[],
|
|
1437
|
-
displacement:
|
|
1461
|
+
displacement: Vec3Handle,
|
|
1438
1462
|
options?: { count?: number; mode?: PluginCopyMode },
|
|
1439
1463
|
): PluginApiReturn<ComponentHandle[]>
|
|
1440
1464
|
|
|
@@ -1657,7 +1681,7 @@ export const PluginDesignCreateSpaceArgs = z.object({
|
|
|
1657
1681
|
contour: ContourHandle,
|
|
1658
1682
|
height: z.number(),
|
|
1659
1683
|
label: z.string().optional(),
|
|
1660
|
-
position:
|
|
1684
|
+
position: Vec3Handle.optional(),
|
|
1661
1685
|
spaceType: PluginSpaceType.optional(),
|
|
1662
1686
|
massType: PluginMassType.optional(),
|
|
1663
1687
|
departmentId: PluginDepartmentId.optional(),
|
|
@@ -1688,7 +1712,7 @@ export const PluginDesignCreateMassArgs = z.object({
|
|
|
1688
1712
|
contour: ContourHandle,
|
|
1689
1713
|
height: z.number(),
|
|
1690
1714
|
label: z.string().optional(),
|
|
1691
|
-
position:
|
|
1715
|
+
position: Vec3Handle.optional(),
|
|
1692
1716
|
massType: PluginMassType.optional(),
|
|
1693
1717
|
})
|
|
1694
1718
|
export type PluginDesignCreateMassArgs = z.infer<
|
|
@@ -1755,7 +1779,7 @@ export type PluginDesignCreateSlabArgs = z.infer<
|
|
|
1755
1779
|
export const PluginDesignCreateFloorArgs = z.object({
|
|
1756
1780
|
contour: ContourHandle,
|
|
1757
1781
|
thickness: z.number(),
|
|
1758
|
-
position:
|
|
1782
|
+
position: Vec3Handle.optional(),
|
|
1759
1783
|
})
|
|
1760
1784
|
export type PluginDesignCreateFloorArgs = z.infer<
|
|
1761
1785
|
typeof PluginDesignCreateFloorArgs
|
|
@@ -1818,10 +1842,10 @@ export type PluginDesignCreateCeilingArgs = z.infer<
|
|
|
1818
1842
|
* | `directionUp` | {@linkcode Vec3Handle}? | Up axis (default world up) |
|
|
1819
1843
|
*/
|
|
1820
1844
|
export const PluginDesignCreateColumnArgs = z.object({
|
|
1821
|
-
position:
|
|
1845
|
+
position: Vec3Handle,
|
|
1822
1846
|
crossSection: ContourHandle,
|
|
1823
1847
|
height: z.number(),
|
|
1824
|
-
directionUp:
|
|
1848
|
+
directionUp: Vec3Handle.optional(),
|
|
1825
1849
|
})
|
|
1826
1850
|
export type PluginDesignCreateColumnArgs = z.infer<
|
|
1827
1851
|
typeof PluginDesignCreateColumnArgs
|
|
@@ -1843,7 +1867,7 @@ export type PluginDesignCreateColumnArgs = z.infer<
|
|
|
1843
1867
|
export const PluginDesignCreateBeamArgs = z.object({
|
|
1844
1868
|
section: ContourHandle,
|
|
1845
1869
|
length: z.number(),
|
|
1846
|
-
direction:
|
|
1870
|
+
direction: Vec3Handle.optional(),
|
|
1847
1871
|
})
|
|
1848
1872
|
export type PluginDesignCreateBeamArgs = z.infer<
|
|
1849
1873
|
typeof PluginDesignCreateBeamArgs
|
|
@@ -1898,7 +1922,7 @@ export type PluginDesignCreateWallsArgs = z.infer<
|
|
|
1898
1922
|
*/
|
|
1899
1923
|
export const PluginDesignCreateStaircaseArgs = z.object({
|
|
1900
1924
|
preset: PluginStaircasePreset,
|
|
1901
|
-
position:
|
|
1925
|
+
position: Vec3Handle,
|
|
1902
1926
|
label: z.string().optional(),
|
|
1903
1927
|
structureId: z.string().optional(),
|
|
1904
1928
|
level: z.string().optional(),
|
|
@@ -1925,7 +1949,7 @@ export type PluginDesignCreateStaircaseArgs = z.infer<
|
|
|
1925
1949
|
*/
|
|
1926
1950
|
export const PluginDesignCreateFurnitureArgs = z.object({
|
|
1927
1951
|
catalogId: z.string().min(1),
|
|
1928
|
-
position:
|
|
1952
|
+
position: Vec3Handle,
|
|
1929
1953
|
label: z.string().optional(),
|
|
1930
1954
|
createNewSourceMesh: z.boolean().optional(),
|
|
1931
1955
|
angleInDegrees: z.number().optional(),
|
|
@@ -2183,7 +2207,7 @@ export type PluginCopyMode = z.infer<typeof PluginCopyMode>
|
|
|
2183
2207
|
*/
|
|
2184
2208
|
export const PluginDesignCreateCopyArgs = z.object({
|
|
2185
2209
|
components: z.array(ComponentHandle).min(1),
|
|
2186
|
-
displacement:
|
|
2210
|
+
displacement: Vec3Handle,
|
|
2187
2211
|
count: z.number().int().positive().optional(),
|
|
2188
2212
|
mode: PluginCopyMode.optional(),
|
|
2189
2213
|
})
|
|
@@ -2216,7 +2240,7 @@ export const PluginCreateSpaceItem = z.object({
|
|
|
2216
2240
|
contour: ContourHandle,
|
|
2217
2241
|
height: z.number(),
|
|
2218
2242
|
label: z.string().optional(),
|
|
2219
|
-
position:
|
|
2243
|
+
position: Vec3Handle.optional(),
|
|
2220
2244
|
spaceType: PluginSpaceType.optional(),
|
|
2221
2245
|
massType: PluginMassType.optional(),
|
|
2222
2246
|
departmentId: PluginDepartmentId.optional(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
|
-
import { ComponentHandle,
|
|
2
|
+
import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The shared field bag every hosted opening (door / window) carries — used by
|
|
@@ -17,9 +17,9 @@ import { ComponentHandle, Vec3Input } from "../../../handles"
|
|
|
17
17
|
* | `version` | `number`? | Exact family version; newest known by default |
|
|
18
18
|
* | `values` | `Record<string, number \| string>`? | Authored instance parameters; numeric lengths use Snaptrude units |
|
|
19
19
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the opening |
|
|
20
|
-
* | `position` | {@linkcode
|
|
21
|
-
* | `facing` | {@linkcode
|
|
22
|
-
* | `hinge` | {@linkcode
|
|
20
|
+
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
21
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the opening swings open to (default engine-chosen) |
|
|
22
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires the recipe's hand parameter |
|
|
23
23
|
* | `label` | `string`? | Instance name (optional) |
|
|
24
24
|
* | `width` | `number`? | Sets the declared width parameter, not the opening's evaluated envelope |
|
|
25
25
|
* | `height` | `number`? | Sets the declared height parameter |
|
|
@@ -31,9 +31,9 @@ export const PluginOpeningBaseOptions = {
|
|
|
31
31
|
.record(z.string(), z.union([z.number().finite(), z.string()]))
|
|
32
32
|
.optional(),
|
|
33
33
|
hostWall: ComponentHandle,
|
|
34
|
-
position:
|
|
35
|
-
facing:
|
|
36
|
-
hinge:
|
|
34
|
+
position: Vec3Handle,
|
|
35
|
+
facing: Vec3Handle.optional(),
|
|
36
|
+
hinge: Vec3Handle.optional(),
|
|
37
37
|
label: z.string().optional(),
|
|
38
38
|
width: z.number().finite().positive().optional(),
|
|
39
39
|
height: z.number().finite().positive().optional(),
|
|
@@ -8,7 +8,7 @@ import { PluginDesignChangeResult } from "../lock"
|
|
|
8
8
|
*
|
|
9
9
|
* | Property | Type | Description |
|
|
10
10
|
* |---|---|---|
|
|
11
|
-
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to delete.
|
|
11
|
+
* | `components` | {@linkcode ComponentHandle}`[]` | Entities to delete. Unknown/forged handles reject the whole call (fail-fast). |
|
|
12
12
|
*
|
|
13
13
|
* `.min(1)` is deliberately stricter than the shipped `PluginDesignLockArgs`
|
|
14
14
|
* (which allows an empty array) — an empty delete is a caller error, not a no-op.
|
|
@@ -43,19 +43,12 @@ export abstract class PluginDesignDeleteApi {
|
|
|
43
43
|
* entry, exactly as the editor's Delete key does — see `design.dimensions`. They are
|
|
44
44
|
* NOT listed in `affected`, which reports component handles only.
|
|
45
45
|
*
|
|
46
|
-
* @param components - Entities to delete.
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* resolved and were skipped; `rejected`, handles the engine accepted but left standing
|
|
53
|
-
* (delete them again, one at a time, or report them). Deleted handles are **stale**
|
|
54
|
-
* afterwards: re-resolving one throws `HANDLE_STALE`.
|
|
55
|
-
* @throws `HANDLE_INVALID` when NONE of the supplied handles resolve (nothing is deleted);
|
|
56
|
-
* hosts before Oct 2026 reject the whole call when any handle is gone. `OPERATION_FAILED`
|
|
57
|
-
* when the parametric engine rejects the deletion — the batch is rolled back.
|
|
58
|
-
* `HANDLE_STALE` for a handle the caller held that has since been retired.
|
|
46
|
+
* @param components - Entities to delete. Unknown/forged handles reject the whole call (fail-fast).
|
|
47
|
+
* @returns The entities that were deleted, as {@linkcode ComponentHandle}`[]`
|
|
48
|
+
* (echoed host-side from the resolved+deleted set — the engine returns no ids).
|
|
49
|
+
* Deleted handles are **stale** afterwards: re-resolving one throws `HANDLE_INVALID`.
|
|
50
|
+
* @throws If any supplied handle is unknown/forged (`HANDLE_INVALID`) — the whole
|
|
51
|
+
* call rejects before anything is deleted (all-or-nothing resolution).
|
|
59
52
|
*
|
|
60
53
|
* @examplePrompt Delete the selected objects
|
|
61
54
|
* @examplePrompt Remove these walls from the model
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
DimensionHandle,
|
|
6
6
|
Vec3Components,
|
|
7
7
|
Vec3Handle,
|
|
8
|
-
Vec3Input,
|
|
9
8
|
} from "../../handles"
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -95,8 +94,8 @@ export abstract class PluginDesignDimensionsApi {
|
|
|
95
94
|
* ```
|
|
96
95
|
*/
|
|
97
96
|
public abstract create(
|
|
98
|
-
from:
|
|
99
|
-
to:
|
|
97
|
+
from: Vec3Handle,
|
|
98
|
+
to: Vec3Handle,
|
|
100
99
|
anchor: ComponentHandle,
|
|
101
100
|
options?: { anchorTo?: ComponentHandle; offset?: number },
|
|
102
101
|
): PluginApiReturn<DimensionHandle>
|
|
@@ -363,8 +362,8 @@ export type PluginDimensionsChangeResult = z.infer<
|
|
|
363
362
|
* TRANSPORT: positional args — validated host-side as this object.
|
|
364
363
|
*/
|
|
365
364
|
export const PluginDesignDimensionsCreateArgs = z.object({
|
|
366
|
-
from:
|
|
367
|
-
to:
|
|
365
|
+
from: Vec3Handle,
|
|
366
|
+
to: Vec3Handle,
|
|
368
367
|
anchor: ComponentHandle,
|
|
369
368
|
anchorTo: ComponentHandle.optional(),
|
|
370
369
|
offset: z.number().finite().optional(),
|
|
@@ -2,6 +2,10 @@ import * as z from "zod"
|
|
|
2
2
|
import { PluginApiReturn } from "../../../types"
|
|
3
3
|
import { ComponentHandle } from "../../../handles"
|
|
4
4
|
import { PluginDesignChangeResult } from "../lock"
|
|
5
|
+
import type {
|
|
6
|
+
PluginOpeningPlacementArgs,
|
|
7
|
+
PluginOpeningPlacementResult,
|
|
8
|
+
} from "../opening-placement"
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* `snaptrude.design.doors` — door-specific reads + edits. Creation lives at
|
|
@@ -22,6 +26,33 @@ import { PluginDesignChangeResult } from "../lock"
|
|
|
22
26
|
export abstract class PluginDesignDoorsApi {
|
|
23
27
|
constructor() {}
|
|
24
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Trial the native host fit and geometry rebuild, then restore the model without publishing commands.
|
|
31
|
+
* The first result uses the creation options; subsequent results use candidateWidths in input order.
|
|
32
|
+
* Widths are authored parameters, not physical envelopes or a guaranteed maximum width.
|
|
33
|
+
* No catalog save, history entry or model persistence occurs. Rerun after model edits.
|
|
34
|
+
* A failed fit leaves cut unverified. Family-host cuts are also unverified: their rebuild
|
|
35
|
+
* cannot supply a reversible, authoritative trial result. Material clearance checks evaluated
|
|
36
|
+
* parts against physical neighbours across hosts. The intended host uses native fit/cut checks.
|
|
37
|
+
* Creation repeats clearance immediately before placement; this report grants no later approval.
|
|
38
|
+
* Editing permission is required; locked hosts and an active opening tool reject.
|
|
39
|
+
* It does not say which room the door opens into: read `opensInto` from
|
|
40
|
+
* `design.validation.access()` after placement (see {@linkcode getSwingDirection}).
|
|
41
|
+
* A requested width/height on a family sized by its Type (Custom Sizes off) picks the Type
|
|
42
|
+
* within 25 mm, else turns Custom Sizes on; each result's `sizing` says which. Creation
|
|
43
|
+
* (`design.create.door(s)`) applies the same rule, so the size you pass is the size built.
|
|
44
|
+
* @param options Door creation options and up to 12 alternative widths; numeric lengths use SU.
|
|
45
|
+
* @returns Separate fit/cut/clearance evidence, evaluated bounds and explicit limitations.
|
|
46
|
+
* @examplePrompt Check which door widths fit this host without placing a door
|
|
47
|
+
* @example
|
|
48
|
+
* const result = await snaptrude.design.doors.checkPlacement({
|
|
49
|
+
* familyId, version, hostWall, position, width: 3.5, candidateWidths: [3, 2.5],
|
|
50
|
+
* })
|
|
51
|
+
*/
|
|
52
|
+
public abstract checkPlacement(
|
|
53
|
+
options: PluginOpeningPlacementArgs,
|
|
54
|
+
): PluginApiReturn<PluginOpeningPlacementResult>
|
|
55
|
+
|
|
25
56
|
/**
|
|
26
57
|
* Get the type name of a door — the label that identifies which kind of door
|
|
27
58
|
* the instance is, as shown in its properties.
|
|
@@ -163,6 +194,12 @@ export abstract class PluginDesignDoorsApi {
|
|
|
163
194
|
* Read the saved hand parameter. left means local -X; right means local +X.
|
|
164
195
|
* Returns null when the recipe does not declare that control.
|
|
165
196
|
*
|
|
197
|
+
* Hand is the hinge side, not the room the leaf swings into. For that, read
|
|
198
|
+
* `(await design.validation.access()).topology.rooms[].doors[].opensInto`: a
|
|
199
|
+
* converted room or `"outside"`. A door whose wall is not a room edge is listed
|
|
200
|
+
* in `topology.unresolvedDoors` instead. To make it open into the other room,
|
|
201
|
+
* call {@linkcode mirror} (axis `x`) and read access again.
|
|
202
|
+
*
|
|
166
203
|
* @param door The door to query
|
|
167
204
|
* @returns `'left'` / `'right'`, or `null` if indeterminate
|
|
168
205
|
*
|
|
@@ -170,12 +207,16 @@ export abstract class PluginDesignDoorsApi {
|
|
|
170
207
|
* @examplePrompt Is the selected door left-handed or right-handed?
|
|
171
208
|
* @examplePrompt Check the hinge side of this door
|
|
172
209
|
* @examplePrompt Does the entrance door open to the left or the right?
|
|
210
|
+
* @examplePrompt Which room does this door open into?
|
|
173
211
|
*
|
|
174
212
|
* # Example
|
|
175
213
|
* ```ts
|
|
176
214
|
* const [door] = await snaptrude.design.query.listDoors({ isSelected: true })
|
|
177
215
|
* const swing = await snaptrude.design.doors.getSwingDirection(door)
|
|
178
216
|
* if (swing) console.log("opens as a", swing, "hand door")
|
|
217
|
+
* // Which room it opens into
|
|
218
|
+
* const { topology } = await snaptrude.design.validation.access()
|
|
219
|
+
* const side = topology.rooms.flatMap((r) => r.doors).find((d) => d.door === door)?.opensInto
|
|
179
220
|
* ```
|
|
180
221
|
*/
|
|
181
222
|
public abstract getSwingDirection(
|
|
@@ -188,6 +229,8 @@ export abstract class PluginDesignDoorsApi {
|
|
|
188
229
|
* Axis y rejects. No mesh reflection occurs. Recipes use outputs.swingSide
|
|
189
230
|
* (1 or -1) for the adjoining room's floor ownership. A door between two
|
|
190
231
|
* room floors requires this output; a missing or invalid report rejects the cut.
|
|
232
|
+
* The same side decides `opensInto` in `design.validation.access()`; read it
|
|
233
|
+
* there to confirm which room the door now opens into.
|
|
191
234
|
*
|
|
192
235
|
* @param door The door to mirror
|
|
193
236
|
* @param axis Reflection axis (optional; default `'x'` — the swing-flip axis; `'z'` — the hinge-jamb axis)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../../types"
|
|
3
|
-
import { ComponentHandle,
|
|
3
|
+
import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
4
4
|
import { OffsetSplitOutcome } from "../shared"
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -41,7 +41,7 @@ export abstract class PluginDesignEditApi {
|
|
|
41
41
|
public abstract offsetSplit(
|
|
42
42
|
component: ComponentHandle,
|
|
43
43
|
offsetDistance: number,
|
|
44
|
-
options?: { profilePickPoint?:
|
|
44
|
+
options?: { profilePickPoint?: Vec3Handle },
|
|
45
45
|
): PluginApiReturn<OffsetSplitOutcome>
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -49,6 +49,6 @@ export abstract class PluginDesignEditApi {
|
|
|
49
49
|
export const PluginDesignOffsetSplitArgs = z.object({
|
|
50
50
|
component: ComponentHandle,
|
|
51
51
|
offsetDistance: z.number(),
|
|
52
|
-
profilePickPoint:
|
|
52
|
+
profilePickPoint: Vec3Handle.optional(),
|
|
53
53
|
})
|
|
54
54
|
export type PluginDesignOffsetSplitArgs = z.infer<typeof PluginDesignOffsetSplitArgs>
|
package/src/api/design/family.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
ComponentHandle,
|
|
6
6
|
Vec3Components,
|
|
7
7
|
Vec3Handle,
|
|
8
|
-
Vec3Input,
|
|
9
8
|
} from "../../handles"
|
|
10
9
|
import { NetworkFamilyContract } from "./networks"
|
|
11
10
|
|
|
@@ -1320,7 +1319,7 @@ export type PluginDesignFamilyDeleteArgs = z.infer<
|
|
|
1320
1319
|
export const PluginDesignFamilyPlaceArgs = z.object({
|
|
1321
1320
|
id: z.string().optional(),
|
|
1322
1321
|
version: z.number().int().positive().optional(),
|
|
1323
|
-
position: z.union([
|
|
1322
|
+
position: z.union([Vec3Handle, Vec3Components]).optional(),
|
|
1324
1323
|
rotation: z.number().optional(),
|
|
1325
1324
|
values: z.record(z.string(), z.union([z.number(), z.string()])).optional(),
|
|
1326
1325
|
storey: z.number().int().optional(),
|
package/src/api/design/index.ts
CHANGED
package/src/api/design/lock.ts
CHANGED
|
@@ -9,12 +9,6 @@ import { ComponentHandle } from "../../handles"
|
|
|
9
9
|
*/
|
|
10
10
|
export const PluginDesignChangeResult = z.object({
|
|
11
11
|
affected: z.array(ComponentHandle),
|
|
12
|
-
/** Derived BIM (walls/floors/slabs) the parametric engine removed with its host. Delete only. */
|
|
13
|
-
cascaded: z.array(ComponentHandle).optional(),
|
|
14
|
-
/** Handles that no longer resolved when the call ran and were skipped. Delete only. */
|
|
15
|
-
missing: z.array(ComponentHandle).optional(),
|
|
16
|
-
/** Handles the engine accepted but left standing; delete them again or report them. Delete only. */
|
|
17
|
-
rejected: z.array(ComponentHandle).optional(),
|
|
18
12
|
})
|
|
19
13
|
export type PluginDesignChangeResult = z.infer<typeof PluginDesignChangeResult>
|
|
20
14
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginOpeningBaseOptions } from "./create/opening-fields"
|
|
3
|
+
|
|
4
|
+
/** Creation options plus bounded alternative widths. Each trial starts from the same model. */
|
|
5
|
+
export const PluginOpeningPlacementArgs = z.object({
|
|
6
|
+
...PluginOpeningBaseOptions,
|
|
7
|
+
sillHeight: z.number().finite().nonnegative().optional(),
|
|
8
|
+
candidateWidths: z.array(z.number().finite().positive()).max(12).optional(),
|
|
9
|
+
})
|
|
10
|
+
export type PluginOpeningPlacementArgs = z.infer<
|
|
11
|
+
typeof PluginOpeningPlacementArgs
|
|
12
|
+
>
|
|
13
|
+
|
|
14
|
+
/** A failed fit leaves the cut unverified: no geometry trial was attempted. */
|
|
15
|
+
export const PluginOpeningPlacementCheck = z.object({
|
|
16
|
+
status: z.enum(["pass", "fail", "unverified"]),
|
|
17
|
+
reason: z.string(),
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const bounds = z.object({
|
|
21
|
+
min: z.object({ x: z.number().finite(), y: z.number().finite(), z: z.number().finite() }),
|
|
22
|
+
max: z.object({ x: z.number().finite(), y: z.number().finite(), z: z.number().finite() }),
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
/** Fit, cut and material clearance are independent checks, not an accessibility certificate. */
|
|
26
|
+
export const PluginOpeningPlacementResult = z.object({
|
|
27
|
+
units: z.literal("SU"),
|
|
28
|
+
results: z.array(
|
|
29
|
+
z.object({
|
|
30
|
+
requestedWidth: z.number().finite().positive().optional(),
|
|
31
|
+
requestedHeight: z.number().finite().positive().optional(),
|
|
32
|
+
/** Original parameter overrides. Evaluated bounds can differ from these values. */
|
|
33
|
+
requestedValues: z.record(z.string(), z.union([z.number().finite(), z.string()])).optional(),
|
|
34
|
+
/**
|
|
35
|
+
* Present when the family sizes itself from a Type unless Custom Sizes is on, and a width
|
|
36
|
+
* or height was requested. `type`: the Type within 25 mm was chosen (its label stays true).
|
|
37
|
+
* `custom`: none matched, so Custom Sizes was turned on and the requested size is built;
|
|
38
|
+
* `type` then names the Type that no longer describes it. Creation applies the same rule.
|
|
39
|
+
*/
|
|
40
|
+
sizing: z
|
|
41
|
+
.object({
|
|
42
|
+
mode: z.enum(["type", "custom"]),
|
|
43
|
+
typeKey: z.string(),
|
|
44
|
+
type: z.string(),
|
|
45
|
+
note: z.string(),
|
|
46
|
+
})
|
|
47
|
+
.optional(),
|
|
48
|
+
/** World-space bounds of evaluated material parts, never the opening proxy. */
|
|
49
|
+
physicalBounds: bounds.optional(),
|
|
50
|
+
/** Only present when the recipe declares semantic frame anatomy. */
|
|
51
|
+
frameBounds: bounds.optional(),
|
|
52
|
+
/** World enclosure of the authored cut envelope; not frame or clear passage width. */
|
|
53
|
+
roughOpeningBounds: bounds.optional(),
|
|
54
|
+
dimensions: z
|
|
55
|
+
.object({
|
|
56
|
+
width: z.number().finite().positive(),
|
|
57
|
+
height: z.number().finite().positive(),
|
|
58
|
+
thickness: z.number().finite().nonnegative(),
|
|
59
|
+
})
|
|
60
|
+
.optional(),
|
|
61
|
+
fit: PluginOpeningPlacementCheck,
|
|
62
|
+
cut: PluginOpeningPlacementCheck,
|
|
63
|
+
clearance: PluginOpeningPlacementCheck.extend({
|
|
64
|
+
candidatePairs: z.number().int().nonnegative(),
|
|
65
|
+
checkedPairs: z.number().int().nonnegative(),
|
|
66
|
+
obstructions: z.array(z.object({
|
|
67
|
+
entity: z.string(),
|
|
68
|
+
status: z.enum(["fail", "unverified"]),
|
|
69
|
+
reason: z.string(),
|
|
70
|
+
intersectionVolume: z.number().finite().nonnegative().optional(),
|
|
71
|
+
})),
|
|
72
|
+
}),
|
|
73
|
+
}),
|
|
74
|
+
),
|
|
75
|
+
limitations: z.array(z.string()),
|
|
76
|
+
})
|
|
77
|
+
export type PluginOpeningPlacementResult = z.infer<
|
|
78
|
+
typeof PluginOpeningPlacementResult
|
|
79
|
+
>
|