Add new functionality for image rectification and depth metadata handling

- Implemented a preview tool for rectifying images with interactive aspect controls in `preview.py`.
- Added tests for depth metadata loading to ensure consistent schema usage in `test_depth_metadata.py`.
- Developed comprehensive tests for cutout calibration processes in `test_cutout_calibration.py`, including stability checks and depth calibration.
- Created tests for frame compositing operations in `test_frame_compositing.py`, ensuring correct handling of depth and transparency.
- Introduced material slot inheritance functionality in `material_slots.py` to manage geometry material assignments.
- Built shared shader nodes for material processing in `shader.py`, including roughness and bump mapping setups.
This commit is contained in:
2026-09-12 19:20:06 +08:00
parent e8268504c2
commit 938d95db0f
175 changed files with 3812 additions and 6864 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-12

View File

@@ -0,0 +1,49 @@
## Context
Cutout 的 `SelectCutoutSelection` 已继承 `common.viewport.ImageGesture`,目前固定为 Lasso 并通过拖动键位启动。Mask 的 Polyline 已由该共用类实现。Cutout 完成选区后打开 Shape 饼菜单,Depth Solid 经异步生成后使用 `O Image Depth Cutout` 创建对象。
节点构建内部的 Uniform Thickness 输入在保存前显示名改为 Thickness;节点组同时存在 Balloon 使用的 Thickness 输入,初始化必须区分 socket 标识。
## Goals
支持 Cutout 逐点剪出及 Uniform 初始化;统一 Mask 的 Extend 命名和 Set 默认值。
## Decisions
### 共用手势与独立设置
在 `properties.py` 定义 Cutout 的 Lasso / Polyline 属性,由 Scene 保存,默认 Lasso。Cutout 在启动时读取手势,沿用 `ImageGesture` 的逐点输入、实时预览、闭合提示和取消清理。使用共用按下启动键位支持首点输入,并验证 Lasso 拖动完成以及空白处源对象保持行为。共用逻辑留在 `common`,Cutout 负责自己的状态文本和选区提交。
### 创建时应用 Uniform
```mermaid
flowchart TD
A[读取 Cutout Gesture] --> B[ImageGesture 收集并确认选区]
B --> C[Shape 饼菜单携带本次 Gesture 快照]
C --> D[CutoutSelectionToShape 保存 Gesture]
D --> E[生成所需图像并在主线程创建对象]
E --> F{Polyline 且 Depth Solid}
F -->|是| G[设置新修改器 Mode 为 Uniform]
F -->|否| H[按 Shape 初始化修改器]
```
手势作为普通字符串从选择 Operator 显式传到饼菜单、转换 Operator 和对象创建链路,异步响应使用该快照,避免用户中途切换 Scene 设置影响结果。服务器生成协议继续处理深度和法线产物;修改器初始化由主线程完成。Uniform 自动设置针对本次新建的 Depth Solid 对象,之后用户可手动修改 Mode。
### 节点厚度默认值
将构建内部 Uniform Thickness 默认值设为 0.5,并验证最终资产对应 socket 的默认值和新修改器实际值。检查现有通用 Thickness 赋值只初始化其目标输入,避免同名 socket 覆盖 Uniform 默认值。按现有资产修订机制更新 Depth Solid 版本并运行 `uv run node-group build`。
### Mask 模式
统一为 `SET` / Set、`EXTEND` / Extend、`SUBTRACT` / Subtract,保留枚举数值 0、1、2。Scene 和 Operator 均通过共用属性默认 Set。Extend 保持 `max(alpha, mask)`,Set 保持 `alpha * mask`,Subtract 保持 `alpha * (1-mask)`;状态文本和测试同步命名。
## Risks / Trade-offs
- 按下启动可能改变 Cutout 的源对象选择时机 → 覆盖 Lasso、Polyline、空白点击和取消行为。
- 异步生成期间手势被切换 → 在提交时保存本次手势,并覆盖设置改变后的响应。
- 同名 Thickness socket 容易导致写入错误 → 验证具体 socket identifier、资产默认值及实际修改器值。
- 旧脚本传入 `ADD` 将失效 → 调用方统一使用 `EXTEND`,保持原枚举数值且不增加别名。
## Migration Plan
实现代码与测试后重建节点资产,执行相关测试及全量测试。回退时将本次代码、测试和资产作为同一变更回退。

