@snaptrude/plugin-core 0.0.0-dev-20260911064951 → 0.0.0-surfaces-20260921090636
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 +0 -25
- package/api-manifest.json +151 -12
- package/dist/api/core/geom/create/index.d.ts +918 -93
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/brep.d.ts +50 -0
- package/dist/api/core/geom/query/brep.d.ts.map +1 -1
- package/dist/api/core/geom/query/curve.d.ts +58 -35
- package/dist/api/core/geom/query/curve.d.ts.map +1 -1
- package/dist/api/core/geom/query/edge.d.ts +2 -2
- package/dist/api/core/geom/query/face.d.ts +105 -0
- package/dist/api/core/geom/query/face.d.ts.map +1 -1
- package/dist/api/core/geom/update/curve.d.ts +5 -5
- package/dist/api/core/geom/update/profile.d.ts +1 -1
- package/dist/api/core/io/import/index.d.ts +1 -3
- package/dist/api/core/io/import/index.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +22 -310
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +0 -4
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +13 -20
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +0 -5
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/query/geometry/index.d.ts +27 -1
- package/dist/api/design/query/geometry/index.d.ts.map +1 -1
- package/dist/api/design/query/index.d.ts +47 -0
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/query/spaces.d.ts +5 -5
- package/dist/api/design/update/index.d.ts +87 -0
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/entity/referenceLine.d.ts +2 -2
- package/dist/api/entity/referenceLine.d.ts.map +1 -1
- package/dist/api/entity/space.d.ts +5 -4
- package/dist/api/entity/space.d.ts.map +1 -1
- package/dist/api/entity/story.d.ts +4 -4
- package/dist/api/presentation/annotate.d.ts +2 -2
- package/dist/api/presentation/shapes.d.ts +2 -2
- package/dist/api/program/site.d.ts +4 -4
- package/dist/api/program/spreadsheet.d.ts +4 -4
- package/dist/handles.d.ts +12 -22
- package/dist/handles.d.ts.map +1 -1
- package/dist/index.cjs +2773 -2445
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2726 -2422
- package/dist/index.js.map +1 -1
- package/dist/massParameters.d.ts +280 -0
- package/dist/massParameters.d.ts.map +1 -0
- package/dist/massParameters.ops.d.ts +135 -0
- package/dist/massParameters.ops.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/api/core/geom/create/index.ts +1011 -94
- package/src/api/core/geom/query/brep.ts +51 -0
- package/src/api/core/geom/query/curve.ts +25 -2
- package/src/api/core/geom/query/edge.ts +2 -2
- package/src/api/core/geom/query/face.ts +109 -4
- package/src/api/core/io/import/index.ts +3 -11
- package/src/api/design/create/index.ts +38 -335
- package/src/api/design/delete/index.ts +0 -4
- package/src/api/design/doors/index.ts +13 -20
- package/src/api/design/index.ts +0 -5
- package/src/api/design/query/geometry/index.ts +29 -0
- package/src/api/design/query/index.ts +50 -0
- package/src/api/design/update/index.ts +94 -0
- package/src/handles.ts +15 -27
- package/src/index.ts +2 -0
- package/src/massParameters.ops.ts +243 -0
- package/src/massParameters.ts +418 -0
- package/test/massParameters.test.mjs +936 -0
- package/dist/api/design/create/bulk-items.d.ts +0 -185
- package/dist/api/design/create/bulk-items.d.ts.map +0 -1
- package/dist/api/design/create/opening-fields.d.ts +0 -37
- package/dist/api/design/create/opening-fields.d.ts.map +0 -1
- package/dist/api/design/dimensions.d.ts +0 -427
- package/dist/api/design/dimensions.d.ts.map +0 -1
- package/src/api/design/create/bulk-items.ts +0 -186
- package/src/api/design/create/opening-fields.ts +0 -37
- package/src/api/design/dimensions.ts +0 -453
|
@@ -18,21 +18,12 @@ import {
|
|
|
18
18
|
PluginBuildableEnvelopeVerticalCap,
|
|
19
19
|
PluginBuildableEnvelopeCreateResult,
|
|
20
20
|
} from "../../entity/buildableEnvelope"
|
|
21
|
-
import { PluginOpeningBaseOptions } from "./opening-fields"
|
|
22
|
-
import type {
|
|
23
|
-
PluginCreateDoorItem,
|
|
24
|
-
PluginCreateFloorItem,
|
|
25
|
-
PluginCreateFurnitureItem,
|
|
26
|
-
PluginCreateWallRunItem,
|
|
27
|
-
PluginCreateWindowItem,
|
|
28
|
-
} from "./bulk-items"
|
|
29
21
|
|
|
30
22
|
/**
|
|
31
23
|
* `design.create.*` — author new scene-committed BIM entities.
|
|
32
24
|
*
|
|
33
25
|
* Every creator takes geometry handles + scalars and returns a
|
|
34
|
-
* {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators
|
|
35
|
-
* `wallRuns` returns one `ComponentHandle[]` per run) — the
|
|
26
|
+
* {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators) — the
|
|
36
27
|
* `Component.id` of the created entity, resolvable across the rest of the
|
|
37
28
|
* `design.*` surface. Creation is an undoable host call; it **throws** on failure
|
|
38
29
|
* (no `Result` wrapper — consistent with `core.geom.create.*`).
|
|
@@ -243,10 +234,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
243
234
|
* const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
|
|
244
235
|
* const floor = await snaptrude.design.create.floor(contour, 0.1)
|
|
245
236
|
* ```
|
|
246
|
-
*
|
|
247
|
-
* @performance For MORE THAN ONE floor, call `design.create.floors(items[])` — one
|
|
248
|
-
* host round-trip and ONE undo entry for the whole batch. Looping this single-floor
|
|
249
|
-
* creator is N round-trips and N undo entries.
|
|
250
237
|
*/
|
|
251
238
|
public abstract floor(
|
|
252
239
|
contour: ContourHandle,
|
|
@@ -254,46 +241,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
254
241
|
position?: Vec3Handle,
|
|
255
242
|
): PluginApiReturn<ComponentHandle>
|
|
256
243
|
|
|
257
|
-
/**
|
|
258
|
-
* Create **many floors** in one undoable operation (bulk plural of
|
|
259
|
-
* {@linkcode floor}). Each item extrudes its own footprint contour (outer
|
|
260
|
-
* profile + holes) upward by its own `thickness`, at its own optional
|
|
261
|
-
* position offset. Validate-all-or-throw; one command.
|
|
262
|
-
*
|
|
263
|
-
* @param items - One {@linkcode PluginCreateFloorItem} per floor to create
|
|
264
|
-
* (≥1, ≤1000)
|
|
265
|
-
* @returns the created floors as {@linkcode ComponentHandle}`[]`, in input order
|
|
266
|
-
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
267
|
-
* 1000 items, a non-positive thickness) or a contour is degenerate;
|
|
268
|
-
* `HANDLE_INVALID` if a `contour` or `position` handle is unknown or
|
|
269
|
-
* released; `OPERATION_FAILED` if extrusion fails (nothing is created —
|
|
270
|
-
* `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
|
|
271
|
-
* plugin may not write.
|
|
272
|
-
*
|
|
273
|
-
* @examplePrompt Create floors for all these room outlines at once
|
|
274
|
-
* @examplePrompt Add a floor to every space in one operation
|
|
275
|
-
* @examplePrompt Bulk create the floor plates for this building
|
|
276
|
-
* @examplePrompt Lay 100mm floors across these five footprints in one undo step
|
|
277
|
-
* @examplePrompt Create the ground and first floor slabs together
|
|
278
|
-
*
|
|
279
|
-
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
280
|
-
* entry. Always prefer this over calling `design.create.floor` in a loop: build the
|
|
281
|
-
* full `items[]` array first (all contours and offsets up front), then make one call.
|
|
282
|
-
*
|
|
283
|
-
* # Example
|
|
284
|
-
* ```ts
|
|
285
|
-
* const rect = await snaptrude.core.geom.create.profileRect(5, 4)
|
|
286
|
-
* const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
|
|
287
|
-
* const [ground, upper] = await snaptrude.design.create.floors([
|
|
288
|
-
* { contour, thickness: 0.1 },
|
|
289
|
-
* { contour, thickness: 0.1, position: await snaptrude.core.math.vec3.new(0, 3, 0) },
|
|
290
|
-
* ])
|
|
291
|
-
* ```
|
|
292
|
-
*/
|
|
293
|
-
public abstract floors(
|
|
294
|
-
items: PluginCreateFloorItem[],
|
|
295
|
-
): PluginApiReturn<ComponentHandle[]>
|
|
296
|
-
|
|
297
244
|
/**
|
|
298
245
|
* Create a **roof** by extruding a footprint contour by `thickness`. Created
|
|
299
246
|
* flat (extruded downward); pitch/slope is a separate post-creation edit.
|
|
@@ -475,10 +422,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
475
422
|
* centerlines, 3, undefined, brick.label,
|
|
476
423
|
* )
|
|
477
424
|
* ```
|
|
478
|
-
*
|
|
479
|
-
* @performance For MORE THAN ONE run, call `design.create.wallRuns(items[])` — one
|
|
480
|
-
* host round-trip and ONE undo entry for every run in the batch. Looping this
|
|
481
|
-
* single-run creator is N round-trips and N undo entries.
|
|
482
425
|
*/
|
|
483
426
|
public abstract walls(
|
|
484
427
|
profile: ProfileHandle,
|
|
@@ -488,60 +431,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
488
431
|
storey?: number,
|
|
489
432
|
): PluginApiReturn<ComponentHandle[]>
|
|
490
433
|
|
|
491
|
-
/**
|
|
492
|
-
* Create **many wall runs** in one undoable operation (bulk plural of
|
|
493
|
-
* {@linkcode walls}). Each item is one full run — a wall per curve in that
|
|
494
|
-
* item's profile chain, mitred at shared endpoints. Junctions resolve within a
|
|
495
|
-
* run, not between runs. Each item carries its own
|
|
496
|
-
* dimensions, `wallType` and `storey`, so a single call can build a whole
|
|
497
|
-
* floor plate or several storeys at once. Validate-all-or-throw; one command.
|
|
498
|
-
*
|
|
499
|
-
* @param items - One {@linkcode PluginCreateWallRunItem} per run to create
|
|
500
|
-
* (≥1, ≤1000)
|
|
501
|
-
* @returns one {@linkcode ComponentHandle}`[]` per item, in input order —
|
|
502
|
-
* each inner array holding that run's walls in profile-curve order
|
|
503
|
-
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
504
|
-
* 1000 items, a non-positive height or thickness, a zero-length curve);
|
|
505
|
-
* `HANDLE_INVALID` if a `profile` handle is unknown or released;
|
|
506
|
-
* `PRECONDITION_FAILED` if a profile has no curves, `wallType` names no
|
|
507
|
-
* wall type in the project, or `storey` does not exist;
|
|
508
|
-
* `OPERATION_FAILED` if wall creation fails (nothing is created —
|
|
509
|
-
* `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
|
|
510
|
-
* plugin may not write.
|
|
511
|
-
*
|
|
512
|
-
* @examplePrompt Draw all the walls of this floor plan at once
|
|
513
|
-
* @examplePrompt Build every room's perimeter in one operation
|
|
514
|
-
* @examplePrompt Bulk create wall runs from these centerlines
|
|
515
|
-
* @examplePrompt Create the walls for both storeys in a single undo step
|
|
516
|
-
* @examplePrompt Turn these polylines into 200mm brick walls together
|
|
517
|
-
*
|
|
518
|
-
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
519
|
-
* entry. Always prefer this over calling `design.create.walls` in a loop: build the
|
|
520
|
-
* full `items[]` array first (all profiles up front), then make one call.
|
|
521
|
-
*
|
|
522
|
-
* # Example
|
|
523
|
-
* ```ts
|
|
524
|
-
* const v = snaptrude.core.math.vec3
|
|
525
|
-
* const ground = await snaptrude.core.geom.create.profileFromLinePoints([
|
|
526
|
-
* await v.new(0, 0, 0),
|
|
527
|
-
* await v.new(8, 0, 0),
|
|
528
|
-
* await v.new(8, 0, 6),
|
|
529
|
-
* ])
|
|
530
|
-
* const upper = await snaptrude.core.geom.create.profileFromLinePoints([
|
|
531
|
-
* await v.new(0, 0, 0),
|
|
532
|
-
* await v.new(8, 0, 0),
|
|
533
|
-
* ])
|
|
534
|
-
* const [groundWalls, upperWalls] = await snaptrude.design.create.wallRuns([
|
|
535
|
-
* { profile: ground, height: 3, thickness: 0.2 },
|
|
536
|
-
* { profile: upper, height: 3, storey: 2 },
|
|
537
|
-
* ])
|
|
538
|
-
* console.log(groundWalls.length, "walls on the ground floor")
|
|
539
|
-
* ```
|
|
540
|
-
*/
|
|
541
|
-
public abstract wallRuns(
|
|
542
|
-
items: PluginCreateWallRunItem[],
|
|
543
|
-
): PluginApiReturn<ComponentHandle[][]>
|
|
544
|
-
|
|
545
434
|
/**
|
|
546
435
|
* Create a **staircase** from a parametric preset, placed at a point.
|
|
547
436
|
*
|
|
@@ -646,19 +535,15 @@ export abstract class PluginDesignCreateApi {
|
|
|
646
535
|
* `position.y` (the same surface-flush contract as interactive drag-drop) —
|
|
647
536
|
* pass the floor/storey elevation to stand furniture on it; never add half
|
|
648
537
|
* the item's height yourself.
|
|
649
|
-
* @param options - Optional placement options: `label` — instance name
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* source-mesh persistence: a catalog source is recorded exactly once, by the
|
|
653
|
-
* first placement that brings it in, and this flag cannot skip that record.
|
|
538
|
+
* @param options - Optional placement options: `label` — instance name
|
|
539
|
+
* (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
|
|
540
|
+
* source-mesh creation command (default `true`)
|
|
654
541
|
* @param angleInDegrees - Optional signed rotation about the vertical axis, in
|
|
655
542
|
* degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
|
|
656
543
|
* Applied at creation time so it is part of the placement's single undo entry.
|
|
657
544
|
* Default: the item's own (unrotated) orientation.
|
|
658
545
|
* @returns the {@linkcode ComponentHandle} of the placed furniture instance
|
|
659
|
-
* @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
|
|
660
|
-
* `PRECONDITION_FAILED` (`details.engineCode: "TOOL_ACTIVE"`) while the interactive
|
|
661
|
-
* furniture tool is active — finish or cancel it first
|
|
546
|
+
* @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
|
|
662
547
|
*
|
|
663
548
|
* @examplePrompt Place a chair from the library at this spot
|
|
664
549
|
* @examplePrompt Add a sofa from the furniture catalog to the living room
|
|
@@ -682,10 +567,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
682
567
|
* 90,
|
|
683
568
|
* )
|
|
684
569
|
* ```
|
|
685
|
-
*
|
|
686
|
-
* @performance For MORE THAN ONE item, call `design.create.furnitureItems(items[])` —
|
|
687
|
-
* one host round-trip and ONE undo entry, and a catalog source shared by several
|
|
688
|
-
* items is fetched once. Looping this single-item creator is N round-trips.
|
|
689
570
|
*/
|
|
690
571
|
public abstract furniture(
|
|
691
572
|
catalogId: string,
|
|
@@ -694,52 +575,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
694
575
|
angleInDegrees?: number,
|
|
695
576
|
): PluginApiReturn<ComponentHandle>
|
|
696
577
|
|
|
697
|
-
/**
|
|
698
|
-
* Place **many furniture items** in one undoable operation (bulk plural of
|
|
699
|
-
* {@linkcode furniture}). Each item names a catalog id and an absolute world
|
|
700
|
-
* position (`position.y` is the REST elevation — the same grounding contract
|
|
701
|
-
* as the singular creator), with optional label and rotation. A catalog
|
|
702
|
-
* source shared by several items is fetched and recorded once for the whole
|
|
703
|
-
* batch, so the host — not the caller — owns source persistence (there is no
|
|
704
|
-
* per-item `createNewSourceMesh`). Validate-all-or-throw; one command.
|
|
705
|
-
*
|
|
706
|
-
* @param items - One {@linkcode PluginCreateFurnitureItem} per instance to
|
|
707
|
-
* place (≥1, ≤1000)
|
|
708
|
-
* @returns the placed instances as {@linkcode ComponentHandle}`[]`, in input order
|
|
709
|
-
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
710
|
-
* 1000 items); `HANDLE_INVALID` if a `position` handle is unknown or
|
|
711
|
-
* released; `PRECONDITION_FAILED` if a catalog id is unknown, a furniture
|
|
712
|
-
* tool is active, or a parametric group is active (exit it first, or place
|
|
713
|
-
* items one at a time with `furniture`); `OPERATION_FAILED` if a source
|
|
714
|
-
* mesh fails to load or placement fails (nothing is created —
|
|
715
|
-
* `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the plugin may not write.
|
|
716
|
-
*
|
|
717
|
-
* @examplePrompt Place all the desks for this office at once
|
|
718
|
-
* @examplePrompt Furnish every bedroom in one operation
|
|
719
|
-
* @examplePrompt Bulk place these chairs around the table
|
|
720
|
-
* @examplePrompt Add the whole furniture layout in a single undo step
|
|
721
|
-
* @examplePrompt Drop twenty copies of this chair at these positions
|
|
722
|
-
*
|
|
723
|
-
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
724
|
-
* entry, and each distinct catalog source loads once. Always prefer this over
|
|
725
|
-
* calling `design.create.furniture` in a loop: build the full `items[]` array
|
|
726
|
-
* first (all positions and angles up front), then make one call.
|
|
727
|
-
*
|
|
728
|
-
* # Example
|
|
729
|
-
* ```ts
|
|
730
|
-
* const v = snaptrude.core.math.vec3
|
|
731
|
-
* const [chair] = await snaptrude.design.furniture.listCatalog()
|
|
732
|
-
* const placed = await snaptrude.design.create.furnitureItems([
|
|
733
|
-
* { catalogId: chair.id, position: await v.new(3, 0, 5), label: "Chair-01" },
|
|
734
|
-
* { catalogId: chair.id, position: await v.new(4, 0, 5), angleInDegrees: 90 },
|
|
735
|
-
* { catalogId: chair.id, position: await v.new(5, 0, 5), angleInDegrees: 180 },
|
|
736
|
-
* ])
|
|
737
|
-
* ```
|
|
738
|
-
*/
|
|
739
|
-
public abstract furnitureItems(
|
|
740
|
-
items: PluginCreateFurnitureItem[],
|
|
741
|
-
): PluginApiReturn<ComponentHandle[]>
|
|
742
|
-
|
|
743
578
|
/**
|
|
744
579
|
* Place a **door** from the catalog into a host wall.
|
|
745
580
|
*
|
|
@@ -753,15 +588,12 @@ export abstract class PluginDesignCreateApi {
|
|
|
753
588
|
* @param catalogId - Library id: team `_id` or general `fullName`
|
|
754
589
|
* @param hostWall - The wall to host the door
|
|
755
590
|
* @param position - World point projected onto the wall to locate the opening
|
|
756
|
-
* @param options - Optional placement options: `label` — instance name
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
* Any point clearly on that side works (e.g. the room's center). Default:
|
|
763
|
-
* the engine picks a side (nondeterministic when `position` sits on the
|
|
764
|
-
* wall centerline).
|
|
591
|
+
* @param options - Optional placement options: `label` — instance name
|
|
592
|
+
* @param facing - World point selecting which side of the wall the door faces
|
|
593
|
+
* (the room it opens into) — the same convention as approaching the wall
|
|
594
|
+
* from that side with the cursor in the interactive tool. Any point clearly
|
|
595
|
+
* on that side works (e.g. the room's center). Default: the engine picks a
|
|
596
|
+
* side (nondeterministic when `position` sits on the wall centerline).
|
|
765
597
|
* @returns the {@linkcode ComponentHandle} of the placed door
|
|
766
598
|
* @throws if the catalog id is unknown, the host is not a wall, the source
|
|
767
599
|
* mesh fails to load, or the projected point falls **outside** the host wall
|
|
@@ -772,7 +604,6 @@ export abstract class PluginDesignCreateApi {
|
|
|
772
604
|
* @examplePrompt Insert the entrance door into this wall
|
|
773
605
|
* @examplePrompt Add a door to the wall and call it Entry-01
|
|
774
606
|
* @examplePrompt Add a door that opens into the living room
|
|
775
|
-
* @examplePrompt Put a door here hinged on the north jamb
|
|
776
607
|
*
|
|
777
608
|
* # Example
|
|
778
609
|
* ```ts
|
|
@@ -792,83 +623,16 @@ export abstract class PluginDesignCreateApi {
|
|
|
792
623
|
* undefined,
|
|
793
624
|
* await snaptrude.core.math.vec3.new(3, 0, 9),
|
|
794
625
|
* )
|
|
795
|
-
* // …and hinged on the jamb nearest a point (here the +x end of the opening):
|
|
796
|
-
* const hingedRight = await snaptrude.design.create.door(
|
|
797
|
-
* entry.id,
|
|
798
|
-
* wall,
|
|
799
|
-
* await snaptrude.core.math.vec3.new(3, 0, 5),
|
|
800
|
-
* { hinge: await snaptrude.core.math.vec3.new(3.5, 0, 5) },
|
|
801
|
-
* await snaptrude.core.math.vec3.new(3, 0, 9),
|
|
802
|
-
* )
|
|
803
626
|
* ```
|
|
804
|
-
*
|
|
805
|
-
* @performance For MORE THAN ONE door, call `design.create.doors(items[])` — one host
|
|
806
|
-
* round-trip and ONE undo entry, with each host wall re-cut once per opening inside
|
|
807
|
-
* that single call. Looping this single-door creator is N round-trips.
|
|
808
627
|
*/
|
|
809
628
|
public abstract door(
|
|
810
629
|
catalogId: string,
|
|
811
630
|
hostWall: ComponentHandle,
|
|
812
631
|
position: Vec3Handle,
|
|
813
|
-
options?: { label?: string
|
|
632
|
+
options?: { label?: string },
|
|
814
633
|
facing?: Vec3Handle,
|
|
815
634
|
): PluginApiReturn<ComponentHandle>
|
|
816
635
|
|
|
817
|
-
/**
|
|
818
|
-
* Place **many doors** into host walls in one undoable operation (bulk plural
|
|
819
|
-
* of {@linkcode door}). Each item carries its own catalog id, host wall,
|
|
820
|
-
* world position, and optional `facing`, `label`, `width` and `height` — the
|
|
821
|
-
* same fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}.
|
|
822
|
-
* Validate-all-or-throw; one command.
|
|
823
|
-
*
|
|
824
|
-
* As with the singular creator, placing an opening **re-cuts its host wall**:
|
|
825
|
-
* the wall you passed as `hostWall` stops resolving once the call returns.
|
|
826
|
-
* Several items MAY name the same original wall handle in one call — the host
|
|
827
|
-
* chains the re-cuts internally — but after the call recover the surviving
|
|
828
|
-
* wall with `design.query.getHost(opening)`, never by reusing the handle you
|
|
829
|
-
* passed in.
|
|
830
|
-
*
|
|
831
|
-
* @param items - One {@linkcode PluginCreateDoorItem} per door to place
|
|
832
|
-
* (≥1, ≤1000)
|
|
833
|
-
* @returns the placed doors as {@linkcode ComponentHandle}`[]`, in input order
|
|
834
|
-
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
835
|
-
* 1000 items, unknown fields, a non-positive `width`/`height`);
|
|
836
|
-
* `HANDLE_INVALID` if a `position`, `facing` or `hinge` handle is unknown
|
|
837
|
-
* or released; `PRECONDITION_FAILED` if a catalog id is unknown, a `hostWall`
|
|
838
|
-
* is not a wall / is locked / is not in the active proposal, the projected
|
|
839
|
-
* point falls outside its host wall, or a door tool is active;
|
|
840
|
-
* `OPERATION_FAILED` if a source mesh fails to load or placement fails
|
|
841
|
-
* (nothing is created — `details.itemIndex` is the failing item);
|
|
842
|
-
* `METHOD_NOT_PERMITTED` if the plugin may not write.
|
|
843
|
-
*
|
|
844
|
-
* @examplePrompt Add doors to all of these walls at once
|
|
845
|
-
* @examplePrompt Place a door in every room in one operation
|
|
846
|
-
* @examplePrompt Bulk add the entrance doors from this schedule
|
|
847
|
-
* @examplePrompt Put three doors on this wall in a single undo step
|
|
848
|
-
* @examplePrompt Add all the doors for this floor plan together
|
|
849
|
-
*
|
|
850
|
-
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
851
|
-
* entry, and each distinct catalog source loads once. Always prefer this over
|
|
852
|
-
* calling `design.create.door` in a loop: build the full `items[]` array first
|
|
853
|
-
* (all host walls and points up front), then make one call.
|
|
854
|
-
*
|
|
855
|
-
* # Example
|
|
856
|
-
* ```ts
|
|
857
|
-
* const v = snaptrude.core.math.vec3
|
|
858
|
-
* const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
|
|
859
|
-
* const [entry] = await snaptrude.design.doors.listCatalog()
|
|
860
|
-
* const [front, side] = await snaptrude.design.create.doors([
|
|
861
|
-
* { catalogId: entry.id, hostWall: wall, position: await v.new(2, 0, 5), label: "D-01" },
|
|
862
|
-
* { catalogId: entry.id, hostWall: wall, position: await v.new(6, 0, 5), width: 1.2 },
|
|
863
|
-
* ])
|
|
864
|
-
* // `wall` was re-cut twice and no longer resolves — ask the opening for its host:
|
|
865
|
-
* const currentWall = await snaptrude.design.query.getHost(front)
|
|
866
|
-
* ```
|
|
867
|
-
*/
|
|
868
|
-
public abstract doors(
|
|
869
|
-
items: PluginCreateDoorItem[],
|
|
870
|
-
): PluginApiReturn<ComponentHandle[]>
|
|
871
|
-
|
|
872
636
|
/**
|
|
873
637
|
* Place a **window** from the catalog into a host wall.
|
|
874
638
|
*
|
|
@@ -882,14 +646,11 @@ export abstract class PluginDesignCreateApi {
|
|
|
882
646
|
* @param catalogId - Library id: team `_id` or general `fullName`
|
|
883
647
|
* @param hostWall - The wall to host the window
|
|
884
648
|
* @param position - World point projected onto the wall to locate the opening
|
|
885
|
-
* @param options - Optional placement options: `label` — instance name
|
|
886
|
-
*
|
|
887
|
-
*
|
|
888
|
-
*
|
|
889
|
-
*
|
|
890
|
-
* (matters for asymmetric windows, e.g. casement swing) — same convention
|
|
891
|
-
* as {@linkcode PluginDesignCreateApi.door}. Default: the engine picks a
|
|
892
|
-
* side (nondeterministic when `position` sits on the centerline).
|
|
649
|
+
* @param options - Optional placement options: `label` — instance name
|
|
650
|
+
* @param facing - World point selecting which side of the wall the window
|
|
651
|
+
* faces (matters for asymmetric windows, e.g. casement swing) — same
|
|
652
|
+
* convention as {@linkcode PluginDesignCreateApi.door}. Default: the engine
|
|
653
|
+
* picks a side (nondeterministic when `position` sits on the centerline).
|
|
893
654
|
* @returns the {@linkcode ComponentHandle} of the placed window
|
|
894
655
|
* @throws if the catalog id is unknown, the host is not a wall, the source
|
|
895
656
|
* mesh fails to load, or the projected point falls **outside** the host wall
|
|
@@ -912,75 +673,15 @@ export abstract class PluginDesignCreateApi {
|
|
|
912
673
|
* { label: "Win-01" },
|
|
913
674
|
* )
|
|
914
675
|
* ```
|
|
915
|
-
*
|
|
916
|
-
* @performance For MORE THAN ONE window, call `design.create.windows(items[])` — one
|
|
917
|
-
* host round-trip and ONE undo entry, with each host wall re-cut once per opening
|
|
918
|
-
* inside that single call. Looping this single-window creator is N round-trips.
|
|
919
676
|
*/
|
|
920
677
|
public abstract window(
|
|
921
678
|
catalogId: string,
|
|
922
679
|
hostWall: ComponentHandle,
|
|
923
680
|
position: Vec3Handle,
|
|
924
|
-
options?: { label?: string
|
|
681
|
+
options?: { label?: string },
|
|
925
682
|
facing?: Vec3Handle,
|
|
926
683
|
): PluginApiReturn<ComponentHandle>
|
|
927
684
|
|
|
928
|
-
/**
|
|
929
|
-
* Place **many windows** into host walls in one undoable operation (bulk
|
|
930
|
-
* plural of {@linkcode window}). Each item carries its own catalog id, host
|
|
931
|
-
* wall, world position, and optional `facing`, `label`, `width`, `height` and
|
|
932
|
-
* `sillHeight` — the same fields as a `"window"`
|
|
933
|
-
* {@linkcode PluginDesignCreateOpeningOptions}. `sillHeight` is measured from
|
|
934
|
-
* the host wall base to the BOTTOM of the window. Validate-all-or-throw; one
|
|
935
|
-
* command.
|
|
936
|
-
*
|
|
937
|
-
* As with the singular creator, placing an opening **re-cuts its host wall**:
|
|
938
|
-
* the wall you passed as `hostWall` stops resolving once the call returns.
|
|
939
|
-
* Several items MAY name the same original wall handle in one call — the host
|
|
940
|
-
* chains the re-cuts internally — but after the call recover the surviving
|
|
941
|
-
* wall with `design.query.getHost(opening)`, never by reusing the handle you
|
|
942
|
-
* passed in.
|
|
943
|
-
*
|
|
944
|
-
* @param items - One {@linkcode PluginCreateWindowItem} per window to place
|
|
945
|
-
* (≥1, ≤1000)
|
|
946
|
-
* @returns the placed windows as {@linkcode ComponentHandle}`[]`, in input order
|
|
947
|
-
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
948
|
-
* 1000 items, unknown fields, a non-positive `width`/`height`, a negative
|
|
949
|
-
* `sillHeight`); `HANDLE_INVALID` if a `position`, `facing` or `hinge`
|
|
950
|
-
* handle is unknown or released; `PRECONDITION_FAILED` if a catalog id is unknown, a
|
|
951
|
-
* `hostWall` is not a wall / is locked / is not in the active proposal, the
|
|
952
|
-
* projected point falls outside its host wall, or a window tool is active;
|
|
953
|
-
* `OPERATION_FAILED` if a source mesh fails to load or placement fails
|
|
954
|
-
* (nothing is created — `details.itemIndex` is the failing item);
|
|
955
|
-
* `METHOD_NOT_PERMITTED` if the plugin may not write.
|
|
956
|
-
*
|
|
957
|
-
* @examplePrompt Add windows along this whole facade at once
|
|
958
|
-
* @examplePrompt Place a window in every bedroom in one operation
|
|
959
|
-
* @examplePrompt Bulk add the windows from this schedule
|
|
960
|
-
* @examplePrompt Put four windows on this wall in a single undo step
|
|
961
|
-
* @examplePrompt Add all the windows with a 0.9m sill height together
|
|
962
|
-
*
|
|
963
|
-
* @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
|
|
964
|
-
* entry, and each distinct catalog source loads once. Always prefer this over
|
|
965
|
-
* calling `design.create.window` in a loop: build the full `items[]` array first
|
|
966
|
-
* (all host walls and points up front), then make one call.
|
|
967
|
-
*
|
|
968
|
-
* # Example
|
|
969
|
-
* ```ts
|
|
970
|
-
* const v = snaptrude.core.math.vec3
|
|
971
|
-
* const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
|
|
972
|
-
* const [casement] = await snaptrude.design.windows.listCatalog()
|
|
973
|
-
* const placed = await snaptrude.design.create.windows([
|
|
974
|
-
* { catalogId: casement.id, hostWall: wall, position: await v.new(2, 0, 5), sillHeight: 0.9 },
|
|
975
|
-
* { catalogId: casement.id, hostWall: wall, position: await v.new(5, 0, 5), sillHeight: 0.9 },
|
|
976
|
-
* ])
|
|
977
|
-
* const currentWall = await snaptrude.design.query.getHost(placed[0])
|
|
978
|
-
* ```
|
|
979
|
-
*/
|
|
980
|
-
public abstract windows(
|
|
981
|
-
items: PluginCreateWindowItem[],
|
|
982
|
-
): PluginApiReturn<ComponentHandle[]>
|
|
983
|
-
|
|
984
685
|
/**
|
|
985
686
|
* Place a catalog **door or window** into a host wall with optional size overrides.
|
|
986
687
|
*
|
|
@@ -990,7 +691,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
990
691
|
* its center. Placement is asynchronous and committed as one undoable creation.
|
|
991
692
|
*
|
|
992
693
|
* @param options - Opening kind, catalog and host references, placement, and
|
|
993
|
-
* optional facing
|
|
694
|
+
* optional facing, label, and dimensions
|
|
994
695
|
* @returns the {@linkcode ComponentHandle} of the placed door or window
|
|
995
696
|
* @throws if the options are invalid, the catalog id is unknown, the host is
|
|
996
697
|
* not a wall, loading fails, or the opening cannot be placed on the host
|
|
@@ -998,9 +699,8 @@ export abstract class PluginDesignCreateApi {
|
|
|
998
699
|
* @examplePrompt Add a 1m wide door to this wall here
|
|
999
700
|
* @examplePrompt Place a window with a 0.9m sill height on the selected wall
|
|
1000
701
|
*
|
|
1001
|
-
* @performance Single-opening creator — use it for one hosted opening.
|
|
1002
|
-
*
|
|
1003
|
-
* the same per-item fields, one host round-trip, ONE undo entry.
|
|
702
|
+
* @performance Single-opening creator — use it for one hosted opening. A plural
|
|
703
|
+
* API is intentionally unavailable until host placement can be atomic.
|
|
1004
704
|
*
|
|
1005
705
|
* # Example
|
|
1006
706
|
* ```ts
|
|
@@ -1562,7 +1262,7 @@ export type PluginDesignCreateStaircaseArgs = z.infer<
|
|
|
1562
1262
|
* | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
|
|
1563
1263
|
* | `position` | {@linkcode Vec3Handle} | Absolute world placement point |
|
|
1564
1264
|
* | `label` | `string`? | Instance name (default auto `${name}Ins${n}`) |
|
|
1565
|
-
* | `createNewSourceMesh` | `boolean`? |
|
|
1265
|
+
* | `createNewSourceMesh` | `boolean`? | Emit a source-mesh creation command (default `true`) |
|
|
1566
1266
|
* | `angleInDegrees` | `number`? | Rotation about the vertical axis, in degrees (default unrotated) |
|
|
1567
1267
|
*/
|
|
1568
1268
|
export const PluginDesignCreateFurnitureArgs = z.object({
|
|
@@ -1591,8 +1291,7 @@ export type PluginDesignCreateFurnitureArgs = z.infer<
|
|
|
1591
1291
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
|
|
1592
1292
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
1593
1293
|
* | `label` | `string`? | Instance name (optional) |
|
|
1594
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door
|
|
1595
|
-
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the door is hinged on (default the catalog item's authored side) |
|
|
1294
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door faces (default engine-chosen) |
|
|
1596
1295
|
*/
|
|
1597
1296
|
export const PluginDesignCreateDoorArgs = z.object({
|
|
1598
1297
|
catalogId: z.string().min(1),
|
|
@@ -1600,13 +1299,12 @@ export const PluginDesignCreateDoorArgs = z.object({
|
|
|
1600
1299
|
position: Vec3Handle,
|
|
1601
1300
|
label: z.string().optional(),
|
|
1602
1301
|
facing: Vec3Handle.optional(),
|
|
1603
|
-
hinge: Vec3Handle.optional(),
|
|
1604
1302
|
})
|
|
1605
1303
|
export type PluginDesignCreateDoorArgs = z.infer<
|
|
1606
1304
|
typeof PluginDesignCreateDoorArgs
|
|
1607
1305
|
>
|
|
1608
|
-
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg
|
|
1609
|
-
// door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label
|
|
1306
|
+
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
|
|
1307
|
+
// door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
|
|
1610
1308
|
|
|
1611
1309
|
// ---------------------------------------------------------------------------
|
|
1612
1310
|
// window
|
|
@@ -1621,8 +1319,7 @@ export type PluginDesignCreateDoorArgs = z.infer<
|
|
|
1621
1319
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
|
|
1622
1320
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
1623
1321
|
* | `label` | `string`? | Instance name (optional) |
|
|
1624
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window
|
|
1625
|
-
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the window is hinged on (default the catalog item's authored side) |
|
|
1322
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window faces (default engine-chosen) |
|
|
1626
1323
|
*/
|
|
1627
1324
|
export const PluginDesignCreateWindowArgs = z.object({
|
|
1628
1325
|
catalogId: z.string().min(1),
|
|
@@ -1630,18 +1327,27 @@ export const PluginDesignCreateWindowArgs = z.object({
|
|
|
1630
1327
|
position: Vec3Handle,
|
|
1631
1328
|
label: z.string().optional(),
|
|
1632
1329
|
facing: Vec3Handle.optional(),
|
|
1633
|
-
hinge: Vec3Handle.optional(),
|
|
1634
1330
|
})
|
|
1635
1331
|
export type PluginDesignCreateWindowArgs = z.infer<
|
|
1636
1332
|
typeof PluginDesignCreateWindowArgs
|
|
1637
1333
|
>
|
|
1638
|
-
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg
|
|
1639
|
-
// window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label
|
|
1334
|
+
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
|
|
1335
|
+
// window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
|
|
1640
1336
|
|
|
1641
1337
|
// ---------------------------------------------------------------------------
|
|
1642
1338
|
// opening
|
|
1643
1339
|
// ---------------------------------------------------------------------------
|
|
1644
1340
|
|
|
1341
|
+
const PluginOpeningBaseOptions = {
|
|
1342
|
+
catalogId: z.string().min(1),
|
|
1343
|
+
hostWall: ComponentHandle,
|
|
1344
|
+
position: Vec3Handle,
|
|
1345
|
+
facing: Vec3Handle.optional(),
|
|
1346
|
+
label: z.string().optional(),
|
|
1347
|
+
width: z.number().finite().positive().optional(),
|
|
1348
|
+
height: z.number().finite().positive().optional(),
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1645
1351
|
/**
|
|
1646
1352
|
* Options for {@linkcode PluginDesignCreateApi.opening}, discriminated by
|
|
1647
1353
|
* `kind`. Width and height are positive Snaptrude engine-unit values.
|
|
@@ -1818,6 +1524,3 @@ export const PluginCreateSpaceItem = z.object({
|
|
|
1818
1524
|
storey: z.number().int().optional(),
|
|
1819
1525
|
})
|
|
1820
1526
|
export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>
|
|
1821
|
-
|
|
1822
|
-
export * from "./opening-fields"
|
|
1823
|
-
export * from "./bulk-items"
|
|
@@ -39,10 +39,6 @@ export abstract class PluginDesignDeleteApi {
|
|
|
39
39
|
* children are removed and linked-list neighbours are fixed up — not caller-tunable
|
|
40
40
|
* in v1. Undoable — commits as a **single** undo entry.
|
|
41
41
|
*
|
|
42
|
-
* Dimension lines anchored to a deleted entity are removed with it, in the same undo
|
|
43
|
-
* entry, exactly as the editor's Delete key does — see `design.dimensions`. They are
|
|
44
|
-
* NOT listed in `affected`, which reports component handles only.
|
|
45
|
-
*
|
|
46
42
|
* @param components - Entities to delete. Unknown/forged handles reject the whole call (fail-fast).
|
|
47
43
|
* @returns The entities that were deleted, as {@linkcode ComponentHandle}`[]`
|
|
48
44
|
* (echoed host-side from the resolved+deleted set — the engine returns no ids).
|
|
@@ -8,11 +8,9 @@ import { PluginDesignChangeResult } from "../lock"
|
|
|
8
8
|
* `design.create.door`; generic reads (`listDoors`/`getHost`/`getProperties`) live at
|
|
9
9
|
* `design.query.*`. Door targets are {@linkcode ComponentHandle}s.
|
|
10
10
|
*
|
|
11
|
-
* `getSwingDirection` is a DERIVED read (no persisted field) — computed from the
|
|
12
|
-
* mesh
|
|
13
|
-
*
|
|
14
|
-
* axes (undoable, one command): `'x'` flips the swing side, `'z'` swaps the hinged jamb;
|
|
15
|
-
* `setType` is intentionally absent (the engine has no in-place re-type —
|
|
11
|
+
* `getSwingDirection` is a DERIVED read (no persisted field) — computed from the door
|
|
12
|
+
* mesh reflection state. `mirror` reflects the door across an axis (undoable, one
|
|
13
|
+
* command); `setType` is intentionally absent (the engine has no in-place re-type —
|
|
16
14
|
* it would require delete+recreate).
|
|
17
15
|
*
|
|
18
16
|
* The **catalog** reads (`listCatalogGroups`/`listCatalog`/`getCatalogItem`/`exists`)
|
|
@@ -156,11 +154,9 @@ export abstract class PluginDesignDoorsApi {
|
|
|
156
154
|
public abstract getSupportFloor(door: ComponentHandle): PluginApiReturn<ComponentHandle | null>
|
|
157
155
|
|
|
158
156
|
/**
|
|
159
|
-
* Get a door's swing (hinge) handedness
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* orientation (the same reflection `mirror` and the `hinge` placement option
|
|
163
|
-
* apply), not a persisted field.
|
|
157
|
+
* Get a door's swing (hinge) handedness — whether it opens as a left-hand or
|
|
158
|
+
* right-hand door. Derived from the door mesh's reflection state, not a
|
|
159
|
+
* persisted field.
|
|
164
160
|
*
|
|
165
161
|
* @param door The door to query
|
|
166
162
|
* @returns `'left'` / `'right'`, or `null` if indeterminate
|
|
@@ -182,13 +178,11 @@ export abstract class PluginDesignDoorsApi {
|
|
|
182
178
|
): PluginApiReturn<"left" | "right" | null>
|
|
183
179
|
|
|
184
180
|
/**
|
|
185
|
-
* Mirror a door
|
|
186
|
-
*
|
|
187
|
-
* (left-hand ↔ right-hand, same swing side); `'y'` turns it upside down.
|
|
188
|
-
* Undoable as a single command.
|
|
181
|
+
* Mirror a door across an axis, flipping its swing so it opens from the
|
|
182
|
+
* other side. Undoable as a single command.
|
|
189
183
|
*
|
|
190
184
|
* @param door The door to mirror
|
|
191
|
-
* @param axis Reflection axis (optional; default `'x'` — the swing-flip axis
|
|
185
|
+
* @param axis Reflection axis (optional; default `'x'` — the swing-flip axis)
|
|
192
186
|
* @returns The affected door(s)
|
|
193
187
|
*
|
|
194
188
|
* @examplePrompt Flip this door's swing
|
|
@@ -199,11 +193,10 @@ export abstract class PluginDesignDoorsApi {
|
|
|
199
193
|
*
|
|
200
194
|
* # Example
|
|
201
195
|
* ```ts
|
|
202
|
-
* // Flip the selected door's swing
|
|
196
|
+
* // Flip the selected door's swing — axis defaults to "x" (the swing-flip
|
|
197
|
+
* // axis); pass "y" or "z" to reflect across a different axis
|
|
203
198
|
* const [door] = await snaptrude.design.query.listDoors({ isSelected: true })
|
|
204
199
|
* const { affected } = await snaptrude.design.doors.mirror(door)
|
|
205
|
-
* // …or swap the hinged jamb instead (keeps the swing side)
|
|
206
|
-
* await snaptrude.design.doors.mirror(door, "z")
|
|
207
200
|
* ```
|
|
208
201
|
*/
|
|
209
202
|
public abstract mirror(
|
|
@@ -376,7 +369,7 @@ export const PluginDoorDimensions = z.object({
|
|
|
376
369
|
})
|
|
377
370
|
export type PluginDoorDimensions = z.infer<typeof PluginDoorDimensions>
|
|
378
371
|
|
|
379
|
-
/** Mirror axis — tokens mirror the engine `FlipDirection` verbatim
|
|
372
|
+
/** Mirror axis — tokens mirror the engine `FlipDirection` verbatim (§6.1). */
|
|
380
373
|
export const PluginMirrorAxis = z.enum(["x", "y", "z"])
|
|
381
374
|
export type PluginMirrorAxis = z.infer<typeof PluginMirrorAxis>
|
|
382
375
|
|
|
@@ -386,7 +379,7 @@ export type PluginMirrorAxis = z.infer<typeof PluginMirrorAxis>
|
|
|
386
379
|
* | Property | Type | Description |
|
|
387
380
|
* |---|---|---|
|
|
388
381
|
* | `door` | {@linkcode ComponentHandle} | The door to mirror |
|
|
389
|
-
* | `axis` | {@linkcode PluginMirrorAxis} | Reflection axis (optional; default `'x'` — the swing-flip axis
|
|
382
|
+
* | `axis` | {@linkcode PluginMirrorAxis} | Reflection axis (optional; default `'x'` — the swing-flip axis) |
|
|
390
383
|
*/
|
|
391
384
|
export const PluginDesignDoorMirrorArgs = z.object({
|
|
392
385
|
door: ComponentHandle,
|