incanto 0.56.0 → 0.57.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.
Files changed (60) hide show
  1. package/bin/incanto-verify.mjs +9 -2
  2. package/dist/2d.d.ts +59 -7
  3. package/dist/2d.js +3 -3
  4. package/dist/3d.d.ts +34 -4
  5. package/dist/3d.js +5 -5
  6. package/dist/{behavior-CyQoSu4n.d.ts → behavior-l08AEbq9.d.ts} +5 -0
  7. package/dist/{create-game-CqJkfMzm.js → create-game-C5jQYPah.js} +28 -71
  8. package/dist/{create-game-YvaNWhe6.js → create-game-DpbUrMOQ.js} +146 -7
  9. package/dist/debug.d.ts +1 -1
  10. package/dist/{duplicate-MNLMAcbz.js → duplicate-BPLZDZpd.js} +1 -1
  11. package/dist/{environment-presets-DLHqgNAF.js → environment-presets-CvvQr_bJ.js} +106 -24
  12. package/dist/{frame-report-njybhZon.js → frame-report-BSMny7oe.js} +1 -1
  13. package/dist/{frame-report-DZ70IY26.d.ts → frame-report-DCnHFmto.d.ts} +1 -1
  14. package/dist/{gameplay-C_SPzmUe.js → gameplay-BVphcxmE.js} +89 -13
  15. package/dist/gameplay.d.ts +26 -1
  16. package/dist/gameplay.js +1 -1
  17. package/dist/index.d.ts +45 -5
  18. package/dist/index.js +8 -9
  19. package/dist/{loader-DhI1jFW_.d.ts → loader-BbEMTuWg.d.ts} +1 -1
  20. package/dist/{loader-BTkHYrQn.js → loader-BcrRSjxB.js} +682 -682
  21. package/dist/net.d.ts +2 -2
  22. package/dist/net.js +1 -1
  23. package/dist/{pathfinding-CXGCpRQe.d.ts → pathfinding-mEN4V1CU.d.ts} +1 -1
  24. package/dist/{physics-2d-CfWAggJ1.js → physics-2d-BLcvEFDR.js} +2 -2
  25. package/dist/{physics-3d-NzDwWPrF.js → physics-3d-QBrfIT2Y.js} +3 -3
  26. package/dist/react.d.ts +1 -1
  27. package/dist/react.js +1 -1
  28. package/dist/{register-en63AEZO.js → register-C6ZBFRjd.js} +63 -60
  29. package/dist/{register-p48lHE2o.js → register-Ch70uByv.js} +1615 -1502
  30. package/dist/{replay-ePMz26jw.d.ts → replay-Dw6gMlYA.d.ts} +1 -1
  31. package/dist/{replay-t1pP0gQg.js → replay-s7I2GstT.js} +31 -11
  32. package/dist/sheet-grid-BT6N_Bjs.js +59 -0
  33. package/dist/{split-screen-BsdOHbzP.d.ts → split-screen-B0baBwxI.d.ts} +5 -1
  34. package/dist/{split-screen-CSb_uZ6W.js → split-screen-DLsUrleX.js} +14 -3
  35. package/dist/{sprite-animation-7qvUxF6Z.js → sprite-animation-C0wXLBZJ.js} +8 -4
  36. package/dist/{src-51GA-9m-.js → src-CGjmPw65.js} +55 -2
  37. package/dist/{teardown-C7uVSJvx.js → teardown-Cs113S9F.js} +74 -2
  38. package/dist/{test-Bu6SPNsV.js → test-it1VekWs.js} +28 -19
  39. package/dist/test.d.ts +4 -4
  40. package/dist/test.js +2 -2
  41. package/dist/{touch-BnMyy9tr.js → touch-DESwnpOc.js} +173 -1
  42. package/dist/vite.d.ts +1 -1
  43. package/dist/vite.js +3 -3
  44. package/editor/assets/{agent8-X0Nesj-k.js → agent8-CGT7r3Mb.js} +1 -1
  45. package/editor/assets/{debug-TXqu-ftX.js → debug-BxWSIHG3.js} +1 -1
  46. package/editor/assets/{index-DTdwKKIv.js → index-CV1m-aX5.js} +62 -62
  47. package/editor/index.html +1 -1
  48. package/package.json +1 -1
  49. package/skills/incanto-assets.md +5 -1
  50. package/skills/incanto-audio.md +7 -1
  51. package/skills/incanto-gameplay-behaviors.md +2 -1
  52. package/skills/incanto-hud.md +6 -0
  53. package/skills/incanto-performance.md +5 -0
  54. package/skills/incanto-physics-and-input.md +14 -0
  55. package/skills/incanto-save-slots.md +2 -1
  56. package/skills/incanto-verifying-your-game.md +4 -0
  57. package/templates-app/beacon-isle-3d/package.json +1 -1
  58. package/templates-app/tps-3d/package.json +1 -1
  59. package/templates-app/village-quest-3d/package.json +1 -1
  60. package/dist/log-report-CPFm4OXf.js +0 -173
