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
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type ReverbPreset = "room" | "hall" | "cave" | "arena" | "bathroom" | "outdoor";
|
|
2
|
+
export type ReverbParams = {
|
|
3
|
+
/** 0 (a closet) … 1 (a cathedral). */
|
|
4
|
+
roomSize?: number;
|
|
5
|
+
/** High-frequency loss per reflection, 0 … 1. */
|
|
6
|
+
damping?: number;
|
|
7
|
+
/** Stereo width of the tail, 0 … 1. */
|
|
8
|
+
width?: number;
|
|
9
|
+
/** Wet amount, 0 … 1. */
|
|
10
|
+
mix?: number;
|
|
11
|
+
/** Seconds before the tail starts (a big hall: 0.02 … 0.05). */
|
|
12
|
+
preDelay?: number;
|
|
13
|
+
};
|
|
14
|
+
export type EchoParams = {
|
|
15
|
+
/** Seconds between repeats (up to 2). */
|
|
16
|
+
delay?: number;
|
|
17
|
+
/** Feedback, 0 … 0.95 — how many repeats survive. */
|
|
18
|
+
decay?: number;
|
|
19
|
+
/** Wet amount, 0 … 1. */
|
|
20
|
+
mix?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const REVERB_PRESETS: Record<ReverbPreset, Required<ReverbParams>>;
|
|
23
|
+
export declare class Bus {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
private _volume;
|
|
26
|
+
private _muted;
|
|
27
|
+
private _reverb;
|
|
28
|
+
private _echo;
|
|
29
|
+
private _lowpass;
|
|
30
|
+
private get _live();
|
|
31
|
+
get volume(): number;
|
|
32
|
+
set volume(v: number);
|
|
33
|
+
get muted(): boolean;
|
|
34
|
+
set muted(v: boolean);
|
|
35
|
+
/** A preset name, explicit params, or null (off). */
|
|
36
|
+
get reverb(): ReverbPreset | ReverbParams | null;
|
|
37
|
+
set reverb(v: ReverbPreset | ReverbParams | null);
|
|
38
|
+
get echo(): EchoParams | null;
|
|
39
|
+
set echo(v: EchoParams | null);
|
|
40
|
+
/** Low-pass cutoff in Hz (20 … 20000), null = off. */
|
|
41
|
+
get lowpass(): number | null;
|
|
42
|
+
set lowpass(v: number | null);
|
|
43
|
+
/** Stop every voice on this bus (fade in seconds). */
|
|
44
|
+
stopAll(fade?: number): void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type SoundOptions = {
|
|
2
|
+
/** Keep two channels (2D playback of stereo material — music beds, ambiences). Default: the clip
|
|
3
|
+
* is decoded MONO, which is what 3D spatialization needs and what SFX are anyway. */
|
|
4
|
+
stereo?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare class Sound {
|
|
7
|
+
/** The urls this clip was loaded from (one per variant). */
|
|
8
|
+
readonly urls: readonly string[];
|
|
9
|
+
private readonly _durations;
|
|
10
|
+
private _channels;
|
|
11
|
+
private _disposed;
|
|
12
|
+
private _last;
|
|
13
|
+
private constructor();
|
|
14
|
+
/** Fetch + decode. An array = variants: `play` picks a random one (never the same twice in a row
|
|
15
|
+
* when there are 3 or more). Rejects with the failing url when a file cannot be decoded. */
|
|
16
|
+
static load(src: string | string[], options?: SoundOptions): Promise<Sound>;
|
|
17
|
+
/** Seconds (the first variant's). 0 for a silent clip. */
|
|
18
|
+
get duration(): number;
|
|
19
|
+
/** Decoded channel count: 1, or 2 with `{ stereo: true }`. */
|
|
20
|
+
get channels(): number;
|
|
21
|
+
/** How many variants this clip carries. */
|
|
22
|
+
get variants(): number;
|
|
23
|
+
/** True when the engine has this clip (false on hosts without audio, or after dispose). */
|
|
24
|
+
get ready(): boolean;
|
|
25
|
+
get disposed(): boolean;
|
|
26
|
+
/** Free the engine's PCM. Voices playing it stop at once. Idempotent. */
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Emitter } from "../core/events";
|
|
2
|
+
export type VoiceEvents = {
|
|
3
|
+
/** The voice is over: the clip ended, `stop` completed, or the pool reused the slot. */
|
|
4
|
+
ended: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare class Voice extends Emitter<VoiceEvents> {
|
|
7
|
+
private _volume;
|
|
8
|
+
private _pitch;
|
|
9
|
+
private _pan;
|
|
10
|
+
private _over;
|
|
11
|
+
addEventListener<K extends keyof VoiceEvents>(channel: K, callback: VoiceEvents[K]): void;
|
|
12
|
+
/** True while the engine plays this voice. */
|
|
13
|
+
get playing(): boolean;
|
|
14
|
+
/** Seconds into the clip. */
|
|
15
|
+
get time(): number;
|
|
16
|
+
get volume(): number;
|
|
17
|
+
set volume(v: number);
|
|
18
|
+
get pitch(): number;
|
|
19
|
+
set pitch(v: number);
|
|
20
|
+
/** 2D voices only: -1 left … 1 right. */
|
|
21
|
+
get pan(): number;
|
|
22
|
+
set pan(v: number);
|
|
23
|
+
/** Stop now, or fade out over `fade` seconds. `ended` fires from the engine afterwards. */
|
|
24
|
+
stop(options?: {
|
|
25
|
+
fade?: number;
|
|
26
|
+
}): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Vec3Like } from "../math/vec";
|
|
2
|
+
import { Bus } from "./Bus";
|
|
3
|
+
import type { Sound } from "./Sound";
|
|
4
|
+
import { Voice } from "./Voice";
|
|
5
|
+
export type PlaySoundOptions = {
|
|
6
|
+
/** 0 … 1 (and above, at your own risk). Default 1. */
|
|
7
|
+
volume?: number;
|
|
8
|
+
/** Playback rate, 1 = unchanged. Default 1. */
|
|
9
|
+
pitch?: number;
|
|
10
|
+
loop?: boolean;
|
|
11
|
+
/** Bus name; default: the source's bus, `sfx` for 2D. */
|
|
12
|
+
bus?: string;
|
|
13
|
+
/** Higher survives voice stealing when the pool is full. Default 0. */
|
|
14
|
+
priority?: number;
|
|
15
|
+
/** Fade-in seconds. Default 0. */
|
|
16
|
+
fade?: number;
|
|
17
|
+
/** Seconds into the clip to start from. */
|
|
18
|
+
startAt?: number;
|
|
19
|
+
/** 2D only: -1 left … 1 right. */
|
|
20
|
+
pan?: number;
|
|
21
|
+
};
|
|
22
|
+
export type Rolloff = "none" | "inverse" | "linear" | "exponential";
|
|
23
|
+
/** Distance model of an AudioSource / playAt. */
|
|
24
|
+
export type SpatialOptions = {
|
|
25
|
+
/** Metres of full volume around the source. Default 1. */
|
|
26
|
+
minDistance?: number;
|
|
27
|
+
/** Metres beyond which the source no longer gets quieter. Default 50. */
|
|
28
|
+
maxDistance?: number;
|
|
29
|
+
/** How volume falls between the two: `inverse` (default, physical), `linear`, `exponential`, `none`. */
|
|
30
|
+
rolloff?: Rolloff;
|
|
31
|
+
};
|
|
32
|
+
export declare const ROLLOFF: Record<Rolloff, number>;
|
|
33
|
+
export type AudioStats = {
|
|
34
|
+
voicesPlaying: number;
|
|
35
|
+
voicesMono: number;
|
|
36
|
+
voicesStereo: number;
|
|
37
|
+
/** Voices displaced (or dropped) by a fuller pool since start. */
|
|
38
|
+
stolen: number;
|
|
39
|
+
clips: number;
|
|
40
|
+
clipBytes: number;
|
|
41
|
+
/** Master peak since the previous read, linear (1 = full scale). */
|
|
42
|
+
peak: number;
|
|
43
|
+
sampleRate: number;
|
|
44
|
+
/** The reverb zone the listener is in (0 = none) and how far inside (0 … 1). */
|
|
45
|
+
listenerZone: number;
|
|
46
|
+
zoneBlend: number;
|
|
47
|
+
/** Voices rendered binaurally right now (see `audio.hrtf`). */
|
|
48
|
+
hrtfVoices: number;
|
|
49
|
+
};
|
|
50
|
+
declare class AudioSystem {
|
|
51
|
+
private readonly _buses;
|
|
52
|
+
private _hrtf;
|
|
53
|
+
private _hrtfVoices;
|
|
54
|
+
private _timeScalePitch;
|
|
55
|
+
/** True when this host mixes sound. Everything below is a silent no-op otherwise. */
|
|
56
|
+
get supported(): boolean;
|
|
57
|
+
/** HRTF binaural rendering (MIT KEMAR filters on the CPU): sounds get a real up / down / behind in
|
|
58
|
+
* HEADPHONES. Off by default — on speakers it only smears the image. Applies to the `hrtfVoices`
|
|
59
|
+
* nearest 3D voices; the rest keep plain panning. */
|
|
60
|
+
get hrtf(): boolean;
|
|
61
|
+
set hrtf(v: boolean);
|
|
62
|
+
/** `Time.scale` also pitches the sfx bus: slow motion drops every effect's tone, like a film. Default
|
|
63
|
+
* false — a pause only mutes sfx, the menu click keeps its pitch. */
|
|
64
|
+
get timeScalePitch(): boolean;
|
|
65
|
+
set timeScalePitch(v: boolean);
|
|
66
|
+
/** How many voices get the (CPU-heavier) binaural path. Default 16. */
|
|
67
|
+
get hrtfVoices(): number;
|
|
68
|
+
set hrtfVoices(n: number);
|
|
69
|
+
/** A bus by name — the five built-ins, or an app-defined one created on first use. */
|
|
70
|
+
bus(name: string): Bus;
|
|
71
|
+
get master(): Bus;
|
|
72
|
+
/** 2D playback (UI, stingers, music one-shots). */
|
|
73
|
+
play(sound: Sound, options?: PlaySoundOptions): Voice;
|
|
74
|
+
/** A one-shot at a world position with its own transient source — impacts, ricochets, debris.
|
|
75
|
+
* The source is freed when the voice ends. */
|
|
76
|
+
playAt(sound: Sound, position: Vec3Like, options?: PlaySoundOptions & SpatialOptions): Voice;
|
|
77
|
+
/** Stop every voice on every bus (fade in seconds). */
|
|
78
|
+
stopAll(fade?: number): void;
|
|
79
|
+
/** Engine counters for a debug overlay or a perf log. */
|
|
80
|
+
get stats(): AudioStats;
|
|
81
|
+
}
|
|
82
|
+
export declare const audio: AudioSystem;
|
|
83
|
+
export type { AudioSystem };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const audioSupported: boolean;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Aspect } from "../core/Aspect";
|
|
2
|
+
import type { FieldMeta } from "../core/fields";
|
|
3
|
+
import { type PlaySoundOptions, type Rolloff } from "../audio/audio";
|
|
4
|
+
import type { Sound } from "../audio/Sound";
|
|
5
|
+
import type { Voice } from "../audio/Voice";
|
|
6
|
+
import type { Node } from "./Node";
|
|
7
|
+
export type AudioCone = {
|
|
8
|
+
/** Degrees of full volume around the node's −Z. */
|
|
9
|
+
inner: number;
|
|
10
|
+
/** Degrees where the volume has fallen to `outerGain`. */
|
|
11
|
+
outer: number;
|
|
12
|
+
/** Volume behind the source, 0 … 1. */
|
|
13
|
+
outerGain?: number;
|
|
14
|
+
};
|
|
15
|
+
export declare class AudioSource extends Aspect<"audio", Node> {
|
|
16
|
+
static readonly aspect = "audio";
|
|
17
|
+
static fields: FieldMeta<AudioSource>;
|
|
18
|
+
private _minDistance;
|
|
19
|
+
private _maxDistance;
|
|
20
|
+
private _rolloff;
|
|
21
|
+
private _cone;
|
|
22
|
+
private _doppler;
|
|
23
|
+
private _spread;
|
|
24
|
+
private _occlusion;
|
|
25
|
+
private _bus;
|
|
26
|
+
/** Metres of full volume around the node. Default 1. */
|
|
27
|
+
get minDistance(): number;
|
|
28
|
+
set minDistance(v: number);
|
|
29
|
+
/** Metres beyond which the source no longer gets quieter. Default 50. */
|
|
30
|
+
get maxDistance(): number;
|
|
31
|
+
set maxDistance(v: number);
|
|
32
|
+
/** `inverse` (default), `linear`, `exponential`, `none`. */
|
|
33
|
+
get rolloff(): Rolloff;
|
|
34
|
+
set rolloff(v: Rolloff);
|
|
35
|
+
/** Directional source along the node's −Z; null = omnidirectional (default). */
|
|
36
|
+
get cone(): AudioCone | null;
|
|
37
|
+
set cone(v: AudioCone | null);
|
|
38
|
+
/** Doppler amount 0 … 1 (0 = off, the default) — needs the node to actually move. */
|
|
39
|
+
get doppler(): number;
|
|
40
|
+
set doppler(v: number);
|
|
41
|
+
/** 0 = pin-point panning (default) … 1 = the same on every speaker (a big, close source). */
|
|
42
|
+
get spread(): number;
|
|
43
|
+
set spread(v: number);
|
|
44
|
+
/** The engine raycasts listener → source (against solid bodies) and muffles the voices when
|
|
45
|
+
* something is in the way. Default false. */
|
|
46
|
+
get occlusion(): boolean;
|
|
47
|
+
set occlusion(v: boolean);
|
|
48
|
+
/** Default bus for voices on this source. Default `sfx`. */
|
|
49
|
+
get bus(): string;
|
|
50
|
+
set bus(v: string);
|
|
51
|
+
/** Live voices on this source. */
|
|
52
|
+
get voices(): number;
|
|
53
|
+
onAttach(): void;
|
|
54
|
+
onDetach(): void;
|
|
55
|
+
/** Play a clip from this node. */
|
|
56
|
+
play(sound: Sound, options?: PlaySoundOptions): Voice;
|
|
57
|
+
/** Stop every voice on this source (fade in seconds). */
|
|
58
|
+
stopAll(fade?: number): void;
|
|
59
|
+
private _push;
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Aspect } from "../core/Aspect";
|
|
2
|
+
import { type ReverbParams, type ReverbPreset } from "../audio/Bus";
|
|
3
|
+
import { type Vec3Like } from "../math/vec";
|
|
4
|
+
import type { Node } from "./Node";
|
|
5
|
+
export declare class AudioZone extends Aspect<"audioZone", Node> {
|
|
6
|
+
static readonly aspect = "audioZone";
|
|
7
|
+
private _box;
|
|
8
|
+
private _sphere;
|
|
9
|
+
private _reverb;
|
|
10
|
+
private _blend;
|
|
11
|
+
private _bus;
|
|
12
|
+
/** The engine's zone id — what `audio.stats.listenerZone` reports while the listener is inside. */
|
|
13
|
+
get id(): number;
|
|
14
|
+
/** Half-extents [hx, hy, hz]; falls back to the node's Shape box, then a 1 m cube. */
|
|
15
|
+
get box(): Vec3Like | null;
|
|
16
|
+
set box(v: Vec3Like | null);
|
|
17
|
+
/** Radius; falls back to the node's Shape sphere. */
|
|
18
|
+
get sphere(): number | null;
|
|
19
|
+
set sphere(v: number | null);
|
|
20
|
+
/** A preset name or explicit params (see Bus.reverb). */
|
|
21
|
+
get reverb(): ReverbPreset | ReverbParams;
|
|
22
|
+
set reverb(v: ReverbPreset | ReverbParams);
|
|
23
|
+
/** Crossfade depth in metres inside the border (0 = a hard edge). Default 1. */
|
|
24
|
+
get blend(): number;
|
|
25
|
+
set blend(v: number);
|
|
26
|
+
/** The bus the zone's reverb rides on. Default `sfx`. */
|
|
27
|
+
get bus(): string;
|
|
28
|
+
set bus(v: string);
|
|
29
|
+
onAttach(): void;
|
|
30
|
+
onDetach(): void;
|
|
31
|
+
private _push;
|
|
32
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Node } from "./Node";
|
|
2
|
+
import { Material } from "./Material";
|
|
3
|
+
import type { Texture } from "./Texture";
|
|
4
|
+
import { type Vec3Like } from "../math/vec";
|
|
5
|
+
import { type QuatLike } from "../math/quat";
|
|
6
|
+
import { type ColorInput } from "../core/color";
|
|
7
|
+
/** Per-decal look and life — defaults come from the set's options. */
|
|
8
|
+
export type DecalOptions = {
|
|
9
|
+
/** Image width and height on the surface (world units); a number = square. Default 0.2. */
|
|
10
|
+
size?: number | [number, number];
|
|
11
|
+
/** Projection depth (world units): how far in front of and behind the hit point the decal still
|
|
12
|
+
* lands. Default = the smaller of width / height. */
|
|
13
|
+
depth?: number;
|
|
14
|
+
/** Atlas cell (row-major from the top-left) for a set with a `sheet`; `"random"` picks one.
|
|
15
|
+
* Default 0. */
|
|
16
|
+
frame?: number | "random";
|
|
17
|
+
/** Tint multiplied into the image. Default white. */
|
|
18
|
+
tint?: ColorInput;
|
|
19
|
+
/** 0..1 on top of the tint's alpha. Default 1. */
|
|
20
|
+
opacity?: number;
|
|
21
|
+
/** Seconds until the decal is gone; 0 = stays until recycled. Default 0. */
|
|
22
|
+
life?: number;
|
|
23
|
+
/** Seconds to fade in after spawning. Default 0. */
|
|
24
|
+
fadeIn?: number;
|
|
25
|
+
/** Seconds of fade at the end of `life` (ignored with life 0). Default 0. */
|
|
26
|
+
fadeOut?: number;
|
|
27
|
+
};
|
|
28
|
+
export type DecalSetOptions = DecalOptions & {
|
|
29
|
+
/** The material — `Material.decal({ map })` by default (`map` below is its shortcut). A custom
|
|
30
|
+
* material must keep decal.mat's vertex contract. */
|
|
31
|
+
material?: Material;
|
|
32
|
+
/** Atlas texture for the default material. */
|
|
33
|
+
map?: Texture;
|
|
34
|
+
/** Tangent-space normal atlas (same cell grid) → a RELIEF decal that bends the surface's
|
|
35
|
+
* lighting instead of painting a colour (`Material.decal` `normalMap`). Footprints and dents
|
|
36
|
+
* need only this; a bullet hole gives `map` too and its colour multiplies in. */
|
|
37
|
+
normalMap?: Texture;
|
|
38
|
+
/** Relief strength for `normalMap`. Default 1. Default material only. */
|
|
39
|
+
bump?: number;
|
|
40
|
+
/** Atlas grid of the map: columns, or [columns, rows]. Default 1 (the whole texture). */
|
|
41
|
+
sheet?: number | [number, number];
|
|
42
|
+
/** Slot budget — the most decals alive at once. Default 256. */
|
|
43
|
+
max?: number;
|
|
44
|
+
/** Soft fraction (0..1) of the box's half depth at both ends, so an oblique surface leaves the
|
|
45
|
+
* box gently. Default 0.3. Default material only. */
|
|
46
|
+
edge?: number;
|
|
47
|
+
/** Surfaces turned more than this away from the projection axis fade out — the cosine of the
|
|
48
|
+
* angle (0.3 ≈ 72°) keeps a floor hit off the wall it meets; 0 = project onto anything.
|
|
49
|
+
* Default 0.3. Default material only. */
|
|
50
|
+
angleFade?: number;
|
|
51
|
+
/** HDR boost of the image (0 = none). Default material only. */
|
|
52
|
+
emissive?: number;
|
|
53
|
+
name?: string;
|
|
54
|
+
/** Coarse draw order, 0 (first) … 7 (last); default 4 — see `Mesh.renderPriority`. Decals are
|
|
55
|
+
* blended and sort with the other blended draws of their priority. */
|
|
56
|
+
renderPriority?: number;
|
|
57
|
+
};
|
|
58
|
+
/** `spawn` placement: where the image sits on the surface. */
|
|
59
|
+
export type DecalSpawnOptions = DecalOptions & {
|
|
60
|
+
/** World direction the image's top points along the surface (projected onto it) — a footprint's
|
|
61
|
+
* travel direction. Default: a random spin. */
|
|
62
|
+
up?: Vec3Like;
|
|
63
|
+
/** Extra spin around the normal, radians. Default: random when `up` is not given, else 0. */
|
|
64
|
+
rotation?: number;
|
|
65
|
+
};
|
|
66
|
+
/** `place` / `update` placement: a full frame, like a node looking INTO the surface (its −Z is the
|
|
67
|
+
* projection direction, +Y the image's top). */
|
|
68
|
+
export type DecalPlacement = DecalOptions & {
|
|
69
|
+
position: Vec3Like;
|
|
70
|
+
/** A quaternion, or Euler degrees (YXZ) like `Node.eulerAngles`. Default identity = projecting
|
|
71
|
+
* down −Z. */
|
|
72
|
+
rotation?: QuatLike | Vec3Like;
|
|
73
|
+
};
|
|
74
|
+
export declare class DecalSet extends Node {
|
|
75
|
+
private _material;
|
|
76
|
+
private readonly _max;
|
|
77
|
+
private readonly _cols;
|
|
78
|
+
private readonly _rows;
|
|
79
|
+
private readonly _defaults;
|
|
80
|
+
private readonly _rec;
|
|
81
|
+
private readonly _slots;
|
|
82
|
+
private static _warned;
|
|
83
|
+
constructor(options?: DecalSetOptions);
|
|
84
|
+
get material(): Material;
|
|
85
|
+
/** Decals alive right now. */
|
|
86
|
+
get count(): number;
|
|
87
|
+
/** The slot budget the set was created with. */
|
|
88
|
+
get max(): number;
|
|
89
|
+
/** Coarse draw order, 0 … 7 — see `Mesh.renderPriority`. Write-only. */
|
|
90
|
+
set renderPriority(v: number);
|
|
91
|
+
/** Stamp a decal on a surface: `point` on it, `normal` out of it (a raycast hit, a foot plant
|
|
92
|
+
* with `Vec3.up`). Returns the slot for `update` / `remove` (−1 when the host draws none). */
|
|
93
|
+
spawn(point: Vec3Like, normal: Vec3Like, options?: DecalSpawnOptions): number;
|
|
94
|
+
/** Place a decal by a full frame (an editor-placed stain, a moving marker). Returns the slot. */
|
|
95
|
+
place(placement: DecalPlacement): number;
|
|
96
|
+
/** Move / restyle a placed decal; fields left out keep the values it was placed with. Its birth
|
|
97
|
+
* time (the life clock) is kept. */
|
|
98
|
+
update(slot: number, placement: Partial<DecalPlacement>): this;
|
|
99
|
+
remove(slot: number): this;
|
|
100
|
+
clear(): this;
|
|
101
|
+
private _writePlacement;
|
|
102
|
+
private _write;
|
|
103
|
+
}
|
|
@@ -10,6 +10,11 @@ export declare class Geometry {
|
|
|
10
10
|
* tiles per face, which would fold every face onto the same texels); absent = the host reuses
|
|
11
11
|
* `uv`, which is right for a plane. */
|
|
12
12
|
uv1?: Float32Array;
|
|
13
|
+
/** Per-vertex COLOURS: 4 bytes (r, g, b, a) per vertex, 0..255. A material that declares
|
|
14
|
+
* `requires: [color]` reads them through `getColor()` — one mesh, many colours, no material per
|
|
15
|
+
* shade (a debug drawer, a gradient along a curve). Absent = every vertex white, which is what
|
|
16
|
+
* the built-in materials expect. */
|
|
17
|
+
colors?: Uint8Array;
|
|
13
18
|
constructor(vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array);
|
|
14
19
|
translate(x: number, y: number, z: number): this;
|
|
15
20
|
scale(x: number, y: number, z: number): this;
|
package/dist/types/gl/Light.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export declare class Light extends Node {
|
|
|
53
53
|
private _intensity;
|
|
54
54
|
/** The most recently created sun — what `Lightmap.load` uses unless told otherwise. */
|
|
55
55
|
static lastSun: Light | null;
|
|
56
|
+
_shadowDistance: number;
|
|
56
57
|
/** A directional sun light. */
|
|
57
58
|
static sun(options?: SunOptions): Light;
|
|
58
59
|
/**
|
|
@@ -70,4 +71,10 @@ export declare class Light extends Node {
|
|
|
70
71
|
set intensity(value: number);
|
|
71
72
|
destroy(): void;
|
|
72
73
|
set color(value: ColorInput);
|
|
74
|
+
get color(): ColorInput;
|
|
75
|
+
/** Sun direction as created (the engine keeps it; a settings menu rebuilds a sun from it). */
|
|
76
|
+
get direction(): [number, number, number];
|
|
77
|
+
/** Sun shadow options as created — creation-time in the engine, so a change means a new sun. */
|
|
78
|
+
get shadowsQuality(): number;
|
|
79
|
+
get shadowDistance(): number;
|
|
73
80
|
}
|
|
@@ -7,8 +7,47 @@ export type MaterialColorOptions = {
|
|
|
7
7
|
color?: ColorInput;
|
|
8
8
|
map?: Texture | Canvas | null;
|
|
9
9
|
};
|
|
10
|
+
/** How a stencil test / write on a material compares and what it writes. `test` runs against the
|
|
11
|
+
* scene's stencil buffer (`Scene.stencil` must be on); the ops say what the buffer gets when the
|
|
12
|
+
* fragment passes / fails the stencil test / fails the depth test (`replace` writes `ref`). */
|
|
13
|
+
export type StencilTest = "always" | "never" | "less" | "lessEqual" | "greater" | "greaterEqual" | "equal" | "notEqual";
|
|
14
|
+
export type StencilOp = "keep" | "zero" | "replace" | "increment" | "decrement" | "invert";
|
|
15
|
+
export type MaterialStencil = {
|
|
16
|
+
/** Write the stencil buffer at all. Default `false`. */
|
|
17
|
+
write?: boolean;
|
|
18
|
+
/** The reference value, 0..255. Default 0. */
|
|
19
|
+
ref?: number;
|
|
20
|
+
/** Default `"always"`. */
|
|
21
|
+
test?: StencilTest;
|
|
22
|
+
onPass?: StencilOp;
|
|
23
|
+
onFail?: StencilOp;
|
|
24
|
+
onDepthFail?: StencilOp;
|
|
25
|
+
readMask?: number;
|
|
26
|
+
writeMask?: number;
|
|
27
|
+
};
|
|
28
|
+
/** Render state a material instance can override at run time (Filament keeps the defaults in the
|
|
29
|
+
* shader package; these are per-instance overrides on top). */
|
|
30
|
+
export type MaterialStateOptions = {
|
|
31
|
+
/** Test against the scene's depth buffer. `false` draws over everything already drawn — an
|
|
32
|
+
* editor gizmo, a marker that must never hide behind a wall. Pair it with a high
|
|
33
|
+
* `Mesh.renderPriority` so nothing drawn later covers it. Default `true`. */
|
|
34
|
+
depthTest?: boolean;
|
|
35
|
+
/** Write to the depth buffer. Leave it on for something drawn over the scene whose own parts must
|
|
36
|
+
* still occlude each other (a gizmo's cone in front of its shaft). Unset = the shader's default
|
|
37
|
+
* (on for opaque, off for a blended one). */
|
|
38
|
+
depthWrite?: boolean;
|
|
39
|
+
/** Draw both faces (no back-face culling): a plane seen from behind, a ribbon, cloth, a flat
|
|
40
|
+
* marker. Default `false` = the shader's culling (back faces dropped). */
|
|
41
|
+
doubleSided?: boolean;
|
|
42
|
+
/** A stencil test / write for this material — see `MaterialStencil`. The selection-outline
|
|
43
|
+
* recipe: the object writes `{ write: true, ref: 1, onPass: "replace" }`, and a slightly larger
|
|
44
|
+
* copy of it draws with `{ test: "notEqual", ref: 1 }` + `depthTest: false` in `renderPriority` 7. */
|
|
45
|
+
stencil?: MaterialStencil;
|
|
46
|
+
};
|
|
47
|
+
/** @deprecated the name before doubleSided / stencil joined it — the same type */
|
|
48
|
+
export type MaterialDepthOptions = MaterialStateOptions;
|
|
10
49
|
/** `Material.unlit` options. */
|
|
11
|
-
export type UnlitMaterialOptions = MaterialColorOptions & {
|
|
50
|
+
export type UnlitMaterialOptions = MaterialColorOptions & MaterialStateOptions & {
|
|
12
51
|
/** Alpha-blend this material instead of drawing it opaque. Opaque is the default: a blended draw
|
|
13
52
|
* writes no depth, is sorted back-to-front and casts no shadow, which is rarely what a flat
|
|
14
53
|
* colour wants. Turn it on for anything that must show what is behind it — a glass pane, a
|
|
@@ -16,6 +55,26 @@ export type UnlitMaterialOptions = MaterialColorOptions & {
|
|
|
16
55
|
* (`"#ffffff80"`) mean anything; the opaque material has no alpha channel at all. */
|
|
17
56
|
transparent?: boolean;
|
|
18
57
|
};
|
|
58
|
+
/** `Material.decal` options — the projected-decal material a `DecalSet` draws with. */
|
|
59
|
+
export type DecalMaterialOptions = {
|
|
60
|
+
/** The atlas (a `DecalSet`'s `sheet` cuts it into cells). */
|
|
61
|
+
map?: Texture;
|
|
62
|
+
/** A tangent-space normal atlas (same cell grid; +X = the image's right, +Y = its top; LINEAR —
|
|
63
|
+
* `Texture.fromPixels(…, { srgb: false })`). Turns the decal into a RELIEF decal: instead of
|
|
64
|
+
* painting a colour it bends the surface's lighting, so a footprint or a dent shows on any
|
|
65
|
+
* surface without a colour of its own. With `map` too, the colour multiplies in (a crater
|
|
66
|
+
* darkens by the map's alpha). The sun term applies in shadow as well (no shadow read). */
|
|
67
|
+
normalMap?: Texture;
|
|
68
|
+
/** Relief strength — the normal map's xy scale. Default 1. */
|
|
69
|
+
bump?: number;
|
|
70
|
+
/** Soft fraction (0..1) of the box's half depth at both ends. Default 0.3. */
|
|
71
|
+
edge?: number;
|
|
72
|
+
/** Cosine of the surface angle past which the decal fades (0.3 ≈ 72°); 0 = project onto
|
|
73
|
+
* anything. Default 0.3. */
|
|
74
|
+
angleFade?: number;
|
|
75
|
+
/** HDR boost of the image (0 = none). */
|
|
76
|
+
emissive?: number;
|
|
77
|
+
};
|
|
19
78
|
/** `Material.particles` options — the default point-sprite material for particle systems. */
|
|
20
79
|
export type ParticlesMaterialOptions = {
|
|
21
80
|
/** Sprite texture — a single image or a flipbook sheet of frames. Unset = soft round dot. */
|
|
@@ -54,12 +113,14 @@ export type ParticlesMaterialOptions = {
|
|
|
54
113
|
stretch?: number;
|
|
55
114
|
};
|
|
56
115
|
/** `Material.lit` options — PBR scalars on top of the color/map pair. */
|
|
57
|
-
export type LitMaterialOptions = MaterialColorOptions & {
|
|
116
|
+
export type LitMaterialOptions = MaterialColorOptions & MaterialStateOptions & {
|
|
58
117
|
/** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */
|
|
59
118
|
roughness?: number;
|
|
60
119
|
/** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */
|
|
61
120
|
metallic?: number;
|
|
62
121
|
};
|
|
122
|
+
/** `Material.lightmapShading` tiers — see the setter. */
|
|
123
|
+
export type LightmapShading = "full" | "baked" | "baked-lite";
|
|
63
124
|
export declare class Material {
|
|
64
125
|
readonly shader: FetchResponse | "unknown";
|
|
65
126
|
readonly uniforms: Record<string, UniformValue>;
|
|
@@ -68,6 +129,15 @@ export declare class Material {
|
|
|
68
129
|
/** Set a uniform (chainable). */
|
|
69
130
|
set(key: string, value: UniformValue): this;
|
|
70
131
|
set color(c: ColorInput);
|
|
132
|
+
/** Depth test against the scene (write-only; see `MaterialDepthOptions`). A host that predates
|
|
133
|
+
* the call leaves the material as the shader has it. */
|
|
134
|
+
set depthTest(on: boolean);
|
|
135
|
+
/** Depth write (write-only; see `MaterialStateOptions`). */
|
|
136
|
+
set depthWrite(on: boolean);
|
|
137
|
+
/** Both faces drawn (write-only; see `MaterialStateOptions`). */
|
|
138
|
+
set doubleSided(on: boolean);
|
|
139
|
+
/** The stencil test / write (write-only; `null` = back to none). See `MaterialStencil`. */
|
|
140
|
+
set stencil(s: MaterialStencil | null);
|
|
71
141
|
set map(value: Texture | Canvas | null);
|
|
72
142
|
/** PBR lit material. */
|
|
73
143
|
static lit(options?: LitMaterialOptions): Material;
|
|
@@ -77,6 +147,10 @@ export declare class Material {
|
|
|
77
147
|
* driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look
|
|
78
148
|
* knob is primed here; JS writes after construction override them. */
|
|
79
149
|
static particles(options?: ParticlesMaterialOptions): Material;
|
|
150
|
+
/** Projected-decal material (`DecalSet`): samples the atlas where the decal's box meets the opaque
|
|
151
|
+
* scene behind it. Blended, no depth write, no shadows — the engine keeps the scene depth bound
|
|
152
|
+
* while a set with live decals is on screen. */
|
|
153
|
+
static decal(options?: DecalMaterialOptions): Material;
|
|
80
154
|
/** Material that samples a VideoPlayer's texture. */
|
|
81
155
|
static video(map?: Texture): Material;
|
|
82
156
|
/** The lightmap material (docs/lightmap-plan.md): PBR base colour × a baked shadow/AO atlas on UV1.
|
|
@@ -92,6 +166,16 @@ export declare class Material {
|
|
|
92
166
|
* unset layer is white and an unbaked terrain is fully lit. */
|
|
93
167
|
static terrain(): Material;
|
|
94
168
|
private static _lmTemplate;
|
|
169
|
+
static _lightmapShading: LightmapShading;
|
|
170
|
+
/** Which shader lightmapped models take — a graphics-quality tier, engine-wide. `"full"` is filament's
|
|
171
|
+
* lit path over the baked atlas (IBL specular, real-time point lights such as a muzzle flash, sun
|
|
172
|
+
* shadows on dynamic objects). `"baked"` keeps the baked light and an approximated ambient but drops
|
|
173
|
+
* the lit path: ~40 % cheaper per pixel on a fill-bound GPU. `"baked-lite"` is that minus the normal,
|
|
174
|
+
* metallic/roughness and occlusion map reads (the factors stand in, the atlas keeps the baked AO;
|
|
175
|
+
* emissive still glows): +20 % more at 1080p on the same GPU. Read when a lightmapped model LOADS, so set
|
|
176
|
+
* it before the level (a settings menu applies it on the next level load), like `Texture.maxSize`. */
|
|
177
|
+
static get lightmapShading(): LightmapShading;
|
|
178
|
+
static set lightmapShading(mode: LightmapShading);
|
|
95
179
|
/** Shadow-catcher material (transparent except where shadows fall). */
|
|
96
180
|
static shadow(color?: ColorInput): Material;
|
|
97
181
|
/** Load a custom compiled shader (.mat URL) as a material. */
|
package/dist/types/gl/Mesh.d.ts
CHANGED
|
@@ -11,15 +11,26 @@ export type MeshOptions = {
|
|
|
11
11
|
name?: string;
|
|
12
12
|
castShadows?: boolean;
|
|
13
13
|
receiveShadows?: boolean;
|
|
14
|
+
/** Coarse draw order, 0 (first) … 7 (last); default 4. See `Mesh.renderPriority`. */
|
|
15
|
+
renderPriority?: number;
|
|
14
16
|
};
|
|
15
17
|
export declare class Mesh extends Node {
|
|
16
18
|
private _geometry?;
|
|
17
19
|
constructor(geometry?: Geometry, material?: Material);
|
|
18
20
|
get geometry(): Geometry | undefined;
|
|
21
|
+
/** Replace the geometry in place — the node, its transform and its material stay, the vertex and
|
|
22
|
+
* index buffers are rebuilt. What an editor overlay or a debug drawer redraws with. */
|
|
23
|
+
setGeometry(geometry: Geometry): this;
|
|
19
24
|
/** A Mesh always carries a material (slot 0) — see Node.setMaterial for the slot API. */
|
|
20
25
|
get material(): Material;
|
|
21
26
|
set material(m: Material);
|
|
22
27
|
set culling(v: boolean);
|
|
28
|
+
/** Coarse draw order within the frame: 0 draws first, 7 last, 4 is the default (Filament's
|
|
29
|
+
* renderable priority; within one priority opaque draws sort front-to-back, blended back-to-front).
|
|
30
|
+
* Something drawn over the scene with `Material.depthTest = false` goes in 7, so nothing drawn
|
|
31
|
+
* after it can cover it. Write-only; a host that predates the call ignores it. */
|
|
32
|
+
set renderPriority(v: number);
|
|
33
|
+
private static _warnedPriority;
|
|
23
34
|
set castShadows(v: boolean);
|
|
24
35
|
set receiveShadows(v: boolean);
|
|
25
36
|
static box(options?: MeshOptions & {
|
package/dist/types/gl/Scene.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Presentable, type PresentOptions } from "../ui/presentable";
|
|
|
4
4
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch";
|
|
5
5
|
import type { FetchResponse } from "../runtime/fetch";
|
|
6
6
|
import { Camera } from "./Camera";
|
|
7
|
+
import { SceneAudio } from "./SceneAudio";
|
|
7
8
|
import { type ControlsHandle, type ControlsOptions } from "./controls";
|
|
8
9
|
import { Material } from "./Material";
|
|
9
10
|
import { Node } from "./Node";
|
|
@@ -95,6 +96,9 @@ export type SceneOptions = {
|
|
|
95
96
|
* takes over). Unset keeps the host default (desktop 4×, mobile/web off). The biggest single
|
|
96
97
|
* fill-rate cost after resolution — turn it down on big screens before anything else. */
|
|
97
98
|
antialias?: boolean | 2 | 4;
|
|
99
|
+
/** Keep a stencil buffer for this scene (off by default: it costs memory and a clear per frame).
|
|
100
|
+
* Needed before any material's `stencil` test or write does anything. */
|
|
101
|
+
stencil?: boolean;
|
|
98
102
|
/** Render the 3D at this fraction of the viewport (0.25–1) and upscale; the UI stays at native
|
|
99
103
|
* resolution. A fixed, predictable cut of per-pixel GPU work — `0.75` is ~45 % cheaper and
|
|
100
104
|
* barely visible in motion, `0.5` quarters it. Headless renders ignore it. */
|
|
@@ -118,6 +122,10 @@ export type SceneOptions = {
|
|
|
118
122
|
* scene file — `env` is applied before the nodes build) and leaves already-loaded ones alone.
|
|
119
123
|
* On the desktop host `CREATOR_TEXTURE_ANISOTROPY` overrides it, for tuning without a rebuild. */
|
|
120
124
|
anisotropy?: number;
|
|
125
|
+
/** Engine-wide cap on texture size, 0 / unset = none (see `Texture.maxSize`): a KTX2 above it
|
|
126
|
+
* loses its top mip levels on load, a glTF image is downsampled. Applied before this scene's
|
|
127
|
+
* assets load; like `anisotropy` it does not touch textures already loaded. */
|
|
128
|
+
maxTextureSize?: number;
|
|
121
129
|
/** The look on an HDR display (a screen with headroom above SDR white — Apple XDR panels, the
|
|
122
130
|
* macOS host today); ignored on SDR. `strength` 0..1 is how much of the picture reaches for the
|
|
123
131
|
* display's headroom (0 only what SDR clipped, 1 nearly everything; default 0.35). `paperWhite`
|
|
@@ -132,6 +140,8 @@ export type SceneOptions = {
|
|
|
132
140
|
};
|
|
133
141
|
export declare class Scene implements Presentable {
|
|
134
142
|
readonly camera: Camera;
|
|
143
|
+
/** The listener + global 3D audio knobs (docs/audio-plan.md). */
|
|
144
|
+
readonly audio: SceneAudio;
|
|
135
145
|
readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node | null>) => void>;
|
|
136
146
|
private _material?;
|
|
137
147
|
private static _active;
|
|
@@ -153,6 +163,19 @@ export declare class Scene implements Presentable {
|
|
|
153
163
|
setFog(options: FogOptions | false): void;
|
|
154
164
|
setMaterialGlobalParameter(i: number, x: number, y: number, z: number, w: number): void;
|
|
155
165
|
setAntialias(enabled: boolean, scale?: number): void;
|
|
166
|
+
/** Depth-reading effects on / off (a graphics-settings menu): soft particles and projected decals
|
|
167
|
+
* read the scene depth, which costs a depth pre-pass of every opaque draw (~12 % of a fill-bound
|
|
168
|
+
* frame). Off = hard-edged particles, no decals, no pre-pass. Engine-wide, live. */
|
|
169
|
+
setDepthEffects(enabled: boolean): void;
|
|
170
|
+
/** LOD distance (a graphics-settings menu): the engine's LOD thresholds × `bias`. 2 = every level
|
|
171
|
+
* switches at half the distance (a model must look twice as big on screen to keep its detail),
|
|
172
|
+
* 0.5 = full detail twice as far, 1 = the defaults. Engine-wide, live. Only GLBs that carry
|
|
173
|
+
* `_LOD<n>` meshes (`lecodes assets doctor --lod`) have levels to switch. */
|
|
174
|
+
setLodBias(bias: number): void;
|
|
175
|
+
/** Runtime form of `bloom` / `bloomIntensity` (a graphics-settings menu). */
|
|
176
|
+
setBloom(enabled: boolean, intensity?: number): void;
|
|
177
|
+
/** The scene's stencil buffer on / off (see `SceneOptions.stencil`). */
|
|
178
|
+
setStencil(enabled: boolean): void;
|
|
156
179
|
add(...nodes: Node[]): this;
|
|
157
180
|
remove(...nodes: Node[]): this;
|
|
158
181
|
/** Attach (and configure) a system, or reconfigure it if already present. Returns the scene typed
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Node } from "./Node";
|
|
2
|
+
export declare class SceneAudio {
|
|
3
|
+
private _listener;
|
|
4
|
+
private _doppler;
|
|
5
|
+
/** The node the engine listens from; null (default) = the active camera. */
|
|
6
|
+
get listener(): Node | null;
|
|
7
|
+
set listener(node: Node | null);
|
|
8
|
+
/** Multiplies every source's doppler amount (0 = off everywhere). Default 1. */
|
|
9
|
+
get dopplerFactor(): number;
|
|
10
|
+
set dopplerFactor(v: number);
|
|
11
|
+
}
|