@umicat/phaser-sdk 1.0.13 → 1.0.15
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.
|
@@ -109,6 +109,20 @@ export function preloadSceneAssets(scene, sceneFile, manifest) {
|
|
|
109
109
|
queueAssetLoad(scene, asset);
|
|
110
110
|
state.requestedAssetIds.add(id);
|
|
111
111
|
}
|
|
112
|
+
// Audio assets are GLOBAL — BGM / SFX are played from code (`sound.play(key)`),
|
|
113
|
+
// not attached to a scene entity — so the entity walk above never collects
|
|
114
|
+
// them and they'd never load. Eagerly load every audio asset in the manifest
|
|
115
|
+
// so `cache.audio.has(key)` is true and the game can play it with no manual
|
|
116
|
+
// BootScene preload. (Without this, registering BGM in the manifest silently
|
|
117
|
+
// produced no sound — the asset existed but was never queued.)
|
|
118
|
+
for (const asset of manifest.assets ?? []) {
|
|
119
|
+
if (asset.kind !== 'audio')
|
|
120
|
+
continue;
|
|
121
|
+
if (state.requestedAssetIds.has(asset.id))
|
|
122
|
+
continue;
|
|
123
|
+
queueAssetLoad(scene, asset);
|
|
124
|
+
state.requestedAssetIds.add(asset.id);
|
|
125
|
+
}
|
|
112
126
|
}
|
|
113
127
|
function collectAssetIds(entities, manifest, resolveTilemapFile) {
|
|
114
128
|
const ids = new Set();
|
|
@@ -345,10 +359,15 @@ function queueAssetLoad(scene, asset) {
|
|
|
345
359
|
}
|
|
346
360
|
return;
|
|
347
361
|
case 'audio':
|
|
348
|
-
|
|
362
|
+
// Fall back to `id` when `textureKey` is absent. Audio (and json) entries
|
|
363
|
+
// are naturally written as `{ id, path, kind:'audio' }` — "textureKey" is
|
|
364
|
+
// a misnomer for a sound — so an agent/human routinely omits it. Without
|
|
365
|
+
// the fallback the clip loads under key `undefined` and `sound.play(id)`
|
|
366
|
+
// silently no-ops (the "generated BGM never plays" bug).
|
|
367
|
+
scene.load.audio(asset.textureKey || asset.id, asset.path);
|
|
349
368
|
return;
|
|
350
369
|
case 'json':
|
|
351
|
-
scene.load.json(asset.textureKey, asset.path);
|
|
370
|
+
scene.load.json(asset.textureKey || asset.id, asset.path);
|
|
352
371
|
return;
|
|
353
372
|
default: {
|
|
354
373
|
const exhaustive = asset.kind;
|
|
@@ -16,8 +16,52 @@ export function setupScreenshotListener(game) {
|
|
|
16
16
|
console.error('[UmicatSDK] Screenshot failed:', e);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
else if (event.data?.type === 'screenshotRegion') {
|
|
20
|
+
// Marquee-to-chat: the host drew a selection rect over the iframe (in
|
|
21
|
+
// iframe-relative CSS px); crop the canvas to it here, where the canvas's
|
|
22
|
+
// on-screen position + intrinsic resolution are known (handles letterbox
|
|
23
|
+
// bars + display scaling). Responds with the cropped PNG.
|
|
24
|
+
try {
|
|
25
|
+
const r = event.data.rect;
|
|
26
|
+
const dataUrl = cropCanvasRegion(game, r);
|
|
27
|
+
window.parent.postMessage({ type: 'screenshot_region_result', dataUrl, requestId: event.data.requestId }, '*');
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.error('[UmicatSDK] Region screenshot failed:', e);
|
|
31
|
+
window.parent.postMessage({ type: 'screenshot_region_result', dataUrl: null, requestId: event.data?.requestId }, '*');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
19
34
|
});
|
|
20
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Crop the game canvas to a rect given in iframe-relative CSS pixels (the host's
|
|
38
|
+
* marquee). Maps display px → intrinsic canvas px via the canvas's bounding rect
|
|
39
|
+
* + resolution (uniform scale — Phaser FIT preserves aspect), clamps to bounds.
|
|
40
|
+
*/
|
|
41
|
+
function cropCanvasRegion(game, rect) {
|
|
42
|
+
const canvas = game.canvas;
|
|
43
|
+
const cr = canvas.getBoundingClientRect();
|
|
44
|
+
if (cr.width <= 0 || cr.height <= 0)
|
|
45
|
+
return null;
|
|
46
|
+
const scale = canvas.width / cr.width; // intrinsic px per displayed px
|
|
47
|
+
let sx = Math.round((rect.x - cr.x) * scale);
|
|
48
|
+
let sy = Math.round((rect.y - cr.y) * scale);
|
|
49
|
+
let sw = Math.round(rect.width * scale);
|
|
50
|
+
let sh = Math.round(rect.height * scale);
|
|
51
|
+
// Clamp to the canvas (the marquee can run past the letterboxed edges).
|
|
52
|
+
sx = Math.max(0, Math.min(sx, canvas.width - 1));
|
|
53
|
+
sy = Math.max(0, Math.min(sy, canvas.height - 1));
|
|
54
|
+
sw = Math.max(1, Math.min(sw, canvas.width - sx));
|
|
55
|
+
sh = Math.max(1, Math.min(sh, canvas.height - sy));
|
|
56
|
+
const out = document.createElement('canvas');
|
|
57
|
+
out.width = sw;
|
|
58
|
+
out.height = sh;
|
|
59
|
+
const ctx = out.getContext('2d');
|
|
60
|
+
if (!ctx)
|
|
61
|
+
return null;
|
|
62
|
+
ctx.drawImage(canvas, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
63
|
+
return out.toDataURL('image/png');
|
|
64
|
+
}
|
|
21
65
|
/**
|
|
22
66
|
* Take a screenshot programmatically (e.g., from within a scene).
|
|
23
67
|
* Returns a base64 data URL of the current canvas.
|