incanto 0.27.0 → 0.29.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/README.md +44 -0
- package/bin/incanto-editor.mjs +118 -1
- package/dist/2d.d.ts +38 -5
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +496 -150
- package/dist/3d.js +5 -5
- package/dist/{behavior-CPibUfnH.d.ts → behavior-BAc0erXF.d.ts} +21 -0
- package/dist/{create-game-DUAtTqID.js → create-game-CNKXGfpr.js} +270 -47
- package/dist/{create-game-C0bPoURs.js → create-game-CbuLWorm.js} +53 -14
- package/dist/debug.d.ts +51 -6
- package/dist/debug.js +242 -19
- package/dist/editor-switch-B0wB_DSr.d.ts +59 -0
- package/dist/editor-switch-CAKlJMIY.js +161 -0
- package/dist/editor.d.ts +49 -0
- package/dist/editor.js +8439 -0
- package/dist/{gameplay-Ddk13pQ6.js → gameplay-L05WgWd1.js} +220 -37
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +22 -3
- package/dist/index.js +2 -2
- package/dist/{loader-DILt9PGC.d.ts → loader-B242FF6N.d.ts} +1 -1
- package/dist/net.d.ts +1 -1
- package/dist/net.js +2 -2
- package/dist/{pathfinding-RWYkNKx9.d.ts → pathfinding-BwD974Ss.d.ts} +1 -1
- package/dist/{physics-2d-DiVFFlH3.js → physics-2d-CCVTrKOd.js} +62 -2
- package/dist/{physics-3d-4mGzOZ2J.js → physics-3d-BZZLtwJu.js} +439 -8
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-nObreUQR.js → register-BTg0EM7s.js} +35 -3
- package/dist/{register-DcHXS1MA.js → register-C44aSduO.js} +5694 -5108
- package/dist/{register-CvpSUU3O.js → register-DWcWq4QG.js} +22 -2
- package/dist/{register-BFFE1Mh1.js → register-MelqEdza.js} +1 -1
- package/dist/test.d.ts +35 -3
- package/dist/test.js +104 -10
- package/dist/vite.d.ts +53 -1
- package/dist/vite.js +94 -2
- package/editor/assets/{agent8-DElIPozC.js → agent8-DEVkEa3d.js} +1 -1
- package/editor/assets/debug-zGAtpDF0.js +2 -0
- package/editor/assets/index-Bx4UtWYY.js +10586 -0
- package/editor/index.html +3 -157
- package/package.json +3 -2
- package/schemas/scene.schema.json +110 -4
- package/skills/incanto-3d-models.md +38 -0
- package/skills/incanto-assets.md +13 -0
- package/skills/incanto-building-3d-games.md +83 -6
- package/skills/incanto-editor.md +151 -0
- package/skills/incanto-environment.md +88 -1
- package/skills/incanto-node-reference.md +35 -1
- package/skills/incanto-physics-and-input.md +45 -6
- package/skills/incanto-verifying-your-game.md +51 -2
- package/templates-app/beacon-isle-3d/docs/project-3d-rules.md +5 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/docs/project-3d-rules.md +5 -0
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/docs/project-3d-rules.md +5 -0
- package/templates-app/village-quest-3d/package.json +1 -1
- package/editor/assets/index-BrneVqN0.js +0 -8330
- package/editor/assets/index-D8QvwvOm.css +0 -1
|
@@ -97,10 +97,19 @@ never be one node each. One instanced node draws them all at once:
|
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
- Each row: `[x, y, z, yawDeg?, scale?]` — dense enough to GENERATE hundreds
|
|
100
|
-
(pair with `terrain.heightAt` for y).
|
|
100
|
+
(pair with `snapToGround` or `terrain.heightAt` for y).
|
|
101
101
|
- Same `mesh`/`size`/`material` surface as MeshInstance3D. Replace the whole
|
|
102
|
-
`transforms` array to update.
|
|
103
|
-
|
|
102
|
+
`transforms` array to update.
|
|
103
|
+
- **`collider` makes the whole field SOLID**: `"collider": {}` gives every row
|
|
104
|
+
its own static collider SHAPED LIKE THE MESH — a faceted `gem` stone collides
|
|
105
|
+
as that stone's own hull, not as a ball tucked inside it, so you can't clip
|
|
106
|
+
through the corners that stick out. Sized from `size` × that row's scale and
|
|
107
|
+
turned by its yaw. All of them hang off one fixed body, so a fifty-stone
|
|
108
|
+
scatter costs fifty shapes and no per-frame work. A boulder field the player
|
|
109
|
+
walks straight through is the tell that a world is scenery rather than a
|
|
110
|
+
place.
|
|
111
|
+
`{ "shape": "sphere", "radius": r }` / `{ "shape": "box", "size": [x,y,z] }`
|
|
112
|
+
opt out into a cheaper approximation when a rough blocker is all you want.
|
|
104
113
|
|
|
105
114
|
### `LoftMesh3D` (smooth swept hulls — vehicle bodies, canopies)
|
|
106
115
|
|
|
@@ -367,14 +376,82 @@ show it as the background (otherwise `background` color applies). Standard
|
|
|
367
376
|
materials need this OR explicit lights to be visible. An explicit HDRI wins
|
|
368
377
|
over the `sky`'s image-based ambience.
|
|
369
378
|
|
|
370
|
-
##
|
|
379
|
+
## NEVER compute a Y against the terrain by hand
|
|
380
|
+
|
|
381
|
+
This is the single most repeated mistake in scene authoring, and it is not a
|
|
382
|
+
careless one: the number is right when you write it and wrong the moment
|
|
383
|
+
anything reshapes the ground under it — a river carving its bed, a basin, a new
|
|
384
|
+
seed, a generator that mirrors a carve slightly differently. Boulders in
|
|
385
|
+
mid-air, a player buried to the waist, bridge posts hanging over a creek: all
|
|
386
|
+
the same bug.
|
|
387
|
+
|
|
388
|
+
**Say what you mean instead.** Every `Node3D` takes `snapToGround`:
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{ "name": "Boulder", "type": "MeshInstance3D",
|
|
392
|
+
"props": { "mesh": "gem", "size": [1.2, 0.8, 1.1],
|
|
393
|
+
"position": [12, 0, -30], // y is IGNORED
|
|
394
|
+
"snapToGround": 0.4 } } // half its height → it rests on the ground
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
- `true` — put the node's origin on the ground.
|
|
398
|
+
- a number — the same, lifted that many metres (a prop whose origin is at its
|
|
399
|
+
middle wants half its height).
|
|
400
|
+
- `false` — "this hangs in the air ON PURPOSE" (a bridge deck, a lantern, a
|
|
401
|
+
cloud). The grounding check below skips these, so mark them.
|
|
402
|
+
- omitted — `y` is used exactly as authored.
|
|
403
|
+
|
|
404
|
+
Resolved at load, in the same frame the terrain is built, and it honours an
|
|
405
|
+
ancestor's yaw, so props under a turned rig land where they look.
|
|
406
|
+
|
|
407
|
+
**And check it.** `findFloatingProps` from `incanto/test` reports every prop
|
|
408
|
+
whose underside is off the ground, instanced fields row by row:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
import { findFloatingProps } from 'incanto/test';
|
|
412
|
+
const off = findFloatingProps(gameJson);
|
|
413
|
+
ok(`every prop meets the ground (${off.length})`, off.length === 0);
|
|
414
|
+
for (const o of off) console.error(` ${o.path}: ${o.gap > 0 ? 'floats' : 'buried'} ${o.gap} m`);
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Put it in your `verify.ts` next to `auditScene`. It costs nothing and it is the
|
|
418
|
+
difference between shipping a floating bridge and not.
|
|
419
|
+
|
|
420
|
+
## The loading screen has to cover the WHOLE boot
|
|
421
|
+
|
|
422
|
+
Downloading the assets is the first half. Building a dressed scene and
|
|
423
|
+
compiling its GPU programs is the second, and on a big outdoor scene the second
|
|
424
|
+
is the longer one (measured on the creek template: 1.5 s of assets, then **7 s
|
|
425
|
+
of shader compile** — 49 programs). A bar that reaches 100% on the last
|
|
426
|
+
downloaded byte and then leaves the player looking at a blank canvas is worse
|
|
427
|
+
than no bar at all.
|
|
428
|
+
|
|
429
|
+
So run ONE bar across both, with `createGame3D`'s `onProgress`:
|
|
371
430
|
|
|
372
431
|
```ts
|
|
373
432
|
import { assetUrls, preloadUrls } from 'incanto';
|
|
433
|
+
|
|
434
|
+
const progress = (fraction: number, label: string) => {
|
|
435
|
+
bar.style.width = `${Math.round(fraction * 100)}%`;
|
|
436
|
+
text.textContent = `${Math.round(fraction * 100)}% · ${label}`;
|
|
437
|
+
};
|
|
374
438
|
await preloadUrls(assetUrls(sceneJson.assets), (done, total) =>
|
|
375
|
-
|
|
439
|
+
progress((done / total) * 0.5, 'assets'));
|
|
440
|
+
const game = await createGame3D({
|
|
441
|
+
canvas, scene: sceneJson,
|
|
442
|
+
onProgress: (f, label) => progress(0.5 + f * 0.5, label),
|
|
443
|
+
});
|
|
444
|
+
document.querySelector('#loading')?.remove(); // now it is really ready
|
|
376
445
|
```
|
|
377
|
-
|
|
446
|
+
|
|
447
|
+
`onProgress` reports `scene` → `physics` → `renderer` → `shaders` → `ready`,
|
|
448
|
+
and yields a frame at each step so the bar actually repaints (a callback fired
|
|
449
|
+
inside one synchronous block updates nothing a player can see). `createGame3D`
|
|
450
|
+
also draws its FIRST FRAME before it resolves, so the compile lands while your
|
|
451
|
+
screen is still up rather than after you remove it.
|
|
452
|
+
|
|
453
|
+
Preloading warms the HTTP cache before the engine starts; failures warn, never
|
|
454
|
+
block.
|
|
378
455
|
|
|
379
456
|
## Particles
|
|
380
457
|
|
package/skills/incanto-editor.md
CHANGED
|
@@ -110,6 +110,157 @@ Save activates only when the working scene differs from the original
|
|
|
110
110
|
(`Ctrl/Cmd+S`); undo is `Ctrl/Cmd+Z`. Saving writes pretty-printed JSON to
|
|
111
111
|
`--output` (default: the input file).
|
|
112
112
|
|
|
113
|
+
## The agent8 asset library (📚)
|
|
114
|
+
|
|
115
|
+
Every field that takes a resource carries a **📚** button:
|
|
116
|
+
|
|
117
|
+
| Field | Writes |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `ModelInstance3D.model` | scene asset (`model`) + the `$ref` |
|
|
120
|
+
| `ModelInstance3D.animation` | scene asset (`animation`) + the `$ref` — or type an embedded clip name |
|
|
121
|
+
| `Sprite2D.texture`, `AnimatedSprite2D.sheet` | scene asset (`texture` / `spritesheet`) + the `$ref` |
|
|
122
|
+
| `TileMap2D.texture` | scene asset (`texture`) + the `$ref` |
|
|
123
|
+
| `Sprite3D.texture`, `AnimatedSprite3D.sheet` | the URL (3D sprites take raw URLs) |
|
|
124
|
+
| material `map` / `normalMap`, `Tree3D.leafTexture`, `AudioPlayer.src` | the URL |
|
|
125
|
+
| ASSETS + form, and any asset's `url` | the URL (+ a suggested key) |
|
|
126
|
+
|
|
127
|
+
It opens the agent8 catalog that opens the agent8 catalog: shelves down the
|
|
128
|
+
left (**Everything** / 2D · sprite characters / 3D · characters, monsters,
|
|
129
|
+
objects, vehicles, weapons, polyhaven, textures), keyword search, and a detail
|
|
130
|
+
pane with the description, tags, format/size/mime and the URL. **Everything** is
|
|
131
|
+
the tagless shelf — the one that searches the whole catalog and the only way to
|
|
132
|
+
reach assets the tag tree does not name (sounds, one-off props).
|
|
133
|
+
|
|
134
|
+
The preview is the real thing: an image renders as an image, a **GLB is
|
|
135
|
+
rendered by the engine itself** (turntable, drag to spin, `targetHeight: 1` so
|
|
136
|
+
everything frames the same) — the same loader the game will use, so what you
|
|
137
|
+
see is what the scene gets.
|
|
138
|
+
|
|
139
|
+
Picking does the whole job, not half of it:
|
|
140
|
+
|
|
141
|
+
- a **URL field** (material map, leaf texture, audio src) gets the URL;
|
|
142
|
+
- a **`$assetKey` field** (`ModelInstance3D.model`, sprite texture/sheet) gets a
|
|
143
|
+
scene `assets{}` entry AND the ref that resolves to it — one action, no
|
|
144
|
+
separate "declare the asset" step. An entry with the same url is reused, so
|
|
145
|
+
browsing to the model you already have does not duplicate it;
|
|
146
|
+
- the ASSETS **+** form fills the url and suggests the key from the file name.
|
|
147
|
+
|
|
148
|
+
A sheet lands as a `spritesheet`, not a plain `texture` — the engine hard-fails
|
|
149
|
+
on the latter in an `AnimatedSprite2D.sheet` — with `frameWidth`/`frameHeight`
|
|
150
|
+
taken from the catalog's metadata when it carries them, and LEFT BLANK when it
|
|
151
|
+
does not (an invented frame size renders wrong art in silence; a blank field
|
|
152
|
+
asks you the question).
|
|
153
|
+
|
|
154
|
+
**Sprite configs are the good pick.** Many sprite characters ship a sibling
|
|
155
|
+
`<name>.json` (frame grid + named frame ranges) and the card wears an
|
|
156
|
+
`animated` badge. Picking one declares the sheet asset with its frame size AND
|
|
157
|
+
writes the node's `animations` + `autoplay` — one click gives you a sprite that
|
|
158
|
+
actually animates, instead of a still frame and a homework assignment.
|
|
159
|
+
|
|
160
|
+
What is on the shelves depends on the account behind your token. The public
|
|
161
|
+
catalog at the time of writing:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
3d 5,325 characters 392 · objects 1,992 · textures 2,538 · polyhaven 2,723
|
|
165
|
+
animations 24 · shaders 14 · vehicles 12 · weapons 6 · monsters 6
|
|
166
|
+
2d 436 projects 361 (ui, characters, sounds) · sprite_characters 54
|
|
167
|
+
building 9 · minecraft 7 · characterportraits 5
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Tags are lowercase — the catalog's own convention, and the query is
|
|
171
|
+
case-sensitive. If a shelf you expect is missing it is missing upstream: browse
|
|
172
|
+
from **Everything** and the tree shows what is actually there.
|
|
173
|
+
|
|
174
|
+
A field that knows where its art lives opens there — a model at
|
|
175
|
+
`3d / characters`, a clip at `3d / animations`, a material map at
|
|
176
|
+
`3d / textures`, a sprite sheet at `2d / sprite_characters` — and the rest start
|
|
177
|
+
at the root. It is a hint, not a cage: the breadcrumb walks anywhere. Either way
|
|
178
|
+
the kind filter applies, so a "model" field never offers you a .png.
|
|
179
|
+
|
|
180
|
+
**Access.** The catalog is per-account and its CORS list has no localhost in it,
|
|
181
|
+
so the page cannot call it directly — `incanto-editor` proxies it at
|
|
182
|
+
`GET /api/library`. Give the server a Verse8 token:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
bunx incanto-editor --token <v8 access token>
|
|
186
|
+
INCANTO_V8_TOKEN=<token> bunx incanto-editor # same thing
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
With no token the 📚 panel asks for one and keeps it in the browser
|
|
190
|
+
(`localStorage`), which is the right answer for a shared machine — the token is
|
|
191
|
+
sent only to your own editor server, never written to disk by it, and forwarded
|
|
192
|
+
upstream as a bearer. `INCANTO_LIBRARY_URL` points the proxy somewhere else
|
|
193
|
+
(a mirror, or a stub in tests).
|
|
194
|
+
|
|
195
|
+
A game hosting the editor (the live play ⇄ edit switch) has no catalog of its
|
|
196
|
+
own — but its dev server can serve the same proxy, and then the 📚 works there
|
|
197
|
+
too:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
// vite.config.ts
|
|
201
|
+
import { incantoLibrary, incantoScenes } from 'incanto/vite';
|
|
202
|
+
export default defineConfig({ plugins: [incantoScenes(), incantoLibrary()] });
|
|
203
|
+
```
|
|
204
|
+
```ts
|
|
205
|
+
// main.ts
|
|
206
|
+
createGame3D({
|
|
207
|
+
...,
|
|
208
|
+
debug: import.meta.env.VITE_INCANTO_DEBUG === '1',
|
|
209
|
+
editor: { library: true }, // "my dev server serves /api/library"
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
`incantoLibrary()` is `apply: 'serve'` — dev only, nothing reaches a build, and
|
|
214
|
+
the token stays in the terminal that started the server (`INCANTO_V8_TOKEN`, or
|
|
215
|
+
`incantoLibrary({ token })`). `editor: { library: fn }` plugs in your own
|
|
216
|
+
transport instead. With neither, the buttons are simply absent.
|
|
217
|
+
|
|
218
|
+
## Play, and the switch into the running game
|
|
219
|
+
|
|
220
|
+
**▶ play** means two different things and the editor asks which:
|
|
221
|
+
|
|
222
|
+
- **▶ preview here** — the scene simulates inside the editor viewport with the
|
|
223
|
+
game's TypeScript behaviors STRIPPED. Engine-native motion only (physics,
|
|
224
|
+
animation, water) — a quick look, not the game.
|
|
225
|
+
- **⤢ run as the game** — the page BECOMES the game: `createGame3D` boots the
|
|
226
|
+
working scene with your behaviors, your loading screen and the debug overlay.
|
|
227
|
+
This is the real thing, and it carries the edits you have not saved.
|
|
228
|
+
|
|
229
|
+
From that game, the ☰ debug menu's **✎ edit this scene** switches straight back
|
|
230
|
+
to the editor — same window, no reload, and the edit camera picks up the pose
|
|
231
|
+
the player was looking from. **✕ exit** in the editor returns to the game
|
|
232
|
+
without playing. The pair is one loop you can ride all session:
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
game --(☰ debug ▸ ✎ edit this scene)--> editor
|
|
236
|
+
editor --(▶ play ▸ ⤢ run as the game)--> game
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
What crosses is the AUTHORED scene, never the stepped tree: a running scene has
|
|
240
|
+
been moved by physics and spawned into by behaviors, and editing that would mean
|
|
241
|
+
editing wherever the simulation happened to be. Games hosting the editor
|
|
242
|
+
themselves (`createGame3D({ editor: … })`) get a **save** button only when they
|
|
243
|
+
pass `editor.save` — otherwise edits live as long as the session does.
|
|
244
|
+
|
|
245
|
+
## Animating a model from the inspector
|
|
246
|
+
|
|
247
|
+
Select a `ModelInstance3D` and everything about what it is DOING sits in one
|
|
248
|
+
**animation** card: the clip, whether it loops, how fast, and where in the clip
|
|
249
|
+
it starts. The clip list is the model's own embedded clips plus the scene's
|
|
250
|
+
animation assets, and 📚 pulls a clip-only GLB from the agent8 library
|
|
251
|
+
(`3d / animations`) — picking one declares the asset and writes the ref.
|
|
252
|
+
|
|
253
|
+
- **speed** −3…3. `1` is as authored, `0` freezes the pose, negative plays
|
|
254
|
+
backwards. It retimes the clip already playing, so dragging it is smooth.
|
|
255
|
+
- **animationOffset** seconds into the clip. Changing it re-seeks live, which
|
|
256
|
+
makes it a scrubber as well as a stagger control — give copies different
|
|
257
|
+
offsets so a row of torches stops flickering in lockstep.
|
|
258
|
+
- The **upper-body layer** (a second clip on the upper body only) is folded away
|
|
259
|
+
until you use it.
|
|
260
|
+
|
|
261
|
+
The edit viewport keeps ambient visuals moving, so all of this animates while
|
|
262
|
+
you are editing — you see the change, not a still frame.
|
|
263
|
+
|
|
113
264
|
## Painting TileMap2D levels
|
|
114
265
|
|
|
115
266
|
Select a `TileMap2D` node and the inspector grows a **🖌 paint tiles** tool:
|
|
@@ -359,6 +359,7 @@ tops radially away with a smooth falloff as a character wades through.
|
|
|
359
359
|
| `flowers` | `0` | DEPRECATED — confetti heads; use a `Flowers3D` node (load-time check 0–0.2) |
|
|
360
360
|
| `seed` | `1` | placement seed — identical field across runs/machines |
|
|
361
361
|
| `drape` | `null` | **AUTO by default**: whenever the scene has a Terrain3D, every blade roots on the ground under it (samples `heightAt`) — omit this prop and rolling terrain just works. `true` forces it (keeps retrying until a terrain appears — streamed worlds), `false` opts out (flat carpet at the node's Y) |
|
|
362
|
+
| `avoidWater` | `true` | blades keep OUT of the water — any instance whose ground sits under a `Water3D` or `River3D` surface is dropped, so a creek that cuts its bed through a meadow gets banks instead of blades waving in the current. `false` plants reeds and paddy fields |
|
|
362
363
|
| `terrain` | `""` | drape target node path; empty = **auto-find the first Terrain3D** in the tree. A non-empty path that is NOT a Terrain3D fails at load — no silent floating |
|
|
363
364
|
|
|
364
365
|
> **Rolling terrain just works.** Since 0.14 draping is on by default: with a
|
|
@@ -415,6 +416,7 @@ billboard confetti. Deterministic from the `seed` PROP.
|
|
|
415
416
|
| `clustering` | `0.6` | 0 uniform … 1 tight Voronoi patches (load-time check) |
|
|
416
417
|
| `sway` | `0.5` | head-bob wind strength; 0 disables |
|
|
417
418
|
| `drape` | `null` | AUTO by default — plants root on the scene's Terrain3D when one exists; `true` forces, `false` opts out — see the Foliage3D drape note above |
|
|
419
|
+
| `avoidWater` | `true` | plants keep OUT of the water (see the Foliage3D note) — `false` for lilies and marsh planting |
|
|
418
420
|
| `terrain` | `""` | drape target node path; empty = auto-find the first Terrain3D (a wrong path fails at load) |
|
|
419
421
|
|
|
420
422
|
## Tree3D
|
|
@@ -518,6 +520,64 @@ automatic, no props.
|
|
|
518
520
|
{ "name": "Terrain", "type": "Terrain3D",
|
|
519
521
|
"props": { "size": [200, 200], "maxHeight": 6, "seed": 1, "theme": "island" } }
|
|
520
522
|
] }
|
|
523
|
+
**`reflectivity` (0..1, null = the preset's own)** dials how much sky the
|
|
524
|
+
surface throws back at grazing angles. Turn it DOWN under a bright or overcast
|
|
525
|
+
sky: that sky's radiance runs far past 1, so a high ceiling paints the water
|
|
526
|
+
white — and a Water3D doing that beside a River3D (which paints an AUTHORED sky
|
|
527
|
+
palette and never blows out) reads as two unrelated materials meeting at a line.
|
|
528
|
+
The river template's plunge pool runs 0.06 for exactly that reason.
|
|
529
|
+
|
|
530
|
+
### Condition a traced course before a river runs it
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
import { smoothCourse, traceDownhillPath } from 'incanto/3d';
|
|
534
|
+
const path = smoothCourse(traceDownhillPath(heightAt, opts), widestWidth / 2);
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
**Do this every time you feed `traceDownhillPath` into a River3D.** A steepest-
|
|
538
|
+
descent trace zigzags at the terrain's noise scale and can hook back within
|
|
539
|
+
metres of a reach it already ran. A ribbon on that course cannot be well formed:
|
|
540
|
+
tight corners fold its inner edge, and a hook stacks two sheets of water on the
|
|
541
|
+
same ground — which renders as translucent sheets of paper pasted over one
|
|
542
|
+
another, with no rendering fix available. `smoothCourse` relaxes the bends to
|
|
543
|
+
what the width can take, drops sub-width noise, and CUTS the course where it
|
|
544
|
+
folds back (a creek does not flow over its own reach; ending is the better
|
|
545
|
+
answer).
|
|
546
|
+
|
|
547
|
+
### A river's course sets its maximum width
|
|
548
|
+
|
|
549
|
+
A `River3D` surface is a RIBBON swept along `path`, and a swept ribbon cannot be
|
|
550
|
+
wider than the bend it is taking — past that, its inner edge folds through
|
|
551
|
+
itself. The engine holds the INNER bank inside the local turn radius (the outer
|
|
552
|
+
bank keeps every metre the ground gives it, which is what a real bend looks
|
|
553
|
+
like: point bar inside, cut bank outside).
|
|
554
|
+
|
|
555
|
+
The failure this prevents is worth recognising, because it is the one visual bug
|
|
556
|
+
this node keeps producing: **bare channel floor beside the water — the creek
|
|
557
|
+
appears to stop in the middle of its own bed.** It means the ground is wetter
|
|
558
|
+
than the course can carry. River3D says so at load:
|
|
559
|
+
|
|
560
|
+
```
|
|
561
|
+
[incanto] River3D 'Creek': the course is too tight for the water it holds —
|
|
562
|
+
41 of 608 stations leave bare channel beside the ribbon (worst at 210 m: ground
|
|
563
|
+
wet to 11.3 m from the centre, a bend that can only carry 2.1 m). Fix by EASING
|
|
564
|
+
THE BENDS in `path` (fewer, straighter points), NARROWING `widths` there, or
|
|
565
|
+
placing standing water (a Water3D) if that reach is really a pool.
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Three rules that keep a river out of this entirely:
|
|
569
|
+
|
|
570
|
+
1. **Widths ≤ ⅓ of the tightest bend.** A `traceDownhillPath` result zig-zags;
|
|
571
|
+
thin it or raise its `step` before handing it to a wide river.
|
|
572
|
+
2. **A wide slow reach is still the river.** Don't put a Water3D pool at the
|
|
573
|
+
foot of a River3D — they are different shaders with different sky and foam
|
|
574
|
+
models, they cannot be tuned to match, and they meet along a visible seam.
|
|
575
|
+
Open the `widths` profile instead (`[2.4, 4.5, 7, 9]` is a spring→pool run).
|
|
576
|
+
3. **Verify it, don't eyeball it.** `findRiverCoverageGaps(rings)` (exported from
|
|
577
|
+
`incanto/3d`) reports the reaches where the ribbon falls short, and a probe a
|
|
578
|
+
metre outside each bank — ground still BELOW the waterline out there — counts
|
|
579
|
+
bare channel headlessly. The river template gates on both.
|
|
580
|
+
|
|
521
581
|
That snippet is the canonical PHYSICS recipe: the `heightfield` collider has
|
|
522
582
|
no params of its own — it pulls the height grid from its Terrain3D CHILD, so
|
|
523
583
|
visuals and collision can never drift apart. It is static-only (load-time
|
|
@@ -817,6 +877,12 @@ the scene root a cutout has nothing to stand in for, and the loader says so.
|
|
|
817
877
|
| `size` | `[2, 1, 1]` | box extent in meters, centered on the node — which PART of the parent holds water back |
|
|
818
878
|
| `enabled` | `true` | live toggle — a scuttled hull can start letting the sea in |
|
|
819
879
|
|
|
880
|
+
**A plunge pool is a `Water3D`, not a river.** A `River3D` is a current: a
|
|
881
|
+
ribbon fitted to the ground it runs over. Run one across a carved basin and it
|
|
882
|
+
lays a strip of water over the bowl with its edges hanging in mid-air — end the
|
|
883
|
+
creek at the lip and put a pool in the basin instead. Size a square surface to
|
|
884
|
+
`side = radius · √2` so its corners land on the rim rather than over the bank.
|
|
885
|
+
|
|
820
886
|
**A cutout cannot punch a hole in open water**, because nothing is ever cut out
|
|
821
887
|
of the water. The mask is the parent's own silhouette, so water can only be
|
|
822
888
|
hidden behind geometry the player is already looking at. Overshoot the box and
|
|
@@ -977,7 +1043,7 @@ underneath decides everything else.
|
|
|
977
1043
|
| `terrain` | `''` | drape target path; empty = auto-find the first Terrain3D (a wrong path fails at load) |
|
|
978
1044
|
| `carve` | `true` | cut the bed. The river trenches its own channel into the terrain it drapes on — see below |
|
|
979
1045
|
| `flowForce` | `1` | how hard the current sweeps bodies downstream (0 = visual only) |
|
|
980
|
-
| `spray` | `1` | mist at the foot of every
|
|
1046
|
+
| `spray` | `1` | mist at the foot of every drop the course turns out to contain — the node finds them and hangs a Particles3D plume on each (0 = off) |
|
|
981
1047
|
| `sunDirection` / `sunColor` / `sunIntensity` | sky / `#fff6e0` / `1` | glint (the environment sun wins while `sunDirection` is default) |
|
|
982
1048
|
|
|
983
1049
|
**What the node derives for you**, all from `path` + the ground:
|
|
@@ -991,6 +1057,10 @@ underneath decides everything else.
|
|
|
991
1057
|
runs faster), which is what puts rapids where a real river has them;
|
|
992
1058
|
- **whitewater**: grade × speed makes rapids, the bank shear line makes edge
|
|
993
1059
|
froth, a thinning column riffles over rock. Foam then rides downstream.
|
|
1060
|
+
- **a dry bank**: `Foliage3D` and `Flowers3D` refuse to plant where a river
|
|
1061
|
+
runs (`avoidWater`, on by default), so a creek cutting its bed through a
|
|
1062
|
+
meadow gets bare wet ground at the edge instead of blades waving in the
|
|
1063
|
+
current;
|
|
994
1064
|
- **what stands in the water**: drop boulders in the channel and the current
|
|
995
1065
|
answers them — a cushion of white piled on the upstream face, a torn wake
|
|
996
1066
|
opening downstream, and the surface sheen bending around the stone. Nothing
|
|
@@ -1048,6 +1118,23 @@ should be.
|
|
|
1048
1118
|
const path = traceDownhillPath(terrain.heightAt, { x: peakX, z: peakZ, step: 7 });
|
|
1049
1119
|
```
|
|
1050
1120
|
|
|
1121
|
+
**Placing things against a self-carved bed?** Ask the engine what the cut will
|
|
1122
|
+
be — never mirror it by hand. `riverCarveChannels` is the same function the node
|
|
1123
|
+
runs at load, so a generator that assigns its result to a scratch Terrain3D gets
|
|
1124
|
+
the EXACT ground the game will have; a hand-rolled approximation puts the player
|
|
1125
|
+
inside a hill.
|
|
1126
|
+
|
|
1127
|
+
```ts
|
|
1128
|
+
const carved = new Terrain3D('probe');
|
|
1129
|
+
Object.assign(carved, terrainProps);
|
|
1130
|
+
carved.channels = riverCarveChannels({
|
|
1131
|
+
path, widths, depth,
|
|
1132
|
+
cell: size / resolution, // the terrain's own grid
|
|
1133
|
+
groundAt: (x, z) => rawTerrain.heightAt(x, z),
|
|
1134
|
+
});
|
|
1135
|
+
const groundAt = (x: number, z: number) => carved.heightAt(x, z); // place against THIS
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1051
1138
|
|
|
1052
1139
|
### Waterfalls happen — you do not author them
|
|
1053
1140
|
|
|
@@ -49,6 +49,7 @@ Signals: `animationFinished(name)`
|
|
|
49
49
|
| `visible` | `true` | boolean |
|
|
50
50
|
| `renderOrder` | `0` | number |
|
|
51
51
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
52
|
+
| `snapToGround` | `null` | null |
|
|
52
53
|
| `texture` | `""` | string |
|
|
53
54
|
| `size` | `[1,1]` | array |
|
|
54
55
|
| `billboard` | `"y"` | one of: `y` `full` `none` |
|
|
@@ -94,6 +95,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
94
95
|
| `visible` | `true` | boolean |
|
|
95
96
|
| `renderOrder` | `0` | number |
|
|
96
97
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
98
|
+
| `snapToGround` | `null` | null |
|
|
97
99
|
| `collider` | `{}` | object |
|
|
98
100
|
|
|
99
101
|
Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
@@ -128,6 +130,7 @@ Signals: `finished`
|
|
|
128
130
|
| `visible` | `true` | boolean |
|
|
129
131
|
| `renderOrder` | `0` | number |
|
|
130
132
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
133
|
+
| `snapToGround` | `null` | null |
|
|
131
134
|
| `mode` | `"screen"` | one of: `screen` `y` `none` |
|
|
132
135
|
|
|
133
136
|
## `BoneAttachment3D` — `incanto/3d`
|
|
@@ -141,6 +144,7 @@ Signals: `finished`
|
|
|
141
144
|
| `visible` | `true` | boolean |
|
|
142
145
|
| `renderOrder` | `0` | number |
|
|
143
146
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
147
|
+
| `snapToGround` | `null` | null |
|
|
144
148
|
| `target` | `""` | string |
|
|
145
149
|
| `bone` | `""` | string |
|
|
146
150
|
|
|
@@ -155,6 +159,7 @@ Signals: `finished`
|
|
|
155
159
|
| `visible` | `true` | boolean |
|
|
156
160
|
| `renderOrder` | `0` | number |
|
|
157
161
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
162
|
+
| `snapToGround` | `null` | null |
|
|
158
163
|
| `target` | `""` | string |
|
|
159
164
|
| `bone` | `"Head"` | string |
|
|
160
165
|
| `lookAt` | `""` | string |
|
|
@@ -190,6 +195,7 @@ Signals: `finished`
|
|
|
190
195
|
| `visible` | `true` | boolean |
|
|
191
196
|
| `renderOrder` | `0` | number |
|
|
192
197
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
198
|
+
| `snapToGround` | `null` | null |
|
|
193
199
|
| `fov` | `60` | number |
|
|
194
200
|
| `near` | `0.1` | number |
|
|
195
201
|
| `far` | `1000` | number |
|
|
@@ -224,9 +230,9 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
224
230
|
| `visible` | `true` | boolean |
|
|
225
231
|
| `renderOrder` | `0` | number |
|
|
226
232
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
233
|
+
| `snapToGround` | `true` | boolean |
|
|
227
234
|
| `collider` | `{}` | object |
|
|
228
235
|
| `velocity` | `[0,0,0]` | array |
|
|
229
|
-
| `snapToGround` | `true` | boolean |
|
|
230
236
|
| `slopeLimitDeg` | `45` | number |
|
|
231
237
|
|
|
232
238
|
Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
@@ -252,6 +258,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
252
258
|
| `visible` | `true` | boolean |
|
|
253
259
|
| `renderOrder` | `0` | number |
|
|
254
260
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
261
|
+
| `snapToGround` | `null` | null |
|
|
255
262
|
| `view` | `"free"` | one of: `free` `firstPerson` `quarter` `side` |
|
|
256
263
|
| `camDistance` | `4` | number |
|
|
257
264
|
| `eyeHeight` | `0.64` | number |
|
|
@@ -304,6 +311,7 @@ Signals: `movementStateChanged(state)`
|
|
|
304
311
|
| `visible` | `true` | boolean |
|
|
305
312
|
| `renderOrder` | `0` | number |
|
|
306
313
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
314
|
+
| `snapToGround` | `null` | null |
|
|
307
315
|
| `color` | `"#ffffff"` | string |
|
|
308
316
|
| `intensity` | `1` | number |
|
|
309
317
|
| `castShadow` | `false` | boolean |
|
|
@@ -322,6 +330,7 @@ Signals: `movementStateChanged(state)`
|
|
|
322
330
|
| `visible` | `true` | boolean |
|
|
323
331
|
| `renderOrder` | `0` | number |
|
|
324
332
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
333
|
+
| `snapToGround` | `null` | null |
|
|
325
334
|
| `density` | `"sparse"` | one of: `lush` `sparse` `none` |
|
|
326
335
|
| `area` | `[20,20]` | array |
|
|
327
336
|
| `seed` | `1` | number |
|
|
@@ -331,6 +340,7 @@ Signals: `movementStateChanged(state)`
|
|
|
331
340
|
| `clustering` | `0.6` | number |
|
|
332
341
|
| `sway` | `0.5` | number |
|
|
333
342
|
| `drape` | `null` | null |
|
|
343
|
+
| `avoidWater` | `true` | boolean |
|
|
334
344
|
| `terrain` | `""` | string |
|
|
335
345
|
|
|
336
346
|
## `Foliage3D` — `incanto/3d`
|
|
@@ -344,6 +354,7 @@ Signals: `movementStateChanged(state)`
|
|
|
344
354
|
| `visible` | `true` | boolean |
|
|
345
355
|
| `renderOrder` | `2` | number |
|
|
346
356
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
357
|
+
| `snapToGround` | `null` | null |
|
|
347
358
|
| `kind` | `"grass"` | one of: `grass` `flowers` `reeds` |
|
|
348
359
|
| `style` | `"mesh"` | one of: `blades` `simple` `mesh` `tufts` |
|
|
349
360
|
| `tuftStyle` | `"grass"` | one of: `grass` `fern` |
|
|
@@ -363,6 +374,7 @@ Signals: `movementStateChanged(state)`
|
|
|
363
374
|
| `flowers` | `0` | number |
|
|
364
375
|
| `seed` | `1` | number |
|
|
365
376
|
| `drape` | `null` | null |
|
|
377
|
+
| `avoidWater` | `true` | boolean |
|
|
366
378
|
| `terrain` | `""` | string |
|
|
367
379
|
|
|
368
380
|
## `HudLayer` — `incanto`
|
|
@@ -383,12 +395,14 @@ Signals: `movementStateChanged(state)`
|
|
|
383
395
|
| `visible` | `true` | boolean |
|
|
384
396
|
| `renderOrder` | `0` | number |
|
|
385
397
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
398
|
+
| `snapToGround` | `null` | null |
|
|
386
399
|
| `mesh` | `"box"` | one of: `box` `sphere` `capsule` `plane` `cylinder` `gem` |
|
|
387
400
|
| `size` | `[1,1,1]` | array |
|
|
388
401
|
| `material` | `{}` | object |
|
|
389
402
|
| `transforms` | `[]` | array |
|
|
390
403
|
| `castShadow` | `false` | boolean |
|
|
391
404
|
| `receiveShadow` | `false` | boolean |
|
|
405
|
+
| `collider` | `null` | null |
|
|
392
406
|
|
|
393
407
|
## `Joint2D` — `incanto/2d`
|
|
394
408
|
|
|
@@ -420,6 +434,7 @@ Signals: `movementStateChanged(state)`
|
|
|
420
434
|
| `visible` | `true` | boolean |
|
|
421
435
|
| `renderOrder` | `0` | number |
|
|
422
436
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
437
|
+
| `snapToGround` | `null` | null |
|
|
423
438
|
| `type` | `"spherical"` | one of: `fixed` `spherical` `rope` `spring` |
|
|
424
439
|
| `target` | `""` | string |
|
|
425
440
|
| `anchor` | `[0,0,0]` | array |
|
|
@@ -456,6 +471,7 @@ Signals: `movementStateChanged(state)`
|
|
|
456
471
|
| `visible` | `true` | boolean |
|
|
457
472
|
| `renderOrder` | `0` | number |
|
|
458
473
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
474
|
+
| `snapToGround` | `null` | null |
|
|
459
475
|
| `sections` | `[]` | array |
|
|
460
476
|
| `slices` | `24` | number |
|
|
461
477
|
| `smooth` | `4` | number |
|
|
@@ -474,6 +490,7 @@ Signals: `movementStateChanged(state)`
|
|
|
474
490
|
| `visible` | `true` | boolean |
|
|
475
491
|
| `renderOrder` | `0` | number |
|
|
476
492
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
493
|
+
| `snapToGround` | `null` | null |
|
|
477
494
|
| `mesh` | `"box"` | one of: `box` `sphere` `capsule` `plane` `cylinder` `gem` |
|
|
478
495
|
| `size` | `[1,1,1]` | array |
|
|
479
496
|
| `material` | `{}` | object |
|
|
@@ -491,11 +508,14 @@ Signals: `movementStateChanged(state)`
|
|
|
491
508
|
| `visible` | `true` | boolean |
|
|
492
509
|
| `renderOrder` | `0` | number |
|
|
493
510
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
511
|
+
| `snapToGround` | `null` | null |
|
|
494
512
|
| `model` | `""` | string |
|
|
495
513
|
| `animation` | `""` | string |
|
|
496
514
|
| `targetHeight` | `0` | number |
|
|
497
515
|
| `castShadow` | `false` | boolean |
|
|
498
516
|
| `animationLoop` | `true` | boolean |
|
|
517
|
+
| `animationSpeed` | `1` | number |
|
|
518
|
+
| `animationOffset` | `0` | number |
|
|
499
519
|
| `animationUpper` | `""` | string |
|
|
500
520
|
| `animationUpperLoop` | `false` | boolean |
|
|
501
521
|
| `upperBodyRoot` | `"Spine"` | string |
|
|
@@ -543,6 +563,7 @@ _No props (structural fields only)._
|
|
|
543
563
|
| `visible` | `true` | boolean |
|
|
544
564
|
| `renderOrder` | `0` | number |
|
|
545
565
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
566
|
+
| `snapToGround` | `null` | null |
|
|
546
567
|
|
|
547
568
|
## `OmniLight3D` — `incanto/3d`
|
|
548
569
|
|
|
@@ -555,6 +576,7 @@ _No props (structural fields only)._
|
|
|
555
576
|
| `visible` | `true` | boolean |
|
|
556
577
|
| `renderOrder` | `0` | number |
|
|
557
578
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
579
|
+
| `snapToGround` | `null` | null |
|
|
558
580
|
| `color` | `"#ffffff"` | string |
|
|
559
581
|
| `intensity` | `1` | number |
|
|
560
582
|
| `range` | `0` | number |
|
|
@@ -604,6 +626,7 @@ Signals: `finished`
|
|
|
604
626
|
| `visible` | `true` | boolean |
|
|
605
627
|
| `renderOrder` | `0` | number |
|
|
606
628
|
| `orderGroup` | `"effects"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
629
|
+
| `snapToGround` | `null` | null |
|
|
607
630
|
| `preset` | `"custom"` | one of: `custom` `fire` `smoke` `sparks` `fireworks` `explosion` `flash` `lightning` `rain` `snow` `magic` |
|
|
608
631
|
| `emitting` | `true` | boolean |
|
|
609
632
|
| `rate` | `40` | number |
|
|
@@ -660,6 +683,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
660
683
|
| `visible` | `true` | boolean |
|
|
661
684
|
| `renderOrder` | `0` | number |
|
|
662
685
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
686
|
+
| `snapToGround` | `null` | null |
|
|
663
687
|
| `collider` | `{}` | object |
|
|
664
688
|
| `mass` | `1` | number |
|
|
665
689
|
| `gravityScale` | `1` | number |
|
|
@@ -681,6 +705,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
681
705
|
| `visible` | `true` | boolean |
|
|
682
706
|
| `renderOrder` | `0` | number |
|
|
683
707
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
708
|
+
| `snapToGround` | `null` | null |
|
|
684
709
|
| `path` | `[]` | array |
|
|
685
710
|
| `width` | `6` | number |
|
|
686
711
|
| `widths` | `[]` | array |
|
|
@@ -728,6 +753,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
728
753
|
| `visible` | `true` | boolean |
|
|
729
754
|
| `renderOrder` | `0` | number |
|
|
730
755
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
756
|
+
| `snapToGround` | `null` | null |
|
|
731
757
|
| `texture` | `""` | string |
|
|
732
758
|
| `size` | `[1,1]` | array |
|
|
733
759
|
| `billboard` | `"y"` | one of: `y` `full` `none` |
|
|
@@ -766,6 +792,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
766
792
|
| `visible` | `true` | boolean |
|
|
767
793
|
| `renderOrder` | `0` | number |
|
|
768
794
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
795
|
+
| `snapToGround` | `null` | null |
|
|
769
796
|
| `collider` | `{}` | object |
|
|
770
797
|
|
|
771
798
|
Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
@@ -781,6 +808,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
781
808
|
| `visible` | `true` | boolean |
|
|
782
809
|
| `renderOrder` | `0` | number |
|
|
783
810
|
| `orderGroup` | `"terrain"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
811
|
+
| `snapToGround` | `null` | null |
|
|
784
812
|
| `size` | `[200,200]` | array |
|
|
785
813
|
| `maxHeight` | `28` | number |
|
|
786
814
|
| `seed` | `1` | number |
|
|
@@ -836,6 +864,7 @@ Signals: `timeout`
|
|
|
836
864
|
| `visible` | `true` | boolean |
|
|
837
865
|
| `renderOrder` | `0` | number |
|
|
838
866
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
867
|
+
| `snapToGround` | `null` | null |
|
|
839
868
|
| `width` | `0.3` | number |
|
|
840
869
|
| `color` | `"#ffffff"` | string |
|
|
841
870
|
| `opacity` | `0.8` | number |
|
|
@@ -855,6 +884,7 @@ Signals: `timeout`
|
|
|
855
884
|
| `visible` | `true` | boolean |
|
|
856
885
|
| `renderOrder` | `0` | number |
|
|
857
886
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
887
|
+
| `snapToGround` | `null` | null |
|
|
858
888
|
| `tier` | `"medium"` | one of: `simple` `medium` `high` |
|
|
859
889
|
| `type` | `"conifer"` | one of: `conifer` `broadleaf` `dead` `bush` |
|
|
860
890
|
| `seed` | `1` | number |
|
|
@@ -950,6 +980,7 @@ Signals: `lineShown` · `choiceMade` · `dialogueFinished`
|
|
|
950
980
|
| `visible` | `true` | boolean |
|
|
951
981
|
| `renderOrder` | `0` | number |
|
|
952
982
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
983
|
+
| `snapToGround` | `null` | null |
|
|
953
984
|
| `voxels` | `[]` | array |
|
|
954
985
|
|
|
955
986
|
Signals: `blocksChanged`
|
|
@@ -965,6 +996,7 @@ Signals: `blocksChanged`
|
|
|
965
996
|
| `visible` | `true` | boolean |
|
|
966
997
|
| `renderOrder` | `1` | number |
|
|
967
998
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
999
|
+
| `snapToGround` | `null` | null |
|
|
968
1000
|
| `size` | `[40,40]` | array |
|
|
969
1001
|
| `color` | `"#2a6fbe"` | string |
|
|
970
1002
|
| `opacity` | `0.8` | number |
|
|
@@ -978,6 +1010,7 @@ Signals: `blocksChanged`
|
|
|
978
1010
|
| `mirrorInterval` | `33` | number |
|
|
979
1011
|
| `swellSteepness` | `0.35` | number |
|
|
980
1012
|
| `foam` | `true` | boolean |
|
|
1013
|
+
| `reflectivity` | `null` | null |
|
|
981
1014
|
| `interaction` | `true` | boolean |
|
|
982
1015
|
| `splash` | `true` | boolean |
|
|
983
1016
|
| `sunDirection` | `[0.5,0.8,0.3]` | array |
|
|
@@ -1008,6 +1041,7 @@ Signals: `entered(body)` · `exited(body)`
|
|
|
1008
1041
|
| `visible` | `true` | boolean |
|
|
1009
1042
|
| `renderOrder` | `0` | number |
|
|
1010
1043
|
| `orderGroup` | `"default"` | one of: `background` `terrain` `default` `characters` `effects` `overlay` |
|
|
1044
|
+
| `snapToGround` | `null` | null |
|
|
1011
1045
|
| `size` | `[2,1,1]` | array |
|
|
1012
1046
|
| `enabled` | `true` | boolean |
|
|
1013
1047
|
|