编辑作用域:撤销分栈不等于拥有完整会话
自动关联目录:编辑作用域:撤销分栈不等于拥有完整会话
核心判断:场景与 Prefab 使用不同 Undo 栈避免了历史串台,但真正的编辑作用域还必须拥有选择、Gizmo、相机、预览 World、Dirty Revision 和异步 generation;只拆历史仍是半个会话模型。
一、业务场景击穿了“当前编辑器只有一个上下文”
用户可以在主场景、Prefab 隔离视图和运行预览之间切换。一次属性写入的对象、选择反馈、相机位置和撤销目标必须属于同一文档。若 Undo 已分栈,而选择、网格吸附、Gizmo 或数据通道仍是全局状态,切换后就会出现“撤销正确,但视图操作了另一个上下文”。
工程代码已经明确把场景与 Prefab 历史分开,也明确说明这个 scope 目前只约束 Undo,并不自动约束其他编辑状态。这是一个重要且诚实的边界,不应在复盘中把它包装成完整多文档架构。
二、目标模型:EditorSession 是状态所有者
struct EditorSession {
EditSessionId id;
Generation generation;
DocumentId document;
PreviewWorldHandle world;
SelectionModel selection;
GizmoState gizmo;
CameraBookmark camera;
GridPolicy grid;
HistoryStack history;
Revision savedRevision;
Revision currentRevision;
};所有前端命令必须显式解析到一个 Session;异步资产回调、属性面板事件和脚本工具也携带 SessionId + generation。Dirty 状态由 currentRevision != savedRevision 推导,不能由散落的布尔标记拼接。
三、模型、视图、命令的边界
内容模型只保存可发布事实;选择、相机和 Gizmo 是会话态;命令读取二者并产生结构化 Change;UE Actor、Component 和 Slate Widget 是可重建投影。Prefab 隔离编辑使用独立预览 World 时,不能把其运行时指针写回主文档。
四、代价与验证
显式会话会让许多过去无参获取“当前编辑器”的 API 增加参数,也会暴露隐藏的全局依赖。但迁移可以从日志化隐式访问开始,再逐步要求调用者传 Session。
验证应同时打开两个文档,交错执行选择、拖拽、Undo、异步加载和关闭重开,证明任何迟到事件都无法改变另一个 Session。复盘后的提升是:作用域不是一个枚举,而是一组必须同生共死的编辑状态。