incanto 0.38.0 → 0.39.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 (41) hide show
  1. package/dist/2d.d.ts +2 -2
  2. package/dist/2d.js +3 -3
  3. package/dist/3d.d.ts +57 -3
  4. package/dist/3d.js +4 -4
  5. package/dist/{behavior-B5PJ32eu.d.ts → behavior-BNNSIXS5.d.ts} +40 -1
  6. package/dist/{create-game-C4t5gVhc.js → create-game-DEtU2PRg.js} +4 -4
  7. package/dist/{create-game-DqY2lMBc.js → create-game-R_8_gTCU.js} +13 -6
  8. package/dist/debug.d.ts +1 -1
  9. package/dist/{environment-presets-C0Axpfth.js → environment-presets-bokhdw_w.js} +2 -2
  10. package/dist/{gameplay-CsJDUQh_.js → gameplay-BPGomkHR.js} +83 -13
  11. package/dist/gameplay.d.ts +1 -1
  12. package/dist/gameplay.js +1 -1
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +3 -3
  15. package/dist/{loader-DSMdqasu.d.ts → loader-mSL65Djg.d.ts} +1 -1
  16. package/dist/net.d.ts +1 -1
  17. package/dist/net.js +2 -2
  18. package/dist/{pathfinding-BrE5Uec6.d.ts → pathfinding-D7W8uqm1.d.ts} +1 -1
  19. package/dist/{physics-2d-OfKb0PV_.js → physics-2d-B9ktSWrr.js} +1 -1
  20. package/dist/{physics-3d-C8242nXr.js → physics-3d-Cpgc5ZM0.js} +2 -2
  21. package/dist/react.d.ts +1 -1
  22. package/dist/react.js +1 -1
  23. package/dist/{register-DnB9m7Rl.js → register-C2iO_yLv.js} +1 -1
  24. package/dist/{register-Dm7nrd-E.js → register-CGf5NKrc.js} +11 -11
  25. package/dist/{register-B4RRQbyq.js → register-CiXP3-GB.js} +1 -1
  26. package/dist/{replay-Cxrr-ApH.d.ts → replay-CwdWgz0f.d.ts} +1 -1
  27. package/dist/{replay-DH0UOuZ-.js → replay-YQ9FW7Yh.js} +1 -1
  28. package/dist/{test-CoDPWx-m.js → test-Bf-lUxr2.js} +10 -10
  29. package/dist/test.d.ts +3 -3
  30. package/dist/test.js +2 -2
  31. package/dist/vite.js +1 -1
  32. package/editor/assets/{agent8-BtIlblPm.js → agent8-DfIcNKb4.js} +1 -1
  33. package/editor/assets/{debug-BvTmHXI7.js → debug-ex82CxIM.js} +1 -1
  34. package/editor/assets/{index-BS01WWgM.js → index-eVTVArHd.js} +91 -91
  35. package/editor/index.html +1 -1
  36. package/package.json +1 -1
  37. package/skills/incanto-environment.md +21 -0
  38. package/skills/incanto-performance.md +7 -0
  39. package/templates-app/beacon-isle-3d/package.json +1 -1
  40. package/templates-app/tps-3d/package.json +1 -1
  41. package/templates-app/village-quest-3d/package.json +1 -1
