合并分支.

pull/7/head
ChenX 7 years ago
commit e89c81b590

1
.gitignore vendored

@ -60,3 +60,4 @@ typings/
#custom
.vscode
/dist
/package-lock.json

@ -0,0 +1,45 @@
webCAD需要将数据存储在云端,并且本地需要要备份的数据以便快速的检索到数据.
目前暂时需要存储的数据:
1.纹理(纹理的本质是<图片>)
每个用户都可以保存他自己的纹理,用户可以上传新的纹理,我打算将图片存入公共的池中,并且使用md5防止文件重复.
需要注意的是,如果用户删除了自身的图片,那么如果该图片没有人在使用,那么应该尝试将其删除.(与云盘工作原理类似.)
每个用户自身保存的纹理只包含 纹理信息和纹理的文件哈希,如果需要,可以从服务器上检索出图片
用户可以存入自己的纹理列表,以供各个图纸导入.
这里假设文件的校验码为`FileMd5`
Texture:
```
{
fileMd5:"xxxxxxxx"
....//其他数据
}
```
2.材质.
由于最大的数据(图片二进制)已经在纹理中被处理,所有材质列表并不需要保存优化.
材质同纹理一样,用户可以存入自己的材质列表,以供各个图纸导入.
3.外部二进制模型(FBX 等)
同网盘工作模式,使用md5检测碰撞,防止文件重复.
每个图纸文件中,并不会真实的存入fbx的模型信息,而是存入文件校验码,如果需要时,从服务器读取.
4.模版数据
模版数据可以认为是一段数据.可以是json序列化的格式. 数据类型可变,参数个数可变.
5.图纸数据
同模版数据
6.文件备份.
用户在使用应用时,程序会自动尝试备份图纸,并且如有网络资源可以上传到服务器.
7.配置信息.
用户设置的应用配置也应该上传到服务器,保持同步更新.

@ -1,16 +0,0 @@
test("", () =>
{
})
// window["t"] = () =>
// {
// app.m_Database.StartTransaction();
// let line = new Line(new THREE.Vector3(Math.random() * 100, Math.random() * 100), new THREE.Vector3(Math.random() * 100, Math.random() * 100))
// app.m_Database.appendEntity(line);
// app.m_Database.CommitTransaction();
// }

@ -1,33 +0,0 @@
import * as mst from 'mobx-state-tree';
import { EntityData } from '../../src/DatabaseServices/EntityData';
test("Entity", () =>
{
let d = EntityData.create({ size: [0, 1, 2] })
console.log(mst.getSnapshot(d));
console.log(d.getSize());
d.setSize(1, 1, 1000);
console.log(d.getSize());
expect(d.getSize().x).toBe(1);
})
test("not late", () =>
{
let d = EntityData.create({ size: [0, 1, 2] })
console.log(mst.getSnapshot(d));
console.log(d.getSize());
d.setSize(1, 1, 1000);
console.log(d.getSize());
expect(d.getSize().x).toBe(1);
expect(d.getSize().y).toBe(1);
expect(d.getSize().z).toBe(1000);
console.log(typeof d.getSize());
})

@ -1,98 +0,0 @@
import * as console from 'console';
import { autorun } from 'mobx';
import * as mst from 'mobx-state-tree';
import { EntityData, IEntityData, LineData } from '../src/DatabaseServices/EntityData';
class E
{
m_Data: IEntityData;
constructor()
{
this.initData();
autorun(() =>
{
this.eraseT(this.m_Data.isErase);
})
}
initData()
{
this.m_Data = EntityData.create();
console.log("hello e");
}
erase(isErase: boolean)
{
this.m_Data.setErase(isErase);
}
private eraseT(isErase: boolean)
{
console.log(isErase);
}
}
class L extends E
{
constructor()
{
super()
}
initData()
{
this.m_Data = LineData.create();
console.log("hello l");
}
}
{
let l = new L()
let a: (typeof EntityData.SnapshotType) = mst.getSnapshot(l.m_Data);
console.log(mst.getSnapshot(l.m_Data));
let snp = mst.getSnapshot(l.m_Data);
l.erase(true);
l.erase(true);
l.erase(true);
l.erase(true);
l.erase(true);
console.log(l.m_Data.isErase);
mst.applySnapshot(l.m_Data, snp);
console.log(l.m_Data.isErase);
}
function add(a, b)
{
return a + b;
}
//Remove Path
{
const L = mst.types.model(
"Test",
{
lst: mst.types.array(mst.types.number)
})
.actions(self =>
{
return {
remove(a)
{
this.lst.remove(a)
}
}
})
let l = L.create({ lst: [1, 2, 3] })
mst.onPatch(l, (p, rp) =>
{
console.log(p);
})
l.remove(3);
}

@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`changev 1`] = `"[1,2,[\\"BlockTableRecord\\",1,0,1,[\\"Line\\",1,1,2,7,1,[2,3,4],[0,0,0]]],[\\"MaerialTableRecord\\",1,1,0],1,0,1,[\\"CommandHistoryRecord\\",1,\\"\\",2,0,1,[\\"HistorycRecord\\",1,[\\"RemoveObjectData\\",1,0],[\\"CreateObjectData\\",1,[[\\"Line\\",1,1,2,7,1,[0,0,0],[0,0,0]]]],\\"\\"],2,1,[\\"ObjectAllDataHistoryRecord\\",1,1,[\\"AllObjectData\\",1,-1,1,[1,1,2,7,1,[0,0,0],[0,0,0]]],\\"\\",\\"\\",2]]]"`;
exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[1,2,[\\"BlockTableRecord\\",1,0,1,[\\"Line\\",1,1,2,7,1,[1,2,3],[0,0,0]]],[\\"MaerialTableRecord\\",1,1,0],1,1,2,[\\"CommandHistoryRecord\\",1,\\"\\",1,0,1,[\\"HistorycRecord\\",1,[\\"RemoveObjectData\\",1,0],[\\"CreateObjectData\\",1,[[\\"Line\\",1,1,2,7,1,[0,0,0],[0,0,0]]]],\\"\\"]],[\\"CommandHistoryRecord\\",1,\\"U\\",1,2,1,[\\"ObjectAllDataHistoryRecord\\",1,1,[\\"AllObjectData\\",1,-1,1,[1,1,2,7,1,[0,0,0],[0,0,0]]],[\\"AllObjectData\\",1,-1,1,[1,1,2,7,1,[1,2,3],[0,0,0]]],\\"\\",2]]]"`;
exports[`创建 修改 撤销撤销 重做重做 撤销 重做 2`] = `"[[\\"HistoricManage\\",1,1,2,[\\"CommandHistoryRecord\\",1,\\"\\",1,0,1,[\\"HistorycRecord\\",1,[\\"RemoveObjectData\\",1,0],[\\"CreateObjectData\\",1,[[\\"Line\\",1,1,2,7,1,[0,0,0],[0,0,0]]]],\\"\\"]],[\\"CommandHistoryRecord\\",1,\\"U\\",1,2,1,[\\"ObjectAllDataHistoryRecord\\",1,1,[\\"AllObjectData\\",1,-1,1,[1,1,2,7,1,[0,0,0],[0,0,0]]],[\\"AllObjectData\\",1,-1,1,[1,1,2,7,1,[1,2,3],[0,0,0]]],\\"\\",2]]]]"`;
exports[`测试创建 1`] = `"[[\\"AllObjectData\\",1,-1,1,[]]]"`;
exports[`测试创建 2`] = `"[[\\"BlockTableRecord\\",1,-1,0]]"`;
exports[`测试创建 3`] = `"[[\\"CommandHistoryRecord\\",1,null,0]]"`;
exports[`测试创建 4`] = `"[[\\"CreateObjectData\\",1,[]]]"`;
exports[`测试创建 5`] = `"[[\\"HistorycRecord\\",1,\\"\\",\\"\\",\\"\\"]]"`;
exports[`测试创建 6`] = `"[[\\"Line\\",1,1,-1,7,1,[0,0,0],[0,0,0]]]"`;
exports[`测试创建 7`] = `"[[\\"ObjectAllDataHistoryRecord\\",1,1,\\"\\",\\"\\",\\"\\",-1]]"`;
exports[`测试创建 8`] = `"[[\\"RemoveObjectData\\",1,null]]"`;

@ -0,0 +1,187 @@
import * as THREE from 'three';
import { BlockTableRecord } from '../../src/DatabaseServices/BlockTableRecord';
import { CADFactory } from '../../src/DatabaseServices/CADFactory';
import { CADFile } from '../../src/DatabaseServices/CADFile';
import { CommandHistoryRecord } from '../../src/DatabaseServices/CommandHistoryRecord';
import { CreateObjectData } from '../../src/DatabaseServices/CreateObjectData';
import { Database } from '../../src/DatabaseServices/Database';
import { HistorycRecord } from '../../src/DatabaseServices/HistorycRecord';
import { Line } from '../../src/DatabaseServices/Line';
import { ObjectAllDataHistoryRecord } from '../../src/DatabaseServices/ObjectAllDataHistoryRecord';
import { RemoveObjectData } from '../../src/DatabaseServices/RemoveObjectData';
import { CADObject, AllObjectData } from '../../src/DatabaseServices/CADObject';
function CadObjectToString(obj: CADObject)
{
let file = new CADFile();
file.WriteObject(obj)
return file.ToString();
}
test('测试创建', () =>
{
for (let C of [AllObjectData,
BlockTableRecord,
CommandHistoryRecord,
CreateObjectData,
HistorycRecord,
Line,
ObjectAllDataHistoryRecord,
RemoveObjectData,
])
{
console.log(C);
//确保每个对象都被正确的创建
let obj = CADFactory.CreateObject(C.name /*?*/);
let str = CadObjectToString(obj);
console.log(obj.constructor.name);
expect(str).toMatchSnapshot();
//确保对象正确的反序列化
let fileNew = new CADFile();
fileNew.Data = JSON.parse(str);
let objNew = CADFactory.CreateObject(C.name);
let str2 = CadObjectToString(objNew);
//确保反序列化之后的数据是正确的
expect(str).toBe(str2);
}
});
test('id分配', () =>
{
let db = new Database();
let line = new Line();
//对象添加到模型空间 分配id
let id = db.ModelSpace.Append(line);
expect(id != undefined).toBeTruthy();//对象已经被创建,所以id被分配
expect(id.Object === line).toBeTruthy();//对象id指向对象
//撤销添加
db.hm.Undo();
expect(id.IsErase).toBeTruthy(); //对象已经被删除
expect(db.ModelSpace.Cout()).toBe(0); //个数应该为0
//还原对象
db.hm.Redo();
expect(db.ModelSpace.Cout()).toBe(1); //对象还原
expect(!id.IsErase).toBeTruthy(); //id指向的对象不被删除
});
test('clone object', () =>
{
let db = new Database();
let line = new Line();
db.ModelSpace.Append(line);
line.StartPoint = new THREE.Vector3(9, 9, 8);
CadObjectToString(line)/*?*/
let line2 = line.Clone();
CadObjectToString(line2) /*?*/
});
test('changev', () =>
{
let db = new Database();
let l1 = new Line();
let id = db.ModelSpace.Append(l1);
db.hm.Undo();
db.hm.Redo();
expect(id.Object !== l1).toBeTruthy(); //创建对象的撤销和重做后 id指向了新的实体
(id.Object as Line).StartPoint = new THREE.Vector3(2, 3, 4);
let file = db.FileWrite();
expect(file.ToString()/*?*/).toMatchSnapshot();
});
test('xxx', () =>
{
let db = new Database();
db.hm.StartCmd("");
let l1 = new Line();
let l2 = new Line();
let id1 = db.ModelSpace.Append(l1);
let in2 = db.ModelSpace.Append(l2);
db.hm.Undo(); //?
db.hm.Redo(); //?
db.hm.StartCmd("");
db.ModelSpace.Remove(db.GetObjectId(1).Object);
db.hm.Undo(); //?
db.hm.Undo(); //?
db.hm.Redo(); //?
// db.hm.StartCmd("");
(id1.Object as Line).StartPoint = new THREE.Vector3(10, 4, 2);
(id1.Object as Line).EndPoint = new THREE.Vector3(2, 2, 2);
let file = db.FileWrite();
console.log(file.ToString());
db.hm.StartCmd("");
(id1.Object as Line).StartPoint = new THREE.Vector3(100, 300, 400);
(id1.Object as Line).EndPoint = new THREE.Vector3(2000, 3000, 4000);
db.hm.Undo();
db.hm.Redo();
let f = new CADFile();
db.hm.WriteFile(f);
let db2 = new Database();
db2.hm.ReadFile(f);
let f3 = new CADFile();
db2.hm.WriteFile(f3);
expect(f3.ToString()).toBe(f.ToString());//对象序列化反序列化后 数据应该一样
});
test('创建 修改 撤销撤销 重做重做 撤销 重做', () =>
{
let db = new Database();
let line = new Line();
let id = db.ModelSpace.Append(line);
db.hm.StartCmd("U");
line.StartPoint = new THREE.Vector3(1, 2, 3);
db.hm.EndCmd();
db.hm.Undo(); /*?*/
db.hm.Undo();/*?*/
db.hm.Redo();/*?*/
db.hm.Redo();/*?*/
db.hm.Undo();/*?*/
db.hm.Redo();/*?*/
expect(db.FileWrite().ToString()).toMatchSnapshot();
expect(CadObjectToString(db.hm)).toMatchSnapshot();
});

@ -1,15 +0,0 @@
import { GeUtils } from '../../src/Geometry/GeUtils';
import * as THREE from "three";
import { Vector3 } from 'three';
test("测试平行", () =>
{
let v1 = new Vector3(0, 0, 1);
let v2 = new Vector3(0.0001, 0, 1);
expect(GeUtils.isParallelTo(v1, v2)).toBe(false);
expect(v1.equals(new THREE.Vector3(0, 0, 1))).toBe(true);
expect(v2.equals(new THREE.Vector3(0.0001, 0, 1))).toBe(true);
// console.log(v1.isParallelTo(v2));
// console.log(v1);
// console.log(v2);
})

@ -1,19 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`相交测试 1`] = `
Vector3 {
"x": 0.5,
"y": 0,
"z": 0,
}
`;
exports[`相交测试 2`] = `undefined`;
exports[`相交测试 3`] = `
Vector3 {
"x": 0.5,
"y": 5,
"z": 0,
}
`;

@ -1,33 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`测试求向量 1`] = `
Vector3 {
"x": 0,
"y": -1,
"z": 0,
}
`;
exports[`测试求向量 2`] = `
Vector3 {
"x": 0,
"y": -1,
"z": 0,
}
`;
exports[`测试求向量 3`] = `
Vector3 {
"x": 0,
"y": 1,
"z": 0,
}
`;
exports[`测试求向量 4`] = `
Vector3 {
"x": 0.7071067811865475,
"y": 0,
"z": 0.7071067811865475,
}
`;

@ -1,18 +0,0 @@
import { GeUtils } from "../../src/Geometry/GeUtils";
test("GeUtils.angle", () =>
{
let pi2 = Math.PI * 0.5;
let pi4 = pi2 * 0.5;
console.log(GeUtils.fixAngle(0.05, pi2, 0.1)/*?*/ == 0);
console.log(GeUtils.fixAngle(0.08, pi2, 0.1)/*?*/ == 0);
console.log(GeUtils.fixAngle(0.09, pi2, 0.1)/*?*/ == 0);
console.log(GeUtils.fixAngle(-0.05, pi2, 0.1)/*?*/ == Math.PI * 2);
console.log(GeUtils.fixAngle(Math.PI / 2 + 0.01, pi2, 0.1)/*?*/ == Math.PI / 2);
console.log(GeUtils.fixAngle(0.3, pi2));
})

@ -1,32 +0,0 @@
import * as THREE from 'three';
import { Intersect } from '../../src/Geometry/GeUtils';
test('相交测试', () =>
{
let p1 = new THREE.Vector3(0, 0, 0);
let p2 = new THREE.Vector3(1, 0, 0);
let p3 = new THREE.Vector3(0.5, 0.5, 0);
let p4 = new THREE.Vector3(0.5, 1, 0);
let p5 = new THREE.Vector3(3, 0, 0);
let p6 = new THREE.Vector3(6, 0, 0);
let res = Intersect(p1, p2, p3, p4);/*?*/
expect(res).toMatchSnapshot();
res = Intersect(p1, p2, p5, p6);/*?*/
expect(res).toMatchSnapshot();
let ins = Intersect(
new THREE.Vector3(0, 5),
new THREE.Vector3(5, 5),
new THREE.Vector3(0.5, 1),
new THREE.Vector3(0.5, 8));
expect(ins).toMatchSnapshot();
}
)

