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

当前界面:分组文件菜单、4 个动画片段、1024 × 1024 即时装箱、双页图集与分页导航。
> **连续 PNG 不再只是散图。** Texture Maker 会识别编号、自然排序、裁掉四周全透明区域,再把原画布中心补偿进帧坐标。图集只保存有内容的像素,动画位置仍保持原样。
## 核心卖点
### 连续图片,直接成为可编辑动画
不用 Flash,也不用先拼 spritesheet。点击“导入连续图片”,一次选中编号 PNG,再设置播放帧率和每张图片默认保持多少帧,就能直接得到可编辑动画。
 1. 点击导入 主界面直接进入连续 PNG 工作流 |
 2. 批量选择 自动识别编号并按文件名自然排序 |
 3. 设置节奏 选择帧率、每图持续与初始对齐 |
“每图持续”与播放帧率共同决定初始节奏:`单张显示时间 = 每图持续 ÷ 播放帧率`。例如 `60 fps`、每图持续 `5` 帧时,每张图显示约 `83.3 ms`,整组图片以每秒 `12` 张的节奏播放。这个值只是批量导入的统一起点,导入后仍能逐个关键帧段调整。
#### 透明区域不进图集,显存预算可以直接算
仓库中的 10 张 `TestRes/testPIC` 原图都是 `200 × 200`。默认“去除空白位置”会裁掉四边全透明像素,同时把裁剪偏移补偿到帧坐标,所以动画中心不漂移;有效图块最终被装进一张 `463 × 505` 图集。
 原始素材:10 张 200 × 200 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 规则为准。
### 时间轴不只是播放预览
亮色帧工具栏集中提供插入帧、空白关键帧、复制、删除、删除关键帧和前后移动。关键帧还可以直接在时间轴拖动换序;洋葱皮支持后看 1-5 个关键帧段,适合校准逐帧动作。

导入时设置的是所有图片的默认持续帧数;进入动画预览后,可以针对某一段使用“插入帧”延长停留,或用“删除帧”缩短停留。这样同一组素材里,蓄力帧可以更慢、爆发帧可以更快,美术无需改代码就能直接调整动画节奏。
播放期间编辑器会锁定帧操作、画布拖动和右侧帧面板,并停止逐帧重建编辑侧栏;暂停后再恢复编辑,检查动画时更稳定。
### 从图集预算到发布体积
装箱算法、图块间隙和单页最大尺寸修改后会立即重新装箱,不再需要额外点击“应用”。资源超过上限时自动分页,状态栏可按页聚焦;2 次幂补边、PNG 优化和 JSON/TMD 数据压缩集中在发布面板完成。
### 一个文件保留完整制作方案
顶部菜单把方案、常用导入、兼容导入和辅助导出分开。`.tmproj` 会把原始素材、当前编辑图块、时间轴、坐标、缩放、装箱和导出设置保存为一个可拷贝文件;即使原始素材不在原目录,也能重新打开继续编辑。
导出设置可勾选“自动保存方案”,发布图集时会额外生成同名 `.tmproj`。它只供 Texture Maker 二次编辑,**不需要复制到游戏资源目录**;游戏仍只加载 JSON/TMD 与 PNG。
### 忘记保存,也还有一条退路
“导入其他”提供两条兼容路径:使用完整 JSON/TMD 与全部 PNG 页急救恢复 Texture Maker 发布文件,或直接导入旧 TextureMerger JSON/PNG。恢复使用的是已发布像素,不能替代正式 `.tmproj`,但足以重新装箱、编辑帧并保存新方案。

### 关键帧可以直接交给下一道工序
当前动画可按关键帧段导出统一尺寸 PNG。所有图片以动画原点居中、四边保留 `2px` 透明边;duration 为 5 的关键帧段仍只输出一张,不制造重复文件,不同关键帧段即使画面相同也分别保留。

