# TextureMaker **Repository Path**: seraph2047/texture-maker ## Basic Information - **Project Name**: TextureMaker - **Description**: 制作H5为主各类游戏引擎的2D图集。其中可以把flash生成的swf拆解,或自行导入连续的动画图片 - **Primary Language**: JavaScript - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-26 - **Last Updated**: 2026-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Texture Maker 软件图标

Texture Maker

把 SWF 与连续 PNG,整理成可编辑、可压缩、可预加载的游戏动画

动画导入 · 帧编辑 · 智能装箱 · 方案续作 · 压缩发布 · LayaAir 播放

Windows  |  macOS  |  Web UI  |  CLI

当前版本 v0.1.139 · 需要 Node.js 20 或更新版本

Texture Maker 是面向游戏美术与客户端开发的 2D 动画资源生产工具。它既能拆解 Flash 制作的 `.swf`,也能把一组连续编号 PNG 直接建立为动画;两种来源可以放在同一个项目中整理、编辑、装箱和发布。 最终输出统一为引擎容易接入的 **PNG 图集 + JSON/TMD 动画数据**。美术在可视化界面完成帧调整与发布,程序通过相同格式、CLI 和播放器接入项目,双方不必维护两套资源流程。
双轨导入
SWF 与连续 PNG
可混合追加
帧级编辑
关键帧、洋葱皮
事件与指令
显存可控
透明裁剪、即时装箱
自动分页
方案可续作
单文件 .tmproj
换目录继续编辑
发布可救援
JSON/TMD + PNG 恢复
兼容 TextureMerger
运行时就绪
压缩数据、预加载缓存
LayaAir Demo

导入素材 → 编辑动画 → 智能装箱 → 保存方案 / 压缩发布 → 游戏播放

![Texture Maker 主界面](docs/images/ui-main.jpg)

当前界面:分组文件菜单、4 个动画片段、1024 × 1024 即时装箱、双页图集与分页导航。

