incanto 0.29.0 → 0.30.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 (38) hide show
  1. package/bin/incanto-editor.mjs +101 -28
  2. package/dist/2d.d.ts +16 -1
  3. package/dist/2d.js +2 -2
  4. package/dist/3d.d.ts +34 -1
  5. package/dist/3d.js +4 -4
  6. package/dist/{create-game-CbuLWorm.js → create-game-5z_QVtLx.js} +13 -9
  7. package/dist/{create-game-CNKXGfpr.js → create-game-DuBTv2zI.js} +14 -10
  8. package/dist/debug-draw-BM3DsvtT.js +18 -0
  9. package/dist/debug.js +1 -1
  10. package/dist/editor.js +1346 -1231
  11. package/dist/{gameplay-L05WgWd1.js → gameplay-Cfr6aFZ1.js} +12 -3
  12. package/dist/gameplay.js +1 -1
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.js +1 -1
  15. package/dist/{physics-2d-CCVTrKOd.js → physics-2d-3kOQCtgd.js} +26 -1
  16. package/dist/{physics-3d-BZZLtwJu.js → physics-3d-CeRH-Ff_.js} +38 -3
  17. package/dist/react.js +1 -1
  18. package/dist/{register-C44aSduO.js → register-DJ0SByQg.js} +1 -1
  19. package/dist/{editor-switch-CAKlJMIY.js → teardown-ByzfDPyu.js} +83 -4
  20. package/dist/test.js +6 -6
  21. package/dist/vite.d.ts +87 -1
  22. package/dist/vite.js +262 -3
  23. package/editor/assets/{agent8-DEVkEa3d.js → agent8-CAp0i5qn.js} +1 -1
  24. package/editor/assets/{debug-zGAtpDF0.js → debug-BoEYfbqK.js} +1 -1
  25. package/editor/assets/index-BO6WU8by.js +10696 -0
  26. package/editor/index.html +1 -1
  27. package/package.json +1 -1
  28. package/skills/incanto-editor.md +61 -8
  29. package/skills/incanto-physics-and-input.md +15 -0
  30. package/skills/incanto-verifying-your-game.md +6 -0
  31. package/templates-app/beacon-isle-3d/package.json +1 -1
  32. package/templates-app/beacon-isle-3d/vite.config.ts +7 -0
  33. package/templates-app/tps-3d/package.json +1 -1
  34. package/templates-app/tps-3d/vite.config.ts +7 -0
  35. package/templates-app/village-quest-3d/package.json +1 -1
  36. package/templates-app/village-quest-3d/vite.config.ts +7 -0
  37. package/dist/debug-draw-CZmOYjL2.js +0 -13
  38. package/editor/assets/index-Bx4UtWYY.js +0 -10586
package/editor/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Incanto Scene Editor</title>
7
7
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect width='16' height='16' rx='3' fill='%236ee7dc'/><text x='8' y='12' text-anchor='middle' font-size='11' font-family='monospace' fill='%230e1018'>i</text></svg>" />
8
- <script type="module" crossorigin src="./assets/index-Bx4UtWYY.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-BO6WU8by.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incanto",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -18,9 +18,50 @@ bunx incanto-editor level.scene.json --output build/level.scene.json --port 5179
18
18
 
19
19
  **Project mode** (no file argument — the usual way) scans the current directory for
20
20
  `*.scene.json` (skipping node_modules/dist/hidden dirs): one scene auto-opens; several
21
- show a picker; the picker can also CREATE a new scene (`levels/arena.scene.json`
22
- minimal 2D scene, parent dirs made). A `scenes` button switches files anytime. The page
23
- can only ever address `*.scene.json` files under the launch directory.
21
+ open the scene browser. The page can only ever address `*.scene.json` files under the
22
+ launch directory.
23
+
24
+ ### The scene browser (`scenes`)
25
+
26
+ The `scenes` button opens the project as a tree, not a list of paths:
27
+
28
+ - **Every `.json` in the project is listed** — a scene is JSON by definition, so
29
+ nothing else could be one — and each row says whether it IS a scene, read from
30
+ the file rather than guessed from its name. A scene declares itself:
31
+ `{"format": 1, "type": "scene", "name", "root"}`, the same four keys the loader
32
+ demands. Scene rows show `3d · 24 nodes`; anything else is dimmed and marked
33
+ `not a scene`, and opening it fails with the reason (`"type" must be "scene",
34
+ and this file has no "type"`). So a scene you saved as `level.json` is right
35
+ there and opens; `package.json` is right there and tells you why it will not.
36
+ (Non-scene contents never leave the server — only the reason does.)
37
+ - **Folders**, sorted, with a scene count each; a chain that holds nothing else
38
+ collapses into one row (`src / scenes`). Small projects open fully expanded.
39
+ - **The scene you are editing** is marked and revealed, and the cursor starts on it.
40
+ - **A filter box** — type any part of a path; matches show wherever they are hiding.
41
+ Keyboard from that box: `↑↓` move · `→` open a folder · `←` close it · `⏎` load ·
42
+ `Esc` close (backdrop and ✕ work too).
43
+ - Each row carries **when it was last written and how big it is**, which is usually
44
+ how you recognise the file you were just in.
45
+ - **create** makes a new scene at the path in the box — left empty it uses the
46
+ placeholder, which tracks the folder you are standing in, so a scene lands beside
47
+ its siblings rather than at the project root. Parent dirs are created.
48
+ - Loading another scene while you have unsaved EDITS asks first.
49
+
50
+ **The same browser opens inside a running game.** When the game's dev server serves
51
+ the project's scenes, `☰ debug ▸ ✎ edit this scene` gives you the whole project: the
52
+ editor opens on the scene the game is running, and `scenes` switches to any other one,
53
+ saves back to ITS file, and `play ▸ run as the game` boots whichever scene you loaded.
54
+ That needs one plugin in `vite.config.ts` (already there in every `incanto-new`
55
+ project):
56
+
57
+ ```ts
58
+ import { incantoScenes } from 'incanto/vite';
59
+ export default defineConfig({ plugins: [incantoScenes()] });
60
+ ```
61
+
62
+ Without it the `scenes` button is still there and says what to add — a missing
63
+ one-line plugin should be a sentence you can act on, not a button that quietly
64
+ is not there. The editor still edits the scene the game booted with meanwhile.
24
65
 
