lecodes-sdk 0.20.2 → 1.1.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 +35 -9
- 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/canvas/Canvas.d.ts +2 -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/DecalSet.d.ts +48 -3
- package/dist/types/gl/Foliage.d.ts +47 -0
- package/dist/types/gl/Geometry.d.ts +36 -0
- package/dist/types/gl/Light.d.ts +25 -7
- package/dist/types/gl/Lightmap.d.ts +90 -51
- package/dist/types/gl/Material.d.ts +32 -20
- package/dist/types/gl/Mesh.d.ts +7 -1
- package/dist/types/gl/Model.d.ts +41 -5
- package/dist/types/gl/Node.d.ts +18 -0
- package/dist/types/gl/Particles.d.ts +53 -1
- package/dist/types/gl/Scene.d.ts +21 -1
- 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 +184 -0
- package/dist/types/gl/animation/IK.d.ts +109 -0
- package/dist/types/gl/{Locomotion.d.ts → animation/Locomotion.d.ts} +6 -6
- package/dist/types/gl/animation/Warp.d.ts +2 -1
- package/dist/types/gl/animation/core.d.ts +35 -4
- package/dist/types/gl/{AudioSource.d.ts → audio/AudioSource.d.ts} +6 -6
- package/dist/types/gl/{AudioZone.d.ts → audio/AudioZone.d.ts} +4 -4
- package/dist/types/gl/{SceneAudio.d.ts → audio/SceneAudio.d.ts} +1 -1
- package/dist/types/gl/{NavAgent.d.ts → nav/NavAgent.d.ts} +4 -4
- package/dist/types/gl/{NavMesh.d.ts → nav/NavMesh.d.ts} +4 -4
- package/dist/types/gl/{CharacterController.d.ts → physics/CharacterController.d.ts} +5 -5
- package/dist/types/gl/{Physics.d.ts → physics/Physics.d.ts} +6 -5
- package/dist/types/gl/physics/Ragdoll.d.ts +161 -0
- package/dist/types/gl/{Shape.d.ts → physics/Shape.d.ts} +3 -3
- package/dist/types/gl/{Trigger.d.ts → physics/Trigger.d.ts} +2 -2
- package/dist/types/gl/{Terrain.d.ts → terrain/Terrain.d.ts} +10 -8
- package/dist/types/gl/{terrainMesh.d.ts → terrain/terrainMesh.d.ts} +1 -1
- package/dist/types/gl/vehicle/Vehicle.d.ts +300 -0
- package/dist/types/gl/vehicle/Wheel.d.ts +147 -0
- package/dist/types/inject.d.ts +35 -27
- package/dist/types/runtime/files.d.ts +24 -1
- package/dist/types/scene/defineScene.d.ts +50 -31
- 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/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/bridges.d.ts +1760 -1481
- package/src/canvas/Canvas.ts +21 -0
- package/src/compile/__tests__/assetMacro.test.ts +26 -0
- package/src/compile/__tests__/compile.test.ts +11 -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/header.ts +6 -3
- package/src/compile/index.ts +3 -0
- package/src/compile/sceneEditor.ts +42 -1
- 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/DecalSet.ts +132 -5
- package/src/gl/Foliage.ts +102 -0
- package/src/gl/Geometry.ts +109 -0
- package/src/gl/Light.ts +46 -16
- package/src/gl/Lightmap.ts +440 -249
- package/src/gl/Material.ts +69 -36
- package/src/gl/Mesh.ts +120 -102
- package/src/gl/Model.ts +167 -124
- package/src/gl/Node.ts +40 -1
- package/src/gl/Particles.ts +82 -5
- package/src/gl/Scene.ts +35 -2
- package/src/gl/animation/AnimationClip.ts +52 -0
- package/src/gl/animation/Animator.ts +42 -2
- package/src/gl/animation/DynamicBone.ts +482 -0
- package/src/gl/animation/IK.ts +214 -0
- package/src/gl/{Locomotion.ts → animation/Locomotion.ts} +7 -7
- 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/{AudioSource.ts → audio/AudioSource.ts} +7 -7
- package/src/gl/{AudioZone.ts → audio/AudioZone.ts} +75 -75
- package/src/gl/{SceneAudio.ts → audio/SceneAudio.ts} +2 -2
- package/src/gl/{NavAgent.ts → nav/NavAgent.ts} +5 -5
- package/src/gl/{NavMesh.ts → nav/NavMesh.ts} +8 -8
- package/src/gl/{CharacterController.ts → physics/CharacterController.ts} +5 -5
- package/src/gl/{Physics.ts → physics/Physics.ts} +12 -5
- package/src/gl/physics/Ragdoll.ts +451 -0
- package/src/gl/{Shape.ts → physics/Shape.ts} +3 -3
- package/src/gl/{Trigger.ts → physics/Trigger.ts} +45 -45
- package/src/gl/{physicsEvents.ts → physics/physicsEvents.ts} +1 -1
- package/src/gl/{Terrain.ts → terrain/Terrain.ts} +14 -12
- package/src/gl/{terrainMesh.ts → terrain/terrainMesh.ts} +1 -1
- package/src/gl/vehicle/Vehicle.ts +666 -0
- package/src/gl/vehicle/Wheel.ts +290 -0
- package/src/inject.ts +236 -224
- package/src/runtime/files.ts +32 -2
- package/src/scene/defineScene.ts +92 -66
- package/src/scene/level.ts +2 -2
- 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/dist/types/gl/Gearbox.d.ts +0 -86
- package/dist/types/gl/IK.d.ts +0 -53
- package/dist/types/gl/Ragdoll.d.ts +0 -86
- package/dist/types/gl/Vehicle.d.ts +0 -191
- package/dist/types/gl/Wheel.d.ts +0 -95
- package/src/animate/animate.ts +0 -238
- package/src/gl/Gearbox.ts +0 -212
- package/src/gl/IK.ts +0 -193
- package/src/gl/Ragdoll.ts +0 -270
- package/src/gl/Vehicle.ts +0 -473
- package/src/gl/Wheel.ts +0 -240
- /package/dist/types/gl/{physicsEvents.d.ts → physics/physicsEvents.d.ts} +0 -0
|
@@ -116,6 +116,12 @@ type Noise = {
|
|
|
116
116
|
strength?: number;
|
|
117
117
|
frequency?: number;
|
|
118
118
|
speed?: number;
|
|
119
|
+
/** How much of the displacement a particle earns with AGE (default 0 = all of it from birth).
|
|
120
|
+
* The field is sampled by position, so at 0 every particle born at the same spot is pushed the
|
|
121
|
+
* same way and a plume's root wanders off its emitter by up to `strength` metres; at 1 a particle
|
|
122
|
+
* is born exactly where the emitter put it and drifts into the field over its life — what you
|
|
123
|
+
* want whenever the source is visible (an exhaust pipe, a contact patch, a muzzle). */
|
|
124
|
+
ramp?: number;
|
|
119
125
|
};
|
|
120
126
|
/** Ground plane for bouncing particles (all render modes). `height` is in the simulation space:
|
|
121
127
|
* world y with `space: 'world'`, emitter-local y otherwise. */
|
|
@@ -164,11 +170,25 @@ export type ParticlesOptions = ParticlesMaterialOptions & {
|
|
|
164
170
|
* spread evenly along the path — trail density independent of speed, no per-frame clumps.
|
|
165
171
|
* Meant for `space: 'world'`. */
|
|
166
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;
|
|
167
182
|
/** Draw order among blended systems at the same depth — higher draws later, i.e. on top (Unity's
|
|
168
183
|
* sortingOrder). Systems are depth-sorted by their node, so the emitters of one effect tie and
|
|
169
184
|
* without this the engine picks who covers whom per frame (smoke popping over a fireball).
|
|
170
185
|
* Default 0; a fireball wants 2, its smoke 1, a smoke trail -1. */
|
|
171
186
|
order?: number;
|
|
187
|
+
/** Coarse draw order among ALL blended draws, 0 (first) … 7 (last) — see `Mesh.renderPriority`.
|
|
188
|
+
* Default 5: meshes sit at 4 and decals at 3, so smoke covers a car's glass and its skid marks
|
|
189
|
+
* whatever the camera does (the engine's depth sort compares object centres, and an emitter's
|
|
190
|
+
* centre says nothing about where its cloud is). `order` breaks ties inside one priority. */
|
|
191
|
+
renderPriority?: number;
|
|
172
192
|
shape?: Shape;
|
|
173
193
|
/** Extra velocity over life (radial burst that decays, axis drift) — see `VelocityOverLife`. */
|
|
174
194
|
velocityOverLife?: VelocityOverLife;
|
|
@@ -211,7 +231,11 @@ export declare class Particles extends Node {
|
|
|
211
231
|
set space(val: "local" | "world");
|
|
212
232
|
set inheritVelocity(val: number);
|
|
213
233
|
set rateOverDistance(val: number);
|
|
234
|
+
/** Lay a frame's spawns along a curve through the emitter's path, not the straight chord. */
|
|
235
|
+
set smooth(val: boolean);
|
|
214
236
|
set order(val: number);
|
|
237
|
+
/** Coarse draw order, 0 … 7 — see `Mesh.renderPriority`. Write-only. */
|
|
238
|
+
set renderPriority(v: number);
|
|
215
239
|
set velocityOverLife(v: VelocityOverLife);
|
|
216
240
|
set shape(shape: Shape);
|
|
217
241
|
/** (mesh mode) Replace the particle mesh; live particles keep flying as the new shape. */
|
|
@@ -247,8 +271,28 @@ export type TrailOptions = Omit<ParticlesMaterialOptions, "render" | "stretch">
|
|
|
247
271
|
width?: ParticleValue;
|
|
248
272
|
/** Minimum emitter movement (world units) between recorded points. Default 0.05. */
|
|
249
273
|
minDistance?: number;
|
|
250
|
-
/** Point capacity (default 128).
|
|
274
|
+
/** Point capacity (default 128). A spawn that does not fit is DROPPED, so a fast emitter at a
|
|
275
|
+
* small `minDistance` wants headroom: a sword tip covers metres inside one `time` window. */
|
|
251
276
|
maxPoints?: number;
|
|
277
|
+
/** Follow a CURVE through the emitter's recent path instead of the straight line between frames.
|
|
278
|
+
* A trail is where this shows most — the strip is the path — and it shows worse the lower the
|
|
279
|
+
* frame rate, since a longer frame bows further off its own chord. Default false; see
|
|
280
|
+
* `ParticlesOptions.smooth`. */
|
|
281
|
+
smooth?: boolean;
|
|
282
|
+
/** Which way the strip's WIDTH points.
|
|
283
|
+
*
|
|
284
|
+
* `'camera'` (default) rolls the strip about its own length to stay flat to the viewer — it can
|
|
285
|
+
* never disappear, which is why it is the default, but it bears no relation to the thing that drew
|
|
286
|
+
* it. An AXIS (`'x'`/`'y'`/`'z'`) uses that axis of the emitter's own transform, as it was when
|
|
287
|
+
* each point was laid: on a node riding a sword's blade, `'z'` (the blade) makes the strip the
|
|
288
|
+
* surface the blade actually swept, and `width` stops being a made-up number — it is the blade. */
|
|
289
|
+
orient?: "camera" | "x" | "y" | "z";
|
|
290
|
+
/** With `orient` on an axis: the floor under the strip's APPARENT width, 0..1 of its real width,
|
|
291
|
+
* below which it rolls back toward the camera. An honestly oriented strip goes edge-on — and
|
|
292
|
+
* vanishes — whenever the swing happens in the plane of view; this is the hybrid that keeps it
|
|
293
|
+
* readable. 0 = never roll (honest, and it will vanish), 1 = always (the same as `'camera'`).
|
|
294
|
+
* Default 0.4: a sweep still reads as a sweep, and a swing toward the camera still shows. */
|
|
295
|
+
faceCamera?: number;
|
|
252
296
|
color?: ParticleColor;
|
|
253
297
|
/** Opacity along the trail. Defaults to fading the tail out (`curve().to(0)`). */
|
|
254
298
|
opacity?: ParticleValue;
|
|
@@ -261,6 +305,8 @@ export type TrailOptions = Omit<ParticlesMaterialOptions, "render" | "stretch">
|
|
|
261
305
|
export declare class Trail extends Node {
|
|
262
306
|
private _material;
|
|
263
307
|
private _rateDistance;
|
|
308
|
+
private _orient;
|
|
309
|
+
private _faceCamera;
|
|
264
310
|
constructor(options?: TrailOptions);
|
|
265
311
|
private _send;
|
|
266
312
|
/** Trail length in seconds — how long each laid-down point lives. */
|
|
@@ -269,6 +315,12 @@ export declare class Trail extends Node {
|
|
|
269
315
|
set opacity(val: ParticleValue);
|
|
270
316
|
set color(value: ParticleColor);
|
|
271
317
|
set minDistance(val: number);
|
|
318
|
+
/** Follow a curve through the emitter's path instead of the straight chord between frames. */
|
|
319
|
+
set smooth(val: boolean);
|
|
320
|
+
/** Which way the strip's width points — see `TrailOptions.orient`. Keeps the current `faceCamera`. */
|
|
321
|
+
set orient(val: "camera" | "x" | "y" | "z");
|
|
322
|
+
/** The hybrid's floor — see `TrailOptions.faceCamera`. */
|
|
323
|
+
set faceCamera(val: number);
|
|
272
324
|
/** Pause/resume laying down points — existing ones still age out, so the trail fades naturally
|
|
273
325
|
* after e.g. a sword swing ends. */
|
|
274
326
|
set emitting(val: boolean);
|
package/dist/types/gl/Scene.d.ts
CHANGED
|
@@ -4,7 +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
|
+
import { SceneAudio } from "./audio/SceneAudio";
|
|
8
8
|
import { type ControlsHandle, type ControlsOptions } from "./controls";
|
|
9
9
|
import { Material } from "./Material";
|
|
10
10
|
import { Node } from "./Node";
|
|
@@ -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. */
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Aspect } from "../../core/Aspect";
|
|
2
|
+
import type { FieldMeta } from "../../core/fields";
|
|
3
|
+
import { Vec3, type Vec3Like } from "../../math/vec";
|
|
4
|
+
import { Node } from "../Node";
|
|
5
|
+
/** One value for the chain, or `[root, tip]` interpolated down it by depth. */
|
|
6
|
+
export type DynamicBoneCurve = number | readonly [root: number, tip: number];
|
|
7
|
+
/** `'none'`, `'probe'` (a ray from the chain root down against the physics world, every frame), a
|
|
8
|
+
* height (a horizontal plane at that world y) or a world point (a plane through it, `floorNormal` up). */
|
|
9
|
+
export type DynamicBoneFloor = "none" | "probe" | number | Vec3Like;
|
|
10
|
+
/** `'auto'` = every DynamicBoneCollider under the model; `'humanoid'` = those plus capsules generated
|
|
11
|
+
* on the standard humanoid bones (hips, spine, head, limbs — the Ragdoll's layout); `'none'`; or the
|
|
12
|
+
* nodes carrying the colliders to use. */
|
|
13
|
+
export type DynamicBoneColliders = "auto" | "humanoid" | "none" | Node[];
|
|
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. */
|
|
22
|
+
export type DynamicBoneSide = "none" | "auto" | Vec3Like;
|
|
23
|
+
/** A capsule (or a sphere) riding a bone — what dynamic bones stay out of. Attach to a body bone:
|
|
24
|
+
* `hips.aspect(DynamicBoneCollider, { radius: 0.12, to: 'Spine' })`. The capsule runs from
|
|
25
|
+
* `offset` (the bone's origin by default) to the `to` bone's origin, or to `end` (both in the bone's
|
|
26
|
+
* local space); neither = a sphere at `offset`. Picked up by every DynamicBone on the same model
|
|
27
|
+
* with `colliders: 'auto'` / `'humanoid'`, or listed explicitly. */
|
|
28
|
+
export declare class DynamicBoneCollider extends Aspect<"dynamicBoneCollider", Node> {
|
|
29
|
+
static readonly aspect = "dynamicBoneCollider";
|
|
30
|
+
/** Radius in metres, in the world: the bone's scale does not touch it (`offset` / `end` are in the bone's own units). */
|
|
31
|
+
radius: number;
|
|
32
|
+
/** Start of the capsule in the bone's local space (default: the bone's origin). */
|
|
33
|
+
offset: Vec3Like;
|
|
34
|
+
/** End of the capsule in the bone's local space (a sphere when neither `end` nor `to` is set). */
|
|
35
|
+
end?: Vec3Like;
|
|
36
|
+
/** The bone the capsule reaches (its origin), instead of `end`. */
|
|
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;
|
|
42
|
+
static fields: FieldMeta<DynamicBoneCollider>;
|
|
43
|
+
private _id;
|
|
44
|
+
private _segment;
|
|
45
|
+
onAttach(): void;
|
|
46
|
+
onReconfigure(): void;
|
|
47
|
+
onDetach(): void;
|
|
48
|
+
}
|
|
49
|
+
export declare class DynamicBone extends Aspect<"dynamicBone", Node> {
|
|
50
|
+
static readonly aspect = "dynamicBone";
|
|
51
|
+
/** Only these bones (by name) join the chain — the root always does, a bone left out takes its
|
|
52
|
+
* subtree with it. Default: the root's whole subtree. */
|
|
53
|
+
bones?: string[];
|
|
54
|
+
/** Depth limit under the root (0 = no limit). */
|
|
55
|
+
depth: number;
|
|
56
|
+
/** Particle radius for the collisions, metres. */
|
|
57
|
+
radius: DynamicBoneCurve;
|
|
58
|
+
/** 0..1 — how fast a bone returns to the animated shape (per 1/60 s). 0 = a rope, 1 = rigid. */
|
|
59
|
+
stiffness: DynamicBoneCurve;
|
|
60
|
+
/** 0..1 — velocity lost per 1/60 s. 0.02 swings like a rope, 0.1 settles like a tail, 0.3 is honey. */
|
|
61
|
+
damping: DynamicBoneCurve;
|
|
62
|
+
/** m/s² downward. A hanging rest pose feels none of it (the bone length cancels it); a pose that
|
|
63
|
+
* sticks out droops by as much as `stiffness` lets it. */
|
|
64
|
+
gravity: DynamicBoneCurve;
|
|
65
|
+
/** Max deviation from the animated direction, degrees per bone (0 = free). */
|
|
66
|
+
angleLimit: DynamicBoneCurve;
|
|
67
|
+
/** Relative mass per bone. A bone-length constraint moves its two ends in inverse proportion to
|
|
68
|
+
* their masses (the root is kinematic): `[3, 1]` makes a tail's base carry its tip, `1` shares
|
|
69
|
+
* evenly like a rope. */
|
|
70
|
+
mass: DynamicBoneCurve;
|
|
71
|
+
/** Bones (by name) that ride the animation exactly while their subtrees still simulate: a sheet's
|
|
72
|
+
* several roots under one anchor (a cloak's seven strips under the spine), so ONE chain owns them all
|
|
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. */
|
|
75
|
+
pinned?: string[];
|
|
76
|
+
/** Metres a PINNED bone may be pushed off its animated place by a collider — a soft pin. Its particle
|
|
77
|
+
* collides and takes the edge pushes like a free bone (the strip below hangs from where it IS) and is
|
|
78
|
+
* drawn back to the animation when the collider leaves; the bone's local translation follows. A hard
|
|
79
|
+
* pin (0) at a capsule's edge made the first free bone below it jitter: the edge push on a segment
|
|
80
|
+
* with an immovable end is a lever, and a touch near the root threw the child out. 2–3 cm for a
|
|
81
|
+
* cloak's roots under a shoulder capsule. */
|
|
82
|
+
pinGive: number;
|
|
83
|
+
/** 0..1 of the character's travel the chain takes rigidly (0 = the full whip on a dash, 1 = it
|
|
84
|
+
* moves with the body and only the pose's own motion swings it). */
|
|
85
|
+
follow: number;
|
|
86
|
+
/** World wind, m/s². */
|
|
87
|
+
wind: Vec3Like;
|
|
88
|
+
/** The BODY'S TURN, ≥ 0. Above 0 the chain lives in the parent bone's ROTATING frame: `damping` acts
|
|
89
|
+
* against the body's rigid motion (its travel plus its spin), so a heavily damped cloak RIDES a turn —
|
|
90
|
+
* sweeps round with the back — instead of standing in the world while the character spins under it and
|
|
91
|
+
* being dragged round after. The turn's inertia comes back as the frame's forces, scaled by this value:
|
|
92
|
+
* a centrifugal push `ω² · r` along each bone's animated direction from the axis (the hem, farthest
|
|
93
|
+
* from the spine, flies out and, on the chain's length, up). The frame's own physics is built in: the
|
|
94
|
+
* whip back when the turn starts and forward when it stops, Coriolis. 1 = the physical push; more = a
|
|
95
|
+
* bigger fling. With low damping the frame reproduces a free particle (nothing is counted twice);
|
|
96
|
+
* an animation's spine sway is ~1 % of a 900°/s turn. A rotation over 90° in one frame (a respawn
|
|
97
|
+
* facing) counts as a snap, not a spin. 0 = the plain translational frame, no turn forces. */
|
|
98
|
+
spin: number;
|
|
99
|
+
/** With `spin`: the cloth's INERTIA against the body's turn, seconds — the cloth's own rotation follows the
|
|
100
|
+
* body's with this time constant. It falls behind when a turn starts (by about ω·τ: 45° at 900°/s and 0.05),
|
|
101
|
+
* rides once caught up, and keeps turning past the back when the body stops (the same angle, eased out over
|
|
102
|
+
* τ). Smooth by construction. 0 = glued to the turn; large = the cloth stays in the world while the body spins. */
|
|
103
|
+
spinInertia: number;
|
|
104
|
+
/** 0..1 strength of the ties between neighbouring columns at the same depth (a cloak). */
|
|
105
|
+
link: number;
|
|
106
|
+
/** 0..1 blend from the animation (0) to the simulation (1). At 0 nothing is simulated and the
|
|
107
|
+
* chain re-arms on the animated pose when it comes back. */
|
|
108
|
+
weight: number;
|
|
109
|
+
/** Substep rate, Hz (≤ 4 substeps per frame). */
|
|
110
|
+
rate: number;
|
|
111
|
+
/** A root jump longer than this in one frame (metres) resets the chain instead of whipping it. */
|
|
112
|
+
teleport: number;
|
|
113
|
+
/** What the particles stay above: `'none'`, `'probe'`, a height, or a world point. */
|
|
114
|
+
floor: DynamicBoneFloor;
|
|
115
|
+
/** The floor plane's normal when `floor` is a point. */
|
|
116
|
+
floorNormal: Vec3Like;
|
|
117
|
+
/** Friction against the floor, a Coulomb coefficient: a resting bone's slide loses up to
|
|
118
|
+
* `floorFriction · gravity · dt` of speed per substep (0 = ice, 1 = a rubber sole). While a bone
|
|
119
|
+
* rests on the floor or a collider, `stiffness` and `angleLimit` let go of it: the surface's
|
|
120
|
+
* reaction outranks the spring, or a hem folded on the floor would run away along it. */
|
|
121
|
+
floorFriction: number;
|
|
122
|
+
/** Constraint passes per substep (1..8, default 4). Each pass shares every bone length between its
|
|
123
|
+
* ends, so a pull needs passes to travel down a long chain: a long rope may want 8, a short tail is
|
|
124
|
+
* fine with 2. */
|
|
125
|
+
iterations: number;
|
|
126
|
+
/** What the chain collides with (see DynamicBoneColliders). */
|
|
127
|
+
colliders: DynamicBoneColliders;
|
|
128
|
+
/** The cloth's outside — makes the colliders one-sided (see DynamicBoneSide). */
|
|
129
|
+
side: DynamicBoneSide;
|
|
130
|
+
/** How firmly `guide()` targets are HELD through the constraint passes, 0..1. At 0 a guide is applied once
|
|
131
|
+
* before the passes and the length / link passes may drag the bone back toward its un-guided neighbours
|
|
132
|
+
* within the same frame; at 0.5 it is re-pulled after every pass with half its weight (converges with the
|
|
133
|
+
* passes), at 1 with its full weight (a target the bone length cannot reach then jitters). */
|
|
134
|
+
guideHold: number;
|
|
135
|
+
/** The chain's EDGES collide with the capsules too — every bone segment and every link, not only the bones'
|
|
136
|
+
* particles: a capsule thinner than a bone's length (a forearm) no longer passes through the cloth between
|
|
137
|
+
* two bones. Off = particles only. */
|
|
138
|
+
edges: boolean;
|
|
139
|
+
static fields: FieldMeta<DynamicBone>;
|
|
140
|
+
private _id;
|
|
141
|
+
private _chain;
|
|
142
|
+
private _depths;
|
|
143
|
+
private _blob;
|
|
144
|
+
private _sent;
|
|
145
|
+
private _floorKey;
|
|
146
|
+
private _colliderKey;
|
|
147
|
+
private _collidersDirty;
|
|
148
|
+
private _collidersRef;
|
|
149
|
+
private _own;
|
|
150
|
+
private _colliderSet;
|
|
151
|
+
/** The bones of the chain, the root first. */
|
|
152
|
+
get chain(): readonly Node[];
|
|
153
|
+
onAttach(): void;
|
|
154
|
+
onReconfigure(): void;
|
|
155
|
+
/** Every field is live: what changed since the last frame is pushed here, before the engine's stage. */
|
|
156
|
+
update(): void;
|
|
157
|
+
onDetach(): void;
|
|
158
|
+
/** Snap the chain onto the animated pose next frame (a teleport, a camera cut). */
|
|
159
|
+
reset(): void;
|
|
160
|
+
/** GUIDES: world points the bones' particles are drawn to each substep before the constraints —
|
|
161
|
+
* weight 1 = there before them, the rest of the chain hangs, collides and links as before (a cape's
|
|
162
|
+
* strips riding the arms). Replaces the previous set; an empty list clears. A late-phase script
|
|
163
|
+
* (after the animator, before the engine's chain stage) refreshes it every frame. */
|
|
164
|
+
guide(rows: readonly {
|
|
165
|
+
bone: Node;
|
|
166
|
+
at: Vec3Like;
|
|
167
|
+
weight: number;
|
|
168
|
+
}[]): void;
|
|
169
|
+
/** The particles' world positions (the bones, then the leaves' virtual tips) — for a debug draw. */
|
|
170
|
+
get particles(): Vec3[];
|
|
171
|
+
private _collect;
|
|
172
|
+
private _fill;
|
|
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. */
|
|
178
|
+
private _links;
|
|
179
|
+
private _sync;
|
|
180
|
+
private _pushFloor;
|
|
181
|
+
private _pushColliders;
|
|
182
|
+
/** Capsules on the standard humanoid bones, sized like the Ragdoll's parts. */
|
|
183
|
+
private _makeHumanoid;
|
|
184
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Aspect } from "../../core/Aspect";
|
|
2
|
+
import { type Vec3Like } from "../../math/vec";
|
|
3
|
+
import { Quat } from "../../math/quat";
|
|
4
|
+
import type { Node } from "../Node";
|
|
5
|
+
import type { Core } from "./core";
|
|
6
|
+
type Target = Node | Vec3Like;
|
|
7
|
+
/** What both chains share: the native handle, the parameter push, the readback. */
|
|
8
|
+
declare abstract class Chain<Name extends string> extends Aspect<Name, Node> {
|
|
9
|
+
protected _rig?: Core;
|
|
10
|
+
protected _ik: number;
|
|
11
|
+
protected _weight: number;
|
|
12
|
+
protected _enabled: boolean;
|
|
13
|
+
protected abstract readonly kind: 0 | 1;
|
|
14
|
+
/** 0–1 contribution (blend in/out, e.g. foot planting only while grounded). */
|
|
15
|
+
get weight(): number;
|
|
16
|
+
set weight(v: number);
|
|
17
|
+
/** Solve every frame (default). */
|
|
18
|
+
get enabled(): boolean;
|
|
19
|
+
set enabled(v: boolean);
|
|
20
|
+
/** After the last solve: how far the end bone still is from its target, metres (0 = reached). */
|
|
21
|
+
get error(): number;
|
|
22
|
+
onAttach(): void;
|
|
23
|
+
onDetach(): void;
|
|
24
|
+
onReconfigure(): void;
|
|
25
|
+
protected params(): Float32Array;
|
|
26
|
+
/** Push the description to the engine (a no-op until attached). */
|
|
27
|
+
protected abstract push(): void;
|
|
28
|
+
}
|
|
29
|
+
/** Two-bone analytic IK (limbs). Attach to the END bone: `foot.aspect(IK.TwoBone, { target })` solves
|
|
30
|
+
* upper (grandparent) + mid (parent) so the end reaches `target`; `pole` steers the bend (knee /
|
|
31
|
+
* elbow) — a Node or world point; `anchor` makes it ride a socket of the rig instead (see the file
|
|
32
|
+
* header). */
|
|
33
|
+
declare class TwoBone extends Chain<"ik"> {
|
|
34
|
+
static readonly aspect = "ik";
|
|
35
|
+
protected readonly kind: 0;
|
|
36
|
+
private _target?;
|
|
37
|
+
private _pole?;
|
|
38
|
+
private _rotation?;
|
|
39
|
+
private _rotationWeight;
|
|
40
|
+
private _anchor;
|
|
41
|
+
private _anchorTime;
|
|
42
|
+
private _anchorPin;
|
|
43
|
+
/** Where the end bone should be (a Node — read by the engine every frame — or a world position). */
|
|
44
|
+
get target(): Target | undefined;
|
|
45
|
+
set target(v: Target | undefined);
|
|
46
|
+
/** Bend hint — the mid joint is pulled toward it (a Node or a world point). */
|
|
47
|
+
get pole(): Target | undefined;
|
|
48
|
+
set pole(v: Target | undefined);
|
|
49
|
+
/** World rotation the END bone takes after the solve — a Node (its world rotation) or a Quat. Unset =
|
|
50
|
+
* the end bone keeps its animated rotation (a hand on a grip, a foot on a slope want it set). Blended
|
|
51
|
+
* by `weight · rotationWeight`. An anchored chain takes its rotation from the socket instead. */
|
|
52
|
+
get rotation(): Node | Quat | undefined;
|
|
53
|
+
set rotation(v: Node | Quat | undefined);
|
|
54
|
+
/** 0–1 contribution of `rotation` (on top of `weight`); for an anchored chain, of the socket's turn. */
|
|
55
|
+
get rotationWeight(): number;
|
|
56
|
+
set rotationWeight(v: number);
|
|
57
|
+
/** ANCHORED: the name of the LIVE socket the end bone rides (`anim.sockets(...)`) — its target and
|
|
58
|
+
* rotation come from the socket and the playing clips' anchor spans; `target` / `pole` / `rotation`
|
|
59
|
+
* are ignored. '' = a plain chain. */
|
|
60
|
+
get anchor(): string;
|
|
61
|
+
set anchor(v: string);
|
|
62
|
+
/** Anchored: how fast the hand moves between sockets — the halflife (s) of the spring the applied
|
|
63
|
+
* delta follows the wanted one with (default 0.05). */
|
|
64
|
+
get anchorTime(): number;
|
|
65
|
+
set anchorTime(v: number);
|
|
66
|
+
/** Anchored: 0..1 how hard the end bone is PINNED on its socket while the playing clips leave it there
|
|
67
|
+
* (a GAP in their spans — the hand is holding the gun). 1 = it sits exactly on the socket, so nothing
|
|
68
|
+
* in the pose below can slide it along the gun; 0 (default) = it keeps the take's own relation to the
|
|
69
|
+
* socket, moved by the delta. A clip's SPANS carry their own pin and default to 0, because a hand on
|
|
70
|
+
* its way to a magazine must keep the take's motion — so this knob is about holding, not reaching. */
|
|
71
|
+
get anchorPin(): number;
|
|
72
|
+
set anchorPin(v: number);
|
|
73
|
+
/** After the last solve: the anchor delta applied — how far (m) and how much (rad) the live socket
|
|
74
|
+
* moved the hand off the take's own pose. 0 for a plain chain. */
|
|
75
|
+
get anchorDelta(): {
|
|
76
|
+
distance: number;
|
|
77
|
+
angle: number;
|
|
78
|
+
};
|
|
79
|
+
protected push(): void;
|
|
80
|
+
}
|
|
81
|
+
/** Aim a bone at a target (head / eyes / turret). Attach to the bone itself:
|
|
82
|
+
* `head.aspect(IK.LookAt, { target: camera, limit: 70 })`. `axis` is the bone's LOCAL forward
|
|
83
|
+
* (the direction that should point at the target) — rigs differ; default −Z, Mixamo heads look
|
|
84
|
+
* along +Z of the head bone in most exports, so pass `axis: [0, 0, 1]` there if it faces backwards. */
|
|
85
|
+
declare class LookAt extends Chain<"lookAt"> {
|
|
86
|
+
static readonly aspect = "lookAt";
|
|
87
|
+
protected readonly kind: 1;
|
|
88
|
+
private _target?;
|
|
89
|
+
private _axis;
|
|
90
|
+
private _limit;
|
|
91
|
+
/** What to look at (a Node — read by the engine every frame — or a world position). */
|
|
92
|
+
get target(): Target | undefined;
|
|
93
|
+
set target(v: Target | undefined);
|
|
94
|
+
/** The bone's local axis that should point at the target. */
|
|
95
|
+
get axis(): Vec3Like;
|
|
96
|
+
set axis(v: Vec3Like);
|
|
97
|
+
/** Max deflection from the animated direction, in degrees (default 80). */
|
|
98
|
+
get limit(): number;
|
|
99
|
+
set limit(v: number);
|
|
100
|
+
protected push(): void;
|
|
101
|
+
}
|
|
102
|
+
/** Inverse kinematics aspects — attach to bones (see file header). */
|
|
103
|
+
export declare const IK: {
|
|
104
|
+
TwoBone: typeof TwoBone;
|
|
105
|
+
LookAt: typeof LookAt;
|
|
106
|
+
};
|
|
107
|
+
export type IKTwoBone = TwoBone;
|
|
108
|
+
export type IKLookAt = LookAt;
|
|
109
|
+
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Aspect } from "
|
|
2
|
-
import { Vec3, type Vec3Like } from "
|
|
3
|
-
import { Animator } from "./
|
|
4
|
-
import type { FeetOptions } from "./
|
|
5
|
-
import type { WarpOptions } from "./
|
|
6
|
-
import type { Node } from "
|
|
1
|
+
import { Aspect } from "../../core/Aspect";
|
|
2
|
+
import { Vec3, type Vec3Like } from "../../math/vec";
|
|
3
|
+
import { Animator } from "./Animator";
|
|
4
|
+
import type { FeetOptions } from "./Feet";
|
|
5
|
+
import type { WarpOptions } from "./Warp";
|
|
6
|
+
import type { Node } from "../Node";
|
|
7
7
|
/** How fast the character wants to go: the gait picks its clips and its speed. */
|
|
8
8
|
export type Gait = "walk" | "run" | "sprint";
|
|
9
9
|
/** What the engine shows: the idle, a start, the gait loop, a turn while moving, a stop, or a turn on the spot. */
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
export type WarpOptions = {
|
|
3
3
|
/** Fit the stride to the speed the body actually travels at. `[min, max]` clamps the scale (default
|
|
4
4
|
* 0.85…1.2). A CORRECTION: a pack whose takes already read right at the speeds it is played at wants
|
|
5
|
-
* none of this; open the range for a pack that must cover speeds it was never recorded at.
|
|
5
|
+
* none of this; open the range for a pack that must cover speeds it was never recorded at. The clip's
|
|
6
|
+
* own speed is its root motion — an in-place loop takes part only with a declared pace (see above). */
|
|
6
7
|
stride?: boolean | [number, number];
|
|
7
8
|
/** Turn the lower body toward where the body really travels; a number caps the turn in degrees
|
|
8
9
|
* (default 20). The whole twist lives in one joint: a few degrees read as a lean, a lot as a broken
|
|
@@ -13,15 +13,24 @@ export type PlayOptions = {
|
|
|
13
13
|
fade?: number;
|
|
14
14
|
/** Transition seconds for the way in only (overrides `fade`). */
|
|
15
15
|
fadeIn?: number;
|
|
16
|
-
/** One-shots: the transition BACK to the loop
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
/** One-shots: the transition BACK to the loop after the end (overrides `fade`; `0` = cut at the end).
|
|
17
|
+
* The clip plays to its last frame; the loop then takes over and the difference between the two poses
|
|
18
|
+
* (and their velocities) decays over this time, so no part of the clip is cut — to play less of it,
|
|
19
|
+
* give it an `end`. On a layer with no loop the clip HOLDS its last frame (a rock that broke stays
|
|
20
|
+
* broken) — `anim.stop({ fade })` is the way back to rest. */
|
|
20
21
|
fadeOut?: number;
|
|
21
22
|
/** Playback rate for this clip (default 1). */
|
|
22
23
|
speed?: number;
|
|
23
24
|
/** Rewind even if the clip is already playing (default: rewind only if it isn't). */
|
|
24
25
|
restart?: boolean;
|
|
26
|
+
/** Play a WINDOW of the clip, seconds of the clip: enter at `start` (default 0; only when the play
|
|
27
|
+
* rewinds — see `restart`) and treat `end` (default the clip's end) as the end — the hand-over fires
|
|
28
|
+
* there, the last frame held there, events beyond it never fire. Only the swing of a longer take, the
|
|
29
|
+
* wind-up without the recovery. A window that lives in the clip table belongs in
|
|
30
|
+
* `AnimationClip.from(clip, { from, to })` instead. Not combined with `phase`. Hosts without the
|
|
31
|
+
* window play the whole clip. */
|
|
32
|
+
start?: number;
|
|
33
|
+
end?: number;
|
|
25
34
|
/** Enter the clip at a point in the GAIT CYCLE instead of at its start: `'match'` = the phase the
|
|
26
35
|
* layer shows right now (the walk's left foot is down → the turn clip starts where its left foot
|
|
27
36
|
* is down too, so nothing slides), or a number 0–1. Clips without a gait cycle ignore it. */
|
|
@@ -302,6 +311,9 @@ export declare class Core {
|
|
|
302
311
|
private clipNames;
|
|
303
312
|
/** Create the native animator on demand. False = nothing to animate (warned). */
|
|
304
313
|
ensure(): boolean;
|
|
314
|
+
/** The native animator for the RIG alone — an IK chain or a socket on a model that has no clips
|
|
315
|
+
* still needs the joint tree described to the engine. False = no transform hierarchy (warned). */
|
|
316
|
+
ensureRig(): boolean;
|
|
305
317
|
destroy(): void;
|
|
306
318
|
newLayer(options?: LayerOptions): LayerRec;
|
|
307
319
|
addLayer(options: LayerOptions): Layer;
|
|
@@ -392,12 +404,31 @@ export declare class Core {
|
|
|
392
404
|
/** Stride / orientation warping, as the engine's fixed-order parameter array. */
|
|
393
405
|
private _warp?;
|
|
394
406
|
setWarp(params: Float32Array): void;
|
|
407
|
+
/** The body's world velocity this frame (m/s) — the game side of the stride / orientation fit. Nothing
|
|
408
|
+
* to feed before the animator exists; hosts without the warp stage have no method. */
|
|
409
|
+
setMotion(vx: number, vy: number, vz: number): void;
|
|
395
410
|
/** The feet stage (lock / ground IK), as the engine's fixed-order parameter array. */
|
|
396
411
|
private _feetParams?;
|
|
397
412
|
setFeetParams(params: Float32Array): void;
|
|
398
413
|
/** One foot's lock state after this frame's evaluation into `out` (8 floats); false = no such foot
|
|
399
414
|
* or no feet stage on this host. */
|
|
400
415
|
footState(side: 0 | 1, out: Float32Array): boolean;
|
|
416
|
+
private static _warnedIk;
|
|
417
|
+
private hasIk;
|
|
418
|
+
/** A chain ending in `endEntity` (kind 0 two-bone: the bone, its parent, its grandparent; 1 look-at). 0 = none. */
|
|
419
|
+
ikCreate(kind: 0 | 1, endEntity: number): number;
|
|
420
|
+
ikDestroy(ik: number): void;
|
|
421
|
+
ikSet(ik: number, params: Float32Array): void;
|
|
422
|
+
ikNodes(ik: number, target: number, pole: number, rotation: number): void;
|
|
423
|
+
ikAnchor(ik: number, socket: string): void;
|
|
424
|
+
ikState(ik: number, out: Float32Array): boolean;
|
|
425
|
+
/** Sockets by "set/name", replayed when the animator is (re)created. */
|
|
426
|
+
private readonly _sockets;
|
|
427
|
+
/** Define a socket on joint `joint` (a bone's entity): a NODE socket (read by the engine every frame) or a
|
|
428
|
+
* fixed TRS in the joint's space. set "" = the live set, any other name = a donor's. */
|
|
429
|
+
setSocket(set: string, name: string, joint: number, node: number, trs: Float32Array | null): void;
|
|
430
|
+
removeSocket(set: string, name: string): void;
|
|
431
|
+
private pushSocket;
|
|
401
432
|
private readonly _steps;
|
|
402
433
|
onStepHandler(cb: StepHandler): void;
|
|
403
434
|
offStepHandler(cb: StepHandler): void;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Aspect } from "
|
|
2
|
-
import type { FieldMeta } from "
|
|
3
|
-
import { type PlaySoundOptions, type Rolloff } from "
|
|
4
|
-
import type { Sound } from "
|
|
5
|
-
import type { Voice } from "
|
|
6
|
-
import type { Node } from "
|
|
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
7
|
export type AudioCone = {
|
|
8
8
|
/** Degrees of full volume around the node's −Z. */
|
|
9
9
|
inner: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Aspect } from "
|
|
2
|
-
import { type ReverbParams, type ReverbPreset } from "
|
|
3
|
-
import { type Vec3Like } from "
|
|
4
|
-
import type { Node } from "
|
|
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
5
|
export declare class AudioZone extends Aspect<"audioZone", Node> {
|
|
6
6
|
static readonly aspect = "audioZone";
|
|
7
7
|
private _box;
|