You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

299 lines
16 KiB

<html>
<head>
<link rel="icon" href="./favicon.ico" />
<meta charset="utf-8" />
<title><%=title%></title>
<meta
name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1,minimum-scale=1,maximum-scale=1,minimal-ui=true"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes">
<meta name="full-screen" content="yes" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="renderer" content="webkit" />
<meta name="force-rendering" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<link rel="stylesheet" type="text/css" href="./index.css" />
<link rel="stylesheet" type="text/css" href="/workbench/css/workbench.css" />
<script>
(function () {
var m = new URLSearchParams(location.search).get('pw');
// iframe 内一律按游戏页处理,禁止再套壳(否则双引擎/无限嵌套会打崩 Electron)
if (window.parent !== window) {
m = 'game';
}
window.__PW_MODE = m === 'game' ? 'game' : 'shell';
document.documentElement.setAttribute('data-pw', window.__PW_MODE);
})();
</script>
</head>
<body style="overflow: hidden;">
<%- include(cocosToolBar, {config: config}) %>
<div id="pw-root" class="pw-root pw-mode-desktop">
<div id="pw-toolbar" class="pw-toolbar pw-shell-only">
<div class="pw-toolbar-left" title="菜单">
<span class="pw-brand">调试工作台</span>
<button type="button" class="pw-btn pw-panel-btn" data-panel="hierarchy">层级</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="inspector">属性</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="assets">资源</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="perf">性能</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="console">控制台</button>
</div>
<div class="pw-toolbar-center" title="设备与快捷">
<select id="pw-device-select" class="pw-select" title="设备"></select>
<button type="button" id="pw-device-rotate" class="pw-btn" title="旋转">旋转</button>
<button type="button" id="pw-game-refresh" class="pw-btn" title="刷新并重启游戏">刷新</button>
<button type="button" id="pw-show-fps" class="pw-btn" title="显示 FPS 浮窗" aria-pressed="false">FPS</button>
<button type="button" id="pw-game-pause" class="pw-btn">暂停</button>
<button type="button" id="pw-game-step" class="pw-btn" title="暂停时推进一帧">按帧执行</button>
<button type="button" id="pw-pure-measure" class="pw-btn" title="关闭全部探针,测真实帧率" aria-pressed="false">纯净测帧</button>
<div class="pw-mode-toggle" role="group" aria-label="输入模式">
<button type="button" id="pw-mode-game" class="pw-btn active" data-mode="game">游戏</button>
<button type="button" id="pw-mode-inspect" class="pw-btn" data-mode="inspect">检视</button>
</div>
</div>
<div class="pw-toolbar-right" title="状态">
<div class="pw-live-stats" id="pw-live-stats" title="游戏实时帧率与占用内存">
<span id="pw-stat-fps" class="pw-stat">FPS --</span>
<span class="pw-stat-sep">·</span>
<span id="pw-stat-mem" class="pw-stat">内存 --</span>
</div>
<span id="pw-engine-status" class="pw-status">引擎等待中…</span>
<select id="pw-layout-preset" class="pw-select" title="布局预设">
<option value="analyze">分析(按横竖屏)</option>
<option value="portrait">竖屏分析</option>
<option value="landscape">横屏分析</option>
<option value="scene">场景</option>
<option value="minimal">精简</option>
</select>
<button type="button" id="pw-layout-reset" class="pw-btn" title="重置布局">重置布局</button>
<button type="button" id="pw-workbench-toggle" class="pw-btn active" title="开启/关闭调试工作台(关闭后仍保留设备选项)" aria-pressed="true">工作台</button>
</div>
</div>
<div id="pw-workspace" class="pw-workspace pw-shell-only"></div>
<script>
(function () {
if (window.__PW_MODE === 'game') {
document.write(
'<div id="pw-game-host" class="pw-game-host">' +
'<div id="pw-center" class="pw-center">' +
'<div id="content" class="content" style="overflow: hidden;">' +
'<div class="contentWrap">' +
'<div id="GameDiv" class="wrapper">' +
'<div id="Cocos3dGameContainer">' +
'<canvas id="GameCanvas" tabindex="-1" style="background-color: \'\';"></canvas>' +
'</div>' +
'<div id="splash"><div class="progress-bar stripes"><span></span></div></div>' +
'<div id="bulletin"><div id="sceneIsEmpty" class="inner"><%=tip_sceneIsEmpty%></div></div>' +
'<div class="error" id="error"><div class="title">Error <i>(Please open the console to see detailed errors)</i></div>' +
'<div class="error-main"></div><div class="error-stack"></div></div>' +
'</div></div></div>' +
'<div id="pw-pick-overlay" class="pw-pick-overlay" hidden></div>' +
'</div></div>'
);
} else {
// 壳页:不加载引擎,只挂 iframe 宿主
document.write(
'<div id="pw-game-host" class="pw-game-host pw-game-iframe-host"></div>'
);
}
})();
</script>
<div id="pw-drop-overlay" class="pw-drop-overlay pw-shell-only" hidden>
<div class="pw-drop-edge pw-drop-e-center" data-edge="center">合并到此区域</div>
<div class="pw-drop-edge pw-drop-e-left" data-edge="left">左侧新建</div>
<div class="pw-drop-edge pw-drop-e-right" data-edge="right">右侧新建</div>
<div class="pw-drop-edge pw-drop-e-top" data-edge="top">上方新建</div>
<div class="pw-drop-edge pw-drop-e-bottom" data-edge="bottom">下方新建</div>
</div>
<div id="pw-compact-bar" class="pw-compact-bar pw-shell-only">
<button type="button" class="pw-btn pw-panel-btn" data-panel="perf">性能</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="assets">资源</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="hierarchy">层级</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="inspector">属性</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="console">控制台</button>
<button type="button" id="pw-show-fps-compact" class="pw-btn" title="显示 FPS 浮窗" aria-pressed="false">FPS</button>
<button type="button" id="pw-game-step-compact" class="pw-btn" title="暂停时推进一帧">按帧执行</button>
</div>
<div id="pw-drawer" class="pw-drawer pw-shell-only" hidden>
<div class="pw-drawer-head">
<span id="pw-drawer-title">面板</span>
<button type="button" id="pw-drawer-close" class="pw-btn">关闭</button>
</div>
<div id="pw-drawer-body" class="pw-drawer-body"></div>
</div>
</div>
<!--
关键:壳页绝不能执行 cocosTemplate(双引擎会打崩 Electron/Cursor)。
放进 <template> 解析时不运行;仅 game 模式按序激活。
-->
<template id="pw-cocos-boot">
<%- include(cocosTemplate, {}) %>
</template>
<script>
(function () {
if (window.__PW_MODE !== 'game') return;
// cocosTemplate 用 window.onload 启动;动态激活时 load 常已错过,必须补跑且只跑一次
(function patchOnLoad() {
var ran = false;
function run(fn) {
if (ran || typeof fn !== 'function') return;
ran = true;
try { fn.call(window); } catch (e) { console.error('[调试工作台] onload 引导失败', e); }
}
try {
Object.defineProperty(window, 'onload', {
configurable: true,
enumerable: true,
get: function () { return null; },
set: function (fn) {
if (typeof fn !== 'function') return;
if (document.readyState === 'complete') {
setTimeout(function () { run(fn); }, 0);
} else {
window.addEventListener('load', function () { run(fn); });
}
},
});
} catch (e) {
console.warn('[调试工作台] 无法劫持 onload', e);
}
})();
var tpl = document.getElementById('pw-cocos-boot');
if (!tpl || !tpl.content) {
console.error('[调试工作台] 缺少 #pw-cocos-boot');
return;
}
var nodes = [];
var child = tpl.content.firstChild;
while (child) {
nodes.push(child);
child = child.nextSibling;
}
var i = 0;
var finished = false;
function bootWorkbench() {
if (finished) return;
finished = true;
window.__PW_ENGINE_BOOT_DONE = true;
var files = [
'/workbench/js/idle.js',
'/workbench/js/perf-sampler.js',
'/workbench/js/markers.js',
'/workbench/js/device.js',
'/workbench/js/agent-util.js',
'/workbench/js/agent-core.js',
'/workbench/js/agent-serialize.js',
'/workbench/js/agent-pick.js',
'/workbench/js/agent-console.js',
'/workbench/js/agent.js',
];
var fi = 0;
function nextWb() {
if (fi >= files.length) return;
var el = document.createElement('script');
el.src = files[fi++];
el.onload = nextWb;
el.onerror = function () {
console.warn('[调试工作台] 探针脚本加载失败', el.src);
nextWb();
};
document.body.appendChild(el);
}
nextWb();
}
function next() {
if (i >= nodes.length) {
bootWorkbench();
return;
}
var node = nodes[i++];
if (!node) {
next();
return;
}
if (node.nodeName === 'SCRIPT') {
var s = document.createElement('script');
var src = node.getAttribute('src');
var typ = node.getAttribute('type') || '';
for (var a = 0; a < node.attributes.length; a++) {
var attr = node.attributes[a];
if (attr.name === 'src') continue;
s.setAttribute(attr.name, attr.value);
}
if (src) {
s.async = false;
var done = false;
var cont = function () {
if (done) return;
done = true;
next();
};
s.onload = cont;
s.onerror = function () {
console.warn('[调试工作台] 引擎脚本加载失败', src);
cont();
};
// importmap 常不触发 onload,必须推进,否则游戏永远黑屏
var isImportMap = typ.indexOf('importmap') >= 0;
s.src = src;
document.body.appendChild(s);
setTimeout(cont, isImportMap ? 0 : 8000);
return;
}
s.text = node.text || node.textContent || '';
document.body.appendChild(s);
next();
return;
}
try {
document.body.appendChild(node.cloneNode(true));
} catch (e) {
console.warn('[调试工作台] 挂载节点失败', e);
}
next();
}
console.info('[调试工作台] 游戏页开始激活引擎脚本', nodes.length);
next();
})();
</script>
<script>
(function () {
if (window.__PW_MODE === 'game') return;
var files = [
'/workbench/js/idle.js',
'/workbench/js/charts/ring-chart.js',
'/workbench/js/bridge.js',
'/workbench/js/panels/console.js',
'/workbench/js/panels/hierarchy.js',
'/workbench/js/panels/inspector.js',
'/workbench/js/panels/assets.js',
'/workbench/js/panels/perf.js',
'/workbench/js/layout-core.js',
'/workbench/js/layout-presets.js',
'/workbench/js/layout-render.js',
'/workbench/js/layout-dock.js',
'/workbench/js/layout-tree.js',
'/workbench/js/layout-float.js',
'/workbench/js/host.js',
];
var i = 0;
function next() {
if (i >= files.length) return;
var el = document.createElement('script');
el.src = files[i++];
el.onload = next;
el.onerror = next;
document.body.appendChild(el);
}
next();
})();
</script>
</body>
</html>