25
66
  Opens a local page (default `http://127.0.0.1:5179/`) with three panes:
26
67
 
@@ -45,9 +86,16 @@ Opens a local page (default `http://127.0.0.1:5179/`) with three panes:
45
86
  (dimension, gravity with real inputs, environment/input/assets/multiplayer).
46
87
  - **Viewport with DIRECT MANIPULATION** — a mode toolbar (top left) + the
47
88
  Unity/Godot keys: **W move · E rotate · R scale** (active mode highlighted).
48
- A collider-visibility toggle sits beside the mode tools: light-green
49
- wireframes for every body (2D shapes AND 3D box/sphere/capsule), persisted,
50
- and carried into play mode as the engine's physics debugDraw.
89
+ A collider-visibility toggle sits beside the mode tools, and it shows the
90
+ colliders the ENGINE builds, not a drawing of the `collider` prop: it attaches
91
+ Rapier to the edit view with `simulate: false` and turns on the same
92
+ `debugDraw` the play view uses. So a mesh-fitted body, an InstancedMesh3D
93
+ scatter's hulls, a terrain and a character capsule all appear — none of them
94
+ are in the scene JSON — and rotation, scale and offset are wherever physics
95
+ actually puts them. Nothing is simulated: bodies are posed from the tree each
96
+ tick (an outline follows a gizmo drag) and the solver never runs, so the scene
97
+ does not fall over while you edit it. Persisted, and carried into play mode
98
+ unchanged.
51
99
  Move: axis arrows (X red, Y green, Z blue in 3D) + center square for free
52
100
  movement. Rotate: drag the ring(s) — one ring in 2D, three world-axis rings
53
101
  in 3D — with a live degree readout at the cursor. Scale: the same arrows with
@@ -56,8 +104,13 @@ and carried into play mode as the engine's physics debugDraw.
56
104
  SNAP** — rotations to 15°, positions to the grid (10 px in 2D, 0.5 u in 3D),
57
105
  scales to 0.25 steps (the readout shows the snapped value).
58
106
  2D additionally supports click-pick, body drag, wheel zoom-at-cursor,
59
- right/middle/Shift-drag pan, Alt+wheel scale, and collider wireframes;
60
- `F` frames the scene in both dimensions. The add-node dropdown is grouped by
107
+ right/middle/Shift-drag pan, Alt+wheel scale, and collider wireframes.
108
+ **`F` frames the SELECTED node** (its whole subtree; a light or empty node has
109
+ no bounds, so the camera goes to it at a readable distance) — and the whole
110
+ scene when nothing is selected, which is the Maya/Unity/Unreal meaning of the
111
+ key. Same as the ⌖ frame button, and as `frame in view` in the tree's
112
+ right-click menu. This is how you find a node you selected in the tree that is
113
+ nowhere near the camera; double-click in the tree stays RENAME. The add-node dropdown is grouped by
61
114
  category (Core / 2D / 2D Physics / 3D / 3D Physics / Network, plus a trailing
62
115
  Other catch-all so an unclaimed type can never vanish from the list). The
63
116
  dropdown, inspector and in-editor docs are registry/schema-driven — newly
@@ -243,6 +243,21 @@ it, a map with terrain is a wall of grid lines and the shape you came to check i
243
243
  somewhere inside it. The debug overlay's **Colliders** menu item cycles
244
244
  off → all → selected over exactly these two fields.
245
245
 
