incanto 0.19.0 → 0.21.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/dist/3d.d.ts CHANGED
@@ -1541,6 +1541,230 @@ declare class Particles3D extends Node3D {
1541
1541
  private syncParticles;
1542
1542
  }
1543
1543
  //#endregion
1544
+ //#region src/3d/water/river.d.ts
1545
+ /**
1546
+ * River centerline math — the CPU half of {@link River3D}.
1547
+ *
1548
+ * Everything here works in the river node's LOCAL frame (the caller hands in a
1549
+ * `bedAt(x, z)` sampler that has already been shifted into it), so this module
1550
+ * imports nothing from three and stays testable in plain node.
1551
+ *
1552
+ * The shape of a river is NOT authored: it is derived. A path of control
1553
+ * points and a width profile is all a scene declares; the ground underneath
1554
+ * decides the rest —
1555
+ *
1556
+ * - the **surface profile** follows the bed's descending envelope, so the water
1557
+ * runs downhill and never climbs (a rising bed dams it into a still pool);
1558
+ * - the **visible width** is whatever the terrain lets the water occupy: every
1559
+ * vertex carries its own water column (`surfaceY − bed`), the shader fades to
1560
+ * nothing where that reaches zero, so banks, gravel bars and half-drowned
1561
+ * boulders carve the ribbon instead of a hand-authored outline;
1562
+ * - the **current** obeys continuity (narrow = fast) and grade (steep = fast),
1563
+ * which is what makes rapids sit where a channel pinches or tips.
1564
+ */
1565
+ /** Terrain height under a LOCAL-frame point, in the same frame's meters. */
1566
+ type BedSampler = (x: number, z: number) => number;
1567
+ /** One arc-length sample of the smoothed centerline. */
1568
+ interface PathSample {
1569
+ x: number;
1570
+ z: number;
1571
+ /** Unit tangent, pointing downstream. */
1572
+ tx: number;
1573
+ tz: number;
1574
+ /** Meters from the source. */
1575
+ along: number;
1576
+ }
1577
+ /** A cross-section station: where the water is, how wide, how fast. */
1578
+ interface RiverRing extends PathSample {
1579
+ halfWidth: number;
1580
+ /** Water surface height (local Y). */
1581
+ surfaceY: number;
1582
+ /** Downhill grade of the surface (dimensionless, ≥ 0). */
1583
+ slope: number;
1584
+ /** Surface current in m/s. */
1585
+ speed: number;
1586
+ }
1587
+ interface RiverHit {
1588
+ /** In the channel: inside the banks AND between source and mouth. */
1589
+ inside: boolean;
1590
+ /** Signed offset from the centerline in half-widths (±1 = the banks). */
1591
+ across: number;
1592
+ /** Meters downstream from the source. */
1593
+ along: number;
1594
+ surfaceY: number;
1595
+ /** Unit downstream direction at the projection. */
1596
+ dirX: number;
1597
+ dirZ: number;
1598
+ speed: number;
1599
+ halfWidth: number;
1600
+ }
1601
+ /** A place where the river stops flowing and starts falling. */
1602
+ interface RiverFall {
1603
+ /** Where the water LANDS (local frame) — the plunge point. */
1604
+ x: number;
1605
+ z: number;
1606
+ /** Water surface at the lip and at the base. */
1607
+ topY: number;
1608
+ baseY: number;
1609
+ /** Vertical drop in meters. */
1610
+ drop: number;
1611
+ /** Channel half-width at the base — how wide the curtain is. */
1612
+ halfWidth: number;
1613
+ /** Downstream direction at the base (a fall keeps carrying the water). */
1614
+ dirX: number;
1615
+ dirZ: number;
1616
+ /** Current speed at the base. */
1617
+ speed: number;
1618
+ }
1619
+ interface DownhillTraceOptions {
1620
+ /** Where the water starts (local frame, same as the sampler). */
1621
+ x: number;
1622
+ z: number;
1623
+ /** Meters per step — also the gradient probe radius. */
1624
+ step: number;
1625
+ /** Stop after this many points (default 200). */
1626
+ maxPoints?: number;
1627
+ /** Half-extent of a square play area to stay inside (default: unbounded). */
1628
+ bounds?: number;
1629
+ /** Drop per step below which the water is judged to have pooled (default 1 %
1630
+ * of the step — a genuinely flat basin, not a gentle reach). */
1631
+ minDrop?: number;
1632
+ }
1633
+ /**
1634
+ * Trace where water would actually run from a point: repeated steepest descent
1635
+ * with momentum, so the line follows a valley floor instead of rattling between
1636
+ * its walls. Ends when the ground goes flat (a pool), the trace leaves the play
1637
+ * area, or `maxPoints` is reached.
1638
+ *
1639
+ * Feed the result straight into a {@link River3D} `path` — the terrain then
1640
+ * picks its own river, which is how a generated map gets water that belongs.
1641
+ */
1642
+ declare function traceDownhillPath(bedAt: BedSampler, opts: DownhillTraceOptions): number[][];
1643
+ //#endregion
1644
+ //#region src/3d/nodes/river-3d.d.ts
1645
+ /**
1646
+ * A river: running water that finds its own shape.
1647
+ *
1648
+ * A scene declares a centerline `path`, a `width` (constant or a profile) and a
1649
+ * `depth`; the node samples the Terrain3D underneath and derives everything
1650
+ * else — a surface that descends with the ground and never climbs, a current
1651
+ * that speeds up where the channel pinches or tips, whitewater wherever those
1652
+ * two make it, and banks cut by the ground itself (each vertex carries its own
1653
+ * water column, and the shader stops drawing where that runs out).
1654
+ *
1655
+ * Unlike {@link Water3D} it costs no extra render passes — a river is a ribbon
1656
+ * with one draw call, so a map can carry a dozen of them.
1657
+ *
1658
+ * ```json
1659
+ * { "type": "River3D", "props": {
1660
+ * "path": [[-80, -30], [-20, 5], [30, 10], [90, -10]],
1661
+ * "widths": [3, 6, 11], "depth": 0.9, "flowSpeed": 1.8 } }
1662
+ * ```
1663
+ */
1664
+ declare class River3D extends Node3D implements SunConsumer3D {
1665
+ static override readonly typeName: string;
1666
+ static override readonly props: PropSchema;
1667
+ /** Centerline control points `[[x, z], …]` in the node's local frame. */
1668
+ path: number[][];
1669
+ /** Channel width in meters (constant unless `widths` overrides it). */
1670
+ width: number;
1671
+ /** Width profile lerped source→mouth, e.g. `[2, 5, 9]` for a stream growing
1672
+ * into a river. Empty = the constant `width`. */
1673
+ widths: number[];
1674
+ /** Water column at the centerline, in meters. */
1675
+ depth: number;
1676
+ /** Reference current in m/s (the mean; reaches speed up and slow down). */
1677
+ flowSpeed: number;
1678
+ /** `{ shallow, deep, sky, horizon, bank }` — the body ramp plus what the
1679
+ * surface mirrors (a grazing river mostly mirrors its BANK, not the sky). */
1680
+ colors: JsonObject;
1681
+ /** Beer's-law density: how fast the water hides its bed. */
1682
+ absorption: number;
1683
+ /** Upper bound on the body's opacity (1 = the deep reach goes solid). */
1684
+ opacity: number;
1685
+ /** Whitewater dial: 0 = a glassy canal, 1 = default, 2 = raging. */
1686
+ foam: number;
1687
+ /** Surface-detail dial: ripple relief and glitter. */
1688
+ ripples: number;
1689
+ /** Glint direction (the sky's sun overrides while this is at its default). */
1690
+ sunDirection: number[];
1691
+ sunColor: string;
1692
+ sunIntensity: number;
1693
+ /** Drape target path; empty = auto-find the first Terrain3D in the tree. */
1694
+ terrain: string;
1695
+ /** How hard the current sweeps bodies downstream (0 = visual only). */
1696
+ flowForce: number;
1697
+ /**
1698
+ * Mist at the foot of every waterfall the course contains: the node finds
1699
+ * the drops itself (see {@link detectFalls}) and hangs a Particles3D plume
1700
+ * on each, sized by how far the water falls. 0 = off.
1701
+ */
1702
+ spray: number;
1703
+ override renderOrder: number;
1704
+ private time;
1705
+ private rings;
1706
+ private falls;
1707
+ private sprayKey;
1708
+ private courseKey;
1709
+ private bedAt;
1710
+ private world;
1711
+ private readonly _bodies;
1712
+ /** Loader hook: a malformed river fails at LOAD, not as an invisible ribbon. */
1713
+ static validateJson(node: Node): void;
1714
+ protected override _createObject3D(): Object3D;
1715
+ override update(dt: number): void;
1716
+ override _syncObject3D(): void;
1717
+ /**
1718
+ * Where a WORLD point sits in the channel — the query gameplay scripts run
1719
+ * (steer a raft, drown a torch, decide a ford is too fast to cross). `null`
1720
+ * until the river has been built.
1721
+ */
1722
+ sampleAt(x: number, z: number): (RiverHit & {
1723
+ surfaceY: number;
1724
+ }) | null;
1725
+ /**
1726
+ * The waterfalls on this course — where the water stops flowing and starts
1727
+ * falling, with the drop height and the plunge point in WORLD coordinates.
1728
+ * Hang your own effects (sound, a rainbow, a hidden cave) on these.
1729
+ */
1730
+ fallsAt(): (RiverFall & {
1731
+ worldX: number;
1732
+ worldY: number;
1733
+ worldZ: number;
1734
+ })[];
1735
+ /** @internal The derived centerline stations (surface, grade, current). */
1736
+ _rings(): readonly RiverRing[];
1737
+ /**
1738
+ * @internal Environment-sky sun hand-off (see {@link SunConsumer3D}): only
1739
+ * while `sunDirection` sits at its schema default — an authored glint wins.
1740
+ */
1741
+ _applySunDirection(dir: readonly [number, number, number]): void;
1742
+ override free(): void;
1743
+ private widthProfile;
1744
+ /** Resolve the drape terrain; an explicit path that misses is a hard error. */
1745
+ private resolveTerrain;
1746
+ /**
1747
+ * Derive the course (stations + water column) when a shaping prop changed.
1748
+ * Pure CPU work — no three objects — so gameplay can call it any time.
1749
+ */
1750
+ private ensureCourse;
1751
+ private rebuildIfNeeded;
1752
+ private buildMaterial;
1753
+ private syncUniforms;
1754
+ /**
1755
+ * Hang a mist plume on every fall. Runtime children (`__spray*`), rebuilt
1756
+ * only when the course or the dial changes — a plume is a Particles3D, so it
1757
+ * carries its own budget, culling and editor visibility for free.
1758
+ */
1759
+ private syncSpray;
1760
+ /**
1761
+ * Drag every body floating in the channel toward the water's own velocity.
1762
+ * Drag rather than thrust: a raft accelerates until it matches the current
1763
+ * and then coasts, and a swimmer can still fight across a slow ford.
1764
+ */
1765
+ private sweepBodies;
1766
+ }
1767
+ //#endregion
1544
1768
  //#region src/3d/terrain/heightmap.d.ts