package/dist/net.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { At as Node, d as PropSchema } from "./behavior-CyQoSu4n.js";
2
- import { a as NetworkManagerOptions, c as LocalGameServer, d as ServerClass, f as createLocalGameServer, g as Unsubscribe, h as NetworkTransport, i as NetworkManager, l as LocalGameServerOptions, m as LoopbackTransport, n as SplitScreenPlayer, o as applySyncPatch, p as LoopbackHub, r as createSplitScreen, s as CollectionOptions, t as SplitScreenOptions, u as LocalGameServerTransport } from "./split-screen-BsdOHbzP.js";
1
+ import { At as Node, d as PropSchema } from "./behavior-l08AEbq9.js";
2
+ import { a as NetworkManagerOptions, c as LocalGameServer, d as ServerClass, f as createLocalGameServer, g as Unsubscribe, h as NetworkTransport, i as NetworkManager, l as LocalGameServerOptions, m as LoopbackTransport, n as SplitScreenPlayer, o as applySyncPatch, p as LoopbackHub, r as createSplitScreen, s as CollectionOptions, t as SplitScreenOptions, u as LocalGameServerTransport } from "./split-screen-B0baBwxI.js";
3
3
 
4
4
  //#region src/net/agent8.d.ts
5
5
  /**
package/dist/net.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { n as createAgent8Server } from "./agent8-CvsfVskX.js";
2
- import { a as applySyncPatch, c as createLocalGameServer, i as NetworkManager, l as LoopbackHub, n as registerNodesNet, o as LocalGameServer, r as NetworkSpawner, s as LocalGameServerTransport, t as createSplitScreen, u as LoopbackTransport } from "./split-screen-CSb_uZ6W.js";
2
+ import { a as applySyncPatch, c as createLocalGameServer, i as NetworkManager, l as LoopbackHub, n as registerNodesNet, o as LocalGameServer, r as NetworkSpawner, s as LocalGameServerTransport, t as createSplitScreen, u as LoopbackTransport } from "./split-screen-DLsUrleX.js";
3
3
  export { LocalGameServer, LocalGameServerTransport, LoopbackHub, LoopbackTransport, NetworkManager, NetworkSpawner, applySyncPatch, createAgent8Server, createLocalGameServer, createSplitScreen, registerNodesNet };
@@ -1,4 +1,4 @@
1
- import { At as Node, d as PropSchema, dt as Listener } from "./behavior-CyQoSu4n.js";
1
+ import { At as Node, d as PropSchema, dt as Listener } from "./behavior-l08AEbq9.js";
2
2
 
3
3
  //#region src/core/nodes/audio-player.d.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { C as diagnose } from "./loader-BTkHYrQn.js";
2
+ import { C as diagnose } from "./loader-BcrRSjxB.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
- import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-en63AEZO.js";
4
+ import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-C6ZBFRjd.js";
5
5
  import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
6
6
  //#region src/2d/physics/physics-2d.ts
7
7
  var physics_2d_exports = /* @__PURE__ */ __exportAll({
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { C as diagnose } from "./loader-BTkHYrQn.js";
2
+ import { C as diagnose } from "./loader-BcrRSjxB.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
- import { B as Node3D, F as Area3D, I as CharacterBody3D, L as PhysicsBody3D, R as RigidBody3D, V as validateCollider3D } from "./gameplay-C_SPzmUe.js";
4
+ import { H as validateCollider3D, I as Area3D, L as CharacterBody3D, R as PhysicsBody3D, V as Node3D, z as RigidBody3D } from "./gameplay-BVphcxmE.js";
5
5
  import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
6
- import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-DLHqgNAF.js";
6
+ import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-CvvQr_bJ.js";
7
7
  import { Euler, Matrix4, Quaternion, Vector3 } from "three";
8
8
  //#region src/3d/physics/collider-lines.ts
9
9
  /**
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-CyQoSu4n.js";
1
+ import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-l08AEbq9.js";
2
2
  import { c as JsonValue } from "./schema-CFeioQRE.js";
3
3
  import { CSSProperties, ReactNode } from "react";
4
4
 
package/dist/react.js CHANGED
@@ -156,7 +156,7 @@ function IncantoCanvas(props) {
156
156
  pointer: latest.pointer,
157
157
  ...keyboard !== void 0 ? { keyboard } : {}
158
158
  };
159
- const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-CqJkfMzm.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-YvaNWhe6.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-C5jQYPah.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-DpbUrMOQ.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;
@@ -1,10 +1,11 @@
1
- import { C as diagnose, b as effectiveOrder, f as Node } from "./loader-BTkHYrQn.js";
2
- import { t as registerCoreNodes } from "./register-p48lHE2o.js";
1
+ import { C as diagnose, S as Node, y as effectiveOrder } from "./loader-BcrRSjxB.js";
2
+ import { t as registerCoreNodes } from "./register-Ch70uByv.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { t as Rng } from "./rng-DP-SR7eg.js";
5
5
  import { i as getNodeSchema, l as registerNode } from "./registry-C7u42TID.js";
6
- import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-7qvUxF6Z.js";
7
- import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry } from "three";
6
+ import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-C0wXLBZJ.js";
7
+ import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
8
+ import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry, SRGBColorSpace } from "three";
8
9
  //#region src/2d/physics/collider-validate.ts
9
10
  /**
10
11
  * Hard-validate a 2D collider prop — called at LOAD time (via the loader's
@@ -305,59 +306,6 @@ var Joint2D = class extends Node2D {
305
306
  }
306
307
  };
307
308
  //#endregion
308
- //#region src/2d/sheet-grid.ts
309
- /**
310
- * Does this spritesheet's grid actually fit the image?
311
- *
312
- * `frameWidth`/`frameHeight` are taken on trust, and the frame math floors the
313
- * division — so a frame size that does not divide the sheet slices every row a
314
- * little further off, and an animation naming a frame past the end of the grid
315
- * reads whatever texels are there. Both draw WRONG ART with no error anywhere,
316
- * which is the one symptom an author cannot tell apart from having picked the
317
- * wrong sheet in the first place.
318
- *
319
- * Pure arithmetic on numbers that are known the moment the image loads, so it
320
- * costs nothing and it is exact.
321
- */
322
- /**
323
- * Frame sizes that divide `total` cleanly, biggest first.
324
- *
325
- * Bounded to grids of 2–32 cells so the suggestion is a frame size someone
326
- * might actually have meant, not every factor of the number.
327
- */
328
- function divisors(total) {
329
- const out = [];
330
- for (let cells = 2; cells <= 32; cells++) if (total % cells === 0) out.push(total / cells);
331
- return out.sort((a, b) => b - a).slice(0, 6);
332
- }
333
- /**
334
- * The problem with this grid, or null when there is none.
335
- *
336
- * `highestFrame` is the largest frame index the scene asks for, when it is
337
- * known — an animation range that runs off the end is the other half of the
338
- * same mistake.
339
- */
340
- function checkSheetGrid(key, frameWidth, frameHeight, imageWidth, imageHeight, highestFrame) {
341
- if (!imageWidth || !imageHeight || !frameWidth || !frameHeight) return null;
342
- if (imageWidth % frameWidth !== 0 || imageHeight % frameHeight !== 0) {
343
- const parts = [];
344
- if (imageWidth % frameWidth !== 0) {
345
- const fits = divisors(imageWidth);
346
- parts.push(`${imageWidth} px wide is not a whole number of ${frameWidth} px frames` + (fits.length > 0 ? ` (${fits.join(", ")} would divide it)` : ""));
347
- }
348
- if (imageHeight % frameHeight !== 0) {
349
- const fits = divisors(imageHeight);
350
- parts.push(`${imageHeight} px tall is not a whole number of ${frameHeight} px frames` + (fits.length > 0 ? ` (${fits.join(", ")} would divide it)` : ""));
351
- }
352
- return `[incanto] spritesheet '${key}' does not fit its frame size: ${parts.join("; ")}. Every row after the first is cut off centre.`;
353
- }
354
- if (highestFrame !== void 0) {
355
- const frames = imageWidth / frameWidth * (imageHeight / frameHeight);
356
- if (highestFrame >= frames) return `[incanto] spritesheet '${key}' has ${frames} frames (0–${frames - 1}), and an animation asks for frame ${highestFrame}. Those frames draw whatever is at the wrong end of the sheet.`;
357
- }
358
- return null;
359
- }
360
- //#endregion
361
309
  //#region src/2d/nodes/sprite-2d.ts
362
310
  /** Shared unit quad — sprites are sized via the quad's scale, never THREE.Sprite. */
363
311
  const UNIT_PLANE$2 = new PlaneGeometry(1, 1);
@@ -908,7 +856,9 @@ var Label = class extends Node2D {
908
856
  const quad = this._quad();
909
857
  const mat = quad.material;
910
858
  mat.map?.dispose();
911
- mat.map = new CanvasTexture(this.canvas);
859
+ const texture = new CanvasTexture(this.canvas);
860
+ texture.colorSpace = SRGBColorSpace;
861
+ mat.map = texture;
912
862
  mat.needsUpdate = true;
913
863
  const cssW = w / dpr;
914
864
  const cssH = h / dpr;
@@ -916,6 +866,25 @@ var Label = class extends Node2D {
916
866
  const ax = this.align === "center" ? .5 : this.align === "right" ? 1 : 0;
917
867
  quad.position.set((.5 - ax) * cssW, 0, 0);
918
868
  }
869
+ /**
870
+ * Hand the canvas and its texture back.
871
+ *
872
+ * LABEL_PLANE is shared by every Label in the process and stays; the material
873
+ * and the CanvasTexture are this node's, and a scene that spawns floating
874
+ * text left one of each behind per freed node.
875
+ */
876
+ free() {
877
+ const quad = this.quadMesh;
878
+ if (quad) {
879
+ const mat = quad.material;
880
+ mat.map?.dispose();
881
+ mat.dispose();
882
+ quad.removeFromParent();
883
+ this.quadMesh = null;
884
+ }
885
+ this.canvas = null;
886
+ super.free();
887
+ }
919
888
  };
920
889
  //#endregion
921
890
  //#region src/2d/nodes/particles-2d.ts
@@ -1111,6 +1080,22 @@ var Particles2D = class Particles2D extends Node2D {
1111
1080
  z
1112
1081
  ];
1113
1082
  }
1083
+ /** What the current mesh was built FOR — capacity and blend, the two things
1084
+ * baked into it. Not the draw count, which changes every frame. */
1085
+ meshKey = "";
1086
+ /**
1087
+ * Hand the GPU back. UNIT_PLANE is shared by every 2D particle system in the
1088
+ * process, so the geometry stays; the per-node material and the instance
1089
+ * buffers inside the InstancedMesh do not.
1090
+ */
1091
+ free() {
1092
+ if (this.mesh) {
1093
+ this.mesh.removeFromParent();
1094
+ disposeMesh(this.mesh);
1095
+ this.mesh = null;
1096
+ }
1097
+ super.free();
1098
+ }
1114
1099
  /** Tell the engine an effect fired — the visual half of the audio record. */
1115
1100
  report(kind, amount) {
1116
1101
  const engine = this.tree?.engine;
@@ -1157,8 +1142,13 @@ var Particles2D = class Particles2D extends Node2D {
1157
1142
  _syncObject2D(assets) {
1158
1143
  super._syncObject2D(assets);
1159
1144
  const sim = this._ensureSim();
1160
- if (!this.mesh || this.mesh.count !== this.maxParticles) {
1161
- if (this.mesh) this.mesh.removeFromParent();
1145
+ const key = `${this.maxParticles}|${this.blend}`;
1146
+ if (!this.mesh || this.meshKey !== key) {
1147
+ if (this.mesh) {
1148
+ this.mesh.removeFromParent();
1149
+ disposeMesh(this.mesh);
1150
+ }
1151
+ this.meshKey = key;
1162
1152
  const material = new MeshBasicMaterial({
1163
1153
  transparent: true,
1164
1154
  depthWrite: false,
@@ -1193,6 +1183,12 @@ var Particles2D = class Particles2D extends Node2D {
1193
1183
  mesh.renderOrder = this.effectiveRenderOrder;
1194
1184
  }
1195
1185
  };
1186
+ /** Release an InstancedMesh's material and instance buffers, never UNIT_PLANE. */
1187
+ function disposeMesh(mesh) {
1188
+ mesh.dispose();
1189
+ const material = mesh.material;
1190
+ for (const m of Array.isArray(material) ? material : [material]) m.dispose();
1191
+ }
1196
1192
  const matrixScratch = new Matrix4();
1197
1193
  const colorScratchA = new Color();
1198
1194
  const colorScratchB = new Color();
@@ -1300,6 +1296,8 @@ var TileMap2D = class extends Node2D {
1300
1296
  _solid = [];
1301
1297
  /** Rebuild flags — raised when the map-shaping props are REPLACED. */
1302
1298
  geometryDirty = true;
1299
+ /** Reported once per atlas, so a bad grid says so on the first build only. */
1300
+ gridChecked = "";
1303
1301
  collidersDirty = true;
1304
1302
  /** Replace the whole array to change the map (mutations are not watched). */
1305
1303
  get cells() {
@@ -1393,6 +1391,11 @@ var TileMap2D = class extends Node2D {
1393
1391
  mat.needsUpdate = true;
1394
1392
  this.geometryDirty = true;
1395
1393
  }
1394
+ if (this.gridChecked !== this.texture) {
1395
+ this.gridChecked = this.texture;
1396
+ const problem = checkSheetGrid(this.texture, this.tileSize, this.tileSize, image.width, image.height);
1397
+ if (problem) diagnose(this.tree?.engine ?? null, "error", problem);
1398
+ }
1396
1399
  const columns = this.columns > 0 ? this.columns : Math.max(1, Math.floor(image.width / this.tileSize));
1397
1400
  const atlasRows = Math.max(1, Math.floor(image.height / this.tileSize));
1398
1401
  if (columns !== this.builtColumns || atlasRows !== this.builtRows) this.geometryDirty = true;