@snaptrude/plugin-core 1.0.3 → 1.0.4
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 +6 -0
- package/api-manifest.json +146 -2135
- package/dist/api/core/camera/index.d.ts +16 -6
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/comment/index.d.ts +7 -3
- package/dist/api/core/comment/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +69 -21
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/circle.d.ts +31 -11
- package/dist/api/core/geom/query/circle.d.ts.map +1 -1
- package/dist/api/core/geom/query/contour.d.ts +19 -7
- package/dist/api/core/geom/query/contour.d.ts.map +1 -1
- package/dist/api/core/geom/query/curve.d.ts +72 -24
- package/dist/api/core/geom/query/curve.d.ts.map +1 -1
- package/dist/api/core/geom/query/profile.d.ts +19 -7
- package/dist/api/core/geom/query/profile.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +36 -12
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/geom/update/curve.d.ts +13 -5
- package/dist/api/core/geom/update/curve.d.ts.map +1 -1
- package/dist/api/core/geom/update/profile.d.ts +36 -12
- package/dist/api/core/geom/update/profile.d.ts.map +1 -1
- package/dist/api/core/io/import/index.d.ts +7 -3
- 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 +5 -0
- package/dist/api/core/storeys/index.d.ts.map +1 -1
- package/dist/api/design/boolean/index.d.ts +20 -4
- package/dist/api/design/boolean/index.d.ts.map +1 -1
- package/dist/api/design/create/bulk-items.d.ts +84 -16
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +134 -59
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +18 -6
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +14 -7
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/dimensions.d.ts +12 -4
- package/dist/api/design/dimensions.d.ts.map +1 -1
- package/dist/api/design/edit/index.d.ts +7 -3
- package/dist/api/design/edit/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +5 -1
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/lock.d.ts +3 -0
- package/dist/api/design/lock.d.ts.map +1 -1
- package/dist/api/design/opening-placement.d.ts +15 -3
- package/dist/api/design/opening-placement.d.ts.map +1 -1
- package/dist/api/design/transform/index.d.ts +28 -8
- package/dist/api/design/transform/index.d.ts.map +1 -1
- package/dist/api/entity/space.d.ts +30 -6
- package/dist/api/entity/space.d.ts.map +1 -1
- package/dist/api/entity/story.d.ts +4 -0
- 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 +5 -1
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/handles.d.ts +8 -0
- package/dist/handles.d.ts.map +1 -1
- package/dist/index.cjs +96 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +95 -82
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/api/core/camera/index.ts +9 -7
- 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 +7 -6
- package/src/api/core/geom/query/curve.ts +25 -25
- package/src/api/core/geom/query/profile.ts +7 -6
- package/src/api/core/geom/update/contour.ts +12 -11
- package/src/api/core/geom/update/curve.ts +5 -5
- package/src/api/core/geom/update/profile.ts +12 -11
- package/src/api/core/io/import/index.ts +3 -2
- 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 +5 -0
- package/src/api/design/boolean/index.ts +2 -2
- package/src/api/design/create/bulk-items.ts +7 -2
- package/src/api/design/create/index.ts +34 -46
- package/src/api/design/create/opening-fields.ts +7 -7
- package/src/api/design/delete/index.ts +14 -7
- package/src/api/design/dimensions.ts +5 -4
- package/src/api/design/edit/index.ts +3 -3
- package/src/api/design/family.ts +2 -1
- package/src/api/design/lock.ts +6 -0
- package/src/api/design/transform/index.ts +15 -7
- package/src/api/entity/space.ts +5 -4
- package/src/api/entity/story.ts +4 -0
- package/src/api/presentation/views.ts +7 -2
- package/src/handles.ts +11 -0
- package/test/handles.test.mjs +36 -0
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
CurveHandle,
|
|
9
9
|
ProfileHandle,
|
|
10
10
|
Vec3Handle,
|
|
11
|
+
Vec3Input,
|
|
11
12
|
} from "../../../handles"
|
|
12
13
|
import { PluginGridStyleOptions } from "./grids"
|
|
13
14
|
import { PluginGraphicsLineStyleId } from "../../presentation/graphics"
|
|
@@ -130,7 +131,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
130
131
|
contour: ContourHandle,
|
|
131
132
|
height: number,
|
|
132
133
|
label?: string,
|
|
133
|
-
position?:
|
|
134
|
+
position?: Vec3Input,
|
|
134
135
|
spaceType?: PluginSpaceType,
|
|
135
136
|
massType?: PluginMassType,
|
|
136
137
|
departmentId?: PluginDepartmentId,
|
|
@@ -165,7 +166,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
165
166
|
contour: ContourHandle,
|
|
166
167
|
height: number,
|
|
167
168
|
label?: string,
|
|
168
|
-
position?:
|
|
169
|
+
position?: Vec3Input,
|
|
169
170
|
massType?: PluginMassType,
|
|
170
171
|
): PluginApiReturn<ComponentHandle>
|
|
171
172
|
|
|
@@ -288,7 +289,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
288
289
|
*/
|
|
289
290
|
public abstract floor(
|
|
290
291
|
...args:
|
|
291
|
-
| [contour: ContourHandle, thickness: number, position?:
|
|
292
|
+
| [contour: ContourHandle, thickness: number, position?: Vec3Input]
|
|
292
293
|
| [contour: ContourHandle, options: PluginFamilyFloorOptions]
|
|
293
294
|
): PluginApiReturn<ComponentHandle[]>
|
|
294
295
|
|
|
@@ -422,10 +423,10 @@ export abstract class PluginDesignCreateApi {
|
|
|
422
423
|
public abstract column(
|
|
423
424
|
...args:
|
|
424
425
|
| [
|
|
425
|
-
position:
|
|
426
|
+
position: Vec3Input,
|
|
426
427
|
crossSection: ContourHandle,
|
|
427
428
|
height: number,
|
|
428
|
-
directionUp?:
|
|
429
|
+
directionUp?: Vec3Input,
|
|
429
430
|
]
|
|
430
431
|
| [axis: LineHandle, options: PluginFamilyPlacement]
|
|
431
432
|
): PluginApiReturn<ComponentHandle>
|
|
@@ -472,7 +473,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
472
473
|
*/
|
|
473
474
|
public abstract beam(
|
|
474
475
|
...args:
|
|
475
|
-
| [section: ContourHandle, length: number, direction?:
|
|
476
|
+
| [section: ContourHandle, length: number, direction?: Vec3Input]
|
|
476
477
|
| [axis: LineHandle, options: PluginFamilyPlacement]
|
|
477
478
|
): PluginApiReturn<ComponentHandle>
|
|
478
479
|
|
|
@@ -496,10 +497,10 @@ export abstract class PluginDesignCreateApi {
|
|
|
496
497
|
* single undo entry. The storey must already exist
|
|
497
498
|
* (`core.storeys.create` first). Default: geometry-derived — a profile
|
|
498
499
|
* drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
|
|
499
|
-
* @param topProfiles -
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
500
|
+
* @param topProfiles - Top edge per curve of `profile` (same order). Current
|
|
501
|
+
* hosts build walls with one height: any non-null entry is refused with
|
|
502
|
+
* `PRECONDITION_FAILED` ("sloped or stepped tops are not supported") and
|
|
503
|
+
* nothing is created. Pass `null` entries or omit it.
|
|
503
504
|
* @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
|
|
504
505
|
* @throws if the profile is empty, `wallType` names no wall type in the
|
|
505
506
|
* project, `storey` does not exist, `topProfiles` has more entries than the
|
|
@@ -513,9 +514,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
513
514
|
* @examplePrompt Add walls with mitred corners along the path
|
|
514
515
|
* @examplePrompt Draw brick walls with plaster along this outline
|
|
515
516
|
* @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
|
|
519
517
|
*
|
|
520
518
|
* # Example
|
|
521
519
|
* ```ts
|
|
@@ -531,13 +529,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
531
529
|
* const brickWalls = await snaptrude.design.create.walls(
|
|
532
530
|
* centerlines, 3, undefined, brick.label,
|
|
533
531
|
* )
|
|
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
|
-
* ])
|
|
541
532
|
* ```
|
|
542
533
|
*
|
|
543
534
|
* @performance For MORE THAN ONE run, call `design.create.wallRuns(items[])` — one
|
|
@@ -560,8 +551,9 @@ export abstract class PluginDesignCreateApi {
|
|
|
560
551
|
* item's profile chain, mitred at shared endpoints. Junctions resolve within a
|
|
561
552
|
* run, not between runs. Each item carries its own
|
|
562
553
|
* dimensions, `wallType` and `storey`, so a single call can build a whole
|
|
563
|
-
* floor plate or several storeys at once.
|
|
564
|
-
*
|
|
554
|
+
* floor plate or several storeys at once. Walls have one height: a non-null
|
|
555
|
+
* `topProfiles` entry is refused with `PRECONDITION_FAILED` (`details.itemIndex`
|
|
556
|
+
* names the item) and nothing is created. Validate-all-or-throw;
|
|
565
557
|
* one command.
|
|
566
558
|
*
|
|
567
559
|
* @param items - One {@linkcode PluginCreateWallRunItem} per run to create
|
|
@@ -582,7 +574,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
582
574
|
* @examplePrompt Bulk create wall runs from these centerlines
|
|
583
575
|
* @examplePrompt Create the walls for both storeys in a single undo step
|
|
584
576
|
* @examplePrompt Turn these polylines into 200mm brick walls together
|
|
585
|
-
* @examplePrompt Import these raked walls with their top profiles in one go
|
|
586
577
|
*
|
|
587
578
|
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
588
579
|
* entry. Always prefer this over calling `design.create.walls` in a loop: build the
|
|
@@ -603,9 +594,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
603
594
|
* const [groundWalls, upperWalls] = await snaptrude.design.create.wallRuns([
|
|
604
595
|
* { profile: ground, height: 3, thickness: 0.2 },
|
|
605
596
|
* { 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 }]] },
|
|
609
597
|
* ])
|
|
610
598
|
* console.log(groundWalls.length, "walls on the ground floor")
|
|
611
599
|
* ```
|
|
@@ -649,7 +637,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
649
637
|
*/
|
|
650
638
|
public abstract staircase(
|
|
651
639
|
preset: PluginStaircasePreset,
|
|
652
|
-
position:
|
|
640
|
+
position: Vec3Input,
|
|
653
641
|
label?: string,
|
|
654
642
|
structureId?: string,
|
|
655
643
|
level?: string,
|
|
@@ -740,7 +728,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
740
728
|
spacingY: number,
|
|
741
729
|
options?: {
|
|
742
730
|
angle?: number
|
|
743
|
-
center?:
|
|
731
|
+
center?: Vec3Input
|
|
744
732
|
} & PluginGridStyleOptions,
|
|
745
733
|
): PluginApiReturn<ComponentHandle>
|
|
746
734
|
|
|
@@ -895,7 +883,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
895
883
|
*/
|
|
896
884
|
public abstract furniture(
|
|
897
885
|
catalogId: string,
|
|
898
|
-
position:
|
|
886
|
+
position: Vec3Input,
|
|
899
887
|
options?: { label?: string; createNewSourceMesh?: boolean },
|
|
900
888
|
angleInDegrees?: number,
|
|
901
889
|
): PluginApiReturn<ComponentHandle>
|
|
@@ -1008,14 +996,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
1008
996
|
public abstract door(
|
|
1009
997
|
familyId: string,
|
|
1010
998
|
hostWall: ComponentHandle,
|
|
1011
|
-
position:
|
|
999
|
+
position: Vec3Input,
|
|
1012
1000
|
options?: {
|
|
1013
1001
|
label?: string
|
|
1014
|
-
hinge?:
|
|
1002
|
+
hinge?: Vec3Input
|
|
1015
1003
|
version?: number
|
|
1016
1004
|
values?: Record<string, number | string>
|
|
1017
1005
|
},
|
|
1018
|
-
facing?:
|
|
1006
|
+
facing?: Vec3Input,
|
|
1019
1007
|
): PluginApiReturn<ComponentHandle>
|
|
1020
1008
|
|
|
1021
1009
|
/**
|
|
@@ -1118,14 +1106,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
1118
1106
|
public abstract window(
|
|
1119
1107
|
familyId: string,
|
|
1120
1108
|
hostWall: ComponentHandle,
|
|
1121
|
-
position:
|
|
1109
|
+
position: Vec3Input,
|
|
1122
1110
|
options?: {
|
|
1123
1111
|
label?: string
|
|
1124
|
-
hinge?:
|
|
1112
|
+
hinge?: Vec3Input
|
|
1125
1113
|
version?: number
|
|
1126
1114
|
values?: Record<string, number | string>
|
|
1127
1115
|
},
|
|
1128
|
-
facing?:
|
|
1116
|
+
facing?: Vec3Input,
|
|
1129
1117
|
): PluginApiReturn<ComponentHandle>
|
|
1130
1118
|
|
|
1131
1119
|
/**
|
|
@@ -1458,7 +1446,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
1458
1446
|
*/
|
|
1459
1447
|
public abstract copy(
|
|
1460
1448
|
components: ComponentHandle[],
|
|
1461
|
-
displacement:
|
|
1449
|
+
displacement: Vec3Input,
|
|
1462
1450
|
options?: { count?: number; mode?: PluginCopyMode },
|
|
1463
1451
|
): PluginApiReturn<ComponentHandle[]>
|
|
1464
1452
|
|
|
@@ -1681,7 +1669,7 @@ export const PluginDesignCreateSpaceArgs = z.object({
|
|
|
1681
1669
|
contour: ContourHandle,
|
|
1682
1670
|
height: z.number(),
|
|
1683
1671
|
label: z.string().optional(),
|
|
1684
|
-
position:
|
|
1672
|
+
position: Vec3Input.optional(),
|
|
1685
1673
|
spaceType: PluginSpaceType.optional(),
|
|
1686
1674
|
massType: PluginMassType.optional(),
|
|
1687
1675
|
departmentId: PluginDepartmentId.optional(),
|
|
@@ -1712,7 +1700,7 @@ export const PluginDesignCreateMassArgs = z.object({
|
|
|
1712
1700
|
contour: ContourHandle,
|
|
1713
1701
|
height: z.number(),
|
|
1714
1702
|
label: z.string().optional(),
|
|
1715
|
-
position:
|
|
1703
|
+
position: Vec3Input.optional(),
|
|
1716
1704
|
massType: PluginMassType.optional(),
|
|
1717
1705
|
})
|
|
1718
1706
|
export type PluginDesignCreateMassArgs = z.infer<
|
|
@@ -1779,7 +1767,7 @@ export type PluginDesignCreateSlabArgs = z.infer<
|
|
|
1779
1767
|
export const PluginDesignCreateFloorArgs = z.object({
|
|
1780
1768
|
contour: ContourHandle,
|
|
1781
1769
|
thickness: z.number(),
|
|
1782
|
-
position:
|
|
1770
|
+
position: Vec3Input.optional(),
|
|
1783
1771
|
})
|
|
1784
1772
|
export type PluginDesignCreateFloorArgs = z.infer<
|
|
1785
1773
|
typeof PluginDesignCreateFloorArgs
|
|
@@ -1842,10 +1830,10 @@ export type PluginDesignCreateCeilingArgs = z.infer<
|
|
|
1842
1830
|
* | `directionUp` | {@linkcode Vec3Handle}? | Up axis (default world up) |
|
|
1843
1831
|
*/
|
|
1844
1832
|
export const PluginDesignCreateColumnArgs = z.object({
|
|
1845
|
-
position:
|
|
1833
|
+
position: Vec3Input,
|
|
1846
1834
|
crossSection: ContourHandle,
|
|
1847
1835
|
height: z.number(),
|
|
1848
|
-
directionUp:
|
|
1836
|
+
directionUp: Vec3Input.optional(),
|
|
1849
1837
|
})
|
|
1850
1838
|
export type PluginDesignCreateColumnArgs = z.infer<
|
|
1851
1839
|
typeof PluginDesignCreateColumnArgs
|
|
@@ -1867,7 +1855,7 @@ export type PluginDesignCreateColumnArgs = z.infer<
|
|
|
1867
1855
|
export const PluginDesignCreateBeamArgs = z.object({
|
|
1868
1856
|
section: ContourHandle,
|
|
1869
1857
|
length: z.number(),
|
|
1870
|
-
direction:
|
|
1858
|
+
direction: Vec3Input.optional(),
|
|
1871
1859
|
})
|
|
1872
1860
|
export type PluginDesignCreateBeamArgs = z.infer<
|
|
1873
1861
|
typeof PluginDesignCreateBeamArgs
|
|
@@ -1922,7 +1910,7 @@ export type PluginDesignCreateWallsArgs = z.infer<
|
|
|
1922
1910
|
*/
|
|
1923
1911
|
export const PluginDesignCreateStaircaseArgs = z.object({
|
|
1924
1912
|
preset: PluginStaircasePreset,
|
|
1925
|
-
position:
|
|
1913
|
+
position: Vec3Input,
|
|
1926
1914
|
label: z.string().optional(),
|
|
1927
1915
|
structureId: z.string().optional(),
|
|
1928
1916
|
level: z.string().optional(),
|
|
@@ -1949,7 +1937,7 @@ export type PluginDesignCreateStaircaseArgs = z.infer<
|
|
|
1949
1937
|
*/
|
|
1950
1938
|
export const PluginDesignCreateFurnitureArgs = z.object({
|
|
1951
1939
|
catalogId: z.string().min(1),
|
|
1952
|
-
position:
|
|
1940
|
+
position: Vec3Input,
|
|
1953
1941
|
label: z.string().optional(),
|
|
1954
1942
|
createNewSourceMesh: z.boolean().optional(),
|
|
1955
1943
|
angleInDegrees: z.number().optional(),
|
|
@@ -2207,7 +2195,7 @@ export type PluginCopyMode = z.infer<typeof PluginCopyMode>
|
|
|
2207
2195
|
*/
|
|
2208
2196
|
export const PluginDesignCreateCopyArgs = z.object({
|
|
2209
2197
|
components: z.array(ComponentHandle).min(1),
|
|
2210
|
-
displacement:
|
|
2198
|
+
displacement: Vec3Input,
|
|
2211
2199
|
count: z.number().int().positive().optional(),
|
|
2212
2200
|
mode: PluginCopyMode.optional(),
|
|
2213
2201
|
})
|
|
@@ -2240,7 +2228,7 @@ export const PluginCreateSpaceItem = z.object({
|
|
|
2240
2228
|
contour: ContourHandle,
|
|
2241
2229
|
height: z.number(),
|
|
2242
2230
|
label: z.string().optional(),
|
|
2243
|
-
position:
|
|
2231
|
+
position: Vec3Input.optional(),
|
|
2244
2232
|
spaceType: PluginSpaceType.optional(),
|
|
2245
2233
|
massType: PluginMassType.optional(),
|
|
2246
2234
|
departmentId: PluginDepartmentId.optional(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
|
-
import { ComponentHandle,
|
|
2
|
+
import { ComponentHandle, Vec3Input } 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, Vec3Handle } 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 Vec3Input} | World point projected onto the wall (a vec3 handle or a plain `{ x, y, z }`) |
|
|
21
|
+
* | `facing` | {@linkcode Vec3Input}? | World point on the side of the wall the opening swings open to (default engine-chosen) |
|
|
22
|
+
* | `hinge` | {@linkcode Vec3Input}? | 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: Vec3Input,
|
|
35
|
+
facing: Vec3Input.optional(),
|
|
36
|
+
hinge: Vec3Input.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. Handles that no longer resolve are skipped and returned as `missing`; the call rejects only when none resolve. |
|
|
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,12 +43,19 @@ 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
|
-
*
|
|
46
|
+
* @param components - Entities to delete. A handle that no longer resolves (already
|
|
47
|
+
* removed by an earlier edit — a door deleted with its wall, a wall replaced by an
|
|
48
|
+
* opening's re-cut) is skipped, not fatal.
|
|
49
|
+
* @returns `{ affected, cascaded?, missing?, rejected? }`: the entities you asked to delete
|
|
50
|
+
* (echoed host-side — the engine returns no ids); `cascaded`, the derived walls/floors/slabs
|
|
51
|
+
* the parametric graph removed with a deleted space; `missing`, handles that no longer
|
|
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.
|
|
52
59
|
*
|
|
53
60
|
* @examplePrompt Delete the selected objects
|
|
54
61
|
* @examplePrompt Remove these walls from the model
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
DimensionHandle,
|
|
6
6
|
Vec3Components,
|
|
7
7
|
Vec3Handle,
|
|
8
|
+
Vec3Input,
|
|
8
9
|
} from "../../handles"
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -94,8 +95,8 @@ export abstract class PluginDesignDimensionsApi {
|
|
|
94
95
|
* ```
|
|
95
96
|
*/
|
|
96
97
|
public abstract create(
|
|
97
|
-
from:
|
|
98
|
-
to:
|
|
98
|
+
from: Vec3Input,
|
|
99
|
+
to: Vec3Input,
|
|
99
100
|
anchor: ComponentHandle,
|
|
100
101
|
options?: { anchorTo?: ComponentHandle; offset?: number },
|
|
101
102
|
): PluginApiReturn<DimensionHandle>
|
|
@@ -362,8 +363,8 @@ export type PluginDimensionsChangeResult = z.infer<
|
|
|
362
363
|
* TRANSPORT: positional args — validated host-side as this object.
|
|
363
364
|
*/
|
|
364
365
|
export const PluginDesignDimensionsCreateArgs = z.object({
|
|
365
|
-
from:
|
|
366
|
-
to:
|
|
366
|
+
from: Vec3Input,
|
|
367
|
+
to: Vec3Input,
|
|
367
368
|
anchor: ComponentHandle,
|
|
368
369
|
anchorTo: ComponentHandle.optional(),
|
|
369
370
|
offset: z.number().finite().optional(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../../types"
|
|
3
|
-
import { ComponentHandle,
|
|
3
|
+
import { ComponentHandle, Vec3Input } 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?: Vec3Input },
|
|
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: Vec3Input.optional(),
|
|
53
53
|
})
|
|
54
54
|
export type PluginDesignOffsetSplitArgs = z.infer<typeof PluginDesignOffsetSplitArgs>
|
package/src/api/design/family.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
ComponentHandle,
|
|
6
6
|
Vec3Components,
|
|
7
7
|
Vec3Handle,
|
|
8
|
+
Vec3Input,
|
|
8
9
|
} from "../../handles"
|
|
9
10
|
import { NetworkFamilyContract } from "./networks"
|
|
10
11
|
|
|
@@ -1319,7 +1320,7 @@ export type PluginDesignFamilyDeleteArgs = z.infer<
|
|
|
1319
1320
|
export const PluginDesignFamilyPlaceArgs = z.object({
|
|
1320
1321
|
id: z.string().optional(),
|
|
1321
1322
|
version: z.number().int().positive().optional(),
|
|
1322
|
-
position: z.union([
|
|
1323
|
+
position: z.union([Vec3Input, Vec3Components]).optional(),
|
|
1323
1324
|
rotation: z.number().optional(),
|
|
1324
1325
|
values: z.record(z.string(), z.union([z.number(), z.string()])).optional(),
|
|
1325
1326
|
storey: z.number().int().optional(),
|
package/src/api/design/lock.ts
CHANGED
|
@@ -9,6 +9,12 @@ 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(),
|
|
12
18
|
})
|
|
13
19
|
export type PluginDesignChangeResult = z.infer<typeof PluginDesignChangeResult>
|
|
14
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../../types"
|
|
3
|
-
import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
3
|
+
import { ComponentHandle, Vec3Handle, Vec3Input } from "../../../handles"
|
|
4
4
|
import { PluginDesignChangeResult } from "../lock"
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -22,9 +22,17 @@ export abstract class PluginDesignTransformApi {
|
|
|
22
22
|
* component's absolute position as the anchor). Undoable.
|
|
23
23
|
*
|
|
24
24
|
* @param components - Entities to move
|
|
25
|
-
* @param displacement - Relative translation as a {@linkcode Vec3Handle}
|
|
25
|
+
* @param displacement - Relative translation as a {@linkcode Vec3Handle}. A displacement
|
|
26
|
+
* shorter than 1e-6 is a no-op that succeeds (hosts before Oct 2026 throw
|
|
27
|
+
* `OPERATION_FAILED` "No movement occurred" instead, so skip the call when nothing moves).
|
|
26
28
|
* @param options - `is2D`, `trackParentChange`
|
|
27
29
|
* @returns {@linkcode PluginDesignChangeResult}
|
|
30
|
+
* @throws `OPERATION_FAILED` when the engine drops the whole move. A single connected
|
|
31
|
+
* parametric wall moves only across its own line: the vertical part and the part along
|
|
32
|
+
* the line are dropped. Move the whole connected run in one call to lift walls; to slide
|
|
33
|
+
* or lengthen one wall, delete it and create it again on the new line. Graph-bound walls
|
|
34
|
+
* made by Sketch-to-BIM refuse `move` outright (`TOPOLOGY_ERROR` / `ZERO_MOVEMENT`):
|
|
35
|
+
* adjust the room boundary that owns the wall instead.
|
|
28
36
|
*
|
|
29
37
|
* @examplePrompt Move the selected room 5 metres to the right
|
|
30
38
|
* @examplePrompt Shift these walls 3m along the x axis
|
|
@@ -43,7 +51,7 @@ export abstract class PluginDesignTransformApi {
|
|
|
43
51
|
*/
|
|
44
52
|
public abstract move(
|
|
45
53
|
components: ComponentHandle[],
|
|
46
|
-
displacement:
|
|
54
|
+
displacement: Vec3Input,
|
|
47
55
|
options?: { is2D?: boolean; trackParentChange?: boolean },
|
|
48
56
|
): PluginApiReturn<PluginDesignChangeResult>
|
|
49
57
|
|
|
@@ -81,7 +89,7 @@ export abstract class PluginDesignTransformApi {
|
|
|
81
89
|
public abstract rotate(
|
|
82
90
|
components: ComponentHandle[],
|
|
83
91
|
angleInDegrees: number,
|
|
84
|
-
options?: { axis?:
|
|
92
|
+
options?: { axis?: Vec3Input; pivot?: Vec3Input; is2D?: boolean },
|
|
85
93
|
): PluginApiReturn<PluginDesignChangeResult>
|
|
86
94
|
|
|
87
95
|
/**
|
|
@@ -205,7 +213,7 @@ export type PluginAlignEdge = z.infer<typeof PluginAlignEdge>
|
|
|
205
213
|
*/
|
|
206
214
|
export const PluginDesignMoveArgs = z.object({
|
|
207
215
|
components: z.array(ComponentHandle).min(1),
|
|
208
|
-
displacement:
|
|
216
|
+
displacement: Vec3Input,
|
|
209
217
|
is2D: z.boolean().optional(),
|
|
210
218
|
trackParentChange: z.boolean().optional(),
|
|
211
219
|
})
|
|
@@ -217,9 +225,9 @@ export type PluginDesignMoveArgs = z.infer<typeof PluginDesignMoveArgs>
|
|
|
217
225
|
export const PluginDesignRotateArgs = z.object({
|
|
218
226
|
components: z.array(ComponentHandle).min(1),
|
|
219
227
|
angleInDegrees: z.number(),
|
|
220
|
-
axis:
|
|
228
|
+
axis: Vec3Input.optional(),
|
|
221
229
|
is2D: z.boolean().optional(),
|
|
222
|
-
pivot:
|
|
230
|
+
pivot: Vec3Input.optional(),
|
|
223
231
|
})
|
|
224
232
|
export type PluginDesignRotateArgs = z.infer<typeof PluginDesignRotateArgs>
|
|
225
233
|
|
package/src/api/entity/space.ts
CHANGED
|
@@ -6,6 +6,7 @@ import * as z from "zod"
|
|
|
6
6
|
import {
|
|
7
7
|
ProfileHandle,
|
|
8
8
|
Vec3Handle,
|
|
9
|
+
Vec3Input,
|
|
9
10
|
Vec3Components,
|
|
10
11
|
QuatComponents,
|
|
11
12
|
CurveHandle,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
* | `dimensions` | `{ width, height, depth }` | Box dimensions in Babylon units |
|
|
22
23
|
*/
|
|
23
24
|
export const PluginSpaceCreateRectangularArgs = z.object({
|
|
24
|
-
position:
|
|
25
|
+
position: Vec3Input,
|
|
25
26
|
dimensions: z.object({
|
|
26
27
|
width: z.number(),
|
|
27
28
|
height: z.number(),
|
|
@@ -62,7 +63,7 @@ export const PluginSpaceCreateFromProfileArgs = z.object({
|
|
|
62
63
|
profile: ProfileHandle,
|
|
63
64
|
innerProfiles: z.array(ProfileHandle).optional(),
|
|
64
65
|
extrudeHeight: z.number(),
|
|
65
|
-
position:
|
|
66
|
+
position: Vec3Input,
|
|
66
67
|
})
|
|
67
68
|
|
|
68
69
|
export type PluginSpaceCreateFromProfileArgs = z.infer<
|
|
@@ -466,7 +467,7 @@ export type PluginSpaceUpdateResult = z.infer<typeof PluginSpaceUpdateResult>
|
|
|
466
467
|
export const PluginSpaceBulkCreateItem = z.discriminatedUnion("kind", [
|
|
467
468
|
z.object({
|
|
468
469
|
kind: z.literal("rectangular"),
|
|
469
|
-
position:
|
|
470
|
+
position: Vec3Input,
|
|
470
471
|
dimensions: z.object({
|
|
471
472
|
width: z.number(),
|
|
472
473
|
height: z.number(),
|
|
@@ -482,7 +483,7 @@ export const PluginSpaceBulkCreateItem = z.discriminatedUnion("kind", [
|
|
|
482
483
|
profile: ProfileHandle,
|
|
483
484
|
innerProfiles: z.array(ProfileHandle).optional(),
|
|
484
485
|
extrudeHeight: z.number(),
|
|
485
|
-
position:
|
|
486
|
+
position: Vec3Input,
|
|
486
487
|
room_type: z.string().optional(),
|
|
487
488
|
spaceType: PluginSpaceType.optional(),
|
|
488
489
|
massType: PluginMassType.optional(),
|
package/src/api/entity/story.ts
CHANGED
|
@@ -88,6 +88,10 @@ export abstract class PluginStoryApi {
|
|
|
88
88
|
* @returns A {@linkcode PluginStoryCreateResult} with `storyId` and `storyValue`
|
|
89
89
|
* @throws If a story with the given value already exists or creation fails
|
|
90
90
|
*
|
|
91
|
+
* Storeys are added at the ends of the stack only: a value above the top also creates
|
|
92
|
+
* every storey in between (returning only the requested one), and a value inside a gap
|
|
93
|
+
* is refused.
|
|
94
|
+
*
|
|
91
95
|
* @examplePrompt Add a third floor to the building
|
|
92
96
|
* @examplePrompt Create a new storey above the second floor
|
|
93
97
|
* @examplePrompt Add a basement level to this project
|
|
@@ -522,8 +522,13 @@ export type PluginPresentationViewsCreateArgs = z.infer<
|
|
|
522
522
|
typeof PluginPresentationViewsCreateArgs
|
|
523
523
|
>
|
|
524
524
|
|
|
525
|
-
/**
|
|
526
|
-
|
|
525
|
+
/**
|
|
526
|
+
* Result of {@linkcode PluginPresentationViewsApi.create} — the saved view, plus `framed`:
|
|
527
|
+
* whether the view was framed on the given elements or bounds (always `false` without `frame`).
|
|
528
|
+
*/
|
|
529
|
+
export const PluginPresentationViewsCreateResult = PluginPresentationView.extend({
|
|
530
|
+
framed: z.boolean().optional(),
|
|
531
|
+
})
|
|
527
532
|
export type PluginPresentationViewsCreateResult = z.infer<
|
|
528
533
|
typeof PluginPresentationViewsCreateResult
|
|
529
534
|
>
|
package/src/handles.ts
CHANGED
|
@@ -288,6 +288,17 @@ export const EdgeHandle = handleSchema("edge")
|
|
|
288
288
|
export const HalfEdgeHandle = handleSchema("halfedge")
|
|
289
289
|
export const VertexHandle = handleSchema("vertex")
|
|
290
290
|
export const Vec3Components = z.object({ x: z.number(), y: z.number(), z: z.number() })
|
|
291
|
+
/**
|
|
292
|
+
* A vec3 ARGUMENT: a {@linkcode Vec3Handle} in any inbound form, or a plain finite
|
|
293
|
+
* `{ x, y, z }` point. Geometry reads return plain points, and callers pass them straight
|
|
294
|
+
* back where a vec3 is expected; the host resolves the point as a vector. Returns stay
|
|
295
|
+
* {@linkcode Vec3Handle}. Explicitly typed to keep handles.d.ts inside its size budget.
|
|
296
|
+
*/
|
|
297
|
+
export type Vec3Input = Handle<"vec3"> | Vec3Components
|
|
298
|
+
export const Vec3Input: z.ZodUnion<readonly [typeof Vec3Handle, typeof Vec3Components]> = z.union(
|
|
299
|
+
[Vec3Handle, Vec3Components],
|
|
300
|
+
{ error: 'expected a "vec3" handle or a plain { x, y, z } point' }
|
|
301
|
+
)
|
|
291
302
|
export const QuatComponents = z.object({
|
|
292
303
|
x: z.number(),
|
|
293
304
|
y: z.number(),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Node built-in test runner suite for the handle schemas.
|
|
2
|
+
// Imports the BUILT package (dist) — run `pnpm build` first.
|
|
3
|
+
import test from "node:test"
|
|
4
|
+
import assert from "node:assert/strict"
|
|
5
|
+
import { Vec3Handle, Vec3Input, Handle, PluginDesignMoveArgs } from "../dist/index.js"
|
|
6
|
+
|
|
7
|
+
test("a vec3 handle parses in every inbound form, and only as a handle", () => {
|
|
8
|
+
for (const v of ["vec3_abc", new Handle("vec3_abc"), { __h: "vec3_abc" }, { id: "vec3_abc" }]) {
|
|
9
|
+
const out = Vec3Handle.parse(v)
|
|
10
|
+
assert.ok(out instanceof Handle)
|
|
11
|
+
assert.equal(out.id, "vec3_abc")
|
|
12
|
+
}
|
|
13
|
+
assert.equal(Vec3Handle.safeParse({ x: 1, y: 2, z: 3 }).success, false)
|
|
14
|
+
const bad = Vec3Handle.safeParse("profile_1")
|
|
15
|
+
assert.equal(bad.success, false)
|
|
16
|
+
assert.match(bad.error.issues[0].message, /expected a "vec3" handle/)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test("Vec3Input takes a handle or a plain { x, y, z } point", () => {
|
|
20
|
+
// Geometry reads return plain points; agents pass them back where a vec3 belongs.
|
|
21
|
+
const point = { x: 1, y: 2.5, z: -3 }
|
|
22
|
+
assert.deepEqual(Vec3Input.parse(point), point)
|
|
23
|
+
assert.ok(Vec3Input.parse("vec3_abc") instanceof Handle)
|
|
24
|
+
const args = PluginDesignMoveArgs.parse({ components: ["wl_1"], displacement: { x: 0, y: 0, z: 10 } })
|
|
25
|
+
assert.deepEqual(args.displacement, { x: 0, y: 0, z: 10 })
|
|
26
|
+
const handled = PluginDesignMoveArgs.parse({ components: ["wl_1"], displacement: "vec3_d" })
|
|
27
|
+
assert.equal(handled.displacement.id, "vec3_d")
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("Vec3Input still rejects non-points and wrong handles, with one message", () => {
|
|
31
|
+
for (const v of [{ x: 1, y: 2 }, { x: 1, y: Number.NaN, z: 3 }, { x: "1", y: 2, z: 3 }, "profile_1", null, 42]) {
|
|
32
|
+
const r = Vec3Input.safeParse(v)
|
|
33
|
+
assert.equal(r.success, false, JSON.stringify(v))
|
|
34
|
+
assert.equal(r.error.issues[0].message, 'expected a "vec3" handle or a plain { x, y, z } point')
|
|
35
|
+
}
|
|
36
|
+
})
|