@ -1,111 +0,0 @@
import * as THREE from 'three';
import { GeUtils } from '../../src/Geometry/GeUtils';
import { Orbit } from '../../src/Geometry/Orbit';
test("", () =>
{
//构造一个控制类.
let orb = new Orbit();
let dir = new THREE.Vector3(0, 1, 0);
orb.UpdateRoValue(dir);
expect(GeUtils.equaln(orb.RoX, 0)).toBe(true);
expect(GeUtils.equaln(orb.RoZ, Math.PI * 0.5)).toBe(true);
//试着还原
orb.UpdateDirection(dir);
expect(GeUtils.equal(dir, new THREE.Vector3(0, 1, 0))).toBe(true);
//试试新的
dir.set(1, 0, 0);
orb.UpdateRoValue(dir);
expect(GeUtils.equaln(orb.RoX, 0)).toBe(true);
expect(GeUtils.equaln(orb.RoZ, 0)).toBe(true);
//试着还原
orb.UpdateDirection(dir);
expect(GeUtils.equal(dir, new THREE.Vector3(1, 0, 0))).toBe(true);
//试试新的
dir.set(0.5, 0.5, 0).normalize();
let dirc = dir.clone();
orb.UpdateRoValue(dir);
//试着还原
orb.UpdateDirection(dir);
console.log('dir: ', dir);
expect(GeUtils.equal(dir, dirc)).toBe(true);
//试试新的
dir.set(0.5, 0.5, 1).normalize();
dirc = dir.clone();
orb.UpdateRoValue(dir);
//试着还原
orb.UpdateDirection(dir);
console.log('dir: ', dir);
expect(GeUtils.equal(dir, dirc)).toBe(true);
dir.set(0, 0, -1);
dirc = dir.clone();
orb.UpdateRoValue(dir);
expect(GeUtils.equaln(orb.RoZ, Math.PI * 0.5)).toBe(true);
expect(GeUtils.equaln(orb.RoX, Math.PI * -0.5)).toBe(true);
//试着还原
orb.UpdateDirection(dir);
console.log('dir: ', dir);
expect(GeUtils.equal(dir, dirc)).toBe(true);
let newDir = orb.UpdateDirection();
console.log('newDir: ', newDir);
let up = Orbit.ComputUpDirection(new THREE.Vector3(0, 0, 1));
expect(GeUtils.equal(up, new THREE.Vector3(0, -1, 0))).toBe(true);
Orbit.ComputUpDirection(new THREE.Vector3(0, 0, -1), up);
console.log(up);
Orbit.ComputUpDirection(new THREE.Vector3(0, 0, 1), up);
console.log(up);
Orbit.ComputUpDirection(new THREE.Vector3(1, 0, 0), up);
let newD = orb.UpdateDirection();
console.log(newD);
expect(GeUtils.equal(newD, new THREE.Vector3(0, 0, -1))).toBe(true);
})
test("测试求向量", () =>
{
let dir = new THREE.Vector3(0, 0, 1);
let up = Orbit.ComputUpDirection(dir);
console.log(up);
expect(up).toMatchSnapshot();
Orbit.ComputUpDirection(dir, up);
console.log(up);
expect(up).toMatchSnapshot();
dir.z = -1;
Orbit.ComputUpDirection(dir, up);
console.log('up: ', up);
expect(up).toMatchSnapshot();
dir.x = 1;
Orbit.ComputUpDirection(dir, up);
console.log('up: ', up);
expect(up).toMatchSnapshot();
})

@ -1,15 +0,0 @@
import * as THREE from 'three';
test('should behave...', () =>
{
let p1 = new THREE.Vector3(0, 0, 0);
let p2 = new THREE.Vector3(1, 0, 0);
let p3 = new THREE.Vector3(0.5, 0.5, 0);
let p4 = new THREE.Vector3(0.5, 1, 0);
});

File diff suppressed because one or more lines are too long

@ -19,23 +19,23 @@
"license": "ISC",
"devDependencies": {
"@types/dat-gui": "^0.6.3",
"@types/jest": "^21.1.8",
"@types/jquery": "^3.2.16",
"@types/lodash": "^4.14.85",
"@types/node": "^8.0.47",
"@types/react": "^16.0.25",
"@types/jest": "^22.0.0",
"@types/jquery": "^3.2.17",
"@types/lodash": "^4.14.91",
"@types/node": "^8.5.2",
"@types/react": "^16.0.31",
"@types/react-dom": "^16.0.3",
"@types/stats.js": "^0.16.1",
"@types/three": "^0.84.33",
"@types/webpack-env": "^1.13.2",
"@types/stats.js": "^0.17.0",
"@types/three": "^0.84.36",
"@types/webpack-env": "^1.13.3",
"add-asset-html-webpack-plugin": "^2.1.2",
"awesome-typescript-loader": "^3.4.0",
"awesome-typescript-loader": "^3.4.1",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.5",
"file-loader": "^1.1.6",
"html-loader": "^0.5.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^21.2.1",
"jest": "^22.0.4",
"jest-environment-node-debug": "^2.0.0",
"less": "^2.7.3",
"less-loader": "^4.0.5",
@ -43,35 +43,35 @@
"open-browser-webpack-plugin": "0.0.5",
"required-loader": "^1.3.16",
"source-map-loader": "^0.2.3",
"style-loader": "^0.19.0",
"ts-jest": "^21.2.3",
"style-loader": "^0.19.1",
"ts-jest": "^22.0.0",
"typed-css-modules": "^0.3.1",
"typescript": "^2.6.2",
"typings": "^2.1.1",
"typings-for-css-modules-loader": "^1.7.0",
"url-loader": "^0.6.2",
"wallaby-webpack": "0.0.45",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4"
"wallaby-webpack": "^3.9.3",
"webpack": "^3.10.0",
"webpack-dev-server": "^2.9.7"
},
"dependencies": {
"@blueprintjs/core": "^1.33.0",
"@types/blueimp-md5": "^2.7.0",
"blueimp-md5": "^2.10.0",
"css-element-queries": "^0.4.0",
"dat.gui": "^0.6.1",
"dat.gui": "^0.6.5",
"golden-layout": "^1.5.9",
"immutable": "^3.8.2",
"jquery": "^3.2.1",
"lodash": "^4.17.4",
"mobx": "^3.3.2",
"mobx": "^3.4.1",
"mobx-react": "^4.3.5",
"mobx-state-tree": "^1.1.0",
"react": "^16.1.1",
"react": "^16.2.0",
"react-addons-css-transition-group": "^15.6.2",
"react-color": "^2.13.8",
"react-dom": "^16.1.1",
"react-dom": "^16.2.0",
"stats.js": "^0.17.0",
"three": "^0.88.0",
"three": "^0.89.0",
"verb-nurbs-web": "^2.1.3",
"xaop": "^1.1.9"
},
@ -84,20 +84,6 @@
"ts",
"tsx",
"js"
],
"moduleNameMapper": {
"dat.gui": "<rootDir>/node_modules/dat.gui/build/dat.gui.js",
"three-FBXLoader": "<rootDir>/src/Loader/FBXLoader.js",
"zlib": "<rootDir>/node_modules/three/examples/js/libs/inflate.min.js",
"three-CopyShader": "<rootDir>/node_modules/three/examples/js/shaders/CopyShader.js",
"three-SMAAShader": "<rootDir>/node_modules/three/examples/js/shaders/SMAAShader.js",
"three-FXAAShader": "<rootDir>/node_modules/three/examples/js/shaders/FXAAShader.js",
"three-OutlinePass": "<rootDir>/src/GraphicsSystem/OutlinePass.js",
"three-EffectComposer": "<rootDir>/node_modules/three/examples/js/postprocessing/EffectComposer.js",
"three-RenderPass": "<rootDir>/node_modules/three/examples/js/postprocessing/RenderPass.js",
"three-ShaderPass": "<rootDir>/node_modules/three/examples/js/postprocessing/ShaderPass.js",
"three-SMAAPass": "<rootDir>/node_modules/three/examples/js/postprocessing/SMAAPass.js",
"three-Reflector": "<rootDir>/src/objects/Reflector.js"
}
]
}
}

@ -1,63 +1,63 @@
//绘制板件
import * as THREE from 'three';
import { app } from '../ApplicationServices/Application';
import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard';
import { MaterialNeedUpdateKey } from '../DatabaseServices/MaterialDictionary';
import { Command } from '../Editor/CommandMachine';
import { Move } from '../Geometry/GeUtils';
export class Command_DrawBoard implements Command
{
async exec()
{
let boardMaterial = new THREE.MeshStandardMaterial({
roughness: 0.3,
color: 0xffffff,
metalness: 0.2,
bumpScale: 0.0005
})
boardMaterial.name = "板"
let textureLoader = new THREE.TextureLoader();
textureLoader.load("textures/019.jpg", function (map)
{
map.wrapS = THREE.MirroredRepeatWrapping;
map.wrapT = THREE.MirroredRepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
boardMaterial.map = map;
boardMaterial.needsUpdate = true;
boardMaterial[MaterialNeedUpdateKey] = true;
});
// let scale = new THREE.Matrix4();
// scale.scale(new THREE.Vector3(0.001, 0.001, 0.001));
let move = Move(new THREE.Vector3(-1, 2.5, 0));
// let mat = move.multiply(scale);
app.m_Database.m_MaterialDictionary.addMaterial(boardMaterial);
for (let i = 0; i < 50; i++)
{
let boardList = CreateBoardUtil.createTemplateBoard();
for (let board of boardList)
{
let br = board as THREE.Mesh;
br.applyMatrix(move);
br.material = boardMaterial;
br.castShadow = true;
br.receiveShadow = true;
app.m_Viewer.m_Scene.add(board);
let move2 = Move(new THREE.Vector3(i * 1, 0, 0));
br.applyMatrix(move2);
}
}
}
}
// //绘制板件
// import * as THREE from 'three';
// import { app } from '../ApplicationServices/Application';
// import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard';
// import { MaterialNeedUpdateKey } from '../DatabaseServices/MaterialDictionary';
// import { Command } from '../Editor/CommandMachine';
// import { Move } from '../Geometry/GeUtils';
// export class Command_DrawBoard implements Command
// {
// async exec()
// {
// let boardMaterial = new THREE.MeshStandardMaterial({
// roughness: 0.3,
// color: 0xffffff,
// metalness: 0.2,
// bumpScale: 0.0005
// })
// boardMaterial.name = "板"
// let textureLoader = new THREE.TextureLoader();
// textureLoader.load("textures/019.jpg", function (map)
// {
// map.wrapS = THREE.MirroredRepeatWrapping;
// map.wrapT = THREE.MirroredRepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// boardMaterial.map = map;
// boardMaterial.needsUpdate = true;
// boardMaterial[MaterialNeedUpdateKey] = true;
// });
// // let scale = new THREE.Matrix4();
// // scale.scale(new THREE.Vector3(0.001, 0.001, 0.001));
// let move = Move(new THREE.Vector3(-1, 2.5, 0));
// // let mat = move.multiply(scale);
// app.m_Database.m_MaterialDictionary.addMaterial(boardMaterial);
// for (let i = 0; i < 50; i++)
// {
// let boardList = CreateBoardUtil.createTemplateBoard();
// for (let board of boardList)
// {
// let br = board as THREE.Mesh;
// br.applyMatrix(move);
// br.material = boardMaterial;
// br.castShadow = true;
// br.receiveShadow = true;
// app.m_Viewer.m_Scene.add(board);
// let move2 = Move(new THREE.Vector3(i * 1, 0, 0));
// br.applyMatrix(move2);
// }
// }
// }
// }

