incanto 0.38.0 → 0.40.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 +83 -3
  4. package/dist/3d.js +4 -4
  5. package/dist/{behavior-B5PJ32eu.d.ts → behavior-TA8nySqb.d.ts} +61 -1
  6. package/dist/{create-game-DqY2lMBc.js → create-game-CEKCtnKw.js} +13 -6
  7. package/dist/{create-game-C4t5gVhc.js → create-game-Dc2CEFtD.js} +4 -4
  8. package/dist/debug.d.ts +1 -1
  9. package/dist/{environment-presets-C0Axpfth.js → environment-presets-Z0PkDH62.js} +2 -2
  10. package/dist/{gameplay-CsJDUQh_.js → gameplay-CqNfawyn.js} +135 -15
  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-CvSDKC3v.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-_UlKUoox.d.ts} +1 -1
  19. package/dist/{physics-2d-OfKb0PV_.js → physics-2d-CxIqR1cW.js} +1 -1
  20. package/dist/{physics-3d-C8242nXr.js → physics-3d-CcUaeJXq.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-CgMO5JBY.js} +1 -1
  24. package/dist/{register-B4RRQbyq.js → register-D5v8iqjZ.js} +1 -1
  25. package/dist/{register-Dm7nrd-E.js → register-DMFJI-c_.js} +23 -11
  26. package/dist/{replay-Cxrr-ApH.d.ts → replay-DN-kG4va.d.ts} +1 -1
  27. package/dist/{replay-DH0UOuZ-.js → replay-D_QY5Xm3.js} +1 -1
  28. package/dist/{test-CoDPWx-m.js → test-CFhY8No9.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-COwolmAe.js} +1 -1
  33. package/editor/assets/{debug-BvTmHXI7.js → debug-DJSCLmsL.js} +1 -1
  34. package/editor/assets/{index-BS01WWgM.js → index-tRXhfJEm.js} +91 -91
  35. package/editor/index.html +1 -1
  36. package/package.json +1 -1
  37. package/skills/incanto-environment.md +32 -0
  38. package/skills/incanto-performance.md +23 -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-TA8nySqb.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-CvSDKC3v.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-Dc2CEFtD.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-CgMO5JBY.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-CxIqR1cW.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-TA8nySqb.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-CvSDKC3v.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-_UlKUoox.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,74 @@ 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
+ /**
3050
+ * Whether collapsing to the simple shader would still produce a waterline.
3051
+ *
3052
+ * A tier may make a game cheaper; it may not make it look broken. Found by
3053
+ * looking at the four water templates at every tier in a browser: the ocean
3054
+ * at low met the beach in a razor-straight line, because the simple shader's
3055
+ * only shoreline is a fade of its own rectangle and that rectangle's edge was
3056
+ * 800 m out to sea. Big water keeps the fancy shader at low — and still loses
3057
+ * its mirror, so the saving moves rather than disappears.
3058
+ *
3059
+ * This is NOT a veto on the author: a scene that asked for `quality: 'simple'`
3060
+ * gets it at any size. The guardrail only stops a TIER from choosing it.
3061
+ */
3062
+ private canFadeItsOwnRim;
3063
+ /** Whether the planar mirror runs — the tier can take it away, never add it. */
3064
+ private effectiveMirror;
3065
+ /**
3066
+ * How often the reflection cube may refresh, in ms.
3067
+ *
3068
+ * The floor is the whole reason a tier can drop the mirror and keep the
3069
+ * saving: the cube slows to `MIRRORED_CUBE_INTERVAL` only BECAUSE a mirror is
3070
+ * carrying the near reflection, so a capped-away mirror without a floor sends
3071
+ * the cube back to the scene's own interval — six faces of the scene, several
3072
+ * times a second.
3073
+ */
3074
+ private effectiveCubeInterval;
3075
+ /** One frame that took no pass; release everything once it has been a while. */
3076
+ private noteIdleFrame;
3009
3077
  override free(): void;
3010
3078
  /** Swap geometry+material only when a surface-shaping prop changed. */
3011
3079
  private rebuildSurfaceIfNeeded;