package/dist/2d.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-B5PJ32eu.js";
1
+ import { Et as Node, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-BNNSIXS5.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DVwIGZdK.js";
3
3
  import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
4
- import { t as LoadSceneOptions } from "./loader-DSMdqasu.js";
4
+ import { t as LoadSceneOptions } from "./loader-mSL65Djg.js";
5
5
  import { t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
6
6
  import { Group, Mesh, Object3D, Scene, Texture } from "three";
7
7
  import * as RapierNs from "@dimforge/rapier2d-compat";
package/dist/2d.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-C4t5gVhc.js";
3
- import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-DnB9m7Rl.js";
4
- import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-OfKb0PV_.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-DEtU2PRg.js";
3
+ import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-C2iO_yLv.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-B9ktSWrr.js";
5
5
  //#region src/2d/library-sprite.ts
6
6
  /**
7
7
  * Turn a library sprite-animation JSON into a scene-ready spritesheet asset
package/dist/3d.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { N as Scene$1, S as Scheduler, T as RendererStats, Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-B5PJ32eu.js";
1
+ import { D as QualityCaps, Et as Node, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, n as BehaviorCtor, w as GameStats } from "./behavior-BNNSIXS5.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DVwIGZdK.js";
3
3
  import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
4
- import { t as LoadSceneOptions } from "./loader-DSMdqasu.js";
4
+ import { t as LoadSceneOptions } from "./loader-mSL65Djg.js";
5
5
  import { t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
6
- import { n as PathGrid, s as SpatialPose } from "./pathfinding-BrE5Uec6.js";
6
+ import { n as PathGrid, s as SpatialPose } from "./pathfinding-D7W8uqm1.js";
7
7
  import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
8
8
  import { VRM } from "@pixiv/three-vrm";
9
9
  import { Sky } from "three/examples/jsm/objects/Sky.js";
@@ -3006,6 +3006,48 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
3006
3006
  underwaterAt(camX: number, camY: number, camZ: number): (UnderwaterConfig & {
3007
3007
  surfaceY: number;
3008
3008
  }) | null;
3009
+ /**
3010
+ * Give the GPU allocations back.
3011
+ *
3012
+ * A fancy surface holds a cube target, a half-res scene pre-pass (colour +
3013
+ * depth) and — with `mirror` on — a mirror target at half the drawing buffer,
3014
+ * 4x MSAA, half-float. Tens of megabytes, PER WATER NODE.
3015
+ *
3016
+ * Until now the only thing that released any of it was `free()`, so every way
3017
+ * of stopping using one kept all of it: turning the mirror off zeroed a
3018
+ * uniform, and water off camera or under the player simply returned early.
3019
+ * Survivable while quality was decided once at load; not survivable now that
3020
+ * a settings menu turns the mirror off on a running game.
3021
+ */
3022
+ private releasePassTargets;
3023
+ /**
3024
+ * Frames in a row that took no pass at all (submerged, or off camera).
3025
+ *
3026
+ * Releasing on the FIRST idle frame would be worse than the leak: a camera
3027
+ * panning past a lake would allocate and free a mirror target every other
3028
+ * frame, and allocation is not free either. Only a surface nobody has looked
3029
+ * at for a couple of seconds hands its memory back.
3030
+ */
3031
+ private idleFrames;
3032
+ /**
3033
+ * The tier's ceiling, or null when nothing has told us (headless, tests, a
3034
+ * renderer that does not push caps). Null means "no ceiling" — the authored
3035
+ * props stand.
3036
+ */
3037
+ private caps;
3038
+ /** @internal See {@link QualityConsumer3D} — a ceiling, never an upgrade. */
3039
+ _applyQualityCaps(caps: QualityCaps): void;
3040
+ /**
3041
+ * What this surface actually draws, once the tier has had its say.
3042
+ *
3043
+ * ONE-DIRECTIONAL: a cap can turn fancy into simple, never simple into fancy.
3044
+ * And it never writes `this.quality` — a tier is a runtime ceiling, not an
3045
+ * edit, so serializing a game running at low still writes what the author
3046
+ * chose.
3047
+ */
3048
+ private effectiveQuality;
3049
+ /** One frame that took no pass; release everything once it has been a while. */
3050
+ private noteIdleFrame;
3009
3051
  override free(): void;
3010
3052
  /** Swap geometry+material only when a surface-shaping prop changed. */
3011
3053
  private rebuildSurfaceIfNeeded;
@@ -3408,6 +3450,17 @@ interface SyncOptions {
3408
3450
  /** Render interpolation factor (0..1) for fixed-step physics bodies; see
3409
3451
  * Engine.interpolationAlpha. Defaults to 1 (render the current transform). */
3410
3452
  alpha?: number;
3453
+ /**
3454
+ * The quality tier's ceiling, pushed to every `_applyQualityCaps` node
3455
+ * (Water3D) BEFORE its own sync — a node that rebuilds because the cap
3456
+ * changed must do it in the same frame, not the next one.
3457
+ *
3458
+ * The same route as `sunDirection` and for the same reason: the walk already
3459
+ * touches every node, so nothing has to subscribe or unsubscribe. A `static`
3460
+ * subtree is pruned before this point and never receives caps — which is
3461
+ * correct, since it is not being synced at all.
3462
+ */
3463
+ quality?: QualityCaps | null;
3411
3464
  }
3412
3465
  /**
3413
3466
  * Mirror an Incanto node tree onto a three.js scene (dirty-push, once per frame):
@@ -3434,6 +3487,7 @@ interface WalkState {
3434
3487
  sunLight: DirectionalLight3D | null;
3435
3488
  alpha: number;
3436
3489
  ignoreStatic: boolean;
3490
+ quality: QualityCaps | null;
3437
3491
  }
3438
3492
  //#endregion
3439
3493
  //#region src/3d/terrain-nav.d.ts
package/dist/3d.js CHANGED
@@ -1,8 +1,8 @@
1
- import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-CsJDUQh_.js";
2
- import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-C0Axpfth.js";
3
- import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-DqY2lMBc.js";
1
+ import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-BPGomkHR.js";
2
+ import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-bokhdw_w.js";
3
+ import { a as Environment3D, c as parseEnvironment3D, d as AssetStore3D, i as syncTree, l as sunDirectionFromElevationAzimuth, o as setEnvironment3D, r as Renderer3D, s as horizonColorFromSky, t as createGame3D, u as sunDirectionFromSky } from "./create-game-R_8_gTCU.js";
4
4
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
5
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-C8242nXr.js";
5
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-Cpgc5ZM0.js";
6
6
  //#region src/3d/terrain-nav.ts
7
7
  function buildTerrainNav(terrain, opts) {
8
8
  const cellSize = opts?.cellSize ?? 2;
@@ -1209,6 +1209,45 @@ declare class Settings {
1209
1209
  * `qualityRendering`.
1210
1210
  */
1211
1211
  declare function qualityEnvironment(tier: QualityTier): Record<string, JsonValue>;
1212
+ /**
1213
+ * What a quality tier means for the levers that can only be set at BOOT.
1214
+ *
1215
+ * `antialias` is a context attribute: three fixes it when the WebGL context is
1216
+ * created, so a settings menu that changes it is choosing what the NEXT launch
1217
+ * gets. Every engine has this constraint and every game's options screen says
1218
+ * "requires restart" next to it — `createGame3D` reads the saved tier at boot,
1219
+ * so the restart is all it takes.
1220
+ *
1221
+ * `pixelRatio` CAN change live (adaptive resolution already does it), but it
1222
+ * belongs with antialias as "how many pixels do we draw" rather than "what is in
1223
+ * the scene".
1224
+ */
1225
+ /**
1226
+ * The per-tier CEILING for nodes that are expensive on their own.
1227
+ *
1228
+ * The quality tier travels as an environment patch, and an environment patch
1229
+ * can only reach environment stages — shadows, bloom, post, clouds. Water is
1230
+ * the single most expensive thing this engine draws and it is a NODE, so no
1231
+ * tier could touch it.
1232
+ *
1233
+ * These caps ride the render sync walk instead (see `SyncOptions.quality`). The
1234
+ * contract is one-directional and everything rests on it: **a cap clamps DOWN,
1235
+ * never up.** A tier may take away what the scene asked for; it may never give
1236
+ * a scene something it did not ask for, or `high` on a phone would silently
1237
+ * upgrade a deliberately cheap pond into a mirror.
1238
+ */
1239
+ interface QualityCaps {
1240
+ /**
1241
+ * Whether a water surface may run its multi-pass "fancy" path at all.
1242
+ *
1243
+ * False collapses it to the single-pass lake shader: no planar mirror, no
1244
+ * reflection cube, no refraction grab, no depth completion — 8.4 scene
1245
+ * submissions a frame become 3.5. It is the largest single saving available
1246
+ * on a low-end device, and it is not free: the simple shader has no samplers,
1247
+ * so the shoreline dissolve, contact foam and depth absorption go with it.
1248
+ */
1249
+ fancyWater: boolean;
1250
+ }
1212
1251
  //#endregion
1213
1252
  //#region src/core/stats.d.ts
1214
1253
  /**
@@ -1620,4 +1659,4 @@ declare function registeredBehaviors(): string[];
1620
1659
  /** Test isolation helper. */
1621
1660
  declare function clearBehaviors(): void;
1622
1661
  //#endregion
1623
- export { translationKey as $, qualityEnvironment as A, LogManager as At, restoreBehaviors as B, EngineStats as C, AudioBuses as Ct, QualityTier as D, SceneTree as Dt, DeviceHints as E, NodeLifecycle as Et, RestoreReport as F, OrderGroupTable as G, createSaveStore as H, SaveSlot as I, BASE_LOCALE as J, effectiveOrder as K, SaveSlots as L, suggestQuality as M, SignalListener as Mt, Scene as N, Settings as O, LogEntry as Ot, BehaviorState as P, suggestLocale as Q, behaviorsWithoutSave as R, Scheduler as S, PlayMusicOptions as St, RendererStats as T, Node as Tt, ORDER_GROUP_BASE as U, SaveStore as V, OrderGroup as W, Localization as X, LocaleTables as Y, T_PREFIX as Z, mergeStaticSignals as _, SynthOptions as _t, clearBehaviors as a, VoicePreset as at, Engine as b, MusicManager as bt, registeredBehaviors as c, RolloffModel as ct, PropSchema as d, spatialGain as dt, InputMap as et, clearRegistry as f, spatialPan as ft, getNodeType as g, SfxWave as gt, getNodeSignals as h, SfxParams as ht, behaviorSignals as i, Voice as it, readDeviceHints as j, Signal as jt, SettingsValues as k, LogLevel as kt, NodeCtor as l, SpatialParams as lt, getNodeSchema as m, SFX_PRESET_NAMES as mt, BehaviorCtor as n, SfxPlayOptions as nt, getBehavior as o, Listener as ot, createNode as p, SFX_PRESETS as pt, resolveOrderGroups as q, behaviorSchema as r, isAudioContextAvailable as rt, registerBehavior as s, ROLLOFF_MODELS as st, Behavior as t, SfxEngine as tt, PropDef as u, Vec3 as ut, registerNode as v, synthSfx as vt, GameStats as w, BusName as wt, EngineOptions as x, MusicTrack as xt, registeredTypes as y, MusicBackend as yt, captureBehaviors as z };
1662
+ export { suggestLocale as $, SettingsValues as A, LogLevel as At, captureBehaviors as B, EngineStats as C, PlayMusicOptions as Ct, QualityCaps as D, NodeLifecycle as Dt, DeviceHints as E, Node as Et, BehaviorState as F, OrderGroup as G, SaveStore as H, RestoreReport as I, resolveOrderGroups as J, OrderGroupTable as K, SaveSlot as L, readDeviceHints as M, Signal as Mt, suggestQuality as N, SignalListener as Nt, QualityTier as O, SceneTree as Ot, Scene as P, T_PREFIX as Q, SaveSlots as R, Scheduler as S, MusicTrack as St, RendererStats as T, BusName as Tt, createSaveStore as U, restoreBehaviors as V, ORDER_GROUP_BASE as W, LocaleTables as X, BASE_LOCALE as Y, Localization as Z, mergeStaticSignals as _, SfxWave as _t, clearBehaviors as a, Voice as at, Engine as b, MusicBackend as bt, registeredBehaviors as c, ROLLOFF_MODELS as ct, PropSchema as d, Vec3 as dt, translationKey as et, clearRegistry as f, spatialGain as ft, getNodeType as g, SfxParams as gt, getNodeSignals as h, SFX_PRESET_NAMES as ht, behaviorSignals as i, isAudioContextAvailable as it, qualityEnvironment as j, LogManager as jt, Settings as k, LogEntry as kt, NodeCtor as l, RolloffModel as lt, getNodeSchema as m, SFX_PRESETS as mt, BehaviorCtor as n, SfxEngine as nt, getBehavior as o, VoicePreset as ot, createNode as p, spatialPan as pt, effectiveOrder as q, behaviorSchema as r, SfxPlayOptions as rt, registerBehavior as s, Listener as st, Behavior as t, InputMap as tt, PropDef as u, SpatialParams as ut, registerNode as v, SynthOptions as vt, GameStats as w, AudioBuses as wt, EngineOptions as x, MusicManager as xt, registeredTypes as y, synthSfx as yt, behaviorsWithoutSave as z };
@@ -1,13 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { n as loadScene, o as computeViewport, s as resolveViewport, v as diagnose, w as registerBehavior } from "./loader-r49nDwB4.js";
3
- import { h as Engine, m as AudioPlayer } from "./register-Dm7nrd-E.js";
3
+ import { h as Engine, m as AudioPlayer } from "./register-CGf5NKrc.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
6
6
  import { i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-CCtAMDLB.js";
7
- import { n as registerGameplayBehaviors } from "./gameplay-CsJDUQh_.js";
8
- import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-DnB9m7Rl.js";
7
+ import { n as registerGameplayBehaviors } from "./gameplay-BPGomkHR.js";
8
+ import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-C2iO_yLv.js";
9
9
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
10
- import { n as enablePhysics2D } from "./physics-2d-OfKb0PV_.js";
10
+ import { n as enablePhysics2D } from "./physics-2d-B9ktSWrr.js";
11
11
  import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
12
12
  //#region src/2d/assets.ts
13
13
  /**
@@ -1,13 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { n as loadScene, v as diagnose, w as registerBehavior } from "./loader-r49nDwB4.js";
3
- import { h as Engine, m as AudioPlayer, v as qualityRendering } from "./register-Dm7nrd-E.js";
3
+ import { _ as qualityCaps, h as Engine, m as AudioPlayer, y as qualityRendering } from "./register-CGf5NKrc.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
6
6
  import { a as poseFromRenderer, i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-CCtAMDLB.js";
7
- import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-CsJDUQh_.js";
7
+ import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-BPGomkHR.js";
8
8
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
9
- import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-C0Axpfth.js";
10
- import { n as enablePhysics3D } from "./physics-3d-C8242nXr.js";
9
+ import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-bokhdw_w.js";
10
+ import { n as enablePhysics3D } from "./physics-3d-Cpgc5ZM0.js";
11
11
  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";
12
12
  import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
13
13
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
@@ -1382,7 +1382,8 @@ function createSyncScratch() {
1382
1382
  sunDirection: null,
1383
1383
  sunLight: null,
1384
1384
  alpha: 1,
1385
- ignoreStatic: false
1385
+ ignoreStatic: false,
1386
+ quality: null
1386
1387
  }
1387
1388
  };
1388
1389
  }
@@ -1409,6 +1410,7 @@ function syncTree(root, threeScene, assets, opts, scratch) {
1409
1410
  state.ignoreStatic = opts?.ignoreStatic === true;
1410
1411
  state.sunLight = null;
1411
1412
  state.alpha = opts?.alpha ?? 1;
1413
+ state.quality = opts?.quality ?? null;
1412
1414
  walk(root, threeScene, state);
1413
1415
  prune(threeScene, s.visited);
1414
1416
  let current = null;
@@ -1484,6 +1486,10 @@ function walk(node, parentObj, state) {
1484
1486
  return;
1485
1487
  }
1486
1488
  if (obj.parent !== parentObj) parentObj.add(obj);
1489
+ if (state.quality) {
1490
+ const applyCaps = node._applyQualityCaps;
1491
+ if (typeof applyCaps === "function") applyCaps.call(node, state.quality);
1492
+ }
1487
1493
  node._syncObject3D(state.alpha, state.assets ?? null);
1488
1494
  if (state.assets && node instanceof ModelInstance3D) node._syncModel(state.assets);
1489
1495
  if (typeof node._onRender3D === "function") state.renderHooks.push(node);
@@ -1798,7 +1804,8 @@ var Renderer3D = class {
1798
1804
  const { activeCamera: sceneCamera, renderHooks, sunLight } = syncTree(scene.root, this.threeScene, this.assets, {
1799
1805
  sunDirection: this.environment.sunDirection,
1800
1806
  alpha: this.engine.interpolationAlpha,
1801
- ignoreStatic: this.ignoreStatic
1807
+ ignoreStatic: this.ignoreStatic,
1808
+ quality: qualityCaps(this.engine.settings.get("quality"))
1802
1809
  }, this.syncScratch);
1803
1810
  let activeCamera = sceneCamera;
1804
1811
  if (this.viewOverride) {
package/dist/debug.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { T as RendererStats, b as Engine, kt as LogLevel } from "./behavior-B5PJ32eu.js";
1
+ import { At as LogLevel, T as RendererStats, b as Engine } from "./behavior-BNNSIXS5.js";
2
2
 
3
3
  //#region src/debug/panel.d.ts
4
4
  /** Minimal document surface the overlay needs (injectable for tests). */
@@ -1,10 +1,10 @@
1
- import { t as registerCoreNodes } from "./register-Dm7nrd-E.js";
1
+ import { t as registerCoreNodes } from "./register-CGf5NKrc.js";
2
2
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
3
  import { t as Rng } from "./rng-DP-SR7eg.js";
4
4
  import { i as getNodeSchema, l as registerNode } from "./registry-IyWCGe4q.js";
5
5
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
6
6
  import { i as applyParticlePreset, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
7
- import { A as Water3D, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-CsJDUQh_.js";
7
+ import { A as Water3D, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-BPGomkHR.js";
8
8
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
9
9
  import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, ClampToEdgeWrapping, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LinearMipmapLinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NoColorSpace, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
10
10
  import { clone } from "three/addons/utils/SkeletonUtils.js";
@@ -2797,6 +2797,13 @@ const WAVE_WORLD_REF = 128;
2797
2797
  const AMPLITUDE_PER_WAVE_HEIGHT = REFERENCE_AMPLITUDE / REFERENCE_WAVE_HEIGHT;
2798
2798
  /** Cube-map reflection resolution (source: reflectionQuality = 256). */
2799
2799
  const REFLECTION_RESOLUTION = 256;
2800
+ /**
2801
+ * Idle frames before a surface hands its render targets back — ~2 seconds at
2802
+ * 60 fps, and longer at a capped 30. Long enough that turning to look at a lake
2803
+ * and turning away again never reallocates, short enough that the water behind
2804
+ * you in an open world is not still holding tens of megabytes a minute later.
2805
+ */
2806
+ const IDLE_FRAMES_BEFORE_RELEASE = 120;
2800
2807
  /** Cube-map refresh floor while a planar mirror is on — it is only the
2801
2808
  * off-screen fallback then, so six faces a second is already generous. */
2802
2809
  const MIRRORED_CUBE_INTERVAL = 2e3;
@@ -3154,7 +3161,7 @@ var Water3D = class Water3D extends Node3D {
3154
3161
  super._syncObject3D();
3155
3162
  const mesh = this._ensureObject3D();
3156
3163
  this.rebuildSurfaceIfNeeded(mesh);
3157
- if (this.quality === "simple") this.syncSimple(mesh);
3164
+ if (this.effectiveQuality() === "simple") this.syncSimple(mesh);
3158
3165
  else this.syncFancy(mesh);
3159
3166
  }
3160
3167
  /**
@@ -3177,13 +3184,18 @@ var Water3D = class Water3D extends Node3D {
3177
3184
  if (u.uUseMirror) u.uUseMirror.value = 0;
3178
3185
  if (u.uCameraSubmerged) u.uCameraSubmerged.value = 1;
3179
3186
  }
3187
+ this.noteIdleFrame();
3180
3188
  return;
3181
3189
  }
3182
- if (this.quality !== "fancy" || !material.isShaderMaterial) return;
3190
+ if (this.effectiveQuality() !== "fancy" || !material.isShaderMaterial) return;
3183
3191
  const halfDiagonal = Math.hypot((this.size[0] ?? 1) / 2, (this.size[1] ?? 1) / 2);
3184
- if (!sphereInCameraFrustum(ctx.camera, worldTranslationOf(this), halfDiagonal + 1)) return;
3192
+ if (!sphereInCameraFrustum(ctx.camera, worldTranslationOf(this), halfDiagonal + 1)) {
3193
+ this.noteIdleFrame();
3194
+ return;
3195
+ }
3185
3196
  const u = material.uniforms;
3186
3197
  if (u.uCameraSubmerged) u.uCameraSubmerged.value = 0;
3198
+ this.idleFrames = 0;
3187
3199
  const now = Date.now();
3188
3200
  if (this.reflection) {
3189
3201
  if (!this.cubeTarget) this.cubeTarget = new WebGLCubeRenderTarget(REFLECTION_RESOLUTION, {
@@ -3273,7 +3285,10 @@ var Water3D = class Water3D extends Node3D {
3273
3285
  u.uMirrorMap.value = this.mirrorTarget.texture;
3274
3286
  u.uMirrorMatrix.value.copy(this.mirrorMatrix);
3275
3287
  u.uUseMirror.value = 1;
3276
- } else if (u.uUseMirror) u.uUseMirror.value = 0;
3288
+ } else if (u.uUseMirror) {
3289
+ u.uUseMirror.value = 0;
3290
+ this.releasePassTargets("mirror");
3291
+ }
3277
3292
  ctx.gl.getDrawingBufferSize(drawingBufferScratch);
3278
3293
  const passW = Math.max(1, Math.min(Math.round(drawingBufferScratch.x / 2), SCENE_PASS_MAX));
3279
3294
  const passH = Math.max(1, Math.min(Math.round(drawingBufferScratch.y / 2), SCENE_PASS_MAX));
@@ -3356,30 +3371,85 @@ var Water3D = class Water3D extends Node3D {
3356
3371
  surfaceY: center.y
3357
3372
  } : null;
3358
3373
  }
3359
- free() {
3360
- const mesh = this._builtObject3D;
3361
- mesh?.geometry?.dispose();
3362
- (mesh?.material)?.dispose?.();
3374
+ /**
3375
+ * Give the GPU allocations back.
3376
+ *
3377
+ * A fancy surface holds a cube target, a half-res scene pre-pass (colour +
3378
+ * depth) and — with `mirror` on — a mirror target at half the drawing buffer,
3379
+ * 4x MSAA, half-float. Tens of megabytes, PER WATER NODE.
3380
+ *
3381
+ * Until now the only thing that released any of it was `free()`, so every way
3382
+ * of stopping using one kept all of it: turning the mirror off zeroed a
3383
+ * uniform, and water off camera or under the player simply returned early.
3384
+ * Survivable while quality was decided once at load; not survivable now that
3385
+ * a settings menu turns the mirror off on a running game.
3386
+ */
3387
+ releasePassTargets(which) {
3388
+ this.mirrorTarget?.dispose();
3389
+ this.mirrorTarget = null;
3390
+ if (which === "mirror") return;
3363
3391
  this.cubeTarget?.dispose();
3364
3392
  this.cubeTarget = null;
3365
3393
  this.cubeCamera = null;
3366
3394
  this.scenePassTarget?.depthTexture?.dispose();
3367
3395
  this.scenePassTarget?.dispose();
3368
3396
  this.scenePassTarget = null;
3369
- this.mirrorTarget?.dispose();
3370
- this.mirrorTarget = null;
3397
+ }
3398
+ /**
3399
+ * Frames in a row that took no pass at all (submerged, or off camera).
3400
+ *
3401
+ * Releasing on the FIRST idle frame would be worse than the leak: a camera
3402
+ * panning past a lake would allocate and free a mirror target every other
3403
+ * frame, and allocation is not free either. Only a surface nobody has looked
3404
+ * at for a couple of seconds hands its memory back.
3405
+ */
3406
+ idleFrames = 0;
3407
+ /**
3408
+ * The tier's ceiling, or null when nothing has told us (headless, tests, a
3409
+ * renderer that does not push caps). Null means "no ceiling" — the authored
3410
+ * props stand.
3411
+ */
3412
+ caps = null;
3413
+ /** @internal See {@link QualityConsumer3D} — a ceiling, never an upgrade. */
3414
+ _applyQualityCaps(caps) {
3415
+ this.caps = caps;
3416
+ }
3417
+ /**
3418
+ * What this surface actually draws, once the tier has had its say.
3419
+ *
3420
+ * ONE-DIRECTIONAL: a cap can turn fancy into simple, never simple into fancy.
3421
+ * And it never writes `this.quality` — a tier is a runtime ceiling, not an
3422
+ * edit, so serializing a game running at low still writes what the author
3423
+ * chose.
3424
+ */
3425
+ effectiveQuality() {
3426
+ if (this.caps && !this.caps.fancyWater) return "simple";
3427
+ return this.quality;
3428
+ }
3429
+ /** One frame that took no pass; release everything once it has been a while. */
3430
+ noteIdleFrame() {
3431
+ this.idleFrames += 1;
3432
+ if (this.idleFrames === IDLE_FRAMES_BEFORE_RELEASE) this.releasePassTargets("all");
3433
+ }
3434
+ free() {
3435
+ const mesh = this._builtObject3D;
3436
+ mesh?.geometry?.dispose();
3437
+ (mesh?.material)?.dispose?.();
3438
+ this.releasePassTargets("all");
3371
3439
  super.free();
3372
3440
  }
3373
3441
  /** Swap geometry+material only when a surface-shaping prop changed. */
3374
3442
  rebuildSurfaceIfNeeded(mesh) {
3375
- const key = JSON.stringify([this.size, this.quality]);
3443
+ const quality = this.effectiveQuality();
3444
+ const key = JSON.stringify([this.size, quality]);
3376
3445
  if (key === this.surfaceKey && mesh.geometry.getAttribute("position")) return;
3377
3446
  this.surfaceKey = key;
3378
3447
  mesh.geometry?.dispose();
3379
3448
  mesh.material?.dispose?.();
3380
3449
  const w = this.size[0] ?? 1;
3381
3450
  const d = this.size[1] ?? 1;
3382
- if (this.quality === "simple") {
3451
+ if (quality === "simple") {
3452
+ this.releasePassTargets("all");
3383
3453
  mesh.geometry = buildWaterGeometry(w, d, SIMPLE_SEGMENTS);
3384
3454
  mesh.material = this.buildLakeMaterial();
3385
3455
  } else {
@@ -3766,7 +3836,7 @@ var Water3D = class Water3D extends Node3D {
3766
3836
  /** Base wave height at world (x, z) — the CPU twin of the active shader.
3767
3837
  * Ripples are excluded on purpose: a splash must not re-trigger itself. */
3768
3838
  waveOffsetAt(x, z, center) {
3769
- if (this.quality === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.rp("waveHeight"));
3839
+ if (this.effectiveQuality() === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.rp("waveHeight"));
3770
3840
  return waveElevation(x, z, this.time, {
3771
3841
  amplitude: this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT,
3772
3842
  frequency: FANCY_WAVE.frequency,
@@ -1,4 +1,4 @@
1
- import { Tt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, t as Behavior } from "./behavior-B5PJ32eu.js";
1
+ import { Et as Node, b as Engine, d as PropSchema, n as BehaviorCtor, t as Behavior } from "./behavior-BNNSIXS5.js";
2
2
  import { c as JsonValue, s as JsonObject } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/gameplay/chase.d.ts
package/dist/gameplay.js CHANGED
@@ -1,2 +1,2 @@
1
- import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-CsJDUQh_.js";
1
+ import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-BPGomkHR.js";
2
2
  export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { $ as translationKey, A as qualityEnvironment, At as LogManager, B as restoreBehaviors, C as EngineStats, Ct as AudioBuses, D as QualityTier, Dt as SceneTree, E as DeviceHints, Et as NodeLifecycle, F as RestoreReport, G as OrderGroupTable, H as createSaveStore, I as SaveSlot, J as BASE_LOCALE, K as effectiveOrder, L as SaveSlots, M as suggestQuality, Mt as SignalListener, N as Scene, O as Settings, Ot as LogEntry, P as BehaviorState, Q as suggestLocale, R as behaviorsWithoutSave, S as Scheduler, St as PlayMusicOptions, T as RendererStats, Tt as Node, U as ORDER_GROUP_BASE, V as SaveStore, W as OrderGroup, X as Localization, Y as LocaleTables, Z as T_PREFIX, _ as mergeStaticSignals, _t as SynthOptions, a as clearBehaviors, at as VoicePreset, b as Engine, bt as MusicManager, c as registeredBehaviors, ct as RolloffModel, d as PropSchema, dt as spatialGain, et as InputMap, f as clearRegistry, ft as spatialPan, g as getNodeType, gt as SfxWave, h as getNodeSignals, ht as SfxParams, i as behaviorSignals, it as Voice, j as readDeviceHints, jt as Signal, k as SettingsValues, kt as LogLevel, l as NodeCtor, lt as SpatialParams, m as getNodeSchema, mt as SFX_PRESET_NAMES, n as BehaviorCtor, nt as SfxPlayOptions, o as getBehavior, ot as Listener, p as createNode, pt as SFX_PRESETS, q as resolveOrderGroups, r as behaviorSchema, rt as isAudioContextAvailable, s as registerBehavior, st as ROLLOFF_MODELS, t as Behavior, tt as SfxEngine, u as PropDef, ut as Vec3, v as registerNode, vt as synthSfx, w as GameStats, wt as BusName, x as EngineOptions, xt as MusicTrack, y as registeredTypes, yt as MusicBackend, z as captureBehaviors } from "./behavior-B5PJ32eu.js";
1
+ import { $ as suggestLocale, A as SettingsValues, At as LogLevel, B as captureBehaviors, C as EngineStats, Ct as PlayMusicOptions, Dt as NodeLifecycle, E as DeviceHints, Et as Node, F as BehaviorState, G as OrderGroup, H as SaveStore, I as RestoreReport, J as resolveOrderGroups, K as OrderGroupTable, L as SaveSlot, M as readDeviceHints, Mt as Signal, N as suggestQuality, Nt as SignalListener, O as QualityTier, Ot as SceneTree, P as Scene, Q as T_PREFIX, R as SaveSlots, S as Scheduler, St as MusicTrack, T as RendererStats, Tt as BusName, U as createSaveStore, V as restoreBehaviors, W as ORDER_GROUP_BASE, X as LocaleTables, Y as BASE_LOCALE, Z as Localization, _ as mergeStaticSignals, _t as SfxWave, a as clearBehaviors, at as Voice, b as Engine, bt as MusicBackend, c as registeredBehaviors, ct as ROLLOFF_MODELS, d as PropSchema, dt as Vec3, et as translationKey, f as clearRegistry, ft as spatialGain, g as getNodeType, gt as SfxParams, h as getNodeSignals, ht as SFX_PRESET_NAMES, i as behaviorSignals, it as isAudioContextAvailable, j as qualityEnvironment, jt as LogManager, k as Settings, kt as LogEntry, l as NodeCtor, lt as RolloffModel, m as getNodeSchema, mt as SFX_PRESETS, n as BehaviorCtor, nt as SfxEngine, o as getBehavior, ot as VoicePreset, p as createNode, pt as spatialPan, q as effectiveOrder, r as behaviorSchema, rt as SfxPlayOptions, s as registerBehavior, st as Listener, t as Behavior, tt as InputMap, u as PropDef, ut as SpatialParams, v as registerNode, vt as SynthOptions, w as GameStats, wt as AudioBuses, x as EngineOptions, xt as MusicManager, y as registeredTypes, yt as synthSfx, z as behaviorsWithoutSave } from "./behavior-BNNSIXS5.js";
2
2
  import { a as Rng, c as JsonValue, d as jsonKind, i as SceneJson, l as jsonClone, n as NodeJson, o as JsonKind, r as SCENE_FORMAT, s as JsonObject, t as ConnectionJson, u as jsonEquals } from "./schema-CFeioQRE.js";
3
- import { n as loadScene, t as LoadSceneOptions } from "./loader-DSMdqasu.js";
3
+ import { n as loadScene, t as LoadSceneOptions } from "./loader-mSL65Djg.js";
4
4
  import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
5
- import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-BrE5Uec6.js";
6
- import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-Cxrr-ApH.js";
5
+ import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-D7W8uqm1.js";
6
+ import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-CwdWgz0f.js";
7
7
 
8
8
  //#region src/core/audio/crossfade.d.ts
9
9
  /**
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { C as getBehavior, E as Signal, S as clearBehaviors, T as registeredBehaviors, _ as InputMap, a as SCENE_FORMAT, b as behaviorSchema, c as SceneTree, d as resolveConstants, f as Node, g as resolveOrderGroups, h as effectiveOrder, i as serializeNode, l as CONST_REF_KEY, m as ORDER_GROUP_BASE, n as loadScene, o as computeViewport, p as parseNodePath, r as Scene, s as resolveViewport, u as isConstRef, w as registerBehavior, x as behaviorSignals, y as Behavior } from "./loader-r49nDwB4.js";
2
- import { A as suggestLocale, B as MusicManager, C as captureBehaviors, D as BASE_LOCALE, E as LogManager, F as spatialGain, H as crossfadeGains, I as spatialPan, L as SFX_PRESETS, M as SfxEngine, N as isAudioContextAvailable, O as Localization, P as ROLLOFF_MODELS, R as SFX_PRESET_NAMES, S as behaviorsWithoutSave, T as createSaveStore, U as fadeGain, V as WebAudioMusicBackend, W as AudioBuses, _ as qualityEnvironment, a as UiSlider, b as suggestQuality, c as UiButton, d as UiBanner, f as UiBar, g as Settings, h as Engine, i as UiSelect, j as translationKey, k as T_PREFIX, l as UiDialogue, m as AudioPlayer, n as UiImage, o as UiToggle, p as UiText, r as UiPanel, s as Timer, t as registerCoreNodes, u as HudLayer, w as restoreBehaviors, x as SaveSlots, y as readDeviceHints, z as synthSfx } from "./register-Dm7nrd-E.js";
2
+ import { A as T_PREFIX, B as synthSfx, C as behaviorsWithoutSave, D as LogManager, E as createSaveStore, F as ROLLOFF_MODELS, G as AudioBuses, H as WebAudioMusicBackend, I as spatialGain, L as spatialPan, M as translationKey, N as SfxEngine, O as BASE_LOCALE, P as isAudioContextAvailable, R as SFX_PRESETS, S as SaveSlots, T as restoreBehaviors, U as crossfadeGains, V as MusicManager, W as fadeGain, a as UiSlider, b as readDeviceHints, c as UiButton, d as UiBanner, f as UiBar, g as Settings, h as Engine, i as UiSelect, j as suggestLocale, k as Localization, l as UiDialogue, m as AudioPlayer, n as UiImage, o as UiToggle, p as UiText, r as UiPanel, s as Timer, t as registerCoreNodes, u as HudLayer, v as qualityEnvironment, w as captureBehaviors, x as suggestQuality, z as SFX_PRESET_NAMES } from "./register-CGf5NKrc.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { t as Rng } from "./rng-DP-SR7eg.js";
5
- import { n as startRecording, r as auditScene, t as replay } from "./replay-DH0UOuZ-.js";
5
+ import { n as startRecording, r as auditScene, t as replay } from "./replay-YQ9FW7Yh.js";
6
6
  import { n as jsonEquals, r as jsonKind, t as jsonClone } from "./json-BLk7H2Qa.js";
7
7
  import { a as getNodeSignals, c as mergeStaticSignals, i as getNodeSchema, l as registerNode, n as clearRegistry, o as getNodeType, r as createNode, u as registeredTypes } from "./registry-IyWCGe4q.js";
8
8
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
@@ -172,6 +172,6 @@ function newUid() {
172
172
  //#endregion
173
173
  //#region src/index.ts
174
174
  /** Engine version. Kept in sync with package.json by the release pipeline. */
175
- const VERSION = "0.38.0";
175
+ const VERSION = "0.39.0";
176
176
  //#endregion
177
177
  export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, 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, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
@@ -1,4 +1,4 @@
1
- import { N as Scene, b as Engine } from "./behavior-B5PJ32eu.js";
1
+ import { P as Scene, b as Engine } from "./behavior-BNNSIXS5.js";
2
2
  import { i as SceneJson } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/core/scene/loader.d.ts
package/dist/net.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Tt as Node, b as Engine, d as PropSchema, jt as Signal } from "./behavior-B5PJ32eu.js";
1
+ import { Et as Node, Mt as Signal, b as Engine, d as PropSchema } from "./behavior-BNNSIXS5.js";
2
2
  import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/net/types.d.ts
package/dist/net.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { n as loadScene } from "./loader-r49nDwB4.js";
2
- import { h as Engine } from "./register-Dm7nrd-E.js";
2
+ import { h as Engine } from "./register-CGf5NKrc.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { t as jsonClone } from "./json-BLk7H2Qa.js";
5
5
  import { n as createAgent8Server } from "./agent8-CvsfVskX.js";
6
- import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-B4RRQbyq.js";
6
+ import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-CiXP3-GB.js";
7
7
  //#region src/net/loopback.ts
8
8
  /**
9
9
  * In-memory multiplayer hub implementing the SAME kernel contract as
@@ -1,4 +1,4 @@
1
- import { Tt as Node, d as PropSchema, ot as Listener } from "./behavior-B5PJ32eu.js";
1
+ import { Et as Node, d as PropSchema, st as Listener } from "./behavior-BNNSIXS5.js";
2
2
 
3
3
  //#region src/core/nodes/audio-player.d.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { v as diagnose } from "./loader-r49nDwB4.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
- import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-DnB9m7Rl.js";
4
+ import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-C2iO_yLv.js";
5
5
  import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
6
6
  //#region src/2d/physics/physics-2d.ts
7
7
  var physics_2d_exports = /* @__PURE__ */ __exportAll({
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { v as diagnose } from "./loader-r49nDwB4.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
- import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-CsJDUQh_.js";
4
+ import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-BPGomkHR.js";
5
5
  import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
6
- import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-C0Axpfth.js";
6
+ import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-bokhdw_w.js";
7
7
  import { Euler, Matrix4, Quaternion, Vector3 } from "three";
8
8
  //#region src/3d/physics/collider-lines.ts
9
9
  /**
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { N as Scene, b as Engine, n as BehaviorCtor } from "./behavior-B5PJ32eu.js";
1
+ import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-BNNSIXS5.js";
2
2
  import { c as JsonValue } from "./schema-CFeioQRE.js";
3
3
  import { CSSProperties, ReactNode } from "react";
4
4
 
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-DqY2lMBc.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-C4t5gVhc.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-R_8_gTCU.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-DEtU2PRg.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;
@@ -1,5 +1,5 @@
1
1
  import { f as Node, h as effectiveOrder } from "./loader-r49nDwB4.js";
2
- import { t as registerCoreNodes } from "./register-Dm7nrd-E.js";
2
+ import { t as registerCoreNodes } from "./register-CGf5NKrc.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { t as Rng } from "./rng-DP-SR7eg.js";
5
5
  import { i as getNodeSchema, l as registerNode } from "./registry-IyWCGe4q.js";