八国语言+eagle图片

This commit is contained in:
tianmo committed 2026-10-29 11:02:01 +08:00
1 parent acc93d5404
commit 3bd3ba7404
46 files changed
+2520 -290

No files matched your search

+40 -33
View File
@@ -2,7 +2,7 @@
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SpineThumbnailGenerateServer</title>
<title data-i18n="thumb.title">Spine缩略图</title>
<style>
:root { --bg: #1e1e1e; --panel: #252526; --text: #e6e6e6; --dim: #9d9d9d; --accent: #4fc1ff; --border: #3c3c3c; --warn: #e3b341; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
@@ -11,6 +11,8 @@
h1 { font-size: 15px; margin: 0; font-weight: 600; text-align: center; }
.notice { color: var(--dim); line-height: 1.6; background: var(--panel);
border: 1px solid var(--border); border-radius: 6px; padding: 9px 11px; }
.notice p { margin: 0 0 6px; }
.notice p:last-child { margin-bottom: 0; }
.notice b { color: var(--text); font-weight: 500; }
.notice code { color: var(--accent); font-family: ui-monospace, Consolas, monospace; }
.toggle-row { display: flex; align-items: center; gap: 8px; cursor: pointer; white-space: nowrap;
@@ -52,56 +54,45 @@
</style>
</head>
<body>
<h1>Spine缩略图</h1>
<h1 data-i18n="thumb.title">Spine缩略图</h1>
<div class="notice">
导入 Spine 资产(<code>.skel</code> / <code>.json</code> + <code>.atlas</code> + 贴图)后,
本插件会为还没设置缩略图的素材生成一张骨骼预览图。
<b>它只处理本次新导入的素材,不扫描、不修改历史素材,也不会覆盖你已经设置过的自定义缩略图。</b>
生成方式可切换:<b>动态</b>取骨骼里的第一个动画压成 WebP(200×200,体积按动画时长自动定,
参数与主插件默认值一致),<b>静帧</b>始终用 setup pose。
自动生成默认关闭,需要你在下面手动启用。
<p data-i18n="thumb.noticeIntro">导入 Spine 资产(.skel / .json + .atlas + 贴图)后,本插件会为还没设置缩略图的素材生成一张骨骼预览图。</p>
<p data-i18n="thumb.noticeSafety">它只处理本次新导入的素材,不扫描、不修改历史素材,也不会覆盖你已经设置过的自定义缩略图。</p>
<p data-i18n="thumb.noticeModes">动态取骨骼里的第一个动画压成 WebP;静帧始终使用 setup pose。</p>
<p data-i18n="thumb.noticeDefault">自动生成默认关闭,需要你在下面手动启用。</p>
</div>
<div class="toolbar">
<div class="toolbar-group">
<label class="toggle-row"><input type="checkbox" id="toggle"><span>导入时自动生成缩略图</span></label>
<button id="clear" type="button">清空日志</button>
<label class="toggle-row"><input type="checkbox" id="toggle"><span data-i18n="thumb.autoToggle">导入时自动生成缩略图</span></label>
<button id="clear" type="button" data-i18n="thumb.clear">清空日志</button>
</div>
<div class="toolbar-group">
<label class="mode-row"><span>生成方式</span>
<label class="mode-row"><span data-i18n="thumb.modeLabel">生成方式</span>
<select id="mode">
<option value="animated">动态(第一个动画)</option>
<option value="static">静帧(setup pose)</option>
<option value="animated" data-i18n="thumb.modeAnimated">动态(第一个动画)</option>
<option value="static" data-i18n="thumb.modeStatic">静帧(setup pose)</option>
</select>
</label>
<label class="mode-row"><span>生成策略</span>
<label class="mode-row"><span data-i18n="thumb.strategyLabel">生成策略</span>
<select id="strategy">
<option value="size">最优体积(慢)</option>
<option value="speed">最优速度(快)</option>
<option value="size" data-i18n="thumb.strategySize">最优体积(慢)</option>
<option value="speed" data-i18n="thumb.strategySpeed">最优速度(快)</option>
</select>
</label>
</div>
</div>
<div class="row"><span>状态</span><b id="status">启动中…</b></div>
<div class="row"><span>素材库</span><b id="library">—</b></div>
<div class="row"><span>统计</span><b id="stats">—</b></div>
<div class="row"><span data-i18n="thumb.statusLabel">状态</span><b id="status" data-i18n="thumb.statusStarting">启动中…</b></div>
<div class="row"><span data-i18n="thumb.libraryLabel">素材库</span><b id="library">—</b></div>
<div class="row"><span data-i18n="thumb.statsLabel">统计</span><b id="stats">—</b></div>
<div class="filters" id="filters">
<button type="button" data-filter="all" class="active">全部</button>
<button type="button" data-filter="ok">成功</button>
<button type="button" data-filter="fail">失败</button>
<button type="button" data-filter="warn">警告</button>
<button type="button" data-filter="error">错误</button>
<button type="button" data-filter="all" class="active" data-i18n="thumb.filterAll">全部</button>
<button type="button" data-filter="ok" data-i18n="thumb.filterOk">成功</button>
<button type="button" data-filter="fail" data-i18n="thumb.filterFail">失败</button>
<button type="button" data-filter="warn" data-i18n="thumb.filterWarn">警告</button>
<button type="button" data-filter="error" data-i18n="thumb.filterError">错误</button>
</div>
<ul id="log"></ul>
<script>
// 诊断用:脚本一旦抛错,直接把原因写在状态栏,避免停在「启动中…」看不出问题。
window.addEventListener('error', (event) => {
const el = document.getElementById('status');
if (el) el.textContent = '脚本错误:' + (event.message || event.error || '未知错误');
});
window.addEventListener('unhandledrejection', (event) => {
const el = document.getElementById('status');
if (el) el.textContent = '未处理的 Promise 错误:' + (event.reason && event.reason.message || event.reason);
});
// service 页面里的 require 不以插件目录为基准,本地资源要用绝对路径,这里先把根目录算出来。
(function () {
try {
@@ -114,6 +105,22 @@
}
})();
</script>
<script src="js/i18n.js"></script>
<script>
// 诊断用:脚本一旦抛错,直接把原因写在状态栏,避免停在「启动中…」看不出问题。
window.addEventListener('error', (event) => {
const el = document.getElementById('status');
if (el) el.textContent = SpineThumbI18n.t('thumb.scriptError', {
error: event.message || event.error || SpineThumbI18n.t('thumb.unknownError'),
});
});
window.addEventListener('unhandledrejection', (event) => {
const el = document.getElementById('status');
if (el) el.textContent = SpineThumbI18n.t('thumb.promiseError', {
error: event.reason && event.reason.message || event.reason,
});
});
</script>
<!-- 顺序有依赖:rasterizer 先于 clipping,utils/badge 先于 renderer,plugin.js 最后。 -->
<script src="js/spine-webgl-rasterizer.js"></script>
<script src="js/spine-canvas-clipping.js"></script>