@@ -3408,6 +3476,17 @@ interface SyncOptions {
3408
3476
  /** Render interpolation factor (0..1) for fixed-step physics bodies; see
3409
3477
  * Engine.interpolationAlpha. Defaults to 1 (render the current transform). */
3410
3478
  alpha?: number;
3479
+ /**
3480
+ * The quality tier's ceiling, pushed to every `_applyQualityCaps` node
3481
+ * (Water3D) BEFORE its own sync — a node that rebuilds because the cap
3482
+ * changed must do it in the same frame, not the next one.
3483
+ *
3484
+ * The same route as `sunDirection` and for the same reason: the walk already
3485
+ * touches every node, so nothing has to subscribe or unsubscribe. A `static`
3486
+ * subtree is pruned before this point and never receives caps — which is
3487
+ * correct, since it is not being synced at all.
3488
+ */
3489
+ quality?: QualityCaps | null;
3411
3490
  }
3412
3491
  /**
3413
3492
  * Mirror an Incanto node tree onto a three.js scene (dirty-push, once per frame):
@@ -3434,6 +3513,7 @@ interface WalkState {
3434
3513
  sunLight: DirectionalLight3D | null;
3435
3514
  alpha: number;
3436
3515
  ignoreStatic: boolean;
3516
+ quality: QualityCaps | null;
3437
3517
  }
3438
3518
  //#endregion
3439
3519
  //#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-CqNfawyn.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-Z0PkDH62.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-CEKCtnKw.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-CcUaeJXq.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,66 @@ 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
+ /**
1251
+ * Whether a water surface may run its planar MIRROR pass — a whole extra
1252
+ * render of the scene, per water node, per frame.
1253
+ *
1254
+ * The most expensive single thing water does, and the first to go on a phone
1255
+ * that can still afford the rest of the fancy shader. The surface keeps its
1256
+ * cube reflection, so it still mirrors the sky and the far shore; what it
1257
+ * loses is the sharp reflection of nearby geometry.
1258
+ */
1259
+ waterMirror: boolean;
1260
+ /**
1261
+ * Floor (ms) on how often a reflection may be re-rendered. 0 = the scene
1262
+ * decides.
1263
+ *
1264
+ * This exists because of a trap: the reflection cube runs on a SLOW schedule
1265
+ * precisely because a mirror is present. Suppress the mirror without holding
1266
+ * that schedule and the cube starts refreshing at the scene's own interval —
1267
+ * six faces of the scene, several times a second — which hands most of the
1268
+ * saving straight back.
1269
+ */
1270
+ minReflectionIntervalMs: number;
1271
+ }
1212
1272
  //#endregion
1213
1273
  //#region src/core/stats.d.ts
1214
1274
  /**
@@ -1620,4 +1680,4 @@ declare function registeredBehaviors(): string[];
1620
1680
  /** Test isolation helper. */
1621
1681
  declare function clearBehaviors(): void;
1622
1682
  //#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 };
1683
+ 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, 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-DMFJI-c_.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-CqNfawyn.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-Z0PkDH62.js";
10
+ import { n as enablePhysics3D } from "./physics-3d-CcUaeJXq.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) {
@@ -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-DMFJI-c_.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-CqNfawyn.js";
8
+ import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-CgMO5JBY.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-CxIqR1cW.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
  /**
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-TA8nySqb.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-DMFJI-c_.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-CqNfawyn.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;
@@ -2826,6 +2833,22 @@ const FANCY_SEGMENTS_MIN = 24;
2826
2833
  const FANCY_SEGMENTS_MAX = 160;
2827
2834
  /** Simple quality: coarse enough to animate every vertex on the CPU. */
2828
2835
  const SIMPLE_SEGMENTS = 32;
2836
+ /**
2837
+ * The fraction of its half-extent over which the simple shader dissolves its
2838
+ * own rim — `smoothstep(0.82, 1.0, …)` in lake.ts, so the outer 18%.
2839
+ */
2840
+ const SIMPLE_EDGE_FADE_FRACTION = .18;
2841
+ /**
2842
+ * How wide that dissolve may be and still read as a SHORE, in metres.
2843
+ *
2844
+ * The simple shader has no depth texture, so fading its own rectangle is the
2845
+ * only waterline it can draw — it dissolves the plane's EDGE, not the place
2846
+ * where the ground rises. Fine when the water fills its basin (a 12 m pond
2847
+ * fades over 1.1 m, a 70 m lake over 6.3 m); useless when it does not (a
2848
+ * 1920 m ocean fades over 173 m, 800 m out to sea from the island it surrounds,
2849
+ * and meets the beach in a razor-straight line with no surf).
2850
+ */
2851
+ const SIMPLE_SHORE_BAND_MAX = 10;
2829
2852
  /** Bodies must rise this far above the waterline to 'exit' (no surface flicker). */
