incanto 0.52.0 → 0.54.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/bin/incanto-check.mjs +56 -1
- package/dist/2d.d.ts +95 -4
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +111 -6
- package/dist/3d.js +10 -6
- package/dist/{behavior-uPEuZrUB.d.ts → behavior-CyQoSu4n.d.ts} +212 -10
- package/dist/{create-game-B_e9hJf7.js → create-game-BRt6XKmP.js} +31 -12
- package/dist/{create-game-CGnoypjL.js → create-game-Czzp6ZuE.js} +26 -14
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/{duplicate-B-OtSRFL.js → duplicate-MNLMAcbz.js} +1 -1
- package/dist/editor.js +14 -0
- package/dist/{environment-presets-DSZwsKPs.js → environment-presets-BQ_QsIBY.js} +222 -11
- package/dist/{gameplay-B6jqvYeM.js → gameplay-CZ2yq37J.js} +32 -23
- package/dist/gameplay.d.ts +8 -3
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +178 -6
- package/dist/index.js +9 -9
- package/dist/{loader-B-Gft32x.js → loader-BTkHYrQn.js} +54 -18
- package/dist/{loader-B9iTqs27.d.ts → loader-DhI1jFW_.d.ts} +1 -1
- package/dist/{log-report-lxrQY9cH.js → log-report-CPFm4OXf.js} +0 -0
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/{particle-sim-BzJ1yxoE.d.ts → particle-sim-C5OfBbmU.d.ts} +11 -0
- package/dist/{pathfinding-CAR9DjQQ.d.ts → pathfinding-CXGCpRQe.d.ts} +24 -1
- package/dist/{physics-2d-Dns-oZlE.js → physics-2d-CfWAggJ1.js} +2 -2
- package/dist/{physics-3d-BhI0ehpe.js → physics-3d-Bes-GIuR.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-Trx7WHnD.js → register-en63AEZO.js} +163 -4
- package/dist/{register-DVwlnZAZ.js → register-p48lHE2o.js} +433 -36
- package/dist/{replay-BU1CCM15.d.ts → replay-ePMz26jw.d.ts} +1 -1
- package/dist/{replay-BicPOMX0.js → replay-t1pP0gQg.js} +2 -2
- package/dist/{split-screen-paxkQs_q.d.ts → split-screen-BsdOHbzP.d.ts} +1 -1
- package/dist/{split-screen-CZ9ccBBQ.js → split-screen-CSb_uZ6W.js} +2 -2
- package/dist/{sprite-animation-D_p28jwU.js → sprite-animation-7qvUxF6Z.js} +19 -0
- package/dist/{src-5gbZO47I.js → src-vNPQeQ1W.js} +1 -1
- package/dist/{teardown-ks3d5W9n.js → teardown-C7uVSJvx.js} +30 -1
- package/dist/{test-DAojuFdb.js → test-Tnf1nQl3.js} +25 -13
- package/dist/test.d.ts +4 -4
- package/dist/test.js +2 -2
- package/dist/{touch-BoNg_MnF.js → touch-BnMyy9tr.js} +4 -4
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-CCvckvbw.js → agent8-BWaW-D85.js} +1 -1
- package/editor/assets/{debug-CLNCOnbc.js → debug-DLF8rUtr.js} +2 -2
- package/editor/assets/{index-Cb5Brupb.js → index-BYfiwbQx.js} +91 -91
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +221 -0
- package/skills/incanto-assets.md +45 -2
- package/skills/incanto-audio.md +97 -10
- package/skills/incanto-building-2d-games.md +55 -3
- package/skills/incanto-building-3d-games.md +3 -1
- package/skills/incanto-environment.md +3 -1
- package/skills/incanto-gameplay-behaviors.md +51 -4
- package/skills/incanto-hud.md +7 -0
- package/skills/incanto-node-reference.md +36 -0
- package/skills/incanto-performance.md +47 -0
- package/skills/incanto-physics-and-input.md +38 -0
- package/skills/incanto-verifying-your-game.md +50 -1
- package/skills/incanto-web-integration.md +1 -0
- package/templates-app/beacon-isle-3d/index.html +3 -3
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/index.html +3 -3
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/index.html +3 -3
- package/templates-app/village-quest-3d/package.json +1 -1
package/bin/incanto-check.mjs
CHANGED
|
@@ -58,6 +58,61 @@ function collectScenes(entry) {
|
|
|
58
58
|
return out;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Local art the project does not contain.
|
|
63
|
+
*
|
|
64
|
+
* A scene asset pointing at a file nobody copied loads fine, validates fine and
|
|
65
|
+
* draws NOTHING — the failure exists only in a browser, in `assetErrors()`,
|
|
66
|
+
* which needs a running game and someone to look at it. This command has the
|
|
67
|
+
* scene's path and runs after every edit, and the file is either there or it is
|
|
68
|
+
* not. A WARNING, not an error: a url can legitimately be produced at runtime,
|
|
69
|
+
* and refusing to load a scene over a guess would be worse than the bug.
|
|
70
|
+
*/
|
|
71
|
+
function missingArt(file, json) {
|
|
72
|
+
const assets = json && typeof json === 'object' ? json.assets : null;
|
|
73
|
+
if (!assets || typeof assets !== 'object') return [];
|
|
74
|
+
const sceneDir = dirname(file);
|
|
75
|
+
const root = projectRoot(sceneDir);
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const [key, decl] of Object.entries(assets)) {
|
|
78
|
+
const url = decl && typeof decl === 'object' ? decl.url : null;
|
|
79
|
+
if (typeof url !== 'string' || url === '') continue;
|
|
80
|
+
// Remote and inline are not this command's business to guess about.
|
|
81
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('//')) continue;
|
|
82
|
+
const rel = url.replace(/^\//, '');
|
|
83
|
+
const candidates = [
|
|
84
|
+
join(root, 'public', rel),
|
|
85
|
+
join(root, rel),
|
|
86
|
+
join(sceneDir, rel),
|
|
87
|
+
join(sceneDir, '..', rel),
|
|
88
|
+
];
|
|
89
|
+
if (candidates.some((p) => existsSync(p))) continue;
|
|
90
|
+
out.push(
|
|
91
|
+
`$${key} → ${url} is not in the project ` +
|
|
92
|
+
`(looked in ${relativeish(root, join(root, 'public'))}, ${relativeish(root, root)}` +
|
|
93
|
+
`, and beside the scene). It will draw nothing.`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Nearest ancestor with a package.json, else the scene's own directory. */
|
|
100
|
+
function projectRoot(from) {
|
|
101
|
+
let dir = resolve(from);
|
|
102
|
+
for (let i = 0; i < 8; i++) {
|
|
103
|
+
if (existsSync(join(dir, 'package.json'))) return dir;
|
|
104
|
+
const up = dirname(dir);
|
|
105
|
+
if (up === dir) break;
|
|
106
|
+
dir = up;
|
|
107
|
+
}
|
|
108
|
+
return resolve(from);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function relativeish(root, p) {
|
|
112
|
+
const r = p.slice(root.length).replace(/^[\\/]/, '');
|
|
113
|
+
return r === '' ? './' : `${r}/`;
|
|
114
|
+
}
|
|
115
|
+
|
|
61
116
|
const roots = args.files.length > 0 ? args.files : ['.'];
|
|
62
117
|
for (const r of roots) {
|
|
63
118
|
if (!existsSync(resolve(r))) {
|
|
@@ -84,7 +139,7 @@ const results = files.map((file) => {
|
|
|
84
139
|
strictBehaviors: args.strict,
|
|
85
140
|
resolveScene: (p) => JSON.parse(readFileSync(resolve(dirname(file), p), 'utf-8')),
|
|
86
141
|
});
|
|
87
|
-
if (res.ok) return { file, ok: true, warnings: auditScene(json) };
|
|
142
|
+
if (res.ok) return { file, ok: true, warnings: [...auditScene(json), ...missingArt(file, json)] };
|
|
88
143
|
return {
|
|
89
144
|
file,
|
|
90
145
|
ok: false,
|
package/dist/2d.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { At as Node, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-CyQoSu4n.js";
|
|
2
2
|
import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DAvWQeld.js";
|
|
3
3
|
import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-DhI1jFW_.js";
|
|
5
5
|
import { n as AnimationEntry } from "./sprite-animation-CMr6f1K2.js";
|
|
6
|
-
import { t as ParticleSim } from "./particle-sim-
|
|
6
|
+
import { r as ParticleView, t as ParticleSim } from "./particle-sim-C5OfBbmU.js";
|
|
7
7
|
import { Group, Mesh, Object3D, Scene, Texture } from "three";
|
|
8
8
|
import * as RapierNs from "@dimforge/rapier2d-compat";
|
|
9
9
|
|
|
@@ -304,7 +304,21 @@ interface CreateGame2DOptions {
|
|
|
304
304
|
* false disables. They overlay `touchContainer` (default: the canvas's
|
|
305
305
|
* parent element — give it position: relative).
|
|
306
306
|
*/
|
|
307
|
+
/**
|
|
308
|
+
* Attach pointer input (mouse, finger or pen) to the canvas: positions for
|
|
309
|
+
* `input.pointerPosition()`, buttons for `input.mousePressed()`.
|
|
310
|
+
* `{ lockOnClick: true }` captures the cursor — rare in 2D, so it is off.
|
|
311
|
+
*/
|
|
312
|
+
pointer?: boolean | {
|
|
313
|
+
lockOnClick?: boolean;
|
|
314
|
+
};
|
|
307
315
|
touch?: "auto" | boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Leave the browser's touch gestures (scroll/zoom/pull-to-refresh) on the
|
|
318
|
+
* canvas. Default false: the GAME owns them, or a drag on a phone scrolls
|
|
319
|
+
* the page instead of playing.
|
|
320
|
+
*/
|
|
321
|
+
pageGestures?: boolean;
|
|
308
322
|
touchContainer?: HTMLElement;
|
|
309
323
|
/** @internal Test seam — replaces `document` for the touch overlay. */
|
|
310
324
|
_touchDoc?: {
|
|
@@ -344,10 +358,32 @@ interface CreateGame2DOptions {
|
|
|
344
358
|
_scheduler?: Scheduler;
|
|
345
359
|
}
|
|
346
360
|
/** What createGame needs from a renderer (stats is optional for test stubs). */
|
|
361
|
+
/** What a renderer must do for the engine. The test seam supplies this much. */
|
|
347
362
|
interface GameRenderer {
|
|
348
363
|
dispose(): void;
|
|
349
364
|
stats?(): RendererStats;
|
|
350
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* What a GAME can ask its renderer for.
|
|
368
|
+
*
|
|
369
|
+
* The two coordinate conversions live here rather than only on `Renderer2D`,
|
|
370
|
+
* because `game.renderer` is what a consumer holds: a tap needs screen→world
|
|
371
|
+
* and a pinned DOM element needs world→screen, both are documented in the
|
|
372
|
+
* skills, and neither typechecked through the narrow interface. Found by
|
|
373
|
+
* following my own documentation in a fresh project.
|
|
374
|
+
*/
|
|
375
|
+
interface Game2DRenderer extends GameRenderer {
|
|
376
|
+
/** Canvas px → world px, through the design viewport and the camera. */
|
|
377
|
+
worldFromScreen(sx: number, sy: number): {
|
|
378
|
+
x: number;
|
|
379
|
+
y: number;
|
|
380
|
+
};
|
|
381
|
+
/** World px → canvas px (pin DOM to a node). */
|
|
382
|
+
screenFromWorld(wx: number, wy: number): {
|
|
383
|
+
x: number;
|
|
384
|
+
y: number;
|
|
385
|
+
};
|
|
386
|
+
}
|
|
351
387
|
interface Game2D {
|
|
352
388
|
engine: Engine;
|
|
353
389
|
scene: Scene$1;
|
|
@@ -356,13 +392,25 @@ interface Game2D {
|
|
|
356
392
|
* A running tree has moved; the editor gets what was written down.
|
|
357
393
|
*/
|
|
358
394
|
sourceJson: SceneJson;
|
|
359
|
-
renderer:
|
|
395
|
+
renderer: Game2DRenderer;
|
|
360
396
|
physics: Physics2D | null;
|
|
361
397
|
/**
|
|
362
398
|
* The node under a screen pixel, or null. The raycast the renderer already
|
|
363
399
|
* does — reachable now without holding the renderer.
|
|
364
400
|
*/
|
|
365
401
|
pick(x: number, y: number): Node | null;
|
|
402
|
+
/**
|
|
403
|
+
* Assets that did not arrive — a texture that 404'd, a sound that cannot be
|
|
404
|
+
* played — with the ref and the reason.
|
|
405
|
+
*
|
|
406
|
+
* The verify loop names this as one of its four signals, and 2D never had it:
|
|
407
|
+
* a 2D game could not ask the question at all.
|
|
408
|
+
*/
|
|
409
|
+
assetErrors(): Array<{
|
|
410
|
+
ref: string;
|
|
411
|
+
url: string;
|
|
412
|
+
error: string;
|
|
413
|
+
}>;
|
|
366
414
|
/** Engine + renderer perf counters in one read (fps/nodes/triangles/…). */
|
|
367
415
|
stats(): GameStats;
|
|
368
416
|
/**
|
|
@@ -469,6 +517,16 @@ declare class AnimatedSprite2D extends Sprite2D {
|
|
|
469
517
|
stop(): void;
|
|
470
518
|
override onReady(): void;
|
|
471
519
|
override update(dt: number): void;
|
|
520
|
+
/** Sheets already reported, so a bad grid says so ONCE, not every frame. */
|
|
521
|
+
private gridChecked;
|
|
522
|
+
/**
|
|
523
|
+
* Tell the author their grid does not fit, the first time it is drawn.
|
|
524
|
+
*
|
|
525
|
+
* Both halves of this were silent: a frame size that does not divide the
|
|
526
|
+
* sheet slices every row further off centre, and an animation naming a frame
|
|
527
|
+
* past the end of the grid draws whatever is at the wrong end of the image.
|
|
528
|
+
*/
|
|
529
|
+
private checkGrid;
|
|
472
530
|
protected override resolveTexture(assets: AssetStore2D | null): ResolvedSpriteTexture | null;
|
|
473
531
|
}
|
|
474
532
|
//#endregion
|
|
@@ -651,6 +709,18 @@ declare class Particles2D extends Node2D {
|
|
|
651
709
|
static override readonly props: PropSchema;
|
|
652
710
|
preset: string;
|
|
653
711
|
emitting: boolean;
|
|
712
|
+
/**
|
|
713
|
+
* Where a particle LIVES once it is born.
|
|
714
|
+
*
|
|
715
|
+
* `false` (default) — the emitter's local space: the plume moves with the
|
|
716
|
+
* node, which is what a torch on a moving platform wants.
|
|
717
|
+
*
|
|
718
|
+
* `true` — the world: a particle keeps the place it was born, so dust is left
|
|
719
|
+
* BEHIND a running player instead of glued to it, and moving a one-shot to
|
|
720
|
+
* the next explosion (the documented `p.position = …; p.replay()` recipe)
|
|
721
|
+
* stops dragging the previous one across the level.
|
|
722
|
+
*/
|
|
723
|
+
worldSpace: boolean;
|
|
654
724
|
rate: number;
|
|
655
725
|
burst: number;
|
|
656
726
|
lifetime: number[];
|
|
@@ -680,9 +750,30 @@ declare class Particles2D extends Node2D {
|
|
|
680
750
|
private finishedEmitted;
|
|
681
751
|
/** @internal Lazily applies the preset + builds the deterministic sim. */
|
|
682
752
|
_ensureSim(): ParticleSim;
|
|
753
|
+
/** Particles alive this frame — an emitter that is running, told from one
|
|
754
|
+
* that is not. `framing()` says where it IS; this says whether it is going. */
|
|
755
|
+
get aliveCount(): number;
|
|
756
|
+
/** A snapshot of the live particles — positions are in whichever space
|
|
757
|
+
* `worldSpace` selects, relative to the emitter. */
|
|
758
|
+
particles(): ParticleView[];
|
|
759
|
+
/** The emitter's world position last frame, for world-space counter-motion. */
|
|
760
|
+
private lastWorld;
|
|
761
|
+
/** Last frame's `emitting`, so turning one ON is a reportable event. */
|
|
762
|
+
private wasEmitting;
|
|
683
763
|
override update(dt: number): void;
|
|
764
|
+
/**
|
|
765
|
+
* Undo the emitter's own motion on everything already alive.
|
|
766
|
+
*
|
|
767
|
+
* Ancestor-summed like the physics helpers, so it follows a moving PARENT
|
|
768
|
+
* (dust under a player) as well as the node's own position.
|
|
769
|
+
*/
|
|
770
|
+
private holdWorldSpace;
|
|
771
|
+
/** Tell the engine an effect fired — the visual half of the audio record. */
|
|
772
|
+
private report;
|
|
684
773
|
/** Restart a one-shot (re-burst + allow finished to fire again). */
|
|
685
774
|
replay(): void;
|
|
775
|
+
/** `replay()` asked for this burst, so `emitting: false` does not hold it. */
|
|
776
|
+
private armedByReplay;
|
|
686
777
|
private mesh;
|
|
687
778
|
/** Parsed `paletteColors`, reused; rebuilt only when the hex list changes. */
|
|
688
779
|
private paletteCache;
|
package/dist/2d.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
-
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-
|
|
3
|
-
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-
|
|
4
|
-
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-
|
|
2
|
+
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-BRt6XKmP.js";
|
|
3
|
+
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-en63AEZO.js";
|
|
4
|
+
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-CfWAggJ1.js";
|
|
5
5
|
//#region src/2d/library-sprite.ts
|
|
6
6
|
/**
|
|
7
7
|
* What a `CharacterController2D`/`3D` will ask a skin to play, and the clip in
|
package/dist/3d.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { At as Node, D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-CyQoSu4n.js";
|
|
2
2
|
import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DAvWQeld.js";
|
|
3
3
|
import { i as SceneJson$1, s as JsonObject } from "./schema-CFeioQRE.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
5
|
-
import { t as ParticleSim } from "./particle-sim-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-DhI1jFW_.js";
|
|
5
|
+
import { r as ParticleView, t as ParticleSim } from "./particle-sim-C5OfBbmU.js";
|
|
6
6
|
import { a as GridCell, c as diffText, d as frameText, i as FrameStatsOptions, l as frameSignature, n as FrameSignature, o as SIGNATURE_GRID, r as FrameStats, s as diffSignatures, t as FrameDiff, u as frameStats } from "./frame-report-DZ70IY26.js";
|
|
7
|
-
import { n as PathGrid, s as SpatialPose } from "./pathfinding-
|
|
7
|
+
import { n as PathGrid, s as SpatialPose } from "./pathfinding-CXGCpRQe.js";
|
|
8
8
|
import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
|
|
9
9
|
import { VRM } from "@pixiv/three-vrm";
|
|
10
10
|
import { Sky } from "three/examples/jsm/objects/Sky.js";
|
|
@@ -61,6 +61,15 @@ declare class TextureCache3D {
|
|
|
61
61
|
*/
|
|
62
62
|
acquireOwn(url: string, spec?: TextureSpec): Texture | null;
|
|
63
63
|
/**
|
|
64
|
+
* File a failure this store did not load itself.
|
|
65
|
+
*
|
|
66
|
+
* `Tree3D` keeps its own cache on purpose (it decodes off-thread and its
|
|
67
|
+
* page-session lifetime is load-bearing for the editor), which left its bark
|
|
68
|
+
* and leaf textures outside the one place `assetErrors()` reads. A 404'd leaf
|
|
69
|
+
* texture is a forest of bare branches and no message anywhere.
|
|
70
|
+
*/
|
|
71
|
+
noteError(url: string, error: unknown): void;
|
|
72
|
+
/**
|
|
64
73
|
* What 404'd, by URL — reported raw, never by cache key, because an agent
|
|
65
74
|
* greps this against the URL it wrote.
|
|
66
75
|
*/
|
|
@@ -563,6 +572,12 @@ interface CreateGame3DOptions {
|
|
|
563
572
|
* parent element — give it position: relative).
|
|
564
573
|
*/
|
|
565
574
|
touch?: "auto" | boolean;
|
|
575
|
+
/**
|
|
576
|
+
* Leave the browser's touch gestures (scroll/zoom/pull-to-refresh) on the
|
|
577
|
+
* canvas. Default false: the GAME owns them, or a drag on a phone scrolls
|
|
578
|
+
* the page instead of playing.
|
|
579
|
+
*/
|
|
580
|
+
pageGestures?: boolean;
|
|
566
581
|
touchContainer?: HTMLElement;
|
|
567
582
|
/** @internal Test seam — replaces `document` for the touch overlay. */
|
|
568
583
|
_touchDoc?: {
|
|
@@ -1853,6 +1868,15 @@ declare class LoftMesh3D extends Node3D {
|
|
|
1853
1868
|
private geometryKey;
|
|
1854
1869
|
protected override _createObject3D(): Object3D;
|
|
1855
1870
|
override _syncObject3D(): void;
|
|
1871
|
+
/**
|
|
1872
|
+
* Hand the GPU back.
|
|
1873
|
+
*
|
|
1874
|
+
* Every other node that builds geometry disposes it here; these four did not,
|
|
1875
|
+
* so a scene swap left their buffers and materials resident and a game with
|
|
1876
|
+
* level transitions climbed until the tab died — with `stats().geometries` the
|
|
1877
|
+
* only witness, and only if someone was watching it.
|
|
1878
|
+
*/
|
|
1879
|
+
override free(): void;
|
|
1856
1880
|
}
|
|
1857
1881
|
//#endregion
|
|
1858
1882
|
//#region src/3d/nodes/model-instance-3d.d.ts
|
|
@@ -2024,6 +2048,18 @@ declare class Particles3D extends Node3D {
|
|
|
2024
2048
|
static override readonly props: PropSchema;
|
|
2025
2049
|
preset: string;
|
|
2026
2050
|
emitting: boolean;
|
|
2051
|
+
/**
|
|
2052
|
+
* Where a particle LIVES once it is born.
|
|
2053
|
+
*
|
|
2054
|
+
* `false` (default) — the emitter's local space: the plume moves with the
|
|
2055
|
+
* node, which is what a torch on a moving platform wants.
|
|
2056
|
+
*
|
|
2057
|
+
* `true` — the world: a particle keeps the place it was born, so dust is left
|
|
2058
|
+
* BEHIND a running player instead of glued to it, and moving a one-shot to
|
|
2059
|
+
* the next explosion (the documented `p.position = …; p.replay()` recipe)
|
|
2060
|
+
* stops dragging the previous one across the level.
|
|
2061
|
+
*/
|
|
2062
|
+
worldSpace: boolean;
|
|
2027
2063
|
rate: number;
|
|
2028
2064
|
burst: number;
|
|
2029
2065
|
lifetime: number[];
|
|
@@ -2059,9 +2095,30 @@ declare class Particles3D extends Node3D {
|
|
|
2059
2095
|
private finishedEmitted;
|
|
2060
2096
|
/** @internal */
|
|
2061
2097
|
_ensureSim(): ParticleSim;
|
|
2098
|
+
/** Particles alive this frame — an emitter that is running, told from one
|
|
2099
|
+
* that is not. `framing()` says where it IS; this says whether it is going. */
|
|
2100
|
+
get aliveCount(): number;
|
|
2101
|
+
/** A snapshot of the live particles — positions are in whichever space
|
|
2102
|
+
* `worldSpace` selects, relative to the emitter. */
|
|
2103
|
+
particles(): ParticleView[];
|
|
2104
|
+
/** The emitter's world position last frame, for world-space counter-motion. */
|
|
2105
|
+
private lastWorld;
|
|
2106
|
+
/** Last frame's `emitting`, so turning one ON is a reportable event. */
|
|
2107
|
+
private wasEmitting;
|
|
2062
2108
|
override update(dt: number): void;
|
|
2109
|
+
/**
|
|
2110
|
+
* Undo the emitter's own motion on everything already alive.
|
|
2111
|
+
*
|
|
2112
|
+
* Ancestor-summed like the physics helpers, so it follows a moving PARENT
|
|
2113
|
+
* (dust under a player) as well as the node's own position.
|
|
2114
|
+
*/
|
|
2115
|
+
private holdWorldSpace;
|
|
2116
|
+
/** Tell the engine an effect fired — the visual half of the audio record. */
|
|
2117
|
+
private report;
|
|
2063
2118
|
/** Restart a one-shot (re-burst + allow finished to fire again). */
|
|
2064
2119
|
replay(): void;
|
|
2120
|
+
/** `replay()` asked for this burst, so `emitting: false` does not hold it. */
|
|
2121
|
+
private armedByReplay;
|
|
2065
2122
|
private points;
|
|
2066
2123
|
private positions;
|
|
2067
2124
|
private colors;
|
|
@@ -2074,6 +2131,15 @@ declare class Particles3D extends Node3D {
|
|
|
2074
2131
|
* uses the colorStart→colorEnd ramp. */
|
|
2075
2132
|
private refreshPalette;
|
|
2076
2133
|
private syncParticles;
|
|
2134
|
+
/**
|
|
2135
|
+
* Hand the GPU back.
|
|
2136
|
+
*
|
|
2137
|
+
* Every other node that builds geometry disposes it here; these four did not,
|
|
2138
|
+
* so a scene swap left their buffers and materials resident and a game with
|
|
2139
|
+
* level transitions climbed until the tab died — with `stats().geometries` the
|
|
2140
|
+
* only witness, and only if someone was watching it.
|
|
2141
|
+
*/
|
|
2142
|
+
override free(): void;
|
|
2077
2143
|
}
|
|
2078
2144
|
//#endregion
|
|
2079
2145
|
//#region src/3d/terrain/heightmap.d.ts
|
|
@@ -2750,10 +2816,30 @@ declare class Trail3D extends Node3D {
|
|
|
2750
2816
|
private mesh;
|
|
2751
2817
|
private lastColor;
|
|
2752
2818
|
protected override _createObject3D(): Object3D;
|
|
2819
|
+
/** Last frame's `emitting`, so laying ribbon is a reportable event. */
|
|
2820
|
+
private wasEmitting;
|
|
2753
2821
|
override update(dt: number): void;
|
|
2754
2822
|
_onRender3D(ctx: RenderContext3D): void;
|
|
2755
|
-
/**
|
|
2823
|
+
/**
|
|
2824
|
+
* How many points the ribbon is made of.
|
|
2825
|
+
*
|
|
2826
|
+
* ZERO with no renderer, and that is not a bug: the ribbon is laid in the
|
|
2827
|
+
* render sync, because each point needs the node's real world transform (a
|
|
2828
|
+
* sword arc is a ROTATING parent, which an ancestor position sum cannot see).
|
|
2829
|
+
* Assert it from a browser check; read a headless 0 as "nothing rendered"
|
|
2830
|
+
* rather than "my trail is broken", and use the `trail` effect record for the
|
|
2831
|
+
* wiring question.
|
|
2832
|
+
*/
|
|
2756
2833
|
get pointCount(): number;
|
|
2834
|
+
/**
|
|
2835
|
+
* Hand the GPU back.
|
|
2836
|
+
*
|
|
2837
|
+
* Every other node that builds geometry disposes it here; these four did not,
|
|
2838
|
+
* so a scene swap left their buffers and materials resident and a game with
|
|
2839
|
+
* level transitions climbed until the tab died — with `stats().geometries` the
|
|
2840
|
+
* only witness, and only if someone was watching it.
|
|
2841
|
+
*/
|
|
2842
|
+
override free(): void;
|
|
2757
2843
|
}
|
|
2758
2844
|
//#endregion
|
|
2759
2845
|
//#region src/3d/vegetation/tree-blueprint.d.ts
|
|
@@ -2853,7 +2939,17 @@ declare class Tree3D extends Node3D {
|
|
|
2853
2939
|
/** @internal Every grown variant (medium/high tiers; empty for 'simple'). */
|
|
2854
2940
|
_variantMeshes(): TreeVariant[];
|
|
2855
2941
|
override update(dt: number): void;
|
|
2856
|
-
|
|
2942
|
+
/** The scene's asset store, so a 404'd bark or leaf reaches assetErrors(). */
|
|
2943
|
+
private assets;
|
|
2944
|
+
override _syncObject3D(alpha?: number, assets?: AssetStore3D | null): void;
|
|
2945
|
+
/**
|
|
2946
|
+
* File a texture failure where the ladder reads it.
|
|
2947
|
+
*
|
|
2948
|
+
* This node keeps its own cache on purpose, and that left its textures
|
|
2949
|
+
* outside the one place `assetErrors()` looks — so a leaf URL that 404s was a
|
|
2950
|
+
* forest of bare branches with no message anywhere.
|
|
2951
|
+
*/
|
|
2952
|
+
private noteTextureError;
|
|
2857
2953
|
/** Re-grow only when a grove-shaping prop changed (the JSON IS the grove). */
|
|
2858
2954
|
private rebuildIfNeeded;
|
|
2859
2955
|
/** Resolve the drape target + cache the grove's world position for `bedY`. */
|
|
@@ -2924,6 +3020,15 @@ declare class VoxelGrid3D extends Node3D {
|
|
|
2924
3020
|
blocks(): VoxelBlock[];
|
|
2925
3021
|
protected override _createObject3D(): Object3D;
|
|
2926
3022
|
override update(): void;
|
|
3023
|
+
/**
|
|
3024
|
+
* Hand the GPU back.
|
|
3025
|
+
*
|
|
3026
|
+
* Every other node that builds geometry disposes it here; these four did not,
|
|
3027
|
+
* so a scene swap left their buffers and materials resident and a game with
|
|
3028
|
+
* level transitions climbed until the tab died — with `stats().geometries` the
|
|
3029
|
+
* only witness, and only if someone was watching it.
|
|
3030
|
+
*/
|
|
3031
|
+
override free(): void;
|
|
2927
3032
|
}
|
|
2928
3033
|
//#endregion
|
|
2929
3034
|
//#region src/3d/water/interaction.d.ts
|
package/dist/3d.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { F as CharacterBody3D, H as WATER_MAX_RIPPLES, I as PhysicsBody3D, L as RigidBody3D, M as WATER_CUTOUT_MAX, N as WaterCutout3D, P as Area3D, R as StaticBody3D, j as Water3D, z as Node3D } from "./gameplay-
|
|
2
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-
|
|
3
|
-
import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-
|
|
1
|
+
import { F as CharacterBody3D, H as WATER_MAX_RIPPLES, I as PhysicsBody3D, L as RigidBody3D, M as WATER_CUTOUT_MAX, N as WaterCutout3D, P as Area3D, R as StaticBody3D, j as Water3D, z as Node3D } from "./gameplay-CZ2yq37J.js";
|
|
2
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-BQ_QsIBY.js";
|
|
3
|
+
import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-Czzp6ZuE.js";
|
|
4
4
|
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-njybhZon.js";
|
|
5
5
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
6
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
6
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-Bes-GIuR.js";
|
|
7
7
|
//#region src/3d/model-verdict.ts
|
|
8
8
|
/** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
|
|
9
9
|
const MIXAMO = /^mixamorig[:_]?/i;
|
|
@@ -50,6 +50,10 @@ const BODY = {
|
|
|
50
50
|
radius: .34,
|
|
51
51
|
height: 1
|
|
52
52
|
};
|
|
53
|
+
/** Three decimals — enough for millimetres, and no float dust in pasted JSON. */
|
|
54
|
+
function round3(n) {
|
|
55
|
+
return Math.round(n * 1e3) / 1e3;
|
|
56
|
+
}
|
|
53
57
|
/**
|
|
54
58
|
* A found character, as a thing that walks.
|
|
55
59
|
*
|
|
@@ -122,10 +126,10 @@ function characterJson(target) {
|
|
|
122
126
|
type: "ModelInstance3D",
|
|
123
127
|
props: {
|
|
124
128
|
model: `$${target.key}`,
|
|
125
|
-
targetHeight: BODY.height + 2 * BODY.radius,
|
|
129
|
+
targetHeight: round3(BODY.height + 2 * BODY.radius),
|
|
126
130
|
position: [
|
|
127
131
|
0,
|
|
128
|
-
-(BODY.height / 2 + BODY.radius),
|
|
132
|
+
round3(-(BODY.height / 2 + BODY.radius)),
|
|
129
133
|
0
|
|
130
134
|
],
|
|
131
135
|
castShadow: true
|