@snaptrude/plugin-core 0.9.16 → 0.9.18-networks-20261016.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/AGENTS.md +231 -231
  2. package/CHANGELOG.md +408 -402
  3. package/CLAUDE.md +11 -11
  4. package/dist/api/analysis/daylight.d.ts +5 -5
  5. package/dist/api/analysis/solar.d.ts +2 -2
  6. package/dist/api/core/camera/index.d.ts +29 -0
  7. package/dist/api/core/camera/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +7 -1
  9. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  10. package/dist/api/core/geom/update/contour.d.ts +8 -2
  11. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  12. package/dist/api/core/zoom/index.d.ts +13 -0
  13. package/dist/api/core/zoom/index.d.ts.map +1 -1
  14. package/dist/api/design/bim.d.ts +209 -0
  15. package/dist/api/design/bim.d.ts.map +1 -0
  16. package/dist/api/design/boolean/index.d.ts +2 -0
  17. package/dist/api/design/boolean/index.d.ts.map +1 -1
  18. package/dist/api/design/catalog.d.ts +320 -0
  19. package/dist/api/design/catalog.d.ts.map +1 -0
  20. package/dist/api/design/create/bulk-items.d.ts +65 -25
  21. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  22. package/dist/api/design/create/index.d.ts +272 -99
  23. package/dist/api/design/create/index.d.ts.map +1 -1
  24. package/dist/api/design/create/opening-fields.d.ts +13 -12
  25. package/dist/api/design/create/opening-fields.d.ts.map +1 -1
  26. package/dist/api/design/delete/index.d.ts +1 -0
  27. package/dist/api/design/delete/index.d.ts.map +1 -1
  28. package/dist/api/design/doors/index.d.ts +18 -24
  29. package/dist/api/design/doors/index.d.ts.map +1 -1
  30. package/dist/api/design/family.d.ts +797 -27
  31. package/dist/api/design/family.d.ts.map +1 -1
  32. package/dist/api/design/index.d.ts +16 -0
  33. package/dist/api/design/index.d.ts.map +1 -1
  34. package/dist/api/design/networks.d.ts +1763 -0
  35. package/dist/api/design/networks.d.ts.map +1 -0
  36. package/dist/api/design/query/index.d.ts +42 -32
  37. package/dist/api/design/query/index.d.ts.map +1 -1
  38. package/dist/api/design/selection/index.d.ts +10 -10
  39. package/dist/api/design/types/index.d.ts +40 -24
  40. package/dist/api/design/types/index.d.ts.map +1 -1
  41. package/dist/api/design/update/index.d.ts +43 -3
  42. package/dist/api/design/update/index.d.ts.map +1 -1
  43. package/dist/api/design/windows/index.d.ts +8 -8
  44. package/dist/api/design/windows/index.d.ts.map +1 -1
  45. package/dist/api/presentation/aiInspiration.d.ts +10 -10
  46. package/dist/api/presentation/annotate.d.ts +38 -22
  47. package/dist/api/presentation/annotate.d.ts.map +1 -1
  48. package/dist/api/presentation/drawingContract.d.ts +32 -0
  49. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  50. package/dist/api/presentation/drawings.d.ts +3523 -0
  51. package/dist/api/presentation/drawings.d.ts.map +1 -0
  52. package/dist/api/presentation/export.d.ts +23 -5
  53. package/dist/api/presentation/export.d.ts.map +1 -1
  54. package/dist/api/presentation/index.d.ts +41 -12
  55. package/dist/api/presentation/index.d.ts.map +1 -1
  56. package/dist/api/presentation/placedViews.d.ts +106 -6
  57. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  58. package/dist/api/presentation/sections.d.ts +461 -0
  59. package/dist/api/presentation/sections.d.ts.map +1 -0
  60. package/dist/api/presentation/shapes.d.ts +2 -2
  61. package/dist/api/presentation/sheets.d.ts +175 -19
  62. package/dist/api/presentation/sheets.d.ts.map +1 -1
  63. package/dist/api/presentation/viewPresets.d.ts +222 -0
  64. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  65. package/dist/api/presentation/views.d.ts +103 -5
  66. package/dist/api/presentation/views.d.ts.map +1 -1
  67. package/dist/api/presentation/walkthroughs.d.ts +6 -6
  68. package/dist/errors/codes.d.ts +3 -1
  69. package/dist/errors/codes.d.ts.map +1 -1
  70. package/dist/index.cjs +3788 -2328
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.js +3650 -2328
  73. package/dist/index.js.map +1 -1
  74. package/package.json +42 -42
  75. package/scripts/check-dist-fresh.mjs +22 -22
  76. package/scripts/generate-manifest.mjs +243 -238
  77. package/scripts/generate-manifest.test.mjs +303 -303
  78. package/src/api/analysis/daylight.ts +470 -470
  79. package/src/api/analysis/heatmaps.ts +683 -683
  80. package/src/api/analysis/illuminance.ts +155 -155
  81. package/src/api/analysis/index.ts +61 -61
  82. package/src/api/analysis/shadows.ts +183 -183
  83. package/src/api/analysis/solar.ts +237 -237
  84. package/src/api/analysis/sunlightHours.ts +211 -211
  85. package/src/api/analysis/sunpath.ts +83 -83
  86. package/src/api/analysis/weather.ts +179 -179
  87. package/src/api/core/buildings.ts +485 -485
  88. package/src/api/core/camera/index.ts +696 -667
  89. package/src/api/core/comment/index.ts +376 -376
  90. package/src/api/core/geom/create/index.ts +2139 -2133
  91. package/src/api/core/geom/delete/index.ts +84 -84
  92. package/src/api/core/geom/index.ts +35 -35
  93. package/src/api/core/geom/query/arc.ts +169 -169
  94. package/src/api/core/geom/query/brep.ts +621 -621
  95. package/src/api/core/geom/query/circle.ts +404 -404
  96. package/src/api/core/geom/query/contour.ts +540 -540
  97. package/src/api/core/geom/query/curve.ts +1102 -1102
  98. package/src/api/core/geom/query/edge.ts +130 -130
  99. package/src/api/core/geom/query/face.ts +508 -508
  100. package/src/api/core/geom/query/halfedge.ts +210 -210
  101. package/src/api/core/geom/query/index.ts +63 -63
  102. package/src/api/core/geom/query/profile.ts +473 -473
  103. package/src/api/core/geom/query/vertex.ts +205 -205
  104. package/src/api/core/geom/update/contour.ts +323 -317
  105. package/src/api/core/geom/update/curve.ts +209 -209
  106. package/src/api/core/geom/update/index.ts +29 -29
  107. package/src/api/core/geom/update/profile.ts +379 -379
  108. package/src/api/core/groups.ts +521 -521
  109. package/src/api/core/handles/index.ts +234 -234
  110. package/src/api/core/history/index.ts +84 -84
  111. package/src/api/core/index.ts +99 -99
  112. package/src/api/core/io/export/index.ts +126 -126
  113. package/src/api/core/io/import/index.ts +504 -504
  114. package/src/api/core/io/index.ts +42 -42
  115. package/src/api/core/io/job/index.ts +140 -140
  116. package/src/api/core/io/query/index.ts +71 -71
  117. package/src/api/core/io/terrain/index.ts +360 -360
  118. package/src/api/core/io/underlay/index.ts +705 -705
  119. package/src/api/core/layers.ts +540 -540
  120. package/src/api/core/math/index.ts +20 -20
  121. package/src/api/core/math/quat.ts +172 -172
  122. package/src/api/core/math/vec3.ts +179 -179
  123. package/src/api/core/mode/index.ts +108 -108
  124. package/src/api/core/project/index.ts +479 -479
  125. package/src/api/core/proposals/index.ts +570 -570
  126. package/src/api/core/storeys/index.ts +308 -308
  127. package/src/api/core/storeys/layers.ts +339 -339
  128. package/src/api/core/tags.ts +911 -911
  129. package/src/api/core/units/index.ts +164 -164
  130. package/src/api/core/user.ts +46 -46
  131. package/src/api/core/zoom/index.ts +64 -51
  132. package/src/api/design/bim.ts +121 -0
  133. package/src/api/design/boolean/index.ts +181 -179
  134. package/src/api/design/catalog.ts +203 -0
  135. package/src/api/design/create/bulk-items.ts +294 -254
  136. package/src/api/design/create/grids.ts +137 -137
  137. package/src/api/design/create/index.ts +2148 -1980
  138. package/src/api/design/create/opening-fields.ts +40 -37
  139. package/src/api/design/delete/index.ts +75 -74
  140. package/src/api/design/dimensions.ts +453 -453
  141. package/src/api/design/doors/index.ts +516 -500
  142. package/src/api/design/edit/index.ts +54 -54
  143. package/src/api/design/erase/index.ts +151 -151
  144. package/src/api/design/family.ts +1334 -704
  145. package/src/api/design/furniture/index.ts +319 -319
  146. package/src/api/design/grids.ts +237 -237
  147. package/src/api/design/index.ts +304 -274
  148. package/src/api/design/lock.ts +69 -69
  149. package/src/api/design/materials/index.ts +608 -608
  150. package/src/api/design/networks.ts +667 -0
  151. package/src/api/design/query/geometry/index.ts +319 -319
  152. package/src/api/design/query/grids.ts +197 -197
  153. package/src/api/design/query/index.ts +1236 -1226
  154. package/src/api/design/query/referenceLines.ts +52 -52
  155. package/src/api/design/query/spaces.ts +275 -275
  156. package/src/api/design/selection/index.ts +273 -273
  157. package/src/api/design/shared.ts +40 -40
  158. package/src/api/design/transform/index.ts +254 -254
  159. package/src/api/design/types/index.ts +163 -156
  160. package/src/api/design/update/index.ts +1024 -983
  161. package/src/api/design/visibility.ts +143 -143
  162. package/src/api/design/windows/index.ts +351 -333
  163. package/src/api/entity/buildableEnvelope.ts +322 -322
  164. package/src/api/entity/index.ts +30 -30
  165. package/src/api/entity/referenceLine.ts +235 -235
  166. package/src/api/entity/space.ts +612 -612
  167. package/src/api/entity/story.ts +517 -517
  168. package/src/api/index.ts +47 -47
  169. package/src/api/presentation/aiInspiration.ts +1116 -1116
  170. package/src/api/presentation/annotate.ts +417 -385
  171. package/src/api/presentation/camera.ts +289 -289
  172. package/src/api/presentation/diagrams.ts +194 -194
  173. package/src/api/presentation/drawingContract.ts +70 -0
  174. package/src/api/presentation/drawings.ts +1179 -0
  175. package/src/api/presentation/export.ts +134 -108
  176. package/src/api/presentation/import.ts +159 -159
  177. package/src/api/presentation/index.ts +160 -126
  178. package/src/api/presentation/placedViews.ts +1211 -1120
  179. package/src/api/presentation/sections.ts +420 -0
  180. package/src/api/presentation/shapes.ts +274 -274
  181. package/src/api/presentation/sheets.ts +746 -585
  182. package/src/api/presentation/slideshow.ts +134 -134
  183. package/src/api/presentation/tables.ts +84 -84
  184. package/src/api/presentation/viewPresets.ts +241 -0
  185. package/src/api/presentation/views.ts +713 -673
  186. package/src/api/presentation/walkthroughs.ts +1201 -1201
  187. package/src/api/program/adjacency.ts +164 -164
  188. package/src/api/program/areas.ts +408 -408
  189. package/src/api/program/classification.ts +138 -138
  190. package/src/api/program/cores.ts +83 -83
  191. package/src/api/program/departments.ts +517 -517
  192. package/src/api/program/index.ts +73 -73
  193. package/src/api/program/labels.ts +332 -332
  194. package/src/api/program/layout.ts +422 -422
  195. package/src/api/program/metadata.ts +364 -364
  196. package/src/api/program/metrics.ts +120 -120
  197. package/src/api/program/site.ts +748 -748
  198. package/src/api/program/spreadsheet.ts +2698 -2698
  199. package/src/api/workspace/index.ts +612 -612
  200. package/src/errors/codes.ts +143 -136
  201. package/src/errors/envelope.ts +75 -75
  202. package/src/errors/index.ts +21 -21
  203. package/src/errors/plugin-error.ts +134 -134
  204. package/src/handles.ts +297 -297
  205. package/src/host-utils.ts +67 -67
  206. package/src/index.ts +7 -7
  207. package/src/massParameters.ops.ts +246 -246
  208. package/src/massParameters.ts +427 -427
  209. package/src/types.ts +16 -16
  210. package/test/drawingContract.test.mjs +288 -0
  211. package/test/errors.test.mjs +185 -184
  212. package/test/massParameters.test.mjs +952 -952
  213. package/tsconfig.json +22 -22
  214. package/tsup.config.ts +12 -12
  215. package/api-manifest.json +0 -9618