2830
2853
  const SURFACE_HYSTERESIS = .05;
2831
2854
  /** Entry splash amplitude: base + per-(m/s of |vy|), capped. */
@@ -3154,7 +3177,7 @@ var Water3D = class Water3D extends Node3D {
3154
3177
  super._syncObject3D();
3155
3178
  const mesh = this._ensureObject3D();
3156
3179
  this.rebuildSurfaceIfNeeded(mesh);
3157
- if (this.quality === "simple") this.syncSimple(mesh);
3180
+ if (this.effectiveQuality() === "simple") this.syncSimple(mesh);
3158
3181
  else this.syncFancy(mesh);
3159
3182
  }
3160
3183
  /**
@@ -3177,13 +3200,18 @@ var Water3D = class Water3D extends Node3D {
3177
3200
  if (u.uUseMirror) u.uUseMirror.value = 0;
3178
3201
  if (u.uCameraSubmerged) u.uCameraSubmerged.value = 1;
3179
3202
  }
3203
+ this.noteIdleFrame();
3180
3204
  return;
3181
3205
  }
3182
- if (this.quality !== "fancy" || !material.isShaderMaterial) return;
3206
+ if (this.effectiveQuality() !== "fancy" || !material.isShaderMaterial) return;
3183
3207
  const halfDiagonal = Math.hypot((this.size[0] ?? 1) / 2, (this.size[1] ?? 1) / 2);
3184
- if (!sphereInCameraFrustum(ctx.camera, worldTranslationOf(this), halfDiagonal + 1)) return;
3208
+ if (!sphereInCameraFrustum(ctx.camera, worldTranslationOf(this), halfDiagonal + 1)) {
3209
+ this.noteIdleFrame();
3210
+ return;
3211
+ }
3185
3212
  const u = material.uniforms;
3186
3213
  if (u.uCameraSubmerged) u.uCameraSubmerged.value = 0;
3214
+ this.idleFrames = 0;
3187
3215
  const now = Date.now();
3188
3216
  if (this.reflection) {
3189
3217
  if (!this.cubeTarget) this.cubeTarget = new WebGLCubeRenderTarget(REFLECTION_RESOLUTION, {
@@ -3197,7 +3225,7 @@ var Water3D = class Water3D extends Node3D {
3197
3225
  this.cubeCamera = new CubeCamera(near, 1e3, this.cubeTarget);
3198
3226
  this.lastReflectionAt = 0;
3199
3227
  }
3200
- const cubeInterval = this.mirror ? Math.max(this.rp("reflectionInterval"), MIRRORED_CUBE_INTERVAL) : this.rp("reflectionInterval");
3228
+ const cubeInterval = this.effectiveCubeInterval();
3201
3229
  if (this.lastReflectionAt === 0 || now - this.lastReflectionAt >= cubeInterval) {
3202
3230
  this.lastReflectionAt = now;
3203
3231
  const center = worldTranslationOf(this);
@@ -3213,7 +3241,7 @@ var Water3D = class Water3D extends Node3D {
3213
3241
  u.uUseEnvironmentMap.value = 1;
3214
3242
  }
3215
3243
  }
3216
- if (this.mirror && u.uMirrorMap && u.uMirrorMatrix && u.uUseMirror) {
3244
+ if (this.effectiveMirror() && u.uMirrorMap && u.uMirrorMatrix && u.uUseMirror) {
3217
3245
  ctx.gl.getDrawingBufferSize(drawingBufferScratch);
3218
3246
  const mirrorW = Math.max(1, Math.min(Math.round(drawingBufferScratch.x / MIRROR_PASS_SCALE), MIRROR_PASS_MAX));
3219
3247
  const mirrorH = Math.max(1, Math.min(Math.round(drawingBufferScratch.y / MIRROR_PASS_SCALE), MIRROR_PASS_MAX));
@@ -3273,7 +3301,10 @@ var Water3D = class Water3D extends Node3D {
3273
3301
  u.uMirrorMap.value = this.mirrorTarget.texture;
3274
3302
  u.uMirrorMatrix.value.copy(this.mirrorMatrix);
3275
3303
  u.uUseMirror.value = 1;
3276
- } else if (u.uUseMirror) u.uUseMirror.value = 0;
3304
+ } else if (u.uUseMirror) {
3305
+ u.uUseMirror.value = 0;
3306
+ this.releasePassTargets("mirror");
3307
+ }
3277
3308
  ctx.gl.getDrawingBufferSize(drawingBufferScratch);
3278
3309
  const passW = Math.max(1, Math.min(Math.round(drawingBufferScratch.x / 2), SCENE_PASS_MAX));
3279
3310
  const passH = Math.max(1, Math.min(Math.round(drawingBufferScratch.y / 2), SCENE_PASS_MAX));
@@ -3356,30 +3387,119 @@ var Water3D = class Water3D extends Node3D {
3356
3387
  surfaceY: center.y
3357
3388
  } : null;
3358
3389
  }
3359
- free() {
3360
- const mesh = this._builtObject3D;
3361
- mesh?.geometry?.dispose();
3362
- (mesh?.material)?.dispose?.();
3390
+ /**
3391
+ * Give the GPU allocations back.
3392
+ *
3393
+ * A fancy surface holds a cube target, a half-res scene pre-pass (colour +
3394
+ * depth) and — with `mirror` on — a mirror target at half the drawing buffer,
3395
+ * 4x MSAA, half-float. Tens of megabytes, PER WATER NODE.
3396
+ *
3397
+ * Until now the only thing that released any of it was `free()`, so every way
3398
+ * of stopping using one kept all of it: turning the mirror off zeroed a
3399
+ * uniform, and water off camera or under the player simply returned early.
3400
+ * Survivable while quality was decided once at load; not survivable now that
3401
+ * a settings menu turns the mirror off on a running game.
3402
+ */
3403
+ releasePassTargets(which) {
3404
+ this.mirrorTarget?.dispose();
3405
+ this.mirrorTarget = null;
3406
+ if (which === "mirror") return;
3363
3407
  this.cubeTarget?.dispose();
3364
3408
  this.cubeTarget = null;
3365
3409
  this.cubeCamera = null;
3366
3410
  this.scenePassTarget?.depthTexture?.dispose();
3367
3411
  this.scenePassTarget?.dispose();
3368
3412
  this.scenePassTarget = null;
3369
- this.mirrorTarget?.dispose();
3370
- this.mirrorTarget = null;
3413
+ }
3414
+ /**
3415
+ * Frames in a row that took no pass at all (submerged, or off camera).
3416
+ *
3417
+ * Releasing on the FIRST idle frame would be worse than the leak: a camera
3418
+ * panning past a lake would allocate and free a mirror target every other
3419
+ * frame, and allocation is not free either. Only a surface nobody has looked
3420
+ * at for a couple of seconds hands its memory back.
3421
+ */
3422
+ idleFrames = 0;
3423
+ /**
3424
+ * The tier's ceiling, or null when nothing has told us (headless, tests, a
3425
+ * renderer that does not push caps). Null means "no ceiling" — the authored
3426
+ * props stand.
3427
+ */
3428
+ caps = null;
3429
+ /** @internal See {@link QualityConsumer3D} — a ceiling, never an upgrade. */
3430
+ _applyQualityCaps(caps) {
3431
+ this.caps = caps;
3432
+ }
3433
+ /**
3434
+ * What this surface actually draws, once the tier has had its say.
3435
+ *
3436
+ * ONE-DIRECTIONAL: a cap can turn fancy into simple, never simple into fancy.
3437
+ * And it never writes `this.quality` — a tier is a runtime ceiling, not an
3438
+ * edit, so serializing a game running at low still writes what the author
3439
+ * chose.
3440
+ */
3441
+ effectiveQuality() {
3442
+ if (this.caps && !this.caps.fancyWater && this.canFadeItsOwnRim()) return "simple";
3443
+ return this.quality;
3444
+ }
3445
+ /**
3446
+ * Whether collapsing to the simple shader would still produce a waterline.
3447
+ *
3448
+ * A tier may make a game cheaper; it may not make it look broken. Found by
3449
+ * looking at the four water templates at every tier in a browser: the ocean
3450
+ * at low met the beach in a razor-straight line, because the simple shader's
3451
+ * only shoreline is a fade of its own rectangle and that rectangle's edge was
3452
+ * 800 m out to sea. Big water keeps the fancy shader at low — and still loses
3453
+ * its mirror, so the saving moves rather than disappears.
3454
+ *
3455
+ * This is NOT a veto on the author: a scene that asked for `quality: 'simple'`
3456
+ * gets it at any size. The guardrail only stops a TIER from choosing it.
3457
+ */
3458
+ canFadeItsOwnRim() {
3459
+ return Math.max(this.size[0] ?? 1, this.size[1] ?? 1) / 2 * SIMPLE_EDGE_FADE_FRACTION <= SIMPLE_SHORE_BAND_MAX;
3460
+ }
3461
+ /** Whether the planar mirror runs — the tier can take it away, never add it. */
3462
+ effectiveMirror() {
3463
+ return this.mirror && (this.caps ? this.caps.waterMirror : true);
3464
+ }
3465
+ /**
3466
+ * How often the reflection cube may refresh, in ms.
3467
+ *
3468
+ * The floor is the whole reason a tier can drop the mirror and keep the
3469
+ * saving: the cube slows to `MIRRORED_CUBE_INTERVAL` only BECAUSE a mirror is
3470
+ * carrying the near reflection, so a capped-away mirror without a floor sends
3471
+ * the cube back to the scene's own interval — six faces of the scene, several
3472
+ * times a second.
3473
+ */
3474
+ effectiveCubeInterval() {
3475
+ const authored = this.rp("reflectionInterval");
3476
+ const base = this.effectiveMirror() ? Math.max(authored, MIRRORED_CUBE_INTERVAL) : authored;
3477
+ return Math.max(base, this.caps?.minReflectionIntervalMs ?? 0);
3478
+ }
3479
+ /** One frame that took no pass; release everything once it has been a while. */
3480
+ noteIdleFrame() {
3481
+ this.idleFrames += 1;
3482
+ if (this.idleFrames === IDLE_FRAMES_BEFORE_RELEASE) this.releasePassTargets("all");
3483
+ }
3484
+ free() {
3485
+ const mesh = this._builtObject3D;
3486
+ mesh?.geometry?.dispose();
3487
+ (mesh?.material)?.dispose?.();
3488
+ this.releasePassTargets("all");
3371
3489
  super.free();
3372
3490
  }
