diff --git a/__test__/FileSystem/file.test.ts b/__test__/FileSystem/file.test.ts index a77172075..c9464fce7 100644 --- a/__test__/FileSystem/file.test.ts +++ b/__test__/FileSystem/file.test.ts @@ -78,7 +78,26 @@ test('xxx', () => let file = db.FileWrite(); console.log(file.ToString()); - console.log(JSON.stringify(db.ObjectOut())); + db.hm.StartCmd(""); + + (id1.Object as Line).StartPoint = new Vector3(100, 300, 400); + (id1.Object as Line).EndPoint = new Vector3(2000, 3000, 4000); + + console.log((id1.Object as Line).StartPoint); + console.log((id1.Object as Line).EndPoint); + + db.hm.Undo(); + + console.log((id1.Object as Line).StartPoint); + console.log((id1.Object as Line).EndPoint); + + db.hm.Redo(); + + console.log((id1.Object as Line).StartPoint); + console.log((id1.Object as Line).EndPoint); + + console.log(db.hm.historyRecord); + }); diff --git a/src/DatabaseServices/FileSystem.ts b/src/DatabaseServices/FileSystem.ts index 567986697..ff8c33b80 100644 --- a/src/DatabaseServices/FileSystem.ts +++ b/src/DatabaseServices/FileSystem.ts @@ -1,5 +1,5 @@ import { ArrayRemove } from '../../src/Common/Utils'; -import { Vector3 } from 'three'; +import { Vector3, Line3 } from 'three'; /* 关于webCAD 文件系统的原型. 包括了对象的保存,撤销,还原. @@ -90,6 +90,17 @@ cmdName:"Ohther" //假设这个是一个复杂度很高的命令 ] +优化A +当连续2个命令是A时,优化第二个命令A的undo数据为空 +当第一个数据为A时,优化后续的P. +A写入时,只写入undo信息,并不写入redo信息.当命令结束时,写入redo数据. + +优化C: +当第一个数据为C时,优化后续的P. +同A 写入时,只写入UNDO,并不写入redo,命令结束时,写入redo数据 + + + 问题:对象id的更新. 跨文档复制时,对象的id和引用的id应该被更新. 加入ObjectId类. @@ -123,20 +134,6 @@ export class CADFactory if (createF) return createF(); } - - static ReadObject(data: any, db: Database): CADObject - { - if (data.className) - { - let obj = this.CreateObject(data.className); - if (obj) - { - obj.SetDefaultDb(db); - obj.ObjectIn(data); - return obj - } - } - } } //所有cad对象的基类 @@ -227,21 +224,32 @@ export class CADObject file.Write(1); this.WriteObjectId(file) } - ObjectIn(obj: any) + //局部撤销 + ApplyPartialUndo(undoData: CADObject) { - this.objectId = ObjectId.Create(this._db, obj.id); + if (undoData instanceof AllObjectData) + { + this.ReadFile(undoData.file); + } } - ObjectOut(): Object + + //撤销所保存的位置 + UndoRecord(): CommandHistoryRecord { - return { - className: this.ClassName, - id: this.Id.Index - }; + if (this._db) + return this._db.hm.UndoData; } - //局部撤销 - ApplyPartialUndo(file: CADObject) + + //写入所有的对象数据 以便还原对象 + protected WriteAllObjectRecord() { + let undoData = this.UndoRecord(); + if (undoData) + { + undoData.WriteObjectHistoryPath(this, new ObjectAllDataHistoryRecord(this)); + } } + //#endregion @@ -393,14 +401,15 @@ export class CADFile } } -export class AppendData extends CADObject +export class CreateObjectData extends CADObject { private cadFile: CADFile; - constructor(obj: CADObject) + constructor(obj?: CADObject) { super(); this.cadFile = new CADFile(); - this.cadFile.WriteObject(obj); + if (obj) + this.cadFile.WriteObject(obj); } getObject(db: Database): CADObject @@ -415,20 +424,27 @@ export class AppendData extends CADObject //类名,保证序列化时得到正确的new get ClassName(): string { - return "AppendData"; + return "CreateObjectData"; } //对象从文件中读取数据,初始化自身 ReadFile(file: CADFile) - { } + { + file.Write(1);//ver + let data = file.Read(); + this.cadFile.Data = data; + } //对象将自身数据写入到文件. WriteFile(file: CADFile) - { } + { + file.Read();//ver; + file.Write(this.cadFile.Data); + } //局部撤销 ApplyPartialUndo(file: CADObject) { } //#endregion -----------------------------File End----------------------------- } -export class RemoveData extends CADObject +export class RemoveObjectData extends CADObject { private index: number; constructor(index?: number) @@ -450,16 +466,34 @@ export class RemoveData extends CADObject } //对象从文件中读取数据,初始化自身 ReadFile(file: CADFile) - { } + { + file.Read();//ver + this.index = file.Read(); + } //对象将自身数据写入到文件. WriteFile(file: CADFile) - { } + { + file.Write(1); + file.Write(this.index); + } //局部撤销 ApplyPartialUndo(file: CADObject) { } //#endregion -----------------------------File End----------------------------- } +export class AllObjectData extends CADObject +{ + file: CADFile; + constructor(obj?: CADObject) + { + super(); + this.file = new CADFile(); + if (obj) + obj.WriteFile(this.file); + } +} + //对象集合. export class ObjectCollection extends CADObject { @@ -475,13 +509,14 @@ export class ObjectCollection extends CADObject obj.InitObjectId(this._db); } - if (this._db && this._db.hm.UndoData) + let undoRec = this.UndoRecord(); + if (undoRec) { - let hisRec = new HistoricRecord(); - hisRec.redoData = new AppendData(obj); - hisRec.undoData = new RemoveData(this.objectCol.length - 1); + let hisRec = new HistorycRecord(); + hisRec.redoData = new CreateObjectData(obj); + hisRec.undoData = new RemoveObjectData(this.objectCol.length - 1); - this._db.hm.UndoData.WriteObjectHistoryPath(this, hisRec); + undoRec.WriteObjectHistoryPath(this, hisRec); } return obj.Id; @@ -490,13 +525,14 @@ export class ObjectCollection extends CADObject { ArrayRemove(this.objectCol, obj); obj.Erase(); - if (this._db && this._db.hm.UndoData) + let undoRec = this.UndoRecord(); + if (undoRec) { - let hisRec = new HistoricRecord(); - hisRec.undoData = new AppendData(obj); - hisRec.redoData = new RemoveData(this.objectCol.length - 1); + let hisRec = new HistorycRecord(); + hisRec.undoData = new CreateObjectData(obj); + hisRec.redoData = new RemoveObjectData(this.objectCol.length - 1); - this._db.hm.UndoData.WriteObjectHistoryPath(this, hisRec); + undoRec.WriteObjectHistoryPath(this, hisRec); } } Cout(): number @@ -504,12 +540,6 @@ export class ObjectCollection extends CADObject return this.objectCol.length; } - //迭代器 - Entries() - { - return this.objectCol.entries; - } - //#region -----------------------------File----------------------------- //对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化 //类名,保证序列化时得到正确的new @@ -539,28 +569,15 @@ export class ObjectCollection extends CADObject file.WriteObject(obj); } } - - ObjectIn(obj: any) - { - super.ObjectIn(obj); - let objList: Object[] = obj.objectCol; - this.objectCol = objList.map(o => CADFactory.ReadObject(o, this._db)); - } - ObjectOut(): Object - { - let obj = super.ObjectOut() as any; - obj.objectCol = this.objectCol.map(o => o.ObjectOut()); - return obj; - } //局部撤销 ApplyPartialUndo(undoData: CADObject) { - if (undoData instanceof AppendData) + if (undoData instanceof CreateObjectData) { let obj = undoData.getObject(this._db); this.objectCol.push(obj); } - else if (undoData instanceof RemoveData) + else if (undoData instanceof RemoveObjectData) { this.Remove(this.objectCol[undoData.Index]); } @@ -579,9 +596,9 @@ export class CommandHistoryRecord extends CADObject //命令名称 private commandName: string; //历史记录表 - private historyCol = new Map(); + private historyCol = new Map(); - get HistoryList(): Map + get HistoryList(): Map { return this.historyCol; } @@ -594,20 +611,76 @@ export class CommandHistoryRecord extends CADObject return this.historyCol.get(id); } + EndCommand() + { + for (let [id, recs] of this.historyCol) + { + let rec = this.GetObjectAllDataRecord(recs); + if (rec) + { + rec.WriteRedo(); + } + } + } + //获得对象的记录 + GetObjectAllDataRecord(historyList: HistorycRecord[]): ObjectAllDataHistoryRecord + { + if (historyList.length > 0) + { + let rec = historyList[historyList.length - 1]; + if (rec instanceof ObjectAllDataHistoryRecord) + { + return rec; + } + } + } //对象写入数据 - WriteObjectHistoryPath(obj: CADObject, history: HistoricRecord) + WriteObjectHistoryPath(obj: CADObject, history: HistorycRecord) { - this.GetObjectHistoryList(obj.Id).push(history); + let his = this.GetObjectHistoryList(obj.Id); + if (this.GetObjectAllDataRecord(his)) + { + console.log("优化掉重复的全部数据"); + return; + } + if (history instanceof ObjectAllDataHistoryRecord) + { + history.WriteUndo(); + } + his.push(history); } + + //#region -------------------------File------------------------- + //对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化 + + //类名,保证序列化时得到正确的new + get ClassName(): string + { + return "CommandHistoryRecord"; + } + + //对象从文件中读取数据,初始化自身 + ReadFile(file: CADFile) + { + let ver = file.Read(); + } + //对象将自身数据写入到文件. + WriteFile(file: CADFile) + { + + } + //#endregion + } + /** * 历史记录,用于撤销和重做的数据. * * @class HistoricRecord * @extends {CADObject} */ -export class HistoricRecord extends CADObject +export class HistorycRecord extends CADObject { //指定撤销时所需要的数据 undoData: CADObject; @@ -616,6 +689,29 @@ export class HistoricRecord extends CADObject userData: CADObject; } +export class ObjectAllDataHistoryRecord extends HistorycRecord +{ + obj: CADObject; + file: CADFile; + constructor(obj?: CADObject) + { + super(); + this.obj = obj; + this.file = new CADFile(); + } + + //将数据写入 手动调用 + WriteUndo() + { + this.undoData = new AllObjectData(this.obj); + } + WriteRedo() + { + this.redoData = new AllObjectData(this.obj); + } +} + + //历史记录管理 export class HistoricManage extends CADObject { @@ -627,29 +723,73 @@ export class HistoricManage extends CADObject { super(); } - get UndoData(): CommandHistoryRecord + + + //对象从文件中读取数据,初始化自身 + ReadFile(file: CADFile) { - if (this.doing) + let ver = file.Read(); + this.curIndex = file.Read(); + + this.historyRecord = []; + let cout = file.Read(); + for (let i = 0; i < cout; i++) { - return undefined; + this.historyRecord.push(file.ReadObject(this._db) as CommandHistoryRecord); } - if (this.historyRecord.length === 0 || this.curIndex != this.historyRecord.length - 1) + } + //对象将自身数据写入到文件. + WriteFile(file: CADFile) + { + file.Write(1); + file.Write(this.historyRecord.length); + for (let rec of this.historyRecord) { - this.StartCmd(""); + file.WriteObject(rec); } + } + + + + //命令正在当前状态 + get IsNow(): boolean + { + return this.historyRecord.length !== 0 && this.curIndex === this.historyRecord.length - 1; + } + get UndoData(): CommandHistoryRecord + { + if (this.doing) + return undefined; + if (!this.IsNow) + this.StartCmd(""); return this.historyRecord[this.historyRecord.length - 1]; } StartCmd(cmdName: string) { + this.EndCmd(); + //删除当前状态以后的所有状态 this.historyRecord.splice(this.curIndex + 1, this.historyRecord.length - (this.curIndex + 1)); this.historyRecord.push(new CommandHistoryRecord(cmdName)); this.curIndex = this.historyRecord.length - 1; } + //结束当前的命令. + EndCmd() + { + if (!this.IsNow) + return; + let lastRec = this.historyRecord[this.curIndex]; + if (lastRec) + { + lastRec.EndCommand(); + } + } + Undo(): boolean { + this.EndCmd(); let historyRec = this.historyRecord[this.curIndex]; if (!historyRec) { @@ -724,18 +864,6 @@ export class Database file.ReadObject(this, this.ModelSpace); } - - ObjectIn(obj: any) - { - } - ObjectOut(): Object - { - return { - idCout: this.idCout, - ms: this.ModelSpace.ObjectOut(), - } - } - //创建一个id,自动递增它的索引号,并且会自动加入到db的id列表中. AllocateId(obj: CADObject): ObjectId { @@ -747,9 +875,7 @@ export class Database return id; } else - { console.warn("警告:对象不属于该数据库!"); - } } /* private 请不要调用该方法,只暴露给 ObjectId使用. @@ -770,9 +896,7 @@ export class Database SetObjectId(index: number, id: ObjectId) { if (this.idMap.has(index)) - { console.warn("警告:尝试加入已经存在的id!"); - } this.idMap.set(index, id); } } @@ -802,9 +926,9 @@ export class BlockTableRecord extends ObjectCollection super.WriteFile(file); } //局部撤销 - ApplyPartialUndo(file: CADObject) + ApplyPartialUndo(undoData: CADObject) { - super.ApplyPartialUndo(file); + super.ApplyPartialUndo(undoData); } //#endregion-----------------------------File End----------------------------- } @@ -850,26 +974,16 @@ export class Line extends Entity file.Write(this.startPoint.toArray()); file.Write(this.endPoint.toArray()); } - - ObjectIn(obj: any) - { - } - ObjectOut(): Object - { - let obj = super.ObjectOut() as any; - obj.sp = this.startPoint.toArray(); - obj.ep = this.endPoint.toArray(); - return obj - } - ApplyPartialUndo(data) { + super.ApplyPartialUndo(data); } //-----------------------------File End----------------------------- set StartPoint(v: Vector3) { + this.WriteAllObjectRecord(); this.startPoint.copy(v); } get StartPoint(): Vector3 @@ -879,11 +993,12 @@ export class Line extends Entity get EndPoint(): Vector3 { - return this.endPoint; + return this.endPoint.clone(); } set EndPoint(v: Vector3) { - this.endPoint = v; + this.WriteAllObjectRecord(); + this.endPoint.copy(v); } }