incanto 0.25.3 → 0.26.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/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-BGtXxzJn.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-D4_I76v2.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-D8QvwvOm.css">
11
11
  </head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incanto",
3
- "version": "0.25.3",
3
+ "version": "0.26.0",
4
4
  "description": "Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -331,6 +331,9 @@
331
331
  {
332
332
  "$ref": "#/$defs/Water3D"
333
333
  },
334
+ {
335
+ "$ref": "#/$defs/WaterCutout3D"
336
+ },
334
337
  {
335
338
  "$ref": "#/$defs/_instance"
336
339
  }
@@ -6691,6 +6694,114 @@
6691
6694
  }
6692
6695
  },
6693
6696
  "required": ["name", "type"]
6697
+ },
6698
+ "WaterCutout3D": {
6699
+ "type": "object",
6700
+ "properties": {
6701
+ "name": {
6702
+ "type": "string"
6703
+ },
6704
+ "uid": {
6705
+ "type": "string"
6706
+ },
6707
+ "type": {
6708
+ "const": "WaterCutout3D"
6709
+ },
6710
+ "groups": {
6711
+ "type": "array",
6712
+ "items": {
6713
+ "type": "string"
6714
+ }
6715
+ },
6716
+ "tags": {
6717
+ "type": "object"
6718
+ },
6719
+ "props": {
6720
+ "type": "object",
6721
+ "properties": {
6722
+ "position": {
6723
+ "type": "array",
6724
+ "items": {
6725
+ "type": "number"
6726
+ },
6727
+ "minItems": 3,
6728
+ "maxItems": 3,
6729
+ "default": [0, 0, 0]
6730
+ },
6731
+ "rotation": {
6732
+ "type": "array",
6733
+ "items": {
6734
+ "type": "number"
6735
+ },
6736
+ "minItems": 3,
6737
+ "maxItems": 3,
6738
+ "default": [0, 0, 0]
6739
+ },
6740
+ "static": {
6741
+ "type": "boolean",
6742
+ "default": false
6743
+ },
6744
+ "scale": {
6745
+ "type": "array",
6746
+ "items": {
6747
+ "type": "number"
6748
+ },
6749
+ "minItems": 3,
6750
+ "maxItems": 3,
6751
+ "default": [1, 1, 1]
6752
+ },
6753
+ "visible": {
6754
+ "type": "boolean",
6755
+ "default": true
6756
+ },
6757
+ "renderOrder": {
6758
+ "type": "number",
6759
+ "default": 0
6760
+ },
6761
+ "orderGroup": {
6762
+ "type": "string",
6763
+ "enum": ["background", "terrain", "default", "characters", "effects", "overlay"],
6764
+ "default": "default"
6765
+ },
6766
+ "size": {
6767
+ "type": "array",
6768
+ "items": {
6769
+ "type": "number"
6770
+ },
6771
+ "minItems": 3,
6772
+ "maxItems": 3,
6773
+ "default": [2, 1, 1]
6774
+ },
6775
+ "enabled": {
6776
+ "type": "boolean",
6777
+ "default": true
6778
+ }
6779
+ },
6780
+ "additionalProperties": false
6781
+ },
6782
+ "script": {
6783
+ "type": "object",
6784
+ "properties": {
6785
+ "name": {
6786
+ "type": "string"
6787
+ },
6788
+ "props": {
6789
+ "type": "object"
6790
+ }
6791
+ },
6792
+ "required": ["name"]
6793
+ },
6794
+ "network": {
6795
+ "type": "object"
6796
+ },
6797
+ "children": {
6798
+ "type": "array",
6799
+ "items": {
6800
+ "$ref": "#/$defs/node"
6801
+ }
6802
+ }
6803
+ },
6804
+ "required": ["name", "type"]
6694
6805
  }
6695
6806
  }
6696
6807
  }
@@ -789,6 +789,44 @@ Swimming down is a different optical world, and the engine renders it as one:
789
789
  "caustics": { "intensity": 0.6 } } } }