@ -1,401 +1,401 @@
import * as path from 'path';
import * as THREE from 'three';
import { app } from '../ApplicationServices/Application';
import { Solid3d } from '../DatabaseServices/Entity';
import { Command } from '../Editor/CommandMachine';
import { Move } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum';
export class DrawFloor implements Command
{
textureLoader: THREE.TextureLoader;
get scene()
{
return app.m_Viewer.m_Scene;
}
constructor()
{
this.textureLoader = new THREE.TextureLoader();
}
async exec()
{
app.m_Viewer.m_Camera.Camera.position.set(0, 0, 2);
this.drawFloor();
this.drawLight();
this.drawHemiLight();
// this.drawWall();
// this.drawBox();
// //绘制一个盒子 带反射
// this.drawBox2();
this.loadMaterial();
app.m_Viewer.m_Render.toneMappingExposure = Math.pow(0.68, 5.0); // to allow for very bright scenes.
}
async loadFbx()
{
// let obj = await loadFBX("123456.FBX");
// this.scene.add(obj.object);
}
private drawFloor()
{
let floorMat = new THREE.MeshStandardMaterial({
roughness: 0.8,
color: 0xffffff,
metalness: 0.2,
bumpScale: 0.0005,
transparent: true,
opacity: 0.9
});
this.materialList.push(floorMat);
var floorGeometry = new THREE.PlaneBufferGeometry(20, 20);
var floorMesh = new THREE.Mesh(floorGeometry, floorMat);
floorMesh.receiveShadow = true;
this.scene.add(floorMesh);
//使用镜子
let useRef = false;
if (useRef)
{
floorMat.transparent = true;
floorMat.opacity = 0.9
// let ref = new THREE.Reflector(20, 20, {
// clipBias: 0.003,
// textureWidth: app.m_Viewer.Width * window.devicePixelRatio,
// textureHeight: app.m_Viewer.Height * window.devicePixelRatio,
// color: 0x777777
// import * as path from 'path';
// import * as THREE from 'three';
// import { app } from '../ApplicationServices/Application';
// import { Solid3d } from '../DatabaseServices/Entity';
// import { Command } from '../Editor/CommandMachine';
// import { Move } from '../Geometry/GeUtils';
// import { RenderType } from '../GraphicsSystem/Enum';
// export class DrawFloor implements Command
// {
// textureLoader: THREE.TextureLoader;
// get scene()
// {
// return app.m_Viewer.m_Scene;
// }
// constructor()
// {
// this.textureLoader = new THREE.TextureLoader();
// }
// async exec()
// {
// app.m_Viewer.m_Camera.Camera.position.set(0, 0, 2);
// this.drawFloor();
// this.drawLight();
// this.drawHemiLight();
// // this.drawWall();
// // this.drawBox();
// // //绘制一个盒子 带反射
// // this.drawBox2();
// this.loadMaterial();
// app.m_Viewer.m_Render.toneMappingExposure = Math.pow(0.68, 5.0); // to allow for very bright scenes.
// }
// async loadFbx()
// {
// // let obj = await loadFBX("123456.FBX");
// // this.scene.add(obj.object);
// }
// private drawFloor()
// {
// let floorMat = new THREE.MeshStandardMaterial({
// roughness: 0.8,
// color: 0xffffff,
// metalness: 0.2,
// bumpScale: 0.0005,
// transparent: true,
// opacity: 0.9
// });
// this.materialList.push(floorMat);
// ref.position.z = -0.1;
// this.scene.add(ref);
}
}
materialList = [];
loadMaterial()
{
let self = this;
this.textureLoader.load("textures/hardwood2_diffuse.jpg", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(10, 24);
self.materialList.forEach(m =>
{
m.map = map;
m.needsUpdate = true;
})
});
this.textureLoader.load("textures/hardwood2_bump.jpg", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(10, 24);
self.materialList.forEach(m =>
{
(<THREE.MeshStandardMaterial>m).bumpMap = map;
m.needsUpdate = true;
})
});
this.textureLoader.load("textures/hardwood2_roughness.jpg", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(10, 24);
self.materialList.forEach(m =>
{
(<THREE.MeshStandardMaterial>m).roughnessMap = map;
m.needsUpdate = true;
})
});
}
drawLight()
{
var bulbGeometry = new THREE.SphereGeometry(0.02, 16, 8);
let bulbLight = new THREE.PointLight(0x999999, 1, 100, 2);
let bulbMat = new THREE.MeshStandardMaterial({
emissive: 0xffffee,
emissiveIntensity: 1,
color: 0x000000
});
bulbLight.add(new THREE.Mesh(bulbGeometry, bulbMat));
bulbLight.position.set(0, 2, 2);
bulbLight.castShadow = true;
bulbLight.power = 400;
bulbMat.emissiveIntensity = bulbLight.intensity / Math.pow(0.02, 2.0); // convert from intensity to irradiance at bulb surface
this.scene.add(bulbLight);
let light2 = bulbLight.clone();
light2.position.set(-3, -1, 2);
this.scene.add(light2);
// var floorGeometry = new THREE.PlaneBufferGeometry(20, 20);
// var floorMesh = new THREE.Mesh(floorGeometry, floorMat);
// floorMesh.receiveShadow = true;
// this.scene.add(floorMesh);
// //使用镜子
// let useRef = false;
// if (useRef)
// {
// floorMat.transparent = true;
// floorMat.opacity = 0.9
// // let ref = new THREE.Reflector(20, 20, {
// // clipBias: 0.003,
// // textureWidth: app.m_Viewer.Width * window.devicePixelRatio,
// // textureHeight: app.m_Viewer.Height * window.devicePixelRatio,
// // color: 0x777777
// // });
// // ref.position.z = -0.1;
// // this.scene.add(ref);
// }
// }
// materialList = [];
// loadMaterial()
// {
// let self = this;
// var clock = new THREE.Clock();
// xaop.begin(app.m_Viewer, app.m_Viewer.StartRender, () =>
// this.textureLoader.load("textures/hardwood2_diffuse.jpg", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(10, 24);
// self.materialList.forEach(m =>
// {
// var time = Date.now() * 0.0005;
// var delta = clock.getDelta();
// bulbLight.position.z = Math.cos(time) * 0.75 + 1.25;
// app.m_Viewer.m_bNeedUpdate = true;
// m.map = map;
// m.needsUpdate = true;
// })
}
private drawHemiLight()
{
//0xddeeff 0x0f0e0d
var hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.02);
hemiLight.intensity = 3;
this.scene.add(hemiLight);
}
// });
// this.textureLoader.load("textures/hardwood2_bump.jpg", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(10, 24);
// self.materialList.forEach(m =>
// {
// (<THREE.MeshStandardMaterial>m).bumpMap = map;
// m.needsUpdate = true;
// })
// });
// this.textureLoader.load("textures/hardwood2_roughness.jpg", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(10, 24);
drawWall()
{
let floorMat = new THREE.MeshStandardMaterial({
roughness: 0.8,
color: 0xffffff,
metalness: 0.2,
bumpScale: 0.0005
});
this.textureLoader.load("textures/wallmap.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 4;
map.repeat.set(10, 24);
floorMat.map = map;
floorMat.needsUpdate = true;
});
let wallFont = new Solid3d(4, 0.12, 2.8);
let obj = wallFont.Draw(RenderType.Wireframe) as THREE.Mesh;
obj.material = floorMat;
obj.castShadow = true;
obj.receiveShadow = true;
let objLeft = obj.clone();
let objRight = obj.clone();
obj.applyMatrix(Move(new THREE.Vector3(-2.1, 4, 0)));
let roMatLeft = new THREE.Matrix4();
roMatLeft.makeRotationZ(Math.PI / 2);
objLeft.applyMatrix(roMatLeft);
// self.materialList.forEach(m =>
// {
// (<THREE.MeshStandardMaterial>m).roughnessMap = map;
// m.needsUpdate = true;
// })
// });
// }
let roMatRight = new THREE.Matrix4();
roMatRight.makeRotationZ(Math.PI / 2);
objRight.applyMatrix(roMatRight);
// drawLight()
// {
// var bulbGeometry = new THREE.SphereGeometry(0.02, 16, 8);
// let bulbLight = new THREE.PointLight(0x999999, 1, 100, 2);
objLeft.applyMatrix(Move(new THREE.Vector3(-2, 0, 0)))
objRight.applyMatrix(Move(new THREE.Vector3(2, 0, 0)))
// let bulbMat = new THREE.MeshStandardMaterial({
// emissive: 0xffffee,
// emissiveIntensity: 1,
// color: 0x000000
// });
this.scene.add(obj);
this.scene.add(objLeft);
this.scene.add(objRight);
// bulbLight.add(new THREE.Mesh(bulbGeometry, bulbMat));
// bulbLight.position.set(0, 2, 2);
// bulbLight.castShadow = true;
// bulbLight.power = 400;
// bulbMat.emissiveIntensity = bulbLight.intensity / Math.pow(0.02, 2.0); // convert from intensity to irradiance at bulb surface
// this.scene.add(bulbLight);
let skyMaterail = new THREE.MeshStandardMaterial({
roughness: 0.8,
color: 0xffffff,
metalness: 0.2,
bumpScale: 0.0005
})
//天花板.
let skyWall = new Solid3d(4.12, 4, 0.12);
let skyObj = skyWall.Draw(RenderType.Wireframe) as THREE.Mesh;
skyObj.material = skyMaterail;
// let light2 = bulbLight.clone();
// light2.position.set(-3, -1, 2);
// this.scene.add(light2);
// var clock = new THREE.Clock();
// // xaop.begin(app.m_Viewer, app.m_Viewer.StartRender, () =>
// // {
// // var time = Date.now() * 0.0005;
// // var delta = clock.getDelta();
// // bulbLight.position.z = Math.cos(time) * 0.75 + 1.25;
// // app.m_Viewer.m_bNeedUpdate = true;
// // })
// }
// private drawHemiLight()
// {
// //0xddeeff 0x0f0e0d
// var hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.02);
// hemiLight.intensity = 3;
// this.scene.add(hemiLight);
// }
skyObj.applyMatrix(Move(new THREE.Vector3(-2.12, 0, 2.8)));
this.scene.add(skyObj);
}
// drawWall()
// {
// let floorMat = new THREE.MeshStandardMaterial({
// roughness: 0.8,
// color: 0xffffff,
// metalness: 0.2,
// bumpScale: 0.0005
// });
drawBox()
{
let solid = new Solid3d(1.2, 0.05, 2.4);
// this.textureLoader.load("textures/wallmap.png", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 4;
// map.repeat.set(10, 24);
// floorMat.map = map;
// floorMat.needsUpdate = true;
// });
let obj = solid.Draw(RenderType.Wireframe);
obj.castShadow = true;
// let wallFont = new Solid3d(4, 0.12, 2.8);
// let obj = wallFont.Draw(RenderType.Wireframe) as THREE.Mesh;
// obj.material = floorMat;
let mat = new THREE.MeshStandardMaterial({
roughness: 0.8,
color: 0xffffff,
metalness: 0.2,
bumpScale: 0.0005
});
// obj.castShadow = true;
// obj.receiveShadow = true;
this.textureLoader.load("textures/door.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.map = map;
mat.needsUpdate = true;
});
(<THREE.Mesh>obj).material = mat;
// let objLeft = obj.clone();
// let objRight = obj.clone();
this.scene.add(obj);
}
// obj.applyMatrix(Move(new THREE.Vector3(-2.1, 4, 0)));
// let roMatLeft = new THREE.Matrix4();
// roMatLeft.makeRotationZ(Math.PI / 2);
// objLeft.applyMatrix(roMatLeft);
cubemap()
{
var path = "textures/cube/Park2/";
var format = '.jpg';
var urls = [
path + 'posx' + format, path + 'negx' + format,
path + 'posy' + format, path + 'negy' + format,
path + 'posz' + format, path + 'negz' + format
];
var textureCube = new THREE.CubeTextureLoader().load(urls);
textureCube.format = THREE.RGBFormat;
return textureCube;
};
// let roMatRight = new THREE.Matrix4();
// roMatRight.makeRotationZ(Math.PI / 2);
// objRight.applyMatrix(roMatRight);
drawBox2()
{
let solid = new Solid3d(1, 1, 1);
// objLeft.applyMatrix(Move(new THREE.Vector3(-2, 0, 0)))
// objRight.applyMatrix(Move(new THREE.Vector3(2, 0, 0)))
let obj = solid.Draw(RenderType.Wireframe);
// obj = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32));
obj.position.set(0, 0, 1);
// this.scene.add(obj);
// this.scene.add(objLeft);
// this.scene.add(objRight);
obj.castShadow = true;
let cubeCamera1 = new THREE.CubeCamera(0.1, 15, 1024);
let cubeCamera2 = new THREE.CubeCamera(0.1, 15, 1024);
cubeCamera1.position.set(0, 0, 1);
cubeCamera2.position.set(0, 0, 1);
cubeCamera1.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
cubeCamera2.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
cubeCamera1.renderTarget.texture.anisotropy = 16;
cubeCamera2.renderTarget.texture.anisotropy = 16;
// let skyMaterail = new THREE.MeshStandardMaterial({
// roughness: 0.8,
// color: 0xffffff,
// metalness: 0.2,
// bumpScale: 0.0005
// })
// //天花板.
// let skyWall = new Solid3d(4.12, 4, 0.12);
// let skyObj = skyWall.Draw(RenderType.Wireframe) as THREE.Mesh;
// skyObj.material = skyMaterail;
// skyObj.applyMatrix(Move(new THREE.Vector3(-2.12, 0, 2.8)));
this.scene.add(cubeCamera1);
this.scene.add(cubeCamera2);
// this.scene.add(skyObj);
// }
// drawBox()
// {
// let solid = new Solid3d(1.2, 0.05, 2.4);
// let obj = solid.Draw(RenderType.Wireframe);
// obj.castShadow = true;
let mat = new THREE.MeshStandardMaterial({
roughness: 0.8,
metalness: 0.8,
// let mat = new THREE.MeshStandardMaterial({
// roughness: 0.8,
// color: 0xffffff,
// emissive: 0x000000,
emissiveIntensity: 0,
envMap: cubeCamera1.renderTarget.texture,
envMapIntensity: 1
});
this.textureLoader.load("textures/Metal/130616_header2.jpg", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.map = map;
mat.needsUpdate = true;
});
this.textureLoader.load("textures/Metal/Titanium-Scuffed_basecolor.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.map = map;
mat.needsUpdate = true;
});
this.textureLoader.load("textures/Metal/Titanium-Scuffed_roughness.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.roughnessMap = map;
mat.needsUpdate = true;
});
this.textureLoader.load("textures/Metal/Titanium-Scuffed_normal.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.normalMap = map;
mat.needsUpdate = true;
});
this.textureLoader.load("textures/Metal/Titanium-Scuffed_metallic.png", function (map)
{
map.wrapS = THREE.RepeatWrapping;
map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
map.repeat.set(1, 1);
mat.metalnessMap = map;
mat.needsUpdate = true;
});
let isOne = false;
// begin(app.m_Viewer, app.m_Viewer.StartRender, () =>
// {
// obj.visible = false;
// let render = app.m_Viewer.m_Render;
// let scene = app.m_Viewer.m_Scene;
// metalness: 0.2,
// bumpScale: 0.0005
// });
// render.autoClear = true;
// // render.clear();
// if (isOne)
// this.textureLoader.load("textures/door.png", function (map)
// {
// mat.envMap = cubeCamera2.renderTarget.texture;
// cubeCamera2.position.copy(obj.position);
// cubeCamera2.update(render, scene);
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.map = map;
// mat.needsUpdate = true;
// });
// (<THREE.Mesh>obj).material = mat;
// this.scene.add(obj);
// }
// else
// cubemap()
// {
// mat.envMap = cubeCamera1.renderTarget.texture;
// cubeCamera1.position.copy(obj.position);
// cubeCamera1.update(render, scene);
// }
// obj.visible = true;
// isOne = !isOne;
// var path = "textures/cube/Park2/";
// var format = '.jpg';
// var urls = [
// path + 'posx' + format, path + 'negx' + format,
// path + 'posy' + format, path + 'negy' + format,
// path + 'posz' + format, path + 'negz' + format
// ];
// var textureCube = new THREE.CubeTextureLoader().load(urls);
// textureCube.format = THREE.RGBFormat;
// return textureCube;
// };
// drawBox2()
// {
// let solid = new Solid3d(1, 1, 1);
// let obj = solid.Draw(RenderType.Wireframe);
// // obj = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32));
// obj.position.set(0, 0, 1);
// obj.castShadow = true;
// let cubeCamera1 = new THREE.CubeCamera(0.1, 15, 1024);
// let cubeCamera2 = new THREE.CubeCamera(0.1, 15, 1024);
// cubeCamera1.position.set(0, 0, 1);
// cubeCamera2.position.set(0, 0, 1);
// cubeCamera1.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
// cubeCamera2.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
// cubeCamera1.renderTarget.texture.anisotropy = 16;
// cubeCamera2.renderTarget.texture.anisotropy = 16;
// this.scene.add(cubeCamera1);
// this.scene.add(cubeCamera2);
// let mat = new THREE.MeshStandardMaterial({
// roughness: 0.8,
// metalness: 0.8,
// // color: 0xffffff,
// // emissive: 0x000000,
// emissiveIntensity: 0,
// envMap: cubeCamera1.renderTarget.texture,
// envMapIntensity: 1
// });
(<THREE.Mesh>obj).material = mat;
this.scene.add(obj);
}
// this.textureLoader.load("textures/Metal/130616_header2.jpg", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.map = map;
// mat.needsUpdate = true;
// });
loadMaterialNode()
{
}
}
// this.textureLoader.load("textures/Metal/Titanium-Scuffed_basecolor.png", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.map = map;
// mat.needsUpdate = true;
// });
// this.textureLoader.load("textures/Metal/Titanium-Scuffed_roughness.png", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.roughnessMap = map;
// mat.needsUpdate = true;
// });
// this.textureLoader.load("textures/Metal/Titanium-Scuffed_normal.png", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.normalMap = map;
// mat.needsUpdate = true;
// });
// this.textureLoader.load("textures/Metal/Titanium-Scuffed_metallic.png", function (map)
// {
// map.wrapS = THREE.RepeatWrapping;
// map.wrapT = THREE.RepeatWrapping;
// map.anisotropy = 16;
// map.repeat.set(1, 1);
// mat.metalnessMap = map;
// mat.needsUpdate = true;
// });
// let isOne = false;
// // begin(app.m_Viewer, app.m_Viewer.StartRender, () =>
// // {
// // obj.visible = false;
// // let render = app.m_Viewer.m_Render;
// // let scene = app.m_Viewer.m_Scene;
// // render.autoClear = true;
// // // render.clear();
// // if (isOne)
// // {
// // mat.envMap = cubeCamera2.renderTarget.texture;
// // cubeCamera2.position.copy(obj.position);
// // cubeCamera2.update(render, scene);
// // }
// // else
// // {
// // mat.envMap = cubeCamera1.renderTarget.texture;
// // cubeCamera1.position.copy(obj.position);
// // cubeCamera1.update(render, scene);
// // }
// // obj.visible = true;
// // isOne = !isOne;
// // });
// (<THREE.Mesh>obj).material = mat;
// this.scene.add(obj);
// }
// loadMaterialNode()
// {
// }
// }

@ -1,11 +1,12 @@
import * as THREE from 'three';
import { Vector3 } from 'three';
import { app } from '../ApplicationServices/Application';
import { Circle, Line, Solid3d } from '../DatabaseServices/Entity';
import { Circle } from '../DatabaseServices/Circle';
import { Line } from '../DatabaseServices/Line';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
import { RenderType } from '../GraphicsSystem/Enum';
import { UndoData } from '../DatabaseServices/UndoData';
export class DrawLine implements Command
{
@ -38,8 +39,12 @@ export class DrawLine implements Command
if (ptRes.Status == PromptStatus.OK)
{
p2 = ptRes.Value;
let line = new Line(p1, p2);
app.m_Database.appendEntity(line);
let line = new Line();
line.ColorIndex = i++;
line.StartPoint = p1;
line.EndPoint = p2;
app.m_Database.ModelSpace.Append(line);
pts.push(p1);
@ -54,7 +59,7 @@ export class DrawLine implements Command
{
if (lastLines.length > 0)
{
app.m_Database.removeEntityId(lastLines[lastLines.length - 1].objectId);
app.m_Database.ModelSpace.Remove(lastLines[lastLines.length - 1]);
lastLines.pop();
p1 = pts[pts.length - 1];
@ -135,7 +140,7 @@ void main() {
}
*/
export class DrawRect implements Command
console.log(); export class DrawRect implements Command
{
async exec()
{
@ -154,10 +159,10 @@ export class DrawRect implements Command
let l3 = new Line(p1.clone(), p1.clone());
let l4 = new Line(p1.clone(), p1.clone());
app.m_Database.appendEntity(l1);
app.m_Database.appendEntity(l2);
app.m_Database.appendEntity(l3);
app.m_Database.appendEntity(l4);
app.m_Database.ModelSpace.Append(l1);
app.m_Database.ModelSpace.Append(l2);
app.m_Database.ModelSpace.Append(l3);
app.m_Database.ModelSpace.Append(l4);
app.m_Editor.AddNoSnapEntity(l1.Draw(RenderType.Wireframe));
app.m_Editor.AddNoSnapEntity(l2.Draw(RenderType.Wireframe));
@ -173,17 +178,17 @@ export class DrawRect implements Command
let px3 = box.max;
let px2 = new THREE.Vector3(px3.x, px1.y);
let px4 = new THREE.Vector3(px1.x, px3.y);
l1.setStartPoint(px1);
l1.setEndPoint(px2);
l1.StartPoint = (px1);
l1.EndPoint = (px2);
l2.setStartPoint(px2);
l2.setEndPoint(px3);
l2.StartPoint = (px2);
l2.EndPoint = (px3);
l3.setStartPoint(px3);
l3.setEndPoint(px4);
l3.StartPoint = (px3);
l3.EndPoint = (px4);
l4.setStartPoint(px1);
l4.setEndPoint(px4);
l4.StartPoint = (px1);
l4.EndPoint = (px4);
}
ptRes = await app.m_Editor.GetPoint({
@ -203,14 +208,14 @@ export class DrawCircle implements Command
{
async exec()
{
let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 10);
let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 1e-3);
app.m_Editor.m_CommandStore.Prompt("指定圆的圆心:");
app.m_Editor.UpdateScreen();
let ptRes = await app.m_Editor.GetPoint({
Msg: "指定圆的圆心",
Callback: (p) =>
{
cir.m_Center.copy(p);
cir.Center = p;
},
KeyWordList: [{ key: "3P", msg: "三点" }, { key: "2P", msg: "二点" }, { key: "T", msg: "切点、切点、半径" }]
});
@ -219,7 +224,7 @@ export class DrawCircle implements Command
return;
}
app.m_Database.appendEntity(cir);
app.m_Database.ModelSpace.Append(cir);
app.m_Editor.AddNoSnapEntity(cir.Draw(RenderType.Wireframe));
@ -231,11 +236,13 @@ export class DrawCircle implements Command
BasePoint: ptRes.Value,
Callback: (p) =>
{
cir.Radius = p.distanceTo(cir.m_Center);
cir.Radius = p.distanceTo(cir.Center);
},
AllowDrawRubberBand: true
}
);
app.m_Database.hm.EndCmd();
}
}
@ -243,17 +250,17 @@ export class DrawTest implements Command
{
async exec()
{
for (let i = 0; i < 5000; i++)
{
let box = new Solid3d(1, 1, 1);
// for (let i = 0; i < 5000; i++)
// {
// let box = new Solid3d(1, 1, 1);
let obj = box.Draw(RenderType.Wireframe);
// let obj = box.Draw(RenderType.Wireframe);
obj.position.set(Math.random() * 1000, Math.random() * 1000, Math.random() * 1000, );
// obj.position.set(Math.random() * 1000, Math.random() * 1000, Math.random() * 1000, );
// app.m_Database.appendEntity(box);
app.m_Viewer.m_Scene.add(obj);
}
// // app.m_Database.appendEntity(box);
// app.m_Viewer.m_Scene.add(obj);
// }
}
}

@ -1,7 +1,8 @@
import * as THREE from 'three';
import { app } from '../ApplicationServices/Application';
import { Circle, Line } from '../DatabaseServices/Entity';
import { Circle } from '../DatabaseServices/Circle';
import { Line } from '../DatabaseServices/Line';
import { Command } from '../Editor/CommandMachine';
export class DrawCircle0 implements Command
@ -9,7 +10,7 @@ export class DrawCircle0 implements Command
async exec()
{
let cir = new Circle(new THREE.Vector3(0, 0, 0), 10);
app.m_Database.appendEntity(cir);
app.m_Database.ModelSpace.Append(cir);
let p = new THREE.Vector3(0, 0, 0);
@ -17,10 +18,8 @@ export class DrawCircle0 implements Command
app.m_Viewer.WorldToScreen(p);
app.m_Viewer.ScreenToWorld(p);
let line = new Line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(100, 0, 0));
app.m_Database.appendEntity(line);
app.m_Database.ModelSpace.Append(line);
}
}

