Files
AnyImage/docs/development.md
nan 9bb603b532
Some checks failed
构建扩展 / build (push) Failing after 5m10s
构建并部署文档 / deploy (push) Failing after 2m54s
Update CI workflow to use uv for testing and packaging; enhance development documentation on dependency management
2026-08-19 20:24:35 +08:00

179 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 程序设计、开发与许可证
## 程序设计
SnapForm 分成 Blender 主进程与独立 Job Server 两侧。Blender 侧只负责界面、任务参数和 `.blend` 数据修改;模型下载、媒体准备、ONNX 推理和文件输出都在 Python 3.12 Environment 中运行。两侧由随扩展分发的 BlendJob wheel 连接,避免把 FastAPI、ONNX Runtime 等计算依赖载入 Blender Python。
```mermaid
flowchart LR
User["Image Empty / Debug Panel"] --> Operator["Blender Operator"]
Operator --> Runtime["JobRuntime"]
Runtime --> Server["JobServer FIFO Queue"]
Server --> Handler["SnapForm Job Handler"]
Handler --> Model["ModelManager / ONNX"]
Handler --> JobFiles["Job Directory"]
JobFiles --> Response["Operator response"]
Response --> Scene["Blender Scene"]
```
核心边界如下:
- `src/snapform/__init__.py` 是注册入口,集中注册 Blender 类型、`Scene.snapform_settings`、右键菜单与 Runtime
- `panel.py`、`preferences.py`、`properties.py` 只描述 UI 和 Blender 属性,不直接导入 Server 模型实现
- `operators.py` 将 Blender 状态转换为普通字典参数;Job 完成后在主线程导入图片、网格、材质和相机
- `blender/depth_plane.py` 与 `blender/surface.py` 实现 Image Empty 输入检查、几何构建和资产挂载
- `job_runtime.py` 以入口字符串声明独立 Server,并配置 Environment、Storage Root 与首次安装后的推荐模型下载
- `server/__init__.py` 创建 `JobServer`、注册公开 Job,并把 `ModelManager` 注册为 Resource
- `server/jobs/` 按任务组织完整流程;DA3、MoGe-2、BEN2 Debug 各自拥有独立模块和 Job,不用模型分支总控函数
- `server/models/` 包含三个模型适配器及其 ONNX 实现,只负责模型载入、推理和 Prediction;不接收 Job Context、不写文件
- `server/geometry/` 包含投影、像素网格和唯一 Surface Builder,均为纯数据转换;不负责 Debug 或文件输出
- `server/outputs/` 只负责 Depth、Surface 与各模型 Debug 的序列化;Debug writer 原样保存 API 字段,不构建派生几何
- `server/media/input.py` 只处理图片、序列和视频输入;共享的可选前景流程保留在 `jobs/foreground.py`
- 根目录 `model_catalog.py` 供 Blender UI 与本地就绪检查使用;`server/model_catalog.py` 独立声明下载与推理所需模型,二者的模型键、目录名和 `ready_patterns` 由测试约束一致
- `server/__init__.py` 只注册 Job 与 Resource;`jobs/background.py`、`jobs/frames.py` 分别实现去背景和帧提取
- 所有任务产物写入 Runtime 分配的 opaque-ID Job 目录
功能细节继续按主题维护:[Depth Plane](depth-plane.md)、[Surface](surface.md)、[输出格式](outputs.md) 和 [Job Server](server.md)。
## 项目结构
```text
.
├── AGENTS.md
├── README.md
├── pack.py
├── sync_models.py
├── docs/
├── src/
│ └── snapform/
│ ├── __init__.py
│ ├── blender_manifest.toml
│ ├── job_runtime.py
│ ├── operators.py
│ ├── panel.py
│ ├── preferences.py
│ ├── properties.py
│ ├── assets/
│ │ └── O_SnapForm.blend
│ ├── blender/
│ │ ├── depth_plane.py
│ │ └── surface.py
│ ├── model_catalog.py
│ ├── server/
│ │ ├── __init__.py
│ │ ├── jobs/
│ │ │ ├── background.py
│ │ │ ├── debug_ben2.py
│ │ │ ├── debug_da3.py
│ │ │ ├── debug_moge2.py
│ │ │ ├── depth.py
│ │ │ ├── foreground.py
│ │ │ ├── frames.py
│ │ │ └── surface.py
│ │ ├── geometry/
│ │ │ ├── projection.py
│ │ │ ├── grid_mesh.py
│ │ │ └── surface.py
│ │ ├── media/
│ │ │ └── input.py
│ │ ├── model_download.py
│ │ ├── model_catalog.py
│ │ ├── model_manager.py
│ │ ├── models/
│ │ │ ├── ben2.py
│ │ │ ├── da3.py
│ │ │ ├── moge2.py
│ │ │ ├── onnx_ben2.py
│ │ │ ├── onnx_da3.py
│ │ │ ├── onnx_moge2.py
│ │ │ └── onnx_runtime.py
│ │ └── outputs/
│ │ ├── debug_da3.py
│ │ ├── debug_moge2.py
│ │ ├── depth.py
│ │ └── surface.py
│ └── wheels/
│ └── blendjob-0.1.13-py3-none-any.whl
├── tests/
└── tools/
```
## 常见命令
在项目根目录使用 Git Bash:
```bash
uv sync
uv run pytest
uv run pytest tests/test_addon.py tests/test_manifest.py tests/test_pack.py -v
uv run python pack.py
```
`.github/workflows/build.yml` 使用 Python 3.12 与 `uv.lock` 中锁定的开发依赖运行完整测试和打包;新增测试依赖时应在 `pyproject.toml` 的 `dev` 依赖组中声明并更新锁文件,不要在 Workflow 中另行维护 `pip install` 清单。
本地预览用户文档:
```bash
uv run mkdocs serve
```
构建静态文档或使用 Mike 发布版本化文档:
```bash
uv run mkdocs build
uv run mike deploy <version> -p
uv run mike set-default <version> -p
```
### 文档部署
`.github/workflows/docs.yml` 在 `main` 分支的文档相关文件变化后运行,也可从 Gitea Actions 手动触发。工作流使用锁定的 Python 依赖严格构建 `site/`,将其放入与站点 URL 对应的 `public/snapform/`,再通过 Wrangler 部署为 Cloudflare Workers Static Assets。
在 Gitea 仓库的 **Settings > Actions** 中配置:
- Secret `CLOUDFLARE_ACCOUNT_ID`:Cloudflare Account ID
- Secret `CLOUDFLARE_API_TOKEN`:限制到目标账号的 Cloudflare API Token,使用 **Edit Cloudflare Workers** 模板
- Variable `CLOUDFLARE_WORKER_NAME`:承载文档的 Worker 名称
API Token 不写入仓库。Workflow 只在 `main` 上部署生产文档,不在 Pull Request 中读取 Cloudflare Secret。
目标 Worker 必须专门用于 SnapForm,并把 `docs.omoolab.xyz/snapform/*` 路由到该 Worker。每次 Wrangler 部署都会更新目标 Worker 的整套静态资源;如果一个 Worker 同时承载多个项目,应改由中央文档仓库聚合全部站点后统一部署,不能从各项目仓库分别覆盖它。
Mike 不依赖 GitHub API;`mike deploy --branch <branch> --push` 也可以向 Gitea 保存版本化静态站点。当前自动部署先发布 `mkdocs build` 生成的单版本站点,等确定版本 URL 规则后再启用 Mike 分支,避免在 Cloudflare 上提前固化不合适的路径结构。
`pack.py` 根据 `blender_manifest.toml` 分别生成 Windows、macOS 和 Linux 扩展包,例如 `dist/SnapForm.v0.12.14.windows-x64.zip`。更换 `src/snapform/wheels/` 中随扩展分发的 wheel 后,先刷新锁文件再测试:
```bash
uv lock --refresh
uv run pytest
```
## 资产构建与验证
`tools/` 脚本依赖 `bpy`,必须由 Blender 执行。设置本机 Blender 可执行文件后,可以重建或验证 `O_SnapForm.blend`:
```bash
BLENDER_BIN="/c/Program Files/Blender Foundation/Blender 4.5/blender.exe"
"$BLENDER_BIN" --background --python tools/build_geometry_nodes_asset.py
"$BLENDER_BIN" --background --python tools/validate_depth_plane_asset.py
"$BLENDER_BIN" --background --python tools/validate_geometry_nodes_asset.py
"$BLENDER_BIN" --background --python tools/validate_moge_depth_plane.py
"$BLENDER_BIN" --background --python tools/validate_moge_surface.py
```
验证脚本会自动把 `src/snapform/wheels/` 中的 BlendJob wheel 加入 Blender Python 路径,因此可在
`--factory-startup` 的干净环境中直接运行。
只改 Python、文档或打包逻辑时不需要重建 `.blend` 资产;修改节点组、材质组或其接口时,应运行相应资产验证脚本,并再次运行完整测试。
## 上游与许可证
- Depth Anything 3 代码采用 Apache 2.0
- BEN2 ONNX 模型采用其仓库声明的 Apache 2.0 License
- SnapForm Extension 代码采用 GPL-3.0-or-later
- 模型权重许可证由所选 Hugging Face 模型仓库决定,Extension 下载前会在界面显示