incanto 0.66.0 → 0.68.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/bin/_behaviors-loader.mjs +87 -0
- package/bin/_pick-server.mjs +48 -0
- package/bin/incanto-check.mjs +16 -2
- package/bin/incanto-editor.mjs +39 -2
- package/bin/incanto-feel.mjs +4 -1
- package/bin/incanto-frame.mjs +37 -3
- package/bin/incanto-logs.mjs +23 -3
- package/bin/incanto-multiplay.mjs +50 -1
- package/bin/incanto-play.mjs +3 -1
- package/bin/incanto-playtest.mjs +3 -25
- package/bin/incanto-verify.mjs +15 -2
- package/dist/2d.d.ts +44 -7
- package/dist/2d.js +6 -4
- package/dist/3d.d.ts +112 -16
- package/dist/3d.js +8 -6
- package/dist/{audio-player-_UAcHxnC.d.ts → audio-player-DOrq7sP-.d.ts} +62 -4
- package/dist/{behavior-BXNLfIJk.d.ts → behavior-DoFPYrgo.d.ts} +117 -2
- package/dist/boot-failure-CKYrEcGF.js +47 -0
- package/dist/{create-game-DYJCIzO0.js → create-game-DbWtVTxD.js} +91 -29
- package/dist/{create-game-Dd7H4bJV.js → create-game-IZIydDwI.js} +16 -10
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +3 -2
- package/dist/{duplicate-CqSAtdrh.js → duplicate-IWIqk0HJ.js} +1 -1
- package/dist/{editor-switch-DAvWQeld.d.ts → editor-switch-CnIOiyNJ.d.ts} +1 -1
- package/dist/editor.js +18 -7
- package/dist/env.d.ts +1 -1
- package/dist/{environment-presets-BlPsEmq6.js → environment-presets-CybQXNqS.js} +100 -11
- package/dist/{gameplay-D1RADWu3.js → gameplay-DM1eu_cV.js} +46 -5
- package/dist/gameplay.d.ts +75 -6
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +52 -8
- package/dist/index.js +9 -7
- package/dist/{loader-lQDCwNag.js → loader-BC4PNtJX.js} +173 -1
- package/dist/{loader-Cga7FVP4.d.ts → loader-CcB533FR.d.ts} +2 -2
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/{physics-2d-Cji5A6sX.js → physics-2d-B7Y6dPZO.js} +29 -2
- package/dist/{physics-3d-BkHjwJgI.js → physics-3d-bG3n70Ky.js} +30 -3
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/{register-BmuqYTiY.js → register-3ta-2Xig.js} +148 -22
- package/dist/{register-D0CxCveZ.js → register-ibCjm-wH.js} +3 -3
- package/dist/{replay-IsZbNu6d.js → replay-CYvhVHHN.js} +28 -4
- package/dist/{replay-BHoB6fCU.d.ts → replay-Dvn8aeBd.d.ts} +38 -4
- package/dist/{schema-CFeioQRE.d.ts → schema-B6ugCV1Q.d.ts} +11 -0
- package/dist/{split-screen-D_i7GRcY.js → split-screen-CYwDkbLF.js} +2 -2
- package/dist/{split-screen-eJUFjhi1.d.ts → split-screen-DhrSzZIB.d.ts} +3 -3
- package/dist/{src-BTLbXFPZ.js → src-D7RIqXYF.js} +1 -1
- package/dist/{teardown-byR9USax.js → teardown-D2NEmxPB.js} +2 -2
- package/dist/{test-DgrD0jHD.js → test-8hoHeRmo.js} +140 -32
- package/dist/test.d.ts +9 -7
- package/dist/test.js +3 -3
- package/dist/{touch-DESwnpOc.js → touch-DEAmqGdf.js} +30 -186
- package/dist/vite.d.ts +0 -7
- package/dist/vite.js +13 -3
- package/dist/webgl-unavailable-N9nQqesw.js +228 -0
- package/editor/assets/{agent8-9N-Pd_YS.js → agent8-BrrHOjMJ.js} +1 -1
- package/editor/assets/debug-BBhKuBNV.js +3 -0
- package/editor/assets/{index-CeDhIPTC.js → index-eVd0BToA.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +5 -1
- package/skills/incanto-3d-character.md +1 -0
- package/skills/incanto-audio.md +49 -0
- package/skills/incanto-building-2d-games.md +37 -0
- package/skills/incanto-building-3d-games.md +56 -0
- package/skills/incanto-editor.md +5 -1
- package/skills/incanto-environment.md +2 -2
- package/skills/incanto-gameplay-behaviors.md +29 -2
- package/skills/incanto-hud.md +14 -1
- package/skills/incanto-multiplayer.md +14 -0
- package/skills/incanto-node-reference.md +2 -1
- package/skills/incanto-performance.md +35 -0
- package/skills/incanto-physics-and-input.md +23 -0
- package/skills/incanto-playtesting.md +15 -1
- package/skills/incanto-save-slots.md +21 -1
- package/skills/incanto-scene-json-authoring.md +12 -1
- package/skills/incanto-verifying-your-game.md +19 -0
- package/skills/incanto-your-first-game.md +4 -4
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +38 -19
- package/templates-app/beacon-isle-3d/src/main.ts +8 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +99 -53
- package/templates-app/platformer-2d/src/main.ts +8 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/game.scene.json +31 -17
- package/templates-app/star-survivor/src/main.ts +8 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/game.scene.json +14 -8
- package/templates-app/tps-3d/src/main.ts +8 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/grove.scene.json +20 -11
- package/templates-app/village-quest-3d/src/main.ts +8 -1
- package/templates-app/village-quest-3d/src/village.scene.json +10 -7
- package/editor/assets/debug-CkbJICYp.js +0 -3
package/dist/vite.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as VERSION } from "./src-
|
|
1
|
+
import { t as VERSION } from "./src-D7RIqXYF.js";
|
|
2
2
|
import { n as diffSignatures } from "./frame-report-BSMny7oe.js";
|
|
3
|
-
import { s as validateScene } from "./test-
|
|
3
|
+
import { s as validateScene } from "./test-8hoHeRmo.js";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, normalize, relative, resolve, sep } from "node:path";
|
|
6
6
|
//#region src/vite/frame-endpoint.ts
|
|
@@ -28,6 +28,14 @@ const DEFAULT_LABEL = "last";
|
|
|
28
28
|
* the container: it enumerates the ports that are actually open and asks each
|
|
29
29
|
* one. That answer has to be cheap and unmistakable.
|
|
30
30
|
*/
|
|
31
|
+
/** The consuming project's package name, for the ping's identity. */
|
|
32
|
+
function projectName(root) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(readFileSync(join(root, "package.json"), "utf8")).name ?? "";
|
|
35
|
+
} catch {
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
31
39
|
function serveFrameEndpoints(host, version, opts = {}) {
|
|
32
40
|
const channels = [
|
|
33
41
|
host.environments?.client?.hot,
|
|
@@ -65,7 +73,9 @@ function serveFrameEndpoints(host, version, opts = {}) {
|
|
|
65
73
|
host.middlewares.use("/__incanto/ping", (_req, res) => {
|
|
66
74
|
json$1(res, 200, {
|
|
67
75
|
incanto: version,
|
|
68
|
-
frame: Boolean(channel)
|
|
76
|
+
frame: Boolean(channel),
|
|
77
|
+
root: host.config?.root ?? process.cwd(),
|
|
78
|
+
project: projectName(host.config?.root ?? process.cwd())
|
|
69
79
|
});
|
|
70
80
|
});
|
|
71
81
|
serveLogs(host, channels, waiting, () => nextId++, timeoutMs);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
+
//#region src/core/drive-script.ts
|
|
3
|
+
const num = (raw) => {
|
|
4
|
+
if (raw === void 0) return null;
|
|
5
|
+
const n = Number(raw);
|
|
6
|
+
return Number.isFinite(n) ? n : null;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* `vector move 0 1; step 2000` → steps, or an error naming the bad command.
|
|
10
|
+
*
|
|
11
|
+
* Semicolons and newlines both separate, so a whole plan fits in one shell
|
|
12
|
+
* argument and a longer one fits in a file. `#` starts a comment.
|
|
13
|
+
*
|
|
14
|
+
* A command it does not know REFUSES THE WHOLE SCRIPT. Skipping it would leave
|
|
15
|
+
* an agent looking at a frame that never moved, believing it had walked
|
|
16
|
+
* somewhere — the failure mode this exists to prevent.
|
|
17
|
+
*/
|
|
18
|
+
function parseDrive(text) {
|
|
19
|
+
const steps = [];
|
|
20
|
+
let totalMs = 0;
|
|
21
|
+
const lines = text.split(/[;\n]/).map((l) => l.replace(/#.*$/, "").trim()).filter(Boolean);
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
const [word, ...rest] = line.split(/\s+/);
|
|
24
|
+
const bad = (why) => ({
|
|
25
|
+
steps: [],
|
|
26
|
+
error: `${why}: "${line}"`,
|
|
27
|
+
totalMs: 0
|
|
28
|
+
});
|
|
29
|
+
switch (word) {
|
|
30
|
+
case "press":
|
|
31
|
+
case "release": {
|
|
32
|
+
const action = rest[0];
|
|
33
|
+
if (!action) return bad(`${word} needs an action name`);
|
|
34
|
+
steps.push(word === "press" ? {
|
|
35
|
+
kind: "press",
|
|
36
|
+
action
|
|
37
|
+
} : {
|
|
38
|
+
kind: "release",
|
|
39
|
+
action
|
|
40
|
+
});
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case "vector": {
|
|
44
|
+
const action = rest[0];
|
|
45
|
+
const x = num(rest[1]);
|
|
46
|
+
const y = num(rest[2]);
|
|
47
|
+
if (!action || x === null || y === null) return bad("vector needs an action and two numbers");
|
|
48
|
+
steps.push({
|
|
49
|
+
kind: "vector",
|
|
50
|
+
action,
|
|
51
|
+
x,
|
|
52
|
+
y
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "key": {
|
|
57
|
+
const code = rest[0];
|
|
58
|
+
const dir = rest[1];
|
|
59
|
+
if (!code || dir !== "down" && dir !== "up") return bad("key needs a code and down|up");
|
|
60
|
+
steps.push({
|
|
61
|
+
kind: "key",
|
|
62
|
+
code,
|
|
63
|
+
down: dir === "down"
|
|
64
|
+
});
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case "pointer": {
|
|
68
|
+
const dx = num(rest[0]);
|
|
69
|
+
const dy = num(rest[1]);
|
|
70
|
+
if (dx === null || dy === null) return bad("pointer needs two numbers");
|
|
71
|
+
steps.push({
|
|
72
|
+
kind: "pointer",
|
|
73
|
+
dx,
|
|
74
|
+
dy
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case "step": {
|
|
79
|
+
const ms = num(rest[0]);
|
|
80
|
+
if (ms === null || ms < 0) return bad("step needs a duration in ms");
|
|
81
|
+
steps.push({
|
|
82
|
+
kind: "step",
|
|
83
|
+
ms
|
|
84
|
+
});
|
|
85
|
+
totalMs += ms;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
default: return bad("not a command");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
steps,
|
|
93
|
+
error: null,
|
|
94
|
+
totalMs
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/core/log-report.ts
|
|
99
|
+
const RANK = {
|
|
100
|
+
debug: 0,
|
|
101
|
+
info: 1,
|
|
102
|
+
warn: 2,
|
|
103
|
+
error: 3
|
|
104
|
+
};
|
|
105
|
+
/** Under this, with the loop running, is a frame rate somebody can feel. */
|
|
106
|
+
const SLOW_FPS = 50;
|
|
107
|
+
/** How many distinct messages to carry. Beyond this it is a log file, not a report. */
|
|
108
|
+
const MAX_GROUPS = 20;
|
|
109
|
+
/** The engine logs values, not strings — format them the way a console would. */
|
|
110
|
+
function format(parts) {
|
|
111
|
+
return parts.map((p) => {
|
|
112
|
+
if (typeof p === "string") return p;
|
|
113
|
+
if (p instanceof Error) return p.message;
|
|
114
|
+
try {
|
|
115
|
+
return JSON.stringify(p);
|
|
116
|
+
} catch {
|
|
117
|
+
return String(p);
|
|
118
|
+
}
|
|
119
|
+
}).join(" ");
|
|
120
|
+
}
|
|
121
|
+
function logReport(input) {
|
|
122
|
+
const counts = {
|
|
123
|
+
debug: 0,
|
|
124
|
+
info: 0,
|
|
125
|
+
warn: 0,
|
|
126
|
+
error: 0
|
|
127
|
+
};
|
|
128
|
+
const byMessage = /* @__PURE__ */ new Map();
|
|
129
|
+
for (const e of input.entries) {
|
|
130
|
+
counts[e.level] += 1;
|
|
131
|
+
const message = format(e.parts);
|
|
132
|
+
const key = `${e.level}\0${message}`;
|
|
133
|
+
const seen = byMessage.get(key);
|
|
134
|
+
if (seen) {
|
|
135
|
+
seen.count += 1;
|
|
136
|
+
seen.lastMs = Math.max(seen.lastMs, e.timeMs);
|
|
137
|
+
} else byMessage.set(key, {
|
|
138
|
+
level: e.level,
|
|
139
|
+
message,
|
|
140
|
+
count: 1,
|
|
141
|
+
lastMs: e.timeMs
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const grouped = [...byMessage.values()].sort((a, b) => RANK[b.level] - RANK[a.level] || b.lastMs - a.lastMs).slice(0, MAX_GROUPS);
|
|
145
|
+
const hidden = input.hidden === true;
|
|
146
|
+
const slow = !hidden && input.stats.running && input.stats.fps > 0 && input.stats.fps < SLOW_FPS;
|
|
147
|
+
return {
|
|
148
|
+
hidden,
|
|
149
|
+
ok: counts.error === 0 && input.stats.errors === 0 && input.assetErrors.length === 0,
|
|
150
|
+
slow,
|
|
151
|
+
counts,
|
|
152
|
+
grouped,
|
|
153
|
+
worst: grouped.find((g) => g.level === "error") ?? grouped[0] ?? null,
|
|
154
|
+
stats: input.stats,
|
|
155
|
+
assetErrors: input.assetErrors
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** The report as a person or an agent reads it: what is wrong, then the numbers. */
|
|
159
|
+
function logText(r) {
|
|
160
|
+
const lines = [];
|
|
161
|
+
if (r.stats.errors > 0) lines.push(`${r.stats.errors} error${r.stats.errors === 1 ? "" : "s"} were swallowed to keep the game alive — it is running, and something in it is broken`);
|
|
162
|
+
for (const a of r.assetErrors) lines.push(`asset ${a.ref} never loaded: ${a.error} (${a.url})`);
|
|
163
|
+
for (const g of r.grouped) {
|
|
164
|
+
if (g.level === "debug") continue;
|
|
165
|
+
lines.push(`[${g.level}] ${g.message}${g.count > 1 ? ` ×${g.count}` : ""}`);
|
|
166
|
+
}
|
|
167
|
+
if (lines.length === 0) lines.push("nothing wrong — no warnings, no errors, no failed assets");
|
|
168
|
+
if (!r.stats.running) lines.push(`not running — the loop is stopped (${r.stats.nodes} nodes in the scene)`);
|
|
169
|
+
else if (r.hidden) lines.push(`${r.stats.nodes} nodes · frame rate not measurable — the page is hidden (a window covered by another counts), and the browser throttles it. Bring it to the front`);
|
|
170
|
+
else lines.push(`${Math.round(r.stats.fps)} fps · ${r.stats.frameMs.toFixed(1)}ms per frame · ${r.stats.nodes} nodes${r.slow ? " — slow enough to feel" : ""}`);
|
|
171
|
+
return lines.join("\n");
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/core/rendering-options.ts
|
|
175
|
+
function resolveRendering(environment, fallback, devicePixelRatio, explicit) {
|
|
176
|
+
const rendering = environment?.rendering ?? {};
|
|
177
|
+
const scenePixelRatio = rendering.pixelRatio === "device" ? devicePixelRatio : rendering.pixelRatio;
|
|
178
|
+
return {
|
|
179
|
+
antialias: explicit?.antialias ?? rendering.antialias ?? fallback.antialias,
|
|
180
|
+
pixelRatio: explicit?.pixelRatio ?? scenePixelRatio ?? fallback.pixelRatio,
|
|
181
|
+
preserveDrawingBuffer: explicit?.preserveDrawingBuffer ?? rendering.preserveDrawingBuffer ?? fallback.preserveDrawingBuffer
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/core/webgl-unavailable.ts
|
|
186
|
+
/**
|
|
187
|
+
* Turn three's bare "Error creating WebGL context." into something a game can
|
|
188
|
+
* act on.
|
|
189
|
+
*
|
|
190
|
+
* A machine with no GPU acceleration, a locked-down or headless browser, a
|
|
191
|
+
* driver on the blocklist, or simply too many live contexts already: the call
|
|
192
|
+
* throws synchronously from inside `new WebGLRenderer`, and three's message
|
|
193
|
+
* says only that it failed. `createGame2D`/`createGame3D` did not catch it, and
|
|
194
|
+
* every shipped starter removes its `#loading` overlay on the line AFTER the
|
|
195
|
+
* await — so the player watched "100%" forever while the console held a
|
|
196
|
+
* sentence nobody was looking at.
|
|
197
|
+
*
|
|
198
|
+
* Wrapping it costs nothing when WebGL works and gives the failure a code, so a
|
|
199
|
+
* game can tell "this browser cannot run me" apart from "your scene is wrong"
|
|
200
|
+
* without matching on three's wording.
|
|
201
|
+
*/
|
|
202
|
+
function withWebGLContext(make) {
|
|
203
|
+
try {
|
|
204
|
+
return make();
|
|
205
|
+
} catch (cause) {
|
|
206
|
+
if (cause instanceof IncantoError) throw cause;
|
|
207
|
+
throw new IncantoError("WEBGL_UNAVAILABLE", `this browser would not give the canvas a WebGL context. Usually one of: hardware acceleration is off, the GPU or driver is blocklisted, the page is running in a headless or locked-down browser, or too many WebGL contexts are already open on this page. Tell the player — a game that cannot draw should say so rather than wait. (three: ${String(cause?.message ?? cause)})`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Can this document make a WebGL context at all?
|
|
212
|
+
*
|
|
213
|
+
* The question a game wants BEFORE it boots, so the answer can be a screen
|
|
214
|
+
* instead of an exception. Uses a throwaway canvas and never touches yours;
|
|
215
|
+
* `false` outside a browser, where the question is not meaningful.
|
|
216
|
+
*/
|
|
217
|
+
function isWebGLAvailable() {
|
|
218
|
+
const doc = globalThis.document;
|
|
219
|
+
if (!doc) return false;
|
|
220
|
+
try {
|
|
221
|
+
const probe = doc.createElement("canvas");
|
|
222
|
+
return Boolean(probe.getContext("webgl2") ?? probe.getContext("webgl"));
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//#endregion
|
|
228
|
+
export { logText as a, logReport as i, withWebGLContext as n, parseDrive as o, resolveRendering as r, isWebGLAvailable as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
1
|
+
import{n as e}from"./index-eVd0BToA.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};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as e,i as t,r as n,t as r}from"./index-eVd0BToA.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,n,r,i,a,o=180,s=120){let c=Math.max(o,n),l=Math.max(s,r);return{x:Math.min(Math.max(0,e),Math.max(0,i-c)),y:Math.min(Math.max(0,t),Math.max(0,a-l)),w:c,h:l}}function v(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 y(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 b(e,t){for(let[n,r]of Object.entries(t))e.style[n]=r}var x=`rgba(18, 20, 26, 0.92)`,S=`1px solid rgba(255,255,255,0.14)`,C=`12px ui-monospace, SFMono-Regular, Menlo, monospace`,w=class{host;el;body;onClose=()=>{};x;y;w;h;constructor(e,t,n,r){this.host=t,this.x=r.x,this.y=r.y,this.w=r.w,this.h=r.h,this.el=e.createElement(`div`),b(this.el,{position:`absolute`,background:x,border:S,borderRadius:`8px`,color:`rgba(255,255,255,0.88)`,font:C,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,b(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`,b(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`),b(this.body,{flex:`1`,overflow:`auto`,padding:`8px 10px`}),this.el.appendChild(this.body);let o=e.createElement(`div`);o.textContent=`◢`,b(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.getBoundingClientRect(),t=_(this.x,this.y,this.w,this.h,e.width,e.height);this.x=t.x,this.y=t.y,this.w=t.w,this.h=t.h,b(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)}},T=4,E=`#6ee7dc`,D=`rgba(18,20,26,0.94)`,O=`12px ui-monospace, Menlo, monospace`;function k(e){let{doc:t,container:r}=e,i=t.createElement(`div`);b(i,{position:`absolute`,inset:`0`,cursor:`crosshair`,zIndex:`80`,pointerEvents:`auto`,userSelect:`none`,touchAction:`none`});let a=t.createElement(`div`);b(a,{position:`absolute`,inset:`0`,background:`rgba(10,14,20,0.35)`,pointerEvents:`none`}),i.appendChild(a);let o=t.createElement(`div`);b(o,{position:`absolute`,outline:`1px solid ${E}`,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`);b(s,{position:`absolute`,padding:`2px 6px`,borderRadius:`4px`,background:D,color:E,font:O,pointerEvents:`none`,display:`none`,whiteSpace:`nowrap`}),i.appendChild(s);let c=t.createElement(`div`);c.textContent=`drag to select · Esc to cancel`,b(c,{position:`absolute`,top:`10px`,left:`50%`,transform:`translateX(-50%)`,padding:`4px 10px`,borderRadius:`6px`,background:D,color:`rgba(255,255,255,0.85)`,font:O,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},x=()=>({w:r.clientWidth||1,h:r.clientHeight||1});for(let e of l){let n=t.createElement(`div`),[r,i]=u[e];b(n,{position:`absolute`,left:`${r*100}%`,top:`${i*100}%`,width:`10px`,height:`10px`,marginLeft:`-5px`,marginTop:`-5px`,borderRadius:`2px`,background:E,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`);b(S,{position:`absolute`,display:`none`,gap:`6px`,padding:`6px`,borderRadius:`8px`,background:D,border:`1px solid rgba(255,255,255,0.18)`,font:O,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,b(i,{padding:`5px 10px`,borderRadius:`5px`,cursor:`pointer`,color:n?`#08121a`:`rgba(255,255,255,0.85)`,background:n?E:`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 k(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=k(e),_=t,t===`create`?f={x:v.x,y:v.y,w:0,h:0}:f&&(y=f),b(S,{display:`none`}),b(o,{cursor:t===`move`?`grabbing`:`crosshair`});let r=e.pointerId;r!==void 0&&n(i,r),j()}function j(){if(!f){b(o,{display:`none`}),b(s,{display:`none`}),b(a,{display:`block`});return}b(a,{display:`none`}),b(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;b(s,{display:`block`,left:`${Math.max(2,f.x)}px`,top:`${n>=2?n:f.y+4}px`})}function M(){if(!f||f.w<T||f.h<T)return;b(S,{display:`flex`});let e=x(),t=S.offsetWidth||200,n=S.offsetHeight||36,r=g(f,t,n,e.w,e.h);b(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=k(e),n=x();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<T||f.h<T)&&(f=null),_=`idle`,b(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 A=96,j=200,M=8192;function N(e){return Array.isArray(e)?`Array(${e.length})`:`Object(${Object.keys(e).length} keys)`}function P(e,t){if(Array.isArray(e)&&e.some(e=>typeof e==`object`&&!!e)){let t=e.slice(0,j).map(e=>JSON.stringify(e)),n=e.length-j;return t.join(`
|
|
2
|
+
`)+(n>0?`\n… ${n} more`:``)}return t.length>M?`${t.slice(0,M)} … (${t.length-M} more chars)`:t}function F(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var I=2,L=4;function R(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 V(e,r,n,t.statsSource,t.actions,t.frameSource)}var z=300,B=[`log`,`info`,`warn`,`error`,`debug`],V=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`,b(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(W).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 w(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 B){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(W).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)<L||(t||(t=!0,this.closeDropdown(),b(this.menuButton,{cursor:`grabbing`})),this.moveMenuButton(e.bx+i,e.by+a))});let n=()=>{if(!e)return;let n=t;e=null,t=!1,b(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=_(e,t,n.offsetWidth??0,n.offsetHeight??0,this.container.clientWidth||0,this.container.clientHeight||0,0,0);this.menuPos={x:r.x,y:r.y},b(this.menuButton,{left:`${r.x}px`,top:`${r.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`);b(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),b(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,b(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=v({x:this.menuPos.x,y:this.menuPos.y,w:n.offsetWidth??0,h:n.offsetHeight??26},t.offsetWidth??0,t.offsetHeight??0,this.container.clientWidth||0,this.container.clientHeight||0);b(e,{left:`${r.x}px`,top:`${r.y}px`}),this.dismissDropdown=y(this.doc,[e,this.menuButton],()=>this.closeDropdown())}openStatsChip(){if(this.statsChip)return;let e=this.doc.createElement(`div`);b(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 ${U(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;H(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`);b(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?`▸`:`▾`:`·`,b(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,b(c,{whiteSpace:`nowrap`}),o.appendChild(c);let l=this.doc.createElement(`span`);if(l.textContent=` ${n.typeName}`,b(l,{opacity:`0.45`,whiteSpace:`nowrap`,fontSize:`10px`}),o.appendChild(l),i&&a){let t=this.doc.createElement(`span`);t.textContent=` (${e.children.length})`,b(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`);b(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 e=this.panels.get(`inspector`);if(!e)return;let n=e.body.scrollTop;H(e.body);let r=this.selected;if(r&&r.tree===null&&(this.selected=null,this.engine.debugSelection=null,this.applyColliderScope(),r=null),!r){let t=this.doc.createElement(`div`);t.textContent=`select a node in the Explorer`,b(t,{opacity:`0.6`}),e.body.appendChild(t);return}let i=r.constructor,a=this.doc.createElement(`div`);if(a.textContent=`${r.getPath()} · ${i.typeName}${r.uid?` · ${r.uid}`:``}`,b(a,{fontWeight:`700`,marginBottom:`6px`,whiteSpace:`pre-wrap`}),e.body.appendChild(a),r.groups.size>0){let t=this.doc.createElement(`div`);t.textContent=`groups: ${[...r.groups].join(`, `)}`,b(t,{opacity:`0.7`,marginBottom:`6px`}),e.body.appendChild(t)}let o=t(i),s=r;for(let t of Object.keys(o)){let n=o[t];this.renderValueRow(e.body,r,t,{read:()=>s[t],write:e=>{s[t]=e},options:n?.options,variants:n?.variants})}e.body.scrollTop=n}renderValueRow(t,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`);b(c,{display:`flex`,gap:`6px`,alignItems:`center`,margin:`2px 0`});let l=this.doc.createElement(`div`);l.textContent=r,b(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),b(i,K(`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}),b(e,K(`110px`)),c.appendChild(e)}else if(typeof a==`string`){let e=this.doc.createElement(`input`);e.type=`text`,e.value=a,this.trackEditing(e),b(e,K(`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(F(a)){let o=this.doc.createElement(`div`);b(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 t of l){let r=t===s;this.renderValueRow(o,n,t,{path:`${u}.${t}`,read:()=>i.read()[t]??(r?``:null),write:n=>{if(r&&i.variants){let t=i.variants.byTag[String(n)];if(t!==void 0){i.write(e(t));return}}i.write({...i.read(),[t]:n})},options:r&&i.variants?Object.keys(i.variants.byTag):void 0})}t.appendChild(c),t.appendChild(o);return}else{let o=JSON.stringify(e(a));if(o.length<=A){let e=this.doc.createElement(`div`);e.textContent=o,b(e,{opacity:`0.65`,whiteSpace:`pre-wrap`,wordBreak:`break-all`}),c.appendChild(e)}else{let e=i.path??r,s=this.detailOpen.get(n)?.has(e)??!1,l=this.doc.createElement(`div`);if(l.textContent=`${s?`▾`:`▸`} ${N(a)}`,b(l,{opacity:`0.75`,cursor:`pointer`,userSelect:`none`}),l.addEventListener(`click`,()=>{let t=this.detailOpen.get(n);t||(t=new Set,this.detailOpen.set(n,t)),s?t.delete(e):t.add(e),this.renderInspector()}),c.appendChild(l),t.appendChild(c),s){let e=this.doc.createElement(`div`);e.textContent=P(a,o),b(e,{opacity:`0.6`,whiteSpace:`pre-wrap`,wordBreak:`break-all`,marginLeft:`10px`,paddingLeft:`8px`,borderLeft:`1px solid rgba(255,255,255,0.14)`}),t.appendChild(e)}return}}t.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>z&&this.logRows.splice(0,this.logRows.length-z),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(()=>{}),k({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,b(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,I)),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;H(e.body),this.timeEls=null;let t=this.doc.createElement(`div`);b(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(I),n.step=`0.05`,n.value=String(Math.min(this.engine.timeScale,I)),b(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`);b(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),b(i,K(`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}×`,b(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`);b(a,{display:`flex`,gap:`8px`});let o=this.doc.createElement(`div`);b(o,G()),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`,b(s,G()),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,I)),e.box.value=String(Math.round(t*1e3)/1e3)}renderLogs(){let e=this.panels.get(`logs`);if(!e)return;H(e.body);let t=this.doc.createElement(`div`);b(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}`,b(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`,b(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}`,b(n,{color:r[t.level],whiteSpace:`pre-wrap`}),e.body.appendChild(n)}}};function H(e){for(let t of[...e.children])t.remove()}function U(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function W(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 G(){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 K(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{R as attachDebugOverlay};
|