diff --git a/__test__/Board/__snapshots__/Mirror.test.ts.snap b/__test__/Board/__snapshots__/Mirror.test.ts.snap index a72376fbe..1405b584e 100644 --- a/__test__/Board/__snapshots__/Mirror.test.ts.snap +++ b/__test__/Board/__snapshots__/Mirror.test.ts.snap @@ -3,7 +3,7 @@ exports[`板件镜像 1`] = ` Array [ "Board", - 10, + 11, 2, 0, 0, @@ -52,13 +52,14 @@ Array [ 0, 0, 1, + 0, 3, 764, 500.00000000000006, 18, true, "Polyline", - 10, + 11, 2, 0, 0, @@ -107,6 +108,7 @@ Array [ 0, 0, 1, + 0, 2, 4, Array [ @@ -211,7 +213,7 @@ Array [ exports[`板镜像后板边数据错误 1`] = ` Array [ "Board", - 10, + 11, 2, 0, 0, @@ -260,13 +262,14 @@ Array [ 0, 0, 1, + 0, 3, 569.9999999999945, 88, 17.5, false, "Polyline", - 10, + 11, 2, 0, 0, @@ -315,6 +318,7 @@ Array [ 0, 0, 1, + 0, 2, 6, Array [ diff --git a/__test__/CFImport/__snapshots__/CFImport.test.ts.snap b/__test__/CFImport/__snapshots__/CFImport.test.ts.snap index 0ed409299..57fc2b2b0 100644 --- a/__test__/CFImport/__snapshots__/CFImport.test.ts.snap +++ b/__test__/CFImport/__snapshots__/CFImport.test.ts.snap @@ -2,14 +2,14 @@ exports[`晨丰导入CAD解析 1`] = `"[12,103,1,2,1,0,0,1,\\"\\",2,2,0,0,3,\\"Board\\",10,2,100,0,1,2,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,20,0,0,1],0,0,1,3,100,80,18,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,100],0,[80,100],0,[80,0],0,true,1,3,20,10,1,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,20],0,[10,20],0,[10,0],0,true,0,3,0,0,0,0,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,6.123233995736766e-16,10,1],3,0,0,0,0,0,20,1,\\"层板\\",\\"板主卧\\",\\"板标准柜\\",\\"默认板材5厘\\",\\"生态板\\",\\"经典檀木\\",0,0,\\"不排\\",2,0,\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"\\",\\"\\",\\"\\",4,\\"三合一\\",\\"三合一\\",\\"三合一\\",\\"三合一\\",true,true,2,\\"备注1\\",\\"434\\",\\"备注2\\",\\"434\\",0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,\\"HardwareCompositeEntity\\",1,10,2,101,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,30,50,60,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[50,0],0,[50,30],0,[0,30],0,true,0,3,0,0,0,0,0,20,null,\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,0,\\"\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0,\\"HardwareTopline\\",10,2,102,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"\\",1,\\"\\",1,0,\\"0\\",\\"\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,3,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,2,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null,2,13,0,0,0]"`; -exports[`晨丰导入五金解析 1`] = `"[1,10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,30,50,60,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[50,0],0,[50,30],0,[0,30],0,true,0,3,0,0,0,0,0,20,null,\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,0,\\"\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0]"`; +exports[`晨丰导入五金解析 1`] = `"[1,11,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,1,\\"Board\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,3,30,50,60,true,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,4,[0,0],0,[50,0],0,[50,30],0,[0,30],0,true,0,3,0,0,0,0,0,20,null,\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,0,\\"\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0]"`; exports[`晨丰导入五金解析 2`] = `"[12,102,1,2,1,0,0,1,\\"\\",2,2,0,0,2,\\"HardwareCompositeEntity\\",1,10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,101,0,1,2,0,[0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,20,0,\\"层板\\",\\"五金主卧\\",\\"五金标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0,\\"Board\\",10,2,101,0,1,2,0,[0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,20,0,\\"层板\\",\\"五金主卧\\",\\"五金标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,2,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null,2,13,0,0,0]"`; -exports[`晨丰导入板解析 1`] = `"[10,2,0,0,0,2,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,20,0,0,1],0,0,1,3,100,80,18,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,100],0,[80,100],0,[80,0],0,true,1,3,20,10,1,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,20],0,[10,20],0,[10,0],0,true,0,3,0,0,0,0,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,6.123233995736766e-16,10,1],3,0,0,0,0,0,20,1,\\"层板\\",\\"板主卧\\",\\"板标准柜\\",\\"默认板材5厘\\",\\"生态板\\",\\"经典檀木\\",0,0,\\"不排\\",2,0,\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"\\",\\"\\",\\"\\",4,\\"三合一\\",\\"三合一\\",\\"三合一\\",\\"三合一\\",true,true,2,\\"备注1\\",\\"434\\",\\"备注2\\",\\"434\\",0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0]"`; +exports[`晨丰导入板解析 1`] = `"[11,2,0,0,0,2,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,20,0,0,1],0,0,1,0,3,100,80,18,true,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,4,[0,0],0,[0,100],0,[80,100],0,[80,0],0,true,1,3,20,10,1,true,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,4,[0,0],0,[0,20],0,[10,20],0,[10,0],0,true,0,3,0,0,0,0,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,6.123233995736766e-16,10,1],3,0,0,0,0,0,20,1,\\"层板\\",\\"板主卧\\",\\"板标准柜\\",\\"默认板材5厘\\",\\"生态板\\",\\"经典檀木\\",0,0,\\"不排\\",2,0,\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"\\",\\"\\",\\"\\",4,\\"三合一\\",\\"三合一\\",\\"三合一\\",\\"三合一\\",true,true,2,\\"备注1\\",\\"434\\",\\"备注2\\",\\"434\\",0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0]"`; exports[`晨丰导入模板解析 1`] = `"[12,102,1,2,1,0,0,1,\\"\\",2,2,0,0,2,\\"HardwareCompositeEntity\\",1,10,2,100,0,1,7,0,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,1,\\"Board\\",10,2,101,0,1,2,0,[0,6.123233995736766e-17,1,0,-1,0,0,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,20,0,\\"层板\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,5,\\"五金\\",false,false,\\"\\",\\"\\",\\"复合实体\\",\\"模板主卧\\",\\"模板标准柜\\",\\"L*W*H*100\\",\\"L*W*H*300\\",\\"X-1\\",\\"晨丰\\",\\"晨丰\\",\\"个\\",\\"1\\",\\"\\",\\"\\",0,true,0,0,0,\\"Board\\",10,2,101,0,1,2,0,[0,6.123233995736766e-17,1,0,-1,0,0,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,20,0,\\"层板\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,\\"\\",\\"\\",\\"\\",\\"\\",0,false,0,\\"\\",0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,2,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null,2,13,0,0,0]"`; -exports[`晨丰导入顶线解析 1`] = `"[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,20],0,[20,20],0,[20,0],0,[0,0],0,false,1,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`; +exports[`晨丰导入顶线解析 1`] = `"[11,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,5,[0,0],0,[0,20],0,[20,20],0,[20,0],0,[0,0],0,false,1,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`; -exports[`晨丰导入顶线解析 2`] = `"[10,2,101,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[10,0],0,[10,10],0,[0,10],0,true,1,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`; +exports[`晨丰导入顶线解析 2`] = `"[11,2,101,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,4,[0,0],0,[10,0],0,[10,10],0,[0,10],0,true,1,\\"Polyline\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`; diff --git a/__test__/DTO/__snapshots__/Board2CADViewer.test.ts.snap b/__test__/DTO/__snapshots__/Board2CADViewer.test.ts.snap index 83df0fdd0..a08a70802 100644 --- a/__test__/DTO/__snapshots__/Board2CADViewer.test.ts.snap +++ b/__test__/DTO/__snapshots__/Board2CADViewer.test.ts.snap @@ -2,7 +2,7 @@ exports[`拉伸夹点时更新子槽轮廓 1`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -51,13 +51,14 @@ Array [ 0, 0, 1, + 0, 3, 530.9629629629628, 283.2592592592594, 18, true, "Polyline", - 10, + 11, 2, 0, 0, @@ -106,6 +107,7 @@ Array [ 0, 0, 1, + 0, 2, 4, Array [ diff --git a/__test__/FileSystem/__snapshots__/file.test.ts.snap b/__test__/FileSystem/__snapshots__/file.test.ts.snap index f719e82fb..794667a86 100644 --- a/__test__/FileSystem/__snapshots__/file.test.ts.snap +++ b/__test__/FileSystem/__snapshots__/file.test.ts.snap @@ -4,7 +4,7 @@ exports[`changev 1`] = `"[12,101,1,2,1,0,0,1,\\"\\",2,2,0,0,1,\\"Line\\",10,2,10 exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[12,101,1,2,1,0,0,1,\\"\\",2,2,0,0,1,\\"Line\\",10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[1,2,3],[0,0,0],2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,1,2,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[0,0,0],[0,0,0]],\\"CommandHistoryRecord\\",1,\\"\\",1,100,1,\\"ObjectAllDataHistoryRecord\\",1,2,\\"AllObjectData\\",1,[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[0,0,0],[0,0,0]],\\"AllObjectData\\",1,[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[1,2,3],[0,0,0]],100,2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null,2,13,0,0,0]"`; -exports[`创建 修改 撤销撤销 重做重做 撤销 重做 2`] = `"[\\"HistoricManage\\",1,1,2,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[0,0,0],[0,0,0]],\\"CommandHistoryRecord\\",1,\\"\\",1,100,1,\\"ObjectAllDataHistoryRecord\\",1,2,\\"AllObjectData\\",1,[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[0,0,0],[0,0,0]],\\"AllObjectData\\",1,[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[1,2,3],[0,0,0]],100]"`; +exports[`创建 修改 撤销撤销 重做重做 撤销 重做 2`] = `"[\\"HistoricManage\\",1,1,2,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",11,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,1,[0,0,0],[0,0,0]],\\"CommandHistoryRecord\\",1,\\"\\",1,100,1,\\"ObjectAllDataHistoryRecord\\",1,2,\\"AllObjectData\\",1,[11,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,1,[0,0,0],[0,0,0]],\\"AllObjectData\\",1,[11,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,1,[1,2,3],[0,0,0]],100]"`; exports[`测试创建 1`] = `"[\\"AllObjectData\\",1,[]]"`; @@ -16,7 +16,7 @@ exports[`测试创建 4`] = `"[\\"CreateObjectData\\",1,[]]"`; exports[`测试创建 5`] = `"[\\"HistorycRecord\\",2,\\"\\",\\"\\"]"`; -exports[`测试创建 6`] = `"[\\"Line\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,[0,0,0],[0,0,0]]"`; +exports[`测试创建 6`] = `"[\\"Line\\",11,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,0,1,[0,0,0],[0,0,0]]"`; exports[`测试创建 7`] = `"[\\"ObjectAllDataHistoryRecord\\",1,2,\\"\\",\\"\\",0]"`; diff --git a/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap b/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap index 0aafa800d..2cea6e3fb 100644 --- a/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap +++ b/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap @@ -2,10 +2,21 @@ exports[`wblockClone 1`] = ` Array [ - 12, + 13, 102, 1, 2, + 14, + 0, + 0, + 5, + 0, + 0, + "LayerNode", + "根节点", + 0, + 1, + 2, 1, 0, 0, @@ -170,10 +181,21 @@ Array [ exports[`wblockClone 2`] = ` Array [ - 12, + 13, 104, 1, 2, + 14, + 0, + 0, + 5, + 0, + 0, + "LayerNode", + "根节点", + 0, + 1, + 2, 1, 0, 0, @@ -413,10 +435,21 @@ Array [ exports[`wblockClone 3`] = ` Array [ - 12, + 13, 102, 1, 2, + 14, + 0, + 0, + 5, + 0, + 0, + "LayerNode", + "根节点", + 0, + 1, + 2, 1, 0, 0, diff --git a/__test__/FileSystem/file.test.ts b/__test__/FileSystem/file.test.ts index 47242c5cf..801067032 100644 --- a/__test__/FileSystem/file.test.ts +++ b/__test__/FileSystem/file.test.ts @@ -93,8 +93,6 @@ test('clone object', () => }); - - test('changev', () => { let db = new Database(); diff --git a/__test__/Fillet/__snapshots__/ParalleLine.test.ts.snap b/__test__/Fillet/__snapshots__/ParalleLine.test.ts.snap index c0566bab4..fdc663bbd 100644 --- a/__test__/Fillet/__snapshots__/ParalleLine.test.ts.snap +++ b/__test__/Fillet/__snapshots__/ParalleLine.test.ts.snap @@ -34,7 +34,7 @@ Vector3 { exports[`平行线倒角 5`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -83,6 +83,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499446, 5.248426322899339, @@ -125,7 +126,7 @@ Vector3 { exports[`平行线倒角 10`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -174,6 +175,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499456, 5.248426322899337, @@ -216,7 +218,7 @@ Vector3 { exports[`平行线倒角 15`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -265,6 +267,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499446, 2.1068336693095455, @@ -307,7 +310,7 @@ Vector3 { exports[`平行线倒角 20`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -356,6 +359,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499446, 2.1068336693095455, @@ -398,7 +402,7 @@ Vector3 { exports[`平行线倒角 25`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -447,6 +451,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499475, 3.6776299961044363, @@ -489,7 +494,7 @@ Vector3 { exports[`平行线倒角 30`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -538,6 +543,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499473, 3.6776299961044363, @@ -580,7 +586,7 @@ Vector3 { exports[`平行线倒角 35`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -629,6 +635,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499475, 0.5360373425146432, @@ -671,7 +678,7 @@ Vector3 { exports[`平行线倒角 40`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -720,6 +727,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499446, 0.5360373425146522, @@ -762,7 +770,7 @@ Vector3 { exports[`平行线倒角 45`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -811,6 +819,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499451, 2.5106277611946757, @@ -853,7 +862,7 @@ Vector3 { exports[`平行线倒角 50`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -902,6 +911,7 @@ Array [ 0, 0, 1, + 0, 2, 73.3494332249947, 2.510627761194672, @@ -944,7 +954,7 @@ Vector3 { exports[`平行线倒角 55`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -993,6 +1003,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499451, 5.652220414784469, @@ -1035,7 +1046,7 @@ Vector3 { exports[`平行线倒角 60`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1084,6 +1095,7 @@ Array [ 0, 0, 1, + 0, 2, 73.34943322499456, 5.652220414784465, @@ -1126,7 +1138,7 @@ Vector3 { exports[`平行线倒角 65`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1175,6 +1187,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861262, 3.141592653589793, @@ -1217,7 +1230,7 @@ Vector3 { exports[`平行线倒角 70`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1266,6 +1279,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861262, 3.141592653589793, @@ -1308,7 +1322,7 @@ Vector3 { exports[`平行线倒角 75`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1357,6 +1371,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861262, 0, @@ -1399,7 +1414,7 @@ Vector3 { exports[`平行线倒角 80`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1448,6 +1463,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861262, 0, @@ -1490,7 +1506,7 @@ Vector3 { exports[`平行线倒角 85`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1539,6 +1555,7 @@ Array [ 0, 0, 1, + 0, 2, 25.71770334928226, 3.141592653589793, @@ -1581,7 +1598,7 @@ Vector3 { exports[`平行线倒角 90`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1630,6 +1647,7 @@ Array [ 0, 0, 1, + 0, 2, 25.71770334928226, 3.141592653589793, @@ -1672,7 +1690,7 @@ Vector3 { exports[`平行线倒角 95`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1721,6 +1739,7 @@ Array [ 0, 0, 1, + 0, 2, 25.71770334928226, 0, @@ -1763,7 +1782,7 @@ Vector3 { exports[`平行线倒角 100`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1812,6 +1831,7 @@ Array [ 0, 0, 1, + 0, 2, 25.71770334928226, 0, @@ -1854,7 +1874,7 @@ Vector3 { exports[`平行线倒角 105`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1903,6 +1923,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861163, 2.5347869566053345, @@ -1945,7 +1966,7 @@ Vector3 { exports[`平行线倒角 110`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -1994,6 +2015,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861216, 2.5347869566053323, @@ -2036,7 +2058,7 @@ Vector3 { exports[`平行线倒角 115`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2085,6 +2107,7 @@ Array [ 0, 0, 1, + 0, 2, 19.13875598086116, 5.676379610195135, @@ -2127,7 +2150,7 @@ Vector3 { exports[`平行线倒角 120`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2176,6 +2199,7 @@ Array [ 0, 0, 1, + 0, 2, 19.138755980861294, 5.676379610195132, @@ -2218,7 +2242,7 @@ Vector3 { exports[`平行线倒角 125`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2267,6 +2291,7 @@ Array [ 0, 0, 1, + 0, 2, 25.71770334928209, 2.5347869566053367, @@ -2309,7 +2334,7 @@ Vector3 { exports[`平行线倒角 130`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2358,6 +2383,7 @@ Array [ 0, 0, 1, + 0, 2, 25.717703349282267, 2.5347869566053376, @@ -2400,7 +2426,7 @@ Vector3 { exports[`平行线倒角 135`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2449,6 +2475,7 @@ Array [ 0, 0, 1, + 0, 2, 25.717703349282235, 5.6763796101951325, @@ -2491,7 +2518,7 @@ Vector3 { exports[`平行线倒角 140`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2540,6 +2567,7 @@ Array [ 0, 0, 1, + 0, 2, 25.717703349282118, 5.676379610195134, @@ -2582,7 +2610,7 @@ Vector3 { exports[`平行线倒角 145`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2631,6 +2659,7 @@ Array [ 0, 0, 1, + 0, 2, 45.20012262101521, 1.5707963267948966, @@ -2673,7 +2702,7 @@ Vector3 { exports[`平行线倒角 150`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2722,6 +2751,7 @@ Array [ 0, 0, 1, + 0, 2, 45.20012262101521, 1.5707963267948966, @@ -2764,7 +2794,7 @@ Vector3 { exports[`平行线倒角 155`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2813,6 +2843,7 @@ Array [ 0, 0, 1, + 0, 2, 45.20012262101521, 4.71238898038469, @@ -2855,7 +2886,7 @@ Vector3 { exports[`平行线倒角 160`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2904,6 +2935,7 @@ Array [ 0, 0, 1, + 0, 2, 45.20012262101521, 4.71238898038469, @@ -2946,7 +2978,7 @@ Vector3 { exports[`平行线倒角 165`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -2995,6 +3027,7 @@ Array [ 0, 0, 1, + 0, 2, 58.10252336584995, 3.141592653589793, @@ -3037,7 +3070,7 @@ Vector3 { exports[`平行线倒角 170`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3086,6 +3119,7 @@ Array [ 0, 0, 1, + 0, 2, 58.10252336584995, 3.141592653589793, @@ -3128,7 +3162,7 @@ Vector3 { exports[`平行线倒角 175`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3177,6 +3211,7 @@ Array [ 0, 0, 1, + 0, 2, 58.10252336584995, 0, @@ -3219,7 +3254,7 @@ Vector3 { exports[`平行线倒角 180`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3268,6 +3303,7 @@ Array [ 0, 0, 1, + 0, 2, 58.10252336584995, 0, @@ -3310,7 +3346,7 @@ Vector3 { exports[`平行线倒角 185`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3359,6 +3395,7 @@ Array [ 0, 0, 1, + 0, 2, 82.31190810162093, 3.141592653589793, @@ -3401,7 +3438,7 @@ Vector3 { exports[`平行线倒角 190`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3450,6 +3487,7 @@ Array [ 0, 0, 1, + 0, 2, 82.31190810162093, 3.141592653589793, @@ -3492,7 +3530,7 @@ Vector3 { exports[`平行线倒角 195`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3541,6 +3579,7 @@ Array [ 0, 0, 1, + 0, 2, 82.31190810162093, 0, @@ -3583,7 +3622,7 @@ Vector3 { exports[`平行线倒角 200`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3632,6 +3671,7 @@ Array [ 0, 0, 1, + 0, 2, 82.31190810162093, 0, @@ -3674,7 +3714,7 @@ Vector3 { exports[`平行线倒角 205`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3723,6 +3763,7 @@ Array [ 0, 0, 1, + 0, 2, 51.64668743631091, 3.141592653589794, @@ -3765,7 +3806,7 @@ Vector3 { exports[`平行线倒角 210`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3814,6 +3855,7 @@ Array [ 0, 0, 1, + 0, 2, 51.64668743631091, 3.141592653589793, @@ -3856,7 +3898,7 @@ Vector3 { exports[`平行线倒角 215`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3905,6 +3947,7 @@ Array [ 0, 0, 1, + 0, 2, 51.64668743631091, 0, @@ -3947,7 +3990,7 @@ Vector3 { exports[`平行线倒角 220`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -3996,6 +4039,7 @@ Array [ 0, 0, 1, + 0, 2, 51.64668743631091, 0, @@ -4038,7 +4082,7 @@ Vector3 { exports[`平行线倒角 225`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4087,6 +4131,7 @@ Array [ 0, 0, 1, + 0, 2, 51.98014101416747, 1.5707963267948966, @@ -4129,7 +4174,7 @@ Vector3 { exports[`平行线倒角 230`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4178,6 +4223,7 @@ Array [ 0, 0, 1, + 0, 2, 51.98014101416747, 1.5707963267948966, @@ -4220,7 +4266,7 @@ Vector3 { exports[`平行线倒角 235`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4269,6 +4315,7 @@ Array [ 0, 0, 1, + 0, 2, 51.98014101416747, 4.71238898038469, @@ -4311,7 +4358,7 @@ Vector3 { exports[`平行线倒角 240`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4360,6 +4407,7 @@ Array [ 0, 0, 1, + 0, 2, 51.98014101416747, 4.71238898038469, @@ -4402,7 +4450,7 @@ Vector3 { exports[`平行线倒角 245`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4451,6 +4499,7 @@ Array [ 0, 0, 1, + 0, 2, 304.88159012329635, 2.623635128323958, @@ -4493,7 +4542,7 @@ Vector3 { exports[`平行线倒角 250`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4542,6 +4591,7 @@ Array [ 0, 0, 1, + 0, 2, 304.88159012329595, 2.6236351283239516, @@ -4584,7 +4634,7 @@ Vector3 { exports[`平行线倒角 255`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4633,6 +4683,7 @@ Array [ 0, 0, 1, + 0, 2, 304.88159012329635, 5.765227781913751, @@ -4675,7 +4726,7 @@ Vector3 { exports[`平行线倒角 260`] = ` Array [ - 10, + 11, 2, 0, 0, @@ -4724,6 +4775,7 @@ Array [ 0, 0, 1, + 0, 2, 304.88159012329686, 5.765227781913755, diff --git a/__test__/Layer/Layer.test.ts b/__test__/Layer/Layer.test.ts new file mode 100644 index 000000000..eb7ac5e56 --- /dev/null +++ b/__test__/Layer/Layer.test.ts @@ -0,0 +1,309 @@ + +import { TreeAction } from "../../src/UI/Components/ToolBar/Layer/State/Action"; +import { LayerStore } from "../../src/UI/Components/ToolBar/Layer/State/Store"; +import type { ILayerNode } from "../../src/UI/Components/ToolBar/Layer/State/Type"; +import { LayerAPI } from "../../src/UI/Components/ToolBar/Layer/layerAPI"; + +// 测试命令(用于复制):npm run test -- Layer.test.ts + +test("添加图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + layerAPI.AppendFile(); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(layerStore.data.at(-1)); +}); + +test("添加组", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + layerAPI.AppendFolder(); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "组1", children: [], isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true } + ]); +}); + +test("组里添加图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + const file = layerAPI.AppendFile(); + folder.selected = false; + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { + name: "组1", isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ] + } + ]); + expect(layerStore.currentLayer).toEqual(file); +}); + +test("组里添加组", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + layerAPI.AppendFolder(); + folder.selected = false; + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { + name: "组1", isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "组2", isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [] } + ] + } + ]); + expect(layerStore.currentLayer).toBe(layerStore.data[0]); +}); + +test("删除图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.RemoveFile(file); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toBe(layerStore.data[0]); +}); + +test("删除组", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + layerAPI.RemoveFolder(folder); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toBe(layerStore.data[0]); +}); + +test("删除组(组内有图层)", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + layerAPI.AppendFile(); + folder.selected = false; + layerAPI.RemoveFolder(folder); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toBe(layerStore.data[0]); +}); + +test("隐藏图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.UpdateShowFile(file, true); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: true, isOff: true, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(layerStore.data.at(-1)); +}); + +test("隐藏组(组内有图层)", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + const file = layerAPI.AppendFile(); + folder.selected = false; + layerAPI.UpdateShowFolder(folder, true); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { + name: "组1", isOff: true, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "图层1", isCurrent: true, isOff: true, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ] + } + ]); + expect(layerStore.currentLayer).toEqual(file); +}); + +test("锁定图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.UpdateLockFile(file, !file.isLock); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: true, isOff: false, isLock: true, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(layerStore.data.at(-1)); +}); + +test("锁定组(组内有图层)", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + const file = layerAPI.AppendFile(); + folder.selected = false; + layerAPI.UpdateLockFolder(folder, !folder.isLock); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { + name: "组1", isOff: false, isLock: true, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "图层1", isCurrent: true, isOff: false, isLock: true, colorIndex: 1, visible: true, selected: false, changeable: false } + ] + } + ]); + expect(layerStore.currentLayer).toEqual(file); +}); + +test("双重锁定表解锁", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.UpdateLockFile(file, !file.isLock); + layerAPI.UpdateLockFile(file, !file.isLock); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(layerStore.data.at(-1)); +}); + +test("设置颜色", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.UpdateColorFile(file, 2); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 2, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(layerStore.data.at(-1)); +}); + +test("设置当前图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + layerAPI.AppendFile(); + const normal = layerStore.data[0]; + layerAPI.SetCurrentFile(normal); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "图层1", isCurrent: false, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(normal); +}); + +test("重命名图层", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + layerAPI.RenameNode(file, "新图层1"); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "新图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ]); + expect(layerStore.currentLayer).toEqual(file); +}); + +test("重命名组", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + layerAPI.RenameNode(folder, "新组1"); + expect(layerStore.data).toEqual([ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { name: "新组1", children: [], isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true } + ]); + expect(layerStore.currentLayer).toBe(layerStore.data[0]); +}); + +test("可以移动序列", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const file = layerAPI.AppendFile(); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + layerAPI.AppendFile(); + folder.selected = false; + const node = TreeAction.FindNode(layerStore.data, (item: ILayerNode) => item.name === file.name) as ILayerNode; + node.selected = true; + const nodes = TreeAction.FilterNodes(layerStore.data, (item: ILayerNode) => !item.selected); + expect(nodes).toEqual([ + { name: "默认", isCurrent: false, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + { + name: "组1", isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "图层2", isCurrent: true, isOff: false, isLock: false, colorIndex: 2, visible: true, selected: false, changeable: false } + ] + }, + ]); +}); + +test("搜索组", () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.Init(); + const layerAPI = new LayerAPI(layerStore); + const folder = layerAPI.AppendFolder(); + folder.selected = true; + layerAPI.AppendFile(); + folder.selected = false; + const nodes = TreeAction.FindFlatNodes(layerStore.data, (node: ILayerNode) => node.name === "组1"); + expect(nodes).toEqual([ + { + name: "组1", isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true, children: [ + { name: "图层1", isCurrent: true, isOff: false, isLock: false, colorIndex: 1, visible: true, selected: false, changeable: false } + ] + }, + ]); +}); + +const log = () => +{ + const layerStore = LayerStore.GetInstance(); + console.group("View层数据"); + console.log(JSON.parse(JSON.stringify(layerStore.data))); + const current = TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.isCurrent); + if (current !== layerStore.currentLayer) + console.log(`Error: ${current.name} `); + console.groupEnd(); +}; diff --git a/__test__/Layer/layer_db.test.ts b/__test__/Layer/layer_db.test.ts new file mode 100644 index 000000000..c9ea49110 --- /dev/null +++ b/__test__/Layer/layer_db.test.ts @@ -0,0 +1,79 @@ + +//#region 避免无法进入测试 依赖错误导致的测试失败 ref file.test.ts +import { HostApplicationServices } from '../../src/ApplicationServices/HostApplicationServices'; +import { DuplicateRecordCloning } from '../../src/Common/Status'; +import { AllObjectData } from '../../src/DatabaseServices/AllObjectData'; +AllObjectData; +//#endregion + +import { Database } from '../../src/DatabaseServices/Database'; +import { Entity } from '../../src/DatabaseServices/Entity/Entity'; +import { Line } from '../../src/DatabaseServices/Entity/Line'; +import { LayerTableRecord } from '../../src/DatabaseServices/LayerTableRecord'; + + +/** + * 1.新绘制的对象必须在当前层上 + * 2.能够被序列化 + */ +test('绘制的对象默认图层', () => +{ + let db = new Database(true, true, true); + + let line = new Line; + + db.ModelSpace.Append(line); + + expect(line.Layer === db.DefaultLayer.Id).toBeTruthy();//图层等于默认图层 + + let layer = new LayerTableRecord(); + layer.Name = "新图层1"; + db.LayerTable.Add(layer); + + db.LayerTable.Current = layer.Id; + + line = new Line; + db.ModelSpace.Append(line); + expect(line.Layer === layer.Id).toBeTruthy();//图层应该等于当前图层 + + let id = line.Id.Index; + + let db2 = new Database(false, false, true); + db2.FileRead(db.FileWrite()); + + let idnew = db2.GetObjectId(id); + + (idnew.Object as Entity).Layer.Index;//? + + expect((idnew.Object as Entity).Layer.Object.Name).toBe(layer.Name); +}); + + +/** + * 1.对于模块内的实体,由于之前没有图层,新绘入后,需要设置到当前图层 + */ +test('模版文件的图层', () => +{ + let db1 = new Database(true, true, true); + HostApplicationServices.Database = db1; + + let db2 = new Database(false, false, true); + + let line = new Line; + db2.ModelSpace.Append(line); + line.Layer; + line.HasLayer;//? + + db1.WblockCloneObejcts([line], db1.ModelSpace, new Map, DuplicateRecordCloning.Ignore); + + db1.ModelSpace.Entitys[0].Layer.Object.Name;//? + + let layer = new LayerTableRecord(); + layer.Name = "新图层1"; + db1.LayerTable.Add(layer); + db1.LayerTable.Current = layer.Id; + + db1.WblockCloneObejcts([line], db1.ModelSpace, new Map, DuplicateRecordCloning.Ignore); + + expect(db1.ModelSpace.Entitys[1].Layer.Object.Name).toBe(layer.Name); +}); diff --git a/src/Add-on/BoardCutting/AutoCuttingReactor.ts b/src/Add-on/BoardCutting/AutoCuttingReactor.ts index 5ebc5a149..a3c86ec56 100644 --- a/src/Add-on/BoardCutting/AutoCuttingReactor.ts +++ b/src/Add-on/BoardCutting/AutoCuttingReactor.ts @@ -10,7 +10,7 @@ export class AutoCuttingReactor { constructor() { - const cuttingCommands = new Set(["购买模块并插入", "插入模块"]); + const cuttingCommands = new Set(["购买模块并插入", CommandNames.InsertModule]); app.CommandReactor.OnCommandEnd(async (cmdName, changeObjects, createObjects) => { @@ -19,7 +19,7 @@ export class AutoCuttingReactor let brs = createObjects.filter(o => !o.IsErase && o instanceof Board) as Board[]; - if (cmdName !== "插入模块" && cmdName !== "购买模块并插入" && cmdName !== CommandNames.Drawer) + if (cmdName !== CommandNames.InsertModule && cmdName !== "购买模块并插入" && cmdName !== CommandNames.Drawer) if (brs.length > 10) { app.Editor.Prompt("复制的板件超过10个,取消触发切割反应器!", LogType.Error, brs); diff --git a/src/Add-on/BoardCutting/HardwareCuttingReactor.ts b/src/Add-on/BoardCutting/HardwareCuttingReactor.ts index 4876e6864..c757f2fdd 100644 --- a/src/Add-on/BoardCutting/HardwareCuttingReactor.ts +++ b/src/Add-on/BoardCutting/HardwareCuttingReactor.ts @@ -9,7 +9,7 @@ export class HardwareCuttingReactor EnableHardware = true; constructor() { - const hardwareCmds = new Set(["购买模块并插入", "插入模块", CommandNames.Door, CommandNames.Drawer]); + const hardwareCmds = new Set(["购买模块并插入", CommandNames.InsertModule, CommandNames.Door, CommandNames.Drawer]); app.CommandReactor.OnCommandEnd(async (cmdName, changeObjects, createObjects) => { diff --git a/src/Add-on/BoardCutting/LinearCutting.ts b/src/Add-on/BoardCutting/LinearCutting.ts index a1169c795..6fe1a7e01 100644 --- a/src/Add-on/BoardCutting/LinearCutting.ts +++ b/src/Add-on/BoardCutting/LinearCutting.ts @@ -36,7 +36,7 @@ export class LinearCutting implements Command { for (let ent of app.Database.ModelSpace.Entitys) { - if (!ent.IsErase && ent.Visible && ent instanceof Board) + if (!ent.IsErase && ent.IsVisible && ent instanceof Board) brs.push(ent); } } diff --git a/src/Add-on/DrawDrilling/DrillingReactor.ts b/src/Add-on/DrawDrilling/DrillingReactor.ts index 88b692d0e..897ab5c1a 100644 --- a/src/Add-on/DrawDrilling/DrillingReactor.ts +++ b/src/Add-on/DrawDrilling/DrillingReactor.ts @@ -49,7 +49,14 @@ const ForbidReactorCmd = new Set([ //对纹组 CommandNames.AlignLineGroup, CommandNames.AddAlignLineGroup, - CommandNames.DeleteAlignLineGroup + CommandNames.DeleteAlignLineGroup, + + //图层操作 + CommandNames.UpdateLock, + CommandNames.PutEntitysInLayer, + CommandNames.RemoveLayer, + CommandNames.RemoveLayerFolder, + ]); export class DrillingReactor diff --git a/src/ApplicationServices/Application.ts b/src/ApplicationServices/Application.ts index 13cc68266..b0380d085 100644 --- a/src/ApplicationServices/Application.ts +++ b/src/ApplicationServices/Application.ts @@ -41,6 +41,7 @@ import { WebRtcRenderer } from '../GraphicsSystem/WebRtcRenderer'; import { IndexedDbStore } from '../IndexedDb/IndexedDbStore'; import { InitClipperCpp } from '../Nest/Common/ClipperCpp'; import { CommandReactor } from '../Reactor/CommandReactor'; +import { LayerReactor } from '../Reactor/LayerReactor'; import { RelevanceCuttingReactor } from '../Reactor/RelevanceCuttingReactor'; import { SyncDataReactor } from '../Reactor/SyncDataReactor'; import { AppToaster } from '../UI/Components/Toaster'; @@ -274,6 +275,9 @@ export class ApplicationService rcrr.RegistCommandEnd();//保证在分析墙体后在更新关联关系 避免错误 this.SyncDataReactor.RegistCommandEnd();//保证命令结束后 先分析墙体,在发送数据 + /** 图层反应器 */ + const layerReactor = new LayerReactor(); + //在更新实体后,如果网洞被删除,则操作控制器被禁用 app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) => { diff --git a/src/ApplicationServices/HostApplicationServices.ts b/src/ApplicationServices/HostApplicationServices.ts index 434c904e8..147f98f16 100644 --- a/src/ApplicationServices/HostApplicationServices.ts +++ b/src/ApplicationServices/HostApplicationServices.ts @@ -1,5 +1,7 @@ import { MeshBasicMaterial, MeshStandardMaterial, Texture } from 'three'; import { FractionDigitsType } from '../Common/SystemEnum'; +import { Database } from '../DatabaseServices/Database'; +import { LayerTableRecord } from '../DatabaseServices/LayerTableRecord'; import { ObjectId } from '../DatabaseServices/ObjectId'; import { ICursorConfig } from '../Editor/ICursorConfig'; import { RenderType } from '../GraphicsSystem/RenderType'; @@ -7,6 +9,8 @@ import { DrillingOption } from '../UI/Store/drillInterface'; export class IHostApplicationServices { + Database: Database;//app.Db + DefaultMeshMaterial?: MeshBasicMaterial | MeshStandardMaterial; DefaultFloorMaterial?: MeshBasicMaterial | MeshStandardMaterial; DefaultWallMaterial?: MeshBasicMaterial | MeshStandardMaterial; @@ -15,6 +19,10 @@ export class IHostApplicationServices IsRoomEntityVisible = true;//室内实体可见 CurrentDimStyle: ObjectId; + CurrentLayer: ObjectId; + /** 当前画笔的颜色索引 */ + CurrentColorindex: number = 7; + @ProxyValue isShowLightShadow: boolean = true;//灯光阴影 (除太阳光外) ShowHistoryLog: boolean = true; diff --git a/src/Common/CommandNames.ts b/src/Common/CommandNames.ts index d099a2d5a..5a4232b09 100644 --- a/src/Common/CommandNames.ts +++ b/src/Common/CommandNames.ts @@ -152,6 +152,7 @@ export enum CommandNames ComanPanel = "COMMANDPANEL", Comanp = "COMANP", PropertiesBar = "PROPERTIESBAR", + LayerListBar = "LAYERLISTBAR", ModuleBar = "MODULEBAR", ChangeLayout = "CHANGELAYOUT", RightPanelTemplateParam = "RIGHTPANELTEMPLATEPARAM", @@ -201,6 +202,10 @@ export enum CommandNames TemplateSearch = "TEMPLATESEARCH", TemplateDelete = "TEMPLATEDELETE", // 删除模板节点 TemplateCheck = "TEMPLATECHECK", + /** 插入模块 */ + InsertModule = "插入模块", + /** 编辑模块 */ + EditTemplate = "编辑模板", RotateTemplate = "ROTATETEMP", Print = "PRINT", Extrude = "EXTRUDE", @@ -400,4 +405,19 @@ export enum CommandNames HighlightNode = "HIGHLIGHTNODE",//高亮本节点 HighlightNodeAndChilds = "HIGHLIGHTNODEANDCHILDS",//亮显本节点及子节点 ClearCDBrHoleModeling = "CLEARCDBRHOLEMODELING",//板件取消孔槽加工 + /* ---- 图层相关 ---- */ + AppendLayer = "创建图层", + AppendLayerFolder = "创建图层文件夹", + RemoveLayer = "删除图层", + RemoveLayerFolder = "删除图层文件夹", + SetCurrentLayer = "置为当前图层", + PutEntitysInLayer = "修改实体所在的图层", + UpdateShow = "设置图层是否显示", + UpdateLock = "设置图层是否锁定", + UpdateViewPoint = "设置图层是否视口冻结", + UpdateColor = "设置图层颜色", + RenameLayer = "重命名图层", + RenameLayerFolder = "重命名图层文件夹", + MoveLayer = "移动图层", + MoveLayerFolder = "移动图层文件夹", } diff --git a/src/Common/HotKeyList.ts b/src/Common/HotKeyList.ts index 562cc162b..ffa706713 100644 --- a/src/Common/HotKeyList.ts +++ b/src/Common/HotKeyList.ts @@ -2,6 +2,7 @@ export enum HotkeyList { C1 = "Control+1", C2 = "Control+2", + C3 = "Control+3", CA = "Control+A", CB = "Control+B", CC = "Control+C", diff --git a/src/DatabaseServices/3DSolid/ExtrudeHole.ts b/src/DatabaseServices/3DSolid/ExtrudeHole.ts index 98a6645ad..255797d35 100644 --- a/src/DatabaseServices/3DSolid/ExtrudeHole.ts +++ b/src/DatabaseServices/3DSolid/ExtrudeHole.ts @@ -373,12 +373,12 @@ export class ExtrudeHole extends Hole { if (renderType === RenderType.Wireframe || renderType === RenderType.Edge) { - return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); } else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical2) { return new Object3D().add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7)) ); } @@ -413,7 +413,7 @@ export class ExtrudeHole extends Hole { let l = obj as LineSegments; l.geometry = this.EdgeGeometry; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else if (renderType === RenderType.Print) { @@ -428,7 +428,7 @@ export class ExtrudeHole extends Hole else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical2) { obj.add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7)) ); } @@ -442,7 +442,7 @@ export class ExtrudeHole extends Hole if (renderType === RenderType.Wireframe || renderType === RenderType.Edge) { let l = obj as LineSegments; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else if (renderType === RenderType.Physical) { @@ -452,7 +452,7 @@ export class ExtrudeHole extends Hole else if (renderType !== RenderType.Jig && renderType !== RenderType.Print) { let mesh = obj.children[0] as Mesh; - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex); } } diff --git a/src/DatabaseServices/3DSolid/RevolveSolid.ts b/src/DatabaseServices/3DSolid/RevolveSolid.ts index d060d1dff..bfa9c56a2 100644 --- a/src/DatabaseServices/3DSolid/RevolveSolid.ts +++ b/src/DatabaseServices/3DSolid/RevolveSolid.ts @@ -327,7 +327,7 @@ export class RevolveSolid extends Entity else// if (type === RenderType.Conceptual || type===RenderType.Physical || type === RenderType.Jig) { let g = this.MeshGeometry; - obj.add(new Mesh(g, ColorMaterial.GetConceptualMaterial(this.ColorIndex))); + obj.add(new Mesh(g, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex))); } return obj; @@ -357,7 +357,7 @@ export class RevolveSolid extends Entity if (type === RenderType.Wireframe) mesh.material = RevolveSolid.MeshNromal; else - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex); } } } @@ -370,7 +370,7 @@ export class RevolveSolid extends Entity if (renderType === RenderType.Conceptual) { let mesh = obj.children[0] as Mesh; - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex); } else if (renderType === RenderType.Physical2 || renderType === RenderType.Physical) { diff --git a/src/DatabaseServices/3DSolid/SweepSolid.ts b/src/DatabaseServices/3DSolid/SweepSolid.ts index 8d1933b25..305145e95 100644 --- a/src/DatabaseServices/3DSolid/SweepSolid.ts +++ b/src/DatabaseServices/3DSolid/SweepSolid.ts @@ -210,7 +210,7 @@ export class SweepSolid extends Entity { if (renderType === RenderType.Wireframe || renderType === RenderType.Edge) { - let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); // for (let p of this.Paths) // { @@ -227,7 +227,7 @@ export class SweepSolid extends Entity else if (renderType === RenderType.Conceptual) { return new Object3D().add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetConceptualEdgeMaterial()) ); } @@ -284,7 +284,7 @@ export class SweepSolid extends Entity { let l = obj as LineSegments; l.geometry = this.EdgeGeometry; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); // Object3DRemoveAll(l); // for (let p of this.Paths) @@ -300,7 +300,7 @@ export class SweepSolid extends Entity { Object3DRemoveAll(obj); return obj.add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetConceptualEdgeMaterial()) ); } @@ -337,12 +337,12 @@ export class SweepSolid extends Entity if (type === RenderType.Wireframe) { let l = obj as TLine; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else if (type === RenderType.Conceptual) { let mesh = obj.children[0] as Mesh; - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex); } else if (type === RenderType.Physical2) { diff --git a/src/DatabaseServices/AllObjectData.ts b/src/DatabaseServices/AllObjectData.ts index 7156da39d..65fec8b04 100644 --- a/src/DatabaseServices/AllObjectData.ts +++ b/src/DatabaseServices/AllObjectData.ts @@ -1,7 +1,6 @@ import { Factory } from './CADFactory'; import { CADFiler } from './CADFiler'; import { ISerialize } from './ISerialize'; -import { CADObject } from './CADObject'; /** * 保存对象创建或者修改时的所有数据记录 @@ -10,7 +9,7 @@ import { CADObject } from './CADObject'; export class AllObjectData implements ISerialize { file: CADFiler; - constructor(obj?: CADObject) + constructor(obj?: ISerialize) { this.file = new CADFiler(); if (obj) diff --git a/src/DatabaseServices/BlockTableRecord.ts b/src/DatabaseServices/BlockTableRecord.ts index d54dee739..22415f452 100644 --- a/src/DatabaseServices/BlockTableRecord.ts +++ b/src/DatabaseServices/BlockTableRecord.ts @@ -63,6 +63,9 @@ export class BlockTableRecord extends SymbolTableRecord if (!entity.Material) entity.Material = this._db.MaterialTable.CurBoardMtl; } + + if (!entity.HasLayer) + entity.Layer = this._db.LayerTable.Current; } this.EntityCol.Append(entity, isCheckObjectCleanly); diff --git a/src/DatabaseServices/Database.ts b/src/DatabaseServices/Database.ts index e7d3b9c9a..13de2c5b1 100644 --- a/src/DatabaseServices/Database.ts +++ b/src/DatabaseServices/Database.ts @@ -14,6 +14,7 @@ import { Entity } from './Entity/Entity'; import { GroupTable } from './GroupTable'; import { HistoricManage } from './HistoricManage'; import { IdMaping } from './IdMaping'; +import { LayerTableRecord } from './LayerTableRecord'; import { AmbientLight } from './Lights/AmbientLight'; import { DirectionalLight } from './Lights/DirectionalLight'; import { HemisphereLight } from './Lights/HemisphereLight'; @@ -24,6 +25,7 @@ import { PhysicalMaterialRecord } from './PhysicalMaterialRecord'; import { ProcessingGroupTable } from './ProcessingGroup/ProcessingGroupTable'; import { SymbolTableRecord } from './SymbolTableRecord'; import { BlockTable } from './Tables/BlockTable'; +import { LayerNode, LayerTable } from './Tables/LayerTable'; import { MaterialTable } from './Tables/MaterialTable'; import { SymbolTable } from './Tables/SymbolTable'; import { TextureTable } from './Tables/TextureTable'; @@ -46,6 +48,7 @@ export class Database ProcessingGroupTable: ProcessingGroupTable; AlignLineGroupTable: AlignLineGroupTable; DimStyleTable: DimStyleTable; + LayerTable: LayerTable; //模型空间(里面有模型空间的实体列表) ModelSpace: BlockTableRecord; @@ -62,7 +65,9 @@ export class Database SunLight: DirectionalLight; HemisphereLight: HemisphereLight; - //默认材质 + //默认图层 id=61 + DefaultLayer: LayerTableRecord; + //默认材质 id=71 DefaultMaterial: PhysicalMaterialRecord; /** 这是为UE设计器提供的拓展数据,WebCAD只负责保存,不使用它. @@ -72,6 +77,13 @@ export class Database private idIndex = 1; private idMap = new Map(); + + /** + * + * @param [buildDefaultDrawing=false] 构建默认对象(标注 图层 材质 灯光) + * @param [IsDefaultDatabase=false] app图纸 + * @param [disableHistoric=false] 禁止命令记录(撤销重做) + */ constructor(buildDefaultDrawing = false, public IsDefaultDatabase = false, disableHistoric = false) { //注意:下面的注释是严格排序的,请不要随意插入某个表 @@ -88,12 +100,22 @@ export class Database this.DimStyleTable = new DimStyleTable().SetOwnerDatabase(this); this.AlignLineGroupTable = new AlignLineGroupTable().SetOwnerDatabase(this); //注意:新对象在这里添加 + this.LayerTable = new LayerTable().SetOwnerDatabase(this); + + if (IsDefaultDatabase) + { + if (HostApplicationServices.Database) console.error("重复初始化默认图纸"); + + HostApplicationServices.Database = this; + } if (buildDefaultDrawing) { - this.InitDimStyle(); + this.InitDimStyle();//60 + + this.InitLayer(); //61; - this.InitMaterial(); + this.InitMaterial();//70 this.InitLight(); @@ -118,6 +140,23 @@ export class Database this.DimStyleTable.Current = styleRd.Id; } + private InitLayer() + { + this.idIndex = 61; + + let layerRd = new LayerTableRecord; + layerRd.Name = "默认"; + + this.LayerTable.Add(layerRd); + + this.LayerTable.Current = layerRd.Id; + HostApplicationServices.CurrentLayer = layerRd.Id; + + const root = new LayerNode("根节点"); + root.children = [new LayerNode(layerRd.Name)]; + this.LayerTable.Root = root; + } + private InitMaterial() { this.idIndex = 70; @@ -154,7 +193,7 @@ export class Database this.Lights.Add(this.HemisphereLight); } - SettingDefaultStyleAndMaterial() + private SettingDefaultStyleAndMaterial() { if (!this.IsDefaultDatabase) return; @@ -162,12 +201,15 @@ export class Database this.DefaultMaterial = this.GetObjectId(71)?.Object as PhysicalMaterialRecord ?? this.DefaultMaterial; this.DefaultMaterial.Update(); + this.DefaultLayer = this.GetObjectId(61)?.Object as LayerTableRecord ?? this.DefaultLayer; + HostApplicationServices.DefaultMeshMaterial = (this.MaterialTable.CurBoardMtl?.Object as PhysicalMaterialRecord)?.Material ?? this.DefaultMaterial.Material; HostApplicationServices.DefaultWallMaterial = (this.MaterialTable.CurWallMtl?.Object as PhysicalMaterialRecord)?.Material ?? this.DefaultMaterial.Material; HostApplicationServices.DefaultFloorMaterial = (this.MaterialTable.CurFloorMtl?.Object as PhysicalMaterialRecord)?.Material ?? this.DefaultMaterial.Material; HostApplicationServices.DefaultBulkheadCeilingMaterial = (this.MaterialTable.CurBulkCeilingFaceMaterial?.Object as PhysicalMaterialRecord)?.Material ?? this.DefaultMaterial.Material; HostApplicationServices.CurrentDimStyle = this.DimStyleTable.Current; + HostApplicationServices.CurrentLayer = this.LayerTable.Current; } Destroy() @@ -185,6 +227,7 @@ export class Database this.ProcessingGroupTable.Destroy(); this.AlignLineGroupTable.Destroy(); this.DimStyleTable.Destroy(); + this.LayerTable.Destroy(); this.hm.Destroy(); this.CameraSnapshoots.length = 0; this.hm.historyRecord.length = 0; @@ -203,7 +246,7 @@ export class Database this.DimStyleTable.SetOwnerDatabase(this); this.AlignLineGroupTable.SetOwnerDatabase(this); //注意:新对象在这里添加 - + this.LayerTable.SetOwnerDatabase(this); this.idIndex = 100; } @@ -211,8 +254,11 @@ export class Database FileWrite(file = new CADFiler): CADFiler { - file.Write(12);//ver; + file.Write(13);//ver; file.Write(this.idIndex); + + this.LayerTable.WriteFile(file); + this.ModelSpace.WriteFile(file); this.TextureTable.WriteFile(file); this.MaterialTable.WriteFile(file); @@ -235,6 +281,7 @@ export class Database this.AlignLineGroupTable.WriteFile(file); return file; } + FileRead(file: CADFiler) { Entity.__ReadFileIng__ = true; @@ -244,6 +291,17 @@ export class Database file.database = this; let ver = file.Read(); this.idIndex = file.Read(); + + //图层 + if (ver > 12) + this.LayerTable.ReadFile(file); + else + { + let indexBak = this.idIndex; + this.InitLayer(); + this.idIndex = indexBak; + } + this.ModelSpace.ReadFile(file); this.TextureTable.ReadFile(file); this.MaterialTable.ReadFile(file); diff --git a/src/DatabaseServices/Dimension/AlignedDimension.ts b/src/DatabaseServices/Dimension/AlignedDimension.ts index 2eff7d1d2..2ad10ac66 100644 --- a/src/DatabaseServices/Dimension/AlignedDimension.ts +++ b/src/DatabaseServices/Dimension/AlignedDimension.ts @@ -1,4 +1,4 @@ -import { BufferGeometry, Line as TLine, Material, Matrix3, Matrix4, Mesh, Object3D, Vector2, Vector3 } from "three"; +import { BufferGeometry, Material, Matrix3, Matrix4, Mesh, Object3D, Line as TLine, Vector2, Vector3 } from "three"; import { Line2 } from "three/examples/jsm/lines/Line2"; import { LineGeometry } from "three/examples/jsm/lines/LineGeometry"; import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices"; @@ -9,13 +9,13 @@ import { UpdateDraw } from "../../Common/Status"; import { FixedNotZero } from "../../Common/Utils"; import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils"; -import { angle, angleAndX, AsVector2, AsVector3, equaln, equalv3, isParallelTo, midPoint, ZAxis } from "../../Geometry/GeUtils"; +import { AsVector2, AsVector3, ZAxis, angle, angleAndX, equaln, equalv3, isParallelTo, midPoint } from "../../Geometry/GeUtils"; import { ROTATE_MTX2 } from "../../Geometry/RotateUV"; import { RenderType } from "../../GraphicsSystem/RenderType"; import { Factory } from "../CADFactory"; import { CADFiler } from "../CADFiler"; -import { DimStyleKeyCode } from "../DimStyle/DimstyleKeyCodeEnum"; import { DimTextPosDir } from "../DimStyle/DimStyleRecord"; +import { DimStyleKeyCode } from "../DimStyle/DimstyleKeyCodeEnum"; import { Line } from "../Entity/Line"; import { Polyline } from "../Entity/Polyline"; import { TextAligen } from "../Text/Text"; @@ -470,7 +470,7 @@ export class AlignedDimension extends Dimension this._LeadLine.AutoUpdate = false; this._LeadLine.IsEmbedEntity = true;//使它可以捕捉 this._LeadLine.LineData = [textPosition, leadP1, leadP2].map(p => { return { pt: AsVector2(p), bul: 0 }; }); - this._LeadLine.ColorIndex = this.ColorIndex; + this._LeadLine.ColorIndex = this.DrawColorIndex; this._LeadLine.Visible = true;//可见性设置 this._LeadLine.AutoUpdate = true; this._LeadLine.DeferUpdate(); @@ -492,7 +492,7 @@ export class AlignedDimension extends Dimension this._Text.TextString = this.TextString; this._Text.Position = textPos ?? midPoint(this._ArmP1, this._ArmP2); this._Text.TextRotation = textRo; - this._Text.ColorIndex = this._Color; + this._Text.ColorIndex = this.DrawColorIndex; this._Text.Height = this.TextSize * 0.923;//雅黑数字*0.923 this._Text.DeferUpdate(); @@ -559,12 +559,12 @@ export class AlignedDimension extends Dimension return; this.WriteAllObjectRecord(); let mtl = GetDimLineMaterial(this, renderType); - this._LeadLine.ColorIndex = this._Color; + this._LeadLine.ColorIndex = this.DrawColorIndex; let [line, arrow1, arrow2] = obj.children; (line).material = mtl; (arrow1).material = mtl; (arrow2).material = mtl; - this._Text.ColorIndex = this._Color; + this._Text.ColorIndex = this.DrawColorIndex; } GetGripPoints(): Array diff --git a/src/DatabaseServices/Dimension/DiameterDimension.ts b/src/DatabaseServices/Dimension/DiameterDimension.ts index 517ff82ba..6f6d1b725 100644 --- a/src/DatabaseServices/Dimension/DiameterDimension.ts +++ b/src/DatabaseServices/Dimension/DiameterDimension.ts @@ -1,4 +1,4 @@ -import { BufferGeometry, Line as TLine, Material, Mesh, Object3D, Vector3 } from "three"; +import { BufferGeometry, Material, Mesh, Object3D, Line as TLine, Vector3 } from "three"; import { Line2 } from "three/examples/jsm/lines/Line2"; import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices"; import { AddEntityDrawObject } from "../../Common/AddEntityDrawObject"; @@ -21,7 +21,7 @@ export class DiameterDimension extends RadiusDimension protected _TextString: string = "D<>"; InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D { - this._Text.ColorIndex = this.ColorIndex; + this._Text.ColorIndex = this.DrawColorIndex; let obj = new Object3D(); let colorMaterial = GetDimLineMaterial(this, renderType); @@ -100,13 +100,13 @@ export class DiameterDimension extends RadiusDimension arrow.material = line.material; arrow2.material = lineMaterial; - this._Text.ColorIndex = this.ColorIndex; + this._Text.ColorIndex = this.DrawColorIndex; //如果实体是拷贝的,那么可能修改材质失败 if (textObj.children[0]) { let mesh = textObj.children[0] as Mesh; - mesh.material = ColorMaterial.GetBasicMaterialDoubleSide(this.ColorIndex);//TODO:在布局时应该如何渲染? + mesh.material = ColorMaterial.GetBasicMaterialDoubleSide(this.DrawColorIndex);//TODO:在布局时应该如何渲染? } } diff --git a/src/DatabaseServices/Dimension/GetDimLineMaterial.ts b/src/DatabaseServices/Dimension/GetDimLineMaterial.ts index 31633df82..5709f5ca4 100644 --- a/src/DatabaseServices/Dimension/GetDimLineMaterial.ts +++ b/src/DatabaseServices/Dimension/GetDimLineMaterial.ts @@ -6,7 +6,7 @@ import { Entity } from "../Entity/Entity"; export function GetDimLineMaterial(dim: Entity, renderType: RenderType): LineBasicMaterial { if (renderType === RenderType.Wireframe) - return ColorMaterial.GetLineMaterial(dim.ColorIndex); + return ColorMaterial.GetLineMaterial(dim.DrawColorIndex); else if (renderType > 100) return ColorMaterial.GetLineMaterial(0); else diff --git a/src/DatabaseServices/Entity/Board.ts b/src/DatabaseServices/Entity/Board.ts index 7883f1f57..65678f6c5 100644 --- a/src/DatabaseServices/Entity/Board.ts +++ b/src/DatabaseServices/Entity/Board.ts @@ -2091,7 +2091,7 @@ export class Board extends ExtrudeSolid p.applyMatrix4(this.ArcBuild.Rotate2OCSMtx); } let geo = new BufferGeometry().setFromPoints(pts); - obj.add(new TLine(geo, ColorMaterial.GetLineMaterial(this._Color))); + obj.add(new TLine(geo, ColorMaterial.GetLineMaterial(this.DrawColorIndex))); return; } @@ -2125,7 +2125,7 @@ export class Board extends ExtrudeSolid if (renderType === RenderType.CustomNumberPrint) obj.add(...this.GetPrintObject3D()); else - obj.add(new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex, FrontSide, true))); + obj.add(new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex, FrontSide, true))); //#region 添加文字 if (!this._CustomNumberTextEntity) diff --git a/src/DatabaseServices/Entity/Circle.ts b/src/DatabaseServices/Entity/Circle.ts index 0ecd4d105..a02c758fb 100644 --- a/src/DatabaseServices/Entity/Circle.ts +++ b/src/DatabaseServices/Entity/Circle.ts @@ -266,7 +266,7 @@ export class Circle extends Curve } else { - let line = new TLine(cirGeo, ColorMaterial.GetLineMaterial(this._Color)); + let line = new TLine(cirGeo, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); obj.add(line); } @@ -287,7 +287,7 @@ export class Circle extends Curve else { let m = obj.children[0] as TLine; - m.material = material ? material : ColorMaterial.GetLineMaterial(this._Color); + m.material = material ? material : ColorMaterial.GetLineMaterial(this.DrawColorIndex); return obj; } diff --git a/src/DatabaseServices/Entity/Curve.ts b/src/DatabaseServices/Entity/Curve.ts index b56e250d6..55ed5455a 100644 --- a/src/DatabaseServices/Entity/Curve.ts +++ b/src/DatabaseServices/Entity/Curve.ts @@ -215,7 +215,7 @@ export abstract class Curve extends Entity return new Line2(geometry, ColorMaterial.PrintLineMatrial); } let geo = new BufferGeometry().setFromPoints(pts); - return new TLine(geo, ColorMaterial.GetLineMaterial(this._Color)); + return new TLine(geo, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); } /** @@ -255,7 +255,7 @@ export abstract class Curve extends Entity else { let m = obj as Line; - m.material = material || ColorMaterial.GetLineMaterial(this._Color); + m.material = material || ColorMaterial.GetLineMaterial(this.DrawColorIndex); } } diff --git a/src/DatabaseServices/Entity/Entity.ts b/src/DatabaseServices/Entity/Entity.ts index 24c84091c..ec356ba7f 100644 --- a/src/DatabaseServices/Entity/Entity.ts +++ b/src/DatabaseServices/Entity/Entity.ts @@ -16,6 +16,7 @@ import { CADFiler } from '../CADFiler'; import { CADObject } from '../CADObject'; import { HistorycRecord } from '../HistorycRecord'; import { ISerialize } from '../ISerialize'; +import { LayerTableRecord } from '../LayerTableRecord'; import { ObjectId } from '../ObjectId'; import { PhysicalMaterialRecord } from '../PhysicalMaterialRecord'; @@ -39,7 +40,8 @@ export class Entity extends CADObject protected _CacheDrawObject = new Map(); //材质id protected _MaterialId: ObjectId; - protected _Color: number = 7; + protected _Color: number = HostApplicationServices.CurrentColorindex; + protected _Layer: ObjectId; //自身坐标系 protected _Matrix = new Matrix4(); @@ -137,6 +139,39 @@ export class Entity extends CADObject this.Material = mtl; } + get HasLayer() { return this._Layer?.Object !== undefined; } + + get Layer() + { + return this._Layer?.Object ? this._Layer : HostApplicationServices.Database.LayerTable.Current; + } + + set Layer(id: ObjectId) + { + if (id === this._Layer) return; + this.WriteAllObjectRecord(); + const oldLayerIsOff = this._Layer?.Object?.IsOff; + const oldLayerIsLocked = this._Layer?.Object?.IsLocked; + const oldLayerColorIndex = this._Layer?.Object?.ColorIndex; + this._Layer = id; + // 更新隐藏 + if (id.Object.IsOff !== oldLayerIsOff) + this.UpdateVisible(); + // 更新锁定 + if (id.Object.IsLocked !== oldLayerIsLocked) + { + this.Freeze = id.Object.IsLocked; + for (let [type, obj] of this._CacheDrawObject) + this.UpdateDrawObjectMaterial(type, obj); + } + // 更新颜色 + else if (this._Color === 256 && id.Object.ColorIndex !== oldLayerColorIndex) + { + for (let [type, obj] of this._CacheDrawObject) + this.UpdateDrawObjectMaterial(type, obj); + } + } + set ColorIndex(color: number) { if (color !== this._Color) @@ -154,10 +189,17 @@ export class Entity extends CADObject this.Update(UpdateDraw.Material); } } + get ColorIndex(): number { return this._Color; } + + get DrawColorIndex(): number + { + return this._Color === 256 ? this.Layer.Object.ColorIndex : this._Color; + } + /** * 炸开实体 */ @@ -575,7 +617,7 @@ export class Entity extends CADObject get IsVisible() { - return !this._isErase && this._Visible; + return !this._isErase && this._Visible && !this.Layer.Object.IsOff; } UpdateVisible() @@ -790,11 +832,16 @@ export class Entity extends CADObject this._VisibleInRender = file.ReadBool(); else this._VisibleInRender = true; + + if (ver > 10) + this._Layer = file.ReadObjectId() as ObjectId; + else + this._Layer = undefined; } //对象将自身数据写入到文件. WriteFile(file: CADFiler) { - file.Write(10); + file.Write(11); super.WriteFile(file); file.Write(this._Color); file.WriteHardObjectId(this._MaterialId); @@ -810,6 +857,7 @@ export class Entity extends CADObject file.WriteBool(this._Freeze); file.WriteBool(this._VisibleInRender); + file.WriteHardObjectId(this._Layer); } //局部撤销 ApplyPartialUndo(undoData: CADObject) diff --git a/src/DatabaseServices/Entity/Extrude.ts b/src/DatabaseServices/Entity/Extrude.ts index 53e4dfca1..3686956ba 100644 --- a/src/DatabaseServices/Entity/Extrude.ts +++ b/src/DatabaseServices/Entity/Extrude.ts @@ -1687,12 +1687,12 @@ export class ExtrudeSolid extends Entity { if (renderType === RenderType.Wireframe) { - return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex, this.Freeze)); + return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex, this.Freeze)); } else if (renderType === RenderType.Conceptual) { return new Object3D().add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex, FrontSide, true, this.Freeze)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex, FrontSide, true, this.Freeze)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetConceptualEdgeMaterial()) ); } @@ -2029,7 +2029,7 @@ export class ExtrudeSolid extends Entity if (this.grooves.length > 100 || (!this.Has2DPath && (this.grooves.length === 0 || this.grooves.every(g => equaln(g.thickness, this.thickness)))) ) { - let coords = FastExtrudeEdgeGeometry(this, this.ColorIndex, 12, true); + let coords = FastExtrudeEdgeGeometry(this, this.DrawColorIndex, 12, true); let edgeGeo = new BufferGeometry(); edgeGeo.setAttribute('position', new Float32BufferAttribute(coords, 3)); this._EdgeGeometry = edgeGeo; @@ -2125,12 +2125,12 @@ export class ExtrudeSolid extends Entity { let l = obj as LineSegments; l.geometry = this.EdgeGeometry; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex, this.Freeze); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex, this.Freeze); } else if (renderType === RenderType.Conceptual) { return obj.add( - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex, FrontSide, true, this.Freeze)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex, FrontSide, true, this.Freeze)), new LineSegments(this.EdgeGeometry, ColorMaterial.GetConceptualEdgeMaterial()) ); } @@ -2180,12 +2180,12 @@ export class ExtrudeSolid extends Entity if (renderType === RenderType.Wireframe) { let l = obj as TLine; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex, this.Freeze); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex, this.Freeze); } else if (renderType === RenderType.Conceptual) { let mesh = obj.children[0] as Mesh; - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex, FrontSide, true, this.Freeze); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex, FrontSide, true, this.Freeze); } else if (renderType === RenderType.Physical2) { diff --git a/src/DatabaseServices/Entity/Line.ts b/src/DatabaseServices/Entity/Line.ts index faa4a6dd8..2752116ce 100644 --- a/src/DatabaseServices/Entity/Line.ts +++ b/src/DatabaseServices/Entity/Line.ts @@ -85,7 +85,7 @@ export class Line extends Curve return new Line2(geometry, ColorMaterial.PrintLineMatrial); } let geo = new BufferGeometry().setFromPoints(pts); - return new TLine(geo, ColorMaterial.GetLineMaterial(this._Color)); + return new TLine(geo, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); } /** diff --git a/src/DatabaseServices/Entity/Region.ts b/src/DatabaseServices/Entity/Region.ts index fea3823b2..50e45961f 100644 --- a/src/DatabaseServices/Entity/Region.ts +++ b/src/DatabaseServices/Entity/Region.ts @@ -293,13 +293,13 @@ export class Region extends Entity { if (renderType === RenderType.Wireframe) { - return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); } else if (renderType === RenderType.Conceptual) { return new Object3D().add( - new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)), - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), ); } else if (renderType === RenderType.Physical) @@ -319,7 +319,7 @@ export class Region extends Entity mesh.castShadow = true; mesh.receiveShadow = true; return new Object3D().add( - new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)), mesh, ); } @@ -333,13 +333,13 @@ export class Region extends Entity { let l = obj as LineSegments; l.geometry = this.EdgeGeometry; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else if (renderType === RenderType.Conceptual) { return obj.add( - new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)), - new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)), + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)), ); } else if (renderType === RenderType.Physical) @@ -354,7 +354,7 @@ export class Region extends Entity mesh.castShadow = true; mesh.receiveShadow = true; return obj.add( - new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)), mesh, ); } @@ -374,7 +374,7 @@ export class Region extends Entity if (type === RenderType.Wireframe || type === RenderType.Print) { let line = obj as LineSegments; - line.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + line.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else if (type === RenderType.Conceptual) { @@ -383,12 +383,12 @@ export class Region extends Entity if (i % 2 === 0) { let l = obj.children[i] as LineSegments; - l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + l.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } else { let mesh = obj.children[i] as Mesh; - mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetConceptualMaterial(this.DrawColorIndex); } } } diff --git a/src/DatabaseServices/LayerTableRecord.ts b/src/DatabaseServices/LayerTableRecord.ts new file mode 100644 index 000000000..37c9a9155 --- /dev/null +++ b/src/DatabaseServices/LayerTableRecord.ts @@ -0,0 +1,58 @@ +import { AutoRecord } from "./AutoRecord"; +import { Factory } from "./CADFactory"; +import { CADFiler } from "./CADFiler"; +import { CADObject } from "./CADObject"; +import { SymbolTableRecord } from "./SymbolTableRecord"; + +@Factory +export class LayerTableRecord extends SymbolTableRecord +{ + @AutoRecord ColorIndex: number = 7; + + // @AutoRecord LineWeight: number = 0; + + @AutoRecord IsOff = false;//关 + + @AutoRecord IsLocked = false;//锁定 + + // @AutoRecord IsFrozen = false;//冻结 + + // @AutoRecord IsHidden = false;//隐藏 + + // @AutoRecord Description = "";//描述 + + constructor() + { + super(); + } + + //#region -------------------------File------------------------- + //对象从文件中读取数据,初始化自身 + override ReadFile(file: CADFiler) + { + let ver = file.Read(); + super.ReadFile(file); + + this.ColorIndex = file.Read(); + this.IsOff = file.Read(); + this.IsLocked = file.Read(); + } + + //对象将自身数据写入到文件. + override WriteFile(file: CADFiler) + { + file.Write(1); + super.WriteFile(file); + + file.Write(this.ColorIndex); + file.Write(this.IsOff); + file.Write(this.IsLocked); + } + + //局部撤销 + override ApplyPartialUndo(undoData: CADObject) + { + super.ApplyPartialUndo(undoData); + } + //#endregion +} diff --git a/src/DatabaseServices/Room/Entity/Wall/RoomWallLine.ts b/src/DatabaseServices/Room/Entity/Wall/RoomWallLine.ts index f88ef7077..a9dcd030b 100644 --- a/src/DatabaseServices/Room/Entity/Wall/RoomWallLine.ts +++ b/src/DatabaseServices/Room/Entity/Wall/RoomWallLine.ts @@ -801,7 +801,7 @@ export class RoomWallLine extends RoomWallBase axisLine.computeLineDistances(); obj.add(axisLine); - let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); obj.add(line); } else if (renderType === RenderType.Print) @@ -810,8 +810,8 @@ export class RoomWallLine extends RoomWallBase } else if (renderType === RenderType.Conceptual) { - let mesh = new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)); - let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + let mesh = new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.DrawColorIndex)); + let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.DrawColorIndex)); obj.add(mesh, line); } return obj; diff --git a/src/DatabaseServices/SymbolTableRecord.ts b/src/DatabaseServices/SymbolTableRecord.ts index 17b074a42..27e790afe 100644 --- a/src/DatabaseServices/SymbolTableRecord.ts +++ b/src/DatabaseServices/SymbolTableRecord.ts @@ -1,6 +1,9 @@ import { Status } from "../Common/Status"; +import { Factory } from "./CADFactory"; import { CADFiler } from "./CADFiler"; import { CADObject } from "./CADObject"; +import { HistorycRecord } from "./HistorycRecord"; +import { ISerialize } from "./ISerialize"; import { SymbolTable } from "./Tables/SymbolTable"; export abstract class SymbolTableRecord extends CADObject @@ -13,7 +16,16 @@ export abstract class SymbolTableRecord extends CADObject set Name(name: string) { if (this.name === name) return; - this.WriteAllObjectRecord(); + + let undoData = this.UndoRecord(); + if (undoData) + { + let hr = new HistorycRecord(); + hr.undoData = new NameData(this.name); + hr.redoData = new NameData(name); + undoData.WriteObjectHistoryPath(this, hr); + } + if (this.Owner) { let symbolTable = this.Owner.Object as SymbolTable; @@ -42,4 +54,40 @@ export abstract class SymbolTableRecord extends CADObject this.name = file.Read(); } + //局部撤销 + ApplyPartialUndo(undoData: CADObject) + { + super.ApplyPartialUndo(undoData); + if (undoData instanceof NameData) + { + if (this.name === undoData.name) + return; + if (this.Owner) + { + let symbolTable = this.Owner.Object as SymbolTable; + if (!symbolTable.ChangeRecordName(this, undoData.name)) + return; + } + this.name = undoData.name; + } + } +} + +/** + * 记录当前Name的序列化数据 + */ +@Factory +export class NameData implements ISerialize +{ + ReadFile(file: CADFiler): this + { + this.name = file.Read(); + return this; + } + WriteFile(file: CADFiler): this + { + file.Write(this.name); + return this; + } + constructor(public name: string) { } } diff --git a/src/DatabaseServices/Tables/LayerTable.ts b/src/DatabaseServices/Tables/LayerTable.ts new file mode 100644 index 000000000..009be5aed --- /dev/null +++ b/src/DatabaseServices/Tables/LayerTable.ts @@ -0,0 +1,173 @@ +import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices"; +import { Factory } from "../CADFactory"; +import { CADFiler } from "../CADFiler"; +import { CADObject } from "../CADObject"; +import { HistorycRecord } from "../HistorycRecord"; +import { ISerialize } from "../ISerialize"; +import { LayerTableRecord } from "../LayerTableRecord"; +import { ObjectId } from "../ObjectId"; +import { SymbolTable } from "./SymbolTable"; + +@Factory +export class LayerTable extends SymbolTable +{ + protected _Current: ObjectId;//默认当前图层 + + public get Current(): ObjectId + { + return this._Current; + } + + public set Current(id: ObjectId)//设置当前层 + { + if (this._Current === id) return; + + let undoData = this.UndoRecord(); + if (undoData) + { + let hr = new HistorycRecord(); + hr.undoData = new ObjectIdData(this._Current); + hr.redoData = new ObjectIdData(id); + undoData.WriteObjectHistoryPath(this, hr); + } + + this._Current = id; + HostApplicationServices.CurrentLayer = id; + } + + /** 用于描述图层结构的根节点 */ + private _Root = new LayerNode("根节点", true); + + public get Root(): LayerNode + { + return this._Root; + } + + public set Root(root: LayerNode) + { + if (this._Root === root) return; + + let undoData = this.UndoRecord(); + if (undoData) + { + let hr = new HistorycRecord(); + hr.undoData = new ObjectTreeData(this._Root); + hr.redoData = new ObjectTreeData(root); + undoData.WriteObjectHistoryPath(this, hr); + } + + this._Root = root; + } + + //#region -------------------------File------------------------- + //对象从文件中读取数据,初始化自身 + override ReadFile(file: CADFiler) + { + let ver = file.Read(); + super.ReadFile(file); + + this._Current = file.ReadObjectId() as ObjectId; + this._Root = file.ReadObject(); + } + //对象将自身数据写入到文件. + override WriteFile(file: CADFiler) + { + file.Write(1); + super.WriteFile(file); + + file.WriteObjectId(this._Current); + file.WriteObject(this._Root); + } + //局部撤销 + override ApplyPartialUndo(undoData: CADObject) + { + if (undoData instanceof ObjectIdData) + { + this._Current = undoData.objectId as any; + HostApplicationServices.CurrentLayer = this._Current; + } + else if (undoData instanceof ObjectTreeData) + this._Root = undoData.data; + else + super.ApplyPartialUndo(undoData); + } + //#endregion +} + +/** 用于描述图层结构的节点 */ +@Factory +export class LayerNode implements ISerialize +{ + children: LayerNode[]; + + constructor(public name: string, isHasChildren = false) + { + if (isHasChildren) + this.children = []; + } + + ReadFile(f: CADFiler) + { + this.name = f.ReadString(); + const count = f.Read(); + if (count !== -1) + { + this.children = []; + for (let i = 0; i < count; i++) + { + const child = new LayerNode(""); + child.ReadFile(f); + this.children.push(child); + } + } + } + + WriteFile(f: CADFiler) + { + f.WriteString(this.name); + if (!this.children) + f.Write(-1); + else + { + f.Write(this.children.length); + for (const child of this.children) + child.WriteFile(f); + } + } +} + +/** + * 记录当前id的序列化数据 + */ +@Factory +export class ObjectIdData implements ISerialize +{ + ReadFile(file: CADFiler): this + { + this.objectId = file.ReadObjectId(); + return this; + } + WriteFile(file: CADFiler): this + { + file.WriteObjectId(this.objectId); + return this; + } + constructor(public objectId: ObjectId) { } +} + +/** 记录树状结构的序列化数据*/ +@Factory +export class ObjectTreeData implements ISerialize +{ + ReadFile(file: CADFiler): this + { + this.data = file.ReadObject(); + return this; + } + WriteFile(file: CADFiler): this + { + file.WriteObject(this.data); + return this; + } + constructor(public data: LayerNode) { } +} diff --git a/src/DatabaseServices/Tables/SymbolTable.ts b/src/DatabaseServices/Tables/SymbolTable.ts index ab97df9c9..928057b2a 100644 --- a/src/DatabaseServices/Tables/SymbolTable.ts +++ b/src/DatabaseServices/Tables/SymbolTable.ts @@ -133,6 +133,8 @@ export class SymbolTable extends CADObject this.Symbols.delete(undoData.Index as string); undoData.RemoveObject = obj; } + else + super.ApplyPartialUndo(undoData); // else if (undoData instanceof RenameObjectData) // { // let record = this.GetAt(undoData._oldName); diff --git a/src/DatabaseServices/Template/TempateUtils.ts b/src/DatabaseServices/Template/TempateUtils.ts index 520ec7bb9..39ed0e82c 100644 --- a/src/DatabaseServices/Template/TempateUtils.ts +++ b/src/DatabaseServices/Template/TempateUtils.ts @@ -5,6 +5,7 @@ import { FaceDirection } from "../../Add-on/DrawDrilling/DrillType"; import { IsHinge } from "../../Add-on/HideSelect/HideSelectUtils"; import { app } from "../../ApplicationServices/Application"; import { arrayRemoveOnce } from "../../Common/ArrayExt"; +import { CommandNames } from "../../Common/CommandNames"; import { TemplateUrls } from "../../Common/HostUrl"; import { Log, LogType } from "../../Common/Log"; import { PostJson, RequestStatus } from "../../Common/Request"; @@ -1375,7 +1376,7 @@ export async function EditorOnlineTemplate(template: TemplateRecord, module_id: store.InitParams(); app.Editor.ModalManage.DestoryAll(); app.Editor.ModalManage.RenderModeless(TemplateEditor, { store, tid: module_id, isCheck, diy_logo }); - }, "编辑模板"); + }, CommandNames.EditTemplate); } /**仅移除模块节点 */ diff --git a/src/DatabaseServices/Text/Text.ts b/src/DatabaseServices/Text/Text.ts index 3b55cd00c..f02e1b190 100644 --- a/src/DatabaseServices/Text/Text.ts +++ b/src/DatabaseServices/Text/Text.ts @@ -143,7 +143,7 @@ export class Text extends Entity } mesh.geometry = geometry; - let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.ColorIndex; + let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.DrawColorIndex; mesh.material = this.IsDoubleMesh ? ColorMaterial.GetBasicMaterial(color) : ColorMaterial.GetBasicMaterialDoubleSide(color); if (this.IsDoubleMesh) @@ -321,7 +321,7 @@ export class Text extends Entity let obj = this.CacheDrawObject.get(RenderType.Wireframe); if (obj && obj.children.length === 1 && (obj.children[0] as Mesh).geometry) { - let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.ColorIndex; + let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.DrawColorIndex; let mesh = new Mesh((obj.children[0] as Mesh).geometry, ColorMaterial.GetBasicMaterial(color)); g.add((mesh)); g.updateMatrixWorld(true); @@ -343,7 +343,7 @@ export class Text extends Entity { let mesh = en.children[0] as Mesh; //因为我们是OnlyRnderType 所以Print会变成WireframePrint,所以要用下面的写法 - let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.ColorIndex; + let color = (renderType > 100 || renderType === RenderType.Print) ? 0 : this.DrawColorIndex; mesh.material = ColorMaterial.GetBasicMaterialDoubleSide(color); } } diff --git a/src/DatabaseServices/ViewportEntity.ts b/src/DatabaseServices/ViewportEntity.ts index add29010d..02be10406 100644 --- a/src/DatabaseServices/ViewportEntity.ts +++ b/src/DatabaseServices/ViewportEntity.ts @@ -18,6 +18,7 @@ import { Factory } from "./CADFactory"; import { CADFiler } from "./CADFiler"; import { Board } from "./Entity/Board"; import { Entity } from "./Entity/Entity"; +import { LayerTableRecord } from "./LayerTableRecord"; import { ObjectId } from "./ObjectId"; import { Text } from "./Text/Text"; @@ -33,6 +34,7 @@ export class ViewportEntity extends Entity private _renderType: RenderType = RenderType.Print; private _HideObjectIds = new Set(); private _ShowObjectIds = new Set(); + private _FreezeLayers = new Set>(); private _RenderTarget: WebGLRenderTarget = new WebGLRenderTarget(0, 0); private _EntitysBoundingBox: Box3; ViewData = { @@ -110,6 +112,25 @@ export class ViewportEntity extends Entity return [...this._ShowObjectIds]; } + HasFreezeLayer(id: ObjectId) + { + return this._FreezeLayers.has(id); + } + + DeleteFreezeLayer(id: ObjectId) + { + if (!this._FreezeLayers.has(id)) return; + this.WriteAllObjectRecord(); + this._FreezeLayers.delete(id); + } + + AddFreezeLayer(id: ObjectId) + { + if (this._FreezeLayers.has(id)) return; + this.WriteAllObjectRecord(); + this._FreezeLayers.add(id); + } + //#region 显示隐藏实体控制 @@ -468,6 +489,17 @@ export class ViewportEntity extends Entity let hideIndexs = new Set(this.HideObjects.map(i => i.Index.toString())); let showIndexs = new Set(this.ShowObjects.map(i => i.Index.toString())); + // 隐藏被视口冻结的实体 + for (let id of this._ShowObjectIds) + { + if (this._FreezeLayers.has((id.Object as Entity)?.Layer)) + { + const name = id.Index.toString(); + hideIndexs.add(name); + showIndexs.delete(name); + } + } + for (let o of this.scene.children) { if (!showIndexs.has(o.name) || hideIndexs.has(o.name)) @@ -573,13 +605,25 @@ export class ViewportEntity extends Entity this.camera.Camera.up = new Vector3(file.Read(), file.Read(), file.Read()); } + this._FreezeLayers.clear(); + if (ver > 4) + { + let count = file.Read(); + for (let i = 0; i < count; i++) + { + let id = file.ReadSoftObjectId() as ObjectId; + if (id) + this._FreezeLayers.add(id); + } + } + if (!this._isErase) this.UpdateScene(); } WriteFile(file: CADFiler) { super.WriteFile(file); - file.Write(4); + file.Write(5); this.camera.WriteFile(file); file.Write(this._width); file.Write(this._height); @@ -592,5 +636,9 @@ export class ViewportEntity extends Entity file.WriteVec3(this.camera.Direction); file.WriteVec3(this.camera.Camera.up); + + // 图层的视口冻结 + file.Write(this._FreezeLayers.size); + this._FreezeLayers.forEach(id => file.WriteSoftObjectId(id)); } } diff --git a/src/Editor/BoardMoveTool.ts b/src/Editor/BoardMoveTool.ts index 76ffd33b1..f15326be8 100644 --- a/src/Editor/BoardMoveTool.ts +++ b/src/Editor/BoardMoveTool.ts @@ -257,6 +257,7 @@ export class BoardMoveTool for (let i = this._DrawDims.length; i < this._DrawDimPoints.length; i++) { let dim = new AlignedDimension(); + dim.ColorIndex = 7; dim.TextSize = 20; dim.LeadVisible = false; this._DrawDims.push(dim); diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index e0c35e01a..6e79d544f 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -295,7 +295,7 @@ import { Command_TestSum } from "../Nest/Test/TestSum"; import { Command_TestYH2 } from "../Nest/Test/TestYH2"; import { Command_TestYHSingle } from "../Nest/Test/TestYHSingle"; import { Command_TestYHWorker } from "../Nest/Test/TestYHWorker"; -import { Comman_SwitchServers, Command_ChangeLayout, Command_ModuleBar, Command_PropertiesBar, Command_RightPanel, RightTabCommandMap } from "../UI/Components/CommandPanel/SystemCommand/UICpmmand"; +import { Comman_SwitchServers, Command_ChangeLayout, Command_LayerListBar, Command_ModuleBar, Command_PropertiesBar, Command_RightPanel, RightTabCommandMap } from "../UI/Components/CommandPanel/SystemCommand/UICpmmand"; import Command_Gallery from "../UI/Components/Gallery/command/Command_Gallery"; import { Command_HeadCeilingContourManage } from "../UI/Components/HeadCeiling/HeadCeilingContourManageCommand"; import { Command_HeadCeilingInfoConfigPanel, Command_HeadCeilingMaterialPanel } from "../UI/Components/HeadCeiling/HeadCeilingInfoConfigPanelCommand"; @@ -634,6 +634,7 @@ export function registerCommand() //UI命令 commandMachine.RegisterCommand(CommandNames.Comanp, new Command_CommandPanel()); commandMachine.RegisterCommand(CommandNames.PropertiesBar, new Command_PropertiesBar()); + commandMachine.RegisterCommand(CommandNames.LayerListBar, new Command_LayerListBar()); commandMachine.RegisterCommand(CommandNames.ModuleBar, new Command_ModuleBar()); commandMachine.RegisterCommand(CommandNames.ChangeLayout, new Command_ChangeLayout()); diff --git a/src/Editor/DbClick/DbClick.ts b/src/Editor/DbClick/DbClick.ts index f63c17c11..7c0ebaa2d 100644 --- a/src/Editor/DbClick/DbClick.ts +++ b/src/Editor/DbClick/DbClick.ts @@ -37,6 +37,7 @@ import { CompositeMatalPanel } from "../../UI/Components/RightPanel/CompositeMet import { RightTabId } from "../../UI/Components/RightPanel/RightPanel"; import { ToplineMetalsPanel } from "../../UI/Components/RightPanel/ToplineMetalsPanel"; import { AppToaster } from "../../UI/Components/Toaster"; +import { UpdateLayerByNoViewPoint, UpdateLayerByViewPoint } from "../../UI/Components/ToolBar/Layer/LayerCMD"; import RoomFlatTopParams from "../../UI/Components/ToolBar/ModifyModel/RoomFlatTopParams"; import { IConfigStore } from "../../UI/Store/BoardStore"; import { EntityStore } from "../../UI/Store/EntityStore"; @@ -63,6 +64,7 @@ export class DbClickManager extends Singleton { if (app.Viewer.CurrentViewport) { + UpdateLayerByNoViewPoint(); let oldVP = app.Viewer.CurrentViewport; app.Viewer.CurrentViewport = null; pickObj = PointPickOneObject(app.Editor.MouseCtrl._CurMousePointVCS, app.Viewer, { filterErase: true }); @@ -294,6 +296,7 @@ export class DbClickManager extends Singleton app.Viewer.Scene.add(app.Viewer.GripScene); } }, VP_TOATER_KEY); + UpdateLayerByViewPoint(pickEnt); } else if (pickEnt instanceof BulkheadCeiling) { diff --git a/src/Editor/VisualSpaceBox.ts b/src/Editor/VisualSpaceBox.ts index 2e472a143..a7384619c 100644 --- a/src/Editor/VisualSpaceBox.ts +++ b/src/Editor/VisualSpaceBox.ts @@ -180,9 +180,9 @@ export class VisualSpaceBox extends Entity let obj = new Object3D(); //box - obj.add(new Mesh(backGeo, ColorMaterial.GetBasicMaterialTransparent2(this.ColorIndex, 0.5))); + obj.add(new Mesh(backGeo, ColorMaterial.GetBasicMaterialTransparent2(this.DrawColorIndex, 0.5))); //edge - obj.add(new LineSegments(edgeGeo, ColorMaterial.GetLineMaterial(this.ColorIndex))); + obj.add(new LineSegments(edgeGeo, ColorMaterial.GetLineMaterial(this.DrawColorIndex))); obj.add(this._LText.DrawObject); obj.add(this._WText.DrawObject); @@ -243,8 +243,8 @@ export class VisualSpaceBox extends Entity { let [mesh, line] = obj.children as [Mesh, LineSegments]; - mesh.material = ColorMaterial.GetBasicMaterialTransparent2(this.ColorIndex, 0.2); - line.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + mesh.material = ColorMaterial.GetBasicMaterialTransparent2(this.DrawColorIndex, 0.2); + line.material = ColorMaterial.GetLineMaterial(this.DrawColorIndex); } //#endregion diff --git a/src/Reactor/LayerReactor.ts b/src/Reactor/LayerReactor.ts new file mode 100644 index 000000000..23ab70bc0 --- /dev/null +++ b/src/Reactor/LayerReactor.ts @@ -0,0 +1,65 @@ +import { end } from "xaop"; +import { app } from "../ApplicationServices/Application"; +import { CommandNames } from "../Common/CommandNames"; +import { CommandHistoryRecord } from "../DatabaseServices/CommandHistoryRecord"; +import { LayerTableRecord } from "../DatabaseServices/LayerTableRecord"; +import { LayerTable } from "../DatabaseServices/Tables/LayerTable"; +import { LayerTopStore } from "../UI/Components/ToolBar/Layer/LayerPanel"; +import { LayerStore } from "../UI/Components/ToolBar/Layer/State/Store"; +import { DataToViewForLayer } from "../UI/Components/ToolBar/Layer/State/Transform"; + + +/** 图层反应器 */ +export class LayerReactor +{ + constructor() + { + //解析撤销重做 + const ParseFunction = (isUndo = true) => + { + return (cmdName: string, historyRec: CommandHistoryRecord) => + { + if (!app.Database.LayerTable || !app.Database.LayerTable.Current) return; + // 图层UI随图层表更新 + for (const [k, v] of historyRec.HistoryList) + { + const o = k.Object; + if (o instanceof LayerTableRecord || o instanceof LayerTable) + { + DataToViewForLayer.UpdateAll(); + break; + } + } + }; + }; + + const ParseUndo = ParseFunction(true); + const ParseRedo = ParseFunction(false); + + end(app.Database.hm, app.Database.hm.RedoEvent, ParseRedo); + end(app.Database.hm, app.Database.hm.UndoEvent, ParseUndo); + + // 新建图纸时初始化图层UI + const InitLayer = () => + { + const layerStore = LayerStore.GetInstance(); + const layerTopStore = LayerTopStore.GetInstance(); + DataToViewForLayer.UpdateAll(); + layerTopStore.setCurrentLayerValue(layerStore.currentLayer.name); + }; + end(app, app.CreateDocument, () => InitLayer()); + + // 打开图纸时加载图层UI + end(app, app.OpenFile, () => InitLayer()); + + // 插入图纸/插入模板时更新图层UI + app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) => + { + if (cmdName === CommandNames.Insert || cmdName === CommandNames.InsertModule || cmdName === CommandNames.EditTemplate) + { + DataToViewForLayer.UpdateRootByTable(); + DataToViewForLayer.UpdateAll(); + } + }); + } +} diff --git a/src/UI/Components/Board/BoardConfigModal.tsx b/src/UI/Components/Board/BoardConfigModal.tsx index 69b0c3759..08b7c86da 100644 --- a/src/UI/Components/Board/BoardConfigModal.tsx +++ b/src/UI/Components/Board/BoardConfigModal.tsx @@ -546,7 +546,7 @@ export class BoardConfigModal extends React.Component for (const curve of finalCurve) { - const colorIndex = curve.ColorIndex; + const colorIndex = curve.DrawColorIndex; if (!colorIndexMap.has(colorIndex)) colorIndexMap.set(colorIndex, [curve]); else @@ -564,7 +564,7 @@ export class BoardConfigModal extends React.Component { for (let c of g) { - let cd = rightStore.modeling2Store.modelingItems[c.ColorIndex - 1];//cd可能为空,因为颜色不受控制 + let cd = rightStore.modeling2Store.modelingItems[c.DrawColorIndex - 1];//cd可能为空,因为颜色不受控制 if (!cd || cd.items.every(item => CheckExpr(item.depth as string, { BH: br.Thickness }).res <= 0) || cd.items.every(item => item.knife.id === "")) { @@ -623,11 +623,11 @@ export class BoardConfigModal extends React.Component //没有刀具轮廓时不保留偏移的路径 if (i === 0) { - path.ColorIndex = c.ColorIndex; - if (!pathMap.has(c.ColorIndex)) - pathMap.set(c.ColorIndex, [path]); + path.ColorIndex = c.DrawColorIndex; + if (!pathMap.has(c.DrawColorIndex)) + pathMap.set(c.DrawColorIndex, [path]); else - pathMap.get(c.ColorIndex).push(path); + pathMap.get(c.DrawColorIndex).push(path); } continue; } @@ -670,11 +670,11 @@ export class BoardConfigModal extends React.Component //不记录偏移的路径 if (i > 0) continue; - path.ColorIndex = c.ColorIndex; - if (!pathMap.has(c.ColorIndex)) - pathMap.set(c.ColorIndex, [path]); + path.ColorIndex = c.DrawColorIndex; + if (!pathMap.has(c.DrawColorIndex)) + pathMap.set(c.DrawColorIndex, [path]); else - pathMap.get(c.ColorIndex).push(path); + pathMap.get(c.DrawColorIndex).push(path); } break; @@ -930,7 +930,7 @@ export class BoardConfigModal extends React.Component { for (let c of g) { - let cd = rightStore.modelingStore.modelingItems[c.ColorIndex - 1]; + let cd = rightStore.modelingStore.modelingItems[c.DrawColorIndex - 1]; if (!cd || cd.height <= 0) break; @@ -939,10 +939,10 @@ export class BoardConfigModal extends React.Component //在创建内部造型时,如果存在封闭的轮廓或者圆,那么自动分裂将失效(需要用户自己裂开) let contours = CreateContours(g); - if (!contourMap.has(c.ColorIndex)) - contourMap.set(c.ColorIndex, contours); + if (!contourMap.has(c.DrawColorIndex)) + contourMap.set(c.DrawColorIndex, contours); else - contourMap.get(c.ColorIndex).push(...contours); + contourMap.get(c.DrawColorIndex).push(...contours); //删除应用的轮廓 if (contours.length) diff --git a/src/UI/Components/CommandPanel/CommandList.ts b/src/UI/Components/CommandPanel/CommandList.ts index b5e0eb13b..f399d5b4f 100644 --- a/src/UI/Components/CommandPanel/CommandList.ts +++ b/src/UI/Components/CommandPanel/CommandList.ts @@ -3080,6 +3080,15 @@ export const CommandList: ICommand[] = [ chDes: "开关右侧面板", defaultHotkeys: HotkeyList.C2, }, + { + typeId: "interface", + defaultCustom: "LAYERLISTBAR", + command: CommandNames.LayerListBar, + type: "界面", + chName: "开关左侧图层栏", + chDes: "显示图层列表", + defaultHotkeys: HotkeyList.C3, + }, { typeId: "interface", defaultCustom: "CHANGELAYOUT", diff --git a/src/UI/Components/CommandPanel/SystemCommand/UICpmmand.ts b/src/UI/Components/CommandPanel/SystemCommand/UICpmmand.ts index 084403cfc..41d56a347 100644 --- a/src/UI/Components/CommandPanel/SystemCommand/UICpmmand.ts +++ b/src/UI/Components/CommandPanel/SystemCommand/UICpmmand.ts @@ -26,6 +26,14 @@ export class Command_PropertiesBar implements Command } } +export class Command_LayerListBar implements Command +{ + async exec() + { + DownPanelStore.GetInstance().ToggleLayerList(); + } +} + export class Command_ModuleBar implements Command { async exec() diff --git a/src/UI/Components/Template/TemplateComponent.tsx b/src/UI/Components/Template/TemplateComponent.tsx index bbee8482e..ecc963a25 100644 --- a/src/UI/Components/Template/TemplateComponent.tsx +++ b/src/UI/Components/Template/TemplateComponent.tsx @@ -10,6 +10,7 @@ import { templateTagCommand } from '../../../Add-on/Template/TemplateTagCommand' import { app } from '../../../ApplicationServices/Application'; import { equalArray } from '../../../Common/ArrayExt'; import { EBoardKeyList } from '../../../Common/BoardKeyList'; +import { CommandNames } from '../../../Common/CommandNames'; import { TemplateUrls } from '../../../Common/HostUrl'; import { DirectoryId, PostJson, RequestStatus } from '../../../Common/Request'; import { DuplicateRecordCloning } from '../../../Common/Status'; @@ -290,7 +291,7 @@ export class TemplateManage extends React.Component { if (this.templateManageOption.autoCutOption.isAutoCut) await AutoCutting(this.templateManageOption.autoCutOption.isRelevance, true); - }, "插入模块"); + }, CommandNames.InsertModule); this.templateManageOption.option.cabName = this.templateManageOption.option.originCabName + (++this.templateManageOption.option.cabIndex); app.Editor.ModalManage.ToggleShow(); app.Editor.MaskManage.ShowMask(); diff --git a/src/UI/Components/ToolBar/Layer/Component/Color.css b/src/UI/Components/ToolBar/Layer/Component/Color.css new file mode 100644 index 000000000..925b8c152 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/Color.css @@ -0,0 +1,7 @@ +.colorHoverActive { + border-color: #fff !important; +} + +.colorHover:hover { + border-color: #fff !important; +} diff --git a/src/UI/Components/ToolBar/Layer/Component/Color.tsx b/src/UI/Components/ToolBar/Layer/Component/Color.tsx new file mode 100644 index 000000000..20411de68 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/Color.tsx @@ -0,0 +1,89 @@ +import { Button, Classes } from "@blueprintjs/core"; +import { observable } from "mobx"; +import { observer } from "mobx-react"; +import React from "react"; +import { app } from "../../../../../ApplicationServices/Application"; +import { ColorPalette } from "../../../../../Common/ColorPalette"; +import { ModalContainer, ModalHeader } from "../../../Modal/ModalContainer"; +import "./Color.css"; +import { ColorAPI } from "./ColorAPI"; + +/** 颜色选择的弹窗 */ +@observer +export class ColorDialog extends React.Component<{ colorIndex: number, onConfirm?: (colorIndex?: number) => void; }> { + constructor(props) + { + super(props); + } + + /** 图层名称输入框的DOM */ + _ColorManagerRef = React.createRef(); + + // 视图渲染(这是主要部分,上面做的都是一些参数的初始化) + public render() + { + const { colorIndex, onConfirm } = this.props; + return ( + + app.Editor.ModalManage.Destory()} + /> +
+ +
+
+
+
+
+
+ ); + } +} + +/** 颜色选择器 */ +@observer +class ColorManager extends React.Component<{ colorIndex: number; }> { + constructor(props) + { + super(props); + } + + /** 当前选择的颜色索引 */ + @observable + colorIndex = this.props.colorIndex; + + // 视图渲染(这是主要部分,上面做的都是一些参数的初始化) + public render() + { + return ( +
+ {ColorPalette.slice(0, 256).map((color, index) =>
+ { + this.colorIndex = index; + }}>{index}
)} +
+ ); + } +} + +/** 颜色块 */ +export const ColorBlock = (props: { colorIndex: number; }) =>
; diff --git a/src/UI/Components/ToolBar/Layer/Component/ColorAPI.ts b/src/UI/Components/ToolBar/Layer/Component/ColorAPI.ts new file mode 100644 index 000000000..12c43b868 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/ColorAPI.ts @@ -0,0 +1,20 @@ +import { ColorPalette } from "../../../../../Common/ColorPalette"; + +export class ColorAPI +{ + /** 获取WebCAD中的颜色 */ + static GetColor = (colorIndex: number) => `rgb(${ColorPalette[colorIndex][0]}, ${ColorPalette[colorIndex][1]}, ${ColorPalette[colorIndex][2]})`; + + /** 获取WebCAD中的颜色索引(头尾相连) */ + static GetColorIndex = (index: number) => index % 7 + 1; + + /** RGB转黑白色 */ + static Rgb2Gray = (r: number, g: number, b: number) => (r * 0.299) + (g * 0.587) + (b * 0.114) > 128 ? 255 : 0; + + /** 获取WebCAD中的颜色对应的反向黑白色 */ + static GetGrayColor(colorIndex: number) + { + const value = Math.abs(255 - ColorAPI.Rgb2Gray(ColorPalette[colorIndex][0], ColorPalette[colorIndex][1], ColorPalette[colorIndex][2])); + return `rgb(${value},${value},${value})`; + }; +} diff --git a/src/UI/Components/ToolBar/Layer/Component/Icon.tsx b/src/UI/Components/ToolBar/Layer/Component/Icon.tsx new file mode 100644 index 000000000..fe1e3fa7a --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/Icon.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +/** 创建一个SVG图标 */ +export const IconSVG = (props: { name: string, size?: number, color?: string; }) => +{ + const { name, size = 40, color = "#000000" } = props; + if (name === "图层特性") + return + + + + + + + + + + + + + ; + if (name === "锁定选定对象图层") + return + + ; + if (name === "解锁选定对象图层") + return + + ; + if (name === "置为当前图层") + return + + ; + if (name === "特性匹配") + return + + + + + + + + + + ; +}; diff --git a/src/UI/Components/ToolBar/Layer/Component/Select.css b/src/UI/Components/ToolBar/Layer/Component/Select.css new file mode 100644 index 000000000..55427e533 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/Select.css @@ -0,0 +1,47 @@ +.layer-select { + position: relative; + width: 150px; + font-size: 14px; + z-index: 29; +} + +/* 当前选择项 */ +.layer-select-current { + display: flex; + justify-content: space-between; + padding: 5px; + width: 100%; + border: 1px solid #ccc; + border-radius: 3px; + cursor: pointer; +} + +.layer-select-value { + display: flex; + align-items: center; + width: calc(100% - 20px); +} + +/* 下拉选项 */ +.layer-select-options { + overflow-y: auto; + position: absolute; + top: 30px; + left: 0; + padding: 5px; + width: 100%; + max-height: 400px; + border: 1px solid #ccc; + border-radius: 3px; + cursor: default; +} + +.layer-select-option { + display: flex; + align-items: center; + height: 20px; +} + +.layer-select-option:hover { + background: rgba(200, 210, 220, 0.5); +} diff --git a/src/UI/Components/ToolBar/Layer/Component/Select.tsx b/src/UI/Components/ToolBar/Layer/Component/Select.tsx new file mode 100644 index 000000000..6465afcf7 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/Component/Select.tsx @@ -0,0 +1,73 @@ +import { Icon } from "@blueprintjs/core"; +import { observable } from "mobx"; +import { observer } from "mobx-react"; +import React from "react"; +import { ColorPalette } from "../../../../../Common/ColorPalette"; +import { ColorBlock } from "./Color"; +import "./Select.css"; + +export interface ISelectOption +{ + /** 选项的显示(可以是字符串或JSX) */ + label: string | JSX.Element; + /** key值,可选-(不填表示,只做显示,不做选择) */ + value?: TSelectValue; + /** 用于重载选项的点击事件 */ + onClick?: (currentItem?: ISelectOption, HandleChange?: (currentItem?: ISelectOption) => void) => void; + /** 用于传递的数据(可随意挂载) */ + data?: Record; +} +export type TSelectValue = string | number; + +/** 下拉选择器 */ +@observer +export class SelectInLayer extends React.Component<{ value: TSelectValue, options: ISelectOption[]; style?: React.CSSProperties; isColorByValue?: boolean; onChange?: (currentItem?: ISelectOption) => void; }>{ + constructor(props) + { + super(props); + // 任意位置点击都取消下拉 + document.body.addEventListener('click', e => + { + if (this._IsShow) + this._IsShow = false; + }); + } + + @observable + private _IsShow = false; + + render() + { + const { value, options, style, isColorByValue = false, onChange } = this.props; + /** 根据value生成颜色块 */ + const CreateColor = () => + { + if (isColorByValue && typeof value === 'number' && value > 0 && value < ColorPalette.length) + return <>{value}; + return value; + }; + return ( +
+ {/* 当前选择项 */} +
{ this._IsShow = !this._IsShow; e.stopPropagation(); }}> +
+ {options.find(item => item.value === value)?.label || CreateColor()} +
+ {this._IsShow ? : } +
+ {/* 下拉选项 */} + {this._IsShow &&
+ {options.map(item =>
+ { + item.onClick && item.onClick(item, onChange); + onChange && onChange(item); + }}> + {item.label} +
)} +
} +
+ ); + } +} diff --git a/src/UI/Components/ToolBar/Layer/LayerAPI.ts b/src/UI/Components/ToolBar/Layer/LayerAPI.ts new file mode 100644 index 000000000..b85f10b5d --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerAPI.ts @@ -0,0 +1,148 @@ +import { ColorAPI } from "./Component/ColorAPI"; +import { LayerAction, TreeAction } from "./State/Action"; +import { LayerStore } from "./State/Store"; +import type { ILayerNode } from "./State/Type"; + +/** 图层API(纯store操作,不含任何UI)提供给LayerCMD使用 */ +export class LayerAPI +{ + layerAction: LayerAction; + constructor(public store: LayerStore) + { + this.layerAction = new LayerAction(this.store); + } + + /** 创建一个文件 */ + AppendFile = () => + { + const store = this.store; + const layerAction = this.layerAction; + // 默认新图层为当前选中 + layerAction.ClearIsCurrent(); + let name = `图层${++store.ID.file}`; + while (layerAction.FindNodeByName(name)) + name = `图层${++store.ID.file}`; + const node: ILayerNode = { name, isCurrent: true, isOff: false, isLock: false, colorIndex: ColorAPI.GetColorIndex(store.ID.file - 1), visible: true, selected: false, changeable: false }; + // 组内添加新图层 + const selected = layerAction.FindNodeBySelected(); + if (selected && selected.children) + { + selected.children.push(node); + store.currentLayer = selected.children.at(-1) as ILayerNode; + } + else + { + store.data.push(node); + store.currentLayer = store.data.at(-1) as ILayerNode; + } + return store.currentLayer; + }; + + /** 创建一个文件夹 */ + AppendFolder = () => + { + const store = this.store; + const layerAction = this.layerAction; + let name = `组${++store.ID.folder}`; + while (layerAction.FindNodeByName(name)) + name = `组${++store.ID.folder}`; + const node: ILayerNode = { name: `组${store.ID.folder}`, children: [], isOff: false, isLock: false, visible: true, selected: false, changeable: false, expanded: true }; + // 组内添加新组 + const selected = layerAction.FindNodeBySelected(); + if (selected && selected.children) + { + selected.children.push(node); + return selected.children.at(-1) as ILayerNode; + } + else + { + store.data.push(node); + return store.data.at(-1) as ILayerNode; + } + }; + + /** 删除文件 */ + RemoveFile = (node: ILayerNode) => + { + const store = this.store; + const layerAction = this.layerAction; + if (node.isCurrent) + { + const normal = layerAction.FindNodeByName("默认"); + layerAction.SetCurrent(normal); + } + TreeAction.RemoveNode(store.data, node.name); + }; + + /** 删除文件夹 */ + RemoveFolder = (node: ILayerNode) => + { + const layerAction = this.layerAction; + const current = TreeAction.FindNode(node.children, (child: ILayerNode) => child.isCurrent); + if (current) + { + const normal = layerAction.FindNodeByName("默认"); + layerAction.SetCurrent(normal); + } + this.RemoveFile(node); + }; + + /** 设置文件是否显示 */ + UpdateShowFile = (node: ILayerNode, isOff: boolean) => + { + node.isOff = isOff; + }; + + /** 设置文件夹是否显示 */ + UpdateShowFolder = (node: ILayerNode, isOff: boolean) => + { + node.isOff = isOff; + TreeAction.UpdateNode(node.children, (child: ILayerNode) => child.isOff = isOff); + }; + + /** 设置文件是否锁定 */ + UpdateLockFile = (node: ILayerNode, isLock: boolean) => + { + node.isLock = isLock; + }; + + /** 设置文件夹是否锁定 */ + UpdateLockFolder = (node: ILayerNode, isLock: boolean) => + { + node.isLock = isLock; + TreeAction.UpdateNode(node.children, (child: ILayerNode) => child.isLock = isLock); + }; + + /** 设置文件视口冻结 */ + UpdateViewportOffFile = (node: ILayerNode, isViewportOff: boolean) => + { + node.isViewportOff = isViewportOff; + }; + + /** 设置文件夹视口冻结 */ + UpdateViewportOffFolder = (node: ILayerNode, isViewportOff: boolean) => + { + node.isViewportOff = isViewportOff; + TreeAction.UpdateNode(node.children, (child: ILayerNode) => child.isViewportOff = isViewportOff); + }; + + /** 设置图层颜色 */ + UpdateColorFile = (node: ILayerNode, colorIndex: number) => + { + node.colorIndex = colorIndex; + }; + + /** 设置当前图层 */ + SetCurrentFile = (node: ILayerNode) => + { + const layerAction = new LayerAction(LayerStore.GetInstance()); + layerAction.ClearIsCurrent(); + layerAction.SetCurrent(node); + }; + + /** 节点重命名 */ + RenameNode = (node: ILayerNode, name: string) => + { + node.name = name; + }; +} diff --git a/src/UI/Components/ToolBar/Layer/LayerCMD.ts b/src/UI/Components/ToolBar/Layer/LayerCMD.ts new file mode 100644 index 000000000..cbf065b19 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerCMD.ts @@ -0,0 +1,278 @@ +import { app } from "../../../../ApplicationServices/Application"; +import { CommandNames } from "../../../../Common/CommandNames"; +import { Log } from "../../../../Common/Log"; +import { Entity } from "../../../../DatabaseServices/Entity/Entity"; +import { LayerTableRecord } from "../../../../DatabaseServices/LayerTableRecord"; +import { AmbientLight } from "../../../../DatabaseServices/Lights/AmbientLight"; +import { DirectionalLight } from "../../../../DatabaseServices/Lights/DirectionalLight"; +import { HemisphereLight } from "../../../../DatabaseServices/Lights/HemisphereLight"; +import { ObjectId } from "../../../../DatabaseServices/ObjectId"; +import { ViewportEntity } from "../../../../DatabaseServices/ViewportEntity"; +import { CommandWrap } from "../../../../Editor/CommandMachine"; +import { LayerAPI } from "./layerAPI"; +import { LayerTopStore } from "./LayerPanel"; +import { LayerAction, TreeAction } from "./State/Action"; +import { LayerStore } from "./State/Store"; +import { ViewToDataForLayer } from "./State/Transform"; +import type { ILayerNode } from "./State/Type"; + +/** 图层命令 */ +export class LayerCMD +{ + /** 创建图层 */ + static AppendLayer = () => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + const layerTopStore = LayerTopStore.GetInstance(); + // 更新View层数据 + const node = layerAPI.AppendFile(); + layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex; + // 更新Data层数据 + CommandWrap(() => + { + if (node) + ViewToDataForLayer.AppendLayer(node); + }, CommandNames.AppendLayer); + }; + + /** 创建文件夹 */ + static AppendLayerFolder = () => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + // 更新View层数据 + const node = layerAPI.AppendFolder(); + // 更新Data层数据 + CommandWrap(() => + { + if (node) + ViewToDataForLayer.AppendLayer(node); + }, CommandNames.AppendLayerFolder); + }; + + /** 删除图层 */ + static RemoveLayer = (node: ILayerNode, moveWhere?: string) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + const layerTopStore = LayerTopStore.GetInstance(); + // 更新View层数据 + if (!node.children) + { + layerAPI.RemoveFile(node); + if (node.isCurrent) + { + const layerAction = new LayerAction(LayerStore.GetInstance()); + const normal = layerAction.FindNodeByName("默认"); + layerTopStore.featureMatchOptions[0].colorIndex = normal.colorIndex; + } + } + else + layerAPI.RemoveFolder(node); + // 更新Data层数据 + CommandWrap(() => + { + ViewToDataForLayer.RemoveLayer(node, moveWhere); + }, !node.children ? CommandNames.RemoveLayer : CommandNames.RemoveLayerFolder); + }; + + /** 置为当前图层 */ + static SetCurrentLayer = (node: ILayerNode) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + const layerTopStore = LayerTopStore.GetInstance(); + if (node.isCurrent) + { + Log("已经是当前图层"); + return; + } + layerAPI.SetCurrentFile(node); + layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex; + CommandWrap(() => + { + ViewToDataForLayer.SetCurrentLayer(); + }, CommandNames.SetCurrentLayer); + }; + + /** 修改实体所在的图层 */ + static PutEntitysInLayer = (ens: Entity[], node: ILayerNode) => + { + const layerTable = app.Database.LayerTable; + const layerTopStore = LayerTopStore.GetInstance(); + if (!layerTable.Has(node.name)) + return; + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + layerTopStore.setColorIndex(node.colorIndex, 0); + CommandWrap(() => + { + for (const en of ens) + en.Layer = layer.Id; + }, CommandNames.PutEntitysInLayer); + }; + + /** 设置是否显示 */ + static UpdateShow = (node: ILayerNode) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + if (!node.children) + layerAPI.UpdateShowFile(node, !node.isOff); + else + layerAPI.UpdateShowFolder(node, !node.isOff); + CommandWrap(() => + { + ViewToDataForLayer.UpdateShow(node); + }, CommandNames.UpdateShow); + }; + + /** 设置是否锁定 */ + static UpdateLock = (node: ILayerNode, isLock: boolean) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + if (!node.children) + layerAPI.UpdateLockFile(node, isLock); + else + layerAPI.UpdateLockFolder(node, isLock); + CommandWrap(() => + { + ViewToDataForLayer.UpdateLock(node); + }, CommandNames.UpdateLock); + }; + + /** 设置是否视口冻结 */ + static UpdateViewPoint = (node: ILayerNode) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + if (!node.children) + layerAPI.UpdateViewportOffFile(node, !node.isViewportOff); + else + layerAPI.UpdateViewportOffFolder(node, !node.isViewportOff); + CommandWrap(() => + { + ViewToDataForLayer.UpdateViewPoint(node); + }, CommandNames.UpdateViewPoint); + }; + + /** 设置颜色 */ + static UpdateColor = (node: ILayerNode, colorIndex: number) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + const layerTopStore = LayerTopStore.GetInstance(); + layerAPI.UpdateColorFile(node, colorIndex); + if (node.isCurrent) + layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex; + CommandWrap(() => + { + ViewToDataForLayer.UpdateColor(node); + }, CommandNames.UpdateColor); + }; + + /** 重命名图层 */ + static RenameLayer = (node: ILayerNode, name: string) => + { + const layerAPI = new LayerAPI(LayerStore.GetInstance()); + const layerTopStore = LayerTopStore.GetInstance(); + const oldName = node.name; + layerAPI.RenameNode(node, name); + if (layerTopStore.currentLayerValue === node.name) + layerTopStore.currentLayerValue = name; + CommandWrap(() => + { + ViewToDataForLayer.RenameLayer(oldName, name); + }, !node.children ? CommandNames.RenameLayer : CommandNames.RenameLayerFolder); + }; + + /** 移动图层 */ + static MoveLayer = (node: ILayerNode, moveWhere: string, isFolder) => + { + if (moveWhere === node.name) + return; + const layerStore = LayerStore.GetInstance(); + TreeAction.RemoveNode(layerStore.data, node.name); + if (moveWhere === "--LAST") + layerStore.data.push(node); + else if (isFolder) + TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.name === moveWhere).children.push(node); + else + { + const indexs = TreeAction.FindIndexsByName(layerStore.data, moveWhere); + TreeAction.InsertNode(layerStore.data, node, indexs); + } + CommandWrap(() => + { + ViewToDataForLayer.MoveLayer(node); + }, !node.children ? CommandNames.MoveLayer : CommandNames.MoveLayerFolder); + }; +} + +/** 选中图层中的实体 */ +export const SelectLayerEntitys = (data: ILayerNode) => +{ + const layerTable = app.Database.LayerTable; + const nodeSet: Set> = new Set(); + // 获取ID + if (data.children && data.children.length > 0) + { + TreeAction.UpdateNode(data.children, (node: ILayerNode) => + { + if (!layerTable.Has(node.name)) + return; + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + nodeSet.add(layer.Id); + }); + } + else + { + if (!layerTable.Has(data.name)) + return; + const layer = layerTable.GetAt(data.name) as LayerTableRecord; + nodeSet.add(layer.Id); + } + + // 开始选择 + const ens: Entity[] = []; + if (app.Viewer.isLayout) + { + const CurrentViewport = app.Viewer.CurrentViewport; + if (CurrentViewport) + ens.push(...app.Viewer.CurrentViewport.ShowObjects.map((id: ObjectId) => id.Object).filter(en => nodeSet.has(en.Layer))); + else + ens.push(...app.Database.LayoutSpace.Entitys.filter(viewPoint => nodeSet.has(viewPoint.Layer) && viewPoint.IsVisible)); + } + else + { + const isNormalLight = (en: Entity) => en instanceof AmbientLight || en instanceof DirectionalLight || en instanceof HemisphereLight; + ens.push(...app.Database.ModelSpace.Entitys.filter(en => nodeSet.has(en.Layer) && en.IsVisible)); + ens.push(...app.Database.Lights.Entitys.filter(en => !isNormalLight(en) && nodeSet.has(en.Layer) && en.IsVisible)); + } + app.Editor.SetSelection(ens); +}; + +/** 选中视口时更新图层状态 */ +export const UpdateLayerByViewPoint = (viewPoint: ViewportEntity) => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.isShowViewportOff = true; + const UpdateNode = (nodes: ILayerNode[], Callback: (node: ILayerNode) => void, Predicate = (node: ILayerNode) => true) => + { + nodes.map(node => + { + if (Predicate(node)) + Callback(node); + if (node.children && node.children.length > 0) + UpdateNode(node.children, Callback, Predicate); + }); + }; + UpdateNode(layerStore.data, (data) => + { + const layerTable = app.Database.LayerTable; + if (!layerTable.Has(data.name)) + return; + const layer = layerTable.GetAt(data.name) as LayerTableRecord; + data.isViewportOff = viewPoint.HasFreezeLayer(layer.Id); + }); +}; + +/** 取消视口时更新图层状态 */ +export const UpdateLayerByNoViewPoint = () => +{ + const layerStore = LayerStore.GetInstance(); + layerStore.isShowViewportOff = false; +}; diff --git a/src/UI/Components/ToolBar/Layer/LayerManager.css b/src/UI/Components/ToolBar/Layer/LayerManager.css new file mode 100644 index 000000000..4c67d5052 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerManager.css @@ -0,0 +1,74 @@ +/* 搜索框 */ +.layer-search { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 40px; +} + +/* 操作栏 */ +.layer-operation { + display: flex; + align-items: center; + width: 100%; + height: 30px; +} + +.layer-operation-btn { + margin: 0 5px; + cursor: pointer +} + +/* 图层列表-表头 */ +.layer-header { + display: flex; + width: 100%; + height: 30px; +} + +.layer-header-item { + display: flex; + justify-content: center; + align-items: center; + width: 30px; + height: 100%; + border-bottom: 1px solid #ccc; + border-top: 1px solid #ccc; + border-right: 1px solid #ccc; +} + +/* 图层列表-表项 */ +.layer-body { + width: 100%; + height: calc(100% - 100px); +} + +.layer-body-content { + width: 100%; + height: calc(100% - 100px); + overflow-y: auto; +} + +.layer-body-line { + width: 100%; + height: 0; + background: rgba(100, 150, 200, 0.5); +} + +/* 图层列表 */ +.layer-list { + display: flex; + width: 100%; + height: 30px; + border-bottom: 1px solid #ccc; +} + +.layer-list-item { + display: flex; + justify-content: center; + align-items: center; + width: 30px; + height: 100%; + cursor: pointer; +} diff --git a/src/UI/Components/ToolBar/Layer/LayerManager.tsx b/src/UI/Components/ToolBar/Layer/LayerManager.tsx new file mode 100644 index 000000000..ac24a426b --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerManager.tsx @@ -0,0 +1,679 @@ +import { Button, Card, Checkbox, Classes, ContextMenu, Icon, InputGroup, Intent, Menu, MenuItem, Position, Tooltip } from "@blueprintjs/core"; +import { observable } from "mobx"; +import { observer } from "mobx-react"; +import React from "react"; +import { app } from "../../../../ApplicationServices/Application"; +import { CoolDownTime } from "../../../../Common/CoolDownTime"; +import { KeyBoard } from "../../../../Common/KeyEnum"; +import { DownPanelStore } from "../../../Store/DownPanelStore"; +import { ModalContainer, ModalHeader } from "../../Modal/ModalContainer"; +import { AppToaster } from "../../Toaster"; +import { ColorDialog } from "./Component/Color"; +import { ColorAPI } from "./Component/ColorAPI"; +import { SelectInLayer } from "./Component/Select"; +import { LayerCMD, SelectLayerEntitys } from "./LayerCMD"; +import "./LayerManager.css"; +import { getLayerOptions } from "./LayerPanel"; +import { LayerAction, TreeAction } from "./State/Action"; +import { LayerStore } from "./State/Store"; +import type { ILayerNode } from "./State/Type"; + +/** 图层状态机 */ +const layerStore = LayerStore.GetInstance(); +const layerAction = new LayerAction(layerStore); + +/** 图层管理器 */ +@observer +export class LayerManager extends React.Component<{}, {}> +{ + constructor(props) + { + super(props); + // 任意位置点击都取消选中 + document.body.addEventListener('mousedown', e => + { + this._Rename(); + layerAction.ClearSelected(); + layerAction.ClearChangeable(); + this._LayerName = "_NULL_"; + if (this._SearchInputRef.current) + this._SearchInputRef.current.blur(); + }); + } + + /** 组件注销时清除搜索 */ + componentWillUnmount() + { + this._SearchInputRef.current.value = ""; + layerAction.SearchByName(""); + } + + /** 图层列表内部按钮被点击所触发的事件 */ + private ClickInnerEvent(e: React.MouseEvent) + { + e.stopPropagation(); + } + + /** 被双击的节点数据 */ + private _DataByDoubleClick; + + /** 图层搜索输入框的DOM */ + private _SearchInputRef = React.createRef(); + + /** 图层名称输入框的DOM */ + private _NameInputRef = React.createRef(); + + /** 图层嵌套层级 */ + private _Level = -1; + + /** 用于函数防抖 */ + private _CoolDownTime = new CoolDownTime; + + /** 用于拖拽显示的DOM */ + private _LineRefs: React.RefObject[] = []; + + /** 用于拖拽显示的DOM */ + private _LastLineRef = React.createRef(); + + /** 被拖拽的节点 */ + private _MoveWhat: ILayerNode; + + /** 放置的位置 */ + private _ToWhere: string; + + /** 是否放入文件夹 */ + private _IsFolder = false; + + /** 布局面板的状态 */ + private _DownPanelStore = DownPanelStore.GetInstance(); + + /** 当前输入的图层名称 */ + @observable + private _LayerName = "_NULL_"; + + /** 重命名 */ + private _Rename = () => + { + if (!this._DataByDoubleClick) + return; + if (!this._LayerName) + { + AppToaster.show({ + message: "名称不能为空", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + else + { + const layers = layerAction.FindFlatNodesByName(this._LayerName); + if (layers.length === 0 || (layers.length === 1 && layers[0].name === this._DataByDoubleClick.name)) + { + if (this._LayerName !== "_NULL_" && this._LayerName !== this._DataByDoubleClick.name) + LayerCMD.RenameLayer(this._DataByDoubleClick, this._LayerName); + this._DataByDoubleClick.changeable = false; + this._LayerName = "_NULL_"; + } + else + { + AppToaster.show({ + message: "名称重复,请修改名称", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + } + }; + + /** 初始化拖拽样式 */ + private InitDragStyle = () => + { + const line = this._LastLineRef.current; + line.style.height = "0"; + this._IsFolder = false; + for (const lineRef of this._LineRefs) + { + const dom = lineRef.current; + const line = dom.children[0] as HTMLDivElement; + line.style.height = "0"; + const div = dom.children[1] as HTMLDivElement; + div.style.background = "none"; + } + }; + + /** 右击菜单 */ + private _ShowMenu(e: React.MouseEvent, selected: ILayerNode) + { + ContextMenu.show( + + + { + this.ClickInnerEvent(e); + SelectLayerEntitys(selected); + }} + /> + + { + this.ClickInnerEvent(e); + const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList; + if (ens.length > 0) + LayerCMD.PutEntitysInLayer(ens, selected); + else + { + AppToaster.show({ + message: "请先选中实体", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + }} + /> + , + { left: e.clientX, top: e.clientY }, + () => this.setState({ isContextMenuOpen: false }), + ); + } + + /** 生成图层列表 */ + private CreateList = (dataList: ILayerNode[]) => + { + this._Level++; + const level = this._Level; + return ( + dataList.map(data => + { + /** 层级的偏移距离 */ + const BIAS_SIZE = 10; + /** 选中某一项 */ + const ChooseItem = (data: ILayerNode) => + { + if (!data.selected) + { + layerAction.ClearSelected(); + layerAction.ClearChangeable(); + this._LayerName = "_NULL_"; + data.selected = true; + } + }; + const lineRef = React.createRef(); + data.visible && this._LineRefs.push(lineRef); + return (<> + {data.visible && +
+ { + e.preventDefault(); + this.InitDragStyle(); + const line = this._LastLineRef.current; + const rect = line.getBoundingClientRect(); + if (e.clientX > rect.left && e.clientX < rect.right) + { + this._MoveWhat = data; + for (const lineRef of this._LineRefs) + { + const dom = lineRef.current; + const rect = dom.getBoundingClientRect(); + const boundary = rect.top + rect.height / 2; + const line = dom.children[0] as HTMLDivElement; + const key = dom.getAttribute("data-key"); + const node = TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.name === key); + if (e.clientY > rect.top && e.clientY < rect.bottom && node.children) + { + if (!data.children || !TreeAction.FindNode(data.children, (node: ILayerNode) => node.name === key)) + { + const div = dom.children[1] as HTMLDivElement; + div.style.background = "rgba(150, 180, 210, 0.5)"; + this._IsFolder = true; + this._ToWhere = key; + return; + } + } + if (e.clientY < boundary) + { + line.style.height = "5px"; + this._ToWhere = key; + return; + } + } + this._ToWhere = "--LAST"; + line.style.height = "5px"; + } + }} + onMouseDown={e => + { + this.ClickInnerEvent(e); + ChooseItem(data); + if (e.button === 2) + { + const selected = layerAction.FindNodeBySelected(); + if (selected) + this._ShowMenu(e, selected); + } + }}> +
+
+ {/* 状态 */} + {data.children ? +
{ data.expanded = !data.expanded; this.ClickInnerEvent(e); }}> + {!data.expanded ? <> : <>} +
+ : +
+ { + LayerCMD.SetCurrentLayer(data); + }}> + {data.isCurrent && } +
+ } + {/* 名称 */} +
+ { + if (data.name === "默认") + { + AppToaster.show({ + message: "默认图层不能改名", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + TreeAction.UpdateNode(layerStore.data, (node: ILayerNode) => node.changeable = false); + data.changeable = true; + this._DataByDoubleClick = data; + }}> + {!data.changeable ? +
+ {data.name} +
+ : this.ClickInnerEvent(e)} + onChange={() => + { + const name = this._NameInputRef.current.value; + this._LayerName = name; + }} + onKeyDown={(e: React.KeyboardEvent) => + { + if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space) + this._Rename(); + else if (e.keyCode === KeyBoard.Escape) + { + data.changeable = false; + this._LayerName = "_NULL_"; + } + e.stopPropagation(); + }} + />} +
+ {/* 显示 */} +
+ { + if (data.isCurrent && !data.isOff) + { + AppToaster.show({ + message: "当前图层不能隐藏", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + else + LayerCMD.UpdateShow(data); + this.ClickInnerEvent(e); + }}> + {data.isOff ? : } +
+ {/* 锁定 */} +
+ { + LayerCMD.UpdateLock(data, !data.isLock); + this.ClickInnerEvent(e); + }}> + {data.isLock ? : } +
+ {/* 视口 */} + { + layerStore.isShowViewportOff && +
+ { + this.ClickInnerEvent(e); + if (!app.Viewer.CurrentViewport) + { + AppToaster.show({ + message: "请先选中视口", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + else + LayerCMD.UpdateViewPoint(data); + }}> + {data.isViewportOff ? : } +
+ } + {/* 颜色 */} +
+ {!data.children && +
+ { + app.Editor.ModalManage.RenderModal(ColorDialog, { + colorIndex: data.colorIndex, + onConfirm: (colorIndex: number) => + { + LayerCMD.UpdateColor(data, colorIndex); + } + }); + this.ClickInnerEvent(e); + }}> + {data.colorIndex} +
+ } +
+
+
+ } + {data.expanded && data.children && this.CreateList(data.children)} + ); + }) + ); + }; + + render() + { + this._Level = -1; + this._LineRefs.length = 0; + return ( + + { + e.preventDefault(); + this._MoveWhat.selected = false; + this._MoveWhat.changeable = false; + LayerCMD.MoveLayer(this._MoveWhat, this._ToWhere, this._IsFolder); + this.InitDragStyle(); + }}> + {/* 搜索框 */} +
+ TreeAction.UpdateNode(layerStore.data, (node: ILayerNode) => node.changeable = false)} + onChange={() => + { + this._CoolDownTime.Debounce(() => + { + layerAction.SearchByName(this._SearchInputRef.current.value); + }, 500); + }} + onKeyDown={(e: React.KeyboardEvent) => + { + e.stopPropagation(); + }} + rightElement={ + +
+ {/* 操作栏 */} +
+ 图层管理 +
+ { + LayerCMD.AppendLayerFolder(); + this.ClickInnerEvent(e); + }}> + +
+
+ { + LayerCMD.AppendLayer(); + this.ClickInnerEvent(e); + }}> + +
+
+ { + const selected = TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.selected) as ILayerNode; + if (!selected) + { + AppToaster.show({ + message: "请先选中想要删除的图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + if (selected.name === "默认") + { + AppToaster.show({ + message: "请不要删除默认图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + if (selected.isCurrent) + { + AppToaster.show({ + message: "请不要删除当前图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + let isHasNormal = false; + let isHasCurrent = false; + let isHasLock = false; + if (selected.children && selected.children.length > 0) + { + const arr = []; + for (const node of selected.children) + { + if (node.name === "默认") + { + isHasNormal = true; + break; + } + if (node.isCurrent) + { + isHasCurrent = true; + break; + } + if (node.isLock) + { + isHasLock = true; + break; + } + if (node.children && node.children.length > 0) + arr.push(...node.children); + } + } + if (isHasCurrent) + { + AppToaster.show({ + message: "组里含有当前图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + if (isHasNormal) + { + AppToaster.show({ + message: "组里含有默认图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + if (isHasLock) + { + AppToaster.show({ + message: "组里含有被锁定的图层", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + return; + } + app.Editor.ModalManage.RenderModal(DeleteDialog, { selected, RemoveLayer: LayerCMD.RemoveLayer }); + this.ClickInnerEvent(e); + }}> + +
+
+ {/* 图层列表-表头 */} +
+
状态
+
名称
+
显示
+
锁定
+ {layerStore.isShowViewportOff &&
视口
} +
颜色
+
+ {/* 图层列表-表项 */} +
+
+ {this.CreateList(layerStore.data)} +
+
+
+
+ ); + } +} + +/** 删除图层的弹窗 */ +@observer +class DeleteDialog extends React.Component<{ selected: ILayerNode; RemoveLayer: Function; }> { + constructor(props) + { + super(props); + } + + /** 图层内的对象是否要一起删除 */ + @observable + _IsDelete = false; + + options = getLayerOptions(TreeAction.FilterNodes(layerStore.data, (item: ILayerNode) => + { + if (item.name !== this.props.selected.name) + { + const children = this.props.selected.children; + if (children && children.length > 0) + { + if (!TreeAction.FindNode(children, (child: ILayerNode) => child.name === item.name)) + return true; + } + else + return true; + } + return false; + }) as ILayerNode[]); + + /** 若图层内的对象不删除,要放置的位置 */ + @observable + _MoveWhere = this.options[0].value; + + // 视图渲染(这是主要部分,上面做的都是一些参数的初始化) + public render() + { + const { selected, RemoveLayer } = this.props; + const TextOverflow = (text: string, num: number = 10) => + { + if (text.length > num) + return text.substring(0, 10) + "..."; + else + return text; + }; + return ( + + app.Editor.ModalManage.Destory()} + /> +
+
+ { + selected.isLock ? +
+
+

+ 选定的图层中有锁定图层,无法删除,解锁后再进行删除! +

+ +
+
+ : + <> +
+

确定删除方式:

+ + this._IsDelete = !this._IsDelete} + /> + +
+ { + !this._IsDelete && +
+

删除图层后选择图层中对象放置位置:

+ this._MoveWhere = item.value as string} /> +
+ } + + } +
+
+
+
+
+
+
+ ); + } +} diff --git a/src/UI/Components/ToolBar/Layer/LayerPanel.css b/src/UI/Components/ToolBar/Layer/LayerPanel.css new file mode 100644 index 000000000..e2fa1e13c --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerPanel.css @@ -0,0 +1,69 @@ +/* 图层特性 */ +.layer-feature { + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin-bottom: 5px; + padding-right: 20px; + height: 70px; + font-size: 14px; + border-right: 1px solid #ccc; +} + +.layer-feature-current { + display: flex; + align-items: center; + justify-content: center; + margin-left: 20px; + height: 100%; +} + +.layer-feature-logo { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 20px; + height: 100%; +} + +.layer-feature-btn { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 20px; + height: 100%; + cursor: pointer; +} + +.layer-feature-btn:hover { + background: rgba(200, 210, 220, 0.5); +} + +/* 特性匹配 */ +.feature-match { + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin-bottom: 5px; + height: 70px; + font-size: 14px; +} + +.feature-match-logo { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-left: 20px; + height: 100%; +} + +.feature-match-color { + display: flex; + align-items: center; + justify-content: center; + margin-left: 20px; + height: 100%; +} diff --git a/src/UI/Components/ToolBar/Layer/LayerPanel.tsx b/src/UI/Components/ToolBar/Layer/LayerPanel.tsx new file mode 100644 index 000000000..6fea8de39 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/LayerPanel.tsx @@ -0,0 +1,360 @@ +import { Icon, Intent } from "@blueprintjs/core"; +import { action, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from 'react'; +import { app } from "../../../../ApplicationServices/Application"; +import { HostApplicationServices } from "../../../../ApplicationServices/HostApplicationServices"; +import { Singleton } from "../../../../Common/Singleton"; +import { CommandWrap } from "../../../../Editor/CommandMachine"; +import { AppToaster } from "../../Toaster"; +import { PropertiesStore } from "../PropertiesStore"; +import { ColorBlock, ColorDialog } from "./Component/Color"; +import { ColorAPI } from "./Component/ColorAPI"; +import { IconSVG } from "./Component/Icon"; +import { ISelectOption, SelectInLayer, TSelectValue } from "./Component/Select"; +import { LayerCMD } from "./LayerCMD"; +import "./LayerPanel.css"; +import { LayerAction, TreeAction } from "./State/Action"; +import { LayerPropertieStore, LayerStore } from "./State/Store"; +import type { ILayerNode } from "./State/Type"; + +/** 图层状态机 */ +const layerStore = LayerStore.GetInstance(); +const layerAction = new LayerAction(layerStore); + +interface IFeatureMatchOption +{ + colorIndex?: number; + name: string; + value?: number; + onClick?: (currentItem?: ISelectOption, HandleChange?: (currentItem?: ISelectOption) => void) => void; +} + +export class LayerTopStore extends Singleton +{ + /** 当前图层key */ + @observable + currentLayerValue = layerStore.currentLayer.name; + + /** 颜色key */ + @observable + colorValue: TSelectValue = 7; + + /** 默认颜色key */ + @observable + normalColorValue: TSelectValue = 7; + + /** 是否使用默认颜色 */ + @observable + isUseNormal = false; + + /** 特性匹配里的颜色选项 */ + @observable + featureMatchOptions: IFeatureMatchOption[] = [ + { colorIndex: layerStore.currentLayer.colorIndex, name: "跟随图层", value: 0 }, + { colorIndex: 1, name: "红色", value: 1 }, + { colorIndex: 2, name: "黄色", value: 2 }, + { colorIndex: 3, name: "绿色", value: 3 }, + { colorIndex: 4, name: "青色", value: 4 }, + { colorIndex: 5, name: "蓝色", value: 5 }, + { colorIndex: 6, name: "紫色", value: 6 }, + { colorIndex: 7, name: "白色", value: 7 }, + { colorIndex: 8, name: "更多颜色", value: 8, onClick: this.OpenMoreColor }, + ]; + + /** 点击更多颜色 */ + OpenMoreColor(currentItem: ISelectOption, HandleChange: Function) + { + app.Editor.ModalManage.RenderModal(ColorDialog, { + colorIndex: layerTopStore.featureMatchOptions[8].colorIndex, + onConfirm: (colorIndex: number) => + { + layerTopStore.featureMatchOptions[8].colorIndex = colorIndex; + currentItem.data.colorIndex = colorIndex; + const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList; + // 没有选中实体,设置默认颜色 + if (ens.length === 0) + { + HostApplicationServices.CurrentColorindex = colorIndex; + layerTopStore.normalColorValue = colorIndex; + layerTopStore.isUseNormal = true; + } + // 选中实体,设置实体颜色 + else + { + CommandWrap(() => + { + ens.forEach(en => en.ColorIndex = colorIndex); + layerTopStore.setColorValue(colorIndex); + layerTopStore.isUseNormal = false; + }, "设置颜色"); + } + } + }); + } + + @action + setColorValue(value: TSelectValue) + { + this.colorValue = value; + } + + @action + setIsUseNormal(value: boolean) + { + this.isUseNormal = value; + } + + @action + setColorIndex(colorIndex: number, index = 8) + { + this.featureMatchOptions[index].colorIndex = colorIndex; + } + + @action + setCurrentLayerValue(value: string) + { + this.currentLayerValue = value; + } +} + +/** 颜色状态机 */ +const layerTopStore = LayerTopStore.GetInstance(); + +/** 图层特性面板 */ +@observer +export class LayerPanel extends React.Component<{}, {}> +{ + constructor(props: {}) + { + super(props); + LayerPropertieStore.isShow = true; + } + render() + { + const propertiesStore = PropertiesStore.GetInstance(); + /** 图层颜色 */ + let layerColorIndex = layerStore.currentLayer.colorIndex; + const ens = propertiesStore.GetEntitys(); + const en = ens[0]; + // 获取到正确的颜色 + let colorIndex = 0; + const colorSet = new Set(); + for (const en of ens) + colorSet.add(en.ColorIndex); + if (colorSet.size > 1) + colorIndex = 0; + else if (colorSet.size === 1) + for (const color of colorSet) + colorIndex = color; + /** 是否为多种颜色 */ + const isMoreColor = colorIndex === 0; + // 获取实体的图层 + const currentSet: Set = new Set(); + ens.forEach(en => currentSet.add(en.Layer.Object.Name)); + if (currentSet.size > 1) + layerTopStore.setCurrentLayerValue("多种"); + else + { + if (en) + { + const data = layerAction.FindNodeByName(en.Layer.Object.Name); + if (data) + { + layerColorIndex = data.colorIndex; + layerTopStore.setCurrentLayerValue(data.name); + colorIndex = en.ColorIndex; + } + } + else + layerTopStore.setCurrentLayerValue(layerStore.currentLayer.name); + } + // 获取实体的颜色 + if (en) + { + layerTopStore.setIsUseNormal(false); + if (isMoreColor) + layerTopStore.setColorValue("多种"); + else if (colorIndex === 256) + { + if (layerTopStore.colorValue !== 0) + layerTopStore.setColorValue(0); + layerTopStore.setColorIndex(layerColorIndex, 0); + } + else if (colorIndex < 8) + { + if (layerTopStore.colorValue !== colorIndex) + layerTopStore.setColorValue(colorIndex); + } + else + { + if (layerTopStore.colorValue !== colorIndex) + { + layerTopStore.setColorValue(colorIndex); + layerTopStore.setColorIndex(colorIndex); + } + } + } + else + layerTopStore.setIsUseNormal(true); + + return ( +
+ {/* 图层特性 */} + + {/* 特性匹配 */} + +
+ ); + } +} + +/** 获取图层选项(一维展开) */ +export const getLayerOptions = (layerDatas: ILayerNode[]) => TreeAction.FindFlatNodes(layerDatas, (node: ILayerNode) => !node.children).map((data: ILayerNode) => +({ + label: (<> +
+ {data.isOff ? : } +
+
+ {data.isLock ? : } +
+
+
{data.name}
+ ), + value: data.name +})); + +/** 图层特性 */ +@observer +class LayerFeature extends React.Component<{}> +{ + /** 创建当前图层的选择器 */ + private CreateLayerSelect = (layerDatas: ILayerNode[]) => + { + const layerFeatureOptions = getLayerOptions(layerDatas); + return ( +
+
当前图层
+ + { + const value = item.value as string; + layerTopStore.currentLayerValue = value; + const data = layerAction.FindNodeByName(value); + const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList; + if (ens.length === 0) + LayerCMD.SetCurrentLayer(data); + else + LayerCMD.PutEntitysInLayer(ens, data); + }} /> +
+ ); + }; + render() + { + return ( + < div className="layer-feature"> +
+ +
+ {this.CreateLayerSelect(layerStore.data)} +
+ { + const layerAction = new LayerAction(layerStore); + const currentLayer = layerAction.FindNodeByName(layerTopStore.currentLayerValue); + if (currentLayer) + LayerCMD.UpdateLock(currentLayer, false); + }}> + +
解锁选定对象图层
+
+
+ { + const layerAction = new LayerAction(layerStore); + const currentLayer = layerAction.FindNodeByName(layerTopStore.currentLayerValue); + if (currentLayer) + LayerCMD.UpdateLock(currentLayer, true); + }}> + +
锁定选定对象图层
+
+
+ { + const en = app.Editor.SelectCtrl.SelectSet.SelectEntityList[0]; + if (en) + { + const data = layerAction.FindNodeByName(en.Layer.Object.Name); + if (data) + LayerCMD.SetCurrentLayer(data); + } + else + { + AppToaster.show({ + message: "请先选中实体", + timeout: 2000, + intent: Intent.DANGER + }, 'openfile'); + } + }}> + +
置为当前图层
+
+ + ); + } +} +/** 特性匹配 */ +@observer +class FeatureMatch extends React.Component<{}> +{ + render() + { + const options = layerTopStore.featureMatchOptions.map(data => ({ + label: (<>{data.colorIndex && }{data.name}), + value: data.value, + data: { colorIndex: data.colorIndex }, + onClick: data.onClick + })); + return ( + < div className="feature-match"> +
+ +
特性匹配
+
+
+
颜色
+ + { + const value = currentItem.value as number; + // 点击更多颜色 + if (value === 8) + return; + const colorIndex = value === 0 ? 256 : currentItem.data.colorIndex as number; + const ens = app.Editor.SelectCtrl.SelectSet.SelectEntityList; + // 没选中实体,设置默认颜色 + if (ens.length === 0) + { + HostApplicationServices.CurrentColorindex = colorIndex; + layerTopStore.normalColorValue = value; + layerTopStore.isUseNormal = true; + } + // 选中实体,设置实体颜色 + else + { + CommandWrap(() => + { + ens.forEach(en => en.ColorIndex = colorIndex); + layerTopStore.setColorValue(value); + layerTopStore.isUseNormal = false; + }, "设置颜色"); + } + }} /> +
+ + ); + } +} diff --git a/src/UI/Components/ToolBar/Layer/State/Action.ts b/src/UI/Components/ToolBar/Layer/State/Action.ts new file mode 100644 index 000000000..d69b55106 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/State/Action.ts @@ -0,0 +1,256 @@ +import { LayerStore } from "./Store"; +import type { ILayerNode, INode } from "./Type"; + +/** 树的基础操作 */ +export class TreeAction +{ + + /** 插入节点 + * @param {INode[]} nodes 节点数组 + * @param {INode} newNode 新节点 + * @param {number[]} indexs 索引数组(插入的位置) + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 在文件夹1下插入文件2 + * InsertNode(nodes, { name: "文件2" }, [1, 1]); + * // returns [{name: "文件夹1", children: [{name: "文件1"}, {name: "文件2"}]}] + */ + static InsertNode(nodes: INode[], newNode: INode, indexs: number[]) + { + let tempNodes = nodes; + indexs.forEach((index, i) => + { + const node = tempNodes[index]; + if (i !== indexs.length - 1 && node.children) + tempNodes = node.children; + }); + tempNodes.splice(indexs[indexs.length - 1], 0, newNode); + }; + + /** 删除节点 + * @param {INode[]} nodes 节点数组 + * @param {string} name 节点名称 + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 删除文件1 + * RemoveNode(nodes, "文件1"); + * // returns [{name: "文件夹1", children: []}] + */ + static RemoveNode(nodes: INode[], name: string) + { + const indexs = TreeAction.FindIndexsByName(nodes, name); + let tempNodes = nodes; + indexs.forEach((index, i) => + { + const node = tempNodes[index]; + if (i !== indexs.length - 1 && node.children) + tempNodes = node.children; + }); + tempNodes.splice(indexs[indexs.length - 1], 1); + }; + + /** 修改节点 + * @param {INode[]} nodes 节点数组 + * @param {Function} Callback 回调函数(修改操作) + * @param {Function} Predicate 条件函数(过滤操作) + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 修改文件1的名称 + * UpdateNode(nodes, node => node.name = "新文件1", node => node.name === "文件1"); + * // returns [{name: "文件夹1", children: [{name: "新文件1"}]}] + */ + static UpdateNode(nodes: INode[], Callback: (node: INode) => void, Predicate = (node: INode) => true) + { + nodes.forEach(node => + { + if (Predicate(node)) + Callback(node); + if (node.children && node.children.length > 0) + TreeAction.UpdateNode(node.children, Callback, Predicate); + }); + }; + + /** 找到某个节点 + * @param {INode[]} nodes 节点数组 + * @param {Function} Predicate 条件函数(过滤操作) + * @returns {INode | undefined} 节点 + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 找到文件1 + * FindNode(nodes, node => node.name === "文件1"); + * // returns {name: "文件1"} + */ + static FindNode(nodes: INode[], Predicate: (node: INode) => boolean): INode | undefined + { + for (const node of nodes) + { + + if (Predicate(node)) + return node; + if (node.children && node.children.length > 0) + { + const subNode = TreeAction.FindNode(node.children, Predicate); + if (subNode) + return subNode; + } + } + }; + + /** 通过ID找到某个节点的索引 + * @param {INode[]} nodes 节点数组 + * @param {string} id 节点ID + * @returns {number[]} 索引数组 + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 找到文件1的索引 + * FindIndexsByName(nodes, "文件1"); + * // returns [1, 0] + */ + static FindIndexsByName(nodes: INode[], name: string) + { + const indexs: number[] = []; + const FindIndexs = (nodes: INode[], name: string, preIndexs: number[] = []) => + { + for (let i = 0; i < nodes.length; i++) + { + const data = nodes[i]; + if (data.name === name) + { + if (preIndexs.length > 0) indexs.push(...preIndexs); + indexs.push(i); + break; + } + if (data.children && data.children.length > 0) + { + preIndexs.push(i); + FindIndexs(data.children, name, preIndexs); + preIndexs.pop(); + } + } + }; + FindIndexs(nodes, name); + return indexs; + }; + + /** 找到某些节点(打平父子结构 + * @param {INode[]} nodes 节点数组 + * @param {Function} Predicate 条件函数(过滤操作) + * @returns {INode | undefined} 节点 + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 找到文件1 + * FindNode(nodes, node => node.name === "文件1"); + * // returns {name: "文件1"} + */ + static FindFlatNodes(nodes: INode[], Predicate: (node: INode) => boolean): INode[] + { + const result: INode[] = []; + for (const node of nodes) + { + if (Predicate(node)) + result.push(node); + if (node.children && node.children.length > 0) + { + const subNodes = TreeAction.FindFlatNodes(node.children, Predicate); + if (subNodes.length > 0) + result.push(...subNodes); + } + } + return result; + }; + + /** 找到某些节点(保留父子结构且拷贝数据) + * @param {INode[]} nodes 节点数组 + * @param {Function} Predicate 条件函数(过滤操作) + * @returns {INode | undefined} 节点 + * @example + * const nodes = [{name: "文件夹1", children: [{name: "文件1"}]}] + * // 找到文件1 + * FilterNodes(nodes, node => node.name === "文件1"); + * // returns {name: "文件1"} + */ + static FilterNodes(nodes: INode[], Predicate: (node: INode) => boolean) + { + const dataListCopy = nodes.map(data => ({ ...data })); + const Filter = (dataList: INode[]) => + { + const allSelectd: INode[] = []; + for (const node of dataList) + { + if (Predicate(node)) + allSelectd.push(node); + if (node.children && node.children.length > 0) + node.children = Filter(node.children); + } + return allSelectd; + }; + return Filter(dataListCopy); + }; + +} + +/** 图层的基础操作 */ +export class LayerAction +{ + constructor(public store: LayerStore) { } + + /** 设置当前图层 */ + SetCurrent(node: ILayerNode) + { + node.isCurrent = true; + this.store.currentLayer = node; + }; + + /** 清楚所有图层的isCurrent属性 */ + ClearIsCurrent() + { + TreeAction.UpdateNode(this.store.data, (node: ILayerNode) => + { + if (node.isCurrent !== undefined) + node.isCurrent = false; + }); + }; + + /** 清楚所有图层的visible属性 */ + ClearVisible() + { + TreeAction.UpdateNode(this.store.data, (node: ILayerNode) => node.visible = false); + }; + + /** 清楚所有图层的selected属性 */ + ClearSelected() + { + TreeAction.UpdateNode(this.store.data, (node: ILayerNode) => node.selected = false); + }; + + /** 清楚所有图层的changeable属性 */ + ClearChangeable() + { + TreeAction.UpdateNode(this.store.data, (node: ILayerNode) => node.changeable = false); + }; + + /** 找到选中的图层 */ + FindNodeBySelected = () => TreeAction.FindNode(this.store.data, (node: ILayerNode) => node.selected) as ILayerNode; + + /** 根据名称过滤节点 */ + FindFlatNodesByName(name: String, isFuzzy = false) + { + return TreeAction.FindFlatNodes(this.store.data, (node: ILayerNode) => isFuzzy ? new RegExp(`${name}`).test(node.name) : node.name === name) as ILayerNode[]; + }; + + /** 搜索图层 */ + SearchByName(name: String) + { + if (name === "") + { + TreeAction.UpdateNode(this.store.data, (node: ILayerNode) => node.visible = true); + return; + } + this.ClearVisible(); + const layers = this.FindFlatNodesByName(name, true); + TreeAction.UpdateNode(layers, (node: ILayerNode) => node.visible = true); + }; + + /** 根据名称查找图层 */ + FindNodeByName = (name: string) => TreeAction.FindNode(LayerStore.GetInstance().data, (node: ILayerNode) => node.name === name) as ILayerNode; +} diff --git a/src/UI/Components/ToolBar/Layer/State/Store.ts b/src/UI/Components/ToolBar/Layer/State/Store.ts new file mode 100644 index 000000000..c0b36b746 --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/State/Store.ts @@ -0,0 +1,40 @@ +import { observable } from "mobx"; +import { Singleton } from "../../../../../Common/Singleton"; +import type { ILayerNode } from "./Type"; + +/** 图层的状态单例 */ +export class LayerStore extends Singleton +{ + /** 自增ID */ + ID = { file: 0, folder: 0 }; + + /** 图层数据 */ + @observable + data: ILayerNode[] = [ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + ]; + + /** 当前图层 */ + @observable + currentLayer = this.data[0]; + + /** 是否显示视口冻结 */ + @observable + isShowViewportOff = false; + + /** 初始化 */ + Init() + { + this.data = [ + { name: "默认", isCurrent: true, isOff: false, isLock: false, colorIndex: 7, visible: true, selected: false, changeable: false }, + ]; + this.currentLayer = this.data[0]; + this.ID = { file: 0, folder: 0 }; + } +} + +/** 图层特性 */ +export const LayerPropertieStore = { + /** 是否显示 */ + isShow: false +}; diff --git a/src/UI/Components/ToolBar/Layer/State/Transform.ts b/src/UI/Components/ToolBar/Layer/State/Transform.ts new file mode 100644 index 000000000..59826ee3a --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/State/Transform.ts @@ -0,0 +1,336 @@ +import { app } from "../../../../../ApplicationServices/Application"; +import { HostApplicationServices } from "../../../../../ApplicationServices/HostApplicationServices"; +import { CompositeEntity } from "../../../../../DatabaseServices/Entity/CompositeEntity"; +import { Entity } from "../../../../../DatabaseServices/Entity/Entity"; +import { LayerTableRecord } from "../../../../../DatabaseServices/LayerTableRecord"; +import { AmbientLight } from "../../../../../DatabaseServices/Lights/AmbientLight"; +import { DirectionalLight } from "../../../../../DatabaseServices/Lights/DirectionalLight"; +import { HemisphereLight } from "../../../../../DatabaseServices/Lights/HemisphereLight"; +import { LayerNode } from "../../../../../DatabaseServices/Tables/LayerTable"; +import { LayerTopStore } from "../LayerPanel"; +import { TreeAction } from "./Action"; +import { LayerStore } from "./Store"; +import type { ILayerNode } from "./Type"; + +/** 针对图层的数据转换器(Data层->View层) + * @description 该类用于将图层的Data层数据转换为图层的View层数据,便于Undo操作 + * 如:当图纸颜色被改变时(此时Undo只会撤销Data层数据),通过该类可以更新View层数据,实现UI状态的同步改变 + */ +export class DataToViewForLayer +{ + /** 根据Table更新Root(注意这里采用少补不多还) */ + static UpdateRootByTable() + { + const layerTable = app.Database.LayerTable; + const root = layerTable.Root; + layerTable.Symbols.forEach((value: LayerTableRecord, key: string) => + { + const node = TreeAction.FindNode(root.children, (node: ILayerNode) => node.name === key); + if (!node) + { + const lNode = new LayerNode(key); + root.children.push(lNode); + } + }); + } + + /** 全量更新(根据Root+Record更新View层数据) */ + static UpdateAll() + { + const layerStore = LayerStore.GetInstance(); + const layerTopStore = LayerTopStore.GetInstance(); + const layerTable = app.Database.LayerTable; + const names = []; + const Update = (lNodes: LayerNode[], nodes: ILayerNode[]) => + { + for (let i = 0; i < lNodes.length; i++) + { + const lNode = lNodes[i]; + if (!layerTable.Has(lNode.name)) + { + console.log(`Layer ${lNode.name} not found in layer table`); + continue; + } + const layer = layerTable.GetAt(lNode.name) as LayerTableRecord; + names.push(lNode.name); + // 文件夹 + if (lNode.children) + { + const node: ILayerNode = { name: layer.Name, children: [], isOff: layer.IsOff, isLock: layer.IsLocked, visible: true, selected: false, changeable: false, expanded: true }; + nodes.push(node); + // 下钻 + if (lNode.children.length > 0) + Update(lNode.children, node.children); + } + // 文件 + else + { + const node: ILayerNode = { name: lNode.name, colorIndex: layer.ColorIndex, isOff: layer.IsOff, isLock: layer.IsLocked, visible: true, selected: false, changeable: false, isCurrent: false }; + if (layerTable.Current === layer.Id) + { + node.isCurrent = true; + layerTopStore.featureMatchOptions[0].colorIndex = node.colorIndex; + } + nodes.push(node); + } + } + }; + // 更新View层数据 + const data: ILayerNode[] = []; + Update(layerTable.Root.children, data); + layerStore.data = data; + // 更新关联的实体 + UpdateEntity(names, (en: Entity) => en.Update()); + } +} + +/** 操作与图层关联的实体 */ +const UpdateEntity = (names: string[], Callback: (en: Entity) => void) => +{ + const layerTable = app.Database.LayerTable; + for (const name of names) + { + if (!layerTable.Has(name)) + continue; + const layer = layerTable.GetAt(name) as LayerTableRecord; + const isNormalLight = (en: Entity) => en instanceof AmbientLight || en instanceof DirectionalLight || en instanceof HemisphereLight; + for (let en of app.Database.ModelSpace.Entitys) + if (en.Layer === layer.Id) + Callback(en); + for (let en of app.Database.Lights.Entitys) + if (en.Layer === layer.Id && !isNormalLight(en)) + Callback(en); + } +}; + +/** 针对图层的数据转换器(View层->Data层) + * @description 该类用于将图层的View层数据转换为图层的Data层数据,便于数据库的读写 + * 如:锁定按钮被点击时(只需要关心按钮状态的UI数据),调用该类对应的方法即可实现图层的锁定功能 + */ +export class ViewToDataForLayer +{ + /** 创建图层 */ + static AppendLayer(node: ILayerNode) + { + const layerTable = app.Database.LayerTable; + // Root + UpdateTableRoot(); + // Record + const layer = new LayerTableRecord(); + layer.Name = node.name; + layer.IsOff = node.isOff; + layer.IsLocked = node.isLock; + if (!node.children) + layer.ColorIndex = node.colorIndex; + layerTable.Add(layer); + // Current + UpdateTableCurrent(); + } + + /** 删除图层 */ + static RemoveLayer(node: ILayerNode, moveWhere: string) + { + const layerTable = app.Database.LayerTable; + // Root + UpdateTableRoot(); + // Record + const Remove = (node: ILayerNode) => + { + if (!layerTable.Has(node.name)) + return; + if (!moveWhere) + UpdateEntity([node.name], (en: Entity) => en.Erase()); + else + { + if (!layerTable.Has(moveWhere)) + return; + const moveLayer = layerTable.GetAt(moveWhere) as LayerTableRecord; + UpdateEntity([node.name], (en: Entity) => en.Layer = moveLayer.Id); + } + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + layerTable.Remove(layer); + }; + if (!node.children) + Remove(node); + else + TreeAction.UpdateNode(node.children, (child: ILayerNode) => Remove(child)); + // Current + UpdateTableCurrent(); + } + + /** 置为当前图层 */ + static SetCurrentLayer() + { + // Current + UpdateTableCurrent(); + } + + /** 设置是否显示 */ + static UpdateShow(node: ILayerNode) + { + // Record + UpdateTableRecord(); + // Update + const names = [node.name]; + if (node.children) + TreeAction.UpdateNode(node.children, (subNode: ILayerNode) => names.push(subNode.name)); + UpdateEntity(names, (en: Entity) => en.UpdateVisible()); + } + + /** 设置是否锁定 */ + static UpdateLock(node: ILayerNode) + { + // Record + UpdateTableRecord(); + // Update + const names = [node.name]; + if (node.children) + TreeAction.UpdateNode(node.children, (subNode: ILayerNode) => names.push(subNode.name)); + UpdateEntity(names, (en: Entity) => + { + en.Freeze = node.isLock; + }); + } + + /** 设置是否视口冻结 */ + static UpdateViewPoint(node: ILayerNode) + { + const layerTable = app.Database.LayerTable; + const currentViewport = app.Viewer.CurrentViewport; + const UpdateFreeze = (node: ILayerNode) => + { + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + // 选中了视口 + if (currentViewport) + { + if (node.isViewportOff) + { + if (!currentViewport.HasFreezeLayer(layer.Id)) + currentViewport.AddFreezeLayer(layer.Id); + } + else + if (currentViewport.HasFreezeLayer(layer.Id)) + currentViewport.DeleteFreezeLayer(layer.Id); + currentViewport.UpdateScene(); + } + // 没选择视口 + else + { + const ViewPorts = app.Viewer.ViewPorts; + if (node.isViewportOff) + ViewPorts.forEach(ViewPort => !ViewPort.HasFreezeLayer(layer.Id) && ViewPort.AddFreezeLayer(layer.Id)); + else + ViewPorts.forEach(ViewPort => ViewPort.HasFreezeLayer(layer.Id) && ViewPort.DeleteFreezeLayer(layer.Id)); + ViewPorts.forEach(ViewPort => ViewPort.UpdateScene()); + } + }; + if (node.children) + node.children.forEach(child => UpdateFreeze(child)); + else + UpdateFreeze(node); + app.Editor.UpdateScreen(); + } + + /** 设置颜色 */ + static UpdateColor(node: ILayerNode) + { + // Record + const layerTable = app.Database.LayerTable; + if (!layerTable.Has(node.name)) + return; + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + layer.ColorIndex = node.colorIndex; + // Update + UpdateEntity([node.name], (en: Entity) => + { + if (en instanceof CompositeEntity) + en.Entitys.map(en => en.Update()); + else + en.Update(); + }); + } + + /** 重命名图层 */ + static RenameLayer(oldName: string, newName: string) + { + // Root + UpdateTableRoot(); + // Record + const layerTable = app.Database.LayerTable; + if (!layerTable.Has(oldName)) + return; + const layer = layerTable.GetAt(oldName) as LayerTableRecord; + layer.Name = newName; + } + + /** 移动图层 */ + static MoveLayer(node: ILayerNode) + { + // Root + UpdateTableRoot(); + } +} + +/** 更新Root */ +const UpdateTableRoot = () => +{ + const layerStore = LayerStore.GetInstance(); + const layerTable = app.Database.LayerTable; + /** 更新图层结构 */ + const Update = (nodes: ILayerNode[], lNodes: LayerNode[]) => + { + for (let i = 0; i < nodes.length; i++) + { + const node = nodes[i]; + // 文件夹 + if (node.children) + { + const lNode = new LayerNode(node.name, true); + lNodes.push(lNode); + // 下钻 + if (node.children.length > 0) + Update(node.children, lNode.children); + } + // 文件 + else + { + const lNode = new LayerNode(node.name); + lNodes.push(lNode); + } + } + }; + const root = new LayerNode("Root", true); + Update(layerStore.data, root.children); + layerTable.Root = root; +}; + +/** 更新Current */ +const UpdateTableCurrent = () => +{ + const layerStore = LayerStore.GetInstance(); + const layerTable = app.Database.LayerTable; + const node = TreeAction.FindNode(layerStore.data, (node: ILayerNode) => node.isCurrent); + if (!node || !layerTable.Has(node.name)) + return; + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + layerTable.Current = layer.Id; + HostApplicationServices.CurrentLayer = layer.Id; +}; + +/** 更新Record */ +const UpdateTableRecord = () => +{ + const layerStore = LayerStore.GetInstance(); + const layerTable = app.Database.LayerTable; + TreeAction.UpdateNode(layerStore.data, (node: ILayerNode) => + { + if (!layerTable.Has(node.name)) + return; + const layer = layerTable.GetAt(node.name) as LayerTableRecord; + layer.Name = node.name; + layer.IsOff = node.isOff; + layer.IsLocked = node.isLock; + if (!node.children) + layer.ColorIndex = node.colorIndex; + }); +}; diff --git a/src/UI/Components/ToolBar/Layer/State/Type.ts b/src/UI/Components/ToolBar/Layer/State/Type.ts new file mode 100644 index 000000000..6601252fd --- /dev/null +++ b/src/UI/Components/ToolBar/Layer/State/Type.ts @@ -0,0 +1,35 @@ +/** 树的基本数据类型 */ +export interface INode +{ + /** 名称 */ + name: string; + /** 子节点 */ + children?: INode[]; +} + +/** 图层的数据类型 */ +export interface ILayerNode extends INode +{ + children?: ILayerNode[]; + /** 是否为当前图层 */ + isCurrent?: boolean; + /** 是否隐藏 */ + isOff: boolean; + /** 是否锁定 */ + isLock: boolean; + /** 是否视口隐藏(仅在视口模式下有效) */ + isViewportOff?: boolean; + /** 图层颜色索引 */ + colorIndex?: number; + + /* ---- 以下仅用于UI ---- */ + + /** 是否显示(用于搜索过滤) */ + visible: boolean; + /** 是否选中 */ + selected: boolean; + /** 是否可输入(用于重命名) */ + changeable: boolean; + /** 是否展开 */ + expanded?: boolean; +} diff --git a/src/UI/Components/ToolBar/PropertiesPanel.less b/src/UI/Components/ToolBar/PropertiesPanel.less index c29fee258..535c29b0a 100644 --- a/src/UI/Components/ToolBar/PropertiesPanel.less +++ b/src/UI/Components/ToolBar/PropertiesPanel.less @@ -1,5 +1,5 @@ .properties { - width: 170px; + width: 230px; .bp3-card { padding: 5px; height : 100%; diff --git a/src/UI/Components/ToolBar/PropertiesPanel.tsx b/src/UI/Components/ToolBar/PropertiesPanel.tsx index e88ae0f42..54805928e 100644 --- a/src/UI/Components/ToolBar/PropertiesPanel.tsx +++ b/src/UI/Components/ToolBar/PropertiesPanel.tsx @@ -11,6 +11,7 @@ import { CommandWrap } from "../../../Editor/CommandMachine"; import { DownPanelStore } from "../../Store/DownPanelStore"; import { ColorModal } from "../EntityModal/EntityColorList"; import { GetEntityProperty } from "../EntityModal/GetEntityProperty"; +import { LayerManager } from "./Layer/LayerManager"; import { PropertiesStore } from "./PropertiesStore"; import { Properties_AlignedDimPanel } from "./Properties_AlignedDim"; import { Properties_DimPanel } from "./Properties_Dim"; @@ -111,87 +112,98 @@ export class PropertiesPanel extends React.Component<{}, {}> options.unshift({ label: "无选择", value: "none" }); let ents = store.GetEntitys(); let pers = GetEntityProperty(ents[0]); + const downStore = DownPanelStore.GetInstance(); return (
- -
- 特性 -
-
- this._HandleSelectOnChange(e)} - /> -
-
    - 常规 - { - ents.length > 0 && - <> -
  • - -
  • - {pers.map(p =>
  • {p}
  • )} - { - ents[0] instanceof AlignedDimension && - <> - 使用样式 -
    - - { - if (e.button === -1) - this._ChangeDimStyle(e.currentTarget.value, ents); - }} - /> -
    - - } - { - ents[0] instanceof Dimension && - <> - 其他 - - } - { - ents[0] instanceof AlignedDimension && - <> -
  • - -
  • - - } - { - ents[0] instanceof Dimension && - <> -
  • - -
  • - - } - { - ents[0] instanceof Text && - <> - 其他 -
  • - -
  • - - } - - } -
-
+
+
{ downStore.isLayer = true; }}>图层
+
+
{ downStore.isLayer = false; }}>特性
+
+ {downStore.isLayer ? + : + +
+ 特性 +
+
+ this._HandleSelectOnChange(e)} + /> +
+
    + 常规 + { + ents.length > 0 && + <> +
  • + +
  • + {pers.map(p =>
  • {p}
  • )} + { + ents[0] instanceof AlignedDimension && + <> + 使用样式 +
    + + { + if (e.button === -1) + this._ChangeDimStyle(e.currentTarget.value, ents); + }} + /> +
    + + } + { + ents[0] instanceof Dimension && + <> + 其他 + + } + { + ents[0] instanceof AlignedDimension && + <> +
  • + +
  • + + } + { + ents[0] instanceof Dimension && + <> +
  • + +
  • + + } + { + ents[0] instanceof Text && + <> + 其他 +
  • + +
  • + + } + + } +
