incanto 0.70.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/incanto-verify.mjs +36 -98
- package/dist/2d.d.ts +18 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +3 -3
- package/dist/3d.js +6 -6
- package/dist/{agent8-CmNF01gA.js → agent8-Cfmd3ar_.js} +1 -1
- package/dist/{audio-player-DaMxqfNE.d.ts → audio-player-L8yccdMP.d.ts} +1 -1
- package/dist/{behavior-DZExDn9o.d.ts → behavior-Dcz0fr1S.d.ts} +11 -0
- package/dist/{create-game-Bwvh6q8A.js → create-game-CH4kt78v.js} +7 -7
- package/dist/{create-game-C7ffQWW7.js → create-game-LCHBLfA4.js} +7 -7
- package/dist/debug.d.ts +1 -1
- package/dist/editor.js +29 -25
- package/dist/{environment-presets-D6Q5BxeE.js → environment-presets-99BzP_L-.js} +3 -3
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-BfHkuzVb.js → gameplay-CNULJvwh.js} +108 -6
- package/dist/gameplay.d.ts +68 -4
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +27 -4
- package/dist/index.js +4 -4
- package/dist/{loader-Cff09LMm.d.ts → loader-8-IHvbKD.d.ts} +1 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +2 -2
- package/dist/{physics-2d-CE0Qvy3V.js → physics-2d-FhrXUc6B.js} +2 -2
- package/dist/{physics-3d-CpH-2gn5.js → physics-3d-CFEGxBXZ.js} +3 -3
- package/dist/{picking-CQJ_PJKh.js → picking-DVo7fI13.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-Bkk0wSDB.js → register-BYQCBySi.js} +100 -8
- package/dist/{register-6DYnKZcy.js → register-DuVdzxbq.js} +49 -15
- package/dist/{replay-DjAkAzMq.js → replay-DEvp3kyV.js} +2 -2
- package/dist/{replay-Dmw-PKQu.d.ts → replay-F7IZHdFR.d.ts} +1 -1
- package/dist/{save-slots-BXVg148r.js → save-slots-Bvuh2p_r.js} +56 -3
- package/dist/{split-screen--k-XpBjr.d.ts → split-screen-CIYf1zSf.d.ts} +2 -2
- package/dist/{split-screen-PL78oVXP.js → split-screen-eULetcg-.js} +3 -3
- package/dist/{src-Cxfiv1Hg.js → src-_jk0qLsS.js} +1 -1
- package/dist/{test-iHYVUcDK.js → test-CmN54kWv.js} +252 -24
- package/dist/test.d.ts +113 -5
- package/dist/test.js +3 -3
- package/dist/vite.js +3 -3
- package/editor/assets/{agent8-D0MS174y.js → agent8-yLIEYHbd.js} +1 -1
- package/editor/assets/{debug-BnXkKuYu.js → debug-u31w_yhq.js} +1 -1
- package/editor/assets/{index-CIu3uc3l.js → index-DK9xMGpW.js} +94 -94
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +4 -0
- package/skills/incanto-behaviors-and-scripts.md +30 -9
- package/skills/incanto-building-2d-games.md +20 -2
- package/skills/incanto-gameplay-behaviors.md +63 -1
- package/skills/incanto-hud.md +14 -0
- package/skills/incanto-node-reference.md +18 -2
- package/skills/incanto-playtesting.md +34 -0
- package/skills/incanto-save-slots.md +56 -1
- package/skills/incanto-verifying-your-game.md +11 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +44 -226
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/molehill-2d/src/game.scene.json +10 -60
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +80 -416
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/game.scene.json +5 -24
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/game.scene.json +13 -71
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/behaviors.ts +21 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +16 -87
- package/templates-app/village-quest-3d/src/village.scene.json +5 -27
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
-
import { B as
|
|
2
|
+
import { B as HudLayer, F as resolveOrderGroups, G as UiText, H as TAPPABLE, I as InputMap, J as Node, N as ORDER_GROUP_BASE, U as UiBanner, V as HudWidgetBase, W as UiBar, Y as diagnose, a as restoreBehaviors, ct as Signal, i as captureBehaviors, j as createSaveStore, q as requireText, t as ENGINE_STATE_KEY, z as FITS } from "./save-slots-Bvuh2p_r.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-CDOMybym.js";
|
|
5
5
|
import { p as registerNode } from "./touch-BnCyPA0G.js";
|
|
@@ -2470,7 +2470,11 @@ var Engine = class {
|
|
|
2470
2470
|
this._scene.root.free();
|
|
2471
2471
|
this._scene.tree._setEngine(null);
|
|
2472
2472
|
this._scene = null;
|
|
2473
|
-
|
|
2473
|
+
try {
|
|
2474
|
+
this.sceneChanged.emit(null);
|
|
2475
|
+
} catch (error) {
|
|
2476
|
+
diagnose(this, "warn", "[incanto] teardown: a `sceneChanged` listener threw (continuing) — it fires with NULL here, so a handler that reads the scene has to check for it", error);
|
|
2477
|
+
}
|
|
2474
2478
|
}
|
|
2475
2479
|
this.input.dispose();
|
|
2476
2480
|
this.input.clear();
|
|
@@ -3612,7 +3616,20 @@ var UiSlider = class extends HudWidgetBase {
|
|
|
3612
3616
|
/** Left/right nudge by one step — the only sane thing a d-pad can mean here. */
|
|
3613
3617
|
_activate(dir) {
|
|
3614
3618
|
if (dir === 0) return;
|
|
3615
|
-
|
|
3619
|
+
this.choose(this.value + dir * this.step);
|
|
3620
|
+
}
|
|
3621
|
+
/**
|
|
3622
|
+
* Move it as a PERSON would: set the value and say so.
|
|
3623
|
+
*
|
|
3624
|
+
* `UiButton` has `press()` and the value widgets had nothing, because
|
|
3625
|
+
* assigning `.value` deliberately does not emit (restoring a saved setting
|
|
3626
|
+
* must not fire the handler that saved it). So a harness — or a game driving
|
|
3627
|
+
* its own menu: a preset button, "reset to defaults", a tutorial that moves a
|
|
3628
|
+
* slider for you — had one route to "the player changed this", and it was
|
|
3629
|
+
* `_activate`, which is internal and takes a direction rather than a value.
|
|
3630
|
+
*/
|
|
3631
|
+
choose(value) {
|
|
3632
|
+
const next = Math.min(this.max, Math.max(this.min, value));
|
|
3616
3633
|
if (next === this.value) return;
|
|
3617
3634
|
this.value = next;
|
|
3618
3635
|
this.last = next;
|
|
@@ -3670,12 +3687,15 @@ var UiToggle = class extends HudWidgetBase {
|
|
|
3670
3687
|
focusable = true;
|
|
3671
3688
|
/** Confirm flips it; left/right set it explicitly, which reads better on a pad. */
|
|
3672
3689
|
_activate(dir) {
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
if (this.
|
|
3678
|
-
this.
|
|
3690
|
+
this.choose(dir === 0 ? !this.value : dir > 0);
|
|
3691
|
+
}
|
|
3692
|
+
/** Flip it as a PERSON would: set the value and say so. See `UiSlider.choose`. */
|
|
3693
|
+
choose(value) {
|
|
3694
|
+
if (value === this.value) return;
|
|
3695
|
+
this.value = value;
|
|
3696
|
+
this.last = value;
|
|
3697
|
+
if (this.input) this.input.checked = value;
|
|
3698
|
+
this.emit("changed", value);
|
|
3679
3699
|
}
|
|
3680
3700
|
input = null;
|
|
3681
3701
|
last = null;
|
|
@@ -3754,14 +3774,28 @@ var UiSelect = class extends HudWidgetBase {
|
|
|
3754
3774
|
}
|
|
3755
3775
|
/** Left/right (and confirm) walk the list — a select has no other gesture. */
|
|
3756
3776
|
_activate(dir) {
|
|
3757
|
-
const choices = this.
|
|
3777
|
+
const choices = this.choices();
|
|
3758
3778
|
if (choices.length === 0) return;
|
|
3759
3779
|
const next = choices[(Math.max(0, choices.indexOf(this.value)) + (dir === 0 ? 1 : dir) + choices.length) % choices.length];
|
|
3760
|
-
if (
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3780
|
+
if (next) this.choose(next);
|
|
3781
|
+
}
|
|
3782
|
+
/**
|
|
3783
|
+
* Pick an option as a PERSON would: set the value and say so. See
|
|
3784
|
+
* `UiSlider.choose`.
|
|
3785
|
+
*
|
|
3786
|
+
* An option the list does not offer is refused, for the reason
|
|
3787
|
+
* `validateJson` refuses it in the file: the browser would show the first one
|
|
3788
|
+
* while the node kept answering with what it was given, and nothing would
|
|
3789
|
+
* ever reconcile them.
|
|
3790
|
+
*/
|
|
3791
|
+
choose(value) {
|
|
3792
|
+
const choices = this.choices();
|
|
3793
|
+
if (choices.length > 0 && !choices.includes(value)) throw new IncantoError("PROP_TYPE_MISMATCH", `UiSelect '${this.name}': choose('${value}') is not one of its options [${choices.join(", ")}].`, { prop: "value" });
|
|
3794
|
+
if (value === this.value) return;
|
|
3795
|
+
this.value = value;
|
|
3796
|
+
this.last = value;
|
|
3797
|
+
if (this.select) this.select.value = value;
|
|
3798
|
+
this.emit("changed", value);
|
|
3765
3799
|
}
|
|
3766
3800
|
select = null;
|
|
3767
3801
|
labelEl = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { N as translationKey } from "./register-
|
|
1
|
+
import { L as handlerShadowWarnings, R as sceneDimension, V as HudWidgetBase, Z as nodeRefWarnings } from "./save-slots-Bvuh2p_r.js";
|
|
2
|
+
import { N as translationKey } from "./register-DuVdzxbq.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { u as getNodeType } from "./touch-BnCyPA0G.js";
|
|
5
5
|
//#region src/core/audit.ts
|
|
@@ -113,7 +113,10 @@ var Behavior = class {
|
|
|
113
113
|
*/
|
|
114
114
|
get engine() {
|
|
115
115
|
const engine = this.node?.tree?.engine;
|
|
116
|
-
if (!engine)
|
|
116
|
+
if (!engine) {
|
|
117
|
+
if (this.node?.freed) throw new IncantoError("TREE_VIOLATION", `Behavior on '${this.node.name}' has been FREED — a scene swap frees the tree it replaces, so \`this.engine\` (which reads \`this.node.tree\`) is gone with it. Hold it BEFORE the swap: \`const engine = this.engine; goToScene(engine, next);\` and use that afterwards.`);
|
|
118
|
+
throw new IncantoError("TREE_VIOLATION", `Behavior on '${this.node?.name ?? "?"}' is not attached to a running engine. If this came from \`onReady\` during a load, the scene does not know its engine yet: pass it — \`loadScene(json, { engine })\` — which is what createGame2D/3D and runScript do. Otherwise the node is not in a scene set on an Engine.`);
|
|
119
|
+
}
|
|
117
120
|
return engine;
|
|
118
121
|
}
|
|
119
122
|
/** Shortcut for `this.engine.input`. */
|
|
@@ -669,7 +672,11 @@ var Node = class {
|
|
|
669
672
|
*/
|
|
670
673
|
wiringPath() {
|
|
671
674
|
const parts = [];
|
|
672
|
-
for (let n = this; n; n = n._parent)
|
|
675
|
+
for (let n = this; n; n = n._parent) {
|
|
676
|
+
const authored = n._authoredPath;
|
|
677
|
+
if (authored !== void 0) return parts.length === 0 ? authored : `${authored}/${parts.join("/")}`;
|
|
678
|
+
parts.unshift(n._cloneOf ?? n._name);
|
|
679
|
+
}
|
|
673
680
|
return `/${parts.join("/")}`;
|
|
674
681
|
}
|
|
675
682
|
getNode(path) {
|
|
@@ -874,9 +881,23 @@ var Node = class {
|
|
|
874
881
|
if (this._tree) this._tree._queueFree(this);
|
|
875
882
|
else this.free();
|
|
876
883
|
}
|
|
884
|
+
/**
|
|
885
|
+
* Has this node been torn down?
|
|
886
|
+
*
|
|
887
|
+
* A scene swap frees the tree it replaces, so the answer is `true` for every
|
|
888
|
+
* node of the scene you just left — which is exactly the state a behavior is
|
|
889
|
+
* in when it runs one more line after `goToScene`. Kept as a flag rather than
|
|
890
|
+
* inferred from `parent`/`tree`, because a DETACHED node (a prefab on a
|
|
891
|
+
* shelf, a clone waiting to be added) has neither and is perfectly alive.
|
|
892
|
+
*/
|
|
893
|
+
get freed() {
|
|
894
|
+
return this._freed;
|
|
895
|
+
}
|
|
896
|
+
_freed = false;
|
|
877
897
|
/** Immediately detach and tear down this node and its children. */
|
|
878
898
|
free() {
|
|
879
899
|
const tree = this._tree;
|
|
900
|
+
this._freed = true;
|
|
880
901
|
for (const child of [...this._children]) child.free();
|
|
881
902
|
this._parent?.removeChild(this);
|
|
882
903
|
if (this._tree) this._propagateExitTree();
|
|
@@ -5145,6 +5166,7 @@ function duplicateNode(node, opts) {
|
|
|
5145
5166
|
const clone = buildNodeJson(stripUids(serializeNode(node)), opts ?? rebuildOptions(node));
|
|
5146
5167
|
markCloned(clone);
|
|
5147
5168
|
markTemplateName(clone);
|
|
5169
|
+
markTemplateOrigin(clone, node);
|
|
5148
5170
|
return clone;
|
|
5149
5171
|
}
|
|
5150
5172
|
/**
|
|
@@ -5196,6 +5218,37 @@ function markCloned(node) {
|
|
|
5196
5218
|
function markTemplateName(node) {
|
|
5197
5219
|
node._cloneOf = node.name;
|
|
5198
5220
|
}
|
|
5221
|
+
/**
|
|
5222
|
+
* @internal Where the template this clone came from was AUTHORED.
|
|
5223
|
+
*
|
|
5224
|
+
* `_cloneOf` (the name) is enough only while clones land where the template
|
|
5225
|
+
* was authored — the `Spawner` case (`/Waves/Grunt` template, `/Waves/Grunt2`
|
|
5226
|
+
* clone) and no other. A game that clones from a SHELF authors the template at
|
|
5227
|
+
* `/Game/Prefabs/Tower` and adds the clone under `/Game/Towers`, so its audio
|
|
5228
|
+
* was logged at `/Game/Towers/Tower/Thud`: a path no scene file contains, and
|
|
5229
|
+
* one no report that reads the file can ever match. Recording the address
|
|
5230
|
+
* itself is what lets `wiringPath` answer with the authored node wherever the
|
|
5231
|
+
* clone ends up — including a clone OF a clone, which carries it forward.
|
|
5232
|
+
*
|
|
5233
|
+
* Taken while the source is still in a tree; a template detached before the
|
|
5234
|
+
* first clone (`PrefabShelf`, `SpawnSource`) records its own on the way out.
|
|
5235
|
+
*/
|
|
5236
|
+
function markTemplateOrigin(clone, source) {
|
|
5237
|
+
const origin = source._authoredPath ?? (source.tree ? source.getPath() : null);
|
|
5238
|
+
if (origin) clone._authoredPath = origin;
|
|
5239
|
+
}
|
|
5240
|
+
/**
|
|
5241
|
+
* @internal Remember where a node was authored, before it leaves the tree.
|
|
5242
|
+
*
|
|
5243
|
+
* A shelf or a spawner lifts its templates out at enter; from then on the
|
|
5244
|
+
* template cannot say where it came from, and neither can anything cloned from
|
|
5245
|
+
* it. Called on the way out, while the answer is still there.
|
|
5246
|
+
*/
|
|
5247
|
+
function rememberAuthoredPath(node) {
|
|
5248
|
+
const at = node;
|
|
5249
|
+
if (at._authoredPath !== void 0) return;
|
|
5250
|
+
if (node.tree || node.parent?.tree) at._authoredPath = node.getPath();
|
|
5251
|
+
}
|
|
5199
5252
|
/** @internal Was this node made at runtime rather than loaded from a file? */
|
|
5200
5253
|
function isCloned(node) {
|
|
5201
5254
|
return node._cloned === true;
|
|
@@ -5648,4 +5701,4 @@ function savesWithoutUid(root) {
|
|
|
5648
5701
|
return out;
|
|
5649
5702
|
}
|
|
5650
5703
|
//#endregion
|
|
5651
|
-
export {
|
|
5704
|
+
export { parseNodePath as $, SceneTree as A, HudLayer as B, sunDirectionFromSky as C, computeViewport as D, resolveConstants as E, resolveOrderGroups as F, UiText as G, TAPPABLE as H, InputMap as I, Node as J, requireNumber as K, handlerShadowWarnings as L, resetMemorySaves as M, ORDER_GROUP_BASE as N, resolveViewport as O, effectiveOrder as P, resolveRefInJson as Q, sceneDimension as R, sunDirectionFromElevationAzimuth as S, isConstRef as T, UiBanner as U, HudWidgetBase as V, UiBar as W, describeRefProblem as X, diagnose as Y, nodeRefWarnings as Z, Scene as _, restoreBehaviors as a, getBehavior as at, horizonColorFromSky as b, isCloned as c, Signal as ct, rebuildOptions as d, Behavior as et, rememberAuthoredPath as f, loader_exports as g, loadScene as h, captureBehaviors as i, clearBehaviors as it, createSaveStore as j, newUid as k, markCloned as l, buildSceneSubtree as m, SaveSlots as n, behaviorSchema as nt, savesWithoutUid as o, registerBehavior as ot, stripUids as p, requireText as q, behaviorsWithoutSave as r, behaviorSignals as rt, duplicateNode as s, registeredBehaviors as st, ENGINE_STATE_KEY as t, StubBehavior as tt, markTemplateName as u, serializeNode as v, CONST_REF_KEY as w, parseEnvironment3D as x, SCENE_FORMAT as y, FITS$1 as z };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-
|
|
1
|
+
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-Dcz0fr1S.js";
|
|
2
2
|
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
3
3
|
import { a as SceneJson, c as JsonValue, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-8-IHvbKD.js";
|
|
5
5
|
|
|
6
6
|
//#region src/net/types.d.ts
|
|
7
7
|
type Unsubscribe = () => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as jsonEquals, t as jsonClone } from "./json-CfTjpvW8.js";
|
|
2
|
-
import {
|
|
3
|
-
import { t as registerCoreNodes, v as Engine } from "./register-
|
|
2
|
+
import { J as Node, Y as diagnose, ct as Signal, d as rebuildOptions, h as loadScene, l as markCloned, m as buildSceneSubtree, p as stripUids, u as markTemplateName } from "./save-slots-Bvuh2p_r.js";
|
|
3
|
+
import { t as registerCoreNodes, v as Engine } from "./register-DuVdzxbq.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { p as registerNode } from "./touch-BnCyPA0G.js";
|
|
6
6
|
//#region src/net/loopback.ts
|
|
@@ -1150,7 +1150,7 @@ function applySyncPatch(root, patch, setProp, onMissingNode) {
|
|
|
1150
1150
|
}
|
|
1151
1151
|
}
|
|
1152
1152
|
async function createDefaultTransport(config, diagnostics) {
|
|
1153
|
-
const { createAgent8Server } = await import("./agent8-
|
|
1153
|
+
const { createAgent8Server } = await import("./agent8-Cfmd3ar_.js").then((n) => n.t);
|
|
1154
1154
|
return createAgent8Server(config, diagnostics);
|
|
1155
1155
|
}
|
|
1156
1156
|
//#endregion
|
|
@@ -199,6 +199,6 @@ async function preloadSceneAssets(assets, title) {
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region src/index.ts
|
|
201
201
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
202
|
-
const VERSION = "0.
|
|
202
|
+
const VERSION = "0.71.0";
|
|
203
203
|
//#endregion
|
|
204
204
|
export { findPath as a, preloadUrls as i, assetUrls as n, gridFromRows as o, preloadSceneAssets as r, VERSION as t };
|