View File

@@ -0,0 +1,27 @@
## Why
Cutout 目前只能自由绘制 Lasso,沿直线轮廓剪出时需要逐点定义边界。复用 Mask 的 Polyline 交互,并为这种剪出方式设置 Uniform 厚度,可减少手动调整;Mask 使用 Extend 和默认 Set,使名称与常用操作一致。
## What Changes
- Cutout 增加 Gesture 选项 Lasso / Polyline,默认 Lasso,复用共用逐点交互和选区提交链路。
- Polyline 剪出创建使用 `O Image Depth Cutout` 的 Depth Solid 对象时,自动设置修改器 Mode 为 Uniform。
- `O Image Depth Cutout` 的 Uniform Thickness 接口默认值改为 0.5(资产中显示为 Thickness)。
- **BREAKING** Mask 的 `ADD` / Add 统一重命名为 `EXTEND` / Extend,保留扩展 Alpha 的运算语义;默认模式从 Subtract 改为 Set。
## Capabilities
### New Capabilities
- `cutout-polyline`: Cutout 手势选择、共用 Polyline 交互,以及创建结果的 Uniform 初始化。
- `mask-mode-options`: Mask 的 Set / Extend / Subtract 名称、运算和默认值。
### Modified Capabilities
无。当前 `openspec/specs` 尚无已归档的对应规范。
## Impact
- `properties.py`、`common/viewport.py`、`operators/cutout_tool`、`operators/mask_tool.py` 和相关注册、交互、对象创建测试。
- `tools/nodes/groups/image_depth_cutout.py`、节点资产 `O_AnyImage.blend` 及节点测试;实现阶段需运行节点构建与验证。
- 无新增依赖。已有 change 中的 Mask、Polyline 和 Cutout 提案作为实现背景,本 change 定义本次行为。

View File

@@ -0,0 +1,57 @@
## ADDED Requirements
### Requirement: Cutout offers persistent gesture selection
Cutout SHALL 提供 Lasso 和 Polyline 手势,默认 Lasso,并保存到 Scene 的独立 Cutout 设置。
#### Scenario: User selects Polyline
- **WHEN** 用户将 Cutout Gesture 切换为 Polyline 并开始剪出
- **THEN** 工具以首次左键按下的位置为起点,随后通过点击添加顶点
#### Scenario: User returns to Cutout
- **WHEN** 用户选择 Polyline 后切换到其他工具再返回
- **THEN** Cutout 继续使用 Polyline,Mask Gesture 保持自己的设置
#### Scenario: Default Lasso interaction
- **WHEN** 新 Scene 中用户拖动 Cutout 并释放左键
- **THEN** 工具以 Lasso 收集轮廓并在有效选区完成后打开 Shape 饼菜单
### Requirement: Cutout reuses shared Polyline interaction
Cutout MUST 复用 Mask 所用的共用 Polyline 手势,提供轮廓预览、起点闭合提示、左键添加顶点、Backspace 删除末点、点击起点或双击或 Enter 完成,以及 RMB、Esc 和切换工具取消。
#### Scenario: User completes a polygon
- **WHEN** 至少三个顶点后,用户点击起点闭合范围内、双击或按 Enter / Numpad Enter
- **THEN** 工具提交已确认的闭合 SelectionPath 并打开 Shape 饼菜单,闭合点击和双击第二击不添加重复顶点
#### Scenario: Too few points
- **WHEN** 少于三个顶点时用户尝试完成
- **THEN** 工具继续收集顶点,不打开 Shape 菜单
#### Scenario: User edits or cancels a polygon
- **WHEN** 用户按 Backspace,或通过 RMB、Esc、切换工具取消
- **THEN** Backspace 删除末点并至少保留起点;取消清理预览且不创建结果对象
#### Scenario: Empty click preserves the source
- **WHEN** 用户在空白处启动 Cutout 手势
- **THEN** 工具保持现有源对象选择规则,不因空白点击清空源对象
### Requirement: Polyline initializes Depth Solid with Uniform mode
通过 Polyline 创建 Depth Solid 时,系统 MUST 将新对象的 `O Image Depth Cutout` 修改器 Mode 初始化为 Uniform。手势 MUST 使用本次提交快照。
#### Scenario: Polyline depth result completes asynchronously
- **WHEN** 用户提交 Polyline 并选择 Depth Solid,在生成结束前将 Cutout Gesture 改为 Lasso
- **THEN** 本次结果的 Mode 仍为 Uniform,用户可在创建后手动调整
#### Scenario: Lasso or another shape is used
- **WHEN** 用户通过 Lasso 创建 Depth Solid,或通过 Polyline 创建 Flat、Solid、Depth Balloon
- **THEN** 对象沿用该 Shape 的现有 Mode 初始化规则
### Requirement: Uniform thickness defaults to half a unit
`O Image Depth Cutout` 的 Uniform Thickness socket MUST 默认 0.5,保存资产中对应显示为 Thickness 的 socket 和新建修改器 MUST 使用该值。
#### Scenario: Node asset is built and loaded
- **WHEN** 完成节点资产构建并从资产加载节点组创建 Polyline Depth Solid
- **THEN** Mode 为 Uniform,Uniform 厚度值为 0.5,通用 Thickness 初始化不会覆盖该值

View File

@@ -0,0 +1,25 @@
## ADDED Requirements
### Requirement: Mask exposes Set Extend and Subtract
Mask MUST 按顺序提供 `SET` / Set、`EXTEND` / Extend、`SUBTRACT` / Subtract,枚举数值分别为 0、1、2;界面和状态文本 MUST 使用 Extend。
#### Scenario: User extends Alpha
- **WHEN** 用户以 Extend 提交值为 mask 的选区到现有 alpha
- **THEN** 结果 Alpha 为 `max(alpha, mask)`,RGB 保持不变
#### Scenario: User uses Set or Subtract
- **WHEN** 用户使用 Set 或 Subtract
- **THEN** 结果 Alpha 分别为 `alpha * mask` 或 `alpha * (1-mask)`,RGB 保持不变
### Requirement: Mask defaults to Set
Scene 的 Mask Mode 和 Mask Operator 的模式属性 MUST 默认 Set,并通过同一属性定义保持一致。
#### Scenario: New scene and operator defaults
- **WHEN** 创建新 Scene 或未指定模式的 Mask Operator
- **THEN** 模式默认值为 `SET`
#### Scenario: User chooses another mode
- **WHEN** 用户主动设置 Extend 或 Subtract 后启动 Mask
- **THEN** 本次操作使用用户保存的模式

View File

@@ -0,0 +1,21 @@
## 1. Cutout 手势
- [x] 1.1 在 properties.py 添加默认 Lasso 的 Cutout Gesture 属性并接入 Scene、Operator 和工具设置,检查注册与逆序注销测试。
- [x] 1.2 将 Cutout 接入共用 Polyline 启动、预览与完成逻辑,更新状态文本;覆盖逐点、闭合、双击、Enter、Backspace、取消、Lasso 回归和空白处源对象保持行为。
## 2. Uniform 初始化与资产
- [x] 2.1 将本次 Gesture 快照从选区提交经 Shape 菜单传入转换 Operator 和对象创建链路;覆盖异步期间切换设置的行为。
- [x] 2.2 为 Polyline 创建的 Depth Solid 设置 Mode 为 Uniform,验证 Lasso 与其他 Shape 的初始化行为。
- [x] 2.3 将节点内部 Uniform Thickness 默认值改为 0.5,检查同名 Thickness socket 的赋值目标并更新资产修订号;补充资产默认值与实际修改器值测试。
- [x] 2.4 运行 `uv run node-group build`,更新并验证 O_AnyImage.blend,确认源码与保存资产的 Capture Attribute 数量为零。
## 3. Mask 模式
- [x] 3.1 将 Mask 的 ADD / Add 统一改为 EXTEND / Extend,保持枚举数值与 Alpha 运算语义,将共用模式属性默认值改为 SET。
- [x] 3.2 更新模式、状态文本、设置持久化和注册测试,验证三种模式的 Alpha 结果及 RGB 保持行为。
## 4. 验证
- [x] 4.1 运行相关测试及 `uv run pytest`,确认正常退出。
- [x] 4.2 检查运行时代码和测试中的旧 Mask 模式引用及最终差异,确认源码、测试和节点资产一致。