+
+ }
); } diff --git a/src/UI/Components/TopToolBar/TopToolBar.tsx b/src/UI/Components/TopToolBar/TopToolBar.tsx index 4dbeccacf..58de15928 100644 --- a/src/UI/Components/TopToolBar/TopToolBar.tsx +++ b/src/UI/Components/TopToolBar/TopToolBar.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { CommandNames } from "../../../Common/CommandNames"; import { IconEnum } from "../../IconEnum"; import { DownPanelStore } from "../../Store/DownPanelStore"; +import { LayerPanel } from "../ToolBar/Layer/LayerPanel"; import { DimensionPanel } from "./DimensionPanel"; import { DrawingPanel } from "./DrawingPanel"; import { FileOperationPanel } from "./FileOperationPanel"; @@ -245,6 +246,7 @@ export class TopToolBar extends React.Component<{}, {}> > } /> } /> + } /> } /> } /> } /> diff --git a/src/UI/Css/golden.less b/src/UI/Css/golden.less index 85d3de399..4fd0f9c75 100644 --- a/src/UI/Css/golden.less +++ b/src/UI/Css/golden.less @@ -31,13 +31,14 @@ @properties_header_bg: #202b33, @properties_li_title_bg: #293742, @templateParam_detail_title_bg: #394b59, - @keyBoardBar_bg:#5c7080, + @keyBoardBar_bg: #5c7080, @recommand_cmd_custom_li_color: #dddddd, @recommand_cmd_system_li_color: #fbc38e, @recommand_cmd_chNames_li_color: #57e97d, @command_setting_bg: #4b6070, - @command_setting_console:#abaeb1, + @command_setting_console: #abaeb1, ) { + /*-----FileItem文件名-----*/ #bp3-tab-panel_Tabs_fl li[id] input { background-color: @fileName_bg; @@ -79,17 +80,19 @@ background-color: @recommand_cmd_bg; } - #input-hint .recommend-command > li.hover { + #input-hint .recommend-command>li.hover { background-color: @recommand_cmd_bg_hover; } - #input-hint .recommend-command .command { + #input-hint .recommend-command .command { color: @recommand_cmd_system_li_color; } - #input-hint .recommend-command .custom { + + #input-hint .recommend-command .custom { color: @recommand_cmd_custom_li_color; } - #input-hint .recommend-command .chName { + + #input-hint .recommend-command .chName { color: @recommand_cmd_chNames_li_color; } @@ -108,7 +111,7 @@ background: @topToolBar_bg; } - #TopToolBar .tool-block > div > .bp3-button { + #TopToolBar .tool-block>div>.bp3-button { background: @topToolsBlock_btn_bg; &:hover { @@ -120,7 +123,7 @@ background: @topToolBar_ul_bg; } - #TopToolBar .small-iconlist > .bp3-button { + #TopToolBar .small-iconlist>.bp3-button { background: @topToolBar_smallIconList_btn_bg; &:hover { @@ -128,7 +131,7 @@ } } - #TopToolBar .ul-unstyle > li:hover { + #TopToolBar .ul-unstyle>li:hover { background: @topToolBar_li_hover; } @@ -142,7 +145,7 @@ background: @topToolBar_tablist_bg_hover; } - .bp3-tabs.bp3-vertical > .bp3-tab-list .bp3-tab.tab-unstyle[aria-selected="true"] { + .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab.tab-unstyle[aria-selected="true"] { background: @verticalTab_selected_bg; } @@ -156,13 +159,16 @@ /*----------浮动命令栏-----------*/ #CommandInput .react-draggable { + .terminal-output-area, .command-input-area { background: @commandInput_bg; - .command-setting-wrench{ + + .command-setting-wrench { background: @command_setting_bg; border-color: @text_color_unactive; - .command-console{ + + .command-console { color: @command_setting_console; } } @@ -178,15 +184,15 @@ } /*----------F1面板-----------*/ - #commandPanel .bp3-card > ul > li:hover, - #commandPanel .bp3-card > ul > ul > li:hover { + #commandPanel .bp3-card>ul>li:hover, + #commandPanel .bp3-card>ul>ul>li:hover { background-color: @commandPanel_li_bg_hover; cursor: pointer; } /*-----------BBS-------------*/ #modal .br-lookover .react-draggable { - > div { + >div { background-color: @fileName_bg; } } @@ -199,6 +205,7 @@ } ul { + //.props .li-title { background: @properties_li_title_bg; @@ -220,8 +227,8 @@ /*-------右侧模板参数--------*/ #templateParam { .template-detail { - & > ul { - & > li:first-child { + &>ul { + &>li:first-child { span { background: @templateParam_detail_title_bg; } @@ -232,8 +239,8 @@ /*-------模块管理参数列表--------*/ #commonModal .template-detail { - & > ul { - & > li:first-child { + &>ul { + &>li:first-child { span { background: @templateParam_detail_title_bg; } @@ -242,58 +249,73 @@ } //全局 - #modal{ - .bp3-dialog-body{ + #modal { + .bp3-dialog-body { background-color: @topToolBar_bg; } - .bp3-dialog-footer{ + .bp3-dialog-footer { background-color: @topToolBar_bg; } } //模型库 .resourcePanel .bp3-card { - .header{ + .header { background-color: @properties_header_bg; } .categoryList { - .categoryTitle{ + .categoryTitle { background-color: @properties_header_bg; } - .resources ul li{ + + .resources ul li { background-color: @fileName_bg; } } } //画廊 - .GalleryIndexList{ - .GalleryIndexListHeader{ + .GalleryIndexList { + .GalleryIndexListHeader { background-color: @fileName_bg; } } //分享图设置 - #ShareBoardInfoPanel{ - .container{ + #ShareBoardInfoPanel { + .container { background-color: @verticalTab_selected_bg; } - .options{ + .options { background-color: @verticalTab_selected_bg; } } + //吊顶材质面板 #BulkheadCeilingConfig { .bp3-dialog-body { background-color: @fileName_bg; } - } - - #commonModal .get-name .needBoardName - { + } + + #commonModal .get-name .needBoardName { background-color: @commandPanel_li_bg_hover; } + + // 颜色跟随主题-导航栏 + .styleWithThemeInNav { + background: @topToolBar_tablist_bg; + } + + .styleWithThemeInNavHover { + background: @topToolBar_bg; + } + + // 颜色跟随主题 + .styleWithTheme { + background-color: @fileName_bg; + } } diff --git a/src/UI/Store/DownPanelStore.ts b/src/UI/Store/DownPanelStore.ts index 8097ab856..25b91a941 100644 --- a/src/UI/Store/DownPanelStore.ts +++ b/src/UI/Store/DownPanelStore.ts @@ -52,6 +52,8 @@ export class DownPanelStore { @observable useDynInput: boolean = true; @observable showType: ToolBarType = 1; + /** 是否显示图层 */ + @observable isLayer: boolean = false; @observable useDynSnap: boolean = true; @observable usePass: boolean = true; @observable useOrtho: boolean = false; @@ -338,7 +340,17 @@ export class DownPanelStore TogglePropertiesPanel() { - this.showType ^= ToolBarType.properties; + if (this.showType === 1 || !this.isLayer) + this.showType ^= ToolBarType.properties; + this.isLayer = false; + } + /** 打开/关闭图层列表 */ + ToggleLayerList() + { + // 若特性面板已打开,则切换成图层列表 + if (this.showType === 1 || this.isLayer) + this.showType ^= ToolBarType.properties; + this.isLayer = true; } ToggleResourcePanel() { diff --git a/src/UI/Store/EntityStore.ts b/src/UI/Store/EntityStore.ts index 43d8b9015..a5fd72c8b 100644 --- a/src/UI/Store/EntityStore.ts +++ b/src/UI/Store/EntityStore.ts @@ -10,6 +10,7 @@ import { Line } from "../../DatabaseServices/Entity/Line"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Region } from "../../DatabaseServices/Entity/Region"; import { Text } from "../../DatabaseServices/Text/Text"; +import { LayerPropertieStore } from "../Components/ToolBar/Layer/State/Store"; import { DownPanelStore, ToolBarType } from "./DownPanelStore"; export class EntityStore extends Singleton @@ -64,7 +65,7 @@ export class EntityStore extends Singleton get IsWorking() { - return (DownPanelStore.GetInstance().showType & ToolBarType.properties) > 0; + return (DownPanelStore.GetInstance().showType & ToolBarType.properties) > 0 || LayerPropertieStore.isShow; } GetEntitys()