@@ -1,667 +1,696 @@
1
- import * as z from "zod"
2
- import { PluginApiReturn } from "../../../types"
3
- import { Vec3Components, Vec3Handle } from "../../../handles"
4
-
5
- /**
6
- * Camera controls.
7
- *
8
- * Position the viewport camera, snap it to a standard orthographic/isometric
9
- * view, and toggle between the 2D (plan) and 3D modelling modes — mirrors the
10
- * canvas view menu and the 2D/3D toggle. Like {@linkcode PluginZoomApi}, these
11
- * are transient VIEW-STATE changes: they are not model edits, so they are not
12
- * write-gated and are not undoable. Accessed via `snaptrude.core.camera`.
13
- *
14
- * Read and set the full camera pose (`getPose`/`setPose`), walk and turn it the
15
- * way the arrow keys do (`move`/`rotate`), and read or change the arrow-key
16
- * navigation settings (`getNavigationSettings`/`updateNavigationSettings`).
17
- * Positions are world coordinates in internal `babylon` units (1 unit =
18
- * 0.254 m, Y up); yaw is degrees clockwise from +z seen from above, pitch is
19
- * degrees above level.
20
- */
21
- export abstract class PluginCameraApi {
22
- constructor() {}
23
-
24
- /**
25
- * Point the camera: place its eye at `eye` looking toward `target` (world
26
- * coordinates, internal `babylon` units). View-state only — not undoable.
27
- *
28
- * @param eye - Camera position as a {@linkcode Vec3Handle}
29
- * @param target - Point the camera looks at as a {@linkcode Vec3Handle}
30
- * @returns `true` once the camera has been positioned.
31
- *
32
- * @examplePrompt Look at the model from above the north-east corner
33
- * @examplePrompt Position the camera at (50, 30, 50) looking at the origin
34
- * @examplePrompt Point the camera at the centre of the building from the side
35
- * @examplePrompt Set the eye to this point and aim it at that point
36
- *
37
- * # Example
38
- * ```ts
39
- * const { vec3 } = snaptrude.core.math
40
- * await snaptrude.core.camera.lookFrom(vec3.new(50, 30, 50), vec3.new(0, 0, 0))
41
- * ```
42
- */
43
- public abstract lookFrom(
44
- eye: Vec3Handle,
45
- target: Vec3Handle,
46
- ): PluginApiReturn<boolean>
47
-
48
- /**
49
- * Snap the camera to a standard view — the five orthographic elevations
50
- * (`top` / `front` / `back` / `left` / `right`) or the 3D `iso` (isometric
51
- * perspective) view. Mirrors the canvas view menu. View-state only — not
52
- * undoable. The orthographic presets exit 2D mode first if needed.
53
- *
54
- * @param view - The standard view to snap to ({@linkcode PluginStandardView})
55
- * @returns `true` once the view has been applied.
56
- *
57
- * @examplePrompt Switch to the top view
58
- * @examplePrompt Show me the front elevation
59
- * @examplePrompt Go to the isometric view
60
- * @examplePrompt Look at the model from the left
61
- * @examplePrompt Give me a plan view from the top
62
- *
63
- * # Example
64
- * ```ts
65
- * await snaptrude.core.camera.setStandardView("top")
66
- * ```
67
- */
68
- public abstract setStandardView(
69
- view: PluginStandardView,
70
- ): PluginApiReturn<boolean>
71
-
72
- /**
73
- * Get the current camera mode. Paired with {@linkcode PluginCameraApi.setMode}.
74
- *
75
- * @returns `"2d"` when the editor is in plan view, `"3d"` otherwise.
76
- *
77
- * @examplePrompt Am I in 2D or 3D?
78
- * @examplePrompt What view mode is the editor in?
79
- *
80
- * # Example
81
- * ```ts
82
- * if ((await snaptrude.core.camera.getMode()) === "2d") {
83
- * await snaptrude.core.camera.setMode("3d")
84
- * }
85
- * ```
86
- */
87
- public abstract getMode(): PluginApiReturn<PluginCameraMode>
88
-
89
- /**
90
- * Toggle the modelling mode between `2d` (plan) and `3d`. Mirrors the canvas
91
- * 2D/3D toggle: `3d` enters the isometric perspective view, `2d` drops to the
92
- * orthographic plan of the active storey. View-state only — not undoable.
93
- *
94
- * @param mode - `"2d"` or `"3d"` ({@linkcode PluginCameraMode})
95
- * @returns `true` once the mode switch has been requested.
96
- *
97
- * @examplePrompt Switch to 3D view
98
- * @examplePrompt Drop into 2D plan mode
99
- * @examplePrompt Go back to 3D
100
- * @examplePrompt Show the floor plan in 2D
101
- *
102
- * # Example
103
- * ```ts
104
- * await snaptrude.core.camera.setMode("3d")
105
- * ```
106
- */
107
- public abstract setMode(mode: PluginCameraMode): PluginApiReturn<boolean>
108
-
109
- /**
110
- * Read the camera's current projection: `"perspective"` (the default 3D
111
- * view) or `"orthographic"`. In 2D (plan) mode this always reports
112
- * `"orthographic"` — a plan is an orthographic projection.
113
- *
114
- * @returns The current {@linkcode PluginCameraProjection}.
115
- *
116
- * @examplePrompt Is the camera in perspective or orthographic?
117
- * @examplePrompt What projection is the 3D view using?
118
- * @examplePrompt Check whether perspective is on
119
- *
120
- * # Example
121
- * ```ts
122
- * const projection = await snaptrude.core.camera.getProjection()
123
- * console.log(projection) // "perspective" | "orthographic"
124
- * ```
125
- */
126
- public abstract getProjection(): PluginApiReturn<PluginCameraProjection>
127
-
128
- /**
129
- * Switch the 3D camera between `"perspective"` and `"orthographic"`
130
- * projection — the Perspective/Orthographic control in the Design tab's
131
- * View Settings panel. Like {@linkcode PluginCameraApi.setMode}, this is a
132
- * transient view-state change: not write-gated, not undoable.
133
- *
134
- * In 2D (plan) mode the canvas is always an orthographic plan:
135
- * `"orthographic"` is accepted as a no-op, while `"perspective"` is
136
- * rejected — switch to 3D first via `setMode("3d")`.
137
- *
138
- * @param projection - `"perspective"` or `"orthographic"` ({@linkcode PluginCameraProjection})
139
- * @returns `true` once the projection has been applied.
140
- *
141
- * @examplePrompt Switch the camera to orthographic
142
- * @examplePrompt Turn perspective off
143
- * @examplePrompt Give me a perspective view of the model
144
- * @examplePrompt Make the 3D view orthographic like an axonometric drawing
145
- *
146
- * # Example
147
- * ```ts
148
- * await snaptrude.core.camera.setProjection("orthographic")
149
- * const projection = await snaptrude.core.camera.getProjection() // "orthographic"
150
- * ```
151
- */
152
- public abstract setProjection(
153
- projection: PluginCameraProjection,
154
- ): PluginApiReturn<boolean>
155
-
156
- /**
157
- * Zoom (fit) the camera to all geometry in the scene — the "zoom extents"
158
- * action. View-state only — not undoable. Canonical home of the zoom-extents
159
- * read (the deprecated `core.zoom.extents`).
160
- *
161
- * @returns `true` once the camera has been framed to the scene.
162
- *
163
- * @examplePrompt Zoom out so I can see the whole model
164
- * @examplePrompt Fit everything in the view
165
- * @examplePrompt Frame the entire building in the viewport
166
- * @examplePrompt Do a zoom extents on the canvas
167
- *
168
- * # Example
169
- * ```ts
170
- * await snaptrude.core.camera.zoomExtents()
171
- * ```
172
- */
173
- public abstract zoomExtents(): PluginApiReturn<boolean>
174
-
175
- /**
176
- * Zoom (fit) the camera to the current selection. View-state only — not
177
- * undoable. Canonical home of the zoom-to-selection read (the deprecated
178
- * `core.zoom.selection`).
179
- *
180
- * @returns `true` if there was a selection to frame; `false` if nothing is
181
- * selected (no-op).
182
- *
183
- * @examplePrompt Zoom in on what I have selected
184
- * @examplePrompt Frame the selected walls in the view
185
- * @examplePrompt Focus the camera on my current selection
186
- * @examplePrompt Fit the view to the selected room
187
- *
188
- * # Example
189
- * ```ts
190
- * await snaptrude.core.camera.zoomSelection()
191
- * ```
192
- */
193
- public abstract zoomSelection(): PluginApiReturn<boolean>
194
-
195
- /**
196
- * Read where the camera is and where it looks: the eye and target positions
197
- * (world coordinates, internal `babylon` units), the view direction as yaw
198
- * and pitch, the vertical field of view, the projection and the 2D/3D mode.
199
- * Paired with {@linkcode PluginCameraApi.setPose}.
200
- *
201
- * @returns The current {@linkcode PluginCameraPose}.
202
- * @throws PRECONDITION_FAILED when there is no active camera.
203
- *
204
- * @examplePrompt Where is the camera right now?
205
- * @examplePrompt Remember this viewpoint so we can come back to it
206
- * @examplePrompt Which way is the camera facing?
207
- * @examplePrompt How high above the ground is the camera?
208
- *
209
- * # Example
210
- * ```ts
211
- * const pose = await snaptrude.core.camera.getPose()
212
- * console.log(pose.eye, pose.yawInDegrees, pose.pitchInDegrees)
213
- * ```
214
- */
215
- public abstract getPose(): PluginApiReturn<PluginCameraPose>
216
-
217
- /**
218
- * Place the camera, optionally easing there over `options.durationInSeconds`,
219
- * and resolve once the new view has been drawn, so a capture that follows sees
220
- * it without a fixed wait. `pose` is one of:
221
- *
222
- * - `{ eye, target }`: stand at `eye` looking at `target`, as
223
- * {@linkcode PluginCameraApi.lookFrom} does with handles;
224
- * - `{ eye, yawInDegrees, pitchInDegrees }`: stand at `eye` looking along a
225
- * direction;
226
- * - `{ standAt, yawInDegrees? }`: stand on the floor, stair, terrain or
227
- * ground at or below `standAt`, at the user's eye height above it (the `I`
228
- * key), facing `yawInDegrees` (the current yaw when omitted).
229
- *
230
- * Stops a playing walkthrough and switches from 2D plan view to 3D first.
231
- * View-state only: not write-gated, not undoable.
232
- *
233
- * @param pose - Where to put the camera ({@linkcode PluginCameraPoseInput})
234
- * @param options - `durationInSeconds`: ease over this long (0 to 10, default 0 jumps)
235
- * @returns The camera's {@linkcode PluginCameraPose} once it has arrived.
236
- * @throws PRECONDITION_FAILED when there is no active camera, while a
237
- * walkthrough export is recording, or when `standAt` lies below the ground
238
- * with nothing under it. VALIDATION when `eye` and `target` coincide or a
239
- * pitch is beyond ±89°.
240
- *
241
- * @examplePrompt Stand in the living room at eye level facing the window
242
- * @examplePrompt Move the camera to (40, 12, 30) looking at the entrance
243
- * @examplePrompt Fly the camera smoothly over to the courtyard
244
- * @examplePrompt Put me back at the viewpoint we saved earlier
245
- *
246
- * # Example
247
- * ```ts
248
- * const { camera } = snaptrude.core
249
- * await camera.setPose({ standAt: { x: 20, y: 0, z: 35 }, yawInDegrees: 90 })
250
- * await camera.setPose(
251
- * { eye: { x: 60, y: 25, z: 60 }, target: { x: 0, y: 5, z: 0 } },
252
- * { durationInSeconds: 1.5 },
253
- * )
254
- * ```
255
- */
256
- public abstract setPose(
257
- pose: PluginCameraPoseInput,
258
- options?: PluginCameraSetPoseOptions,
259
- ): PluginApiReturn<PluginCameraPose>
260
-
261
- /**
262
- * Walk or fly the camera by a displacement in its own frame: `forward` along
263
- * the level view direction, `right` to its side and `up` vertically, in
264
- * internal `babylon` units. The view direction does not change. With
265
- * `options.followsFloor` the camera keeps its height above the floor as it
266
- * goes, climbing and descending stairs and ramps the way the arrow keys do.
267
- * Stops a playing walkthrough and switches from 2D plan view to 3D first.
268
- * View-state only: not write-gated, not undoable.
269
- *
270
- * @param displacement - {@linkcode PluginCameraMoveDisplacement}; omitted components are 0
271
- * @param options - `followsFloor` (default `false`) and `durationInSeconds` (0 to 10, default 0)
272
- * @returns The camera's {@linkcode PluginCameraPose} after the move.
273
- * @throws PRECONDITION_FAILED when there is no active camera, or while a
274
- * walkthrough export is recording.
275
- *
276
- * @examplePrompt Walk forward 3 metres
277
- * @examplePrompt Step to the right a little
278
- * @examplePrompt Walk up the stairs ahead
279
- * @examplePrompt Raise the camera by 2 metres
280
- *
281
- * # Example
282
- * ```ts
283
- * const metre = 1 / 0.254
284
- * await snaptrude.core.camera.move(
285
- * { forward: 3 * metre },
286
- * { followsFloor: true, durationInSeconds: 2 },
287
- * )
288
- * ```
289
- */
290
- public abstract move(
291
- displacement: PluginCameraMoveDisplacement,
292
- options?: PluginCameraMoveOptions,
293
- ): PluginApiReturn<PluginCameraPose>
294
-
295
- /**
296
- * Turn the camera in place by signed angles: `yawInDegrees` to the right
297
- * (clockwise seen from above) and `pitchInDegrees` up. The eye does not move;
298
- * the resulting pitch is kept within ±89°. Stops a playing walkthrough and
299
- * switches from 2D plan view to 3D first. View-state only: not write-gated,
300
- * not undoable.
301
- *
302
- * @param yawInDegrees - Turn to the right by this much (negative turns left)
303
- * @param pitchInDegrees - Tilt up by this much (negative tilts down; default 0)
304
- * @param options - `durationInSeconds` (0 to 10, default 0)
305
- * @returns The camera's {@linkcode PluginCameraPose} after turning.
306
- * @throws PRECONDITION_FAILED when there is no active camera, or while a
307
- * walkthrough export is recording.
308
- *
309
- * @examplePrompt Turn around
310
- * @examplePrompt Look 45 degrees to the left
311
- * @examplePrompt Tilt the camera down a bit
312
- *
313
- * # Example
314
- * ```ts
315
- * await snaptrude.core.camera.rotate(180, 0, { durationInSeconds: 1 })
316
- * ```
317
- */
318
- public abstract rotate(
319
- yawInDegrees: number,
320
- pitchInDegrees?: number,
321
- options?: PluginCameraRotateOptions,
322
- ): PluginApiReturn<PluginCameraPose>
323
-
324
- /**
325
- * Read the arrow-key navigation settings: whether the arrow keys walk the
326
- * camera, the eye height used by `setPose`'s `standAt` and by walkthroughs
327
- * that follow the floor, the walking speed, and whether walking stops at
328
- * walls. Paired with {@linkcode PluginCameraApi.updateNavigationSettings}.
329
- *
330
- * @returns The current {@linkcode PluginCameraNavigationSettings}.
331
- *
332
- * @examplePrompt Is arrow-key navigation on?
333
- * @examplePrompt What eye height does the camera use?
334
- *
335
- * # Example
336
- * ```ts
337
- * const { isKeyboardNavigationEnabled } =
338
- * await snaptrude.core.camera.getNavigationSettings()
339
- * ```
340
- */
341
- public abstract getNavigationSettings(): PluginApiReturn<PluginCameraNavigationSettings>
342
-
343
- /**
344
- * Change arrow-key navigation settings; only the fields given change.
345
- * `isKeyboardNavigationEnabled` is the user's Project Settings switch and is
346
- * saved on this device; the other settings last for the session.
347
- * Write-gated: this changes the user's preferences, not just the view.
348
- *
349
- * @param patch - The settings to change ({@linkcode PluginCameraNavigationSettingsPatch})
350
- * @returns The {@linkcode PluginCameraNavigationSettings} after the change.
351
- * @throws METHOD_NOT_PERMITTED when plugin writes are disabled.
352
- *
353
- * @examplePrompt Turn off arrow-key navigation
354
- * @examplePrompt Use a 1.6 m eye height
355
- * @examplePrompt Make walking stop at walls
356
- *
357
- * # Example
358
- * ```ts
359
- * await snaptrude.core.camera.updateNavigationSettings({
360
- * eyeHeight: 1.6 / 0.254,
361
- * isCollisionEnabled: true,
362
- * })
363
- * ```
364
- */
365
- public abstract updateNavigationSettings(
366
- patch: PluginCameraNavigationSettingsPatch,
367
- ): PluginApiReturn<PluginCameraNavigationSettings>
368
- }
369
-
370
- /**
371
- * A standard camera view: the five orthographic elevations (`top`/`front`/
372
- * `back`/`left`/`right`) or the 3D isometric perspective (`iso`).
373
- */
374
- export const PluginStandardView = z.enum([
375
- "top",
376
- "front",
377
- "back",
378
- "left",
379
- "right",
380
- "iso",
381
- ])
382
- export type PluginStandardView = z.infer<typeof PluginStandardView>
383
-
384
- /**
385
- * The modelling mode: `2d` (orthographic plan) or `3d` (isometric perspective).
386
- */
387
- export const PluginCameraMode = z.enum(["2d", "3d"])
388
- export type PluginCameraMode = z.infer<typeof PluginCameraMode>
389
-
390
- /**
391
- * The 3D camera projection: `perspective` (the default) or `orthographic` —
392
- * the Perspective/Orthographic control in the Design tab's View Settings panel.
393
- */
394
- export const PluginCameraProjection = z.enum(["perspective", "orthographic"])
395
- export type PluginCameraProjection = z.infer<typeof PluginCameraProjection>
396
-
397
- /**
398
- * Arguments for {@linkcode PluginCameraApi.lookFrom}.
399
- *
400
- * | Property | Type | Description |
401
- * |---|---|---|
402
- * | `eye` | {@linkcode Vec3Handle} | Camera position (world, `babylon` units) |
403
- * | `target` | {@linkcode Vec3Handle} | Point the camera looks at |
404
- */
405
- export const PluginCameraLookFromArgs = z.object({
406
- eye: Vec3Handle,
407
- target: Vec3Handle,
408
- })
409
- export type PluginCameraLookFromArgs = z.infer<typeof PluginCameraLookFromArgs>
410
-
411
- /**
412
- * Arguments for {@linkcode PluginCameraApi.setStandardView}.
413
- *
414
- * | Property | Type | Description |
415
- * |---|---|---|
416
- * | `view` | {@linkcode PluginStandardView} | The standard view to snap to |
417
- */
418
- export const PluginCameraSetStandardViewArgs = z.object({
419
- view: PluginStandardView,
420
- })
421
- export type PluginCameraSetStandardViewArgs = z.infer<
422
- typeof PluginCameraSetStandardViewArgs
423
- >
424
-
425
- /**
426
- * Arguments for {@linkcode PluginCameraApi.setMode}.
427
- *
428
- * | Property | Type | Description |
429
- * |---|---|---|
430
- * | `mode` | {@linkcode PluginCameraMode} | `"2d"` or `"3d"` |
431
- */
432
- export const PluginCameraSetModeArgs = z.object({
433
- mode: PluginCameraMode,
434
- })
435
- export type PluginCameraSetModeArgs = z.infer<typeof PluginCameraSetModeArgs>
436
-
437
- /**
438
- * Arguments for {@linkcode PluginCameraApi.setProjection}.
439
- *
440
- * | Property | Type | Description |
441
- * |---|---|---|
442
- * | `projection` | {@linkcode PluginCameraProjection} | `"perspective"` or `"orthographic"` |
443
- */
444
- export const PluginCameraSetProjectionArgs = z.object({
445
- projection: PluginCameraProjection,
446
- })
447
- export type PluginCameraSetProjectionArgs = z.infer<
448
- typeof PluginCameraSetProjectionArgs
449
- >
450
-
451
- // Plain {x, y, z} record with finite components (the brepFromRevolution `axisOrigin` pattern).
452
- const FiniteVec3Components = z.object({
453
- x: z.number().finite(),
454
- y: z.number().finite(),
455
- z: z.number().finite(),
456
- })
457
-
458
- /** Pitch is kept off the vertical, where yaw has no meaning. */
459
- const PitchInDegrees = z.number().finite().min(-89).max(89)
460
-
461
- /** How long a camera move eases for; 0 jumps. */
462
- const DurationInSeconds = z.number().finite().min(0).max(10)
463
-
464
- /**
465
- * The camera's pose — result of {@linkcode PluginCameraApi.getPose},
466
- * {@linkcode PluginCameraApi.setPose}, {@linkcode PluginCameraApi.move} and
467
- * {@linkcode PluginCameraApi.rotate}.
468
- *
469
- * | Property | Type | Description |
470
- * |---|---|---|
471
- * | `eye` | `{ x, y, z }` | Camera position (world, `babylon` units) |
472
- * | `target` | `{ x, y, z }` | Point the camera looks at |
473
- * | `yawInDegrees` | `number` | View direction, degrees clockwise from +z seen from above (-180 to 180) |
474
- * | `pitchInDegrees` | `number` | View direction, degrees above level (negative looks down) |
475
- * | `fieldOfViewInDegrees` | `number` | Vertical field of view |
476
- * | `projection` | {@linkcode PluginCameraProjection} | `"perspective"` or `"orthographic"` |
477
- * | `mode` | {@linkcode PluginCameraMode} | `"2d"` or `"3d"` |
478
- */
479
- export const PluginCameraPose = z.object({
480
- eye: Vec3Components,
481
- target: Vec3Components,
482
- yawInDegrees: z.number(),
483
- pitchInDegrees: z.number(),
484
- fieldOfViewInDegrees: z.number(),
485
- projection: PluginCameraProjection,
486
- mode: PluginCameraMode,
487
- })
488
- export type PluginCameraPose = z.infer<typeof PluginCameraPose>
489
-
490
- /**
491
- * Where {@linkcode PluginCameraApi.setPose} puts the camera — exactly one of:
492
- *
493
- * | Shape | Meaning |
494
- * |---|---|
495
- * | `{ eye, target }` | Stand at `eye` looking at `target` |
496
- * | `{ eye, yawInDegrees, pitchInDegrees }` | Stand at `eye` looking along a direction (pitch within ±89°) |
497
- * | `{ standAt, yawInDegrees? }` | Stand at eye height on the floor, stair, terrain or ground at or below `standAt`, facing `yawInDegrees` (default: current yaw) |
498
- *
499
- * Points are plain `{ x, y, z }` world coordinates in `babylon` units.
500
- */
501
- export const PluginCameraPoseInput = z.union([
502
- z
503
- .object({ eye: FiniteVec3Components, target: FiniteVec3Components })
504
- .strict(),
505
- z
506
- .object({
507
- eye: FiniteVec3Components,
508
- yawInDegrees: z.number().finite(),
509
- pitchInDegrees: PitchInDegrees,
510
- })
511
- .strict(),
512
- z
513
- .object({
514
- standAt: FiniteVec3Components,
515
- yawInDegrees: z.number().finite().optional(),
516
- })
517
- .strict(),
518
- ])
519
- export type PluginCameraPoseInput = z.infer<typeof PluginCameraPoseInput>
520
-
521
- /**
522
- * Options for {@linkcode PluginCameraApi.setPose}.
523
- *
524
- * | Property | Type | Description |
525
- * |---|---|---|
526
- * | `durationInSeconds` | `number \| undefined` | Ease to the pose over this long (0 to 10; default 0 jumps) |
527
- */
528
- export const PluginCameraSetPoseOptions = z
529
- .object({ durationInSeconds: DurationInSeconds.optional() })
530
- .strict()
531
- export type PluginCameraSetPoseOptions = z.infer<
532
- typeof PluginCameraSetPoseOptions
533
- >
534
-
535
- /**
536
- * Arguments for {@linkcode PluginCameraApi.setPose}.
537
- */
538
- export const PluginCameraSetPoseArgs = z.object({
539
- pose: PluginCameraPoseInput,
540
- options: PluginCameraSetPoseOptions.optional(),
541
- })
542
- export type PluginCameraSetPoseArgs = z.infer<typeof PluginCameraSetPoseArgs>
543
-
544
- /**
545
- * A displacement in the camera's own frame, for {@linkcode PluginCameraApi.move}
546
- * (`babylon` units; omitted components are 0).
547
- *
548
- * | Property | Type | Description |
549
- * |---|---|---|
550
- * | `forward` | `number \| undefined` | Along the level view direction (negative walks back) |
551
- * | `right` | `number \| undefined` | To the camera's right (negative steps left) |
552
- * | `up` | `number \| undefined` | Vertically (negative descends) |
553
- */
554
- export const PluginCameraMoveDisplacement = z
555
- .object({
556
- forward: z.number().finite().optional(),
557
- right: z.number().finite().optional(),
558
- up: z.number().finite().optional(),
559
- })
560
- .strict()
561
- export type PluginCameraMoveDisplacement = z.infer<
562
- typeof PluginCameraMoveDisplacement
563
- >
564
-
565
- /**
566
- * Options for {@linkcode PluginCameraApi.move}.
567
- *
568
- * | Property | Type | Description |
569
- * |---|---|---|
570
- * | `followsFloor` | `boolean \| undefined` | Keep the height above the floor, climbing stairs and ramps (default `false`) |
571
- * | `durationInSeconds` | `number \| undefined` | Walk over this long (0 to 10; default 0 jumps) |
572
- */
573
- export const PluginCameraMoveOptions = z
574
- .object({
575
- followsFloor: z.boolean().optional(),
576
- durationInSeconds: DurationInSeconds.optional(),
577
- })
578
- .strict()
579
- export type PluginCameraMoveOptions = z.infer<typeof PluginCameraMoveOptions>
580
-
581
- /**
582
- * Arguments for {@linkcode PluginCameraApi.move}.
583
- */
584
- export const PluginCameraMoveArgs = z.object({
585
- displacement: PluginCameraMoveDisplacement,
586
- options: PluginCameraMoveOptions.optional(),
587
- })
588
- export type PluginCameraMoveArgs = z.infer<typeof PluginCameraMoveArgs>
589
-
590
- /**
591
- * Options for {@linkcode PluginCameraApi.rotate}.
592
- *
593
- * | Property | Type | Description |
594
- * |---|---|---|
595
- * | `durationInSeconds` | `number \| undefined` | Turn over this long (0 to 10; default 0 jumps) |
596
- */
597
- export const PluginCameraRotateOptions = z
598
- .object({ durationInSeconds: DurationInSeconds.optional() })
599
- .strict()
600
- export type PluginCameraRotateOptions = z.infer<
601
- typeof PluginCameraRotateOptions
602
- >
603
-
604
- /**
605
- * Arguments for {@linkcode PluginCameraApi.rotate}.
606
- */
607
- export const PluginCameraRotateArgs = z.object({
608
- yawInDegrees: z.number().finite(),
609
- pitchInDegrees: z.number().finite().optional(),
610
- options: PluginCameraRotateOptions.optional(),
611
- })
612
- export type PluginCameraRotateArgs = z.infer<typeof PluginCameraRotateArgs>
613
-
614
- /**
615
- * How fast the arrow keys walk: the Slow / Normal / Fast navigation setting.
616
- */
617
- export const PluginCameraWalkSpeed = z.enum(["slow", "normal", "fast"])
618
- export type PluginCameraWalkSpeed = z.infer<typeof PluginCameraWalkSpeed>
619
-
620
- /**
621
- * The arrow-key navigation settings — result of
622
- * {@linkcode PluginCameraApi.getNavigationSettings} and
623
- * {@linkcode PluginCameraApi.updateNavigationSettings}.
624
- *
625
- * | Property | Type | Description |
626
- * |---|---|---|
627
- * | `isKeyboardNavigationEnabled` | `boolean` | Whether the arrow keys walk the camera (Project Settings) |
628
- * | `eyeHeight` | `number` | Eye height above the floor, `babylon` units |
629
- * | `walkSpeed` | {@linkcode PluginCameraWalkSpeed} | Arrow-key walking speed |
630
- * | `isCollisionEnabled` | `boolean` | Whether walking stops at walls |
631
- */
632
- export const PluginCameraNavigationSettings = z.object({
633
- isKeyboardNavigationEnabled: z.boolean(),
634
- eyeHeight: z.number(),
635
- walkSpeed: PluginCameraWalkSpeed,
636
- isCollisionEnabled: z.boolean(),
637
- })
638
- export type PluginCameraNavigationSettings = z.infer<
639
- typeof PluginCameraNavigationSettings
640
- >
641
-
642
- /**
643
- * The settings to change in {@linkcode PluginCameraApi.updateNavigationSettings};
644
- * omitted fields keep their value. `eyeHeight` is in `babylon` units, between
645
- * 0.8 m and 2.5 m (3.15 to 9.84 units).
646
- */
647
- export const PluginCameraNavigationSettingsPatch = z
648
- .object({
649
- isKeyboardNavigationEnabled: z.boolean().optional(),
650
- eyeHeight: z.number().finite().min(3.15).max(9.84).optional(),
651
- walkSpeed: PluginCameraWalkSpeed.optional(),
652
- isCollisionEnabled: z.boolean().optional(),
653
- })
654
- .strict()
655
- export type PluginCameraNavigationSettingsPatch = z.infer<
656
- typeof PluginCameraNavigationSettingsPatch
657
- >
658
-
659
- /**
660
- * Arguments for {@linkcode PluginCameraApi.updateNavigationSettings}.
661
- */
662
- export const PluginCameraUpdateNavigationSettingsArgs = z.object({
663
- patch: PluginCameraNavigationSettingsPatch,
664
- })
665
- export type PluginCameraUpdateNavigationSettingsArgs = z.infer<
666
- typeof PluginCameraUpdateNavigationSettingsArgs
667
- >
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../types"
3
+ import { Vec3Components, Vec3Handle } from "../../../handles"
4
+
5
+ /**
6
+ * Camera controls.
7
+ *
8
+ * Position the viewport camera, snap it to a standard orthographic/isometric
9
+ * view, and toggle between the 2D (plan) and 3D modelling modes — mirrors the
10
+ * canvas view menu and the 2D/3D toggle. Like {@linkcode PluginZoomApi}, these
11
+ * are transient VIEW-STATE changes: they are not model edits, so they are not
12
+ * write-gated and are not undoable. Accessed via `snaptrude.core.camera`.
13
+ *
14
+ * Read and set the full camera pose (`getPose`/`setPose`), walk and turn it the
15
+ * way the arrow keys do (`move`/`rotate`), and read or change the arrow-key
16
+ * navigation settings (`getNavigationSettings`/`updateNavigationSettings`).
17
+ * Positions are world coordinates in internal `babylon` units (1 unit =
18
+ * 0.254 m, Y up); yaw is degrees clockwise from +z seen from above, pitch is
19
+ * degrees above level.
20
+ *
21
+ * While Present mode is open these calls set the Design frame a view saved in
22
+ * Present (`presentation.views.create`) is taken from; they never move the
23
+ * Present sheet canvas. To pan, zoom or screenshot the Present canvas, use
24
+ * {@linkcode PluginPresentationCameraApi} (`presentation.camera`).
25
+ */
26
+ export abstract class PluginCameraApi {
27
+ constructor() {}
28
+
29
+ /**
30
+ * Point the camera: place its eye at `eye` looking toward `target` (world
31
+ * coordinates, internal `babylon` units). View-state only — not undoable.
32
+ *
33
+ * While Present is open this sets the Design frame a view saved in Present
34
+ * is taken from; it never moves the Present sheet canvas; use
35
+ * `presentation.camera` for that.
36
+ *
37
+ * @param eye - Camera position as a {@linkcode Vec3Handle}
38
+ * @param target - Point the camera looks at as a {@linkcode Vec3Handle}
39
+ * @returns `true` once the camera has been positioned.
40
+ *
41
+ * @examplePrompt Look at the model from above the north-east corner
42
+ * @examplePrompt Position the camera at (50, 30, 50) looking at the origin
43
+ * @examplePrompt Point the camera at the centre of the building from the side
44
+ * @examplePrompt Set the eye to this point and aim it at that point
45
+ *
46
+ * # Example
47
+ * ```ts
48
+ * const { vec3 } = snaptrude.core.math
49
+ * await snaptrude.core.camera.lookFrom(vec3.new(50, 30, 50), vec3.new(0, 0, 0))
50
+ * ```
51
+ */
52
+ public abstract lookFrom(
53
+ eye: Vec3Handle,
54
+ target: Vec3Handle,
55
+ ): PluginApiReturn<boolean>
56
+
57
+ /**
58
+ * Snap the camera to a standard view — the five orthographic elevations
59
+ * (`top` / `front` / `back` / `left` / `right`) or the 3D `iso` (isometric
60
+ * perspective) view. Mirrors the canvas view menu. View-state only — not
61
+ * undoable. The orthographic presets exit 2D mode first if needed.
62
+ *
63
+ * While Present is open this sets the Design frame a view saved in Present
64
+ * is taken from; it never moves the Present sheet canvas; use
65
+ * `presentation.camera` for that.
66
+ *
67
+ * @param view - The standard view to snap to ({@linkcode PluginStandardView})
68
+ * @returns `true` once the view has been applied.
69
+ *
70
+ * @examplePrompt Switch to the top view
71
+ * @examplePrompt Show me the front elevation
72
+ * @examplePrompt Go to the isometric view
73
+ * @examplePrompt Look at the model from the left
74
+ * @examplePrompt Give me a plan view from the top
75
+ *
76
+ * # Example
77
+ * ```ts
78
+ * await snaptrude.core.camera.setStandardView("top")
79
+ * ```
80
+ */
81
+ public abstract setStandardView(
82
+ view: PluginStandardView,
83
+ ): PluginApiReturn<boolean>
84
+
85
+ /**
86
+ * Get the current camera mode. Paired with {@linkcode PluginCameraApi.setMode}.
87
+ *
88
+ * @returns `"2d"` when the editor is in plan view, `"3d"` otherwise.
89
+ *
90
+ * @examplePrompt Am I in 2D or 3D?
91
+ * @examplePrompt What view mode is the editor in?
92
+ *
93
+ * # Example
94
+ * ```ts
95
+ * if ((await snaptrude.core.camera.getMode()) === "2d") {
96
+ * await snaptrude.core.camera.setMode("3d")
97
+ * }
98
+ * ```
99
+ */
100
+ public abstract getMode(): PluginApiReturn<PluginCameraMode>
101
+
102
+ /**
103
+ * Toggle the modelling mode between `2d` (plan) and `3d`. Mirrors the canvas
104
+ * 2D/3D toggle: `3d` enters the isometric perspective view, `2d` drops to the
105
+ * orthographic plan of the active storey. View-state only — not undoable.
106
+ *
107
+ * While Present is open this sets the Design frame a view saved in Present
108
+ * is taken from; it never moves the Present sheet canvas; use
109
+ * `presentation.camera` for that.
110
+ *
111
+ * @param mode - `"2d"` or `"3d"` ({@linkcode PluginCameraMode})
112
+ * @returns `true` once the mode switch has been requested.
113
+ *
114
+ * @examplePrompt Switch to 3D view
115
+ * @examplePrompt Drop into 2D plan mode
116
+ * @examplePrompt Go back to 3D
117
+ * @examplePrompt Show the floor plan in 2D
118
+ *
119
+ * # Example
120
+ * ```ts
121
+ * await snaptrude.core.camera.setMode("3d")
122
+ * ```
123
+ */
124
+ public abstract setMode(mode: PluginCameraMode): PluginApiReturn<boolean>
125
+
126
+ /**
127
+ * Read the camera's current projection: `"perspective"` (the default 3D
128
+ * view) or `"orthographic"`. In 2D (plan) mode this always reports
129
+ * `"orthographic"` — a plan is an orthographic projection.
130
+ *
131
+ * @returns The current {@linkcode PluginCameraProjection}.
132
+ *
133
+ * @examplePrompt Is the camera in perspective or orthographic?
134
+ * @examplePrompt What projection is the 3D view using?
135
+ * @examplePrompt Check whether perspective is on
136
+ *
137
+ * # Example
138
+ * ```ts
139
+ * const projection = await snaptrude.core.camera.getProjection()
140
+ * console.log(projection) // "perspective" | "orthographic"
141
+ * ```
142
+ */
143
+ public abstract getProjection(): PluginApiReturn<PluginCameraProjection>
144
+
145
+ /**
146
+ * Switch the 3D camera between `"perspective"` and `"orthographic"`
147
+ * projection — the Perspective/Orthographic control in the Design tab's
148
+ * View Settings panel. Like {@linkcode PluginCameraApi.setMode}, this is a
149
+ * transient view-state change: not write-gated, not undoable.
150
+ *
151
+ * In 2D (plan) mode the canvas is always an orthographic plan:
152
+ * `"orthographic"` is accepted as a no-op, while `"perspective"` is
153
+ * rejected — switch to 3D first via `setMode("3d")`.
154
+ *
155
+ * While Present is open this sets the Design frame a view saved in Present
156
+ * is taken from; it never moves the Present sheet canvas; use
157
+ * `presentation.camera` for that.
158
+ *
159
+ * @param projection - `"perspective"` or `"orthographic"` ({@linkcode PluginCameraProjection})
160
+ * @returns `true` once the projection has been applied.
161
+ *
162
+ * @examplePrompt Switch the camera to orthographic
163
+ * @examplePrompt Turn perspective off
164
+ * @examplePrompt Give me a perspective view of the model
165
+ * @examplePrompt Make the 3D view orthographic like an axonometric drawing
166
+ *
167
+ * # Example
168
+ * ```ts
169
+ * await snaptrude.core.camera.setProjection("orthographic")
170
+ * const projection = await snaptrude.core.camera.getProjection() // "orthographic"
171
+ * ```
172
+ */
173
+ public abstract setProjection(
174
+ projection: PluginCameraProjection,
175
+ ): PluginApiReturn<boolean>
176
+
177
+ /**
178
+ * Zoom (fit) the camera to all geometry in the scene — the "zoom extents"
179
+ * action. View-state only — not undoable. Canonical home of the zoom-extents
180
+ * read (the deprecated `core.zoom.extents`).
181
+ *
182
+ * While Present is open this sets the Design frame a view saved in Present
183
+ * is taken from; it never moves the Present sheet canvas; use
184
+ * `presentation.camera` for that.
185
+ *
186
+ * @returns `true` once the camera has been framed to the scene.
187
+ *
188
+ * @examplePrompt Zoom out so I can see the whole model
189
+ * @examplePrompt Fit everything in the view
190
+ * @examplePrompt Frame the entire building in the viewport
191
+ * @examplePrompt Do a zoom extents on the canvas
192
+ *
193
+ * # Example
194
+ * ```ts
195
+ * await snaptrude.core.camera.zoomExtents()
196
+ * ```
197
+ */
198
+ public abstract zoomExtents(): PluginApiReturn<boolean>
199
+
200
+ /**
201
+ * Zoom (fit) the camera to the current selection. View-state only — not
202
+ * undoable. Canonical home of the zoom-to-selection read (the deprecated
203
+ * `core.zoom.selection`).
204
+ *
205
+ * While Present is open this sets the Design frame a view saved in Present
206
+ * is taken from; it never moves the Present sheet canvas; use
207
+ * `presentation.camera` for that.
208
+ *
209
+ * @returns `true` if there was a selection to frame; `false` if nothing is
210
+ * selected (no-op).
211
+ *
212
+ * @examplePrompt Zoom in on what I have selected
213
+ * @examplePrompt Frame the selected walls in the view
214
+ * @examplePrompt Focus the camera on my current selection
215
+ * @examplePrompt Fit the view to the selected room
216
+ *
217
+ * # Example
218
+ * ```ts
219
+ * await snaptrude.core.camera.zoomSelection()
220
+ * ```
221
+ */
222
+ public abstract zoomSelection(): PluginApiReturn<boolean>
223
+
224
+ /**
225
+ * Read where the camera is and where it looks: the eye and target positions
226
+ * (world coordinates, internal `babylon` units), the view direction as yaw
227
+ * and pitch, the vertical field of view, the projection and the 2D/3D mode.
228
+ * Paired with {@linkcode PluginCameraApi.setPose}.
229
+ *
230
+ * @returns The current {@linkcode PluginCameraPose}.
231
+ * @throws PRECONDITION_FAILED when there is no active camera.
232
+ *
233
+ * @examplePrompt Where is the camera right now?
234
+ * @examplePrompt Remember this viewpoint so we can come back to it
235
+ * @examplePrompt Which way is the camera facing?
236
+ * @examplePrompt How high above the ground is the camera?
237
+ *
238
+ * # Example
239
+ * ```ts
240
+ * const pose = await snaptrude.core.camera.getPose()
241
+ * console.log(pose.eye, pose.yawInDegrees, pose.pitchInDegrees)
242
+ * ```
243
+ */
244
+ public abstract getPose(): PluginApiReturn<PluginCameraPose>
245
+
246
+ /**
247
+ * Place the camera, optionally easing there over `options.durationInSeconds`,
248
+ * and resolve once the new view has been drawn, so a capture that follows sees
249
+ * it without a fixed wait. `pose` is one of:
250
+ *
251
+ * - `{ eye, target }`: stand at `eye` looking at `target`, as
252
+ * {@linkcode PluginCameraApi.lookFrom} does with handles;
253
+ * - `{ eye, yawInDegrees, pitchInDegrees }`: stand at `eye` looking along a
254
+ * direction;
255
+ * - `{ standAt, yawInDegrees? }`: stand on the floor, stair, terrain or
256
+ * ground at or below `standAt`, at the user's eye height above it (the `I`
257
+ * key), facing `yawInDegrees` (the current yaw when omitted).
258
+ *
259
+ * Stops a playing walkthrough and switches from 2D plan view to 3D first.
260
+ * View-state only: not write-gated, not undoable.
261
+ *
262
+ * @param pose - Where to put the camera ({@linkcode PluginCameraPoseInput})
263
+ * @param options - `durationInSeconds`: ease over this long (0 to 10, default 0 jumps)
264
+ * @returns The camera's {@linkcode PluginCameraPose} once it has arrived.
265
+ * @throws PRECONDITION_FAILED when there is no active camera, while a
266
+ * walkthrough export is recording, or when `standAt` lies below the ground
267
+ * with nothing under it. VALIDATION when `eye` and `target` coincide or a
268
+ * pitch is beyond ±89°.
269
+ *
270
+ * @examplePrompt Stand in the living room at eye level facing the window
271
+ * @examplePrompt Move the camera to (40, 12, 30) looking at the entrance
272
+ * @examplePrompt Fly the camera smoothly over to the courtyard
273
+ * @examplePrompt Put me back at the viewpoint we saved earlier
274
+ *
275
+ * # Example
276
+ * ```ts
277
+ * const { camera } = snaptrude.core
278
+ * await camera.setPose({ standAt: { x: 20, y: 0, z: 35 }, yawInDegrees: 90 })
279
+ * await camera.setPose(
280
+ * { eye: { x: 60, y: 25, z: 60 }, target: { x: 0, y: 5, z: 0 } },
281
+ * { durationInSeconds: 1.5 },
282
+ * )
283
+ * ```
284
+ */
285
+ public abstract setPose(
286
+ pose: PluginCameraPoseInput,
287
+ options?: PluginCameraSetPoseOptions,
288
+ ): PluginApiReturn<PluginCameraPose>
289
+
290
+ /**
291
+ * Walk or fly the camera by a displacement in its own frame: `forward` along
292
+ * the level view direction, `right` to its side and `up` vertically, in
293
+ * internal `babylon` units. The view direction does not change. With
294
+ * `options.followsFloor` the camera keeps its height above the floor as it
295
+ * goes, climbing and descending stairs and ramps the way the arrow keys do.
296
+ * Stops a playing walkthrough and switches from 2D plan view to 3D first.
297
+ * View-state only: not write-gated, not undoable.
298
+ *
299
+ * @param displacement - {@linkcode PluginCameraMoveDisplacement}; omitted components are 0
300
+ * @param options - `followsFloor` (default `false`) and `durationInSeconds` (0 to 10, default 0)
301
+ * @returns The camera's {@linkcode PluginCameraPose} after the move.
302
+ * @throws PRECONDITION_FAILED when there is no active camera, or while a
303
+ * walkthrough export is recording.
304
+ *
305
+ * @examplePrompt Walk forward 3 metres
306
+ * @examplePrompt Step to the right a little
307
+ * @examplePrompt Walk up the stairs ahead
308
+ * @examplePrompt Raise the camera by 2 metres
309
+ *
310
+ * # Example
311
+ * ```ts
312
+ * const metre = 1 / 0.254
313
+ * await snaptrude.core.camera.move(
314
+ * { forward: 3 * metre },
315
+ * { followsFloor: true, durationInSeconds: 2 },
316
+ * )
317
+ * ```
318
+ */
319
+ public abstract move(
320
+ displacement: PluginCameraMoveDisplacement,
321
+ options?: PluginCameraMoveOptions,
322
+ ): PluginApiReturn<PluginCameraPose>
323
+
324
+ /**
325
+ * Turn the camera in place by signed angles: `yawInDegrees` to the right
326
+ * (clockwise seen from above) and `pitchInDegrees` up. The eye does not move;
327
+ * the resulting pitch is kept within ±89°. Stops a playing walkthrough and
328
+ * switches from 2D plan view to 3D first. View-state only: not write-gated,
329
+ * not undoable.
330
+ *
331
+ * @param yawInDegrees - Turn to the right by this much (negative turns left)
332
+ * @param pitchInDegrees - Tilt up by this much (negative tilts down; default 0)
333
+ * @param options - `durationInSeconds` (0 to 10, default 0)
334
+ * @returns The camera's {@linkcode PluginCameraPose} after turning.
335
+ * @throws PRECONDITION_FAILED when there is no active camera, or while a
336
+ * walkthrough export is recording.
337
+ *
338
+ * @examplePrompt Turn around
339
+ * @examplePrompt Look 45 degrees to the left
340
+ * @examplePrompt Tilt the camera down a bit
341
+ *
342
+ * # Example
343
+ * ```ts
344
+ * await snaptrude.core.camera.rotate(180, 0, { durationInSeconds: 1 })
345
+ * ```
346
+ */
347
+ public abstract rotate(
348
+ yawInDegrees: number,
349
+ pitchInDegrees?: number,
350
+ options?: PluginCameraRotateOptions,
351
+ ): PluginApiReturn<PluginCameraPose>
352
+
353
+ /**
354
+ * Read the arrow-key navigation settings: whether the arrow keys walk the
355
+ * camera, the eye height used by `setPose`'s `standAt` and by walkthroughs
356
+ * that follow the floor, the walking speed, and whether walking stops at
357
+ * walls. Paired with {@linkcode PluginCameraApi.updateNavigationSettings}.
358
+ *
359
+ * @returns The current {@linkcode PluginCameraNavigationSettings}.
360
+ *
361
+ * @examplePrompt Is arrow-key navigation on?
362
+ * @examplePrompt What eye height does the camera use?
363
+ *
364
+ * # Example
365
+ * ```ts
366
+ * const { isKeyboardNavigationEnabled } =
367
+ * await snaptrude.core.camera.getNavigationSettings()
368
+ * ```
369
+ */
370
+ public abstract getNavigationSettings(): PluginApiReturn<PluginCameraNavigationSettings>
371
+
372
+ /**
373
+ * Change arrow-key navigation settings; only the fields given change.
374
+ * `isKeyboardNavigationEnabled` is the user's Project Settings switch and is
375
+ * saved on this device; the other settings last for the session.
376
+ * Write-gated: this changes the user's preferences, not just the view.
377
+ *
378
+ * @param patch - The settings to change ({@linkcode PluginCameraNavigationSettingsPatch})
379
+ * @returns The {@linkcode PluginCameraNavigationSettings} after the change.
380
+ * @throws METHOD_NOT_PERMITTED when plugin writes are disabled.
381
+ *
382
+ * @examplePrompt Turn off arrow-key navigation
383
+ * @examplePrompt Use a 1.6 m eye height
384
+ * @examplePrompt Make walking stop at walls
385
+ *
386
+ * # Example
387
+ * ```ts
388
+ * await snaptrude.core.camera.updateNavigationSettings({
389
+ * eyeHeight: 1.6 / 0.254,
390
+ * isCollisionEnabled: true,
391
+ * })
392
+ * ```
393
+ */
394
+ public abstract updateNavigationSettings(
395
+ patch: PluginCameraNavigationSettingsPatch,
396
+ ): PluginApiReturn<PluginCameraNavigationSettings>
397
+ }
398
+
399
+ /**
400
+ * A standard camera view: the five orthographic elevations (`top`/`front`/
401
+ * `back`/`left`/`right`) or the 3D isometric perspective (`iso`).
402
+ */
403
+ export const PluginStandardView = z.enum([
404
+ "top",
405
+ "front",
406
+ "back",
407
+ "left",
408
+ "right",
409
+ "iso",
410
+ ])
411
+ export type PluginStandardView = z.infer<typeof PluginStandardView>
412
+
413
+ /**
414
+ * The modelling mode: `2d` (orthographic plan) or `3d` (isometric perspective).
415
+ */
416
+ export const PluginCameraMode = z.enum(["2d", "3d"])
417
+ export type PluginCameraMode = z.infer<typeof PluginCameraMode>
418
+
419
+ /**
420
+ * The 3D camera projection: `perspective` (the default) or `orthographic` —
421
+ * the Perspective/Orthographic control in the Design tab's View Settings panel.
422
+ */
423
+ export const PluginCameraProjection = z.enum(["perspective", "orthographic"])
424
+ export type PluginCameraProjection = z.infer<typeof PluginCameraProjection>
425
+
426
+ /**
427
+ * Arguments for {@linkcode PluginCameraApi.lookFrom}.
428
+ *
429
+ * | Property | Type | Description |
430
+ * |---|---|---|
431
+ * | `eye` | {@linkcode Vec3Handle} | Camera position (world, `babylon` units) |
432
+ * | `target` | {@linkcode Vec3Handle} | Point the camera looks at |
433
+ */
434
+ export const PluginCameraLookFromArgs = z.object({
435
+ eye: Vec3Handle,
436
+ target: Vec3Handle,
437
+ })
438
+ export type PluginCameraLookFromArgs = z.infer<typeof PluginCameraLookFromArgs>
439
+
440
+ /**
441
+ * Arguments for {@linkcode PluginCameraApi.setStandardView}.
442
+ *
443
+ * | Property | Type | Description |
444
+ * |---|---|---|
445
+ * | `view` | {@linkcode PluginStandardView} | The standard view to snap to |
446
+ */
447
+ export const PluginCameraSetStandardViewArgs = z.object({
448
+ view: PluginStandardView,
449
+ })
450
+ export type PluginCameraSetStandardViewArgs = z.infer<
451
+ typeof PluginCameraSetStandardViewArgs
452
+ >
453
+
454
+ /**
455
+ * Arguments for {@linkcode PluginCameraApi.setMode}.
456
+ *
457
+ * | Property | Type | Description |
458
+ * |---|---|---|
459
+ * | `mode` | {@linkcode PluginCameraMode} | `"2d"` or `"3d"` |
460
+ */
461
+ export const PluginCameraSetModeArgs = z.object({
462
+ mode: PluginCameraMode,
463
+ })
464
+ export type PluginCameraSetModeArgs = z.infer<typeof PluginCameraSetModeArgs>
465
+
466
+ /**
467
+ * Arguments for {@linkcode PluginCameraApi.setProjection}.
468
+ *
469
+ * | Property | Type | Description |
470
+ * |---|---|---|
471
+ * | `projection` | {@linkcode PluginCameraProjection} | `"perspective"` or `"orthographic"` |
472
+ */
473
+ export const PluginCameraSetProjectionArgs = z.object({
474
+ projection: PluginCameraProjection,
475
+ })
476
+ export type PluginCameraSetProjectionArgs = z.infer<
477
+ typeof PluginCameraSetProjectionArgs
478
+ >
479
+
480
+ // Plain {x, y, z} record with finite components (the brepFromRevolution `axisOrigin` pattern).
481
+ const FiniteVec3Components = z.object({
482
+ x: z.number().finite(),
483
+ y: z.number().finite(),
484
+ z: z.number().finite(),
485
+ })
486
+
487
+ /** Pitch is kept off the vertical, where yaw has no meaning. */
488
+ const PitchInDegrees = z.number().finite().min(-89).max(89)
489
+
490
+ /** How long a camera move eases for; 0 jumps. */
491
+ const DurationInSeconds = z.number().finite().min(0).max(10)
492
+
493
+ /**
494
+ * The camera's pose — result of {@linkcode PluginCameraApi.getPose},
495
+ * {@linkcode PluginCameraApi.setPose}, {@linkcode PluginCameraApi.move} and
496
+ * {@linkcode PluginCameraApi.rotate}.
497
+ *
498
+ * | Property | Type | Description |
499
+ * |---|---|---|
500
+ * | `eye` | `{ x, y, z }` | Camera position (world, `babylon` units) |
501
+ * | `target` | `{ x, y, z }` | Point the camera looks at |
502
+ * | `yawInDegrees` | `number` | View direction, degrees clockwise from +z seen from above (-180 to 180) |
503
+ * | `pitchInDegrees` | `number` | View direction, degrees above level (negative looks down) |
504
+ * | `fieldOfViewInDegrees` | `number` | Vertical field of view |
505
+ * | `projection` | {@linkcode PluginCameraProjection} | `"perspective"` or `"orthographic"` |
506
+ * | `mode` | {@linkcode PluginCameraMode} | `"2d"` or `"3d"` |
507
+ */
508
+ export const PluginCameraPose = z.object({
509
+ eye: Vec3Components,
510
+ target: Vec3Components,
511
+ yawInDegrees: z.number(),
512
+ pitchInDegrees: z.number(),
513
+ fieldOfViewInDegrees: z.number(),
514
+ projection: PluginCameraProjection,
515
+ mode: PluginCameraMode,
516
+ })
517
+ export type PluginCameraPose = z.infer<typeof PluginCameraPose>
518
+
519
+ /**
520
+ * Where {@linkcode PluginCameraApi.setPose} puts the camera — exactly one of:
521
+ *
522
+ * | Shape | Meaning |
523
+ * |---|---|
524
+ * | `{ eye, target }` | Stand at `eye` looking at `target` |
525
+ * | `{ eye, yawInDegrees, pitchInDegrees }` | Stand at `eye` looking along a direction (pitch within ±89°) |
526
+ * | `{ standAt, yawInDegrees? }` | Stand at eye height on the floor, stair, terrain or ground at or below `standAt`, facing `yawInDegrees` (default: current yaw) |
527
+ *
528
+ * Points are plain `{ x, y, z }` world coordinates in `babylon` units.
529
+ */
530
+ export const PluginCameraPoseInput = z.union([
531
+ z
532
+ .object({ eye: FiniteVec3Components, target: FiniteVec3Components })
533
+ .strict(),
534
+ z
535
+ .object({
536
+ eye: FiniteVec3Components,
537
+ yawInDegrees: z.number().finite(),
538
+ pitchInDegrees: PitchInDegrees,
539
+ })
540
+ .strict(),
541
+ z
542
+ .object({
543
+ standAt: FiniteVec3Components,
544
+ yawInDegrees: z.number().finite().optional(),
545
+ })
546
+ .strict(),
547
+ ])
548
+ export type PluginCameraPoseInput = z.infer<typeof PluginCameraPoseInput>
549
+
550
+ /**
551
+ * Options for {@linkcode PluginCameraApi.setPose}.
552
+ *
553
+ * | Property | Type | Description |
554
+ * |---|---|---|
555
+ * | `durationInSeconds` | `number \| undefined` | Ease to the pose over this long (0 to 10; default 0 jumps) |
556
+ */
557
+ export const PluginCameraSetPoseOptions = z
558
+ .object({ durationInSeconds: DurationInSeconds.optional() })
559
+ .strict()
560
+ export type PluginCameraSetPoseOptions = z.infer<
561
+ typeof PluginCameraSetPoseOptions
562
+ >
563
+
564
+ /**
565
+ * Arguments for {@linkcode PluginCameraApi.setPose}.
566
+ */
567
+ export const PluginCameraSetPoseArgs = z.object({
568
+ pose: PluginCameraPoseInput,
569
+ options: PluginCameraSetPoseOptions.optional(),
570
+ })
571
+ export type PluginCameraSetPoseArgs = z.infer<typeof PluginCameraSetPoseArgs>
572
+
573
+ /**
574
+ * A displacement in the camera's own frame, for {@linkcode PluginCameraApi.move}
575
+ * (`babylon` units; omitted components are 0).
576
+ *
577
+ * | Property | Type | Description |
578
+ * |---|---|---|
579
+ * | `forward` | `number \| undefined` | Along the level view direction (negative walks back) |
580
+ * | `right` | `number \| undefined` | To the camera's right (negative steps left) |
581
+ * | `up` | `number \| undefined` | Vertically (negative descends) |
582
+ */
583
+ export const PluginCameraMoveDisplacement = z
584
+ .object({
585
+ forward: z.number().finite().optional(),
586
+ right: z.number().finite().optional(),
587
+ up: z.number().finite().optional(),
588
+ })
589
+ .strict()
590
+ export type PluginCameraMoveDisplacement = z.infer<
591
+ typeof PluginCameraMoveDisplacement
592
+ >
593
+
594
+ /**
595
+ * Options for {@linkcode PluginCameraApi.move}.
596
+ *
597
+ * | Property | Type | Description |
598
+ * |---|---|---|
599
+ * | `followsFloor` | `boolean \| undefined` | Keep the height above the floor, climbing stairs and ramps (default `false`) |
600
+ * | `durationInSeconds` | `number \| undefined` | Walk over this long (0 to 10; default 0 jumps) |
601
+ */
602
+ export const PluginCameraMoveOptions = z
603
+ .object({
604
+ followsFloor: z.boolean().optional(),
605
+ durationInSeconds: DurationInSeconds.optional(),
606
+ })
607
+ .strict()
608
+ export type PluginCameraMoveOptions = z.infer<typeof PluginCameraMoveOptions>
609
+
610
+ /**
611
+ * Arguments for {@linkcode PluginCameraApi.move}.
612
+ */
613
+ export const PluginCameraMoveArgs = z.object({
614
+ displacement: PluginCameraMoveDisplacement,
615
+ options: PluginCameraMoveOptions.optional(),
616
+ })
617
+ export type PluginCameraMoveArgs = z.infer<typeof PluginCameraMoveArgs>
618
+
619
+ /**
620
+ * Options for {@linkcode PluginCameraApi.rotate}.
621
+ *
622
+ * | Property | Type | Description |
623
+ * |---|---|---|
624
+ * | `durationInSeconds` | `number \| undefined` | Turn over this long (0 to 10; default 0 jumps) |
625
+ */
626
+ export const PluginCameraRotateOptions = z
627
+ .object({ durationInSeconds: DurationInSeconds.optional() })
628
+ .strict()
629
+ export type PluginCameraRotateOptions = z.infer<
630
+ typeof PluginCameraRotateOptions
631
+ >
632
+
633
+ /**
634
+ * Arguments for {@linkcode PluginCameraApi.rotate}.
635
+ */
636
+ export const PluginCameraRotateArgs = z.object({
637
+ yawInDegrees: z.number().finite(),
638
+ pitchInDegrees: z.number().finite().optional(),
639
+ options: PluginCameraRotateOptions.optional(),
640
+ })
641
+ export type PluginCameraRotateArgs = z.infer<typeof PluginCameraRotateArgs>
642
+
643
+ /**
644
+ * How fast the arrow keys walk: the Slow / Normal / Fast navigation setting.
645
+ */
646
+ export const PluginCameraWalkSpeed = z.enum(["slow", "normal", "fast"])
647
+ export type PluginCameraWalkSpeed = z.infer<typeof PluginCameraWalkSpeed>
648
+
649
+ /**
650
+ * The arrow-key navigation settings — result of
651
+ * {@linkcode PluginCameraApi.getNavigationSettings} and
652
+ * {@linkcode PluginCameraApi.updateNavigationSettings}.
653
+ *
654
+ * | Property | Type | Description |
655
+ * |---|---|---|
656
+ * | `isKeyboardNavigationEnabled` | `boolean` | Whether the arrow keys walk the camera (Project Settings) |
657
+ * | `eyeHeight` | `number` | Eye height above the floor, `babylon` units |
658
+ * | `walkSpeed` | {@linkcode PluginCameraWalkSpeed} | Arrow-key walking speed |
659
+ * | `isCollisionEnabled` | `boolean` | Whether walking stops at walls |
660
+ */
661
+ export const PluginCameraNavigationSettings = z.object({
662
+ isKeyboardNavigationEnabled: z.boolean(),
663
+ eyeHeight: z.number(),
664
+ walkSpeed: PluginCameraWalkSpeed,
665
+ isCollisionEnabled: z.boolean(),
666
+ })
667
+ export type PluginCameraNavigationSettings = z.infer<
668
+ typeof PluginCameraNavigationSettings
669
+ >
670
+
671
+ /**
672
+ * The settings to change in {@linkcode PluginCameraApi.updateNavigationSettings};
673
+ * omitted fields keep their value. `eyeHeight` is in `babylon` units, between
674
+ * 0.8 m and 2.5 m (3.15 to 9.84 units).
675
+ */
676
+ export const PluginCameraNavigationSettingsPatch = z
677
+ .object({
678
+ isKeyboardNavigationEnabled: z.boolean().optional(),
679
+ eyeHeight: z.number().finite().min(3.15).max(9.84).optional(),
680
+ walkSpeed: PluginCameraWalkSpeed.optional(),
681
+ isCollisionEnabled: z.boolean().optional(),
682
+ })
683
+ .strict()
684
+ export type PluginCameraNavigationSettingsPatch = z.infer<
685
+ typeof PluginCameraNavigationSettingsPatch
686
+ >
687
+
688
+ /**
689
+ * Arguments for {@linkcode PluginCameraApi.updateNavigationSettings}.
690
+ */
691
+ export const PluginCameraUpdateNavigationSettingsArgs = z.object({
692
+ patch: PluginCameraNavigationSettingsPatch,
693
+ })
694
+ export type PluginCameraUpdateNavigationSettingsArgs = z.infer<
695
+ typeof PluginCameraUpdateNavigationSettingsArgs
696
+ >