@ -0,0 +1,19 @@
import { Command } from "../Editor/CommandMachine";
import { app } from "../ApplicationServices/Application";
import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore";
import { CADFile } from "../DatabaseServices/CADFile";
export class Open implements Command
{
async exec()
{
let store = await IndexedDbStore.CADStore();
let file = await store.Get(StoreName.Dwg, "1");
let cadF = new CADFile();
cadF.Data = file;
app.m_Database.FileRead(cadF);
}
}

@ -1,70 +0,0 @@
import * as THREE from 'three';
import { app } from '../ApplicationServices/Application';
import { Line } from '../DatabaseServices/Entity';
import { Command } from '../Editor/CommandMachine';
import { RenderType } from '../GraphicsSystem/Enum';
import { Viewer } from '../GraphicsSystem/Viewer';
import { CameraControl } from '../GraphicsSystem/CameraControl';
let bufferTexture: THREE.WebGLRenderTarget;
let render: THREE.WebGLRenderer;
export class SaveTarget implements Command
{
async exec()
{
// bufferTexture = new THREE.WebGLRenderTarget(app.m_Viewer.Width, app.m_Viewer.Height);
// app.m_Viewer.m_Render.render(app.m_Viewer.m_Scene, app.m_Viewer.m_Camera.m_CurCamera, bufferTexture);
let el = document.getElementById("Webgl");
let can = document.createElement("canvas");
can.style.position = "absolute"
can.style.zIndex = "100px";
can.style.pointerEvents = "none";
can.style.width = "100%";
can.style.height = "100%";
can.style.left = "0px";
can.style.top = "0px";
el.appendChild(can);
render = new THREE.WebGLRenderer({ canvas: can, clearColor: 0, alpha: true })
render.setSize(app.m_Viewer.Width, app.m_Viewer.Height);
}
}
export class RevTarget implements Command
{
async exec()
{
let scene = new THREE.Scene();
let line = new Line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(100, 0, 0));
scene.add(line.Draw(RenderType.Wireframe));
render.render(scene, app.m_Viewer.m_Camera.Camera);
}
}
/**
*
*
* @class CursorViewer
*/
class CursorViewer
{
private m_Scene = new THREE.Scene();
private m_Camera: CameraControl;
constructor(view: Viewer)
{
this.m_Camera = new CameraControl();
}
}

@ -0,0 +1,15 @@
import { Command } from "../Editor/CommandMachine";
import { app } from "../ApplicationServices/Application";
import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore";
export class Save implements Command
{
async exec()
{
let cadFile = app.m_Database.FileWrite();
let store = await IndexedDbStore.CADStore();
store.Put(StoreName.Dwg, "1", cadFile.Data);
}
}

@ -2,6 +2,7 @@ import { Callback } from 'awesome-typescript-loader/dist/paths-plugin';
import * as THREE from 'three';
import { app } from '../ApplicationServices/Application';
import { Entity } from '../DatabaseServices/Entity';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
import { SelectBox } from '../Editor/SelectBox';
@ -70,18 +71,17 @@ export class Stretch implements Command
}
else
{
for (let obj of set.m_SelectList)
{
let indexArr = [];
stretchPtsIndexMap.set(obj, indexArr);
let geo = obj["geometry"];
if (geo && geo instanceof THREE.Geometry)
let en = obj.userData;
if (en && en instanceof Entity)
{
for (let i = 0; i < geo.vertices.length; i++)
let pts = en.GetStretchPoints();
for (let i = pts.length; i--;)
{
let p = geo.vertices[i].clone();
p.applyMatrix4(obj.matrix);
let p = pts[i];
set.WorldToScreenPoint(p);
if (set.ContainerScreenPoint(p))
{
@ -89,21 +89,6 @@ export class Stretch implements Command
}
}
}
else if (geo && geo instanceof THREE.BufferGeometry)
{
let positions: Float32Array = geo.attributes["position"].array;
let ptCout = positions.length / 3;
for (let i = 0; i < ptCout; i++)
{
let p = new THREE.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
let sp = p.clone();
set.WorldToScreenPoint(sp);
if (set.ContainerScreenPoint(sp))
{
indexArr.push(i);
}
}
}
}
}
}
@ -122,102 +107,9 @@ export class Stretch implements Command
}
for (let [obj, arr] of d.str)
{
let geo = obj["geometry"];
if (geo instanceof THREE.Geometry)
{
for (let i of arr)
{
geo.vertices[i].applyMatrix4(moveMat);
}
geo.verticesNeedUpdate = true;
geo.computeBoundingSphere();
}
else if (geo instanceof THREE.BufferGeometry)
{
let positions: Float32Array = geo.attributes["position"].array;
for (let i of arr)
{
let p = new THREE.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
p.applyMatrix4(moveMat);
positions[i * 3] = p.x;
positions[i * 3 + 1] = p.y;
positions[i * 3 + 2] = p.z;
}
geo.computeBoundingSphere();
}
}
}
stretch(ss: SelectSet, vec: THREE.Vector3)
{
let moveMat = Move(vec);
for (let set of ss.SelectSetList)
{
if (set instanceof SelectPick)
{
for (let obj of set.m_SelectList)
{
obj.applyMatrix(moveMat);
}
set.m_SelectList
}
else if (set instanceof SelectBox)
{
if (set.m_SelectType == SelectType.W)
{
for (let obj of set.m_SelectList)
{
obj.applyMatrix(moveMat);
}
}
else
{
for (let obj of set.m_SelectList)
{
let geo = obj["geometry"];
if (geo && geo instanceof THREE.Geometry)
{
for (let ver of geo.vertices)
{
let p = ver.clone();
p.applyMatrix4(obj.matrix);
set.WorldToScreenPoint(p);
if (set.ContainerScreenPoint(p))
{
ver.applyMatrix4(moveMat);
}
}
geo.verticesNeedUpdate = true;
geo.computeBoundingSphere();
}
else if (geo && geo instanceof THREE.BufferGeometry)
{
let positions: Float32Array = geo.attributes["position"].array;
let ptCout = positions.length / 3;
for (let i = 0; i < ptCout; i++)
{
let p = new THREE.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
let sp = p.clone();
set.WorldToScreenPoint(sp);
if (set.ContainerScreenPoint(sp))
if (obj.userData instanceof Entity)
{
p.applyMatrix4(moveMat);
positions[i * 3] = p.x;
positions[i * 3 + 1] = p.y;
positions[i * 3 + 2] = p.z;
}
}
geo.attributes["position"].needsUpdate = true;
geo.computeBoundingSphere();
}
}
}
obj.userData.MoveStretchPoints(arr, vec);
}
}
}

@ -5,7 +5,8 @@ export class Undo implements Command
{
async exec()
{
app.m_Undo.undo(1);
app.m_Database.hm.Undo();
app.m_Editor.UpdateScreen();
}
}
@ -14,6 +15,7 @@ export class Redo implements Command
{
async exec()
{
app.m_Undo.redo(1);
app.m_Database.hm.Redo();
app.m_Editor.UpdateScreen();
}
}

@ -15,6 +15,6 @@ export class ViewToFont implements Command
{
async exec()
{
app.m_Viewer.ViewToFont();
app.m_Viewer.ViewToFront();
}
}

@ -1,6 +1,7 @@
import * as THREE from 'three';
import * as xaop from 'xaop';
import { KeyBoard } from '../Common/KeyEnum';
import { Database } from '../DatabaseServices/Database';
import { CameraControls } from '../Editor/CameraControls';
import { commandMachine } from '../Editor/CommandMachine';
@ -11,7 +12,6 @@ import { SnapDrag } from '../Editor/SnapDrag';
import { SnapServices } from '../GraphicsSystem/SnapServices';
import { Viewer } from '../GraphicsSystem/Viewer';
import { layoutOnsizeEvent } from '../UI/Layout/LayoutOnSizeEventManage';
import { UndoData } from '../DatabaseServices/UndoData';
export var app: ApplicationService
export var ed: Editor
@ -29,7 +29,6 @@ export class ApplicationService
m_Database: Database;
m_Viewer: Viewer;
m_Editor: Editor;
m_Undo: UndoData;
constructor()
{
ApplicationService.Application = this;
@ -100,7 +99,24 @@ export class ApplicationService
db = this.m_Database
window["app"] = this;
this.m_Undo = new UndoData(this);
//撤销 重做
xaop.begin(app.m_Editor.m_KeyCtrl, app.m_Editor.m_KeyCtrl.OnKeyDown, (e: KeyboardEvent) =>
{
if (app.m_Editor.m_KeyCtrl.KeyIsDown(KeyBoard.Control))
{
if (e.keyCode == KeyBoard.KeyZ)
{
app.m_Database.hm.Undo();
app.m_Viewer.m_GripScene.UpdateAll();
}
else if (e.keyCode == KeyBoard.KeyY)
{
app.m_Database.hm.Redo();
app.m_Viewer.m_GripScene.UpdateAll();
}
app.m_Editor.UpdateScreen();
}
})
}
static Application: ApplicationService;
}
@ -139,7 +155,7 @@ window["viewtop"] = function ()
window["viewfont"] = function ()
{
app.m_Viewer.ViewToFont();
app.m_Viewer.ViewToFront();
}

@ -143,56 +143,4 @@ export namespace CreateBoardUtil
return boardList;
}
//TODO:TestCode 以后做到另外一个测试部分
// export function test()
// {
// var points = []
// points.push(new THREE.Vector2(100, 0));
// points.push(new THREE.Vector2(100, 60));
// points.push(new THREE.Vector2(40, 90));
// points.push(new THREE.Vector2(-40, 90));
// points.push(new THREE.Vector2(-100, 60));
// points.push(new THREE.Vector2(-100, 0));
// // var path = new THREE.LineCurve3(new THREE.Vector3(45, 0, 0), new THREE.Vector3(-45, 0, 0));
// var extrusionSettings = {
// steps: 1,
// bevelEnabled: false,
// amount: 90
// };
// var shape = new THREE.Shape(points);
// var geometry = new THREE.ExtrudeGeometry(shape, extrusionSettings);
// var loader: THREE.TextureLoader = new THREE.TextureLoader();
// var url = require("file-loader?!../textures/017.jpg");
// var texture: THREE.Texture = loader.load(require("file-loader?!../textures/UV_Grid_Sm.jpg"));
// texture.wrapS = texture.wrapT = THREE.RepeatWrapping; // CHANGED
// texture.offset.set(0, 0.01); // CHANGED
// texture.repeat.set(0.001, 0.001); // CHANGED
// texture.needsUpdate = true;
// var material = new THREE.MeshBasicMaterial({
// color: 0xFF00FF,
// map: texture
// });
// // add a wireframe to highlight the segmentation
// var mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, [material, new THREE.MeshBasicMaterial({
// color: 0x000000,
// // wireframe: true,
// transparent: true
// })]);
// mesh.position.z = -50;
// mesh.position.y = -40;
// mesh.rotation.y = 0.8;
// mesh.rotation.z = 0.4;
// }
}

@ -1,5 +1,5 @@
import * as THREE from 'three';
export let ColorPalette = [
const ColorPalette = [
[255, 0, 0, 255], //----- 0 - lets make it red for an example
//[255, 255, 255, 255],//----- 0 - ByBlock - White
[255, 0, 0, 255], //----- 1 - Red
@ -265,32 +265,24 @@ export let ColorPalette = [
];
var colorMatBuff = new Map<number, THREE.Material>();
export function GetColorIndex(index: number)
//颜色材质,对于二维图像来说可能有用,应该不对三维对象使用该材质
export class ColorMaterial
{
if (colorMatBuff.has(index))
private constructor() { }
private static m_LineMaterialMap = new Map<number, THREE.LineBasicMaterial>();
static GetLineMaterial(index): THREE.LineBasicMaterial
{
return colorMatBuff.get(index);
}
let colorRgb = ColorPalette[index];
let colorx = new THREE.Color(colorRgb[0] / 255, colorRgb[1] / 255, colorRgb[2] / 255);
console.log(colorx.getHex());
let mat = new THREE.MeshStandardMaterial(
{
color: colorx,
// side: THREE.DoubleSide,
// roughness: 0.7,
// bumpScale: 0.2,
// metalness: 0.8
}
);
colorMatBuff.set(index, mat);
if (this.m_LineMaterialMap.has(index))
return this.m_LineMaterialMap.get(index);
let mat = new THREE.LineBasicMaterial({ color: this.GetColor(index) });
this.m_LineMaterialMap.set(index, mat);
return mat;
}
export function GetColorFormIndex(index: number)
static GetColor(index: number)
{
let colorRgb = ColorPalette[index];
let colorx = new THREE.Color(colorRgb[0]/255, colorRgb[1]/255, colorRgb[2]/255);
return colorx;
let rgb = ColorPalette[index];
if (rgb)
return new THREE.Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255);
}
}

