feat: Introduce Balloon Lasso Tool for mesh extraction
- Added BalloonTool workspace tool to facilitate the extraction of balloon meshes in the 3D viewport. - Implemented ActivateBalloonTool operator to activate the Balloon Lasso Tool. - Refactored BalloonLasso operator into ExtractBalloon for better clarity and functionality. - Enhanced properties for balloon extraction, including mode, thickness, resolution, and material reuse options. - Updated SnapFormSettings to include new balloon-related properties. - Improved material and image handling for balloon extraction, ensuring compatibility and reusability. - Added tests to validate the registration and functionality of the new balloon tools and properties.
This commit is contained in:
@@ -2,94 +2,64 @@
|
||||
|
||||
## 程序设计
|
||||
|
||||
SnapForm 分成 Blender 主进程与独立 Job Server 两侧。Blender 侧只负责界面、任务参数和 `.blend` 数据修改;模型下载、媒体准备、ONNX 推理和文件输出都在 Python 3.12 Environment 中运行。两侧由随扩展分发的 BlendJob wheel 连接,避免把 FastAPI、ONNX Runtime 等计算依赖载入 Blender Python。
|
||||
SnapForm 分为 Blender 交互层、BlendJob Runtime 和 Job Server 计算层。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
User["Image Empty / Debug Panel"] --> Operator["Blender Operator"]
|
||||
UI["菜单 / Panel"] --> Operator["Feature 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"]
|
||||
Runtime --> Job["Server Job"]
|
||||
Job --> Files["Job Directory"]
|
||||
Files --> Response["Operator Response"]
|
||||
Response --> Scene["Blender Scene"]
|
||||
```
|
||||
|
||||
核心边界如下:
|
||||
Blender 交互层管理 UI、RNA 状态、任务参数和结果导入。Runtime 管理 Environment、Server、队列、进度与取消。Server Job 组合媒体、模型、几何和输出模块。完整运行设计见 [Job Server](server.md)。
|
||||
|
||||
- `src/snapform/__init__.py` 是注册入口,集中注册 Blender 类型、`Scene.snapform_settings`、右键菜单与 Runtime
|
||||
- `menu.py` 与 `panel.py` 是同级 Blender UI 入口;`preferences.py`、`properties.py` 分别保存插件配置和 RNA 状态,它们都不直接导入 Server 模型实现
|
||||
- `runtime.py` 创建唯一 `JobRuntime`,配置 Environment、Storage Root、Server 入口与首次安装后的推荐模型下载
|
||||
- `operators/` 按功能组织 Blender 操作。Depth Plane、Surface、Background 与 Balloon 各自包含入口 Operator、Job 请求和结果回写,不设置跨功能的 `results.py`
|
||||
- `operators/common.py` 只保留跨 Job Operator 共用的参数校验、模型就绪检查、临时输入清理和请求参数构造;`operators/image.py` 与 `operators/material.py` 提供各功能 Operator 共用的 Image Empty、序列和材质操作,三者同层但不互相混合职责
|
||||
- `operators/models.py` 与 `operators/debug.py` 分别承载模型管理和 Debug 操作
|
||||
- `operators/balloon/` 以持续 `BalloonLasso` 控制器分发单次、可独立 Redo/Undo 的 `ExtractBalloon`;`geometry.py` 负责共用拓扑,`poisson.py` 与 `teddy.py` 分别计算两种厚度场
|
||||
- `operators/depth_plane/` 将转换入口、Job 请求、响应回写、深度数据和网格构建收拢在同一功能包;`operators/surface.py` 与 `operators/background.py` 采用相同的功能内聚原则
|
||||
- `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)。
|
||||
| 位置 | 内容 |
|
||||
| --- | --- |
|
||||
| `__init__.py` | Blender 类型、菜单与 Runtime 注册 |
|
||||
| `menu.py`、`panel.py` | 用户入口 |
|
||||
| `preferences.py`、`properties.py` | 扩展配置与 Scene 状态 |
|
||||
| `runtime.py` | JobRuntime 配置 |
|
||||
| `operators/` | Blender 功能与结果导入 |
|
||||
| `server/jobs/` | Server 工作流 |
|
||||
| `server/models/` | ONNX 模型适配 |
|
||||
| `server/geometry/` | 纯数据几何处理 |
|
||||
| `server/outputs/` | 文件序列化 |
|
||||
| `server/media/` | 媒体输入 |
|
||||
| `assets/O_SnapForm.blend` | Geometry Nodes 与材质资产 |
|
||||
|
||||
Depth Plane、Surface、Background 和 Balloon 按功能组织。一个功能的入口、请求和 Blender 回写放在一起;跨功能的图片、材质和参数处理放在 `operators/common.py`、`operators/image.py` 与 `operators/material.py`。
|
||||
|
||||
Server 的模型模块返回 Prediction,几何模块处理数组与网格,输出模块写文件。Blender 数据只在 Operator Response 的主线程阶段创建。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```text
|
||||
.
|
||||
├── AGENTS.md
|
||||
├── README.md
|
||||
├── docs/
|
||||
├── pack.py
|
||||
├── sync_models.py
|
||||
├── docs/
|
||||
├── src/
|
||||
│ └── snapform/
|
||||
│ ├── __init__.py
|
||||
│ ├── blender_manifest.toml
|
||||
│ ├── runtime.py
|
||||
│ ├── menu.py
|
||||
│ ├── panel.py
|
||||
│ ├── preferences.py
|
||||
│ ├── properties.py
|
||||
│ ├── model_catalog.py
|
||||
│ ├── assets/
|
||||
│ │ └── O_SnapForm.blend
|
||||
│ ├── operators/
|
||||
│ │ ├── common.py
|
||||
│ │ ├── image.py
|
||||
│ │ ├── material.py
|
||||
│ │ ├── models.py
|
||||
│ │ ├── debug.py
|
||||
│ │ ├── background.py
|
||||
│ │ ├── surface.py
|
||||
│ │ ├── depth_plane/
|
||||
│ │ │ ├── operator.py
|
||||
│ │ │ ├── data.py
|
||||
│ │ │ └── build.py
|
||||
│ │ └── balloon/
|
||||
│ │ ├── operator.py
|
||||
│ │ ├── geometry.py
|
||||
│ │ ├── poisson.py
|
||||
│ │ └── teddy.py
|
||||
│ ├── server/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── jobs/
|
||||
│ │ ├── geometry/
|
||||
│ │ ├── media/
|
||||
│ │ ├── models/
|
||||
│ │ └── outputs/
|
||||
│ └── wheels/
|
||||
│ └── blendjob-*.whl
|
||||
├── src/snapform/
|
||||
│ ├── blender_manifest.toml
|
||||
│ ├── runtime.py
|
||||
│ ├── menu.py
|
||||
│ ├── panel.py
|
||||
│ ├── preferences.py
|
||||
│ ├── properties.py
|
||||
│ ├── operators/
|
||||
│ ├── server/
|
||||
│ ├── assets/
|
||||
│ └── wheels/
|
||||
├── tests/
|
||||
└── tools/
|
||||
```
|
||||
|
||||
## 常见命令
|
||||
## 开发命令
|
||||
|
||||
在项目根目录使用 Git Bash:
|
||||
|
||||
@@ -100,51 +70,35 @@ uv run pytest tests/test_addon.py tests/test_manifest.py tests/test_pack.py -v
|
||||
uv run python pack.py
|
||||
```
|
||||
|
||||
`.github/workflows/test.yml` 在 `main` push、Pull Request 与手动触发时使用 Python 3.11 和锁定依赖运行完整测试。`.github/workflows/build.yml` 只响应 `v*` tag,在再次通过完整测试后运行 `pack.py`,并把生成的 ZIP 上传到该 tag 对应的 Gitea Release。`pack.py` 从 `pyproject.toml` 的默认 `dependencies` 读取 Extension wheel 需求,按 Manifest 平台从 PyPI 下载 wheel,并把各平台对应的 wheel 列入包内 Manifest;`src/snapform/wheels/` 只保留本地资产,不作为 uv source。`.github/workflows/docs.yml` 在 `main` 的文档内容、MkDocs 配置或自身 Workflow 变化时部署,也可手动触发;它只使用 `docs` 依赖组,因此不安装默认依赖。Server Environment 与测试依赖声明在 `dev` 组,文档工具声明在 `docs` 组;新增依赖后应更新锁文件,不要在 Workflow 中另行维护下载清单。
|
||||
`pack.py` 为 Windows x64、macOS Apple Silicon 与 Linux x64 构建扩展 ZIP 到 `dist/`。依赖、wheel 或 Manifest 改变后,应同步检查 `pyproject.toml`、`uv.lock`、`blender_manifest.toml` 与打包测试。
|
||||
|
||||
本地预览用户文档:
|
||||
CI 分为三条流程:
|
||||
|
||||
- `test.yml`:在 push、Pull Request 与手动触发时运行测试
|
||||
- `build.yml`:响应 `v*` tag,测试后构建并上传 Release
|
||||
- `docs.yml`:文档变化后构建并部署站点
|
||||
|
||||
## 文档
|
||||
|
||||
本地预览和严格构建:
|
||||
|
||||
```bash
|
||||
uv run mkdocs serve
|
||||
uv run --only-group docs mkdocs serve
|
||||
uv run --only-group docs mkdocs build
|
||||
```
|
||||
|
||||
构建静态文档或使用 Mike 发布版本化文档:
|
||||
版本化发布可使用 Mike:
|
||||
|
||||
```bash
|
||||
uv run mkdocs build
|
||||
uv run mike deploy <version> -p
|
||||
uv run mike set-default <version> -p
|
||||
uv run --only-group docs mike deploy <version> -p
|
||||
uv run --only-group docs 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
|
||||
```
|
||||
自动部署将 MkDocs 站点发布到专用 Cloudflare Worker。仓库需要配置 `CLOUDFLARE_ACCOUNT_ID`、`CLOUDFLARE_API_TOKEN` 和 `CLOUDFLARE_WORKER_NAME`。Worker 路由对应 `docs.omoolab.xyz/snapform/*`。
|
||||
|
||||
## 资产构建与验证
|
||||
|
||||
`tools/` 脚本依赖 `bpy`,必须由 Blender 执行。设置本机 Blender 可执行文件后,可以重建或验证 `O_SnapForm.blend`:
|
||||
`tools/` 中的资产脚本依赖 `bpy`,应由 Blender 执行:
|
||||
|
||||
```bash
|
||||
BLENDER_BIN="/c/Program Files/Blender Foundation/Blender 4.5/blender.exe"
|
||||
@@ -156,14 +110,11 @@ BLENDER_BIN="/c/Program Files/Blender Foundation/Blender 4.5/blender.exe"
|
||||
"$BLENDER_BIN" --background --python tools/validate_moge_surface.py
|
||||
```
|
||||
|
||||
验证脚本会自动把 `src/snapform/wheels/` 中的 BlendJob wheel 加入 Blender Python 路径,因此可在
|
||||
`--factory-startup` 的干净环境中直接运行。
|
||||
|
||||
只改 Python、文档或打包逻辑时不需要重建 `.blend` 资产;修改节点组、材质组或其接口时,应运行相应资产验证脚本,并再次运行完整测试。
|
||||
修改节点组、材质组或资产接口后,运行对应验证脚本和完整测试。Python、文档或打包逻辑变化无需重建 `.blend` 资产。
|
||||
|
||||
## 上游与许可证
|
||||
|
||||
- Depth Anything 3 代码采用 Apache 2.0
|
||||
- BEN2 ONNX 模型采用其仓库声明的 Apache 2.0 License
|
||||
- SnapForm Extension 代码采用 GPL-3.0-or-later
|
||||
- 模型权重许可证由所选 Hugging Face 模型仓库决定,Extension 下载前会在界面显示
|
||||
- 模型权重许可证由所选 Hugging Face 模型仓库决定
|
||||
|
||||
Reference in New Issue
Block a user