17 KiB
17 KiB
预演台统一重构:分析、设计与执行方案
0. 结论先行
当前问题不是“高频工作流样式还不够精致”,而是产品结构上同时维护了两套入口:
- 高频工作流:真实高频工作流,布局清晰,用户已经反复调试到可用。
- 旧分裂工作台:功能覆盖更广,但布局、样式和交互边界长期没有同步,已经出现样式 bug、功能 bug、滚动问题和空白问题。
继续在两套页面上各自修复,会让同一份场景数据拥有两套操作语义,之后每次新增能力都要重复接线、重复测试、重复修复。
本轮方向确定为:
删除“高频工作流”和“旧分裂工作台”这两个产品层级,把所有能力合并到一个统一的“预演台”工作区。布局、视觉和交互以已经验证过的高频工作流方案为主;从 DirectorDesk 只吸收真正有价值的场景编排能力,尤其是轨迹绘制与轨迹播放,不复制它的表面结构。
“预演台”是产品名称。内部可以继续保留 layout / pose / animate / camera 作为能力状态,但它们只能是同一工作区中的上下文,不再是两套工作台。
1. 反复犯错的问题
1.1 把参考产品的表面结构当成了产品答案
错误表现:
- 看到 DirectorDesk 的左侧布景、右侧摄影机、底部时间轴,就把“多面板旧分裂工作台”整体搬过来。
- 只复制了组件形状、标题和分栏,没有先确认我们的用户真正高频的任务顺序。
- 参考产品里真正有价值的能力(轨迹、路径、基于距离的步行动画、镜头连续性)反而没有成为主线。
修复思路:
- 参考产品只提取“能力和原则”,不提取它的页面壳。
- 先问用户在当前产品里最常做什么,再决定入口、密度和默认视图。
- 对 DirectorDesk 的吸收清单只保留:自由手绘轨迹、轨迹简化、按距离分配时间、路径朝向、演员/摄影机路径可视化、同一场景多视图观察。
- 明确不复制:独立桌面应用的菜单层级、复杂资源管理、与本项目无关的深度导出和外部工程概念。
1.2 把“功能完整”误解成“再造一个页面
错误表现:
- 为了补齐布景、姿态、动画、摄影机,新增旧分裂工作台。
- 结果是高频工作流和旧分裂工作台分别拥有一部分能力,任何一边都不是完整事实来源。
- 同一个操作在两套页面上可能使用不同的保存、选择、视口和检查器路径。
修复思路:
- 功能完整不等于页面分裂。
- 所有场景修改都必须进入同一套
commit / history / save coordinator链路。 - 所有对象、灯光、摄影机、资产、姿态、关键帧和输出都在同一个预演台布局中可达。
- 复杂功能通过同一页面里的分区、抽屉、工具栏、检查器和时间轴渐进展开,而不是增加第二个工作台。
1.3 先修局部样式,后补产品信息架构
错误表现:
- 不断调整圆角、颜色、间距、按钮样式。
- 但页面仍然有两套入口,用户不知道该进入哪一个。
- 旧分裂工作台中的功能不在高频工作流出现,导致“看起来有功能,实际上找不到”。
修复思路:
- 顺序固定为:信息架构 -> 任务路径 -> 状态模型 -> 组件布局 -> 视觉细节。
- 页面只有一个产品入口,先解决“在哪里做”再解决“看起来怎样”。
- 视觉规范以高频工作流当前已验证的密度、面板、颜色、对象列表和视口胶囊切换为基线。
1.4 通过重新实现,破坏已经修好的行为
错误表现:
- 修复 UI 时把保存、撤销、模型加载、上下文恢复、对象摆位等已稳定链路一起改动。
- 为了“统一”,把刻意放宽的产品规则重新收紧。
- 用逐个报错、逐个补洞的方式开发,最后无法确认完整流程是否可靠。
修复思路:
- 统一页面只替换产品壳,不重写已稳定的场景数据和保存底座。
- 保留
touchPrevisScene、commit、stagedTransaction、保存协调器、模型加载诊断和 WebGL 恢复机制。 - 每轮修改后跑完整流程:打开、加对象、选中、摆位、画轨迹、播放、保存、回写、关闭、重开。
- 不以“某一个错误消失”为完成标准,而以端到端流程通过为标准。
1.5 把轨迹当成动画的附属细节,而不是核心能力
错误表现:
- 目前主要依靠零散 transform 关键帧和简单折线显示。
- 用户无法像导演在场地上画走位一样直接表达动作。
- 轨迹时间可能受鼠标事件数量、停顿和绘制速度影响,导致播放速度不稳定。
修复思路:
- 轨迹是预演台的核心编辑对象,必须有明显的“画轨迹”入口。
- 轨迹采样后先做三维简化,再按路径距离分配时间,不能按 pointer event 间隔直接写时间。
- 演员沿轨迹移动时默认按路径方向转向;摄影机轨迹至少保证位置连续,并保留原镜头朝向。
- 轨迹必须能在导演视角、机位视角和时间轴播放中被验证。
2. 用户调教出来的产品设计原则
这些不是装饰偏好,而是预演台的产品约束:
- 高频工作流是 99% 用户使用的真实入口,所有功能必须进入主工作流。
- 不允许用“高级模式”作为缺功能的借口;高级能力必须在同一个预演台中自然出现。
- UI 需要高端、专业、有质感,但不能靠装饰遮盖信息架构问题。
- 画布节点必须有真实场景缩略图或可靠的实时预览,不用空白文字占位冒充完成。
- 新演员必须默认拥有可区分的颜色,颜色可直接编辑。
- 对象、摄影机、灯光、资产、环境、姿态、运镜、动画和输出必须在同一场景事实源中工作。
- 操作必须可逆、可保存、可重开,不能出现“界面看起来成功但数据没有保存”。
- 功能入口应该面向任务:添加角色、搭景、画轨迹、设计镜头、调整动作、输出,而不是面向内部代码模块。
- 不用重复造同一套 UI。一个布局、一个状态模型、一个保存链路、一个测试入口。
- 重构不得把已经明确放宽的产品规则重新收紧,例如素材删除不因为引用关系被拦截。
3. DirectorDesk 真正值得吸收的东西
吸收
- 自由手绘路径:在地面或物体表面直接拖出演员/摄影机路线。
- 路径点清理和简化:去掉高频采样噪声,同时保留拐角和闭环形状。
- 基于距离的时间分配:相同路径不因鼠标快慢、帧率或事件密度而改变播放速度。
- 连续路径与途经点停留:后续可支持停留点、分段速度和连续曲线。
- 路径方向:演员沿路径方向朝向;摄影机可选择沿路径、看向目标或保持镜头方向。
- 路径可视化:轨迹线、起点、终点、当前播放位置、选中状态要一眼可见。
- 位置和动作分离:路线控制空间移动,动作片段控制走路/跑步/姿势,二者可以独立调整。
- 多视图验证:导演视角调整空间关系,机位视角检查最终画面,时间轴检查连续性。
不吸收
- 不复制 DirectorDesk 的独立应用信息架构。
- 不复制与本项目无关的资源目录、导出协议和菜单层级。
- 不为了“看起来像”而保留第二个高级页面。
- 不把桌面端复杂能力一次性全部塞进首屏;复杂选项放入检查器和可展开工具。
4. 统一预演台设计
4.1 统一产品结构
名称:预演台。
单一全屏工作区:
- 顶部:关闭、场景标题、撤销/重做、保存状态、渲染模式、生成白膜、回写构图。
- 左侧:场景对象、摄影机、灯光、道具库、画布资产、轨迹目标入口。
- 中间:主 3D 视口;导演视角/机位视角/正交视图切换;对象和轨迹直接可见。
- 右侧:当前镜头与选中对象检查器;景别、运镜、时长、帧率、姿态、体型、颜色、变换、灯光、镜头参数和生成提示词。
- 底部:时间轴按需展开;镜头条、对象轨道、摄影机轨道、关键帧、播放和 Auto Key 都在这里。
没有“高频工作流 / 旧分裂工作台”切换按钮,也没有“进入旧分裂工作台”的隐藏入口。
4.2 统一页面中的上下文
内部仍可以使用 layout / pose / animate / camera 作为能力上下文,但它们只影响:
- 当前检查器优先展示什么。
- 是否显示时间轴和 Auto Key。
- 渲染模式有哪些。
- 当前工具栏的默认工具。
它们不能切换到另一套页面,也不能改变对象数据的来源。
4.3 主任务顺序
- 选镜头或创建镜头。
- 从左侧添加演员、道具、资产、灯光和摄影机。
- 在中间视口拖动对象,或点击“画轨迹”直接绘制走位。
- 在右侧调整姿态、体型、颜色和镜头参数。
- 在底部时间轴播放、补关键帧、查看轨迹连续性。
- 在机位视角确认画面。
- 生成白膜或回写构图。
每一步都应在同一个页面完成,不需要跳转或换工作台。
4.4 轨迹交互
- 选中演员或摄影机后,工具栏出现“画轨迹”。
- 点击后进入绘制态:视口进入路径采样,OrbitControls 暂停,鼠标/触摸拖动生成地面路径。
- 绘制中显示临时路径和起点/终点。
- 松开后按当前镜头时长生成路径关键帧。
- 演员:按路径方向生成水平朝向,保留当前高度、缩放和姿态/动作。
- 摄影机:写入连续位置关键帧,默认保留当前旋转;后续再提供“沿路朝向 / 看向主体”的切换。
- 再次绘制覆盖该对象当前轨迹,撤销可以恢复旧轨迹。
- 没有选中可移动对象时,按钮给出明确提示,不进入半成品状态。
5. 数据与实现边界
保留
PrevisScene、PrevisObject、PrevisCamera、PrevisLight。- 现有 transform keyframe 结构,轨迹首版直接编译为关键帧,避免引入第二套持久化格式。
previs-animation-semantics.ts的动画编辑语义。- 保存协调器、草稿恢复、页面卸载保护、诊断事件和视口 capture/record。
- 既有对象颜色、actor archetype、actorProfile、motionClips 和 boneTracks。
新增
previs-path.ts:- 三维点清理与 Ramer-Douglas-Peucker 简化。
- 按路径距离计算 waypoint 时间。
- 轨迹关键帧生成。
- 路径方向和 yaw 计算。
- 视口绘制态:仅在显式绘制轨迹时接管 pointer 事件。
- 轨迹预览:临时线、已保存路径、当前播放点。
- 单元测试覆盖:简化、距离计时、退化路径、方向角连续性、关键帧生成。
不新增
- 不再增加 第二套模式状态。
- 不再保留一套只为“旧分裂工作台”服务的 JSX 和 CSS。
- 不建立第二个场景编辑器 store。
- 不把路径采样事件直接持久化为大量 pointer 记录。
6. 重构阶段与验收门
Phase 1:先写统一事实源
- 删除顶部快速/高级切换。
- 统一预演台默认显示场景对象、摄影机、灯光、资产、镜头检查器。
- 将原旧分裂工作台中仍有价值的工具接入现有
pv-*布局。 - 删除重复 JSX 和对应的高级 CSS。
成功标志:项目中只剩一个预演台 UI 分支,搜索不到“高频工作流/旧分裂工作台”产品入口。
Phase 2:轨迹基础能力
- 增加纯函数路径库和单元测试。
- 视口增加显式画轨迹态。
- 演员和摄影机轨迹编译为已有关键帧。
- 播放头和轨迹预览同步。
成功标志:能在同一页面画演员路线、播放并撤销;摄影机路线能在导演视角看到。
Phase 3:布局与体验收敛
- 左侧补齐旧分裂工作台里的对象、灯光、模型资产和道具入口。
- 右侧补齐对象/灯光/镜头检查器和提示词输出。
- 底部时间轴按动画上下文展开,不再用页面切换表达“高级”。
- 统一按钮、焦点、触控尺寸、滚动容器和空状态。
成功标志:用户不需要记住功能属于哪一种工作台;所有高频能力在一个页面可发现。
Phase 4:测试和清理
- 更新 Chrome E2E:不再点击旧分裂工作台;默认打开即验证统一界面。
- 保留对象添加、撤销、模型加载、上下文丢失恢复、保存失败重试等 P0 场景。
- 增加轨迹的纯函数测试和至少一条浏览器轨迹 smoke。
- 删除无引用的高级组件、样式、旧命名和测试描述。
成功标志:TypeScript、ESLint、单元测试、Vite build、Chrome E2E 全部通过;完整流程可从打开走到保存、关闭和重开。
7. 明确的完成标准
- 用户只看到一个产品:预演台。
- 高频工作流中已验证的布局和视觉成为全局基线。
- 布景、演员、姿态、动画、摄影机、灯光、资产、环境、提示词和输出全部可达。
- 轨迹绘制成为一等交互,不是隐藏在高级模式里的补充按钮。
- 轨迹播放速度由路径距离和镜头时长决定,不由鼠标事件或绘制速度决定。
- 新演员颜色自动区分且可编辑。
- 画布卡片、模型加载、保存恢复和输出链路没有回归。
- 没有“进入旧分裂工作台”或“切换高频工作流”的产品级文案、按钮和双份页面。
8. 本轮 IA 实施记录(2026-10-05)
已落地的左右面板职责
- 左侧只负责场景层级、对象、摄影机、灯光、道具和资源浏览;移除重复的摄影机、灯光、道具库添加入口,避免同一动作在多个面板出现。
- 中央只负责真实 WebGL 视口、对象操作、视角工具和轨迹绘制;移除旧的视图胶囊,视图状态统一由视口工具层管理。
- 右侧只负责当前选择上下文:选中对象显示对象检查器,选中灯光显示灯光检查器,选中摄影机显示摄影机检查器,无选择时才显示镜头设计上下文。
- 底部只负责时间、播放、Auto Key、镜头条、对象轨道和关键帧;不在左右面板复制时间控制。
- 移动端将右侧检查器变成滑入抽屉,通过显式打开/关闭按钮进入,不牺牲检查器能力,也不压缩主视口到不可用尺寸。
覆盖层与响应式纠错记录
- 下拉菜单、工具提示和检查器抽屉使用明确的层级、边界和碰撞策略;打开菜单时不遮盖错误面板,Escape 可关闭,焦点回到触发控件。
- 本轮曾将移动工具声明放在 media block 外并多写一个
},导致 Vite 在canvas-previs-workbench.css:1415失败。修正方式是把移动端工具栏、轨迹按钮和时间轴声明收回同一个@media (max-width: 860px),再以生产构建验证 CSS 结构。 - 移动端保留 176-200px 左侧层级栏、单列视口和 280px 时间轴下限;右侧检查器使用不超过 92vw 的抽屉,避免面板相互覆盖。
当前验收状态(截至 2026-10-05)
- 已通过:TypeScript、目标 ESLint、
git diff --check、Vite production build、轨迹纯函数测试(npx --yes bun test test/previs-path.test.ts,5 tests / 12 assertions)。 - 已通过:完整 Chrome P0 E2E,A-F 共 62/62 断言通过;覆盖统一工作台启动、真实 WebGL、添加/撤销、动画时间轴、模型成功加载、模型失败重试、加载中删除、WebGL context loss/restore、保存失败提示、重试入口和关闭保护。
- 已通过:桌面结构探针(1680×932):左/右面板各 272px,中央 canvas 约 1132×879;DOM 中
.pv-viewport-toolbar、取景模式组和 canvas 各 1 个,旧 Dock 与视图胶囊均为 0。 - 已通过:窄屏结构探针(390×844):左层级栏 176px,主视口约 299px,右检查器以约 359px 抽屉停在屏幕外,工具栏位于主视口内;未发现面板几何重叠。开发环境仅出现已知 Ant Design/Three 弃用提示,无运行时异常。
- 已通过:精确旧双工作台/旧产品入口扫描为 0 命中;保留的历史文档术语不构成运行时入口。
- 尚未覆盖:浏览器内真实轨迹拖拽、轨迹取消/预览/播放、轨迹撤销和演员/摄影机轨迹持久化重载;保存成功后的重开闭环;保存失败后实际点击“重试保存”并确认恢复;移动端截图级视觉验收;完整下拉碰撞与焦点回归。
- 不能宣称完成的门禁:上述浏览器轨迹与持久化闭环仍需专门 smoke;本轮已证明轨迹算法和基础 pointer 取消逻辑,但没有把它们扩大解释为完整端到端通过。
下一轮验收顺序
- 在稳定的本地预演台页面完成浏览器轨迹绘制、取消、距离计时、预览、播放、撤销、镜头切换、模式切换和保存重载闭环。
- 补保存成功重开、保存失败后重试成功,以及导出动作的浏览器断言。
- 补移动端实际截图和打开检查器抽屉后的边界/焦点/Escape 断言。
- 扫描源代码、测试和文档,确认不存在旧的双页面入口、路由、分支或产品级名称。
- 最后再次运行 TypeScript、ESLint、轨迹测试、Vite build、E2E 和
git diff --check。