dsh-wallpaper_share 26.8.22-T
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/LICENSE +674 -0
- package/README.md +114 -0
- package/README.zh-CN.md +251 -0
- package/cordis.patch.yml +6 -0
- package/lib/client.js +2283 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +3466 -0
- package/package.json +58 -0
- package/tools/scene-renderer/README.md +68 -0
- package/tools/scene-renderer/scene-renderer.mjs +268 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","samplePuppet"],"sources":["../src/client/WallpaperSharePanel.tsx","../src/client/panelStyle.ts","../src/client/SceneCanvas.ts","../src/scene/ScenePuppet.ts","../src/client/ParticleRuntime.ts","../src/client/WaterwavesGL.ts","../src/client/SceneModelRenderer.ts","../src/client/index.ts"],"sourcesContent":["/**\r\n * wallpaper_share 会话视图标签页:当前壁纸信息、同步开关、显示器选择、\r\n * 专注模式、渲染模式,以及透明度 / 模糊 / 阴影三个滑块(即时生效)。\r\n * 样式类名由 PANEL_CSS 在 apply 阶段注入,不依赖 CSS Modules。\r\n */\r\nimport { useEffect, useState } from 'react'\r\nimport { store, type WeSyncInfo, FOCUS_WORK, FOCUS_IDLE } from './index'\r\n\r\nexport function WallpaperSharePanel() {\r\n const [, force] = useState(0)\r\n const [info, setInfo] = useState<WeSyncInfo | null>(store.info)\r\n const [enabled, setEnabled] = useState(store.settings.enabled)\r\n const [alpha, setAlpha] = useState(store.settings.panelAlpha)\r\n const [blur, setBlur] = useState(store.settings.blur)\r\n const [shadow, setShadow] = useState(store.settings.shadow)\r\n const [status, setStatus] = useState('')\r\n const [monitor, setMonitor] = useState(store.settings.monitor)\r\n const [focus, setFocus] = useState(store.settings.focus)\r\n const [renderMode, setRenderMode] = useState(store.settings.renderMode)\r\n const [immersive, setImmersive] = useState(store.settings.immersive)\r\n\r\n useEffect(() => store.subscribe(() => {\r\n setInfo(store.info)\r\n force((x) => x + 1)\r\n }), [])\r\n\r\n const flash = (text: string): void => {\r\n setStatus(text)\r\n window.setTimeout(() => setStatus(''), 3500)\r\n }\r\n\r\n const onAlpha = (v: number): void => {\r\n store.settings.panelAlpha = v\r\n setAlpha(v)\r\n store.actions.applyTheme()\r\n }\r\n\r\n const onBlur = (v: number): void => {\r\n store.settings.blur = v\r\n setBlur(v)\r\n store.actions.applyBackground()\r\n }\r\n\r\n const onShadow = (v: number): void => {\r\n store.settings.shadow = v\r\n setShadow(v)\r\n store.actions.applyBackground()\r\n }\r\n\r\n const onPower = (): void => {\r\n const next = !store.settings.enabled\r\n store.settings.enabled = next\r\n setEnabled(next)\r\n store.actions.applyBackground()\r\n flash(next ? '已开启壁纸同步' : '已关闭壁纸同步')\r\n }\r\n\r\n const onMonitor = (v: string): void => {\r\n store.settings.monitor = v\r\n setMonitor(v)\r\n store.actions.repoll()\r\n }\r\n\r\n const onFocus = (): void => {\r\n const next = !store.settings.focus\r\n store.settings.focus = next\r\n setFocus(next)\r\n store.actions.applyTheme()\r\n store.actions.applyBackground()\r\n flash(next ? '专注模式已开启:任务中 30%/15px/90%,空闲 9%/6px/40%' : '专注模式已关闭,恢复手动滑块')\r\n }\r\n\r\n const onImmersive = (): void => {\r\n const next = !store.settings.immersive\r\n store.settings.immersive = next\r\n setImmersive(next)\r\n store.actions.applyImmersive()\r\n store.notify()\r\n flash(next ? '沉浸模式已开启:对话上边栏/输入框已隐藏,壁纸可交互(Esc 或右上角按钮退出)' : '已退出沉浸模式')\r\n }\r\n\r\n const onRenderMode = (): void => {\r\n const next: 'preview' | 'source' = store.settings.renderMode === 'source' ? 'preview' : 'source'\r\n store.settings.renderMode = next\r\n setRenderMode(next)\r\n store.actions.applyBackground()\r\n if (next === 'source') {\r\n const kind = store.info !== null ? store.info.source.kind : ''\r\n if (kind === 'video') flash('增强模式:播放壁纸源视频')\r\n else if (kind === 'web') flash('增强模式:加载 Web 壁纸页面')\r\n else if (kind === 'scene') flash(store.info?.scene?.live === true\r\n ? '增强模式:Scene 实时渲染中'\r\n : '增强模式:Scene(renderer 未出帧,回退纹理/预览)')\r\n else flash('当前壁纸(' + (kind === '' ? '无' : kind) + ')仅支持预览,增强模式自动回退')\r\n } else {\r\n flash('性能模式:使用静态预览图')\r\n }\r\n }\r\n\r\n const wallpaper = info !== null && info.wallpaper !== null ? info.wallpaper : null\r\n const title = wallpaper === null\r\n ? (info !== null && info.kind === 'web' ? '当前为网页壁纸(无本地预览)' : 'Wallpaper Engine 尚未应用壁纸')\r\n : wallpaper.title\r\n const subtitle = wallpaper === null\r\n ? '在 Wallpaper Engine 中应用壁纸后,此处会同步显示'\r\n : wallpaper.type + (info !== null && info.kind === 'image' ? ' · 已同步静态预览' : ' · 无静态预览图') + (info !== null && info.monitor !== '' ? ' · 显示器 ' + info.monitor : '') + (info !== null && info.kind === 'scene' && info.scene !== null ? ' · Scene[' + (info.scene.mode ?? 'browser') + '] ' + (info.scene.live ? 'live ' + String(info.scene.status?.fps ?? '?') + 'fps' : (info.scene.model === true ? 'model 渲染' : 'fallback:' + info.scene.fallback)) : '')\r\n\r\n const monitors = info !== null && Array.isArray(info.monitors) && info.monitors.length > 1 ? info.monitors : null\r\n const focusVisuals = focus ? (store.settings.taskActive ? FOCUS_WORK : FOCUS_IDLE) : null\r\n\r\n return (\r\n <div className=\"wesync-panel\">\r\n <div className=\"wesync-card\">\r\n <div className=\"wesync-title\">{title}</div>\r\n <div className=\"wesync-sub\">{subtitle}</div>\r\n {monitors !== null\r\n ? (\r\n <div className=\"wesync-row\">\r\n <label>背景显示器</label>\r\n <select\r\n className=\"wesync-select\"\r\n value={monitor}\r\n onChange={(e) => onMonitor(e.target.value)}\r\n >\r\n <option value=\"\">自动 · 跟随最新变化</option>\r\n {monitors.map((m) => (\r\n <option key={m.key} value={m.key}>{m.key + ' · ' + m.title}</option>\r\n ))}\r\n </select>\r\n <output>{monitor === '' ? 'auto' : monitor}</output>\r\n </div>\r\n )\r\n : null}\r\n <div className=\"wesync-actions\">\r\n <button className=\"wesync-btn\" onClick={onPower}>\r\n {enabled ? '⏻ 同步开启' : '⏻ 同步关闭'}\r\n </button>\r\n </div>\r\n {status !== '' ? <div className=\"wesync-status\">{status}</div> : null}\r\n </div>\r\n <div className=\"wesync-card\">\r\n <div className=\"wesync-sub\">视觉效果 · 即时生效</div>\r\n <div className=\"wesync-actions\">\r\n <button className={['wesync-btn', focus ? 'wesync-focusOn' : 'wesync-focusOff'].join(' ')} onClick={onFocus}>\r\n {focus\r\n ? (store.settings.taskActive ? '专注模式 · 任务进行中' : '专注模式 · 已完成')\r\n : '开启专注模式'}\r\n </button>\r\n <button className={['wesync-btn', renderMode === 'source' ? 'wesync-sourceOn' : 'wesync-sourceOff'].join(' ')} onClick={onRenderMode}>\r\n {renderMode === 'source' ? '渲染:增强(源文件)' : '渲染:性能(预览)'}\r\n </button>\r\n <button className={['wesync-btn', immersive ? 'wesync-focusOn' : 'wesync-focusOff'].join(' ')} onClick={onImmersive}>\r\n {immersive ? '沉浸模式 · 已开启' : '开启沉浸模式'}\r\n </button>\r\n </div>\r\n <Slider label=\"面板透明度\" min={0} max={100} value={focusVisuals !== null ? focusVisuals.panelAlpha : alpha} unit=\"%\" disabled={focusVisuals !== null} onChange={onAlpha} />\r\n <Slider label=\"背景模糊\" min={0} max={30} value={focusVisuals !== null ? focusVisuals.blur : blur} unit=\"px\" disabled={focusVisuals !== null} onChange={onBlur} />\r\n <Slider label=\"阴影深度\" min={0} max={100} value={focusVisuals !== null ? focusVisuals.shadow : shadow} unit=\"%\" disabled={focusVisuals !== null} onChange={onShadow} />\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nfunction Slider(props: {\r\n label: string\r\n min: number\r\n max: number\r\n value: number\r\n unit: string\r\n disabled?: boolean\r\n onChange: (v: number) => void\r\n}) {\r\n return (\r\n <div className=\"wesync-row\" style={props.disabled === true ? { opacity: 0.45 } : undefined}>\r\n <label>{props.label}</label>\r\n <input\r\n type=\"range\"\r\n min={props.min}\r\n max={props.max}\r\n step={1}\r\n value={props.value}\r\n disabled={props.disabled}\r\n onChange={(e) => props.onChange(Number(e.target.value))}\r\n />\r\n <output>{String(props.value) + props.unit}</output>\r\n </div>\r\n )\r\n}\r\n","/**\r\n * 面板样式(独立构建不再依赖 CSS Modules,运行时注入 <style>)。\r\n */\r\nexport const PANEL_CSS = `\r\n.wesync-panel {\r\n padding: 24px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n max-width: 660px;\r\n box-sizing: border-box;\r\n}\r\n\r\n.wesync-card {\r\n padding: 16px 18px;\r\n border-radius: 12px;\r\n background: var(--dsw-alias-bg-layer-1);\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n}\r\n\r\n.wesync-title {\r\n font-size: 15px;\r\n font-weight: 600;\r\n color: var(--dsw-alias-label-primary);\r\n margin: 0 0 4px 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.wesync-sub {\r\n font-size: 12px;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.wesync-status {\r\n font-size: 12px;\r\n color: var(--dsw-alias-label-secondary);\r\n margin-top: 10px;\r\n}\r\n\r\n.wesync-actions {\r\n display: flex;\r\n gap: 8px;\r\n margin-top: 12px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.wesync-btn {\r\n padding: 6px 14px;\r\n border-radius: 999px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n background: var(--dsw-alias-bg-layer-2);\r\n color: var(--dsw-alias-label-primary);\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n}\r\n\r\n.wesync-btn:hover:not(:disabled) {\r\n background: var(--dsw-alias-bg-overlay);\r\n}\r\n\r\n.wesync-btn:disabled {\r\n opacity: 0.5;\r\n cursor: default;\r\n}\r\n\r\n.wesync-focusOff {\r\n background: rgba(139, 92, 246, 0.18);\r\n border-color: rgba(139, 92, 246, 0.55);\r\n color: #c4b5fd;\r\n}\r\n\r\n.wesync-focusOff:hover:not(:disabled) {\r\n background: rgba(139, 92, 246, 0.32);\r\n}\r\n\r\n.wesync-focusOn {\r\n background: rgba(46, 160, 67, 0.20);\r\n border-color: rgba(46, 160, 67, 0.55);\r\n color: #7ee2a8;\r\n}\r\n\r\n.wesync-focusOn:hover:not(:disabled) {\r\n background: rgba(46, 160, 67, 0.32);\r\n}\r\n\r\n.wesync-sourceOff {\r\n background: rgba(249, 115, 22, 0.15);\r\n border-color: rgba(249, 115, 22, 0.5);\r\n color: #fdba74;\r\n}\r\n\r\n.wesync-sourceOff:hover:not(:disabled) {\r\n background: rgba(249, 115, 22, 0.28);\r\n}\r\n\r\n.wesync-sourceOn {\r\n background: rgba(46, 160, 67, 0.20);\r\n border-color: rgba(46, 160, 67, 0.55);\r\n color: #7ee2a8;\r\n}\r\n\r\n.wesync-sourceOn:hover:not(:disabled) {\r\n background: rgba(46, 160, 67, 0.32);\r\n}\r\n\r\n.wesync-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n margin-top: 12px;\r\n}\r\n\r\n.wesync-row label {\r\n flex: 0 0 92px;\r\n font-size: 12px;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.wesync-row input[type='range'] {\r\n flex: 1;\r\n accent-color: var(--dsw-alias-brand-primary);\r\n height: 20px;\r\n}\r\n\r\n.wesync-select {\r\n flex: 1;\r\n padding: 4px 8px;\r\n border-radius: 8px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n background: var(--dsw-alias-bg-layer-2);\r\n color: var(--dsw-alias-label-primary);\r\n font-size: 12px;\r\n font-family: inherit;\r\n}\r\n\r\n.wesync-row output {\r\n flex: 0 0 44px;\r\n text-align: right;\r\n font-size: 12px;\r\n color: var(--dsw-alias-label-secondary);\r\n font-variant-numeric: tabular-nums;\r\n}\r\n`\r\n","/**\r\n * SceneCanvas —— 浏览器半的 scene 动态背景层。\r\n *\r\n * 通过 WebSocket(/we-sync/scene/stream)接收 Node 中继的编码帧,\r\n * 解码为 ImageBitmap 后按 requestAnimationFrame 画到 <canvas>,覆盖铺满。\r\n *\r\n * 职责:canvas resize / devicePixelRatio / 帧解码 / rAF 调度 / 可见性暂停 /\r\n * 自动重连 / 模糊与缩放(模糊 opacity 仍在 CSS 层,不进 renderer)。\r\n */\r\nimport { WS_HEADER_BYTES } from '../scene/SceneProtocol.ts'\r\n\r\nexport interface SceneCanvasHandlers {\r\n /** 首帧到达 → true;连接彻底失败(重试耗尽)→ false,由调用方回退纹理 */\r\n onLiveChange?: (live: boolean) => void\r\n}\r\n\r\nconst MAX_RECONNECT = 5\r\nconst RECONNECT_DELAY_MS = 1000\r\n\r\nexport class SceneCanvas {\r\n private el: HTMLCanvasElement | null = null\r\n private ctx: CanvasRenderingContext2D | null = null\r\n private ws: WebSocket | null = null\r\n private rafId = 0\r\n private needDraw = false\r\n private latest: ImageBitmap | null = null\r\n private dpr = 1\r\n private live = false\r\n private closed = false\r\n private retries = 0\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\r\n private blurPx = 0\r\n private scale = 1\r\n private handlers: SceneCanvasHandlers\r\n\r\n constructor(handlers: SceneCanvasHandlers = {}) {\r\n this.handlers = handlers\r\n }\r\n\r\n get isLive(): boolean {\r\n return this.live\r\n }\r\n\r\n start(monitor: string, version: number): void {\r\n this.stop()\r\n this.closed = false\r\n this.retries = 0\r\n\r\n this.el = document.createElement('canvas')\r\n this.el.style.position = 'fixed'\r\n this.el.style.top = '0'\r\n this.el.style.left = '0'\r\n this.el.style.width = '100%'\r\n this.el.style.height = '100%'\r\n this.el.style.zIndex = '-2'\r\n this.el.style.pointerEvents = 'none'\r\n this.el.style.border = '0'\r\n document.body.appendChild(this.el)\r\n this.ctx = this.el.getContext('2d')\r\n this.resize()\r\n this.applyVisuals()\r\n\r\n window.addEventListener('resize', this.onResize)\r\n document.addEventListener('visibilitychange', this.onVisibility)\r\n\r\n const proto = location.protocol === 'https:' ? 'wss:' : 'ws:'\r\n const query = (monitor !== '' ? 'monitor=' + encodeURIComponent(monitor) : '') +\r\n (monitor !== '' ? '&v=' : 'v=') + encodeURIComponent(String(version))\r\n this.connect(proto + '//' + location.host + '/we-sync/scene/stream?' + query)\r\n }\r\n\r\n stop(): void {\r\n this.closed = true\r\n this.setLive(false)\r\n if (this.reconnectTimer !== null) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null }\r\n if (this.rafId !== 0) { cancelAnimationFrame(this.rafId); this.rafId = 0 }\r\n if (this.ws !== null) {\r\n try { this.ws.onclose = null; this.ws.onerror = null; this.ws.onmessage = null; this.ws.close() } catch { /* 忽略 */ }\r\n this.ws = null\r\n }\r\n if (this.latest !== null) { try { this.latest.close() } catch { /* 忽略 */ } this.latest = null }\r\n window.removeEventListener('resize', this.onResize)\r\n document.removeEventListener('visibilitychange', this.onVisibility)\r\n if (this.el !== null) { this.el.remove(); this.el = null; this.ctx = null }\r\n }\r\n\r\n applyVisuals(blurPx?: number, scale?: number): void {\r\n if (blurPx !== undefined) this.blurPx = blurPx\r\n if (scale !== undefined) this.scale = scale\r\n if (this.el !== null) {\r\n this.el.style.filter = 'blur(' + Math.round(this.blurPx) + 'px)'\r\n this.el.style.transform = 'scale(' + this.scale.toFixed(3) + ')'\r\n }\r\n }\r\n\r\n private connect(url: string): void {\r\n if (this.closed) return\r\n let ws: WebSocket\r\n try { ws = new WebSocket(url) } catch { this.fail(); return }\r\n ws.binaryType = 'arraybuffer'\r\n this.ws = ws\r\n ws.onopen = () => { this.retries = 0 }\r\n ws.onmessage = (ev) => this.onMessage(ev)\r\n ws.onerror = () => { /* 交给 onclose 处理 */ }\r\n ws.onclose = () => {\r\n if (this.closed) return\r\n this.ws = null\r\n if (this.retries < MAX_RECONNECT) {\r\n this.retries += 1\r\n this.reconnectTimer = setTimeout(() => this.connect(url), RECONNECT_DELAY_MS)\r\n } else {\r\n this.fail()\r\n }\r\n }\r\n }\r\n\r\n private fail(): void {\r\n this.setLive(false)\r\n this.closed = true\r\n // 通知调用方回退(texture/preview)\r\n // 注意:不在此处自毁,交给调用方 stop()\r\n }\r\n\r\n private onMessage(ev: MessageEvent): void {\r\n if (this.closed) return\r\n const buf = ev.data as ArrayBuffer\r\n if (!(buf instanceof ArrayBuffer)) return\r\n const view = new DataView(buf)\r\n if (buf.byteLength < WS_HEADER_BYTES) return\r\n const format = view.getUint8(0)\r\n const w = view.getUint32(1, true)\r\n const h = view.getUint32(5, true)\r\n if (w < 1 || h < 1 || w > 16384 || h > 16384) return\r\n const payload = new Uint8Array(buf, WS_HEADER_BYTES)\r\n this.decode(format, w, h, payload)\r\n }\r\n\r\n private decode(format: number, w: number, h: number, payload: Uint8Array): void {\r\n let promise: Promise<ImageBitmap>\r\n if (format === 0) {\r\n promise = createImageBitmap(new Blob([payload as BlobPart], { type: 'image/jpeg' }))\r\n } else if (format === 1) {\r\n promise = createImageBitmap(new Blob([payload as BlobPart], { type: 'image/webp' }))\r\n } else if (format === 2 || format === 3) {\r\n let px = new Uint8ClampedArray(payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength))\r\n if (format === 3) {\r\n px = this.bgraToRgba(payload)\r\n }\r\n promise = createImageBitmap(new ImageData(px, w, h))\r\n } else {\r\n return\r\n }\r\n void promise.then((bmp) => {\r\n if (this.closed) { bmp.close(); return }\r\n if (this.latest !== null) { try { this.latest.close() } catch { /* 忽略 */ } }\r\n this.latest = bmp\r\n this.retries = 0\r\n this.setLive(true)\r\n this.scheduleDraw()\r\n }).catch(() => { /* 解码失败,跳过该帧 */ })\r\n }\r\n\r\n private bgraToRgba(payload: Uint8Array): Uint8ClampedArray {\r\n const out = new Uint8ClampedArray(payload.length)\r\n for (let i = 0; i < payload.length; i += 4) {\r\n out[i] = payload[i + 2]\r\n out[i + 1] = payload[i + 1]\r\n out[i + 2] = payload[i]\r\n out[i + 3] = payload[i + 3]\r\n }\r\n return out\r\n }\r\n\r\n private scheduleDraw(): void {\r\n this.needDraw = true\r\n if (this.rafId === 0 && !document.hidden) this.rafId = requestAnimationFrame(this.draw)\r\n }\r\n\r\n private draw = (): void => {\r\n this.rafId = 0\r\n if (this.closed || this.ctx === null || this.el === null) return\r\n if (this.needDraw && this.latest !== null) {\r\n this.needDraw = false\r\n this.drawCover(this.ctx, this.latest, this.el.width, this.el.height)\r\n }\r\n }\r\n\r\n /** 以 cover 方式绘制(等比裁切铺满),与 background-size: cover 对齐 */\r\n private drawCover(ctx: CanvasRenderingContext2D, bmp: ImageBitmap, cw: number, ch: number): void {\r\n const iw = bmp.width\r\n const ih = bmp.height\r\n if (iw === 0 || ih === 0) return\r\n const scale = Math.max(cw / iw, ch / ih)\r\n const sw = cw / scale\r\n const sh = ch / scale\r\n const sx = (iw - sw) / 2\r\n const sy = (ih - sh) / 2\r\n ctx.drawImage(bmp, sx, sy, sw, sh, 0, 0, cw, ch)\r\n }\r\n\r\n private resize(): void {\r\n if (this.el === null) return\r\n this.dpr = window.devicePixelRatio || 1\r\n const w = Math.max(1, Math.round(this.el.clientWidth * this.dpr))\r\n const h = Math.max(1, Math.round(this.el.clientHeight * this.dpr))\r\n if (this.el.width !== w) this.el.width = w\r\n if (this.el.height !== h) this.el.height = h\r\n }\r\n\r\n private onResize = (): void => {\r\n this.resize()\r\n this.scheduleDraw()\r\n }\r\n\r\n private onVisibility = (): void => {\r\n if (document.hidden) {\r\n // 暂停绘制(冻结最后一帧),WS 保持连接\r\n if (this.rafId !== 0) { cancelAnimationFrame(this.rafId); this.rafId = 0 }\r\n } else {\r\n this.scheduleDraw()\r\n }\r\n }\r\n\r\n private setLive(live: boolean): void {\r\n if (this.live === live) return\r\n this.live = live\r\n if (this.handlers.onLiveChange !== undefined) this.handlers.onLiveChange(live)\r\n }\r\n}\r\n","/**\r\n * ScenePuppet —— WE _puppet.mdl 解析器(顶点网格 + 骨骼矩阵 + 动画)。\r\n *\r\n * 格式(经 3463520581 实测 + linux-wallpaperengine 参考交叉验证):\r\n * MDLV0023: 魔数后 json(材质)\\0 + 变长填充 + 网格块:\r\n * [4B ?][4B vertexBytes][顶点 80B×N][4B indexBytes][uint16 索引]\r\n * 顶点 80B = [pos3 f32 @0][44B 其他][weights4 f32 @56][uv2 f32 @72]\r\n * (vertexBytes % 80、indexBytes % 6;网格块用扫描定位,边界=MDLS)\r\n * MDLS0004: \"MDLS0004\\0\" + u32@9 + u32@13 boneCount + u8@17 +\r\n * 骨骼定义 × count:{u32 u0, i32 parent, f32 f0, 矩阵 64B @+12}(76B)\r\n * MDAT0001: \"MDAT0001\\0\" + u32@9 + u16@13 count + u16@15 ? +\r\n * 条目 × count:{name\\0 矩阵64B}(矩阵 = 名字起点 + strlen + 1)\r\n * 矩阵平移 = 具名骨骼位置(模型空间 y-up)→ attachment 锚点\r\n * MDLA0006: \"MDLA0006\\0\" + u32@9 + u32@13 animCount +\r\n * 每动画 {u32 id, f16 2B, name\\0, loop\\0, f32, u32, u32, u32 dataLen,\r\n * u8 extra, 数据 dataLen}\r\n * 帧 = [t:3B LE][8×f32](36B)\r\n * MDLE0002: \"MDLE0002\\0\" + u32@9 + u32@13 byteCount + 矩阵 × (byteCount/64) @+17\r\n * (姿势矩阵:静态壁纸 = bind;动画壁纸 = 当前姿势)\r\n *\r\n * 蒙皮语义(linux 参考一致):静态渲染用 raw 顶点(bind 姿势);\r\n * 动画蒙皮 skinPos = Σ w_i × pose_i × bindInv_i × pos。\r\n * 本模块仅 node 半使用(模型构建时解析),纯字节解析无 node API。\r\n */\r\nexport interface PuppetVertex {\r\n pos: [number, number, number]\r\n /** 4 个骨骼权重(f32 @56..68,对应骨骼 0..3) */\r\n weights: number[]\r\n uv: [number, number]\r\n}\r\n\r\nexport interface PuppetMesh {\r\n vertices: PuppetVertex[]\r\n /** uint16 三角形索引(每 3 个一组) */\r\n indices: number[]\r\n /** UV v 方向自适应:pos y 与 uv.v 正相关(顶部采样立绘下部)→ 渲染需翻转 v */\r\n flipV: boolean\r\n}\r\n\r\nexport interface PuppetBone {\r\n name: string\r\n /** 父骨骼索引(-1 = root,来自 MDLS 定义表) */\r\n parent: number\r\n /** MDLS bind 矩阵(16 f32 列主序)或 null */\r\n bind: number[] | null\r\n /** MDLE 姿势矩阵(16 f32 列主序)或 null */\r\n pose: number[] | null\r\n}\r\n\r\nexport interface PuppetKeyframe {\r\n /** 相对时间(t 字段) */\r\n t: number\r\n /** 8 值:[pos.x pos.y pos.z][旋转 4][scale] */\r\n values: number[]\r\n}\r\n\r\nexport interface PuppetAnimation {\r\n id: number\r\n name: string\r\n loop: boolean\r\n /** 驱动骨骼数(bones 字段) */\r\n boneCount: number\r\n /** 动画时长(秒,目录项 f32 字段;>0 时播放周期用此值) */\r\n duration: number\r\n keyframes: PuppetKeyframe[]\r\n}\r\n\r\nexport interface PuppetModel {\r\n material: string\r\n bones: PuppetBone[]\r\n mesh: PuppetMesh | null\r\n animations: PuppetAnimation[]\r\n /** MDAT 具名骨骼位置(骨骼名 → [x,y,z],y-up 模型空间,相对图片中心);\r\n * 用于 attachment=\"head\" 等部件的锚点偏移 */\r\n bonePositions: Record<string, [number, number, number]>\r\n}\r\n\r\nconst f32At = (bytes: Uint8Array, q: number): number => {\r\n const v = (bytes[q] | (bytes[q + 1] << 8) | (bytes[q + 2] << 16) | (bytes[q + 3] << 24)) | 0\r\n return new Float32Array(new Int32Array([v]).buffer)[0]\r\n}\r\nconst u32At = (bytes: Uint8Array, q: number): number => {\r\n return (bytes[q] | (bytes[q + 1] << 8) | (bytes[q + 2] << 16) | (bytes[q + 3] << 24)) >>> 0\r\n}\r\nconst i32At = (bytes: Uint8Array, q: number): number => {\r\n return (bytes[q] | (bytes[q + 1] << 8) | (bytes[q + 2] << 16) | (bytes[q + 3] << 24)) | 0\r\n}\r\nconst u16At = (bytes: Uint8Array, q: number): number => {\r\n return bytes[q] | (bytes[q + 1] << 8)\r\n}\r\n\r\n/** 解析 mdl;失败返回 null */\r\nexport function parsePuppetMdl(bytes: Uint8Array): PuppetModel | null {\r\n try {\r\n const len = bytes.length\r\n const find = (tag: string, from: number): number => {\r\n const t = new Uint8Array(tag.length)\r\n for (let i = 0; i < tag.length; i++) t[i] = tag.charCodeAt(i)\r\n let i = from\r\n while (i < len - tag.length) {\r\n let ok = true\r\n for (let k = 0; k < tag.length; k++) if (bytes[i + k] !== t[k]) { ok = false; break }\r\n if (ok) return i\r\n i++\r\n }\r\n return -1\r\n }\r\n\r\n // 魔数(MDLV0021/0023 变体;0023 有 json 材质)\r\n if (bytes.length < 16) return null\r\n let material = ''\r\n let p = 0\r\n const magic1 = (() => {\r\n let s = ''\r\n while (p < len && bytes[p] !== 0 && s.length < 32) { s += String.fromCharCode(bytes[p]); p++ }\r\n p++\r\n return s\r\n })()\r\n if (!magic1.startsWith('0023') && !magic1.startsWith('0021') && !magic1.startsWith('0020')) return null\r\n p += 12 // 跳过魔数后 3 个 DWORD\r\n if (p < len) {\r\n // 材质 json(string 至 null)\r\n let s = ''\r\n let q = p\r\n while (q < len && bytes[q] !== 0 && s.length < 4096) { s += String.fromCharCode(bytes[q]); q++ }\r\n if (s.includes('\"name\"') || s.includes('{')) material = s\r\n p = q + 1\r\n }\r\n\r\n const mdls4 = find('MDLS0004', 0)\r\n const mdls3 = find('MDLS0003', 0)\r\n const mdls = mdls4 >= 0 ? mdls4 : mdls3\r\n const mdlsIs3 = mdls >= 0 && mdls4 < 0\r\n const mdat = find('MDAT0001', 0)\r\n const mdla = find('MDLA0006', 0)\r\n const mdle = find('MDLE0002', 0)\r\n\r\n // --- MDLV 顶点网格(仿 linux-wallpaperengine findPuppetMeshBlock:stride=80)---\r\n let mesh: PuppetMesh | null = null\r\n {\r\n const stride = 80\r\n const mdlsOffset = mdls >= 0 ? mdls : len\r\n for (let offset = 9; offset + 12 < mdlsOffset; offset++) {\r\n const candidateVertexBytes = u32At(bytes, offset + 4)\r\n const verticesOffset = offset + 8\r\n const indexLengthOffset = verticesOffset + candidateVertexBytes\r\n if (candidateVertexBytes === 0 || candidateVertexBytes % stride !== 0 || indexLengthOffset + 4 > mdlsOffset) continue\r\n const candidateIndexBytes = u32At(bytes, indexLengthOffset)\r\n const indicesOffset = indexLengthOffset + 4\r\n if (candidateIndexBytes === 0 || candidateIndexBytes % 6 !== 0 || indicesOffset + candidateIndexBytes > mdlsOffset) continue\r\n // 顶点数据合理性:索引范围检查 + 位置有限\r\n const vc = candidateVertexBytes / stride\r\n const idxCount = candidateIndexBytes / 2\r\n let valid = true\r\n let minX = Infinity\r\n for (let i = 0; i < vc; i++) {\r\n const vp = verticesOffset + i * stride\r\n const x = f32At(bytes, vp)\r\n if (!Number.isFinite(x)) { valid = false; break }\r\n if (x < minX) minX = x\r\n }\r\n if (!valid || !Number.isFinite(minX)) continue\r\n const maxIdx = vc - 1\r\n for (let i = 0; i < idxCount && valid; i++) {\r\n const v = u16At(bytes, indicesOffset + i * 2)\r\n if (v > maxIdx) valid = false\r\n }\r\n if (!valid) continue\r\n const vertices: PuppetVertex[] = []\r\n for (let i = 0; i < vc; i++) {\r\n const vp = verticesOffset + i * stride\r\n const weights: number[] = []\r\n for (let w = 0; w < 4; w++) weights.push(f32At(bytes, vp + 56 + w * 4))\r\n vertices.push({\r\n pos: [f32At(bytes, vp), f32At(bytes, vp + 4), f32At(bytes, vp + 8)],\r\n weights,\r\n uv: [f32At(bytes, vp + 72), f32At(bytes, vp + 76)],\r\n })\r\n }\r\n const indices: number[] = []\r\n for (let i = 0; i < idxCount; i++) indices.push(u16At(bytes, indicesOffset + i * 2))\r\n // v 方向自适应:pos y 与 uv.v 的相关性(顶部顶点采样立绘上部 = 负相关 → 不翻)\r\n let sy = 0\r\n let sv = 0\r\n let syv = 0\r\n let sy2 = 0\r\n let sv2 = 0\r\n const vn = vertices.length\r\n for (const v of vertices) {\r\n const y = v.pos[1]\r\n const vv = v.uv[1]\r\n sy += y; sv += vv; syv += y * vv; sy2 += y * y; sv2 += vv * vv\r\n }\r\n const denom = Math.sqrt(Math.max(1e-9, (vn * sy2 - sy * sy) * (vn * sv2 - sv * sv)))\r\n const r = (vn * syv - sy * sv) / denom\r\n mesh = { vertices, indices, flipV: r > 0 }\r\n break\r\n }\r\n }\r\n\r\n // --- MDLS 骨骼定义 ---\r\n // 0004:count@+13,定义表 @+18,76B/骨骼(u0+parent+f0+矩阵@+12)\r\n // 0003(Miku 等):定义表 @+17,头 13B(u0 4B+pad 1B+parent 4B+f0 4B),矩阵 @+13,\r\n // 矩阵后跟 json 属性块(\\0 结尾,变长)——逐骨骼跳过 json\r\n let boneCount = 0\r\n const mdlsBones: Array<{ parent: number; bind: number[] }> = []\r\n if (mdls >= 0 && mdls + 18 + 76 <= len) {\r\n boneCount = u32At(bytes, mdls + 13)\r\n if (boneCount > 512) boneCount = 0\r\n if (mdlsIs3) {\r\n let q = mdls + 17\r\n for (let i = 0; i < boneCount && q + 77 <= len; i++) {\r\n const parent = i32At(bytes, q + 5)\r\n const mp = q + 13\r\n const bind: number[] = []\r\n for (let k = 0; k < 16; k++) bind.push(f32At(bytes, mp + k * 4))\r\n mdlsBones.push({ parent, bind })\r\n // 跳过 json 属性块(矩阵后到 \\0)\r\n let j = mp + 64\r\n while (j < len && bytes[j] !== 0 && j < q + 4096) j++\r\n q = j + 1\r\n }\r\n } else {\r\n let q = mdls + 18\r\n for (let i = 0; i < boneCount && q + 76 <= len; i++) {\r\n const parent = i32At(bytes, q + 4)\r\n const mp = q + 12\r\n const bind: number[] = []\r\n for (let k = 0; k < 16; k++) bind.push(f32At(bytes, mp + k * 4))\r\n mdlsBones.push({ parent, bind })\r\n q += 76\r\n }\r\n }\r\n }\r\n\r\n // --- MDLE 姿势矩阵(byteCount@+13,矩阵 @+17)---\r\n let poseMatrices: number[] | null = null\r\n if (mdle >= 0 && mdle + 17 + 64 <= len) {\r\n const byteCount = u32At(bytes, mdle + 13)\r\n const count = byteCount / 64\r\n if (count >= 1 && count <= 512 && mdle + 17 + count * 64 <= len) {\r\n const mats: number[] = []\r\n for (let i = 0; i < count * 16; i++) mats.push(f32At(bytes, mdle + 17 + i * 4))\r\n poseMatrices = mats\r\n }\r\n }\r\n\r\n // --- MDAT 具名骨骼(count u16@+13,名字 @+17 起,矩阵 = 名字起点 + strlen + 1)---\r\n const bonePositions: Record<string, [number, number, number]> = {}\r\n const mdatNames: string[] = []\r\n if (mdat >= 0) {\r\n const mdatEnd = (() => {\r\n let e = len\r\n if (mdla >= 0 && mdla > mdat) e = Math.min(e, mdla)\r\n if (mdle >= 0 && mdle > mdat) e = Math.min(e, mdle)\r\n return e\r\n })()\r\n const mdatCount = u16At(bytes, mdat + 13)\r\n if (mdatCount > 0 && mdatCount <= 256) {\r\n let q = mdat + 17\r\n for (let i = 0; i < mdatCount && q + 65 <= mdatEnd; i++) {\r\n // 条目间可能有 1B pad(0x00):跳过\r\n let skips = 0\r\n while (skips < 4 && q < mdatEnd && bytes[q] === 0 && q + 66 <= mdatEnd) { q++; skips++ }\r\n // 名字(ASCII)\r\n let nm = ''\r\n let s = q\r\n while (s < mdatEnd && bytes[s] !== 0 && bytes[s] >= 32 && bytes[s] < 127 && nm.length < 128) { nm += String.fromCharCode(bytes[s]); s++ }\r\n if (nm.length < 1 || s >= mdatEnd || bytes[s] !== 0) break\r\n const mp = s + 1\r\n if (mp + 64 > mdatEnd) break\r\n mdatNames.push(nm)\r\n bonePositions[nm] = [f32At(bytes, mp + 48), f32At(bytes, mp + 52), f32At(bytes, mp + 56)]\r\n q = mp + 64\r\n }\r\n } else {\r\n // 兜底:循环扫描名字(count 字段不可靠时)\r\n let q = mdat + 17\r\n let guard = 0\r\n while (q + 66 <= mdatEnd && guard++ < 256) {\r\n let nm = ''\r\n let s = q\r\n while (s < mdatEnd && bytes[s] !== 0 && bytes[s] >= 32 && bytes[s] < 127 && nm.length < 128) { nm += String.fromCharCode(bytes[s]); s++ }\r\n if (nm.length < 1 || s >= mdatEnd || bytes[s] !== 0) break\r\n const mp = s + 1\r\n if (mp + 64 > mdatEnd) break\r\n mdatNames.push(nm)\r\n bonePositions[nm] = [f32At(bytes, mp + 48), f32At(bytes, mp + 52), f32At(bytes, mp + 56)]\r\n q = mp + 64\r\n }\r\n }\r\n }\r\n\r\n // --- 组装骨骼 ---\r\n const bones: PuppetBone[] = []\r\n const total = Math.max(boneCount, mdatNames.length, poseMatrices !== null ? poseMatrices.length / 16 : 0)\r\n for (let i = 0; i < total; i++) {\r\n const mdlsB = mdlsBones[i]\r\n const pose = poseMatrices !== null && i * 16 + 15 < poseMatrices.length\r\n ? poseMatrices.slice(i * 16, i * 16 + 16)\r\n : null\r\n bones.push({\r\n name: mdatNames[i] ?? '',\r\n parent: mdlsB !== undefined ? mdlsB.parent : -1,\r\n bind: mdlsB !== undefined ? mdlsB.bind : null,\r\n pose,\r\n })\r\n }\r\n\r\n // --- MDLA 动画 ---\r\n const animations: PuppetAnimation[] = []\r\n if (mdla >= 0 && mdla + 17 <= len) {\r\n const animCount = Math.max(0, Math.min(64, u32At(bytes, mdla + 13)))\r\n let q = mdla + 17\r\n for (let a = 0; a < animCount && q + 8 <= len; a++) {\r\n const id = u32At(bytes, q); q += 4\r\n q += 4 // u32(id 后)\r\n let nm = ''\r\n while (q < len && bytes[q] !== 0 && nm.length < 128) { nm += String.fromCharCode(bytes[q]); q++ }\r\n q++\r\n let lp = ''\r\n while (q < len && bytes[q] !== 0 && lp.length < 128) { lp += String.fromCharCode(bytes[q]); q++ }\r\n q++\r\n if (nm === '' || q + 20 > len) break\r\n const duration = f32At(bytes, q); q += 4 // f32(动画时长秒)\r\n const bc = u32At(bytes, q); q += 4\r\n q += 4 // u32\r\n q += 4 // u32\r\n q += 4 // u32\r\n const dataLen = u32At(bytes, q); q += 4\r\n if (dataLen <= 0 || dataLen > len - q) break\r\n q++ // extra (1B)\r\n const kf = parseKeyframes(bytes, q, dataLen)\r\n q += kf.offset + dataLen\r\n animations.push({ id, name: nm, loop: lp === 'loop', boneCount: bc, duration, keyframes: kf.keyframes })\r\n }\r\n }\r\n\r\n return { material, bones, mesh, animations, bonePositions }\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n/**\r\n * 解析关键帧数据区:每帧 36B = [t:3B LE][8×f32][1B]。\r\n * 偏移探测:尝试 0..8 字节偏移,选质量最高的解析;\r\n * 质量 = t 单调峰得分 − 帧值合理性惩罚(NaN/巨大值 = 错位解析)。\r\n * 返回探测到的数据起点偏移(供调用方前进游标)。\r\n */\r\nfunction parseKeyframes(bytes: Uint8Array, dataStart: number, dataLen: number): { keyframes: PuppetKeyframe[]; offset: number } {\r\n const len = bytes.length\r\n const frameCount = Math.floor(dataLen / 36)\r\n if (frameCount <= 0) return { keyframes: [], offset: 0 }\r\n let best: PuppetKeyframe[] = []\r\n let bestOff = 0\r\n let bestScore = -Infinity\r\n for (let off = 0; off <= 8 && dataStart + off + 36 <= len; off++) {\r\n const kf: PuppetKeyframe[] = []\r\n let bad = false\r\n let penalty = 0\r\n for (let f = 0; f < frameCount; f++) {\r\n const fp = dataStart + off + f * 36\r\n if (fp + 36 > len) { bad = true; break }\r\n const t = (bytes[fp] | (bytes[fp + 1] << 8) | (bytes[fp + 2] << 16)) >>> 0\r\n const values: number[] = []\r\n for (let k = 0; k < 8; k++) {\r\n const v = f32At(bytes, fp + 3 + k * 4)\r\n values.push(v)\r\n if (!Number.isFinite(v) || Math.abs(v) > 1e7) penalty += 10\r\n else if (Math.abs(v) > 1e5) penalty += 1\r\n }\r\n kf.push({ t, values })\r\n }\r\n if (bad) continue\r\n let peak = 0\r\n for (let i = 1; i < kf.length; i++) if (kf[i].t > kf[peak].t) peak = i\r\n let score = 0\r\n for (let i = 1; i <= peak; i++) if (kf[i].t >= kf[i - 1].t) score++\r\n for (let i = peak + 1; i < kf.length; i++) if (kf[i].t <= kf[i - 1].t) score++\r\n // 平铺惩罚:t 全等时所有偏移得分相同 → 用值合理性区分\r\n let tMin = Infinity\r\n let tMax = -Infinity\r\n for (const k of kf) { if (k.t < tMin) tMin = k.t; if (k.t > tMax) tMax = k.t }\r\n if (tMin === tMax) score -= frameCount * 0.5\r\n if (score - penalty > bestScore) { bestScore = score - penalty; best = kf; bestOff = off }\r\n }\r\n return { keyframes: best, offset: bestOff }\r\n}\r\n\r\n/** 按相对时间 t 在关键帧间线性插值(循环动画自动回卷处理) */\r\nexport function sampleAnimation(anim: PuppetAnimation, t: number): { values: number[]; t: number } | null {\r\n const kf = anim.keyframes\r\n if (kf.length === 0) return null\r\n if (kf.length === 1) return { values: kf[0].values, t: kf[0].t }\r\n let peak = 0\r\n for (let i = 1; i < kf.length; i++) if (kf[i].t > kf[peak].t) peak = i\r\n const period = kf[peak].t - kf[0].t\r\n if (period <= 0) {\r\n // t 常量或递减(ping-pong 回卷 / 编辑器导出):按帧号线性播放\r\n const n = kf.length\r\n const idx = ((t % n) + n) % n\r\n const i0 = Math.floor(idx)\r\n const frac = idx - i0\r\n if (i0 + 1 >= n) return { values: kf[i0].values, t: i0 }\r\n return { values: kf[i0].values.map((v, k) => v + (kf[i0 + 1].values[k] - v) * frac), t: i0 + frac }\r\n }\r\n const startT = kf[0].t\r\n const curve: Array<{ p: number; values: number[] }> = []\r\n for (let i = 0; i <= peak; i++) curve.push({ p: kf[i].t - startT, values: kf[i].values })\r\n for (let i = peak; i < kf.length; i++) curve.push({ p: period - (kf[i].t - startT), values: kf[i].values })\r\n const mono: typeof curve = []\r\n let lastP = -Infinity\r\n for (const c of curve) {\r\n if (c.p >= lastP) { mono.push(c); lastP = c.p }\r\n }\r\n if (mono.length < 2) return { values: kf[0].values, t: kf[0].t }\r\n const prog = ((t % period) + period) % period\r\n let a = mono[0]\r\n for (let i = 1; i < mono.length; i++) {\r\n const b = mono[i]\r\n if (prog <= b.p) {\r\n const span = b.p - a.p\r\n const frac = span > 0 ? Math.min(1, Math.max(0, (prog - a.p) / span)) : 0\r\n return { values: a.values.map((v, k) => v + (b.values[k] - v) * frac), t: prog + startT }\r\n }\r\n a = b\r\n }\r\n return { values: mono[mono.length - 1].values, t: prog + startT }\r\n}\r\n","/**\r\n * ParticleRuntime —— 浏览器侧粒子系统运行时(Phase C)。\r\n *\r\n * 数据源:SceneModel 的 ParticleSystemDesc(源自 WE particles/*.json 预设):\r\n * emitter(发射器:sphererandom/boxrandom + rate + 方向/距离/origin 偏移)\r\n * initializers(寿命/尺寸/速度/颜色/alpha/旋转/角速度 随机范围)\r\n * operators(重力 / alpha 淡入淡出 / 湍流 / alpha 振荡 / 尺寸变化)\r\n * renderer(sprite / spritetrail —— 本实现以 sprite 近似)\r\n *\r\n * 坐标系:WE 粒子为局部 3D 坐标,**y 向上**(velocityrandom y 负值 = 向下落,\r\n * gravity \"0 -10 0\" = 向下加速)。绘制时把局部 y 翻转为屏幕 y 向下:\r\n * 屏幕 y = py0 - p.y * scale * s\r\n *\r\n * 诚实边界:多 emitter / children 子粒子 / oscillateposition / 序列帧动画\r\n * (animationmode=sequence)尚未实现;rate 单位按 /0.1s 推断(×4 折中)。\r\n */\r\nimport type { ParticleSystemDesc } from '../scene/SceneModel.ts'\r\n\r\ninterface Particle {\r\n x: number\r\n y: number\r\n vx: number\r\n vy: number\r\n life: number\r\n maxLife: number\r\n /** 出生尺寸(sizechange 线性插值的基准) */\r\n baseSize: number\r\n size: number\r\n alpha: number\r\n /** 颜色 tint(0-255) */\r\n color: [number, number, number]\r\n /** 旋转(弧度) */\r\n rot: number\r\n /** 角速度(弧度/秒) */\r\n angVel: number\r\n phase: number\r\n /** oscillateposition 相位(每粒子独立) */\r\n oscPhase: number\r\n /** oscillateposition 频率(每粒子独立) */\r\n oscFreq: number\r\n}\r\n\r\nexport class ParticleRuntime {\r\n private particles: Particle[] = []\r\n private acc = 0\r\n private time = 0\r\n /** 纹理染色缓存(颜色 → 染色 canvas) */\r\n private tintCache = new Map<string, HTMLCanvasElement>()\r\n\r\n constructor(private desc: ParticleSystemDesc, private rateScale = 1, private sizeScale = 1) {}\r\n\r\n get count(): number {\r\n return this.particles.length\r\n }\r\n\r\n update(dt: number): void {\r\n this.time += dt\r\n const em = this.desc.emitter\r\n const ini = this.desc.initializers\r\n const ops = this.desc.operators\r\n\r\n // 发射(rate × 视觉缩放)\r\n this.acc += em.rate * this.rateScale * dt\r\n while (this.acc >= 1 && this.particles.length < this.desc.maxCount) {\r\n this.acc -= 1\r\n this.spawn(em, ini)\r\n }\r\n\r\n // 更新\r\n const g = ops.gravity ?? [0, 0, 0]\r\n const drag = ops.drag ?? 0\r\n const angDrag = ops.angularDrag ?? 0\r\n const angForce = ops.angularForce ?? [0, 0, 0]\r\n const fade = ops.alphaFade\r\n const osc = ops.oscillateAlpha\r\n const oscPos = ops.oscillatePosition\r\n const sizeChanges = ops.sizeChanges ?? []\r\n const turb = ops.turbulence\r\n for (const p of this.particles) {\r\n p.life -= dt\r\n const frac = 1 - p.life / p.maxLife\r\n p.x += p.vx * dt\r\n p.y += p.vy * dt\r\n p.vx += g[0] * dt\r\n p.vy += g[1] * dt\r\n // movement drag:速度阻尼\r\n if (drag > 0) {\r\n p.vx *= Math.max(0, 1 - drag * dt)\r\n p.vy *= Math.max(0, 1 - drag * dt)\r\n }\r\n // angularmovement:角速度阻尼 + 角加速度\r\n if (angDrag > 0) p.angVel *= Math.max(0, 1 - angDrag * dt)\r\n p.angVel += angForce[2] * dt\r\n p.rot += p.angVel * dt\r\n // oscillateposition:位置正弦振荡(每粒子独立频率/相位)\r\n if (oscPos !== undefined) {\r\n const sw = Math.sin(this.time * p.oscFreq + p.oscPhase)\r\n p.x += sw * oscPos.mask[0] * dt\r\n p.y += sw * oscPos.mask[1] * dt\r\n }\r\n if (turb !== undefined) {\r\n const phase = this.time * (turb.speedMin + (turb.speedMax - turb.speedMin) * 0.5) + p.phase\r\n p.x += Math.sin(phase) * turb.scale * 100 * dt\r\n p.y += Math.cos(phase * 0.7) * turb.scale * 100 * dt\r\n }\r\n let a = 1\r\n if (fade !== undefined) {\r\n const fadeIn = fade.fadeIn ?? 0\r\n const fadeOut = fade.fadeOut ?? 0\r\n if (fadeIn > 0 && frac < fadeIn) a = Math.min(a, frac / fadeIn)\r\n if (fadeOut > 0) {\r\n const tail = 1 - frac\r\n if (tail < fadeOut) a = Math.min(a, tail / fadeOut)\r\n }\r\n }\r\n if (osc !== undefined) {\r\n const s = Math.sin(this.time * osc.frequencyMax * Math.PI * 2 + p.phase)\r\n a *= osc.scaleMin + (1 - osc.scaleMin) * Math.max(0, s)\r\n }\r\n // sizechange:寿命比例区间内从 startValue 线性变到 endValue(相对出生尺寸)\r\n for (const sc of sizeChanges) {\r\n if (frac >= sc.startTime) {\r\n const span = Math.max(0.0001, (sc.endTime ?? 1) - sc.startTime)\r\n const t = Math.min(1, Math.max(0, (frac - sc.startTime) / span))\r\n p.size = p.baseSize * (sc.startValue + (sc.endValue - sc.startValue) * t)\r\n }\r\n }\r\n p.alpha = Math.max(0, Math.min(1, a))\r\n }\r\n this.particles = this.particles.filter((p) => p.life > 0)\r\n }\r\n\r\n /**\r\n * 绘制(局部坐标 → 世界变换 → 画布)。\r\n * 混合模式按材质 blending:translucent → alpha 混合(source-over,雾/雪等半透明);\r\n * additive → 'lighter'(光效/火花)。t 为图层世界变换(含 parent 合并)。\r\n * 粒子局部 y 向上 → 绘制时翻转。粒子颜色按 colorrandom 染色(缓存染色纹理)。\r\n */\r\n draw(ctx: CanvasRenderingContext2D, ox: number, oy: number, s: number, t: { ox: number; oy: number; sx: number; sy: number }, tex: ImageBitmap | HTMLCanvasElement): void {\r\n const lx = t.sx\r\n const ly = t.sy\r\n const px0 = ox + t.ox * s\r\n const py0 = oy + t.oy * s\r\n const additive = this.desc.blending === 'additive'\r\n ctx.save()\r\n if (additive) ctx.globalCompositeOperation = 'lighter'\r\n for (const p of this.particles) {\r\n const x = px0 + p.x * lx * s\r\n const y = py0 - p.y * ly * s\r\n const ps = Math.max(2, p.size * lx * s)\r\n // 保持纹理宽高比(雾/风等非正方形粒子纹理不拉伸变形)\r\n const aspect = tex.width / tex.height\r\n const pw = aspect >= 1 ? ps * aspect : ps\r\n const ph = aspect >= 1 ? ps : ps / aspect\r\n const img = this.tinted(tex, p.color)\r\n ctx.globalAlpha = Math.max(0, Math.min(1, p.alpha))\r\n if (p.rot !== 0) {\r\n ctx.save()\r\n ctx.translate(x, y)\r\n ctx.rotate(p.rot)\r\n ctx.drawImage(img, -pw / 2, -ph / 2, pw, ph)\r\n ctx.restore()\r\n } else {\r\n ctx.drawImage(img, x - pw / 2, y - ph / 2, pw, ph)\r\n }\r\n }\r\n ctx.restore()\r\n }\r\n\r\n /** 纹理染色(source-in 保留 alpha),按颜色缓存 */\r\n private tinted(tex: ImageBitmap | HTMLCanvasElement, color: [number, number, number]): HTMLCanvasElement {\r\n const key = color[0] + ',' + color[1] + ',' + color[2]\r\n const hit = this.tintCache.get(key)\r\n if (hit !== undefined) return hit\r\n const c = document.createElement('canvas')\r\n c.width = tex.width\r\n c.height = tex.height\r\n const g = c.getContext('2d')\r\n if (g !== null) {\r\n g.drawImage(tex, 0, 0)\r\n g.globalCompositeOperation = 'source-in'\r\n g.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')'\r\n g.fillRect(0, 0, c.width, c.height)\r\n }\r\n this.tintCache.set(key, c)\r\n return c\r\n }\r\n\r\n private spawn(em: ParticleSystemDesc['emitter'], ini: ParticleSystemDesc['initializers']): void {\r\n let x = 0\r\n let y = 0\r\n const [dx, dy] = em.directions\r\n if (em.type === 'boxrandom') {\r\n const d = Array.isArray(em.distanceMax) ? em.distanceMax : [em.distanceMax, em.distanceMax, 0]\r\n x = (Math.random() * 2 - 1) * d[0] * 0.5\r\n y = (Math.random() * 2 - 1) * d[1] * 0.5\r\n } else {\r\n const maxD = typeof em.distanceMax === 'number' ? em.distanceMax : Math.hypot(em.distanceMax[0], em.distanceMax[1])\r\n const dist = em.distanceMin + Math.random() * Math.max(0, maxD - em.distanceMin)\r\n x = (Math.random() * 2 - 1) * dist * dx\r\n y = (Math.random() * 2 - 1) * dist * dy\r\n }\r\n // emitter.origin 偏移(局部坐标,如 leaves2 origin=\"350 750 0\" 从树上发射)\r\n x += em.origin[0]\r\n y += em.origin[1]\r\n const life = rand(ini.lifetime ?? [1, 1])\r\n // size:sizerandom 分布(exponent 幂次 >1 偏向小值)× 视觉缩放\r\n let size: number\r\n if (ini.size !== undefined) {\r\n const [smn, smx] = ini.size\r\n const exp = ini.sizeExponent ?? 1\r\n size = (smn + Math.pow(Math.random(), exp) * Math.max(0, smx - smn)) * this.sizeScale\r\n } else {\r\n size = 32 * this.sizeScale\r\n }\r\n let vx = 0\r\n let vy = 0\r\n if (ini.velocityMin !== undefined && ini.velocityMax !== undefined) {\r\n vx = rand(ini.velocityMin[0], ini.velocityMax[0])\r\n vy = rand(ini.velocityMin[1], ini.velocityMax[1])\r\n }\r\n if (ini.turbulentVelocity !== undefined) {\r\n const tv = ini.turbulentVelocity\r\n vx += (Math.random() * 2 - 1) * Math.abs(tv.scale) * 100\r\n vy += (Math.random() * 2 - 1) * Math.abs(tv.scale) * 100\r\n }\r\n const alpha = rand(ini.alphaMin ?? 1, ini.alphaMax ?? 1)\r\n // 颜色:colorrandom min/max 分量随机(0-255)\r\n let cr = 255\r\n let cg = 255\r\n let cb = 255\r\n if (ini.colorMin !== undefined && ini.colorMax !== undefined) {\r\n cr = Math.round(rand(ini.colorMin[0], ini.colorMax[0]))\r\n cg = Math.round(rand(ini.colorMin[1], ini.colorMax[1]))\r\n cb = Math.round(rand(ini.colorMin[2], ini.colorMax[2]))\r\n }\r\n // 旋转 + 角速度\r\n const rot = ini.rotation !== undefined ? rand(ini.rotation[0], ini.rotation[1]) : 0\r\n const angVel = ini.angularVelocity !== undefined ? rand(ini.angularVelocity[0], ini.angularVelocity[1]) : 0\r\n // overbright(genericparticle g_Overbright):颜色亮度系数(材质 ui_editor_properties_overbright)\r\n const ob = this.desc.overbright > 0 ? this.desc.overbright : 1\r\n cr = Math.min(255, Math.round(cr * ob))\r\n cg = Math.min(255, Math.round(cg * ob))\r\n cb = Math.min(255, Math.round(cb * ob))\r\n // oscillateposition 每粒子独立频率/相位\r\n const osc = this.desc.operators.oscillatePosition\r\n const oscFreq = osc !== undefined ? rand(osc.frequencyMin, osc.frequencyMax) : 0\r\n const oscPhase = Math.random() * Math.PI * 2\r\n this.particles.push({\r\n x,\r\n y,\r\n vx,\r\n vy,\r\n life,\r\n maxLife: Math.max(0.001, life),\r\n baseSize: size,\r\n size,\r\n alpha,\r\n color: [cr, cg, cb],\r\n rot,\r\n angVel,\r\n phase: Math.random() * Math.PI * 2,\r\n oscPhase,\r\n oscFreq,\r\n })\r\n }\r\n}\r\n\r\nfunction rand(a: number | [number, number], b?: number): number {\r\n if (Array.isArray(a)) {\r\n const [mn, mx] = a\r\n return mn + Math.random() * Math.max(0, mx - mn)\r\n }\r\n if (b === undefined) return a\r\n return a + Math.random() * Math.max(0, b - a)\r\n}\r\n","/**\n * WaterwavesGL —— waterwaves 效果的 WebGL 逐像素实现。\n *\n * 许可说明:Wallpaper Engine 官方效果(闭源商业资产)仅作**黑盒行为参考**\n * (观察参数语义与输出),本 shader 为**独立编写**的数学等价实现\n * (正弦波沿方向传播 + 垂直扰动 + mask 门控——通用数学事实,不受版权保护)。\n * 不复制官方源码;未包含 linux-wallpaperengine(GPL)代码。\n *\n * 行为模型(观察所得):波相位沿 (-sinθ, cosθ) 方向随空间/时间变化,\n * 扰动沿 (cosθ, sinθ) 垂直方向,幅度 = strength² 的指数波形,mask 门控。\n * 本实现:WebGL 全屏 quad + fragment shader(支持 1-4 个波叠加 + mask),\n * 逐像素 UV 场扰动;图层纹理与 mask 纹理缓存(首次上传,之后只更新 uniforms)。\n */\nexport type WaterwavesParams = { direction: number; speed: number; scale: number; strength: number; exponent: number }\n\nconst VERT_SRC = `\nattribute vec2 a_Pos;\nvarying vec2 v_UV;\nvoid main() {\n gl_Position = vec4(a_Pos, 0.0, 1.0);\n v_UV = a_Pos * 0.5 + 0.5;\n}\n`\n\nconst FRAG_SRC = `\nprecision mediump float;\n// 独立实现的水波扰动(数学事实:沿某方向传播的正弦波 + 垂直方向扰动)。\n// 行为参考 Wallpaper Engine 官方 waterwaves 效果(黑盒观察),代码为独立编写。\nuniform sampler2D u_Src;\nuniform sampler2D u_MaskTex;\nuniform float u_UseMask;\nuniform float u_MaskAlpha;\nuniform float u_Clock;\nuniform vec4 u_Params[4]; // x=方向角, y=速度, z=尺度, w=强度\nuniform float u_Power[4]; // 波形指数\nuniform int u_Count;\nvarying vec2 v_Uv;\nvoid main() {\n vec2 uv = v_Uv;\n float gate = 1.0;\n if (u_UseMask > 0.5) {\n vec4 m = texture2D(u_MaskTex, uv);\n gate = u_MaskAlpha > 0.5 ? m.a : m.r;\n }\n vec2 total = vec2(0.0);\n for (int i = 0; i < 4; i++) {\n if (i >= u_Count) break;\n vec4 p = u_Params[i];\n float sinA = sin(p.x);\n float cosA = cos(p.x);\n // 波相位沿 (-sinA, cosA) 方向随空间与时间变化\n float phase = u_Clock * p.y + (uv.x * -sinA + uv.y * cosA) * p.z;\n float wave = sin(phase);\n // 扰动沿 (cosA, sinA),幅度为强度平方的指数波形\n float amp = pow(abs(wave), u_Power[i]) * sign(wave) * p.w * p.w;\n total += amp * vec2(cosA, sinA);\n }\n uv += total * gate;\n gl_FragColor = texture2D(u_Src, uv);\n}\n`\n\nexport class WaterwavesGL {\n private canvas: HTMLCanvasElement | null = null\n private gl: WebGLRenderingContext | null = null\n private prog: WebGLProgram | null = null\n private locs: Record<string, WebGLUniformLocation | null> = {}\n private vbo: WebGLBuffer | null = null\n private texCache = new Map<string, WebGLTexture>()\n private curW = 0\n private curH = 0\n\n /** WebGL 是否可用 */\n static get available(): boolean {\n try {\n const c = document.createElement('canvas')\n return !!(c.getContext('webgl') || c.getContext('experimental-webgl'))\n } catch {\n return false\n }\n }\n\n private ensure(): boolean {\n if (this.gl !== null && this.prog !== null) return true\n try {\n const c = document.createElement('canvas')\n const gl = (c.getContext('webgl') || c.getContext('experimental-webgl')) as WebGLRenderingContext | null\n if (gl === null) return false\n this.canvas = c\n this.gl = gl\n const compile = (type: number, src: string): WebGLShader | null => {\n const sh = gl.createShader(type)\n if (sh === null) return null\n gl.shaderSource(sh, src)\n gl.compileShader(sh)\n if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {\n console.warn('waterwaves shader: ' + gl.getShaderInfoLog(sh))\n return null\n }\n return sh\n }\n const vs = compile(gl.VERTEX_SHADER, VERT_SRC)\n const fs = compile(gl.FRAGMENT_SHADER, FRAG_SRC)\n if (vs === null || fs === null) return false\n const prog = gl.createProgram()\n if (prog === null) return false\n gl.attachShader(prog, vs)\n gl.attachShader(prog, fs)\n gl.linkProgram(prog)\n if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) return false\n this.prog = prog\n gl.useProgram(prog)\n for (const name of ['u_Src', 'u_MaskTex', 'u_UseMask', 'u_MaskAlpha', 'u_Clock', 'u_Params', 'u_Power', 'u_Count']) {\n this.locs[name] = gl.getUniformLocation(prog, name)\n }\n const aPos = gl.getAttribLocation(prog, 'a_Pos')\n this.vbo = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo)\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW)\n gl.enableVertexAttribArray(aPos)\n gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0)\n return true\n } catch {\n return false\n }\n }\n\n private uploadTexture(key: string, src: TexImageSource, w: number, h: number): WebGLTexture | null {\n const gl = this.gl\n if (gl === null) return null\n const hit = this.texCache.get(key)\n if (hit !== undefined) return hit\n const tex = gl.createTexture()\n if (tex === null) return null\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n this.texCache.set(key, tex)\n return tex\n }\n\n /**\n * 渲染 waterwaves 效果到离屏 WebGL canvas(逐像素 UV 场扰动)。\n * src:图层纹理;mask:mask 纹理(null = 无);maskUseA:mask 用 A 通道(R8 alpha 语义)。\n */\n render(src: TexImageSource, w: number, h: number, mask: HTMLCanvasElement | ImageBitmap | null, maskUseA: boolean, waves: WaterwavesParams[], time: number, key: string): HTMLCanvasElement | null {\n if (!this.ensure()) return null\n const gl = this.gl\n const prog = this.prog\n if (gl === null || prog === null || this.canvas === null) return null\n if (this.curW !== w || this.curH !== h) {\n this.canvas.width = w\n this.canvas.height = h\n this.curW = w\n this.curH = h\n }\n gl.viewport(0, 0, w, h)\n gl.useProgram(prog)\n // 纹理\n const tex = this.uploadTexture('tex:' + key, src, w, h)\n if (tex === null) return null\n gl.activeTexture(gl.TEXTURE0)\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.uniform1i(this.locs['u_Src'], 0)\n if (mask !== null) {\n const mtex = this.uploadTexture('mask:' + key, mask, 0, 0)\n gl.activeTexture(gl.TEXTURE1)\n gl.bindTexture(gl.TEXTURE_2D, mtex)\n gl.uniform1i(this.locs['u_MaskTex'], 1)\n gl.uniform1f(this.locs['u_UseMask'], 1)\n gl.uniform1f(this.locs['u_MaskAlpha'], maskUseA ? 1 : 0)\n } else {\n gl.uniform1f(this.locs['u_UseMask'], 0)\n }\n // 参数\n gl.uniform1f(this.locs['u_Clock'], time)\n const wv: number[] = []\n const ex: number[] = []\n const n = Math.min(4, waves.length)\n for (let i = 0; i < 4; i++) {\n if (i < n) {\n wv.push(waves[i].direction, waves[i].speed, waves[i].scale, waves[i].strength)\n ex.push(Math.max(0.5, Math.min(4, waves[i].exponent)))\n } else {\n wv.push(0, 0, 0, 0)\n ex.push(1)\n }\n }\n gl.uniform4fv(this.locs['u_Params'], new Float32Array(wv))\n gl.uniform1fv(this.locs['u_Power'], new Float32Array(ex))\n gl.uniform1i(this.locs['u_Count'], n)\n // 绘制\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n return this.canvas\n }\n\n /** 释放(场景切换时) */\n dispose(): void {\n for (const t of this.texCache.values()) {\n if (this.gl !== null) this.gl.deleteTexture(t)\n }\n this.texCache.clear()\n }\n}\n","/**\r\n * SceneModelRenderer —— 浏览器子集渲染器(Phase 1 最小切片)。\r\n *\r\n * 数据源:Node 半解析的归一化 SceneModel(/we-sync/scene/model):\r\n * - 图层树 + transform(origin/angles/scale/parallaxDepth)\r\n * - visible 解析\r\n * - 纹理引用链;可解码(jpg/png)纹理经 /we-sync/scene/texture 加载\r\n *\r\n * 渲染(Canvas2D):\r\n * 1) clearcolor 或预览图打底(cover 映射进场景坐标)\r\n * 2) 按 scene.json 数组顺序(z-order)逐图层绘制:\r\n * - 有可解码纹理 → drawImage + transform\r\n * - 无(TEX 待 Phase 2)→ 半透明占位块 + 图层名标注(先看图层效果)\r\n *\r\n * 诚实边界:Phase 1 不做 TEX 解码 / shader / 粒子 / keyframe 动画;\r\n * 静态合成,用于验证「真实 scene.json 图层树 + transform 能进 Harness」。\r\n */\r\nimport type { SceneModel, SceneModelLayer, LayerEffect } from '../scene/SceneModel.ts'\r\nimport { sampleAnimation as samplePuppet, type PuppetAnimation } from '../scene/ScenePuppet.ts'\r\nimport { ParticleRuntime } from './ParticleRuntime.ts'\r\nimport { WaterwavesGL, type WaterwavesParams } from './WaterwavesGL.ts'\r\n\r\nexport interface SceneModelRendererHandlers {\r\n onLiveChange?: (live: boolean) => void\r\n}\r\n\r\nconst PLACEHOLDER_SIZE = 100 // 场景单位\r\n\r\n/**\r\n * puppet 网格离屏渲染:把部件网格(三角形 + UV 纹理)渲染一次到离屏 canvas。\r\n * 模型空间(y-up,原点=图片中心)→ canvas 像素(y 向下):\r\n * x_c = x_m, y_c = -y_m(绘制时经场景变换把图片中心对齐图层锚点)。\r\n * UV v 翻转(模型 v-up → 纹理 v-down)。\r\n * 每三角形:clip 路径 + 仿射变换(UV 三角 → 位置三角)+ drawImage 纹理。\r\n * anim 可选:{rot, bx, by} = root 骨骼旋转(绕骨骼 0 bind 位置旋转的蒙皮)——\r\n * 顶点 skinPos = w0 × Rz(rot; bx,by) × pos + (1-w0) × pos(骨骼 1-3 权重静态 = raw)。\r\n */\r\nfunction buildMeshCanvas(mesh: { vertices: { pos: [number, number, number]; uv: [number, number]; weights?: number[] }[]; indices: number[]; flipV?: boolean }, tex: HTMLCanvasElement | ImageBitmap, anim?: { rot: number; bx: number; by: number } | null): { canvas: HTMLCanvasElement; originX: number; originY: number } {\r\n // 蒙皮预计算:顶点位置数组(raw 或蒙皮后)\r\n const posArr: Array<[number, number]> = []\r\n if (anim !== undefined && anim !== null) {\r\n const c = Math.cos(anim.rot)\r\n const sn = Math.sin(anim.rot)\r\n const bx = anim.bx\r\n const by = anim.by\r\n for (const v of mesh.vertices) {\r\n const w0 = v.weights !== undefined ? v.weights[0] ?? 0 : 0\r\n const rx = bx + c * (v.pos[0] - bx) - sn * (v.pos[1] - by)\r\n const ry = by + sn * (v.pos[0] - bx) + c * (v.pos[1] - by)\r\n posArr.push([w0 * rx + (1 - w0) * v.pos[0], w0 * ry + (1 - w0) * v.pos[1]])\r\n }\r\n } else {\r\n for (const v of mesh.vertices) posArr.push([v.pos[0], v.pos[1]])\r\n }\r\n let mnx = Infinity\r\n let mny = Infinity\r\n let mxx = -Infinity\r\n let mxy = -Infinity\r\n for (const [x, y] of posArr) {\r\n const yy = -y // y-up → y-down\r\n if (x < mnx) mnx = x\r\n if (yy < mny) mny = yy\r\n if (x > mxx) mxx = x\r\n if (yy > mxy) mxy = yy\r\n }\r\n const c0 = document.createElement('canvas')\r\n c0.width = 1\r\n c0.height = 1\r\n if (!Number.isFinite(mnx) || mxx - mnx > 20000 || mxy - mny > 20000) return { canvas: c0, originX: 0, originY: 0 }\r\n const pad = 4\r\n const cw = Math.max(1, Math.ceil(mxx - mnx) + pad * 2)\r\n const ch = Math.max(1, Math.ceil(mxy - mny) + pad * 2)\r\n const c = document.createElement('canvas')\r\n c.width = cw\r\n c.height = ch\r\n const g = c.getContext('2d')\r\n if (g === null) return { canvas: c, originX: pad - mnx, originY: pad - mny }\r\n g.translate(pad - mnx, pad - mny) // 模型原点 (0,0) → (pad-mnx, pad-mny)\r\n const tw = tex.width\r\n const th = tex.height\r\n const verts = mesh.vertices\r\n const idx = mesh.indices\r\n for (let i = 0; i + 2 < idx.length; i += 3) {\r\n const a = verts[idx[i]]\r\n const b = verts[idx[i + 1]]\r\n const cc = verts[idx[i + 2]]\r\n if (a === undefined || b === undefined || cc === undefined) continue\r\n // UV v 方向按壁纸自适应(mesh.flipV:pos y 与 v 正相关才翻转)\r\n const fv = (val: number): number => (mesh.flipV ? 1 - val : val) * th\r\n const u0 = a.uv[0] * tw\r\n const v0 = fv(a.uv[1])\r\n const u1 = b.uv[0] * tw\r\n const v1 = fv(b.uv[1])\r\n const u2 = cc.uv[0] * tw\r\n const v2 = fv(cc.uv[1])\r\n const x0 = posArr[idx[i]][0]\r\n const y0 = -posArr[idx[i]][1]\r\n const x1 = posArr[idx[i + 1]][0]\r\n const y1 = -posArr[idx[i + 1]][1]\r\n const x2 = posArr[idx[i + 2]][0]\r\n const y2 = -posArr[idx[i + 2]][1]\r\n const det = (u1 - u0) * (v2 - v0) - (u2 - u0) * (v1 - v0)\r\n if (Math.abs(det) < 1e-9) continue\r\n g.save()\r\n g.beginPath()\r\n g.moveTo(x0, y0)\r\n g.lineTo(x1, y1)\r\n g.lineTo(x2, y2)\r\n g.closePath()\r\n g.clip()\r\n const m00 = ((x1 - x0) * (v2 - v0) - (x2 - x0) * (v1 - v0)) / det\r\n const m01 = ((u1 - u0) * (x2 - x0) - (u2 - u0) * (x1 - x0)) / det\r\n const m10 = ((y1 - y0) * (v2 - v0) - (y2 - y0) * (v1 - v0)) / det\r\n const m11 = ((u1 - u0) * (y2 - y0) - (u2 - u0) * (y1 - y0)) / det\r\n g.transform(m00, m10, m01, m11, x0 - m00 * u0 - m01 * v0, y0 - m10 * u0 - m11 * v0)\r\n g.drawImage(tex, 0, 0)\r\n g.restore()\r\n }\r\n return { canvas: c, originX: pad - mnx, originY: pad - mny }\r\n}\r\n\r\n/**\r\n * 粒子纹理径向软边合成:中心不衰减,边缘 30% 区间线性淡出到透明。\r\n * 用于雾/雪/光晕类粒子,避免硬边方块在大尺寸 + additive 下叠加成\"白线\"。\r\n */\r\nfunction makeSoftTexture(src: ImageBitmap | HTMLCanvasElement): HTMLCanvasElement {\r\n const w = src.width\r\n const h = src.height\r\n const c = document.createElement('canvas')\r\n c.width = w\r\n c.height = h\r\n const g = c.getContext('2d')\r\n if (g === null) return c\r\n g.drawImage(src, 0, 0)\r\n const cx = w / 2\r\n const cy = h / 2\r\n const r = Math.max(1, Math.min(w, h) / 2)\r\n const grad = g.createRadialGradient(cx, cy, r * 0.65, cx, cy, r)\r\n grad.addColorStop(0, 'rgba(255,255,255,1)')\r\n grad.addColorStop(1, 'rgba(255,255,255,0)')\r\n g.globalCompositeOperation = 'destination-in'\r\n g.fillStyle = grad\r\n g.fillRect(0, 0, w, h)\r\n return c\r\n}\r\n\r\n/**\r\n * waterwaves 效果(Canvas2D 条带近似),对照官方 shader:\r\n * vert: v_Direction = rotateVec2((0,1), θ) = (-sinθ, cosθ) ← 传播方向\r\n * frag: distance = t*speed + dot(uv, v_Direction)*scale\r\n * offset = (v_Direction.y, -v_Direction.x) = (cosθ, sinθ) ← 扰动方向\r\n * texCoord += sign(sin)^exp * |sin|^exp * strength² * offset * mask\r\n * 条带 = 等 phase 线(垂直 v_Direction,即沿 offset),带内沿 offset 整体平移;\r\n * 多个 waterwaves(ww1-ww4)扰动叠加;mask 限制扰动区域。\r\n */\r\nfunction applyWaterwaves(src: HTMLCanvasElement | ImageBitmap, w: number, h: number, waves: WaterwavesParams[], time: number, mask?: HTMLCanvasElement | ImageBitmap | null): HTMLCanvasElement {\r\n const c = document.createElement('canvas')\r\n c.width = w\r\n c.height = h\r\n const g = c.getContext('2d')\r\n if (g === null) return c\r\n // 主波(第一个)决定条带方向:扰动方向 offset = (cosθ, sinθ)\r\n const p0 = waves[0]\r\n const theta = p0.direction\r\n const offx = Math.cos(theta)\r\n const offy = Math.sin(theta)\r\n const bands = w * h > 900000 ? 32 : 48\r\n const horizontal = Math.abs(offx) >= Math.abs(offy)\r\n // mask 平均亮度(64×64 采样,每带一个值)\r\n let maskAvg: number[] | null = null\r\n if (mask !== null && mask !== undefined) {\r\n const mc = document.createElement('canvas')\r\n mc.width = 64\r\n mc.height = 64\r\n const mg = mc.getContext('2d')\r\n if (mg !== null) {\r\n mg.drawImage(mask, 0, 0, 64, 64)\r\n const img = mg.getImageData(0, 0, 64, 64)\r\n maskAvg = []\r\n for (let i = 0; i < bands; i++) {\r\n let sumR = 0\r\n let sumA = 0\r\n let cnt = 0\r\n if (horizontal) {\r\n const x0 = Math.floor((i / bands) * 64)\r\n const x1 = Math.max(x0 + 1, Math.floor(((i + 1) / bands) * 64))\r\n for (let x = x0; x < x1; x++) for (let y = 0; y < 64; y++) { sumR += img.data[(y * 64 + x) * 4]; sumA += img.data[(y * 64 + x) * 4 + 3]; cnt++ }\r\n } else {\r\n const y0 = Math.floor((i / bands) * 64)\r\n const y1 = Math.max(y0 + 1, Math.floor(((i + 1) / bands) * 64))\r\n for (let y = y0; y < y1; y++) for (let x = 0; x < 64; x++) { sumR += img.data[(y * 64 + x) * 4]; sumA += img.data[(y * 64 + x) * 4 + 3]; cnt++ }\r\n }\r\n // R8/RG88 解码为 alpha 语义(rgb=255, a=灰度):R 恒 255 → 用 A 通道;\r\n // RGBA8888 黑白 mask:用 R 通道\r\n const useA = sumR >= cnt * 254\r\n maskAvg.push(cnt > 0 ? (useA ? sumA : sumR) / cnt / 255 : 0)\r\n }\r\n }\r\n }\r\n if (horizontal) {\r\n // 扰动主要沿 x → 垂直条带(沿传播方向分段),带内 dx 平移\r\n const bw = w / bands\r\n for (let i = 0; i < bands; i++) {\r\n const x0 = i * bw\r\n const cx = (x0 + bw / 2) / w\r\n let disp = 0\r\n for (const p of waves) {\r\n const s = p.strength * p.strength\r\n const e = Math.max(0.5, Math.min(4, p.exponent))\r\n // 传播投影:dot(uv, v_Direction),v_Direction = (-sinθ, cosθ)\r\n const phase = time * p.speed + (cx * -Math.sin(p.direction) + 0.5 * Math.cos(p.direction)) * p.scale\r\n const val = Math.sin(phase)\r\n disp += Math.sign(val) * Math.pow(Math.abs(val), e) * s * Math.cos(p.direction) * w\r\n }\r\n disp *= maskAvg !== null ? maskAvg[i] : 1\r\n g.drawImage(src, x0, 0, bw + 0.5, h, x0 + disp, 0, bw + 0.5, h)\r\n }\r\n } else {\r\n // 扰动主要沿 y → 水平条带,带内 dy 平移\r\n const bh = h / bands\r\n for (let i = 0; i < bands; i++) {\r\n const y0 = i * bh\r\n const cy = (y0 + bh / 2) / h\r\n let disp = 0\r\n for (const p of waves) {\r\n const s = p.strength * p.strength\r\n const e = Math.max(0.5, Math.min(4, p.exponent))\r\n const phase = time * p.speed + (0.5 * -Math.sin(p.direction) + cy * Math.cos(p.direction)) * p.scale\r\n const val = Math.sin(phase)\r\n disp += Math.sign(val) * Math.pow(Math.abs(val), e) * s * Math.sin(p.direction) * h\r\n }\r\n disp *= maskAvg !== null ? maskAvg[i] : 1\r\n g.drawImage(src, 0, y0, w, bh + 0.5, 0, y0 + disp, w, bh + 0.5)\r\n }\r\n }\r\n return c\r\n}\r\n\r\nexport class SceneModelRenderer {\r\n private el: HTMLCanvasElement | null = null\r\n private ctx: CanvasRenderingContext2D | null = null\r\n private model: SceneModel | null = null\r\n private base: HTMLImageElement | null = null\r\n private layerTextures = new Map<number, ImageBitmap>()\r\n /** 效果 mask 纹理(waterwaves/shake opacitymask)+ 通道模式(true=R8 alpha 语义用 A) */\r\n private effectMasks = new Map<number, { bmp: ImageBitmap; useA: boolean; flowDir: [number, number] }>()\r\n /** WebGL waterwaves 渲染器(惰性创建) */\r\n private wwGL: WaterwavesGL | null = null\r\n /** 图层纹理的 Image 内容区域尺寸(tex 画布内左上角);无则用位图原生尺寸 */\r\n private layerTexImage = new Map<number, [number, number]>()\r\n /** 图层世界变换(递归 parent 合并;局部 y-up 翻转) */\r\n private worldTransform = new Map<number, { ox: number; oy: number; sx: number; sy: number }>()\r\n /** 图层 id → 图层(链式查找 puppet 祖先用) */\r\n private byId = new Map<number, SceneModelLayer>()\r\n private runtimes = new Map<number, ParticleRuntime>()\r\n private particleTextures = new Map<number, ImageBitmap | HTMLCanvasElement>()\r\n /** puppet 动画状态:puppet 图层 id → { 动画, 播放时间 } */\r\n private puppetAnims = new Map<number, { anim: PuppetAnimation; time: number }>()\r\n /** 每帧计算的动画变换:puppet 图层 id → 平移/旋转 */\r\n private animXform = new Map<number, { dx: number; dy: number; rot: number }>()\r\n /** puppet 网格离屏渲染缓存:图层 id → { canvas, 模型原点 } */\r\n private meshCanvases = new Map<number, { canvas: HTMLCanvasElement; originX: number; originY: number; animKey: string }>()\r\n private dpr = 1\r\n private live = false\r\n private closed = false\r\n private rafId = 0\r\n private lastT = 0\r\n /** 全局动画时间(秒,effects/粒子用) */\r\n private animTime = 0\r\n private blurPx = 0\r\n private scale = 1\r\n private monitor = ''\r\n private version = 0\r\n private handlers: SceneModelRendererHandlers\r\n\r\n constructor(handlers: SceneModelRendererHandlers = {}) {\r\n this.handlers = handlers\r\n }\r\n\r\n get isLive(): boolean {\r\n return this.live\r\n }\r\n\r\n start(monitor: string, version: number): void {\r\n this.stop()\r\n this.closed = false\r\n this.monitor = monitor\r\n this.version = version\r\n\r\n this.el = document.createElement('canvas')\r\n this.el.style.position = 'fixed'\r\n this.el.style.top = '0'\r\n this.el.style.left = '0'\r\n this.el.style.width = '100%'\r\n this.el.style.height = '100%'\r\n this.el.style.zIndex = '-2'\r\n this.el.style.pointerEvents = 'none'\r\n this.el.style.border = '0'\r\n document.body.appendChild(this.el)\r\n this.ctx = this.el.getContext('2d')\r\n this.resize()\r\n this.applyVisuals()\r\n\r\n window.addEventListener('resize', this.onResize)\r\n document.addEventListener('visibilitychange', this.onVisibility)\r\n\r\n void this.load()\r\n }\r\n\r\n stop(): void {\r\n this.closed = true\r\n if (this.rafId !== 0) { cancelAnimationFrame(this.rafId); this.rafId = 0 }\r\n window.removeEventListener('resize', this.onResize)\r\n document.removeEventListener('visibilitychange', this.onVisibility)\r\n if (this.el !== null) { this.el.remove(); this.el = null; this.ctx = null }\r\n this.model = null\r\n this.base = null\r\n for (const bmp of this.layerTextures.values()) { try { bmp.close() } catch { /* 忽略 */ } }\r\n this.layerTextures.clear()\r\n this.layerTexImage.clear()\r\n this.worldTransform.clear()\r\n this.byId.clear()\r\n this.puppetAnims.clear()\r\n this.animXform.clear()\r\n this.meshCanvases.clear()\r\n for (const v of this.effectMasks.values()) { try { if ('close' in v.bmp) v.bmp.close() } catch { /* 忽略 */ } }\r\n this.effectMasks.clear()\r\n if (this.wwGL !== null) { this.wwGL.dispose(); this.wwGL = null }\r\n for (const bmp of this.particleTextures.values()) { try { if ('close' in bmp) bmp.close() } catch { /* 忽略 */ } }\r\n this.particleTextures.clear()\r\n this.runtimes.clear()\r\n this.setLive(false)\r\n }\r\n\r\n applyVisuals(blurPx?: number, scale?: number): void {\r\n if (blurPx !== undefined) this.blurPx = blurPx\r\n if (scale !== undefined) this.scale = scale\r\n if (this.el !== null) {\r\n this.el.style.filter = 'blur(' + Math.round(this.blurPx) + 'px)'\r\n this.el.style.transform = 'scale(' + this.scale.toFixed(3) + ')'\r\n }\r\n }\r\n\r\n // ---- 数据加载 ----\r\n private async load(): Promise<void> {\r\n if (this.closed) return\r\n let model: SceneModel\r\n try {\r\n const res = await fetch('/we-sync/scene/model?monitor=' + encodeURIComponent(this.monitor) + '&v=' + this.version, { cache: 'no-store' })\r\n if (!res.ok) throw new Error('model ' + res.status)\r\n model = await res.json() as SceneModel\r\n } catch {\r\n this.fail()\r\n return\r\n }\r\n if (this.closed) return\r\n this.model = model\r\n this.byId.clear()\r\n for (const l of model.layers) this.byId.set(l.id, l)\r\n this.computeWorldTransforms()\r\n this.setLive(true)\r\n\r\n // 预览图打底(异步,不阻塞图层渲染)\r\n void this.loadBase(model)\r\n // 图层纹理:按候选顺序尝试(decodable jpg/png 优先,然后 .tex——\r\n // 路由会解码 .tex(内嵌图片或 raw LZ4+DXT → PNG);失败 → 该图层占位)\r\n const jobs: Array<Promise<void>> = []\r\n for (const layer of model.layers) {\r\n jobs.push(this.loadLayerTexture(layer))\r\n }\r\n // 粒子系统:创建运行时 + 加载粒子纹理(引擎资产 /we-sync/asset/texture)\r\n for (const layer of model.layers) {\r\n if (layer.particle !== null && layer.particle.textureNames.length > 0) {\r\n this.runtimes.set(layer.id, new ParticleRuntime(layer.particle, model.particleRateScale, model.particleSizeScale))\r\n jobs.push(this.loadParticleTexture(layer.id, layer.particle.textureNames[0]))\r\n }\r\n }\r\n // puppet 动画:所有带\"真实逐帧动画\"的层播放(装配根 alpha=0 锚点整体动画 +\r\n // 部件自身动画如头发/草/裙子摆动)。静态姿势表(帧值全同)跳过。\r\n for (const layer of model.layers) {\r\n if (layer.puppet === null || layer.puppet.animations.length === 0) continue\r\n const anim = layer.animationIds.length > 0\r\n ? layer.puppet.animations.find((a) => layer.animationIds.includes(a.id)) ?? layer.puppet.animations[0]\r\n : layer.puppet.animations[0]\r\n if (anim.keyframes.length < 2) continue\r\n // 静态姿势表检测:所有分量跨度 < 0.01 → 不播放\r\n const kf = anim.keyframes\r\n let maxSpan = 0\r\n for (let vi = 0; vi < 8; vi++) {\r\n let mn = Infinity\r\n let mx = -Infinity\r\n for (const k of kf) {\r\n const v = k.values[vi]\r\n if (!Number.isFinite(v)) continue\r\n if (v < mn) mn = v\r\n if (v > mx) mx = v\r\n }\r\n if (Number.isFinite(mn) && mx - mn > maxSpan) maxSpan = mx - mn\r\n }\r\n if (maxSpan < 0.01) continue\r\n this.puppetAnims.set(layer.id, { anim, time: 0 })\r\n }\r\n if (jobs.length > 0) await Promise.all(jobs)\r\n if (!this.closed) this.startAnimation()\r\n }\r\n\r\n /**\r\n * 递归合并 parent 层级变换(含 attachment 骨骼挂载)。\r\n * 顶层(无 parent):WE 场景坐标 **y 向上** → 屏幕 y = 场景高 - origin.y。\r\n * 子图层:局部坐标 y 向上,父 scale 施加于子的位移与尺寸。\r\n * attachment(如 \"head\"/\"Attachment\"):子层挂到 parent puppet 的具名骨骼,\r\n * 锚点 = parent 锚点 + 骨骼局部位置(y-up)+ 子层 origin。\r\n */\r\n private computeWorldTransforms(): void {\r\n const model = this.model\r\n if (model === null) return\r\n const H = model.height\r\n const byId = new Map<number, SceneModelLayer>()\r\n for (const l of model.layers) byId.set(l.id, l)\r\n const cache = new Map<number, { ox: number; oy: number; sx: number; sy: number }>()\r\n const walk = (l: SceneModelLayer): { ox: number; oy: number; sx: number; sy: number } => {\r\n const hit = cache.get(l.id)\r\n if (hit !== undefined) return hit\r\n let t: { ox: number; oy: number; sx: number; sy: number }\r\n const parent = l.parent !== null ? byId.get(l.parent) : undefined\r\n if (parent !== undefined) {\r\n const p = walk(parent)\r\n // attachment 骨骼局部位置(y-up 模型空间);父 scale 施加\r\n const bp = l.attachment !== null && parent.puppet !== null\r\n ? parent.puppet.bonePositions?.[l.attachment]\r\n : undefined\r\n t = {\r\n ox: p.ox + p.sx * (l.origin[0] + (bp !== undefined ? bp[0] : 0)),\r\n oy: p.oy - p.sy * (l.origin[1] + (bp !== undefined ? bp[1] : 0)),\r\n sx: p.sx * (l.scale[0] ?? 1),\r\n sy: p.sy * (l.scale[1] ?? 1),\r\n }\r\n } else {\r\n t = { ox: l.origin[0], oy: H - l.origin[1], sx: l.scale[0] ?? 1, sy: l.scale[1] ?? 1 }\r\n }\r\n cache.set(l.id, t)\r\n return t\r\n }\r\n for (const l of model.layers) walk(l)\r\n this.worldTransform = cache\r\n }\r\n\r\n private async loadParticleTexture(layerId: number, name: string): Promise<void> {\r\n try {\r\n const res = await fetch('/we-sync/asset/texture?name=' + encodeURIComponent(name), { cache: 'no-store' })\r\n if (!res.ok) return\r\n const blob = await res.blob()\r\n const bmp = await createImageBitmap(blob)\r\n if (this.closed) { bmp.close(); return }\r\n // 径向软边仅用于小尺寸点状纹理(雪花/光点,<128px),避免硬边方块叠加成白线;\r\n // 大片纹理(雾/风,如 fog3)自带羽化形状,软边遮罩会破坏形状\r\n let tex: HTMLCanvasElement | ImageBitmap = bmp\r\n if (bmp.width < 128 && bmp.height < 128) {\r\n tex = makeSoftTexture(bmp)\r\n bmp.close()\r\n }\r\n if (this.closed) return\r\n this.particleTextures.set(layerId, tex)\r\n } catch { /* 粒子纹理不可用:该粒子层不绘制 */ }\r\n }\r\n\r\n private async loadLayerTexture(layer: SceneModelLayer): Promise<void> {\r\n if (this.layerTextures.has(layer.id)) return\r\n const candidates = layer.decodableTexture !== null\r\n ? [layer.decodableTexture, ...layer.textureRefs.filter((t) => t !== layer.decodableTexture)]\r\n : layer.textureRefs\r\n for (const name of candidates) {\r\n if (this.closed) return\r\n const got = await this.fetchTexture(name)\r\n if (got === null) continue\r\n if (this.closed) { got.bmp.close(); return }\r\n this.layerTextures.set(layer.id, got.bmp)\r\n if (got.imgW > 0 && got.imgH > 0) this.layerTexImage.set(layer.id, [got.imgW, got.imgH])\r\n this.startAnimation()\r\n return\r\n }\r\n // 效果 mask 纹理(waterwaves/shake 的 opacitymask,独立于图层纹理)\r\n for (const e of layer.effects) {\r\n const m = e.type === 'waterwaves' || e.type === 'shake' ? e.mask : null\r\n if (m === null || this.effectMasks.has(layer.id)) continue\r\n try {\r\n const res = await fetch('/we-sync/scene/texture?monitor=' + encodeURIComponent(this.monitor) + '&name=' + encodeURIComponent(m), { cache: 'no-store' })\r\n if (!res.ok) continue\r\n const blob = await res.blob()\r\n const bmp = await createImageBitmap(blob)\r\n if (this.closed) { bmp.close(); return }\r\n // 通道判断:R8/RG88 解码为 alpha 语义(rgb=255, a=灰度)→ 用 A 通道;\r\n // shake 的 direction map(RG 方向场)→ 平均方向(flowDir)\r\n let useA = false\r\n let flowDir: [number, number] = [0, -1]\r\n try {\r\n const tc = document.createElement('canvas')\r\n tc.width = 16\r\n tc.height = 16\r\n const tg = tc.getContext('2d')\r\n if (tg !== null) {\r\n tg.drawImage(bmp, 0, 0, 16, 16)\r\n const px = tg.getImageData(0, 0, 16, 16)\r\n let all255 = true\r\n let sr = 0\r\n let sg = 0\r\n let n = 0\r\n for (let i = 0; i < px.data.length; i += 4) {\r\n if (px.data[i] < 254) all255 = false\r\n sr += px.data[i]\r\n sg += px.data[i + 1]\r\n n++\r\n }\r\n useA = all255\r\n if (!all255 && n > 0) {\r\n // direction map:flowMask = (rg - 0.498) * 2(官方语义)\r\n flowDir = [(sr / n / 255 - 0.498) * 2, (sg / n / 255 - 0.498) * 2]\r\n const len = Math.hypot(flowDir[0], flowDir[1])\r\n if (len > 0.01) { flowDir[0] /= len; flowDir[1] /= len }\r\n }\r\n }\r\n } catch { /* 通道判断失败:默认 R */ }\r\n this.effectMasks.set(layer.id, { bmp, useA, flowDir })\r\n this.startAnimation()\r\n } catch { /* mask 加载失败:无 mask 全图扰动 */ }\r\n }\r\n }\r\n\r\n private async fetchTexture(name: string): Promise<{ bmp: ImageBitmap; imgW: number; imgH: number } | null> {\r\n try {\r\n const res = await fetch('/we-sync/scene/texture?monitor=' + encodeURIComponent(this.monitor) + '&name=' + encodeURIComponent(name), { cache: 'no-store' })\r\n if (!res.ok) return null\r\n const blob = await res.blob()\r\n const bmp = await createImageBitmap(blob)\r\n const imgW = Number(res.headers.get('X-WE-Image-W'))\r\n const imgH = Number(res.headers.get('X-WE-Image-H'))\r\n return {\r\n bmp,\r\n imgW: Number.isFinite(imgW) && imgW > 0 ? imgW : bmp.width,\r\n imgH: Number.isFinite(imgH) && imgH > 0 ? imgH : bmp.height,\r\n }\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n private async loadBase(model: SceneModel): Promise<void> {\r\n try {\r\n const res = await fetch('/we-sync/preview?v=' + this.version, { cache: 'no-store' })\r\n if (!res.ok) return\r\n const blob = await res.blob()\r\n const img = new Image()\r\n img.src = URL.createObjectURL(blob)\r\n await new Promise<void>((resolve, reject) => { img.onload = () => resolve(); img.onerror = () => reject(new Error('preview decode')) })\r\n if (this.closed) { URL.revokeObjectURL(img.src); return }\r\n this.base = img\r\n this.startAnimation()\r\n } catch { /* 预览图不可用:用 clearcolor 打底 */ }\r\n }\r\n\r\n private fail(): void {\r\n this.setLive(false)\r\n this.closed = true\r\n }\r\n\r\n // ---- 渲染(持续动画循环) ----\r\n private startAnimation(): void {\r\n if (this.rafId === 0 && !document.hidden) {\r\n this.lastT = performance.now()\r\n this.rafId = requestAnimationFrame(this.draw)\r\n }\r\n }\r\n\r\n private draw = (): void => {\r\n this.rafId = 0\r\n if (this.closed || this.ctx === null || this.el === null) return\r\n const now = performance.now()\r\n const dt = Math.min(0.1, (now - this.lastT) / 1000)\r\n this.lastT = now\r\n this.animTime += dt\r\n // 更新粒子(动画)\r\n for (const rt of this.runtimes.values()) rt.update(dt)\r\n this.updatePuppetAnims(dt)\r\n this.renderScene()\r\n // 持续动画循环\r\n this.rafId = requestAnimationFrame(this.draw)\r\n }\r\n\r\n /**\r\n * 更新 puppet 动画 → 部件变换(装配根整体呼吸 + 部件自身摆动)。\r\n * 帧值布局(实测):[pos3][rotZ(v4)][scale3];v4 摆动 = 绕 z 旋转(呼吸/头发/草);\r\n * v0/v1(或 v6/v7,petal 类)变化 = 位置位移(相对首帧)。\r\n */\r\n private updatePuppetAnims(dt: number): void {\r\n this.animXform.clear()\r\n for (const [layerId, st] of this.puppetAnims) {\r\n st.time += dt\r\n const kf = st.anim.keyframes\r\n if (kf.length === 0) continue\r\n // 循环周期 = 目录项 duration(秒,官方时长);fallback t 峰值跨度\r\n // 异常数据(多骨骼动画/解析失败,周期异常大)跳过不播放\r\n let peak = 0\r\n for (let i = 1; i < kf.length; i++) if (kf[i].t > kf[peak].t) peak = i\r\n const period = kf[peak].t - kf[0].t\r\n if (period > 5_000_000) continue\r\n const dur = st.anim.duration > 0 ? st.anim.duration : 3\r\n const t = period > 0 ? (st.time * period) / dur : st.time * (kf.length - 1) / dur\r\n const s = samplePuppet(st.anim, t)\r\n if (s === null) continue\r\n const v = s.values\r\n const base = st.anim.keyframes[0].values\r\n // 每分量跨度(用于位置位移判定;每帧算一次成本低)\r\n const spans = [0, 0, 0, 0, 0, 0, 0, 0]\r\n for (let vi = 0; vi < 8; vi++) {\r\n let mn = Infinity\r\n let mx = -Infinity\r\n for (const k of kf) {\r\n const val = k.values[vi]\r\n if (!Number.isFinite(val)) continue\r\n if (val < mn) mn = val\r\n if (val > mx) mx = val\r\n }\r\n if (Number.isFinite(mn)) spans[vi] = mx - mn\r\n }\r\n // 旋转:quat 接近单位 → 四元数 z 旋转;否则 v4 直接作为角度\r\n const qx = v[3]\r\n const qy = v[4]\r\n const qz = v[5]\r\n const qw = v[6]\r\n const qlen2 = qx * qx + qy * qy + qz * qz + qw * qw\r\n let rot: number\r\n if (Math.abs(qlen2 - 1) < 0.05) {\r\n rot = 2 * Math.atan2(qz, qw)\r\n } else {\r\n rot = v[4]\r\n }\r\n // 位置位移:v0 = y(模型 y-up,bind 验证);v6/v7(petal 类)→ dx/dy\r\n let dx = 0\r\n let dy = 0\r\n if (spans[0] > 0.5) dy += v[0] - base[0]\r\n if (spans[6] > 0.5) dx += v[6] - base[6]\r\n if (spans[7] > 0.5) dy += v[7] - base[7]\r\n this.animXform.set(layerId, { dx, dy, rot })\r\n }\r\n }\r\n\r\n private renderScene(): void {\r\n const ctx = this.ctx\r\n if (ctx === null || this.el === null) return\r\n const cw = this.el.clientWidth\r\n const ch = this.el.clientHeight\r\n if (cw === 0 || ch === 0) return\r\n ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0)\r\n ctx.clearRect(0, 0, cw, ch)\r\n const model = this.model\r\n if (model === null) return\r\n\r\n // 打底:clearcolor → 预览图(cover 铺满画布)\r\n if (this.base !== null) {\r\n this.drawCoverBase(ctx, this.base, cw, ch)\r\n } else if (model.clearColor !== null) {\r\n ctx.fillStyle = 'rgb(' + Math.round(model.clearColor[0] * 255) + ',' + Math.round(model.clearColor[1] * 255) + ',' + Math.round(model.clearColor[2] * 255) + ')'\r\n ctx.fillRect(0, 0, cw, ch)\r\n }\r\n\r\n // 场景坐标 → 画布:cover 映射(场景空间 0..w × 0..h,y 向下)\r\n const s = Math.max(cw / model.width, ch / model.height)\r\n const ox = (cw - model.width * s) / 2\r\n const oy = (ch - model.height * s) / 2\r\n\r\n // 图层(scene.json 数组顺序 = z-order)\r\n for (const layer of model.layers) {\r\n if (!layer.visible || layer.alpha <= 0) continue\r\n const t = this.worldTransform.get(layer.id)\r\n // puppet 动画:层自身动画绕自身锚点旋转/位移;否则绕最近的带动画祖先锚点旋转\r\n let ax = 0\r\n let ay = 0\r\n let arot = 0\r\n const selfXf = this.animXform.get(layer.id)\r\n if (selfXf !== undefined && t !== undefined) {\r\n ax = selfXf.dx\r\n ay = -selfXf.dy // 模型 y-up → 屏幕 y-down\r\n arot = selfXf.rot\r\n } else if (layer.parent !== null) {\r\n let anchorId: number | null = null\r\n let p: number | null = layer.parent\r\n while (p !== null && this.byId.has(p)) {\r\n if (this.animXform.has(p)) { anchorId = p; break }\r\n p = this.byId.get(p)?.parent ?? null\r\n }\r\n if (anchorId !== null && t !== undefined) {\r\n const xf = this.animXform.get(anchorId)\r\n const pt = this.worldTransform.get(anchorId)\r\n if (xf !== undefined && pt !== undefined) {\r\n const relx = t.ox - pt.ox\r\n const rely = t.oy - pt.oy\r\n const c = Math.cos(xf.rot)\r\n const sn = Math.sin(xf.rot)\r\n ax = pt.ox + c * relx - sn * rely - t.ox\r\n ay = pt.oy + sn * relx + c * rely - t.oy\r\n arot = xf.rot\r\n }\r\n }\r\n }\r\n const px = ox + ((t !== undefined ? t.ox : layer.origin[0]) + ax) * s\r\n const py = oy + ((t !== undefined ? t.oy : layer.origin[1]) + ay) * s\r\n // 粒子层:运行时绘制(additive sprite)\r\n const rt = this.runtimes.get(layer.id)\r\n const ptex = this.particleTextures.get(layer.id)\r\n if (rt !== undefined && ptex !== undefined) {\r\n const wt = t ?? { ox: layer.origin[0], oy: layer.origin[1], sx: layer.scale[0] ?? 1, sy: layer.scale[1] ?? 1 }\r\n rt.draw(ctx, ox, oy, s, wt, ptex)\r\n continue\r\n }\r\n ctx.save()\r\n ctx.translate(px, py)\r\n // 动画部件:旋转锚点 = 骨骼 0 bind 位置(模型空间 → 局部,y 翻转),\r\n // 官方骨骼旋转绕骨骼原点而非图层中心\r\n const animB0 = selfXf !== undefined && layer.puppet !== null ? layer.puppet.bones[0]?.bind ?? null : null\r\n const rotAngle = ((layer.angles[2] ?? 0) * Math.PI / 180) + arot\r\n if (animB0 !== null && animB0.length >= 15 && rotAngle !== 0) {\r\n const sxv = (t !== undefined ? t.sx : layer.scale[0] ?? 1) * s\r\n const syv = (t !== undefined ? t.sy : layer.scale[1] ?? 1) * s\r\n const bx = animB0[12] * sxv\r\n const by = -animB0[13] * syv\r\n ctx.translate(bx, by)\r\n ctx.rotate(rotAngle)\r\n ctx.translate(-bx, -by)\r\n } else {\r\n ctx.rotate(rotAngle)\r\n }\r\n ctx.scale((t !== undefined ? t.sx : layer.scale[0] ?? 1) * s, (t !== undefined ? t.sy : layer.scale[1] ?? 1) * s)\r\n if (layer.alpha < 1) ctx.globalAlpha = Math.max(0, Math.min(1, layer.alpha))\r\n const bmp = this.layerTextures.get(layer.id) ?? null\r\n // puppet 网格蒙皮渲染(实验开关;模型空间顶点 → 离屏 canvas → 场景变换)\r\n if (model.puppetMeshRender && layer.puppet !== null && layer.puppet.mesh !== null && bmp !== null) {\r\n // 动画部件:每帧按当前 root 骨骼旋转重建(蒙皮:绕骨骼 0 bind 位置旋转)\r\n const selfXf2 = this.animXform.get(layer.id)\r\n const b0 = layer.puppet.bones[0]?.bind ?? null\r\n const animSkin = selfXf2 !== undefined && b0 !== null && b0.length >= 15\r\n ? { rot: selfXf2.rot, bx: b0[12], by: b0[13] } as const\r\n : null\r\n const key = layer.id + ':' + (animSkin !== null ? animSkin.rot.toFixed(4) : 'static')\r\n let mc = this.meshCanvases.get(layer.id)\r\n if (mc === undefined || mc.animKey !== key) {\r\n const built = buildMeshCanvas(layer.puppet.mesh, bmp, animSkin)\r\n mc = { canvas: built.canvas, originX: built.originX, originY: built.originY, animKey: key }\r\n this.meshCanvases.set(layer.id, mc)\r\n }\r\n ctx.drawImage(mc.canvas, -mc.originX, -mc.originY)\r\n } else if (bmp !== null) {\r\n // 源 = 纹理 Image 内容区域(画布左上角);目标 = 图层 size(缺省用 Image 尺寸)\r\n const ti = this.layerTexImage.get(layer.id)\r\n const sw = ti !== undefined ? ti[0] : bmp.width\r\n const sh = ti !== undefined ? ti[1] : bmp.height\r\n const dw = layer.size !== null ? layer.size[0] : sw\r\n const dh = layer.size !== null ? layer.size[1] : sh\r\n // 图层效果:waterwaves(逐像素 UV 场扰动,多个 ww 叠加)/ shake(整体平移)\r\n const effScale = model.effectStrengthScale ?? 1\r\n const wws = layer.effects\r\n .filter((e): e is Extract<LayerEffect, { type: 'waterwaves' }> => e.type === 'waterwaves')\r\n .map((e) => ({ ...e, strength: e.strength * effScale }))\r\n const shk = layer.effects.find((e) => e.type === 'shake')\r\n if (wws.length > 0) {\r\n const maskInfo = this.effectMasks.get(layer.id)\r\n let eff: HTMLCanvasElement | null = null\r\n // WebGL 逐像素 UV 场扰动(独立实现的数学等价 shader);不可用时回退条带近似\r\n if (this.wwGL !== null || WaterwavesGL.available) {\r\n if (this.wwGL === null) this.wwGL = new WaterwavesGL()\r\n eff = this.wwGL.render(bmp, sw, sh, maskInfo !== undefined ? maskInfo.bmp : null, maskInfo !== undefined ? maskInfo.useA : false, wws, this.animTime, String(layer.id))\r\n }\r\n if (eff === null) {\r\n eff = applyWaterwaves(bmp, sw, sh, wws, this.animTime, maskInfo !== undefined ? maskInfo.bmp : null)\r\n }\r\n ctx.drawImage(eff, 0, 0, sw, sh, -dw / 2, -dh / 2, dw, dh)\r\n } else if (shk !== undefined && shk.type === 'shake') {\r\n // 官方 shake:offset = sin(speed×t)(标量波形),位移 = offset × strength² × flow 方向\r\n // (direction map 平均;无 flow 默认垂直)——单向位移,非圆周\r\n const maskInfo2 = this.effectMasks.get(layer.id)\r\n const fd = maskInfo2 !== undefined ? maskInfo2.flowDir : [0, -1]\r\n const offset = Math.sin(this.animTime * shk.speed)\r\n const amp = shk.strength * shk.strength * effScale\r\n const dx = offset * amp * fd[0] * dw\r\n const dy = offset * amp * fd[1] * dh\r\n ctx.drawImage(bmp, 0, 0, sw, sh, -dw / 2 + dx, -dh / 2 + dy, dw, dh)\r\n } else {\r\n ctx.drawImage(bmp, 0, 0, sw, sh, -dw / 2, -dh / 2, dw, dh)\r\n }\r\n } else {\r\n // 占位标记(effect/composelayer/无纹理图层):极小圆点,避免像\"错误控件\"\r\n ctx.fillStyle = 'rgba(120, 170, 255, 0.5)'\r\n ctx.beginPath()\r\n ctx.arc(0, 0, 3, 0, Math.PI * 2)\r\n ctx.fill()\r\n }\r\n ctx.restore()\r\n // 图层名标注(画布坐标,保证可读)\r\n ctx.font = '10px system-ui, sans-serif'\r\n ctx.textBaseline = 'top'\r\n ctx.fillStyle = 'rgba(255,255,255,0.85)'\r\n ctx.strokeStyle = 'rgba(0,0,0,0.55)'\r\n const label = '#' + layer.id + ' ' + layer.name + ' [' + layer.kind + (this.layerTextures.has(layer.id) ? ' tex' : '') + ']'\r\n ctx.lineWidth = 3\r\n ctx.strokeText(label, px + 6, py + 6)\r\n ctx.fillText(label, px + 6, py + 6)\r\n }\r\n\r\n // 场景边界框(诊断用)\r\n ctx.strokeStyle = 'rgba(255,255,255,0.28)'\r\n ctx.lineWidth = 1\r\n ctx.strokeRect(ox, oy, model.width * s, model.height * s)\r\n }\r\n\r\n private drawCoverBase(ctx: CanvasRenderingContext2D, img: HTMLImageElement, cw: number, ch: number): void {\r\n const iw = img.naturalWidth\r\n const ih = img.naturalHeight\r\n if (iw === 0 || ih === 0) return\r\n const s = Math.max(cw / iw, ch / ih)\r\n const sw = cw / s\r\n const sh = ch / s\r\n ctx.drawImage(img, (iw - sw) / 2, (ih - sh) / 2, sw, sh, 0, 0, cw, ch)\r\n }\r\n\r\n private resize(): void {\r\n if (this.el === null) return\r\n this.dpr = window.devicePixelRatio || 1\r\n const w = Math.max(1, Math.round(this.el.clientWidth * this.dpr))\r\n const h = Math.max(1, Math.round(this.el.clientHeight * this.dpr))\r\n if (this.el.width !== w) this.el.width = w\r\n if (this.el.height !== h) this.el.height = h\r\n }\r\n\r\n private onResize = (): void => {\r\n this.resize()\r\n // 动画循环每帧重绘,resize 后下一帧即生效\r\n }\r\n\r\n private onVisibility = (): void => {\r\n if (document.hidden) {\r\n if (this.rafId !== 0) { cancelAnimationFrame(this.rafId); this.rafId = 0 }\r\n } else {\r\n this.startAnimation()\r\n }\r\n }\r\n\r\n private setLive(live: boolean): void {\r\n if (this.live === live) return\r\n this.live = live\r\n if (this.handlers.onLiveChange !== undefined) this.handlers.onLiveChange(live)\r\n }\r\n}\r\n","/**\r\n * dsh-wallpaper_share · browser half(内部 id / 路由前缀仍为 we-sync)\r\n * 玻璃面板主题覆盖 + 壁纸背景层 + wallpaper_share 会话视图标签页。\r\n * 与 node half 通过同源 HTTP 路由(/we-sync/state、/we-sync/preview、\r\n * /we-sync/source、/we-sync/scene)通信,不依赖任何 RPC 基础设施。\r\n * 多显示器:?monitor= 锁定某台;不传则跟随\"最近变化\"的一台。\r\n */\r\nimport { WallpaperSharePanel } from './WallpaperSharePanel.tsx'\r\nimport { PANEL_CSS } from './panelStyle.ts'\r\nimport { SceneCanvas } from './SceneCanvas.ts'\r\nimport { SceneModelRenderer } from './SceneModelRenderer.ts'\r\n\r\nexport const inject = ['slots', 'theme']\r\n\r\nexport interface WeSyncMonitor {\r\n key: string\r\n file: string\r\n title: string\r\n type: string\r\n}\r\n\r\nexport interface WeSyncInfo {\r\n version: number\r\n kind: string\r\n hash: string\r\n monitor: string\r\n latestMonitor: string\r\n monitors: WeSyncMonitor[]\r\n wallpaper: null | { title: string; type: string }\r\n /** 当前生效显示器的源文件类型('video' | 'web' | 'scene' | 'application' | 'image' | 'other' | '');\r\n * scene 表示增强模式下已从 scene.pkg 提取出可用的内嵌纹理 */\r\n source: { kind: string; mime: string; scene: boolean }\r\n /** scene 增强状态:renderer 是否可用/在跑、纹理是否存在、渲染模式、当前 fallback 层(来自 node half) */\r\n scene: null | {\r\n live: boolean\r\n available: boolean\r\n version: string\r\n texture: boolean\r\n fallback: string\r\n /** 'browser' = 浏览器子集渲染器(SceneModelRenderer);'external' = 外部 renderer(WS 帧流) */\r\n mode?: 'browser' | 'external'\r\n /** 浏览器子集渲染器能否拿到 SceneModel */\r\n model?: boolean\r\n status?: { state: string; fps?: number; frameIndex?: number; restarts?: number; lastError?: string }\r\n }\r\n /** 壁纸源服务器端口(web 壁纸 iframe 用);0 = 不可用(回退旧代理) */\r\n webPort: number\r\n}\r\n\r\nexport interface WeSyncSettings {\r\n enabled: boolean\r\n panelAlpha: number\r\n blur: number\r\n shadow: number\r\n /** 锁定的显示器 key;'' = 自动(跟随最近变化) */\r\n monitor: string\r\n /** 专注模式开关 */\r\n focus: boolean\r\n /** 当前会话是否有任务在进行(由 sessions 列表快照推导) */\r\n taskActive: boolean\r\n /** 渲染模式:'preview' 性能(预览图)| 'source' 增强(壁纸源文件) */\r\n renderMode: 'preview' | 'source'\r\n /** 沉浸模式:隐藏对话 chrome(上边栏 + 输入框),并把 web 壁纸 iframe 置顶解锁鼠标交互 */\r\n immersive: boolean\r\n /** 是否有待用户授权的请求(黄色状态信号) */\r\n approvalPending: boolean\r\n}\r\n\r\n/** 专注模式:任务进行中 */\r\nexport const FOCUS_WORK = { panelAlpha: 30, blur: 15, shadow: 90 }\r\n/** 专注模式:任务全部完成 */\r\nexport const FOCUS_IDLE = { panelAlpha: 9, blur: 6, shadow: 40 }\r\n\r\n/** 当前生效的视觉参数(专注模式覆盖用户滑块值) */\r\nexport function effectiveVisuals(): { panelAlpha: number; blur: number; shadow: number } {\r\n if (store.settings.focus) return store.settings.taskActive ? FOCUS_WORK : FOCUS_IDLE\r\n return { panelAlpha: store.settings.panelAlpha, blur: store.settings.blur, shadow: store.settings.shadow }\r\n}\r\n\r\n/** 包内单例 store:apply 循环更新,面板组件订阅渲染。 */\r\nexport const store = {\r\n info: null as WeSyncInfo | null,\r\n settings: { enabled: true, panelAlpha: 72, blur: 6, shadow: 30, monitor: '', focus: false, taskActive: false, renderMode: 'preview', immersive: false, approvalPending: false } as WeSyncSettings,\r\n listeners: new Set<() => void>(),\r\n actions: {\r\n applyTheme: (): void => {},\r\n applyBackground: (): void => {},\r\n applyImmersive: (): void => {},\r\n repoll: (): void => {},\r\n },\r\n subscribe(fn: () => void): () => void {\r\n store.listeners.add(fn)\r\n return () => { store.listeners.delete(fn) }\r\n },\r\n notify(): void {\r\n for (const fn of store.listeners) fn()\r\n },\r\n}\r\n\r\ninterface ThemeService {\r\n overrideTokens(source: string, tokens: Record<string, { light: string; dark: string }>): () => void\r\n}\r\n\r\ninterface SlotsService {\r\n inject(key: string, callback: () => unknown): unknown\r\n register(registration: unknown, render: unknown): unknown\r\n}\r\n\r\ninterface SessionsService {\r\n list: {\r\n getSnapshot(): { current?: string; byId: Record<string, { running?: boolean; blank?: boolean }> } | null\r\n subscribe(fn: () => void): () => void\r\n }\r\n}\r\n\r\ninterface WorkspacesService {\r\n startSession(workspaceId?: string): void\r\n}\r\n\r\n/** 最小化的 Cordis 上下文结构(独立构建不依赖 @deepseek-ai/cordis 的类型包) */\r\ninterface CordisCtx {\r\n get(name: string): unknown\r\n effect(callback: () => (() => void) | void): void\r\n}\r\n\r\nexport function apply(ctx: CordisCtx): void {\r\n const theme = ctx.get('theme') as unknown as ThemeService | undefined\r\n const slots = ctx.get('slots') as unknown as SlotsService | undefined\r\n if (theme === undefined || slots === undefined) return\r\n\r\n const sessions = ctx.get('sessions') as unknown as SessionsService | undefined\r\n const workspaces = ctx.get('workspaces') as unknown as WorkspacesService | undefined\r\n\r\n const themeService = theme\r\n const slotsService = slots\r\n\r\n let themeDisposer: (() => void) | null = null\r\n function applyTheme(): void {\r\n if (themeDisposer !== null) { themeDisposer(); themeDisposer = null }\r\n const a = 0.30 + (effectiveVisuals().panelAlpha / 100) * 0.60\r\n const dark: Record<string, string> = {\r\n '--dsw-alias-bg-base': 'rgba(15,16,20,' + a.toFixed(3) + ')',\r\n '--dsw-alias-bg-layer-1': 'rgba(24,26,32,' + (a * 0.95).toFixed(3) + ')',\r\n '--dsw-alias-bg-layer-2': 'rgba(31,33,40,' + (a * 0.90).toFixed(3) + ')',\r\n '--dsw-alias-bg-overlay': 'rgba(22,24,29,' + Math.min(a + 0.12, 0.96).toFixed(3) + ')',\r\n '--dsw-specific-sidebar-fill': 'rgba(13,14,17,' + (a * 0.92).toFixed(3) + ')',\r\n }\r\n const light: Record<string, string> = {\r\n '--dsw-alias-bg-base': 'rgba(246,247,250,' + Math.min(a + 0.10, 0.95).toFixed(3) + ')',\r\n '--dsw-alias-bg-layer-1': 'rgba(255,255,255,' + (a * 0.95).toFixed(3) + ')',\r\n '--dsw-alias-bg-layer-2': 'rgba(251,252,253,' + (a * 0.90).toFixed(3) + ')',\r\n '--dsw-alias-bg-overlay': 'rgba(255,255,255,' + Math.min(a + 0.14, 0.97).toFixed(3) + ')',\r\n '--dsw-specific-sidebar-fill': 'rgba(238,240,244,' + (a * 0.92).toFixed(3) + ')',\r\n }\r\n const tokens: Record<string, { light: string; dark: string }> = {}\r\n for (const key of Object.keys(dark)) tokens[key] = { light: light[key] ?? '', dark: dark[key] ?? '' }\r\n themeDisposer = themeService.overrideTokens('we-sync', tokens)\r\n }\r\n\r\n const styleTag = document.createElement('style')\r\n styleTag.dataset.plugin = 'dsh-wallpaper_share'\r\n document.head.appendChild(styleTag)\r\n\r\n const panelStyleTag = document.createElement('style')\r\n panelStyleTag.dataset.plugin = 'dsh-wallpaper_share'\r\n panelStyleTag.textContent = PANEL_CSS\r\n document.head.appendChild(panelStyleTag)\r\n\r\n // 增强模式媒体层:视频或 iframe(性能模式不创建)\r\n let mediaEl: HTMLVideoElement | HTMLIFrameElement | null = null\r\n\r\n // scene 动态背景层:live canvas(外部 renderer 出帧,mode=external)\r\n let sceneCanvas: SceneCanvas | null = null\r\n function stopSceneCanvas(): void {\r\n if (sceneCanvas !== null) { sceneCanvas.stop(); sceneCanvas = null }\r\n }\r\n\r\n // scene 浏览器子集渲染器(mode=browser:真实图层树 + transform 合成)\r\n let sceneModelRenderer: SceneModelRenderer | null = null\r\n function stopSceneModelRenderer(): void {\r\n if (sceneModelRenderer !== null) { sceneModelRenderer.stop(); sceneModelRenderer = null }\r\n }\r\n function stopSceneLayers(): void {\r\n stopSceneCanvas()\r\n stopSceneModelRenderer()\r\n }\r\n\r\n function setMedia(el: HTMLVideoElement | HTMLIFrameElement | null): void {\r\n if (mediaEl !== null && mediaEl !== el) {\r\n if (mediaEl instanceof HTMLVideoElement) mediaEl.pause()\r\n mediaEl.remove()\r\n }\r\n mediaEl = el\r\n if (el !== null) {\r\n el.style.position = 'fixed'\r\n el.style.top = '0'\r\n el.style.left = '0'\r\n el.style.width = '100%'\r\n el.style.height = '100%'\r\n el.style.zIndex = '-2'\r\n el.style.pointerEvents = 'none'\r\n el.style.border = '0'\r\n document.body.appendChild(el)\r\n }\r\n }\r\n\r\n // —— 沉浸模式:隐藏对话 chrome(上边栏 + 输入框),并把 web iframe 置顶解锁鼠标 ——\r\n const immersiveStyleTag = document.createElement('style')\r\n immersiveStyleTag.dataset.plugin = 'dsh-wallpaper_share'\r\n document.head.appendChild(immersiveStyleTag)\r\n\r\n // 球形状态按钮:侧边栏收起时出现在左缘(搜索下方),点击切换沉浸模式,颜色随状态变化\r\n const orbBtn = document.createElement('button')\r\n orbBtn.type = 'button'\r\n orbBtn.title = ''\r\n orbBtn.style.cssText = 'position:fixed;left:11px;top:232px;width:34px;height:34px;border-radius:50%;border:3px solid rgba(255,255,255,0.4);cursor:pointer;z-index:2147483001;opacity:0;visibility:hidden;background:rgba(15,16,20,0.4);box-shadow:0 2px 8px rgba(0,0,0,0.45);outline:none;transition:opacity 0.25s ease, visibility 0.25s ease, border-color 0.25s ease;'\r\n document.body.appendChild(orbBtn)\r\n\r\n const STATUS_COLORS = { approval: '#eab308', running: '#3b82f6', idle: '#22c55e' }\r\n\r\n function syncStatus(): void {\r\n // 优先级:待授权(黄) > 任务进行中(蓝) > 空闲(绿)\r\n const approval = document.querySelector('[data-approval-key]') !== null\r\n if (approval !== store.settings.approvalPending) {\r\n store.settings.approvalPending = approval\r\n store.notify()\r\n }\r\n const color = approval ? STATUS_COLORS.approval : (store.settings.taskActive ? STATUS_COLORS.running : STATUS_COLORS.idle)\r\n orbBtn.style.borderColor = color\r\n orbBtn.title = approval ? '等待授权' : (store.settings.taskActive ? '任务进行中' : '空闲')\r\n // 仅在侧边栏收起时显示球形按钮(opacity/visibility 过渡动画)\r\n const sidebarCollapsed = document.querySelector('[data-sidebar-collapsed]') !== null\r\n orbBtn.style.opacity = sidebarCollapsed ? '1' : '0'\r\n orbBtn.style.visibility = sidebarCollapsed ? 'visible' : 'hidden'\r\n }\r\n\r\n function applyImmersive(): void {\r\n const on = store.settings.immersive\r\n immersiveStyleTag.textContent = on\r\n ? '[data-phase] > header, [data-composer-seat] { opacity: 0 !important; pointer-events: none !important; transition: opacity 0.3s ease !important; }'\r\n : ''\r\n if (mediaEl instanceof HTMLIFrameElement) {\r\n // 沉浸时置顶,但不遮住侧边栏(左缘 56px rail),保留侧边栏与球形按钮可点\r\n mediaEl.style.zIndex = on ? '2147483000' : '-2'\r\n mediaEl.style.pointerEvents = on ? 'auto' : 'none'\r\n mediaEl.style.left = on ? '56px' : '0'\r\n mediaEl.style.width = on ? 'calc(100% - 56px)' : '100%'\r\n }\r\n }\r\n orbBtn.addEventListener('click', () => {\r\n if (!store.settings.immersive) {\r\n // 进入沉浸前:若当前不是新会话页面,先切到新会话\r\n const snap = sessions?.list.getSnapshot()\r\n const id = snap?.current\r\n const isBlank = id === undefined || (snap != null && snap.byId[id]?.blank === true)\r\n if (!isBlank && typeof workspaces?.startSession === 'function') {\r\n workspaces.startSession()\r\n }\r\n }\r\n store.settings.immersive = !store.settings.immersive\r\n applyImmersive()\r\n store.notify()\r\n })\r\n // 侧边栏收起时,点击其中任意按钮都退出沉浸\r\n function onDocClick(ev: MouseEvent): void {\r\n if (!store.settings.immersive) return\r\n const frame = document.querySelector('[data-sidebar-collapsed]')\r\n if (frame === null) return\r\n const sidebarCol = frame.firstElementChild\r\n if (sidebarCol === null) return\r\n const target = ev.target\r\n if (target instanceof Element) {\r\n const btn = target.closest('button')\r\n if (btn !== null && sidebarCol.contains(btn)) {\r\n store.settings.immersive = false\r\n applyImmersive()\r\n store.notify()\r\n }\r\n }\r\n }\r\n document.addEventListener('click', onDocClick, true)\r\n function onImmersiveKey(ev: KeyboardEvent): void {\r\n if (ev.key === 'Escape' && store.settings.immersive) { store.settings.immersive = false; applyImmersive(); store.notify() }\r\n }\r\n document.addEventListener('keydown', onImmersiveKey)\r\n\r\n // 状态同步:观察审批面板出现/消失 + 侧边栏收起状态,更新球形按钮颜色与显隐\r\n syncStatus()\r\n let statusRaf: number | null = null\r\n const scheduleSync = (): void => {\r\n if (statusRaf !== null) return\r\n statusRaf = requestAnimationFrame(() => { statusRaf = null; syncStatus() })\r\n }\r\n const statusObserver = new MutationObserver(() => { scheduleSync() })\r\n statusObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['data-sidebar-collapsed'] })\r\n\r\n function applyBackground(): void {\r\n const info = store.info\r\n const visuals = effectiveVisuals()\r\n const enabled = store.settings.enabled\r\n const blurPx = Math.round(visuals.blur)\r\n const scale = 1 + blurPx / 400\r\n const shadowAlpha = (visuals.shadow / 100) * 0.60\r\n const monitorKey = info !== null && info.monitor !== '' ? info.monitor : ''\r\n const monitorQuery = store.settings.monitor !== '' ? '&monitor=' + encodeURIComponent(store.settings.monitor) : ''\r\n const rawSourceKind = enabled && info !== null && store.settings.renderMode === 'source' ? info.source.kind : ''\r\n // scene:renderer 可用 或 已提取纹理 → 走 scene 增强;两者皆无 → 回退预览\r\n const sceneEnhance = rawSourceKind === 'scene' && info !== null && (info.scene?.available === true || info.source.scene === true)\r\n const sourceKind = rawSourceKind === 'video' || rawSourceKind === 'web' || rawSourceKind === 'image' || sceneEnhance ? rawSourceKind : ''\r\n\r\n // 增强模式背景:image/scene 走专用路由;性能模式 / 提取失败回退静态预览\r\n let imgUrl = 'none'\r\n if (enabled && info !== null) {\r\n if (sourceKind === 'image') {\r\n imgUrl = 'url(\"/we-sync/source?monitor=' + encodeURIComponent(monitorKey) + '&v=' + info.version + '\")'\r\n } else if (sourceKind === 'scene') {\r\n // 纹理始终垫底(canvas 出帧前 / renderer 失败时可见);无纹理则垫预览\r\n imgUrl = info.source.scene\r\n ? 'url(\"/we-sync/scene?monitor=' + encodeURIComponent(monitorKey) + '&v=' + info.version + '\")'\r\n : 'url(\"/we-sync/preview?v=' + info.version + monitorQuery + '\")'\r\n } else if (sourceKind === '' && info.kind === 'image') {\r\n imgUrl = 'url(\"/we-sync/preview?v=' + info.version + monitorQuery + '\")'\r\n }\r\n }\r\n\r\n styleTag.textContent =\r\n 'html { background-color: #0d0e12; }' +\r\n (imgUrl !== 'none'\r\n ? 'body::before { content: \"\"; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: -2; ' +\r\n 'background-image: ' + imgUrl + '; background-size: cover; background-position: center; background-repeat: no-repeat; ' +\r\n 'filter: blur(' + blurPx + 'px); transform: scale(' + scale.toFixed(3) + '); transition: filter 0.12s linear; }'\r\n : '') +\r\n 'body::after { content: \"\"; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: -1; ' +\r\n 'background: linear-gradient(rgba(6,8,12,' + shadowAlpha.toFixed(3) + '), rgba(6,8,12,' + (shadowAlpha * 0.85).toFixed(3) + ')); }'\r\n\r\n if (sourceKind === 'scene' && info !== null) {\r\n const sceneMode = info.scene?.mode === 'external' ? 'external' : 'browser'\r\n if (sceneMode === 'external' && info.scene?.available === true) {\r\n // 外部 renderer:live canvas(WS 帧流),出帧覆盖在纹理垫底之上;连接失败自动回退\r\n if (sceneCanvas === null) sceneCanvas = new SceneCanvas()\r\n sceneCanvas.applyVisuals(blurPx, scale)\r\n sceneCanvas.start(monitorKey, info.version)\r\n stopSceneModelRenderer()\r\n } else if (sceneMode === 'browser') {\r\n // 浏览器子集渲染器:真实 scene.json 图层树 + transform 合成(Phase 1 最小切片)\r\n if (sceneModelRenderer === null) sceneModelRenderer = new SceneModelRenderer()\r\n sceneModelRenderer.applyVisuals(blurPx, scale)\r\n sceneModelRenderer.start(monitorKey, info.version)\r\n stopSceneCanvas()\r\n } else {\r\n stopSceneLayers()\r\n }\r\n setMedia(null)\r\n } else if (sourceKind === 'video' && info !== null) {\r\n let video = mediaEl instanceof HTMLVideoElement ? mediaEl : null\r\n if (video === null) {\r\n video = document.createElement('video')\r\n video.muted = true\r\n video.loop = true\r\n video.playsInline = true\r\n video.autoplay = true\r\n setMedia(video)\r\n }\r\n const src = '/we-sync/source?monitor=' + encodeURIComponent(monitorKey) + '&v=' + info.version\r\n if (video.src !== location.origin + src) video.src = src\r\n video.style.filter = 'blur(' + blurPx + 'px)'\r\n video.style.transform = 'scale(' + scale.toFixed(3) + ')'\r\n video.style.objectFit = 'cover'\r\n const p = video.play()\r\n if (p !== undefined && p !== null) void p.catch(() => { /* 自动播放被浏览器拦截时静默 */ })\r\n } else if (sourceKind === 'web' && info !== null) {\r\n let frame = mediaEl instanceof HTMLIFrameElement ? mediaEl : null\r\n if (frame === null) {\r\n frame = document.createElement('iframe')\r\n // 壁纸源服务器提供独立同源:allow-same-origin 指壁纸自己的源(127.0.0.1:webPort),\r\n // 与 DSH 主源(3080)隔离;WebGL 贴图因此不被 tainted,module/fetch/import 全通\r\n frame.setAttribute('sandbox', 'allow-scripts allow-same-origin')\r\n setMedia(frame)\r\n }\r\n const src = typeof info.webPort === 'number' && info.webPort > 0\r\n ? 'http://127.0.0.1:' + info.webPort + '/index.html?monitor=' + encodeURIComponent(monitorKey) + '&v=' + info.version\r\n : location.origin + '/we-sync/wallpaper/index.html?monitor=' + encodeURIComponent(monitorKey) + '&v=' + info.version\r\n if (frame.src !== src) frame.src = src\r\n frame.style.filter = 'blur(' + blurPx + 'px)'\r\n } else {\r\n stopSceneLayers()\r\n setMedia(null)\r\n }\r\n applyImmersive()\r\n }\r\n\r\n let polling = false\r\n let lastHash = ''\r\n let lastWebPort = -1\r\n async function poll(): Promise<void> {\r\n if (polling) return\r\n polling = true\r\n try {\r\n const monitorQuery = store.settings.monitor !== '' ? '?monitor=' + encodeURIComponent(store.settings.monitor) : ''\r\n const res = await fetch('/we-sync/state' + monitorQuery, { cache: 'no-store' })\r\n if (!res.ok) return\r\n const info = await res.json() as WeSyncInfo\r\n const changed = typeof info.hash === 'string' && info.hash !== lastHash\r\n const portChanged = typeof info.webPort === 'number' && info.webPort !== lastWebPort\r\n store.info = info\r\n store.notify()\r\n if (changed || portChanged) {\r\n lastHash = typeof info.hash === 'string' ? info.hash : lastHash\r\n lastWebPort = typeof info.webPort === 'number' ? info.webPort : lastWebPort\r\n applyBackground()\r\n }\r\n } catch { /* host 尚未就绪,下轮重试 */ }\r\n polling = false\r\n }\r\n\r\n store.actions.applyTheme = applyTheme\r\n store.actions.applyBackground = applyBackground\r\n store.actions.applyImmersive = applyImmersive\r\n store.actions.repoll = () => { lastHash = ''; void poll() }\r\n\r\n ctx.effect(() => () => {\r\n styleTag.remove()\r\n panelStyleTag.remove()\r\n immersiveStyleTag.remove()\r\n orbBtn.remove()\r\n statusObserver.disconnect()\r\n document.removeEventListener('keydown', onImmersiveKey)\r\n document.removeEventListener('click', onDocClick, true)\r\n stopSceneLayers()\r\n setMedia(null)\r\n if (themeDisposer !== null) { themeDisposer(); themeDisposer = null }\r\n })\r\n\r\n ctx.effect(() => {\r\n const timer = setInterval(() => { void poll() }, 2500)\r\n void poll()\r\n return () => clearInterval(timer)\r\n })\r\n\r\n // 任务状态检测:订阅 sessions 列表快照,任意会话(跨工作区)running = 任务进行中\r\n if (sessions !== undefined) {\r\n const updateTaskState = (): void => {\r\n const snapshot = sessions.list.getSnapshot()\r\n const active = snapshot != null && Object.values(snapshot.byId).some((s) => s.running === true)\r\n if (active !== store.settings.taskActive) {\r\n store.settings.taskActive = active\r\n if (store.settings.focus) { applyTheme(); applyBackground() }\r\n syncStatus()\r\n store.notify()\r\n }\r\n }\r\n ctx.effect(() => sessions.list.subscribe(updateTaskState))\r\n updateTaskState()\r\n }\r\n\r\n applyTheme()\r\n applyBackground()\r\n\r\n slotsService.inject('conversation.view', () => slotsService.register(\r\n { name: 'conversation.view', id: 'wallpaper_share', order: 20, label: 'wallpaper_share' },\r\n WallpaperSharePanel,\r\n ))\r\n}\r\n"],"mappings":"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"}
|