incanto 0.79.0 → 0.79.1
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/debug.d.ts +9 -0
- package/dist/debug.js +48 -7
- package/dist/index.js +1 -1
- package/dist/{src-rS7AyeKD.js → src-3rJ6QSfX.js} +1 -1
- package/dist/vite.js +1 -1
- package/editor/assets/{agent8-WXuvhs5H.js → agent8-q_2WV8pw.js} +1 -1
- package/editor/assets/debug-DepFCl1d.js +3 -0
- package/editor/assets/{index-DJryzpvb.js → index-QEwr2eXD.js} +2 -2
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/editor/assets/debug-xpJQqbx1.js +0 -3
package/dist/debug.d.ts
CHANGED
|
@@ -7,6 +7,15 @@ interface DocumentLike {
|
|
|
7
7
|
addEventListener?(type: string, cb: (event: unknown) => void): void;
|
|
8
8
|
removeEventListener?(type: string, cb: (event: unknown) => void): void;
|
|
9
9
|
createElement(tag: string): HTMLElement;
|
|
10
|
+
/**
|
|
11
|
+
* The viewport, when the overlay's own container cannot supply one — see
|
|
12
|
+
* {@link overlayViewport}. Optional because the test double is not a
|
|
13
|
+
* document and a headless run has no window at all.
|
|
14
|
+
*/
|
|
15
|
+
documentElement?: {
|
|
16
|
+
clientWidth?: number;
|
|
17
|
+
clientHeight?: number;
|
|
18
|
+
};
|
|
10
19
|
}
|
|
11
20
|
//#endregion
|
|
12
21
|
//#region src/debug/index.d.ts
|
package/dist/debug.js
CHANGED
|
@@ -182,13 +182,50 @@ function popupPosition(rect, popupW, popupH, viewW, viewH, gap = 8) {
|
|
|
182
182
|
}
|
|
183
183
|
//#endregion
|
|
184
184
|
//#region src/debug/panel.ts
|
|
185
|
-
/**
|
|
185
|
+
/**
|
|
186
|
+
* The area the overlay's floating pieces may occupy.
|
|
187
|
+
*
|
|
188
|
+
* Normally the container's own box. But the container is
|
|
189
|
+
* `canvas.parentElement`, and in a React project that is `#root`, which every
|
|
190
|
+
* template styles **`display: contents`** — an element that generates no box
|
|
191
|
+
* at all: `clientWidth`, `clientHeight` and `getBoundingClientRect()` are all
|
|
192
|
+
* zero, and `position: relative` on it does nothing either. Measured in a
|
|
193
|
+
* browser: dragging the ☰ chip 300×200 px moved it to (0, 0), and the Logs
|
|
194
|
+
* panel opened there and would not move, because a zero viewport makes
|
|
195
|
+
* {@link clampPanelRect} answer the origin for every input.
|
|
196
|
+
*
|
|
197
|
+
* The fallback is the DOCUMENT's viewport, and that is not a guess: a
|
|
198
|
+
* `display: contents` element is not a containing block either, so the
|
|
199
|
+
* absolutely-positioned children are already laid out against the initial
|
|
200
|
+
* containing block — the window. Clamping them to it is clamping them to
|
|
201
|
+
* where they actually are.
|
|
202
|
+
*/
|
|
203
|
+
function overlayViewport(host, doc) {
|
|
204
|
+
const w = host?.clientWidth ?? 0;
|
|
205
|
+
const h = host?.clientHeight ?? 0;
|
|
206
|
+
if (w > 0 && h > 0) return {
|
|
207
|
+
w,
|
|
208
|
+
h
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
w: doc.documentElement?.clientWidth ?? 0,
|
|
212
|
+
h: doc.documentElement?.clientHeight ?? 0
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Keep a panel rect on screen and above the minimum usable size.
|
|
217
|
+
*
|
|
218
|
+
* A viewport of zero means "not measurable", never "a screen of no size": the
|
|
219
|
+
* axis is left alone rather than collapsed to the origin. Pinning instead is
|
|
220
|
+
* what made a boxless container un-draggable, and it would be the wrong answer
|
|
221
|
+
* anyway — a position nobody can check is better kept than overwritten.
|
|
222
|
+
*/
|
|
186
223
|
function clampPanelRect(x, y, w, h, viewW, viewH, minW = 180, minH = 120) {
|
|
187
224
|
const cw = Math.max(minW, w);
|
|
188
225
|
const ch = Math.max(minH, h);
|
|
189
226
|
return {
|
|
190
|
-
x: Math.min(Math.max(0, x), Math.max(0, viewW - cw)),
|
|
191
|
-
y: Math.min(Math.max(0, y), Math.max(0, viewH - ch)),
|
|
227
|
+
x: viewW > 0 ? Math.min(Math.max(0, x), Math.max(0, viewW - cw)) : x,
|
|
228
|
+
y: viewH > 0 ? Math.min(Math.max(0, y), Math.max(0, viewH - ch)) : y,
|
|
192
229
|
w: cw,
|
|
193
230
|
h: ch
|
|
194
231
|
};
|
|
@@ -257,6 +294,7 @@ const FONT = "12px ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
|
257
294
|
* + corner handle (resize) + × (close). Pure inline styles, zero CSS files.
|
|
258
295
|
*/
|
|
259
296
|
var FloatingPanel = class {
|
|
297
|
+
doc;
|
|
260
298
|
host;
|
|
261
299
|
el;
|
|
262
300
|
body;
|
|
@@ -267,6 +305,7 @@ var FloatingPanel = class {
|
|
|
267
305
|
w;
|
|
268
306
|
h;
|
|
269
307
|
constructor(doc, host, title, rect) {
|
|
308
|
+
this.doc = doc;
|
|
270
309
|
this.host = host;
|
|
271
310
|
this.x = rect.x;
|
|
272
311
|
this.y = rect.y;
|
|
@@ -348,8 +387,8 @@ var FloatingPanel = class {
|
|
|
348
387
|
this.el.remove();
|
|
349
388
|
}
|
|
350
389
|
layout() {
|
|
351
|
-
const view = this.host.
|
|
352
|
-
const rect = clampPanelRect(this.x, this.y, this.w, this.h, view.
|
|
390
|
+
const view = overlayViewport(this.host, this.doc);
|
|
391
|
+
const rect = clampPanelRect(this.x, this.y, this.w, this.h, view.w, view.h);
|
|
353
392
|
this.x = rect.x;
|
|
354
393
|
this.y = rect.y;
|
|
355
394
|
this.w = rect.w;
|
|
@@ -1039,7 +1078,8 @@ var DebugOverlay = class {
|
|
|
1039
1078
|
}
|
|
1040
1079
|
moveMenuButton(x, y) {
|
|
1041
1080
|
const el = this.menuButton;
|
|
1042
|
-
const
|
|
1081
|
+
const view = overlayViewport(this.container, this.doc);
|
|
1082
|
+
const box = clampPanelRect(x, y, el.offsetWidth ?? 0, el.offsetHeight ?? 0, view.w, view.h, 0, 0);
|
|
1043
1083
|
this.menuPos = {
|
|
1044
1084
|
x: box.x,
|
|
1045
1085
|
y: box.y
|
|
@@ -1119,12 +1159,13 @@ var DebugOverlay = class {
|
|
|
1119
1159
|
this.dropdown = menu;
|
|
1120
1160
|
const el = menu;
|
|
1121
1161
|
const btn = this.menuButton;
|
|
1162
|
+
const view = overlayViewport(this.container, this.doc);
|
|
1122
1163
|
const at = anchorDropdown({
|
|
1123
1164
|
x: this.menuPos.x,
|
|
1124
1165
|
y: this.menuPos.y,
|
|
1125
1166
|
w: btn.offsetWidth ?? 0,
|
|
1126
1167
|
h: btn.offsetHeight ?? 26
|
|
1127
|
-
}, el.offsetWidth ?? 0, el.offsetHeight ?? 0,
|
|
1168
|
+
}, el.offsetWidth ?? 0, el.offsetHeight ?? 0, view.w, view.h);
|
|
1128
1169
|
applyStyle(menu, {
|
|
1129
1170
|
left: `${at.x}px`,
|
|
1130
1171
|
top: `${at.y}px`
|
package/dist/index.js
CHANGED
|
@@ -9,5 +9,5 @@ import { t as showBootFailure } from "./boot-failure-CKYrEcGF.js";
|
|
|
9
9
|
import { a as logText, i as logReport, o as parseDrive, r as resolveRendering, t as isWebGLAvailable } from "./webgl-unavailable-C8aDbGmR.js";
|
|
10
10
|
import { t as createNoise2D } from "./noise-D3nPpmFg.js";
|
|
11
11
|
import { a as PARTICLE_PRESETS, i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-SQa5gIu2.js";
|
|
12
|
-
import { a as findPath, i as preloadUrls, n as assetUrls, o as gridFromRows, r as preloadSceneAssets, t as VERSION } from "./src-
|
|
12
|
+
import { a as findPath, i as preloadUrls, n as assetUrls, o as gridFromRows, r as preloadSceneAssets, t as VERSION } from "./src-3rJ6QSfX.js";
|
|
13
13
|
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, EffectLog, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Respawn, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiFrameCapSelect, UiImage, UiLanguageSelect, UiMinimap, UiMuteToggle, UiPanel, UiQualitySelect, UiRenderScaleSelect, UiSelect, UiSlider, UiText, UiToggle, UiVolumeSlider, UiWaypoint, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, describeRefProblem, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, isWebGLAvailable, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, nodeRefWarnings, parseDrive, parseNodePath, preloadSceneAssets, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRefInJson, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, sfxDuration, showBootFailure, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
@@ -199,6 +199,6 @@ async function preloadSceneAssets(assets, title) {
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region src/index.ts
|
|
201
201
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
202
|
-
const VERSION = "0.
|
|
202
|
+
const VERSION = "0.79.1";
|
|
203
203
|
//#endregion
|
|
204
204
|
export { findPath as a, preloadUrls as i, assetUrls as n, gridFromRows as o, preloadSceneAssets as r, VERSION as t };
|
package/dist/vite.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as parseJsonText } from "./json-CfTjpvW8.js";
|
|
2
2
|
import { P as newUid } from "./pose-O50uVW-j.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { t as VERSION } from "./src-
|
|
4
|
+
import { t as VERSION } from "./src-3rJ6QSfX.js";
|
|
5
5
|
import { n as diffSignatures } from "./frame-report-D-_7YF2G.js";
|
|
6
6
|
import { s as validateScene } from "./test-Def33MoL.js";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,n as t}from"./index-
|
|
1
|
+
import{i as e,n as t}from"./index-QEwr2eXD.js";async function n(e,n){return new a((await t(()=>import(`./GameServer-C56iOUgF.js`),[],import.meta.url)).GameServer,e,{diagnostics:n})}var r=[500,1e3,2e3,4e3,8e3],i=8,a=class{raw;active=new Map;reconnecting=!1;disposed=!1;diagnostics;wait;constructor(e,t,n){this.diagnostics=n?.diagnostics??null,this.wait=n?.wait??(e=>new Promise(t=>{setTimeout(t,e)})),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{for(let t=0;t<i;t++){let n=!1,i=null;try{n=await this.rawConnect()!==!1}catch(e){i=e}if(this.disposed)return;if(n){for(let e of this.active.values())e.off(),e.off=e.make();t>0&&e(this.diagnostics,`info`,`[incanto] multiplayer reconnected after ${t+1} attempts.`);return}t===0&&e(this.diagnostics,`warn`,`[incanto] the multiplayer connection dropped and the server would not take it back${i?` (${i instanceof Error?i.message:String(i)})`:``}. Retrying — other players cannot see this one until it comes back.`);let a=r[Math.min(t,r.length-1)]??8e3;if(await this.wait(a),this.disposed)return}e(this.diagnostics,`error`,`[incanto] multiplayer gave up after ${i} reconnect attempts — this client is offline and the others cannot see it. Call connect() again to retry.`)}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{n as createAgent8Server};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as e,o as t,r as n,t as r}from"./index-QEwr2eXD.js";function i(e,t,n,r=1){let i=Math.min(e.x0,e.x1)*r,a=Math.max(e.x0,e.x1)*r,o=Math.min(e.y0,e.y1)*r,s=Math.max(e.y0,e.y1)*r,c=Math.max(0,Math.min(Math.round(i),t-1)),l=Math.max(0,Math.min(Math.round(o),n-1));return{x:c,y:l,w:Math.max(1,Math.min(Math.round(a-i),t-c)),h:Math.max(1,Math.min(Math.round(s-o),n-l))}}function a(e,t,n,r){let{x:i,y:a,w:o,h:s}=r,c=new Uint8ClampedArray(o*s*4);for(let n=0;n<s;n++){let r=((a+n)*t+i)*4,s=n*o*4;c.set(e.subarray(r,r+o*4),s)}return{pixels:c,width:o,height:s}}function o(e){if(!e)return`// no scene loaded`;let t=e.source??e;return JSON.stringify(t,null,2)}async function s(e){let t=globalThis.navigator;if(!t?.clipboard?.writeText)return!1;try{return await t.clipboard.writeText(e),!0}catch{return!1}}async function c(e,t){let n=globalThis,r=n.navigator?.clipboard?.write;if(!r||!n.ImageData||!n.ClipboardItem)return!1;try{let i=e.createElement(`canvas`);i.width=t.width,i.height=t.height;let a=i.getContext(`2d`);if(!a)return!1;a.putImageData(new n.ImageData(t.pixels,t.width,t.height),0,0);let o=await new Promise(e=>i.toBlob(e,`image/png`));return o?(await r.call(n.navigator?.clipboard,[new n.ClipboardItem({"image/png":o})]),!0):!1}catch{return!1}}var l=[`nw`,`n`,`ne`,`e`,`se`,`s`,`sw`,`w`],u={nw:[0,0],n:[.5,0],ne:[1,0],e:[1,.5],se:[1,1],s:[.5,1],sw:[0,1],w:[0,.5]},d={nw:`nwse-resize`,se:`nwse-resize`,ne:`nesw-resize`,sw:`nesw-resize`,n:`ns-resize`,s:`ns-resize`,e:`ew-resize`,w:`ew-resize`},f=(e,t,n)=>Math.max(t,Math.min(n,e));function p(e){return{x:Math.min(e.x0,e.x1),y:Math.min(e.y0,e.y1),w:Math.abs(e.x1-e.x0),h:Math.abs(e.y1-e.y0)}}function m(e,t,n,r,i,a){let o=e.x,s=e.y,c=e.x+e.w,l=e.y+e.h;return t.includes(`w`)&&(o=f(o+n,0,i)),t.includes(`e`)&&(c=f(c+n,0,i)),t.includes(`n`)&&(s=f(s+r,0,a)),t.includes(`s`)&&(l=f(l+r,0,a)),{x:Math.min(o,c),y:Math.min(s,l),w:Math.max(1,Math.abs(c-o)),h:Math.max(1,Math.abs(l-s))}}function h(e,t,n,r,i){return{...e,x:f(e.x+t,0,Math.max(0,r-e.w)),y:f(e.y+n,0,Math.max(0,i-e.h))}}function g(e,t,n,r,i,a=8){let o=f(e.x+e.w/2-t/2,a,Math.max(a,r-t-a)),s=e.y+e.h+a,c=e.y-n-a;return{x:o,y:s+n<=i-a?s:c>=a?c:f(s,a,Math.max(a,i-n-a))}}function _(e,t){let n=e?.clientWidth??0,r=e?.clientHeight??0;return n>0&&r>0?{w:n,h:r}:{w:t.documentElement?.clientWidth??0,h:t.documentElement?.clientHeight??0}}function v(e,t,n,r,i,a,o=180,s=120){let c=Math.max(o,n),l=Math.max(s,r);return{x:i>0?Math.min(Math.max(0,e),Math.max(0,i-c)):e,y:a>0?Math.min(Math.max(0,t),Math.max(0,a-l)):t,w:c,h:l}}function y(e,t,n,r,i,a=4){let o=Math.min(Math.max(0,e.x),Math.max(0,r-t)),s=e.y+e.h+a,c=e.y-n-a;return s+n<=i?{x:o,y:s}:c>=0?{x:o,y:c}:{x:o,y:Math.min(Math.max(0,s),Math.max(0,i-n))}}function b(e,t,n){let r=e=>{e.key===`Escape`&&n()},i=e=>{let r=e.target;if(r){for(let e of t)if(e&&(e===r||e.contains?.(r)))return;n()}};return e.addEventListener?.(`keydown`,r),e.addEventListener?.(`pointerdown`,i),()=>{e.removeEventListener?.(`keydown`,r),e.removeEventListener?.(`pointerdown`,i)}}function x(e,t){for(let[n,r]of Object.entries(t))e.style[n]=r}var S=`rgba(18, 20, 26, 0.92)`,C=`1px solid rgba(255,255,255,0.14)`,w=`12px ui-monospace, SFMono-Regular, Menlo, monospace`,T=class{doc;host;el;body;onClose=()=>{};x;y;w;h;constructor(e,t,n,r){this.doc=e,this.host=t,this.x=r.x,this.y=r.y,this.w=r.w,this.h=r.h,this.el=e.createElement(`div`),x(this.el,{position:`absolute`,background:S,border:C,borderRadius:`8px`,color:`rgba(255,255,255,0.88)`,font:w,display:`flex`,flexDirection:`column`,overflow:`hidden`,zIndex:`40`,pointerEvents:`auto`,boxShadow:`0 8px 28px rgba(0,0,0,0.45)`});let i=e.createElement(`div`);i.textContent=n,x(i,{padding:`6px 28px 6px 10px`,background:`rgba(255,255,255,0.07)`,cursor:`move`,userSelect:`none`,touchAction:`none`,fontWeight:`700`}),this.el.appendChild(i);let a=e.createElement(`div`);a.textContent=`×`,a.title=`close`,x(a,{position:`absolute`,top:`2px`,right:`8px`,cursor:`pointer`,fontSize:`16px`,lineHeight:`20px`,opacity:`0.7`}),a.addEventListener(`click`,()=>this.onClose()),this.el.appendChild(a),this.body=e.createElement(`div`),x(this.body,{flex:`1`,overflow:`auto`,padding:`8px 10px`}),this.el.appendChild(this.body);let o=e.createElement(`div`);o.textContent=`◢`,x(o,{position:`absolute`,right:`2px`,bottom:`0`,cursor:`nwse-resize`,opacity:`0.5`,userSelect:`none`,touchAction:`none`}),this.el.appendChild(o),this.wireDrag(i,(e,t)=>{this.x+=e,this.y+=t,this.layout()}),this.wireDrag(o,(e,t)=>{this.w+=e,this.h+=t,this.layout()}),this.layout(),t.appendChild(this.el)}remove(){this.el.remove()}layout(){let e=_(this.host,this.doc),t=v(this.x,this.y,this.w,this.h,e.w,e.h);this.x=t.x,this.y=t.y,this.w=t.w,this.h=t.h,x(this.el,{left:`${t.x}px`,top:`${t.y}px`,width:`${t.w}px`,height:`${t.h}px`})}wireDrag(e,t){let r=null,i=0,a=0;e.addEventListener(`pointerdown`,t=>{r=t.pointerId,i=t.clientX,a=t.clientY,n(e,t.pointerId)}),e.addEventListener(`pointermove`,e=>{e.pointerId===r&&(t(e.clientX-i,e.clientY-a),i=e.clientX,a=e.clientY)});let o=e=>{e.pointerId===r&&(r=null)};e.addEventListener(`pointerup`,o),e.addEventListener(`pointercancel`,o)}},E=4,D=`#6ee7dc`,O=`rgba(18,20,26,0.94)`,k=`12px ui-monospace, Menlo, monospace`;function A(e){let{doc:t,container:r}=e,i=t.createElement(`div`);x(i,{position:`absolute`,inset:`0`,cursor:`crosshair`,zIndex:`80`,pointerEvents:`auto`,userSelect:`none`,touchAction:`none`});let a=t.createElement(`div`);x(a,{position:`absolute`,inset:`0`,background:`rgba(10,14,20,0.35)`,pointerEvents:`none`}),i.appendChild(a);let o=t.createElement(`div`);x(o,{position:`absolute`,outline:`1px solid ${D}`,boxShadow:`0 0 0 9999px rgba(10,14,20,0.35)`,cursor:`grab`,display:`none`,pointerEvents:`auto`}),i.appendChild(o);let s=t.createElement(`div`);x(s,{position:`absolute`,padding:`2px 6px`,borderRadius:`4px`,background:O,color:D,font:k,pointerEvents:`none`,display:`none`,whiteSpace:`nowrap`}),i.appendChild(s);let c=t.createElement(`div`);c.textContent=`drag to select · Esc to cancel`,x(c,{position:`absolute`,top:`10px`,left:`50%`,transform:`translateX(-50%)`,padding:`4px 10px`,borderRadius:`6px`,background:O,color:`rgba(255,255,255,0.85)`,font:k,pointerEvents:`none`,whiteSpace:`nowrap`}),i.appendChild(c);let f=null,_=`idle`,v={x:0,y:0},y={x:0,y:0,w:0,h:0},b=()=>({w:r.clientWidth||1,h:r.clientHeight||1});for(let e of l){let n=t.createElement(`div`),[r,i]=u[e];x(n,{position:`absolute`,left:`${r*100}%`,top:`${i*100}%`,width:`10px`,height:`10px`,marginLeft:`-5px`,marginTop:`-5px`,borderRadius:`2px`,background:D,border:`1px solid rgba(10,14,20,0.75)`,cursor:d[e],pointerEvents:`auto`}),n.addEventListener(`pointerdown`,t=>{A(t,e)}),o.appendChild(n)}let S=t.createElement(`div`);x(S,{position:`absolute`,display:`none`,gap:`6px`,padding:`6px`,borderRadius:`8px`,background:O,border:`1px solid rgba(255,255,255,0.18)`,font:k,pointerEvents:`auto`,whiteSpace:`nowrap`,boxShadow:`0 4px 16px rgba(0,0,0,0.45)`});let C=(e,n,r)=>{let i=t.createElement(`div`);return i.textContent=e,x(i,{padding:`5px 10px`,borderRadius:`5px`,cursor:`pointer`,color:n?`#08121a`:`rgba(255,255,255,0.85)`,background:n?D:`rgba(255,255,255,0.08)`,userSelect:`none`}),i.addEventListener(`pointerdown`,e=>{w(e),r()}),i};S.appendChild(C(`Copy to clipboard`,!0,()=>P())),S.appendChild(C(`Cancel`,!1,()=>L())),i.appendChild(S);function w(e){e.preventDefault?.(),e.stopPropagation?.()}function T(e){let t=e,n=r.getBoundingClientRect?.()??{left:0,top:0};return{x:(t.clientX??0)-n.left,y:(t.clientY??0)-n.top}}function A(e,t){w(e),v=T(e),_=t,t===`create`?f={x:v.x,y:v.y,w:0,h:0}:f&&(y=f),x(S,{display:`none`}),x(o,{cursor:t===`move`?`grabbing`:`crosshair`});let r=e.pointerId;r!==void 0&&n(i,r),j()}function j(){if(!f){x(o,{display:`none`}),x(s,{display:`none`}),x(a,{display:`block`});return}x(a,{display:`none`}),x(o,{display:`block`,left:`${f.x}px`,top:`${f.y}px`,width:`${f.w}px`,height:`${f.h}px`});let t=e.scale();s.textContent=`${Math.round(f.w*t)}×${Math.round(f.h*t)}`;let n=f.y-24;x(s,{display:`block`,left:`${Math.max(2,f.x)}px`,top:`${n>=2?n:f.y+4}px`})}function M(){if(!f||f.w<E||f.h<E)return;x(S,{display:`flex`});let e=b(),t=S.offsetWidth||200,n=S.offsetHeight||36,r=g(f,t,n,e.w,e.h);x(S,{left:`${r.x}px`,top:`${r.y}px`})}i.addEventListener(`pointerdown`,e=>{A(e,`create`)}),o.addEventListener(`pointerdown`,e=>{A(e,`move`)}),i.addEventListener(`pointermove`,e=>{if(_===`idle`||!f)return;let t=T(e),n=b();if(_===`create`){let e=p({x0:v.x,y0:v.y,x1:t.x,y1:t.y});f={x:Math.max(0,Math.min(e.x,n.w)),y:Math.max(0,Math.min(e.y,n.h)),w:Math.min(e.w,n.w-Math.max(0,Math.min(e.x,n.w))),h:Math.min(e.h,n.h-Math.max(0,Math.min(e.y,n.h)))}}else f=_===`move`?h(y,t.x-v.x,t.y-v.y,n.w,n.h):m(y,_,t.x-v.x,t.y-v.y,n.w,n.h);j()});let N=()=>{_!==`idle`&&(_===`create`&&f&&(f.w<E||f.h<E)&&(f=null),_=`idle`,x(o,{cursor:`grab`}),c.textContent=f?`drag the handles or the middle · Enter to copy · Esc to cancel`:`drag to select · Esc to cancel`,j(),M())};i.addEventListener(`pointerup`,N),i.addEventListener(`pointercancel`,N);function P(){let t=f;L(),t&&e.onCopy(t)}let F=e=>{let t=e.key;t===`Escape`?L():t===`Enter`&&f&&P()};t.addEventListener?.(`keydown`,F);let I=!1;function L(){I||(I=!0,t.removeEventListener?.(`keydown`,F),i.remove(),e.onClose())}return r.appendChild(i),{element:i,close:L}}var j=96,M=200,N=8192;function P(e){return Array.isArray(e)?`Array(${e.length})`:`Object(${Object.keys(e).length} keys)`}function F(e,t){if(Array.isArray(e)&&e.some(e=>typeof e==`object`&&!!e)){let t=e.slice(0,M).map(e=>JSON.stringify(e)),n=e.length-M;return t.join(`
|
|
2
|
+
`)+(n>0?`\n… ${n} more`:``)}return t.length>N?`${t.slice(0,N)} … (${t.length-N} more chars)`:t}function I(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var L=2,R=4;function z(e,t={}){let n=t.doc??(typeof document<`u`?document:null);if(!n)return null;let r=t.container??(typeof document<`u`?document.body:null);return!r||typeof r.appendChild!=`function`?null:new H(e,r,n,t.statsSource,t.actions,t.frameSource)}var B=300,V=[`log`,`info`,`warn`,`error`,`debug`],H=class{engine;container;doc;statsSource;actions;frameSource;panels=new Map;cleanups=[];menuButton;dropdown=null;dismissDropdown=null;menuPos={x:8,y:8};selected=null;collapsedFlags=new Map;statsChip=null;logRows=[];levelEnabled={debug:!0,info:!0,warn:!0,error:!0};consoleCapture=!1;consolePatched=[];frame=0;editing=0;detailOpen=new WeakMap;resumeScale=1;timeEls=null;hovering=!1;constructor(e,t,n,r,i=[],a){this.engine=e,this.container=t,this.doc=n,this.statsSource=r,this.actions=i,this.frameSource=a,this.menuButton=n.createElement(`div`),this.menuButton.textContent=`☰ debug`,x(this.menuButton,{position:`absolute`,top:`8px`,left:`8px`,padding:`4px 10px`,background:`rgba(18,20,26,0.85)`,border:`1px solid rgba(255,255,255,0.18)`,borderRadius:`6px`,color:`rgba(255,255,255,0.85)`,font:`12px ui-monospace, Menlo, monospace`,cursor:`pointer`,userSelect:`none`,zIndex:`50`,pointerEvents:`auto`}),this.bindMenuDrag(),t.style.position||(t.style.position=`relative`),t.appendChild(this.menuButton),this.cleanups.push(e.log.added.connect(e=>{this.pushLog({level:e.level,source:`engine`,text:e.parts.map(G).join(` `)})})),this.cleanups.push(e.sceneChanged.connect(()=>{this.selected=null,this.applyColliderScope(),this.renderExplorer(),this.renderInspector()})),this.cleanups.push(e.updated.connect(()=>{this.frame+=1,this.frame%30==0&&(this.renderExplorer(),this.renderStats(),this.editing===0&&!this.hovering&&this.renderInspector(),this.syncTime())}))}isOpen(e){return e===`copyScene`||e===`captureRegion`?!1:e===`colliders`?this.colliderMode!==`off`:e===`stats`?this.statsChip!==null:this.panels.has(e)}colliderMode=`off`;setColliders(e){this.colliderMode=e,this.applyColliderScope()}applyColliderScope(){let e=this.colliderMode;for(let t of r(`2d`).concat(r(`3d`)))t.debugDraw=e!==`off`,t.debugScope=e===`selected`?this.selected:null}open(e){if(e===`stats`){this.openStatsChip();return}if(this.panels.has(e)){e===`explorer`&&this.renderExplorer(),e===`inspector`&&this.renderInspector(),e===`logs`&&this.renderLogs(),e===`time`&&this.renderTime();return}let t=new T(this.doc,this.container,{explorer:`Explorer`,inspector:`Inspector`,logs:`Logs`,time:`Time`}[e],{explorer:{x:12,y:44,w:240,h:320},inspector:{x:264,y:44,w:280,h:320},logs:{x:12,y:380,w:532,h:200},time:{x:556,y:44,w:260,h:150}}[e]);t.onClose=()=>this.close(e),e===`inspector`&&(t.body.addEventListener(`pointerenter`,()=>{this.hovering=!0}),t.body.addEventListener(`pointerleave`,()=>{this.hovering=!1})),this.panels.set(e,t),e===`explorer`&&this.renderExplorer(),e===`inspector`&&this.renderInspector(),e===`logs`&&this.renderLogs(),e===`time`&&this.renderTime()}close(e){if(e===`inspector`&&(this.hovering=!1),e===`stats`){this.statsChip?.remove(),this.statsChip=null;return}let t=this.panels.get(e);t&&(t.remove(),this.panels.delete(e))}toggle(e){if(e===`copyScene`){this.copyScene();return}if(e===`captureRegion`){this.captureRegion();return}if(e===`colliders`){this.setColliders({off:`all`,all:`selected`,selected:`off`}[this.colliderMode]);return}this.isOpen(e)?this.close(e):this.open(e)}setLevelEnabled(e,t){this.levelEnabled[e]=t,this.renderLogs()}setConsoleCapture(e){if(e!==this.consoleCapture)if(this.consoleCapture=e,e){this.renderLogs();let e=console;for(let t of V){let n=e[t];e[t]=(...e)=>{n.apply(console,e);let r=t===`log`?`info`:t;this.pushLog({level:r,source:`console`,text:e.map(G).join(` `)})},this.consolePatched.push(()=>{e[t]=n})}}else{for(let e of this.consolePatched)e();this.consolePatched=[],this.renderLogs()}}dispose(){this.engine.debugSelection=null,this.setColliders(`off`),this.setConsoleCapture(!1);for(let e of this.cleanups)e();for(let e of[...this.panels.keys()])this.close(e);this.close(`stats`),this.closeDropdown(),this.menuButton.remove()}menuLabel(e,t){let n=e===`colliders`&&this.colliderMode!==`off`?` · ${this.colliderMode}`:``;return`${this.isOpen(e)?`✓ `:``}${t}${n}`}bindMenuDrag(){let e=null,t=!1;this.menuButton.addEventListener(`pointerdown`,n=>{let r=n;e={x:r.clientX??0,y:r.clientY??0,bx:this.menuPos.x,by:this.menuPos.y},t=!1,r.pointerId!==void 0&&this.menuButton.setPointerCapture?.(r.pointerId)}),this.menuButton.addEventListener(`pointermove`,n=>{if(!e)return;let r=n,i=(r.clientX??0)-e.x,a=(r.clientY??0)-e.y;!t&&Math.hypot(i,a)<R||(t||(t=!0,this.closeDropdown(),x(this.menuButton,{cursor:`grabbing`})),this.moveMenuButton(e.bx+i,e.by+a))});let n=()=>{if(!e)return;let n=t;e=null,t=!1,x(this.menuButton,{cursor:`pointer`}),n||this.toggleDropdown()};this.menuButton.addEventListener(`pointerup`,n),this.menuButton.addEventListener(`pointercancel`,n)}moveMenuButton(e,t){let n=this.menuButton,r=_(this.container,this.doc),i=v(e,t,n.offsetWidth??0,n.offsetHeight??0,r.w,r.h,0,0);this.menuPos={x:i.x,y:i.y},x(this.menuButton,{left:`${i.x}px`,top:`${i.y}px`})}closeDropdown(){this.dismissDropdown?.(),this.dismissDropdown=null,this.dropdown?.remove(),this.dropdown=null}toggleDropdown(){if(this.dropdown){this.closeDropdown();return}let e=this.doc.createElement(`div`);x(e,{position:`absolute`,background:`rgba(18,20,26,0.95)`,border:`1px solid rgba(255,255,255,0.18)`,borderRadius:`6px`,font:`12px ui-monospace, Menlo, monospace`,color:`rgba(255,255,255,0.85)`,zIndex:`60`,pointerEvents:`auto`,overflow:`hidden`});for(let[t,n]of[[`explorer`,`Explorer`],[`inspector`,`Inspector`],[`logs`,`Logs`],[`time`,`Time`],[`copyScene`,`Copy scene JSON`],[`captureRegion`,`Capture region`],[`stats`,`Stats`],[`colliders`,`Colliders`]]){let r=this.doc.createElement(`div`);r.textContent=this.menuLabel(t,n),x(r,{padding:`6px 14px`,cursor:`pointer`,userSelect:`none`}),r.addEventListener(`click`,()=>{if(this.toggle(t),t===`colliders`){r.textContent=this.menuLabel(t,n);return}this.closeDropdown()}),e.appendChild(r)}for(let t of this.actions){let n=this.doc.createElement(`div`);n.textContent=t.label,x(n,{padding:`6px 14px`,cursor:`pointer`,userSelect:`none`,borderTop:`1px solid rgba(255,255,255,0.14)`,color:`rgba(158,232,220,0.95)`}),n.addEventListener(`click`,()=>{this.closeDropdown(),t.run()}),e.appendChild(n)}this.container.appendChild(e),this.dropdown=e;let t=e,n=this.menuButton,r=_(this.container,this.doc),i=y({x:this.menuPos.x,y:this.menuPos.y,w:n.offsetWidth??0,h:n.offsetHeight??26},t.offsetWidth??0,t.offsetHeight??0,r.w,r.h);x(e,{left:`${i.x}px`,top:`${i.y}px`}),this.dismissDropdown=b(this.doc,[e,this.menuButton],()=>this.closeDropdown())}openStatsChip(){if(this.statsChip)return;let e=this.doc.createElement(`div`);x(e,{position:`absolute`,top:`8px`,right:`8px`,padding:`4px 10px`,background:`rgba(18,20,26,0.85)`,border:`1px solid rgba(255,255,255,0.18)`,borderRadius:`6px`,color:`rgba(255,255,255,0.85)`,font:`12px ui-monospace, Menlo, monospace`,textAlign:`right`,whiteSpace:`pre`,userSelect:`none`,pointerEvents:`none`,zIndex:`70`}),this.container.appendChild(e),this.statsChip=e,this.renderStats()}renderStats(){let e=this.statsChip;if(!e)return;let t=this.engine.stats(),n=this.statsSource?.()??{},r=[`nodes ${t.nodes}`,...n.triangles===void 0?[]:[`tris ${W(n.triangles)}`],...n.drawCalls===void 0?[]:[`calls ${n.drawCalls}`]].join(` · `),i=t.phases,a=`\nphys ${i.fixedMs.toFixed(1)} · logic ${i.updateMs.toFixed(1)} · draw ${i.renderMs.toFixed(1)} · other ${i.otherMs.toFixed(1)}`;e.textContent=`${Math.round(t.fps)} fps · ${t.frameMs.toFixed(1)} ms\n${r}${a}`}renderExplorer(){let e=this.panels.get(`explorer`);if(!e)return;let t=e.body.scrollTop;U(e.body);let n=this.engine.scene?.root;if(!n){e.body.scrollTop=t;return}let r=(e,t)=>{let n=e.constructor,i=e.children.length>0,a=this.collapsedFlags.get(e)===!0,o=this.doc.createElement(`div`);x(o,{display:`flex`,alignItems:`center`,cursor:`pointer`,padding:`1px 2px`,borderRadius:`3px`,background:e===this.selected?`rgba(110,160,255,0.25)`:`transparent`});let s=this.doc.createElement(`span`);s.textContent=i?a?`▸`:`▾`:`·`,x(s,{width:`14px`,flex:`none`,textAlign:`center`,opacity:i?`0.85`:`0.25`,userSelect:`none`}),i&&s.addEventListener(`click`,t=>{t.stopPropagation?.(),this.collapsedFlags.set(e,!a),this.renderExplorer()}),o.appendChild(s);let c=this.doc.createElement(`span`);c.textContent=e.name,x(c,{whiteSpace:`nowrap`}),o.appendChild(c);let l=this.doc.createElement(`span`);if(l.textContent=` ${n.typeName}`,x(l,{opacity:`0.45`,whiteSpace:`nowrap`,fontSize:`10px`}),o.appendChild(l),i&&a){let t=this.doc.createElement(`span`);t.textContent=` (${e.children.length})`,x(t,{opacity:`0.35`,fontSize:`10px`}),o.appendChild(t)}if(o.addEventListener(`click`,()=>{this.selected=e,this.engine.debugSelection=e,this.applyColliderScope(),this.open(`inspector`),this.renderExplorer(),this.renderInspector()}),t.appendChild(o),i&&!a){let n=this.doc.createElement(`div`);x(n,{marginLeft:`8px`,paddingLeft:`8px`,borderLeft:`1px solid rgba(255,255,255,0.14)`});for(let t of e.children)r(t,n);t.appendChild(n)}};r(n,e.body),e.body.scrollTop=t}renderInspector(){let t=this.panels.get(`inspector`);if(!t)return;let n=t.body.scrollTop;U(t.body);let r=this.selected;if(r&&r.tree===null&&(this.selected=null,this.engine.debugSelection=null,this.applyColliderScope(),r=null),!r){let e=this.doc.createElement(`div`);e.textContent=`select a node in the Explorer`,x(e,{opacity:`0.6`}),t.body.appendChild(e);return}let i=r.constructor,a=this.doc.createElement(`div`);if(a.textContent=`${r.getPath()} · ${i.typeName}${r.uid?` · ${r.uid}`:``}`,x(a,{fontWeight:`700`,marginBottom:`6px`,whiteSpace:`pre-wrap`}),t.body.appendChild(a),r.groups.size>0){let e=this.doc.createElement(`div`);e.textContent=`groups: ${[...r.groups].join(`, `)}`,x(e,{opacity:`0.7`,marginBottom:`6px`}),t.body.appendChild(e)}let o=e(i),s=r;for(let e of Object.keys(o)){let n=o[e];this.renderValueRow(t.body,r,e,{read:()=>s[e],write:t=>{s[e]=t},options:n?.options,variants:n?.variants})}t.body.scrollTop=n}renderValueRow(e,n,r,i){let a=i.read(),o=i.options,s={get[r](){return i.read()},set[r](e){i.write(e)}},c=this.doc.createElement(`div`);x(c,{display:`flex`,gap:`6px`,alignItems:`center`,margin:`2px 0`});let l=this.doc.createElement(`div`);l.textContent=r,x(l,{minWidth:`84px`,opacity:`0.75`}),c.appendChild(l);let u=(e,t)=>{let i=this.doc.createElement(`input`);return i.type=`number`,i.value=String(e),x(i,q(`70px`)),this.trackEditing(i),i.addEventListener(`change`,()=>{let e=Number(i.value);Number.isFinite(e)?t(e):i.value=String(n[r])}),i};if(typeof a==`number`)c.appendChild(u(a,e=>{s[r]=e}));else if(typeof a==`boolean`){let e=this.doc.createElement(`input`);e.type=`checkbox`,e.checked=a,this.trackEditing(e),e.addEventListener(`change`,()=>{s[r]=e.checked}),c.appendChild(e)}else if(typeof a==`string`&&o&&o.length>0){let e=this.doc.createElement(`select`);for(let t of o.includes(a)?o:[a,...o]){let n=this.doc.createElement(`option`);n.value=t,n.textContent=t,t===a&&(n.selected=!0),e.appendChild(n)}e.value=a,this.trackEditing(e),e.addEventListener(`change`,()=>{s[r]=e.value}),x(e,q(`110px`)),c.appendChild(e)}else if(typeof a==`string`){let e=this.doc.createElement(`input`);e.type=`text`,e.value=a,this.trackEditing(e),x(e,q(`140px`)),e.addEventListener(`change`,()=>{s[r]=e.value}),c.appendChild(e)}else if(Array.isArray(a)&&a.length<=8&&a.every(e=>typeof e==`number`))for(let e=0;e<a.length;e++)c.appendChild(u(a[e],t=>{let n=[...s[r]];n[e]=t,s[r]=n}));else if(I(a)){let o=this.doc.createElement(`div`);x(o,{marginLeft:`10px`,paddingLeft:`8px`,borderLeft:`1px solid rgba(255,255,255,0.14)`});let s=i.variants?.tag,l=Object.keys(a);s&&!l.includes(s)&&l.unshift(s);let u=i.path??r;for(let e of l){let r=e===s;this.renderValueRow(o,n,e,{path:`${u}.${e}`,read:()=>i.read()[e]??(r?``:null),write:n=>{if(r&&i.variants){let e=i.variants.byTag[String(n)];if(e!==void 0){i.write(t(e));return}}i.write({...i.read(),[e]:n})},options:r&&i.variants?Object.keys(i.variants.byTag):void 0})}e.appendChild(c),e.appendChild(o);return}else{let o=JSON.stringify(t(a));if(o.length<=j){let e=this.doc.createElement(`div`);e.textContent=o,x(e,{opacity:`0.65`,whiteSpace:`pre-wrap`,wordBreak:`break-all`}),c.appendChild(e)}else{let t=i.path??r,s=this.detailOpen.get(n)?.has(t)??!1,l=this.doc.createElement(`div`);if(l.textContent=`${s?`▾`:`▸`} ${P(a)}`,x(l,{opacity:`0.75`,cursor:`pointer`,userSelect:`none`}),l.addEventListener(`click`,()=>{let e=this.detailOpen.get(n);e||(e=new Set,this.detailOpen.set(n,e)),s?e.delete(t):e.add(t),this.renderInspector()}),c.appendChild(l),e.appendChild(c),s){let t=this.doc.createElement(`div`);t.textContent=F(a,o),x(t,{opacity:`0.6`,whiteSpace:`pre-wrap`,wordBreak:`break-all`,marginLeft:`10px`,paddingLeft:`8px`,borderLeft:`1px solid rgba(255,255,255,0.14)`}),e.appendChild(t)}return}}e.appendChild(c)}trackEditing(e){e.addEventListener(`focus`,()=>{this.editing+=1}),e.addEventListener(`blur`,()=>{this.editing=Math.max(0,this.editing-1)})}pushLog(e){this.logRows.push(e),this.logRows.length>B&&this.logRows.splice(0,this.logRows.length-B),this.renderLogs()}async copyScene(){let e=await s(o(this.engine.scene??null));return this.toast(e?`scene JSON copied`:`could not reach the clipboard`),e}captureRegion(){this.capture||=(this.captureScale=globalThis.devicePixelRatio??1,this.frameSource?.().then(e=>{this.captureScale=e.width/Math.max(1,this.container.clientWidth||e.width)}).catch(()=>{}),A({doc:this.doc,container:this.container,scale:()=>this.captureScale,onCopy:e=>void this.copyRegion({x0:e.x,y0:e.y,x1:e.x+e.w,y1:e.y+e.h}),onClose:()=>{this.capture=null}}))}capture=null;captureScale=1;async copyRegion(e){let t=this.frameSource;if(!t)return this.toast(`no renderer to capture from`),!1;try{let n=await t(),r=n.width/Math.max(1,this.container.clientWidth||n.width),o=i(e,n.width,n.height,r),s=a(n.pixels,n.width,n.height,o),l=await c(this.doc,s);return this.toast(l?`copied ${s.width}×${s.height}`:`could not copy the image`),l}catch(e){return this.toast(`capture failed: ${e instanceof Error?e.message:String(e)}`),!1}}toast(e){let t=this.doc.createElement(`div`);t.textContent=e,x(t,{position:`absolute`,bottom:`16px`,left:`50%`,transform:`translateX(-50%)`,padding:`6px 12px`,borderRadius:`6px`,background:`rgba(18,20,26,0.92)`,color:`rgba(255,255,255,0.9)`,font:`12px ui-monospace, Menlo, monospace`,zIndex:`90`,pointerEvents:`none`}),this.container.appendChild(t),setTimeout(()=>t.remove(),1800)}setTimeScale(e){Number.isFinite(e)&&(this.engine.timeScale=Math.max(0,e),this.syncTime())}setPaused(e){e?(this.engine.timeScale>0&&(this.resumeScale=this.engine.timeScale),this.engine.timeScale=0):this.engine.timeScale=this.resumeScale>0?this.resumeScale:1,this.syncTime()}get paused(){return this.engine.timeScale===0}nextFrame(){this.paused||this.setPaused(!0),this.engine.step({ignorePause:!0}),this.syncTime()}syncTime(){let e=this.timeEls;if(!e)return;let t=this.engine.timeScale,n=String(Math.round(t*1e3)/1e3);this.editing===0&&(e.slider.value=String(Math.min(t,L)),e.box.value=n),e.readout.textContent=`timeScale ${n}${this.paused?` · paused`:``}`,e.pause.textContent=this.paused?`▶ Resume`:`⏸ Pause`}renderTime(){let e=this.panels.get(`time`);if(!e)return;U(e.body),this.timeEls=null;let t=this.doc.createElement(`div`);x(t,{marginBottom:`6px`,opacity:`0.85`}),e.body.appendChild(t);let n=this.doc.createElement(`input`);n.type=`range`,n.min=`0`,n.max=String(L),n.step=`0.05`,n.value=String(Math.min(this.engine.timeScale,L)),x(n,{width:`100%`,marginBottom:`6px`}),this.trackEditing(n),n.addEventListener(`input`,()=>this.setTimeScale(Number(n.value))),e.body.appendChild(n);let r=this.doc.createElement(`div`);x(r,{display:`flex`,gap:`6px`,alignItems:`center`,marginBottom:`8px`});let i=this.doc.createElement(`input`);i.type=`number`,i.min=`0`,i.step=`0.05`,i.value=String(this.engine.timeScale),x(i,q(`72px`)),this.trackEditing(i),i.addEventListener(`change`,()=>{let e=Number(i.value);Number.isFinite(e)&&this.setTimeScale(e),this.syncTimeAfterEdit()}),r.appendChild(i);for(let e of[.25,.5,1,2]){let t=this.doc.createElement(`div`);t.textContent=`${e}×`,x(t,{cursor:`pointer`,opacity:`0.7`,padding:`2px 4px`}),t.addEventListener(`click`,()=>this.setTimeScale(e)),r.appendChild(t)}e.body.appendChild(r);let a=this.doc.createElement(`div`);x(a,{display:`flex`,gap:`8px`});let o=this.doc.createElement(`div`);x(o,K()),o.addEventListener(`click`,()=>this.setPaused(!this.paused)),a.appendChild(o);let s=this.doc.createElement(`div`);s.textContent=`⏭ Next frame`,s.title=`Pauses, then advances one fixed step`,x(s,K()),s.addEventListener(`click`,()=>this.nextFrame()),a.appendChild(s),e.body.appendChild(a),this.timeEls={slider:n,box:i,readout:t,pause:o},this.syncTime()}syncTimeAfterEdit(){let e=this.timeEls;if(!e)return;let t=this.engine.timeScale;e.slider.value=String(Math.min(t,L)),e.box.value=String(Math.round(t*1e3)/1e3)}renderLogs(){let e=this.panels.get(`logs`);if(!e)return;U(e.body);let t=this.doc.createElement(`div`);x(t,{display:`flex`,gap:`8px`,marginBottom:`4px`,flexWrap:`wrap`});for(let e of[`debug`,`info`,`warn`,`error`]){let n=this.doc.createElement(`div`);n.textContent=`${this.levelEnabled[e]?`✓`:`·`}${e}`,x(n,{cursor:`pointer`,opacity:this.levelEnabled[e]?`1`:`0.45`}),n.addEventListener(`click`,()=>this.setLevelEnabled(e,!this.levelEnabled[e])),t.appendChild(n)}let n=this.doc.createElement(`div`);n.textContent=`${this.consoleCapture?`✓`:`·`}console`,x(n,{cursor:`pointer`,marginLeft:`auto`}),n.addEventListener(`click`,()=>this.setConsoleCapture(!this.consoleCapture)),t.appendChild(n),e.body.appendChild(t);let r={debug:`rgba(255,255,255,0.5)`,info:`rgba(255,255,255,0.85)`,warn:`#ffc861`,error:`#ff6b6b`};for(let t of this.logRows){if(!this.levelEnabled[t.level])continue;let n=this.doc.createElement(`div`);n.textContent=`[${t.source===`console`?`console`:t.level}] ${t.text}`,x(n,{color:r[t.level],whiteSpace:`pre-wrap`}),e.body.appendChild(n)}}};function U(e){for(let t of[...e.children])t.remove()}function W(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function G(e){if(typeof e==`string`)return e;if(e instanceof Error){let t=e.stack?.split(`
|
|
3
|
+
`)[1]?.trim();return`${e.name}: ${e.message}${t?` (${t})`:``}`}try{let t=JSON.stringify(e);return t===`{}`||t===void 0?String(e):t}catch{return String(e)}}function K(){return{background:`rgba(255,255,255,0.08)`,border:`1px solid rgba(255,255,255,0.2)`,borderRadius:`4px`,padding:`4px 8px`,cursor:`pointer`,userSelect:`none`}}function q(e){return{width:e,background:`rgba(255,255,255,0.08)`,border:`1px solid rgba(255,255,255,0.2)`,borderRadius:`4px`,color:`inherit`,font:`inherit`,padding:`2px 4px`}}export{z as attachDebugOverlay};
|