### 导出后即可进入游戏
多页图集通过 `pngs` 与 `res.p` 定位资源页;LayaAir 播放器能够识别普通 JSON 和 TMD manifest,预加载全部纹理页并缓存 factory。仓库内置 Demo 用于验证单页、多页、压缩数据、片段切换与帧事件。
## 能力全景
- **SWF 与连续图片导入**:既能拆解 SWF,也能把多张 PNG 按自然文件名顺序建立为动画帧。
- **透明边自动裁剪**:只装箱有效像素,并通过裁剪偏移补偿保持原画布中心。
- **动画帧编辑**:插入、复制、删除、空白关键帧、拖动换序和坐标微调。
- **多帧洋葱皮**:暂停时查看前一关键帧与后续 1-5 个关键帧段。
- **PNG 图集装箱**:把动画引用的资源打包为图集,支持间隙、最大尺寸和多种装箱策略。
- **装箱即时预览**:算法、间隙和分页尺寸一改即重新装箱,快速比较结果。
- **多页图集输出**:单张图集放不下时自动分页,输出 `texture.png`、`texture_2.png` 等多张 PNG。
- **运行时 JSON**:导出短字段 JSON,包含 `mc` 动画片段、`res` 图集矩形、`pngs` 多页图集列表。
- **动画预览**:在工具内查看图集、数据和动画播放效果,辅助检查拆解结果。
- **片段与帧标签**:支持 Flash 帧标签导入,包含 `#MARK` 锚记、`@STOP`、`@GOTO`、`@EVENT` 等指令。
- **片段缩放**:支持导入时原素材缩放和运行时输出缩放,便于处理不同动画片段的尺寸差异。
- **方案保存**:使用单文件 `.tmproj` 保存原始素材与完整编辑状态,支持换目录、换电脑继续制作。
- **发布文件急救**:忘记保存方案时,可选择完整 JSON/TMD 与全部 PNG 页,有限恢复可编辑动画后立即另存 `.tmproj`。
- **旧项目迁移**:可直接导入 TextureMerger JSON/PNG,把旧动画恢复到当前编辑与发布流程。
- **关键帧 PNG 导出**:按当前动画的关键帧段输出统一画布 PNG,不按 duration 制造重复图片。
- **资源信息开关**:缩略图可独立显示帧名字与全部复用帧范围,例如 `1-5、11-15`。
- **PNG 压缩选项**:支持标准 PNG、无损优化、高质量量化和 TinyPNG 风格量化。
- **CLI 批处理**:命令行可用于检查、转换和批量处理 SWF,方便接入自动化工具链。
- **跨平台桌面版**:支持 Windows/macOS 本地运行,也提供 Electron 桌面壳构建脚本。
- **LayaAir 播放器**:内置 LayaAir 运行时播放器核心和 Demo,可验证导出 JSON/PNG 的播放效果。
## 效果预览
### 序列帧动画编辑
下图使用 `MultPage` 演示方案中的 `CHANT` 动画:25 个关键帧段展开为 120 个逻辑帧,开启洋葱皮并后看 3 个关键帧段。顶部集中放置新增、删除、排序和洋葱皮工具,播放与缩放留在底栏。

### 多页图集
当资源超过设定的分页最大尺寸时,Texture Maker 会自动拆成多张图集。JSON 通过 `pngs` 记录所有 PNG 文件名,通过 `res[id].p` 记录资源所在页码。

### 导出 JSON
导出数据只保留运行时播放需要的字段。常用字段包括:
- `v`:数据格式版本。
- `pngs`:多页图集文件列表,单页数据可省略。
- `mc`:动画片段表。
- `res`:资源在图集中的矩形区域。
- `res[id].p`:资源所在 PNG 页码,缺省为第 0 页。

### LayaAir Demo

仓库内置 `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 资源。

## 快速开始
### 环境要求
- 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
```
也可以使用 npm scripts:
```bash
npm run smoke
npm run inspect -- TestRes/testSwf/BladeDamage_2.swf
npm run batch -- TestRes/testSwf
```
## 使用流程
1. 启动工具。
2. 点击“打开 SWF”拆解 Flash 动画,或点击“导入连续图片”选择一组 PNG。
3. SWF 导入可设置资源模式和缩放;PNG 序列可设置动画名称、帧率、每图持续帧数和初始对齐。
4. 在左下角“图片装箱”中选择装箱算法、间隙和分页最大尺寸;修改后会立即重新装箱并刷新预览。
5. 在中间区域切换“图集预览”“数据预览”“动画预览”检查结果。
6. 在右侧设置动画片段缩放、帧锚记、帧指令、导出选项和 PNG 压缩方式。
7. PNG 动画可在动画预览中逐帧拖动位置,并插入、复制、删除或拖动换序关键帧;暂停时可开启洋葱皮校准动作。
8. 点击导出,得到 JSON 与 PNG 图集文件。
### 连续 PNG 动画
一次选择的多张 PNG 会先检查文件名。发现相同前缀和连续数字尾号时,例如 `run_0001.png` 至 `run_0010.png`,工具会先询问是否按连续动画图片导入;确认后再进入参数弹窗。工具不依赖系统文件选择顺序,而是按文件名自然排序,例如 `2.png` 会排在 `10.png` 前。导入弹窗中的“每图持续”默认是 `5` 帧,表示每张图片在时间轴上保持多少帧,与 SWF 关键帧段的 `duration` 完全相同;它不是九宫格或 spritesheet 切片数量。
图片默认按原始画布中心对齐动画原点,并默认勾选“去除空白位置”。工具会裁掉四边 alpha 为 0 的透明区域以减少图集占用,同时把裁剪起点补偿进帧坐标,因此裁剪前后动画中心和播放位置不变。取消勾选即可保留完整原图画布。
进入“动画预览”后,可以点击并拖动当前帧图片,也可以使用右侧 X/Y 和方向按钮精确调整。时间轴提供:
- `插入帧`:延长当前关键帧画面一帧,采用 Flash F5 语义。
- `空白关键帧`:在当前帧后插入透明关键帧。
- `复制关键帧`:深复制当前关键帧段的画面、坐标和持续帧数,插入其后;为避免事件重复触发,不复制锚记、指令、参数和片段标签。
- `删除帧`:缩短当前持续段,或删除只有一帧的关键帧段。
- `删除关键帧`:确认后删除当前完整关键帧段并直接拼接后续段;动画删空时保留一帧空白关键帧。
- `← / →`:将完整关键帧段前移或后移,持续帧、图层与已有标记一起移动。
这些编辑命令集中在动画画布上方的浅色帧工具栏,并使用 Lucide 图标配合文字说明;底栏只保留播放、帧号、缩放和中心点等预览控制。播放期间工具栏、画布拖动和右侧帧编辑会统一锁定,暂停后才恢复,避免编辑联动拖慢动画预览。也可以直接拖动时间轴上的关键帧格换序,青色插入线会提示落点。
开启“洋葱皮”后,暂停状态会以青色显示上一关键帧段,并以洋红色显示后续关键帧段。“后看”可在 1-5 帧间调整,距离越远透明度越低;参考画面不会被选中,也不会进入导出数据。
PNG 动画与 SWF 动画可以混合追加到同一个项目,共用装箱、分页、JSON/TMD 数据和导出设置。两种来源最终生成相同的 `mc/res/layers` 运行时结构,播放器不需要区分素材来源。
## 核心工作流详解
### 多动画集合、分页与容量控制
Texture Maker 可以把多个 SWF 或多个动画片段放在同一个工作区中处理。顶部动画条用于在不同动画之间切换,左侧资源列表展示当前图集里的图块、尺寸和选中状态,方便检查每个资源是否被正确拆出。

