incanto 0.31.0 → 0.32.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.
@@ -17,6 +17,7 @@ import { dirname, join, resolve } from 'node:path';
17
17
  * pointer <dx> <dy> look deltas wheel <dy>
18
18
  * capture [file] current state as scene JSON (stdout or file)
19
19
  * describe one line per node, non-default props only
20
+ * framing what the camera SEES: on/off screen, lights, overlaps
20
21
  * logs engine.log entries since the last call
21
22
  * quit
22
23
  *
@@ -56,7 +57,7 @@ if (args.help || !args.scene) {
56
57
  console.error(`Usage: incanto-play <scene.json> [--behaviors <file.ts|.js>] [--seed N] [--fixed-hz 60] [--commands <file>]
57
58
 
58
59
  Headless play: stdin commands (step/press/release/vector/key/mouse/pointer/
59
- wheel/capture/describe/logs/quit), JSON-line responses on stdout.`);
60
+ wheel/capture/describe/framing/logs/quit), JSON-line responses on stdout.`);
60
61
  process.exit(args.help && args.scene !== undefined ? 0 : 1);
61
62
  }
62
63
 
@@ -175,6 +176,10 @@ function handle(line) {
175
176
  case 'describe':
176
177
  out({ ok: true, cmd, text: session.describe() });
177
178
  break;
179
+ case 'framing':
180
+ // what the camera can SEE — on/off screen, lit or black, overlaps
181
+ out({ ok: true, cmd, text: session.framing() });
182
+ break;
178
183
  case 'logs':
179
184
  out({ ok: true, cmd, entries: session.drainLogs() });
180
185
  break;
@@ -188,7 +193,7 @@ function handle(line) {
188
193
  cmd,
189
194
  error: {
190
195
  code: 'UNKNOWN_COMMAND',
191
- message: `unknown command '${cmd}'. Commands: step press release vector key mouse pointer wheel capture describe logs quit`,
196
+ message: `unknown command '${cmd}'. Commands: step press release vector key mouse pointer wheel capture describe framing logs quit`,
192
197
  },
193
198
  });
194
199
  }
package/dist/2d.js CHANGED
@@ -1,5 +1,5 @@
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-z5XaB1p5.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-bKHgHcsZ.js";
3
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-tkR_8tWg.js";
4
4
  import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-D9wquBvK.js";
5
5
  //#region src/2d/library-sprite.ts
package/dist/3d.d.ts CHANGED
@@ -488,6 +488,16 @@ interface CreateGame3DOptions {
488
488
  /** Keep the frame rate by rendering fewer pixels while frames run slow
489
489
  * (default ON). `false` pins the resolution — screenshots, capture, tests. */
490
490
  adaptiveResolution?: boolean;
491
+ /**
492
+ * Keep the drawing buffer readable so the canvas can be screenshot.
493
+ *
494
+ * WebGL clears it the instant a frame composites, so `toDataURL()` — and every
495
+ * screenshot built on it — is BLANK without this. Off by default: it costs a
496
+ * buffer copy per frame and only a run that means to look at the output should
497
+ * pay for it. `environment.rendering.preserveDrawingBuffer` does the same from
498
+ * the scene.
499
+ */
500
+ preserveDrawingBuffer?: boolean;
491
501
  resolveScene?: LoadSceneOptions["resolveScene"];
492
502
  /**
493
503
  * Boot progress, for the loading screen an app already has.
@@ -2998,6 +3008,16 @@ interface Renderer3DOptions {
2998
3008
  * the resolution — for screenshots, video capture and pixel-diff tests.
2999
3009
  */
3000
3010
  adaptiveResolution?: boolean;
3011
+ /**
3012
+ * Keep the drawing buffer readable so the canvas can be SCREENSHOT.
3013
+ *
3014
+ * WebGL clears it the moment a frame composites, so `canvas.toDataURL()` and
3015
+ * anything built on it (a Playwright screenshot, a pixel-diff test) comes
3016
+ * back blank without this. Off by default — it costs a buffer copy per frame
3017
+ * and only a run that intends to look at the output should pay it. The scene
3018
+ * can ask for it too: `environment.rendering.preserveDrawingBuffer`.
3019
+ */
3020
+ preserveDrawingBuffer?: boolean;
3001
3021
  }
3002
3022
  /**
3003
3023
  * WebGL presentation layer: subscribes to `engine.updated`, mirrors the active
package/dist/3d.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
2
  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-BftxM_It.js";
3
- import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-DqOjMBUS.js";
3
+ import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-gXI7PYl0.js";
4
4
  import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, 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, V as movementState, _ 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--DigHNg4.js";
5
5
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
6
6
  import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-CnPygVGo.js";
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { m as diagnose, n as loadScene, o as computeViewport, s as resolveViewport, y as registerBehavior } from "./loader-BlaRQGaA.js";
3
3
  import { l as AudioPlayer, u as Engine } from "./register-Dzkd6-os.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
- import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
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-ByzfDPyu.js";
7
7
  import { n as registerGameplayBehaviors } from "./gameplay-BftxM_It.js";
8
8
  import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-tkR_8tWg.js";
@@ -269,7 +269,8 @@ var Renderer2D = class {
269
269
  this.assets = opts.assets ?? new AssetStore2D(void 0, this.engine);
270
270
  const rendering = resolveRendering(opts.engine.scene?.environment, {
271
271
  antialias: true,
272
- pixelRatio: 1
272
+ pixelRatio: 1,
273
+ preserveDrawingBuffer: false
273
274
  }, globalThis.devicePixelRatio ?? 1, opts);
274
275
  this.webgl = new WebGLRenderer({
275
276
  canvas: opts.canvas,
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { m as diagnose, n as loadScene, y as registerBehavior } from "./loader-BlaRQGaA.js";
3
3
  import { l as AudioPlayer, u as Engine } from "./register-Dzkd6-os.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
- import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
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-ByzfDPyu.js";
7
7
  import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-BftxM_It.js";
8
8
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
@@ -1554,11 +1554,16 @@ var Renderer3D = class {
1554
1554
  this.assets = opts.assets ?? new AssetStore3D(this.engine);
1555
1555
  const rendering = resolveRendering(opts.engine.scene?.environment, {
1556
1556
  antialias: true,
1557
- pixelRatio: Math.min(globalThis.devicePixelRatio ?? 1, 2)
1558
- }, globalThis.devicePixelRatio ?? 1, { pixelRatio: opts.pixelRatio });
1557
+ pixelRatio: Math.min(globalThis.devicePixelRatio ?? 1, 2),
1558
+ preserveDrawingBuffer: false
1559
+ }, globalThis.devicePixelRatio ?? 1, {
1560
+ pixelRatio: opts.pixelRatio,
1561
+ preserveDrawingBuffer: opts.preserveDrawingBuffer
1562
+ });
1559
1563
  this.webgl = new WebGLRenderer({
1560
1564
  canvas: opts.canvas,
1561
- antialias: rendering.antialias
1565
+ antialias: rendering.antialias,
1566
+ preserveDrawingBuffer: rendering.preserveDrawingBuffer
1562
1567
  });
1563
1568
  this.webgl.info.autoReset = false;
1564
1569
  this.basePixelRatio = rendering.pixelRatio;
@@ -2194,7 +2199,8 @@ async function createGame3D(opts) {
2194
2199
  canvas: opts.canvas,
2195
2200
  engine,
2196
2201
  ...opts.pixelRatio !== void 0 ? { pixelRatio: opts.pixelRatio } : {},
2197
- ...opts.adaptiveResolution !== void 0 ? { adaptiveResolution: opts.adaptiveResolution } : {}
2202
+ ...opts.adaptiveResolution !== void 0 ? { adaptiveResolution: opts.adaptiveResolution } : {},
2203
+ ...opts.preserveDrawingBuffer !== void 0 ? { preserveDrawingBuffer: opts.preserveDrawingBuffer } : {}
2198
2204
  });
2199
2205
  await report(.14, "renderer");
2200
2206
  const wantDebug = opts.debug ?? false;
package/dist/index.d.ts CHANGED
@@ -401,10 +401,20 @@ declare function registerCoreNodes(): void;
401
401
  interface ResolvedRendering {
402
402
  antialias: boolean;
403
403
  pixelRatio: number;
404
+ /**
405
+ * Keep the drawing buffer readable after a frame (default false).
406
+ *
407
+ * WebGL clears it as soon as the frame is composited, so `canvas.toDataURL()`
408
+ * — and therefore ANY screenshot a driver takes — comes back blank. Turning
409
+ * this on costs a buffer copy per frame, which is why it is off for games and
410
+ * on for the run where something is trying to LOOK at the output.
411
+ */
412
+ preserveDrawingBuffer: boolean;
404
413
  }
405
414
  declare function resolveRendering(environment: JsonObject | undefined, fallback: ResolvedRendering, devicePixelRatio: number, explicit?: {
406
415
  antialias?: boolean;
407
416
  pixelRatio?: number;
417
+ preserveDrawingBuffer?: boolean;
408
418
  }): ResolvedRendering;
409
419
  //#endregion
410
420
  //#region src/core/replay.d.ts
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { a as getNodeSignals, c as mergeStaticSignals, i as getNodeSchema, l as
8
8
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
9
9
  import { n as ORDER_GROUP_BASE, r as effectiveOrder, t as duplicateNode } from "./duplicate-KRPtUtzl.js";
10
10
  import { i as applyParticlePreset, n as PARTICLE_PRESETS, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
11
- import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-031PxtCR.js";
11
+ import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-BoNg_MnF.js";
12
12
  //#region src/core/pathfinding.ts
13
13
  /**
14
14
  * A* from `from` to `to` (inclusive cell coords). Returns the cell path
@@ -295,6 +295,6 @@ function newUid() {
295
295
  //#endregion
296
296
  //#region src/index.ts
297
297
  /** Engine version. Kept in sync with package.json by the release pipeline. */
298
- const VERSION = "0.31.0";
298
+ const VERSION = "0.32.0";
299
299
  //#endregion
300
300
  export { AudioBuses, AudioPlayer, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, Scene, SceneTree, SfxEngine, Signal, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiText, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, mergeStaticSignals, newUid, parseNodePath, preloadUrls, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, synthSfx };
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-DqOjMBUS.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-z5XaB1p5.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-gXI7PYl0.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-bKHgHcsZ.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;