# A1 Swap Mod Packer

当前版本：**v0.6.0**

A1 Swap Mod Packer 是一个开源的 3MF 打包工具，专为 Bambu Lab A1 SwapMod 工作流设计。

它接收一个或多个 A1 切片后的 `.3mf` 文件，根据设定份数重复其面板 G-code，插入外部 SwapMod 弹射/换板 G-code 块，并输出一个新的打包 `.3mf` 文件，可直接发送至打印机。

![A1 Swap Mod Packer 截图](https://images-tfb361lw6pyvz9bxue3s.oss-cn-chengdu.aliyuncs.com/obsidian/20260728140250243.png)

![](https://images-tfb361lw6pyvz9bxue3s.oss-cn-chengdu.aliyuncs.com/obsidian/20260728140421994.png)

## 注意事项

- 本项目不含任何闭源代码。所有功能均通过对比 3MF 文件生成前后的状态独立实现。
- 目前仅在 Windows 10 上测试验证过。
- 生产环境使用前，请先在安全/简单的打印任务上测试生成的文件。

## 主要功能

- 拖放式批量打包 GUI。
- 简洁高效的桌面 GUI。
- 支持多个 `.3mf` 输入文件。
- 每个文件独立份数。
- 自动从 `Metadata/slice_info.config` 读取并汇总时间和耗材。
- 外部 SwapMod G-code 模板目录。
- 可编辑 G-code 补丁文件。
- 可选通过 `M73 R...` 编码剩余时间板号。
- GUI 中选中文件缩略图预览。
- 最多 9 个不同输入文件的预览图合成，带 `{plates} P` 绿色标签。
- 合并模式：所有输入行合并为一个打包 3MF。
- 独立批处理模式：每行输入各生成一个独立打包 3MF。
- zlib-ng Deflate ZIP 压缩，默认级别 7。
- GUI 设置保存到程序目录的 `settings.json`。

## 源码安装

推荐 Python 3.13 及以上（Nuitka 4.x 对 3.14 仅实验性支持）。Python 3.10+ 亦可使用。

安装依赖：

```bash
pip install -r requirements.txt
```

当前运行时依赖：

| 依赖 | 用途 |
|---|---|
| `PySide6` | GUI 界面、拖放表格、文件对话框、缩略图预览、设置界面 |
| `Pillow` | 读取和合成输出 3MF 中的 PNG 预览图，包括 `{plates} P` 标签 |
| `zlib-ng` | ZIP Deflate 压缩后端，用于写入压缩 3MF 并控制压缩级别 |

当前 Python 源码版本不需要 Java 运行时、Bambu Studio SDK、外部压缩工具或加密/模板解码器。

启动 GUI：

```bash
python -m a1_swap_mod_packer.gui
```

或

```bash
python run_gui.py
```

## 构建 Windows 可执行文件

仓库包含 Windows 构建脚本：

```cmd
build_win.cmd
```

脚本使用 Nuitka onefile 模式，生成如下便携发布目录：

```text
build/onefile/
```

预期输出：

```text
build/onefile/
  a1packer.exe
  gcode_patches.ini
  swap_gcode/
  x.png               输出预览图示例
  settings.json       可选；GUI 保存设置后自动生成
```

外部资源刻意保留在可执行文件外部。不要将这些文件打包进 onefile 二进制：

```text
swap_gcode/
gcode_patches.ini
settings.json
```

打包为 exe 时，程序会从 exe 所在目录解析这些路径。

### Windows 构建要求

已验证的构建环境：

- Windows 10。
- Python 3.10 及以上。
- 虚拟环境 `.venv/`。
- `requirements.txt` 中的运行时依赖。
- Nuitka 支持 onefile 模式。
- Microsoft C++ Build Tools / Visual Studio Build Tools（含 MSVC 编译器和 Windows SDK）。

在干净的虚拟环境中安装 Python 依赖：

```cmd
py -3.13 -m venv .venv
.venv\Scripts\python.exe -m pip install --upgrade pip
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe -m pip install "Nuitka[onefile]"
```

然后执行：

```cmd
build_win.cmd
```

构建脚本执行一次 Nuitka 编译：

- GUI：`run_gui.py` → `build/onefile/a1packer.exe`

GUI 编译启用 PySide6 插件并包含当前界面所需的 Qt 插件组：

```text
platforms,imageformats,styles,iconengines
```

### 构建后验证

启动一次 `build/onefile/a1packer.exe`，确认：

- 换盘 G-code 下拉框列出已复制的模板。
- 修改 GUI 选项会创建或更新 `build/onefile/settings.json`。
- 首次启动前 `settings.json` 不存在时程序仍能正常运行。

## 换盘 G-code 模板

GUI 会自动扫描以下固定目录：

```text
swap_gcode/
```

纯 UTF-8 文本文件直接读取。当前扫描器接受以下后缀：

```text
.gcode
.nc
.ngc
.txt
```

当前源码版本不解码加密的或厂商模板的 G-code 归档。

GUI 中使用方法：

1. 将模板文件放入 `swap_gcode/`。
2. 点击 **换盘 G-code** 旁的 **刷新**。
3. 从下拉框中选择模板。

## 可编辑 G-code 补丁

GUI 读取固定补丁文件：

```text
gcode_patches.ini
```

默认规则：

```ini
[patch.a1_start_y]
enabled = true
flag = G0 X128 F30000
find = G0 Y254 F3000
replace = G0 Y250 F3000 ; Patched
max_count = 1
```

含义：

- 从可选的 `flag` 行之后开始查找。
- 将第一个匹配 `find` 的行替换为 `replace`。
- 最多替换 `max_count` 次。

可在 GUI 中通过 **G-code 补丁** 复选框禁用，或编辑 INI 文件并保持启用。

换板插入标记也可编辑：

```ini
[swap]
insert_before_marker = ;=====printer finish  sound=========
```

## GUI 使用指南

### 输入 3MF 文件

输入表格支持：

- **添加 3MF**：选择一个或多个 `.3mf` 文件。
- 拖放 `.3mf` 文件到表格中。
- 拖放文件夹到表格中。GUI 会添加该文件夹内所有顶层 `.3mf` 文件。
- **移除**：移除选中行。
- **全部移除**：清空全部输入列表。
- **上移 / 下移**：调整输入顺序。
- **应用默认份数至选中行**：将当前默认份数覆盖到选中行。

列说明：

- **3MF 文件**：源文件路径。
- **份数**：该源文件重复的次数。
- **时间**：预估打印时间 × 份数。
- **耗材**：预估耗材用量 × 份数。

时间和耗材数据读取自：

```text
Metadata/slice_info.config
```

如果源 3MF 缺少此元数据，GUI 显示"未知"。

输入列表下方的汇总行显示当前表格的总板数、预估时间和耗材。

右侧缩略图面板显示选中输入文件的活动面板预览（若 3MF 中包含）。

### 构建 3MF 按钮

**构建 3MF** 按钮位于输入列表右下方，便于快速批量操作。

正常合并模式下，一次点击生成一个包含所有输入行的输出 3MF。

独立批处理模式下，一次点击为每行输入各生成一个输出 3MF。

### 换盘 G-code

选择插入到每个重复面板中的弹射/换板 G-code 块。

下拉框内容来自：

```text
swap_gcode/
```

按钮：

- **刷新**：重新扫描目录。
- **打开文件夹**：打开模板目录。

### 新输入的默认份数

设置添加到或拖入的新文件的默认份数。

这不会自动更改已有行。对已有行使用 **应用默认份数至选中行**。

> 提示：所有数值输入框均为纯数字输入（QLineEdit），无上下箭头，可直接键入任意数值。

### 热床降温

控制是否在 SwapMod G-code 块之前插入热床等待温度。

启用示例：

```gcode
M190 S45
```

禁用后，打包器不添加 `M190` 行。

### 换盘后等待时间

勾选框控制是否在换盘 G-code 块之后插入驻留时间。

默认 30 秒，可通过纯数字输入框（QLineEdit）调整：

```gcode
G4 P30000
```

### 剩余时间板号

启用后，打包器按以下公式偏移 `M73 ... R...` 剩余时间值：

```text
板号 × 100 小时 × 60 分钟
```

这使得 A1 剩余时间的百位能显示当前板号。

示例：

- 第 1 板：+6000 分钟
- 第 2 板：+12000 分钟
- 第 3 板：+18000 分钟

### 最后换盘

启用后，换板/弹射块也会插入到最后一个重复面板之后。

禁用后，最后一个重复面板正常结束，不执行换盘 G-code 块。

### G-code 补丁

应用来自以下文件的规则：

```text
gcode_patches.ini
```

**打开配置文件** 按钮打开该固定文件进行编辑。

### 3MF 元数据

选项：

- **累加预测和耗材用量（默认）**  
  使用所有重复面板的总和更新第一块面板的元数据。从统计角度看更合理，适合 SwapMod 场景。

- **保留原始预测和重量**  
  保持基础 3MF 中 `slice_info.config` 的预测和重量值不变。

### 预览图处理

默认情况下，输出 3MF 保留基础归档中对应当前输出面板的预览成员，并用以下内容重写这些 PNG 预览：

- 最多 9 个不同输入文件的预览图合成；
- 一个简短的绿色标签（如 `5 P`），施加在最终合成图上。

如果预览图缺失或无法读取，打包器保留可用基础预览，仍尝试施加面板标签。

### 批处理模式

#### 合并模式

默认行为。

所有输入行打包为一个输出文件。

示例：

```text
A.3mf 份数 2
B.3mf 份数 3
```

输出：

```text
一个打包 3MF，包含 A, A, B, B, B
```

#### 独立批处理模式

启用时，GUI 显示说明弹窗。

每行输入被视为独立构建。

示例：

```text
A.3mf 份数 5
B.3mf 份数 5
C.3mf 份数 5
```

输出：

```text
5 Plates - A.3mf
5 Plates - B.3mf
5 Plates - C.3mf
```

此模式用于快速将大量独立的单板 3MF 文件批量转换为多份数 SwapMod 包。

GUI 并行构建这些独立输出，并发数受 CPU 核心数及安全上限限制。

它**不会**将所有输入合并为一个文件。

### 输入处理

- **添加输入时跳过重复文件路径**  
  防止意外多次添加同一路径。

### 构建成功后

- **清空输入列表**  
  构建成功后清空表格。在独立批处理模式下，仅当所有输出构建成功后才会清空。

### 输出目录

如果此字段为空：

- 合并模式写入第一个输入文件同目录。
- 独立批处理模式将每个输出写入各自输入文件同目录。

如果选择了目录，所有输出都写入该目录。

### 输出文件名规则

默认规则：

```text
{plates} Plates - {sources}.3mf
```

点击规则字段旁的 `?` 按钮显示标记帮助。

可用标记：

| 标记 | 含义 |
|---|---|
| `{source}` | 第一个输入文件的文件名（不含 `.3mf`） |
| `{sources}` | 源文件摘要。单个源使用其文件名；多个源则显示为 `first_source_and_N_more` |
| `{plates}` | 本输出中的总板数 |
| `{copies}` | 本输出中的总份数 |
| `{date}` | 当前日期，格式 `YYYYMMDD` |
| `{time}` | 当前时间，格式 `HHMMSS` |

在独立批处理模式下，标记按每行输入单独计算。

示例：

```text
{plates} Plates - {sources}.3mf
SwapMod - {source} - x{copies}.3mf
{date}_{time}_{source}.3mf
```

## GUI 设置

GUI 将设置写入程序目录：

```text
settings.json
```

这是有意为之，以便便携式解压目录或打包的 `.exe` 版本能将选项保持在应用程序旁边。

保存的选项包括：

- 当前选中的换盘 G-code 文件。
- 默认份数。
- 热床降温设置。
- 换盘后等待时间。
- 剩余时间板号开关。
- 最后换盘开关。
- G-code 补丁开关。
- 元数据模式。
- ZIP 压缩级别。
- 独立批处理模式。
- 输入处理选项。
- 构建成功后清空输入列表。
- 输出目录。
- 输出文件名规则。