1545
1769
  /**
1546
1770
  * A smooth radial depression carved into the terrain — a lake/pond bowl. x/z
@@ -1555,6 +1779,17 @@ interface BasinSpec {
1555
1779
  /** > 0 carves a bowl; < 0 RAISES a smooth dome mound of that height. */
1556
1780
  depth: number;
1557
1781
  }
1782
+ /**
1783
+ * A river/road trench carved along a polyline: the line version of a basin.
1784
+ * `width` is the flat bed, `taper` the bank blend beyond it (default: the bed
1785
+ * width again, which is what makes a walkable V instead of a slot).
1786
+ */
1787
+ interface ChannelSpec {
1788
+ path: readonly (readonly number[])[];
1789
+ width: number;
1790
+ depth: number;
1791
+ taper?: number;
1792
+ }
1558
1793
  interface HeightmapOptions {
1559
1794
  /** Terrain extent in meters along x. */
1560
1795
  width: number;
@@ -1584,6 +1819,8 @@ interface HeightmapOptions {
1584
1819
  edgeCornerSmoothness?: number;
1585
1820
  /** Smooth radial lake/pond bowls carved into the surface (interior basins). */
1586
1821
  basins?: BasinSpec[];
1822
+ /** River/road trenches carved along polylines (see {@link ChannelSpec}). */
1823
+ channels?: ChannelSpec[];
1587
1824
  }
1588
1825
  interface Heightmap {
1589
1826
  readonly width: number;
@@ -1709,6 +1946,10 @@ declare class Terrain3D extends Node3D {
1709
1946
  * collider + heightAt + dressing all see (place a Water3D in each).
1710
1947
  * NEGATIVE depth raises a smooth dome MOUND instead (a hill, an islet). */
1711
1948
  basins: BasinSpec[];
1949
+ /** River/road trenches carved along polylines — `[{ path, width, depth,
1950
+ * taper? }]`. The line counterpart of `basins`: what gives running water a
1951
+ * bed to sit in, and the collider/heightAt/drape all see it. */
1952
+ channels: ChannelSpec[];
1712
1953
  /**
1713
1954
  * WET SAND band: `{ y, band? }` darkens + glosses the splat in a noisy,
1714
1955
  * breathing band just above height `y` (a waterline) — the trace of the
@@ -2025,6 +2266,14 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2025
2266
  colors: JsonObject;
2026
2267
  /** CubeCamera reflections (fancy only; needs a live renderer). */
2027
2268
  reflection: boolean;
2269
+ /**
2270
+ * TRUE planar reflection: the scene re-rendered from the camera mirrored
2271
+ * across this surface, sampled per fragment. A cube map can only carry
2272
+ * distant content — the shoreline trees, the moored boat, the player at the
2273
+ * water's edge only appear in the water with this on. Costs one extra scene
2274
+ * render per frame, so it is off by default; a still lake earns it.
2275
+ */
2276
+ mirror: boolean;
2028
2277
  /** ms between reflection (and foam depth) re-renders. */
2029
2278
  reflectionInterval: number;
2030
2279
  /** Depth-texture shoreline foam — rides the always-on fancy scene pass. */
@@ -2069,6 +2318,13 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2069
2318
  swellDirectionDeg: number;
2070
2319
  /** Primary swell wavelength in meters (the two crossing trains derive). */
2071
2320
  swellWavelength: number;
2321
+ /**
2322
+ * GERSTNER pinch on the swell: 0 keeps the legacy height-only trains, 1 is
2323
+ * maximum trochoid (crests narrow to a peak, troughs go broad). It also
2324
+ * decides where whitecaps break — the surface's Jacobian collapses on a
2325
+ * folding crest, and that is where foam belongs.
2326
+ */
2327
+ swellSteepness: number;
2072
2328
  /** Open-water whitecap foam on the tallest crests, 0–1 (fancy only). Works
2073
2329
  * best with `swell` — the caps ride the swell's crest lines. */
2074
2330
  whitecaps: number;
@@ -2118,6 +2374,9 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2118
2374
  private lastReflectionAt;
2119
2375
  /** Per-frame scene pre-pass: depth (absorption/foam) + color grab (refraction). */
2120
2376
  private scenePassTarget;
2377
+ private mirrorTarget;
2378
+ private readonly mirrorCamera;
2379
+ private readonly mirrorMatrix;
2121
2380
  protected override _createObject3D(): Object3D;
2122
2381
  override update(dt: number): void;
2123
2382
  override _syncObject3D(): void;
@@ -2451,4 +2710,4 @@ declare function createNavDebugNode(nav: TerrainNav, opts?: {
2451
2710
  name?: string;
2452
2711
  }): InstancedMesh3D;
2453
2712
  //#endregion
2454
- export { Area3D, AssetStore3D, Billboard3D, type BillboardGroupMode, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type Game3D, type HeightSampler, type Heightmap, type HeightmapOptions, InstancedMesh3D, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type RigView, RigidBody3D, type Ripple, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, setEnvironment3D, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
2713
+ export { Area3D, AssetStore3D, type BedSampler, Billboard3D, type BillboardGroupMode, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, type DownhillTraceOptions, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type Game3D, type HeightSampler, type Heightmap, type HeightmapOptions, InstancedMesh3D, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type RigView, RigidBody3D, type Ripple, River3D, type RiverHit, type RiverRing, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, setEnvironment3D, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath };
package/dist/3d.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-Ct6RC4LF.js";
3
- import { A as Joint3D, B as keyboardIntensity, C as BoneLookAt3D, D as DEFAULT_TERRAIN_TEXTURE_BASE, E as Terrain3D, F as StaticBody3D, H as rigPose, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, O as TERRAIN_THEMES, P as RigidBody3D, R as QUARTER_PITCH, S as Camera3D, T as Billboard3D, V as movementState, _ as DENSITY_PRESETS, a as VOXEL_PALETTE, b as FLOWER_VARIETIES, c as Trail3D, d as LoftMesh3D, f as DirectionalLight3D, g as Foliage3D, h as MeshInstance3D, i as WATER_MAX_RIPPLES, j as Area3D, k as terrainThemeLayers, l as Particles3D, m as InstancedMesh3D, n as Water3D, o as VoxelGrid3D, p as OmniLight3D, s as Tree3D, t as registerNodes3D, u as ModelInstance3D, v as Flowers3D, w as BoneAttachment3D, x as CharacterController3D, y as resolveFlowerDensity, z as cameraRelative } from "./register-Cv5GNiVo.js";
4
- import { n as splatWeights, t as buildHeightmap } from "./heightmap-DgX-Opav.js";
5
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-JPdedRAB.js";
2
+ import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-xbxZRFwR.js";
3
+ import { A as TERRAIN_THEMES, B as QUARTER_PITCH, C as CharacterController3D, D as Billboard3D, E as BoneAttachment3D, F as PhysicsBody3D, H as keyboardIntensity, I as RigidBody3D, L as StaticBody3D, M as Joint3D, N as Area3D, O as Terrain3D, P as CharacterBody3D, R as Node3D, S as FLOWER_VARIETIES, T as BoneLookAt3D, U as movementState, V as cameraRelative, W as rigPose, _ as MeshInstance3D, a as VoxelGrid3D, b as Flowers3D, c as River3D, d as Particles3D, f as ModelInstance3D, g as InstancedMesh3D, h as OmniLight3D, i as VOXEL_PALETTE, j as terrainThemeLayers, k as DEFAULT_TERRAIN_TEXTURE_BASE, l as traceDownhillPath, m as DirectionalLight3D, n as Water3D, o as Tree3D, p as LoftMesh3D, s as Trail3D, t as registerNodes3D, u as WATER_MAX_RIPPLES, v as Foliage3D, w as Camera3D, x as resolveFlowerDensity, y as DENSITY_PRESETS } from "./register-BC55Ez6I.js";
4
+ import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
5
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-DHTZUrr0.js";
6
6
  //#region src/3d/environment-runtime.ts
7
7
  /**
8
8
  * Live environment editing — the renderer re-applies `scene.environment`
@@ -141,4 +141,4 @@ function createNavDebugNode(nav, opts) {
141
141
  return node;
142
142
  }
143
143
  //#endregion
144
- 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, StaticBody3D, TERRAIN_THEMES, Terrain3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, setEnvironment3D, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
144
+ 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, StaticBody3D, TERRAIN_THEMES, Terrain3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, setEnvironment3D, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath };
@@ -5,8 +5,8 @@ import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
6
6
  import { n as registerGameplayBehaviors } from "./gameplay-sSqrUcnz.js";
7
7
  import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
8
- import { I as Node3D, N as PhysicsBody3D, S as Camera3D, f as DirectionalLight3D, r as createCausticsQuad, t as registerNodes3D, u as ModelInstance3D } from "./register-Cv5GNiVo.js";
9
- import { n as enablePhysics3D } from "./physics-3d-JPdedRAB.js";
8
+ import { F as PhysicsBody3D, R as Node3D, f as ModelInstance3D, m as DirectionalLight3D, r as createCausticsQuad, t as registerNodes3D, w as Camera3D } from "./register-BC55Ez6I.js";
9
+ import { n as enablePhysics3D } from "./physics-3d-DHTZUrr0.js";
10
10
  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";
11
11
  import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
12
12
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
package/dist/env.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
2
  import { t as Rng } from "./rng-DP-SR7eg.js";
3
3
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
4
- import { t as buildHeightmap } from "./heightmap-DgX-Opav.js";
4
+ import { t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
5
5
  //#region src/env/round.ts
6
6
  /** 2-decimal rounding — keeps generated JSON readable without hurting determinism. */
7
7
  function round2(value) {
@@ -34,6 +34,20 @@ function buildHeightmap(opts) {
34
34
  radius: b.radius,
35
35
  depth: b.depth
36
36
  }));
37
+ const channels = (opts.channels ?? []).map((c) => ({
38
+ half: Math.max(c.width, 0) / 2,
39
+ taper: Math.max(c.taper ?? c.width, .001),
40
+ depth: c.depth,
41
+ segs: c.path.map((p) => ({
42
+ x: (p[0] ?? 0) + width / 2,
43
+ z: (p[1] ?? 0) + depth / 2
44
+ })).flatMap((p, i, all) => i === 0 ? [] : [{
45
+ ax: all[i - 1].x,
46
+ az: all[i - 1].z,
47
+ bx: p.x,
48
+ bz: p.z
49
+ }])
50
+ })).filter((c) => c.segs.length > 0 && c.depth !== 0);
37
51
  const simplex = createNoise2D(seed);
38
52
  /** Ported: noise remapped from [-1,1] to [0,1]. */
39
53
  const noise01 = (x, y) => (simplex(x, y) + 1) * .5;
@@ -76,6 +90,27 @@ function buildHeightmap(opts) {
76
90
  }
77
91
  final += lift - carve;
78
92
  }
93
+ if (channels.length > 0) {
94
+ let cut = 0;
95
+ for (const c of channels) {
96
+ let best = Number.POSITIVE_INFINITY;
97
+ for (const s of c.segs) {
98
+ const dx = s.bx - s.ax;
99
+ const dz = s.bz - s.az;
100
+ const len2 = dx * dx + dz * dz;
101
+ const t = len2 > 1e-9 ? Math.min(1, Math.max(0, ((x - s.ax) * dx + (z - s.az) * dz) / len2)) : 0;
102
+ const px = s.ax + dx * t;
103
+ const pz = s.az + dz * t;
104
+ const d = Math.hypot(x - px, z - pz);
105
+ if (d < best) best = d;
106
+ if (best <= c.half) break;
107
+ }
108
+ if (best >= c.half + c.taper) continue;
109
+ const t = Math.min(1, Math.max(0, (best - c.half) / c.taper));
110
+ cut = Math.max(cut, c.depth * (1 - t * t * (3 - 2 * t)));
111
+ }
112
+ final -= cut;
113
+ }
79
114
  return final;
80
115
  };
81
116
  /** Quarter-circle edge wrap: drop = R − √(R²−s²), p-norm corner rounding. */
package/dist/index.js CHANGED
@@ -295,6 +295,6 @@ function newUid() {
295
295
  //#endregion
296
296
  //#region src/index.ts
297
297
  /** Engine version. Kept in sync with package.json by the release pipeline. */
298
- const VERSION = "0.19.0";
298
+ const VERSION = "0.21.0";
299
299
  //#endregion
300
300
  export { AudioBuses, AudioPlayer, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, Scene, SceneTree, SfxEngine, Signal, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiText, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, mergeStaticSignals, newUid, parseNodePath, preloadUrls, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, synthSfx };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
3
  import { n as registerDebugSource } from "./debug-draw-CZmOYjL2.js";
4
- import { A as Joint3D, E as Terrain3D, I as Node3D, L as validateCollider3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./register-Cv5GNiVo.js";
4
+ import { F as PhysicsBody3D, I as RigidBody3D, M as Joint3D, N as Area3D, O as Terrain3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./register-BC55Ez6I.js";
5
5
  import { Euler, Quaternion } from "three";
6
6
  //#region src/3d/physics/physics-3d.ts
7
7
  var physics_3d_exports = /* @__PURE__ */ __exportAll({
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-Ct6RC4LF.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-Ct86zczq.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-xbxZRFwR.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-Ct86zczq.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;