incanto 0.29.0 → 0.31.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-editor.mjs +101 -28
- package/dist/2d.d.ts +28 -6
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +81 -7
- package/dist/3d.js +4 -4
- package/dist/{audit-C6rMyict.js → audit-C4kmDK0o.js} +16 -0
- package/dist/{behavior-BAc0erXF.d.ts → behavior-D_jMpFh8.d.ts} +117 -55
- package/dist/{create-game-CNKXGfpr.js → create-game-DqOjMBUS.js} +61 -48
- package/dist/{create-game-CbuLWorm.js → create-game-z5XaB1p5.js} +27 -15
- package/dist/debug-draw-BM3DsvtT.js +18 -0
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +8 -3
- package/dist/{duplicate-BgtFrFo4.js → duplicate-KRPtUtzl.js} +1 -1
- package/dist/{editor-switch-B0wB_DSr.d.ts → editor-switch-BJb-CWfA.d.ts} +12 -1
- package/dist/editor.js +1346 -1231
- package/dist/{register-C44aSduO.js → environment-presets--DigHNg4.js} +42 -11
- package/dist/{gameplay-L05WgWd1.js → gameplay-BftxM_It.js} +14 -5
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +6 -6
- package/dist/{loader-B242FF6N.d.ts → loader-BYBrqTxP.d.ts} +1 -1
- package/dist/{loader-BZqOKfI2.js → loader-BlaRQGaA.js} +482 -6
- package/dist/net.d.ts +1 -1
- package/dist/net.js +3 -3
- package/dist/{pathfinding-BwD974Ss.d.ts → pathfinding-BwhqPD3i.d.ts} +1 -1
- package/dist/{physics-2d-CCVTrKOd.js → physics-2d-D9wquBvK.js} +30 -4
- package/dist/{physics-3d-BZZLtwJu.js → physics-3d-CnPygVGo.js} +41 -5
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-MelqEdza.js → register-CUY284Is.js} +3 -3
- package/dist/{register-BTg0EM7s.js → register-Dzkd6-os.js} +56 -380
- package/dist/{register-DWcWq4QG.js → register-tkR_8tWg.js} +4 -4
- package/dist/{registry-BVJ2HbCn.js → registry-CJdGpT2V.js} +6 -2
- package/dist/{editor-switch-CAKlJMIY.js → teardown-ByzfDPyu.js} +83 -4
- package/dist/test.d.ts +2 -7
- package/dist/test.js +43 -14
- package/dist/vite.d.ts +87 -1
- package/dist/vite.js +262 -3
- package/editor/assets/{agent8-DEVkEa3d.js → agent8-o27_Y1xN.js} +1 -1
- package/editor/assets/{debug-zGAtpDF0.js → debug-DfcWX3uW.js} +3 -2
- package/editor/assets/index-C9fb5QcT.js +10696 -0
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/skills/incanto-editor.md +61 -8
- package/skills/incanto-physics-and-input.md +15 -0
- package/skills/incanto-verifying-your-game.md +68 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/vite.config.ts +7 -0
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/vite.config.ts +7 -0
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/vite.config.ts +7 -0
- package/dist/debug-draw-CZmOYjL2.js +0 -13
- package/editor/assets/index-Bx4UtWYY.js +0 -10586
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
import { a as Rng, c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-CcoWb32N.js";
|
|
2
2
|
|
|
3
|
+
//#region src/core/signal.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Minimal typed observer used for every engine event (Godot signal semantics).
|
|
6
|
+
*
|
|
7
|
+
* Emission is snapshot-based: listeners added during an emit do not fire in that
|
|
8
|
+
* emit, and listeners removed during an emit are skipped.
|
|
9
|
+
*/
|
|
10
|
+
type SignalListener<Args extends unknown[]> = (...args: Args) => void;
|
|
11
|
+
declare class Signal<Args extends unknown[] = unknown[]> {
|
|
12
|
+
private connections;
|
|
13
|
+
/** Connect a listener. Returns a disposer. Connecting the same fn twice is a no-op. */
|
|
14
|
+
connect(fn: SignalListener<Args>, opts?: {
|
|
15
|
+
once?: boolean;
|
|
16
|
+
}): () => void;
|
|
17
|
+
disconnect(fn: SignalListener<Args>): void;
|
|
18
|
+
disconnectAll(): void;
|
|
19
|
+
emit(...args: Args): void;
|
|
20
|
+
get connectionCount(): number;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/core/log.d.ts
|
|
24
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
25
|
+
interface LogEntry {
|
|
26
|
+
/** Monotonic per-manager sequence number (1-based). */
|
|
27
|
+
readonly seq: number;
|
|
28
|
+
/** Wall-clock-ish timestamp (performance.now when available) — diagnostics only. */
|
|
29
|
+
readonly timeMs: number;
|
|
30
|
+
readonly level: LogLevel;
|
|
31
|
+
/** The raw logged values, untouched — consumers format. */
|
|
32
|
+
readonly parts: readonly unknown[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The engine's log channel (`engine.log`, `this.log` in a Behavior): a ring
|
|
36
|
+
* buffer plus a live `added` signal, so debug overlays and headless test
|
|
37
|
+
* harnesses can tail game logs without scraping the browser console.
|
|
38
|
+
*/
|
|
39
|
+
declare class LogManager {
|
|
40
|
+
/** Fires once per entry, after it is buffered. */
|
|
41
|
+
readonly added: Signal<[LogEntry]>;
|
|
42
|
+
private readonly buffer;
|
|
43
|
+
private readonly capacity;
|
|
44
|
+
private seq;
|
|
45
|
+
constructor(capacity?: number);
|
|
46
|
+
debug(...parts: unknown[]): void;
|
|
47
|
+
info(...parts: unknown[]): void;
|
|
48
|
+
warn(...parts: unknown[]): void;
|
|
49
|
+
error(...parts: unknown[]): void;
|
|
50
|
+
/** Buffered entries, oldest first (capped at capacity). */
|
|
51
|
+
entries(): readonly LogEntry[];
|
|
52
|
+
/** Empty the buffer. The sequence keeps counting (entries stay unique). */
|
|
53
|
+
clear(): void;
|
|
54
|
+
private push;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
3
57
|
//#region src/core/scene-tree.d.ts
|
|
4
58
|
/**
|
|
5
59
|
* Owns a node tree and drives its lifecycle:
|
|
@@ -63,26 +117,6 @@ declare class SceneTree {
|
|
|
63
117
|
private flushFreeQueue;
|
|
64
118
|
}
|
|
65
119
|
//#endregion
|
|
66
|
-
//#region src/core/signal.d.ts
|
|
67
|
-
/**
|
|
68
|
-
* Minimal typed observer used for every engine event (Godot signal semantics).
|
|
69
|
-
*
|
|
70
|
-
* Emission is snapshot-based: listeners added during an emit do not fire in that
|
|
71
|
-
* emit, and listeners removed during an emit are skipped.
|
|
72
|
-
*/
|
|
73
|
-
type SignalListener<Args extends unknown[]> = (...args: Args) => void;
|
|
74
|
-
declare class Signal<Args extends unknown[] = unknown[]> {
|
|
75
|
-
private connections;
|
|
76
|
-
/** Connect a listener. Returns a disposer. Connecting the same fn twice is a no-op. */
|
|
77
|
-
connect(fn: SignalListener<Args>, opts?: {
|
|
78
|
-
once?: boolean;
|
|
79
|
-
}): () => void;
|
|
80
|
-
disconnect(fn: SignalListener<Args>): void;
|
|
81
|
-
disconnectAll(): void;
|
|
82
|
-
emit(...args: Args): void;
|
|
83
|
-
get connectionCount(): number;
|
|
84
|
-
}
|
|
85
|
-
//#endregion
|
|
86
120
|
//#region src/core/node.d.ts
|
|
87
121
|
/** Lifecycle hooks a SceneTree drives. Wired in scene-tree.ts. */
|
|
88
122
|
interface NodeLifecycle {
|
|
@@ -186,6 +220,42 @@ declare class Node implements NodeLifecycle {
|
|
|
186
220
|
_propagateUpdate(dt: number): void;
|
|
187
221
|
/** @internal */
|
|
188
222
|
_propagateFixedUpdate(dt: number): void;
|
|
223
|
+
/**
|
|
224
|
+
* Report an engine-level problem about THIS node.
|
|
225
|
+
*
|
|
226
|
+
* Goes to `engine.log` (what the debug overlay, `runScript()` and any agent
|
|
227
|
+
* tool read) as well as the console. A `console.warn` alone is invisible to
|
|
228
|
+
* every channel except a human with devtools open.
|
|
229
|
+
*/
|
|
230
|
+
protected diagnose(level: "warn" | "error", ...parts: unknown[]): void;
|
|
231
|
+
/**
|
|
232
|
+
* This node threw and is being skipped. Its CHILDREN still run.
|
|
233
|
+
*
|
|
234
|
+
* The alternative is what used to happen: the exception escaped into the rAF
|
|
235
|
+
* callback, the loop was never rescheduled, and the game froze — permanently,
|
|
236
|
+
* silently, with `stats().running` still reporting true. In a vibe-coded
|
|
237
|
+
* project the least-tested code in the repo is a behavior's `update`, so this
|
|
238
|
+
* is not an edge case; it is Tuesday.
|
|
239
|
+
*
|
|
240
|
+
* Set it back to false to try the node again (the debug overlay's "resume").
|
|
241
|
+
*/
|
|
242
|
+
errored: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* This node's SCRIPT threw and is being skipped — the node itself still runs.
|
|
245
|
+
*
|
|
246
|
+
* A behavior is your code; the node is the engine's. A typo in the first must
|
|
247
|
+
* not switch off the second, or breaking a sword script stops the character
|
|
248
|
+
* from walking.
|
|
249
|
+
*/
|
|
250
|
+
behaviorErrored: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* Report ONCE and stop running this node's own update.
|
|
253
|
+
*
|
|
254
|
+
* Once, because a behavior that throws throws every frame: sixty identical
|
|
255
|
+
* stack traces a second buries the one line that matters and costs more than
|
|
256
|
+
* the game did.
|
|
257
|
+
*/
|
|
258
|
+
private _quarantine;
|
|
189
259
|
onEnterTree(): void;
|
|
190
260
|
onReady(): void;
|
|
191
261
|
onExitTree(): void;
|
|
@@ -646,40 +716,6 @@ declare class InputMap {
|
|
|
646
716
|
private button;
|
|
647
717
|
}
|
|
648
718
|
//#endregion
|
|
649
|
-
//#region src/core/log.d.ts
|
|
650
|
-
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
651
|
-
interface LogEntry {
|
|
652
|
-
/** Monotonic per-manager sequence number (1-based). */
|
|
653
|
-
readonly seq: number;
|
|
654
|
-
/** Wall-clock-ish timestamp (performance.now when available) — diagnostics only. */
|
|
655
|
-
readonly timeMs: number;
|
|
656
|
-
readonly level: LogLevel;
|
|
657
|
-
/** The raw logged values, untouched — consumers format. */
|
|
658
|
-
readonly parts: readonly unknown[];
|
|
659
|
-
}
|
|
660
|
-
/**
|
|
661
|
-
* The engine's log channel (`engine.log`, `this.log` in a Behavior): a ring
|
|
662
|
-
* buffer plus a live `added` signal, so debug overlays and headless test
|
|
663
|
-
* harnesses can tail game logs without scraping the browser console.
|
|
664
|
-
*/
|
|
665
|
-
declare class LogManager {
|
|
666
|
-
/** Fires once per entry, after it is buffered. */
|
|
667
|
-
readonly added: Signal<[LogEntry]>;
|
|
668
|
-
private readonly buffer;
|
|
669
|
-
private readonly capacity;
|
|
670
|
-
private seq;
|
|
671
|
-
constructor(capacity?: number);
|
|
672
|
-
debug(...parts: unknown[]): void;
|
|
673
|
-
info(...parts: unknown[]): void;
|
|
674
|
-
warn(...parts: unknown[]): void;
|
|
675
|
-
error(...parts: unknown[]): void;
|
|
676
|
-
/** Buffered entries, oldest first (capped at capacity). */
|
|
677
|
-
entries(): readonly LogEntry[];
|
|
678
|
-
/** Empty the buffer. The sequence keeps counting (entries stay unique). */
|
|
679
|
-
clear(): void;
|
|
680
|
-
private push;
|
|
681
|
-
}
|
|
682
|
-
//#endregion
|
|
683
719
|
//#region src/core/scene/scene.d.ts
|
|
684
720
|
/**
|
|
685
721
|
* A loaded, live scene: the node tree plus everything needed to round-trip
|
|
@@ -733,6 +769,13 @@ interface EngineStats {
|
|
|
733
769
|
nodes: number;
|
|
734
770
|
/** Whether the loop is scheduled (start() without stop()/dispose()). */
|
|
735
771
|
running: boolean;
|
|
772
|
+
/**
|
|
773
|
+
* Errors swallowed to keep the game alive since start: nodes that quarantined
|
|
774
|
+
* themselves plus frames that threw. Non-zero means something IS broken and
|
|
775
|
+
* `engine.log` says what — a green-looking game with `errors: 7` is the case
|
|
776
|
+
* this counter exists for.
|
|
777
|
+
*/
|
|
778
|
+
errors: number;
|
|
736
779
|
}
|
|
737
780
|
/** GPU-side counters from `renderer.stats()` — the LAST rendered frame. */
|
|
738
781
|
interface RendererStats {
|
|
@@ -838,6 +881,25 @@ declare class Engine {
|
|
|
838
881
|
/** Replace the active scene. The previous scene's root is freed. */
|
|
839
882
|
setScene(scene: Scene): void;
|
|
840
883
|
start(): void;
|
|
884
|
+
/**
|
|
885
|
+
* A frame threw somewhere outside a single node (a renderer, physics, a
|
|
886
|
+
* signal handler). Report the first one and count the rest: a broken frame
|
|
887
|
+
* repeats sixty times a second, and sixty identical traces a second is how
|
|
888
|
+
* you lose the first one.
|
|
889
|
+
*/
|
|
890
|
+
private reportFrameError;
|
|
891
|
+
/** @internal A node quarantined itself; count it for `stats().errors`. */
|
|
892
|
+
_nodeErrored(_node: unknown): void;
|
|
893
|
+
private errorCount;
|
|
894
|
+
private lastFrameError;
|
|
895
|
+
/**
|
|
896
|
+
* Every node with something quarantined — its own update, its script, or
|
|
897
|
+
* both — so a tool can list them and put them back. Walks on demand; there is
|
|
898
|
+
* no per-frame bookkeeping for this.
|
|
899
|
+
*/
|
|
900
|
+
erroredNodes(): Node[];
|
|
901
|
+
/** Un-skip every quarantined node — the "try again" after you fix the code. */
|
|
902
|
+
resumeErroredNodes(): number;
|
|
841
903
|
stop(): void;
|
|
842
904
|
/**
|
|
843
905
|
* Live performance counters, queryable at ANY time. fps/frameMs come from a
|
|
@@ -973,4 +1035,4 @@ declare function registeredBehaviors(): string[];
|
|
|
973
1035
|
/** Test isolation helper. */
|
|
974
1036
|
declare function clearBehaviors(): void;
|
|
975
1037
|
//#endregion
|
|
976
|
-
export {
|
|
1038
|
+
export { LogEntry as $, VoicePreset as A, SfxParams as B, RendererStats as C, SfxPlayOptions as D, SfxEngine as E, Vec3 as F, MusicManager as G, SynthOptions as H, spatialGain as I, AudioBuses as J, MusicTrack as K, spatialPan as L, ROLLOFF_MODELS as M, RolloffModel as N, isAudioContextAvailable as O, SpatialParams as P, SceneTree as Q, SFX_PRESETS as R, GameStats as S, InputMap as T, synthSfx as U, SfxWave as V, MusicBackend as W, Node as X, BusName as Y, NodeLifecycle as Z, registeredTypes as _, registerBehavior as a, Scheduler as b, PropDef as c, createNode as d, LogLevel as et, getNodeSchema as f, registerNode as g, mergeStaticSignals as h, getBehavior as i, Listener as j, Voice as k, PropSchema as l, getNodeType as m, BehaviorCtor as n, Signal as nt, registeredBehaviors as o, getNodeSignals as p, PlayMusicOptions as q, clearBehaviors as r, SignalListener as rt, NodeCtor as s, Behavior as t, LogManager as tt, clearRegistry as u, Engine as v, Scene as w, EngineStats as x, EngineOptions as y, SFX_PRESET_NAMES as z };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { l as AudioPlayer, u as Engine } from "./register-
|
|
2
|
+
import { m as diagnose, n as loadScene, y as registerBehavior } from "./loader-BlaRQGaA.js";
|
|
3
|
+
import { l as AudioPlayer, u as Engine } from "./register-Dzkd6-os.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
|
|
6
|
-
import {
|
|
7
|
-
import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-
|
|
8
|
-
import { t as debugSources } from "./debug-draw-
|
|
9
|
-
import {
|
|
10
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
6
|
+
import { a as poseFromRenderer, i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-ByzfDPyu.js";
|
|
7
|
+
import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-BftxM_It.js";
|
|
8
|
+
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
9
|
+
import { E as Camera3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets--DigHNg4.js";
|
|
10
|
+
import { n as enablePhysics3D } from "./physics-3d-CnPygVGo.js";
|
|
11
11
|
import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
12
12
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
13
13
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -25,15 +25,47 @@ import { Sky } from "three/examples/jsm/objects/Sky.js";
|
|
|
25
25
|
* @pixiv/three-vrm (VRM 0.x facing fixed via rotateVRM0).
|
|
26
26
|
*/
|
|
27
27
|
var AssetStore3D = class {
|
|
28
|
+
engine;
|
|
28
29
|
models = /* @__PURE__ */ new Map();
|
|
29
30
|
animations = /* @__PURE__ */ new Map();
|
|
30
31
|
modelKeys = /* @__PURE__ */ new Map();
|
|
31
32
|
animationKeys = /* @__PURE__ */ new Map();
|
|
32
33
|
loader;
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* `engine` is optional only so a bare store still constructs in tests. Give it
|
|
36
|
+
* one and every load failure lands in `engine.log` — where the debug overlay,
|
|
37
|
+
* `runScript()` and any agent tool can see it. Without it a 404'd GLB was a
|
|
38
|
+
* console line and an invisible model.
|
|
39
|
+
*/
|
|
40
|
+
constructor(engine = null) {
|
|
41
|
+
this.engine = engine;
|
|
34
42
|
this.loader = new GLTFLoader();
|
|
35
43
|
this.loader.register((parser) => new VRMLoaderPlugin(parser));
|
|
36
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Every asset that failed, with the reason — the answer to "why is my model
|
|
47
|
+
* not there". Empty is the healthy case.
|
|
48
|
+
*/
|
|
49
|
+
errors() {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const [ref, url] of this.modelKeys) {
|
|
52
|
+
const entry = this.models.get(url);
|
|
53
|
+
if (entry?.error) out.push({
|
|
54
|
+
ref,
|
|
55
|
+
url,
|
|
56
|
+
error: String(entry.error)
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
for (const [ref, decl] of this.animationKeys) {
|
|
60
|
+
const entry = this.animations.get(decl.url);
|
|
61
|
+
if (entry?.error) out.push({
|
|
62
|
+
ref,
|
|
63
|
+
url: decl.url,
|
|
64
|
+
error: String(entry.error)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
37
69
|
/** Map a scene's `assets` header. */
|
|
38
70
|
load(assets) {
|
|
39
71
|
for (const [key, def] of Object.entries(assets)) {
|
|
@@ -83,7 +115,7 @@ var AssetStore3D = class {
|
|
|
83
115
|
}, void 0, (error) => {
|
|
84
116
|
entry.status = "error";
|
|
85
117
|
entry.error = error instanceof Error ? error.message : String(error);
|
|
86
|
-
|
|
118
|
+
diagnose(this.engine, "error", `incanto: failed to load model '${url}':`, error);
|
|
87
119
|
});
|
|
88
120
|
return entry;
|
|
89
121
|
}
|
|
@@ -103,11 +135,11 @@ var AssetStore3D = class {
|
|
|
103
135
|
entry.clips = gltf.animations ?? [];
|
|
104
136
|
entry.scene = gltf.scene;
|
|
105
137
|
entry.status = "ready";
|
|
106
|
-
if (entry.clips.length === 0)
|
|
138
|
+
if (entry.clips.length === 0) diagnose(this.engine, "warn", `incanto: animation asset '${def.url}' contains no clips`);
|
|
107
139
|
}, void 0, (error) => {
|
|
108
140
|
entry.status = "error";
|
|
109
141
|
entry.error = error instanceof Error ? error.message : String(error);
|
|
110
|
-
|
|
142
|
+
diagnose(this.engine, "error", `incanto: failed to load animation '${def.url}':`, error);
|
|
111
143
|
});
|
|
112
144
|
return entry;
|
|
113
145
|
}
|
|
@@ -884,37 +916,6 @@ function lerp(a, b, t) {
|
|
|
884
916
|
return a + (b - a) * t;
|
|
885
917
|
}
|
|
886
918
|
//#endregion
|
|
887
|
-
//#region src/3d/environment-presets.ts
|
|
888
|
-
/**
|
|
889
|
-
* drei-compatible environment presets: each name maps to a 1k HDRI (the exact
|
|
890
|
-
* Poly Haven CC0 files @react-three/drei ships), so `preset="sunset"` lights the
|
|
891
|
-
* same here. Served from the agent8 CDN (the only sanctioned external host, same
|
|
892
|
-
* as the terrain splat) — set `environment.hdri` to override with your own URL.
|
|
893
|
-
*/
|
|
894
|
-
const CDN = "https://agent8-games.verse8.io/assets/3D/default/textures/hdri";
|
|
895
|
-
const ENVIRONMENT_PRESETS = {
|
|
896
|
-
apartment: "lebombo_1k.hdr",
|
|
897
|
-
city: "potsdamer_platz_1k.hdr",
|
|
898
|
-
dawn: "kiara_1_dawn_1k.hdr",
|
|
899
|
-
forest: "forest_slope_1k.hdr",
|
|
900
|
-
lobby: "st_fagans_interior_1k.hdr",
|
|
901
|
-
night: "dikhololo_night_1k.hdr",
|
|
902
|
-
park: "rooitou_park_1k.hdr",
|
|
903
|
-
studio: "studio_small_03_1k.hdr",
|
|
904
|
-
sunset: "venice_sunset_1k.hdr",
|
|
905
|
-
warehouse: "empty_warehouse_01_1k.hdr"
|
|
906
|
-
};
|
|
907
|
-
/** Resolve `environment.preset` / `environment.hdri` to the HDR url (or null). */
|
|
908
|
-
function resolveEnvironmentHdri(env) {
|
|
909
|
-
if (typeof env.hdri === "string" && env.hdri !== "") return env.hdri;
|
|
910
|
-
if (typeof env.preset === "string") {
|
|
911
|
-
const file = ENVIRONMENT_PRESETS[env.preset];
|
|
912
|
-
if (!file) throw new Error(`Unknown environment preset '${env.preset}'. Available: ${Object.keys(ENVIRONMENT_PRESETS).join(", ")}.`);
|
|
913
|
-
return `${CDN}/${file}`;
|
|
914
|
-
}
|
|
915
|
-
return null;
|
|
916
|
-
}
|
|
917
|
-
//#endregion
|
|
918
919
|
//#region src/3d/environment-3d.ts
|
|
919
920
|
/** Shadow ortho half-extent when the env header forces a light to cast and the
|
|
920
921
|
* light node configured nothing itself. One static box around the origin — no
|
|
@@ -1499,6 +1500,11 @@ var Renderer3D = class {
|
|
|
1499
1500
|
engine;
|
|
1500
1501
|
disconnect;
|
|
1501
1502
|
canvas;
|
|
1503
|
+
/**
|
|
1504
|
+
* The model/animation store. Public so a game (and an agent's tool) can ask
|
|
1505
|
+
* `renderer.assets.errors()` why a model is not there — it used to be private,
|
|
1506
|
+
* so a 404'd GLB was unanswerable from outside.
|
|
1507
|
+
*/
|
|
1502
1508
|
assets;
|
|
1503
1509
|
ownsAssets;
|
|
1504
1510
|
loadedAssetScenes = /* @__PURE__ */ new WeakSet();
|
|
@@ -1545,7 +1551,7 @@ var Renderer3D = class {
|
|
|
1545
1551
|
this.canvas = opts.canvas;
|
|
1546
1552
|
this.engine = opts.engine;
|
|
1547
1553
|
this.ownsAssets = !opts.assets;
|
|
1548
|
-
this.assets = opts.assets ?? new AssetStore3D();
|
|
1554
|
+
this.assets = opts.assets ?? new AssetStore3D(this.engine);
|
|
1549
1555
|
const rendering = resolveRendering(opts.engine.scene?.environment, {
|
|
1550
1556
|
antialias: true,
|
|
1551
1557
|
pixelRatio: Math.min(globalThis.devicePixelRatio ?? 1, 2)
|
|
@@ -1601,7 +1607,7 @@ var Renderer3D = class {
|
|
|
1601
1607
|
}
|
|
1602
1608
|
syncDebugLines() {
|
|
1603
1609
|
let vertices = null;
|
|
1604
|
-
for (const source of debugSources("3d")) {
|
|
1610
|
+
for (const source of debugSources("3d", this.engine)) {
|
|
1605
1611
|
vertices = source.debugLines();
|
|
1606
1612
|
if (vertices) break;
|
|
1607
1613
|
}
|
|
@@ -2250,10 +2256,14 @@ async function createGame3D(opts) {
|
|
|
2250
2256
|
} catch {}
|
|
2251
2257
|
await report(1, "ready");
|
|
2252
2258
|
function disposeGame() {
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2259
|
+
teardown([
|
|
2260
|
+
physics ? ["physics", () => physics?.dispose()] : null,
|
|
2261
|
+
["app cleanups", () => {
|
|
2262
|
+
for (const cleanup of cleanups) cleanup();
|
|
2263
|
+
}],
|
|
2264
|
+
["engine", () => engine.dispose()],
|
|
2265
|
+
["renderer", () => renderer.dispose()]
|
|
2266
|
+
]);
|
|
2257
2267
|
}
|
|
2258
2268
|
return {
|
|
2259
2269
|
engine,
|
|
@@ -2261,6 +2271,9 @@ async function createGame3D(opts) {
|
|
|
2261
2271
|
sourceJson,
|
|
2262
2272
|
renderer,
|
|
2263
2273
|
physics,
|
|
2274
|
+
assetErrors() {
|
|
2275
|
+
return renderer.assets?.errors() ?? [];
|
|
2276
|
+
},
|
|
2264
2277
|
stats() {
|
|
2265
2278
|
return {
|
|
2266
2279
|
triangles: 0,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { l as AudioPlayer, u as Engine } from "./register-
|
|
2
|
+
import { m as diagnose, n as loadScene, o as computeViewport, s as resolveViewport, y as registerBehavior } from "./loader-BlaRQGaA.js";
|
|
3
|
+
import { l as AudioPlayer, u as Engine } from "./register-Dzkd6-os.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
|
|
6
|
-
import { n as
|
|
7
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
8
|
-
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-
|
|
9
|
-
import { t as debugSources } from "./debug-draw-
|
|
10
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
6
|
+
import { i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-ByzfDPyu.js";
|
|
7
|
+
import { n as registerGameplayBehaviors } from "./gameplay-BftxM_It.js";
|
|
8
|
+
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-tkR_8tWg.js";
|
|
9
|
+
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
10
|
+
import { n as enablePhysics2D } from "./physics-2d-D9wquBvK.js";
|
|
11
11
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
12
12
|
//#region src/2d/assets.ts
|
|
13
13
|
/**
|
|
@@ -17,9 +17,16 @@ import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSe
|
|
|
17
17
|
* `"$key"`. The texture loader is injectable so tests run headless.
|
|
18
18
|
*/
|
|
19
19
|
var AssetStore2D = class {
|
|
20
|
+
engine;
|
|
20
21
|
entries = /* @__PURE__ */ new Map();
|
|
21
22
|
loader;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* `engine` is optional so a bare store still constructs in tests. Given one,
|
|
25
|
+
* a texture that fails to load lands in `engine.log` — where the overlay and
|
|
26
|
+
* `runScript()` can see it — instead of only in the browser console.
|
|
27
|
+
*/
|
|
28
|
+
constructor(loader, engine = null) {
|
|
29
|
+
this.engine = engine;
|
|
23
30
|
this.loader = loader ?? ((url, callbacks) => new TextureLoader().load(url, () => callbacks?.onLoad?.(), void 0, (err) => callbacks?.onError?.(err)));
|
|
24
31
|
}
|
|
25
32
|
/** Load (or extend with) a scene's `assets` declarations. Hard-validates each entry. */
|
|
@@ -43,7 +50,7 @@ var AssetStore2D = class {
|
|
|
43
50
|
},
|
|
44
51
|
onError: (err) => {
|
|
45
52
|
state.status = "error";
|
|
46
|
-
|
|
53
|
+
diagnose(this.engine, "error", `[incanto] failed to load texture '${key}' (${decl.url}):`, err);
|
|
47
54
|
}
|
|
48
55
|
});
|
|
49
56
|
if (previous && previous.texture !== texture) previous.texture.dispose();
|
|
@@ -251,6 +258,7 @@ var Renderer2D = class {
|
|
|
251
258
|
worldCam = new OrthographicCamera(-1, 1, 1, -1, -1e3, 1e3);
|
|
252
259
|
uiCam = new OrthographicCamera(-1, 1, 1, -1, -1e3, 1e3);
|
|
253
260
|
engine;
|
|
261
|
+
/** The texture store. Public so `renderer.assets.status(key)` is reachable. */
|
|
254
262
|
assets;
|
|
255
263
|
loadedAssetScenes = /* @__PURE__ */ new WeakSet();
|
|
256
264
|
disconnect;
|
|
@@ -258,7 +266,7 @@ var Renderer2D = class {
|
|
|
258
266
|
constructor(opts) {
|
|
259
267
|
this.canvas = opts.canvas;
|
|
260
268
|
this.engine = opts.engine;
|
|
261
|
-
this.assets = opts.assets ?? new AssetStore2D();
|
|
269
|
+
this.assets = opts.assets ?? new AssetStore2D(void 0, this.engine);
|
|
262
270
|
const rendering = resolveRendering(opts.engine.scene?.environment, {
|
|
263
271
|
antialias: true,
|
|
264
272
|
pixelRatio: 1
|
|
@@ -310,7 +318,7 @@ var Renderer2D = class {
|
|
|
310
318
|
}
|
|
311
319
|
syncDebugLines() {
|
|
312
320
|
let vertices = null;
|
|
313
|
-
for (const source of debugSources("2d")) {
|
|
321
|
+
for (const source of debugSources("2d", this.engine)) {
|
|
314
322
|
vertices = source.debugLines();
|
|
315
323
|
if (vertices) break;
|
|
316
324
|
}
|
|
@@ -603,10 +611,14 @@ async function createGame2D(opts) {
|
|
|
603
611
|
}
|
|
604
612
|
engine.start();
|
|
605
613
|
function disposeGame() {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
614
|
+
teardown([
|
|
615
|
+
physics ? ["physics", () => physics?.dispose()] : null,
|
|
616
|
+
["app cleanups", () => {
|
|
617
|
+
for (const cleanup of cleanups) cleanup();
|
|
618
|
+
}],
|
|
619
|
+
["engine", () => engine.dispose()],
|
|
620
|
+
["renderer", () => renderer.dispose()]
|
|
621
|
+
]);
|
|
610
622
|
}
|
|
611
623
|
return {
|
|
612
624
|
engine,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/core/debug-draw.ts
|
|
2
|
+
const sources = /* @__PURE__ */ new Set();
|
|
3
|
+
/** @internal physics runtimes self-register on enable. */
|
|
4
|
+
function registerDebugSource(source) {
|
|
5
|
+
sources.add(source);
|
|
6
|
+
return () => sources.delete(source);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @internal renderers pull their OWN engine's sources for their dimension.
|
|
10
|
+
*
|
|
11
|
+
* `engine` is optional only so a caller with nothing to scope by still works;
|
|
12
|
+
* every renderer passes one, and should.
|
|
13
|
+
*/
|
|
14
|
+
function debugSources(dimension, engine) {
|
|
15
|
+
return [...sources].filter((s) => s.dimension === dimension && (engine === void 0 || s.engine === engine));
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { registerDebugSource as n, debugSources as t };
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as RendererStats,
|
|
1
|
+
import { C as RendererStats, et as LogLevel, v as Engine } from "./behavior-D_jMpFh8.js";
|
|
2
2
|
|
|
3
3
|
//#region src/debug/panel.d.ts
|
|
4
4
|
/** Minimal document surface the overlay needs (injectable for tests). */
|
package/dist/debug.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
2
|
-
import { s as mergeStaticProps } from "./registry-
|
|
3
|
-
import { t as debugSources } from "./debug-draw-
|
|
2
|
+
import { s as mergeStaticProps } from "./registry-CJdGpT2V.js";
|
|
3
|
+
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
4
4
|
//#region src/debug/panel.ts
|
|
5
5
|
/** Keep a panel rect on screen and above the minimum usable size. */
|
|
6
6
|
function clampPanelRect(x, y, w, h, viewW, viewH, minW = 180, minH = 120) {
|
|
@@ -913,8 +913,13 @@ function compactCount(n) {
|
|
|
913
913
|
}
|
|
914
914
|
function stringify(part) {
|
|
915
915
|
if (typeof part === "string") return part;
|
|
916
|
+
if (part instanceof Error) {
|
|
917
|
+
const first = part.stack?.split("\n")[1]?.trim();
|
|
918
|
+
return `${part.name}: ${part.message}${first ? ` (${first})` : ""}`;
|
|
919
|
+
}
|
|
916
920
|
try {
|
|
917
|
-
|
|
921
|
+
const text = JSON.stringify(part);
|
|
922
|
+
return text === "{}" || text === void 0 ? String(part) : text;
|
|
918
923
|
} catch {
|
|
919
924
|
return String(part);
|
|
920
925
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { s as JsonObject } from "./schema-CcoWb32N.js";
|
|
2
2
|
|
|
3
|
+
//#region src/core/diagnostics.d.ts
|
|
4
|
+
/** The minimum an engine has to look like to receive a diagnostic. */
|
|
5
|
+
interface DiagnosticSink {
|
|
6
|
+
log: {
|
|
7
|
+
warn(...parts: unknown[]): void;
|
|
8
|
+
error(...parts: unknown[]): void;
|
|
9
|
+
info(...parts: unknown[]): void;
|
|
10
|
+
debug(...parts: unknown[]): void;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
3
14
|
//#region src/core/editor-switch.d.ts
|
|
4
15
|
/** Where a camera is and what it looks at, in world space. */
|
|
5
16
|
interface CameraPose {
|
|
@@ -56,4 +67,4 @@ type LibrarySearch = (query: {
|
|
|
56
67
|
total?: number;
|
|
57
68
|
}>;
|
|
58
69
|
//#endregion
|
|
59
|
-
export { EditorSwitchOptions as t };
|
|
70
|
+
export { DiagnosticSink as n, EditorSwitchOptions as t };
|