lecodes-sdk 1.0.0 → 1.2.0
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 +18 -4
- package/dist/inject.js +260 -361
- package/dist/types/animate/tween/Animation.d.ts +69 -0
- package/dist/types/animate/tween/Timeline.d.ts +55 -0
- package/dist/types/animate/tween/animateValue.d.ts +27 -0
- package/dist/types/animate/tween/easing.d.ts +29 -0
- package/dist/types/animate/tween/spec.d.ts +178 -0
- package/dist/types/g2/Node2D.d.ts +16 -0
- package/dist/types/g2/Sprite.d.ts +11 -1
- package/dist/types/gl/Camera.d.ts +15 -1
- package/dist/types/gl/Foliage.d.ts +47 -0
- package/dist/types/gl/Geometry.d.ts +24 -0
- package/dist/types/gl/Light.d.ts +28 -7
- package/dist/types/gl/Lightmap.d.ts +90 -60
- package/dist/types/gl/Material.d.ts +28 -20
- package/dist/types/gl/Model.d.ts +7 -5
- package/dist/types/gl/Node.d.ts +18 -0
- package/dist/types/gl/Particles.d.ts +55 -1
- package/dist/types/gl/Scene.d.ts +20 -0
- package/dist/types/gl/animation/AnimationClip.d.ts +19 -0
- package/dist/types/gl/animation/Animator.d.ts +27 -0
- package/dist/types/gl/animation/DynamicBone.d.ts +19 -8
- package/dist/types/gl/animation/IK.d.ts +86 -30
- package/dist/types/gl/animation/Locomotion.d.ts +52 -3
- package/dist/types/gl/animation/Warp.d.ts +2 -1
- package/dist/types/gl/animation/core.d.ts +35 -4
- package/dist/types/gl/physics/Ragdoll.d.ts +87 -12
- package/dist/types/gl/terrain/Terrain.d.ts +12 -2
- package/dist/types/inject.d.ts +8 -2
- package/dist/types/runtime/input.d.ts +7 -0
- package/dist/types/scene/defineScene.d.ts +44 -32
- package/dist/types/ui/UIButton.d.ts +3 -1
- package/dist/types/ui/UIInput.d.ts +5 -1
- package/dist/types/ui/UINode.d.ts +24 -24
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/prompts/README.md +142 -142
- package/prompts/core-design.md +27 -4
- package/prompts/core.md +35 -6
- package/prompts/dist/2d-game.md +197 -408
- package/prompts/dist/3d-app.md +166 -491
- package/prompts/dist/ar-app.md +163 -373
- package/prompts/dist/design.md +87 -83
- package/prompts/dist/ui-app.md +136 -325
- package/prompts/select.ts +19 -4
- package/src/animate/tween/Animation.ts +378 -0
- package/src/animate/tween/Timeline.ts +175 -0
- package/src/animate/tween/animateValue.ts +100 -0
- package/src/animate/tween/easing.ts +172 -0
- package/src/animate/tween/spec.ts +479 -0
- package/src/audio/audio.ts +161 -161
- package/src/bridges.d.ts +235 -65
- package/src/compile/__tests__/assetMacro.test.ts +26 -0
- package/src/compile/__tests__/detectEntry.test.ts +19 -0
- package/src/compile/__tests__/serverSplit.test.ts +27 -0
- package/src/compile/bundler.ts +34 -4
- package/src/compile/compileProject.ts +31 -1
- package/src/compile/detectEntry.ts +8 -3
- package/src/compile/index.ts +2 -0
- package/src/compile/serverSplit.ts +9 -3
- package/src/g2/Node2D.ts +38 -0
- package/src/g2/Sprite.ts +20 -1
- package/src/gl/Camera.ts +34 -1
- package/src/gl/CameraPlace.ts +52 -52
- package/src/gl/Foliage.ts +102 -0
- package/src/gl/Geometry.ts +393 -348
- package/src/gl/Light.ts +49 -16
- package/src/gl/Lightmap.ts +439 -275
- package/src/gl/Material.ts +59 -47
- package/src/gl/Mesh.ts +120 -120
- package/src/gl/Model.ts +23 -12
- package/src/gl/Node.ts +39 -0
- package/src/gl/Particles.ts +80 -2
- package/src/gl/Scene.ts +34 -1
- package/src/gl/animation/AnimationClip.ts +52 -0
- package/src/gl/animation/Animator.ts +42 -2
- package/src/gl/animation/DynamicBone.ts +35 -12
- package/src/gl/animation/IK.ts +173 -152
- package/src/gl/animation/Locomotion.ts +72 -8
- package/src/gl/animation/Playback.ts +5 -4
- package/src/gl/animation/Warp.ts +5 -2
- package/src/gl/animation/core.ts +65 -4
- package/src/gl/physics/Ragdoll.ts +451 -272
- package/src/gl/scenarios.ts +291 -291
- package/src/gl/terrain/Terrain.ts +33 -2
- package/src/inject.ts +236 -226
- package/src/runtime/input.ts +11 -0
- package/src/scene/defineScene.ts +72 -62
- package/src/scene/gizmos.ts +148 -148
- package/src/ui/UIButton.ts +2 -2
- package/src/ui/UIInput.ts +3 -3
- package/src/ui/UINode.ts +61 -36
- package/dist/types/animate/animate.d.ts +0 -20
- package/src/animate/animate.ts +0 -238
|
@@ -1,94 +1,124 @@
|
|
|
1
1
|
import { Node } from "./Node";
|
|
2
2
|
import type { Scene } from "./Scene";
|
|
3
3
|
export type LightmapLoadOptions = {
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* (irradiance per axis face, blended by the pixel's normal), so a mover's top takes a lamp above it
|
|
27
|
-
* and its underside does not — the same shading the atlas gives the statics. Before that the volume
|
|
28
|
-
* was one flat 0.5·E on every face and this knob was the workaround. Kept as a trim. */
|
|
29
|
-
volumeBoost?: number;
|
|
30
|
-
/** What an OCCLUDER-only static (a prop without lightmap UVs — traced into the receivers' atlas but
|
|
31
|
-
* carrying no rect of its own) does in real time. `"baked"` (default): its shadow is in the bake, so
|
|
32
|
-
* it stops casting and the shadow pass draws only the movers — on a level of thousands of foliage
|
|
33
|
-
* cards that is a third of the GPU frame. `"realtime"`: it keeps casting, which is the only way its
|
|
34
|
-
* shadow reaches OTHER non-receiver props (a rock under a tree); the honest fix for that is lightmap
|
|
35
|
-
* UVs on the props (`lecodes assets doctor --lightmap-uv`), which makes them receivers. */
|
|
36
|
-
occluderShadows?: "baked" | "realtime";
|
|
4
|
+
/** A DEBUG multiplier on the atlas' lux (default 1): the atlas is physical, so this is a knob for looking,
|
|
5
|
+
* not a look. */
|
|
6
|
+
lightScale?: number;
|
|
7
|
+
/** The level's own radiance of emission 1.0 for the BAKE (cd / m², `BakeConfig.emissiveNits`): an imported pack's
|
|
8
|
+
* emissive values are tuned for a look, not for light - this is where the level says how much its panels really give.
|
|
9
|
+
* The CLI's `--emissive-nits` wins over it; without either the camera's exposure decides. */
|
|
10
|
+
emissiveNits?: number;
|
|
11
|
+
/** `false` = the emissive surfaces light NOTHING in the bake (the level is lit by its lamps, the panels are decoration)
|
|
12
|
+
* while `emissiveNits` still says how bright their glow is drawn. Default true. */
|
|
13
|
+
emissiveBake?: boolean;
|
|
14
|
+
/** FOR THE BAKE: materials that let light THROUGH them, by their glTF name (`"name*"` = every name with that start):
|
|
15
|
+
* the share of a shadow ray that passes, tinted by the material's base colour x map - an awning's warm, patterned light
|
|
16
|
+
* on the sand. The surface itself stays opaque: baked, drawn as before, a real-time shadow caster.
|
|
17
|
+
* A number = the share that goes STRAIGHT through (the gaps of a weave: it draws the map's picture on the ground);
|
|
18
|
+
* `{ through, diffuse }` adds the share the fibres SCATTER - the cloth's underside glows like a matte panel and lights
|
|
19
|
+
* what is under it by the solid angle it fills, with no picture. Dense canvas: `{ through: 0.08, diffuse: 0.25 }`. */
|
|
20
|
+
transmit?: Record<string, LightmapTransmit>;
|
|
21
|
+
};
|
|
22
|
+
/** one `transmit` entry (LightmapLoadOptions.transmit): the straight share, or both shares */
|
|
23
|
+
export type LightmapTransmit = number | {
|
|
24
|
+
through?: number;
|
|
25
|
+
diffuse?: number;
|
|
37
26
|
};
|
|
38
27
|
export type LightmapInfo = {
|
|
39
28
|
size: number;
|
|
40
29
|
texel: number;
|
|
41
|
-
/** Atlas pages the bake took (`
|
|
30
|
+
/** Atlas pages the bake took (`light` / `aux` list them in order). */
|
|
42
31
|
pages: number;
|
|
43
|
-
/** The light volume, when one was loaded: grid dims + cell size in metres. */
|
|
44
|
-
volume?: {
|
|
45
|
-
dims: number[];
|
|
46
|
-
cell: number;
|
|
47
|
-
};
|
|
48
|
-
/** Point lights the bake carries and this load switched off (statics read them from the atlas,
|
|
49
|
-
* movers from the volume); 0 without a `light` atlas. */
|
|
50
|
-
lights: number;
|
|
51
32
|
/** keys applied / keys in the file / registered statics without a rect */
|
|
52
33
|
applied: number;
|
|
53
34
|
total: number;
|
|
54
35
|
missing: string[];
|
|
55
|
-
/** Occluder-only statics whose real-time shadow was switched off (`occluderShadows: "baked"`). */
|
|
56
|
-
occluders: number;
|
|
57
36
|
};
|
|
58
37
|
export type LightmapFiles = {
|
|
59
38
|
data: string;
|
|
60
|
-
/** The atlas — one page, or every page in order for a bake that took several. */
|
|
61
|
-
|
|
62
|
-
/** The
|
|
63
|
-
|
|
39
|
+
/** The irradiance atlas — one page, or every page in order for a bake that took several. */
|
|
40
|
+
light: string | string[];
|
|
41
|
+
/** The aux atlas (sun / sky visibility + light direction), pages like `light`. */
|
|
42
|
+
aux: string | string[];
|
|
43
|
+
/** DEBUG: the direct-light-only pages a `--split` bake wrote (`<stem>-direct[_n].ktx2`), for the "direct" view. */
|
|
44
|
+
direct?: string | string[];
|
|
45
|
+
/** DEBUG: the bounce-only pages of a `--split` bake (`<stem>-indirect[_n].ktx2`), for the "indirect" view. */
|
|
46
|
+
indirect?: string | string[];
|
|
47
|
+
/** The reflection probes (`<stem>-probes.ktx2`), when the bake placed some (`lecodes lightmap bake --probe-spacing`). */
|
|
48
|
+
probes?: string;
|
|
49
|
+
/** THE LIGHT GRID for movers (`<stem>.lgrid`, `lecodes lightmap bake --volume`): the baked ambient light of every
|
|
50
|
+
* place a mover can be. Absent = movers keep the scene's IBL. */
|
|
64
51
|
volume?: string;
|
|
65
52
|
};
|
|
53
|
+
/** The lightmap material's data views (`Lightmap.debug`); "direct" / "indirect" bind a `--split` bake's pages instead. */
|
|
54
|
+
export type LightmapDebugMode = "off" | "irradiance" | "albedo" | "normal" | "shadingNormal" | "share" | "skyVis" | "atlas" | "direction" | "lux" | "relief" | "direct" | "indirect" | "probe" | "probeMap" | "skyPath" | "probePath";
|
|
55
|
+
export type LightmapDebugParams = {
|
|
56
|
+
/** `lux`: the false-colour ramp's log10 range (default 0..5, i.e. 1 lux .. 100 000). */
|
|
57
|
+
luxRange?: [number, number];
|
|
58
|
+
};
|
|
59
|
+
/** What `Lightmap.probe` answers: the baked texel under a screen point. */
|
|
60
|
+
export type LightmapProbe = {
|
|
61
|
+
key: string;
|
|
62
|
+
entity: number;
|
|
63
|
+
node: string;
|
|
64
|
+
material: string;
|
|
65
|
+
page: number;
|
|
66
|
+
/** The texel's column / row on its page. */
|
|
67
|
+
texel: [number, number];
|
|
68
|
+
uv1: [number, number];
|
|
69
|
+
world: [number, number, number];
|
|
70
|
+
distance: number;
|
|
71
|
+
};
|
|
66
72
|
export declare class Lightmap {
|
|
67
73
|
/** True while `lecodes lightmap bake` runs the app — skip menus and build the scene straight away. */
|
|
68
74
|
static get baking(): boolean;
|
|
69
75
|
private static entries;
|
|
70
|
-
private static dynamics;
|
|
71
76
|
private static ordinals;
|
|
72
77
|
private static warned;
|
|
73
|
-
|
|
78
|
+
/** The bake bound last (`load`): what `probe` reads rects from. */
|
|
79
|
+
private static bound;
|
|
74
80
|
/** Register static geometry — a Model, a Mesh, or any node whose subtree holds them. Statics are
|
|
75
|
-
* both receivers and occluders in the bake. `key` names the entry in
|
|
81
|
+
* both receivers and occluders in the bake. `key` names the entry in the .bake (default:
|
|
76
82
|
* the node's name + a running number, `container#3`); pass one when names are not stable. */
|
|
77
83
|
static add(node: Node, key?: string): Node;
|
|
78
84
|
private static next;
|
|
79
|
-
|
|
85
|
+
private static movers;
|
|
86
|
+
private static volumeOn;
|
|
87
|
+
/** A MOVER takes its ambient light from the level's baked LIGHT GRID (`env.lightmap.volume`) at the place it is at,
|
|
88
|
+
* every frame — whatever its shader: the standard glTF one or a custom lit material. Every Model / Mesh under `node`
|
|
89
|
+
* is marked (a character, a weapon with its parts). A scene file does this itself for every node a Physics aspect or
|
|
90
|
+
* a CharacterController moves; call it for what CODE spawns — an enemy, a pickup, a projectile. `on = false` hands
|
|
91
|
+
* the subtree back to the scene's IBL. Safe before the level's bake has loaded. */
|
|
92
|
+
static track(node: Node, on?: boolean): void;
|
|
93
|
+
private static loadVolume;
|
|
94
|
+
/** Forget every registration (a scene rebuild). */
|
|
80
95
|
static clear(): void;
|
|
81
96
|
/** Apply a bake — or, under `lecodes lightmap bake`, run it. Resolves to null when nothing was
|
|
82
97
|
* applied (no bake yet, a host without the feature, bake mode). */
|
|
98
|
+
private static scene;
|
|
83
99
|
static load(scene: Scene, files: LightmapFiles, options?: LightmapLoadOptions): Promise<LightmapInfo | null>;
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
100
|
+
/** The bake's `<key>#k` instances by their base key: the parts of a GLB unwrapped in groups (k = extras.lightmapGroup). */
|
|
101
|
+
private static groupsOf;
|
|
102
|
+
/** Switch every lightmapped surface to a DATA view (or back with `"off"` / 0). Level-wide, instant —
|
|
103
|
+
* except "direct" / "indirect", which load that page set the first time (a `--split` bake listed in the scene). */
|
|
104
|
+
static debug(mode: LightmapDebugMode | number, params?: LightmapDebugParams): void;
|
|
105
|
+
/** Bind another page set of the bound bake to every surface (the "direct" / "indirect" views). */
|
|
106
|
+
private static show;
|
|
107
|
+
private static balls;
|
|
108
|
+
/** DEBUG: a mirror ball at every reflection probe of the bound bake (`on`), or none (`off`) — a ball reflects the
|
|
109
|
+
* probes around its point unoccluded (at a probe's own position that is the probe itself), so a probe inside a
|
|
110
|
+
* wall, a black one or a leak across a wall shows at a glance. Metallic, roughness 0; view "probe" shows the
|
|
111
|
+
* probes alone. */
|
|
112
|
+
static debugProbes(on: boolean, radius?: number): number;
|
|
113
|
+
/** The view names in `lightmapDebug`'s order — for a knob that cycles them. */
|
|
114
|
+
static get debugModes(): readonly LightmapDebugMode[];
|
|
115
|
+
/** The baked texel under a screen point (logical px): its instance key, page and texel column / row,
|
|
116
|
+
* so the value can be looked up in the bake's debug layers (`lecodes lightmap inspect`). null when
|
|
117
|
+
* nothing baked is under the point or the host has no triangle pick. */
|
|
118
|
+
static probe(screenX: number, screenY: number): LightmapProbe | null;
|
|
119
|
+
/** A hex colour as the 9-char form the float4 uniform path expects ("#rrggbbaa"). */
|
|
120
|
+
private static hex8;
|
|
121
|
+
/** The lightmap material for a static Mesh, from whatever lit material it carried (colour, map, roughness, metallic). */
|
|
91
122
|
private static meshMaterial;
|
|
92
|
-
private static swapMeshMaterial;
|
|
93
123
|
private static bake;
|
|
94
124
|
}
|
|
@@ -119,8 +119,6 @@ export type LitMaterialOptions = MaterialColorOptions & MaterialStateOptions & {
|
|
|
119
119
|
/** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */
|
|
120
120
|
metallic?: number;
|
|
121
121
|
};
|
|
122
|
-
/** `Material.lightmapShading` tiers — see the setter. */
|
|
123
|
-
export type LightmapShading = "full" | "baked" | "baked-lite";
|
|
124
122
|
export declare class Material {
|
|
125
123
|
readonly shader: FetchResponse | "unknown";
|
|
126
124
|
readonly uniforms: Record<string, UniformValue>;
|
|
@@ -153,33 +151,43 @@ export declare class Material {
|
|
|
153
151
|
static decal(options?: DecalMaterialOptions): Material;
|
|
154
152
|
/** Material that samples a VideoPlayer's texture. */
|
|
155
153
|
static video(map?: Texture): Material;
|
|
156
|
-
/** The lightmap material (
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* `
|
|
160
|
-
*
|
|
154
|
+
/** The lightmap material (packages/creator-bake): a lit PBR material whose whole DIFFUSE light is the
|
|
155
|
+
* baked irradiance atlas on UV1 (`lightmapLight`, lux) — the real-time sun, lamps and diffuse IBL do not
|
|
156
|
+
* touch it; the specular IBL stays, occluded by the baked sky visibility. Models take it through
|
|
157
|
+
* `Model.load(…, { lightmap: true })`; a static Mesh gets one from here. Parameters use gltfio's names
|
|
158
|
+
* (`baseColorFactor`, `baseColorMap`, `roughnessFactor`, `metallicFactor`) plus `lightmapLight`, `lightmapAux`,
|
|
159
|
+
* `lightmapST`, `lightScale` (the level-wide value `Lightmap.load` sets) and the debug view knobs. */
|
|
161
160
|
static lightmap(): Material;
|
|
162
161
|
/** `Material.lightmap()`'s masked twin (`blending: masked`, same shader and parameters): what the engine
|
|
163
162
|
* gives a lightmapped model's alpha-MASK materials. The cutoff comes from the glTF material. */
|
|
164
163
|
static lightmapMasked(): Material;
|
|
165
164
|
/** The terrain splat material (docs/terrain-plan.md §1.5): four albedo (+ normal-map) layers blended by
|
|
166
165
|
* a control map on the terrain's own grid, per-layer `tiling` (metres per repeat) / `roughness` /
|
|
167
|
-
* `normalScale` / `triplanar
|
|
168
|
-
*
|
|
169
|
-
* unset layer is white and an unbaked terrain is fully lit. */
|
|
166
|
+
* `normalScale` / `triplanar`. `Terrain` builds and owns one per terrain; the uniforms are primed here so an
|
|
167
|
+
* unset layer is white. Lit real-time; a BAKED terrain takes `Material.terrainLightmap()`. */
|
|
170
168
|
static terrain(): Material;
|
|
169
|
+
/** `Material.terrain()` for a BAKED terrain (terrain-lightmap.mat): the same layers and uniforms, shaded like
|
|
170
|
+
* `Material.lightmap()` — the whole diffuse light is the baked atlas on the terrain's UV1 (one rect), which
|
|
171
|
+
* `Lightmap.load` binds. A scene file's `terrain:` node that is a lightmap static is built with it; without a
|
|
172
|
+
* bound bake it draws black, like any lightmapped static. No reflection probes (the sampler budget): it reflects the
|
|
173
|
+
* sky through the baked sky visibility. */
|
|
174
|
+
static terrainLightmap(): Material;
|
|
171
175
|
private static _lmTemplate;
|
|
172
176
|
private static _lmMaskedTemplate;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
static
|
|
177
|
+
/** The FOLIAGE tier (`Model.load(…, { foliage: true })`, see `Foliage`): an unlit shader with its own cheap
|
|
178
|
+
* lighting plus a vertex shader that sways in the wind, bends away from benders and thins out with distance,
|
|
179
|
+
* and a per-copy tint. glTF parameters like `Material.lightmap()` plus `wind` / `sway` / `fade` / `benders`,
|
|
180
|
+
* which the engine writes itself. Not baked by the rewritten bake yet. */
|
|
181
|
+
static foliage(): Material;
|
|
182
|
+
/** `Material.foliage()`'s masked twin (`blending: masked`): what the engine gives a foliage model's alpha-MASK
|
|
183
|
+
* materials — the cards. */
|
|
184
|
+
static foliageMasked(): Material;
|
|
185
|
+
/** the glTF-side identity values every provider-handed material starts from */
|
|
186
|
+
private static _glbDefaults;
|
|
187
|
+
private static _lightmapDefaults;
|
|
188
|
+
private static _folTemplate;
|
|
189
|
+
static _foliageMaskedTemplate(): Material;
|
|
190
|
+
private static _folMaskedTemplate;
|
|
183
191
|
/** Shadow-catcher material (transparent except where shadows fall). */
|
|
184
192
|
static shadow(color?: ColorInput): Material;
|
|
185
193
|
/** Load a custom compiled shader (.mat URL) as a material. */
|
package/dist/types/gl/Model.d.ts
CHANGED
|
@@ -77,11 +77,13 @@ export declare class Model extends Node {
|
|
|
77
77
|
loaded: number;
|
|
78
78
|
total?: number;
|
|
79
79
|
}) => void;
|
|
80
|
-
/** Baked lighting (
|
|
80
|
+
/** Baked lighting (packages/creator-bake). `true` = a STATIC: loads through the lightmap material so
|
|
81
81
|
* `Lightmap.load` can bind its atlas rect (the GLB needs TEXCOORD_1 — `lecodes assets doctor
|
|
82
|
-
* --lightmap-uv`)
|
|
83
|
-
*
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
* --lightmap-uv`) and takes nothing from the real-time lights once the bake applies. Omitted / `false` =
|
|
83
|
+
* the standard shader, lit real-time (movers). Hosts without lightmap support ignore it. */
|
|
84
|
+
lightmap?: boolean;
|
|
85
|
+
/** Vegetation: load through the FOLIAGE tier (see `Foliage`) — wind, touch bending, distance fade,
|
|
86
|
+
* per-copy tint. Hosts without the tier fall back to the standard shader. */
|
|
87
|
+
foliage?: boolean;
|
|
86
88
|
}): Promise<Model>;
|
|
87
89
|
}
|
package/dist/types/gl/Node.d.ts
CHANGED
|
@@ -7,6 +7,17 @@ import type { Geometry } from "./Geometry";
|
|
|
7
7
|
import { Material } from "./Material";
|
|
8
8
|
import type { CompAxis, CompWriter } from "../core/compWrite";
|
|
9
9
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch";
|
|
10
|
+
import type { Animation } from "../animate/tween/Animation";
|
|
11
|
+
import { type TweenMeta } from "../animate/tween/spec";
|
|
12
|
+
/** Animatable transform props of a 3D node: a value tweens from the current one, an ARRAY OF
|
|
13
|
+
* VALUES is a keyframe list (`position: [[0,0,0], [0,2,0]]`). */
|
|
14
|
+
export type NodeTweenProps = {
|
|
15
|
+
position?: Vec3Like | Vec3Like[];
|
|
16
|
+
scale?: number | Vec3Like | (number | Vec3Like)[];
|
|
17
|
+
quaternion?: QuatLike | QuatLike[];
|
|
18
|
+
/** Degrees, YXZ; interpolated per axis without shortest-arc, so `[0, 720, 0]` spins twice. */
|
|
19
|
+
eulerAngles?: Vec3Like | Vec3Like[];
|
|
20
|
+
};
|
|
10
21
|
/** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */
|
|
11
22
|
export declare const nodeRegistry: Registry<Node>;
|
|
12
23
|
export type NodeEvents = {
|
|
@@ -59,6 +70,13 @@ export declare class Node extends AspectHost<NodeEvents> implements CompWriter {
|
|
|
59
70
|
set scale(v: Vec3Like | number);
|
|
60
71
|
get quaternion(): Quat;
|
|
61
72
|
set quaternion(v: QuatLike);
|
|
73
|
+
/** Tween the transform to the given values — `node.animateTo({ position: [0, 2, 0], duration: 800,
|
|
74
|
+
* easing: 'inOutCubic' })`; arrays of values are keyframes. Runs on the game clock (pauses with
|
|
75
|
+
* the game) unless `clock: 'ui'`. Returns the {@link Animation} handle. Phase 1: plain nodes —
|
|
76
|
+
* a physics-owned node (a body / character) is not routed through its engine object yet. */
|
|
77
|
+
animateTo(props: NodeTweenProps & TweenMeta): Animation;
|
|
78
|
+
/** Tween FROM the given values to the node's current transform (an entrance). */
|
|
79
|
+
animateFrom(props: NodeTweenProps & TweenMeta): Animation;
|
|
62
80
|
get eulerAngles(): Vec3;
|
|
63
81
|
set eulerAngles(v: Vec3Like);
|
|
64
82
|
get forward(): Vec3;
|
|
@@ -170,11 +170,29 @@ export type ParticlesOptions = ParticlesMaterialOptions & {
|
|
|
170
170
|
* spread evenly along the path — trail density independent of speed, no per-frame clumps.
|
|
171
171
|
* Meant for `space: 'world'`. */
|
|
172
172
|
rateOverDistance?: number;
|
|
173
|
+
/** Spread those spawn points along a CURVE through the emitter's recent path instead of the
|
|
174
|
+
* straight line between where it was last frame and where it is now. A straight line cuts the
|
|
175
|
+
* corner by however far the path bows inside one frame, which grows with the frame TIME — so a
|
|
176
|
+
* fast curving emitter looks faceted, and looks worse the slower the machine. Default false
|
|
177
|
+
* (the straight line); costs three stored positions and one curve evaluation per spawn.
|
|
178
|
+
*
|
|
179
|
+
* The curve needs a point one frame AHEAD, so each frame's spawns are placed provisionally and
|
|
180
|
+
* nudged into place on the next frame, once it exists. Nothing else observes them in between. */
|
|
181
|
+
smooth?: boolean;
|
|
173
182
|
/** Draw order among blended systems at the same depth — higher draws later, i.e. on top (Unity's
|
|
174
183
|
* sortingOrder). Systems are depth-sorted by their node, so the emitters of one effect tie and
|
|
175
184
|
* without this the engine picks who covers whom per frame (smoke popping over a fireball).
|
|
176
185
|
* Default 0; a fireball wants 2, its smoke 1, a smoke trail -1. */
|
|
177
186
|
order?: number;
|
|
187
|
+
/** Sprites take the light of the PLACE each one is in — the level's baked light grid (`env.lightmap.volume`).
|
|
188
|
+
* A sprite is unlit: its colour is the picture, which is right for fire and wrong for dust — a puff kicked up
|
|
189
|
+
* under an awning glows as if it stood in the sun. With `lit` every particle's colour is multiplied by the light
|
|
190
|
+
* where it is, relative to the level's OPEN ground: exactly the authored colour out in the sun, the ambient's
|
|
191
|
+
* share of it (tinted the way the shade is) under a roof — per particle, so a trail of puffs laid from the sun
|
|
192
|
+
* into the shade is lit along its length. Author the colour for the open; nothing else to tune. Without a grid
|
|
193
|
+
* — a level with no bake, a host that has none — the colours are drawn as authored. Points, quads, stretch and
|
|
194
|
+
* `Trail`; mesh particles are lit by their material. Default false. */
|
|
195
|
+
lit?: boolean;
|
|
178
196
|
/** Coarse draw order among ALL blended draws, 0 (first) … 7 (last) — see `Mesh.renderPriority`.
|
|
179
197
|
* Default 5: meshes sit at 4 and decals at 3, so smoke covers a car's glass and its skid marks
|
|
180
198
|
* whatever the camera does (the engine's depth sort compares object centres, and an emitter's
|
|
@@ -222,7 +240,11 @@ export declare class Particles extends Node {
|
|
|
222
240
|
set space(val: "local" | "world");
|
|
223
241
|
set inheritVelocity(val: number);
|
|
224
242
|
set rateOverDistance(val: number);
|
|
243
|
+
/** Lay a frame's spawns along a curve through the emitter's path, not the straight chord. */
|
|
244
|
+
set smooth(val: boolean);
|
|
225
245
|
set order(val: number);
|
|
246
|
+
/** Colours × the baked light where each particle is — see `ParticlesOptions.lit`. */
|
|
247
|
+
set lit(val: boolean);
|
|
226
248
|
/** Coarse draw order, 0 … 7 — see `Mesh.renderPriority`. Write-only. */
|
|
227
249
|
set renderPriority(v: number);
|
|
228
250
|
set velocityOverLife(v: VelocityOverLife);
|
|
@@ -260,8 +282,31 @@ export type TrailOptions = Omit<ParticlesMaterialOptions, "render" | "stretch">
|
|
|
260
282
|
width?: ParticleValue;
|
|
261
283
|
/** Minimum emitter movement (world units) between recorded points. Default 0.05. */
|
|
262
284
|
minDistance?: number;
|
|
263
|
-
/** Point capacity (default 128).
|
|
285
|
+
/** Point capacity (default 128). A spawn that does not fit is DROPPED, so a fast emitter at a
|
|
286
|
+
* small `minDistance` wants headroom: a sword tip covers metres inside one `time` window. */
|
|
264
287
|
maxPoints?: number;
|
|
288
|
+
/** Follow a CURVE through the emitter's recent path instead of the straight line between frames.
|
|
289
|
+
* A trail is where this shows most — the strip is the path — and it shows worse the lower the
|
|
290
|
+
* frame rate, since a longer frame bows further off its own chord. Default false; see
|
|
291
|
+
* `ParticlesOptions.smooth`. */
|
|
292
|
+
smooth?: boolean;
|
|
293
|
+
/** The strip takes the baked light of the place each of its points is at — `ParticlesOptions.lit`. Smoke and
|
|
294
|
+
* dust trails; leave it off for a glowing one. Default false. */
|
|
295
|
+
lit?: boolean;
|
|
296
|
+
/** Which way the strip's WIDTH points.
|
|
297
|
+
*
|
|
298
|
+
* `'camera'` (default) rolls the strip about its own length to stay flat to the viewer — it can
|
|
299
|
+
* never disappear, which is why it is the default, but it bears no relation to the thing that drew
|
|
300
|
+
* it. An AXIS (`'x'`/`'y'`/`'z'`) uses that axis of the emitter's own transform, as it was when
|
|
301
|
+
* each point was laid: on a node riding a sword's blade, `'z'` (the blade) makes the strip the
|
|
302
|
+
* surface the blade actually swept, and `width` stops being a made-up number — it is the blade. */
|
|
303
|
+
orient?: "camera" | "x" | "y" | "z";
|
|
304
|
+
/** With `orient` on an axis: the floor under the strip's APPARENT width, 0..1 of its real width,
|
|
305
|
+
* below which it rolls back toward the camera. An honestly oriented strip goes edge-on — and
|
|
306
|
+
* vanishes — whenever the swing happens in the plane of view; this is the hybrid that keeps it
|
|
307
|
+
* readable. 0 = never roll (honest, and it will vanish), 1 = always (the same as `'camera'`).
|
|
308
|
+
* Default 0.4: a sweep still reads as a sweep, and a swing toward the camera still shows. */
|
|
309
|
+
faceCamera?: number;
|
|
265
310
|
color?: ParticleColor;
|
|
266
311
|
/** Opacity along the trail. Defaults to fading the tail out (`curve().to(0)`). */
|
|
267
312
|
opacity?: ParticleValue;
|
|
@@ -274,6 +319,8 @@ export type TrailOptions = Omit<ParticlesMaterialOptions, "render" | "stretch">
|
|
|
274
319
|
export declare class Trail extends Node {
|
|
275
320
|
private _material;
|
|
276
321
|
private _rateDistance;
|
|
322
|
+
private _orient;
|
|
323
|
+
private _faceCamera;
|
|
277
324
|
constructor(options?: TrailOptions);
|
|
278
325
|
private _send;
|
|
279
326
|
/** Trail length in seconds — how long each laid-down point lives. */
|
|
@@ -282,6 +329,13 @@ export declare class Trail extends Node {
|
|
|
282
329
|
set opacity(val: ParticleValue);
|
|
283
330
|
set color(value: ParticleColor);
|
|
284
331
|
set minDistance(val: number);
|
|
332
|
+
/** Follow a curve through the emitter's path instead of the straight chord between frames. */
|
|
333
|
+
set smooth(val: boolean);
|
|
334
|
+
set lit(val: boolean);
|
|
335
|
+
/** Which way the strip's width points — see `TrailOptions.orient`. Keeps the current `faceCamera`. */
|
|
336
|
+
set orient(val: "camera" | "x" | "y" | "z");
|
|
337
|
+
/** The hybrid's floor — see `TrailOptions.faceCamera`. */
|
|
338
|
+
set faceCamera(val: number);
|
|
285
339
|
/** Pause/resume laying down points — existing ones still age out, so the trail fades naturally
|
|
286
340
|
* after e.g. a sword swing ends. */
|
|
287
341
|
set emitting(val: boolean);
|
package/dist/types/gl/Scene.d.ts
CHANGED
|
@@ -174,6 +174,19 @@ export declare class Scene implements Presentable {
|
|
|
174
174
|
setLodBias(bias: number): void;
|
|
175
175
|
/** Runtime form of `bloom` / `bloomIntensity` (a graphics-settings menu). */
|
|
176
176
|
setBloom(enabled: boolean, intensity?: number): void;
|
|
177
|
+
/**
|
|
178
|
+
* How bright the environment (IBL) lights the scene, in lux — `SceneOptions.environmentIntensity`
|
|
179
|
+
* after the fact. Live: it changes the probe's intensity, not the probe, so it costs nothing and
|
|
180
|
+
* can be dragged. (`setDefaultIbl`, the call that installs a probe, rebuilds the cubemap from the
|
|
181
|
+
* ktx every time — never drive a slider through a scene option that has to re-open.)
|
|
182
|
+
*
|
|
183
|
+
* `lecodes lightmap bake` reads the same number off the live probe, so a scene dimmed here bakes
|
|
184
|
+
* dimmed. Hosts without the call keep whatever the scene opened with, and the getter still
|
|
185
|
+
* reports what was asked for.
|
|
186
|
+
*/
|
|
187
|
+
get environmentIntensity(): number;
|
|
188
|
+
set environmentIntensity(lux: number);
|
|
189
|
+
private static _warnedEnvIntensity;
|
|
177
190
|
/** The scene's stencil buffer on / off (see `SceneOptions.stencil`). */
|
|
178
191
|
setStencil(enabled: boolean): void;
|
|
179
192
|
add(...nodes: Node[]): this;
|
|
@@ -192,6 +205,13 @@ export declare class Scene implements Presentable {
|
|
|
192
205
|
destroy(): void;
|
|
193
206
|
createOverlay(options?: SceneOptions): Scene;
|
|
194
207
|
warmRender(): Promise<void>;
|
|
208
|
+
/** Precompile the scene's shader variants so nothing is compiled mid-game. Every material the host
|
|
209
|
+
* knows is queued for the sun / shadow / fog / skinning variants and the dynamic-light key — the
|
|
210
|
+
* first point light (a muzzle flash, an explosion) would otherwise rebuild every lit shader in view
|
|
211
|
+
* on that frame. Call it once the sun and fog are set, typically under a loading screen; materials
|
|
212
|
+
* loaded later are queued in the background as they are created. Resolves at once on a host
|
|
213
|
+
* without the bridge. */
|
|
214
|
+
precompileShaders(): Promise<void>;
|
|
195
215
|
readonly cl: (() => void)[];
|
|
196
216
|
_backButtonCallback?: () => void;
|
|
197
217
|
private _vd?;
|
|
@@ -50,6 +50,25 @@ export declare class AnimationClip {
|
|
|
50
50
|
* keeps the ones inside the window, re-timed. Chainable. */
|
|
51
51
|
addEvent(time: number, name: string): this;
|
|
52
52
|
private _pushEvents;
|
|
53
|
+
/** ANCHOR SPANS for a bone — what an anchored IK chain ending in `bone` rides while this clip plays
|
|
54
|
+
* (`IK.TwoBone` with `anchor`; the sockets come from `anim.sockets(...)`). `donor` names the socket
|
|
55
|
+
* set of the gun the take was AUTHORED on ('' = the live set: no delta); `spans` = `[from, to,
|
|
56
|
+
* socket, rotation?, pin?]` in SECONDS — the socket the hand is on through that window (`''` = free:
|
|
57
|
+
* it rides the joint itself), `rotation` 0..1 how much of the socket's turn it takes (default 1),
|
|
58
|
+
* `pin` 0..1 how much it sits ON the socket instead of keeping its own relation to it (default 0: a
|
|
59
|
+
* magazine is REACHED, and the take's motion is what carries the hand there).
|
|
60
|
+
* Gaps between spans = the chain's own socket, pinned by the chain's `anchorPin` — that is where a
|
|
61
|
+
* hand holding the gun is nailed to the grip, so the layers below cannot slide it. A clip WITHOUT
|
|
62
|
+
* anchors takes no part: the hand keeps the take's own relation to the gun. Part of the clip, like
|
|
63
|
+
* events; `AnimationClip.from` carries them re-timed. Chainable.
|
|
64
|
+
* reload.anchors('hand_l', { donor: 'tr15', spans: [[0.9, 1.4, 'mag'], [1.4, 2.0, ''], [2.0, 2.4, 'mag'], [2.4, 2.7, 'bolt']] }) */
|
|
65
|
+
anchors(bone: string, def: {
|
|
66
|
+
donor?: string;
|
|
67
|
+
spans?: readonly (readonly [number, number, string, number?, number?])[];
|
|
68
|
+
}): this;
|
|
69
|
+
/** Drop a bone's anchor spans. */
|
|
70
|
+
clearAnchors(bone: string): this;
|
|
71
|
+
private _pushAnchors;
|
|
53
72
|
/** Load ONE clip from a GLB: the file's only/first clip, or the one named / at the given index. */
|
|
54
73
|
static load(source: string | FetchResponse, clip?: string | number): Promise<AnimationClip>;
|
|
55
74
|
/** Load EVERY clip of a GLB (library files), keyed by clip name. */
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Aspect } from "../../core/Aspect";
|
|
2
|
+
import { type Vec3Like } from "../../math/vec";
|
|
3
|
+
import { type QuatLike } from "../../math/quat";
|
|
2
4
|
import type { Node } from "../Node";
|
|
3
5
|
import type { AnimationClip } from "./AnimationClip";
|
|
4
6
|
import { type ActiveClip, type ClipInfo, type ClipEventHandler, type LayerOptions, type LoopDef, type LoopOptions, type PlayOptions, type StopOptions } from "./core";
|
|
@@ -75,6 +77,31 @@ export declare class Animator extends Aspect<"anim", Node> {
|
|
|
75
77
|
* turn too); on for a rig whose root carries the heading (`lecodes assets retarget --root-rotation yaw`). */
|
|
76
78
|
get rootRotation(): boolean;
|
|
77
79
|
set rootRotation(on: boolean);
|
|
80
|
+
/** The body's WORLD velocity this frame (m/s): what `anim.warp`'s stride and orientation fit the clips
|
|
81
|
+
* to. A `Locomotion` feeds it itself; when you drive the gait by hand set it every frame (the
|
|
82
|
+
* CharacterController's velocity, or your own). Reads back the last value fed. */
|
|
83
|
+
get motion(): readonly [number, number, number];
|
|
84
|
+
set motion(v: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
z: number;
|
|
88
|
+
} | readonly [number, number, number]);
|
|
89
|
+
private _motion;
|
|
90
|
+
/** SOCKETS: named frames on a bone of this rig — a weapon's grip / magazine / bolt empties, placed in
|
|
91
|
+
* the scene editor. A NODE socket is read by the engine every frame (a socket on a moving part
|
|
92
|
+
* follows it); a `{ position, quaternion }` one is fixed in the bone's space. The default set is the
|
|
93
|
+
* LIVE one (the weapon in the hands); `set: 'tr15'` names a DONOR set — the same sockets on the gun a
|
|
94
|
+
* take was authored on, which a clip's `anchors()` refer to. Chainable.
|
|
95
|
+
* arms.anim.sockets('ik_hand_gun', { grip_r: w.gripR, grip_l: w.gripL, mag: w.mag })
|
|
96
|
+
* arms.anim.sockets('ik_hand_gun', { grip_l: { position: [0.03, -0.12, -0.05] } }, { set: 'tr15' }) */
|
|
97
|
+
sockets(joint: Node | string, table: Record<string, Node | {
|
|
98
|
+
position?: Vec3Like;
|
|
99
|
+
quaternion?: QuatLike;
|
|
100
|
+
}>, options?: {
|
|
101
|
+
set?: string;
|
|
102
|
+
}): this;
|
|
103
|
+
/** Drop a socket (the live set, or `set`). */
|
|
104
|
+
removeSocket(name: string, set?: string): this;
|
|
78
105
|
/** `'auto'` (default): a character small on screen or out of view is evaluated every 2nd / 4th frame
|
|
79
106
|
* without its finger, toe and twist joints; `'full'`: every frame, every joint (a hero seen through a
|
|
80
107
|
* scope). Independent of `Model.lod`, the mesh level. */
|
|
@@ -11,12 +11,14 @@ export type DynamicBoneFloor = "none" | "probe" | number | Vec3Like;
|
|
|
11
11
|
* on the standard humanoid bones (hips, spine, head, limbs — the Ragdoll's layout); `'none'`; or the
|
|
12
12
|
* nodes carrying the colliders to use. */
|
|
13
13
|
export type DynamicBoneColliders = "auto" | "humanoid" | "none" | Node[];
|
|
14
|
-
/** The cloth's
|
|
15
|
-
* nearest surface (tails, ropes); `'auto'` = away from the root bone's own axis (a cloak's strips round
|
|
16
|
-
* spine face out from it); a vector = a fixed direction in the root bone's frame (a cape
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* through it
|
|
14
|
+
/** The cloth's SIDE of every collider marked `oneSided`: `'none'` = no side, every collider pushes a bone to
|
|
15
|
+
* its nearest surface (tails, ropes); `'auto'` = away from the root bone's own axis (a cloak's strips round
|
|
16
|
+
* a spine face out from it); a vector = a fixed direction in the root bone's frame (a cape hanging BEHIND
|
|
17
|
+
* the arms: the body's backward). A one-sided collider that is moving AWAY from that side — an arm swinging
|
|
18
|
+
* forward under the cape — puts a bone it has run into over to the side instead of carrying it: the arm
|
|
19
|
+
* passes through the cloth and the cape hangs behind it again, instead of being dragged round the body.
|
|
20
|
+
* Still, or moving toward the cloth, it pushes like any other collider, so cloth draped on an arm at rest
|
|
21
|
+
* stays where it is. Two-sided colliders (the body's) never read the side. */
|
|
20
22
|
export type DynamicBoneSide = "none" | "auto" | Vec3Like;
|
|
21
23
|
/** A capsule (or a sphere) riding a bone — what dynamic bones stay out of. Attach to a body bone:
|
|
22
24
|
* `hips.aspect(DynamicBoneCollider, { radius: 0.12, to: 'Spine' })`. The capsule runs from
|
|
@@ -33,6 +35,10 @@ export declare class DynamicBoneCollider extends Aspect<"dynamicBoneCollider", N
|
|
|
33
35
|
end?: Vec3Like;
|
|
34
36
|
/** The bone the capsule reaches (its origin), instead of `end`. */
|
|
35
37
|
to?: string;
|
|
38
|
+
/** ONE-SIDED: the cloth belongs on the chain's `side` of this capsule (see DynamicBone.side). While the capsule
|
|
39
|
+
* moves away from that side it puts a bone it has run into over to the side instead of carrying it — an arm
|
|
40
|
+
* under a cape may push the cape back, never drag it forward round the body. Needs a `side` on the DynamicBone. */
|
|
41
|
+
oneSided: boolean;
|
|
36
42
|
static fields: FieldMeta<DynamicBoneCollider>;
|
|
37
43
|
private _id;
|
|
38
44
|
private _segment;
|
|
@@ -64,7 +70,8 @@ export declare class DynamicBone extends Aspect<"dynamicBone", Node> {
|
|
|
64
70
|
mass: DynamicBoneCurve;
|
|
65
71
|
/** Bones (by name) that ride the animation exactly while their subtrees still simulate: a sheet's
|
|
66
72
|
* several roots under one anchor (a cloak's seven strips under the spine), so ONE chain owns them all
|
|
67
|
-
* and `link` ties neighbouring strips
|
|
73
|
+
* and `link` ties neighbouring strips — neighbours in THIS order, so list the strips round the ring
|
|
74
|
+
* (front-left … back … front-right); the front stays open. */
|
|
68
75
|
pinned?: string[];
|
|
69
76
|
/** Metres a PINNED bone may be pushed off its animated place by a collider — a soft pin. Its particle
|
|
70
77
|
* collides and takes the edge pushes like a free bone (the strip below hangs from where it IS) and is
|
|
@@ -163,7 +170,11 @@ export declare class DynamicBone extends Aspect<"dynamicBone", Node> {
|
|
|
163
170
|
get particles(): Vec3[];
|
|
164
171
|
private _collect;
|
|
165
172
|
private _fill;
|
|
166
|
-
/** Neighbour links: the bones at the same depth, in
|
|
173
|
+
/** Neighbour links: the bones at the same depth tied pairwise, the columns in the order of `pinned` (a cloak's
|
|
174
|
+
* strips listed round the ring) — columns not listed there follow in tree order. Tree order alone is the
|
|
175
|
+
* engine's child order, which for a GLB is the file's node order REVERSED (Filament prepends each child), so
|
|
176
|
+
* strips added to a rig later were tied across the body instead of to their neighbours: the ermine's cloak
|
|
177
|
+
* had one true neighbour pair out of eight, the rest were rods through the chest. */
|
|
167
178
|
private _links;
|
|
168
179
|
private _sync;
|
|
169
180
|
private _pushFloor;
|