左下角“图片装箱”里的“最大宽度”和“最大高度”用于预设单张图集页的最大尺寸。比如把上限设为 `1024 x 1024`,就能把单页纹理控制在更低的显存容量内;当资源放不下时,工具会自动拆成多页图集,并在底部状态栏显示“装箱分页”和页码。导出时会生成 `name.png`、`name_2.png` 等多张 PNG,JSON 中用 `pngs` 和 `res.p` 标记每个资源属于哪一页。
布局、间隙和最大尺寸没有待应用状态,修改后立即重建预览;连续快速调整时只提交最后一次装箱结果,失败则恢复上一组有效参数。
右上角会显示页数、首张图集实际尺寸、估算显存、装箱算法和间隙。右侧导出面板会汇总图集页数与纹理数量,帮助发布前快速判断资源规模。
### 装箱算法与图块间隙
图集装箱不只有一种排布方式。不同项目对“紧凑度”“稳定性”“可读性”和“显存占用”的取舍不同,因此工具提供多种装箱算法:

- `CommonBestFit`:默认综合策略,优先兼顾紧凑度和稳定性。
- `BestAreaFit`:偏向面积利用率,适合希望尽量塞满图集的情况。
- `BestLongSideFit` / `BestShortSideFit`:按长边或短边匹配,适合某些形状差异明显的图块。
- `BottomLeftRule`:更接近传统左下角排布,结果直观稳定。
- `ContactPointRule`:倾向让图块相互贴合,尝试减少碎片空间。
“间隙”用于在图块之间留出空白边,默认值为 `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 压缩方式、自动保存方案和导出按钮。每个复选项后都有紧邻的问号说明,便于判断兼容性与输出文件用途。

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 四档缩略图大小。
- “图片装箱”区域用于控制图集布局、间隙和分页最大尺寸。
### 顶部文件菜单
- “方案”:打开、保存或关闭可二次编辑的 `.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
```
### 单文件包
生成 Node SEA 单文件发布产物:
```bash
npm run build:single:mac
npm run build:single:win
npm run build:single:all
```
### Electron 桌面版
生成内置 Chromium 的桌面应用:
```bash
npm run build:electron:mac
npm run build:electron:win
npm run build:electron:all
```
构建产物输出到 `export/`,该目录为本地构建产物,不提交到仓库。
## 测试样本
测试代码、原始样本、连续 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.107
```
如果浏览器控制台、页面脚本版本或接口行为和当前版本不一致,优先检查是否开着旧服务进程,或桌面版是否仍在运行旧包。
### 默认端口被占用
Web UI 默认使用 `5177`,如果端口被占用会自动尝试后续端口。以控制台打印的实际 URL 为准。
### 多页图集如何接入
读取 JSON 顶层 `pngs`,按顺序加载 PNG 页。读取 `res[id].p` 判断资源属于哪一页;缺省 `p` 时按第 0 页处理。
### Windows 桌面版打开某些 SWF 报错
如果是旧版本,请更新到包含跨平台 JPEG3 解码的版本。当前版本使用本地 JS JPEG 解码器,不依赖 macOS `sips`,Windows/macOS 行为一致。
### Gitee 上截图不显示
README 使用仓库内相对路径引用截图,例如:
```md

```
确认截图文件已提交到 `docs/images/`,并且文件名大小写完全一致。
## 当前状态
项目仍在持续迭代中。当前已覆盖 SWF/连续 PNG 混合导入、关键帧编辑、洋葱皮、即时装箱、多页 PNG、`.tmproj` 方案续作、发布文件急救、TextureMerger 迁移、关键帧 PNG 输出、JSON/TMD 压缩和 LayaAir 预加载缓存。后续方向持续记录在 [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 使用说明。