incanto 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/3d.d.ts +23 -0
- package/dist/3d.js +1 -1
- package/dist/{create-game-OyjhYUL3.js → create-game-DjWIgtQ_.js} +78 -1
- package/dist/index.js +1 -1
- package/dist/react.js +1 -1
- package/editor/assets/{agent8-C_pbgaQC.js → agent8-DlMVayXX.js} +1 -1
- package/editor/assets/{index-D-bWhSDj.js → index-B5y_MdYb.js} +14 -14
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/skills/incanto-building-3d-games.md +3 -1
- package/skills/incanto-environment.md +16 -4
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
package/dist/3d.d.ts
CHANGED
|
@@ -377,6 +377,9 @@ interface CreateGame3DOptions {
|
|
|
377
377
|
seed?: number;
|
|
378
378
|
fixedHz?: number;
|
|
379
379
|
pixelRatio?: number;
|
|
380
|
+
/** Keep the frame rate by rendering fewer pixels while frames run slow
|
|
381
|
+
* (default ON). `false` pins the resolution — screenshots, capture, tests. */
|
|
382
|
+
adaptiveResolution?: boolean;
|
|
380
383
|
resolveScene?: LoadSceneOptions["resolveScene"];
|
|
381
384
|
/** @internal Test seam — replaces the Renderer3D construction. */
|
|
382
385
|
_rendererFactory?: (engine: Engine, canvas: HTMLCanvasElement) => GameRenderer;
|
|
@@ -2466,6 +2469,14 @@ interface Renderer3DOptions {
|
|
|
2466
2469
|
assets?: AssetStore3D;
|
|
2467
2470
|
/** Defaults to `window.devicePixelRatio` capped at 2. */
|
|
2468
2471
|
pixelRatio?: number;
|
|
2472
|
+
/**
|
|
2473
|
+
* Keep the frame rate by rendering at fewer pixels when frames run slow, and
|
|
2474
|
+
* hand them back when they recover (default ON). A retina display asks for
|
|
2475
|
+
* 4× the pixels; shaded water is fragment-heavy; the honest answer is fewer
|
|
2476
|
+
* pixels of the same world, only while it is actually needed. `false` pins
|
|
2477
|
+
* the resolution — for screenshots, video capture and pixel-diff tests.
|
|
2478
|
+
*/
|
|
2479
|
+
adaptiveResolution?: boolean;
|
|
2469
2480
|
}
|
|
2470
2481
|
/**
|
|
2471
2482
|
* WebGL presentation layer: subscribes to `engine.updated`, mirrors the active
|
|
@@ -2533,10 +2544,22 @@ declare class Renderer3D {
|
|
|
2533
2544
|
private bloomCompositeScene;
|
|
2534
2545
|
private bloomCompositeUniforms;
|
|
2535
2546
|
constructor(opts: Renderer3DOptions);
|
|
2547
|
+
/** The pixel ratio the scene ASKED for — the governor scales this, never replaces it. */
|
|
2548
|
+
private readonly basePixelRatio;
|
|
2549
|
+
private readonly adaptive;
|
|
2550
|
+
private lastFrameAt;
|
|
2536
2551
|
private readonly debugLines;
|
|
2537
2552
|
private readonly selectionLines;
|
|
2538
2553
|
private syncSelectionOutline;
|
|
2539
2554
|
private syncDebugLines;
|
|
2555
|
+
/**
|
|
2556
|
+
* Frame-rate governor: measure the frame, and when the median of a window is
|
|
2557
|
+
* slow, render the same world at fewer pixels (and hand them back when it
|
|
2558
|
+
* recovers). Resizing the drawing buffer is all it takes — every render
|
|
2559
|
+
* target in the pipeline is keyed off `getDrawingBufferSize`, so the water
|
|
2560
|
+
* grab, the mirror and the bloom chain follow automatically.
|
|
2561
|
+
*/
|
|
2562
|
+
private governResolution;
|
|
2540
2563
|
private render;
|
|
2541
2564
|
/**
|
|
2542
2565
|
* Bloom post pass (only when `environment.bloom` is declared). LDR and safe:
|
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 StaticBody3D, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D, z as WATER_MAX_RIPPLES } from "./gameplay-BJ5gXIks.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-
|
|
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-DjWIgtQ_.js";
|
|
4
4
|
import { A as QUARTER_PITCH, C as BoneAttachment3D, D as TERRAIN_THEMES, E as DEFAULT_TERRAIN_TEXTURE_BASE, M as keyboardIntensity, N as movementState, O as terrainThemeLayers, P as rigPose, S as BoneLookAt3D, T as Terrain3D, _ as Flowers3D, a as Trail3D, b as CharacterController3D, c as Particles3D, d as DirectionalLight3D, f as OmniLight3D, g as DENSITY_PRESETS, h as Foliage3D, i as Tree3D, j as cameraRelative, k as Joint3D, l as ModelInstance3D, m as MeshInstance3D, n as VOXEL_PALETTE, o as River3D, p as InstancedMesh3D, r as VoxelGrid3D, s as traceDownhillPath, t as registerNodes3D, u as LoftMesh3D, v as resolveFlowerDensity, w as Billboard3D, x as Camera3D, y as FLOWER_VARIETIES } from "./register-CpJORtm4.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-CpIB9C-F.js";
|
|
@@ -126,6 +126,50 @@ var AssetStore3D = class {
|
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
//#endregion
|
|
129
|
+
//#region src/3d/adaptive-resolution.ts
|
|
130
|
+
const DEFAULTS = {
|
|
131
|
+
slowMs: 20,
|
|
132
|
+
fastMs: 13,
|
|
133
|
+
minScale: .6,
|
|
134
|
+
step: .15,
|
|
135
|
+
window: 45
|
|
136
|
+
};
|
|
137
|
+
var AdaptiveResolution = class {
|
|
138
|
+
opts;
|
|
139
|
+
samples = [];
|
|
140
|
+
scale = 1;
|
|
141
|
+
constructor(options = {}) {
|
|
142
|
+
this.opts = {
|
|
143
|
+
...DEFAULTS,
|
|
144
|
+
...options
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** The fraction of the requested pixel ratio to render at right now. */
|
|
148
|
+
current() {
|
|
149
|
+
return this.scale;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Feed one frame's duration. Returns the new scale when it CHANGED (the
|
|
153
|
+
* caller then resizes), else null — so a steady frame rate costs nothing.
|
|
154
|
+
*/
|
|
155
|
+
push(frameMs) {
|
|
156
|
+
if (!(frameMs > 0) || !Number.isFinite(frameMs)) return null;
|
|
157
|
+
this.samples.push(frameMs);
|
|
158
|
+
if (this.samples.length < this.opts.window) return null;
|
|
159
|
+
const sorted = [...this.samples].sort((a, b) => a - b);
|
|
160
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
161
|
+
this.samples = [];
|
|
162
|
+
const before = this.scale;
|
|
163
|
+
if (median > this.opts.slowMs) this.scale = Math.max(this.opts.minScale, this.scale - this.opts.step);
|
|
164
|
+
else if (median < this.opts.fastMs && this.scale < 1) this.scale = Math.min(1, this.scale + this.opts.step);
|
|
165
|
+
return this.scale === before ? null : this.scale;
|
|
166
|
+
}
|
|
167
|
+
/** Forget the window (a paused or backgrounded game is not "slow"). */
|
|
168
|
+
reset() {
|
|
169
|
+
this.samples = [];
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
//#endregion
|
|
129
173
|
//#region src/3d/bloom/bloom-composite.ts
|
|
130
174
|
/**
|
|
131
175
|
* HDR bloom post pass:
|
|
@@ -1421,7 +1465,9 @@ var Renderer3D = class {
|
|
|
1421
1465
|
canvas: opts.canvas,
|
|
1422
1466
|
antialias: rendering.antialias
|
|
1423
1467
|
});
|
|
1468
|
+
this.basePixelRatio = rendering.pixelRatio;
|
|
1424
1469
|
this.webgl.setPixelRatio(rendering.pixelRatio);
|
|
1470
|
+
this.adaptive = opts.adaptiveResolution === false ? null : new AdaptiveResolution();
|
|
1425
1471
|
this.webgl.shadowMap.enabled = true;
|
|
1426
1472
|
this.webgl.shadowMap.type = PCFShadowMap;
|
|
1427
1473
|
this.webgl.toneMapping = ACESFilmicToneMapping;
|
|
@@ -1445,6 +1491,10 @@ var Renderer3D = class {
|
|
|
1445
1491
|
this.threeScene.add(this.selectionLines);
|
|
1446
1492
|
this.disconnect = this.engine.updated.connect(() => this.render());
|
|
1447
1493
|
}
|
|
1494
|
+
/** The pixel ratio the scene ASKED for — the governor scales this, never replaces it. */
|
|
1495
|
+
basePixelRatio;
|
|
1496
|
+
adaptive;
|
|
1497
|
+
lastFrameAt = 0;
|
|
1448
1498
|
debugLines;
|
|
1449
1499
|
selectionLines;
|
|
1450
1500
|
syncSelectionOutline() {
|
|
@@ -1468,9 +1518,35 @@ var Renderer3D = class {
|
|
|
1468
1518
|
this.debugLines.visible = vertices !== null;
|
|
1469
1519
|
if (vertices) this.debugLines.geometry.setAttribute("position", new BufferAttribute(vertices, 3));
|
|
1470
1520
|
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Frame-rate governor: measure the frame, and when the median of a window is
|
|
1523
|
+
* slow, render the same world at fewer pixels (and hand them back when it
|
|
1524
|
+
* recovers). Resizing the drawing buffer is all it takes — every render
|
|
1525
|
+
* target in the pipeline is keyed off `getDrawingBufferSize`, so the water
|
|
1526
|
+
* grab, the mirror and the bloom chain follow automatically.
|
|
1527
|
+
*/
|
|
1528
|
+
governResolution() {
|
|
1529
|
+
const gov = this.adaptive;
|
|
1530
|
+
if (!gov) return;
|
|
1531
|
+
const now = globalThis.performance?.now?.() ?? 0;
|
|
1532
|
+
const prev = this.lastFrameAt;
|
|
1533
|
+
this.lastFrameAt = now;
|
|
1534
|
+
if (prev === 0) return;
|
|
1535
|
+
const frameMs = now - prev;
|
|
1536
|
+
if (frameMs > 500) {
|
|
1537
|
+
gov.reset();
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
const scale = gov.push(frameMs);
|
|
1541
|
+
if (scale === null) return;
|
|
1542
|
+
this.webgl.setPixelRatio(this.basePixelRatio * scale);
|
|
1543
|
+
const size = this.lastSize;
|
|
1544
|
+
if (size.w > 0 && size.h > 0) this.webgl.setSize(size.w, size.h, false);
|
|
1545
|
+
}
|
|
1471
1546
|
render() {
|
|
1472
1547
|
const scene = this.engine.scene;
|
|
1473
1548
|
if (!scene) return;
|
|
1549
|
+
this.governResolution();
|
|
1474
1550
|
this.syncDebugLines();
|
|
1475
1551
|
this.syncSelectionOutline();
|
|
1476
1552
|
if (scene.assets && !this.loadedAssetScenes.has(scene)) {
|
|
@@ -1937,7 +2013,8 @@ async function createGame3D(opts) {
|
|
|
1937
2013
|
const renderer = opts._rendererFactory ? opts._rendererFactory(engine, opts.canvas) : new Renderer3D({
|
|
1938
2014
|
canvas: opts.canvas,
|
|
1939
2015
|
engine,
|
|
1940
|
-
...opts.pixelRatio !== void 0 ? { pixelRatio: opts.pixelRatio } : {}
|
|
2016
|
+
...opts.pixelRatio !== void 0 ? { pixelRatio: opts.pixelRatio } : {},
|
|
2017
|
+
...opts.adaptiveResolution !== void 0 ? { adaptiveResolution: opts.adaptiveResolution } : {}
|
|
1941
2018
|
});
|
|
1942
2019
|
if (opts.debug ?? false) {
|
|
1943
2020
|
const host = opts.touchContainer ?? opts.canvas.parentElement ?? (typeof document !== "undefined" ? document.body : null);
|
package/dist/index.js
CHANGED
|
@@ -295,6 +295,6 @@ function newUid() {
|
|
|
295
295
|
//#endregion
|
|
296
296
|
//#region src/index.ts
|
|
297
297
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
298
|
-
const VERSION = "0.
|
|
298
|
+
const VERSION = "0.24.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-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-DjWIgtQ_.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-DrcEgRup.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./index-
|
|
1
|
+
import{t as e}from"./index-B5y_MdYb.js";async function t(t){return new n((await e(()=>import(`./GameServer-C56iOUgF.js`),[],import.meta.url)).GameServer,t)}var n=class{raw;active=new Map;reconnecting=!1;disposed=!1;constructor(e,t){this.raw=new e({...t})}get account(){return this.raw.account}get connected(){return this.raw.connected}connect(){return this.raw.connected?Promise.resolve(!0):(this.disposed=!1,this.rawConnect())}rawConnect(){return this.raw.connect({onDisconnect:()=>void this.reconnect()})}disconnect(){this.disposed=!0;for(let e of this.active.values())e.off();return this.active.clear(),this.raw.disconnect()}remoteFunction(e,t,n){return this.raw.remoteFunction(e,t,n)}track(e){let t=Symbol(`sub`),n={make:e,off:e()};return this.active.set(t,n),()=>{n.off(),this.active.delete(t)}}async reconnect(){if(!this.disposed&&!this.reconnecting){this.reconnecting=!0;try{await this.rawConnect();for(let e of this.active.values())e.off(),e.off=e.make()}finally{this.reconnecting=!1}}}subscribeRoomState(e,t){return this.track(()=>this.raw.subscribeRoomState(e,t))}subscribeRoomMyState(e,t){return this.track(()=>this.raw.subscribeRoomMyState(e,t))}subscribeRoomAllUserStates(e,t){return this.track(()=>this.raw.subscribeRoomAllUserStates(e,e=>{let n={};for(let t of e??[]){if(!t||typeof t.account!=`string`||t.__leaved)continue;let{account:e,__updated:r,__leaved:i,...a}=t;n[e]=a}t(n)}))}subscribeRoomCollection(e,t,n){return this.track(()=>this.raw.subscribeRoomCollection(e,t,({items:e})=>{let t={};for(let n of e??[])n&&typeof n.__id==`string`&&(t[n.__id]=n);n(t)}))}onRoomMessage(e,t,n){return this.track(()=>this.raw.onRoomMessage(e,t,n))}onRoomUserJoin(e,t){return this.track(()=>this.raw.onRoomUserJoin(e,t))}onRoomUserLeave(e,t){return this.track(()=>this.raw.onRoomUserLeave(e,t))}subscribeGlobalState(e){return this.track(()=>this.raw.subscribeGlobalState(e))}subscribeGlobalMyState(e){return this.track(()=>this.raw.subscribeGlobalMyState(e))}subscribeGlobalUserState(e,t){return this.track(()=>this.raw.subscribeGlobalUserState(e,t))}subscribeGlobalCollection(e,t){return this.track(()=>this.raw.subscribeGlobalCollection(e,({items:e})=>{let n={};for(let t of e??[])t&&typeof t.__id==`string`&&(n[t.__id]=t);t(n)}))}subscribeAsset(e,t){return this.track(()=>this.raw.subscribeAsset(e,t))}onGlobalMessage(e,t){return this.track(()=>this.raw.onGlobalMessage(e,t))}};export{t as createAgent8Server};
|