@ -357,7 +357,7 @@ export class FileSystem
* @param {String} filter File type filter
* @param {String} saveas Save as format can be also a boolean value
*/
static chooseFile(onLoad: (files: FileList) => any, filter: string, saveas: boolean)
static chooseFile(onLoad: (files: FileList) => any, filter: string, saveas: boolean = false)
{
var chooser = document.createElement("input");
chooser.type = "file";

@ -1,11 +1,13 @@
//鼠标类型
export enum MouseKey {
export enum MouseKey
{
Left = 0,
Middle = 1,
Right = 2,
}
export enum KeyBoard {
export enum KeyBoard
{
// 数字
Digit1 = 49,
Digit2 = 50,
@ -43,7 +45,7 @@ export enum KeyBoard {
KeyW = 87,
KeyX = 88,
KeyY = 89,
KeyZ = 0,
KeyZ = 90,
// 符号
/**

@ -0,0 +1,21 @@
import md5 = require("blueimp-md5")
//计算文件的md5值
export function blobMd5(blob: Blob): Promise<string>
{
return new Promise<string>(res =>
{
let fr = new FileReader();
fr.onload = e =>
{
res(md5(fr.result));
}
fr.onerror = e =>
{
res("")
}
fr.readAsArrayBuffer(blob);
})
}

@ -1,7 +1,6 @@
import { app } from '../ApplicationServices/Application';
export function log(msg)
export async function log(msg)
{
let app = (await import("../ApplicationServices/Application")).app;
app.m_Editor.m_CommandStore.Prompt(msg);
}

@ -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,91 @@
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)
{
if (!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, this.objectId);
}
//局部撤销
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, id: ObjectId)
{
if (id)
{
file.Write(id.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,123 @@
import { EllipseCurve, Geometry, 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 Circle extends Entity
{
constructor(center?: Vector3, radius?: number)
{
super();
this.m_Center = center ? center.clone() : new Vector3();
this.m_Radius = radius ? radius : 1e-6;
}
private m_Center: Vector3;
private m_Radius: number;
get Center()
{
return this.m_Center.clone();
}
set Center(v: Vector3)
{
this.WriteAllObjectRecord();
this.m_Center.copy(v);
}
get Radius()
{
return this.m_Radius;
}
set Radius(v: number)
{
this.WriteAllObjectRecord();
this.m_Radius = v;
this.Update();
}
Draw(renderType: RenderType): THREE.Object3D
{
let obj = super.Draw(renderType);
if (obj) return obj;
let curve = new EllipseCurve(
this.m_Center.x, this.m_Center.y, // ax, aY
this.m_Radius, this.m_Radius, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
let geometry = new Geometry().setFromPoints(curve.getPoints(60));
let circleObj = new THREE.Line(geometry, ColorMaterial.GetLineMaterial(this.m_Color));
this.m_DrawEntity.set(renderType, circleObj);
circleObj.userData = this;
return circleObj;
}
Update()
{
for (let [, obj] of this.m_DrawEntity)
{
let geo = obj["geometry"] as Geometry;
let curve = new EllipseCurve(
this.m_Center.x, this.m_Center.y, // ax, aY
this.m_Radius, this.m_Radius, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
geo.setFromPoints(curve.getPoints(60));
geo.verticesNeedUpdate = true;
geo.computeBoundingSphere();
}
}
GetStretchPoints(): Array<Vector3>
{
return [
this.m_Center.clone().add(new Vector3(0, this.m_Radius)),
this.m_Center.clone().add(new Vector3(0, -this.m_Radius)),
this.m_Center.clone().add(new Vector3(-this.m_Radius, 0)),
this.m_Center.clone().add(new Vector3(this.m_Radius, 0)),
]
}
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{
let pts = this.GetStretchPoints()
if (indexList.length > 0)
{
let p = pts[indexList[0]];
if (p)
{
p.add(vec);
this.Radius = p.distanceTo(this.m_Center);
}
}
}
//#region -------------------------File-------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFile)
{
super.ReadFile(file);
let ver = file.Read();
this.m_Center.fromArray(file.Read());
this.m_Radius = file.Read();
}
//对象将自身数据写入到文件.
WriteFile(file: CADFile)
{
super.WriteFile(file);
file.Write(1);
file.Write(this.m_Center.toArray());
file.Write(this.m_Radius);
}
//#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-----------------------------
}

@ -1,143 +1,97 @@
import * as mst from 'mobx-state-tree';
import { IJsonPatch } from 'mobx-state-tree';
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';
import { ed } from '../ApplicationServices/Application';
import { Entity } from './Entity';
import { DataBaseData, IDataBaseData, ISnapDatabaseData } from './EntityData';
import { MaterialDictionary } from './MaterialDictionary';
import { Transaction } from './Transaction';
//材质字典
/**
* ,,.
* View
*
* -1.(id)Id.
* -2.(id)
* -3......
*
* @export
* @class Database
*/
@Factory
export class Database
{
m_Data: IDataBaseData
//场景
m_EntityCollection: Map<number, Entity> = new Map<number, Entity>();//图形集合
id: ObjectId;
hm: HistoricManage;
//块表记录
blockTableCol: BlockTableRecord[];
//模型空间
ModelSpace: BlockTableRecord;
//材质字典...
MaterialDict: MaerialTableRecord;
m_MaterialDictionary: MaterialDictionary;
constructor()
{
this.initData();
}
initData()
{
this.m_MaterialDictionary = new MaterialDictionary();
private idCout = -1;
private idMap = new Map<number, ObjectId>();
this.m_Data = DataBaseData.create();
mst.onPatch(this.m_Data, (patch: IJsonPatch, reversePatch: IJsonPatch) =>
{
if (patch.op == "add")
{
this.addEntityId(patch.value);
}
else if (patch.op == "remove")
constructor()
{
this.removeEntityId(reversePatch.value);
}
})
}
this.id = ObjectId.Create(this, -100);
dataIn(data: ISnapDatabaseData)
{
mst.applySnapshot(this.m_Data, data);
}
dataOut(): ISnapDatabaseData
{
return mst.getSnapshot(this.m_Data);
}
this.ModelSpace = new BlockTableRecord();
this.ModelSpace.InitObjectId(this);
this.MaterialDict = new MaerialTableRecord();
this.MaterialDict.InitObjectId(this);
//添加图元到数据对象
appendEntity(ent: Entity)
{
if (ent.objectId != 0)
{
console.warn("已经分配ID的图形不允许再次加入数据库!");
return;
this.hm = new HistoricManage();
this.hm.SetDefaultDb(this);
}
ent.m_Db = this;
ent.objectId = this.m_Data.allocateId();
if (ent.objectId != this.m_EntityCollection.size)
{
for (var id = ent.objectId; id < this.m_EntityCollection.size; id++)
Destroy()
{
this.disposeEntity(id);
}
}
this.m_EntityCollection.set(ent.objectId, ent);
this.m_Data.addEntity(ent.objectId);
ed.UpdateScreen();
}
getEntity(id: number): Entity
{
if (this.m_EntityCollection.has(id))
{
return this.m_EntityCollection.get(id);
}
return null;
this.idMap.clear();
}
addEntityId(id: number)
FileWrite(): CADFile
{
let file = new CADFile();
file.Write(1);//ver;
file.Write(this.idCout);
file.WriteObject(this.ModelSpace);
file.WriteObject(this.MaterialDict);
this.hm.WriteFile(file);
return file;
}
//删除
removeEntityId(ent: number)
FileRead(file: CADFile)
{
this.Destroy();
let ver = file.Read();
this.idCout = file.Read();
file.ReadObject(this, this.ModelSpace);
file.ReadObject(this, this.MaterialDict);
this.hm.ReadFile(file);
}
disposeEntity(id: number)
//创建一个id,自动递增它的索引号,并且会自动加入到db的id列表中.
AllocateId(obj: CADObject): ObjectId
{
let ent = this.getEntity(id);
if (ent)
if (obj.Db.id === this.id)
// if (obj.Db === this)
{
this.m_EntityCollection.delete(id);
this.idCout++;
let id = ObjectId.Create(this, this.idCout);
id.Object = obj;
return id;
}
else
console.warn("警告:对象不属于该数据库!");
}
/*
private , ObjectId使.
/**
* id
*
* @returns {Array<number>}
* @memberof Database
id, id, , 使 ObjectId.Create,,使,AllocateId
*/
getObjectIdCollection(): Array<number>
GetObjectId(index: number): ObjectId
{
return this.m_Data.idColl;
}
getEntityCollection(): Array<Entity>
{
let res = []
this.m_EntityCollection.forEach((ent, id) =>
{
res.push(ent);
})
return res;
// return this.m_Data.idColl.map(id =>
// {
// return this.getEntity(id);
// }).filter(e =>
// {
// return e
// })
return this.idMap.get(index);
}
StartTransaction(): Transaction
{
let ts = new Transaction(this);
return ts;
}
CommitTransaction()
{
/*
private , ObjectId使.
idid. Objectid.Cretes使.
*/
SetObjectId(index: number, id: ObjectId)
{
if (this.idMap.has(index))
console.warn("警告:尝试加入已经存在的id!");
this.idMap.set(index, id);
}
}

@ -1,314 +1,101 @@
import { autorun } from 'mobx';
import * as mst from 'mobx-state-tree';
//所有图元的基类
import * as THREE from 'three';
import { Vector3 } from 'three';
import { Move } from '../Geometry/GeUtils';
import { OBB } from '../Geometry/OBB/obb';
import { RenderType } from '../GraphicsSystem/Enum';
import { Database } from './Database';
import { EntityData, IEntityData, ILineData, iSnapshotEntityData, LineData } from './EntityData';
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
import { CADObject } from './CADObject';
import { ObjectId } from './ObjectId';
export class Entity
@Factory
export class Entity extends CADObject
{
/**
* Db
*
* @type {Database}
* @memberof Entity
*/
m_Db: Database;
protected m_DrawEntity = new Map<RenderType, THREE.Object3D>();
//材质id
protected m_MaterialId: ObjectId;
protected m_Color: number = 7;
/**
*
*
* @protected
* @type {IEntityData}
* @memberof Entity
*/
protected m_Data: IEntityData;
/**
* .
*
* @protected
* @type {Map<RenderType, THREE.Object3D>}
* @memberof Entity
*/
protected m_DrawEntity: Map<RenderType, THREE.Object3D> = new Map<RenderType, THREE.Object3D>();
constructor()
set ColorIndex(v: number)
{
this.initData();
this.m_Color = v;
this.Update();
}
/**
*
* @param data
*/
dataIn(data: iSnapshotEntityData)
get ColorIndex(): number
{
mst.applySnapshot(this.m_Data, data);
}
dataOut(): iSnapshotEntityData
{
return mst.getSnapshot(this.m_Data);
return this.m_Color;
}
Draw(renderType: RenderType): THREE.Object3D
{
return null;
}
get objectId(): number
{
return this.m_Data.objectId;
}
set objectId(id: number)
{
this.m_Data.setObjectId(id);
}
get Size()
{
return this.m_Data.getSize();
}
set Size(v: THREE.Vector3)
{
this.m_Data.setSize(v.x, v.y, v.z);
}
initData()
{
this.m_Data = EntityData.create();
}
erase(isErase)
//绘制一个threeJs对象.
Draw(renderType: RenderType = RenderType.Wireframe): THREE.Object3D
{
this.m_Data.setErase(isErase);
}
getBox(): THREE.Box3
if (this.m_DrawEntity && this.m_DrawEntity.has(renderType))
{
let box = new THREE.Box3();
// box.setFromObject(this.m_ThreeObj);
return box;
return this.m_DrawEntity.get(renderType);
}
getStretchPoints(): Array<THREE.Vector3>
{
return []
}
getOBB(): OBB
{
let obb = new OBB();
let size = this.Size;
// obb.m_CoordinateSystem.copyForm(this.m_ThreeObj.matrix);
obb.m_CoordinateSystem.m_Postion.sub(obb.m_CoordinateSystem.m_xAxis.clone().multiplyScalar(size.x * 0.5));
obb.m_CoordinateSystem.m_Postion.sub(obb.m_CoordinateSystem.m_yAxis.clone().multiplyScalar(size.y * 0.5));
obb.m_CoordinateSystem.m_Postion.sub(obb.m_CoordinateSystem.m_zAxis.clone().multiplyScalar(size.z * 0.5));
obb.halfSizes.copy(size)
return obb;
}
applyMatrix4(mat: THREE.Matrix4)
{
this.m_DrawEntity.forEach(e =>
{
e.applyMatrix(mat);
})
}
setIsSelct(bool: boolean)
//你必须重载该方法来更新绘制,在撤销重做时会自动调用该方法.
Update()
{
}
}
export class Curve extends Entity
{
constructor()
{
super();
}
}
export class Line extends Curve
GoodBye()
{
constructor(startPt?: THREE.Vector3, endPt?: THREE.Vector3)
for (let [, obj] of this.m_DrawEntity)
{
super();
let data = <ILineData>this.m_Data;
if (startPt)
let geo = obj['Geometry']
if (geo && geo instanceof THREE.Geometry)
{
data.setStartPoint(startPt);
if (endPt)
data.setEndPoint(endPt);
geo.dispose();
}
obj.parent.remove(obj);
}
initData()
{
this.m_Data = LineData.create();
}
private getData(): ILineData
Erase(isErase: boolean = true)
{
return <ILineData>this.m_Data;
}
Draw(renderType: RenderType): THREE.Object3D
super.Erase(isErase);
if (isErase)
{
if (this.m_DrawEntity.has(renderType))
for (let [, en] of this.m_DrawEntity)
{
return this.m_DrawEntity.get(renderType);
}
//创建几何体
var geometry = new THREE.Geometry();
let sp = this.getData().StartPoint;
let ep = this.getData().EndPoint;
geometry.vertices.push(sp);
geometry.vertices.push(ep);
//TODO:创建材质..明显重复的
var material = new THREE.LineBasicMaterial();
let threeObject: THREE.Object3D = new THREE.Line(geometry, material);
this.m_DrawEntity.set(renderType, threeObject);
//事件注入.
autorun(() =>
{
sp.copy(this.getData().StartPoint);
ep.copy(this.getData().EndPoint);
geometry.verticesNeedUpdate = true;
geometry.computeBoundingSphere();
})
return threeObject;
}
GetGripPoints(): Array<Vector3>
{
return [this.StartPoint, this.EndPoint];
}
getStretchPoints(): Array<THREE.Vector3>
{
return [this.StartPoint, this.EndPoint];
en.visible = !isErase;
}
get StartPoint(): THREE.Vector3
{
return (<ILineData>this.m_Data).StartPoint;
}
get EndPoint(): THREE.Vector3
{
return (<ILineData>this.m_Data).EndPoint;
}
//http://jsfiddle.net/hjx3rLmt/1/
setStartPoint(pt: THREE.Vector3)
{
this.getData().setStartPoint(pt);
}
setEndPoint(pt: THREE.Vector3)
{
this.getData().setEndPoint(pt);
}
}
export class Circle extends Curve
GetStretchPoints(): Array<THREE.Vector3>
{
m_Radius: number;
m_Center: THREE.Vector3;
constructor(center: THREE.Vector3, radius: number)
{
super();
this.m_Center = center;
this.m_Radius = radius;
return []
}
set Center(v: THREE.Vector3)
MoveStretchPoints(indexList: Array<number>, vec: THREE.Vector3)
{
this.m_Center.copy(v);
this.m_DrawEntity.forEach(obj =>
{
let curve = new THREE.EllipseCurve(
this.m_Center.x, this.m_Center.y, // ax, aY
this.m_Radius, this.m_Radius, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
let geometry = new THREE.Geometry().setFromPoints(curve.getPoints(50));
(<THREE.Line>obj).geometry = geometry;
})
}
set Radius(r: number)
{
this.m_Radius = r;
this.m_DrawEntity.forEach(obj =>
{
(<THREE.Line>obj).geometry.dispose();
let curve = new THREE.EllipseCurve(
this.m_Center.x, this.m_Center.y, // ax, aY
this.m_Radius, this.m_Radius, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
let geometry = new THREE.Geometry().setFromPoints(curve.getPoints(60));
(<THREE.Line>obj).geometry = geometry;
})
}
Draw(renderType: RenderType = RenderType.Wireframe): THREE.Object3D
{
if (this.m_DrawEntity.has(renderType))
{
return this.m_DrawEntity.get(renderType);
}
let curve = new THREE.EllipseCurve(
this.m_Center.x, this.m_Center.y, // ax, aY
this.m_Radius, this.m_Radius, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
let geometry = new THREE.Geometry().setFromPoints(curve.getPoints(60));
var material = new THREE.LineBasicMaterial({ color: 0xff0000 });
var ellipse = new THREE.Line(geometry, material);
this.m_DrawEntity.set(renderType, ellipse);
return ellipse;
}
}
//#region -------------------------File-------------------------
export class Solid3d extends Entity
{
constructor(len: number, wid: number, hei: number)
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFile)
{
super();
this.Size = new THREE.Vector3(len, wid, hei);
let ver = file.Read();
super.ReadFile(file);
this.m_Color = file.Read();
}
applyMatrix4(mat: THREE.Matrix4)
//对象将自身数据写入到文件.
WriteFile(file: CADFile)
{
super.applyMatrix4(mat);
// Entity.prototype.applyMatrix4.call(this,mat)
file.Write(1);
super.WriteFile(file);
file.Write(this.m_Color);
}
Draw(renderType: RenderType): THREE.Object3D
{
if (this.m_DrawEntity.has(renderType))
//局部撤销
ApplyPartialUndo(undoData: CADObject)
{
return this.m_DrawEntity.get(renderType);
}
let geometry = new THREE.BoxGeometry(this.Size.x, this.Size.y, this.Size.z);
let mesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial);
mesh.applyMatrix(Move(this.Size.clone().multiplyScalar(0.5)));
this.m_DrawEntity.set(renderType, mesh);
return mesh;
super.ApplyPartialUndo(undoData);
this.Update();
}
//#endregion
}
export class Point extends Entity
{
m_Postion: THREE.Vector3 = new THREE.Vector3()
constructor()
{
super()
}
}

@ -1,123 +0,0 @@
import * as mst from 'mobx-state-tree';
import * as THREE from "three";
const PointData = mst.types.optional(mst.types.array(mst.types.number), [0, 0, 0]);
type IPointData = typeof PointData.Type;
function toVec3(vec: IPointData): THREE.Vector3
{
return new THREE.Vector3(vec[0], vec[1], vec[2]);
}
export const EntityData = mst.types.model(
"Entity",
{
size: PointData,
isErase: false,
objectId: mst.types.optional(mst.types.number, 0)
})
.views(self =>
{
return {
getSize(): THREE.Vector3
{
return toVec3(self.size);
},
}
})
.actions(self =>
{
return {
setSize(x, y, z)
{
self.size.replace([x, y, z]);
},
setErase(isErase: boolean)
{
self.isErase = isErase;
},
afterCreate()
{
},
setObjectId(id: number)
{
self.objectId = id;
}
}
})
export type IEntityData = typeof EntityData.Type;
export type iSnapshotEntityData = typeof EntityData.SnapshotType;
export const CurveData = EntityData.named("Curve");
export const LineData = mst.types.compose(
CurveData,
mst.types.model(
{
startPoint: PointData,
entPoint: PointData
})
.views(self =>
{
return {
get StartPoint(): THREE.Vector3
{
return toVec3(self.startPoint);
},
get EndPoint(): THREE.Vector3
{
return toVec3(self.entPoint)
}
}
})
.actions(self =>
{
return {
setStartPoint(pt: THREE.Vector3)
{
self.startPoint.replace(pt.toArray());
},
setEndPoint(pt: THREE.Vector3)
{
self.entPoint.replace(pt.toArray());
},
}
})
).named("Line");
export type ILineData = typeof LineData.Type;
export const DataBaseData = mst.types.model(
"Database",
{
/**
* 使ID
*/
idColl: mst.types.optional(mst.types.array(mst.types.number), []),
/**
*
*/
curLength: mst.types.optional(mst.types.number, 0)
})
.actions(self =>
{
return {
addEntity(id: number)
{
self.idColl.push(id);
},
removeEntity(id: number)
{
self.idColl.remove(id);
},
allocateId(): number
{
self.curLength++;
return self.curLength
}
}
})
export type IDataBaseData = typeof DataBaseData.Type;
export type ISnapDatabaseData = typeof DataBaseData.SnapshotType;

@ -0,0 +1,109 @@
/*
webCAD .
,,.
ID
.
1..
2..
3..
4.,.
5.
6..
?
db.AppendEntity(ent);
,.
,
###
->
....
undo:, Remove
redo:. A
->
undo:. P
redo:. P
->
undo:. P
redo: P
:,()
R:.
A,P. .
A P P P A P P
| A .
.
A A A A
A.
:.
:,.()
,,.
.
A (insert new A).
A (update A.redo)
cmdName:"Line" //对象的创建命令
[
Object1:[C]//对象保留的创建的记录
]
cmdName:"Move" //对象修改命令
[
Object1:[P],
ObjectN:[P],
ObjectM:[P],
...
]
cmdName:"Ohther" //假设这个是一个复杂度很高的命令
[
Object1:[A,P,A,P,A,P,P,P],.
ObjectN:[A,P,A,P,A,P,P,P],
ObjectM:[C,P,P,P,P] ,C
...
]
A
2A,Aundo
A,P.
A,undo,redo.,redo.
C:
C,P.
A ,UNDO,redo,,redo
:id.
,idid.
ObjectId.
id..
:id.
,id.
,,.
,,.
*/

@ -0,0 +1,124 @@
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
import { CADObject } from './CADObject';
import { CommandHistoryRecord } from './CommandHistoryRecord';
//TODO:对于空的新建命令,应该支持不清空后续命令. 比如切换相机或者切换视图.
//历史记录管理
@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();
let cout = file.Read();
this.historyRecord = [];
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();
if (lastRec.HistoryList.size === 0)
{
this.historyRecord.pop();
this.curIndex--;
}
}
}
Undo(): boolean
{
this.EndCmd();
let historyRec = this.historyRecord[this.curIndex];
if (!historyRec)
return false;
this.doing = true;
for (let [id, recList] of historyRec.HistoryList)
{
for (let i = recList.length; i--;)
{
id.Object.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)
{
for (let rec of recList)
{
id.Object.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,117 @@
//直线对象
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 lineObj = (<THREE.Line>obj);
lineObj.material = ColorMaterial.GetLineMaterial(this.ColorIndex);
let geo = lineObj.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,13 @@
import { observable } from 'mobx';
import { Factory } from './CADFactory';
import { Material } from './Material';
import { ObjectCollection } from './ObjectCollection';
@Factory
export class MaerialTableRecord extends ObjectCollection<Material>
{
@observable
objectCol: Material[] = [];
}

@ -0,0 +1,7 @@
import { Factory } from './CADFactory';
import { CADObject } from './CADObject';
@Factory
export class Material extends CADObject
{
}

@ -1,5 +1,3 @@
import { autorun, extendObservable, observable } from 'mobx';
import { Material } from 'three';
import * as THREE from 'three';
@ -11,18 +9,17 @@ export const MaterialNeedUpdateKey = "needUpdateImg";
export class MaterialDictionary
{
@observable
MaterialDict: Map<number, Material>;
MaterialDict: Map<number, THREE.Material>;
MaterialCallback: Map<number, any>;
private _cout = 0;//Id 分配器.
constructor()
{
this.MaterialDict = new Map<number, Material>();
this.MaterialDict = new Map<number, THREE.Material>();
this.MaterialCallback = new Map<number, any>();
}
//添加材质..
addMaterial(mat: Material)
addMaterial(mat: THREE.Material)
{
this.extendObservable(mat, this._cout);
this.MaterialDict.set(this._cout, mat);
@ -34,39 +31,39 @@ export class MaterialDictionary
mat.name = "材质" + this._cout;
this.addMaterial(mat);
}
extendObservable(mat: Material, id: number)
extendObservable(mat: THREE.Material, id: number)
{
let mobxData: Object = {};
// let mobxData: Object = {};
mobxData[MaterialNeedUpdateKey] = true;
// mobxData[MaterialNeedUpdateKey] = true;
let colorList = ["color"]
for (let key of colorList)
{
let newKey = "mobx_" + key;
mobxData[newKey] = "#" + (mat[key] as THREE.Color).getHexString();
}
for (let d of ["name", "transparent", "roughness", "metalness", "opacity", "depthTest", "map", "bumpMap", "bumpScale", "roughnessMap"])
{
mobxData[d] = mat[d];
}
// let colorList = ["color"]
// for (let key of colorList)
// {
// let newKey = "mobx_" + key;
// mobxData[newKey] = "#" + (mat[key] as THREE.Color).getHexString();
// }
// for (let d of ["name", "transparent", "roughness", "metalness", "opacity", "depthTest", "map", "bumpMap", "bumpScale", "roughnessMap"])
// {
// mobxData[d] = mat[d];
// }
mobxData["useMap"] = false;
// mobxData["useMap"] = false;
extendObservable(mat, mobxData);
// extendObservable(mat, mobxData);
let mobxRemove = autorun(() =>
{
for (let key of colorList)
{
(mat[key] as THREE.Color).set(mat["mobx_" + key])
}
})
// let mobxRemove = autorun(() =>
// {
// for (let key of colorList)
// {
// (mat[key] as THREE.Color).set(mat["mobx_" + key])
// }
// })
this.MaterialCallback.set(id, mobxRemove);
// this.MaterialCallback.set(id, mobxRemove);
}
getMaterial(id: number): Material
getMaterial(id: number): THREE.Material
{
return this.MaterialDict.get(Number(id));
}

@ -0,0 +1,57 @@
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
import { AllObjectData, CADObject } from './CADObject';
import { HistorycRecord } from './HistorycRecord';
import { ObjectId } from './ObjectId';
@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);
}
//#region -------------------------File-------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//类名,保证序列化时得到正确的new
get ClassName(): string
{
return "CADObject";
}
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFile)
{
let ver = file.Read();
super.ReadFile(file);
this.objId = this.ReadObjectId(file);
}
//对象将自身数据写入到文件.
WriteFile(file: CADFile)
{
file.Write(1);
super.WriteFile(file);
this.WriteObjectId(file, this.objId);
}
//局部撤销
ApplyPartialUndo(undoData: CADObject)
{
}
//#endregion
}

@ -0,0 +1,103 @@
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)
{
if (this._db && !obj.Id)
{
obj.InitObjectId(this._db);
}
this.objectCol.push(obj);
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);
}
}
Destroy()
{
this.objectCol.length = 0;
}
Cout(): number
{
return this.objectCol.length;
}
//#region -----------------------------File-----------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFile)
{
this.Destroy();
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';
/*
CADObjectId,.
id,.
ObjectId使 Database(dbid,便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, dbid,id,,newid,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,82 @@
import * as THREE from 'three';
import { Factory } from './CADFactory';
import { Material } from './Material';
import { ObjectId } from './ObjectId';
import { DbTexture } from './Texture';
import { autorun, observable } from 'mobx';
import * as xaop from 'xaop';
/**
* ,,db.three.material
*
* @export
* @class PhysicalMaterial
* @extends {Material}
*/
@Factory
export class DbPhysicalMaterial extends Material
{
@observable name: string = "测试";//名称
@observable color: string = "0";
@observable transparent: boolean = true; //透明度 0-1
@observable matalness: number = 0.8;//金属性 0-1
@observable opacity: number = 1;//不透明度.
@observable depthTest: boolean = true;//深度测试
@observable map: ObjectId;//纹理贴图
@observable bumpMap: ObjectId;//凹凸贴图
@observable bumpScale: number = 0.5;//凹凸比例
@observable roughnessMap: ObjectId;//粗糙贴图
@observable roughness: number = 0.8; //粗糙度
private material: THREE.MeshPhysicalMaterial;
constructor()
{
super();
autorun(() =>
{
this.name;
this.color;
this.transparent;
this.matalness;
this.opacity.toExponential;
this.depthTest;
this.map;
this.bumpMap;
this.bumpScale;
this.roughnessMap;
this.roughness;
this.Update();
})
}
Update()
{
}
get Material(): THREE.MeshPhysicalMaterial
{
if (!this.material)
{
this.material = new THREE.MeshPhysicalMaterial({});
xaop.end(this, this.Update, () =>
{
this.material.color = new THREE.Color(this.color);
this.material.transparent = this.transparent;
this.material.metalness = this.matalness;
this.material.opacity = this.opacity;
this.material.depthTest = this.depthTest;
this.material.bumpScale = this.bumpScale;
this.material.roughness = this.roughness;
this.material.map = this.map ? (this.map.Object as DbTexture).GetThreeTexture() : undefined;
this.material.bumpMap = this.bumpMap ? (this.bumpMap.Object as DbTexture).GetThreeTexture() : undefined;
this.material.roughnessMap = this.roughnessMap ? (this.roughnessMap.Object as DbTexture).GetThreeTexture() : undefined;
this.material.needsUpdate = true;
})
}
return this.material;
}
}

@ -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-----------------------------
}

@ -0,0 +1,44 @@
import * as THREE from 'three';
import { Factory } from './CADFactory';
import { CADObject } from './CADObject';
import { loaderImage, loaderImageFromMd5 } from '../Loader/ImageLoader';
/**
* ..
*
* @export
* @class Texture
* @extends {CADObject}
*/
@Factory
export class DbTexture extends CADObject
{
name: string;
wrapS: THREE.Wrapping = THREE.RepeatWrapping;//横向(水平)平铺
wrapT: THREE.Wrapping = THREE.RepeatWrapping;//竖向(垂直)平铺
repeat: THREE.Vector2 = new THREE.Vector2(1, 1);//重复
rotate: number = 0;//旋转
imageMd5: string; //使用md5保存贴图
private texture: THREE.Texture = new THREE.Texture();
constructor()
{
super();
}
async Update()
{
if (this.imageMd5) this.texture.image = await (loaderImageFromMd5(this.imageMd5));
this.texture.wrapS = THREE.RepeatWrapping;
this.texture.wrapT = THREE.RepeatWrapping;
this.texture.anisotropy = 16;
this.texture.repeat.set(10, 24);
this.texture.format = THREE.RGBFormat;
this.texture.needsUpdate = true;
}
GetThreeTexture()
{
return this.texture;
}
}

@ -1,4 +1,4 @@
import { Database } from './Database';
import { Database } from "./Database";
/**
*

@ -1,72 +0,0 @@
import * as xaop from 'xaop';
import { app, ApplicationService } from '../ApplicationServices/Application';
import { commandMachine } from '../Editor/CommandMachine';
import { ISnapDatabaseData } from './EntityData';
export class UndoData
{
m_App: ApplicationService;
m_UndoDataList: Array<ISnapDatabaseData> = [];
m_UndoIndex = 0;//0表示当前状态
constructor(app: ApplicationService)
{
this.m_App = app;
let ed = app.m_Editor;
this.m_UndoDataList.push(app.m_Database.dataOut())//初始化空状态
xaop.end(commandMachine, commandMachine.CommandEnd, (name) =>
{
if (name == "u" || name == "redo")
{
}
else
{
this.createUndoData();
}
})
xaop.end(app.m_Database, app.m_Database.CommitTransaction, () =>
{
this.createUndoData();
})
}
createUndoData()
{
let remove;
if (this.m_UndoIndex > 0)
{
this.m_UndoDataList = this.m_UndoDataList.splice(0, this.m_UndoDataList.length - this.m_UndoIndex);
}
this.m_UndoIndex = 0;
this.m_UndoDataList.push(app.m_Database.dataOut())
}
undo(cout: number)
{
let index = this.m_UndoIndex + 1;
if (index < this.m_UndoDataList.length)
{
this.m_UndoIndex = index;
app.m_Database.dataIn(this.m_UndoDataList[this.m_UndoDataList.length - index - 1]);
app.m_Editor.UpdateScreen();
}
}
redo(cout: number)
{
let index = this.m_UndoIndex - 1;
if (index < this.m_UndoDataList.length - 1 && index >= 0)
{
this.m_UndoIndex = index;
app.m_Database.dataIn(this.m_UndoDataList[this.m_UndoDataList.length - index - 1]);
app.m_Editor.UpdateScreen();
}
}
}

@ -160,7 +160,7 @@ export class CameraControls
}
case MouseKey.Middle:
{
if (this.m_KeyDown.get(KeyBoard.Shift))
if (this.m_KeyDown.get(KeyBoard.Control))
{
this.beginRotate();
}
@ -189,7 +189,7 @@ export class CameraControls
changeVec.set(event.movementX, event.movementY, 0);
if (
(this.m_LeftUseRotate ||
(this.m_KeyDown.get(KeyBoard.Shift))
(this.m_KeyDown.get(KeyBoard.Control))
)
&& this.m_State == CameraControlState.Rotate
)

@ -13,9 +13,14 @@ export class CommandMachine
private m_CommandNameList = new Set<string>();
async ExecCommand(cmdName: string)
{
app.m_Editor.m_SelectCtrl.EndSelect();
if (this.m_CommandList.has(cmdName))
{
if (cmdName !== "SAVE")
{
app.m_Database.hm.StartCmd(cmdName);
}
app.m_Editor.m_SelectCtrl.EndSelect();
let ss = app.m_Editor.m_SelectCtrl.SelectSet;
this.m_CommandIng = true;
app.m_Editor.m_CommandStore.isCmdIng = true;

@ -1,12 +1,12 @@
import { Command_DrawBoard } from '../Add-on/DrawBoard';
import { DrawFloor } from '../Add-on/DrawFloor';
// import { Command_DrawBoard } from '../Add-on/DrawBoard';
// import { DrawFloor } from '../Add-on/DrawFloor';
import { DrawGripStretch } from '../Add-on/DrawGripStretch';
import { DrawCircle, DrawLine, DrawRect, DrawSphere, DrawTest, ZoomE } from '../Add-on/DrawLine';
import { DrawCircle0 } from '../Add-on/DrawZeroCircle';
import { Command_Erase } from '../Add-on/Erase';
import { Fbx } from '../Add-on/loadfbx';
import { Command_Move } from '../Add-on/Move';
import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
import { Command_Rotate } from '../Add-on/Rotate';
import { Stretch } from '../Add-on/Stretch';
import { Command_SwitchCamera } from '../Add-on/SwitchCamera';
@ -16,6 +16,8 @@ import { Redo, Undo } from '../Add-on/Undo';
import { ViewToFont, ViewToTop } from '../Add-on/ViewChange';
import { commandMachine } from './CommandMachine';
import { Union } from '../Add-on/CSGUnion';
import { Save } from '../Add-on/Save';
import { Open } from '../Add-on/Open';
export function registerCommand()
{
@ -32,13 +34,13 @@ export function registerCommand()
commandMachine.RegisterCommand("sp", new DrawSphere())
commandMachine.RegisterCommand("fl", new DrawFloor())
// commandMachine.RegisterCommand("fl", new DrawFloor())
commandMachine.RegisterCommand("cc", new Command_SwitchCamera())
commandMachine.RegisterCommand("p", new Command_SwitchPass())
commandMachine.RegisterCommand("e", new Command_Erase())
commandMachine.RegisterCommand("br", new Command_DrawBoard())
// commandMachine.RegisterCommand("br", new Command_DrawBoard())
commandMachine.RegisterCommand("c0", new DrawCircle0())
@ -60,4 +62,11 @@ export function registerCommand()
commandMachine.RegisterCommand("uni", new Union())
commandMachine.RegisterCommand("save", new Save());
commandMachine.RegisterCommand("open", new Open());
// commandMachine.RegisterCommand("st", new SaveTarget())
// commandMachine.RegisterCommand("rt", new RevTarget())
}

@ -1,6 +1,6 @@
//用户交互编辑工具
import { Vector3 } from 'three';
import * as THREE from 'three';
import { Vector3 } from 'three';
import * as xaop from 'xaop';
import { app, ApplicationService } from '../ApplicationServices/Application';

@ -4,7 +4,6 @@ import * as xaop from 'xaop';
import { app } from '../ApplicationServices/Application';
import { GetPointPrompt, InputState } from '../Common/InputState';
import { MouseKey, KeyBoard } from '../Common/KeyEnum';
import { Line } from '../DatabaseServices/Entity';
import { angle, equaln, fixAngle, Intersect } from '../Geometry/GeUtils';
import { PromptPointResult, PromptStatus } from './PromptResult';
@ -208,7 +207,7 @@ export class GetPointServices
{
for (let l of this.m_SnapAxisBlueLine)
{
app.m_Viewer.m_PreViewer.Scene.remove(l);
l.parent.remove(l);
l.geometry.dispose();
}
this.m_SnapAxisBlueLine = [];

@ -1,10 +1,10 @@
import { observable, autorun } from 'mobx';
import { MaterialEditorCamerControl } from './MaterialMouseControl';
import { boolean } from 'mobx-state-tree/dist/types/primitives';
import { Viewer } from '../GraphicsSystem/Viewer';
import { autorun } from 'mobx';
import * as THREE from 'three';
import * as xaop from 'xaop';
import { Material } from 'three';
import { DbPhysicalMaterial } from '../DatabaseServices/PhysicalMaterial';
import { Viewer } from '../GraphicsSystem/Viewer';
import { MaterialEditorCamerControl } from './MaterialMouseControl';
/**
*
@ -16,7 +16,6 @@ export class MaterialEditor
m_Geometrys: Map<string, THREE.Geometry | THREE.BufferGeometry>;
@observable
m_CurGeometryName = "球";
m_Canvas: HTMLElement;
m_ShowObject: THREE.Object3D;
@ -107,9 +106,9 @@ export class MaterialEditor
scene.add(point);
}
setMaterial(mat: Material)
setMaterial(mat: DbPhysicalMaterial)
{
this.m_ShowMesh.material = mat;
this.m_ShowMesh.material = mat.Material;
}
dispose()

@ -7,6 +7,7 @@ import { SelectSetBase, SelectType } from './SelectSet';
/**
*
* ,.
*
* @export
* @class SelectBox

@ -3,6 +3,7 @@ import { end } from 'xaop';
import { app } from '../ApplicationServices/Application';
import { KeyBoard, MouseKey } from '../Common/KeyEnum';
import { Entity } from '../DatabaseServices/Entity';
import { GripScene } from '../GraphicsSystem/GripScene';
import { Viewer } from '../GraphicsSystem/Viewer';
import { SelectMarquee } from '../UI/JsPlugin/SelectMarquee';
@ -93,21 +94,22 @@ export class SelectControls
{
return;
}
for (let pts of app.m_Viewer.m_GripScene.children)
for (let ptsObj of app.m_Viewer.m_GripScene.children)
{
if (pts instanceof THREE.Points)
if (ptsObj instanceof THREE.Points)
{
let geo = pts.geometry as THREE.Geometry;
for (let i = 0; i < geo.vertices.length; i++)
let en = ptsObj.userData.userData as Entity;
let pts = en.GetStretchPoints();
for (let i = 0; i < pts.length; i++)
{
let ptC = geo.vertices[i].clone();
let ptC = pts[i];
app.m_Viewer.WorldToScreen(ptC);
if (ptC.distanceToSquared(mouseCtrl.m_CurMousePointVCS) < 100)
{
app.m_Viewer.m_PreViewer.m_LastSnapPoint = ptC;
app.m_Viewer.m_PreViewer.m_LastEntity = pts.userData;
app.m_Viewer.m_PreViewer.m_LastEntity = ptsObj.userData;
app.m_Viewer.m_PreViewer.m_LastIndex = i;
return;
@ -128,40 +130,34 @@ export class SelectControls
{
this.removeSnap();
app.m_Database.hm.StartCmd("drag");
app.m_Viewer.m_GripScene.Clear();
app.m_Viewer.m_bNeedUpdate = true;
app.m_Editor.m_CommandStore.commandPrompt = "拽拖开始:";
let en = app.m_Viewer.m_PreViewer.m_LastEntity as THREE.Mesh;
app.m_Editor.AddNoSnapEntity(en);
let en = app.m_Viewer.m_PreViewer.m_LastEntity.userData as Entity;
let geo = en.geometry as THREE.Geometry;
let movePoint = geo.vertices[app.m_Viewer.m_PreViewer.m_LastIndex];
app.m_Editor.AddNoSnapEntity(app.m_Viewer.m_PreViewer.m_LastEntity);
let lastP = app.m_Viewer.m_PreViewer.m_LastSnapPoint.clone();
app.m_Viewer.ScreenToWorld(lastP);
let index = app.m_Viewer.m_PreViewer.m_LastIndex;
let pt = await app.m_Editor.GetPoint({
Msg: "指定下一个点:",
BasePoint: lastP.clone(),
Callback: (pt: THREE.Vector3) =>
Callback: (callPt: THREE.Vector3) =>
{
let moveV = pt.clone().sub(lastP);
movePoint.add(moveV);
geo.verticesNeedUpdate = true;
geo.computeBoundingBox();
geo.computeBoundingSphere();
lastP.copy(pt);
let p = en.GetStretchPoints()[index];
en.MoveStretchPoints([index], callPt.sub(en.GetStretchPoints()[index]));
}
})
app.m_Editor.RemoveNoSnapEntity(en);
app.m_Editor.RemoveNoSnapEntity(app.m_Viewer.m_PreViewer.m_LastEntity);
app.m_Viewer.m_GripScene.Update(en);
app.m_Viewer.m_GripScene.Update(app.m_Viewer.m_PreViewer.m_LastEntity);
this.SnapGrip();
}

@ -1,10 +1,5 @@
import * as THREE from "three"
import { Viewer } from "./Viewer";
import { Line, Solid3d } from "../DatabaseServices/Entity";
import { CoordinateSystem } from '../Geometry/CoordinateSystem';
import { OBB } from '../Geometry/OBB/obb';
import { PlaneExt } from '../Geometry/Plane';
import { Line3 } from 'three';
import * as THREE from 'three';
import { Orbit } from '../Geometry/Orbit';
/**

@ -1,5 +1,8 @@
import * as THREE from 'three';
import { Entity } from '../DatabaseServices/Entity';
export class GripScene extends THREE.Object3D
{
@ -23,23 +26,17 @@ export class GripScene extends THREE.Object3D
{
return;
}
let geometry = new THREE.Geometry();
if (en instanceof THREE.Mesh || en instanceof THREE.Line)
{
if (en.geometry instanceof THREE.Geometry)
if (en.userData instanceof Entity)
{
for (let p of en.geometry.vertices)
{
geometry.vertices.push(p.clone().applyMatrix4(en.matrix));
}
}
}
let pts = new THREE.Points(geometry, this.m_GripMaterial);
let pts = en.userData.GetStretchPoints();
let geom = new THREE.Geometry();
geom.setFromPoints(pts);
pts.userData = en;
this.add(pts);
this.m_GripMap.set(en, pts);
let ptsObj = new THREE.Points(geom, this.m_GripMaterial);
ptsObj.userData = en;
this.add(ptsObj);
this.m_GripMap.set(en, ptsObj);
}
}
Remove(obj: THREE.Object3D)
{
@ -69,4 +66,21 @@ export class GripScene extends THREE.Object3D
this.Remove(entity);
this.Append(entity);
}
UpdateAll()
{
for (let [obj, pts] of this.m_GripMap)
{
if (obj.parent)
{
let en = obj.userData as Entity;
let geo = <THREE.Geometry>pts.geometry;
geo.setFromPoints(en.GetStretchPoints())
geo.verticesNeedUpdate = true;
}
else
{
this.Remove(obj);
}
}
}
}

@ -225,7 +225,7 @@ export class Viewer
this.m_Camera.LookAt(new THREE.Vector3(0, 0, -1));
this.m_bNeedUpdate = true;
}
ViewToFont()
ViewToFront()
{
this.m_Camera.LookAt(new THREE.Vector3(0, 1, 0));
this.m_bNeedUpdate = true;
@ -239,59 +239,32 @@ export class Viewer
//TODO: 假设我现在只渲染一个数据层. 不渲染多个.
renderDatabase(db: Database)
{
let ens = db.getEntityCollection();
let removeFunctionList = [];
let dispose = () =>
{
removeFunctionList.forEach(f => f())
}
let injectEntity = (ent: Entity) =>
let renderEntitys = () =>
{
let remove = xaop.begin(ent, ent.erase, function (b: boolean)
let ens = db.ModelSpace.objectCol;
for (let en of db.ModelSpace.objectCol)
{
let obj = ent.Draw(RenderType.Wireframe);
obj.visible = !b;
return;
})
removeFunctionList.push(remove);
let obj = (<Entity>en).Draw(RenderType.Wireframe);
this.m_Scene.add(obj);
}
this.m_bNeedUpdate = true;
}
ens.forEach(e =>
renderEntitys();
xaop.begin(db.ModelSpace, db.ModelSpace.Append, (e) =>
{
injectEntity(e);
let obj = e.Draw(RenderType.Wireframe);
let obj = (<Entity>e).Draw(RenderType.Wireframe);
this.m_Scene.add(obj);
})
let remove1 = xaop.begin(db, db.appendEntity, (ent: Entity) =>
xaop.begin(db.ModelSpace, db.ModelSpace.Destroy, () =>
{
injectEntity(ent);
this.m_Scene.add(ent.Draw(RenderType.Wireframe));
})
let remove2 = xaop.begin(db, db.removeEntityId, (id: number) =>
for (let en of db.ModelSpace.objectCol)
{
let ent = db.getEntity(id);
if (ent)
this.m_Scene.remove(ent.Draw(RenderType.Wireframe));
(<Entity>en).GoodBye();
}
})
xaop.begin(db, db.addEntityId, (id: number) =>
xaop.end(db.ModelSpace, db.ModelSpace.ReadFile, () =>
{
let ent = db.getEntity(id);
if (ent)
this.m_Scene.add(ent.Draw(RenderType.Wireframe));
renderEntitys();
})
let remove3 = xaop.begin(db, db.disposeEntity, (id: number) =>
{
let ent = db.getEntity(id);
if (ent)
this.m_Scene.remove(ent.Draw(RenderType.Wireframe));
dispose();
})
// removeFunctionList.push(remove1);
// removeFunctionList.push(remove2);
// removeFunctionList.push(remove3);
}
}

@ -0,0 +1,109 @@
//参考 http://robnyman.github.io/html5demos/indexeddb/js/base.js
enum DbMode
{
ReadWrite = "readwrite",
ReadOnly = "readonly"
}
export enum StoreName
{
Texture = "Texture",
Dwg = "Dwg",
}
export class IndexedDbStore
{
private dbRequest: IDBOpenDBRequest;
private isOK: boolean = true;;
private db: IDBDatabase;
/**
* Creates an instance of IndexedDbStore.
* @param {string} dbName
* @memberof IndexedDbStore
*/
private constructor()
{
}
private static cadStore: IndexedDbStore = new IndexedDbStore();
static async CADStore()
{
await this.cadStore.Open();
return this.cadStore;
}
Open(): Promise<boolean>
{
return new Promise<boolean>((res) =>
{
let funcs = this.InitStore();
this.dbRequest = indexedDB.open("webCAD", funcs.length);
//出错
this.dbRequest.onerror = () =>
{
console.log("打开数据库出错!");
res(false);
}
//连接成功
this.dbRequest.onsuccess = (event) =>
{
this.db = this.dbRequest.result;
this.db.onerror = () =>
{
res(false);
}
res(true);
}
//需要升级版本号时触发该事件
this.dbRequest.onupgradeneeded = (event) =>
{
let db = event.target["result"] as IDBDatabase;
for (let i = event.oldVersion; i < funcs.length; i++)
{
funcs[i](db);
}
};
})
}
InitStore()
{
return [
//ver1.
(db: IDBDatabase) =>
{
db.createObjectStore(StoreName.Texture);
},
//ver2.
(db: IDBDatabase) =>
{
db.createObjectStore(StoreName.Dwg);
}
];
}
Put(storeName: StoreName, key: string, value: any)
{
let tr = this.db.transaction(storeName, DbMode.ReadWrite);
return tr.objectStore(storeName).put(value, key);
}
Get(storeName: StoreName, key: string)
{
return new Promise<any>((res) =>
{
let tr = this.db.transaction(storeName, DbMode.ReadOnly);
let request = tr.objectStore(storeName).get(key);
request.onsuccess = (e) =>
{
res(request.result);
}
request.onerror = (e) =>
{
res(request.result);
}
})
}
}

@ -0,0 +1,49 @@
import { blobMd5 } from "../Common/MD5";
import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore";
//节点缓存.使用它来缓存已经加载的图片.
let imageCache = new Map<string, HTMLImageElement>();
//根据blob文件加载image
export function loaderImage(blob: File): Promise<HTMLImageElement>
{
return new Promise<HTMLImageElement>(async (res, rej) =>
{
let md5 = await blobMd5(blob);
if (imageCache.has(md5))
{
res(imageCache.get(md5));
return;
}
(await IndexedDbStore.CADStore()).Put(StoreName.Texture, md5, blob);
let url = URL.createObjectURL(blob);
let image = document.createElement('img');
image.onload = () =>
{
URL.revokeObjectURL(url);
imageCache.set(md5, image);
res(image);
}
image.onerror = (err) =>
{
URL.revokeObjectURL(url);
rej(err);
}
image.src = url;
})
}
//通过md5来加载图片.这个方法会尝试从缓存里面读取,也会尝试从indexedDb读取,未来也会支持从外部的网站读取.
export async function loaderImageFromMd5(md5: string): Promise<HTMLImageElement>
{
if (imageCache.has(md5))
return imageCache.get(md5);
let store = await IndexedDbStore.CADStore();
let file = await store.Get(StoreName.Texture, md5) as File;
if (file)
{
return await loaderImage(file);
}
}

@ -1,15 +1,13 @@
import { ContextMenuTarget, Menu, MenuItem } from '@blueprintjs/core';
import { autorun } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { CSSProperties } from 'react';
import { Material, Texture } from 'three';
import * as THREE from 'three';
import * as React from 'react';
import * as xaop from 'xaop';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { DbTexture } from '../../DatabaseServices/Texture';
import { MaterialRendererSingle } from '../Editor/Asset/MaterialRenderer';
import { appUi } from '../Layout/ApplicationLayout';
import { app } from '../../ApplicationServices/Application';
import { MaterialNeedUpdateKey } from '../../DatabaseServices/MaterialDictionary';
//蓝图.
const RootStyle: CSSProperties = {
@ -48,11 +46,9 @@ const TextStyle: CSSProperties = {
width: "100%",
}
interface AssetPropsType
{
showObject: Material | Texture,
id: number,
showObject: DbPhysicalMaterial | DbTexture,
}
@ -64,40 +60,35 @@ interface AssetPropsType
* @class Asset
* @extends {React.Component<{}, {}>}
*/
@ContextMenuTarget
@observer
export class Asset extends React.Component<AssetPropsType, {}>{
image: HTMLImageElement
removeAuto;
removeCall: Function[] = [];
componentDidMount()
{
let img = this.image;
let mat = this.props.showObject;
this.removeAuto = autorun(() =>
{
if (mat[MaterialNeedUpdateKey])
let obj = this.props.showObject
let update = () =>
{
if (mat instanceof THREE.Material)
if (obj instanceof DbPhysicalMaterial)
{
MaterialRendererSingle.render(mat, function (url)
MaterialRendererSingle.render(obj.Material, url => this.image.src = url);
}
else
{
img.src = url;
})
this.image.src = obj.GetThreeTexture().image.src;
}
mat.needsUpdate = true;
mat[MaterialNeedUpdateKey] = false;
}
})
update();
this.removeCall.push(
xaop.end(obj, obj.Update, update)
)
}
componentWillUnmount()
{
this.removeAuto();
this.removeCall.forEach(f => f());
}
render()
{
@ -133,25 +124,25 @@ export class Asset extends React.Component<AssetPropsType, {}>{
handleDoubleClick = () =>
{
appUi.showMaterialEditor(this.props.id);
appUi.showMaterialEditor(this.props.showObject.Id);
}
handleApply = () =>
{
//得到选择的实体.
let mat = this.props.showObject as THREE.Material;
mat.needsUpdate = true;
for (let o of app.m_Viewer.m_OutlinePass.selectedObjects)
{
if (o instanceof THREE.Mesh)
{
o.material = mat;
}
}
app.m_Viewer.m_bNeedUpdate = true;
// let mat = this.props.showObject as THREE.Material;
// mat.needsUpdate = true;
// for (let o of app.m_Viewer.m_OutlinePass.selectedObjects)
// {
// if (o instanceof THREE.Mesh)
// {
// o.material = mat;
// }
// }
// app.m_Viewer.m_bNeedUpdate = true;
}
handleDelete = () =>
{
app.m_Database.m_MaterialDictionary.removeMaterial(this.props.id);
// app.m_Database.m_MaterialDictionary.removeMaterial(this.props.id);
}
}

@ -1,4 +1,4 @@
import { inject, observer } from 'mobx-react';
import { Connect } from 'dob-react';
import * as React from 'react';
import { CSSProperties } from 'react';
@ -6,8 +6,7 @@ import { CommandStore } from '../Store/CommandStore';
import { CommandLineContainer } from './CommandLineContainer';
import { InputHint } from './commandLineInput/InputHint';
@inject("commandStore")
@observer
@Connect
export class CommandComponent extends React.Component<{ commandStore?: CommandStore }, null>
{
style: CSSProperties = {

@ -1,10 +1,10 @@
import { Connect } from 'dob-react';
import * as React from 'react';
import * as React from "react";
import { CommandMsg } from '../Store/CommandStore';
import { observer } from 'mobx-react';
@observer
@Connect
export class CommandLine extends React.Component<{ msg: CommandMsg }, {}>
{
render()

@ -1,10 +1,10 @@
import { Connect } from 'dob-react';
import * as React from 'react';
import { CommandStore } from '../Store/CommandStore';
import { CommandLine } from './CommandLine';
import { observer, inject } from 'mobx-react';
@inject("commandStore")
@observer
@Connect
export class CommandLineContainer extends React.Component<{ commandStore?: CommandStore }, null>
{

@ -1,9 +1,9 @@
import * as React from "react";
import { observer, inject } from 'mobx-react';
import { CommandStore } from '../Store/CommandStore';
import { Connect } from 'dob-react';
import * as React from 'react';
import { CommandStore } from '../Store/CommandStore';
@inject("commandStore") @observer
@Connect
export class CommandLineInput extends React.Component<{ commandStore?: CommandStore }, {}>
{
render()

@ -1,60 +1,62 @@
import * as React from "react";
import { MaterialDictionary } from '../../DatabaseServices/MaterialDictionary';
import { ContextMenuTarget, Menu, MenuItem } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { MaerialTableRecord } from '../../DatabaseServices/MaerialTableRecord';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { Asset } from './Asset';
import { observer } from 'mobx-react';
import { Menu, MenuItem, ContextMenuTarget } from '@blueprintjs/core';
import { app } from "../../ApplicationServices/Application";
const rootStyle: React.CSSProperties = {
overflowX: "hidden",
overflowY: "auto",
background: "#444",
color: "white",
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
alignContent: "flex-start",
width: "100%",
height: "100%"
}
/**
*
*
* @export
* @class MaterialExport
* @extends {React.Component<{ dict: MaterialDictionary }, {}>}
*/
@observer
@ContextMenuTarget
export class MaterialExplorer extends React.Component<{ dict: MaterialDictionary }, {}>{
export class MaterialExplorer extends React.Component<{ dict: MaerialTableRecord }, {}>{
renderMaterialList()
{
let itemList = [];
for (let [id, mat] of this.props.dict.MaterialDict)
return this.props.dict.objectCol.map((o) =>
{
itemList.push(<Asset
key={id}
showObject={mat}
id={id}
/>)
}
return itemList;
let m = o as DbPhysicalMaterial;
return (
<Asset
key={o.Id.Index}
showObject={m}
/>
)
})
}
render()
{
return (
<div style={{
overflowX: "hidden",
overflowY: "auto",
background: "#444",
color: "white",
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
alignContent: "flex-start",
width: "100%",
height: "100%"
}}>
<div style={rootStyle}>
<button onClick={this.handleCreateMaterial}></button>
{this.renderMaterialList()}
</div>
)
}
//右键
// renderContextMenu = () =>
public renderContextMenu()
{
// return a single element, or nothing to use default browser behavior
@ -71,8 +73,11 @@ export class MaterialExplorer extends React.Component<{ dict: MaterialDictionary
// Optional method called once the context menu is closed.
}
handleCreateMaterial()
handleCreateMaterial = () =>
{
app.m_Database.m_MaterialDictionary.createMaterial();
let mat = new DbPhysicalMaterial();
mat.Material;
this.props.dict.Append(mat);
}
}

@ -1,9 +1,9 @@
import { Connect } from 'dob-react';
import * as React from 'react';
import * as React from "react";
import { MouseControls } from '../../Editor/MouseControls';
import { inject, observer } from 'mobx-react';
import { Vector3 } from 'three';
import { DownPanelStore } from '../Store/DownPanelStore';
//顶部标题栏.
export class TopPanel extends React.Component<{}, {}>
{
@ -23,8 +23,7 @@ export class TopPanel extends React.Component<{}, {}>
@inject("store") @observer
@Connect
export class DownPanel extends React.Component<{ store?: DownPanelStore }, {}>
{
render()

@ -1,11 +1,11 @@
import './InputHint.css';
import { observer } from 'mobx-react';
import { Connect } from 'dob-react';
import * as React from 'react';
import { KeyWord } from '../../../Common/InputState';
import { KeyBoard } from '../../../Common/KeyEnum';
import { FixIndex, ArrayRemove } from '../../../Common/Utils';
import { ArrayRemove, FixIndex } from '../../../Common/Utils';
interface InputHintProps
{
@ -38,7 +38,7 @@ interface InputHitState
* @export
* @class InputHint
*/
@observer
@Connect
export class InputHint extends React.Component<InputHintProps, InputHitState>
{
public state: InputHitState;
@ -267,6 +267,7 @@ export class InputHint extends React.Component<InputHintProps, InputHitState>
onChange={(e) => { this.handleOnChangeIntelliSense(e.target.value) }}
value={this.state.command}
ref={el => { this.m_InputEl = el; }}
onKeyDown={(e) => { if (e.ctrlKey || e.altKey) e.preventDefault(); }}
/>
<ul
className="history-command"

@ -1,13 +1,14 @@
import { Provider } from 'dob-react';
import GoldenLayout = require('golden-layout');
import { autorun } from 'mobx';
import { Provider } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as xaop from 'xaop';
import { end } from 'xaop';
import { app, ApplicationService } from '../../ApplicationServices/Application';
import { WebSocketClientServer } from '../../ApplicationServices/WebSocketClientServer';
import { MaterialNeedUpdateKey } from '../../DatabaseServices/MaterialDictionary';
import { ObjectId } from '../../DatabaseServices/ObjectId';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { registerCommand } from '../../Editor/CommandRegister';
import { CommandComponent } from '../Components/Command';
import { MaterialExplorer } from '../Components/MaterialExplorer';
@ -16,6 +17,7 @@ import { DownPanelStore } from '../Store/DownPanelStore';
import { AppLayoutKey, applicationLayoutConfig } from './ApplicationLayout.config';
import { ContainerComponenName, LayoutRegisterContainerComponent } from './LayoutUtils';
import { MaterialEditorLayout } from './MaterialEditorLayout';
import * as xaop from 'xaop';
export let appUi: WebCAD;
@ -39,6 +41,11 @@ export class WebCAD
new ApplicationService();
window["sb"] = () =>
{
app.m_Database.MaterialDict.Append(new DbPhysicalMaterial())
}
registerCommand();
this.renderCommand();
@ -163,7 +170,7 @@ export class WebCAD
renderMaterialExplore()
{
let el = document.getElementById("materialManage");
ReactDOM.render(<MaterialExplorer dict={app.m_Database.m_MaterialDictionary}></MaterialExplorer>, el);
ReactDOM.render(<MaterialExplorer dict={app.m_Database.MaterialDict}></MaterialExplorer>, el);
}
getMaterialConfig(htmlId, materialName)
@ -176,10 +183,10 @@ export class WebCAD
componentState: { id: htmlId },
}
}
showMaterialEditor(materialId: number)
showMaterialEditor(materialId: ObjectId)
{
let docName = "mat" + materialId;
let docName = "mat" + materialId.Index;
let mat = materialId.Object as DbPhysicalMaterial;
let seachList = this.docs.getItemsById(docName);
if (seachList.length > 0)
@ -188,41 +195,31 @@ export class WebCAD
}
else
{
let mat = app.m_Database.m_MaterialDictionary.getMaterial(materialId);
//得到布局配置
let itemConfig = this.getMaterialConfig(docName, mat.name);
this.docs.addChild(itemConfig);
let item = this.docs.getActiveContentItem() as any;
//初始化布局
let med = new MaterialEditorLayout(mat, materialId);
let med = new MaterialEditorLayout(mat);
//注入标题的修改
let removeRun = autorun(() =>
{
item.setTitle(mat.name);
})
//注入材质球刷新.
xaop.end(med.editor.m_Viewer, med.editor.m_Viewer.Render, () =>
{
mat[MaterialNeedUpdateKey] = true;
})
//注入 材质被删除事件.
let removeRun_MaterialDelete = autorun(() =>
{
if (!app.m_Database.m_MaterialDictionary.getMaterial(materialId))
let autoDel = xaop.end(mat, mat.GoodBye, () =>
{
item.close();
}
})
function dispose()
{
removeRun();
removeRun_MaterialDelete();
med.dispose();
autoDel();
}
//注入关闭事件

@ -1,8 +1,8 @@
import GoldenLayout = require('golden-layout');
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Material } from 'three';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { MaterialEditor } from '../../Editor/MaterialEditor';
import { MaterialAttPanel } from '../MaterialEditor/MaterialAttPanel';
import { Config } from '../MaterialEditor/MaterialComponen';
@ -12,7 +12,7 @@ import { ContainerComponenName, LayoutRegisterContainerComponent } from './Layou
export class MaterialEditorLayout
{
editor: MaterialEditor;
mat: Material;
mat: DbPhysicalMaterial;
id: number;
// 得到dom 提供的 element 的id.
@ -22,9 +22,9 @@ export class MaterialEditorLayout
layout: GoldenLayout;
disposeList = [];
constructor(mat: Material, id: number)
constructor(mat: DbPhysicalMaterial)
{
this.initValue(mat, id);
this.initValue(mat);
this.initLayout();
@ -54,11 +54,10 @@ export class MaterialEditorLayout
this.disposeList.push(dispose);
}
private initValue(mat: Material, id: number)
private initValue(mat: DbPhysicalMaterial)
{
this.mat = mat;
this.id = id;
this.htmlId = "mat" + id;
this.htmlId = "mat" + mat.Id.Index;
this.htmlEl = document.getElementById(this.htmlId);
}

@ -1,77 +1,46 @@
import * as React from "react";
import * as THREE from 'three';
import { extendObservable, autorun } from 'mobx';
import { MaterialData, ColorData, RangeData, CheckData, TextureData, InputData } from './MaterialData';
import { Color, Slider } from './MaterialComponen';
import { Viewer } from '../../GraphicsSystem/Viewer';
import { app } from "../../ApplicationServices/Application";
import * as React from 'react';
export class MaterialAttPanel extends React.Component<{ mat: THREE.Material, view: Viewer }, {}>{
import { app } from '../../ApplicationServices/Application';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { Viewer } from '../../GraphicsSystem/Viewer';
import { CheckData, ColorData, InputData, MaterialData, RangeData, TextureData } from './MaterialData';
import { autorun } from 'mobx';
import * as xaop from 'xaop';
//渲染视图.
view: Viewer;
//绑定的材质
material: THREE.Material;
export class MaterialAttPanel extends React.Component<{ mat: DbPhysicalMaterial, view: Viewer }, {}>{
//修改的属性列表. 将会生成一个数组
typeList: Array<MaterialData> = [];
unAutoRun
constructor(props)
{
super(props);
this.material = this.props.mat;
this.view = this.props.view;
this.extendObservable();
this.typeList.push(
new InputData(this.props.mat, "name", "名称"),
new ColorData(this.props.mat, "color", "颜色"),
new CheckData(this.props.mat, "transparent", "透明"),
new RangeData(this.props.mat, "roughness", "粗糙度", 0, 1, 0.01),
new RangeData(this.props.mat, "matalness", "金属性", 0, 1, 0.01),
new RangeData(this.props.mat, "opacity", "不透明度", 0, 1, 0.01),
new CheckData(this.props.mat, "depthTest", "深度测试"),
new TextureData(this.props.mat, "map", "纹理贴图", this.props.view),
new TextureData(this.props.mat, "bumpMap", "凹凸贴图", this.props.view),
new RangeData(this.props.mat, "bumpScale", "凹凸比例", 0, 1, 0.01),
new TextureData(this.props.mat, "roughnessMap", "粗糙贴图", this.props.view),
)
this.unAutoRun = autorun(() =>
xaop.end(this.props.mat, this.props.mat.Update, () =>
{
for (let d of this.typeList)
{
this.material[d.key];
}
this.material.needsUpdate = true;
this.view.m_bNeedUpdate = true;
this.props.view.m_bNeedUpdate = true;
})
console.log(this.material["map"]);
}
/**
*
*
* @memberof MaterialAttPanel
*/
extendObservable = () =>
{
let mobxData: Object = {};
if (this.material instanceof THREE.MeshStandardMaterial)
{
let sm = this.material as THREE.MeshStandardMaterial;
this.typeList = [
new InputData(this.material, "name", "名称"),
new ColorData(this.material, "mobx_color", "颜色"),
new CheckData(this.material, "transparent", "透明"),
new RangeData(this.material, "roughness", "粗糙度", 0, 1, 0.01),
new RangeData(this.material, "metalness", "金属性", 0, 1, 0.01),
new RangeData(this.material, "opacity", "不透明度", 0, 1, 0.01),
new CheckData(this.material, "depthTest", "深度测试"),
new TextureData(this.material, "map", "纹理贴图", this.view),
new TextureData(this.material, "bumpMap", "凹凸贴图", this.view),
new RangeData(this.material, "bumpScale", "凹凸比例", 0, 1, 0.01),
new TextureData(this.material, "roughnessMap", "粗糙贴图", this.view),
]
}
}
//销毁
componentWillUnmount()
{
this.unAutoRun();
}
updateView = () =>
{
this.props.mat.needsUpdate = true;
this.view.m_bNeedUpdate = true;
this.props.view.m_bNeedUpdate = true;
app.m_Viewer.m_bNeedUpdate = true;
}
render()
@ -106,6 +75,5 @@ export class MaterialAttPanel extends React.Component<{ mat: THREE.Material, vie
{
e.stopPropagation();
}
}

@ -1,30 +1,22 @@
/*
.
*/
import { MaterialEditor } from '../../Editor/MaterialEditor';
import { Viewer } from '../../GraphicsSystem/Viewer';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './Material.less';
import { observer } from 'mobx-react';
import { ChangeEventHandler } from 'react';
import * as React from 'react';
import { SketchPicker } from 'react-color';
import './Material.less';
import * as THREE from 'three';
import { Material } from 'three';
import { extendObservable, autorun, observable, isObservable } from 'mobx';
import * as _ from 'lodash';
import * as THREE from 'three';
import { ColorData, RangeData, MaterialData, CheckData, SelctData, TextureData } from './MaterialData';
import { MaterialAttPanel } from './MaterialAttPanel';
import { KeyBoard } from '../../Common/KeyEnum';
import { FileSystem } from '../../Common/FileSystem';
import { KeyBoard } from '../../Common/KeyEnum';
import { MaterialEditor } from '../../Editor/MaterialEditor';
import { Image } from '../../resources/Image';
import { Texture } from '../../texture/Texture';
import { CheckData, MaterialData, RangeData, SelctData, TextureData } from './MaterialData';
/*
.
*/
interface InputData
{
@ -72,11 +64,11 @@ export class Slider extends React.Component<InputData, {}>{
remove;
componentDidMount()
{
this.remove = autorun(() =>
{
let data = this.props as InputData;
this.input.value = data.obj[data.data.key];
})
// this.remove = autorun(() =>
// {
// let data = this.props as InputData;
// this.input.value = data.obj[data.data.key];
// })
}
componentWillUnmount()
{
@ -163,7 +155,6 @@ export class Check extends React.Component<InputData, {}>{
}
}
@observer
export class Select extends React.Component<InputData, {}>{
render()
@ -203,13 +194,11 @@ export class Select extends React.Component<InputData, {}>{
}
}
}
@observer
export class Color extends React.Component<InputData, { isFocus: Boolean }>{
constructor()
constructor(p, s)
{
super(null, { isFocus: false });
super(p, s);
this.state = { isFocus: false }
}
handleClose = () =>
@ -294,15 +283,14 @@ export class Color extends React.Component<InputData, { isFocus: Boolean }>{
}
}
//Texu
@observer
export class TextureComponent extends React.Component<InputData, {}>{
repYEl: HTMLInputElement;
repXEl: HTMLInputElement;
@observable use: boolean = false;
@observable repeatX: number = 1;
@observable repeatY: number = 1;
use: boolean = false;
repeatX: number = 1;
repeatY: number = 1;
texture: THREE.Texture;
img: HTMLImageElement;
@ -324,28 +312,28 @@ export class TextureComponent extends React.Component<InputData, {}>{
this.extendObservable();
}
this.removeAutorRun = autorun(() =>
{
let x = this.repeatX;
let y = this.repeatY;
if (this.texture)
{
this.texture.repeat.x = x;
this.texture.repeat.y = y;
}
if (!this.use)
{
data.obj[data.key] = undefined;
}
else
{
data.obj[data.key] = this.texture;
}
material.needsUpdate = true;
data.viewer.m_bNeedUpdate = true;
})
// this.removeAutorRun = autorun(() =>
// {
// let x = this.repeatX;
// let y = this.repeatY;
// if (this.texture)
// {
// this.texture.repeat.x = x;
// this.texture.repeat.y = y;
// }
// if (!this.use)
// {
// data.obj[data.key] = undefined;
// }
// else
// {
// data.obj[data.key] = this.texture;
// }
// material.needsUpdate = true;
// data.viewer.m_bNeedUpdate = true;
// })
}
componentDidMount()
{
@ -357,21 +345,21 @@ export class TextureComponent extends React.Component<InputData, {}>{
extendObservable = () =>
{
if (this.texture && !isObservable(this.texture))
{
let self = this;
let material = this.props.obj as THREE.Material;
let key = this.props.data.key;
//reg mobx
extendObservable(self.texture, {
wrapT: self.texture.wrapT,
wrapS: self.texture.wrapS
});
let callback = this.props.updataValueCallback;
setTimeout(function () { if (callback) callback(); }, 50);
}
// if (this.texture && !isObservable(this.texture))
// {
// let self = this;
// let material = this.props.obj as THREE.Material;
// let key = this.props.data.key;
// //reg mobx
// extendObservable(self.texture, {
// wrapT: self.texture.wrapT,
// wrapS: self.texture.wrapS
// });
// let callback = this.props.updataValueCallback;
// setTimeout(function () { if (callback) callback(); }, 50);
// }
}
removeAutorRun;
componentwillunmount()

@ -1,18 +1,16 @@
import { observable, computed } from 'mobx';
import * as xaop from 'xaop';
import { observable } from 'dob';
import { app } from '../../ApplicationServices/Application';
import { KeyWord } from '../../Common/InputState';
import { KeyBoard } from '../../Common/KeyEnum';
import { commandMachine } from '../../Editor/CommandMachine';
import { Editor } from '../../Editor/Editor';
import { KeyBoardControls } from '../../Editor/KeyBoardControls';
export interface CommandMsg
{
key: number;//react key
msg: string;
}
@observable
export class CommandStore
{
constructor(ed: Editor)
@ -23,13 +21,13 @@ export class CommandStore
private m_promptKeyIndex: number = 0;
//命令执行中
@observable isCmdIng: boolean;
isCmdIng: boolean;
//历史的消息列表
@observable promptList: Array<CommandMsg> = [];
promptList: Array<CommandMsg> = [];
//提示字符串
@observable commandPrompt: string = '';
commandPrompt: string = '';
//关键字列表
@observable keyWordList: KeyWord[] = [];
keyWordList: KeyWord[] = [];
//提示字符串 当前:
Prompt(msg: string)
{
@ -45,7 +43,6 @@ export class CommandStore
}
}
@computed
get cmdList()
{
return commandMachine.CommandNameList;

@ -1,6 +1,6 @@
import * as THREE from 'three';
import { GetColorFormIndex, GetColorIndex } from '../Common/ColorPalette';
import { ColorMaterial } from '../Common/ColorPalette';
import { SetMaterial } from '../Common/SetMaterial';
import { CameraControls } from '../Editor/CameraControls';
import { Viewer } from '../GraphicsSystem/Viewer';
@ -61,7 +61,7 @@ export class WebCADView
// edge.applyMatrix(move)
if (!color) color = 7;
var line = new THREE.LineSegments(edge, new THREE.LineBasicMaterial({ color: GetColorFormIndex(color) }));
var line = new THREE.LineSegments(edge, ColorMaterial.GetLineMaterial(color));
line.userData = color;
this.m_Viewer.m_Scene.add(line);
@ -89,7 +89,7 @@ export class WebCADView
let fbxObj = await loadFBX(pathUrl + element.fileName);
if (fbxObj.State)
{
let Material = GetColorIndex(element.Color);
let Material = ColorMaterial.GetLineMaterial(element.Color);
SetMaterial(fbxObj.object, Material);
this.m_Viewer.m_Scene.add(fbxObj.object);
@ -155,7 +155,7 @@ export class WebCADView
//前视图
ViewToFont()
{
this.m_Viewer.ViewToFont();
this.m_Viewer.ViewToFront();
}
//俯视图
ViewToTop()
@ -173,7 +173,7 @@ export class WebCADView
}
for (let e of this.m_EdgeEntitytList)
{
(<THREE.LineBasicMaterial>e.material).color = GetColorFormIndex(7);
(<THREE.LineBasicMaterial>e.material).color = ColorMaterial.GetColor(7);
}
}
EdgeShow()
@ -184,7 +184,7 @@ export class WebCADView
}
for (let e of this.m_EdgeEntitytList)
{
(<THREE.LineBasicMaterial>e.material).color = GetColorFormIndex(e.userData);
(<THREE.LineBasicMaterial>e.material).color = ColorMaterial.GetColor(e.userData);
}
}
}

@ -3,7 +3,6 @@ import './UI/Css/style.less';
import * as THREE from 'three';
import { guiMaterial, guiMeshBasicMaterial, guiScene } from './Common/Material';
import { Solid3d } from './DatabaseServices/Entity';
import { CameraControlState } from './Editor/CameraControls';
import { DatGUI } from './Editor/DebugDatUi';
import { RenderType } from './GraphicsSystem/Enum';
@ -140,31 +139,6 @@ window.onload = async () =>
}
}
function load()
{
let loader: THREE.TextureLoader = new THREE.TextureLoader();
let texture: THREE.Texture = loader.load("020.jpg");
texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping; // CHANGED
texture.offset.set(0, 1); // CHANGED
texture.repeat.set(4, 4); // CHANGED
texture.needsUpdate = true;
let material = new THREE.MeshStandardMaterial({
map: texture
});
let box = new Solid3d(10, 10, 10);
let obj = <THREE.Mesh>(box.Draw(RenderType.Wireframe));
// obj.material = material;
// let move = new THREE.Matrix4();
// move.makeTranslation(5000, 0, 0);
// obj.applyMatrix(move);
return obj
}
function parseQuery(search): Object
{
let args = search.substring(1).split('&');

@ -4,11 +4,11 @@
"sourceMap": true,
"module": "commonjs",
"allowJs": true,
"target": "es6",
"target": "esnext",
"noLib": false,
"moduleResolution": "node",
"lib": [
"es2017",
"esnext",
"dom"
],
"types": [

@ -128,9 +128,6 @@ module.exports = {
THREE: "three",
Zlib: "zlib"
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new OpenBrowserPlugin({
url: 'http://localhost:7777/'
})
new webpack.optimize.ModuleConcatenationPlugin()
]
};
Loading…
Cancel
Save