790
790
  ```
791
791
 
792
+ ### `WaterCutout3D` — the thing that holds the water back
793
+
794
+ Water is ONE surface; it has no idea a boat has an inside. Float an open hull
795
+ and every crest that rises above its floor renders as sea sloshing through the
796
+ deck. Freeboard cannot promise otherwise — a big enough swell always wins for a
797
+ frame. So name the geometry that keeps the water out:
798
+
799
+ ```json
800
+ { "name": "Rowboat", "type": "RigidBody3D",
801
+ "script": { "name": "Buoyancy", "props": { "draft": 0.2 } },
802
+ "children": [
803
+ { "name": "DryInside", "type": "WaterCutout3D",
804
+ "props": { "size": [2.55, 1.2, 0.95], "position": [-0.1, 0.4, 0] } },
805
+ … hull, seats, oars …
806
+ ] }
807
+ ```
808
+
809
+ It MUST be a CHILD of what it belongs to — a hull, a diving bell, a well under a
810
+ dock, a cave mouth. That parent is the mechanism, not a convenience: the water
811
+ re-draws it (the part inside the box) into the depth pre-pass at the near plane,
812
+ and then hides itself behind it exactly as it hides behind any solid thing. At
813
+ the scene root a cutout has nothing to stand in for, and the loader says so.
814
+
815
+ | prop | default | meaning |
816
+ |---|---|---|
817
+ | `size` | `[2, 1, 1]` | box extent in meters, centered on the node — which PART of the parent holds water back |
818
+ | `enabled` | `true` | live toggle — a scuttled hull can start letting the sea in |
819
+
820
+ **A cutout cannot punch a hole in open water**, because nothing is ever cut out
821
+ of the water. The mask is the parent's own silhouette, so water can only be
822
+ hidden behind geometry the player is already looking at. Overshoot the box and
823
+ more of that hull holds water back; undershoot and water stands in the bow. Size
824
+ it to the interior and err large.
825
+
826
+ Needs the depth pre-pass, so `"quality": "fancy"` (the default). Four cutouts per
827
+ water surface; each costs one extra draw of its parent in that pass. Skinned and
828
+ instanced meshes re-draw at their rest pose — hang cutouts on ordinary geometry.
829
+
792
830
  ### Where water meets ground
793
831
 
794
832
  The waterline is the thing that gives game water away. Incanto fades it in
@@ -471,8 +471,8 @@ all a raft, a buoy, a crate or a body needs to bob, settle and ride the swell.
471
471
  | Prop | Default | Meaning |
472
472
  |---|---|---|
473
473
  | `water` | `""` | Water3D node path; empty = the first Water3D in the tree (a wrong path fails hard) |
474
- | `draft` | `0.35` | how deep the hull sits at rest, in meters (its waterline below the body origin) |
475
- | `stiffness` | `14` | float stiffness (1/s²) higher snaps to the surface, lower wallows |
474
+ | `draft` | `0.35` | where the resting WATERLINE sits below the body origin, in meters — the hull floats with its origin that far above the water |
475
+ | `stiffness` | `3` | how stiffly it returns to that waterline (extra g of lift per draft of submersion): 1 wallows, 3 is a firm dinghy, 8 is a cork |
476
476
  | `damping` | `3.5` | vertical damping (1/s) — how fast the bobbing settles |
477
477
  | `drift` | `0.6` | how hard wave SLOPES carry the body along (0 = bob on the spot) |
478
478
  | `drag` | `0.9` | horizontal drag while submerged (1/s) |
@@ -492,6 +492,22 @@ thing slides down it, so a raft left alone wanders with the swell instead of
492
492
  bobbing on the spot. The lift is capped at a few g — water pushes back, it
493
493
  never launches a body that has been dragged deep.
494
494
 
495
+ **The lift cancels gravity AT the waterline**, so the hull holds that line
496
+ instead of sinking until a spring happens to match its weight. That is what
497
+ `draft` buys you: set it to the freeboard you want and the boat sits there.
498
+
499
+ **Model the hull BELOW the floor.** A boat whose lowest surface is its interior
500
+ floor cannot float dry — the sea closes over that floor and renders inside the
501
+ hull. Give it something to displace with (a keel/hull box under the floor) and
502
+ a `draft` that puts the waterline on it:
503
+
504
+ ```json
505
+ { "name": "Hull", "type": "MeshInstance3D",
506
+ "props": { "mesh": "box", "size": [3, 0.34, 1.06], "position": [0, -0.24, 0] } }
507
+ // …with the body origin at the interior floor and "draft": 0.2 — the water
508
+ // then rests 20 cm below the floor, on the hull, and the boat is dry inside.
509
+ ```
510
+
495
511
  For the water's own height anywhere (jetties, spawn heights, an AI deciding
496
512
  where the shore is), `Water3D.heightAt(x, z)` answers the same surface.
497
513
 
@@ -996,6 +996,20 @@ Signals: `blocksChanged`
996
996
 
997
997
  Signals: `entered(body)` · `exited(body)`
998
998
 
999
+ ## `WaterCutout3D` — `incanto/3d`
1000
+
1001
+ | Prop | Default | Kind |
1002
+ |---|---|---|
1003
+ | `position` | `[0,0,0]` | array |
1004
+ | `rotation` | `[0,0,0]` | array |
1005
+ | `static` | `false` | boolean |
1006
+ | `scale` | `[1,1,1]` | array |
1007
+ | `visible` | `true` | boolean |
1008
+ | `renderOrder` | `0` | number |
1009
+ | `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
1010
+ | `size` | `[2,1,1]` | array |
1011
+ | `enabled` | `true` | boolean |
1012
+
999
1013
  ## Gameplay behaviors — `incanto/gameplay`
1000
1014
 
1001
1015
  Ready-made `Behavior`s auto-registered by `createGame2D`/`createGame3D` (opt out
@@ -1008,7 +1022,7 @@ wire their signals through scene `connections`. Full guide: `incanto-gameplay-be
1008
1022
  |---|---|---|
1009
1023
  | `water` | `""` | string |
1010
1024
  | `draft` | `0.35` | number |
1011
- | `stiffness` | `14` | number |
1025
+ | `stiffness` | `3` | number |
1012
1026
  | `damping` | `3.5` | number |
1013
1027
  | `drift` | `0.6` | number |
1014
1028
  | `drag` | `0.9` | number |
@@ -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.25.3",
17
+ "incanto": "^0.26.0",
18
18
  "three": "^0.184.0"
19
19
  },
20
20
  "devDependencies": {
@@ -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.25.3",
16
+ "incanto": "^0.26.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -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.25.3",
16
+ "incanto": "^0.26.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {