Files
AnyImage/openspec/changes/persist-image-tool-options/specs/crop-tool-options/spec.md

119 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Purpose
规定四合一 Crop Tool 的工具栏结构、裁切工具命名和独立编辑选项,以及相邻 Cutout Tool 成品相对源图片平面的局部向内轴约定。
## ADDED Requirements
### Requirement: Crop Tool is one four-tool toolbar group
系统 SHALL 在 3D Viewport 工具栏中提供两个独立 AnyImage 入口:一个 **Crop Tool** 工具组和一个普通单项 **Cutout Tool**。Crop Tool SHALL 按 **Crop Box**、**Crop Lasso**、**Crop Polyline**、**Crop Perspective** 的顺序包含四个子工具;Cutout Tool SHALL 不属于任何工具组,并紧接在 Crop Tool 组之后。
#### Scenario: User opens the Crop Tool group
- **WHEN** 用户展开 Crop Tool
- **THEN** 工具组只显示 Crop Box、Crop Lasso、Crop Polyline 与 Crop Perspective
- **AND** Crop Box 是该组的首个子工具
#### Scenario: User views adjacent AnyImage tools
- **WHEN** Crop Tool 组和 Cutout Tool 已注册到 3D Viewport
- **THEN** 工具栏显示 Crop Tool 组与 Cutout Tool 两个独立入口
- **AND** Cutout Tool 紧接在 Crop Tool 组之后
- **AND** Cutout Tool 是单个 WorkSpaceTool,不是单项工具组
- **AND** 两个入口之间没有分割线
- **AND** Cutout Tool 使用 Add UV Sphere 图标
### Requirement: Crop terminology replaces Image Tool terminology
系统 SHALL 对四个裁切子工具、激活入口、Tool ID、Operator、设置属性、源码边界和文档统一使用 Crop 术语,不得保留旧 Image Tool 或独立 Perspective Tool 的兼容名称和转发入口。
#### Scenario: User activates the crop entry
- **WHEN** 用户从 AnyImage 入口激活图片裁切功能
- **THEN** 系统激活 Crop Box 并以 Crop Tool 命名该功能
#### Scenario: Extension registers crop tools
- **WHEN** AnyImage 扩展完成注册
- **THEN** 四个 Crop 子工具使用 `anyimage` 前缀的 Crop Tool ID 注册为同一组
- **AND** 旧 Image Tool 与独立 Perspective Tool ID 不再注册
### Requirement: Image Line is removed
系统 SHALL 删除 Image Line 及其按直线划分图片半平面的裁切行为,不得在 Crop Tool、菜单、快捷入口或公开 Operator 中提供该工具。
#### Scenario: User opens Crop Tool
- **WHEN** 用户查看 Crop Tool 的子工具
- **THEN** 列表中没有 Image Line 或 Crop Line
### Requirement: Crop options persist independently per sub-tool
系统 SHALL 为 Crop Box、Crop Lasso、Crop Polyline 与 Crop Perspective 分别保存彼此独立的 **Keep Original**,并为前三个 Selection Crop Tool 分别保存彼此独立的 **Invert**;所有选项默认关闭,切换一个子工具的值不得改变其他子工具的值,Crop Perspective SHALL NOT 提供 Invert。
#### Scenario: User returns to a Crop sub-tool
- **WHEN** 用户修改一个子工具支持的 Invert 或 Keep Original,切换到其他 Crop 子工具后再返回
- **THEN** 该子工具恢复自己上次保存的选项值
#### Scenario: User uses a Crop sub-tool for the first time
- **WHEN** 当前文件尚未修改该子工具支持的 Invert 或 Keep Original
- **THEN** 该子工具支持的选项均为关闭
#### Scenario: User opens Crop Perspective settings
- **WHEN** 用户激活 Crop Perspective
- **THEN** 工具设置提供独立的 Keep Original
- **AND** 工具设置不提供 Invert 或 Refine Selection
### Requirement: Invert follows the persistent Crop sub-tool option
Crop Box、Crop Lasso 与 Crop Polyline SHALL 使用当前子工具保存的 **Invert** 值决定保留 Selection 内部还是外部,并只通过工具选项修改该值;Crop Perspective 不参与该行为,Crop Tool 的 keymap 与 modal 交互 SHALL NOT 将 `F` 或其他字母键绑定为选项快捷键。
#### Scenario: User changes Invert in tool settings
- **WHEN** 用户在任一 Selection Crop Tool 的工具设置中修改 Invert
- **THEN** 系统保存当前子工具的 Invert,下一次裁切使用新值
#### Scenario: User operates a Crop tool with a letter key
- **WHEN** Crop Tool 空闲或正在执行 modal 交互
- **THEN** Crop Tool 不使用 `F` 或其他字母键切换 Invert、Keep Original 或 Refine Selection
### Requirement: Cutout has no letter option shortcuts
Cutout Tool 的 keymap 与 modal 交互 SHALL NOT 使用 `F` 或其他字母键切换选项。
#### Scenario: User presses F during Cutout selection
- **WHEN** Cutout Tool 正在执行 Selection modal 交互
- **THEN** `F` 不切换 Invert 或其他选项
### Requirement: Keep Original preserves the crop source
四个 Crop 子工具 SHALL 在各自的 **Keep Original** 关闭时以裁切结果替换源 Image Empty;开启时 SHALL 为本次裁切创建一个结果 Image Empty,并保留源 Image Empty 的对象、图片、变换和显示设置。
#### Scenario: User crops with Keep Original disabled
- **WHEN** 用户在 Keep Original 关闭时完成任一 Crop 操作
- **THEN** 裁切结果替换源 Image Empty,场景中不额外保留操作前的源对象
#### Scenario: User crops with Keep Original enabled
- **WHEN** 用户在 Keep Original 开启时完成任一 Crop 操作
- **THEN** 场景同时包含未改变的源 Image Empty 和本次裁切的结果 Image Empty
- **AND** 结果 Image Empty 被选中并作为 active object
- **AND** 源 Image Empty 不再保持选中
#### Scenario: User continues cropping the result
- **WHEN** 用户在 Keep Original 开启时完成一次裁切后继续操作当前 active object
- **THEN** 下一次裁切以刚创建的结果 Image Empty 作为输入
- **AND** 前一次源 Image Empty 仍保留在场景中
### Requirement: Cutout exposes the inward local axis
Cutout Tool SHALL 提供持久保存的 **Inward Axis** 选项,可选 `-Z` 与 `+X`,默认值 SHALL 为 `-Z`;该选项 SHALL 决定生成 Mesh Object 在局部坐标中从纸面指向内部的轴向。
#### Scenario: User creates a Cutout with the default axis
- **WHEN** 用户未修改 Inward Axis 并创建任一 Cutout Shape
- **THEN** 结果 Mesh 的纸面位于局部 XY 平面,向内方向为局部 `-Z`
- **AND** 结果的局部坐标轴与源 Image Empty 的局部坐标轴一致
#### Scenario: User chooses the legacy axis
- **WHEN** 用户把 Inward Axis 设为 `+X` 并创建任一 Cutout Shape
- **THEN** 结果 Mesh 的纸面位于局部 YZ 平面,向内方向为局部 `+X`
- **AND** 结果保持变更前的 Cutout 局部坐标约定
### Requirement: Cutout orientation preserves world-space output
Cutout SHALL 对 Surface、Balloon、Depth Balloon 与 Depth Surface 一致应用所选 Inward Axis,同时保持结果在源 Image Empty 图片平面上的世界空间位置、尺寸、纹理方向和纸面正反语义不变。
#### Scenario: Equivalent shapes use different local axes
- **WHEN** 用户从同一源 Image Empty 和 Selection 分别以 `-Z` 与 `+X` 创建相同 Shape
- **THEN** 两个结果的对应表面点在世界空间重合
- **AND** 两个结果只在 Mesh Object 的局部坐标与对象变换约定上不同
#### Scenario: Oriented Depth Surface uses an Object Space Normal Map
- **WHEN** 用户以任一 Inward Axis 创建启用 Normal Map 的 Depth Surface
- **THEN** Object Space Normal Map 按所选局部坐标约定着色
- **AND** 可见表面法线方向与对应几何法线一致