lecodes-sdk 2.2.9 → 2.2.10

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 (61) hide show
  1. package/dist/global.d.ts +42 -1
  2. package/dist/types/gl/Camera.d.ts +5 -2
  3. package/dist/types/gl/Node.d.ts +0 -7
  4. package/dist/types/gl/Scene.d.ts +6 -24
  5. package/dist/types/inject.d.ts +5 -1
  6. package/dist/types/plugin.d.ts +27 -0
  7. package/dist/types/plugins/gen/ar/sdk/ar.d.ts +228 -0
  8. package/dist/types/plugins/gen/ar/sdk/ar.gen.d.ts +73 -0
  9. package/dist/types/plugins/gen/ar/sdk/controls.d.ts +28 -0
  10. package/dist/types/plugins/gen/audio-recorder/sdk/audio-recorder.d.ts +43 -0
  11. package/dist/types/plugins/gen/audio-recorder/sdk/audio-recorder.gen.d.ts +47 -0
  12. package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +6 -2
  13. package/dist/types/plugins/gen/speech/sdk/speech.d.ts +44 -0
  14. package/dist/types/plugins/gen/speech/sdk/speech.gen.d.ts +39 -0
  15. package/dist/types/runtime/permissions.d.ts +16 -0
  16. package/dist/types/version.d.ts +1 -1
  17. package/dist/types.json +1 -1
  18. package/package.json +1 -1
  19. package/prompts/ar.md +81 -48
  20. package/prompts/dist/2d-game.md +1567 -0
  21. package/prompts/dist/3d-app.md +1712 -0
  22. package/prompts/dist/ar-app.md +1585 -0
  23. package/prompts/dist/concept.md +49 -0
  24. package/prompts/dist/design.md +521 -0
  25. package/prompts/dist/ui-app.md +1175 -0
  26. package/prompts/index.md +3 -1
  27. package/src/animate/tween/Timeline.ts +175 -175
  28. package/src/bridges/device.d.ts +20 -6
  29. package/src/bridges/gl.d.ts +33 -19
  30. package/src/compile/header.ts +11 -4
  31. package/src/gl/Camera.ts +5 -2
  32. package/src/gl/CameraPlace.ts +52 -52
  33. package/src/gl/Light.ts +257 -257
  34. package/src/gl/Mesh.ts +120 -120
  35. package/src/gl/Node.ts +0 -8
  36. package/src/gl/Scene.ts +14 -81
  37. package/src/gl/animation/DynamicBone.ts +482 -482
  38. package/src/gl/scenarios.ts +291 -291
  39. package/src/inject.ts +13 -1
  40. package/src/plugin.ts +45 -2
  41. package/src/plugins/gen/ar/contract.d.ts +118 -0
  42. package/src/plugins/gen/ar/sdk/ar.gen.ts +112 -0
  43. package/src/plugins/gen/ar/sdk/ar.ts +699 -0
  44. package/src/plugins/gen/ar/sdk/controls.ts +148 -0
  45. package/src/plugins/gen/audio-recorder/contract.d.ts +64 -0
  46. package/src/plugins/gen/audio-recorder/sdk/audio-recorder.gen.ts +76 -0
  47. package/src/plugins/gen/audio-recorder/sdk/audio-recorder.ts +113 -0
  48. package/src/plugins/gen/geolocation/contract.d.ts +7 -5
  49. package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +6 -2
  50. package/src/plugins/gen/speech/contract.d.ts +67 -0
  51. package/src/plugins/gen/speech/sdk/speech.gen.ts +64 -0
  52. package/src/plugins/gen/speech/sdk/speech.ts +104 -0
  53. package/src/runtime/permissions.ts +40 -0
  54. package/src/server/auth/host.ts +1 -1
  55. package/src/ui/presentable.ts +5 -0
  56. package/src/ui/router.ts +4 -3
  57. package/src/version.ts +1 -1
  58. package/dist/types/gl/controls.d.ts +0 -19
  59. package/dist/types/plugins/permission.d.ts +0 -1
  60. package/src/gl/controls.ts +0 -95
  61. package/src/plugins/permission.ts +0 -8
package/dist/global.d.ts CHANGED
@@ -6,11 +6,14 @@ import type * as SDK from "./types/inject"
6
6
  import type * as SERVER from "./types/server/inject"
7
7
 