3373
3491
  /** Swap geometry+material only when a surface-shaping prop changed. */
3374
3492
  rebuildSurfaceIfNeeded(mesh) {
3375
- const key = JSON.stringify([this.size, this.quality]);
3493
+ const quality = this.effectiveQuality();
3494
+ const key = JSON.stringify([this.size, quality]);
3376
3495
  if (key === this.surfaceKey && mesh.geometry.getAttribute("position")) return;
3377
3496
  this.surfaceKey = key;
3378
3497
  mesh.geometry?.dispose();
3379
3498
  mesh.material?.dispose?.();
3380
3499
  const w = this.size[0] ?? 1;
3381
3500
  const d = this.size[1] ?? 1;
3382
- if (this.quality === "simple") {
3501
+ if (quality === "simple") {
3502
+ this.releasePassTargets("all");
3383
3503
  mesh.geometry = buildWaterGeometry(w, d, SIMPLE_SEGMENTS);
3384
3504
  mesh.material = this.buildLakeMaterial();
3385
3505
  } else {
@@ -3766,7 +3886,7 @@ var Water3D = class Water3D extends Node3D {
3766
3886
  /** Base wave height at world (x, z) — the CPU twin of the active shader.
3767
3887
  * Ripples are excluded on purpose: a splash must not re-trigger itself. */
3768
3888
  waveOffsetAt(x, z, center) {
3769
- if (this.quality === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.rp("waveHeight"));
3889
+ if (this.effectiveQuality() === "simple") return simpleWaveHeight(x - center.x, z - center.z, this.time, this.rp("waveHeight"));
3770
3890
  return waveElevation(x, z, this.time, {
3771
3891
  amplitude: this.rp("waveHeight") * AMPLITUDE_PER_WAVE_HEIGHT,
3772
3892
  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-TA8nySqb.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-CqNfawyn.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-TA8nySqb.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-CvSDKC3v.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-_UlKUoox.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-DN-kG4va.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-DMFJI-c_.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-D_QY5Xm3.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.40.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 };