mark
本文回答:撤销标记 = 把"做了一次某种类型的操作"记到栈里。常用方法:
added_undoMark / erased_undoMark / modEntity_undoMark / moved_undoMark / rotate_undoMark / scaled_undoMark / mirrored_undoMark / entLayer_undoMark / entColorIndex_undoMark / entLineType_undoMark / entLTScale_undoMark / entTransp_undoMark / clayer_undoMark / layerModified_undoMark / ucs_undoMark / plan_undoMark。Engine.addEntities / eraseEntities等封装会自动记录,无需手动 mark。
一、最常用:添加 / 删除 / 修改
const u = Engine.undoManager;
// 添加 — 推荐 Engine.addEntities,自动记录
Engine.addEntities(line1);
// 或手动两步
Engine.pcanvas.addEntity(circle1);
u.added_undoMark([circle1]);
// 删除 — 推荐 Engine.eraseEntities,自动记录
Engine.eraseEntities(line1);
// 或手动
Engine.currentDoc.currentSpace.erase([line1]);
u.erased_undoMark([line1]);
// 修改属性前先记
u.modEntity_undoMark(entity); // 记录修改前状态
entity.color = 1;
entity.setModified();
MCP 参考:vjcad/doc/undo/undo-redo.md、vjcad/example/undo/02mark.js。
二、几何变换
const fromPt = new Point2D(0, 0);
const toPt = new Point2D(40, 0);
// 移动
for (const e of entities) e.move(fromPt, toPt);
u.moved_undoMark(entities, fromPt, toPt);
// 旋转
const basePt = new Point2D(50, 50);
const ang = Math.PI / 4;
for (const e of entities) e.rotate(basePt, ang);
u.rotate_undoMark(entities, basePt, ang);
// 缩放
for (const e of entities) e.scale(basePt, 2.0);
u.scaled_undoMark(entities, basePt, 2.0);
// 镜像
const p1 = new Point2D(0, 0), p2 = new Point2D(100, 0);
for (const e of entities) e.mirror(p1, p2);
u.mirrored_undoMark(entities, p1, p2);
MCP 参考:vjcad/doc/undo/undo-redo.md、vjcad/example/undo/02mark.js。
三、属性 / 图层 / 颜色 / 线型
u.entLayer_undoMark(entities); // 改图层前
u.entColorIndex_undoMark(entities); // 改颜色前
u.entLineType_undoMark(entities); // 改线型前
u.entLTScale_undoMark(entities); // 改线型比例前
u.entTransp_undoMark(entities); // 改透明度前
// 当前图层切换:Engine.setCurrentLayer 内部已 clayer_undoMark,不要再手动 mark(否则记两次)
Engine.setCurrentLayer('新图层');
// 只有直接赋 Engine.currentDoc.CLAYER 时才需要先手动 u.clayer_undoMark(oldLayer)
// 图层属性修改
u.layerModified_undoMark(layer);
layer.color = 1;
MCP 参考:vjcad/doc/undo/undo-redo.md。
四、UCS / PLAN(视图)
UCS / PLAN 是先改值、再 mark:UcsUndoCommand / PlanViewUndoCommand 构造时就把空间当前值记为 redo 目标,先 mark 会把旧值当成 redo 值(redo 失效)。
// UCS 设置时
const oldOrg = Engine.currentSpace.UCSORG.clone();
const oldAng = Engine.currentSpace.UCSXANG;
Engine.currentSpace.UCSORG = newOrg;
Engine.currentSpace.UCSXANG = newAng;
u.ucs_undoMark(oldOrg, oldAng); // 改完再 mark,传旧值
// 平面视图旋转
const oldTwistAngle = Engine.currentSpace.twistAngle;
Engine.currentSpace.twistAngle = newTwistAngle;
u.plan_undoMark(oldTwistAngle); // 改完再 mark,传旧值
MCP 参考:vjcad/example/view/10ucs.js、11planview.js。
五、撤销标记总表
| 方法 | 撤销时行为 |
|---|---|
added_undoMark(ents) |
删除这些实体 |
erased_undoMark(ents) |
恢复这些实体 |
modEntity_undoMark(ent) |
恢复修改前状态 |
moved_undoMark(ents, from, to) |
反向移动 |
rotate_undoMark(ents, base, angle) |
反向旋转 |
scaled_undoMark(ents, base, scale) |
反向缩放(除以 scale) |
mirrored_undoMark(ents, p1, p2) |
再次镜像(自反) |
entLayer_undoMark(ents) |
恢复原图层 |
entColorIndex_undoMark(ents) |
恢复原颜色 |
entLineType_undoMark(ents) |
恢复原线型 |
entLTScale_undoMark(ents) |
恢复原比例 |
entTransp_undoMark(ents) |
恢复原透明度 |
clayer_undoMark(oldLayer) |
恢复原当前图层 |
layerModified_undoMark(layer) |
恢复图层属性 |
ucs_undoMark(oldOrg, oldAng) |
恢复 UCS |
plan_undoMark(oldTwistAngle) |
恢复视图旋转 |
MCP 参考:vjcad/doc/undo/undo-redo.md。
六、Engine.markModified 封装
Engine.markModified(entity); // 单个,等价 modEntity_undoMark
entity.color = 1;
entity.setModified();
Engine.markModifiedBatch([e1, e2, e3]); // 批量
MCP 参考:vjcad/doc/undo/undo-redo.md。
反例
- 修改属性后才 mark:记录的是新值,撤销不了。快照类 mark(
modEntity_undoMark、entColorIndex_undoMark等)必须先 mark,再改;但ucs_undoMark/plan_undoMark相反——先改值再 mark(传旧值),见 §四。 - 用
Engine.addEntities+ 手动added_undoMark:双重记录(addEntities 已自动记录)。撤销按记录条数从块末尾pop,会多删掉一个原本就存在的实体,重做又会把新实体加两次。 - 改了
Engine.currentSpace.UCSORG但不ucs_undoMark:Ctrl+Z不会回滚 UCS。
参考(官方文档 MCP)
- 文档:
vjcad/doc/undo/undo-redo.md、vjcad/doc/undo/index.md - 示例:
vjcad/example/undo/02mark.js