incanto 0.69.0 → 0.71.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/_behaviors-loader.mjs +22 -0
- package/bin/_read-json.mjs +28 -0
- package/bin/incanto-assets.mjs +5 -4
- package/bin/incanto-check.mjs +58 -31
- package/bin/incanto-editor.mjs +128 -5
- package/bin/incanto-env.mjs +3 -2
- package/bin/incanto-feel.mjs +24 -13
- package/bin/incanto-frame.mjs +8 -1
- package/bin/incanto-multiplay.mjs +11 -9
- package/bin/incanto-new.mjs +105 -10
- package/bin/incanto-play.mjs +158 -16
- package/bin/incanto-playtest.mjs +66 -23
- package/bin/incanto-skills.mjs +14 -2
- package/bin/incanto-verify.mjs +121 -102
- package/bin/incanto.mjs +3 -2
- package/dist/2d.d.ts +296 -34
- package/dist/2d.js +4 -4
- package/dist/3d.d.ts +157 -9
- package/dist/3d.js +8 -8
- package/dist/{agent8-CvsfVskX.js → agent8-Cfmd3ar_.js} +61 -8
- package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-L8yccdMP.d.ts} +2 -2
- package/dist/{behavior-rm8vVzu_.d.ts → behavior-Dcz0fr1S.d.ts} +755 -46
- package/dist/{create-game-CwxEDlCm.js → create-game-CH4kt78v.js} +143 -60
- package/dist/{create-game-CvJ1wSRP.js → create-game-LCHBLfA4.js} +98 -48
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +2 -3
- package/dist/diagnostics-Cu85N3tL.d.ts +12 -0
- package/dist/{editor-switch-CnIOiyNJ.d.ts → editor-switch-CFU9mCec.d.ts} +22 -13
- package/dist/editor.js +1088 -882
- package/dist/env.d.ts +1 -1
- package/dist/env.js +5 -3
- package/dist/{environment-presets-BO-7XoFV.js → environment-presets-99BzP_L-.js} +298 -45
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-D1KixWK8.js → gameplay-CNULJvwh.js} +914 -214
- package/dist/gameplay.d.ts +254 -10
- package/dist/gameplay.js +2 -2
- package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
- package/dist/index.d.ts +179 -13
- package/dist/index.js +10 -12
- package/dist/json-CfTjpvW8.js +67 -0
- package/dist/{loader-DadV2QCT.d.ts → loader-8-IHvbKD.d.ts} +2 -2
- package/dist/net.d.ts +27 -3
- package/dist/net.js +2 -2
- package/dist/{noise-CGUMx44x.js → noise-D3nPpmFg.js} +1 -1
- package/dist/{physics-2d-CF5yyjbj.js → physics-2d-FhrXUc6B.js} +136 -11
- package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CFEGxBXZ.js} +104 -23
- package/dist/{teardown-CMqFVxO9.js → picking-DVo7fI13.js} +104 -13
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{register-DbVArsns.js → register-BYQCBySi.js} +429 -28
- package/dist/{register-mmfugpaQ.js → register-DuVdzxbq.js} +594 -831
- package/dist/{replay-BEHLDcQV.js → replay-DEvp3kyV.js} +224 -14
- package/dist/{replay-BQfkX4x7.d.ts → replay-F7IZHdFR.d.ts} +20 -3
- package/dist/{schema-B6ugCV1Q.d.ts → rng-Bb-IutXB.d.ts} +38 -21
- package/dist/{rng-DP-SR7eg.js → rng-CDOMybym.js} +22 -0
- package/dist/{loader-DZE7B07H.js → save-slots-Bvuh2p_r.js} +4619 -2318
- package/dist/{split-screen-Cg76MCV5.d.ts → split-screen-CIYf1zSf.d.ts} +36 -4
- package/dist/{split-screen-CauMwu6y.js → split-screen-eULetcg-.js} +159 -26
- package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
- package/dist/{src-CYEu-_S9.js → src-_jk0qLsS.js} +2 -17
- package/dist/test-CmN54kWv.js +4264 -0
- package/dist/test.d.ts +639 -30
- package/dist/test.js +3 -3
- package/dist/touch-BnCyPA0G.js +519 -0
- package/dist/vite.d.ts +20 -37
- package/dist/vite.js +177 -7
- package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
- package/editor/assets/agent8-yLIEYHbd.js +1 -0
- package/editor/assets/{debug-CMULinBW.js → debug-u31w_yhq.js} +2 -2
- package/editor/assets/index-DK9xMGpW.js +11046 -0
- package/editor/index.html +1 -1
- package/package.json +4 -14
- package/schemas/scene.schema.json +34 -3
- package/skills/incanto-3d-character.md +14 -1
- package/skills/incanto-3d-models.md +12 -0
- package/skills/incanto-assets.md +9 -1
- package/skills/incanto-audio.md +8 -2
- package/skills/incanto-behaviors-and-scripts.md +105 -7
- package/skills/incanto-building-2d-games.md +97 -10
- package/skills/incanto-building-3d-games.md +58 -4
- package/skills/incanto-editor.md +46 -7
- package/skills/incanto-environment.md +19 -1
- package/skills/incanto-game-feel.md +70 -0
- package/skills/incanto-gameplay-behaviors.md +172 -20
- package/skills/incanto-hud.md +142 -7
- package/skills/incanto-localization.md +13 -5
- package/skills/incanto-multiplayer.md +83 -3
- package/skills/incanto-node-reference.md +239 -59
- package/skills/incanto-performance.md +52 -0
- package/skills/incanto-physics-and-input.md +123 -24
- package/skills/incanto-playtesting.md +112 -2
- package/skills/incanto-save-slots.md +217 -7
- package/skills/incanto-scene-json-authoring.md +69 -12
- package/skills/incanto-verifying-your-game.md +207 -10
- package/skills/incanto-web-integration.md +28 -0
- package/skills/incanto-your-first-game.md +3 -1
- package/templates-app/beacon-isle-3d/generate-world.ts +77 -9
- package/templates-app/beacon-isle-3d/package.json +2 -2
- package/templates-app/beacon-isle-3d/src/behaviors.ts +22 -0
- package/templates-app/beacon-isle-3d/src/game.scene.json +143 -600
- package/templates-app/beacon-isle-3d/src/main.ts +11 -1
- package/templates-app/beacon-isle-3d/tsconfig.json +1 -1
- package/templates-app/beacon-isle-3d/verify.ts +3 -1
- package/templates-app/molehill-2d/.incanto/playtest/lost-seed1.json +4277 -0
- package/templates-app/molehill-2d/PROJECT/Context.md +58 -0
- package/templates-app/molehill-2d/PROJECT/Requirements.md +39 -0
- package/templates-app/molehill-2d/PROJECT/Status.md +27 -0
- package/templates-app/molehill-2d/PROJECT/Structure.md +48 -0
- package/templates-app/molehill-2d/docs/project-2d-rules.md +44 -0
- package/templates-app/molehill-2d/index.html +73 -0
- package/templates-app/molehill-2d/package.json +23 -0
- package/templates-app/molehill-2d/src/behaviors.ts +198 -0
- package/templates-app/molehill-2d/src/game.scene.json +1205 -0
- package/templates-app/molehill-2d/src/main.ts +41 -0
- package/templates-app/molehill-2d/tsconfig.json +13 -0
- package/templates-app/molehill-2d/verify.ts +247 -0
- package/templates-app/molehill-2d/vite.config.ts +12 -0
- package/templates-app/platformer-2d/package.json +2 -2
- package/templates-app/platformer-2d/src/game.scene.json +178 -986
- package/templates-app/platformer-2d/src/main.ts +11 -1
- package/templates-app/platformer-2d/tsconfig.json +1 -1
- package/templates-app/star-survivor/package.json +2 -2
- package/templates-app/star-survivor/src/game.scene.json +43 -216
- package/templates-app/star-survivor/src/main.ts +11 -1
- package/templates-app/star-survivor/tsconfig.json +1 -1
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/package.json +2 -2
- package/templates-app/tps-3d/src/behaviors.ts +19 -1
- package/templates-app/tps-3d/src/game.scene.json +66 -263
- package/templates-app/tps-3d/src/main.ts +13 -2
- package/templates-app/tps-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/.incanto/playtest/swapped-seed1.json +1735 -0
- package/templates-app/village-quest-3d/package.json +2 -2
- package/templates-app/village-quest-3d/src/behaviors.ts +42 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +68 -306
- package/templates-app/village-quest-3d/src/main.ts +11 -1
- package/templates-app/village-quest-3d/src/village.scene.json +202 -863
- package/templates-app/village-quest-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/verify.ts +14 -1
- package/dist/duplicate-Dj4L-5AA.js +0 -22
- package/dist/json-CwwhxQgb.js +0 -36
- package/dist/registry-CF70EArN.js +0 -212
- package/dist/rolldown-runtime-D7D4PA-g.js +0 -13
- package/dist/test-D6ISmuFE.js +0 -2383
- package/dist/touch-DEAmqGdf.js +0 -225
- package/editor/assets/agent8-BDvaZMQJ.js +0 -1
- package/editor/assets/index-CZIRr5EL.js +0 -10958
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { _ as AudioPlayer, v as Engine } from "./register-
|
|
1
|
+
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
+
import { D as computeViewport, O as resolveViewport, Y as diagnose, h as loadScene, ot as registerBehavior } from "./save-slots-Bvuh2p_r.js";
|
|
3
|
+
import { C as qualityRendering, _ as AudioPlayer, v as Engine } from "./register-DuVdzxbq.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
|
-
import { n as attachTouchControls } from "./touch-
|
|
6
|
-
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-
|
|
7
|
-
import { a as
|
|
8
|
-
import { o as frameStats } from "./frame-report-
|
|
9
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
10
|
-
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-
|
|
5
|
+
import { n as attachTouchControls } from "./touch-BnCyPA0G.js";
|
|
6
|
+
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-C8aDbGmR.js";
|
|
7
|
+
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, t as nodeFromHits, u as claimCanvasGestures } from "./picking-DVo7fI13.js";
|
|
8
|
+
import { o as frameStats } from "./frame-report-D-_7YF2G.js";
|
|
9
|
+
import { n as registerGameplayBehaviors } from "./gameplay-CNULJvwh.js";
|
|
10
|
+
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-BYQCBySi.js";
|
|
11
11
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
12
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
12
|
+
import { n as enablePhysics2D } from "./physics-2d-FhrXUc6B.js";
|
|
13
13
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
14
14
|
//#region src/2d/assets.ts
|
|
15
15
|
/**
|
|
@@ -101,6 +101,20 @@ var AssetStore2D = class {
|
|
|
101
101
|
getTexture(ref) {
|
|
102
102
|
return this.resolve(ref).texture;
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Hand the GPU back.
|
|
106
|
+
*
|
|
107
|
+
* `AssetStore3D` has had this since it was written and the 2D twin never got
|
|
108
|
+
* one, so a game that swapped scenes or unmounted kept every texture it had
|
|
109
|
+
* ever decoded. `Renderer2D.dispose` walked its scene graph and disposed
|
|
110
|
+
* `material.map` instead — which frees only what is CURRENTLY drawn (a sheet
|
|
111
|
+
* loaded and never used stayed resident), and disposes the STORE'S texture
|
|
112
|
+
* out from under a caller who injected their own store.
|
|
113
|
+
*/
|
|
114
|
+
dispose() {
|
|
115
|
+
for (const entry of this.entries.values()) entry.texture?.dispose();
|
|
116
|
+
this.entries.clear();
|
|
117
|
+
}
|
|
104
118
|
getSheet(ref) {
|
|
105
119
|
const entry = this.resolve(ref);
|
|
106
120
|
if (entry.type !== "spritesheet") throw new IncantoError("BAD_FORMAT", `Asset '${ref}' is a plain texture; a spritesheet (with frameWidth/frameHeight) is required here.`);
|
|
@@ -433,18 +447,32 @@ var Renderer2D = class {
|
|
|
433
447
|
engine;
|
|
434
448
|
/** The texture store. Public so `renderer.assets.status(key)` is reachable. */
|
|
435
449
|
assets;
|
|
450
|
+
ownsAssets;
|
|
436
451
|
loadedAssetScenes = /* @__PURE__ */ new WeakSet();
|
|
437
452
|
disconnect;
|
|
438
453
|
canvas;
|
|
439
454
|
constructor(opts) {
|
|
440
455
|
this.canvas = opts.canvas;
|
|
441
456
|
this.engine = opts.engine;
|
|
457
|
+
const cw = opts.canvas.clientWidth || opts.canvas.width || 1;
|
|
458
|
+
const ch = opts.canvas.clientHeight || opts.canvas.height || 1;
|
|
459
|
+
this.lastView = {
|
|
460
|
+
cx: cw / 2,
|
|
461
|
+
cy: ch / 2,
|
|
462
|
+
zoom: 1,
|
|
463
|
+
w: cw,
|
|
464
|
+
h: ch
|
|
465
|
+
};
|
|
442
466
|
this.assets = opts.assets ?? new AssetStore2D(void 0, this.engine);
|
|
467
|
+
this.ownsAssets = !opts.assets;
|
|
443
468
|
const rendering = resolveRendering(opts.engine.scene?.environment, {
|
|
444
469
|
antialias: true,
|
|
445
470
|
pixelRatio: 1,
|
|
446
471
|
preserveDrawingBuffer: false
|
|
447
472
|
}, globalThis.devicePixelRatio ?? 1, opts);
|
|
473
|
+
const tier = qualityRendering(opts.engine.settings.get("quality"));
|
|
474
|
+
rendering.antialias = rendering.antialias && tier.antialias;
|
|
475
|
+
rendering.pixelRatio = Math.min(rendering.pixelRatio, tier.pixelRatio);
|
|
448
476
|
this.webgl = withWebGLContext(() => new WebGLRenderer({
|
|
449
477
|
canvas: opts.canvas,
|
|
450
478
|
antialias: rendering.antialias,
|
|
@@ -452,6 +480,20 @@ var Renderer2D = class {
|
|
|
452
480
|
}));
|
|
453
481
|
this.webgl.info.autoReset = false;
|
|
454
482
|
this.engine.picker = (x, y) => this.pick(x, y);
|
|
483
|
+
this.engine.toWorld = (x, y) => {
|
|
484
|
+
if (!this.hasRendered) return null;
|
|
485
|
+
const w = this.worldFromScreen(x, y);
|
|
486
|
+
return [w.x, w.y];
|
|
487
|
+
};
|
|
488
|
+
this.engine.toScreen = (world) => {
|
|
489
|
+
if (!this.hasRendered) return null;
|
|
490
|
+
const s = this.screenFromWorld(world[0] ?? 0, world[1] ?? 0);
|
|
491
|
+
return {
|
|
492
|
+
x: s.x,
|
|
493
|
+
y: s.y,
|
|
494
|
+
behind: false
|
|
495
|
+
};
|
|
496
|
+
};
|
|
455
497
|
this.basePixelRatio = rendering.pixelRatio;
|
|
456
498
|
this.webgl.setPixelRatio(rendering.pixelRatio);
|
|
457
499
|
this.webgl.info.autoReset = false;
|
|
@@ -568,6 +610,7 @@ var Renderer2D = class {
|
|
|
568
610
|
h
|
|
569
611
|
};
|
|
570
612
|
this.lastViewport = view;
|
|
613
|
+
this.hasRendered = true;
|
|
571
614
|
if (view && (view.offsetX > .5 || view.offsetY > .5)) {
|
|
572
615
|
this.webgl.setScissorTest(false);
|
|
573
616
|
this.webgl.setViewport(0, 0, w, h);
|
|
@@ -595,13 +638,29 @@ var Renderer2D = class {
|
|
|
595
638
|
h: 1
|
|
596
639
|
};
|
|
597
640
|
lastViewport = null;
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
641
|
+
/**
|
|
642
|
+
* The view the LAST render used — and, before there has been one, the
|
|
643
|
+
* documented default: the whole canvas, centred, at zoom 1.
|
|
644
|
+
*
|
|
645
|
+
* It started as `{cx: 0, cy: 0, w: 1, h: 1}`, a one-pixel canvas nobody has,
|
|
646
|
+
* and `worldFromScreen` answered from it with a straight face. Measured in a
|
|
647
|
+
* browser on a 960x540 canvas with the camera at (160, 80), before the first
|
|
648
|
+
* frame: `toWorld(480, 270)` returned `[479.5, 269.5]` — the arithmetic of a
|
|
649
|
+
* 1x1 window, and a confident number rather than a refusal.
|
|
650
|
+
*/
|
|
651
|
+
lastView;
|
|
652
|
+
/**
|
|
653
|
+
* Has a frame been DRAWN?
|
|
654
|
+
*
|
|
655
|
+
* `Renderer3D` refuses every screen-space question until it has one
|
|
656
|
+
* (`if (!this.lastCamera) return null`, in `pick`, `rayFromScreen` and
|
|
657
|
+
* `worldFromScreen`); the flat renderer had no equivalent, so the engine-level
|
|
658
|
+
* `toWorld`/`toScreen` and `pick` answered from a view no frame had used. The
|
|
659
|
+
* hazard is real in exactly the place agents work: a background tab does not
|
|
660
|
+
* run rAF, so `await createGame2D(...)` there is followed by any number of
|
|
661
|
+
* questions with no frame behind them.
|
|
662
|
+
*/
|
|
663
|
+
hasRendered = false;
|
|
605
664
|
/** The world view used by the LAST render (center/zoom/canvas size). */
|
|
606
665
|
view() {
|
|
607
666
|
return { ...this.lastView };
|
|
@@ -630,11 +689,13 @@ var Renderer2D = class {
|
|
|
630
689
|
* Hits resolve through `userData.incantoNode` and prefer higher renderOrder.
|
|
631
690
|
*/
|
|
632
691
|
pick(sx, sy) {
|
|
692
|
+
if (!this.hasRendered) return null;
|
|
633
693
|
const { w, h } = this.lastView;
|
|
634
694
|
const ox = this.lastViewport?.offsetX ?? 0;
|
|
635
695
|
const oy = this.lastViewport?.offsetY ?? 0;
|
|
636
696
|
const cw = this.lastViewport?.contentW ?? w;
|
|
637
697
|
const ch = this.lastViewport?.contentH ?? h;
|
|
698
|
+
if (sx < ox || sx > ox + cw || sy < oy || sy > oy + ch) return null;
|
|
638
699
|
pickNdc.set((sx - ox) / cw * 2 - 1, -((sy - oy) / ch * 2 - 1));
|
|
639
700
|
const ui = this.hit(this.uiScene, this.uiCam);
|
|
640
701
|
if (ui) return ui;
|
|
@@ -642,20 +703,7 @@ var Renderer2D = class {
|
|
|
642
703
|
}
|
|
643
704
|
hit(scene, cam) {
|
|
644
705
|
raycaster.setFromCamera(pickNdc, cam);
|
|
645
|
-
|
|
646
|
-
let best = null;
|
|
647
|
-
for (const hit of hits) {
|
|
648
|
-
let obj = hit.object;
|
|
649
|
-
while (obj && !obj.userData.incantoNode) obj = obj.parent;
|
|
650
|
-
const node = obj?.userData.incantoNode;
|
|
651
|
-
if (!node) continue;
|
|
652
|
-
const order = hit.object.renderOrder ?? 0;
|
|
653
|
-
if (!best || order >= best.order) best = {
|
|
654
|
-
node,
|
|
655
|
-
order
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
return best?.node ?? null;
|
|
706
|
+
return nodeFromHits(raycaster.intersectObjects(scene.children, true), { byRenderOrder: true });
|
|
659
707
|
}
|
|
660
708
|
/** Does the UI pass draw this node (i.e. is it under a UILayer)? */
|
|
661
709
|
isUiNode(node) {
|
|
@@ -714,16 +762,16 @@ var Renderer2D = class {
|
|
|
714
762
|
}
|
|
715
763
|
dispose() {
|
|
716
764
|
if (this.engine.picker) this.engine.picker = null;
|
|
765
|
+
if (this.engine.toWorld) this.engine.toWorld = null;
|
|
766
|
+
if (this.engine.toScreen) this.engine.toScreen = null;
|
|
717
767
|
this.disconnect();
|
|
718
768
|
for (const scene of [this.worldScene, this.uiScene]) scene.traverse((obj) => {
|
|
719
769
|
const mesh = obj;
|
|
720
770
|
if (!mesh.isMesh) return;
|
|
721
771
|
const mats = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
722
|
-
for (const mat of mats)
|
|
723
|
-
mat?.map?.dispose();
|
|
724
|
-
mat?.dispose();
|
|
725
|
-
}
|
|
772
|
+
for (const mat of mats) mat?.dispose();
|
|
726
773
|
});
|
|
774
|
+
if (this.ownsAssets) this.assets.dispose();
|
|
727
775
|
this.webgl.dispose();
|
|
728
776
|
}
|
|
729
777
|
};
|
|
@@ -775,10 +823,18 @@ async function createGame2D(opts) {
|
|
|
775
823
|
const cleanups = [];
|
|
776
824
|
const keyboard = opts.keyboard ?? (typeof window !== "undefined" ? window : false);
|
|
777
825
|
if (keyboard) engine.input.attachKeyboard(keyboard);
|
|
778
|
-
|
|
826
|
+
let pointerAttached = false;
|
|
827
|
+
const attachPointerIfWanted = () => {
|
|
828
|
+
if (pointerAttached || opts.pointer === false) return;
|
|
829
|
+
const root = engine.scene?.root;
|
|
830
|
+
if (!root) return;
|
|
831
|
+
if (opts.pointer === void 0 && !wantsPointer(root)) return;
|
|
832
|
+
pointerAttached = true;
|
|
779
833
|
const lockOnClick = typeof opts.pointer === "object" ? opts.pointer.lockOnClick ?? false : false;
|
|
780
834
|
engine.input.attachPointer(opts.canvas, { lockOnClick });
|
|
781
|
-
}
|
|
835
|
+
};
|
|
836
|
+
attachPointerIfWanted();
|
|
837
|
+
cleanups.push(engine.sceneChanged.connect(() => attachPointerIfWanted()));
|
|
782
838
|
cleanups.push(wireAudioUnlock(engine, scene.root, opts.canvas));
|
|
783
839
|
cleanups.push(engine.settings.bindAudio(engine.audio));
|
|
784
840
|
cleanups.push(pauseWhenHidden(engine));
|
|
@@ -807,6 +863,7 @@ async function createGame2D(opts) {
|
|
|
807
863
|
canvas: opts.canvas,
|
|
808
864
|
engine,
|
|
809
865
|
...opts.pixelRatio !== void 0 ? { pixelRatio: opts.pixelRatio } : {},
|
|
866
|
+
...opts.preserveDrawingBuffer !== void 0 ? { preserveDrawingBuffer: opts.preserveDrawingBuffer } : {},
|
|
810
867
|
...opts.antialias !== void 0 ? { antialias: opts.antialias } : {}
|
|
811
868
|
});
|
|
812
869
|
cleanups.push(engine.settings.bindFrameCap((fps) => {
|
|
@@ -831,26 +888,15 @@ async function createGame2D(opts) {
|
|
|
831
888
|
requestAnimationFrame(tick);
|
|
832
889
|
};
|
|
833
890
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(tick);
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
break;
|
|
844
|
-
case "key":
|
|
845
|
-
engine.input.handleKey(step.code, step.down);
|
|
846
|
-
break;
|
|
847
|
-
case "pointer":
|
|
848
|
-
engine.input.handlePointerMove(step.dx, step.dy);
|
|
849
|
-
break;
|
|
850
|
-
case "step":
|
|
851
|
-
await new Promise((r) => setTimeout(r, step.ms));
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
891
|
+
const target = {
|
|
892
|
+
engine,
|
|
893
|
+
project: (x, y) => {
|
|
894
|
+
const at = renderer.screenFromWorld;
|
|
895
|
+
return at ? at.call(renderer, x, y) : null;
|
|
896
|
+
},
|
|
897
|
+
wait: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
898
|
+
};
|
|
899
|
+
for (const step of steps) await applyDriveStep(target, step);
|
|
854
900
|
watching = false;
|
|
855
901
|
return frames;
|
|
856
902
|
};
|
|
@@ -876,10 +922,11 @@ async function createGame2D(opts) {
|
|
|
876
922
|
if (!editorSwitch) return;
|
|
877
923
|
const open = editorSwitch.open ?? openBundledEditor;
|
|
878
924
|
const reboot = async (working) => {
|
|
879
|
-
await createGame2D({
|
|
925
|
+
const next = await createGame2D({
|
|
880
926
|
...opts,
|
|
881
927
|
scene: working
|
|
882
928
|
});
|
|
929
|
+
editorSwitch?.onReboot?.(next);
|
|
883
930
|
};
|
|
884
931
|
await crossFade(async () => {
|
|
885
932
|
disposeGame();
|
|
@@ -892,7 +939,7 @@ async function createGame2D(opts) {
|
|
|
892
939
|
...editorSwitch.library ? { library: editorSwitch.library === true ? devServerLibrary() : editorSwitch.library } : {}
|
|
893
940
|
});
|
|
894
941
|
} catch (error) {
|
|
895
|
-
|
|
942
|
+
diagnose(engine, "error", "[incanto] could not open the editor:", error);
|
|
896
943
|
await reboot(sourceJson);
|
|
897
944
|
}
|
|
898
945
|
}, "opening the editor…");
|
|
@@ -912,7 +959,22 @@ async function createGame2D(opts) {
|
|
|
912
959
|
}
|
|
913
960
|
}
|
|
914
961
|
engine.start();
|
|
962
|
+
/**
|
|
963
|
+
* Has this handle already been torn down?
|
|
964
|
+
*
|
|
965
|
+
* After one ✎→▶ editor round trip the handle `createGame*` returned is
|
|
966
|
+
* ORPHANED: `reboot()` builds a replacement and the app still holds the old
|
|
967
|
+
* one. Calling `game.openEditor()` on it then booted a THIRD game on top of
|
|
968
|
+
* the live one, and `game.dispose()` tore down a game that was already gone
|
|
969
|
+
* while leaving the live one running. A second `dispose()` also re-entered
|
|
970
|
+
* Rapier's already-nulled `world.free()` and printed an engine error.
|
|
971
|
+
*
|
|
972
|
+
* A stale handle does nothing rather than something destructive.
|
|
973
|
+
*/
|
|
974
|
+
let disposed = false;
|
|
915
975
|
function disposeGame() {
|
|
976
|
+
if (disposed) return;
|
|
977
|
+
disposed = true;
|
|
916
978
|
teardown([
|
|
917
979
|
["physics", () => physics?.dispose()],
|
|
918
980
|
["app cleanups", () => {
|
|
@@ -954,7 +1016,10 @@ async function createGame2D(opts) {
|
|
|
954
1016
|
...renderer.stats?.()
|
|
955
1017
|
};
|
|
956
1018
|
},
|
|
957
|
-
openEditor: editorSwitch ?
|
|
1019
|
+
openEditor: editorSwitch ? async () => {
|
|
1020
|
+
if (disposed) return;
|
|
1021
|
+
await editorAction.run();
|
|
1022
|
+
} : null,
|
|
958
1023
|
dispose: disposeGame
|
|
959
1024
|
};
|
|
960
1025
|
}
|
|
@@ -1013,5 +1078,23 @@ function wireAudioUnlock(engine, root, canvas) {
|
|
|
1013
1078
|
for (const s of sources) s.target.addEventListener?.(s.type, unlock, { passive: true });
|
|
1014
1079
|
return detachAll;
|
|
1015
1080
|
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Does this tree have anything the CURSOR drives?
|
|
1083
|
+
*
|
|
1084
|
+
* `physics: 'auto'` has always meant "on iff the tree needs it"; the pointer had
|
|
1085
|
+
* no such default, so a board of `Clickable`s booted without `pointer: true` did
|
|
1086
|
+
* nothing when clicked — and the skill that introduces the behaviour says it
|
|
1087
|
+
* "needs no code at all". This makes that true.
|
|
1088
|
+
*
|
|
1089
|
+
* Only `Clickable`, deliberately: a behaviour of your own that reads
|
|
1090
|
+
* `pointerPosition()` is invisible from here, and guessing wider would attach a
|
|
1091
|
+
* pointer to games that never asked (and, with `lockOnClick`, capture a cursor
|
|
1092
|
+
* nobody wanted).
|
|
1093
|
+
*/
|
|
1094
|
+
function wantsPointer(root) {
|
|
1095
|
+
if (root.behavior?.constructor.name === "Clickable") return true;
|
|
1096
|
+
for (const child of root.children) if (wantsPointer(child)) return true;
|
|
1097
|
+
return false;
|
|
1098
|
+
}
|
|
1016
1099
|
//#endregion
|
|
1017
1100
|
export { AssetStore2D as a, syncTree2D as i, create_game_exports as n, Renderer2D as r, createGame2D as t };
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { C as qualityRendering, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-
|
|
1
|
+
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
+
import { C as sunDirectionFromSky, Y as diagnose, b as horizonColorFromSky, h as loadScene, ot as registerBehavior, x as parseEnvironment3D } from "./save-slots-Bvuh2p_r.js";
|
|
3
|
+
import { C as qualityRendering, S as qualityEnvironment, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-DuVdzxbq.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
|
-
import { n as attachTouchControls } from "./touch-
|
|
6
|
-
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-
|
|
7
|
-
import { a as
|
|
8
|
-
import { o as frameStats } from "./frame-report-
|
|
9
|
-
import { J as createCausticsQuad, K as Node3D, U as PhysicsBody3D, n as registerGameplayBehaviors } from "./gameplay-
|
|
5
|
+
import { n as attachTouchControls } from "./touch-BnCyPA0G.js";
|
|
6
|
+
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-C8aDbGmR.js";
|
|
7
|
+
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, s as poseFromRenderer, t as nodeFromHits, u as claimCanvasGestures } from "./picking-DVo7fI13.js";
|
|
8
|
+
import { o as frameStats } from "./frame-report-D-_7YF2G.js";
|
|
9
|
+
import { J as createCausticsQuad, K as Node3D, U as PhysicsBody3D, n as registerGameplayBehaviors } from "./gameplay-CNULJvwh.js";
|
|
10
10
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
11
|
-
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-
|
|
12
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
13
|
-
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";
|
|
11
|
+
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-99BzP_L-.js";
|
|
12
|
+
import { n as enablePhysics3D } from "./physics-3d-CFEGxBXZ.js";
|
|
13
|
+
import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, LoadingManager, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
14
14
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
15
15
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
16
16
|
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
|
|
@@ -72,7 +72,12 @@ var AssetStore3D = class {
|
|
|
72
72
|
*/
|
|
73
73
|
constructor(engine = null) {
|
|
74
74
|
this.engine = engine;
|
|
75
|
-
|
|
75
|
+
const manager = new LoadingManager();
|
|
76
|
+
manager.onError = (url) => {
|
|
77
|
+
if (this.models.has(url) || this.animations.has(url)) return;
|
|
78
|
+
this.textures.noteError(url, "a model needs this texture and it did not load");
|
|
79
|
+
};
|
|
80
|
+
this.loader = new GLTFLoader(manager);
|
|
76
81
|
this.loader.register((parser) => new VRMLoaderPlugin(parser));
|
|
77
82
|
this.textures = new TextureCache3D({ diagnostics: engine ? { warn: (...parts) => diagnose(engine, "warn", ...parts) } : null });
|
|
78
83
|
}
|
|
@@ -1353,7 +1358,7 @@ function walk(node, parentObj, state) {
|
|
|
1353
1358
|
for (const child of node.children) walk(child, nextParent, state);
|
|
1354
1359
|
if (node instanceof Node3D) {
|
|
1355
1360
|
const obj = node._ensureObject3D();
|
|
1356
|
-
if (node.static && !state.ignoreStatic) {
|
|
1361
|
+
if (node.static && !state.ignoreStatic && node._staticReady(state.assets ?? null)) {
|
|
1357
1362
|
obj.userData.incantoStaticSynced = true;
|
|
1358
1363
|
obj.userData.incantoStatic = true;
|
|
1359
1364
|
warnStaticHazards(node);
|
|
@@ -1374,7 +1379,7 @@ function warnStaticHazards(root) {
|
|
|
1374
1379
|
for (const c of n.children) scan(c);
|
|
1375
1380
|
};
|
|
1376
1381
|
scan(root);
|
|
1377
|
-
if (hazards.length > 0)
|
|
1382
|
+
if (hazards.length > 0) diagnose(root.tree?.engine ?? null, "warn", `[incanto] static subtree '${root.name}' freezes animated/per-frame nodes: ${hazards.join(", ")} — they will stop updating. Unmark static or move them out.`);
|
|
1378
1383
|
}
|
|
1379
1384
|
function prune(obj, visited) {
|
|
1380
1385
|
const ch = obj.children;
|
|
@@ -1494,6 +1499,16 @@ var Renderer3D = class {
|
|
|
1494
1499
|
}));
|
|
1495
1500
|
this.webgl.info.autoReset = false;
|
|
1496
1501
|
this.engine.picker = (x, y) => this.pick(x, y);
|
|
1502
|
+
this.engine.toWorld = (x, y) => {
|
|
1503
|
+
const w = this.worldFromScreen(x, y);
|
|
1504
|
+
return w ? [
|
|
1505
|
+
w.x,
|
|
1506
|
+
w.y,
|
|
1507
|
+
w.z
|
|
1508
|
+
] : null;
|
|
1509
|
+
};
|
|
1510
|
+
this.engine.toScreen = (world) => this.screenFromWorld(world[0] ?? 0, world[1] ?? 0, world[2] ?? 0);
|
|
1511
|
+
this.engine.screenRay = (x, y) => this.rayFromScreen(x, y);
|
|
1497
1512
|
this.basePixelRatio = rendering.pixelRatio;
|
|
1498
1513
|
this.webgl.setPixelRatio(rendering.pixelRatio);
|
|
1499
1514
|
this.adaptive = opts.adaptiveResolution === false ? null : new AdaptiveResolution();
|
|
@@ -2067,6 +2082,7 @@ var Renderer3D = class {
|
|
|
2067
2082
|
rayFromScreen(sx, sy) {
|
|
2068
2083
|
const cam = this.lastCamera;
|
|
2069
2084
|
if (!cam) return null;
|
|
2085
|
+
if (sx < 0 || sx > this.lastSize.w || sy < 0 || sy > this.lastSize.h) return null;
|
|
2070
2086
|
pickNdc.set(sx / this.lastSize.w * 2 - 1, -(sy / this.lastSize.h * 2 - 1));
|
|
2071
2087
|
pickRaycaster.setFromCamera(pickNdc, cam);
|
|
2072
2088
|
const o = pickRaycaster.ray.origin;
|
|
@@ -2095,14 +2111,7 @@ var Renderer3D = class {
|
|
|
2095
2111
|
if (!cam) return null;
|
|
2096
2112
|
pickNdc.set(sx / this.lastSize.w * 2 - 1, -(sy / this.lastSize.h * 2 - 1));
|
|
2097
2113
|
pickRaycaster.setFromCamera(pickNdc, cam);
|
|
2098
|
-
|
|
2099
|
-
for (const hit of hits) {
|
|
2100
|
-
let obj = hit.object;
|
|
2101
|
-
while (obj && !obj.userData.incantoNode) obj = obj.parent;
|
|
2102
|
-
const node = obj?.userData.incantoNode;
|
|
2103
|
-
if (node) return node;
|
|
2104
|
-
}
|
|
2105
|
-
return null;
|
|
2114
|
+
return nodeFromHits(pickRaycaster.intersectObjects(this.threeScene.children, true));
|
|
2106
2115
|
}
|
|
2107
2116
|
/**
|
|
2108
2117
|
* GPU counters for the last rendered frame — EVERY pass of it, summed (see
|
|
@@ -2154,6 +2163,9 @@ var Renderer3D = class {
|
|
|
2154
2163
|
}
|
|
2155
2164
|
dispose() {
|
|
2156
2165
|
if (this.engine.picker) this.engine.picker = null;
|
|
2166
|
+
if (this.engine.toWorld) this.engine.toWorld = null;
|
|
2167
|
+
if (this.engine.toScreen) this.engine.toScreen = null;
|
|
2168
|
+
if (this.engine.screenRay) this.engine.screenRay = null;
|
|
2157
2169
|
this.disconnect();
|
|
2158
2170
|
this.threeScene.traverse((obj) => {
|
|
2159
2171
|
const mesh = obj;
|
|
@@ -2257,10 +2269,18 @@ async function createGame3D(opts) {
|
|
|
2257
2269
|
const cleanups = [];
|
|
2258
2270
|
const keyboard = opts.keyboard ?? (typeof window !== "undefined" ? window : false);
|
|
2259
2271
|
if (keyboard) engine.input.attachKeyboard(keyboard);
|
|
2260
|
-
|
|
2272
|
+
let pointerAttached = false;
|
|
2273
|
+
const attachPointerIfWanted = () => {
|
|
2274
|
+
if (pointerAttached || opts.pointer === false) return;
|
|
2275
|
+
const root = engine.scene?.root;
|
|
2276
|
+
if (!root) return;
|
|
2277
|
+
if (opts.pointer === void 0 && !wantsPointer(root)) return;
|
|
2278
|
+
pointerAttached = true;
|
|
2261
2279
|
const lockOnClick = typeof opts.pointer === "object" ? opts.pointer.lockOnClick ?? true : true;
|
|
2262
2280
|
engine.input.attachPointer(opts.canvas, { lockOnClick });
|
|
2263
|
-
}
|
|
2281
|
+
};
|
|
2282
|
+
attachPointerIfWanted();
|
|
2283
|
+
cleanups.push(engine.sceneChanged.connect(() => attachPointerIfWanted()));
|
|
2264
2284
|
cleanups.push(wireAudioUnlock(engine, scene.root, opts.canvas));
|
|
2265
2285
|
if (!opts.pageGestures) claimCanvasGestures(opts.canvas);
|
|
2266
2286
|
const touchMode = opts.touch ?? "auto";
|
|
@@ -2305,10 +2325,11 @@ async function createGame3D(opts) {
|
|
|
2305
2325
|
const camera = poseFromRenderer(renderer);
|
|
2306
2326
|
const open = editorSwitch.open ?? openBundledEditor;
|
|
2307
2327
|
const reboot = async (working) => {
|
|
2308
|
-
await createGame3D({
|
|
2328
|
+
const next = await createGame3D({
|
|
2309
2329
|
...opts,
|
|
2310
2330
|
scene: working
|
|
2311
2331
|
});
|
|
2332
|
+
editorSwitch?.onReboot?.(next);
|
|
2312
2333
|
};
|
|
2313
2334
|
await crossFade(async () => {
|
|
2314
2335
|
disposeGame();
|
|
@@ -2322,7 +2343,7 @@ async function createGame3D(opts) {
|
|
|
2322
2343
|
...editorSwitch.library ? { library: editorSwitch.library === true ? devServerLibrary() : editorSwitch.library } : {}
|
|
2323
2344
|
});
|
|
2324
2345
|
} catch (error) {
|
|
2325
|
-
|
|
2346
|
+
diagnose(engine, "error", "[incanto] could not open the editor:", error);
|
|
2326
2347
|
await reboot(sourceJson);
|
|
2327
2348
|
}
|
|
2328
2349
|
}, "opening the editor…");
|
|
@@ -2355,8 +2376,12 @@ async function createGame3D(opts) {
|
|
|
2355
2376
|
} catch {}
|
|
2356
2377
|
cleanups.push(engine.settings.bindAudio(engine.audio));
|
|
2357
2378
|
cleanups.push(engine.settings.bindLocale(engine.locale));
|
|
2358
|
-
|
|
2379
|
+
const applyTier = (patch) => {
|
|
2359
2380
|
applyQualityTier3D(engine, patch);
|
|
2381
|
+
};
|
|
2382
|
+
cleanups.push(engine.settings.bindQuality(applyTier));
|
|
2383
|
+
cleanups.push(engine.sceneChanged.connect(() => {
|
|
2384
|
+
applyTier(qualityEnvironment(engine.settings.get("quality")));
|
|
2360
2385
|
}));
|
|
2361
2386
|
cleanups.push(engine.settings.bindFrameCap((fps) => {
|
|
2362
2387
|
engine.maxFps = fps;
|
|
@@ -2386,26 +2411,15 @@ async function createGame3D(opts) {
|
|
|
2386
2411
|
requestAnimationFrame(tick);
|
|
2387
2412
|
};
|
|
2388
2413
|
requestAnimationFrame(tick);
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
break;
|
|
2399
|
-
case "key":
|
|
2400
|
-
engine.input.handleKey(s.code, s.down);
|
|
2401
|
-
break;
|
|
2402
|
-
case "pointer":
|
|
2403
|
-
engine.input.handlePointerMove(s.dx, s.dy);
|
|
2404
|
-
break;
|
|
2405
|
-
case "step":
|
|
2406
|
-
await new Promise((r) => setTimeout(r, s.ms));
|
|
2407
|
-
break;
|
|
2408
|
-
}
|
|
2414
|
+
const target = {
|
|
2415
|
+
engine,
|
|
2416
|
+
project: (x, y, z) => {
|
|
2417
|
+
const at = renderer.screenFromWorld;
|
|
2418
|
+
return at ? at.call(renderer, x, y, z) : null;
|
|
2419
|
+
},
|
|
2420
|
+
wait: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
2421
|
+
};
|
|
2422
|
+
for (const s of steps) await applyDriveStep(target, s);
|
|
2409
2423
|
watching = false;
|
|
2410
2424
|
return frames;
|
|
2411
2425
|
};
|
|
@@ -2418,7 +2432,22 @@ async function createGame3D(opts) {
|
|
|
2418
2432
|
}));
|
|
2419
2433
|
cleanups.push(pauseWhenHidden(engine));
|
|
2420
2434
|
await report(1, "ready");
|
|
2435
|
+
/**
|
|
2436
|
+
* Has this handle already been torn down?
|
|
2437
|
+
*
|
|
2438
|
+
* After one ✎→▶ editor round trip the handle `createGame*` returned is
|
|
2439
|
+
* ORPHANED: `reboot()` builds a replacement and the app still holds the old
|
|
2440
|
+
* one. Calling `game.openEditor()` on it then booted a THIRD game on top of
|
|
2441
|
+
* the live one, and `game.dispose()` tore down a game that was already gone
|
|
2442
|
+
* while leaving the live one running. A second `dispose()` also re-entered
|
|
2443
|
+
* Rapier's already-nulled `world.free()` and printed an engine error.
|
|
2444
|
+
*
|
|
2445
|
+
* A stale handle does nothing rather than something destructive.
|
|
2446
|
+
*/
|
|
2447
|
+
let disposed = false;
|
|
2421
2448
|
function disposeGame() {
|
|
2449
|
+
if (disposed) return;
|
|
2450
|
+
disposed = true;
|
|
2422
2451
|
teardown([
|
|
2423
2452
|
["physics", () => physics?.dispose()],
|
|
2424
2453
|
["app cleanups", () => {
|
|
@@ -2460,7 +2489,10 @@ async function createGame3D(opts) {
|
|
|
2460
2489
|
...renderer.stats?.()
|
|
2461
2490
|
};
|
|
2462
2491
|
},
|
|
2463
|
-
openEditor: editorSwitch ?
|
|
2492
|
+
openEditor: editorSwitch ? async () => {
|
|
2493
|
+
if (disposed) return;
|
|
2494
|
+
await editorAction.run();
|
|
2495
|
+
} : null,
|
|
2464
2496
|
dispose: disposeGame
|
|
2465
2497
|
};
|
|
2466
2498
|
}
|
|
@@ -2519,5 +2551,23 @@ function wireAudioUnlock(engine, root, canvas) {
|
|
|
2519
2551
|
for (const s of sources) s.target.addEventListener?.(s.type, unlock, { passive: true });
|
|
2520
2552
|
return detachAll;
|
|
2521
2553
|
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Does this tree have anything the CURSOR drives?
|
|
2556
|
+
*
|
|
2557
|
+
* `physics: 'auto'` has always meant "on iff the tree needs it"; the pointer had
|
|
2558
|
+
* no such default, so a board of `Clickable`s booted without `pointer: true` did
|
|
2559
|
+
* nothing when clicked — and the skill that introduces the behaviour says it
|
|
2560
|
+
* "needs no code at all". This makes that true.
|
|
2561
|
+
*
|
|
2562
|
+
* Only `Clickable`, deliberately: a behaviour of your own that reads
|
|
2563
|
+
* `pointerPosition()` is invisible from here, and guessing wider would attach a
|
|
2564
|
+
* pointer to games that never asked (and, with `lockOnClick`, capture a cursor
|
|
2565
|
+
* nobody wanted).
|
|
2566
|
+
*/
|
|
2567
|
+
function wantsPointer(root) {
|
|
2568
|
+
if (root.behavior?.constructor.name === "Clickable") return true;
|
|
2569
|
+
for (const child of root.children) if (wantsPointer(child)) return true;
|
|
2570
|
+
return false;
|
|
2571
|
+
}
|
|
2522
2572
|
//#endregion
|
|
2523
2573
|
export { Environment3D as a, AssetStore3D as c, syncTree as i, create_game_exports as n, applyQualityTier3D as o, Renderer3D as r, setEnvironment3D as s, createGame3D as t };
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-
|
|
1
|
+
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-Dcz0fr1S.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,5 @@
|
|
|
1
|
-
import { t as jsonClone } from "./json-
|
|
2
|
-
import {
|
|
3
|
-
import { r as capturePointer } from "./touch-DEAmqGdf.js";
|
|
1
|
+
import { t as jsonClone } from "./json-CfTjpvW8.js";
|
|
2
|
+
import { d as mergeStaticProps, r as capturePointer } from "./touch-BnCyPA0G.js";
|
|
4
3
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
5
4
|
//#region src/debug/capture.ts
|
|
6
5
|
/**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/core/diagnostics.d.ts
|
|
2
|
+
/** The minimum an engine has to look like to receive a diagnostic. */
|
|
3
|
+
interface DiagnosticSink {
|
|
4
|
+
log: {
|
|
5
|
+
warn(...parts: unknown[]): void;
|
|
6
|
+
error(...parts: unknown[]): void;
|
|
7
|
+
info(...parts: unknown[]): void;
|
|
8
|
+
debug(...parts: unknown[]): void;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { DiagnosticSink as t };
|