8
8
  declare global {
9
+ const ARPlane: typeof SDK.ARPlane
9
10
  const ARScene: typeof SDK.ARScene
11
+ const Anchor: typeof SDK.Anchor
10
12
  const AnimationClip: typeof SDK.AnimationClip
11
13
  const Animator: typeof SDK.Animator
12
14
  const Aspect: typeof SDK.Aspect
13
15
  const AudioPlayer: typeof SDK.AudioPlayer
16
+ const AudioRecorder: typeof SDK.AudioRecorder
14
17
  const AudioSource: typeof SDK.AudioSource
15
18
  const AudioZone: typeof SDK.AudioZone
16
19
  const Autotile2D: typeof SDK.Autotile2D
@@ -41,6 +44,7 @@ declare global {
41
44
  const Geometry: typeof SDK.Geometry
42
45
  const Gizmos: typeof SDK.Gizmos
43
46
  const IK: typeof SDK.IK
47
+ const ImageAnchor: typeof SDK.ImageAnchor
44
48
  const Input: typeof SDK.Input
45
49
  const InputChannel: typeof SDK.InputChannel
46
50
  const InspectorUI: typeof SDK.InspectorUI
@@ -110,6 +114,7 @@ declare global {
110
114
  const Shape: typeof SDK.Shape
111
115
  const Shape2D: typeof SDK.Shape2D
112
116
  const Sound: typeof SDK.Sound
117
+ const SpeechRecognizer: typeof SDK.SpeechRecognizer
113
118
  const Spin: typeof SDK.Spin
114
119
  const Sprite: typeof SDK.Sprite
115
120
  const SpriteAnimation: typeof SDK.SpriteAnimation
@@ -208,6 +213,7 @@ declare global {
208
213
  const openFilePicker: typeof SDK.openFilePicker
209
214
  const openURL: typeof SDK.openURL
210
215
  const packTile: typeof SDK.packTile
216
+ const permissions: typeof SDK.permissions
211
217
  const rawCell: typeof SDK.rawCell
212
218
  const rawIndex: typeof SDK.rawIndex
213
219
  const ref: typeof SDK.ref
@@ -228,10 +234,31 @@ declare global {
228
234
  const tileTurns: typeof SDK.tileTurns
229
235
  const toast: typeof SDK.toast
230
236
  const use: typeof SDK.use
231
- type ARScene<T extends ARMode = "default"> = SDK.ARScene<T>
237
+ type ARError = SDK.ARError
238
+ type ARErrorCode = SDK.ARErrorCode
239
+ type ARHitResult = SDK.ARHitResult
240
+ type ARHitTarget = SDK.ARHitTarget
241
+ type ARLightEstimate = SDK.ARLightEstimate
242
+ type ARMode = SDK.ARMode
243
+ type AROpenOptions = SDK.AROpenOptions
244
+ type ARPlane = SDK.ARPlane
245
+ type ARPlaneChange = SDK.ARPlaneChange
246
+ type ARPlaneDetection = SDK.ARPlaneDetection
247
+ type ARPlaneEvent = SDK.ARPlaneEvent
248
+ type ARPlaneType = SDK.ARPlaneType
249
+ type ARPose = SDK.ARPose
250
+ type ARPoseLike = SDK.ARPoseLike
251
+ type ARScene = SDK.ARScene
252
+ type ARSceneEvents = SDK.ARSceneEvents
253
+ type ARSceneOptions = SDK.ARSceneOptions
254
+ type ARTrackingReason = SDK.ARTrackingReason
255
+ type ARTrackingState = SDK.ARTrackingState
256
+ type ARWorldAlignment = SDK.ARWorldAlignment
232
257
  type Action<A extends unknown[], R> = SDK.Action<A, R>
233
258
  type ActiveClip = SDK.ActiveClip
234
259
  type AeroConfig = SDK.AeroConfig
260
+ type Anchor = SDK.Anchor
261
+ type AnchorEvents = SDK.AnchorEvents
235
262
  type AnimateOptions<T extends AnimateValue> = SDK.AnimateOptions<T>
236
263
  type AnimateOut<T> = SDK.AnimateOut<T>
237
264
  type AnimateValue = SDK.AnimateValue
@@ -243,6 +270,8 @@ declare global {
243
270
  type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = SDK.AspectEntry<A>
244
271
  type AudioCone = SDK.AudioCone
245
272
  type AudioPlayer = SDK.AudioPlayer
273
+ type AudioRecorder = SDK.AudioRecorder
274
+ type AudioRecorderEvents = SDK.AudioRecorderEvents
246
275
  type AudioSource = SDK.AudioSource
247
276
  type AudioStats = SDK.AudioStats
248
277
  type AudioZone = SDK.AudioZone
@@ -305,6 +334,7 @@ declare global {
305
334
  type EditorRayHit = SDK.EditorRayHit
306
335
  type EditorToolHooks = SDK.EditorToolHooks
307
336
  type EditorWindowFn = SDK.EditorWindowFn
337
+ type EndReason = SDK.EndReason
308
338
  type EngineConfig = SDK.EngineConfig
309
339
  type EventMap = SDK.EventMap
310
340
  type Failure = SDK.Failure
@@ -333,6 +363,7 @@ declare global {
333
363
  type HapticStyle = SDK.HapticStyle
334
364
  type IKLookAt = SDK.IKLookAt
335
365
  type IKTwoBone = SDK.IKTwoBone
366
+ type ImageAnchor = SDK.ImageAnchor
336
367
  type InputEventName = SDK.InputEventName
337
368
  type InputGamepadEvent = SDK.InputGamepadEvent
338
369
  type InputKeyEvent = SDK.InputKeyEvent
@@ -434,6 +465,8 @@ declare global {
434
465
  type PatchMaterial = SDK.PatchMaterial
435
466
  type PatchSlots = SDK.PatchSlots
436
467
  type PathMaterial = SDK.PathMaterial
468
+ type PermissionKind = SDK.PermissionKind
469
+ type PermissionState = SDK.PermissionState
437
470
  type Physics = SDK.Physics
438
471
  type Physics2D = SDK.Physics2D
439
472
  type PhysicsGroup2D = SDK.PhysicsGroup2D
@@ -478,6 +511,9 @@ declare global {
478
511
  type RagdollHitOptions = SDK.RagdollHitOptions
479
512
  type RagdollPart = SDK.RagdollPart
480
513
  type Ray = SDK.Ray
514
+ type RecordOptions = SDK.RecordOptions
515
+ type RecorderState = SDK.RecorderState
516
+ type Recording = SDK.Recording
481
517
  type Replicated = SDK.Replicated
482
518
  type Resource<T> = SDK.Resource<T>
483
519
  type ReverbParams = SDK.ReverbParams
@@ -506,6 +542,11 @@ declare global {
506
542
  type Sound = SDK.Sound
507
543
  type SoundOptions = SDK.SoundOptions
508
544
  type SpatialOptions = SDK.SpatialOptions
545
+ type SpeechErrorCode = SDK.SpeechErrorCode
546
+ type SpeechOptions = SDK.SpeechOptions
547
+ type SpeechRecognizer = SDK.SpeechRecognizer
548
+ type SpeechRecognizerEvents = SDK.SpeechRecognizerEvents
549
+ type SpeechResult = SDK.SpeechResult
509
550
  type Spin = SDK.Spin
510
551
  type Sprite = SDK.Sprite
511
552
  type SpriteAnimation = SDK.SpriteAnimation
@@ -85,9 +85,12 @@ export declare class Camera extends Node {
85
85
  node: Node;
86
86
  applyTo(camera: Camera): void;
87
87
  } | null): this;
88
+ /** The scene view's [width, height] in logical units — the units of the scene's touches
89
+ * (`clientX` / `clientY`) and of `getRay`, on every host; × `device.pixelRatio` for device px.
90
+ * [0, 0] before the scene has a viewport. */
88
91
  get displaySize(): [number, number];
89
- /** World-space ray direction through a screen pixel. */
92
+ /** World-space ray direction through a point of the scene view (logical units, as a touch's). */
90
93
  getViewDirection(screenX: number, screenY: number): Vec3;
91
- /** A pick ray from the camera through a screen pixel. */
94
+ /** A pick ray from the camera through a point of the scene view (logical units, as a touch's). */
92
95
  getRay(screenX: number, screenY: number): Ray;
93
96
  }
@@ -20,10 +20,6 @@ export type NodeTweenProps = {
20
20
  export type NodeEvents = {
21
21
  click: (ev: ClickEvent<Node | null>) => void;
22
22
  touchstart: (ev: TouchStartEvent<Node | null>) => void;
23
- /** AR anchors only (`scene.root` / `scene.createAnchor()`): the anchor began tracking. */
24
- track: () => void;
25
- /** AR anchors only: the anchor lost tracking. */
26
- untrack: () => void;
27
23
  /** A physics contact/trigger overlap began (the other body's node). Needs a Shape + Physics/Trigger. */
28
24
  enter: (other: Node) => void;
29
25
  /** A physics contact/trigger overlap ended. */
@@ -32,9 +28,6 @@ export type NodeEvents = {
32
28
  export declare class Node extends AspectHost<NodeEvents> implements CompWriter {
33
29
  /** Native entity id. */
34
30
  get id(): number;
35
- /** AR anchors only — whether the anchor is currently being tracked. Kept in step with the
36
- * 'track' / 'untrack' events; `false` for any non-anchor node. */
37
- isTracked: boolean;
38
31
  private _matrix?;
39
32
  private _worldMatrix?;
40
33
  private _boneCache?;
@@ -2,11 +2,10 @@ import { type ColorInput } from "../core/color";
2
2
  import { type Aspect, type AspectCtor, type FieldOf, type TargetOf } from "../core/Aspect";
3
3
  import { Presentable, type DismissOptions, type PresentOptions } from "../ui/presentable";
4
4
  import { type WidgetSet } from "../ui/UILayer";
5
+ import { File } from "../runtime/fetch";
5
6
  import type { ClickEvent, TouchStartEvent } from "../runtime/touch";
6
- import type { FetchResponse } from "../runtime/fetch";
7
7
  import { Camera } from "./Camera";
8
8
  import { SceneAudio } from "./audio/SceneAudio";
9
- import { type ControlsHandle, type ControlsOptions } from "./controls";
10
9
  import { Material } from "./Material";
11
10
  import { PostProcessing, type PostProcessingOptions } from "./postProcessing";
12
11
  import { Node } from "./Node";
@@ -214,6 +213,11 @@ export declare class Scene implements Presentable {
214
213
  destroy(): void;
215
214
  createOverlay(options?: SceneOptions): Scene;
216
215
  warmRender(): Promise<void>;
216
+ /** The scene's picture as a PNG `File`: the composite of its next frame — the scene, its overlays
217
+ * and its background (an AR scene's camera image), not the UI over them — encoded by the host
218
+ * (a share, an upload, a `UIImage` source). Rejects when the scene is not the one on screen, or
219
+ * something else is shown before the frame. */
220
+ capture(): Promise<File>;
217
221
  /** Precompile the scene's shader variants so nothing is compiled mid-game. Every material the host
218
222
  * knows is queued for the sun / shadow / fog / skinning variants and the dynamic-light key — the
219
223
  * first point light (a muzzle flash, an explosion) would otherwise rebuild every lit shader in view
@@ -246,28 +250,6 @@ export declare class Scene implements Presentable {
246
250
  addEventListener(channel: "touchstart", callback: (ev: TouchStartEvent<Node | null>) => void): void;
247
251
  removeEventListener(channel: "click" | "touchstart", callback: (ev: any) => void): void;
248
252
  }
249
- export type ARMode = "default" | "markers" | "arcore" | "detached";
250
- export declare class ARScene<T extends ARMode = "default"> extends Scene {
251
- readonly mode: T;
252
- useWarmRender: boolean;
253
- private _root?;
254
- constructor(options?: SceneOptions & {
255
- mode?: T;
256
- });
257
- /** Root anchor node (not available in marker mode). */
258
- get root(): Node;
259
- /** Create an anchor from a tracking source (e.g. an image target). */
260
- createAnchor(source: FetchResponse, physicalWidth?: number): Node;
261
- /**
262
- * Let the user place & manipulate a node with touch gestures — the staple AR object-placement
263
- * interaction: ONE finger drags it across the floor (relative to where the camera looks), TWO fingers
264
- * pinch to scale and twist to rotate. Returns a handle; call `.remove()` to detach. Tunable via
265
- * options (min/max scale, and toggles for `pan` / `pinch` / `twist`).
266
- */
267
- addControls(target: Node, options?: ControlsOptions): ControlsHandle;
268
- open(options?: PresentOptions): Promise<void>;
269
- close(options?: DismissOptions): void;
270
- }
271
253
  /**
272
254
  * A 3D scene rendered in a VR headset (OpenXR — e.g. Meta Quest). The headset drives the camera:
273
255
  * every frame both eyes are rendered from the tracked head pose, so `scene.camera` position/lookAt
@@ -14,6 +14,7 @@ export { Canvas, Bitmap } from "./canvas/Canvas";
14
14
  export { toast, openURL, SvgSource } from "./runtime/misc";
15
15
  export { app, type AppState, type OrientationLock } from "./runtime/app";
16
16
  export { clipboard } from "./runtime/clipboard";
17
+ export { permissions, type PermissionKind, type PermissionState } from "./runtime/permissions";
17
18
  export { date, type DateValue, type DateInput, type Unit, type Locale } from "./runtime/datetime";
18
19
  export { fetch, fetchLocal, FormData, File, type FetchResponse } from "./runtime/fetch";
19
20
  export { localStorage } from "./runtime/storage";
@@ -71,6 +72,9 @@ export { easeIn, easeOut, easeInOut } from "./animate/easings";
71
72
  export { QRScanner } from "./plugins/gen/qr-scanner/sdk/qr-scanner";
72
73
  export { CameraView, type CameraFacing } from "./plugins/gen/camera/sdk/camera";
73
74
  export { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from "./plugins/gen/geolocation/sdk/geolocation";
75
+ export { ARScene, Anchor, ImageAnchor, ARPlane, type ARSceneOptions, type AROpenOptions, type ARSceneEvents, type AnchorEvents, type ARPose, type ARPoseLike, type ARHitResult, type ARLightEstimate, type ARError, type ARErrorCode, type ARPlaneEvent, type ARMode, type HitTarget as ARHitTarget, type PlaneDetection as ARPlaneDetection, type PlaneType as ARPlaneType, type PlaneChange as ARPlaneChange, type TrackingState as ARTrackingState, type TrackingReason as ARTrackingReason, type WorldAlignment as ARWorldAlignment, } from "./plugins/gen/ar/sdk/ar";
76
+ export { AudioRecorder, type AudioRecorderEvents, type RecorderState, type RecordOptions, type Recording, type EndReason } from "./plugins/gen/audio-recorder/sdk/audio-recorder";
77
+ export { SpeechRecognizer, type SpeechRecognizerEvents, type SpeechOptions, type SpeechResult, type SpeechErrorCode } from "./plugins/gen/speech/sdk/speech";
74
78
  export { MapView, type MapOptions, type MapStyle, type MapStyleName, type MapCamera, type MapTap, type LngLat, type CameraMove, type FitOptions, type MapPaddingValues, type MarkerItem, type MarkerTap, type MarkerLayer, type MarkerLayerOptions, type LineLayer, type LineLayerOptions, type UserLocationOptions, } from "./plugins/gen/map/sdk/map";
75
79
  export { Push, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from "./plugins/gen/push/sdk/push";
76
80
  export { Browser, WebView, type BrowserOpenOptions, type WebViewParams, type WebViewEvents } from "./plugins/gen/browser/sdk/browser";
@@ -89,7 +93,7 @@ export type { GizmoStyle, GizmoAnchor } from "./scene/gizmos";
89
93
  export { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from "./gl/scenarios";
90
94
  export { registerEditorWindow, registerEditorTool } from "./scene/editorPlugins";
91
95
  export type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from "./scene/editorPlugins";
92
- export { Scene, ARScene, VRScene } from "./gl/Scene";
96
+ export { Scene, VRScene } from "./gl/Scene";
93
97
  export { Node } from "./gl/Node";
94
98
  export { Mesh } from "./gl/Mesh";
95
99
  export { Model } from "./gl/Model";
@@ -1,11 +1,28 @@
1
1
  import { File as HostFile } from "./runtime/fetch";
2
2
  import { ServiceClient } from "./runtime/service";
3
3
  import { NativeViewElement } from "./ui/NativeView";
4
+ import { _navEpoch } from "./ui/presentable";
5
+ import { _ensurePermission } from "./runtime/permissions";
6
+ export { permissions, type PermissionKind, type PermissionState } from "./runtime/permissions";
7
+ import { type Node } from "./gl/Node";
8
+ import type { Scene } from "./gl/Scene";
4
9
  export type { PresentOptions } from "./ui/presentable";
5
10
  export { Presentable, Router, UIBox, UIButton, UIColumn, UIRow, UIScreen, UIText } from "./ui/UI";
6
11
  export { theme } from "./ui/theme";
12
+ export { Emitter } from "./core/events";
7
13
  export type { NativeView } from "./ui/NativeView";
8
14
  export type { FetchResponse } from "./runtime/fetch";
15
+ export { Scene, type SceneOptions } from "./gl/Scene";
16
+ export { System } from "./core/Aspect";
17
+ export { Node, type NodeEvents } from "./gl/Node";
18
+ export { Mesh } from "./gl/Mesh";
19
+ export { Geometry } from "./gl/Geometry";
20
+ export { Material } from "./gl/Material";
21
+ export { Vec2, Vec3, type Vec3Like } from "./math/vec";
22
+ export { Quat, type QuatLike } from "./math/quat";
23
+ export { Mat4 } from "./math/mat4";
24
+ export type { ClickEvent, TouchStartEvent } from "./runtime/touch";
25
+ export type { DismissOptions } from "./ui/presentable";
9
26
  /** Signed 32-bit integer on the wire. */
10
27
  export type i32 = number;
11
28
  /** Double on the wire — also every integer that can leave 32 bits (a millisecond time stamp). */
@@ -14,6 +31,15 @@ export type f64 = number;
14
31
  * app gets the SDK's `File` handle (a texture source, a `FormData` value, a share) and the bytes
15
32
  * never enter the JS heap. For bytes the app must read itself, a contract says `Uint8Array`. */
16
33
  export type File = HostFile;
34
+ /** A 3D node of the app (`Node`) a plugin drives — an AR anchor, the camera: its entity id on the
35
+ * wire (u32, `node._h.id`); the native half receives `Entity` (a struct over the id) and moves it
36
+ * through the host's gl facade (`engine.gl` / `host.gl`), never creating or freeing it. One the half
37
+ * names back (an event's) is the app's own Node again. */
38
+ export type Entity = Node;
39
+ /** A 3D scene of the app (`Scene`) a plugin drives — its camera's projection, its background: the
40
+ * scene id on the wire (`scene._id`); the native half receives `Scene3D`. From the app to the host
41
+ * only: a half never names a scene back. */
42
+ export type Scene3D = Scene;
17
43
  /** Any JSON value, opaque to the generator (GeoJSON, a developer's own payload): it crosses as is
18
44
  * and the native half receives the platform's untyped value. */
19
45
  export type Json = null | boolean | number | string | Json[] | {
@@ -69,6 +95,7 @@ export declare class ServiceChannel<Events extends object = {}> extends ServiceC
69
95
  on<K extends keyof Events & string>(event: K, callback: Listener<Events, K>): this;
70
96
  off<K extends keyof Events & string>(event: K, callback: Listener<Events, K>): this;
71
97
  }
98
+ export declare const _fromScene3D: (scene: Scene3D) => number;
72
99
  /** Hear the app's "url" events (a deep link while the app runs — an OAuth redirect, a checkout's
73
100
  * return) until the returned function is called. The listener the `app` global fans out from. */
74
101
  export declare const _onAppUrl: (callback: (url: string) => void) => (() => void);
@@ -0,0 +1,228 @@
1
+ import { Node, Quat, Scene, Vec3, type ClickEvent, type DismissOptions, type FetchResponse, type File, type NodeEvents, type PresentOptions, type QuatLike, type SceneOptions, type TouchStartEvent, type Vec3Like } from "../../../../plugin";
2
+ import { type ControlsHandle, type ControlsOptions } from "./controls";
3
+ import type { ARErrorCode, ARMode, HitTarget, PlaneChange, PlaneDetection, PlaneType, StartOptions, TrackingReason, TrackingState, WorldAlignment } from "../contract";
4
+ export type { ARErrorCode, ARMode, ControlsHandle, ControlsOptions, HitTarget, PlaneChange, PlaneDetection, PlaneType, TrackingReason, TrackingState, WorldAlignment, };
5
+ /** A pose in the scene's world: metres, Y up. */
6
+ export type ARPose = {
7
+ position: Vec3;
8
+ rotation: Quat;
9
+ };
10
+ /** A pose as `scene.anchor()` takes it. */
11
+ export type ARPoseLike = {
12
+ position: Vec3Like;
13
+ rotation: QuatLike;
14
+ };
15
+ /** What `scene.hitTest()` finds under a point, nearest first. */
16
+ export type ARHitResult = {
17
+ pose: ARPose;
18
+ /** "plane": on a detected plane (`plane`); "estimated": on a point of the feature cloud or an
19
+ * estimated surface. */
20
+ type: "plane" | "estimated";
21
+ plane: ARPlane | null;
22
+ /** Metres from the camera. */
23
+ distance: number;
24
+ };
25
+ /** The estimated light (`lightEstimation`): an ambient intensity (1000 = neutral) and a colour
26
+ * temperature in kelvin. */
27
+ export type ARLightEstimate = {
28
+ intensity: number;
29
+ temperature: number;
30
+ };
31
+ /** The session failed and is over: "unavailable" (no ARKit / ARCore, ARCore declined), "camera",
32
+ * "failed". */
33
+ export type ARError = {
34
+ code: ARErrorCode;
35
+ message: string;
36
+ };
37
+ /** A plane found, moved or grown, or gone (`mergedInto`: the plane that absorbed it). */
38
+ export type ARPlaneEvent = {
39
+ plane: ARPlane;
40
+ change: PlaneChange;
41
+ mergedInto: ARPlane | null;
42
+ };
43
+ export type ARSceneOptions = SceneOptions & {
44
+ /** "world" (default): planes, hit tests, anchors, image targets. "images": image targets only —
45
+ * lighter on iOS; no planes, no hit test, no `root`. */
46
+ mode?: ARMode;
47
+ };
48
+ export type AROpenOptions = PresentOptions & Omit<StartOptions, "mode" | "images"> & {
49
+ /** The scene's ambient (its `environmentIntensity`) follows the estimated light; turns
50
+ * `lightEstimation` on. */
51
+ followLight?: boolean;
52
+ };
53
+ export type ARSceneEvents = {
54
+ tracking: (state: TrackingState, reason: TrackingReason | null) => void;
55
+ plane: (event: ARPlaneEvent) => void;
56
+ light: (estimate: ARLightEstimate) => void;
57
+ error: (error: ARError) => void;
58
+ };
59
+ export type AnchorEvents = NodeEvents & {
60
+ /** The anchor began tracking: found, placed, or regained after a relocalization. */
61
+ track: () => void;
62
+ /** The anchor lost tracking: it stays where it was last seen. */
63
+ untrack: () => void;
64
+ };
65
+ /**
66
+ * A node the AR session drives: it follows a place in the room (`scene.anchor(pose)`, `scene.root`)
67
+ * or an image (`scene.createAnchor(image)`). Put content under it. `tracked` says whether the session
68
+ * holds it now; `track` / `untrack` fire when that changes.
69
+ */
70
+ export declare class Anchor extends Node {
71
+ /** Whether the session holds the anchor now (it moves with what it follows). */
72
+ get tracked(): boolean;
73
+ addEventListener<K extends keyof AnchorEvents>(channel: K, callback: AnchorEvents[K]): void;
74
+ removeEventListener<K extends keyof AnchorEvents>(channel: K, callback: AnchorEvents[K]): void;
75
+ /** Stop following: the session lets it go (it stays where it was) and it leaves the scene. */
76
+ remove(): void;
77
+ }
78
+ /**
79
+ * An anchor that follows an image (`scene.createAnchor(image, physicalWidth)`): while tracked it sits on
80
+ * the image — a rigid pose in metres, no scale: its centre, Y out of the image, the image in X (its
81
+ * width) and Z (towards its bottom). How big the image is, is `extent`.
82
+ */
83
+ export declare class ImageAnchor extends Anchor {
84
+ constructor(physicalWidth: number);
85
+ /** [width, height] in metres, along the anchor's X and Z: the session's estimate of the printed
86
+ * image, refined while it tracks it. Before the image is first found: [physicalWidth, 0] — the
87
+ * height comes with the image's proportions, which the session reads, at the first `track`. */
88
+ get extent(): [number, number];
89
+ }
90
+ /** A surface the session found: a floor, a table, a wall. Its node sits at the plane's centre with Y
91
+ * along its normal; `extent` and `polygon` are in that space. */
92
+ export declare class ARPlane extends Anchor {
93
+ /** The session's id of the plane (`ARHitResult.plane`, `mergedInto`). */
94
+ readonly planeId: number;
95
+ constructor(planeId: number);
96
+ get type(): PlaneType;
97
+ /** [width, depth] in metres, along the plane's X and Z. */
98
+ get extent(): [number, number];
99
+ /** The boundary as x, z pairs in the plane's space (metres). */
100
+ get polygon(): readonly number[];
101
+ /** The plane's centre in the world. */
102
+ get center(): Vec3;
103
+ }
104
+ /**
105
+ * A 3D scene over the device camera with world tracking: the session (the "ar" plugin) moves
106
+ * `scene.camera` and draws the camera image behind everything, every frame. Everything of `Scene`
107
+ * applies. `ARScene.isSupported` says whether this host has the plugin.
108
+ *
109
+ * ```ts
110
+ * const scene = new ARScene()
111
+ * scene.root.add(await Model.load(asset('./chair.glb')))
112
+ * await scene.open() // camera permission → warm render → session → on screen, drawn
113
+ * ```
114
+ */
115
+ export declare class ARScene extends Scene {
116
+ /** Whether this host registered the "ar" service (the app lists the plugin, the host has a half). */
117
+ static get isSupported(): boolean;
118
+ readonly mode: ARMode;
119
+ /** `open()` warm-renders the scene first (default true). */
120
+ useWarmRender: boolean;
121
+ private _opening;
122
+ /** The wait of `open()` / `Router.push` for the presented scene's first frame (`_presented`), and
123
+ * the navigation epoch of its present. */
124
+ private _shown;
125
+ /** The open's start while it is out (`_begin`). `closed`: close() ended its session meanwhile — the
126
+ * half refuses a start its close cut short ("failed"), which is the close's doing: the open was
127
+ * superseded, not failed. `images`: the image targets changed meanwhile, which the start did not
128
+ * carry (it read them when it was sent) — the set goes to the session once it runs. */
129
+ private _startOut;
130
+ /** A `setImages` is due at the end of this turn (`_setImages`). */
131
+ private _imagesDue;
132
+ private _options;
133
+ private _root;
134
+ /** The first horizontal plane's pose: where `root` is pinned. */
135
+ private _floor;
136
+ /** The image targets. `source` is held for the bytes: a fetched response owns its buffer, which the
137
+ * host frees once the response is collected — the File the session is handed only names it. */
138
+ private readonly _images;
139
+ /** The pose anchors: pinned again where they are when a session starts. (`root` is not one: a
140
+ * session pins it on its own first floor.) */
141
+ private readonly _pinned;
142
+ private readonly _planes;
143
+ private _trackingState;
144
+ private _trackingReason;
145
+ private _light;
146
+ private _showPlanes;
147
+ private _baseIntensity;
148
+ private readonly _arListeners;
149
+ constructor(options?: ARSceneOptions);
150
+ /** The tracking quality: "notAvailable" before a session, "limited" (with `trackingReason`) while
151
+ * it settles or struggles, "normal". */
152
+ get trackingState(): TrackingState;
153
+ get trackingReason(): TrackingReason | null;
154
+ /** The planes the session holds now. */
155
+ get planes(): ARPlane[];
156
+ /** The latest light estimate (`lightEstimation`), null before one. */
157
+ get lightEstimate(): ARLightEstimate | null;
158
+ /** A grid drawn on every plane (each plane's child mesh). */
159
+ get showPlanes(): boolean;
160
+ set showPlanes(on: boolean);
161
+ /** The floor: an anchor pinned on the first horizontal plane the session finds (it fires `track`
162
+ * then). Until that it is the world's origin — where the session began. Not in "images" mode. */
163
+ get root(): Anchor;
164
+ /** An anchor that follows an image (a printed marker, a poster): the session finds it in the camera
165
+ * image and keeps the anchor on it — a rigid pose in metres (its centre, Y out of the image, the
166
+ * image in XZ), its size `anchor.extent`. `physicalWidth` = the printed width in metres. Hidden
167
+ * while not tracked. Before `open()`, or any time: on a running scene the image set is updated in
168
+ * place — the tracking, the planes and the anchors stay. */
169
+ createAnchor(source: FetchResponse | File, physicalWidth?: number): ImageAnchor;
170
+ /** An anchor at `pose` (a hit test's, say): the session keeps it where it is in the room as its
171
+ * map of the world improves. `anchor.remove()` lets it go. */
172
+ anchor(pose: ARPoseLike): Anchor;
173
+ /** What is under a point of the scene's view, nearest first — the point as the scene's touches
174
+ * give it (`ev.clientX` / `ev.clientY` of a `click` or a `touchstart`); empty when nothing is — and
175
+ * always on the web, which finds no surfaces. Rejects without a running session. */
176
+ hitTest(x: number, y: number, target?: HitTarget): Promise<ARHitResult[]>;
177
+ /** The latest camera image as a JPEG `File` (the camera's alone; `capture()` is the composite).
178
+ * Rejects without a running session. */
179
+ captureFrame(): Promise<File>;
180
+ /**
181
+ * Let the user place & manipulate a node with touch gestures — the staple AR object-placement
182
+ * interaction: ONE finger drags it over what the session finds under the finger (a plane), or across
183
+ * the ground where it finds nothing; TWO fingers pinch to scale and twist to rotate. Returns a
184
+ * handle; `.remove()` detaches. Tunable via options (min/max scale, `pan` / `pinch` / `twist`).
185
+ */
186
+ addControls(target: Node, options?: ControlsOptions): ControlsHandle;
187
+ /** Camera permission → warm render → the session → on screen, resolved at the scene's first frame:
188
+ * after `await scene.open()` the scene is shown, `camera.displaySize` is its view's size, and
189
+ * `hitTest` / `captureFrame` answer. The current destination (a loading screen) stays until the
190
+ * session runs; rejects — and leaves it — when the camera is denied, AR is unavailable
191
+ * ("unavailable": no ARKit / ARCore), or another navigation came meanwhile; one that comes before
192
+ * the first frame (a `close()` too) rejects it as superseded. */
193
+ open(options?: AROpenOptions): Promise<void>;
194
+ private _settleShown;
195
+ /** Close the scene; its session stops (the camera is let go). An `open()` still waiting — for the
196
+ * session's start or the first frame — rejects as superseded. */
197
+ close(options?: DismissOptions): void;
198
+ addEventListener(channel: "click", callback: (ev: ClickEvent<Node | null>) => void): void;
199
+ addEventListener(channel: "touchstart", callback: (ev: TouchStartEvent<Node | null>) => void): void;
200
+ addEventListener<K extends keyof ARSceneEvents>(channel: K, callback: ARSceneEvents[K]): void;
201
+ removeEventListener(channel: "click" | "touchstart" | keyof ARSceneEvents, callback: (...args: any[]) => void): void;
202
+ private _emit;
203
+ private _startOptions;
204
+ private _targets;
205
+ private _begin;
206
+ /** The session is over (closed, failed): every anchor untracked, the planes gone. */
207
+ private _drop;
208
+ private _end;
209
+ private _lost;
210
+ /** The image targets changed (one added or removed): a running session takes the whole set in place
211
+ * (`setImages` — the tracking, the planes and the anchors stay). Sent at the end of the turn: several
212
+ * targets added in a row are one set. While the open's start is out it waits for it (the start
213
+ * carried the set it read when it was sent); before a session there is nothing to tell — the start
214
+ * carries the set. Nothing waits for it: a set the half refuses is a console line, and an anchor
215
+ * whose image the session did not take never tracks. */
216
+ private _setImages;
217
+ /** A wire call to the running session; rejects without one. */
218
+ private _wire;
219
+ /** Pin `anchor` at `pose` (where it is until the session holds it) — now, or when a session starts. */
220
+ private _place;
221
+ /** `root` onto the floor (the first horizontal plane of this session). */
222
+ private _pinRoot;
223
+ private _pin;
224
+ /** A session began: every pose anchor is pinned where it is. */
225
+ private _pinAll;
226
+ private _onPlane;
227
+ private _drawPlane;
228
+ }
@@ -0,0 +1,73 @@
1
+ import { ServiceChannel, type Entity, type EventReaders, type File } from "../../../../plugin";
2
+ import type { AREvents, ARParams, HitResult, HitTarget, ImageTarget, Pose, StartOptions } from "../contract";
3
+ /** What the halves register under. */
4
+ export declare const NAME = "ar";
5
+ /** The contract's version: the highest `@since` of its members. */
6
+ export declare const VERSION = 1;
7
+ /** The events whose payload holds a File: read before a listener sees it. */
8
+ export declare const READERS: EventReaders;
9
+ /** Start tracking; resolves at the first frame. A second start rejects "busy".
10
+ * Needs the "camera" permission: the host asks before the call, "denied" when refused.
11
+ * Rejects with "denied" / "busy" / "unavailable" / "failed". */
12
+ export declare const start: (service: ServiceChannel<AREvents>, options?: StartOptions) => Promise<void>;
13
+ /** Stop tracking: the camera is released, the scene's projection and background cleared. Not
14
+ * running is not an error. */
15
+ export declare const stop: (service: ServiceChannel<AREvents>) => Promise<void>;
16
+ /** Replace the set of image targets of a RUNNING session without restarting it (the tracking, the
17
+ * planes and the anchors stay); an image no longer in the set stops driving its entity (its
18
+ * `image` event says `tracked: false` once if it was tracked). Before `start`, the images are
19
+ * `StartOptions.images`.
20
+ * Rejects with "notRunning" / "failed". */
21
+ export declare const setImages: (service: ServiceChannel<AREvents>, images: ImageTarget[]) => Promise<void>;
22
+ /** What is under a point of the scene's view — in its touches' space (a scene touch's `clientX` /
23
+ * `clientY`: the units of the gl facade's viewport) — nearest first. Empty when nothing is, or on
24
+ * a host without surfaces (the web).
25
+ * Rejects with "notRunning". */
26
+ export declare const hitTest: (service: ServiceChannel<AREvents>, x: number, y: number, target?: HitTarget) => Promise<HitResult[]>;
27
+ /** Pin `entity` to `pose`: the host's anchor drives its matrix from now on (and keeps it true
28
+ * as the world map refines).
29
+ * Rejects with "notRunning". */
30
+ export declare const anchor: (service: ServiceChannel<AREvents>, entity: Entity, pose: Pose) => Promise<void>;
31
+ /** Stop driving `entity` (its matrix stays where it was). */
32
+ export declare const release: (service: ServiceChannel<AREvents>, entity: Entity) => Promise<void>;
33
+ /** The latest camera frame as a JPEG (the raw image, not the composite — that is
34
+ * `Scene.capture()`).
35
+ * Rejects with "notRunning" / "failed". */
36
+ export declare const captureFrame: (service: ServiceChannel<AREvents>) => Promise<File>;
37
+ /** A method of the contract. */
38
+ export type Method = "start" | "stop" | "setImages" | "hitTest" | "anchor" | "release" | "captureFrame";
39
+ /** Whether this host has the service "ar" — and, given a method, a half new enough for it
40
+ * (a method added after the first version of the contract is tagged `@since`). */
41
+ export declare const supports: (method?: Method) => boolean;
42
+ /** The service "ar" with the wire's methods as its own. */
43
+ export declare class ARBase extends ServiceChannel<AREvents> {
44
+ constructor(params?: ARParams);
45
+ /** Start tracking; resolves at the first frame. A second start rejects "busy".
46
+ * Needs the "camera" permission: the host asks before the call, "denied" when refused.
47
+ * Rejects with "denied" / "busy" / "unavailable" / "failed". */
48
+ start(options?: StartOptions): Promise<void>;
49
+ /** Stop tracking: the camera is released, the scene's projection and background cleared. Not
50
+ * running is not an error. */
51
+ stop(): Promise<void>;
52
+ /** Replace the set of image targets of a RUNNING session without restarting it (the tracking, the
53
+ * planes and the anchors stay); an image no longer in the set stops driving its entity (its
54
+ * `image` event says `tracked: false` once if it was tracked). Before `start`, the images are
55
+ * `StartOptions.images`.
56
+ * Rejects with "notRunning" / "failed". */
57
+ setImages(images: ImageTarget[]): Promise<void>;
58
+ /** What is under a point of the scene's view — in its touches' space (a scene touch's `clientX` /
59
+ * `clientY`: the units of the gl facade's viewport) — nearest first. Empty when nothing is, or on
60
+ * a host without surfaces (the web).
61
+ * Rejects with "notRunning". */
62
+ hitTest(x: number, y: number, target?: HitTarget): Promise<HitResult[]>;
63
+ /** Pin `entity` to `pose`: the host's anchor drives its matrix from now on (and keeps it true
64
+ * as the world map refines).
65
+ * Rejects with "notRunning". */
66
+ anchor(entity: Entity, pose: Pose): Promise<void>;
67
+ /** Stop driving `entity` (its matrix stays where it was). */
68
+ release(entity: Entity): Promise<void>;
69
+ /** The latest camera frame as a JPEG (the raw image, not the composite — that is
70
+ * `Scene.capture()`).
71
+ * Rejects with "notRunning" / "failed". */
72
+ captureFrame(): Promise<File>;
73
+ }
@@ -0,0 +1,28 @@
1
+ import { Vec3, type Node, type Scene } from "../../../../plugin";
2
+ import type { HitTarget } from "../contract";
3
+ export type ControlsOptions = {
4
+ /** Smallest uniform scale the pinch gesture allows (default 0.08). */
5
+ minScale?: number;
6
+ /** Largest uniform scale the pinch gesture allows (default 2). */
7
+ maxScale?: number;
8
+ /** One-finger drag moves the target over the surfaces under the finger (default true). */
9
+ pan?: boolean;
10
+ /** Two-finger pinch scales the target (default true). */
11
+ pinch?: boolean;
12
+ /** Two-finger twist rotates the target around its Y axis (default true). */
13
+ twist?: boolean;
14
+ };
15
+ /** Returned by `addControls` — call `remove()` to detach the gesture listeners. */
16
+ export type ControlsHandle = {
17
+ remove(): void;
18
+ };
19
+ /** The scene the controls work on: ARScene's hit test, a Scene's camera and touches. */
20
+ type PlacingScene = Scene & {
21
+ hitTest(x: number, y: number, target?: HitTarget): Promise<{
22
+ pose: {
23
+ position: Vec3;
24
+ };
25
+ }[]>;
26
+ };
27
+ export declare const attachControls: (scene: PlacingScene, target: Node, options?: ControlsOptions) => ControlsHandle;
28
+ export {};