> **连续 PNG 不再只是散图。** Texture Maker 会识别编号、自然排序、裁掉四周全透明区域,再把原画布中心补偿进帧坐标。图集只保存有内容的像素,动画位置仍保持原样。 ## 核心卖点 ### 连续图片,直接成为可编辑动画 不用 Flash,也不用先拼 spritesheet。点击“导入连续图片”,一次选中编号 PNG,再设置播放帧率和每张图片默认保持多少帧,就能直接得到可编辑动画。
点击导入连续图片
1. 点击导入
主界面直接进入连续 PNG 工作流
批量选择连续 PNG
2. 批量选择
自动识别编号并按文件名自然排序
设置连续图片动画参数
3. 设置节奏
选择帧率、每图持续与初始对齐
“每图持续”与播放帧率共同决定初始节奏:`单张显示时间 = 每图持续 ÷ 播放帧率`。例如 `60 fps`、每图持续 `5` 帧时,每张图显示约 `83.3 ms`,整组图片以每秒 `12` 张的节奏播放。这个值只是批量导入的统一起点,导入后仍能逐个关键帧段调整。 #### 透明区域不进图集,显存预算可以直接算 仓库中的 10 张 `TestRes/testPIC` 原图都是 `200 × 200`。默认“去除空白位置”会裁掉四边全透明像素,同时把裁剪偏移补偿到帧坐标,所以动画中心不漂移;有效图块最终被装进一张 `463 × 505` 图集。
十张 200x200 连续 PNG
原始素材:10 张 200 × 200 PNG
连续 PNG 自动裁剪并合并图集
导入结果:有效像素合并为 463 × 505 图集
按 `RGBA8` 且纹理需要向上补 2 次幂的项目预算方式计算: ```text 10 张独立纹理:256 × 256 × 4 × 10 = 2,621,440 bytes ≈ 2.5 MiB 合并后的图集:512 × 512 × 4 = 1,048,576 bytes = 1 MiB 显存预算减少:约 60%(节省约 1.5 MiB) ``` 图集有效尺寸的 RGBA8 数据约为 `913 KiB`;界面同时显示 `512 × 512` 的保守显存尺寸,方便美术在发布前直接判断容量。实际占用仍以目标引擎、纹理格式和 GPU 规则为准。 ### 时间轴不只是播放预览 亮色帧工具栏集中提供撤销/重做、插入帧、空白关键帧、复制、删除、删除关键帧和前后移动。时间轴分为三层:绿色顶部带左键拖动平移整条时间轴(向左拖会向右滚动),红色刻度带单击或拖动只切换当前帧,黄色帧格单击定位、拖动选择连续帧。选中连续关键帧后,可从选区内任一帧用鼠标右键拖拽把整组插入任意位置;`Alt+左键拖拽` 仍是同一换序入口。换序在松手时一次生效,保留组内顺序和各段持续时长。Shift+单击连续选择两个端点之间的关键帧;Ctrl+单击(macOS 用 Cmd+单击)可逐个增减非连续关键帧。右栏图层标题旁可一键全选当前片段关键帧,再点一次恢复单选。右栏会明确显示“多帧编辑”,移动与缩放可批量作用于所选帧的全部图层。 ![连续图片动画节奏调整](docs/images/workflow-png-timing.png) 导入时设置的是所有图片的默认持续帧数;进入动画预览后,可以针对某一段使用“插入帧”延长停留,或用“删除帧”缩短停留。这样同一组素材里,蓄力帧可以更慢、爆发帧可以更快,美术无需改代码就能直接调整动画节奏。 播放期间编辑器会锁定帧操作、画布拖动和右侧帧面板,并停止逐帧重建编辑侧栏;暂停后再恢复编辑,检查动画时更稳定。动画预览中按空格可切换播放/暂停;时间轴上方空白区域也可点击或拖动定位,关键帧密集时不必寻找空格。Windows 使用 `Ctrl+Z/Ctrl+Y`,macOS 使用 `Cmd+Z/Cmd+Shift+Z` 撤销和重做动画编辑。 ### 从图集预算到发布体积 装箱算法、图块间隙、单页最大尺寸和全局导出图集缩小修改后会立即重新装箱,不再需要额外点击“应用”。“优化装箱”会额外比较 POT 页面组合,优先减少总纹理面积,其次减少页数。资源超过上限时自动分页,状态栏可按页聚焦;PNG 默认推荐 TinyPNG 风格量化,2 次幂补边和 JSON/TMD 数据压缩集中在发布面板完成。 ### 一个文件保留完整制作方案 顶部菜单把方案、常用导入、兼容导入和辅助导出分开。`.tmproj` 会把原始素材、当前编辑图块、时间轴、坐标、缩放、装箱和导出设置保存为一个可拷贝文件;即使原始素材不在原目录,也能重新打开继续编辑。 导出设置可勾选“自动保存方案”,发布图集时会额外生成同名 `.tmproj`。它只供 Texture Maker 二次编辑,**不需要复制到游戏资源目录**;游戏仍只加载 JSON/TMD 与 PNG。 ### 忘记保存,也还有一条退路 “导入其他”提供两条兼容路径:使用完整 JSON/TMD 与全部 PNG 页急救恢复 Texture Maker 发布文件,或直接导入旧 TextureMerger JSON/PNG。恢复使用的是已发布像素,不能替代正式 `.tmproj`,但足以重新装箱、编辑帧并保存新方案。 ![方案恢复与兼容导入](docs/images/workflow-project-imports.png) ### 关键帧可以直接交给下一道工序 当前动画可按关键帧段导出统一尺寸 PNG。所有图片以动画原点居中、四边保留 `2px` 透明边;duration 为 5 的关键帧段仍只输出一张,不制造重复文件,不同关键帧段即使画面相同也分别保留。 ![导出当前动画序列帧 PNG](docs/images/workflow-frame-export.png) ### 导出后即可进入游戏 多页图集通过 `pngs` 与 `res.p` 定位资源页;LayaAir 播放器能够识别普通 JSON 和 TMD manifest,预加载全部纹理页并缓存 factory。仓库内置 Demo 用于验证单页、多页、压缩数据、片段切换与帧事件。 ## 能力全景 - **SWF 与连续图片导入**:既能拆解 SWF,也能把多张 PNG 按自然文件名顺序建立为动画帧。 - **透明边自动裁剪**:只装箱有效像素,并通过裁剪偏移补偿保持原画布中心。 - **动画帧编辑**:插入、复制、删除、空白关键帧、拖动换序和坐标微调。 - **多帧洋葱皮**:暂停时查看前一关键帧与后续 1-5 个关键帧段。 - **PNG 图集装箱**:把动画引用的资源打包为图集,支持间隙、最大尺寸和多种装箱策略。 - **装箱即时预览**:算法、间隙和分页尺寸一改即重新装箱,快速比较结果。 - **POT 智能装箱**:比较允许范围内的 2 次幂页面组合,先最小化总纹理面积,再减少页数;四个 512 图块优先合并为一个 1024,三个则使用 1024×512 + 512×512。 - **多页图集输出**:单张图集放不下时自动分页,输出 `texture.png`、`texture_2.png` 等多张 PNG。 - **运行时 JSON**:导出短字段 JSON,包含 `mc` 动画片段、`res` 图集矩形、`pngs` 多页图集列表。 - **动画预览**:在工具内查看图集、数据和动画播放效果,辅助检查拆解结果。 - **片段与帧标签**:支持 Flash 帧标签导入,包含 `#MARK` 锚记、`@STOP`、`@GOTO`、`@EVENT` 等指令。 - **片段缩放**:支持导入时原素材缩放和运行时输出缩放,便于处理不同动画片段的尺寸差异。 - **全局导出图集缩小**:按 `10%–100%` 重采样全部图块再装箱,大资源可缩小到分页上限或 2 次幂范围内;源图块不变,运行时通过 `ts` 保持原尺寸。 - **方案保存**:使用单文件 `.tmproj` 保存原始素材与完整编辑状态,支持换目录、换电脑继续制作。 - **发布文件急救**:忘记保存方案时,可选择完整 JSON/TMD 与全部 PNG 页,有限恢复可编辑动画后立即另存 `.tmproj`。 - **旧项目迁移**:可直接导入 TextureMerger JSON/PNG,把旧动画恢复到当前编辑与发布流程。 - **关键帧 PNG 导出**:按当前动画的关键帧段输出统一画布 PNG,不按 duration 制造重复图片。 - **资源信息开关**:缩略图可独立显示帧名字与全部复用帧范围,例如 `1-5、11-15`。 - **PNG 压缩选项**:支持标准 PNG、无损优化、高质量量化和 TinyPNG 风格量化;发布默认推荐 TinyPNG 风格量化。 - **CLI 批处理**:命令行可用于检查、转换和批量处理 SWF,方便接入自动化工具链。 - **跨平台桌面版**:支持 Windows/macOS 本地运行,也提供 Electron 桌面壳构建脚本。 - **LayaAir 播放器**:内置 LayaAir 运行时播放器核心和 Demo,可验证导出 JSON/PNG 的播放效果。 ## 效果预览 ### 序列帧动画编辑 下图使用 `MultPage` 演示方案中的 `CHANT` 动画:25 个关键帧段展开为 120 个逻辑帧,开启洋葱皮并后看 3 个关键帧段。顶部集中放置新增、删除、排序和洋葱皮工具,播放与缩放留在底栏。 ![动画关键帧编辑](docs/images/workflow-frame-actions.png) ### 多页图集 当资源超过设定的分页最大尺寸时,Texture Maker 会自动拆成多张图集。JSON 通过 `pngs` 记录所有 PNG 文件名,通过 `res[id].p` 记录资源所在页码。 ![多页图集输出](docs/images/ui-atlas-pages.jpg) ### 导出 JSON 导出数据只保留运行时播放需要的字段。常用字段包括: - `v`:数据格式版本。 - `pngs`:多页图集文件列表,单页数据可省略。 - `mc`:动画片段表。 - `res`:资源在图集中的矩形区域。 - `res[id].p`:资源所在 PNG 页码,缺省为第 0 页。 ![导出数据预览](docs/images/ui-export-json.jpg) ### LayaAir Demo ![LayaAir Demo 单实例工作台](docs/images/laya-demo-workbench.png) 仓库内置 `Laya3Demo`,用于验证导出的短格式 JSON、单页/多页 PNG 图集和片段切换。`MultPage` 样本用于测试 `pngs` 多页图集与 `res.p` 页码。 Demo 左栏以“单实例 / 压力测试”为一级模式,基础、片段和压缩资源为二级分类;桌面端调用代码横跨样本栏与舞台栏,右侧播放控制和事件日志贯穿上下两行。TypeScript 直接引用 `laya_player_core/core` 中原始 `IMultMoveClip` / `IMultMovieClipFactory` 接口与同名 namespace 公共入口,不复制类型,也不直接调用 `Vc`。最简调用会立即把实例加入父容器,并在共享 factory 加载完成后自动播放: ```ts const mc: IMultMoveClip = IMultMoveClip.play( McType.TYPE_SWF, "boom", "/assets/boom.json", Laya.stage ); ``` 播放器支持 `isPlayEndRemove`:动画自然结束后只从父容器移除,不销毁实例、不使用 Pool、不清 Loader 资源。Demo 还提供 boom 最高 200 个/秒的页面内全屏持续吞吐测试,以及 role_3 `IDLE` 200~2000 个满屏轻重叠、单一公共 `update()` 的峰值测试;两者可通过退出按钮或 Esc 清理并恢复工作台。 动画片段可通过 JSON `endo` 设置自然结束默认行为:缺失或 `1` 停止、`2` 循环、`10` 移除并销毁实例。编辑器右栏可逐片段设置;显式 `play(true/false)` 或 `playEndAction` 优先,销毁不会清 Loader/factory 资源。 ![LayaAir Demo 200/秒持续吞吐全屏](docs/images/laya-demo.jpg) ## 快速开始 ### 环境要求 - Node.js 20 或更新版本。 - Windows 或 macOS。 ### 启动 Web UI ```bash npm run ui ``` 默认会启动本地服务: ```text http://localhost:5177 ``` 如果端口被占用,程序会自动尝试后续端口,并在控制台打印实际地址。 ### 常用 CLI 命令 ```bash node ./bin/texture-maker.js --help node ./bin/texture-maker.js inspect TestRes/testSwf/BladeDamage_2.swf node ./bin/texture-maker.js swf TestRes/testSwf/BladeDamage_2.swf node ./bin/texture-maker.js convert TestRes/testSwf/BladeDamage_2.swf --out export/sample node ./bin/texture-maker.js batch TestRes/testSwf node ./bin/texture-maker.js inspect-texturemerger TestRes/Import/TextureMergerBatch/R_Trans.json node ./bin/texture-maker.js import-texturemerger TestRes/Import/TextureMergerBatch/R_Trans.json --out export/texturemerger node ./bin/texture-maker.js batch-texturemerger TestRes/Import/TextureMergerBatch --out export/texturemerger-batch ``` 转换命令默认使用 `--png-compression quantized` 和 POT 优化。需要像素完全不变时显式传 `--png-compression lossless`;需要对比标准旧布局时传 `--no-pot-optimize`。 也可以使用 npm scripts: ```bash npm run smoke npm run inspect -- TestRes/testSwf/BladeDamage_2.swf npm run batch -- TestRes/testSwf ``` ## AI 集成:安装 textureSkill 与 MCP 仓库把 AI 集成文件集中放在 [`ai/texture-maker/`](ai/texture-maker/)。其中 [`textureSkill`](ai/texture-maker/textureSkill/SKILL.md) 是 AI 使用 Texture Maker 的详细操作规范,`mcp/texture-maker.mcp.json` 是 MCP 客户端配置模板。 ### 安装 textureSkill 将 `ai/texture-maker/textureSkill` 整个目录复制到 Codex 技能目录,目录名保持为 `textureSkill`: ```text Windows: %USERPROFILE%\\.codex\\skills\\textureSkill macOS/Linux: ~/.codex/skills/textureSkill ``` 复制完成后重启 Codex 或重新打开任务,让它重新发现技能。技能会指导 AI 检查/转换 SWF 和 TextureMerger JSON/PNG,并在输出后校验 JSON、PNG 图集和引擎兼容性。 ### 安装 MCP 源码调试 MCP 不需要额外的 npm 包,但要求 Node.js 20+,在仓库根目录执行: ```text npm install npm run mcp ``` 在 MCP 客户端新增一个 stdio server。正式使用复制 [`ai/texture-maker/mcp/texture-maker.mcp.json`](ai/texture-maker/mcp/texture-maker.mcp.json),把 `command` 改为 MCP 可执行文件的绝对路径,`args` 留空;源码调试才使用 [`texture-maker.source.mcp.json`](ai/texture-maker/mcp/texture-maker.source.mcp.json),将 `cwd` 改为仓库绝对路径。连接成功后应出现 17 个 `texture_*` 工具,其中 TextureMerger 使用 `texture_inspect_texturemerger`、`texture_import_texturemerger`、`texture_batch_texturemerger`。 生产环境推荐使用单文件 MCP 程序:Windows 构建 `npm run build:single:mcp:win`,得到 `export/win-single-mcp/TextureMarker-MCP.exe`;macOS 构建 `npm run build:single:mcp:mac`,分别得到 `export/mac-single-mcp-x64/TextureMarker-MCP.app` 和 `export/mac-single-mcp-arm64/TextureMarker-MCP.app`。从 Windows 交叉构建的 Mac 包首次使用前执行同目录 `SIGN-MAC.command`。MCP 客户端直接把 `command` 配成 app 内 `Contents/MacOS/TextureMarker-MCP` 或 Windows EXE 的绝对路径,参数留空,不需要用户安装 Node 或手动启动服务器。 #### MCP 工具清单与调用方式 MCP 使用 stdio JSON-RPC,不是 HTTP 服务。连接后提供 17 个工具;10 个文件工具可独立运行,7 个方案工具需要存活的 UI/桌面窗口: | 工具 | 用途 | | --- | --- | | `texture_inspect_swf` | 读取 SWF 头和标签摘要 | | `texture_inspect_fixture` | 检查 SWF 及同名 JSON/PNG sidecar | | `texture_convert` | 转换单个 SWF 为运行时 JSON/PNG | | `texture_batch_inspect` | 检查目录中的 SWF 样本 | | `texture_validate_export` | 校验 JSON、PNG 页、矩形边界和页码引用 | | `texture_list_samples` | 列出样本及缺失 sidecar | | `texture_inspect_texturemerger` | 只读检查一组 TextureMerger JSON/PNG | | `texture_import_texturemerger` | 转换单组 TextureMerger 文件 | | `texture_batch_texturemerger` | 递归批量转换并保持相对目录结构 | | `texture_optimize_export` | 对已导出的明文 JSON/PNG 做一次最小 POT 面积重装箱,默认 TinyPNG 风格压缩 | | `texture_get_capabilities` | 发现软件版本、存活编辑器 `instanceId` 和 `projectId`;无 UI 时返回 `mode: headless` | | `texture_project_open` | 在指定编辑器中打开绝对路径 `.tmproj`,可选动作/tick;遇到未保存修改拒绝覆盖 | | `texture_project_get` | 读取当前内存修订、dirty、动作列表、选择和保存修订 | | `texture_editor_focus` | 切到动画页并准确定位动作/tick | | `texture_project_save` | 用 `expectedRevision` 和 `requestId` 保存当前快照,备份旧文件并原子替换 | | `texture_project_export` | 从 `saved` 或 `snapshot` 版本导出到指定目录,返回任务 ID | | `texture_job_get` | 查询导出进度、结果、文件摘要和校验 | 转换类工具默认 `optimizePotPages: true` 和 `pngCompression: "quantized"`。除非用户明确要求无损、量化质量检查不通过,或需要做像素级比较,否则不要退回标准 PNG。 TextureMerger 单组调用: ```json { "inputPath": "D:/assets/effects/fire.json", "outDir": "D:/converted/effects/fire", "maxWidth": 2048, "maxHeight": 2048, "overwrite": false } ``` TextureMerger 递归批量调用: ```json { "inputDir": "D:/assets/effects", "outDir": "D:/converted-effects", "recursive": true, "copyOtherFiles": true, "nameSuffix": "_tm", "maxWidth": 2048, "maxHeight": 2048, "overwrite": false } ``` AI 推荐固定顺序: 1. 先调用 `texture_inspect_texturemerger`,确认同名配对、JSON 可解析、PNG 尺寸和 `res` 矩形合法。 2. 单组调用 `texture_import_texturemerger`;项目目录调用 `texture_batch_texturemerger`,传 `recursive: true` 保持目录结构。默认使用 `pngCompression: "quantized"` 并启用 POT 优化。 3. 对已有导出或需要二次分组的明文 JSON 调用一次 `texture_optimize_export`;新转换已优化时不要重复处理。 4. 对每个成功结果调用 `texture_validate_export`,确认所有 PNG 页存在、页面为 POT、`res[id].p` 合法且矩形未越界。 批量工具返回 `total`、`success`、`failed`、`skipped`、`copied`、`copySkipped`、`copyFailed` 和逐项 `results`。任何 MCP 错误都会返回 `isError: true`;输入目录和输出目录不能相同,输出目录也不能位于输入目录内部。默认不覆盖,只有用户明确要求时才传 `overwrite: true`。 编辑器方案调用顺序:先 `texture_get_capabilities` 选定 `serverId/instanceId`,再 `texture_project_open` 或 `texture_project_get` 获取 `projectId/revision`;保存时传同一版本的 `expectedRevision` 与唯一 `requestId`,导出时明确 `source: saved`(磁盘已保存版)或 `source: snapshot`(未保存内存预览),最后用 `texture_job_get` 查询完成状态。MCP 可执行文件不需要手动架设服务器,但读取当前编辑器状态必须保持 Texture Maker UI/桌面窗口运行。完整参数、HTTP 安全边界、错误处理及当前未实现的第二阶段能力见 [`ai/texture-maker/MCP.md`](ai/texture-maker/MCP.md)。 完整的 AI 调用流程、输入参数、返回结构、错误处理和 CLI 备用方式,见 [`ai/texture-maker/README.md`](ai/texture-maker/README.md)、[`MCP.md`](ai/texture-maker/MCP.md) 与 [`textureSkill/SKILL.md`](ai/texture-maker/textureSkill/SKILL.md)。 接入代码契约见 [`ai/texture-maker/CODE.md`](ai/texture-maker/CODE.md)。该文档专门给 AI 读取,区分了 LayaAir 的现成播放器调用与 Cocos Creator 的项目侧适配实现。 ## 使用流程 1. 启动工具。 2. 点击“打开 SWF”拆解 Flash 动画,或点击“导入连续图片”选择一组 PNG。 3. SWF 导入可设置资源模式和缩放;PNG 序列可设置动画名称、帧率、每图持续帧数和初始对齐。 4. 在左下角“图片装箱”中选择装箱算法、间隙和分页最大尺寸;需要自动合并为更优 POT 页面时点击“优化装箱”。右侧可调整全部源图集缩小百分比。 5. 在中间区域切换“图集预览”“数据预览”“动画预览”检查结果;删除关键帧后在图集预览点击“刷新图集”清理无用图块。 6. 在右侧设置动画片段缩放、帧锚记、帧指令、导出选项和 PNG 压缩方式。 7. PNG 动画可在动画预览中逐帧拖动位置,并插入、复制、删除或拖动换序关键帧;暂停时可开启洋葱皮校准动作。 8. 点击导出,得到 JSON 与 PNG 图集文件。 ### TextureMerger JSON/PNG 迁移 “导入其他 → 导入 TextureMerger JSON/PNG(可多组)”支持一次选择多组同名 `.json + .png`。工具按不区分大小写的 basename 自动配对,把旧长格式帧数据归一为 Texture Maker 动画、从旧图集裁出独立图块并重新装箱。每组独立导入,缺失或损坏的一组会显示具体名称和错误,不会回滚已经成功的组。 导入后可继续编辑时间轴、调整图块装箱、保存 `.tmproj`,或通过当前发布面板导出 Texture Maker `v0.9` 短格式 JSON 与单页/多页 PNG。命令行与 MCP 也支持递归批量转换、保持相对目录和可选复制其他文件;默认不覆盖已有输出,并禁止把输出写回输入目录。 如果目标是把一个 TextureMerger 项目目录整体迁移成一批独立的 Texture Maker 成品,请使用顶部的“批量转换 TextureMerger”入口,不要使用上面的导入入口。该入口是独立工作流,不会把结果追加到当前编辑方案: 1. 选择源目录。默认递归扫描全部子目录,按“相对目录 + basename”(不区分扩展名大小写)配对同名 `.json + .png`;缺一侧、重复文件或损坏文件会单独列为跳过/失败。取消“递归扫描子目录并保持目录结构”后才只扫描第一层。 2. 选择输出目录。输出目录必须与源目录不同;源目录只读,转换过程不会改写 TextureMerger 原文件。每组输出会写入源目录对应的相对路径,例如 `effects/fire/R_Trans.json` 会输出到 `目标目录/effects/fire/`。 3. 设置图集最大宽度和最大高度,默认 `2048 x 2048`。每个 TextureMerger 图集会先裁成独立图块,再重新装箱;超出尺寸时自动生成 `.png`、`_2.png` 等多页 PNG。 4. 文件名默认保持原 basename,例如 `SK_ATK2.json` + `SK_ATK2.png` 仍输出 `SK_ATK2.json` + `SK_ATK2.png`。需要区分批次时填写统一“文件名后缀”(例如 `_tm`),会输出 `SK_ATK2_tm.json` + `SK_ATK2_tm.png`;后缀为空则不改名。 5. 可选勾选“复制非 TextureMerger 文件”,工具会把源目录中的其他扩展名文件按原相对路径复制到目标目录;`.json/.png` 只作为 TextureMerger 配对候选,不会把缺配对的文件误当普通文件复制。 6. 默认不覆盖输出目录已有文件。需要重做时勾选“覆盖输出目录中同名文件”,再点击“开始转换”。 7. 完成后面板显示总数、成功、失败、跳过、复制数量和逐项原因,并把每组的 Texture Maker `v0.9` JSON/PNG 直接写入目标目录。输出可继续通过“打开方案”导入编辑,也可直接给 LayaAir/Cocos 运行时使用。 转换过程中会按组实时显示进度条、当前组名、`已完成/总组数`、成功/失败/跳过数量和已写入文件数;单组失败不会中断后续转换。 批量转换需要支持目录读写的 Chromium File System Access API;Windows/macOS 桌面版已内置该能力。浏览器开发态建议使用 Chromium 并通过 `npm run ui` 启动。该 UI 批量转换与“导入 TextureMerger JSON/PNG(可多组)”互不替代:导入用于把资源追加到当前编辑器,批量转换用于高效率生成一批独立发布文件。 ![批量转换 TextureMerger UI](docs/images/texturemerger-batch-ui.png) 图中界面展示了源目录、目标目录、递归扫描、普通文件复制、文件名后缀、覆盖策略和实时进度。工具图标资源见:![TextureMerger 图标](docs/images/texturemerger-icon.png)。 #### 成品格式转换规则 转换不是复制旧图集,而是执行以下步骤: 1. 读取 TextureMerger 长格式 JSON,识别 `mc` 动画、帧持续时间、帧率、图层变换、事件和 `res` 资源矩形。 2. 读取同名 PNG 图集,校验每个 `res` 矩形没有越界。 3. 从旧图集中裁出独立 RGBA 图块,再按最大宽高重新装箱。 4. 输出 Texture Maker `v0.9` 短格式 JSON:包含 `v`、`mc`、`res`;多页时增加 `pngs`,资源跨页时写入 `res[id].p`。 5. 输出 `.json`、`.png`;多页继续输出 `_2.png`、`_3.png`,JSON 中的 `pngs` 顺序与页码一致。 单组转换和批量转换生成的是可继续导入编辑的成品 JSON/PNG,不会修改 TextureMerger 源文件。批量转换保留源目录相对路径;例如 `skill/effects/fire.json` 会生成到 `目标目录/skill/effects/fire.json`。`nameSuffix` 只追加到输出 basename,不改变目录结构。 CLI 等价命令: ```bash node ./bin/texture-maker.js inspect-texturemerger D:/assets/effects/fire.json node ./bin/texture-maker.js import-texturemerger D:/assets/effects/fire.json --out D:/converted/fire node ./bin/texture-maker.js batch-texturemerger D:/assets/effects --out D:/converted-effects --recursive --copy-other --suffix _tm ``` `--recursive` 扫描所有子目录并保持结构;不传时只扫描第一层。`--copy-other` 复制非 `.json/.png` 文件;`--suffix` 追加统一后缀;`--overwrite` 允许覆盖已有输出。单项失败会记录在摘要中,不会阻止其他项目继续转换。 ### 连续 PNG 动画 一次选择的多张 PNG 会先检查文件名。发现相同前缀和连续数字尾号时,例如 `run_0001.png` 至 `run_0010.png`,工具会先询问是否按连续动画图片导入;确认后再进入参数弹窗。工具不依赖系统文件选择顺序,而是按文件名自然排序,例如 `2.png` 会排在 `10.png` 前。导入弹窗中的“每图持续”默认是 `5` 帧,表示每张图片在时间轴上保持多少帧,与 SWF 关键帧段的 `duration` 完全相同;它不是九宫格或 spritesheet 切片数量。 图片默认按原始画布中心对齐动画原点,并默认勾选“去除空白位置”。工具会裁掉四边 alpha 为 0 的透明区域以减少图集占用,同时把裁剪起点补偿进帧坐标,因此裁剪前后动画中心和播放位置不变。取消勾选即可保留完整原图画布。 进入“动画预览”后,可以点击并拖动当前帧图片,也可以使用右侧 X/Y 和方向按钮精确调整。时间轴提供: - `插入帧`:延长当前关键帧画面一帧,采用 Flash F5 语义。 - `空白关键帧`:在当前帧后插入透明关键帧。 - `复制关键帧`:深复制当前关键帧段的画面、坐标和持续帧数,插入其后;为避免事件重复触发,不复制锚记、指令、参数和片段标签。 - `删除帧`:缩短当前持续段,或删除只有一帧的关键帧段。 - `删除关键帧`:确认后删除当前完整关键帧段并直接拼接后续段;动画删空时保留一帧空白关键帧。 - `← / →`:将完整关键帧段前移或后移,持续帧、图层与已有标记一起移动。 - `Shift + 单击`:连续选择两个端点之间的关键帧;右侧坐标与变换操作会作用于这些帧的全部图层。 - `Ctrl + 单击`(macOS 用 `Cmd + 单击`):逐个增减非连续关键帧;右栏图层标题旁的图标可全选,再点一次恢复当前关键帧单选。 - 增删帧、拖动调整和撤销/重做后,时间轴尽量保持原横向滚动位置;若总长度缩短则停在新的最右端。 - `整体相对 / 自身锚点`:多帧缩放默认按动画原点同步缩放尺寸与坐标,保持图块间相对关系;切换为自身锚点后只改变每个图层自身尺寸。 - `撤销 / 重做`:覆盖时间轴、图层、变换、帧事件和外部图块重新导入;连续长按微调会合并为一个步骤。 这些编辑命令集中在动画画布上方的浅色帧工具栏,并使用 Lucide 图标配合文字说明;底栏只保留播放、帧号、缩放和中心点等预览控制。播放期间工具栏、画布拖动和右侧帧编辑会统一锁定,暂停后才恢复,避免编辑联动拖慢动画预览。关键帧拖动期间只显示目标帧线,松手后才修改数据;取消拖动不会留下中间状态。 右侧“图块文件”提供三种入口:点击“在线编辑”在内置画布中使用画笔、橡皮擦、取色、矩形选区、移动选区、缩放和撤销/重做;桌面版点击“编辑”可用 Photoshop、Aseprite 等外部软件编辑临时副本;浏览器版点击“下载 PNG”后可用外部软件编辑,再将 PNG 拖回明确标注的替换区域,或点“选择修改后的 PNG”。在线编辑有独立于动画时间轴的撤销栈:弹窗内 `Ctrl/Cmd+Z` 撤销、`Ctrl/Cmd+Shift+Z` 或 `Ctrl+Y` 重做,取消并重新打开时从新图片状态开始;应用图块才作为动画项目的一次操作进入项目撤销栈。`+` / `-` 缩放画布,`[` / `]` 调整画笔和橡皮擦粗细;拖动弹窗右下角可调整编辑区域大小。图层栏的品红(`#FF00FF`)和绿色(`#00FF00`)按钮切换透明区域的预览底色,再点当前按钮恢复白色;底色不会写入 PNG。图块按资源 ID 定位,应用后重新装箱,同一资源的所有引用帧一起更新;编辑结果仍需保存 `.tmproj`。SWF 来源只更新项目内图块,不修改源 SWF。 连续 PNG 来源在桌面版回存时还会同步更新原 PNG:先把原图复制为同目录下的 `原图片名_bak_YYYYMMDD_HHMMSS.png`,再覆盖原 PNG;外部编辑器打开的是临时副本,直接按 Ctrl+S 不会绕过备份。浏览器版在线编辑点击“应用到方案”时直接更新当前方案和图集,不弹文件或目录选择器,也不改磁盘源 PNG;随后通过“文件 > 保存方案”保存 `.tmproj`。右侧会显示“原 PNG 尚未同步”;如需覆盖源文件,再主动点击“同步源 PNG”,选择源图所在目录并授予权限。程序核对同名源文件与导入时内容一致,先备份再覆盖;取消授权、目录不匹配或备份失败不会丢失已应用到方案的编辑。待同步的编辑 PNG 会随 `.tmproj` 保存,重开后仍可继续编辑或同步。浏览器外部编辑的“选择修改后的 PNG”流程仍需在回写源文件时选择目录。磁盘源 PNG 不受方案撤销/重做控制,需要恢复时使用 `_bak_` 文件。 开启“洋葱皮”后,暂停状态会以青色显示上一关键帧段,并以洋红色显示后续关键帧段。“后看”可在 1-5 帧间调整,距离越远透明度越低;参考画面不会被选中,也不会进入导出数据。 PNG 动画与 SWF 动画可以混合追加到同一个项目,共用装箱、分页、JSON/TMD 数据和导出设置。两种来源最终生成相同的 `mc/res/layers` 运行时结构,播放器不需要区分素材来源。 ## 核心工作流详解 ### 多动画集合、分页与容量控制 Texture Maker 可以把多个 SWF 或多个动画片段放在同一个工作区中处理。顶部动画条用于在不同动画之间切换,左侧资源列表展示当前图集里的图块、尺寸和选中状态,方便检查每个资源是否被正确拆出。 ![多动画集合与分页](docs/images/workflow-multi-animation.png) 左下角“图片装箱”里的“最大宽度”和“最大高度”用于预设单张图集页的最大尺寸。比如把上限设为 `1024 x 1024`,就能把单页纹理控制在更低的显存容量内;当资源放不下时,工具会自动拆成多页图集,并在底部状态栏显示“装箱分页”和页码。导出时会生成 `name.png`、`name_2.png` 等多张 PNG,JSON 中用 `pngs` 和 `res.p` 标记每个资源属于哪一页。 布局、间隙和最大尺寸没有待应用状态,修改后立即重建预览;连续快速调整时只提交最后一次装箱结果,失败则恢复上一组有效参数。 右上角会显示页数、首张图集实际尺寸、估算显存、装箱算法和间隙。右侧导出面板会汇总图集页数与纹理数量,帮助发布前快速判断资源规模。 图集预览工具栏和动画预览工具栏都提供手动“重新装箱 / 刷新图集”。删除或修改关键帧后,图集不会在每次编辑时自动重采样,避免连续操作卡顿;图集预览按钮会扫描所有可编辑动画片段的真实图层引用,有废弃图块时直接显示“刷新图集 (数量)”。点击后移除未被引用的图块并按当前装箱设置重建图集。共享图块只要仍被任一动画引用就会保留;操作完成后会保留当前帧和时间轴位置,若有资源被移除则方案会标记为未保存,需要保存 `.tmproj` 后再用 MCP 的 `source: saved` 导出。 ### 装箱算法与图块间隙 图集装箱不只有一种排布方式。不同项目对“紧凑度”“稳定性”“可读性”和“显存占用”的取舍不同,因此工具提供多种装箱算法: ![装箱算法](docs/images/workflow-packing-algorithms.png) - `CommonBestFit`:默认综合策略,优先兼顾紧凑度和稳定性。 - `BestAreaFit`:偏向面积利用率,适合希望尽量塞满图集的情况。 - `BestLongSideFit` / `BestShortSideFit`:按长边或短边匹配,适合某些形状差异明显的图块。 - `BottomLeftRule`:更接近传统左下角排布,结果直观稳定。 - `ContactPointRule`:倾向让图块相互贴合,尝试减少碎片空间。 点击“优化装箱”后,工具会枚举当前最大宽高范围内允许的 POT 页面组合,对每套组合执行当前 MaxRects 算法,再按以下顺序选择: 1. 总 2 次幂纹理面积最小。 2. 面积相同时页数最少。 3. 面积和页数相同时,优先更紧凑、较低高度且较宽的页面。 因此 `4 × 512` 会使用 `1024 × 1024`,`3 × 512` 会使用 `1024 × 512 + 512 × 512`,而不会为了减少页数把三个图块装进更大的 `1024 × 1024`。再次点击“优化装箱”可恢复标准装箱。 默认 `1px` 间隙遇到 `2 × 512` 这类刚好差 1px 的情况时,优化器还会额外尝试紧贴候选;只有紧贴后确实减少 POT 面积或页数才会采用,否则继续保留配置的间隙。 “间隙”用于在图块之间留出空白边,默认值为 `1px`。2D 引擎在缩放、旋转、线性采样或 mipmap 场景中,图块边缘可能采到隔壁图块颜色,形成出色边。适当增加 `1-2px` 间隙可以降低这类串色风险;如果项目严格使用最近邻采样且不缩放,也可以改为 `0px` 以节省空间。 ### 帧事件、指令与时间轴检查 动画预览页签可以按时间轴查看当前动画。时间轴上会显示关键帧段和指令标记,右侧“当前帧”区域可以查看或编辑锚记、指令和参数。 支持两种工作方式: - 在 Flash 里直接写帧标签,导入时自动识别。 - 在 Texture Maker 里选中帧后,直接编辑锚记、指令和参数。 常用写法: - `#MARK`:给当前帧设置锚记,运行时可 `gotoPlay("MARK")` 或 `gotoAndStop("MARK")`。 - `@STOP`:播放到当前帧后暂停,再次播放时从下一帧段继续。 - `@EVENT:HIT`:播放到当前帧时派发 `HIT` 事件,用于命中、音效、屏幕震动等逻辑。 - `@GOTO:IDLE`:切换到名为 `IDLE` 的动画片段。 - `@JMP:MARK`:跳转到当前片段内的帧锚记。 这些信息会写入导出 JSON 的 `id`、`act`、`parm` 字段,播放端按同一套规则解释,不需要在游戏代码里重新硬编码帧号。 ### 一条龙发布与压缩输出 导出设置面板集中处理发布前常用选项:图集名称、图集格式、全部源图集缩小、2 次幂尺寸、JSON/TMD 数据、PNG 压缩方式、自动保存方案和导出按钮。每个复选项后都有紧邻的问号说明,便于判断兼容性与输出文件用途。 “全部源图集缩小”提供 `10%–100%` 数字输入、滑杆和每次 `1%` 的 `- / +` 按钮,默认 `100%`。拖动滑杆时只实时更新百分比,松手后才重新装箱,避免重采样过程把滑块拉回;点击按钮则立即按 `1%` 步进并提交。缩放在装箱前执行,所有图块先按 alpha-aware Lanczos3 重采样,再重新分页;因大图块超过 `2048` 或 `4096` 上限时,可以先调低百分比再导出。图集 `res.w/res.h` 和最终 PNG 同步缩小,每层 `ts` 按所属图块取整后的实际缩放比补偿,播放时仍保持原动画显示尺寸,极小图块也不会被反向放大。源 PNG、方案编辑图块和 `.tmproj` 内嵌资源都不会被改写;切回 `100%` 即可恢复原始图集质量。 “最终导出尺寸”会同时显示每页 `2POT利用率` 和多页合计利用率: ```text 2POT利用率 = 当前页所有图片矩形面积合计 / (页宽向上取 2 次幂 × 页高向上取 2 次幂) ``` 利用率只反映实际纹理占用,因此分母固定使用宽高分别向上取整后的 2 次幂面积,与是否勾选“2 次幂尺寸”导出选项无关。例如 `398 × 265` 按 `512 × 512` 计算,而不是按 `398 × 265` 的输出尺寸计算。间隙和 2 次幂纹理空白都会进入分母。多页项目会额外显示“合计 2POT利用率”,用所有页图片矩形面积合计除以所有页 POT 面积合计。 ### 三种缩放的区别 三种设置都不会直接覆盖磁盘上的原始 SWF 或 PNG,但作用层级不同: | 设置 | 改变什么 | 是否改磁盘原图 | 是否改当前方案图块 | 质量与恢复 | | --- | --- | --- | --- | --- | | 动画设置 → 原素材缩放 | 重新栅格化/重出项目图块,并写入纹理补偿 `ts` | 否 | 是,当前 `images` 和 `.tmproj` 的可编辑图块会变化 | 缩小会减少项目图块像素;放大不会补回不存在的细节。保存的 `.tmproj` 仍内嵌原始素材,通常可改回 `1.00` 后重新生成 | | 动画设置 → 输出缩放 | 只写运行时片段倍率 `cs`,改变最终显示大小 | 否 | 否,不改变 PNG 图和 `res` 矩形 | 源图和项目图块不损失,但放大显示可能暴露模糊,缩小显示可能产生采样锯齿 | | 导出设置 → 全部源图集缩小 | 装箱前对全部图块生成临时重采样副本 | 否 | 否 | 导出的 PNG 本身会损失被缩掉的细节;调回 `100%` 可从当前项目图块重新导出完整质量 | 因此,图2中真正会改变项目图块像素的是“原素材缩放”;“输出缩放”只改运行时显示倍率。图1新增的“全部源图集缩小”对源图和当前方案都是非破坏性的,但它生成的最终导出 PNG 仍然是缩小后的结果,细节不会凭空恢复。若目标是减小最终纹理和分页,同时保留项目继续编辑的能力,优先使用图1的功能。 ![发布与压缩](docs/images/workflow-export-compression.png) PNG 压缩方式包含: - `不压缩 / 标准 PNG`:无损、速度最快、兼容性最高,体积通常最大。 - `无损优化`:像素完全不变,优化 PNG 行过滤和 zlib 压缩,适合保守发布。 - `高质量量化`:最多 256 色并保留 alpha,优先视觉质量,压缩率中等。 - `TinyPNG 风格量化(推荐)`:默认发布模式,压缩率通常最高,可能有轻微色带或透明边缘变化,不适合时会自动回退。 在合适的特效素材上,量化压缩可能把 PNG 体积减少到原来的很小一部分,最高可减少约 80%,具体取决于素材颜色数量、透明度和压缩方式。建议发布前在动画预览或 LayaAir Demo 中检查最终画面。 “导出压缩数据”会生成运行时入口 `Name.json` 和压缩正文 `Name.tmd`。入口 JSON 是很小的 manifest,包含 `encode` 与 `pngs`;播放器先读取入口 JSON,发现 `encode.type = "tmd"` 后会并行加载 `.tmd` 与 PNG 页,全部完成后再触发加载完成。若同时勾选“导出 JSON 数据”,工具会额外导出 `Name.debug.json` 供人工检查。 ### 压缩数据文件结构 只勾选“导出压缩数据”时,单页动画会得到: ```text Name.json # 运行时入口 manifest Name.tmd # gzip 压缩后的完整动画数据 Name.png # 第 1 页图集 ``` 多页动画会继续生成 `Name_2.png`、`Name_3.png`。同时勾选“导出 JSON 数据”时还会生成 `Name.debug.json`,它是方便人工检查的完整明文数据,不参与播放器加载。 入口 `Name.json` 很小,只负责告诉播放器压缩文件和 PNG 页在哪里: ```json { "v": "0.9", "encode": { "type": "tmd", "version": 1, "file": "Name.tmd", "algorithm": "gzip", "source": "utf8-json" }, "pngs": ["Name.png", "Name_2.png"] } ``` `.tmd` 使用 `TMD1` 自描述容器:固定文件头保存版本、压缩算法和 UTF-8 header 长度,正文是完整运行时 JSON 的 UTF-8 字节经过 gzip 压缩后的 payload。中文动画名、事件参数和文件名都按 UTF-8 保存。 ### 播放器加载原理 ```mermaid flowchart TD A[传入动画资源名] --> B[加载 Name.json] B --> C{是否包含 encode.type = tmd} C -- 否 --> D[读取普通 mc / res 数据] C -- 是 --> E[读取 encode.file 与 pngs] E --> F[并行下载 Name.tmd] E --> G[并行预加载全部 PNG 页] F --> H[校验 TMD1 并 gzip 解压] H --> I[UTF-8 解码并解析运行时 JSON] I --> J{数据与全部 PNG 是否完成} G --> J D --> K[加载同名或 pngs 指定的 PNG] K --> L[建立纹理页与动画数据] J --> L L --> M[factory 标记 loaded] M --> N[触发加载完成并允许播放] ``` 播放器不会在 JSON 失败后尝试探测 `.tmd`,因此不会产生额外 404 和重试延迟。压缩入口识别成功后,TMD 与全部 PNG 页并行下载;只有数据解压解析成功且所有纹理页就绪,factory 才会标记加载完成并触发回调。 `McFactorysManager` 会继续缓存已经加载和正在加载的 factory。关卡可以提前请求本关需要的全部动画,用统一加载进度条等待它们完成;实际播放时复用缓存,不需要再次下载,避免游戏过程中临时加载造成卡顿。 精确的二进制偏移、字段含义和兼容规则见 [dataformat_encode.md](dataformat_encode.md)。 ## 界面区域说明 ### 左侧资源区 - 显示当前项目和已导入资源。 - 支持 16、32、64、128 四档缩略图大小。 - “图片装箱”区域用于控制图集布局、间隙和分页最大尺寸;“优化装箱”用于自动选择总 POT 面积更小的页面组合。 ### 顶部文件菜单 - “方案”:打开、保存或关闭可二次编辑的 `.tmproj`。 - “导入 SWF / 导入连续 PNG”:一级入口,向当前方案追加常用动画素材。 - “导入其他”:急救恢复 Texture Maker 发布文件,或导入旧 TextureMerger JSON/PNG。 - “导出”:把当前动画按关键帧段输出为统一尺寸 PNG;一个 duration 为 5 的关键帧段仍只输出一张,不生成重复帧。 - 方案有未保存修改时,关闭或打开另一方案会提示“保存 / 放弃 / 取消”。 急救恢复只使用已经发布的像素与运行时数据,无法还原原始 SWF、裁剪前画布和原素材参数。它是忘记保存 `.tmproj` 时的补救入口,恢复后应立即保存正式方案。 ### 中间预览区 - “图集预览”:查看打包后的图集页面和资源边框。 - “数据预览”:查看即将导出的运行时 JSON。 - “动画预览”:按 SWF 时间轴播放动画,检查帧、片段和坐标。 左侧图标栏中的标签与有序列表按钮分别控制缩略图帧名字和帧范围;范围会合并同一资源的复用区间,例如 `第 1-5、11-15 帧`。 ### 右侧设置区 - “动画设置”:调整当前片段名称、原素材缩放、输出缩放、帧锚记和帧指令。 - “导出设置”:设置图集名称、全部源图集缩小、PNG 压缩方式、2 次幂输出等导出参数。 ## 导出文件 单页图集通常输出: ```text Blade1.json Blade1.png ``` 多页图集会输出: ```text MultPage.json MultPage.png MultPage_2.png ``` JSON 示例: ```json { "v": "0.9", "pngs": ["MultPage.png", "MultPage_2.png"], "mc": { "CHANT": { "fps": 60, "f": [ { "f": 1, "d": 4, "l": [{ "r": "F51145BF", "x": 0, "y": 0 }] } ] } }, "res": { "F51145BF": { "x": 0, "y": 0, "w": 173, "h": 174 }, "BLADE": { "p": 1, "x": 0, "y": 0, "w": 512, "h": 512 } } } ``` 字段重点: - `mc` 中每个 key 是一个动画片段或 mcGroup。 - `f` 是关键帧段数组,`d` 表示持续帧数。 - `l` 是当前帧的图层数组。 - `r` 引用 `res` 中的资源 id。 - `res` 记录每个资源在 PNG 图集中的 `x/y/w/h`。 - `p` 表示资源所在图集页,从 0 开始,缺省表示第 0 页。 更详细的数据格式说明见 [dataformat.md](dataformat.md)。 ## LayaAir 接入 播放器核心位于: ```text src/laya_player_core/js/vc.core.js ``` TypeScript 声明位于: ```text src/laya_player_core/core/ ``` 播放器支持: - 旧 TextureMerger JSON。 - Texture Maker 短格式 JSON。 - `pngs` 多页图集。 - `res.p` 资源页码。 - `cs` 输出缩放。 - `ts` 纹理预缩放补偿;包含原素材缩放与全局导出图集缩小的乘积。 - `JMP/GOTO/EVENT/STOP` 帧指令。 - `play(loop, tag)` 片段播放。 - `gotoPlay("MARK")`、`gotoAndStop("MARK")` 帧锚记跳转。 启动 Demo: ```bash cd Laya3Demo npm start ``` 默认地址: ```text http://127.0.0.1:17030/ ``` 如果端口被占用,可以指定新端口: ```bash PORT=17031 npm start ``` ## 构建发布 所有 bat/sh 快捷入口和相关 Node 构建实现统一位于 `build/`;npm 命令保持不变,构建产物仍输出到根目录 `export/`。 ### 普通目录包 生成包含 Node 运行时的本地目录包: ```bash npm run build:mac npm run build:win npm run build:all ``` Windows 目录包输出到 `export/win/`,通过 `texture-maker-ui.cmd` 启动。 ### 单文件包 生成 Node SEA 单文件发布产物: ```bash npm run build:single:mac npm run build:single:win npm run build:single:all ``` Windows 单文件程序输出为 `export/win-single/TextureMarker.exe`。程序已内嵌 Node 运行时和 Web UI 资源,启动后会打开浏览器界面;发布时只需要分发这一个 EXE。MCP 使用独立入口,不包含在这个文件中。 ### Electron 桌面版 生成内置 Chromium 的桌面应用: ```bash npm run build:electron:mac npm run build:electron:win npm run build:electron:all ``` Windows Electron 版输出到 `export/desktop-win/TextureMaker-win32-x64/`,主程序为 `TextureMaker.exe`。该目录中的 `resources`、`locales`、DLL 等文件是运行所需组件,分发时需要整体保留。需要完整桌面窗口和内置 Chromium 时使用此版本;只需要单文件启动器和系统浏览器时使用 `build:single:win`。 构建产物输出到 `export/`,该目录为本地构建产物,不提交到仓库。 桌面版首次选择外部编辑软件后会记忆设置;源路径失效时可重新定位 PNG。外部编辑结束后回到 Texture Maker 点击“编辑完成”,工具会校验 PNG、备份图片来源的源文件、重新装箱,并把项目内替换纳入撤销/重做历史。浏览器版在线编辑直接应用到方案;只有明确同步源 PNG 或导入外部修改文件并回写源图时,才需要选择源目录并授予写入权限。 ## 测试样本 测试代码、原始样本、连续 PNG、导出基准和兼容 fixtures 统一位于 `TestRes/`。其中 `TestRes/testSwf/` 包含当前开发和回归用 SWF 样本: - `Blade1.swf/json/png`:帧事件、`@STOP`、`@EVENT` 测试。 - `role_3.swf/json/png`:角色多状态动画,包含 `IDLE`、`SKILL`、`LEVEL_UP`。 - `Suicide.swf/json/png`:自毁技能动画,包含 `CHANT`、`EXPLO`。 - `SuicideCombine.json/png`:多片段缩放验证样本。 - `MultPage.json/png/_2.png`:多页图集验证样本。 其他回归素材: - `TestRes/testPIC/`:连续 PNG 自然排序、透明裁剪和中心补偿样本。 - `TestRes/Import/TextureMergerData/`:旧 TextureMerger JSON/PNG 兼容导入样本。 - `TestRes/testExport/`:`Blade1` 图集/JSON 与 15 张关键帧段 PNG,验证统一中心画布和不展开 duration 重复帧。 - `TestRes/test/`:Node 自动化测试与拆解开发样本。 ## 常见问题 ### 页面显示的版本不是最新 工具启动时会在控制台输出版本号,例如: ```text Texture Maker UI v0.1.139 ``` 如果浏览器控制台、页面脚本版本或接口行为和当前版本不一致,优先检查是否开着旧服务进程,或桌面版是否仍在运行旧包。 ### 默认端口被占用 Web UI 默认使用 `5177`,如果端口被占用会自动尝试后续端口。以控制台打印的实际 URL 为准。 ### 多页图集如何接入 读取 JSON 顶层 `pngs`,按顺序加载 PNG 页。读取 `res[id].p` 判断资源属于哪一页;缺省 `p` 时按第 0 页处理。 ### Windows 桌面版打开某些 SWF 报错 如果是旧版本,请更新到包含跨平台 JPEG3 解码的版本。当前版本使用本地 JS JPEG 解码器,不依赖 macOS `sips`,Windows/macOS 行为一致。 ### Gitee 上截图不显示 README 使用仓库内相对路径引用截图,例如: ```md ![Texture Maker 主界面](docs/images/ui-main.jpg) ``` 确认截图文件已提交到 `docs/images/`,并且文件名大小写完全一致。 ## 当前状态 当前版本为 `0.1.139`。已覆盖 SWF/连续 PNG 混合导入、关键帧多选与时序编辑、洋葱皮、内置图块编辑、POT 优化装箱、全局导出缩放、多页 PNG、`.tmproj` 方案续作、发布文件急救、TextureMerger 迁移、关键帧 PNG 输出、JSON/TMD 压缩、LayaAir 预加载缓存,以及可由 MCP 查询和操作的存活编辑器会话。后续方向持续记录在 [todo.md](todo.md)。 ## 相关文档 - [dataformat.md](dataformat.md):运行时 JSON 数据格式。 - [projectformat.md](projectformat.md):`.tmproj` 二次编辑方案文件格式。 - [swffile.md](swffile.md):SWF 解析记录。 - [filelist.md](filelist.md):项目文件清单。 - [todo.md](todo.md):动画编辑能力的完成状态与后续方向。 - [Laya3Demo/README.md](Laya3Demo/README.md):LayaAir Demo 使用说明。