incanto 0.40.0 → 0.41.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 (32) hide show
  1. package/dist/2d.js +3 -3
  2. package/dist/3d.d.ts +2 -0
  3. package/dist/3d.js +4 -4
  4. package/dist/{create-game-Dc2CEFtD.js → create-game-CZpENyin.js} +4 -4
  5. package/dist/{create-game-CEKCtnKw.js → create-game-u7TDbvln.js} +4 -4
  6. package/dist/debug.d.ts +35 -1
  7. package/dist/debug.js +183 -2
  8. package/dist/{environment-presets-Z0PkDH62.js → environment-presets-pGTHb_V4.js} +9 -5
  9. package/dist/{gameplay-CqNfawyn.js → gameplay-By8mslMc.js} +30 -14
  10. package/dist/gameplay.js +1 -1
  11. package/dist/index.js +3 -3
  12. package/dist/net.js +2 -2
  13. package/dist/{physics-2d-CxIqR1cW.js → physics-2d-CEnZFcpM.js} +1 -1
  14. package/dist/{physics-3d-CcUaeJXq.js → physics-3d-CumBBvQo.js} +2 -2
  15. package/dist/react.js +1 -1
  16. package/dist/{register-D5v8iqjZ.js → register-DnycZ91Q.js} +1 -1
  17. package/dist/{register-DMFJI-c_.js → register-DuTlY56W.js} +2 -0
  18. package/dist/{register-CgMO5JBY.js → register-MSZvnHkp.js} +1 -1
  19. package/dist/{replay-D_QY5Xm3.js → replay-DcWg4LT5.js} +1 -1
  20. package/dist/{test-CFhY8No9.js → test-B4kSwQzq.js} +10 -10
  21. package/dist/test.js +2 -2
  22. package/dist/vite.js +1 -1
  23. package/editor/assets/{agent8-COwolmAe.js → agent8-DCHkff44.js} +1 -1
  24. package/editor/assets/debug-uHHxqj0a.js +3 -0
  25. package/editor/assets/{index-tRXhfJEm.js → index-i1mIkyMA.js} +34 -18
  26. package/editor/index.html +1 -1
  27. package/package.json +1 -1
  28. package/skills/incanto-verifying-your-game.md +19 -2
  29. package/templates-app/beacon-isle-3d/package.json +1 -1
  30. package/templates-app/tps-3d/package.json +1 -1
  31. package/templates-app/village-quest-3d/package.json +1 -1
  32. package/editor/assets/debug-DJSCLmsL.js +0 -3
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-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";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-CZpENyin.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-MSZvnHkp.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-CEnZFcpM.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
@@ -1104,6 +1104,8 @@ declare class CharacterController3D extends Node3D {
1104
1104
  private bufferLeft;
1105
1105
  private jumpsUsed;
1106
1106
  private rising;
1107
+ /** Between the jump impulse and the landing — the animation's clock. */
1108
+ private jumping;
1107
1109
  private get body();
1108
1110
  override onEnterTree(): void;
1109
1111
  override fixedUpdate(dt: number): void;
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-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";
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-By8mslMc.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-pGTHb_V4.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-u7TDbvln.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-CcUaeJXq.js";
5
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-CumBBvQo.js";
6
6
  //#region src/3d/terrain-nav.ts
7
7
  function buildTerrainNav(terrain, opts) {
8
8
  const cellSize = opts?.cellSize ?? 2;
@@ -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-DMFJI-c_.js";
3
+ import { h as Engine, m as AudioPlayer } from "./register-DuTlY56W.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-CqNfawyn.js";
8
- import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-CgMO5JBY.js";
7
+ import { n as registerGameplayBehaviors } from "./gameplay-By8mslMc.js";
8
+ import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-MSZvnHkp.js";
9
9
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
10
- import { n as enablePhysics2D } from "./physics-2d-CxIqR1cW.js";
10
+ import { n as enablePhysics2D } from "./physics-2d-CEnZFcpM.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 { _ as qualityCaps, h as Engine, m as AudioPlayer, y as qualityRendering } from "./register-DMFJI-c_.js";
3
+ import { _ as qualityCaps, h as Engine, m as AudioPlayer, y as qualityRendering } from "./register-DuTlY56W.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-CqNfawyn.js";
7
+ import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-By8mslMc.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-Z0PkDH62.js";
10
- import { n as enablePhysics3D } from "./physics-3d-CcUaeJXq.js";
9
+ import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-pGTHb_V4.js";
10
+ import { n as enablePhysics3D } from "./physics-3d-CumBBvQo.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";
package/dist/debug.d.ts CHANGED
@@ -7,7 +7,7 @@ interface DocumentLike {
7
7
  }
8
8
  //#endregion
9
9
  //#region src/debug/index.d.ts
10
- type DebugPanelId = "explorer" | "inspector" | "logs" | "stats";
10
+ type DebugPanelId = "explorer" | "inspector" | "logs" | "stats" | "time";
11
11
  /** Menu entries that are switches rather than panels. */
12
12
  type DebugSwitchId = "colliders";
13
13
  /** `all` is every collider in the world; `selected` follows the Explorer. */
@@ -64,6 +64,15 @@ declare class DebugOverlay {
64
64
  private editing;
65
65
  /** Which bulky values are unfolded, per node ('transforms', 'collider.vertices'). */
66
66
  private readonly detailOpen;
67
+ /**
68
+ * The scale to come back to when a pause is lifted.
69
+ *
70
+ * Captured only from a RUNNING scale: pausing an already-frozen game (a
71
+ * hit-stop, a previous pause) must not record 0 as the thing to restore, or
72
+ * Resume does nothing and the game looks hung.
73
+ */
74
+ private resumeScale;
75
+ private timeEls;
67
76
  /** Pointer inside the inspector — it stops refreshing under your hand. */
68
77
  private hovering;
69
78
  constructor(engine: Engine, container: HTMLElement, doc: DocumentLike, statsSource?: (() => Partial<RendererStats>) | undefined, actions?: DebugAction[]);
@@ -107,6 +116,31 @@ declare class DebugOverlay {
107
116
  private renderValueRow;
108
117
  private trackEditing;
109
118
  private pushLog;
119
+ /**
120
+ * Set game time, defensively. `timeScale` multiplies every dt in the engine,
121
+ * so a NaN from a text field would poison physics, timers and animation in
122
+ * one frame, and a negative would run the simulation backwards through code
123
+ * that has never been asked to.
124
+ */
125
+ setTimeScale(next: number): void;
126
+ /** Freeze or unfreeze game time. Rendering keeps running — this is a pause,
127
+ * not a stop: the camera still moves and the overlay stays interactive. */
128
+ setPaused(paused: boolean): void;
129
+ get paused(): boolean;
130
+ /**
131
+ * Advance exactly one frame, pausing first.
132
+ *
133
+ * Stepping a RUNNING game is meaningless — the next real frame lands a
134
+ * millisecond later and swamps the step — so this pauses and then steps,
135
+ * which is also the only way the button is useful twice in a row.
136
+ */
137
+ nextFrame(): void;
138
+ /** Push the engine's current time state into the panel, without rebuilding it. */
139
+ private syncTime;
140
+ private renderTime;
141
+ /** After a committed edit the field must show what the ENGINE took — a
142
+ * rejected 'abc' or a clamped -2 has to be visible, not left on screen. */
143
+ private syncTimeAfterEdit;
110
144
  private renderLogs;
111
145
  }
112
146
  //#endregion
package/dist/debug.js CHANGED
@@ -192,6 +192,9 @@ function detailText(value, json) {
192
192
  function isPlainObject(value) {
193
193
  return typeof value === "object" && value !== null && !Array.isArray(value);
194
194
  }
195
+ /** The slider's ceiling. Beyond this the number box is the tool — a 0..8 slider
196
+ * makes the 0.1-to-1 range, where slow-motion debugging actually lives, unusable. */
197
+ const TIME_SLIDER_MAX = 2;
195
198
  /** Attach the overlay; null when no DOM is available (headless). */
196
199
  function attachDebugOverlay(engine, opts = {}) {
197
200
  const doc = opts.doc ?? (typeof document !== "undefined" ? document : null);
@@ -235,6 +238,15 @@ var DebugOverlay = class {
235
238
  editing = 0;
236
239
  /** Which bulky values are unfolded, per node ('transforms', 'collider.vertices'). */
237
240
  detailOpen = /* @__PURE__ */ new WeakMap();
241
+ /**
242
+ * The scale to come back to when a pause is lifted.
243
+ *
244
+ * Captured only from a RUNNING scale: pausing an already-frozen game (a
245
+ * hit-stop, a previous pause) must not record 0 as the thing to restore, or
246
+ * Resume does nothing and the game looks hung.
247
+ */
248
+ resumeScale = 1;
249
+ timeEls = null;
238
250
  /** Pointer inside the inspector — it stops refreshing under your hand. */
239
251
  hovering = false;
240
252
  constructor(engine, container, doc, statsSource, actions = []) {
@@ -282,6 +294,7 @@ var DebugOverlay = class {
282
294
  this.renderExplorer();
283
295
  this.renderStats();
284
296
  if (this.editing === 0 && !this.hovering) this.renderInspector();
297
+ this.syncTime();
285
298
  }));
286
299
  }
287
300
  isOpen(id) {
@@ -314,11 +327,18 @@ var DebugOverlay = class {
314
327
  this.openStatsChip();
315
328
  return;
316
329
  }
317
- if (this.panels.has(id)) return;
330
+ if (this.panels.has(id)) {
331
+ if (id === "explorer") this.renderExplorer();
332
+ if (id === "inspector") this.renderInspector();
333
+ if (id === "logs") this.renderLogs();
334
+ if (id === "time") this.renderTime();
335
+ return;
336
+ }
318
337
  const panel = new FloatingPanel(this.doc, this.container, {
319
338
  explorer: "Explorer",
320
339
  inspector: "Inspector",
321
- logs: "Logs"
340
+ logs: "Logs",
341
+ time: "Time"
322
342
  }[id], {
323
343
  explorer: {
324
344
  x: 12,
@@ -337,6 +357,12 @@ var DebugOverlay = class {
337
357
  y: 380,
338
358
  w: 532,
339
359
  h: 200
360
+ },
361
+ time: {
362
+ x: 556,
363
+ y: 44,
364
+ w: 260,
365
+ h: 150
340
366
  }
341
367
  }[id]);
342
368
  panel.onClose = () => this.close(id);
@@ -352,6 +378,7 @@ var DebugOverlay = class {
352
378
  if (id === "explorer") this.renderExplorer();
353
379
  if (id === "inspector") this.renderInspector();
354
380
  if (id === "logs") this.renderLogs();
381
+ if (id === "time") this.renderTime();
355
382
  }
356
383
  close(id) {
357
384
  if (id === "inspector") this.hovering = false;
@@ -453,6 +480,7 @@ var DebugOverlay = class {
453
480
  ["explorer", "Explorer"],
454
481
  ["inspector", "Inspector"],
455
482
  ["logs", "Logs"],
483
+ ["time", "Time"],
456
484
  ["stats", "Stats"],
457
485
  ["colliders", "Colliders"]
458
486
  ]) {
@@ -849,6 +877,148 @@ var DebugOverlay = class {
849
877
  if (this.logRows.length > MAX_LOG_ROWS) this.logRows.splice(0, this.logRows.length - MAX_LOG_ROWS);
850
878
  this.renderLogs();
851
879
  }
880
+ /**
881
+ * Set game time, defensively. `timeScale` multiplies every dt in the engine,
882
+ * so a NaN from a text field would poison physics, timers and animation in
883
+ * one frame, and a negative would run the simulation backwards through code
884
+ * that has never been asked to.
885
+ */
886
+ setTimeScale(next) {
887
+ if (!Number.isFinite(next)) return;
888
+ this.engine.timeScale = Math.max(0, next);
889
+ this.syncTime();
890
+ }
891
+ /** Freeze or unfreeze game time. Rendering keeps running — this is a pause,
892
+ * not a stop: the camera still moves and the overlay stays interactive. */
893
+ setPaused(paused) {
894
+ if (paused) {
895
+ if (this.engine.timeScale > 0) this.resumeScale = this.engine.timeScale;
896
+ this.engine.timeScale = 0;
897
+ } else this.engine.timeScale = this.resumeScale > 0 ? this.resumeScale : 1;
898
+ this.syncTime();
899
+ }
900
+ get paused() {
901
+ return this.engine.timeScale === 0;
902
+ }
903
+ /**
904
+ * Advance exactly one frame, pausing first.
905
+ *
906
+ * Stepping a RUNNING game is meaningless — the next real frame lands a
907
+ * millisecond later and swamps the step — so this pauses and then steps,
908
+ * which is also the only way the button is useful twice in a row.
909
+ */
910
+ nextFrame() {
911
+ if (!this.paused) this.setPaused(true);
912
+ this.engine.step();
913
+ this.syncTime();
914
+ }
915
+ /** Push the engine's current time state into the panel, without rebuilding it. */
916
+ syncTime() {
917
+ const els = this.timeEls;
918
+ if (!els) return;
919
+ const scale = this.engine.timeScale;
920
+ const text = String(Math.round(scale * 1e3) / 1e3);
921
+ if (this.editing === 0) {
922
+ els.slider.value = String(Math.min(scale, TIME_SLIDER_MAX));
923
+ els.box.value = text;
924
+ }
925
+ els.readout.textContent = `timeScale ${text}${this.paused ? " · paused" : ""}`;
926
+ els.pause.textContent = this.paused ? "▶ Resume" : "⏸ Pause";
927
+ }
928
+ renderTime() {
929
+ const panel = this.panels.get("time");
930
+ if (!panel) return;
931
+ clear(panel.body);
932
+ this.timeEls = null;
933
+ const readout = this.doc.createElement("div");
934
+ applyStyle(readout, {
935
+ marginBottom: "6px",
936
+ opacity: "0.85"
937
+ });
938
+ panel.body.appendChild(readout);
939
+ const slider = this.doc.createElement("input");
940
+ slider.type = "range";
941
+ slider.min = "0";
942
+ slider.max = String(TIME_SLIDER_MAX);
943
+ slider.step = "0.05";
944
+ slider.value = String(Math.min(this.engine.timeScale, TIME_SLIDER_MAX));
945
+ applyStyle(slider, {
946
+ width: "100%",
947
+ marginBottom: "6px"
948
+ });
949
+ this.trackEditing(slider);
950
+ slider.addEventListener("input", () => this.setTimeScale(Number(slider.value)));
951
+ panel.body.appendChild(slider);
952
+ const row = this.doc.createElement("div");
953
+ applyStyle(row, {
954
+ display: "flex",
955
+ gap: "6px",
956
+ alignItems: "center",
957
+ marginBottom: "8px"
958
+ });
959
+ const box = this.doc.createElement("input");
960
+ box.type = "number";
961
+ box.min = "0";
962
+ box.step = "0.05";
963
+ box.value = String(this.engine.timeScale);
964
+ applyStyle(box, inputStyle("72px"));
965
+ this.trackEditing(box);
966
+ box.addEventListener("change", () => {
967
+ const next = Number(box.value);
968
+ if (Number.isFinite(next)) this.setTimeScale(next);
969
+ this.syncTimeAfterEdit();
970
+ });
971
+ row.appendChild(box);
972
+ for (const preset of [
973
+ .25,
974
+ .5,
975
+ 1,
976
+ 2
977
+ ]) {
978
+ const chip = this.doc.createElement("div");
979
+ chip.textContent = `${preset}×`;
980
+ applyStyle(chip, {
981
+ cursor: "pointer",
982
+ opacity: "0.7",
983
+ padding: "2px 4px"
984
+ });
985
+ chip.addEventListener("click", () => this.setTimeScale(preset));
986
+ row.appendChild(chip);
987
+ }
988
+ panel.body.appendChild(row);
989
+ const buttons = this.doc.createElement("div");
990
+ applyStyle(buttons, {
991
+ display: "flex",
992
+ gap: "8px"
993
+ });
994
+ const pause = this.doc.createElement("div");
995
+ applyStyle(pause, buttonStyle());
996
+ pause.addEventListener("click", () => this.setPaused(!this.paused));
997
+ buttons.appendChild(pause);
998
+ const step = this.doc.createElement("div");
999
+ step.textContent = "⏭ Next frame";
1000
+ step.title = "Pauses, then advances one fixed step";
1001
+ applyStyle(step, buttonStyle());
1002
+ step.addEventListener("click", () => this.nextFrame());
1003
+ buttons.appendChild(step);
1004
+ panel.body.appendChild(buttons);
1005
+ this.timeEls = {
1006
+ slider,
1007
+ box,
1008
+ readout,
1009
+ pause
1010
+ };
1011
+ this.syncTime();
1012
+ }
1013
+ /** After a committed edit the field must show what the ENGINE took — a
1014
+ * rejected 'abc' or a clamped -2 has to be visible, not left on screen. */
1015
+ syncTimeAfterEdit() {
1016
+ const els = this.timeEls;
1017
+ if (!els) return;
1018
+ const scale = this.engine.timeScale;
1019
+ els.slider.value = String(Math.min(scale, TIME_SLIDER_MAX));
1020
+ els.box.value = String(Math.round(scale * 1e3) / 1e3);
1021
+ }
852
1022
  renderLogs() {
853
1023
  const panel = this.panels.get("logs");
854
1024
  if (!panel) return;
@@ -924,6 +1094,17 @@ function stringify(part) {
924
1094
  return String(part);
925
1095
  }
926
1096
  }
1097
+ /** A clickable chip that reads as a button in the overlay's flat style. */
1098
+ function buttonStyle() {
1099
+ return {
1100
+ background: "rgba(255,255,255,0.08)",
1101
+ border: "1px solid rgba(255,255,255,0.2)",
1102
+ borderRadius: "4px",
1103
+ padding: "4px 8px",
1104
+ cursor: "pointer",
1105
+ userSelect: "none"
1106
+ };
1107
+ }
927
1108
  function inputStyle(width) {
928
1109
  return {
929
1110
  width,
@@ -1,10 +1,10 @@
1
- import { t as registerCoreNodes } from "./register-DMFJI-c_.js";
1
+ import { t as registerCoreNodes } from "./register-DuTlY56W.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-CqNfawyn.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-By8mslMc.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";
@@ -2621,6 +2621,8 @@ var CharacterController3D = class extends Node3D {
2621
2621
  bufferLeft = 0;
2622
2622
  jumpsUsed = 0;
2623
2623
  rising = false;
2624
+ /** Between the jump impulse and the landing — the animation's clock. */
2625
+ jumping = false;
2624
2626
  get body() {
2625
2627
  const parent = this.parent;
2626
2628
  if (!(parent instanceof RigidBody3D)) throw new IncantoError("TREE_VIOLATION", `CharacterController3D '${this.name}' must be a child of a RigidBody3D (parent is '${parent?.name ?? "none"}').`);
@@ -2708,7 +2710,7 @@ var CharacterController3D = class extends Node3D {
2708
2710
  0,
2709
2711
  -vel[2] * DRAG_DAMPING * mass
2710
2712
  ]);
2711
- if (toi !== null && toi < floatingDis * 2) {
2713
+ if (toi !== null && toi < floatingDis * 2 && !this.jumping) {
2712
2714
  const spring = SPRING_K * (floatingDis - toi) - vel[1] * SPRING_DAMPING;
2713
2715
  body.applyImpulse([
2714
2716
  0,
@@ -2720,9 +2722,10 @@ var CharacterController3D = class extends Node3D {
2720
2722
  this.coyoteLeft = this.coyoteSeconds;
2721
2723
  this.jumpsUsed = 0;
2722
2724
  this.rising = false;
2725
+ this.jumping = false;
2723
2726
  } else {
2724
2727
  this.coyoteLeft = Math.max(0, this.coyoteLeft - dt);
2725
- if (this.coyoteLeft <= 0 && this.jumpsUsed === 0) this.jumpsUsed = 1;
2728
+ if (!this.grounded && this.coyoteLeft <= 0 && this.jumpsUsed === 0) this.jumpsUsed = 1;
2726
2729
  }
2727
2730
  const pressedJump = safeJustPressed(input, this.jumpAction);
2728
2731
  if (pressedJump) this.bufferLeft = Math.max(this.jumpBufferSeconds, 0);
@@ -2739,6 +2742,7 @@ var CharacterController3D = class extends Node3D {
2739
2742
  this.bufferLeft = 0;
2740
2743
  this.coyoteLeft = 0;
2741
2744
  this.rising = true;
2745
+ this.jumping = true;
2742
2746
  vel[1] = jumpVel;
2743
2747
  }
2744
2748
  if (this.rising) {
@@ -2762,7 +2766,7 @@ var CharacterController3D = class extends Node3D {
2762
2766
  body.position[1] ?? 0,
2763
2767
  0
2764
2768
  ];
2765
- const next = movementState(footed, moving ? intensity : 0);
2769
+ const next = movementState(!(this.jumping || !this.grounded), moving ? intensity : 0);
2766
2770
  if (next !== this.state) {
2767
2771
  this.state = next;
2768
2772
  const clip = this.animations[next];
@@ -1409,20 +1409,36 @@ void main() {
1409
1409
 
1410
1410
  // The depth texture DELIBERATELY holds above-water geometry too (the
1411
1411
  // depth-completion pass, for cutouts) — so a sample NEARER than this
1412
- // fragment cannot be a bed, and treating it as "column 0" rendered the
1413
- // water as clear glass over the bare bed. Behind a tree the half-res
1414
- // pre-pass smears the canopy across the gaps between its own leaves, and
1415
- // whole stretches of pond turned to glass — "the water isn't drawn". The
1416
- // column reads the DEEPEST of the 5-tap neighborhood instead; when even
1417
- // that is contaminated, depth is UNKNOWN (-1) and the flat-ramp fallback
1418
- // paints honest murk.
1419
- float seamL = linearizeDepth(texture2D(uDepthTexture, screenUV - vec2(uScenePassTexel.x, 0.0)).r, uCameraNear, uCameraFar);
1420
- float seamR = linearizeDepth(texture2D(uDepthTexture, screenUV + vec2(uScenePassTexel.x, 0.0)).r, uCameraNear, uCameraFar);
1421
- float seamD = linearizeDepth(texture2D(uDepthTexture, screenUV - vec2(0.0, uScenePassTexel.y)).r, uCameraNear, uCameraFar);
1422
- float seamU = linearizeDepth(texture2D(uDepthTexture, screenUV + vec2(0.0, uScenePassTexel.y)).r, uCameraNear, uCameraFar);
1423
- float seamFarthest = max(max(seamL, seamR), max(seamD, max(seamU, linearSceneDepth)));
1424
- if (seamFarthest > linearWaterDepth + 0.02) {
1425
- waterViewDepth = seamFarthest - linearWaterDepth;
1412
+ // fragment can be a lie: behind a tree the half-res pre-pass smears the
1413
+ // canopy across the gaps between its own leaves, and whole stretches of
1414
+ // pond turned to glass ("the water isn't drawn"). Reading the DEEPEST of
1415
+ // the 5-tap neighborhood repairs that.
1416
+ //
1417
+ // But ONLY where there is something to repair. Applied everywhere, it draws
1418
+ // a dark hairline along every shoreline: in the thin swash the true column
1419
+ // is millimetres while one texel further out the bed has already dropped
1420
+ // away, so the deepest-of-5 hands a shallow fragment a deep-water column.
1421
+ // Reported as "a black line on the beach", and it is gone the moment this
1422
+ // reaches for the neighbourhood only when the centre is genuinely occluded.
1423
+ //
1424
+ // The two cases are told apart by HOW FAR IN FRONT the near sample is:
1425
+ // a canopy smeared over the water sits well in front → repair
1426
+ // a beach meeting the surface sits AT it (a few cm) → the column really
1427
+ // is zero; leave it
1428
+ float centreColumn = -depthDiff;
1429
+ if (centreColumn > 0.02) {
1430
+ waterViewDepth = centreColumn;
1431
+ } else if (depthDiff > 0.25) {
1432
+ float seamL = linearizeDepth(texture2D(uDepthTexture, screenUV - vec2(uScenePassTexel.x, 0.0)).r, uCameraNear, uCameraFar);
1433
+ float seamR = linearizeDepth(texture2D(uDepthTexture, screenUV + vec2(uScenePassTexel.x, 0.0)).r, uCameraNear, uCameraFar);
1434
+ float seamD = linearizeDepth(texture2D(uDepthTexture, screenUV - vec2(0.0, uScenePassTexel.y)).r, uCameraNear, uCameraFar);
1435
+ float seamU = linearizeDepth(texture2D(uDepthTexture, screenUV + vec2(0.0, uScenePassTexel.y)).r, uCameraNear, uCameraFar);
1436
+ float seamFarthest = max(max(seamL, seamR), max(seamD, max(seamU, linearSceneDepth)));
1437
+ if (seamFarthest > linearWaterDepth + 0.02) {
1438
+ waterViewDepth = seamFarthest - linearWaterDepth;
1439
+ }
1440
+ } else {
1441
+ waterViewDepth = 0.0;
1426
1442
  }
1427
1443
 
1428
1444
  // waterline dither: on a near-flat beach one half-res depth texel spans a
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-CqNfawyn.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-By8mslMc.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.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 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";
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-DuTlY56W.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-D_QY5Xm3.js";
5
+ import { n as startRecording, r as auditScene, t as replay } from "./replay-DcWg4LT5.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.40.0";
175
+ const VERSION = "0.41.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 };
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-DMFJI-c_.js";
2
+ import { h as Engine } from "./register-DuTlY56W.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-D5v8iqjZ.js";
6
+ import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-DnycZ91Q.js";
7
7
  //#region src/net/loopback.ts
8
8
  /**
9
9
  * In-memory multiplayer hub implementing the SAME kernel contract as
@@ -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-CgMO5JBY.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-MSZvnHkp.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-CqNfawyn.js";
4
+ import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-By8mslMc.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-Z0PkDH62.js";
6
+ import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-pGTHb_V4.js";
7
7
  import { Euler, Matrix4, Quaternion, Vector3 } from "three";
8
8
  //#region src/3d/physics/collider-lines.ts
9
9
  /**
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-CEKCtnKw.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-Dc2CEFtD.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-u7TDbvln.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-CZpENyin.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 { E as Signal, f as Node, t as buildNodeJson } from "./loader-r49nDwB4.js";
2
- import { t as registerCoreNodes } from "./register-DMFJI-c_.js";
2
+ import { t as registerCoreNodes } from "./register-DuTlY56W.js";
3
3
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
5
5
  import { l as registerNode } from "./registry-IyWCGe4q.js";
@@ -1980,6 +1980,8 @@ var Engine = class {
1980
1980
  step() {
1981
1981
  const scene = this._scene;
1982
1982
  if (!scene) return;
1983
+ this._time += this.fixedStep;
1984
+ this._unscaledTime += this.fixedStep;
1983
1985
  scene.tree.fixedUpdate(this.fixedStep);
1984
1986
  this.fixedUpdated.emit(this.fixedStep);
1985
1987
  scene.tree.update(this.fixedStep);
@@ -1,5 +1,5 @@
1
1
  import { f as Node, h as effectiveOrder } from "./loader-r49nDwB4.js";
2
- import { t as registerCoreNodes } from "./register-DMFJI-c_.js";
2
+ import { t as registerCoreNodes } from "./register-DuTlY56W.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";
@@ -1,4 +1,4 @@
1
- import { M as translationKey } from "./register-DMFJI-c_.js";
1
+ import { M as translationKey } from "./register-DuTlY56W.js";
2
2
  //#region src/core/audit.ts
3
3
  const ANIMATED_TYPES = new Set([
4
4
  "Particles2D",