incanto 0.45.1 → 0.47.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 +5 -1
- package/bin/incanto-feel.mjs +5 -1
- package/bin/incanto-frame.mjs +57 -6
- package/bin/incanto-model.mjs +79 -10
- package/bin/incanto-playtest.mjs +5 -1
- package/bin/incanto-verify.mjs +214 -0
- package/dist/2d.d.ts +1 -1
- package/dist/2d.js +1 -1
- package/dist/3d.d.ts +90 -5
- package/dist/3d.js +92 -5
- package/dist/{create-game-DFRbG0Bj.js → create-game-CniOiWzN.js} +1 -1
- package/dist/{create-game-Gifrjhnz.js → create-game-D16MVIPO.js} +24 -5
- package/dist/{editor-switch-DVwIGZdK.d.ts → editor-switch-DAvWQeld.d.ts} +1 -1
- package/dist/editor.js +4674 -4346
- package/dist/{environment-presets-DUsBqvtk.js → environment-presets-D1b0ydTS.js} +5 -4
- package/dist/{frame-report-Ct8XgsmV.d.ts → frame-report-DZ70IY26.d.ts} +25 -0
- package/dist/{frame-report-Lr3VO24R.js → frame-report-njybhZon.js} +130 -3
- package/dist/index.js +1 -1
- package/dist/{physics-3d-DFqMtBUD.js → physics-3d-CSoGjM8P.js} +1 -1
- package/dist/react.js +1 -1
- package/dist/{src-DUxGnvq3.js → src-Ca3oV1fe.js} +1 -1
- package/dist/{teardown-yePMOE1K.js → teardown-BKTCzLek.js} +3 -2
- package/dist/{test-DD5scWfm.js → test-E4-otKqK.js} +54 -7
- package/dist/test.d.ts +55 -1
- package/dist/test.js +2 -2
- package/dist/vite.d.ts +34 -3
- package/dist/vite.js +104 -12
- package/editor/assets/{agent8-B25qJ5Wo.js → agent8-_007gPF8.js} +1 -1
- package/editor/assets/{debug-CUsz-pT8.js → debug-0DI_MJaq.js} +1 -1
- package/editor/assets/{index-3u3GVteP.js → index-B-6eYZEi.js} +173 -96
- package/editor/index.html +1 -1
- package/package.json +3 -2
- package/skills/incanto-3d-models.md +30 -0
- package/skills/incanto-editor.md +6 -1
- package/skills/incanto-verifying-your-game.md +60 -1
- package/templates-app/beacon-isle-3d/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/3d.js
CHANGED
|
@@ -1,9 +1,96 @@
|
|
|
1
1
|
import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-BQOeAid6.js";
|
|
2
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-
|
|
3
|
-
import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-
|
|
4
|
-
import { a as
|
|
2
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-D1b0ydTS.js";
|
|
3
|
+
import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-D16MVIPO.js";
|
|
4
|
+
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-njybhZon.js";
|
|
5
5
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
6
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
6
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-CSoGjM8P.js";
|
|
7
|
+
//#region src/3d/model-verdict.ts
|
|
8
|
+
/** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
|
|
9
|
+
const MIXAMO = /^mixamorig[:_]?/i;
|
|
10
|
+
/**
|
|
11
|
+
* Anything outside this is not a character at this scale, and the fix is one
|
|
12
|
+
* prop. Wide on purpose: a 2.4m ogre is a design choice, a 40m one is
|
|
13
|
+
* centimetres.
|
|
14
|
+
*/
|
|
15
|
+
const CHARACTER_HEIGHT = {
|
|
16
|
+
min: .4,
|
|
17
|
+
max: 4
|
|
18
|
+
};
|
|
19
|
+
/** What `targetHeight` gets set to when a model is plainly the wrong scale. */
|
|
20
|
+
const DEFAULT_TARGET_HEIGHT = 1.7;
|
|
21
|
+
/** Fraction of the model's own height that its origin may drift before it matters. */
|
|
22
|
+
const ORIGIN_TOLERANCE = .25;
|
|
23
|
+
function rigOf(facts) {
|
|
24
|
+
if (facts.vrm && facts.vrm.humanBones > 0) return "vrm-humanoid";
|
|
25
|
+
if (facts.nodes.some((n) => MIXAMO.test(n.name))) return "mixamorig";
|
|
26
|
+
return facts.skins > 0 ? "other" : "none";
|
|
27
|
+
}
|
|
28
|
+
function modelVerdict(facts, target) {
|
|
29
|
+
const rig = rigOf(facts);
|
|
30
|
+
const kind = facts.meshes === 0 && facts.animations.length > 0 ? "animation" : "model";
|
|
31
|
+
const height = facts.bbox ? facts.bbox.size[1] : 0;
|
|
32
|
+
const offset = facts.bbox ? [
|
|
33
|
+
facts.bbox.center[0],
|
|
34
|
+
facts.bbox.min[1],
|
|
35
|
+
facts.bbox.center[2]
|
|
36
|
+
] : [
|
|
37
|
+
0,
|
|
38
|
+
0,
|
|
39
|
+
0
|
|
40
|
+
];
|
|
41
|
+
const slack = Math.max(height * ORIGIN_TOLERANCE, .05);
|
|
42
|
+
const grounded = !facts.bbox || Math.abs(offset[0]) <= slack && Math.abs(offset[1]) <= slack && Math.abs(offset[2]) <= slack;
|
|
43
|
+
const oddSize = height > 0 && (height < CHARACTER_HEIGHT.min || height > CHARACTER_HEIGHT.max);
|
|
44
|
+
const props = { model: `$${target?.key ?? "model"}` };
|
|
45
|
+
if (oddSize) props.targetHeight = DEFAULT_TARGET_HEIGHT;
|
|
46
|
+
return {
|
|
47
|
+
kind,
|
|
48
|
+
rig,
|
|
49
|
+
takesLibraryClips: kind === "model" && (rig === "mixamorig" || rig === "vrm-humanoid"),
|
|
50
|
+
height,
|
|
51
|
+
originOffset: offset,
|
|
52
|
+
groundedAtOrigin: grounded,
|
|
53
|
+
embeddedClips: facts.animations.map((a) => a.name),
|
|
54
|
+
sceneJson: target ? {
|
|
55
|
+
assets: { [target.key]: {
|
|
56
|
+
type: kind,
|
|
57
|
+
url: target.url
|
|
58
|
+
} },
|
|
59
|
+
node: kind === "animation" ? null : {
|
|
60
|
+
name: titleCase(target.key),
|
|
61
|
+
type: "ModelInstance3D",
|
|
62
|
+
props
|
|
63
|
+
}
|
|
64
|
+
} : null
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const titleCase = (key) => key.split(/[-_\s]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("") || "Model";
|
|
68
|
+
const round = (n) => String(Math.round(n * 100) / 100);
|
|
69
|
+
/** The verdict as sentences: what to do, and what will bite if you do not. */
|
|
70
|
+
function verdictText(v) {
|
|
71
|
+
const lines = [];
|
|
72
|
+
if (v.kind === "animation") {
|
|
73
|
+
lines.push("an animation CLIP — no mesh of its own. It plays ON a character: declare it as {\"type\":\"animation\"} and point a ModelInstance3D's `animation` at it. Used as a `model` it draws nothing at all, with no error");
|
|
74
|
+
if (v.embeddedClips.length > 0) lines.push(`clip: ${v.embeddedClips.join(", ")}`);
|
|
75
|
+
return lines.join("\n");
|
|
76
|
+
}
|
|
77
|
+
if (v.rig === "mixamorig") lines.push("mixamorig rig — the 3d/animations clips play on this as they are");
|
|
78
|
+
else if (v.rig === "vrm-humanoid") lines.push("VRM humanoid — clips are retargeted onto it automatically");
|
|
79
|
+
else if (v.rig === "other") lines.push("skinned, but NOT a mixamorig rig — the 3d/animations clips will not bind to it (bones are matched by name; a mismatch keeps the bind pose and only warns)");
|
|
80
|
+
else lines.push("no skeleton — a prop, not a character; `animation` does nothing here");
|
|
81
|
+
if (v.height > 0) {
|
|
82
|
+
const odd = v.height < CHARACTER_HEIGHT.min || v.height > CHARACTER_HEIGHT.max;
|
|
83
|
+
lines.push(`stands ${round(v.height)} units tall` + (odd ? ` — not a character's size; set targetHeight (${DEFAULT_TARGET_HEIGHT}) to fix it` : ""));
|
|
84
|
+
}
|
|
85
|
+
if (!v.groundedAtOrigin) {
|
|
86
|
+
const [x, y, z] = v.originOffset;
|
|
87
|
+
const where = Math.abs(y) > Math.abs(x) && Math.abs(y) > Math.abs(z) ? `${round(Math.abs(y))} units ${y > 0 ? "above" : "below"} the origin` : `off-centre by [${round(x)}, ${round(y)}, ${round(z)}]`;
|
|
88
|
+
lines.push(`does NOT stand on its own origin — it sits ${where}. A node at [0,0,0] puts it there too; offset the node, or expect an empty-looking frame`);
|
|
89
|
+
}
|
|
90
|
+
if (v.embeddedClips.length > 0) lines.push(`clips in the file: ${v.embeddedClips.join(", ")} (play by name, no asset needed)`);
|
|
91
|
+
return lines.join("\n");
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
7
94
|
//#region src/3d/terrain-nav.ts
|
|
8
95
|
function buildTerrainNav(terrain, opts) {
|
|
9
96
|
const cellSize = opts?.cellSize ?? 2;
|
|
@@ -115,4 +202,4 @@ function createNavDebugNode(nav, opts) {
|
|
|
115
202
|
return node;
|
|
116
203
|
}
|
|
117
204
|
//#endregion
|
|
118
|
-
export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, InstancedMesh3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, River3D, SIGNATURE_GRID, StaticBody3D, TERRAIN_THEMES, Terrain3D, TextureCache3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath };
|
|
205
|
+
export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, InstancedMesh3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, River3D, SIGNATURE_GRID, StaticBody3D, TERRAIN_THEMES, Terrain3D, TextureCache3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, modelVerdict, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath, verdictText };
|
|
@@ -3,7 +3,7 @@ import { n as loadScene, o as computeViewport, s as resolveViewport, v as diagno
|
|
|
3
3
|
import { h as Engine, m as AudioPlayer } from "./register-BSXV8T9F.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
|
|
6
|
-
import { a as openBundledEditor, i as devServerLibrary, n as pauseWhenHidden, r as crossFade, t as teardown } from "./teardown-
|
|
6
|
+
import { a as openBundledEditor, i as devServerLibrary, n as pauseWhenHidden, r as crossFade, t as teardown } from "./teardown-BKTCzLek.js";
|
|
7
7
|
import { n as registerGameplayBehaviors } from "./gameplay-BQOeAid6.js";
|
|
8
8
|
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-R2JTnIMw.js";
|
|
9
9
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
@@ -3,12 +3,12 @@ import { n as loadScene, v as diagnose, w as registerBehavior } from "./loader-r
|
|
|
3
3
|
import { _ as qualityCaps, h as Engine, m as AudioPlayer, y as qualityRendering } from "./register-BSXV8T9F.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
|
|
6
|
-
import { a as openBundledEditor, i as devServerLibrary, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, t as teardown } from "./teardown-
|
|
6
|
+
import { a as openBundledEditor, i as devServerLibrary, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, t as teardown } from "./teardown-BKTCzLek.js";
|
|
7
7
|
import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-BQOeAid6.js";
|
|
8
8
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
9
|
-
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-
|
|
10
|
-
import { a as
|
|
11
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
9
|
+
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-D1b0ydTS.js";
|
|
10
|
+
import { a as frameSignature, i as frameImage, o as frameStats } from "./frame-report-njybhZon.js";
|
|
11
|
+
import { n as enablePhysics3D } from "./physics-3d-CSoGjM8P.js";
|
|
12
12
|
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";
|
|
13
13
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
14
14
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -1545,6 +1545,12 @@ function prune(obj, visited) {
|
|
|
1545
1545
|
//#endregion
|
|
1546
1546
|
//#region src/3d/renderer.ts
|
|
1547
1547
|
/**
|
|
1548
|
+
* How long a capture waits for the game's own loop before drawing its own
|
|
1549
|
+
* frame. Long enough that a running game answers from its normal loop (16ms),
|
|
1550
|
+
* short enough that a paused or occluded tab still answers promptly.
|
|
1551
|
+
*/
|
|
1552
|
+
const CAPTURE_NUDGE_MS = 120;
|
|
1553
|
+
/**
|
|
1548
1554
|
* WebGL presentation layer: subscribes to `engine.updated`, mirrors the active
|
|
1549
1555
|
* scene's node tree onto a three.js scene, applies the scene `environment`
|
|
1550
1556
|
* header (ambient/background/sky/fog/shadows/exposure — see Environment3D),
|
|
@@ -1890,6 +1896,14 @@ var Renderer3D = class {
|
|
|
1890
1896
|
resolve,
|
|
1891
1897
|
reject
|
|
1892
1898
|
});
|
|
1899
|
+
setTimeout(() => {
|
|
1900
|
+
if (this.pendingCaptures.length > 0) try {
|
|
1901
|
+
this.render();
|
|
1902
|
+
} catch (error) {
|
|
1903
|
+
const e = error instanceof Error ? error : new Error(String(error));
|
|
1904
|
+
for (const w of this.pendingCaptures.splice(0)) w.reject(e);
|
|
1905
|
+
}
|
|
1906
|
+
}, CAPTURE_NUDGE_MS);
|
|
1893
1907
|
});
|
|
1894
1908
|
}
|
|
1895
1909
|
pendingCaptures = [];
|
|
@@ -2446,11 +2460,16 @@ async function createGame3D(opts) {
|
|
|
2446
2460
|
const onFrameRequest = (data) => {
|
|
2447
2461
|
const request = data;
|
|
2448
2462
|
const id = request?.id;
|
|
2463
|
+
hot.send("incanto:frame-ack", { id });
|
|
2449
2464
|
captureFramePixels().then((shot) => hot.send("incanto:frame-report", {
|
|
2450
2465
|
id,
|
|
2451
2466
|
report: {
|
|
2452
2467
|
...frameStats(shot.pixels, shot.width, shot.height, { grid: request?.grid }),
|
|
2453
|
-
signature: frameSignature(shot.pixels, shot.width, shot.height)
|
|
2468
|
+
signature: frameSignature(shot.pixels, shot.width, shot.height),
|
|
2469
|
+
...request?.image ? { image: frameImage(shot.pixels, shot.width, shot.height, (w, h) => Object.assign(document.createElement("canvas"), {
|
|
2470
|
+
width: w,
|
|
2471
|
+
height: h
|
|
2472
|
+
}), request.image) } : {}
|
|
2454
2473
|
}
|
|
2455
2474
|
})).catch((error) => hot.send("incanto:frame-report", {
|
|
2456
2475
|
id,
|