lecodes-sdk 0.20.0 → 0.20.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 +31 -0
- package/dist/inject.js +361 -260
- package/dist/types/audio/Bus.d.ts +45 -0
- package/dist/types/audio/Sound.d.ts +28 -0
- package/dist/types/audio/Voice.d.ts +27 -0
- package/dist/types/audio/audio.d.ts +83 -0
- package/dist/types/audio/support.d.ts +1 -0
- package/dist/types/gl/AudioSource.d.ts +60 -0
- package/dist/types/gl/AudioZone.d.ts +32 -0
- package/dist/types/gl/DecalSet.d.ts +103 -0
- package/dist/types/gl/Geometry.d.ts +5 -0
- package/dist/types/gl/Light.d.ts +7 -0
- package/dist/types/gl/Material.d.ts +86 -2
- package/dist/types/gl/Mesh.d.ts +11 -0
- package/dist/types/gl/Scene.d.ts +23 -0
- package/dist/types/gl/SceneAudio.d.ts +11 -0
- package/dist/types/gl/Texture.d.ts +29 -1
- package/dist/types/gl/animation/AnimationClip.d.ts +25 -12
- package/dist/types/gl/animation/core.d.ts +15 -10
- package/dist/types/gl/state.d.ts +0 -1
- package/dist/types/inject.d.ts +10 -0
- package/dist/types/runtime/input.d.ts +11 -0
- package/dist/types/ui/UIImage.d.ts +15 -5
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/prompts/dist/2d-game.md +408 -197
- package/prompts/dist/3d-app.md +491 -166
- package/prompts/dist/ar-app.md +373 -163
- package/prompts/dist/design.md +83 -87
- package/prompts/dist/ui-app.md +325 -136
- package/src/audio/Bus.ts +102 -0
- package/src/audio/Sound.ts +96 -0
- package/src/audio/Voice.ts +102 -0
- package/src/audio/audio.ts +161 -0
- package/src/audio/support.ts +6 -0
- package/src/bridges.d.ts +1481 -1352
- package/src/compile/compileProject.ts +30 -15
- package/src/compile/index.ts +3 -0
- package/src/core/Aspect.ts +33 -8
- package/src/g2/Scene2D.ts +7 -0
- package/src/gl/AudioSource.ts +113 -0
- package/src/gl/AudioZone.ts +75 -0
- package/src/gl/CameraPlace.ts +52 -52
- package/src/gl/DecalSet.ts +233 -0
- package/src/gl/Geometry.ts +5 -0
- package/src/gl/Light.ts +16 -0
- package/src/gl/Lightmap.ts +3 -2
- package/src/gl/Material.ts +152 -4
- package/src/gl/Mesh.ts +20 -1
- package/src/gl/Ragdoll.ts +270 -270
- package/src/gl/Scene.ts +41 -7
- package/src/gl/SceneAudio.ts +26 -0
- package/src/gl/Texture.ts +43 -3
- package/src/gl/Trigger.ts +45 -45
- package/src/gl/Vehicle.ts +5 -5
- package/src/gl/animation/AnimationClip.ts +43 -20
- package/src/gl/animation/Animator.ts +4 -3
- package/src/gl/animation/core.ts +20 -15
- package/src/gl/scenarios.ts +291 -291
- package/src/gl/state.ts +1 -1
- package/src/inject.ts +12 -0
- package/src/runtime/input.ts +6 -1
- package/src/scene/gizmos.ts +148 -148
- package/src/ui/UIImage.ts +21 -7
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import { type FetchResponse, type File } from "../runtime/fetch";
|
|
2
|
+
/** `Texture.load` options. */
|
|
3
|
+
export type TextureLoadOptions = {
|
|
4
|
+
/** `true` (default): colour, stored sRGB. `false`: data (normal map, mask, heightmap) — kept linear. */
|
|
5
|
+
srgb?: boolean;
|
|
6
|
+
/** Ignore `Texture.maxSize` for this texture (a lightmap page, a lookup table). */
|
|
7
|
+
fullSize?: boolean;
|
|
8
|
+
};
|
|
2
9
|
export declare class Texture {
|
|
10
|
+
static _maxSize: number;
|
|
11
|
+
/** Engine-wide cap on texture size (a "texture quality" setting), 0 = none. A KTX2 wider or
|
|
12
|
+
* taller than this loses its top mip levels on load (nothing resampled, less memory and
|
|
13
|
+
* bandwidth), a glTF PNG/JPEG is downsampled. Reaches textures loaded AFTER it is set — a loaded
|
|
14
|
+
* level keeps its textures — so set it up front (`SceneOptions.maxTextureSize`, or before the
|
|
15
|
+
* level loads) and apply a menu change on the next level load. Lightmap pages are exempt
|
|
16
|
+
* (`TextureLoadOptions.fullSize`). A host may pin it (desktop `CREATOR_TEXTURE_MAX_SIZE`). */
|
|
17
|
+
static _anisotropy: number;
|
|
18
|
+
/** Engine-wide anisotropic filtering, 1 (off) … 16 (default 2; `SceneOptions.anisotropy` sets it up
|
|
19
|
+
* front). A sampler is baked when its texture is bound, so like `maxSize` this reaches textures
|
|
20
|
+
* loaded AFTER it — set it before the level loads. Measured on a lightmapped interior at 720p:
|
|
21
|
+
* 4× costs ~20 % of the frame over 1× on an integrated GPU. A host may pin it. */
|
|
22
|
+
static get anisotropy(): number;
|
|
23
|
+
static set anisotropy(level: number);
|
|
24
|
+
static get maxSize(): number;
|
|
25
|
+
static set maxSize(size: number);
|
|
3
26
|
readonly width: number;
|
|
4
27
|
readonly height: number;
|
|
5
28
|
/** Horizontal wrap mode (U). */
|
|
@@ -23,5 +46,10 @@ export declare class Texture {
|
|
|
23
46
|
}): Texture;
|
|
24
47
|
/** Re-upload a rectangle of a `fromPixels` texture (same channel count). */
|
|
25
48
|
update(x: number, y: number, width: number, height: number, data: Uint8Array): void;
|
|
26
|
-
|
|
49
|
+
/** Decode an image (PNG / JPG, or a KTX2 the core transcodes) into a texture. `srgb` (default
|
|
50
|
+
* true) says the bytes are COLOUR, stored sRGB so the GPU linearises them on sample; pass
|
|
51
|
+
* `false` for DATA — a normal map, a mask, a heightmap — which must come back as stored (a
|
|
52
|
+
* flat normal read through sRGB bends by ~35°). A KTX2 decides by its own header. Image
|
|
53
|
+
* textures get a mip chain (trilinear) on hosts that build one. */
|
|
54
|
+
static load(source: string | FetchResponse | File, options?: TextureLoadOptions): Promise<Texture>;
|
|
27
55
|
}
|
|
@@ -22,6 +22,19 @@ export type ClipInfo = {
|
|
|
22
22
|
duration: number;
|
|
23
23
|
trackCount: number;
|
|
24
24
|
};
|
|
25
|
+
/** What `AnimationClip.from(clip, …)` derives from a clip. */
|
|
26
|
+
export type DeriveOptions = {
|
|
27
|
+
/** The clip MIRRORED — left ↔ right, the motion on the other side of the body (a stop that brakes on the
|
|
28
|
+
* left foot brakes on the right). Derived on the rig of the clip's own file (joints pair by name, the
|
|
29
|
+
* sagittal plane comes from the rest pose), so the result is the same on every model: its contacts,
|
|
30
|
+
* phase, root motion and heading are the mirrored ones, its name is `<name>_M`. Only clips from a GLB
|
|
31
|
+
* carry a rig; a curve-built clip cannot be mirrored. */
|
|
32
|
+
mirror?: boolean;
|
|
33
|
+
/** Start of the window, seconds of the source (default 0). */
|
|
34
|
+
from?: number;
|
|
35
|
+
/** End of the window, seconds of the source (default the clip's end). */
|
|
36
|
+
to?: number;
|
|
37
|
+
};
|
|
25
38
|
export declare class AnimationClip {
|
|
26
39
|
/** Source name (the clip's name inside its file; `"clip"` for procedural clips). Informational —
|
|
27
40
|
* an Animator addresses clips by the key YOU give it. */
|
|
@@ -33,8 +46,8 @@ export declare class AnimationClip {
|
|
|
33
46
|
private constructor();
|
|
34
47
|
/** Mark a moment of the clip (SECONDS from its start) with an event name: `kick.addEvent(0.4, 'hit')`
|
|
35
48
|
* → `anim.on('hit', (clip, layer) => …)` fires when the playhead crosses it, loops included.
|
|
36
|
-
* Events are part of the clip: every model playing it gets them; `
|
|
37
|
-
* the
|
|
49
|
+
* Events are part of the clip: every model playing it gets them; `AnimationClip.from(clip, { from, to })`
|
|
50
|
+
* keeps the ones inside the window, re-timed. Chainable. */
|
|
38
51
|
addEvent(time: number, name: string): this;
|
|
39
52
|
private _pushEvents;
|
|
40
53
|
/** Load ONE clip from a GLB: the file's only/first clip, or the one named / at the given index. */
|
|
@@ -43,18 +56,18 @@ export declare class AnimationClip {
|
|
|
43
56
|
static loadAll(source: string | FetchResponse): Promise<Record<string, AnimationClip>>;
|
|
44
57
|
/** Build a clip from curves in code — no DCC needed. Keys are `[time, value]`; a track binds to the
|
|
45
58
|
* node of that name when the clip is used by an Animator (bones, or any child node). */
|
|
46
|
-
static
|
|
47
|
-
/** A
|
|
48
|
-
* (`
|
|
49
|
-
* action,
|
|
59
|
+
static fromCurves(def: ClipDef): AnimationClip;
|
|
60
|
+
/** A NEW clip derived from `clip`: its mirror (`{ mirror: true }` — the other side of the body), a window
|
|
61
|
+
* of it (`{ from, to }` seconds of the source, re-timed to 0; array-slice semantics), or both. Cut a
|
|
62
|
+
* too-long take down to the action, carve several sub-clips out of one packed timeline, get the
|
|
63
|
+
* left-footed stop from the right-footed one:
|
|
50
64
|
*
|
|
51
|
-
* clips: { Kick:
|
|
65
|
+
* clips: { Kick: AnimationClip.from(kick, { from: 0.2, to: 1.1 }), StopM: AnimationClip.from(stop, { mirror: true }) }
|
|
52
66
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
slice(start: number, end?: number): AnimationClip;
|
|
67
|
+
* A window drops the keys outside it and interpolates exact boundary values in, so the clip starts and
|
|
68
|
+
* ends precisely on the source's pose at the cut points. Everything downstream (blend spaces, events'
|
|
69
|
+
* times, root motion, foot contacts, phase sync) sees a normal clip. */
|
|
70
|
+
static from(clip: AnimationClip, options: DeriveOptions): AnimationClip;
|
|
58
71
|
private static _label;
|
|
59
72
|
private static _loadSet;
|
|
60
73
|
}
|
|
@@ -6,18 +6,17 @@ import { Vec3 } from "../../math/vec";
|
|
|
6
6
|
import type { Node } from "../Node";
|
|
7
7
|
/** A position on a blend axis (1D) or plane (2D). */
|
|
8
8
|
export type BlendPosition = number | readonly [number, number];
|
|
9
|
-
/** The transition time (seconds) a play / playLoop without `fade` uses. */
|
|
10
|
-
export declare const DEFAULT_FADE = 0.2;
|
|
11
9
|
export type PlayOptions = {
|
|
12
|
-
/** Transition seconds — how long the difference to the pose the layer SHOWED
|
|
13
|
-
*
|
|
10
|
+
/** Transition seconds — how long the difference to the pose the layer SHOWED (its loop, a one-shot,
|
|
11
|
+
* or rest) takes to decay. Default `0` = cut: a fade is always asked for, never implied. Also the
|
|
12
|
+
* transition back to the loop at the end unless `fadeOut` overrides it. */
|
|
14
13
|
fade?: number;
|
|
15
14
|
/** Transition seconds for the way in only (overrides `fade`). */
|
|
16
15
|
fadeIn?: number;
|
|
17
|
-
/** One-shots: the transition BACK at the end (overrides `fade`
|
|
18
|
-
* clip ends — while it still plays — so the hand-over lands on the
|
|
19
|
-
* layer with no loop
|
|
20
|
-
*
|
|
16
|
+
/** One-shots: the transition BACK to the loop at the end (overrides `fade`; `0` = cut at the end).
|
|
17
|
+
* It starts this long before the clip ends — while it still plays — so the hand-over lands on the
|
|
18
|
+
* last pose, not after it. On a layer with no loop the clip HOLDS its last frame (a rock that broke
|
|
19
|
+
* stays broken) — `anim.stop({ fade })` is the way back to rest. */
|
|
21
20
|
fadeOut?: number;
|
|
22
21
|
/** Playback rate for this clip (default 1). */
|
|
23
22
|
speed?: number;
|
|
@@ -39,8 +38,8 @@ export type StopOptions = {
|
|
|
39
38
|
fade?: number;
|
|
40
39
|
};
|
|
41
40
|
export type LoopOptions = {
|
|
42
|
-
/** Transition seconds from whatever the layer shows — its previous loop,
|
|
43
|
-
*
|
|
41
|
+
/** Transition seconds from whatever the layer shows — its previous loop, a one-shot still playing,
|
|
42
|
+
* or rest. Default `0` = cut: a loop wanting a transition asks for one (`{ fade: 0.2 }`). */
|
|
44
43
|
fade?: number;
|
|
45
44
|
/** Playback rate of the loop's clips (default 1). */
|
|
46
45
|
speed?: number;
|
|
@@ -165,6 +164,12 @@ export type ClipInfo = {
|
|
|
165
164
|
turnAt(time: number): number;
|
|
166
165
|
/** the root's own speed at `time`, m/s — how fast the clip is moving the body right there */
|
|
167
166
|
speedAt(time: number): number;
|
|
167
|
+
/** the PELVIS' yaw relative to the clip's heading at `time` (rad, + = left, wrapped to ±π): the stance twist
|
|
168
|
+
* the heading leaves out — an idle stands ~43° off the course it starts along, a stop's tail turns into that
|
|
169
|
+
* stance while the heading holds. A controller that switches clips mid-pose can keep the PELVIS continuous
|
|
170
|
+
* (turn the node by the difference between the two clips' values) where keeping the course would swing
|
|
171
|
+
* the body. Without a baked heading: the pelvis' yaw at frame 0 throughout. */
|
|
172
|
+
pelvisYawAt(time: number): number;
|
|
168
173
|
/** the unit travel direction at `time` ([x, z], model space, held through stills) — integrate
|
|
169
174
|
* direction × d(travel) to reconstruct the root's 2D path (a treadmill display, a turn's arc) */
|
|
170
175
|
directionAt(time: number): [number, number];
|
package/dist/types/gl/state.d.ts
CHANGED
package/dist/types/inject.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export { WebSocket } from "./runtime/net";
|
|
|
23
23
|
export { Net, NetPlayer, Replicated, NetEntity, type NetMessage, type NetRole, type NetStatus, type NetEvents, type NetLaunch, type NetInput, type NetKind, type NetTransform } from "./net";
|
|
24
24
|
export { __rpc, __channel, __serverOnly, RpcError, type ClientChannel } from "./runtime/rpc";
|
|
25
25
|
export { AudioPlayer, VideoPlayer } from "./runtime/media";
|
|
26
|
+
export { Sound, type SoundOptions } from "./audio/Sound";
|
|
27
|
+
export { Voice, type VoiceEvents } from "./audio/Voice";
|
|
28
|
+
export { Bus, REVERB_PRESETS, type ReverbPreset, type ReverbParams, type EchoParams } from "./audio/Bus";
|
|
29
|
+
export { audio, type PlaySoundOptions, type SpatialOptions, type Rolloff, type AudioStats } from "./audio/audio";
|
|
26
30
|
export { openFilePicker, files, type FileData } from "./runtime/files";
|
|
27
31
|
export { share } from "./runtime/share";
|
|
28
32
|
export { ClickEvent, TouchStartEvent, LongPressEvent } from "./runtime/touch";
|
|
@@ -84,6 +88,9 @@ export { Model } from "./gl/Model";
|
|
|
84
88
|
export { Shape } from "./gl/Shape";
|
|
85
89
|
export { Physics } from "./gl/Physics";
|
|
86
90
|
export { Trigger } from "./gl/Trigger";
|
|
91
|
+
export { AudioSource, type AudioCone } from "./gl/AudioSource";
|
|
92
|
+
export { AudioZone } from "./gl/AudioZone";
|
|
93
|
+
export { SceneAudio } from "./gl/SceneAudio";
|
|
87
94
|
export { CharacterController } from "./gl/CharacterController";
|
|
88
95
|
export { Vehicle } from "./gl/Vehicle";
|
|
89
96
|
export type { DriveLayout, DifferentialMode, EngineConfig, SteeringConfig, AeroConfig } from "./gl/Vehicle";
|
|
@@ -121,8 +128,11 @@ export { Geometry } from "./gl/Geometry";
|
|
|
121
128
|
export { InstancedMesh } from "./gl/InstancedMesh";
|
|
122
129
|
export type { InstanceTransform } from "./gl/InstancedMesh";
|
|
123
130
|
export { Texture } from "./gl/Texture";
|
|
131
|
+
export type { TextureLoadOptions } from "./gl/Texture";
|
|
124
132
|
export { Camera } from "./gl/Camera";
|
|
125
133
|
export { Ray } from "./gl/Ray";
|
|
126
134
|
export { Plane } from "./gl/Plane";
|
|
127
135
|
export { Noise } from "./gl/Noise";
|
|
128
136
|
export { Particles, Trail, curve, colorCurve } from "./gl/Particles";
|
|
137
|
+
export { DecalSet } from "./gl/DecalSet";
|
|
138
|
+
export type { DecalOptions, DecalSetOptions, DecalSpawnOptions, DecalPlacement } from "./gl/DecalSet";
|
|
@@ -8,6 +8,7 @@ export declare const InputChannel: {
|
|
|
8
8
|
readonly WheelY: 5;
|
|
9
9
|
readonly PointerLocked: 6;
|
|
10
10
|
readonly GamepadCount: 7;
|
|
11
|
+
readonly PointerOnUI: 8;
|
|
11
12
|
readonly GamepadBase: 16;
|
|
12
13
|
readonly GamepadStride: 16;
|
|
13
14
|
readonly PadConnected: 0;
|
|
@@ -64,6 +65,11 @@ export declare const mouse: {
|
|
|
64
65
|
* gesture (call it in a 'keydown' handler for MouseLeft); hosts drop it on focus loss and
|
|
65
66
|
* re-acquire on focus. Escape does NOT unlock by itself on native hosts — call `unlock()`. */
|
|
66
67
|
readonly locked: boolean;
|
|
68
|
+
/** The primary button went down on a UI element (a button, a scrollable, an input, a modal
|
|
69
|
+
* backdrop) and is still held. Stays true wherever the cursor drifts until the release, so
|
|
70
|
+
* `if (!Input.mouse.onUI) look(Input.mouse.delta)` never turns a HUD drag into camera look.
|
|
71
|
+
* Always false while `locked`. A press that fell through to the scene reads false. */
|
|
72
|
+
readonly onUI: boolean;
|
|
67
73
|
lock(): boolean;
|
|
68
74
|
unlock(): void;
|
|
69
75
|
};
|
|
@@ -108,6 +114,11 @@ export declare const Input: {
|
|
|
108
114
|
* gesture (call it in a 'keydown' handler for MouseLeft); hosts drop it on focus loss and
|
|
109
115
|
* re-acquire on focus. Escape does NOT unlock by itself on native hosts — call `unlock()`. */
|
|
110
116
|
readonly locked: boolean;
|
|
117
|
+
/** The primary button went down on a UI element (a button, a scrollable, an input, a modal
|
|
118
|
+
* backdrop) and is still held. Stays true wherever the cursor drifts until the release, so
|
|
119
|
+
* `if (!Input.mouse.onUI) look(Input.mouse.delta)` never turns a HUD drag into camera look.
|
|
120
|
+
* Always false while `locked`. A press that fell through to the scene reads false. */
|
|
121
|
+
readonly onUI: boolean;
|
|
111
122
|
lock(): boolean;
|
|
112
123
|
unlock(): void;
|
|
113
124
|
};
|
|
@@ -2,6 +2,7 @@ import type { FetchResponse } from "../runtime/fetch";
|
|
|
2
2
|
import type { SvgSourceValue as SvgSource } from "../runtime/misc";
|
|
3
3
|
import type { File } from "../runtime/fetch";
|
|
4
4
|
import { Canvas } from "../canvas/Canvas";
|
|
5
|
+
import type { Scene2D } from "../g2/Scene2D";
|
|
5
6
|
import { type Color, type ElementStyle, type UIElementBase } from "./UINode";
|
|
6
7
|
export type UIImageStyle = ElementStyle & {
|
|
7
8
|
borderRadius?: number;
|
|
@@ -13,12 +14,21 @@ export type UIImageStyle = ElementStyle & {
|
|
|
13
14
|
export type CanvasImageSource = {
|
|
14
15
|
canvasSurface: number;
|
|
15
16
|
};
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export type
|
|
17
|
+
/** A live 2D scene as an image source: the host draws the scene into the node's box every frame
|
|
18
|
+
* (the scene's camera, projected into the box). No intrinsic size — give the node a width and
|
|
19
|
+
* height. */
|
|
20
|
+
export type Scene2DImageSource = {
|
|
21
|
+
scene2d: number;
|
|
22
|
+
};
|
|
23
|
+
/** Accepted image sources. A Canvas is baked to a surface marker on assign; a Scene2D becomes a
|
|
24
|
+
* live-scene marker. */
|
|
25
|
+
export type ImageSource = string | FetchResponse | File | SvgSource | Canvas | Scene2D;
|
|
26
|
+
/** The stored/resolved image source (a Canvas is resolved to a surface marker, a Scene2D to a
|
|
27
|
+
* live-scene marker). */
|
|
28
|
+
export type ResolvedImageSource = string | FetchResponse | File | SvgSource | CanvasImageSource | Scene2DImageSource;
|
|
20
29
|
/** An image element. Sources: URL / `asset(...)`, fetch response / File, an SVG source
|
|
21
|
-
* (`assetIcon`),
|
|
30
|
+
* (`assetIcon`), a live Canvas (`canvas.update()` refreshes the node in place), or a live Scene2D
|
|
31
|
+
* (drawn into the box every frame — a minimap). */
|
|
22
32
|
export interface UIImage extends UIElementBase<UIImageStyle> {
|
|
23
33
|
readonly type: "image";
|
|
24
34
|
/** The image source — writable to swap the picture in place. */
|