lecodes-sdk 2.8.0 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global.d.ts +4 -0
- package/dist/types/core/Aspect.d.ts +7 -0
- package/dist/types/gl/Statics.d.ts +12 -1
- package/dist/types/gl/physics/CharacterController.d.ts +9 -4
- package/dist/types/gl/physics/Physics.d.ts +7 -1
- package/dist/types/gl/physics/Shape.d.ts +4 -0
- package/dist/types/inject.d.ts +1 -0
- package/dist/types/plugin.d.ts +1 -0
- package/dist/types/plugins/gen/ar/sdk/ar.d.ts +25 -5
- package/dist/types/runtime/gestures.d.ts +52 -0
- package/dist/types/ui/UIModal.d.ts +5 -3
- package/dist/types/version.d.ts +1 -1
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/src/bridges/gl.d.ts +7 -0
- package/src/bridges/tree.d.ts +14 -4
- package/src/core/Aspect.ts +7 -0
- package/src/gl/Node.ts +21 -2
- package/src/gl/Statics.ts +48 -2
- package/src/gl/physics/CharacterController.ts +12 -5
- package/src/gl/physics/Physics.ts +17 -3
- package/src/gl/physics/Shape.ts +29 -9
- package/src/gl/physics/physicsEvents.ts +9 -4
- package/src/gl/touch.ts +4 -1
- package/src/inject.ts +2 -0
- package/src/plugin.ts +3 -1
- package/src/plugins/gen/ar/sdk/ar.ts +59 -14
- package/src/runtime/gestures.ts +190 -0
- package/src/scene/defineScene.ts +5 -2
- package/src/scene/grammar.ts +10 -2
- package/src/ui/UIModal.ts +44 -9
- package/src/ui/UINode.ts +4 -0
- package/src/ui/tree.ts +8 -0
- package/src/version.ts +1 -1
package/dist/global.d.ts
CHANGED
|
@@ -248,6 +248,7 @@ declare global {
|
|
|
248
248
|
const tileOriented: typeof SDK.tileOriented
|
|
249
249
|
const tileTurns: typeof SDK.tileTurns
|
|
250
250
|
const toast: typeof SDK.toast
|
|
251
|
+
const trackGesture: typeof SDK.trackGesture
|
|
251
252
|
const use: typeof SDK.use
|
|
252
253
|
type ARError = SDK.ARError
|
|
253
254
|
type ARErrorCode = SDK.ARErrorCode
|
|
@@ -378,6 +379,9 @@ declare global {
|
|
|
378
379
|
type GeoPosition = SDK.GeoPosition
|
|
379
380
|
type GeoWatch = SDK.GeoWatch
|
|
380
381
|
type Geometry = SDK.Geometry
|
|
382
|
+
type Gesture = SDK.Gesture
|
|
383
|
+
type GestureHandler = SDK.GestureHandler
|
|
384
|
+
type GestureTarget = SDK.GestureTarget
|
|
381
385
|
type GizmoAnchor = SDK.GizmoAnchor
|
|
382
386
|
type GizmoStyle = SDK.GizmoStyle
|
|
383
387
|
type HapticStyle = SDK.HapticStyle
|
|
@@ -78,6 +78,13 @@ export declare abstract class Aspect<K extends string, P = Node, E extends Event
|
|
|
78
78
|
static after?: Function[];
|
|
79
79
|
/** Tick BEFORE these classes within the same phase (`static before = [Camera]`). */
|
|
80
80
|
static before?: Function[];
|
|
81
|
+
/** DATA ONLY. A `use(...)` of this aspect in a scene file leaves its node STATIC for the level cache (gl/Statics.ts):
|
|
82
|
+
* the engine builds the node without a JS object, and the aspect is attached the first time a hit, a contact or
|
|
83
|
+
* a pick reaches the node — `hit.node.get(Surface)` answers then. So: fields and the methods the game calls on a
|
|
84
|
+
* hit (a tag like `Surface { kind }`, a breakable's hit points), no `update()` (`use()` refuses one) and nothing in
|
|
85
|
+
* `onAttach()` the level needs from its first frame. Without it a custom aspect keeps its node on the JS path,
|
|
86
|
+
* built at load like any mover. */
|
|
87
|
+
static passive?: boolean;
|
|
81
88
|
/** Every live instance of an aspect/system class, in attach order — the registry a game used to
|
|
82
89
|
* hand-roll as `static all[]`. Live, read-only: copy it (`[...Aspect.all(Barrel)]`) before a loop
|
|
83
90
|
* that detaches. Empty in the scene editor (aspects are inert data there). */
|
|
@@ -3,6 +3,7 @@ import { Model, type FoliageKind } from "./Model";
|
|
|
3
3
|
import { Node } from "./Node";
|
|
4
4
|
import { Scene } from "./Scene";
|
|
5
5
|
import type { SceneDef, SceneNodeDef } from "../scene/defineScene";
|
|
6
|
+
import type { AspectEntry } from "../scene/grammar";
|
|
6
7
|
import type { BakeData } from "./Lightmap";
|
|
7
8
|
import { type Digest } from "./staticsFormat";
|
|
8
9
|
export { bakeDigest, type Digest } from "./staticsFormat";
|
|
@@ -17,6 +18,16 @@ export type CoveredRoot = {
|
|
|
17
18
|
path: string;
|
|
18
19
|
def: SceneNodeDef;
|
|
19
20
|
};
|
|
21
|
+
/** A passive aspect (Aspect.passive): data the engine does not need — attached to the placement's wrapper on the
|
|
22
|
+
* first hit (`attachPassive`), never built at load. */
|
|
23
|
+
export declare const isPassive: (e: AspectEntry<any>) => boolean;
|
|
24
|
+
/** Attach the passive aspects of `def` to `node` (props as written: a passive aspect is data, `ref()`s are not
|
|
25
|
+
* resolved). Who gets them: the entity a hit comes back with. A placement's clone, on the first hit, through
|
|
26
|
+
* `lazyPlacements` — a covered root with a model included, since its clone is what the ray strikes, not the plain
|
|
27
|
+
* JS node the clone hangs under. A root WITHOUT a model (a group tagged `Surface` over its walls) has no clone:
|
|
28
|
+
* its JS node takes them at load, and a hit on a wall under it finds them one `parent` up (a game's surface lookup
|
|
29
|
+
* walks `hit.node.parent`). */
|
|
30
|
+
export declare const attachPassive: (node: Node, def: SceneNodeDef) => void;
|
|
20
31
|
/** The maximal cacheable subtrees among `defs`, depth first: through `children`, and through a prefab's nodes
|
|
21
32
|
* (paths run through the prefab's path, as the bake's keys do). */
|
|
22
33
|
export declare const coveredRoots: (defs: Record<string, SceneNodeDef> | undefined, scene: SceneDef) => CoveredRoot[];
|
|
@@ -53,4 +64,4 @@ export declare const open: (url: string, defs: Digest, bake: Digest) => Promise<
|
|
|
53
64
|
* templates load through `template` (one per kind, as the level's slow path would load them), the engine clones
|
|
54
65
|
* each at its placements as it resolves. `pages` = the bake's light/aux texture ids interleaved (empty = no bake
|
|
55
66
|
* bound). Resolves to the placements made. */
|
|
56
|
-
export declare const build: (opened: OpenedCache, scene: Scene, roots: Node[], pages: Uint32Array, template: (url: string, lightmap: boolean, foliage: FoliageKind) => Promise<Model
|
|
67
|
+
export declare const build: (opened: OpenedCache, scene: Scene, roots: Node[], pages: Uint32Array, template: (url: string, lightmap: boolean, foliage: FoliageKind) => Promise<Model>, covered: CoveredRoot[], def: SceneDef) => Promise<number>;
|
|
@@ -47,13 +47,18 @@ export declare class CharacterController extends Aspect<"controller", Node> impl
|
|
|
47
47
|
* True while a requested collider resize hasn't taken — you asked to stand up and there is something
|
|
48
48
|
* overhead. Resizing goes through the `Shape` aspect itself:
|
|
49
49
|
*
|
|
50
|
-
* hero.
|
|
51
|
-
* hero.
|
|
52
|
-
* if (hero.controller.resizing) … // still crouched;
|
|
50
|
+
* hero.shape.capsule = CROUCHED // always fits — you are shrinking
|
|
51
|
+
* hero.shape.capsule = STANDING // may be refused under a low ceiling
|
|
52
|
+
* if (hero.controller.resizing) … // still crouched; write it again next frame
|
|
53
53
|
*
|
|
54
54
|
* A refusal changes nothing, so the retry is just the same call again — and it is an exact headroom
|
|
55
55
|
* test against the real capsule, unlike a hand-rolled raycast (a ray is a line; a capsule has girth).
|
|
56
|
-
* The FEET stay planted across a resize, so the character neither hovers nor sinks
|
|
56
|
+
* The FEET stay planted across a resize, so the character neither hovers nor sinks — which means the
|
|
57
|
+
* node (the capsule's centre) has ALREADY moved by the feet difference when the write returns. Place
|
|
58
|
+
* a first-person camera from the feet (`node.y − (halfHeight + radius)` of the capsule worn) plus an
|
|
59
|
+
* eased eye height; placed from the node it pops by that difference. Write the property: a second
|
|
60
|
+
* `node.aspect(Shape, …)` builds a fresh Shape (it is handed to the character too, but it is a
|
|
61
|
+
* rebuild per stance, not a resize).
|
|
57
62
|
*/
|
|
58
63
|
get resizing(): boolean;
|
|
59
64
|
/** True while standing on walkable ground. */
|
|
@@ -87,6 +87,12 @@ export declare class Physics extends Aspect<"physics", Node> implements CompWrit
|
|
|
87
87
|
/** Whether this host has 3D physics (an engine built with CREATOR_GL_PHYSICS). False, never a
|
|
88
88
|
* throw, where there is no 3D engine at all. */
|
|
89
89
|
static get supported(): boolean;
|
|
90
|
-
/**
|
|
90
|
+
/** The motion of the body on `node`, read off the engine: it answers for a body the SDK never made (a static the
|
|
91
|
+
* level cache built, which has no `Physics` aspect until a hit reaches it, and no body-making one ever). null = no
|
|
92
|
+
* body on this node. The way to tell a wall from a prop on a hit: `Physics.motionOf(hit.node) === "static"`. */
|
|
93
|
+
static motionOf(node: Node | null): MotionType | null;
|
|
94
|
+
/** Closest pickable body hit by the ray from `origin` along `dir` (up to `maxDist`), or null. `node` is the body's
|
|
95
|
+
* node — for a static the level cache built, a wrapper made on this hit (Node.ts nodeOf), carrying the placement's
|
|
96
|
+
* passive aspects; its `Physics` is read with `Physics.motionOf`. */
|
|
91
97
|
static raycast(origin: Vec3Like, dir: Vec3Like, maxDist?: number): RayHit | null;
|
|
92
98
|
}
|
|
@@ -138,6 +138,10 @@ export declare class Shape extends Aspect<"shape", Node> {
|
|
|
138
138
|
static fitBounds(bounds: ShapeBounds, scale: Vec3Like, kind?: ShapeKind): ShapeFit;
|
|
139
139
|
private _createPickBody;
|
|
140
140
|
private _rebuild;
|
|
141
|
+
/** The character this node belongs to tries the geometry on. Jolt validates the fit (standing up
|
|
142
|
+
* under a pipe) and can refuse; a refusal changes nothing in the engine. The feet stay planted, so
|
|
143
|
+
* on success the node has already moved by the change in the shape's lower bound when this returns. */
|
|
144
|
+
private _offerToCharacter;
|
|
141
145
|
private _build;
|
|
142
146
|
private _applyOrigin;
|
|
143
147
|
private _signature;
|
package/dist/types/inject.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export { audio, type PlaySoundOptions, type SpatialOptions, type Rolloff, type A
|
|
|
37
37
|
export { openFilePicker, files, type FileData } from "./runtime/files";
|
|
38
38
|
export { share } from "./runtime/share";
|
|
39
39
|
export { ClickEvent, TouchStartEvent, LongPressEvent, MouseEnterEvent } from "./runtime/touch";
|
|
40
|
+
export { trackGesture, type Gesture, type GestureHandler, type GestureTarget } from "./runtime/gestures";
|
|
40
41
|
export { Scene2D } from "./g2/Scene2D";
|
|
41
42
|
export { Node2D } from "./g2/Node2D";
|
|
42
43
|
export { Camera2D } from "./g2/Camera2D";
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export { Vec2, Vec3, type Vec3Like } from "./math/vec";
|
|
|
22
22
|
export { Quat, type QuatLike } from "./math/quat";
|
|
23
23
|
export { Mat4 } from "./math/mat4";
|
|
24
24
|
export type { ClickEvent, TouchStartEvent } from "./runtime/touch";
|
|
25
|
+
export { trackGesture, type Gesture, type GestureHandler, type GestureTarget } from "./runtime/gestures";
|
|
25
26
|
export type { DismissOptions } from "./ui/presentable";
|
|
26
27
|
/** The seam the push plugin's wrapper installs its runtime on (src/runtime/pushSeam.ts): what the app's transport
|
|
27
28
|
* reads the device's address from, registers through, and a push channel's handlers are kept by. */
|
|
@@ -44,6 +44,9 @@ export type ARSceneOptions = SceneOptions & {
|
|
|
44
44
|
/** "world" (default): planes, hit tests, anchors, image and QR targets. "images": image and QR
|
|
45
45
|
* targets only — lighter on iOS; no planes, no hit test, no `root`. */
|
|
46
46
|
mode?: ARMode;
|
|
47
|
+
/** How far in front of the user `root` is placed, metres (default 1): along the camera's heading,
|
|
48
|
+
* on the floor. */
|
|
49
|
+
rootDistance?: number;
|
|
47
50
|
};
|
|
48
51
|
export type AROpenOptions = PresentOptions & Omit<StartOptions, "mode" | "images" | "codes"> & {
|
|
49
52
|
/** The scene's ambient (its `environmentIntensity`) follows the estimated light; turns
|
|
@@ -128,6 +131,8 @@ export declare class ARScene extends Scene {
|
|
|
128
131
|
/** Whether this host registered the "ar" service (the app lists the plugin, the host has a half). */
|
|
129
132
|
static get isSupported(): boolean;
|
|
130
133
|
readonly mode: ARMode;
|
|
134
|
+
/** Metres between the user and `root` when it is placed (`rootDistance` option, default 1). */
|
|
135
|
+
readonly rootDistance: number;
|
|
131
136
|
/** `open()` warm-renders the scene first (default true). */
|
|
132
137
|
useWarmRender: boolean;
|
|
133
138
|
private _opening;
|
|
@@ -147,7 +152,8 @@ export declare class ARScene extends Scene {
|
|
|
147
152
|
private _codesWarned;
|
|
148
153
|
private _options;
|
|
149
154
|
private _root;
|
|
150
|
-
/** The first horizontal plane
|
|
155
|
+
/** The floor's height (world Y, metres): the first horizontal plane below the camera this session
|
|
156
|
+
* found. Null until one is; `root` is placed on it. */
|
|
151
157
|
private _floor;
|
|
152
158
|
/** The image targets. `source` is held for the bytes: a fetched response owns its buffer, which the
|
|
153
159
|
* host frees once the response is collected — the File the session is handed only names it. */
|
|
@@ -174,9 +180,17 @@ export declare class ARScene extends Scene {
|
|
|
174
180
|
/** A grid drawn on every plane (each plane's child mesh). */
|
|
175
181
|
get showPlanes(): boolean;
|
|
176
182
|
set showPlanes(on: boolean);
|
|
177
|
-
/** The
|
|
178
|
-
*
|
|
183
|
+
/** The place in front of the user: an anchor `rootDistance` metres ahead of the camera along its
|
|
184
|
+
* heading, on the floor — the first horizontal plane below the camera the session finds; it is
|
|
185
|
+
* pinned there and fires `track` then — turned the way the user looks (its −Z along the heading,
|
|
186
|
+
* so a model's front, +Z, faces the user). Until the floor is found (and on the web, which finds
|
|
187
|
+
* none) it sits the same way at the camera's own height, not pinned. Made on first use; put
|
|
188
|
+
* content under it. `placeRoot()` puts it in front of the user again. Not in "images" mode. */
|
|
179
189
|
get root(): Anchor;
|
|
190
|
+
/** Put `root` in front of the user again — where they look now, `rootDistance` metres ahead, on the
|
|
191
|
+
* floor if one is known (the camera's height otherwise), facing them: a "reset" button, or a
|
|
192
|
+
* placement after the user has moved. Makes `root` when there is none yet. */
|
|
193
|
+
placeRoot(): Anchor;
|
|
180
194
|
/** An anchor that follows an image (a printed marker, a poster): the session finds it in the camera
|
|
181
195
|
* image and keeps the anchor on it — a rigid pose in metres (its centre, Y out of the image, the
|
|
182
196
|
* image in XZ), its size `anchor.extent`. `physicalWidth` = the printed width in metres. Hidden
|
|
@@ -244,8 +258,14 @@ export declare class ARScene extends Scene {
|
|
|
244
258
|
private _wire;
|
|
245
259
|
/** Pin `anchor` at `pose` (where it is until the session holds it) — now, or when a session starts. */
|
|
246
260
|
private _place;
|
|
247
|
-
/** `root`
|
|
248
|
-
|
|
261
|
+
/** Where `root` goes now: `rootDistance` metres from the camera along its heading (its forward
|
|
262
|
+
* flattened to the floor; looking straight down or up, the way the top of the screen points), at
|
|
263
|
+
* the floor's height when one is known, else the camera's; turned so its −Z runs along the
|
|
264
|
+
* heading — a model's front (+Z) faces the user. */
|
|
265
|
+
private _rootPose;
|
|
266
|
+
/** `root` in front of the user: moved there now, and pinned there when the floor is known (a
|
|
267
|
+
* session holds a pin; without one `_pinAll` does not re-pin root — it waits for its own floor). */
|
|
268
|
+
private _placeRoot;
|
|
249
269
|
private _pin;
|
|
250
270
|
/** A session began: every pose anchor is pinned where it is. */
|
|
251
271
|
private _pinAll;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { TouchStartEvent, TrackHandler } from "./touch";
|
|
2
|
+
/** One reading of a gesture, handed to `onStart` / `onMove` / `onEnd` (a fresh object each time). */
|
|
3
|
+
export interface Gesture {
|
|
4
|
+
/** The centroid of the live fingers, in the event's client coordinates (logical px). */
|
|
5
|
+
centerX: number;
|
|
6
|
+
centerY: number;
|
|
7
|
+
/** The centroid's move since the previous `onMove` (0 on start / end). */
|
|
8
|
+
deltaX: number;
|
|
9
|
+
deltaY: number;
|
|
10
|
+
/** Mean finger distance to the centroid over the previous one (1 with one finger, 1 on start / end). */
|
|
11
|
+
scale: number;
|
|
12
|
+
/** The mean change of each finger's angle about the centroid since the previous `onMove`, radians,
|
|
13
|
+
* positive = clockwise on screen (0 with one finger, 0 on start / end). */
|
|
14
|
+
rotation: number;
|
|
15
|
+
/** The number of live fingers (0 in `onEnd`: the last one lifted). */
|
|
16
|
+
pointers: number;
|
|
17
|
+
}
|
|
18
|
+
/** What `trackGesture` takes: the gesture's callbacks and the claim every finger's track makes. */
|
|
19
|
+
export interface GestureHandler {
|
|
20
|
+
/** Passed to every finger's `ev.track(...)` (default `true`: a scrollable above never takes the pan). */
|
|
21
|
+
claim?: TrackHandler["claim"];
|
|
22
|
+
/** The first finger landed. */
|
|
23
|
+
onStart?(g: Gesture): void;
|
|
24
|
+
/** Any finger moved: the change since the previous `onMove`. */
|
|
25
|
+
onMove?(g: Gesture): void;
|
|
26
|
+
/** The last finger lifted. */
|
|
27
|
+
onEnd?(g: Gesture): void;
|
|
28
|
+
/** The host cancelled one of the fingers: the whole gesture is over. */
|
|
29
|
+
onCancel?(): void;
|
|
30
|
+
}
|
|
31
|
+
/** Anything that hands out touchstarts: a UI element (`onTouchStart`) or a scene / node
|
|
32
|
+
* (`addEventListener("touchstart", …)`). */
|
|
33
|
+
export type GestureTarget = {
|
|
34
|
+
onTouchStart(callback: (ev: TouchStartEvent<any>) => void): unknown;
|
|
35
|
+
} | {
|
|
36
|
+
addEventListener(channel: "touchstart", callback: (ev: TouchStartEvent<any>) => void): void;
|
|
37
|
+
removeEventListener(channel: "touchstart", callback: (ev: TouchStartEvent<any>) => void): void;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Follow pan, pinch and twist on `target` as one gesture: every finger that lands on it is tracked,
|
|
41
|
+
* and `onMove` reports the change of the whole set since the previous move — the centroid's move,
|
|
42
|
+
* the spread's ratio, the twist's angle. One finger is a gesture too (a pan, scale 1, rotation 0).
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* trackGesture(scene, {
|
|
46
|
+
* onMove(g) { zoom *= g.scale; angle += g.rotation; panX += g.deltaX; panY += g.deltaY },
|
|
47
|
+
* })
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare const trackGesture: (target: GestureTarget, handler: GestureHandler) => {
|
|
51
|
+
remove(): void;
|
|
52
|
+
};
|
|
@@ -28,9 +28,10 @@ export type UIModalShow = (() => boolean) | Signal<boolean>;
|
|
|
28
28
|
* request, `onDismiss`. By default it hides an unbound modal and writes `false` into a bound
|
|
29
29
|
* signal; a bound function has nowhere to write, so a modal bound to one without `onDismiss`
|
|
30
30
|
* cannot be dismissed (a forced choice — the same as `dismissible(false)`). `display` is not a
|
|
31
|
-
* modal's switch
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* modal's switch (a bound display died on the first dismissal, which wrote a static
|
|
32
|
+
* `display: "none"` over the binding — the dialog never opened again). Deprecated, for the
|
|
33
|
+
* transition period a `.style({ display })` is still accepted, with a warning: a function becomes
|
|
34
|
+
* `bindShow(() => fn() !== "none")`, a value a show() / hide(); it will throw again.
|
|
34
35
|
*/
|
|
35
36
|
export interface UIModal extends UIWidget {
|
|
36
37
|
/**
|
|
@@ -82,6 +83,7 @@ export declare class ModalElement extends WidgetElement {
|
|
|
82
83
|
private _poseObj?;
|
|
83
84
|
private _poseKey;
|
|
84
85
|
constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn);
|
|
86
|
+
private _bindDisplay;
|
|
85
87
|
private _pose;
|
|
86
88
|
transition(hidden: UIModalTransition): this;
|
|
87
89
|
bindShow(value: UIModalShow): this;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.8.
|
|
1
|
+
export declare const SDK_VERSION = "2.8.2";
|
|
2
2
|
/** The major of a semver string, or null when it is not one. */
|
|
3
3
|
export declare const sdkMajor: (version: string | null | undefined) => number | null;
|
|
4
4
|
/** The `// sdk: <version>` line of a compiled bundle's header (sdk/src/compile/header.ts), read from
|