246
+ ### Colliders without a simulation
247
+
248
+ `enablePhysics3D(engine, { simulate: false })` (and the 2D twin) builds the world
249
+ and never advances it: the body set is kept in step with the tree, every body is
250
+ posed FROM the tree each tick and propagated to its colliders, and then it stops
251
+ — no solver, no collision events, no write-back into node props. `debugDraw`
252
+ works exactly as above.
253
+
254
+ This is how the scene editor shows colliders while you edit: the real shapes,
255
+ including the ones that are not in the scene JSON at all (a mesh-fitted body, an
256
+ InstancedMesh3D scatter's hulls, a terrain, a character capsule), sitting where
257
+ the tree says, without your scene falling over while you look at it. Use it for
258
+ any "show me the collision geometry" tool. Do NOT use it to freeze a running
259
+ game — that is `engine.timeScale = 0`, which keeps the world coherent.
260
+
246
261
  ## Placement rules
247
262
 
248
263
  `CharacterController2D` MUST be a direct child of a `CharacterBody2D` — the
@@ -155,6 +155,12 @@ export default { plugins: [incantoScenes()] };
155
155
  Invalid `*.scene.json` saves keep the last good scene running and surface the
156
156
  IncantoError in the terminal AND as a browser overlay.
157
157
 
158
+ The same plugin serves this project's scenes to the editor, so the one you switch
159
+ into from the running game (`☰ debug ▸ ✎ edit this scene`) can open, create and save
160
+ ANY scene in the project — not just the one the game booted with. `incantoScenes({
161
+ root })` bounds that to a directory other than vite's; nothing outside it is readable
162
+ or writable, and none of it exists in a build (`configureServer`).
163
+
158
164
  ## 7. See inside the RUNNING game (debug overlay)
159
165
 
160
166
  ```ts
@@ -14,7 +14,7 @@
14
14
  "@dimforge/rapier2d-compat": "0.19.3",
15
15
  "@dimforge/rapier3d-compat": "0.19.3",
16
16
  "@pixiv/three-vrm": "^3.5.3",
17
- "incanto": "^0.29.0",
17
+ "incanto": "^0.30.0",
18
18
  "three": "^0.184.0"
19
19
  },
20
20
  "devDependencies": {
@@ -1,5 +1,12 @@
1
+ import { incantoLibrary, incantoScenes } from 'incanto/vite';
1
2
  import { defineConfig } from 'vite';
2
3
 
3
4
  export default defineConfig({
4
5
  base: './',
6
+ // Dev-server only, and both are why the editor is useful here:
7
+ // - incantoScenes(): validates every *.scene.json the moment you save it,
8
+ // AND serves this project's scenes, so the editor (☰ debug ▸ edit this
9
+ // scene ▸ scenes) can open, create and save any scene in the project.
10
+ // - incantoLibrary(): the agent8 asset catalog behind the 📚 buttons.
11
+ plugins: [incantoScenes(), incantoLibrary()],
5
12
  });
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.29.0",
16
+ "incanto": "^0.30.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -1,5 +1,12 @@
1
+ import { incantoLibrary, incantoScenes } from 'incanto/vite';
1
2
  import { defineConfig } from 'vite';
2
3
 
3
4
  export default defineConfig({
4
5
  base: './',
6
+ // Dev-server only, and both are why the editor is useful here:
7
+ // - incantoScenes(): validates every *.scene.json the moment you save it,
8
+ // AND serves this project's scenes, so the editor (☰ debug ▸ edit this
9
+ // scene ▸ scenes) can open, create and save any scene in the project.
10
+ // - incantoLibrary(): the agent8 asset catalog behind the 📚 buttons.
11
+ plugins: [incantoScenes(), incantoLibrary()],
5
12
  });
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.29.0",
16
+ "incanto": "^0.30.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -1,5 +1,12 @@
1
+ import { incantoLibrary, incantoScenes } from 'incanto/vite';
1
2
  import { defineConfig } from 'vite';
2
3
 
3
4
  export default defineConfig({
4
5
  base: './',
6
+ // Dev-server only, and both are why the editor is useful here:
7
+ // - incantoScenes(): validates every *.scene.json the moment you save it,
8
+ // AND serves this project's scenes, so the editor (☰ debug ▸ edit this
9
+ // scene ▸ scenes) can open, create and save any scene in the project.
10
+ // - incantoLibrary(): the agent8 asset catalog behind the 📚 buttons.
11
+ plugins: [incantoScenes(), incantoLibrary()],
5
12
  });
@@ -1,13 +0,0 @@
1
- //#region src/core/debug-draw.ts
2
- const sources = /* @__PURE__ */ new Set();
3
- /** @internal physics runtimes self-register on enable. */
4
- function registerDebugSource(source) {
5
- sources.add(source);
6
- return () => sources.delete(source);
7
- }
8
- /** @internal renderers pull their dimension's sources. */
9
- function debugSources(dimension) {
10
- return [...sources].filter((s) => s.dimension === dimension);
11
- }
12
- //#endregion
13
- export { registerDebugSource as n, debugSources as t };