mirror of https://gitee.com/cf-fz/WebCAD.git
parent
4523d0e1d7
commit
75b28fe307
@ -0,0 +1,9 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { Entity } from './Entity';
|
||||
import { ObjectCollection } from './ObjectCollection';
|
||||
|
||||
@Factory
|
||||
export class BlockTableRecord extends ObjectCollection<Entity>
|
||||
{
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
import { CADObject } from "./CADObject";
|
||||
|
||||
/**
|
||||
* CAD对象工厂,通过注册 和暴露的创建方法,动态创建对象
|
||||
*
|
||||
* @export
|
||||
* @class CADFactory
|
||||
*/
|
||||
export class CADFactory
|
||||
{
|
||||
private constructor() { }
|
||||
private objectNameMap = new Map<string, any>();
|
||||
private static factory = new CADFactory();
|
||||
static RegisterObject(C)
|
||||
{
|
||||
this.factory.objectNameMap.set(C.name, C);
|
||||
}
|
||||
static CreateObject(name: string): CADObject
|
||||
{
|
||||
let C = this.factory.objectNameMap.get(name);
|
||||
if (C) return new C();
|
||||
}
|
||||
}
|
||||
|
||||
//可以通过添加装饰器 在类前面(@Factory),自动注册工厂的序列化
|
||||
export function Factory(target: Object)
|
||||
{
|
||||
CADFactory.RegisterObject(target);
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
import { CADFactory } from './CADFactory';
|
||||
import { CADObject } from './CADObject';
|
||||
import { Database } from './Database';
|
||||
|
||||
/**
|
||||
* CAD文件数据
|
||||
*
|
||||
* @export
|
||||
* @class CADFile
|
||||
*/
|
||||
export class CADFile
|
||||
{
|
||||
private readIndex: number = 0;
|
||||
private dataList: any[] = [];
|
||||
|
||||
Destroy()
|
||||
{
|
||||
delete this.dataList;
|
||||
delete this.readIndex;
|
||||
}
|
||||
get Data()
|
||||
{
|
||||
return this.dataList;
|
||||
}
|
||||
set Data(v)
|
||||
{
|
||||
this.dataList = v;
|
||||
this.Reset();
|
||||
}
|
||||
Reset()
|
||||
{
|
||||
this.readIndex = 0;
|
||||
}
|
||||
WriteString(str: string)
|
||||
{
|
||||
this.dataList.push(str);
|
||||
}
|
||||
ReadString(): string
|
||||
{
|
||||
let str = this.dataList[this.readIndex] as string;
|
||||
this.readIndex++;
|
||||
return str;
|
||||
}
|
||||
WriteObject(obj: CADObject)
|
||||
{
|
||||
if (!obj)
|
||||
{
|
||||
this.Write("");
|
||||
return;
|
||||
}
|
||||
let tempFile = new CADFile();
|
||||
tempFile.WriteString(obj.constructor.name);
|
||||
obj.WriteFile(tempFile);
|
||||
this.Write(tempFile.Data);
|
||||
tempFile.Destroy();//GC
|
||||
}
|
||||
ReadObject(db: Database, obj?: CADObject): CADObject
|
||||
{
|
||||
let data = this.Read();
|
||||
let tempFile = new CADFile();
|
||||
tempFile.Data = data;
|
||||
|
||||
let className = tempFile.ReadString();
|
||||
if (className)
|
||||
{
|
||||
obj = obj ? obj : CADFactory.CreateObject(className);
|
||||
obj.SetDefaultDb(db);
|
||||
obj.ReadFile(tempFile);
|
||||
tempFile.Destroy();
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
Write(data: any)
|
||||
{
|
||||
this.dataList.push(data);
|
||||
}
|
||||
Read(): any
|
||||
{
|
||||
let data = this.dataList[this.readIndex];
|
||||
this.readIndex++;
|
||||
return data;
|
||||
}
|
||||
ToString()
|
||||
{
|
||||
return JSON.stringify(this.dataList);
|
||||
}
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CommandHistoryRecord } from './CommandHistoryRecord';
|
||||
import { Database } from './Database';
|
||||
import { ObjectId } from './ObjectId';
|
||||
|
||||
export abstract class CADObject
|
||||
{
|
||||
//对象被彻底遗弃
|
||||
GoodBye(): any
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------DB-------------------------
|
||||
protected _db: Database;
|
||||
get Db(): Database
|
||||
{
|
||||
return this._db;
|
||||
}
|
||||
|
||||
//对象在加入数据库时,必须指定一个源数据库,否则无法读取引用id.
|
||||
SetDefaultDb(db: Database)
|
||||
{
|
||||
if (!this._db)
|
||||
this._db = db;
|
||||
else
|
||||
console.warn("警告:同一个对象无法重复设置默认db.");
|
||||
}
|
||||
|
||||
//private 私有的方法,暴露给Db的添加对象,方法使用.
|
||||
//只用对象加入到db中,我们才初始化ObjectId.
|
||||
//从db池中分配id给自身使用. 除非你创建对象往db里面加,否则不要调用该方法
|
||||
InitObjectId(db: Database)
|
||||
{
|
||||
if (!this._db)
|
||||
{
|
||||
this._db = db;
|
||||
this.objectId = db.AllocateId(this);
|
||||
}
|
||||
else
|
||||
console.warn("同一个对象无法重复设置到数据库中!");
|
||||
}
|
||||
//-------------------------DB End-------------------------
|
||||
|
||||
// -------------------------isErase-------------------------
|
||||
protected _isErase: boolean = false;
|
||||
get IsErase(): boolean
|
||||
{
|
||||
return this._isErase;
|
||||
}
|
||||
Erase(isErase: boolean = true)
|
||||
{
|
||||
this._isErase = isErase;
|
||||
}
|
||||
//-------------------------isErase End-------------------------
|
||||
|
||||
// -------------------------id-------------------------
|
||||
protected objectId: ObjectId;
|
||||
|
||||
get Id(): ObjectId
|
||||
{
|
||||
return this.objectId;
|
||||
}
|
||||
|
||||
// -------------------------id End-------------------------
|
||||
|
||||
// -------------------------File-------------------------
|
||||
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
let ver = file.Read();
|
||||
//write Id;
|
||||
this.objectId = this.ReadObjectId(file);
|
||||
if (this.objectId)
|
||||
{
|
||||
this.objectId.Object = this;
|
||||
}
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
file.Write(1);
|
||||
this.WriteObjectId(file)
|
||||
}
|
||||
//局部撤销
|
||||
ApplyPartialUndo(undoData: CADObject)
|
||||
{
|
||||
if (undoData instanceof AllObjectData)
|
||||
{
|
||||
undoData.file.Reset();
|
||||
this.ReadFile(undoData.file);
|
||||
}
|
||||
}
|
||||
|
||||
//撤销所保存的位置
|
||||
UndoRecord(): CommandHistoryRecord
|
||||
{
|
||||
if (this._db)
|
||||
return this._db.hm.UndoData;
|
||||
}
|
||||
//写入所有的对象数据 以便还原对象
|
||||
protected WriteAllObjectRecord()
|
||||
{
|
||||
let undoData = this.UndoRecord();
|
||||
if (undoData)
|
||||
undoData.CreateObjectHistory(this);
|
||||
}
|
||||
|
||||
//复制出一个实体,所有的关联引用全部失效,如有需要,请重新关联.
|
||||
Clone(): CADObject
|
||||
{
|
||||
let file = new CADFile();
|
||||
file.WriteObject(this);
|
||||
return file.ReadObject(undefined);
|
||||
}
|
||||
|
||||
//-------------------------File End-------------------------
|
||||
|
||||
protected WriteObjectId(file: CADFile)
|
||||
{
|
||||
if (this.objectId)
|
||||
{
|
||||
file.Write(this.objectId.Index);
|
||||
}
|
||||
else
|
||||
file.Write(-1);
|
||||
}
|
||||
protected ReadObjectId(file: CADFile): ObjectId
|
||||
{
|
||||
let index = file.Read();
|
||||
if (index >= 0 && this._db)
|
||||
{
|
||||
return ObjectId.Create(this._db, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存对象创建或者修改时的所有数据记录
|
||||
*
|
||||
* @export
|
||||
* @class AllObjectData
|
||||
* @extends {IFileReadWrite}
|
||||
*/
|
||||
@Factory
|
||||
export class AllObjectData extends CADObject
|
||||
{
|
||||
file: CADFile;
|
||||
constructor(obj?: CADObject)
|
||||
{
|
||||
super();
|
||||
this.file = new CADFile();
|
||||
if (obj)
|
||||
obj.WriteFile(this.file);
|
||||
}
|
||||
|
||||
//#region -------------------------File-------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
super.ReadFile(file);
|
||||
let ver = file.Read();
|
||||
let data = file.Read();
|
||||
this.file.Data = data;
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
super.WriteFile(file);
|
||||
file.Write(1);
|
||||
file.Write(this.file.Data);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
import { HistorycRecord } from './HistorycRecord';
|
||||
import { ObjectAllDataHistoryRecord } from './ObjectAllDataHistoryRecord';
|
||||
import { ObjectId } from './ObjectId';
|
||||
|
||||
/**
|
||||
* 命令的历史记录
|
||||
*
|
||||
* @export
|
||||
* @class CommandHistoryRecord
|
||||
* @extends {DbObject}
|
||||
*/
|
||||
@Factory
|
||||
export class CommandHistoryRecord extends CADObject
|
||||
{
|
||||
constructor(cmdName?: string)
|
||||
{
|
||||
super();
|
||||
this.commandName = cmdName;
|
||||
}
|
||||
//命令名称
|
||||
private commandName: string;
|
||||
//历史记录表
|
||||
private historyCol = new Map<ObjectId, HistorycRecord[]>();
|
||||
|
||||
get HistoryList(): Map<ObjectId, HistorycRecord[]>
|
||||
{
|
||||
return this.historyCol;
|
||||
}
|
||||
private GetObjectHistoryList(id: ObjectId)
|
||||
{
|
||||
if (!this.historyCol.has(id))
|
||||
{
|
||||
this.historyCol.set(id, []);
|
||||
}
|
||||
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: HistorycRecord)
|
||||
{
|
||||
let his = this.GetObjectHistoryList(obj.Id);
|
||||
if (this.GetObjectAllDataRecord(his))
|
||||
{
|
||||
//console.log("优化掉重复的全部数据");
|
||||
return;
|
||||
}
|
||||
if (history instanceof ObjectAllDataHistoryRecord)
|
||||
{
|
||||
history.WriteUndo();
|
||||
}
|
||||
his.push(history);
|
||||
}
|
||||
CreateObjectHistory(obj: CADObject): ObjectAllDataHistoryRecord
|
||||
{
|
||||
if (!obj.Id)
|
||||
{
|
||||
console.warn("错误!CreateObjectHistory");
|
||||
return;
|
||||
}
|
||||
let rec = new ObjectAllDataHistoryRecord(obj.Id);
|
||||
this.WriteObjectHistoryPath(obj, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
//#region -------------------------File-------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
let ver = file.Read();
|
||||
this.commandName = file.Read();
|
||||
let cout = file.Read();
|
||||
|
||||
this.historyCol.clear();
|
||||
for (let i = 0; i < cout; i++)
|
||||
{
|
||||
let id = this.ReadObjectId(file);
|
||||
let length = file.Read();
|
||||
let recs = [];
|
||||
this.historyCol.set(id, recs);
|
||||
for (let j = 0; j < length; j++)
|
||||
{
|
||||
let rec = file.ReadObject(this._db);
|
||||
recs.push(rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
file.Write(1);
|
||||
file.Write(this.commandName);
|
||||
file.Write(this.historyCol.size);
|
||||
for (let [id, recs] of this.historyCol)
|
||||
{
|
||||
file.Write(id.Index);
|
||||
file.Write(recs.length);
|
||||
for (let rec of recs)
|
||||
{
|
||||
file.WriteObject(rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
import { Database } from './Database';
|
||||
|
||||
@Factory
|
||||
export class CreateObjectData extends CADObject
|
||||
{
|
||||
private cadFile: CADFile;
|
||||
constructor(obj?: CADObject)
|
||||
{
|
||||
super();
|
||||
this.cadFile = new CADFile();
|
||||
if (obj)
|
||||
this.cadFile.WriteObject(obj);
|
||||
}
|
||||
|
||||
getObject(db: Database): CADObject
|
||||
{
|
||||
this.cadFile.Reset();
|
||||
let obj = this.cadFile.ReadObject(db);
|
||||
this.cadFile.Reset();
|
||||
return obj;
|
||||
}
|
||||
|
||||
//#region -----------------------------File-----------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
file.Read();//ver;
|
||||
let data = file.Read();
|
||||
this.cadFile.Data = data;
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
file.Write(1);//ver
|
||||
file.Write(this.cadFile.Data);
|
||||
}
|
||||
//#endregion -----------------------------File End-----------------------------
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
import { BlockTableRecord } from './BlockTableRecord';
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
import { HistoricManage } from './HistoricManage';
|
||||
import { MaerialTableRecord } from './MaerialTableRecord';
|
||||
import { ObjectId } from './ObjectId';
|
||||
|
||||
@Factory
|
||||
export class Database
|
||||
{
|
||||
|
||||
hm: HistoricManage;
|
||||
//块表记录
|
||||
blockTableCol: BlockTableRecord[];
|
||||
//模型空间
|
||||
ModelSpace: BlockTableRecord;
|
||||
//材质字典...
|
||||
MaterialDict: MaerialTableRecord;
|
||||
|
||||
private idCout = -1;
|
||||
private idMap = new Map<number, ObjectId>();
|
||||
|
||||
constructor()
|
||||
{
|
||||
this.ModelSpace = new BlockTableRecord();
|
||||
this.ModelSpace.InitObjectId(this);
|
||||
this.MaterialDict = new MaerialTableRecord();
|
||||
this.MaterialDict.InitObjectId(this);
|
||||
|
||||
this.hm = new HistoricManage();
|
||||
this.hm.SetDefaultDb(this);
|
||||
}
|
||||
|
||||
FileWrite(): CADFile
|
||||
{
|
||||
let file = new CADFile();
|
||||
file.Write(1);//ver;
|
||||
file.WriteObject(this.ModelSpace);
|
||||
file.WriteObject(this.MaterialDict);
|
||||
return file;
|
||||
}
|
||||
FileRead(file: CADFile)
|
||||
{
|
||||
let ver = file.Read();
|
||||
file.ReadObject(this, this.ModelSpace);
|
||||
file.ReadObject(this, this.MaterialDict);
|
||||
}
|
||||
|
||||
//创建一个id,自动递增它的索引号,并且会自动加入到db的id列表中.
|
||||
AllocateId(obj: CADObject): ObjectId
|
||||
{
|
||||
if (obj.Db === this)
|
||||
{
|
||||
this.idCout++;
|
||||
let id = ObjectId.Create(this, this.idCout);
|
||||
id.Object = obj;
|
||||
return id;
|
||||
}
|
||||
else
|
||||
console.warn("警告:对象不属于该数据库!");
|
||||
}
|
||||
/*
|
||||
private 请不要调用该方法,只暴露给 ObjectId使用.
|
||||
|
||||
获得指定索引的id, 注意该id可能为空, 如果需要创建, 请使用 ObjectId.Create,如果需要自动分配,请使用,AllocateId
|
||||
*/
|
||||
GetObjectId(index: number): ObjectId
|
||||
{
|
||||
return this.idMap.get(index);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private 请不要调用该方法,只暴露给 ObjectId使用.
|
||||
|
||||
在id池中加入新建的id. 该方法暴露给 Objectid.Cretes使用.
|
||||
*/
|
||||
SetObjectId(index: number, id: ObjectId)
|
||||
{
|
||||
if (this.idMap.has(index))
|
||||
console.warn("警告:尝试加入已经存在的id!");
|
||||
this.idMap.set(index, id);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
//所有图元的基类
|
||||
import * as THREE from 'three';
|
||||
|
||||
import { RenderType } from '../GraphicsSystem/Enum';
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADObject } from './CADObject';
|
||||
import { ObjectId } from './ObjectId';
|
||||
|
||||
@Factory
|
||||
export class Entity extends CADObject
|
||||
{
|
||||
protected m_DrawEntity = new Map<RenderType, THREE.Object3D>();
|
||||
//材质id
|
||||
protected m_MaterialId: ObjectId;
|
||||
protected m_Color: number = 7;
|
||||
//绘制一个threeJs对象.
|
||||
Draw(renderType: RenderType = RenderType.Wireframe): THREE.Object3D
|
||||
{
|
||||
if (this.m_DrawEntity && this.m_DrawEntity.has(renderType))
|
||||
{
|
||||
return this.m_DrawEntity.get(renderType);
|
||||
}
|
||||
}
|
||||
Update()
|
||||
{
|
||||
|
||||
}
|
||||
GoodBye()
|
||||
{
|
||||
for (let [, obj] of this.m_DrawEntity)
|
||||
{
|
||||
|
||||
let geo = obj['Geometry']
|
||||
if (geo && geo instanceof THREE.Geometry)
|
||||
{
|
||||
geo.dispose();
|
||||
}
|
||||
obj.parent.remove(obj);
|
||||
}
|
||||
}
|
||||
Erase(isErase: boolean = true)
|
||||
{
|
||||
super.Erase(isErase);
|
||||
if (isErase)
|
||||
{
|
||||
for (let [, en] of this.m_DrawEntity)
|
||||
{
|
||||
en.visible = !isErase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetStretchPoints(): Array<THREE.Vector3>
|
||||
{
|
||||
return []
|
||||
}
|
||||
MoveStretchPoints(indexList: Array<number>, vec: THREE.Vector3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//#region -------------------------File-------------------------
|
||||
//局部撤销
|
||||
ApplyPartialUndo(undoData: CADObject)
|
||||
{
|
||||
super.ApplyPartialUndo(undoData);
|
||||
this.Update();
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,123 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
import { CommandHistoryRecord } from './CommandHistoryRecord';
|
||||
|
||||
//历史记录管理
|
||||
@Factory
|
||||
export class HistoricManage extends CADObject
|
||||
{
|
||||
curIndex: number = -1; //当前执行位置,也就是当前的状态, undo时,撤销当前状态,redo时,应用下一个状态
|
||||
historyRecord: CommandHistoryRecord[] = []; //历史记录
|
||||
private doing: boolean = false;
|
||||
|
||||
constructor()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
let ver = file.Read();
|
||||
this.curIndex = file.Read();
|
||||
this.historyRecord = [];
|
||||
let cout = file.Read();
|
||||
for (let i = 0; i < cout; i++)
|
||||
{
|
||||
this.historyRecord.push(file.ReadObject(this._db) as CommandHistoryRecord);
|
||||
}
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
file.Write(1);
|
||||
file.Write(this.curIndex);
|
||||
file.Write(this.historyRecord.length);
|
||||
for (let rec of this.historyRecord)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this.doing = true;
|
||||
for (let [id, recList] of historyRec.HistoryList)
|
||||
{
|
||||
let obj = id.Object;
|
||||
for (let i = recList.length; i--;)
|
||||
{
|
||||
obj.ApplyPartialUndo(recList[i].undoData);
|
||||
}
|
||||
}
|
||||
this.curIndex--;
|
||||
this.doing = false;
|
||||
return true;
|
||||
}
|
||||
Redo()
|
||||
{
|
||||
let historyRec = this.historyRecord[this.curIndex + 1];
|
||||
if (!historyRec)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this.doing = true;
|
||||
for (let [id, recList] of historyRec.HistoryList)
|
||||
{
|
||||
let obj = id.Object;
|
||||
for (let rec of recList)
|
||||
{
|
||||
obj.ApplyPartialUndo(rec.redoData);
|
||||
}
|
||||
}
|
||||
this.curIndex++;
|
||||
this.doing = false;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
|
||||
/**
|
||||
* 历史记录,用于撤销和重做的数据.
|
||||
*
|
||||
* @class HistoricRecord
|
||||
* @extends {CADObject}
|
||||
*/
|
||||
@Factory
|
||||
export class HistorycRecord extends CADObject
|
||||
{
|
||||
//指定撤销时所需要的数据
|
||||
undoData: CADObject;
|
||||
//制定重做时所需要的数据
|
||||
redoData: CADObject;
|
||||
userData: CADObject;
|
||||
|
||||
//#region -------------------------File-------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
let ver = file.Read();
|
||||
this.undoData = file.ReadObject(this._db);
|
||||
this.redoData = file.ReadObject(this._db);
|
||||
this.userData = file.ReadObject(this._db);
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
file.Write(1);
|
||||
file.WriteObject(this.undoData);
|
||||
file.WriteObject(this.redoData);
|
||||
file.WriteObject(this.userData);
|
||||
}
|
||||
//#endregion
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
//直线对象
|
||||
import { Geometry, Object3D, Vector3 } from 'three';
|
||||
import * as THREE from 'three';
|
||||
|
||||
import { ColorMaterial } from '../Common/ColorPalette';
|
||||
import { RenderType } from '../GraphicsSystem/Enum';
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { Entity } from './Entity';
|
||||
|
||||
@Factory
|
||||
export class Line extends Entity
|
||||
{
|
||||
private startPoint: Vector3;
|
||||
private endPoint: Vector3;
|
||||
constructor(sp?: Vector3, ep?: Vector3)
|
||||
{
|
||||
super();
|
||||
this.startPoint = sp || new Vector3(0, 0, 0);
|
||||
this.endPoint = ep || new Vector3(0, 0, 0);
|
||||
}
|
||||
|
||||
Draw(renderType: RenderType): Object3D
|
||||
{
|
||||
let obj = super.Draw(renderType);
|
||||
if (obj) return obj;
|
||||
|
||||
let geo = new Geometry();
|
||||
geo.vertices.push(this.StartPoint, this.EndPoint);
|
||||
obj = new THREE.Line(geo, ColorMaterial.GetLineMaterial(this.m_Color));
|
||||
this.m_DrawEntity.set(renderType, obj);
|
||||
obj.userData = this;
|
||||
return obj;
|
||||
}
|
||||
|
||||
Update()
|
||||
{
|
||||
for (let [, obj] of this.m_DrawEntity)
|
||||
{
|
||||
let geo = (<THREE.Line>obj).geometry as THREE.Geometry;
|
||||
|
||||
geo.vertices[0].copy(this.startPoint);
|
||||
geo.vertices[1].copy(this.endPoint);
|
||||
|
||||
geo.computeBoundingSphere();
|
||||
|
||||
geo.verticesNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
GetStretchPoints(): Array<THREE.Vector3>
|
||||
{
|
||||
return [this.StartPoint, this.EndPoint]
|
||||
}
|
||||
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
|
||||
{
|
||||
for (let index of indexList)
|
||||
{
|
||||
if (index == 0)
|
||||
this.StartPoint = this.StartPoint.add(vec);
|
||||
else
|
||||
this.EndPoint = this.EndPoint.add(vec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#region -----------------------------File-----------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
super.ReadFile(file);
|
||||
let ver = file.Read();//1
|
||||
this.startPoint.fromArray(file.Read());
|
||||
this.endPoint.fromArray(file.Read());
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
super.WriteFile(file);
|
||||
file.Write(1);//ver
|
||||
file.Write(this.startPoint.toArray());
|
||||
file.Write(this.endPoint.toArray());
|
||||
}
|
||||
//#endregion-----------------------------File End-----------------------------
|
||||
|
||||
//#region 属性
|
||||
set StartPoint(v: Vector3)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this.startPoint.copy(v);
|
||||
|
||||
this.Update();
|
||||
}
|
||||
get StartPoint(): Vector3
|
||||
{
|
||||
return this.startPoint.clone();
|
||||
}
|
||||
|
||||
get EndPoint(): Vector3
|
||||
{
|
||||
return this.endPoint.clone();
|
||||
}
|
||||
set EndPoint(v: Vector3)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this.endPoint.copy(v);
|
||||
this.Update();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { Material } from './Material';
|
||||
import { ObjectCollection } from './ObjectCollection';
|
||||
|
||||
@Factory
|
||||
export class MaerialTableRecord extends ObjectCollection<Material>
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADObject } from './CADObject';
|
||||
|
||||
@Factory
|
||||
export class Material extends CADObject
|
||||
{
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { ObjectId } from './ObjectId';
|
||||
import { HistorycRecord } from './HistorycRecord';
|
||||
import { AllObjectData } from './CADObject';
|
||||
|
||||
|
||||
|
||||
@Factory
|
||||
export class ObjectAllDataHistoryRecord extends HistorycRecord
|
||||
{
|
||||
objId: ObjectId;
|
||||
constructor(id?: ObjectId)
|
||||
{
|
||||
super();
|
||||
this.objId = id;
|
||||
}
|
||||
|
||||
//将数据写入 手动调用
|
||||
WriteUndo()
|
||||
{
|
||||
this.undoData = new AllObjectData(this.objId.Object);
|
||||
}
|
||||
WriteRedo()
|
||||
{
|
||||
this.redoData = new AllObjectData(this.objId.Object);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
import { HistorycRecord } from './HistorycRecord';
|
||||
import { ArrayRemove } from '../Common/Utils';
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { RemoveObjectData } from './RemoveObjectData';
|
||||
import { CADObject } from './CADObject';
|
||||
import { CreateObjectData } from './CreateObjectData';
|
||||
|
||||
|
||||
//对象集合.
|
||||
@Factory
|
||||
export class ObjectCollection<T> extends CADObject
|
||||
{
|
||||
objectCol: CADObject[] = [];
|
||||
|
||||
//添加一个对象进入集合,这个集合存在db中,那么将自动分配id.
|
||||
Append(obj: CADObject)
|
||||
{
|
||||
this.objectCol.push(obj);
|
||||
|
||||
if (this._db && !obj.Id)
|
||||
{
|
||||
obj.InitObjectId(this._db);
|
||||
}
|
||||
|
||||
let undoRec = this.UndoRecord();
|
||||
if (undoRec)
|
||||
{
|
||||
let hisRec = new HistorycRecord();
|
||||
hisRec.redoData = new CreateObjectData(obj);
|
||||
hisRec.undoData = new RemoveObjectData(this.objectCol.length - 1);
|
||||
|
||||
undoRec.WriteObjectHistoryPath(this, hisRec);
|
||||
}
|
||||
|
||||
return obj.Id;
|
||||
}
|
||||
Remove(obj: CADObject)
|
||||
{
|
||||
ArrayRemove(this.objectCol, obj);
|
||||
obj.Erase();
|
||||
obj.GoodBye();
|
||||
let undoRec = this.UndoRecord();
|
||||
if (undoRec)
|
||||
{
|
||||
let hisRec = new HistorycRecord();
|
||||
hisRec.undoData = new CreateObjectData(obj);
|
||||
hisRec.redoData = new RemoveObjectData(this.objectCol.length - 1);
|
||||
|
||||
undoRec.WriteObjectHistoryPath(this, hisRec);
|
||||
}
|
||||
}
|
||||
Cout(): number
|
||||
{
|
||||
return this.objectCol.length;
|
||||
}
|
||||
|
||||
//#region -----------------------------File-----------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
ReadFile(file: CADFile)
|
||||
{
|
||||
super.ReadFile(file);
|
||||
let cout = file.Read();
|
||||
this.objectCol = [];
|
||||
for (let i = 0; i < cout; i++)
|
||||
{
|
||||
let obj = file.ReadObject(this._db);
|
||||
this.objectCol.push(obj);
|
||||
}
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFile)
|
||||
{
|
||||
super.WriteFile(file);
|
||||
file.Write(this.objectCol.length);
|
||||
for (let obj of this.objectCol)
|
||||
{
|
||||
file.WriteObject(obj);
|
||||
}
|
||||
}
|
||||
//局部撤销
|
||||
ApplyPartialUndo(undoData: CADObject)
|
||||
{
|
||||
if (undoData instanceof CreateObjectData)
|
||||
{
|
||||
let obj = undoData.getObject(this._db);
|
||||
this.Append(obj);
|
||||
}
|
||||
else if (undoData instanceof RemoveObjectData)
|
||||
{
|
||||
this.Remove(this.objectCol[undoData.Index]);
|
||||
}
|
||||
}
|
||||
//#endregion -----------------------------File End-----------------------------
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
import { Database } from './Database';
|
||||
import { CADObject } from './CADObject';
|
||||
|
||||
/*
|
||||
CADObject对象拥有Id属性,用来记录引用关系.
|
||||
通过id可以得到对应的关联实体,或者记录实体的关联关系.
|
||||
|
||||
ObjectId必须使用 Database分配(db里面会存id的列表,以便同时更新id指向实体)
|
||||
|
||||
*/
|
||||
export class ObjectId
|
||||
{
|
||||
private id: number;
|
||||
private obj: CADObject;
|
||||
|
||||
//对外隐藏构造函数,如果需要构造一个id,请使用 Create 静态方法.
|
||||
private constructor(index: number = -1, obj?: CADObject)
|
||||
{
|
||||
this.id = index;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
get IsErase(): boolean
|
||||
{
|
||||
return !this.obj || this.obj.IsErase;
|
||||
}
|
||||
/*
|
||||
创建一个id, 如果db中已经存在id,那么自动获得该id,如果不存在,new一个新的id,并且加入到db中
|
||||
该方法的使用场景:
|
||||
1.对象加入到db中时
|
||||
2.对象从数据从读取时.
|
||||
3.对象redo创建时
|
||||
4.引用读取时
|
||||
*/
|
||||
static Create(db: Database, index: number): ObjectId
|
||||
{
|
||||
let id = db.GetObjectId(index);
|
||||
if (!id && index >= 0)
|
||||
{
|
||||
id = new ObjectId(index);
|
||||
db.SetObjectId(index, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
set Object(v: CADObject)
|
||||
{
|
||||
this.obj = v;
|
||||
}
|
||||
get Object(): CADObject
|
||||
{
|
||||
return this.obj;
|
||||
}
|
||||
get Index(): number
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
import { Factory } from './CADFactory';
|
||||
import { CADFile } from './CADFile';
|
||||
import { CADObject } from './CADObject';
|
||||
|
||||
@Factory
|
||||
export class RemoveObjectData extends CADObject
|
||||
{
|
||||
private index: number;
|
||||
constructor(index?: number)
|
||||
{
|
||||
super();
|
||||
this.index = index;
|
||||
}
|
||||
get Index()
|
||||
{
|
||||
return this.index;
|
||||
}
|
||||
|
||||
//#region -----------------------------File-----------------------------
|
||||
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
|
||||
|
||||
//对象从文件中读取数据,初始化自身
|
||||
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-----------------------------
|
||||
}
|
||||
|
Loading…
Reference in new issue