incanto 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/incanto-check.mjs +13 -0
- package/bin/incanto-verify.mjs +134 -55
- package/dist/2d.d.ts +64 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +5 -5
- package/dist/3d.js +5 -4
- package/dist/{pathfinding-BqWBb0kh.d.ts → audio-player-D5GJgb_x.d.ts} +103 -38
- package/dist/{behavior-DWKTUzKI.d.ts → behavior-DsgayMsH.d.ts} +79 -1
- package/dist/{create-game-ClnIb_M5.js → create-game-BpunnGPX.js} +78 -13
- package/dist/{create-game-BCm38FJV.js → create-game-Caut3bqN.js} +21 -294
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/{duplicate-DJQd44CD.js → duplicate-E4FUs5Bn.js} +1 -1
- package/dist/editor.js +41 -19
- package/dist/{environment-presets-8cjF3t6w.js → environment-presets-BAWeOeqf.js} +50 -13
- package/dist/{gameplay-BBEjPFsR.js → gameplay-CaHqDiQD.js} +177 -24
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +97 -6
- package/dist/index.js +7 -7
- package/dist/{loader-D8n7TU8W.js → loader-DEe272nY.js} +900 -2
- package/dist/{loader-TvkRFbyL.d.ts → loader-DolLJWJn.d.ts} +13 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/pathfinding-_fGrCFmH.d.ts +28 -0
- package/dist/{physics-2d-DqdVp1bt.js → physics-2d-BXmu2i7W.js} +11 -3
- package/dist/{physics-3d-BP0DZb_1.js → physics-3d-ClxP6Uv7.js} +121 -17
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-BSu2dWGC.js → register-CNh4FlbD.js} +104 -16
- package/dist/{register-Da3hXh2H.js → register-D3yx8D4r.js} +228 -16
- package/dist/{registry-WWcQcfMr.js → registry-CF70EArN.js} +55 -3
- package/dist/{replay-BCMK_VRP.d.ts → replay-C5x2vPF5.d.ts} +2 -2
- package/dist/{replay-BlNuIDdg.js → replay-DlgHItNv.js} +57 -197
- package/dist/{split-screen-CL5Yvxse.js → split-screen-CBM9wcMX.js} +3 -3
- package/dist/{split-screen-BQ3tAsf-.d.ts → split-screen-D7OopelJ.d.ts} +2 -2
- package/dist/{src-DFpXBMJN.js → src-CH00_JsR.js} +1 -1
- package/dist/{teardown-CTTwhWSe.js → teardown-C7qP-dcC.js} +1 -1
- package/dist/{test-BeZ95pqw.js → test-BMkg8zMV.js} +29 -16
- package/dist/test.d.ts +45 -4
- package/dist/test.js +2 -2
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-DSJries_.js → agent8-m5mtAO_A.js} +1 -1
- package/editor/assets/{debug-D15Wi5TO.js → debug-CPhzCT8f.js} +1 -1
- package/editor/assets/{index-BjC88k97.js → index-D422P4kW.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +91 -0
- package/skills/incanto-3d-models.md +1 -1
- package/skills/incanto-assets.md +10 -1
- package/skills/incanto-audio.md +21 -13
- package/skills/incanto-behaviors-and-scripts.md +44 -3
- package/skills/incanto-building-2d-games.md +32 -4
- package/skills/incanto-building-3d-games.md +1 -1
- package/skills/incanto-editor.md +1 -1
- package/skills/incanto-gameplay-behaviors.md +39 -2
- package/skills/incanto-hud.md +5 -3
- package/skills/incanto-localization.md +7 -0
- package/skills/incanto-node-reference.md +12 -0
- package/skills/incanto-physics-and-input.md +23 -2
- package/skills/incanto-scene-json-authoring.md +6 -1
- package/skills/incanto-verifying-your-game.md +31 -1
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/dist/particle-sim-C5OfBbmU.d.ts +0 -77
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Scene, b as Engine } from "./behavior-
|
|
1
|
+
import { P as Scene, b as Engine } from "./behavior-DsgayMsH.js";
|
|
2
2
|
import { i as SceneJson } from "./schema-CFeioQRE.js";
|
|
3
3
|
|
|
4
4
|
//#region src/core/scene/loader.d.ts
|
|
@@ -6,6 +6,18 @@ interface LoadSceneOptions {
|
|
|
6
6
|
/** Resolve a sub-scene path referenced by `{instance: '<path>'}`. */
|
|
7
7
|
resolveScene?: (path: string) => SceneJson;
|
|
8
8
|
/**
|
|
9
|
+
* Assets declared ELSEWHERE in the project, for `$ref` validation.
|
|
10
|
+
*
|
|
11
|
+
* A scene a `NetworkSpawner` spawns resolves its refs against the HOST's
|
|
12
|
+
* `assets{}` — `remote-player.scene.json` names `$characters/base` and
|
|
13
|
+
* declares nothing itself, which is correct and cannot be checked from that
|
|
14
|
+
* one file. A tool with the whole project passes the union in; loading the
|
|
15
|
+
* file alone still fails, because alone it really cannot resolve.
|
|
16
|
+
*/
|
|
17
|
+
declaredAssets?: Record<string, {
|
|
18
|
+
type?: unknown;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
9
21
|
* Tool/preview mode (the editor's ▶ play strips behaviors — and their
|
|
10
22
|
* `static signals` with them): declare each connection's signal on its
|
|
11
23
|
* from-node instead of hard-failing with UNKNOWN_SIGNAL. Games should
|
package/dist/net.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
1
|
+
import { d as PropSchema, jt as Node } from "./behavior-DsgayMsH.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-D7OopelJ.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 NetworkManager, d as createLocalGameServer, f as LoopbackHub, l as LocalGameServer, n as registerNodesNet, o as applySyncPatch, p as LoopbackTransport, r as NetworkSpawner, t as createSplitScreen, u as LocalGameServerTransport } from "./split-screen-
|
|
2
|
+
import { a as NetworkManager, d as createLocalGameServer, f as LoopbackHub, l as LocalGameServer, n as registerNodesNet, o as applySyncPatch, p as LoopbackTransport, r as NetworkSpawner, t as createSplitScreen, u as LocalGameServerTransport } from "./split-screen-CBM9wcMX.js";
|
|
3
3
|
export { LocalGameServer, LocalGameServerTransport, LoopbackHub, LoopbackTransport, NetworkManager, NetworkSpawner, applySyncPatch, createAgent8Server, createLocalGameServer, createSplitScreen, registerNodesNet };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/core/pathfinding.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Grid A* — the pathfinding every top-down/RPG/tower-defense asks for and
|
|
4
|
+
* agents keep re-inventing badly. Pure and dimension-free: cells in, cells
|
|
5
|
+
* out; the caller maps cells to world units (px, meters, tiles).
|
|
6
|
+
*/
|
|
7
|
+
interface PathGrid {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
/** True = impassable. Out-of-bounds is always solid. */
|
|
11
|
+
solid(x: number, y: number): boolean;
|
|
12
|
+
}
|
|
13
|
+
interface FindPathOptions {
|
|
14
|
+
/** Allow diagonal steps (blocked from cutting corners). Default true. */
|
|
15
|
+
diagonal?: boolean;
|
|
16
|
+
/** Abort guard for huge/impossible searches. Default 20000 nodes. */
|
|
17
|
+
maxExpansions?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A* from `from` to `to` (inclusive cell coords). Returns the cell path
|
|
21
|
+
* INCLUDING both endpoints, or null when unreachable. Straight steps cost
|
|
22
|
+
* 1, diagonals √2; the heuristic is octile (admissible for both modes).
|
|
23
|
+
*/
|
|
24
|
+
declare function findPath(grid: PathGrid, from: [number, number], to: [number, number], opts?: FindPathOptions): [number, number][] | null;
|
|
25
|
+
/** Build a PathGrid from row-strings ('#' = solid) — tests and tile games. */
|
|
26
|
+
declare function gridFromRows(rows: readonly string[]): PathGrid;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { gridFromRows as i, PathGrid as n, findPath as r, FindPathOptions as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
2
|
+
import { k as diagnose } from "./loader-DEe272nY.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-
|
|
4
|
+
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-CNh4FlbD.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
import { t as withoutRapierInitNoise } from "./quiet-rapier-BAJ4K94N.js";
|
|
7
7
|
//#region src/2d/physics/physics-2d.ts
|
|
@@ -100,7 +100,10 @@ var Physics2D = class {
|
|
|
100
100
|
node.position = [t.x * SCALE - ox, t.y * SCALE - oy];
|
|
101
101
|
}
|
|
102
102
|
if (node instanceof RigidBody2D) {
|
|
103
|
-
if (!node.fixedRotation)
|
|
103
|
+
if (!node.fixedRotation) {
|
|
104
|
+
node.rotation = e.body.rotation() / DEG;
|
|
105
|
+
e.lastRot = node.rotation;
|
|
106
|
+
}
|
|
104
107
|
const lv = e.body.linvel();
|
|
105
108
|
node.linearVelocity = [lv.x * SCALE, lv.y * SCALE];
|
|
106
109
|
e.lastVX = node.linearVelocity[0] ?? 0;
|
|
@@ -428,6 +431,7 @@ var Physics2D = class {
|
|
|
428
431
|
collider,
|
|
429
432
|
lastX: wx,
|
|
430
433
|
lastY: wy,
|
|
434
|
+
lastRot: node.rotation,
|
|
431
435
|
lastVX: 0,
|
|
432
436
|
lastVY: 0
|
|
433
437
|
};
|
|
@@ -456,6 +460,10 @@ var Physics2D = class {
|
|
|
456
460
|
e.lastX = px;
|
|
457
461
|
e.lastY = py;
|
|
458
462
|
}
|
|
463
|
+
if (node.rotation !== e.lastRot) {
|
|
464
|
+
e.body.setRotation(node.rotation * DEG, true);
|
|
465
|
+
e.lastRot = node.rotation;
|
|
466
|
+
}
|
|
459
467
|
if (node instanceof RigidBody2D) {
|
|
460
468
|
const vx = node.linearVelocity[0] ?? 0;
|
|
461
469
|
const vy = node.linearVelocity[1] ?? 0;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
2
|
+
import { k as diagnose } from "./loader-DEe272nY.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import {
|
|
4
|
+
import { B as CharacterBody3D, G as validateCollider3D, H as RigidBody3D, V as PhysicsBody3D, W as Node3D, z as Area3D } from "./gameplay-CaHqDiQD.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
import { t as withoutRapierInitNoise } from "./quiet-rapier-BAJ4K94N.js";
|
|
7
|
-
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-
|
|
7
|
+
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-BAWeOeqf.js";
|
|
8
8
|
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
9
9
|
//#region src/3d/physics/collider-lines.ts
|
|
10
10
|
/**
|
|
@@ -318,6 +318,9 @@ var Physics3D = class {
|
|
|
318
318
|
rot[0] = eulerScratch.x / DEG;
|
|
319
319
|
rot[1] = eulerScratch.y / DEG;
|
|
320
320
|
rot[2] = eulerScratch.z / DEG;
|
|
321
|
+
e.lastRot[0] = rot[0];
|
|
322
|
+
e.lastRot[1] = rot[1];
|
|
323
|
+
e.lastRot[2] = rot[2];
|
|
321
324
|
}
|
|
322
325
|
const lv = e.body.linvel();
|
|
323
326
|
const nv = node.linearVelocity;
|
|
@@ -644,6 +647,11 @@ var Physics3D = class {
|
|
|
644
647
|
wy,
|
|
645
648
|
wz
|
|
646
649
|
],
|
|
650
|
+
lastRot: [
|
|
651
|
+
node.rotation[0] ?? 0,
|
|
652
|
+
node.rotation[1] ?? 0,
|
|
653
|
+
node.rotation[2] ?? 0
|
|
654
|
+
],
|
|
647
655
|
lastV: [
|
|
648
656
|
0,
|
|
649
657
|
0,
|
|
@@ -679,6 +687,21 @@ var Physics3D = class {
|
|
|
679
687
|
e.last[2] = p[2];
|
|
680
688
|
node._interpPrev = node._interpCurr = null;
|
|
681
689
|
}
|
|
690
|
+
const rx = node.rotation[0] ?? 0;
|
|
691
|
+
const ry = node.rotation[1] ?? 0;
|
|
692
|
+
const rz = node.rotation[2] ?? 0;
|
|
693
|
+
if (rx !== e.lastRot[0] || ry !== e.lastRot[1] || rz !== e.lastRot[2]) {
|
|
694
|
+
quatScratch.setFromEuler(eulerScratch.set(rx * DEG, ry * DEG, rz * DEG, "XYZ"));
|
|
695
|
+
e.body.setRotation({
|
|
696
|
+
x: quatScratch.x,
|
|
697
|
+
y: quatScratch.y,
|
|
698
|
+
z: quatScratch.z,
|
|
699
|
+
w: quatScratch.w
|
|
700
|
+
}, true);
|
|
701
|
+
e.lastRot[0] = rx;
|
|
702
|
+
e.lastRot[1] = ry;
|
|
703
|
+
e.lastRot[2] = rz;
|
|
704
|
+
}
|
|
682
705
|
if (node instanceof RigidBody3D) {
|
|
683
706
|
const v = [
|
|
684
707
|
node.linearVelocity[0] ?? 0,
|
|
@@ -854,15 +877,20 @@ function collectBodies(node, out) {
|
|
|
854
877
|
* Convex, always: a hull is a few planes to test against, where a triangle
|
|
855
878
|
* mesh is a tree of them, and nothing scattered across a map needs concavity.
|
|
856
879
|
*/
|
|
857
|
-
function meshShapedDesc(R, kind, size, scale) {
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
const
|
|
880
|
+
function meshShapedDesc(R, kind, size, scale, who) {
|
|
881
|
+
const sx = scale[0] ?? 1;
|
|
882
|
+
const sy = scale[1] ?? 1;
|
|
883
|
+
const sz = scale[2] ?? 1;
|
|
884
|
+
const x = (size[0] ?? 1) * sx;
|
|
885
|
+
const y = (size[1] ?? 1) * sy;
|
|
886
|
+
const z = (size[2] ?? 1) * sz;
|
|
887
|
+
const radial = Math.max(Math.abs(sx), Math.abs(sz));
|
|
888
|
+
if (who && kind !== "box" && kind !== "plane" && Math.abs(sx - sz) > 1e-6) console.warn(`[incanto] Collider on '${who}': shape 'auto' fits a ${kind} to a mesh scaled [${sx}, ${sy}, ${sz}]. A ${kind} has one radius, so the widest of x/z (${radial}) is used. Use a box, or scale x and z the same.`);
|
|
861
889
|
switch (kind) {
|
|
862
890
|
case "box": return R.ColliderDesc.cuboid(x / 2, y / 2, z / 2);
|
|
863
|
-
case "sphere": return R.ColliderDesc.ball(
|
|
864
|
-
case "capsule": return R.ColliderDesc.capsule(y / 2,
|
|
865
|
-
case "cylinder": return R.ColliderDesc.cylinder(y / 2,
|
|
891
|
+
case "sphere": return R.ColliderDesc.ball((size[0] ?? 1) * Math.max(radial, Math.abs(sy)));
|
|
892
|
+
case "capsule": return R.ColliderDesc.capsule(y / 2, (size[0] ?? 1) * radial);
|
|
893
|
+
case "cylinder": return R.ColliderDesc.cylinder(y / 2, (size[0] ?? 1) * radial);
|
|
866
894
|
case "plane": return R.ColliderDesc.cuboid(x / 2, .01, z / 2);
|
|
867
895
|
default: return R.ColliderDesc.convexHull(meshPoints(kind, [
|
|
868
896
|
x,
|
|
@@ -937,18 +965,79 @@ const TRIMESH_BUDGET = 2e4;
|
|
|
937
965
|
function isStaticShape(node) {
|
|
938
966
|
return !(node instanceof RigidBody3D || node instanceof CharacterBody3D);
|
|
939
967
|
}
|
|
940
|
-
/**
|
|
941
|
-
|
|
968
|
+
/**
|
|
969
|
+
* Every mesh a body carries, itself first — `auto` shapes itself on one.
|
|
970
|
+
*
|
|
971
|
+
* The transform chain is composed on the way down because `auto` used to drop
|
|
972
|
+
* it: the collector returned `{name, mesh, size}` and the `auto` branch built
|
|
973
|
+
* the shape at the BODY's origin, at the authored size, scale hard-coded to 1.
|
|
974
|
+
* The renderer applies all three every frame (`Node3D._syncObject3D`), so
|
|
975
|
+
* measured on a body whose plank child sits at `[0, 3, 0]`:
|
|
976
|
+
*
|
|
977
|
+
* ```
|
|
978
|
+
* drawn plank top y = 3.2
|
|
979
|
+
* ray straight down from y=10 : HIT Deck — surface at y=0.200
|
|
980
|
+
* ```
|
|
981
|
+
*
|
|
982
|
+
* and on one scaled 4×:
|
|
983
|
+
*
|
|
984
|
+
* ```
|
|
985
|
+
* drawn crate top y = 2.0
|
|
986
|
+
* ray straight down : HIT Crate — surface at y=0.500
|
|
987
|
+
* ray down inside the DRAWN 4 m crate : MISS
|
|
988
|
+
* ```
|
|
989
|
+
*
|
|
990
|
+
* You walk through the deck you can see and land on an invisible slab at ground
|
|
991
|
+
* level — from the shape whose entire promise is that "a blocker can never
|
|
992
|
+
* disagree with what the player sees". The sibling paths in this same file were
|
|
993
|
+
* already right: `syncScatters` honours every scatter row's translation, yaw
|
|
994
|
+
* and scale, and `modelTriangles` bakes a GLB's world matrices. Only the
|
|
995
|
+
* primitive-mesh branch dropped it.
|
|
996
|
+
*/
|
|
997
|
+
function meshesUnder(node, out, models, at = [
|
|
998
|
+
0,
|
|
999
|
+
0,
|
|
1000
|
+
0
|
|
1001
|
+
], turn = [
|
|
1002
|
+
0,
|
|
1003
|
+
0,
|
|
1004
|
+
0
|
|
1005
|
+
], scale = [
|
|
1006
|
+
1,
|
|
1007
|
+
1,
|
|
1008
|
+
1
|
|
1009
|
+
]) {
|
|
942
1010
|
if (isMountedModel(node)) models.push(node);
|
|
943
1011
|
else {
|
|
944
1012
|
const self = node;
|
|
945
1013
|
if (typeof self.mesh === "string" && Array.isArray(self.size)) out.push({
|
|
946
1014
|
name: node.name,
|
|
947
1015
|
mesh: self.mesh,
|
|
948
|
-
size: self.size
|
|
1016
|
+
size: self.size,
|
|
1017
|
+
at: [...at],
|
|
1018
|
+
turn: [...turn],
|
|
1019
|
+
scale: [...scale]
|
|
949
1020
|
});
|
|
950
1021
|
}
|
|
951
|
-
for (const child of node.children)
|
|
1022
|
+
for (const child of node.children) {
|
|
1023
|
+
const t = child;
|
|
1024
|
+
const p = Array.isArray(t.position) ? t.position : [];
|
|
1025
|
+
const r = Array.isArray(t.rotation) ? t.rotation : [];
|
|
1026
|
+
const c = Array.isArray(t.scale) ? t.scale : [];
|
|
1027
|
+
meshesUnder(child, out, models, [
|
|
1028
|
+
at[0] + (p[0] ?? 0) * scale[0],
|
|
1029
|
+
at[1] + (p[1] ?? 0) * scale[1],
|
|
1030
|
+
at[2] + (p[2] ?? 0) * scale[2]
|
|
1031
|
+
], [
|
|
1032
|
+
turn[0] + (r[0] ?? 0),
|
|
1033
|
+
turn[1] + (r[1] ?? 0),
|
|
1034
|
+
turn[2] + (r[2] ?? 0)
|
|
1035
|
+
], [
|
|
1036
|
+
scale[0] * (c[0] ?? 1),
|
|
1037
|
+
scale[1] * (c[1] ?? 1),
|
|
1038
|
+
scale[2] * (c[2] ?? 1)
|
|
1039
|
+
]);
|
|
1040
|
+
}
|
|
952
1041
|
}
|
|
953
1042
|
/** Every scatter field asking to be solid (see InstancedMesh3D.collider). */
|
|
954
1043
|
function collectScatters(node, out) {
|
|
@@ -1019,7 +1108,10 @@ function parseCollider3D(R, node) {
|
|
|
1019
1108
|
const desc = buildColliderDesc3D(R, collider, node.name, node);
|
|
1020
1109
|
if (!desc) return null;
|
|
1021
1110
|
const offset = collider.offset;
|
|
1022
|
-
if (Array.isArray(offset))
|
|
1111
|
+
if (Array.isArray(offset)) {
|
|
1112
|
+
const at = desc.translation;
|
|
1113
|
+
desc.setTranslation(at.x + (offset[0] ?? 0), at.y + (offset[1] ?? 0), at.z + (offset[2] ?? 0));
|
|
1114
|
+
}
|
|
1023
1115
|
return desc;
|
|
1024
1116
|
}
|
|
1025
1117
|
/**
|
|
@@ -1070,8 +1162,20 @@ function buildColliderDesc3D(R, collider, nodeName, node) {
|
|
|
1070
1162
|
const parts = meshes.length + models.length;
|
|
1071
1163
|
if (parts > 1) console.warn(`[incanto] Collider on '${nodeName}': shape 'auto' fits ONE mesh and took '${(mesh ?? model)?.name}'; ${parts - 1} other mesh(es) here are not solid. Give each part its own body.`);
|
|
1072
1164
|
if (mesh) {
|
|
1073
|
-
const desc = meshShapedDesc(R, mesh.mesh, mesh.size,
|
|
1074
|
-
if (desc)
|
|
1165
|
+
const desc = meshShapedDesc(R, mesh.mesh, mesh.size, mesh.scale, nodeName);
|
|
1166
|
+
if (desc) {
|
|
1167
|
+
desc.setTranslation(mesh.at[0], mesh.at[1], mesh.at[2]);
|
|
1168
|
+
if (mesh.turn[0] !== 0 || mesh.turn[1] !== 0 || mesh.turn[2] !== 0) {
|
|
1169
|
+
quatScratch.setFromEuler(eulerScratch.set(mesh.turn[0] * DEG, mesh.turn[1] * DEG, mesh.turn[2] * DEG, "XYZ"));
|
|
1170
|
+
desc.setRotation({
|
|
1171
|
+
x: quatScratch.x,
|
|
1172
|
+
y: quatScratch.y,
|
|
1173
|
+
z: quatScratch.z,
|
|
1174
|
+
w: quatScratch.w
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
return desc;
|
|
1178
|
+
}
|
|
1075
1179
|
} else if (model && node) {
|
|
1076
1180
|
const tri = modelTriangles(node, model);
|
|
1077
1181
|
if (!tri) return null;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-
|
|
1
|
+
import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-DsgayMsH.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-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-Caut3bqN.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-BpunnGPX.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { O as Node, k as diagnose, w as effectiveOrder } from "./loader-DEe272nY.js";
|
|
2
|
+
import { L as translateOn, t as registerCoreNodes } from "./register-D3yx8D4r.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
|
-
import { i as getNodeSchema, l as registerNode } from "./registry-
|
|
5
|
+
import { i as getNodeSchema, l as registerNode } from "./registry-CF70EArN.js";
|
|
6
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-CY-mrr1L.js";
|
|
7
|
+
import { N as localFromWorld, P as worldPosition } from "./gameplay-CaHqDiQD.js";
|
|
7
8
|
import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
|
|
8
9
|
import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry, SRGBColorSpace } from "three";
|
|
9
10
|
//#region src/2d/physics/collider-validate.ts
|
|
@@ -94,6 +95,30 @@ var Node2D = class extends Node {
|
|
|
94
95
|
return new Object3D();
|
|
95
96
|
}
|
|
96
97
|
/** @internal Push JSON props onto the backing object. Called every frame. */
|
|
98
|
+
/**
|
|
99
|
+
* Has this node produced the thing `static: true` is about to freeze?
|
|
100
|
+
*
|
|
101
|
+
* `static` latches after the first sync, and a textured node's first sync
|
|
102
|
+
* happens BEFORE its texture has decoded — `TextureLoader.load()` returns a
|
|
103
|
+
* `Texture` with `image === undefined` and fills it asynchronously, while
|
|
104
|
+
* `Renderer2D.render()` calls `assets.load()` and `syncTree2D()` in the same
|
|
105
|
+
* frame. So the state frozen was `visible = false`, forever. Measured on two
|
|
106
|
+
* identical sprites differing only in `static`:
|
|
107
|
+
*
|
|
108
|
+
* ```
|
|
109
|
+
* frame 1 Backdrop(static) visible: false Control visible: false
|
|
110
|
+
* 600 frames later Backdrop(static) visible: false width 1
|
|
111
|
+
* Control visible: true width 64
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* Nothing throws: the texture loaded fine, so `assetErrors()` is empty,
|
|
115
|
+
* `stats().errors` is 0, and `framing` reads props rather than pixels and
|
|
116
|
+
* still calls the node on-screen. Overridden by the nodes that wait on an
|
|
117
|
+
* image; a node with nothing to wait for is ready by definition.
|
|
118
|
+
*/
|
|
119
|
+
_staticReady(_assets) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
97
122
|
_syncObject2D(_assets) {
|
|
98
123
|
const o = this._ensureObject2D();
|
|
99
124
|
o.position.set(this.position[0] ?? 0, -(this.position[1] ?? 0), 0);
|
|
@@ -302,7 +327,8 @@ var Joint2D = class extends Node2D {
|
|
|
302
327
|
},
|
|
303
328
|
target: {
|
|
304
329
|
default: "",
|
|
305
|
-
nodePath: true
|
|
330
|
+
nodePath: true,
|
|
331
|
+
required: true
|
|
306
332
|
},
|
|
307
333
|
anchor: { default: [0, 0] },
|
|
308
334
|
targetAnchor: { default: [0, 0] },
|
|
@@ -344,7 +370,13 @@ const UNIT_PLANE$2 = new PlaneGeometry(1, 1);
|
|
|
344
370
|
var Sprite2D = class extends Node2D {
|
|
345
371
|
static typeName = "Sprite2D";
|
|
346
372
|
static props = {
|
|
347
|
-
texture: {
|
|
373
|
+
texture: {
|
|
374
|
+
default: "",
|
|
375
|
+
asset: {
|
|
376
|
+
kind: "texture",
|
|
377
|
+
refOnly: true
|
|
378
|
+
}
|
|
379
|
+
},
|
|
348
380
|
anchor: { default: [.5, .5] },
|
|
349
381
|
flipX: { default: false },
|
|
350
382
|
flipY: { default: false },
|
|
@@ -386,6 +418,9 @@ var Sprite2D = class extends Node2D {
|
|
|
386
418
|
height: image.height
|
|
387
419
|
};
|
|
388
420
|
}
|
|
421
|
+
_staticReady(assets) {
|
|
422
|
+
return this.texture === "" || this.resolveTexture(assets) !== null;
|
|
423
|
+
}
|
|
389
424
|
_syncObject2D(assets) {
|
|
390
425
|
super._syncObject2D(assets);
|
|
391
426
|
const quad = this._quad();
|
|
@@ -422,7 +457,13 @@ var AnimatedSprite2D = class extends Sprite2D {
|
|
|
422
457
|
static typeName = "AnimatedSprite2D";
|
|
423
458
|
static signals = ["animationFinished"];
|
|
424
459
|
static props = {
|
|
425
|
-
sheet: {
|
|
460
|
+
sheet: {
|
|
461
|
+
default: "",
|
|
462
|
+
asset: {
|
|
463
|
+
kind: "spritesheet",
|
|
464
|
+
refOnly: true
|
|
465
|
+
}
|
|
466
|
+
},
|
|
426
467
|
animations: { default: {} },
|
|
427
468
|
autoplay: { default: "" }
|
|
428
469
|
};
|
|
@@ -564,18 +605,36 @@ var Camera2D = class extends Node2D {
|
|
|
564
605
|
if (!this.follow) return;
|
|
565
606
|
const target = this.getNodeOrNull(this.follow);
|
|
566
607
|
if (!(target instanceof Node2D)) return;
|
|
567
|
-
const tx =
|
|
568
|
-
const
|
|
608
|
+
const [tx = 0, ty = 0] = worldPosition(target);
|
|
609
|
+
const [px = 0, py = 0] = worldPosition(this);
|
|
569
610
|
const s = Math.min(Math.max(this.smoothing, 0), .99);
|
|
570
611
|
const f = s <= 0 ? 1 : 1 - s ** (dt * 60);
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
this.position = [px + (tx - px) * f, py + (ty - py) * f];
|
|
612
|
+
const [lx = 0, ly = 0] = localFromWorld(this, [px + (tx - px) * f, py + (ty - py) * f]);
|
|
613
|
+
this.position = [lx, ly];
|
|
574
614
|
}
|
|
575
615
|
/** View center after clamping the (vw×vh)/zoom view rect inside `limits`. */
|
|
616
|
+
/**
|
|
617
|
+
* The view centre the renderer draws around, in WORLD space.
|
|
618
|
+
*
|
|
619
|
+
* It used to read `this.position` raw — the LOCAL prop — while every other
|
|
620
|
+
* 2D node gets its ancestors composed for free by the three scene graph. So a
|
|
621
|
+
* camera parented to the player, the Godot/Phaser idiom the authoring skill
|
|
622
|
+
* explicitly permits, framed the world origin:
|
|
623
|
+
*
|
|
624
|
+
* ```
|
|
625
|
+
* player world position : [1400, 900]
|
|
626
|
+
* renderer view centre : {"x":0,"y":0}
|
|
627
|
+
* framing : camera /Level/Player/Cam centred [1400, 900]
|
|
628
|
+
* 1 in view, 0 outside it
|
|
629
|
+
* ```
|
|
630
|
+
*
|
|
631
|
+
* `framing` composes full world matrices, so the instrument the skills tell
|
|
632
|
+
* you to trust certified a view the renderer never drew.
|
|
633
|
+
*/
|
|
576
634
|
clampedCenter(vw, vh) {
|
|
577
|
-
|
|
578
|
-
let
|
|
635
|
+
const world = worldPosition(this);
|
|
636
|
+
let cx = world[0] ?? 0;
|
|
637
|
+
let cy = world[1] ?? 0;
|
|
579
638
|
if (this.limits.length !== 0 && this.limits.length !== 4) throw new IncantoError("BAD_FORMAT", `Camera2D '${this.name}' limits must be [] or [minX,minY,maxX,maxY], got length ${this.limits.length}.`);
|
|
580
639
|
if (this.limits.length === 4) {
|
|
581
640
|
const [minX, minY, maxX, maxY] = this.limits;
|
|
@@ -828,7 +887,14 @@ var Label = class extends Node2D {
|
|
|
828
887
|
fontSize: { default: 16 },
|
|
829
888
|
color: { default: "#ffffff" },
|
|
830
889
|
font: { default: "monospace" },
|
|
831
|
-
align: { default: "left" }
|
|
890
|
+
align: { default: "left" },
|
|
891
|
+
opacity: {
|
|
892
|
+
default: 1,
|
|
893
|
+
range: {
|
|
894
|
+
min: 0,
|
|
895
|
+
max: 1
|
|
896
|
+
}
|
|
897
|
+
}
|
|
832
898
|
};
|
|
833
899
|
text = "";
|
|
834
900
|
fontSize = 16;
|
|
@@ -836,6 +902,16 @@ var Label = class extends Node2D {
|
|
|
836
902
|
font = "monospace";
|
|
837
903
|
/** 'left' | 'center' | 'right' — anchor of the text block on the node origin. */
|
|
838
904
|
align = "left";
|
|
905
|
+
/**
|
|
906
|
+
* 0..1, like `Sprite2D` and `ColorRect2D`.
|
|
907
|
+
*
|
|
908
|
+
* Label was the one 2D drawable without it, and the gap showed up through
|
|
909
|
+
* `FloatAway` — whose own doc names "a 2D `Label`" as a node it works on.
|
|
910
|
+
* `FloatAway` writes `opacity` when the node has one, so on a Label the
|
|
911
|
+
* number rose to full height at FULL opacity and then vanished in a single
|
|
912
|
+
* frame: the pop that behavior exists to avoid.
|
|
913
|
+
*/
|
|
914
|
+
opacity = 1;
|
|
839
915
|
quadMesh = null;
|
|
840
916
|
canvas = null;
|
|
841
917
|
lastKey = "";
|
|
@@ -863,7 +939,8 @@ var Label = class extends Node2D {
|
|
|
863
939
|
this.lastKey = key;
|
|
864
940
|
this.rasterize();
|
|
865
941
|
}
|
|
866
|
-
quad.visible =
|
|
942
|
+
quad.visible = this.opacity > 0;
|
|
943
|
+
quad.material.opacity = this.opacity;
|
|
867
944
|
quad.renderOrder = this.effectiveRenderOrder;
|
|
868
945
|
}
|
|
869
946
|
rasterize() {
|
|
@@ -1306,7 +1383,13 @@ var TileMap2D = class extends Node2D {
|
|
|
1306
1383
|
static typeName = "TileMap2D";
|
|
1307
1384
|
static props = {
|
|
1308
1385
|
/** Atlas texture asset ref; tiles are tileSize×tileSize squares in it. */
|
|
1309
|
-
texture: {
|
|
1386
|
+
texture: {
|
|
1387
|
+
default: "",
|
|
1388
|
+
asset: {
|
|
1389
|
+
kind: "texture",
|
|
1390
|
+
refOnly: true
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1310
1393
|
tileSize: { default: 32 },
|
|
1311
1394
|
/** Atlas columns; 0 = derive from the texture width. */
|
|
1312
1395
|
columns: { default: 0 },
|
|
@@ -1398,6 +1481,11 @@ var TileMap2D = class extends Node2D {
|
|
|
1398
1481
|
}
|
|
1399
1482
|
return this.tileMesh;
|
|
1400
1483
|
}
|
|
1484
|
+
_staticReady(assets) {
|
|
1485
|
+
if (this.texture === "" || !assets) return this.texture === "";
|
|
1486
|
+
const image = assets.getTexture(this.texture).image;
|
|
1487
|
+
return Boolean(image?.width);
|
|
1488
|
+
}
|
|
1401
1489
|
_syncObject2D(assets) {
|
|
1402
1490
|
super._syncObject2D(assets);
|
|
1403
1491
|
const mesh = this._mesh();
|