From af5603045c801aced0ddd42d2ae495c13ad1a194 Mon Sep 17 00:00:00 2001 From: nan Date: Fri, 21 Aug 2026 09:46:50 +0800 Subject: [PATCH] Remove obsolete implementation and simplify project structure --- .github/workflows/docs.yml | 6 +- AGENTS.md | 16 +- README.md | 24 +-- docs/animation.md | 6 +- docs/development.md | 10 +- docs/faq.md | 8 +- docs/features.md | 8 +- docs/guide-depth-plane.md | 2 +- docs/guide-surface.md | 4 +- docs/index.md | 10 +- docs/installation.md | 20 +-- docs/models-and-storage.md | 10 +- docs/quick-start.md | 4 +- docs/remove-background.md | 4 +- docs/server.md | 10 +- docs/surface.md | 2 +- docs/workflows.md | 2 +- mkdocs.yml | 12 +- pack.py | 2 +- pyproject.toml | 2 +- src/{snapform => anyimage}/__init__.py | 20 +-- .../assets/O_AnyImage.blend} | 0 .../blender_manifest.toml | 4 +- src/{snapform => anyimage}/menu.py | 24 +-- src/{snapform => anyimage}/model_catalog.py | 0 .../operators/__init__.py | 0 .../operators/background.py | 10 +- .../operators/balloon/__init__.py | 0 .../operators/balloon/depth.py | 6 +- .../operators/balloon/geometry.py | 0 .../operators/balloon/operator.py | 50 +++--- .../operators/balloon/poisson.py | 0 .../operators/balloon/teddy.py | 0 .../operators/common.py | 2 +- src/{snapform => anyimage}/operators/debug.py | 12 +- .../operators/depth_plane/__init__.py | 0 .../operators/depth_plane/build.py | 18 +-- .../operators/depth_plane/data.py | 0 .../operators/depth_plane/operator.py | 28 ++-- src/{snapform => anyimage}/operators/image.py | 4 +- .../operators/material.py | 2 +- .../operators/models.py | 6 +- .../operators/surface.py | 24 +-- src/{snapform => anyimage}/panel.py | 54 +++---- src/{snapform => anyimage}/preferences.py | 8 +- src/{snapform => anyimage}/properties.py | 2 +- src/{snapform => anyimage}/runtime.py | 4 +- src/{snapform => anyimage}/server/__init__.py | 4 +- .../server/geometry/__init__.py | 0 .../server/geometry/grid_mesh.py | 0 .../server/geometry/projection.py | 0 .../server/geometry/surface.py | 0 .../server/jobs/__init__.py | 0 .../server/jobs/background.py | 0 .../server/jobs/balloon.py | 0 .../server/jobs/common.py | 0 .../server/jobs/debug_ben2.py | 0 .../server/jobs/debug_da3.py | 0 .../server/jobs/debug_moge2.py | 0 .../server/jobs/depth.py | 0 .../server/jobs/foreground.py | 0 .../server/jobs/frames.py | 0 .../server/jobs/surface.py | 0 .../server/media/__init__.py | 0 .../server/media/input.py | 2 +- .../server/model_catalog.py | 0 .../server/model_download.py | 8 +- .../server/model_manager.py | 0 .../server/models/__init__.py | 0 .../server/models/ben2.py | 0 .../server/models/da3.py | 2 +- .../server/models/moge2.py | 0 .../server/models/onnx_ben2.py | 0 .../server/models/onnx_da3.py | 0 .../server/models/onnx_moge2.py | 0 .../server/models/onnx_runtime.py | 0 .../server/outputs/__init__.py | 0 .../server/outputs/debug_da3.py | 0 .../server/outputs/debug_moge2.py | 0 .../server/outputs/depth.py | 0 .../server/outputs/surface.py | 0 sync_models.py | 4 +- tests/test_addon.py | 144 +++++++++--------- tests/test_ben2_onnx.py | 2 +- tests/test_da3_onnx.py | 2 +- tests/test_download_progress.py | 2 +- tests/test_image_depth.py | 24 +-- tests/test_manifest.py | 4 +- tests/test_models.py | 8 +- tests/test_moge_onnx.py | 22 +-- tests/test_pack.py | 8 +- tests/test_server.py | 6 +- tests/test_worker.py | 2 +- tools/build_geometry_nodes_asset.py | 4 +- tools/validate_balloon_asset.py | 8 +- tools/validate_depth_plane_asset.py | 8 +- tools/validate_geometry_nodes_asset.py | 6 +- tools/validate_moge_depth_plane.py | 8 +- tools/validate_moge_surface.py | 10 +- uv.lock | 2 +- 100 files changed, 365 insertions(+), 365 deletions(-) rename src/{snapform => anyimage}/__init__.py (73%) rename src/{snapform/assets/O_SnapForm.blend => anyimage/assets/O_AnyImage.blend} (100%) rename src/{snapform => anyimage}/blender_manifest.toml (94%) rename src/{snapform => anyimage}/menu.py (78%) rename src/{snapform => anyimage}/model_catalog.py (100%) rename src/{snapform => anyimage}/operators/__init__.py (100%) rename src/{snapform => anyimage}/operators/background.py (92%) rename src/{snapform => anyimage}/operators/balloon/__init__.py (100%) rename src/{snapform => anyimage}/operators/balloon/depth.py (99%) rename src/{snapform => anyimage}/operators/balloon/geometry.py (100%) rename src/{snapform => anyimage}/operators/balloon/operator.py (95%) rename src/{snapform => anyimage}/operators/balloon/poisson.py (100%) rename src/{snapform => anyimage}/operators/balloon/teddy.py (100%) rename src/{snapform => anyimage}/operators/common.py (98%) rename src/{snapform => anyimage}/operators/debug.py (90%) rename src/{snapform => anyimage}/operators/depth_plane/__init__.py (100%) rename src/{snapform => anyimage}/operators/depth_plane/build.py (96%) rename src/{snapform => anyimage}/operators/depth_plane/data.py (100%) rename src/{snapform => anyimage}/operators/depth_plane/operator.py (95%) rename src/{snapform => anyimage}/operators/image.py (99%) rename src/{snapform => anyimage}/operators/material.py (99%) rename src/{snapform => anyimage}/operators/models.py (91%) rename src/{snapform => anyimage}/operators/surface.py (97%) rename src/{snapform => anyimage}/panel.py (86%) rename src/{snapform => anyimage}/preferences.py (89%) rename src/{snapform => anyimage}/properties.py (99%) rename src/{snapform => anyimage}/runtime.py (94%) rename src/{snapform => anyimage}/server/__init__.py (95%) rename src/{snapform => anyimage}/server/geometry/__init__.py (100%) rename src/{snapform => anyimage}/server/geometry/grid_mesh.py (100%) rename src/{snapform => anyimage}/server/geometry/projection.py (100%) rename src/{snapform => anyimage}/server/geometry/surface.py (100%) rename src/{snapform => anyimage}/server/jobs/__init__.py (100%) rename src/{snapform => anyimage}/server/jobs/background.py (100%) rename src/{snapform => anyimage}/server/jobs/balloon.py (100%) rename src/{snapform => anyimage}/server/jobs/common.py (100%) rename src/{snapform => anyimage}/server/jobs/debug_ben2.py (100%) rename src/{snapform => anyimage}/server/jobs/debug_da3.py (100%) rename src/{snapform => anyimage}/server/jobs/debug_moge2.py (100%) rename src/{snapform => anyimage}/server/jobs/depth.py (100%) rename src/{snapform => anyimage}/server/jobs/foreground.py (100%) rename src/{snapform => anyimage}/server/jobs/frames.py (100%) rename src/{snapform => anyimage}/server/jobs/surface.py (100%) rename src/{snapform => anyimage}/server/media/__init__.py (100%) rename src/{snapform => anyimage}/server/media/input.py (98%) rename src/{snapform => anyimage}/server/model_catalog.py (100%) rename src/{snapform => anyimage}/server/model_download.py (98%) rename src/{snapform => anyimage}/server/model_manager.py (100%) rename src/{snapform => anyimage}/server/models/__init__.py (100%) rename src/{snapform => anyimage}/server/models/ben2.py (100%) rename src/{snapform => anyimage}/server/models/da3.py (97%) rename src/{snapform => anyimage}/server/models/moge2.py (100%) rename src/{snapform => anyimage}/server/models/onnx_ben2.py (100%) rename src/{snapform => anyimage}/server/models/onnx_da3.py (100%) rename src/{snapform => anyimage}/server/models/onnx_moge2.py (100%) rename src/{snapform => anyimage}/server/models/onnx_runtime.py (100%) rename src/{snapform => anyimage}/server/outputs/__init__.py (100%) rename src/{snapform => anyimage}/server/outputs/debug_da3.py (100%) rename src/{snapform => anyimage}/server/outputs/debug_moge2.py (100%) rename src/{snapform => anyimage}/server/outputs/depth.py (100%) rename src/{snapform => anyimage}/server/outputs/surface.py (100%) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 59bc6ae..aa41e51 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -28,8 +28,8 @@ jobs: - name: 整理发布目录 run: | - mkdir -p public/snapform - cp -a site/. public/snapform/ + mkdir -p public/anyimage + cp -a site/. public/anyimage/ - name: 配置 Node.js uses: actions/setup-node@v6 @@ -50,5 +50,5 @@ jobs: --name "$CLOUDFLARE_WORKER_NAME" \ --compatibility-date 2026-08-19 \ --keep-vars \ - --message "SnapForm docs $GITHUB_SHA" \ + --message "AnyImage docs $GITHUB_SHA" \ --autoconfig=false diff --git a/AGENTS.md b/AGENTS.md index 350a163..629e234 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# SnapForm 开发约定 +# AnyImage 开发约定 ## 总则 @@ -15,7 +15,7 @@ ├── docs/ # 按功能拆分的设计与开发文档 ├── pack.py # 构建各平台 Blender Extension ZIP ├── sync_models.py # 准备并同步 ONNX 模型 -├── src/snapform/ +├── src/anyimage/ │ ├── __init__.py # Blender 注册入口 │ ├── operators.py # Job Operator 与结果导入 │ ├── panel.py # 3D View 面板 @@ -24,7 +24,7 @@ │ ├── job_runtime.py # BlendJob Runtime 配置 │ ├── blender/ # Depth Plane、Surface 的 Blender 侧实现 │ ├── server/ # Job、模型、ONNX 推理与输出实现 -│ ├── assets/O_SnapForm.blend # Geometry Nodes 与材质资产 +│ ├── assets/O_AnyImage.blend # Geometry Nodes 与材质资产 │ └── wheels/ # 随扩展分发的 BlendJob wheel ├── tools/ # Blender 资产构建与验证脚本 └── tests/ # Python 自动化测试 @@ -58,19 +58,19 @@ uv lock --refresh ## 命名规范 - 变量、函数、Docstring 使用英文;同一概念在代码和文档中使用统一表达 -- Python 类使用大驼峰,不添加项目名前缀。Operator 使用动宾结构,如 `ConvertToDepthPlane`、`RemoveImageBackground`;Menu、Panel、AddonPreferences、PropertyGroup 分别使用实际类型后缀,如 `SnapFormImageMenu`、`ServerPanel`、`SnapFormPreferences`、`SnapFormSettings` -- `bl_idname` 与挂载到公共 Blender RNA 类型的 Property 使用 `snapform` 项目前缀:Operator 如 `snapform.convert_to_depth_plane`,Menu 如 `SNAPFORM_MT_image_context`,Panel 如 `SNAPFORM_PT_server`,公共 Property 如 `Scene.snapform_settings` +- Python 类使用大驼峰,不添加项目名前缀。Operator 使用动宾结构,如 `ConvertToDepthPlane`、`RemoveImageBackground`;Menu、Panel、AddonPreferences、PropertyGroup 分别使用实际类型后缀,如 `AnyImageImageMenu`、`ServerPanel`、`AnyImagePreferences`、`AnyImageSettings` +- `bl_idname` 与挂载到公共 Blender RNA 类型的 Property 使用 `anyimage` 项目前缀:Operator 如 `anyimage.convert_to_depth_plane`,Menu 如 `ANYIMAGE_MT_image_context`,Panel 如 `ANYIMAGE_PT_server`,公共 Property 如 `Scene.anyimage_settings` - Operator 自身 Property 不加项目前缀,使用业务名称,如 `input_path`、`process_res`、`resolution_level` -- 扩展包名使用 Manifest 中的真实名称、版本和平台,例如 `SnapForm.v0.11.2.windows-x64.zip`;节点组名称沿用资产中的 `O DA3 Depth Plane`、`O MoGe2 Surface` 等既有名称 +- 扩展包名使用 Manifest 中的真实名称、版本和平台,例如 `AnyImage.v0.11.2.windows-x64.zip`;节点组名称沿用资产中的 `O DA3 Depth Plane`、`O MoGe2 Surface` 等既有名称 ## 代码规范 - 避免不必要的嵌套,优先使用提前返回和小而明确的函数 - 只为特殊、非常规或存在兼容性原因的实现写注释,不复述代码本身 - 删除功能时同时删除无效参数、分支、测试和文档,不保留没有实际消费者的兼容层 -- Blender 侧不载入 AI 依赖:UI、Operator 和结果导入放在 `src/snapform/` 或 `src/snapform/blender/`,模型下载、ONNX 推理和输出放在 `src/snapform/server/` +- Blender 侧不载入 AI 依赖:UI、Operator 和结果导入放在 `src/anyimage/` 或 `src/anyimage/blender/`,模型下载、ONNX 推理和输出放在 `src/anyimage/server/` - Job 参数使用可序列化的普通字典;Blender 数据只能在主线程的 Operator 响应阶段读写 -- 新增或修改 Blender 类型时同步检查 `src/snapform/__init__.py` 的注册与逆序注销,并补充对应测试 +- 新增或修改 Blender 类型时同步检查 `src/anyimage/__init__.py` 的注册与逆序注销,并补充对应测试 - 依赖版本、wheel 或 Manifest 改变时同步检查 `pyproject.toml`、`uv.lock`、`blender_manifest.toml` 和打包测试 ## 文档与 Markdown 规范 diff --git a/README.md b/README.md index db7ed44..e2848ee 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# SnapForm +# AnyImage -SnapForm 是一个 Blender 扩展,可以把一张照片、一段视频或一组序列帧快速变成有真实深度的立体面片。 +AnyImage 是一个 Blender 扩展,可以把一张照片、一段视频或一组序列帧快速变成有真实深度的立体面片。 完整使用说明请从[文档首页](docs/index.md)开始;首次使用请依次阅读 [安装与首次配置](docs/installation.md)和[五分钟上手](docs/quick-start.md)。 @@ -22,14 +22,14 @@ SnapForm 是一个 Blender 扩展,可以把一张照片、一段视频或一 3. 点击 `Install from Disk`,选择下载的压缩包 4. 在扩展偏好设置中确认 Storage Root 与 Device(保持默认即可);Device 默认取本机 最快的 DirectML provider;Apple M4 或更新芯片可选 MPS/CoreML,其他 Mac 只提供 CPU -5. 打开 3D 视图右侧的 `SnapForm` 面板:使用官方源点击 `Install Environment`,使用国内镜像点击 `Install Environment (Mirror)` +5. 打开 3D 视图右侧的 `AnyImage` 面板:使用官方源点击 `Install Environment`,使用国内镜像点击 `Install Environment (Mirror)` 扩展不内置 uv 或 AI 运行库。首次使用会先下载并校验固定版本的 uv,随后自动安装轻量的 ONNX Runtime 环境,再下载 `MoGe-2 ViT-S Normal` 和 `BEN2 Base`;不安装 PyTorch,也不下载各模型的 Python 源码包。其他 AI 模型可在 `Models` panel 中按需下载,请保持网络畅通,首次安装需要一些时间。 Environment Bootstrap 使用连续的 0–100%:uv 为 1–20%、Python 为 20–50%、packages 为 50–98%,最终验证为 98–100%。三个阶段显示真实的 `1/3`、`2/3`、`3/3`,下载占各阶段的 84–87%;开始与最终验证不显示编号,单阶段状态不显示 `1/1`。官方按钮固定使用 GitHub、uv 默认 Python 下载源和 PyPI;镜像按钮固定使用 CNB uv Release、CNB Python 解释器镜像和清华 PyPI,两种方式都不竞速或自动切换。MoGe-2 与 BEN2 属于 post-install,各自使用独立进度,不计入 Environment 的这轮 0–100%,其模型下载源逻辑不受按钮选择影响。 任一必需模型在两个来源都下载失败时,`Install Environment` 会明确报错;Environment 本身仍会保留。 -选中 Image Empty 后,右键 `SnapForm` 子菜单会在缺少 `MoGe-2 ViT-S Normal` 或 `BEN2 Base` +选中 Image Empty 后,右键 `AnyImage` 子菜单会在缺少 `MoGe-2 ViT-S Normal` 或 `BEN2 Base` 时显示 `Download Required Models`,一次补齐缺失项,不会重复下载已经就绪的模型。 Environment 未安装时,同一位置显示两个安装按钮。Environment 或必需模型未就绪时, 菜单仍显示 `Convert to Depth Plane`、`Convert to Surface` 和 `Remove Background`,但三个入口都会保持禁用。 @@ -41,7 +41,7 @@ Environment 未安装时,同一位置显示两个安装按钮。Environment ### 转换为立体面片 1. 在 3D 视图中选中一个 Image Empty(空物体,显示方式为 Image) -2. 右键打开 `SnapForm` 子菜单,选择 `Convert to Depth Plane` +2. 右键打开 `AnyImage` 子菜单,选择 `Convert to Depth Plane` 3. 在对话框中选择: - `Depth from`:`Original` 直接用原图,`DA3` 使用现有 DA3 流程,`MoGe-2` 生成 metric depth、normal 与有效区域 mask - `Resolution Scale` 使用 `1–100%`,按原图长边计算 Process Res;结果会限制在 `252–1008` 并自动对齐到 14 的倍数 @@ -52,7 +52,7 @@ Environment 未安装时,同一位置显示两个安装按钮。Environment ### 套索生成 Balloon -选中单张图片的 Image Empty,右键打开 `SnapForm` 子菜单并选择 `Balloon Lasso Tool`。Blender 会激活 3D Viewport 左侧工具栏底部、紧邻 Add Cube、且不增加分隔空隙的独立 Balloon Lasso,Poly Build 的绿色图标、Annotate 同款铅笔光标、Tool Header 与状态栏共同提示当前工具状态,不再用黄色外框或强制修改 Shading、Overlay。Blender 的公开 Workspace Tool API 不支持按 Active Object 动态隐藏工具,因此图标在 Object Mode 中保持可见,但只有 Active Object 是 Image Empty 时才能启动 Stroke。 +选中单张图片的 Image Empty,右键打开 `AnyImage` 子菜单并选择 `Balloon Lasso Tool`。Blender 会激活 3D Viewport 左侧工具栏底部、紧邻 Add Cube、且不增加分隔空隙的独立 Balloon Lasso,Poly Build 的绿色图标、Annotate 同款铅笔光标、Tool Header 与状态栏共同提示当前工具状态,不再用黄色外框或强制修改 Shading、Overlay。Blender 的公开 Workspace Tool API 不支持按 Active Object 动态隐藏工具,因此图标在 Object Mode 中保持可见,但只有 Active Object 是 Image Empty 时才能启动 Stroke。 按住左键沿目标轮廓绘制,松开后生成一个带原图 UV 的封闭网格。每次拖动都是一个独立完成的顶层 `Extract Balloon` Operator,工具本身继续保持激活,下一次拖动会创建另一个 Balloon;因此 `Ctrl+Z` 只撤销最近一次生成,`Ctrl+Shift+Z` 重做。每次生成后源 Image Empty 都保持选中和 Active。未绘制时没有持续 Modal 拦截事件,视图导航和其他原生快捷键由 Blender 正常处理;绘制中可用右键或 `Esc` 取消当前轨迹。选择左侧工具栏中的其他工具即可离开 Balloon Lasso。 @@ -68,13 +68,13 @@ MoGe normal 会转换成适配 Balloon UV 的 tangent-space `normal.png`,由 ### 去除背景 -选中 Image Empty 后,右键打开 `SnapForm` 子菜单并选择 `Remove Background`,完成后 Empty 会自动 +选中 Image Empty 后,右键打开 `AnyImage` 子菜单并选择 `Remove Background`,完成后 Empty 会自动 换成透明前景图。该操作在子菜单中使用独立分割区域。 ### 转换为透视网格 -选中单张图片的 Image Empty,右键打开 `SnapForm` 子菜单并选择 `Convert to Surface`。可选择 MoGe-2 -ViT-S、ViT-B、ViT-L 或 DA3 Small、Base,其中 MoGe-2 ViT-S 为默认模型。SnapForm 会按模型输出的 +选中单张图片的 Image Empty,右键打开 `AnyImage` 子菜单并选择 `Convert to Surface`。可选择 MoGe-2 +ViT-S、ViT-B、ViT-L 或 DA3 Small、Base,其中 MoGe-2 ViT-S 为默认模型。AnyImage 会按模型输出的 相机内参与三维点建立透视网格,并匹配原 Empty 的可见尺寸、Offset 与 Transform。Server 通过统一的 Surface 输出流程构建 DA3 与 MoGe-2 源网格:MoGe-2 使用深度断层 mask,DA3 保留 confidence 与边拉伸 数据。两者再由独立的 Geometry Nodes @@ -102,19 +102,19 @@ Layer Color 同时驱动 Principled BSDF 的 Base Color、Subsurface Radius 和 ### 视频与序列帧 -SnapForm 支持视频(mp4、mkv、mov 等)和序列帧,会逐帧处理并生成逐帧对应的立体面片。`.color` 与 `.depth` 按源 Empty Image 的类型载入:普通单图为 `IMAGE`,Movie/Sequence 即使只处理一帧也仍为 `SEQUENCE`。处理范围默认 +AnyImage 支持视频(mp4、mkv、mov 等)和序列帧,会逐帧处理并生成逐帧对应的立体面片。`.color` 与 `.depth` 按源 Empty Image 的类型载入:普通单图为 `IMAGE`,Movie/Sequence 即使只处理一帧也仍为 `SEQUENCE`。处理范围默认 跟随 Empty 上设置的 `Image Frames` 与 `Offset`,不需要额外配置。DA3 的转换任务复用同一个 ONNX Session 逐帧推理,显存峰值不随视频帧数平方增长。Debug 只保存模型 API 的直接返回:DA3 多帧输入 保留联合推理,MoGe-2 与 BEN2 按各自的单图 API 逐帧保存。 ## 任务结果保存在哪里 -任务结果保存在 Runtime Storage Root 的 `jobs/` 下,默认是 `~/.snapform/jobs/`。Job Server 接受任务时自动生成 opaque Job ID,并创建同名文件夹;Blender 不预先申请 ID 或目录。Packed Image 和序列帧的临时输入由 Blender 在任务结束后清理,Server 产物直接写入该 Job 目录。视频或序列帧生成的面片会引用其中的序列帧,请保留对应文件夹,不要随意删除。 +任务结果保存在 Runtime Storage Root 的 `jobs/` 下,默认是 `~/.anyimage/jobs/`。Job Server 接受任务时自动生成 opaque Job ID,并创建同名文件夹;Blender 不预先申请 ID 或目录。Packed Image 和序列帧的临时输入由 Blender 在任务结束后清理,Server 产物直接写入该 Job 目录。视频或序列帧生成的面片会引用其中的序列帧,请保留对应文件夹,不要随意删除。 ## 常见问题 - 从 0.12.0–0.12.5 升级到 0.12.6 或更高版本后,请重新执行一次 `Install Environment`,重建不再单独安装 BlendJob 的 Server Environment -- 首次使用需要下载模型,如果下载慢或失败,可在 Image Empty 的 `SnapForm` 右键菜单点击 +- 首次使用需要下载模型,如果下载慢或失败,可在 Image Empty 的 `AnyImage` 右键菜单点击 `Download Required Models`,也可在 `Models` panel 里逐项重试 - 安装 Environment 时下载状态会显示平均速度;网络适合海外源时选择 `Install Environment`,国内网络选择 `Install Environment (Mirror)`。每个按钮固定使用对应来源,失败时不会自动切换 - 默认模型下载会在 Hugging Face 与 OmooLab 镜像之间自动回退;某一来源暂时断线不会阻止后续模型尝试另一来源 diff --git a/docs/animation.md b/docs/animation.md index 7c03dc7..d72afdf 100644 --- a/docs/animation.md +++ b/docs/animation.md @@ -1,6 +1,6 @@ # 视频与序列帧 -SnapForm 可以逐帧处理视频和序列帧,并生成随场景时间播放的 Depth Plane 或透明 Image Empty。 +AnyImage 可以逐帧处理视频和序列帧,并生成随场景时间播放的 Depth Plane 或透明 Image Empty。 ## 支持的工作流 @@ -17,7 +17,7 @@ SnapForm 可以逐帧处理视频和序列帧,并生成随场景时间播放 - **Start** 决定结果从场景的哪一帧开始播放。 - **Cyclic** 会保留到生成的颜色与深度序列中。 -显式把 Image Frames 设为 `1` 时,SnapForm 只处理一帧。范围超过视频长度时,SnapForm 会把窗口收回有效范围内。 +显式把 Image Frames 设为 `1` 时,AnyImage 只处理一帧。范围超过视频长度时,AnyImage 会把窗口收回有效范围内。 ## 性能建议 @@ -28,7 +28,7 @@ SnapForm 可以逐帧处理视频和序列帧,并生成随场景时间播放 ## 保存和移动工程 -Blender 无法把整组动画图片序列完整打包进 `.blend`。SnapForm 因此让动画结果直接引用 Storage Root 的 Job 文件夹。 +Blender 无法把整组动画图片序列完整打包进 `.blend`。AnyImage 因此让动画结果直接引用 Storage Root 的 Job 文件夹。 !!! danger 删除、移动或清理仍被工程引用的 Job 文件夹,会导致动画颜色或深度序列丢失。 diff --git a/docs/development.md b/docs/development.md index 6be57c1..3b7c83c 100644 --- a/docs/development.md +++ b/docs/development.md @@ -2,7 +2,7 @@ ## 程序设计 -SnapForm 分为 Blender 交互层、BlendJob Runtime 和 Job Server 计算层。 +AnyImage 分为 Blender 交互层、BlendJob Runtime 和 Job Server 计算层。 ```mermaid flowchart LR @@ -30,7 +30,7 @@ Blender 交互层管理 UI、RNA 状态、任务参数和结果导入。Runtime | `server/geometry/` | 纯数据几何处理 | | `server/outputs/` | 文件序列化 | | `server/media/` | 媒体输入 | -| `assets/O_SnapForm.blend` | Geometry Nodes 与材质资产 | +| `assets/O_AnyImage.blend` | Geometry Nodes 与材质资产 | Depth Plane、Surface、Background 和 Balloon 按功能组织。一个功能的入口、请求和 Blender 回写放在一起;跨功能的图片、材质和参数处理放在 `operators/common.py`、`operators/image.py` 与 `operators/material.py`。 @@ -44,7 +44,7 @@ Server 的模型模块返回 Prediction,几何模块处理数组与网格, ├── docs/ ├── pack.py ├── sync_models.py -├── src/snapform/ +├── src/anyimage/ │ ├── blender_manifest.toml │ ├── runtime.py │ ├── menu.py @@ -94,7 +94,7 @@ uv run --only-group docs mike deploy -p uv run --only-group docs mike set-default -p ``` -自动部署将 MkDocs 站点发布到专用 Cloudflare Worker。仓库需要配置 `CLOUDFLARE_ACCOUNT_ID`、`CLOUDFLARE_API_TOKEN` 和 `CLOUDFLARE_WORKER_NAME`。Worker 路由对应 `docs.omoolab.xyz/snapform/*`。 +自动部署将 MkDocs 站点发布到专用 Cloudflare Worker。仓库需要配置 `CLOUDFLARE_ACCOUNT_ID`、`CLOUDFLARE_API_TOKEN` 和 `CLOUDFLARE_WORKER_NAME`。Worker 路由对应 `docs.omoolab.xyz/anyimage/*`。 ## 资产构建与验证 @@ -117,5 +117,5 @@ BLENDER_BIN="/c/Program Files/Blender Foundation/Blender 4.5/blender.exe" - Depth Anything 3 代码采用 Apache 2.0 - BEN2 ONNX 模型采用其仓库声明的 Apache 2.0 License -- SnapForm Extension 代码采用 GPL-3.0-or-later +- AnyImage Extension 代码采用 GPL-3.0-or-later - 模型权重许可证由所选 Hugging Face 模型仓库决定 diff --git a/docs/faq.md b/docs/faq.md index 615e3ce..e1098a3 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,8 +1,8 @@ # 常见问题 -## 找不到 SnapForm 右键菜单 +## 找不到 AnyImage 右键菜单 -SnapForm 菜单只会在选中 Image Empty 时出现。确认对象类型是 Empty,并且显示方式为 Image。普通 Mesh、图片编辑器中的图片或未选中的 Image Empty 都不会显示入口。 +AnyImage 菜单只会在选中 Image Empty 时出现。确认对象类型是 Empty,并且显示方式为 Image。普通 Mesh、图片编辑器中的图片或未选中的 Image Empty 都不会显示入口。 ## 转换入口是灰色的 @@ -10,7 +10,7 @@ SnapForm 菜单只会在选中 Image Empty 时出现。确认对象类型是 Emp - Environment 尚未安装。 - 默认必需模型尚未就绪。 -- 另一个 SnapForm 任务正在运行。 +- 另一个 AnyImage 任务正在运行。 - Surface 的输入不是单张图片。 如果子菜单显示 **Install Environment** 或 **Download Required Models**,先完成对应操作。 @@ -50,7 +50,7 @@ SnapForm 菜单只会在选中 Image Empty 时出现。确认对象类型是 Emp ## 如何完全撤销一次转换 -转换完成后直接按 `Ctrl+Z`。SnapForm 会把网格、材质、图片和修改器的创建合并为一次 Blender Undo 操作。 +转换完成后直接按 `Ctrl+Z`。AnyImage 会把网格、材质、图片和修改器的创建合并为一次 Blender Undo 操作。 ## 从旧版本升级后功能不可用 diff --git a/docs/features.md b/docs/features.md index 4b25256..34dde88 100644 --- a/docs/features.md +++ b/docs/features.md @@ -1,6 +1,6 @@ # 功能参考 -本页概览 SnapForm 的能力。安装步骤见[安装与首次配置](installation.md),实际操作见[工作流选择](workflows.md)与各使用指南。 +本页概览 AnyImage 的能力。安装步骤见[安装与首次配置](installation.md),实际操作见[工作流选择](workflows.md)与各使用指南。 ## 工作流 @@ -16,9 +16,9 @@ Depth Plane 与 Surface 可使用 DA3 或 MoGe-2。DA3 提供相对深度和相 ## Blender 交互 -主要功能位于 Image Empty 的 `SnapForm` 右键菜单。菜单会显示 Environment 和必需模型的就绪状态,并在缺少内容时提供安装或下载入口。 +主要功能位于 Image Empty 的 `AnyImage` 右键菜单。菜单会显示 Environment 和必需模型的就绪状态,并在缺少内容时提供安装或下载入口。 -转换任务完成后,SnapForm 在一个 Undo 步骤中创建网格、图片、材质和修改器。源 Image Empty 是否保留由转换选项决定。 +转换任务完成后,AnyImage 在一个 Undo 步骤中创建网格、图片、材质和修改器。源 Image Empty 是否保留由转换选项决定。 Balloon 默认在 Blender 内部生成,无需 Environment 或模型。Tool Settings 提供模式、厚度、采样距离、材质复用、`Contour`、`Depth` 与 MoGe-2 `Depth Model`。Depth 会把物理距离相对化并稳健拟合初始基面,保留未截断的正负起伏。Base Plane 子 Empty 的旋转定义基面朝向,沿自身局部 Z 移动定义 middle level。 @@ -36,7 +36,7 @@ Blender 无法整体 Pack 图片序列,因此动画结果会继续引用 Job AI 任务在独立 Python Environment 中通过 ONNX Runtime 执行。Blender 负责界面、任务提交和结果导入,Job Server 负责模型与文件处理。 -默认 Storage Root 为 `~/.snapform`,其中保存 Environment、模型、日志和 Job 结果。连续任务会复用已加载的模型 Session;DA3 与 MoGe-2 共享一个深度模型缓存位置,BEN2 可同时保留。 +默认 Storage Root 为 `~/.anyimage`,其中保存 Environment、模型、日志和 Job 结果。连续任务会复用已加载的模型 Session;DA3 与 MoGe-2 共享一个深度模型缓存位置,BEN2 可同时保留。 安装、下载和推理都在后台运行,并通过状态栏提供进度与取消操作。详细设计见[Job Server](server.md)。 diff --git a/docs/guide-depth-plane.md b/docs/guide-depth-plane.md index 16e8f04..8f3d1a5 100644 --- a/docs/guide-depth-plane.md +++ b/docs/guide-depth-plane.md @@ -5,7 +5,7 @@ Depth Plane 将图片转换为带位移的立体面片。它适合快速场景 ## 创建 Depth Plane 1. 选中 Image Empty。 -2. 在 3D View 中右键,选择 **SnapForm > Convert to Depth Plane**。 +2. 在 3D View 中右键,选择 **AnyImage > Convert to Depth Plane**。 3. 选择深度来源和需要的选项。 4. 确认后等待任务完成。 diff --git a/docs/guide-surface.md b/docs/guide-surface.md index 7deb1ab..368a899 100644 --- a/docs/guide-surface.md +++ b/docs/guide-surface.md @@ -8,7 +8,7 @@ Surface 从单张图片构建带透视关系的纹理网格。它适合建筑、 ## 创建 Surface 1. 选中只包含一帧的 Image Empty。 -2. 在 3D View 中右键,选择 **SnapForm > Convert to Surface**。 +2. 在 3D View 中右键,选择 **AnyImage > Convert to Surface**。 3. 选择模型和转换选项。 4. 确认后等待网格、材质和 Geometry Nodes 修改器创建完成。 @@ -16,7 +16,7 @@ Surface 从单张图片构建带透视关系的纹理网格。它适合建筑、 默认的 **MoGe-2 ViT-S Normal** 适合多数图片。MoGe-2 使用 **Resolution Level**,DA3 使用 **Resolution Scale**。提高分辨率会增加耗时和内存占用,建议先用默认值判断整体结构。 -如果某个模型名称后显示 **(Missing)**,请先在 3D View 的 **SnapForm > Models** 面板下载它。 +如果某个模型名称后显示 **(Missing)**,请先在 3D View 的 **AnyImage > Models** 面板下载它。 ## 转换选项 diff --git a/docs/index.md b/docs/index.md index 8e73149..eaf0506 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ -# SnapForm +# AnyImage 把图片里的空间感带进 Blender。 -SnapForm 是一款 Blender 扩展,可以把照片、视频或序列帧转换为带真实深度变化的立体面片。你只需导入图片、选中 Image Empty,然后从右键菜单选择需要的结果。 +AnyImage 是一款 Blender 扩展,可以把照片、视频或序列帧转换为带真实深度变化的立体面片。你只需导入图片、选中 Image Empty,然后从右键菜单选择需要的结果。 - 用 **Depth Plane** 快速得到可调节的浮雕式面片 - 用 **Surface** 从单张图片生成透视纹理网格 @@ -11,13 +11,13 @@ SnapForm 是一款 Blender 扩展,可以把照片、视频或序列帧转换 - 使用 Geometry Nodes 继续调整深度、细分、重拓扑与平滑效果 !!! info "运行环境与 Blender 分离" - SnapForm 的 AI 计算运行在独立环境中,不会把 ONNX Runtime 等计算依赖装进 Blender Python。首次配置完成后,日常操作都可以从 Image Empty 的右键菜单完成。 + AnyImage 的 AI 计算运行在独立环境中,不会把 ONNX Runtime 等计算依赖装进 Blender Python。首次配置完成后,日常操作都可以从 Image Empty 的右键菜单完成。 ## 从这里开始
-- **安装 SnapForm** +- **安装 AnyImage** 下载与你的系统匹配的扩展包,完成环境和默认模型配置。 @@ -51,4 +51,4 @@ SnapForm 是一款 Blender 扩展,可以把照片、视频或序列帧转换 - 正式使用前需要安装独立 Environment,以及默认的 MoGe-2 和 BEN2 模型 !!! tip - 不确定从哪里开始时,先使用默认设置将一张人物或物体照片转换为 Depth Plane。它速度快、参数直观,也最适合熟悉 SnapForm 的基本工作方式。 + 不确定从哪里开始时,先使用默认设置将一张人物或物体照片转换为 Depth Plane。它速度快、参数直观,也最适合熟悉 AnyImage 的基本工作方式。 diff --git a/docs/installation.md b/docs/installation.md index 7a19de9..ab8c6d2 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,13 +1,13 @@ # 安装与首次配置 -SnapForm 的安装分为两步:先安装 Blender Extension,再安装独立运行环境和默认模型。第二步只需在首次使用或环境版本发生变化时执行。 +AnyImage 的安装分为两步:先安装 Blender Extension,再安装独立运行环境和默认模型。第二步只需在首次使用或环境版本发生变化时执行。 ## 安装 Blender Extension 1. 下载与你的系统匹配的 ZIP 文件: - - `SnapForm.v版本号.windows-x64.zip` - - `SnapForm.v版本号.macos-arm64.zip` - - `SnapForm.v版本号.linux-x64.zip` + - `AnyImage.v版本号.windows-x64.zip` + - `AnyImage.v版本号.macos-arm64.zip` + - `AnyImage.v版本号.linux-x64.zip` 2. 打开 Blender,进入 **Edit > Preferences > Extensions**。 3. 点击右上角菜单,选择 **Install from Disk**。 4. 选择下载的 ZIP 文件并完成安装。 @@ -17,21 +17,21 @@ SnapForm 的安装分为两步:先安装 Blender Extension,再安装独立 ## 检查扩展偏好设置 -在 SnapForm 的扩展偏好设置中可以看到两个选项: +在 AnyImage 的扩展偏好设置中可以看到两个选项: -- **Storage Root**:保存运行环境、模型和任务文件的位置。默认是用户目录下的 `.snapform`,一般无需修改。 -- **Device**:正式转换任务使用的计算设备。SnapForm 默认选择本机可用的最快设备;如果 GPU Provider 不可用,会使用 CPU。 +- **Storage Root**:保存运行环境、模型和任务文件的位置。默认是用户目录下的 `.anyimage`,一般无需修改。 +- **Device**:正式转换任务使用的计算设备。AnyImage 默认选择本机可用的最快设备;如果 GPU Provider 不可用,会使用 CPU。 如果准备把 Storage Root 放到其他磁盘,建议在首次安装 Environment 之前修改。更换目录后,旧目录中的环境和模型不会自动移动。 ## 安装 Environment -打开 3D View,按 `N` 显示侧栏并切换到 **SnapForm** 页签。在 **Job Server** 面板中选择一个安装入口: +打开 3D View,按 `N` 显示侧栏并切换到 **AnyImage** 页签。在 **Job Server** 面板中选择一个安装入口: - **Install Environment**:使用官方源,适合能稳定访问 GitHub、Python 下载源和 PyPI 的网络。 - **Install Environment (Mirror)**:使用国内镜像下载 uv、Python 和 Python 包。 -安装程序会依次准备 uv、独立 Python 和运行包。Environment 完成后,SnapForm 还会下载日常功能需要的 **MoGe-2 ViT-S Normal** 与 **BEN2 Base**。 +安装程序会依次准备 uv、独立 Python 和运行包。Environment 完成后,AnyImage 还会下载日常功能需要的 **MoGe-2 ViT-S Normal** 与 **BEN2 Base**。 !!! note 两个安装按钮只影响 Environment 的下载源。模型会按自己的下载源与备用镜像规则获取。 @@ -46,7 +46,7 @@ SnapForm 的安装分为两步:先安装 Blender Extension,再安装独立 - 展开 **Models** 面板,MoGe-2 ViT-S Normal 和 BEN2 Base 显示 **Ready**。 - 选中 Image Empty 后,右键菜单中的 **Convert to Depth Plane**、**Convert to Surface** 和 **Remove Background** 可以点击。 -如果 Environment 已安装但默认模型缺失,Image Empty 的 **SnapForm** 右键子菜单会显示 **Download Required Models**。点击一次即可补齐缺失项。 +如果 Environment 已安装但默认模型缺失,Image Empty 的 **AnyImage** 右键子菜单会显示 **Download Required Models**。点击一次即可补齐缺失项。 ## 下一步 diff --git a/docs/models-and-storage.md b/docs/models-and-storage.md index f86942a..ae53e52 100644 --- a/docs/models-and-storage.md +++ b/docs/models-and-storage.md @@ -1,10 +1,10 @@ # 模型、设备与存储 -SnapForm 把运行环境、模型和任务结果放在 Blender 之外,多个 Blender 版本可以共享同一套数据。 +AnyImage 把运行环境、模型和任务结果放在 Blender 之外,多个 Blender 版本可以共享同一套数据。 ## Models 面板 -打开 3D View 侧栏中的 **SnapForm > Models**,可以查看和下载模型。 +打开 3D View 侧栏中的 **AnyImage > Models**,可以查看和下载模型。 - **Ready** 表示模型文件已经就绪。 - **Download** 用于按需下载模型。 @@ -25,10 +25,10 @@ Debug 面板中的 **Debug Device** 只影响 Debug 任务,不会覆盖正式 ## Storage Root -默认 Storage Root 是 `~/.snapform`,主要包含: +默认 Storage Root 是 `~/.anyimage`,主要包含: ```text -~/.snapform/ +~/.anyimage/ ├── .venv/ # 独立 Python Environment ├── models/ # 模型文件 ├── jobs/ # 每次任务的结果 @@ -36,7 +36,7 @@ Debug 面板中的 **Debug Device** 只影响 Debug 任务,不会覆盖正式 └── server.log # Job Server 日志 ``` -更改 Storage Root 相当于切换到另一套环境、模型和任务数据。SnapForm 不会自动移动旧目录。 +更改 Storage Root 相当于切换到另一套环境、模型和任务数据。AnyImage 不会自动移动旧目录。 ## Job 文件夹 diff --git a/docs/quick-start.md b/docs/quick-start.md index b22ca4e..4f474fc 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -8,9 +8,9 @@ 建议第一次尝试使用主体清晰、前后景关系明确的图片。人物、产品、建筑立面和插画通常都比较适合。 -## 2. 打开 SnapForm 菜单 +## 2. 打开 AnyImage 菜单 -保持 Image Empty 处于选中状态,在 3D View 中点击右键,选择 **SnapForm > Convert to Depth Plane**。 +保持 Image Empty 处于选中状态,在 3D View 中点击右键,选择 **AnyImage > Convert to Depth Plane**。 如果菜单不存在,请确认当前对象是 Image Empty;如果转换入口是灰色,请先完成[安装与首次配置](installation.md)。 diff --git a/docs/remove-background.md b/docs/remove-background.md index 23aa5a1..d23654b 100644 --- a/docs/remove-background.md +++ b/docs/remove-background.md @@ -5,10 +5,10 @@ Remove Background 使用 BEN2 为 Image Empty 生成透明前景,不创建网 ## 使用方法 1. 选中 Image Empty。 -2. 在 3D View 中右键,选择 **SnapForm > Remove Background**。 +2. 在 3D View 中右键,选择 **AnyImage > Remove Background**。 3. 等待状态栏提示任务完成。 -SnapForm 会创建新的透明颜色图,并把当前 Empty 切换到新图。对象的 Transform、显示尺寸、Offset 和其他显示设置保持不变。 +AnyImage 会创建新的透明颜色图,并把当前 Empty 切换到新图。对象的 Transform、显示尺寸、Offset 和其他显示设置保持不变。 ## 在转换时去除背景 diff --git a/docs/server.md b/docs/server.md index 1f592c1..fbc6303 100644 --- a/docs/server.md +++ b/docs/server.md @@ -1,6 +1,6 @@ # Job Server -SnapForm 把 AI 与媒体处理放在独立 Job Server 中运行,使 Blender Python 保持轻量。安装和使用问题见[安装与首次配置](installation.md)与[常见问题](faq.md)。 +AnyImage 把 AI 与媒体处理放在独立 Job Server 中运行,使 Blender Python 保持轻量。安装和使用问题见[安装与首次配置](installation.md)与[常见问题](faq.md)。 ## 架构 @@ -8,7 +8,7 @@ SnapForm 把 AI 与媒体处理放在独立 Job Server 中运行,使 Blender P flowchart LR Blender["Blender Operator"] --> Runtime["JobRuntime"] Runtime --> Queue["FIFO Queue"] - Queue --> Job["SnapForm Job"] + Queue --> Job["AnyImage Job"] Job --> Media["Media"] Job --> Models["ModelManager"] Job --> Geometry["Geometry"] @@ -19,14 +19,14 @@ flowchart LR 每个 Blender 实例拥有自己的 Server 进程,连接绑定到本机随机端口和 Instance ID。多个实例可以共享 Storage Root,但各自维护进程、队列和内存中的模型 Session。 -BlendJob 提供 Runtime、HTTP transport、队列、状态和取消协议。SnapForm 的 Operator 负责业务参数,Server Job 负责工作流编排,结果由 Operator 在 Blender 主线程中导入。 +BlendJob 提供 Runtime、HTTP transport、队列、状态和取消协议。AnyImage 的 Operator 负责业务参数,Server Job 负责工作流编排,结果由 Operator 在 Blender 主线程中导入。 ## Storage Root -默认位置为 `~/.snapform`: +默认位置为 `~/.anyimage`: ```text -~/.snapform/ +~/.anyimage/ ├── .venv/ Python Environment ├── models/ ONNX 模型 ├── jobs/ 任务产物 diff --git a/docs/surface.md b/docs/surface.md index d6d58a3..d81359c 100644 --- a/docs/surface.md +++ b/docs/surface.md @@ -53,7 +53,7 @@ DA3 使用 `O DA3 Surface`,MoGe-2 使用 `O MoGe2 Surface`。两者采用相 网格在 camera space 中生成,再通过源 Image Empty 的 Transform 放入场景。导入过程会匹配图片可见尺寸、宽高比、Offset 与主点位置。 -启用 Create Matching Camera 时,SnapForm 根据模型 intrinsics 创建相机并使用相同坐标变换,使网格与相机视图保持一致。模型估计的焦距和主点决定透视关系;`reference_depth` 决定整体尺度。 +启用 Create Matching Camera 时,AnyImage 根据模型 intrinsics 创建相机并使用相同坐标变换,使网格与相机视图保持一致。模型估计的焦距和主点决定透视关系;`reference_depth` 决定整体尺度。 ## 材质与文件 diff --git a/docs/workflows.md b/docs/workflows.md index 8f63776..4df2306 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -1,6 +1,6 @@ # 选择转换方式 -SnapForm 提供三种日常工作流。选择结果时,先考虑你需要的是可调节的“深度面片”、带透视结构的“空间网格”,还是只需要透明前景。 +AnyImage 提供三种日常工作流。选择结果时,先考虑你需要的是可调节的“深度面片”、带透视结构的“空间网格”,还是只需要透明前景。 | 工作流 | 适合场景 | 输入 | 结果 | 主要优点 | | --- | --- | --- | --- | --- | diff --git a/mkdocs.yml b/mkdocs.yml index 8a6cd05..94e4cf6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,13 +1,13 @@ -site_name: SnapForm 文档 -site_url: https://docs.omoolab.xyz/snapform/ +site_name: AnyImage 文档 +site_url: https://docs.omoolab.xyz/anyimage/ site_author: OmooLab -site_description: SnapForm 是一款将图片、视频和序列帧转换为立体面片的 Blender 扩展。 +site_description: AnyImage 是一款将图片、视频和序列帧转换为立体面片的 Blender 扩展。 -repo_name: OmooLab/SnapForm -repo_url: https://git.omoolab.xyz/icrdr/SnapForm +repo_name: OmooLab/AnyImage +repo_url: https://git.omoolab.xyz/icrdr/AnyImage nav: - - SnapForm: + - AnyImage: - index.md - 开始使用: - 安装与首次配置: installation.md diff --git a/pack.py b/pack.py index 76350f4..ee0921d 100644 --- a/pack.py +++ b/pack.py @@ -8,7 +8,7 @@ from zipfile import ZIP_DEFLATED, ZipFile PROJECT_ROOT = Path(__file__).resolve().parent -SOURCE_DIR = PROJECT_ROOT / "src" / "snapform" +SOURCE_DIR = PROJECT_ROOT / "src" / "anyimage" DIST_DIR = PROJECT_ROOT / "dist" PYTHON_VERSION = "3.11" diff --git a/pyproject.toml b/pyproject.toml index b507552..b067e0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "snapform" +name = "anyimage" version = "0.12.15" description = "Fast image-guided structure building tools for Blender" readme = "README.md" diff --git a/src/snapform/__init__.py b/src/anyimage/__init__.py similarity index 73% rename from src/snapform/__init__.py rename to src/anyimage/__init__.py index 927f784..e8f26e8 100644 --- a/src/snapform/__init__.py +++ b/src/anyimage/__init__.py @@ -3,9 +3,9 @@ import bpy from .runtime import runtime from .operators import CLASSES as OPERATOR_CLASSES from .operators.balloon import BalloonTool -from .preferences import SnapFormPreferences -from .properties import SnapFormSettings -from .menu import SnapFormImageMenu, draw_image_context_menu +from .preferences import AnyImagePreferences +from .properties import AnyImageSettings +from .menu import AnyImageImageMenu, draw_image_context_menu from .panel import ( Ben2RemovalDebugPanel, Da3OutputDebugPanel, @@ -17,10 +17,10 @@ from .panel import ( CLASSES = ( - SnapFormPreferences, - SnapFormSettings, + AnyImagePreferences, + AnyImageSettings, *OPERATOR_CLASSES, - SnapFormImageMenu, + AnyImageImageMenu, ServerPanel, ModelsPanel, DebugPanel, @@ -37,8 +37,8 @@ def register(): BalloonTool, separator=False, ) - bpy.types.Scene.snapform_settings = bpy.props.PointerProperty( - type=SnapFormSettings, + bpy.types.Scene.anyimage_settings = bpy.props.PointerProperty( + type=AnyImageSettings, ) bpy.types.VIEW3D_MT_object_context_menu.append(draw_image_context_menu) bpy.types.OUTLINER_MT_object.append(draw_image_context_menu) @@ -50,7 +50,7 @@ def unregister(): bpy.utils.unregister_tool(BalloonTool) bpy.types.VIEW3D_MT_object_context_menu.remove(draw_image_context_menu) bpy.types.OUTLINER_MT_object.remove(draw_image_context_menu) - if hasattr(bpy.types.Scene, "snapform_settings"): - del bpy.types.Scene.snapform_settings + if hasattr(bpy.types.Scene, "anyimage_settings"): + del bpy.types.Scene.anyimage_settings for class_type in reversed(CLASSES): bpy.utils.unregister_class(class_type) diff --git a/src/snapform/assets/O_SnapForm.blend b/src/anyimage/assets/O_AnyImage.blend similarity index 100% rename from src/snapform/assets/O_SnapForm.blend rename to src/anyimage/assets/O_AnyImage.blend diff --git a/src/snapform/blender_manifest.toml b/src/anyimage/blender_manifest.toml similarity index 94% rename from src/snapform/blender_manifest.toml rename to src/anyimage/blender_manifest.toml index c2ec8bc..b7e37e4 100644 --- a/src/snapform/blender_manifest.toml +++ b/src/anyimage/blender_manifest.toml @@ -1,8 +1,8 @@ schema_version = "1.0.0" -id = "snapform" +id = "anyimage" version = "0.12.15" -name = "SnapForm" +name = "AnyImage" tagline = "Build spatial structures from images, fast" maintainer = "OmooLab" type = "add-on" diff --git a/src/snapform/menu.py b/src/anyimage/menu.py similarity index 78% rename from src/snapform/menu.py rename to src/anyimage/menu.py index ef3f85b..964c26f 100644 --- a/src/snapform/menu.py +++ b/src/anyimage/menu.py @@ -3,9 +3,9 @@ import bpy from .operators.image import is_image_empty -class SnapFormImageMenu(bpy.types.Menu): - bl_idname = "SNAPFORM_MT_image_context" - bl_label = "SnapForm" +class AnyImageImageMenu(bpy.types.Menu): + bl_idname = "ANYIMAGE_MT_image_context" + bl_label = "AnyImage" def draw(self, _context): from .runtime import runtime @@ -14,7 +14,7 @@ class SnapFormImageMenu(bpy.types.Menu): layout = self.layout layout.operator_context = "INVOKE_DEFAULT" layout.operator( - "snapform.activate_balloon_tool", + "anyimage.activate_balloon_tool", text="Balloon Lasso Tool", icon="MOD_SKIN", ) @@ -22,19 +22,19 @@ class SnapFormImageMenu(bpy.types.Menu): environment_ready = runtime.environment_ready() if not environment_ready: layout.operator( - "snapform.install_environment", + "anyimage.install_environment", text="Install Environment", icon="IMPORT", ) layout.operator( - "snapform.install_environment_mirror", + "anyimage.install_environment_mirror", text="Install Environment (Mirror)", icon="IMPORT", ) models_ready = required_models_ready() if environment_ready and not models_ready: layout.operator( - "snapform.download_required_models", + "anyimage.download_required_models", text="Download Required Models", icon="IMPORT", ) @@ -44,14 +44,14 @@ class SnapFormImageMenu(bpy.types.Menu): depth_plane_row = layout.row() depth_plane_row.enabled = features_ready depth_plane_row.operator( - "snapform.convert_to_depth_plane", + "anyimage.convert_to_depth_plane", text="Convert to Depth Plane", icon="MOD_DISPLACE", ) surface_row = layout.row() surface_row.enabled = features_ready surface_row.operator( - "snapform.convert_to_surface", + "anyimage.convert_to_surface", text="Convert to Surface", icon="MESH_GRID", ) @@ -59,7 +59,7 @@ class SnapFormImageMenu(bpy.types.Menu): background_row = layout.row() background_row.enabled = features_ready background_row.operator( - "snapform.remove_image_background", + "anyimage.remove_image_background", text="Remove Background", icon="IMAGE_ALPHA", ) @@ -70,7 +70,7 @@ def draw_image_context_menu(self, context): return self.layout.separator() self.layout.menu( - SnapFormImageMenu.bl_idname, - text="SnapForm", + AnyImageImageMenu.bl_idname, + text="AnyImage", icon="PLUGIN", ) diff --git a/src/snapform/model_catalog.py b/src/anyimage/model_catalog.py similarity index 100% rename from src/snapform/model_catalog.py rename to src/anyimage/model_catalog.py diff --git a/src/snapform/operators/__init__.py b/src/anyimage/operators/__init__.py similarity index 100% rename from src/snapform/operators/__init__.py rename to src/anyimage/operators/__init__.py diff --git a/src/snapform/operators/background.py b/src/anyimage/operators/background.py similarity index 92% rename from src/snapform/operators/background.py rename to src/anyimage/operators/background.py index 0f834ff..f8e9211 100644 --- a/src/snapform/operators/background.py +++ b/src/anyimage/operators/background.py @@ -23,7 +23,7 @@ from .image import ( class RemoveImageBackground(bpy.types.Operator): - bl_idname = "snapform.remove_image_background" + bl_idname = "anyimage.remove_image_background" bl_label = "Remove Background" bl_description = "Remove the background from this Image Empty with BEN2" bl_options = {"REGISTER"} @@ -44,7 +44,7 @@ class RemoveImageBackground(bpy.types.Operator): source_object = context.object total_frames = video_total_frames(source_object.data) if total_frames > 1: - context.scene.snapform_settings.video_frames = ( + context.scene.anyimage_settings.video_frames = ( default_extract_frames(source_object) ) try: @@ -56,7 +56,7 @@ class RemoveImageBackground(bpy.types.Operator): self.report({"ERROR"}, str(error)) return {"CANCELLED"} - result = bpy.ops.snapform.process_image_background( + result = bpy.ops.anyimage.process_image_background( input_path=str(source_path), source_object_name=source_object.name, delete_input=delete_input, @@ -83,7 +83,7 @@ def apply_background_response(result, source_object_name): class ProcessImageBackground(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.process_image_background" + bl_idname = "anyimage.process_image_background" bl_label = "Process Image Background" job_type = "remove-background" starting_message = "Starting Image Empty background removal" @@ -95,7 +95,7 @@ class ProcessImageBackground(JobOperatorBase, bpy.types.Operator): def request(self, context): require_environment() require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { "input": str(background_input_path(self.input_path)), "model": BEN2_MODEL_KEY, diff --git a/src/snapform/operators/balloon/__init__.py b/src/anyimage/operators/balloon/__init__.py similarity index 100% rename from src/snapform/operators/balloon/__init__.py rename to src/anyimage/operators/balloon/__init__.py diff --git a/src/snapform/operators/balloon/depth.py b/src/anyimage/operators/balloon/depth.py similarity index 99% rename from src/snapform/operators/balloon/depth.py rename to src/anyimage/operators/balloon/depth.py index 43e184b..1ca40d0 100644 --- a/src/snapform/operators/balloon/depth.py +++ b/src/anyimage/operators/balloon/depth.py @@ -8,7 +8,7 @@ import bpy BALLOON_DEPTH_ATTRIBUTE = "o_balloon_depth" BALLOON_SHAPE_NODE_GROUP_NAME = "O Balloon Shape" BALLOON_SHAPE_NODE_GROUP_VERSION = 16 -BALLOON_SHAPE_VERSION_PROPERTY = "snapform_balloon_shape_version" +BALLOON_SHAPE_VERSION_PROPERTY = "anyimage_balloon_shape_version" def load_balloon_depth_data(path): @@ -216,8 +216,8 @@ def create_balloon_base_plane(context, balloon, vertices, local_plane): controller.empty_display_size = max(float(extent.max()) * 0.15, 0.01) controller.show_in_front = True controller.hide_render = True - controller["snapform_source_type"] = "BALLOON_BASE_PLANE" - controller["snapform_base_plane"] = (slope_y, slope_z, offset) + controller["anyimage_source_type"] = "BALLOON_BASE_PLANE" + controller["anyimage_base_plane"] = (slope_y, slope_z, offset) return controller diff --git a/src/snapform/operators/balloon/geometry.py b/src/anyimage/operators/balloon/geometry.py similarity index 100% rename from src/snapform/operators/balloon/geometry.py rename to src/anyimage/operators/balloon/geometry.py diff --git a/src/snapform/operators/balloon/operator.py b/src/anyimage/operators/balloon/operator.py similarity index 95% rename from src/snapform/operators/balloon/operator.py rename to src/anyimage/operators/balloon/operator.py index 6770b38..d6c94c8 100644 --- a/src/snapform/operators/balloon/operator.py +++ b/src/anyimage/operators/balloon/operator.py @@ -49,9 +49,9 @@ from ..surface import assign_vertex_uv MIN_PATH_DISTANCE = 2.0 -BALLOON_MATERIAL_PROPERTY = "snapform_balloon_material" -BALLOON_SOURCE_IMAGE_PROPERTY = "snapform_source_image" -BALLOON_NORMAL_IMAGE_PROPERTY = "snapform_balloon_normal_image" +BALLOON_MATERIAL_PROPERTY = "anyimage_balloon_material" +BALLOON_SOURCE_IMAGE_PROPERTY = "anyimage_source_image" +BALLOON_NORMAL_IMAGE_PROPERTY = "anyimage_balloon_normal_image" def simplify_screen_path(path): @@ -395,11 +395,11 @@ def extract_balloon_object( balloon = bpy.data.objects.new(balloon_name, mesh) context.collection.objects.link(balloon) balloon.matrix_world = orient_balloon_world_matrix(matrix_world) - balloon["snapform_source_type"] = "BALLOON" - balloon["snapform_balloon_algorithm"] = algorithm - balloon["snapform_source_object"] = source_name - balloon["snapform_inflation"] = inflation - balloon["snapform_resolution"] = point_spacing + balloon["anyimage_source_type"] = "BALLOON" + balloon["anyimage_balloon_algorithm"] = algorithm + balloon["anyimage_source_object"] = source_name + balloon["anyimage_inflation"] = inflation + balloon["anyimage_resolution"] = point_spacing balloon.data.materials.append(material) if depth_data is not None: base_plane = create_balloon_base_plane( @@ -410,8 +410,8 @@ def extract_balloon_object( ) add_balloon_shape_modifier(balloon, thickness, base_plane) if depth_data is not None: - balloon["snapform_balloon_depth_analysis"] = True - balloon["snapform_reference_depth"] = depth_data["reference_depth"] + balloon["anyimage_balloon_depth_analysis"] = True + balloon["anyimage_reference_depth"] = depth_data["reference_depth"] except Exception: if base_plane is not None: bpy.data.objects.remove(base_plane, do_unlink=True) @@ -473,7 +473,7 @@ def drawing_in_region(area_pointer, region_pointer): class ExtractBalloon(bpy.types.Operator): - bl_idname = "snapform.extract_balloon" + bl_idname = "anyimage.extract_balloon" bl_label = "Extract Balloon" bl_description = "Build one closed Balloon mesh from a saved lasso region" bl_options = {"REGISTER", "UNDO"} @@ -536,7 +536,7 @@ class ExtractBalloon(bpy.types.Operator): def invoke(self, context, event): source_object = context.active_object - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings self.mode = settings.balloon_mode self.thickness = settings.balloon_thickness self.resolution = settings.balloon_resolution @@ -622,7 +622,7 @@ class ExtractBalloon(bpy.types.Operator): source_object.data, context.scene, ) - result = bpy.ops.snapform.analyze_balloon( + result = bpy.ops.anyimage.analyze_balloon( input_path=str(source_path), delete_input=delete_input, source_object_name=self.source_object_name, @@ -657,7 +657,7 @@ class ExtractBalloon(bpy.types.Operator): select_result=False, reuse_material=self.reuse_material, ) - balloon["snapform_resolution_m"] = self.resolution + balloon["anyimage_resolution_m"] = self.resolution except (json.JSONDecodeError, RuntimeError, TypeError, ValueError) as error: self.report({"ERROR"}, str(error)) return {"CANCELLED"} @@ -665,7 +665,7 @@ class ExtractBalloon(bpy.types.Operator): class AnalyzeBalloon(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.analyze_balloon" + bl_idname = "anyimage.analyze_balloon" bl_label = "Analyze Balloon" job_type = "analyze-balloon" starting_message = "Starting Balloon AI analysis" @@ -744,11 +744,11 @@ class AnalyzeBalloon(JobOperatorBase, bpy.types.Operator): depth_data=depth_data, normal_path=(result.file("normal") if self.depth_analysis else None), ) - balloon["snapform_resolution_m"] = self.resolution + balloon["anyimage_resolution_m"] = self.resolution if self.contour_analysis: - balloon["snapform_balloon_contour_analysis"] = True + balloon["anyimage_balloon_contour_analysis"] = True if self.depth_analysis: - balloon["snapform_balloon_depth_model"] = self.depth_model + balloon["anyimage_balloon_depth_model"] = self.depth_model push_undo("Extract Balloon") return "AI-analyzed Balloon is ready" @@ -757,7 +757,7 @@ class AnalyzeBalloon(JobOperatorBase, bpy.types.Operator): class ActivateBalloonTool(bpy.types.Operator): - bl_idname = "snapform.activate_balloon_tool" + bl_idname = "anyimage.activate_balloon_tool" bl_label = "Balloon Lasso Tool" bl_description = "Activate the Balloon Lasso tool in the 3D Viewport" bl_options = {"INTERNAL"} @@ -780,7 +780,7 @@ class ActivateBalloonTool(bpy.types.Operator): class BalloonTool(bpy.types.WorkSpaceTool): bl_space_type = "VIEW_3D" bl_context_mode = "OBJECT" - bl_idname = "snapform.balloon_lasso" + bl_idname = "anyimage.balloon_lasso" bl_label = "Balloon Lasso" bl_description = ( "Draw an Image Empty region and extract one independently undoable " @@ -802,11 +802,11 @@ class BalloonTool(bpy.types.WorkSpaceTool): "properties": [ ( "data_path_primary", - "scene.snapform_settings.balloon_thickness", + "scene.anyimage_settings.balloon_thickness", ), ( "zoom_path", - "scene.snapform_settings.balloon_thickness_radial_zoom", + "scene.anyimage_settings.balloon_thickness_radial_zoom", ), ] }, @@ -818,11 +818,11 @@ class BalloonTool(bpy.types.WorkSpaceTool): "properties": [ ( "data_path_primary", - "scene.snapform_settings.balloon_resolution", + "scene.anyimage_settings.balloon_resolution", ), ( "zoom_path", - "scene.snapform_settings.balloon_resolution_radial_zoom", + "scene.anyimage_settings.balloon_resolution_radial_zoom", ), ] }, @@ -830,7 +830,7 @@ class BalloonTool(bpy.types.WorkSpaceTool): ) def draw_settings(context, layout, tool): - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings layout.prop(settings, "balloon_mode", text="") layout.prop(settings, "balloon_thickness") layout.prop(settings, "balloon_resolution", text="Resolution (m)") diff --git a/src/snapform/operators/balloon/poisson.py b/src/anyimage/operators/balloon/poisson.py similarity index 100% rename from src/snapform/operators/balloon/poisson.py rename to src/anyimage/operators/balloon/poisson.py diff --git a/src/snapform/operators/balloon/teddy.py b/src/anyimage/operators/balloon/teddy.py similarity index 100% rename from src/snapform/operators/balloon/teddy.py rename to src/anyimage/operators/balloon/teddy.py diff --git a/src/snapform/operators/common.py b/src/anyimage/operators/common.py similarity index 98% rename from src/snapform/operators/common.py rename to src/anyimage/operators/common.py index 89619f0..0510705 100644 --- a/src/snapform/operators/common.py +++ b/src/anyimage/operators/common.py @@ -46,7 +46,7 @@ def production_device(): def require_environment(): if not runtime.environment_ready(): - raise RuntimeError("Install the SnapForm Environment first") + raise RuntimeError("Install the AnyImage Environment first") def require_model(model_key): diff --git a/src/snapform/operators/debug.py b/src/anyimage/operators/debug.py similarity index 90% rename from src/snapform/operators/debug.py rename to src/anyimage/operators/debug.py index 74537e1..c943f6e 100644 --- a/src/snapform/operators/debug.py +++ b/src/anyimage/operators/debug.py @@ -14,14 +14,14 @@ from .common import ( class DebugDa3(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.debug_da3" + bl_idname = "anyimage.debug_da3" bl_label = "Debug DA3" job_type = "debug-da3" starting_message = "Starting DA3 API inference" def request(self, context): require_environment() - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings model = settings.model require_model(model) return { @@ -43,14 +43,14 @@ class DebugDa3(JobOperatorBase, bpy.types.Operator): class DebugMoge2(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.debug_moge2" + bl_idname = "anyimage.debug_moge2" bl_label = "Debug MoGe-2" job_type = "debug-moge2" starting_message = "Starting MoGe-2 inference" def request(self, context): require_environment() - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings require_model(settings.moge_model) return { **moge2_parameters( @@ -69,14 +69,14 @@ class DebugMoge2(JobOperatorBase, bpy.types.Operator): class DebugBen2(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.debug_ben2" + bl_idname = "anyimage.debug_ben2" bl_label = "Debug BEN2" job_type = "debug-ben2" starting_message = "Starting BEN2 background removal" def request(self, context): require_environment() - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings require_model(BEN2_MODEL_KEY) return { "input": str(background_input_path(settings.background_input_path)), diff --git a/src/snapform/operators/depth_plane/__init__.py b/src/anyimage/operators/depth_plane/__init__.py similarity index 100% rename from src/snapform/operators/depth_plane/__init__.py rename to src/anyimage/operators/depth_plane/__init__.py diff --git a/src/snapform/operators/depth_plane/build.py b/src/anyimage/operators/depth_plane/build.py similarity index 96% rename from src/snapform/operators/depth_plane/build.py rename to src/anyimage/operators/depth_plane/build.py index 103fdfe..e439e5b 100644 --- a/src/snapform/operators/depth_plane/build.py +++ b/src/anyimage/operators/depth_plane/build.py @@ -326,7 +326,7 @@ def build_image_depth_plane( use_cyclic=source_use_cyclic, animate_frame=is_animated_image(source_object.data), ) - plane_object["snapform_frame_count"] = frame_count + plane_object["anyimage_frame_count"] = frame_count return finish_depth_plane( context, source_object, @@ -431,11 +431,11 @@ def build_depth_plane( use_cyclic=source_use_cyclic, animate_frame=is_animated_image(source_object.data), ) - plane_object["snapform_reference_depth"] = reference_depth - plane_object["snapform_camera_plane_width"] = bounds[1] - bounds[0] - plane_object["snapform_camera_plane_height"] = bounds[3] - bounds[2] - plane_object["snapform_depth_scale"] = depth_scale - plane_object["snapform_frame_count"] = frame_count + plane_object["anyimage_reference_depth"] = reference_depth + plane_object["anyimage_camera_plane_width"] = bounds[1] - bounds[0] + plane_object["anyimage_camera_plane_height"] = bounds[3] - bounds[2] + plane_object["anyimage_depth_scale"] = depth_scale + plane_object["anyimage_frame_count"] = frame_count return finish_depth_plane( context, @@ -536,9 +536,9 @@ def build_moge2_depth_plane( use_cyclic=source_use_cyclic, animate_frame=is_animated_image(source_object.data), ) - plane_object["snapform_reference_depth"] = reference_depth - plane_object["snapform_depth_scale"] = depth_scale - plane_object["snapform_frame_count"] = len(depth) + plane_object["anyimage_reference_depth"] = reference_depth + plane_object["anyimage_depth_scale"] = depth_scale + plane_object["anyimage_frame_count"] = len(depth) return finish_depth_plane( context, source_object, diff --git a/src/snapform/operators/depth_plane/data.py b/src/anyimage/operators/depth_plane/data.py similarity index 100% rename from src/snapform/operators/depth_plane/data.py rename to src/anyimage/operators/depth_plane/data.py diff --git a/src/snapform/operators/depth_plane/operator.py b/src/anyimage/operators/depth_plane/operator.py similarity index 95% rename from src/snapform/operators/depth_plane/operator.py rename to src/anyimage/operators/depth_plane/operator.py index b7b6d63..d6352fa 100644 --- a/src/snapform/operators/depth_plane/operator.py +++ b/src/anyimage/operators/depth_plane/operator.py @@ -36,7 +36,7 @@ def image_depth_model_items(owner, context): class ConvertToDepthPlane(bpy.types.Operator): - bl_idname = "snapform.convert_to_depth_plane" + bl_idname = "anyimage.convert_to_depth_plane" bl_label = "Convert to Depth Plane" bl_description = "Convert an image to a displaced depth plane" bl_options = {"REGISTER"} @@ -101,7 +101,7 @@ class ConvertToDepthPlane(bpy.types.Operator): def execute(self, context): source_object = context.object if video_total_frames(source_object.data) > 1: - context.scene.snapform_settings.video_frames = ( + context.scene.anyimage_settings.video_frames = ( default_extract_frames(source_object) ) if self.model == "ORIGINAL": @@ -114,9 +114,9 @@ class ConvertToDepthPlane(bpy.types.Operator): self.report({"ERROR"}, str(error)) return {"CANCELLED"} run_original = ( - bpy.ops.snapform.generate_original_background + bpy.ops.anyimage.generate_original_background if self.remove_background - else bpy.ops.snapform.extract_original_frames + else bpy.ops.anyimage.extract_original_frames ) result = run_original( input_path=str(source_path), @@ -140,7 +140,7 @@ class ConvertToDepthPlane(bpy.types.Operator): except RuntimeError as error: self.report({"ERROR"}, str(error)) return {"CANCELLED"} - result = bpy.ops.snapform.generate_moge2_depth( + result = bpy.ops.anyimage.generate_moge2_depth( input_path=str(source_path), source_object_name=source_object.name, resolution_level=self.resolution_level, @@ -174,7 +174,7 @@ class ConvertToDepthPlane(bpy.types.Operator): self.report({"ERROR"}, str(error)) return {"CANCELLED"} - result = bpy.ops.snapform.generate_da3_depth( + result = bpy.ops.anyimage.generate_da3_depth( input_path=str(source_path), source_object_name=source_object.name, depth_data_name=depth_data_name(source_object), @@ -306,7 +306,7 @@ def build_original_depth_response( push_undo("Convert to Depth Plane") class GenerateDa3Depth(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.generate_da3_depth" + bl_idname = "anyimage.generate_da3_depth" bl_label = "Generate DA3 Depth" job_type = "generate-depth" starting_message = "Starting depth estimation" @@ -326,7 +326,7 @@ class GenerateDa3Depth(JobOperatorBase, bpy.types.Operator): require_model(self.model) if self.remove_background: require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { **da3_parameters( settings, @@ -358,7 +358,7 @@ class GenerateDa3Depth(JobOperatorBase, bpy.types.Operator): class GenerateMoge2Depth(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.generate_moge2_depth" + bl_idname = "anyimage.generate_moge2_depth" bl_label = "Generate MoGe-2 Depth" job_type = "generate-depth" starting_message = "Starting MoGe-2 inference" @@ -377,7 +377,7 @@ class GenerateMoge2Depth(JobOperatorBase, bpy.types.Operator): require_model(self.model) if self.remove_background: require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { **moge2_parameters( settings, @@ -407,7 +407,7 @@ class GenerateMoge2Depth(JobOperatorBase, bpy.types.Operator): class GenerateOriginalBackground(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.generate_original_background" + bl_idname = "anyimage.generate_original_background" bl_label = "Generate Original Background" job_type = "remove-background" starting_message = "Starting background removal" @@ -421,7 +421,7 @@ class GenerateOriginalBackground(JobOperatorBase, bpy.types.Operator): def request(self, context): require_environment() require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { "input": str(background_input_path(self.input_path)), "model": BEN2_MODEL_KEY, @@ -446,7 +446,7 @@ class GenerateOriginalBackground(JobOperatorBase, bpy.types.Operator): class ExtractOriginalFrames(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.extract_original_frames" + bl_idname = "anyimage.extract_original_frames" bl_label = "Extract Original Frames" job_type = "extract-frames" starting_message = "Extracting source frames" @@ -459,7 +459,7 @@ class ExtractOriginalFrames(JobOperatorBase, bpy.types.Operator): def request(self, context): require_environment() - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { "input": str(input_path(self.input_path)), "video_frames": settings.video_frames, diff --git a/src/snapform/operators/image.py b/src/anyimage/operators/image.py similarity index 99% rename from src/snapform/operators/image.py rename to src/anyimage/operators/image.py index 100921e..891345f 100644 --- a/src/snapform/operators/image.py +++ b/src/anyimage/operators/image.py @@ -205,7 +205,7 @@ def draw_process_resolution(layout, owner, image): def save_packed_image(image, scene): - output_path = Path(tempfile.mkdtemp(prefix="snapform-input-")) / "input.png" + output_path = Path(tempfile.mkdtemp(prefix="anyimage-input-")) / "input.png" image_settings = scene.render.image_settings original_file_format = image_settings.file_format try: @@ -261,7 +261,7 @@ def prepare_image_input(image, scene): return source_path, False sequence_frames = collect_sequence_frames(image) if sequence_frames: - temporary_directory = Path(tempfile.mkdtemp(prefix="snapform-input-")) + temporary_directory = Path(tempfile.mkdtemp(prefix="anyimage-input-")) try: for index, frame_path in enumerate(sequence_frames): suffix = frame_path.suffix.lower() or ".jpg" diff --git a/src/snapform/operators/material.py b/src/anyimage/operators/material.py similarity index 99% rename from src/snapform/operators/material.py rename to src/anyimage/operators/material.py index af43f0a..0e9810b 100644 --- a/src/snapform/operators/material.py +++ b/src/anyimage/operators/material.py @@ -10,7 +10,7 @@ ORIGINAL_DISPLACEMENT_MIDLEVEL = 0.0 BUMP_BASE_DISTANCE = 0.001 DEPTH_PLANE_NODE_GROUP_NAME = "O DA3 Depth Plane" MOGE_DEPTH_PLANE_NODE_GROUP_NAME = "O MoGe2 Depth Plane" -NODE_ASSET_NAME = "O_SnapForm.blend" +NODE_ASSET_NAME = "O_AnyImage.blend" MATERIAL_DISPLACEMENT_ATTRIBUTE = "o_material_displacement" BACKGROUND_DEPTH_ATTRIBUTE = "o_background_depth" DEPTH_SCALE_ATTRIBUTE = "o_depth_scale" diff --git a/src/snapform/operators/models.py b/src/anyimage/operators/models.py similarity index 91% rename from src/snapform/operators/models.py rename to src/anyimage/operators/models.py index d0deb10..cb0d889 100644 --- a/src/snapform/operators/models.py +++ b/src/anyimage/operators/models.py @@ -6,7 +6,7 @@ from .common import HIDDEN, require_environment class DownloadModel(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.download_model" + bl_idname = "anyimage.download_model" bl_label = "Download Model" job_type = "download-model" @@ -23,7 +23,7 @@ class DownloadModel(JobOperatorBase, bpy.types.Operator): class DownloadRequiredModels(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.download_required_models" + bl_idname = "anyimage.download_required_models" bl_label = "Download Required Models" job_type = "download-required-models" starting_message = "Starting required model downloads" @@ -36,7 +36,7 @@ class DownloadRequiredModels(JobOperatorBase, bpy.types.Operator): class ClearModels(bpy.types.Operator): - bl_idname = "snapform.clear_models" + bl_idname = "anyimage.clear_models" bl_label = "Clear Models" def execute(self, _context): diff --git a/src/snapform/operators/surface.py b/src/anyimage/operators/surface.py similarity index 97% rename from src/snapform/operators/surface.py rename to src/anyimage/operators/surface.py index af4ddff..1b1914e 100644 --- a/src/snapform/operators/surface.py +++ b/src/anyimage/operators/surface.py @@ -50,7 +50,7 @@ OPTIONAL_FACE_ATTRIBUTES = { } NODE_GROUP_NAME = "O DA3 Surface" MOGE_NODE_GROUP_NAME = "O MoGe2 Surface" -NODE_ASSET_NAME = "O_SnapForm.blend" +NODE_ASSET_NAME = "O_AnyImage.blend" def image_surface_model_items(owner, context): @@ -212,7 +212,7 @@ def assign_mesh_attribute(mesh, name, data_type, domain, values): attribute.data.foreach_set("value", array.reshape(-1)) -def assign_snapform_attributes(mesh, attributes, moge2=False): +def assign_anyimage_attributes(mesh, attributes, moge2=False): for name, (data_type, key) in POINT_ATTRIBUTES.items(): assign_mesh_attribute( mesh, @@ -446,7 +446,7 @@ def build_image_mesh( mesh = bpy.data.meshes.new(source_name) mesh.from_pydata(vertices.tolist(), [], faces.tolist()) assign_vertex_uv(mesh, uv) - assign_snapform_attributes(mesh, attributes, moge2=moge2) + assign_anyimage_attributes(mesh, attributes, moge2=moge2) mesh.update() for polygon in mesh.polygons: polygon.use_smooth = True @@ -476,8 +476,8 @@ def build_image_mesh( scene=context.scene, ) mesh.materials.append(material) - mesh_object["snapform_reference_depth"] = reference_depth - mesh_object["snapform_source_type"] = "IMAGE_MESH" + mesh_object["anyimage_reference_depth"] = reference_depth + mesh_object["anyimage_source_type"] = "IMAGE_MESH" add_geometry_nodes_processing( mesh_object, vertices, @@ -505,7 +505,7 @@ def build_image_mesh( class ConvertToSurface(bpy.types.Operator): - bl_idname = "snapform.convert_to_surface" + bl_idname = "anyimage.convert_to_surface" bl_label = "Convert to Surface" bl_description = "Convert an Image Empty into a perspective textured surface" bl_options = {"REGISTER"} @@ -604,12 +604,12 @@ class ConvertToSurface(bpy.types.Operator): "remove_background": self.remove_background, } if self.model.startswith("MOGE2_"): - result = bpy.ops.snapform.generate_moge2_surface( + result = bpy.ops.anyimage.generate_moge2_surface( **common, resolution_level=self.resolution_level, ) else: - result = bpy.ops.snapform.generate_da3_surface( + result = bpy.ops.anyimage.generate_da3_surface( **common, process_res=process_res, ) @@ -662,7 +662,7 @@ def build_surface_response( class GenerateDa3Surface(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.generate_da3_surface" + bl_idname = "anyimage.generate_da3_surface" bl_label = "Generate DA3 Surface" job_type = "generate-surface" starting_message = "Starting perspective surface generation" @@ -682,7 +682,7 @@ class GenerateDa3Surface(JobOperatorBase, bpy.types.Operator): require_model(self.model) if self.remove_background: require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { **da3_parameters( settings, @@ -713,7 +713,7 @@ class GenerateDa3Surface(JobOperatorBase, bpy.types.Operator): class GenerateMoge2Surface(JobOperatorBase, bpy.types.Operator): - bl_idname = "snapform.generate_moge2_surface" + bl_idname = "anyimage.generate_moge2_surface" bl_label = "Generate MoGe-2 Surface" job_type = "generate-surface" starting_message = "Starting MoGe-2 inference" @@ -733,7 +733,7 @@ class GenerateMoge2Surface(JobOperatorBase, bpy.types.Operator): require_model(self.model) if self.remove_background: require_model(BEN2_MODEL_KEY) - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings return { **moge2_parameters( settings, diff --git a/src/snapform/panel.py b/src/anyimage/panel.py similarity index 86% rename from src/snapform/panel.py rename to src/anyimage/panel.py index 9d47afa..b80752c 100644 --- a/src/snapform/panel.py +++ b/src/anyimage/panel.py @@ -5,10 +5,10 @@ from .properties import BEN2_MODEL_KEY, model_catalog, model_ready class ServerPanel(bpy.types.Panel): bl_label = "Job Server" - bl_idname = "SNAPFORM_PT_server" + bl_idname = "ANYIMAGE_PT_server" bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_order = 0 def draw(self, _context): @@ -22,14 +22,14 @@ class ServerPanel(bpy.types.Panel): install_row = layout.row() install_row.enabled = not running install_row.operator( - "snapform.install_environment", + "anyimage.install_environment", text="Install Environment", icon="IMPORT", ) mirror_row = layout.row() mirror_row.enabled = not running mirror_row.operator( - "snapform.install_environment_mirror", + "anyimage.install_environment_mirror", text="Install Environment (Mirror)", icon="IMPORT", ) @@ -58,18 +58,18 @@ class ServerPanel(bpy.types.Panel): if state == "READY": controls = row.row(align=True) controls.operator( - "snapform.restart_server", + "anyimage.restart_server", text="", icon="FILE_REFRESH", ) controls.operator( - "snapform.stop_server", + "anyimage.stop_server", text="", icon="PAUSE", ) elif state == "STOPPED": row.operator( - "snapform.start_server", + "anyimage.start_server", text="Start", icon="PLAY", ) @@ -80,7 +80,7 @@ class ServerPanel(bpy.types.Panel): ) if state == "ERROR": row.operator( - "snapform.start_server", + "anyimage.start_server", text="Start", icon="PLAY", ) @@ -103,7 +103,7 @@ class ServerPanel(bpy.types.Panel): clear = cached_row.row(align=True) clear.enabled = state == "READY" clear.operator( - "snapform.clear_models", + "anyimage.clear_models", text="", icon="TRASH", ) @@ -111,10 +111,10 @@ class ServerPanel(bpy.types.Panel): class ModelsPanel(bpy.types.Panel): bl_label = "Models" - bl_idname = "SNAPFORM_PT_models" + bl_idname = "ANYIMAGE_PT_models" bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_options = {"DEFAULT_CLOSED"} bl_order = 1 @@ -150,7 +150,7 @@ class ModelsPanel(bpy.types.Panel): download_row = row.row(align=True) download_row.enabled = runtime.environment_ready() and not running operator = download_row.operator( - "snapform.download_model", + "anyimage.download_model", text="Download", icon="IMPORT", ) @@ -159,16 +159,16 @@ class ModelsPanel(bpy.types.Panel): class DebugPanel(bpy.types.Panel): bl_label = "Debug" - bl_idname = "SNAPFORM_PT_debug" + bl_idname = "ANYIMAGE_PT_debug" bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_options = {"DEFAULT_CLOSED"} bl_order = 2 def draw(self, context): layout = self.layout - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings layout.prop(settings, "device") @@ -198,17 +198,17 @@ def draw_da3_input_settings(layout, settings, model_property): class Da3OutputDebugPanel(bpy.types.Panel): bl_label = "DA3" - bl_idname = "SNAPFORM_PT_debug_da3_output" + bl_idname = "ANYIMAGE_PT_debug_da3_output" bl_parent_id = DebugPanel.bl_idname bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_options = {"DEFAULT_CLOSED"} bl_order = 1 def draw(self, context): layout = self.layout - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings draw_da3_input_settings(layout, settings, "model") export_row = layout.row() @@ -217,7 +217,7 @@ class Da3OutputDebugPanel(bpy.types.Panel): and model_ready(settings.model) ) export_row.operator( - "snapform.debug_da3", + "anyimage.debug_da3", text="Run DA3 API", icon="EXPORT", ) @@ -225,17 +225,17 @@ class Da3OutputDebugPanel(bpy.types.Panel): class Moge2ApiDebugPanel(bpy.types.Panel): bl_label = "MoGe-2" - bl_idname = "SNAPFORM_PT_debug_moge2_api" + bl_idname = "ANYIMAGE_PT_debug_moge2_api" bl_parent_id = DebugPanel.bl_idname bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_options = {"DEFAULT_CLOSED"} bl_order = 0 def draw(self, context): layout = self.layout - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings layout.prop(settings, "input_path") layout.prop(settings, "moge_model") layout.prop(settings, "moge_resolution_level") @@ -245,7 +245,7 @@ class Moge2ApiDebugPanel(bpy.types.Panel): and model_ready(settings.moge_model) ) run_row.operator( - "snapform.debug_moge2", + "anyimage.debug_moge2", text="Run MoGe-2 API", icon="EXPORT", ) @@ -253,17 +253,17 @@ class Moge2ApiDebugPanel(bpy.types.Panel): class Ben2RemovalDebugPanel(bpy.types.Panel): bl_label = "BEN2" - bl_idname = "SNAPFORM_PT_debug_ben2_removal" + bl_idname = "ANYIMAGE_PT_debug_ben2_removal" bl_parent_id = DebugPanel.bl_idname bl_space_type = "VIEW_3D" bl_region_type = "UI" - bl_category = "SnapForm" + bl_category = "AnyImage" bl_options = {"DEFAULT_CLOSED"} bl_order = 2 def draw(self, context): layout = self.layout - settings = context.scene.snapform_settings + settings = context.scene.anyimage_settings layout.prop(settings, "background_input_path") background_row = layout.row() @@ -272,7 +272,7 @@ class Ben2RemovalDebugPanel(bpy.types.Panel): and model_ready(BEN2_MODEL_KEY) ) background_row.operator( - "snapform.debug_ben2", + "anyimage.debug_ben2", text="Remove Background", icon="IMAGE_ALPHA", ) diff --git a/src/snapform/preferences.py b/src/anyimage/preferences.py similarity index 89% rename from src/snapform/preferences.py rename to src/anyimage/preferences.py index 15575b1..941e176 100644 --- a/src/snapform/preferences.py +++ b/src/anyimage/preferences.py @@ -4,7 +4,7 @@ from .runtime import DEFAULT_STORAGE_ROOT, runtime from .properties import device_enum_items -class SnapFormPreferences(bpy.types.AddonPreferences): +class AnyImagePreferences(bpy.types.AddonPreferences): bl_idname = __package__ storage_root: bpy.props.StringProperty( @@ -38,20 +38,20 @@ class SnapFormPreferences(bpy.types.AddonPreferences): install_row = layout.row() install_row.enabled = runtime.active_job is None install_row.operator( - "snapform.install_environment", + "anyimage.install_environment", text="Install Environment", icon="IMPORT", ) mirror_row = layout.row() mirror_row.enabled = runtime.active_job is None mirror_row.operator( - "snapform.install_environment_mirror", + "anyimage.install_environment_mirror", text="Install Environment (Mirror)", icon="IMPORT", ) layout.separator() layout.operator( - "snapform.open_server_log", + "anyimage.open_server_log", text="Open Server Log", icon="TEXT", ) diff --git a/src/snapform/properties.py b/src/anyimage/properties.py similarity index 99% rename from src/snapform/properties.py rename to src/anyimage/properties.py index 7c0c491..bcac99a 100644 --- a/src/snapform/properties.py +++ b/src/anyimage/properties.py @@ -269,7 +269,7 @@ def balloon_radial_zoom_property(scale): ) -class SnapFormSettings(bpy.types.PropertyGroup): +class AnyImageSettings(bpy.types.PropertyGroup): balloon_mode: balloon_mode_property() balloon_thickness: balloon_thickness_property() balloon_resolution: balloon_resolution_property() diff --git a/src/snapform/runtime.py b/src/anyimage/runtime.py similarity index 94% rename from src/snapform/runtime.py rename to src/anyimage/runtime.py index 7815a23..bac1a32 100644 --- a/src/snapform/runtime.py +++ b/src/anyimage/runtime.py @@ -5,7 +5,7 @@ import bpy from blendjob import JobRuntime -DEFAULT_STORAGE_ROOT = Path.home() / ".snapform" +DEFAULT_STORAGE_ROOT = Path.home() / ".anyimage" def configured_storage_root(): @@ -53,7 +53,7 @@ runtime = JobRuntime( storage_root=configured_storage_root, environment=ENVIRONMENT, post_install=post_install, - namespace="snapform", + namespace="anyimage", ) JobOperatorBase = runtime.JobOperatorBase diff --git a/src/snapform/server/__init__.py b/src/anyimage/server/__init__.py similarity index 95% rename from src/snapform/server/__init__.py rename to src/anyimage/server/__init__.py index 9c7970b..4eb10da 100644 --- a/src/snapform/server/__init__.py +++ b/src/anyimage/server/__init__.py @@ -1,4 +1,4 @@ -"""SnapForm Job Server without Blender dependencies.""" +"""AnyImage Job Server without Blender dependencies.""" from blendjob import JobServer @@ -13,7 +13,7 @@ from .jobs.frames import run as _extract_frames from .model_manager import ModelManager, ModelSessionCache -server = JobServer("SnapForm Job Server") +server = JobServer("AnyImage Job Server") @server.resource("model_manager") diff --git a/src/snapform/server/geometry/__init__.py b/src/anyimage/server/geometry/__init__.py similarity index 100% rename from src/snapform/server/geometry/__init__.py rename to src/anyimage/server/geometry/__init__.py diff --git a/src/snapform/server/geometry/grid_mesh.py b/src/anyimage/server/geometry/grid_mesh.py similarity index 100% rename from src/snapform/server/geometry/grid_mesh.py rename to src/anyimage/server/geometry/grid_mesh.py diff --git a/src/snapform/server/geometry/projection.py b/src/anyimage/server/geometry/projection.py similarity index 100% rename from src/snapform/server/geometry/projection.py rename to src/anyimage/server/geometry/projection.py diff --git a/src/snapform/server/geometry/surface.py b/src/anyimage/server/geometry/surface.py similarity index 100% rename from src/snapform/server/geometry/surface.py rename to src/anyimage/server/geometry/surface.py diff --git a/src/snapform/server/jobs/__init__.py b/src/anyimage/server/jobs/__init__.py similarity index 100% rename from src/snapform/server/jobs/__init__.py rename to src/anyimage/server/jobs/__init__.py diff --git a/src/snapform/server/jobs/background.py b/src/anyimage/server/jobs/background.py similarity index 100% rename from src/snapform/server/jobs/background.py rename to src/anyimage/server/jobs/background.py diff --git a/src/snapform/server/jobs/balloon.py b/src/anyimage/server/jobs/balloon.py similarity index 100% rename from src/snapform/server/jobs/balloon.py rename to src/anyimage/server/jobs/balloon.py diff --git a/src/snapform/server/jobs/common.py b/src/anyimage/server/jobs/common.py similarity index 100% rename from src/snapform/server/jobs/common.py rename to src/anyimage/server/jobs/common.py diff --git a/src/snapform/server/jobs/debug_ben2.py b/src/anyimage/server/jobs/debug_ben2.py similarity index 100% rename from src/snapform/server/jobs/debug_ben2.py rename to src/anyimage/server/jobs/debug_ben2.py diff --git a/src/snapform/server/jobs/debug_da3.py b/src/anyimage/server/jobs/debug_da3.py similarity index 100% rename from src/snapform/server/jobs/debug_da3.py rename to src/anyimage/server/jobs/debug_da3.py diff --git a/src/snapform/server/jobs/debug_moge2.py b/src/anyimage/server/jobs/debug_moge2.py similarity index 100% rename from src/snapform/server/jobs/debug_moge2.py rename to src/anyimage/server/jobs/debug_moge2.py diff --git a/src/snapform/server/jobs/depth.py b/src/anyimage/server/jobs/depth.py similarity index 100% rename from src/snapform/server/jobs/depth.py rename to src/anyimage/server/jobs/depth.py diff --git a/src/snapform/server/jobs/foreground.py b/src/anyimage/server/jobs/foreground.py similarity index 100% rename from src/snapform/server/jobs/foreground.py rename to src/anyimage/server/jobs/foreground.py diff --git a/src/snapform/server/jobs/frames.py b/src/anyimage/server/jobs/frames.py similarity index 100% rename from src/snapform/server/jobs/frames.py rename to src/anyimage/server/jobs/frames.py diff --git a/src/snapform/server/jobs/surface.py b/src/anyimage/server/jobs/surface.py similarity index 100% rename from src/snapform/server/jobs/surface.py rename to src/anyimage/server/jobs/surface.py diff --git a/src/snapform/server/media/__init__.py b/src/anyimage/server/media/__init__.py similarity index 100% rename from src/snapform/server/media/__init__.py rename to src/anyimage/server/media/__init__.py diff --git a/src/snapform/server/media/input.py b/src/anyimage/server/media/input.py similarity index 98% rename from src/snapform/server/media/input.py rename to src/anyimage/server/media/input.py index 5a25f1c..b5df2ce 100644 --- a/src/snapform/server/media/input.py +++ b/src/anyimage/server/media/input.py @@ -101,7 +101,7 @@ def prepare_input( import av temporary_directory = Path( - tempfile.mkdtemp(prefix="snapform-video-", dir=temporary_root) + tempfile.mkdtemp(prefix="anyimage-video-", dir=temporary_root) ) try: images = extract_video_frames( diff --git a/src/snapform/server/model_catalog.py b/src/anyimage/server/model_catalog.py similarity index 100% rename from src/snapform/server/model_catalog.py rename to src/anyimage/server/model_catalog.py diff --git a/src/snapform/server/model_download.py b/src/anyimage/server/model_download.py similarity index 98% rename from src/snapform/server/model_download.py rename to src/anyimage/server/model_download.py index 301d674..fcb40d8 100644 --- a/src/snapform/server/model_download.py +++ b/src/anyimage/server/model_download.py @@ -116,7 +116,7 @@ def create_download_progress_class( description = str(kwargs.get("desc", "")) # huggingface_hub 1.x 的字节进度条描述是 "Downloading (incomplete total...)", # 用前缀匹配而非精确匹配,否则真实下载进度会被忽略。 - self.snapform_reports_progress = ( + self.anyimage_reports_progress = ( description.startswith("Downloading") or description.startswith("Fetching ") ) @@ -124,13 +124,13 @@ def create_download_progress_class( def update(self, amount=1): result = super().update(amount) - if self.snapform_reports_progress: + if self.anyimage_reports_progress: reporter.report(self.n, self.total, self._download_rate()) return result def refresh(self, *args, **kwargs): result = super().refresh(*args, **kwargs) - if self.snapform_reports_progress: + if self.anyimage_reports_progress: reporter.report(self.n, self.total, self._download_rate()) return result @@ -295,7 +295,7 @@ def _download_file_from_url( cancel_check=None, ): """Download and verify one model file atomically from a direct URL.""" - request = Request(url, headers={"User-Agent": "SnapForm"}) + request = Request(url, headers={"User-Agent": "AnyImage"}) opener = _download_opener.open if request.type == "https" else urlopen last_error = None for _attempt in range(retries): diff --git a/src/snapform/server/model_manager.py b/src/anyimage/server/model_manager.py similarity index 100% rename from src/snapform/server/model_manager.py rename to src/anyimage/server/model_manager.py diff --git a/src/snapform/server/models/__init__.py b/src/anyimage/server/models/__init__.py similarity index 100% rename from src/snapform/server/models/__init__.py rename to src/anyimage/server/models/__init__.py diff --git a/src/snapform/server/models/ben2.py b/src/anyimage/server/models/ben2.py similarity index 100% rename from src/snapform/server/models/ben2.py rename to src/anyimage/server/models/ben2.py diff --git a/src/snapform/server/models/da3.py b/src/anyimage/server/models/da3.py similarity index 97% rename from src/snapform/server/models/da3.py rename to src/anyimage/server/models/da3.py index c1c7c47..0234e26 100644 --- a/src/snapform/server/models/da3.py +++ b/src/anyimage/server/models/da3.py @@ -53,7 +53,7 @@ def infer( if provider_label(model) == "DirectML": raise RuntimeError( "DA3 inference failed on DirectML. Switch the device to " - "CPU in SnapForm Preferences and retry. " + "CPU in AnyImage Preferences and retry. " f"Original error: {error}" ) from error raise diff --git a/src/snapform/server/models/moge2.py b/src/anyimage/server/models/moge2.py similarity index 100% rename from src/snapform/server/models/moge2.py rename to src/anyimage/server/models/moge2.py diff --git a/src/snapform/server/models/onnx_ben2.py b/src/anyimage/server/models/onnx_ben2.py similarity index 100% rename from src/snapform/server/models/onnx_ben2.py rename to src/anyimage/server/models/onnx_ben2.py diff --git a/src/snapform/server/models/onnx_da3.py b/src/anyimage/server/models/onnx_da3.py similarity index 100% rename from src/snapform/server/models/onnx_da3.py rename to src/anyimage/server/models/onnx_da3.py diff --git a/src/snapform/server/models/onnx_moge2.py b/src/anyimage/server/models/onnx_moge2.py similarity index 100% rename from src/snapform/server/models/onnx_moge2.py rename to src/anyimage/server/models/onnx_moge2.py diff --git a/src/snapform/server/models/onnx_runtime.py b/src/anyimage/server/models/onnx_runtime.py similarity index 100% rename from src/snapform/server/models/onnx_runtime.py rename to src/anyimage/server/models/onnx_runtime.py diff --git a/src/snapform/server/outputs/__init__.py b/src/anyimage/server/outputs/__init__.py similarity index 100% rename from src/snapform/server/outputs/__init__.py rename to src/anyimage/server/outputs/__init__.py diff --git a/src/snapform/server/outputs/debug_da3.py b/src/anyimage/server/outputs/debug_da3.py similarity index 100% rename from src/snapform/server/outputs/debug_da3.py rename to src/anyimage/server/outputs/debug_da3.py diff --git a/src/snapform/server/outputs/debug_moge2.py b/src/anyimage/server/outputs/debug_moge2.py similarity index 100% rename from src/snapform/server/outputs/debug_moge2.py rename to src/anyimage/server/outputs/debug_moge2.py diff --git a/src/snapform/server/outputs/depth.py b/src/anyimage/server/outputs/depth.py similarity index 100% rename from src/snapform/server/outputs/depth.py rename to src/anyimage/server/outputs/depth.py diff --git a/src/snapform/server/outputs/surface.py b/src/anyimage/server/outputs/surface.py similarity index 100% rename from src/snapform/server/outputs/surface.py rename to src/anyimage/server/outputs/surface.py diff --git a/sync_models.py b/sync_models.py index e39a928..d9d1aff 100644 --- a/sync_models.py +++ b/sync_models.py @@ -1,4 +1,4 @@ -"""Prepare SnapForm ONNX models and sync them to OmooLab R2.""" +"""Prepare AnyImage ONNX models and sync them to OmooLab R2.""" import argparse import hashlib @@ -114,7 +114,7 @@ def download_once(model, url): destination.parent.mkdir(parents=True, exist_ok=True) temporary = destination.with_suffix(".onnx.part") temporary.unlink(missing_ok=True) - request = Request(url, headers={"User-Agent": "SnapForm model sync"}) + request = Request(url, headers={"User-Agent": "AnyImage model sync"}) print(f"Download: {url}") downloaded = 0 digest = hashlib.sha256() diff --git a/tests/test_addon.py b/tests/test_addon.py index aed0861..d18ae62 100644 --- a/tests/test_addon.py +++ b/tests/test_addon.py @@ -19,7 +19,7 @@ class AddonTest(unittest.TestCase): cls.remove_modules() def append_status_bar(draw): - draw._owner = "snapform" + draw._owner = "anyimage" cls.status_bar_draws.append(draw) fake_bpy = ModuleType("bpy") @@ -79,28 +79,28 @@ class AddonTest(unittest.TestCase): sys.modules["bpy"] = fake_bpy sys.path.insert(0, str(SOURCE_ROOT)) cls.paths_before_import = tuple(sys.path) - cls.addon = importlib.import_module("snapform") - cls.job_runtime = importlib.import_module("snapform.runtime") - cls.model_operators = importlib.import_module("snapform.operators.models") - cls.image_depth = importlib.import_module("snapform.operators.material") - cls.image_data = importlib.import_module("snapform.operators.image") + cls.addon = importlib.import_module("anyimage") + cls.job_runtime = importlib.import_module("anyimage.runtime") + cls.model_operators = importlib.import_module("anyimage.operators.models") + cls.image_depth = importlib.import_module("anyimage.operators.material") + cls.image_data = importlib.import_module("anyimage.operators.image") cls.depth_operator = importlib.import_module( - "snapform.operators.depth_plane.operator" + "anyimage.operators.depth_plane.operator" ) cls.depth_build = importlib.import_module( - "snapform.operators.depth_plane.build" + "anyimage.operators.depth_plane.build" ) - cls.image_background = importlib.import_module("snapform.operators.background") - cls.image_mesh = importlib.import_module("snapform.operators.surface") - cls.balloon = importlib.import_module("snapform.operators.balloon.operator") + cls.image_background = importlib.import_module("anyimage.operators.background") + cls.image_mesh = importlib.import_module("anyimage.operators.surface") + cls.balloon = importlib.import_module("anyimage.operators.balloon.operator") cls.balloon_geometry = importlib.import_module( - "snapform.operators.balloon.geometry" + "anyimage.operators.balloon.geometry" ) - cls.balloon_depth = importlib.import_module("snapform.operators.balloon.depth") + cls.balloon_depth = importlib.import_module("anyimage.operators.balloon.depth") cls.balloon_poisson = importlib.import_module( - "snapform.operators.balloon.poisson" + "anyimage.operators.balloon.poisson" ) - cls.balloon_teddy = importlib.import_module("snapform.operators.balloon.teddy") + cls.balloon_teddy = importlib.import_module("anyimage.operators.balloon.teddy") cls.paths_after_import = tuple(sys.path) cls.fake_bpy = fake_bpy @@ -113,7 +113,7 @@ class AddonTest(unittest.TestCase): @staticmethod def remove_modules(): for module_name in tuple(sys.modules): - if module_name == "snapform" or module_name.startswith("snapform."): + if module_name == "anyimage" or module_name.startswith("anyimage."): sys.modules.pop(module_name) def setUp(self): @@ -122,7 +122,7 @@ class AddonTest(unittest.TestCase): device="CUDA", ) self.fake_bpy.context.preferences.addons = { - "snapform": SimpleNamespace(preferences=preferences) + "anyimage": SimpleNamespace(preferences=preferences) } def tearDown(self): @@ -135,8 +135,8 @@ class AddonTest(unittest.TestCase): self.fake_bpy.data = SimpleNamespace( objects=SimpleNamespace(get=lambda _name: None), ) - if hasattr(self.fake_bpy.types.Scene, "snapform_settings"): - del self.fake_bpy.types.Scene.snapform_settings + if hasattr(self.fake_bpy.types.Scene, "anyimage_settings"): + del self.fake_bpy.types.Scene.anyimage_settings def test_runtime_and_operator_support_modules_have_explicit_boundaries(self): for name in ( @@ -146,13 +146,13 @@ class AddonTest(unittest.TestCase): "models.py", "status_bar.py", ): - self.assertFalse((SOURCE_ROOT / "snapform" / name).exists(), name) - self.assertTrue((SOURCE_ROOT / "snapform" / "runtime.py").is_file()) - self.assertFalse((SOURCE_ROOT / "snapform" / "job_runtime.py").exists()) - self.assertFalse((SOURCE_ROOT / "snapform" / "client").exists()) - self.assertFalse((SOURCE_ROOT / "snapform" / "ui").exists()) - self.assertFalse((SOURCE_ROOT / "snapform" / "operators.py").exists()) - self.assertFalse((SOURCE_ROOT / "snapform" / "blender").exists()) + self.assertFalse((SOURCE_ROOT / "anyimage" / name).exists(), name) + self.assertTrue((SOURCE_ROOT / "anyimage" / "runtime.py").is_file()) + self.assertFalse((SOURCE_ROOT / "anyimage" / "job_runtime.py").exists()) + self.assertFalse((SOURCE_ROOT / "anyimage" / "client").exists()) + self.assertFalse((SOURCE_ROOT / "anyimage" / "ui").exists()) + self.assertFalse((SOURCE_ROOT / "anyimage" / "operators.py").exists()) + self.assertFalse((SOURCE_ROOT / "anyimage" / "blender").exists()) def test_mps_requires_m4_or_newer(self): properties = self.addon.properties @@ -205,7 +205,7 @@ class AddonTest(unittest.TestCase): self.assertEqual(self.paths_after_import, self.paths_before_import) self.assertFalse( any( - name == "snapform.server" or name.startswith("snapform.server.") + name == "anyimage.server" or name.startswith("anyimage.server.") for name in sys.modules ) ) @@ -217,7 +217,7 @@ class AddonTest(unittest.TestCase): def test_operator_modules_use_plain_properties(self): operators = self.addon.operators for name in ( - "SnapFormJobMixin", + "AnyImageJobMixin", "ImageInputJobOperator", "GeometryImageJobOperator", "Da3ImageJobOperator", @@ -227,11 +227,11 @@ class AddonTest(unittest.TestCase): self.assertFalse(hasattr(operators, name), name) for operator in operators.CLASSES: for name in getattr(operator, "__annotations__", {}): - self.assertFalse(name.startswith("snapform_"), (operator, name)) + self.assertFalse(name.startswith("anyimage_"), (operator, name)) def test_concrete_job_operator_is_the_blender_operator(self): operator = self.addon.operators.GenerateMoge2Depth - self.assertEqual(operator.bl_idname, "snapform.generate_moge2_depth") + self.assertEqual(operator.bl_idname, "anyimage.generate_moge2_depth") self.assertIn(self.job_runtime.JobOperatorBase, operator.__mro__) self.assertIn(self.fake_bpy.types.Operator, operator.__mro__) @@ -364,7 +364,7 @@ class AddonTest(unittest.TestCase): ) self.assertTrue(callable(runtime.post_install)) - def test_snapform_post_install_is_ordinary_code_using_runtime_request(self): + def test_anyimage_post_install_is_ordinary_code_using_runtime_request(self): calls = [] fake_runtime = SimpleNamespace( request=lambda job_type, parameters: calls.append((job_type, parameters)) @@ -378,7 +378,7 @@ class AddonTest(unittest.TestCase): ], ) - def test_snapform_post_install_names_each_failed_model(self): + def test_anyimage_post_install_names_each_failed_model(self): calls = [] def request(_job_type, parameters): @@ -476,7 +476,7 @@ class AddonTest(unittest.TestCase): self.assertNotIn("stages", controller.post_status) def test_conversion_model_lists_default_to_moge2_vits(self): - properties = importlib.import_module("snapform.properties") + properties = importlib.import_module("anyimage.properties") catalog = ( { "key": "SMALL", @@ -534,7 +534,7 @@ class AddonTest(unittest.TestCase): def separator(self): calls.append(("separator", self.enabled)) - menu = self.addon.SnapFormImageMenu() + menu = self.addon.AnyImageImageMenu() menu.layout = Layout() with ( patch.object( @@ -543,7 +543,7 @@ class AddonTest(unittest.TestCase): return_value=True, ), patch( - "snapform.properties.required_models_ready", + "anyimage.properties.required_models_ready", return_value=False, ), ): @@ -551,15 +551,15 @@ class AddonTest(unittest.TestCase): self.assertEqual( calls[0], - ("snapform.activate_balloon_tool", True), + ("anyimage.activate_balloon_tool", True), ) self.assertIn( - ("snapform.download_required_models", True), + ("anyimage.download_required_models", True), calls, ) - self.assertIn(("snapform.convert_to_depth_plane", False), calls) - self.assertIn(("snapform.convert_to_surface", False), calls) - self.assertIn(("snapform.remove_image_background", False), calls) + self.assertIn(("anyimage.convert_to_depth_plane", False), calls) + self.assertIn(("anyimage.convert_to_surface", False), calls) + self.assertIn(("anyimage.remove_image_background", False), calls) def test_image_menu_keeps_disabled_features_when_environment_is_missing(self): calls = [] @@ -581,7 +581,7 @@ class AddonTest(unittest.TestCase): def separator(self): calls.append(("separator", self.enabled)) - menu = self.addon.SnapFormImageMenu() + menu = self.addon.AnyImageImageMenu() menu.layout = Layout() with ( patch.object( @@ -590,7 +590,7 @@ class AddonTest(unittest.TestCase): return_value=False, ), patch( - "snapform.properties.required_models_ready", + "anyimage.properties.required_models_ready", return_value=False, ), ): @@ -598,14 +598,14 @@ class AddonTest(unittest.TestCase): self.assertEqual( calls[0], - ("snapform.activate_balloon_tool", True), + ("anyimage.activate_balloon_tool", True), ) - self.assertIn(("snapform.install_environment", True), calls) - self.assertIn(("snapform.install_environment_mirror", True), calls) - self.assertNotIn(("snapform.download_required_models", True), calls) - self.assertIn(("snapform.convert_to_depth_plane", False), calls) - self.assertIn(("snapform.convert_to_surface", False), calls) - self.assertIn(("snapform.remove_image_background", False), calls) + self.assertIn(("anyimage.install_environment", True), calls) + self.assertIn(("anyimage.install_environment_mirror", True), calls) + self.assertNotIn(("anyimage.download_required_models", True), calls) + self.assertIn(("anyimage.convert_to_depth_plane", False), calls) + self.assertIn(("anyimage.convert_to_surface", False), calls) + self.assertIn(("anyimage.remove_image_background", False), calls) def test_balloon_contour_is_smooth_and_evenly_resampled(self): import numpy as np @@ -892,7 +892,7 @@ class AddonTest(unittest.TestCase): self.assertIn("contour_analysis", operator.__annotations__) self.assertIn("depth_analysis", operator.__annotations__) self.assertIn("depth_model", operator.__annotations__) - settings = self.addon.properties.SnapFormSettings.__annotations__ + settings = self.addon.properties.AnyImageSettings.__annotations__ for name in ( "balloon_contour_analysis", "balloon_depth_analysis", @@ -908,7 +908,7 @@ class AddonTest(unittest.TestCase): request_source = inspect.getsource(self.balloon.AnalyzeBalloon.request) response_source = inspect.getsource(self.balloon.AnalyzeBalloon.response) tool_source = inspect.getsource(self.balloon.BalloonTool.draw_settings) - self.assertIn("bpy.ops.snapform.analyze_balloon", execute_source) + self.assertIn("bpy.ops.anyimage.analyze_balloon", execute_source) self.assertIn("prepare_image_input(", execute_source) self.assertIn( "settings.balloon_contour_analysis", @@ -1103,7 +1103,7 @@ class AddonTest(unittest.TestCase): self.assertIn("resolution", operator.__annotations__) self.assertIn("reuse_material", operator.__annotations__) self.assertIn("source_matrix_data", operator.__annotations__) - settings = self.addon.properties.SnapFormSettings.__annotations__ + settings = self.addon.properties.AnyImageSettings.__annotations__ self.assertIn("balloon_mode", settings) self.assertIn("balloon_thickness", settings) self.assertIn("balloon_resolution", settings) @@ -1150,7 +1150,7 @@ class AddonTest(unittest.TestCase): self.assertIn("return self.execute(context)", modal_source) self.assertIn('return {"RUNNING_MODAL"}', modal_source) self.assertIn('return {"PASS_THROUGH"}', modal_source) - self.assertNotIn("bpy.ops.snapform.extract_balloon", modal_source) + self.assertNotIn("bpy.ops.anyimage.extract_balloon", modal_source) tool = self.balloon.BalloonTool self.assertEqual(tool.bl_space_type, "VIEW_3D") @@ -1169,11 +1169,11 @@ class AddonTest(unittest.TestCase): [ ( "data_path_primary", - "scene.snapform_settings.balloon_thickness", + "scene.anyimage_settings.balloon_thickness", ), ( "zoom_path", - "scene.snapform_settings.balloon_thickness_radial_zoom", + "scene.anyimage_settings.balloon_thickness_radial_zoom", ), ], ) @@ -1182,11 +1182,11 @@ class AddonTest(unittest.TestCase): [ ( "data_path_primary", - "scene.snapform_settings.balloon_resolution", + "scene.anyimage_settings.balloon_resolution", ), ( "zoom_path", - "scene.snapform_settings.balloon_resolution_radial_zoom", + "scene.anyimage_settings.balloon_resolution_radial_zoom", ), ], ) @@ -1281,20 +1281,20 @@ class AddonTest(unittest.TestCase): ) marked = MarkedMaterial( "unrelated-name", - snapform_balloon_material=True, - snapform_source_image=color_image, + anyimage_balloon_material=True, + anyimage_source_image=color_image, ) marked_other = MarkedMaterial( "cow", - snapform_balloon_material=True, - snapform_source_image=other_image, + anyimage_balloon_material=True, + anyimage_source_image=other_image, ) normal_image = SimpleNamespace(name="cow.normal") marked_normal = MarkedMaterial( "depth-material", - snapform_balloon_material=True, - snapform_source_image=color_image, - snapform_balloon_normal_image=normal_image, + anyimage_balloon_material=True, + anyimage_source_image=color_image, + anyimage_balloon_normal_image=normal_image, ) wrong_group = SimpleNamespace( name="cow", @@ -1393,7 +1393,7 @@ class AddonTest(unittest.TestCase): return_value=False, ), patch( - "snapform.properties.required_models_ready", + "anyimage.properties.required_models_ready", return_value=models_ready, ), ): @@ -1414,7 +1414,7 @@ class AddonTest(unittest.TestCase): self.assertEqual(operator.poll(context), expected) def test_ui_reads_required_model_files_without_starting_server(self): - properties = importlib.import_module("snapform.properties") + properties = importlib.import_module("anyimage.properties") with tempfile.TemporaryDirectory() as directory: root = Path(directory) moge = root / "models" / "moge-2-vits-normal-onnx" @@ -1516,7 +1516,7 @@ class AddonTest(unittest.TestCase): ], ) self.assertEqual(len(self.status_bar_draws), 1) - self.assertEqual(self.status_bar_draws[0]._owner, "snapform") + self.assertEqual(self.status_bar_draws[0]._owner, "anyimage") self.addon.unregister() self.assertEqual(self.registered, []) @@ -1545,7 +1545,7 @@ class AddonTest(unittest.TestCase): self.assertEqual(calls[0][1]["factor"], 0.4) self.assertEqual(calls[0][1]["text"], "Working") - self.assertEqual(calls[1], ("operator", "snapform.cancel_job")) + self.assertEqual(calls[1], ("operator", "anyimage.cancel_job")) def test_moge_depth_request_is_written_on_the_operator(self): operator = self.addon.operators.GenerateMoge2Depth() @@ -1555,7 +1555,7 @@ class AddonTest(unittest.TestCase): operator.resolution_level = 6 operator.remove_background = False settings = SimpleNamespace(video_frames=12) - context = SimpleNamespace(scene=SimpleNamespace(snapform_settings=settings)) + context = SimpleNamespace(scene=SimpleNamespace(anyimage_settings=settings)) with ( patch.object(self.depth_operator, "require_environment"), @@ -1603,11 +1603,11 @@ class AddonTest(unittest.TestCase): settings = SimpleNamespace(video_frames=1) context = SimpleNamespace( object=source_object, - scene=SimpleNamespace(snapform_settings=settings), + scene=SimpleNamespace(anyimage_settings=settings), ) calls = [] self.fake_bpy.ops = SimpleNamespace( - snapform=SimpleNamespace( + anyimage=SimpleNamespace( generate_moge2_depth=lambda **options: ( calls.append(options) or {"RUNNING_MODAL"} ) @@ -1623,7 +1623,7 @@ class AddonTest(unittest.TestCase): self.assertEqual(calls[0]["resolution_level"], 7) self.assertEqual(calls[0]["source_object_name"], "Reference") - self.assertFalse(any(key.startswith("snapform_") for key in calls[0])) + self.assertFalse(any(key.startswith("anyimage_") for key in calls[0])) if __name__ == "__main__": diff --git a/tests/test_ben2_onnx.py b/tests/test_ben2_onnx.py index 76d46c2..621d3a4 100644 --- a/tests/test_ben2_onnx.py +++ b/tests/test_ben2_onnx.py @@ -10,7 +10,7 @@ from PIL import Image SOURCE_DIR = ( Path(__file__).resolve().parents[1] / "src" - / "snapform" + / "anyimage" / "server" / "models" ) diff --git a/tests/test_da3_onnx.py b/tests/test_da3_onnx.py index a67d756..885487b 100644 --- a/tests/test_da3_onnx.py +++ b/tests/test_da3_onnx.py @@ -11,7 +11,7 @@ from PIL import Image SOURCE_DIR = ( Path(__file__).resolve().parents[1] / "src" - / "snapform" + / "anyimage" / "server" / "models" ) diff --git a/tests/test_download_progress.py b/tests/test_download_progress.py index fe3a7d0..b947823 100644 --- a/tests/test_download_progress.py +++ b/tests/test_download_progress.py @@ -10,7 +10,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] def load_download_module(): - addon_directory = PROJECT_ROOT / "src" / "snapform" + addon_directory = PROJECT_ROOT / "src" / "anyimage" sys.path.insert(0, str(addon_directory)) try: return __import__( diff --git a/tests/test_image_depth.py b/tests/test_image_depth.py index e924108..e547714 100644 --- a/tests/test_image_depth.py +++ b/tests/test_image_depth.py @@ -27,28 +27,28 @@ def load_image_depth(): module_paths = ( ( - "snapform.operators.image", - PROJECT_ROOT / "src" / "snapform" / "operators" / "image.py", + "anyimage.operators.image", + PROJECT_ROOT / "src" / "anyimage" / "operators" / "image.py", ), ( - "snapform.operators.material", - PROJECT_ROOT / "src" / "snapform" / "operators" / "material.py", + "anyimage.operators.material", + PROJECT_ROOT / "src" / "anyimage" / "operators" / "material.py", ), ( - "snapform.operators.depth_plane.data", - PROJECT_ROOT / "src" / "snapform" / "operators" / "depth_plane" / "data.py", + "anyimage.operators.depth_plane.data", + PROJECT_ROOT / "src" / "anyimage" / "operators" / "depth_plane" / "data.py", ), ( - "snapform.operators.depth_plane.build", - PROJECT_ROOT / "src" / "snapform" / "operators" / "depth_plane" / "build.py", + "anyimage.operators.depth_plane.build", + PROJECT_ROOT / "src" / "anyimage" / "operators" / "depth_plane" / "build.py", ), ) packages = { name: ModuleType(name) for name in ( - "snapform", - "snapform.operators", - "snapform.operators.depth_plane", + "anyimage", + "anyimage.operators", + "anyimage.operators.depth_plane", ) } for package in packages.values(): @@ -81,7 +81,7 @@ class ImageDepthTest(unittest.TestCase): def test_material_asset_path_survives_package_split(self): self.assertEqual( self.image_depth.node_asset_path(), - PROJECT_ROOT / "src" / "snapform" / "assets" / "O_SnapForm.blend", + PROJECT_ROOT / "src" / "anyimage" / "assets" / "O_AnyImage.blend", ) def test_material_color_space_matches_scene_view_transform(self): mappings = { diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 9190cd5..c0fa44f 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -4,7 +4,7 @@ from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] -MANIFEST_PATH = PROJECT_ROOT / "src" / "snapform" / "blender_manifest.toml" +MANIFEST_PATH = PROJECT_ROOT / "src" / "anyimage" / "blender_manifest.toml" class ManifestTest(unittest.TestCase): @@ -14,7 +14,7 @@ class ManifestTest(unittest.TestCase): def test_declares_modern_extension_metadata(self): self.assertEqual(self.manifest["schema_version"], "1.0.0") - self.assertEqual(self.manifest["id"], "snapform") + self.assertEqual(self.manifest["id"], "anyimage") self.assertEqual(self.manifest["type"], "add-on") self.assertNotIn("bl_info", self.manifest) diff --git a/tests/test_models.py b/tests/test_models.py index de314f8..a2b07a7 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -20,12 +20,12 @@ class ModelTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.models = load_module( - "snapform_models", - "src/snapform/model_catalog.py", + "anyimage_models", + "src/anyimage/model_catalog.py", ) cls.server_models = load_module( - "snapform_server_models", - "src/snapform/server/model_catalog.py", + "anyimage_server_models", + "src/anyimage/server/model_catalog.py", ) def test_client_and_server_catalogs_share_storage_contract(self): diff --git a/tests/test_moge_onnx.py b/tests/test_moge_onnx.py index 17aba88..5771697 100644 --- a/tests/test_moge_onnx.py +++ b/tests/test_moge_onnx.py @@ -12,19 +12,19 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] def load_module(): - snapform = ModuleType("snapform") - snapform.__path__ = [str(PROJECT_ROOT / "src" / "snapform")] - server = ModuleType("snapform.server") - server.__path__ = [str(PROJECT_ROOT / "src" / "snapform" / "server")] - models = ModuleType("snapform.server.models") + anyimage = ModuleType("anyimage") + anyimage.__path__ = [str(PROJECT_ROOT / "src" / "anyimage")] + server = ModuleType("anyimage.server") + server.__path__ = [str(PROJECT_ROOT / "src" / "anyimage" / "server")] + models = ModuleType("anyimage.server.models") models.__path__ = [ - str(PROJECT_ROOT / "src" / "snapform" / "server" / "models") + str(PROJECT_ROOT / "src" / "anyimage" / "server" / "models") ] specification = importlib.util.spec_from_file_location( - "snapform.server.models.onnx_moge2", + "anyimage.server.models.onnx_moge2", PROJECT_ROOT / "src" - / "snapform" + / "anyimage" / "server" / "models" / "onnx_moge2.py", @@ -33,9 +33,9 @@ def load_module(): with patch.dict( sys.modules, { - "snapform": snapform, - "snapform.server": server, - "snapform.server.models": models, + "anyimage": anyimage, + "anyimage.server": server, + "anyimage.server.models": models, }, ): specification.loader.exec_module(module) diff --git a/tests/test_pack.py b/tests/test_pack.py index 7fb739d..a165b54 100644 --- a/tests/test_pack.py +++ b/tests/test_pack.py @@ -12,7 +12,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] def load_pack(): specification = importlib.util.spec_from_file_location( - "snapform_pack", + "anyimage_pack", PROJECT_ROOT / "pack.py", ) module = importlib.util.module_from_spec(specification) @@ -47,7 +47,7 @@ class PackTest(unittest.TestCase): self.assertEqual( {path.name for path in output_paths}, { - f"SnapForm.v{version}.{platform}.zip" + f"AnyImage.v{version}.{platform}.zip" for platform in pack.PLATFORMS }, ) @@ -66,7 +66,7 @@ class PackTest(unittest.TestCase): self.assertIn("operators/balloon/operator.py", names) self.assertIn("operators/surface.py", names) self.assertIn( - "assets/O_SnapForm.blend", + "assets/O_AnyImage.blend", names, ) self.assertIn("server/media/input.py", names) @@ -100,7 +100,7 @@ class PackTest(unittest.TestCase): any(name.startswith("blendjob/") for name in names) ) self.assertNotIn("install_env.py", names) - self.assertNotIn("snapform/__init__.py", names) + self.assertNotIn("anyimage/__init__.py", names) self.assertNotIn("importer.py", names) self.assertFalse( any(name.startswith("sources/") for name in names) diff --git a/tests/test_server.py b/tests/test_server.py index e882625..2922bd2 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -13,7 +13,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] def load_server_module(): - server_directory = PROJECT_ROOT / "src" / "snapform" / "server" + server_directory = PROJECT_ROOT / "src" / "anyimage" / "server" specification = importlib.util.spec_from_file_location( "server", server_directory / "__init__.py", @@ -73,7 +73,7 @@ class ServerTest(unittest.TestCase): self.assertEqual(result, {"downloaded": ["MOGE2_VITS_NORMAL"]}) def test_models_are_owned_by_the_server_resource(self): - self.assertFalse((PROJECT_ROOT / "src" / "snapform" / "models.py").exists()) + self.assertFalse((PROJECT_ROOT / "src" / "anyimage" / "models.py").exists()) with tempfile.TemporaryDirectory() as directory: manager = self.server_module.ModelManager(Path(directory)) snapshot = manager.snapshot() @@ -99,7 +99,7 @@ class ServerTest(unittest.TestCase): def create_server(self): source = self.server_module.server server = self.server_module.JobServer( - "SnapForm Job Server", storage_root=self.storage_root + "AnyImage Job Server", storage_root=self.storage_root ) server.handlers.update(source.handlers) server.resource_factories.update(source.resource_factories) diff --git a/tests/test_worker.py b/tests/test_worker.py index 121764f..4540f5a 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -15,7 +15,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] def load_server_module(name): - addon_directory = PROJECT_ROOT / "src" / "snapform" + addon_directory = PROJECT_ROOT / "src" / "anyimage" sys.path.insert(0, str(addon_directory)) try: return __import__(f"server.{name}", fromlist=[name]) diff --git a/tools/build_geometry_nodes_asset.py b/tools/build_geometry_nodes_asset.py index 8399163..c7aca06 100644 --- a/tools/build_geometry_nodes_asset.py +++ b/tools/build_geometry_nodes_asset.py @@ -14,9 +14,9 @@ DEPTH_SCALE_ATTRIBUTE = "o_depth_scale" OUTPUT_PATH = ( Path(__file__).parents[1] / "src" - / "snapform" + / "anyimage" / "assets" - / "O_SnapForm.blend" + / "O_AnyImage.blend" ) diff --git a/tools/validate_balloon_asset.py b/tools/validate_balloon_asset.py index 875213f..45a59cf 100644 --- a/tools/validate_balloon_asset.py +++ b/tools/validate_balloon_asset.py @@ -8,20 +8,20 @@ PROJECT_ROOT = Path(__file__).parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) sys.path.insert( 0, - str(next((PROJECT_ROOT / "src" / "snapform" / "wheels").glob("blendjob-*.whl"))), + str(next((PROJECT_ROOT / "src" / "anyimage" / "wheels").glob("blendjob-*.whl"))), ) -from snapform.operators.balloon.depth import ( +from anyimage.operators.balloon.depth import ( BALLOON_DEPTH_ATTRIBUTE, add_balloon_shape_modifier, balloon_shape_node_group, ) -from snapform.operators.balloon.operator import ( +from anyimage.operators.balloon.operator import ( mark_balloon_material, merge_balloon_normal_image, reusable_balloon_material, ) -from snapform.operators.material import ( +from anyimage.operators.material import ( BALLOON_MATERIAL_NODE_GROUP_NAME, material_node_group, set_modifier_input, diff --git a/tools/validate_depth_plane_asset.py b/tools/validate_depth_plane_asset.py index dc132f8..cf1708e 100644 --- a/tools/validate_depth_plane_asset.py +++ b/tools/validate_depth_plane_asset.py @@ -8,10 +8,10 @@ PROJECT_ROOT = Path(__file__).parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) sys.path.insert( 0, - str(next((PROJECT_ROOT / "src" / "snapform" / "wheels").glob("blendjob-*.whl"))), + str(next((PROJECT_ROOT / "src" / "anyimage" / "wheels").glob("blendjob-*.whl"))), ) -from snapform.operators.material import ( +from anyimage.operators.material import ( DEPTH_PLANE_MATERIAL_NODE_GROUP_NAME, SHADELESS_NODE_GROUP_NAME, SURFACE_MATERIAL_NODE_GROUP_NAME, @@ -23,8 +23,8 @@ from snapform.operators.material import ( modifier_input_identifier, set_modifier_input, ) -from snapform.operators.depth_plane.build import add_depth_plane_processing -from snapform.operators.surface import load_geometry_node_group +from anyimage.operators.depth_plane.build import add_depth_plane_processing +from anyimage.operators.surface import load_geometry_node_group def main(): diff --git a/tools/validate_geometry_nodes_asset.py b/tools/validate_geometry_nodes_asset.py index e0d21c5..a408448 100644 --- a/tools/validate_geometry_nodes_asset.py +++ b/tools/validate_geometry_nodes_asset.py @@ -9,11 +9,11 @@ PROJECT_ROOT = Path(__file__).parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) sys.path.insert( 0, - str(next((PROJECT_ROOT / "src" / "snapform" / "wheels").glob("blendjob-*.whl"))), + str(next((PROJECT_ROOT / "src" / "anyimage" / "wheels").glob("blendjob-*.whl"))), ) -from snapform.operators.material import get_modifier_input, set_modifier_input -from snapform.operators.surface import create_matching_camera, load_geometry_node_group +from anyimage.operators.material import get_modifier_input, set_modifier_input +from anyimage.operators.surface import create_matching_camera, load_geometry_node_group def set_input(modifier, group, name, value): diff --git a/tools/validate_moge_depth_plane.py b/tools/validate_moge_depth_plane.py index 175c32c..04c1b75 100644 --- a/tools/validate_moge_depth_plane.py +++ b/tools/validate_moge_depth_plane.py @@ -12,17 +12,17 @@ PROJECT_ROOT = Path(__file__).parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) sys.path.insert( 0, - str(next((PROJECT_ROOT / "src" / "snapform" / "wheels").glob("blendjob-*.whl"))), + str(next((PROJECT_ROOT / "src" / "anyimage" / "wheels").glob("blendjob-*.whl"))), ) -from snapform.operators.image import create_color_image -from snapform.operators.material import ( +from anyimage.operators.image import create_color_image +from anyimage.operators.material import ( MOGE_DEPTH_PLANE_NODE_GROUP_NAME, MOGE_MATERIAL_NODE_GROUP_NAME, get_modifier_input, modifier_input_identifier, ) -from snapform.operators.depth_plane.build import build_moge2_depth_plane +from anyimage.operators.depth_plane.build import build_moge2_depth_plane def validate_single_frame_source_types(): diff --git a/tools/validate_moge_surface.py b/tools/validate_moge_surface.py index e4b2055..5a644dc 100644 --- a/tools/validate_moge_surface.py +++ b/tools/validate_moge_surface.py @@ -10,16 +10,16 @@ PROJECT_ROOT = Path(__file__).parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) sys.path.insert( 0, - str(next((PROJECT_ROOT / "src" / "snapform" / "wheels").glob("blendjob-*.whl"))), + str(next((PROJECT_ROOT / "src" / "anyimage" / "wheels").glob("blendjob-*.whl"))), ) -from snapform.operators.material import ( +from anyimage.operators.material import ( MOGE_SURFACE_MATERIAL_NODE_GROUP_NAME, material_color_space_name, ) -from snapform.operators.surface import MOGE_NODE_GROUP_NAME, build_image_mesh -from snapform.server.geometry import GeometryFrame, build_surface -from snapform.server.outputs.surface import write_surface_archive +from anyimage.operators.surface import MOGE_NODE_GROUP_NAME, build_image_mesh +from anyimage.server.geometry import GeometryFrame, build_surface +from anyimage.server.outputs.surface import write_surface_archive def write_test_normal_texture(normal, output_path): diff --git a/uv.lock b/uv.lock index 71a9e88..5da2a15 100644 --- a/uv.lock +++ b/uv.lock @@ -1061,7 +1061,7 @@ wheels = [ ] [[package]] -name = "snapform" +name = "anyimage" version = "0.12.15" source = { virtual = "." } dependencies = [