diff --git a/__test__/FileSystem/__snapshots__/file.test.ts.snap b/__test__/FileSystem/__snapshots__/file.test.ts.snap index d35bd9b2d..5f931b698 100644 --- a/__test__/FileSystem/__snapshots__/file.test.ts.snap +++ b/__test__/FileSystem/__snapshots__/file.test.ts.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`changev 1`] = `"[5,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[2,3,4],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",2,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",100,1,\\"ObjectAllDataHistoryRecord\\",1,1,\\"AllObjectData\\",1,[8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",\\"\\",100,2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0]"`; +exports[`changev 1`] = `"[6,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[2,3,4],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",2,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",100,1,\\"ObjectAllDataHistoryRecord\\",1,1,\\"AllObjectData\\",1,[8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",\\"\\",100,2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0]"`; -exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[5,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\",2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0]"`; +exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[6,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\",2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0]"`; exports[`创建 修改 撤销撤销 重做重做 撤销 重做 2`] = `"[\\"HistoricManage\\",1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\"]"`; diff --git a/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap b/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap index e804a5677..2271defec 100644 --- a/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap +++ b/__test__/FileSystem/__snapshots__/wblockClone.test.ts.snap @@ -2,7 +2,7 @@ exports[`wblockClone 1`] = ` Array [ - 5, + 6, 102, 1, 2, @@ -98,12 +98,24 @@ Array [ false, 0, 0, + 1, + 2, + 10, + false, + 0, + 1, + "", + 2, + 11, + false, + 0, + 0, ] `; exports[`wblockClone 2`] = ` Array [ - 5, + 6, 104, 1, 2, @@ -238,12 +250,24 @@ Array [ false, 0, 0, + 1, + 2, + 10, + false, + 0, + 1, + "", + 2, + 11, + false, + 0, + 0, ] `; exports[`wblockClone 3`] = ` Array [ - 5, + 6, 102, 1, 2, @@ -339,5 +363,17 @@ Array [ false, 0, 0, + 1, + 2, + 10, + false, + 0, + 1, + "", + 2, + 11, + false, + 0, + 0, ] `; diff --git a/src/Add-on/Copy.ts b/src/Add-on/Copy.ts index d7e91e8b8..aa0e70e99 100644 --- a/src/Add-on/Copy.ts +++ b/src/Add-on/Copy.ts @@ -72,7 +72,7 @@ export class Command_Copy implements Command if (ptRes2.Status === PromptStatus.OK) { let moveM = MoveMatrix(ptRes2.Point.sub(ptBase)); - let cloneEns = app.Database.DeepCloneObjects(orgEns, app.Database.ModelSpace) as Entity[]; + let cloneEns = app.Database.DeepCloneObjects(orgEns, app.Viewer.isLayout ? app.Database.LayoutSpace : app.Database.ModelSpace) as Entity[]; let set = new Set(cloneEns); diff --git a/src/Add-on/DrawCircle.ts b/src/Add-on/DrawCircle.ts index 3bedcea39..a0cb2b214 100644 --- a/src/Add-on/DrawCircle.ts +++ b/src/Add-on/DrawCircle.ts @@ -55,7 +55,7 @@ export class DrawCircle implements Command if (disRes.Status === PromptStatus.OK) { cir.Radius = disRes.Distance; - app.Database.ModelSpace.Append(cir); + app.LayoutTool.AppendDatabaseSpace(cir); } JigUtils.Destroy(); } @@ -81,7 +81,7 @@ export class DrawCircle implements Command { cir.Radius = ptRes2.Point.distanceTo(ptRes1.Point) / 2; cir.Center = midPoint(ptRes2.Point, ptRes1.Point); - app.Database.ModelSpace.Append(cir); + app.LayoutTool.AppendDatabaseSpace(cir); } JigUtils.Destroy(); } @@ -118,7 +118,7 @@ export class DrawCircle implements Command ar.FromThreePoint(ptRes1.Point, ptRes2.Point, ptRes3.Point); cir.Radius = ar.Radius; cir.Center = ar.Center; - app.Database.ModelSpace.Append(cir); + app.LayoutTool.AppendDatabaseSpace(cir); } JigUtils.Destroy(); } diff --git a/src/Add-on/DrawLine.ts b/src/Add-on/DrawLine.ts index 5f7d9a56a..ecf99f503 100644 --- a/src/Add-on/DrawLine.ts +++ b/src/Add-on/DrawLine.ts @@ -74,8 +74,7 @@ export class DrawLine implements Command if (ptRes.Status === PromptStatus.OK) { updateEndPt(ptRes.Point); - - app.Database.ModelSpace.Append(line); + app.LayoutTool.AppendDatabaseSpace(line); drawLines.push(line); ptLast = ptRes.Point; continue; @@ -87,7 +86,7 @@ export class DrawLine implements Command if (drawLines.length > 0) { let lastLine = drawLines[drawLines.length - 1]; - app.Database.ModelSpace.Remove(lastLine); + app.LayoutTool.RemoveDatabaseSpace(lastLine); drawLines.pop(); ptLast = lastLine.StartPoint; @@ -98,7 +97,7 @@ export class DrawLine implements Command if (drawLines.length > 1) { let line = new Line(ptLast, drawLines[0].StartPoint); - app.Database.ModelSpace.Append(line); + app.LayoutTool.AppendDatabaseSpace(line); break; } } diff --git a/src/Add-on/DrawPoint.ts b/src/Add-on/DrawPoint.ts index d0e477689..27550b6b6 100644 --- a/src/Add-on/DrawPoint.ts +++ b/src/Add-on/DrawPoint.ts @@ -17,7 +17,7 @@ export class CMD_DrawPoint implements Command else { let ptEnt = new Point(ptRes.Point); - app.Database.ModelSpace.Append(ptEnt); + app.LayoutTool.AppendDatabaseSpace(ptEnt); continue; } } diff --git a/src/Add-on/DrawPolyline.ts b/src/Add-on/DrawPolyline.ts index a26d652b8..a95266af8 100644 --- a/src/Add-on/DrawPolyline.ts +++ b/src/Add-on/DrawPolyline.ts @@ -22,7 +22,7 @@ export class DrawPolyline let pl = new Polyline(); pl.ApplyMatrix(app.Editor.UCSMatrix); - app.Database.ModelSpace.Append(pl); + app.LayoutTool.AppendDatabaseSpace(pl); let plJig = JigUtils.Draw(pl); @@ -104,7 +104,7 @@ export class DrawPolyline JigUtils.End(); if (pl.NumberOfVertices < 2) { - app.Database.ModelSpace.Remove(pl); + app.LayoutTool.RemoveDatabaseSpace(pl); return true; } } @@ -143,4 +143,3 @@ export class DrawPolyline pl.RemoveVertexAt(pl.NumberOfVertices - 1); } } - diff --git a/src/Add-on/DrawRect.ts b/src/Add-on/DrawRect.ts index af7284f75..2638171c0 100644 --- a/src/Add-on/DrawRect.ts +++ b/src/Add-on/DrawRect.ts @@ -16,7 +16,7 @@ export class DrawRect implements Command rec.RectangleFrom2Pt(rectRes.Point1UCS, rectRes.Point2UCS); rec.Position = new Vector3(0, 0, rectRes.Point1UCS.z); rec.ApplyMatrix(app.Editor.UCSMatrix); - app.Database.ModelSpace.Append(rec); + app.LayoutTool.AppendDatabaseSpace(rec); } } } diff --git a/src/Add-on/DrawViewport.ts b/src/Add-on/DrawViewport.ts new file mode 100644 index 000000000..956c4b456 --- /dev/null +++ b/src/Add-on/DrawViewport.ts @@ -0,0 +1,67 @@ +import { Command } from "../Editor/CommandMachine"; +import { app } from "../ApplicationServices/Application"; +import { PromptStatus } from "../Editor/PromptResult"; +import { ViewportEntity } from "../DatabaseServices/ViewportEntity"; +import { Log } from "../Common/Log"; +import { Vector3 } from "three"; + +export class DrawViewport implements Command +{ + async exec() + { + if (!app.Viewer.isLayout) + { + Log("仅能在布局模式下使用"); + return; + } + let rectRes = await app.Editor.GetRectPoint(); + + if (rectRes.Status === PromptStatus.OK) + { + let p1 = rectRes.Point1UCS; + let p2 = rectRes.Point2UCS; + let vp = new ViewportEntity(); + vp.UpdateByPts(p1, p2); + app.Database.LayoutSpace.Append(vp); + } + } +} +export class Draw4Viewport implements Command +{ + async exec() + { + if (!app.Viewer.isLayout) + { + Log("仅能在布局模式下使用"); + return; + } + let rectRes = await app.Editor.GetRectPoint(); + + if (rectRes.Status === PromptStatus.OK) + { + let p1 = rectRes.Point1UCS; + let p2 = rectRes.Point2UCS; + let left = Math.min(p1.x, p2.x); + let bottom = Math.min(p1.y, p2.y); + let width = Math.abs(p1.x - p2.x); + let height = Math.abs(p1.y - p2.y); + + let vp1 = new ViewportEntity(width / 2, height / 2); + vp1.Position = new Vector3(left, bottom); + + let vp2 = new ViewportEntity(width / 2, height / 2); + vp2.Position = new Vector3(left + width / 2, bottom); + vp2.camera.LookAt(new Vector3(1, 1, -1)); + + let vp3 = new ViewportEntity(width / 2, height / 2); + vp3.camera.LookAt(new Vector3(-1)); + vp3.Position = new Vector3(left + width / 2, bottom + height / 2); + + let vp4 = new ViewportEntity(width / 2, height / 2); + vp4.camera.LookAt(new Vector3(0, 1)); + vp4.Position = new Vector3(left, bottom + height / 2); + + [vp1, vp2, vp3, vp4].forEach(p => app.Database.LayoutSpace.Append(p)); + } + } +} diff --git a/src/Add-on/Erase.ts b/src/Add-on/Erase.ts index fb3b0c5a2..786070da5 100644 --- a/src/Add-on/Erase.ts +++ b/src/Add-on/Erase.ts @@ -3,11 +3,18 @@ import { IsDev } from '../Common/Deving'; import { GetEntity } from '../Common/Utils'; import { Command } from '../Editor/CommandMachine'; import { PromptStatus } from '../Editor/PromptResult'; +import { Log } from '../Common/Log'; export class Command_Erase implements Command { async exec() { + if (app.Viewer.CurrentViewport) + { + Log("布局视口空间不能删除实体"); + return; + } + if (IsDev() && app.Editor.SelectCtrl.SelectSet.SelectObjectCount) { for (let obj of app.Editor.SelectCtrl.SelectSet.SelectObjectList) diff --git a/src/Add-on/HideSelected.ts b/src/Add-on/HideSelected.ts index 7c39c388b..1690a19ef 100644 --- a/src/Add-on/HideSelected.ts +++ b/src/Add-on/HideSelected.ts @@ -13,6 +13,13 @@ export class Command_HideSelected implements Command async exec() { let selects = app.Editor.SelectCtrl.SelectSet.SelectEntityList; + + if (app.Viewer.CurrentViewport) + { + app.LayoutTool.HideViewportEntitys(selects); + return; + } + if (selects.length !== 0) for (let e of selects) e.Visible = false; @@ -27,6 +34,12 @@ export class Command_ShowAll implements Command { async exec() { + if (app.Viewer.CurrentViewport) + { + app.LayoutTool.ShowViewportEntitys(); + return; + } + app.Database.ModelSpace.Entitys.forEach(o => { o.Visible = true; @@ -39,17 +52,21 @@ export class Command_HideUnselected implements Command async exec() { let selects = app.Editor.SelectCtrl.SelectSet.SelectEntityList; - let count = 0; - app.Database.ModelSpace.Entitys.forEach(o => + let hideEnts = app.Database.ModelSpace.Entitys.filter(o => { - if (!selects.includes(o) && !(o instanceof Light)) - { - o.Visible = false; - count++; - } + return !selects.includes(o) && !(o instanceof Light); }); - if (count === 0) + + if (app.Viewer.CurrentViewport) + { + app.LayoutTool.HideViewportEntitys(hideEnts); + return; + } + + if (hideEnts.length === 0) app.Editor.Prompt("没有未选中的实体,隐藏失败!"); + else + hideEnts.forEach(e => e.Visible = false); } } @@ -60,6 +77,8 @@ export class Command_SwitchDoor implements Command { const DoorCache: Set = new Set(); + let vp = app.Viewer.CurrentViewport; + let ens: Entity[] = []; const ToggleObject = (temp: TemplateRecord) => { @@ -69,7 +88,7 @@ export class Command_SwitchDoor implements Command { let en = id2.Object as Entity; DoorCache.add(id2.Index); - en.Visible = this._isShow; + ens.push(en); } } }; @@ -92,14 +111,18 @@ export class Command_SwitchDoor implements Command if (en instanceof Board) { if (en.OpenDir !== BoardOpenDir.None) - en.Visible = this._isShow; + { + ens.push(en); + } } else if (en instanceof HardwareCompositeEntity) { if (en.HardwareOption.model.endsWith("开门板") || en.HardwareOption.name.includes("铰链") || en.HardwareOption.name.includes("拉手")) - en.Visible = this._isShow; + { + ens.push(en); + } } continue; } @@ -109,7 +132,7 @@ export class Command_SwitchDoor implements Command if ((temp?.Parent?.Object as TemplateRecord)?.Name === "门板空间") { DoorCache.add(en.Id.Index); - en.Visible = this._isShow; + ens.push(en); let doorSpaceTemp = temp.Parent.Object as TemplateRecord;; for (let id of doorSpaceTemp.Children) @@ -135,6 +158,17 @@ export class Command_SwitchDoor implements Command } } } + + if (vp) + { + if (this._isShow) + app.LayoutTool.ShowViewportEntitys(ens); + else + app.LayoutTool.HideViewportEntitys(ens); + } + else + ens.forEach(e => e.Visible = this._isShow); + } } diff --git a/src/Add-on/Offset.ts b/src/Add-on/Offset.ts index 003a084d8..53d473107 100644 --- a/src/Add-on/Offset.ts +++ b/src/Add-on/Offset.ts @@ -158,7 +158,7 @@ export class Command_Offset implements Command DrawOffset(cu: Curve, offsetDist: number) { for (let c of cu.GetOffsetCurves(offsetDist)) - app.Database.ModelSpace.Append(c); + app.LayoutTool.AppendDatabaseSpace(c); } //单一对象,已经确定偏移距离的时候,用户选择偏移方向. diff --git a/src/Add-on/PasteClip.ts b/src/Add-on/PasteClip.ts index 3ecc2ddff..33be71ca2 100644 --- a/src/Add-on/PasteClip.ts +++ b/src/Add-on/PasteClip.ts @@ -127,7 +127,7 @@ export class PasteClip { UpdateEntityPosition(ptRes.Point, false); for (let [en] of entityOCSCache) - app.Database.ModelSpace.Append(en); + app.LayoutTool.AppendDatabaseSpace(en); } else if (ptRes.Status === PromptStatus.Keyword) { diff --git a/src/Add-on/Print.ts b/src/Add-on/Print.ts index f6e9703de..88ce04e1d 100644 --- a/src/Add-on/Print.ts +++ b/src/Add-on/Print.ts @@ -1,15 +1,14 @@ -import { Object3D, Scene, Vector3 } from "three"; +import { Object3D, Scene, Vector3, Line } from "three"; import { app } from "../ApplicationServices/Application"; import { Sleep } from "../Common/Sleep"; import { Hole } from "../DatabaseServices/3DSolid/Hole"; import { CADFiler } from "../DatabaseServices/CADFiler"; import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension"; -import { Board } from "../DatabaseServices/Entity/Board"; import { Entity } from "../DatabaseServices/Entity/Entity"; import { Command } from "../Editor/CommandMachine"; import { PromptStatus } from "../Editor/PromptResult"; import { userConfig } from "../Editor/UserConfig"; -import { isParallelTo, XAxis, YAxis, ZAxis, equalv3 } from "../Geometry/GeUtils"; +import { isParallelTo, XAxis, YAxis, ZAxis, equalv3, GetBox } from "../Geometry/GeUtils"; import { RenderType } from "../GraphicsSystem/RenderType"; import { HotCMD } from "../Hot/HotCommand"; import { CompositeEntity } from "../DatabaseServices/Entity/CompositeEntity"; @@ -19,13 +18,16 @@ import { Text } from "../DatabaseServices/Text/Text"; import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid"; import { AppToaster } from "../UI/Components/Toaster"; import { Intent } from "@blueprintjs/core"; +import { ViewportEntity } from "../DatabaseServices/ViewportEntity"; +import { ColorMaterial } from "../Common/ColorPalette"; +import { Board } from "../DatabaseServices/Entity/Board"; @HotCMD export class Print implements Command { async exec() { - let isSingle = false; + let isSingle = true; const kw = { msg: "", key: "T" }; while (true) @@ -33,35 +35,47 @@ export class Print implements Command kw.msg = isSingle ? "多视图" : "单视图"; let enRes = await app.Editor.GetSelection({ UseSelect: true, - Msg: `选择要打印的实体<${isSingle ? "单视图" : "多视图"}>`, - KeyWordList: [kw], + Msg: `选择要打印的实体`, + // KeyWordList: [kw], Filter: { filterFunction: (o, e) => e && !e.IsErase && e.Id && !(e instanceof Hole) } }); if (enRes.Status === PromptStatus.OK) { let ens = enRes.SelectSet.SelectEntityList; - let printEnts: Entity[] = []; - for (let e of ens) + if (app.Viewer.isLayout) { - if (e instanceof Board) + let cloneEns: Entity[] = []; + for (let e of ens) { - printEnts.push(...e.SplitBoards); + let cn = e.Clone(); + if (cn instanceof ViewportEntity) + { + cn.scene = (e as ViewportEntity).scene; + } + cloneEns.push(cn); } - else - printEnts.push(e); + PrintImage3(cloneEns); } - if (isSingle) + else { + let printEnts: Entity[] = []; + for (let e of ens) + { + if (e instanceof Board) + { + printEnts.push(...e.SplitBoards); + } + else + printEnts.push(e); + } + // if (isSingle) + // { await PrintImage2(printEnts.map(e => e.Clone())); + // } + // else + // await PrintImage(printEnts.map(e => e.Clone())); } - else - await PrintImage(printEnts.map(e => e.Clone())); - return; - } - else if (enRes.Status === PromptStatus.Keyword) - { - isSingle = !isSingle; } else return; } @@ -158,7 +172,7 @@ async function PrintImage(ens: Entity[]) app.Viewer.CameraCtrl.LookAt(dir); //生成预览图 app.Viewer.Render(); - let url = app.Viewer.Renderer.domElement.toDataURL("image/jpeg"); + let url = app.Viewer.Renderer.domElement.toDataURL("image/jpeg", 1.0); imgUrls.push(url); handleObjs.forEach(obj => { @@ -810,7 +824,7 @@ async function PrintImage2(ens: Entity[]) //生成预览图 app.Viewer.ZoomAll(false); app.Viewer.Render(); - let url = app.Viewer.Renderer.domElement.toDataURL("image/jpeg"); + let url = app.Viewer.Renderer.domElement.toDataURL("image/jpeg", 1.0); imgUrls.push(url); handleObjs.forEach(obj => { @@ -891,3 +905,121 @@ async function PrintImage2(ens: Entity[]) CreateFooter(win.document.body); // win.print(); } +async function PrintImage3(ens: Entity[]) +{ + //备份视图 + let sceneBak = app.Viewer.Scene; + let aabak = app.Viewer.AAType; + let clearColorBak = app.Viewer.Renderer.getClearColor().clone(); + let f = new CADFiler(); + app.Viewer.CameraCtrl.WriteFile(f); + let vpsbak = app.Viewer.ViewPorts; + app.Viewer.ViewPorts = ens.filter(e => e instanceof ViewportEntity) as ViewportEntity[]; + + //设置视图 + app.Viewer.Scene = new Scene(); + app.Viewer._AAType = AAType.SMAA; + app.Viewer.Renderer.setClearColor("#fff"); + app.Viewer.OnSize(1450 * 2, 960 * 2); + + //绘制 + for (let e of ens) + { + if (e instanceof ViewportEntity) + { + let o = e.DrawObject; + (o.children[0].children[0] as Line).material = ColorMaterial.TransparentLineMaterial; + app.Viewer.Scene.add(o); + } + else + { + if (IsOnlyRenderType(e)) + { + e["OnlyRenderType"] = false; + } + app.Viewer.Scene.add(e.GetDrawObjectFromRenderType(RenderType.Print)); + } + } + + //等待字体加载完 + await Sleep(10); + let box = GetBox(app.Viewer.Scene, true); + if (box.isEmpty()) + box.set(new Vector3(), new Vector3(1000 * (this.Width / this.Height), 1000, 1000)); + app.Viewer.Control.ZoomExtensBox3(box); + app.Viewer.Control.Zoom(1.01); + app.Viewer.Render(); + + let url = app.Viewer.Renderer.domElement.toDataURL("image/jpeg", 1.0); + + //还原视图 + [app.Viewer.Scene, sceneBak] = [sceneBak, app.Viewer.Scene]; + app.Viewer.Renderer.setClearColor(clearColorBak); + app.Viewer._AAType = aabak; + app.Viewer.ViewPorts = vpsbak; + f.Reset(); + app.Viewer.CameraCtrl.ReadFile(f); + app.Viewer.OnSize(); + app.Viewer.Render(); + + var win = window.open(); + if (!win) + { + app.Editor.Prompt("无法弹出新的窗口,请允许新窗口弹出!(地址栏右侧)"); + return; + } + let style = document.createElement("style"); + const FOOTER_HEIGHT = 80; + style.innerHTML = ` + .flex{ + display:flex; + } + *{ + box-sizing: border-box; + } + body{ + margin:0; + padding:0; + width:1450px; + height:960px; + margin:0 auto; + display:flex; + flex-direction: column; + } + .footer{ + display:flex; + height:${FOOTER_HEIGHT}px; + } + .footer>div,.footer>input{ + outline:1px solid #000; + line-height:${FOOTER_HEIGHT}px; + } + .footer>div>div{ + outline:1px solid #000; + height:${FOOTER_HEIGHT / 2}px; + line-height:${FOOTER_HEIGHT / 2}px; + } + .label-input{ + display:flex; + } + .label-input>div{ + width:65px !important; + } + .label-input>input{ + width:calc(100% - 65px); + } + `; + win.document.head.append(style); + + let div = document.createElement("div"); + div.style.textAlign = "center"; + div.style.flex = "1"; + + let img = new Image(); + img.style.height = "960px"; + img.style.width = "1450px"; + img.src = url; + div.append(img); + + win.document.body.append(div); +} diff --git a/src/Add-on/SwitchVisualStyles.ts b/src/Add-on/SwitchVisualStyles.ts index 5a309f22a..6c7c64b00 100644 --- a/src/Add-on/SwitchVisualStyles.ts +++ b/src/Add-on/SwitchVisualStyles.ts @@ -1,34 +1,48 @@ import { Command } from "../Editor/CommandMachine"; import { userConfig } from "../Editor/UserConfig"; import { RenderType } from "../GraphicsSystem/RenderType"; +import { app } from "../ApplicationServices/Application"; +import { ViewportEntity } from "../DatabaseServices/ViewportEntity"; +import { PromptStatus } from "../Editor/PromptResult"; -export class CMD_Wireframe implements Command +export class ChangeRenderType implements Command { - exec() + constructor(private _type: RenderType) { - userConfig.RenderType = RenderType.Wireframe; - } -} -export class CMD_Conceptual implements Command -{ - exec() - { - userConfig.RenderType = RenderType.Conceptual; } -} - -export class CMD_Physical implements Command -{ - exec() + async exec() { - userConfig.RenderType = RenderType.Physical; + if (app.Viewer.isLayout) + { + if (app.Viewer.CurrentViewport) + { + this.ChangeViewport([app.Viewer.CurrentViewport]); + return; + } + let vres = await app.Editor.GetSelection({ + Msg: "选择要改变渲染类型的视口", + UseSelect: true, + Filter: { + filterTypes: [ViewportEntity] + } + }); + + + if (vres.Status === PromptStatus.OK) + { + let vs = vres.SelectSet.SelectEntityList as ViewportEntity[]; + this.ChangeViewport(vs); + } + return; + } + userConfig.RenderType = this._type; } -} -export class CMD_Physical2 implements Command -{ - exec() + ChangeViewport(vs: ViewportEntity[]) { - userConfig.RenderType = RenderType.Physical2; + for (let v of vs) + { + v.RenderType = this._type; + } } } diff --git a/src/Add-on/Template/ShowFrame.ts b/src/Add-on/Template/ShowFrame.ts new file mode 100644 index 000000000..e050d9610 --- /dev/null +++ b/src/Add-on/Template/ShowFrame.ts @@ -0,0 +1,11 @@ +import { Command } from "../../Editor/CommandMachine"; +import { app } from "../../ApplicationServices/Application"; +import { FrameManage } from "../../UI/Components/Modal/FrameManager"; + +export class ShowFrmae implements Command +{ + async exec() + { + app.Editor.ModalManage.RenderModeless(FrameManage); + } +} diff --git a/src/Add-on/Trim.ts b/src/Add-on/Trim.ts index 3ba72e6c7..9e229bcaa 100644 --- a/src/Add-on/Trim.ts +++ b/src/Add-on/Trim.ts @@ -82,7 +82,7 @@ export class Command_Trim implements Command if (kniefCus.length !== len) kniefCus.push(...cus); for (let c of cus) - app.Database.ModelSpace.Append(c); + app.LayoutTool.AppendDatabaseSpace(c); } app.Editor.UpdateScreen(); @@ -125,7 +125,7 @@ export class Command_Trim implements Command { let inPts: Vector3[] = []; if (kniefCus.length === 0) - kniefCus = app.Database.ModelSpace.Entitys.filter(cu => cu instanceof Curve && !cu.IsErase) as Curve[]; + kniefCus = app.LayoutTool.CurrentSpace.Entitys.filter(cu => cu instanceof Curve && !cu.IsErase) as Curve[]; for (let icu of kniefCus) if (icu !== thisCurve) diff --git a/src/Add-on/ViewChange.ts b/src/Add-on/ViewChange.ts index a3be7d462..8f369dec4 100644 --- a/src/Add-on/ViewChange.ts +++ b/src/Add-on/ViewChange.ts @@ -1,6 +1,8 @@ import { Matrix4, Vector3 } from "three"; import { app } from '../ApplicationServices/Application'; import { Command } from "../Editor/CommandMachine"; +import { ViewportEntity } from "../DatabaseServices/ViewportEntity"; +import { PromptStatus } from "../Editor/PromptResult"; export class ViewChange implements Command { @@ -12,6 +14,32 @@ export class ViewChange implements Command } async exec() { + if (app.Viewer.isLayout) + { + if (app.Viewer.CurrentViewport) + { + this.ChangeViewport([app.Viewer.CurrentViewport]); + return; + } + + let vres = await app.Editor.GetSelection({ + Msg: "选择要改变视图的视口", + UseSelect: true, + Filter: { + filterTypes: [ViewportEntity] + } + }); + + + if (vres.Status === PromptStatus.OK) + { + let vs = vres.SelectSet.SelectEntityList as ViewportEntity[]; + + this.ChangeViewport(vs); + } + return; + } + app.Viewer.CameraCtrl.LookAt(this.viewDir); this.UcsLookAt(this.viewDir); app.Viewer.ZoomAll(); @@ -29,4 +57,12 @@ export class ViewChange implements Command app.Editor.SetUCSLookAt(viewDir); } } + private ChangeViewport(vs: ViewportEntity[]) + { + for (let v of vs) + { + v.camera.LookAt(this.viewDir); + v.ZoomAll(); + } + } } diff --git a/src/ApplicationServices/Application.ts b/src/ApplicationServices/Application.ts index 047e39d2d..1ba480490 100644 --- a/src/ApplicationServices/Application.ts +++ b/src/ApplicationServices/Application.ts @@ -31,6 +31,8 @@ import { AutoSaveServer } from '../Editor/AutoSave'; import { CommandNames } from '../Common/CommandNames'; import { userConfig } from '../Editor/UserConfig'; import { ViewDirType } from '../Common/SystemEnum'; +import { LayoutTool } from '../Editor/LayoutTool'; + export let app: ApplicationService; /** @@ -51,6 +53,7 @@ export class ApplicationService WebSocket: WebSocketClientServer = new WebSocketClientServer("ws://localhost:9002/loadmesh"); SyncDataReactor: SyncDataReactor; AutoSaveServer: AutoSaveServer; + LayoutTool: LayoutTool; constructor() { app = this; @@ -63,6 +66,7 @@ export class ApplicationService this.Viewer = new Viewer(container); this.Viewer.RenderDatabase(this.Database); + function Root(o: Object3D): Object3D { while (o.parent) @@ -277,6 +281,7 @@ export class ApplicationService FontLoader.GetLoader("songti").LoadGlyphs("1234567890."); this.MoveTool = new BoardMoveTool(); + this.LayoutTool = new LayoutTool(); } InitViewDir() @@ -301,11 +306,15 @@ export class ApplicationService //创建一张新图纸. CreateDocument(name: string = "新文件") { + this.Viewer.ViewPorts.length = 0; + (DownPanelStore.GetInstance() as DownPanelStore).isLayout = false; this.InitViewDir(); this.Viewer.CameraCtrl.ViewHeight = 1000; this.Viewer.CameraCtrl.Update(); this.Database.FileRead(new Database(true).FileWrite()); + + app.LayoutTool.CacheCamera(); } FileOut(): CADFiler @@ -334,6 +343,7 @@ export class ApplicationService OpenFile(f: CADFiler) { + this.Viewer.ViewPorts.length = 0; f.Reset(); this.Database.FileRead(f); let viewData = f.Read(); @@ -341,5 +351,8 @@ export class ApplicationService this.Viewer.CameraCtrl.ReadFile(new CADFiler(viewData)); else this.Viewer.ZoomAll(); + + app.LayoutTool.CacheCamera(); + app.LayoutTool.Switch(); } } diff --git a/src/Common/ColorPalette.ts b/src/Common/ColorPalette.ts index 0c197b413..467de94fd 100644 --- a/src/Common/ColorPalette.ts +++ b/src/Common/ColorPalette.ts @@ -267,6 +267,7 @@ const ColorPalette = [ [0, 0, 0, 0] //----- ByLayer - White ]; +export const LINE_WIDTH = 2; //颜色材质,对于二维图像来说可能有用,应该不对三维对象使用该材质 export class ColorMaterial @@ -315,6 +316,24 @@ export class ColorMaterial this._ConceptualMaterial.set(color, mtl); return mtl; } + private static _printConceptualMaterial: ShaderMaterial; + static GetPrintConceptualMaterial() + { + if (!this._printConceptualMaterial) + { + this._printConceptualMaterial = new ShaderMaterial({ + uniforms: { + "SurfaceColor": { value: [1.0, 1.0, 1.0] } + }, + vertexShader: require("../GLSL/GoodchSimple.vs"), + fragmentShader: require("../GLSL/GoodchSimple2.fs"), + polygonOffset: true, + polygonOffsetFactor: 1, + polygonOffsetUnits: LINE_WIDTH + }); + } + return this._printConceptualMaterial; + } private static _BasicTransparentMaterialMap: Map = new Map(); static GetBasicMaterialTransparent(color: number, opacity: number) @@ -361,7 +380,7 @@ export class ColorMaterial static PrintLineMatrial = new LineMaterial({ color: 0x000000, - linewidth: 2 / 1000, + linewidth: LINE_WIDTH / 1000, dashed: false }); static GrayTransparentMeshMaterial = new MeshBasicMaterial({ @@ -369,4 +388,12 @@ export class ColorMaterial transparent: true, opacity: 0.3, }); + static TransparentMeshMaterial = new MeshBasicMaterial({ + transparent: true, + opacity: 0, + }); + static TransparentLineMaterial = new MeshBasicMaterial({ + transparent: true, + opacity: 0, + }); } diff --git a/src/Common/CommandNames.ts b/src/Common/CommandNames.ts index 6af370a54..5b8df708b 100644 --- a/src/Common/CommandNames.ts +++ b/src/Common/CommandNames.ts @@ -113,6 +113,7 @@ export enum CommandNames Conceptual = "CONCEPTUAL", Physical = "PHYSICAL", Physical2 = "PHYSICAL2", + PrintType = "PRINTTYPE", DownloadHoleOption = "DOWNHOLECONFIG", UploadHoleConfig = "UPLOADHOLECONFIG", ChaiDan = "CHAIDAN", @@ -169,4 +170,8 @@ export enum CommandNames CheckHoles = "CHECKHOLES", CombinatAttributeBrush = "COMBINATATTRIBUTEBRUSH",//复合实体刷 Rect2Winerack = "RECT2WINERACK",//复合实体刷 + MView = "MVIEW",//添加视口 + MView4 = "MVIEW4",//添加视口 + ShowFrame = "SHOWFRAME",//添加视口 + UnGroup = "UNGROUP",//添加视口 } diff --git a/src/Common/Request.ts b/src/Common/Request.ts index 3d7c327db..2e009151f 100644 --- a/src/Common/Request.ts +++ b/src/Common/Request.ts @@ -15,6 +15,7 @@ export enum DirectoryId TemplateDir = "5", //材质根目录 DrillingDir = "6", //排钻目录 KnifePathDir = "7", //刀路目录 + Frame = "8", //图框目录 } export enum RequestStatus diff --git a/src/Common/SerializeMaterial.ts b/src/Common/SerializeMaterial.ts index 620e21d7c..531d514ad 100644 --- a/src/Common/SerializeMaterial.ts +++ b/src/Common/SerializeMaterial.ts @@ -197,7 +197,7 @@ export function ExtrudeDrillFileIn(data: any[]) return en; } -export async function GetEntitysLogo(ens: Entity[], isConceptual = false) +export async function GetEntitysLogo(ens: Entity[], isConceptual = false, dir = new Vector3(1, 1, -1)) { //备份视图 let sceneBak = app.Viewer.Scene; @@ -217,7 +217,7 @@ export async function GetEntitysLogo(ens: Entity[], isConceptual = false) //设置视图 app.Viewer.Scene = new Scene(); app.Viewer._AAType = AAType.SMAA; - app.Viewer.CameraCtrl.LookAt(new Vector3(1, 1, -1)); + app.Viewer.CameraCtrl.LookAt(dir); //绘制 for (let e of ens) @@ -246,3 +246,28 @@ export async function GetEntitysLogo(ens: Entity[], isConceptual = false) return logo; } + +export function GroupOut(ens: Entity[]) +{ + + let file = new CADFiler(); + file.Write(ens.length); + for (let e of ens) + { + file.WriteObject(e); + } + return JSON.stringify(file.Data); +} + +export function GroupFileIn(fileData: Object[]): Entity[] +{ + let f = new CADFiler(fileData); + let count = f.Read(); + let ens: Entity[] = []; + for (let i = 0; i < count; i++) + { + let en = f.ReadObject() as Entity; + ens.push(en); + } + return ens; +} diff --git a/src/Common/TempVar.ts b/src/Common/TempVar.ts new file mode 100644 index 000000000..376734de4 --- /dev/null +++ b/src/Common/TempVar.ts @@ -0,0 +1,3 @@ +import { CADFiler } from "../DatabaseServices/CADFiler"; + +export const TempCADFiler = new CADFiler(); diff --git a/src/DatabaseServices/3DSolid/ExtrudeHole.ts b/src/DatabaseServices/3DSolid/ExtrudeHole.ts index 72a0167a1..72ea04a60 100644 --- a/src/DatabaseServices/3DSolid/ExtrudeHole.ts +++ b/src/DatabaseServices/3DSolid/ExtrudeHole.ts @@ -345,7 +345,7 @@ export class ExtrudeHole extends Hole } else if (renderType === RenderType.Print) { - let mat2 = ColorMaterial.GetBasicMaterial(7).clone(); + let mat2 = ColorMaterial.GetPrintConceptualMaterial(); let meshGeo = this.MeshGeometry.clone(); let mesh = new Mesh(meshGeo, mat2); var geometry = new CLineGeometry().FromCSG(Geometry2CSG(this.MeshGeometry)); diff --git a/src/DatabaseServices/3DSolid/SweepSolid.ts b/src/DatabaseServices/3DSolid/SweepSolid.ts index 72864a0eb..c240f1219 100644 --- a/src/DatabaseServices/3DSolid/SweepSolid.ts +++ b/src/DatabaseServices/3DSolid/SweepSolid.ts @@ -180,8 +180,8 @@ export class SweepSolid extends Entity return new Mesh(this.MeshGeometry, this.MeshMaterial); else if (renderType === RenderType.Print) { - let mat2 = ColorMaterial.GetBasicMaterial(7).clone(); - let meshGeo = this.MeshGeometry.clone(); + let mat2 = ColorMaterial.GetPrintConceptualMaterial(); + let meshGeo = this.MeshGeometry; let mesh = new Mesh(meshGeo, mat2); let line = new Line2(this._lineGeo, ColorMaterial.PrintLineMatrial); return new Object3D().add(line, mesh); diff --git a/src/DatabaseServices/Database.ts b/src/DatabaseServices/Database.ts index f3e2e8833..b5410cb7e 100644 --- a/src/DatabaseServices/Database.ts +++ b/src/DatabaseServices/Database.ts @@ -24,6 +24,7 @@ import { TemplateTable } from './Template/TemplateTable'; import { TextureTableRecord } from './Texture'; import { TextureTable } from './TextureTable'; import { WblockCloneFiler } from './WblockCloneFiler'; +import { ViewportEntity } from './ViewportEntity'; interface OwnerContainer { @@ -43,6 +44,7 @@ export class Database ProcessingGroupTable: ProcessingGroupTable; ModelSpace: BlockTableRecord; + LayoutSpace: BlockTableRecord; Lights: BlockTableRecord; AmbientLight: AmbientLight; @@ -63,6 +65,8 @@ export class Database this.Lights = new BlockTableRecord().SetOwnerDatabase(this); this.ProcessingGroupTable = new ProcessingGroupTable().SetOwnerDatabase(this); + this.LayoutSpace = new BlockTableRecord().SetOwnerDatabase(this); + this.hm = new HistoricManage().SetDefaultDb(this); this.hm.Enable = false; @@ -123,6 +127,7 @@ export class Database { this.idMap.clear(); this.ModelSpace.Destroy(); + this.LayoutSpace.Destroy(); this.MaterialTable.Destroy(); this.TextureTable.Destroy(); this.TemplateTable.Destroy(); @@ -134,6 +139,7 @@ export class Database this.idIndex = 1; this.ModelSpace.SetOwnerDatabase(this); + this.LayoutSpace.SetOwnerDatabase(this); this.MaterialTable.SetOwnerDatabase(this); this.TextureTable.SetOwnerDatabase(this); this.TemplateTable.SetOwnerDatabase(this); @@ -149,7 +155,7 @@ export class Database FileWrite(): CADFiler { let file = new CADFiler(); - file.Write(5);//ver; + file.Write(6);//ver; file.Write(this.idIndex); this.ModelSpace.WriteFile(file); this.TextureTable.WriteFile(file); @@ -160,6 +166,8 @@ export class Database this.Lights.WriteFile(file); this.ProcessingGroupTable.WriteFile(file); + this.LayoutSpace.WriteFile(file); + return file; } FileRead(file: CADFiler) @@ -196,6 +204,9 @@ export class Database if (ver > 4) this.ProcessingGroupTable.ReadFile(file); + if (ver > 5) + this.LayoutSpace.ReadFile(file); + this.SettingDefaultMaterial(); this.hm.doing = false; diff --git a/src/DatabaseServices/Entity/CompositeEntity.ts b/src/DatabaseServices/Entity/CompositeEntity.ts index 3d4f29fd8..80d1919d1 100644 --- a/src/DatabaseServices/Entity/CompositeEntity.ts +++ b/src/DatabaseServices/Entity/CompositeEntity.ts @@ -10,6 +10,7 @@ import { CADFiler } from "../CADFiler"; import { DragPointType } from "./DragPointType"; import { Entity } from "./Entity"; import { ExtrudeSolid } from "./Extrude"; +import { UpdateDraw } from "../../Common/Status"; @Factory @@ -36,6 +37,17 @@ export class CompositeEntity extends Entity return cloneE.ApplyMatrix(this.OCS); }); } + Traverse(callback: (arg0: Entity) => void) + { + callback(this); + for (let en of this.Entitys) + { + if (en instanceof CompositeEntity) + en.Traverse(callback); + else + callback(en); + } + } get BoundingBox() { let box = new Box3Ext(); @@ -64,6 +76,24 @@ export class CompositeEntity extends Entity obj.add(o); } } + get ColorIndex(): number + { + return super._Color; + } + set ColorIndex(color: number) + { + if (color !== this._Color) + { + this.WriteAllObjectRecord(); + this.Traverse(e => + { + if (e instanceof CompositeEntity) + e._Color = color; + else + e.ColorIndex = color; + }); + } + } get Material() { return super.Material; @@ -201,7 +231,27 @@ export class CompositeEntity extends Entity } this.__UpdateVersion__++; } + CloneDrawObject(from: this) + { + for (let [type, obj] of from._CacheDrawObject) + { + let oldUserDaata = obj.userData; + obj.userData = {}; + let newObj = obj.clone(false); + obj.userData = oldUserDaata; + obj.userData.IsClone = true; + newObj.matrix = this._Matrix; + newObj.userData = { Entity: this }; + newObj.userData.IsClone = true; + + for (let e of this.Entitys) + newObj.add(e.DrawObject); + + this._CacheDrawObject.set(type, newObj); + } + this.NeedUpdateFlag = UpdateDraw.None; + } //#endregion //#region 文件序列化 diff --git a/src/DatabaseServices/Entity/Entity.ts b/src/DatabaseServices/Entity/Entity.ts index 0801b10e0..721dcb5ad 100644 --- a/src/DatabaseServices/Entity/Entity.ts +++ b/src/DatabaseServices/Entity/Entity.ts @@ -40,6 +40,7 @@ export class Entity extends CADObject //模块空间的标系 protected _SpaceOCS: Matrix4 = new Matrix4(); + __CacheRenderType__: RenderType; get SpaceOCS() { return this._SpaceOCS.clone(); @@ -248,7 +249,7 @@ export class Entity extends CADObject this._drawObject.userData.Entity = this; if (this.IsVisible) { - let obj = this.GetDrawObjectFromRenderType(userConfig.RenderType); + let obj = this.GetDrawObjectFromRenderType(this.__CacheRenderType__ ?? userConfig.RenderType); if (obj) this._drawObject.add(obj); } else @@ -288,7 +289,7 @@ export class Entity extends CADObject { if (renderType === RenderType.Jig) return; - renderType = RenderType.Wireframe; + renderType = this.__CacheRenderType__ ?? userConfig.RenderType; } if (this._CacheDrawObject.has(renderType)) @@ -448,7 +449,7 @@ export class Entity extends CADObject { this._drawObject.visible = this.IsVisible; if (this.IsVisible) - this.UpdateRenderType(userConfig.RenderType); + this.UpdateRenderType(this.__CacheRenderType__ ?? userConfig.RenderType); } } diff --git a/src/DatabaseServices/Entity/Extrude.ts b/src/DatabaseServices/Entity/Extrude.ts index 99fbc3a19..239454d91 100644 --- a/src/DatabaseServices/Entity/Extrude.ts +++ b/src/DatabaseServices/Entity/Extrude.ts @@ -1389,7 +1389,13 @@ export class ExtrudeSolid extends Entity //#endregion //#region Draw - + GetPrintObject3D() + { + let geometry = new CLineGeometry().FromCSG(this.CSG); + let line = new Line2(geometry, ColorMaterial.PrintLineMatrial); + let mesh = new Mesh(this.MeshGeometry, ColorMaterial.GetPrintConceptualMaterial()); + return [line, mesh]; + } InitDrawObject(renderType: RenderType = RenderType.Wireframe) { if (renderType === RenderType.Wireframe) @@ -1417,18 +1423,7 @@ export class ExtrudeSolid extends Entity } else if (renderType === RenderType.Print) { - var geometry = new CLineGeometry().FromCSG(this.CSG); - let line = new Line2(geometry, ColorMaterial.PrintLineMatrial); - let mat2 = ColorMaterial.GetBasicMaterial(7).clone(); - let meshGeo = this.MeshGeometry.clone(); - const n1 = 4 / this.width; - const n2 = 4 / this.height; - const n3 = 2 / this.thickness; - meshGeo.translate(this.width * n1 / 2, this.height * n2 / 2, n3 / 2 * this.thickness); - meshGeo.scale(1 - n1, 1 - n2, 1 - n3); - let mesh = new Mesh(meshGeo, mat2); - - return new Object3D().add(line, mesh); + return new Object3D().add(...this.GetPrintObject3D()); } else if (renderType === RenderType.Physical2) { @@ -1747,6 +1742,9 @@ export class ExtrudeSolid extends Entity } else if (renderType === RenderType.Print) { + return obj.add( + ...this.GetPrintObject3D() + ); } else if (renderType === RenderType.Physical2) { diff --git a/src/DatabaseServices/Text/Text.ts b/src/DatabaseServices/Text/Text.ts index f2fb15cdf..1488c9010 100644 --- a/src/DatabaseServices/Text/Text.ts +++ b/src/DatabaseServices/Text/Text.ts @@ -102,15 +102,19 @@ export class Text extends Entity this.UpdateTranslate(); this.AsyncUpdated(); } + /**大概宽度 */ + get Width() + { + let alllen = (this.TextString.length + (this.TextString.match('/[\u4e00-\u9fa5]/g')?.length ?? 0)) / 2; + return alllen * this._Height; + } get BoundingBox() { if (!this.box) if (this._TextString) { let box: Box3; - //一个汉字宽一个this.Height 一个数字/字母宽半个Height(大概) - let alllen = (this.TextString.length + (this.TextString.match('/[\u4e00-\u9fa5]/g')?.length ?? 0)) / 2; - box = new Box3(new Vector3(), new Vector3((alllen * this._Height), this._Height)); + box = new Box3(new Vector3(), new Vector3(this.Width, this.Height)); this.box = box.applyMatrix4(this.OCS); } return this.box; @@ -175,12 +179,18 @@ export class Text extends Entity } GetGripPoints(): Array { - return [this.Position]; + return [this.Position, new Vector3(0, this.Height).applyMatrix4(this.OCS)]; } MoveGripPoints(indexList: number[], vec: Vector3) { - if (indexList.length === 1) + + if (indexList[0] === 0) this.Position = this.Position.add(vec); + else + { + let v = vec.clone().applyMatrix4(this.OCSInv.setPosition(new Vector3)); + this.Height = this.Height + v.y; + } } GetStretchPoints(): Array diff --git a/src/DatabaseServices/Text/TextArea.ts b/src/DatabaseServices/Text/TextArea.ts index 4997c7663..105cc6fce 100644 --- a/src/DatabaseServices/Text/TextArea.ts +++ b/src/DatabaseServices/Text/TextArea.ts @@ -188,7 +188,7 @@ export class TextArea extends Singleton let text = new Text(new Vector3(), el.innerText, f.FontName, this.m_TextHeight, this.m_TextRotation); text.ApplyMatrix(app.Editor.UCSMatrix.setPosition(pos)); - app.Database.ModelSpace.Append(text); + app.LayoutTool.AppendDatabaseSpace(text); if (el.parentElement) this.m_AreaContiner.removeChild(el); el = null; diff --git a/src/DatabaseServices/ViewportEntity.ts b/src/DatabaseServices/ViewportEntity.ts new file mode 100644 index 000000000..39586844c --- /dev/null +++ b/src/DatabaseServices/ViewportEntity.ts @@ -0,0 +1,295 @@ +import { Scene, Vector3, Line, Object3D, BufferGeometry, Color, Box3, AmbientLight, Mesh, Group, Matrix3, Curve } from "three"; +import { CameraUpdate } from "../GraphicsSystem/CameraUpdate"; +import { Entity } from "./Entity/Entity"; +import { RenderType } from "../GraphicsSystem/RenderType"; +import { BufferGeometryUtils } from "../Geometry/BufferGeometryUtils"; +import { ColorMaterial } from "../Common/ColorPalette"; +import { Factory } from "./CADFactory"; +import { updateGeometry, GetBox } from "../Geometry/GeUtils"; +import { UpdateDraw } from "../Common/Status"; +import { ObjectId } from "./ObjectId"; +import { CADFiler } from "./CADFiler"; +import { FixIndex } from "../Nest/Common/Util"; +import { AutoRecord } from "./AutoRecord"; +import { ObjectSnapMode } from "../Editor/ObjectSnapMode"; +import { Hole } from "./3DSolid/Hole"; +import { GetEntity } from "../Common/Utils"; +import { CompositeEntity } from "./Entity/CompositeEntity"; +import { DisposeThreeObj } from "../Common/Dispose"; +import { VisualSpaceBox } from "../Editor/VisualSpaceBox"; +import { Board } from "./Entity/Board"; + +@Factory +export class ViewportEntity extends Entity +{ + scene: Scene = new Scene(); + readonly camera: CameraUpdate = new CameraUpdate(); + private _renderType: RenderType = RenderType.Print; + @AutoRecord hideObjectIds = new Set(); + ViewData = { + left: 0, + bottom: 0, + }; + _Color = 256; + constructor( + private _width: number = 1, + private _height: number = 1, + ) + { + super(); + this.scene.background = new Color(0xffffff); + } + get Left() + { + return this.Position.x; + } + get Bottom() + { + return this.Position.y; + } + get Width() + { + return this._width; + } + set Width(v: number) + { + if (v === this._height || v < 0) + return; + this.WriteAllObjectRecord(); + this._width = v; + this.Update(UpdateDraw.Geometry); + } + get ViewWidth() + { + return this.camera.Width; + } + get ViewHeight() + { + return this.camera.Height; + } + get Height() + { + return this._height; + } + set Height(v: number) + { + if (v === this._height || v < 0) + return; + this.WriteAllObjectRecord(); + this._height = v; + this.Update(UpdateDraw.Geometry); + } + GetObjectSnapPoints( + snapMode: ObjectSnapMode, + pickPoint: Vector3, + lastPoint: Vector3, + viewXform: Matrix3 + ): Vector3[] + { + switch (snapMode) + { + case ObjectSnapMode.End: + return this.GetGripPoints(); + case ObjectSnapMode.Mid: + case ObjectSnapMode.Nea: + case ObjectSnapMode.Ext: + case ObjectSnapMode.Per: + default: + break; + } + return []; + } + protected OnlyRenderType = true; + get Entitys() + { + let ens: Entity[] = []; + for (let obj of this.scene.children) + { + let e = GetEntity(obj); + if (e?.TempData?.Entity) + ens.push(e); + } + return ens; + } + get Points() + { + return [ + new Vector3(), + new Vector3(this._width), + new Vector3(this._width, this._height), + new Vector3(0, this._height), + ]; + } + InitDrawObject(type: RenderType) + { + let pts = this.Points; + let geo = BufferGeometryUtils.CreateFromPts([...pts, pts[0]]); + this.camera.SetSize(this._width, this._height); + let o = new Group(); + let l = new Line(geo, ColorMaterial.GetLineMaterial(this._Color)); + o.add(l); + let geo2 = BufferGeometryUtils.CreateFromPts([0, 1, 2, 2, 3, 0].map(i => pts[i])); + let mesh = new Mesh(geo2, ColorMaterial.TransparentMeshMaterial); + o.add(mesh); + return o; + } + + UpdateDrawObject(type: RenderType, obj: Object3D) + { + let pts = this.Points; + let line = (obj.children[0] as Line); + let geo = line.geometry as BufferGeometry; + if (!BufferGeometryUtils.UpdatePts(geo, [...pts, pts[0]])) + { + updateGeometry(line, BufferGeometryUtils.CreateFromPts([...pts, pts[0]])); + } + let mesh = obj.children[1] as Mesh; + let geo2 = mesh.geometry as BufferGeometry; + if (!BufferGeometryUtils.UpdatePts(geo2, [0, 1, 2, 2, 3, 0].map(i => pts[i]))) + { + updateGeometry(line, BufferGeometryUtils.CreateFromPts([0, 1, 2, 2, 3, 0].map(i => pts[i]))); + } + this.scene.updateMatrixWorld(); + } + UpdateByPts(p1: Vector3, p2: Vector3) + { + let left = Math.min(p1.x, p2.x); + let bottom = Math.min(p1.y, p2.y); + this._width = Math.abs(p1.x - p2.x); + this._height = Math.abs(p1.y - p2.y); + this.Position = new Vector3(left, bottom); + } + GetGripPoints() + { + return this.Points.map(p => p.applyMatrix4(this.OCS)); + } + MoveGripPoints(indexList: number[], moveVec: Vector3) + { + this.WriteAllObjectRecord(); + + let pts = this.GetGripPoints(); + + for (let index of indexList) + { + pts[index].add(moveVec); + this.UpdateByPts(pts[index], pts[FixIndex(index + 2, 4)]); + } + this.Update(UpdateDraw.Geometry); + } + ZoomAll() + { + let box = GetBox(this.scene, true); + if (box.isEmpty()) + box.set(new Vector3(), new Vector3(1000 * (this.Width / this.Height), 1000, 1000)); + this.camera.ZoomExtensBox3(box); + this.camera.Zoom(1.5); + } + get RenderType() + { + return this._renderType; + } + set RenderType(v: RenderType) + { + if (v === this._renderType) return; + this.WriteAllObjectRecord(); + this._renderType = v; + this.Entitys.forEach(e => + { + e.__CacheRenderType__ = v; + e.UpdateRenderType(v); + }); + } + get BoundingBox() + { + return new Box3().setFromPoints(this.GetGripPoints()); + } + AppendEntity(en: Entity) + { + if (en.Id + && en.Visible + && !this.hideObjectIds.has(en.Id) + && !en.IsErase && !(en instanceof Hole) + && !(en instanceof ViewportEntity) + && !(en instanceof VisualSpaceBox)) + { + let ens: Entity[]; + if (en instanceof Board) + { + ens = en.SplitBoards; + } + else + ens = [en]; + + for (let e of ens) + { + let originEn = e; + if (originEn instanceof Board && originEn.__OriginalEnt__) + originEn = originEn.__OriginalEnt__; + + let o = this.scene.getObjectByName(e.Id.Index.toString()); + if (o) + { + o.visible = true; + return; + } + + let cloneEN = e["__OriginalEnt__"] ? e : e.Clone(); + + cloneEN.TempData = { Entity: originEn }; + if (cloneEN instanceof CompositeEntity) + { + cloneEN.Traverse((e) => + { + if (e.ColorIndex === 7) + e.ColorIndex = 256; + }); + } + else + if (e.ColorIndex === 7) + cloneEN.ColorIndex = 256; + cloneEN.UpdateRenderType(this._renderType); + let cloneObject = cloneEN.DrawObject; + cloneObject.name = originEn.Id.Index.toString(); + this.scene.add(cloneObject); + } + } + } + RemoveEntity(en: Entity) + { + for (let o of this.scene.children) + { + if (o.name === en.Id.Index.toString()) + o.visible = false; + } + } + GoodBye() + { + super.GoodBye(); + DisposeThreeObj(this.scene); + this.scene.dispose(); + } + protected _ReadFile(file: CADFiler) + { + super._ReadFile(file); + let ver = file.Read(); + this.camera.ReadFile(file); + this.Width = file.Read(); + this.Height = file.Read(); + this._renderType = file.Read(); + let count = file.Read(); + this.hideObjectIds.clear(); + for (let i = 0; i < count; i++) + this.hideObjectIds.add(file.ReadSoftObjectId()); + } + WriteFile(file: CADFiler) + { + super.WriteFile(file); + file.Write(1); + this.camera.WriteFile(file); + file.Write(this.Width); + file.Write(this.Height); + file.Write(this._renderType); + file.Write(this.hideObjectIds.size); + this.hideObjectIds.forEach(id => file.WriteSoftObjectId(id)); + } +} diff --git a/src/Editor/AutoSave.ts b/src/Editor/AutoSave.ts index eb709a722..a35c97e67 100644 --- a/src/Editor/AutoSave.ts +++ b/src/Editor/AutoSave.ts @@ -7,6 +7,7 @@ import { StoreageKeys } from "../Common/StoreageKeys"; import { TopPanelStore } from "../UI/Store/TopPanelStore"; import { userConfig } from "./UserConfig"; import { FileServer } from "../DatabaseServices/FileServer"; +import { TempEditor } from "./TempEditor"; export class AutoSaveServer { @@ -28,7 +29,7 @@ export class AutoSaveServer const topStore = TopPanelStore.GetInstance() as TopPanelStore; this.timeId = setInterval(async () => { - if (app.Saved || !topStore.editoring || this.isCached) return; + if (app.Saved || !topStore.editoring || this.isCached || TempEditor.EditorIng) return; let f = app.Database.FileWrite(); if (false) diff --git a/src/Editor/BoardMoveTool.ts b/src/Editor/BoardMoveTool.ts index 990b601a3..afbe85347 100644 --- a/src/Editor/BoardMoveTool.ts +++ b/src/Editor/BoardMoveTool.ts @@ -24,6 +24,7 @@ export class BoardMoveTool let selectCtrl = app.Editor.SelectCtrl; end(selectCtrl, selectCtrl.UpdateSelectEvent, async () => { + if (app.Viewer.isLayout) return; if (!CommandState.CommandIng) { let set = selectCtrl.SelectSet; diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index 37253473a..e5a4bf75e 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -133,7 +133,7 @@ import { Command_ShowProcessingGroupModal2 } from "../Add-on/ShowProcessingGroup import { Stretch } from "../Add-on/Stretch"; import { Sweep } from "../Add-on/Sweep"; import { Command_SwitchCamera } from "../Add-on/SwitchCamera"; -import { CMD_Conceptual, CMD_Physical, CMD_Physical2, CMD_Wireframe } from "../Add-on/SwitchVisualStyles"; +import { ChangeRenderType } from "../Add-on/SwitchVisualStyles"; import { Command_DisableSyncData, Command_EnableSyncData, Command_ToggleSyncData } from "../Add-on/SyncData"; import { DrawTangentLine } from "../Add-on/Tangent"; import { BoardReplaceTempate } from "../Add-on/Template/BoardReplaceTemplate"; @@ -188,6 +188,9 @@ import { ChangeColorByMaterial } from "../Add-on/ChangeColorByBoardMaterial"; import { CheckHoles } from "../Add-on/CheckHoles"; import { CombinatAttributeBrush } from "../Add-on/CombinatAttributeBrush"; import { Polyline2Winerack } from "../Add-on/DrawWineRack/Polyline2Winerack"; +import { DrawViewport, Draw4Viewport } from "../Add-on/DrawViewport"; +import { RenderType } from "../GraphicsSystem/RenderType"; +import { ShowFrmae } from "../Add-on/Template/ShowFrame"; export function registerCommand() { @@ -202,8 +205,8 @@ export function registerCommand() commandMachine.RegisterCommand(CommandNames.KJLExport, new KjlExport()); commandMachine.RegisterCommand("clearkjltoken", new ClearKjlToken()); - commandMachine.RegisterCommand("group", new Command_Group()); - commandMachine.RegisterCommand("ungroup", new Command_UnGroup()); + commandMachine.RegisterCommand(CommandNames.Group, new Command_Group()); + commandMachine.RegisterCommand(CommandNames.UnGroup, new Command_UnGroup()); commandMachine.RegisterCommand("dxf", new Command_DXFImport()); @@ -421,10 +424,11 @@ export function registerCommand() // commandMachine.RegisterCommand("rt", new RevTarget()) //视觉样式 - commandMachine.RegisterCommand(CommandNames.Wireframe, new CMD_Wireframe()); - commandMachine.RegisterCommand(CommandNames.Conceptual, new CMD_Conceptual()); - commandMachine.RegisterCommand(CommandNames.Physical, new CMD_Physical()); - commandMachine.RegisterCommand(CommandNames.Physical2, new CMD_Physical2()); + commandMachine.RegisterCommand(CommandNames.Wireframe, new ChangeRenderType(RenderType.Wireframe)); + commandMachine.RegisterCommand(CommandNames.Conceptual, new ChangeRenderType(RenderType.Conceptual)); + commandMachine.RegisterCommand(CommandNames.Physical, new ChangeRenderType(RenderType.Physical)); + commandMachine.RegisterCommand(CommandNames.Physical2, new ChangeRenderType(RenderType.Physical2)); + commandMachine.RegisterCommand(CommandNames.PrintType, new ChangeRenderType(RenderType.Print)); //导入导出配置 commandMachine.RegisterCommand("downloadconfig", new DownLoadDConfig()); @@ -526,6 +530,10 @@ export function registerCommand() commandMachine.RegisterCommand(CommandNames.CombinatAttributeBrush, new CombinatAttributeBrush()); commandMachine.RegisterCommand(CommandNames.Rect2Winerack, new Polyline2Winerack()); + + commandMachine.RegisterCommand(CommandNames.MView, new DrawViewport()); + commandMachine.RegisterCommand(CommandNames.MView4, new Draw4Viewport()); + commandMachine.RegisterCommand(CommandNames.ShowFrame, new ShowFrmae()); } export async function RegistCustomCommand() diff --git a/src/Editor/DbClick/DbClick.ts b/src/Editor/DbClick/DbClick.ts index 839f94c80..265cc1abc 100644 --- a/src/Editor/DbClick/DbClick.ts +++ b/src/Editor/DbClick/DbClick.ts @@ -28,15 +28,41 @@ import { VisualSpaceBox } from "../VisualSpaceBox"; import { DBClickPolyline } from "./DBClickPolyline"; import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole"; import { ExtrudeHoleModal } from "../../UI/Components/EntityModal/ExtrudeHoleModal"; +import { ViewportEntity } from "../../DatabaseServices/ViewportEntity"; +import { AppToaster } from "../../UI/Components/Toaster"; +import { Intent } from "@blueprintjs/core"; export class DbClickManager extends Singleton { OnDbClick = async () => { - let pickObj = PointPickOneObject(app.Editor.MouseCtrl._CurMousePointVCS, app.Viewer, { filterErase: true }); + let pt = app.Editor.MouseCtrl._CurMousePointVCS.clone(); + let iViewer = app.Viewer.GetIViewer([pt]); + + let pickObj = PointPickOneObject(pt, iViewer, { filterErase: true }); let pickEnt = GetEntity(pickObj); if (!pickEnt) - return; + { + if (app.Viewer.CurrentViewport) + { + let oldVP = app.Viewer.CurrentViewport; + app.Viewer.CurrentViewport = null; + pickObj = PointPickOneObject(app.Editor.MouseCtrl._CurMousePointVCS, app.Viewer, { filterErase: true }); + pickEnt = GetEntity(pickObj); + if (pickEnt === oldVP) + { + app.Viewer.CurrentViewport = oldVP; + return; + } + if (!pickEnt) + { + AppToaster.clear(); + return; + } + } + else + return; + } let enStore = EntityStore.GetInstance() as EntityStore; @@ -187,6 +213,23 @@ export class DbClickManager extends Singleton { app.Editor.ModalManage.RenderModeless(ExtrudeHoleModal, { entity: pickEnt }, { position: ModalPosition.Mouse }); } + else if (pickEnt instanceof ViewportEntity) + { + AppToaster.clear(); + app.Viewer.CurrentViewport = pickEnt; + pickEnt.scene.add(app.Viewer.GripScene); + AppToaster.show({ + message: "正在操作视口,关闭退出", + timeout: 0, + intent: Intent.SUCCESS, + onDismiss: () => + { + app.Viewer.CurrentViewport = null; + app.Viewer.GripScene.Clear(); + app.Viewer.Scene.add(app.Viewer.GripScene); + } + }, "vp"); + } else { enStore.AddEntitysToMap([pickEnt]); diff --git a/src/Editor/LayoutTool.ts b/src/Editor/LayoutTool.ts new file mode 100644 index 000000000..62925cddc --- /dev/null +++ b/src/Editor/LayoutTool.ts @@ -0,0 +1,292 @@ +import { TempCADFiler } from "../Common/TempVar"; +import { Vector3 } from "three"; +import { AppToaster } from "../UI/Components/Toaster"; +import { app } from "../ApplicationServices/Application"; +import { Entity } from "../DatabaseServices/Entity/Entity"; +import { end } from "xaop"; +import { CommandHistoryRecord } from "../DatabaseServices/CommandHistoryRecord"; +import { CommandNames } from "../Common/CommandNames"; +import { ViewportEntity } from "../DatabaseServices/ViewportEntity"; +import { arrayRemoveIf } from "../Common/ArrayExt"; +import { Hole } from "../DatabaseServices/3DSolid/Hole"; +import { CreateObjectData } from "../DatabaseServices/CreateObjectData"; +import { RemoveObjectData } from "../DatabaseServices/RemoveObjectData"; + + +const Hide_Cmds = new Set([ + CommandNames.Erase, CommandNames.HideSelect, CommandNames.HideUnSelect, CommandNames.HideDoor +]); + +const Show_cmds = new Set([ + CommandNames.Show, CommandNames.ShowDoor +]); + + +export class LayoutTool +{ + private colorBak: number; + constructor() + { + //监听模块树的变更,当变更时,刷新视图 + end(app.Database.hm, app.Database.hm.RedoEvent, (cmdName: CommandNames, historyRec: CommandHistoryRecord) => + { + let createEntitys: Entity[] = []; + let changeEntitys: Entity[] = []; + let deleteEntitys: Entity[] = []; + + for (let [h, hs] of historyRec.HistoryList) + { + if (h.Object === app.Database.ModelSpace.EntityCol) + { + for (let h of hs) + { + if (h.redoData instanceof RemoveObjectData) + deleteEntitys.push(h.redoData.RemoveObject as Entity); + else if (h.redoData instanceof CreateObjectData) + createEntitys.push(h.redoData.CreateObject as Entity); + } + } + if (!(h.Object instanceof Entity)) + continue; + + let e = h.Object; + + for (let h of hs) + { + if (h.redoData instanceof CreateObjectData) + { + createEntitys.push(e); + break; + } + else + { + if (e.IsErase) + deleteEntitys.push(e); + else + changeEntitys.push(e); + } + } + } + + if (Hide_Cmds.has(cmdName)) + { + this.HideViewportEntitys(changeEntitys); + } + else if (Show_cmds.has(cmdName)) + { + this.ShowViewportEntitys(changeEntitys); + } + else + { + this.ShowViewportEntitys(createEntitys); + this.HideViewportEntitys(deleteEntitys); + this.ChangeViewportEntitys(changeEntitys); + } + + }); + end(app.Database.hm, app.Database.hm.UndoEvent, (cmdName: CommandNames, historyRec: CommandHistoryRecord) => + { + + let createEntitys: Entity[] = []; + let changeEntitys: Entity[] = []; + let deleteEntitys: Entity[] = []; + + for (let [h, hs] of historyRec.HistoryList) + { + if (h.Object === app.Database.ModelSpace.EntityCol) + { + for (let h of hs) + { + if (h.undoData instanceof RemoveObjectData) + deleteEntitys.push(h.undoData.RemoveObject as Entity); + else if (h.undoData instanceof CreateObjectData) + createEntitys.push(h.undoData.CreateObject as Entity); + } + } + if (!(h.Object instanceof Entity)) + continue; + + let e = h.Object; + + for (let h of hs) + { + if (h.undoData instanceof CreateObjectData) + { + createEntitys.push(e); + break; + } + else + { + if (e.IsErase) + deleteEntitys.push(e); + else + changeEntitys.push(e); + } + } + } + + if (Hide_Cmds.has(cmdName)) + { + this.ShowViewportEntitys(changeEntitys); + } + else if (Show_cmds.has(cmdName)) + { + this.HideViewportEntitys(changeEntitys); + } + else + { + this.ShowViewportEntitys(createEntitys); + this.HideViewportEntitys(deleteEntitys); + this.ChangeViewportEntitys(changeEntitys); + } + }); + app.CommandReactor.OnCommandEnd((cmdName: CommandNames, changeObjects, createObjects) => + { + if (app.Viewer.isLayout) return; + + this.ShowViewportEntitys(createObjects.filter(e => e instanceof Entity) as Entity[]); + + let ens = changeObjects.filter(e => e instanceof Entity) as Entity[]; + + if (Hide_Cmds.has(cmdName)) + { + this.HideViewportEntitys(ens); + } + else if (Show_cmds.has(cmdName)) + { + this.ShowViewportEntitys(ens); + } + else + { + this.ChangeViewportEntitys(ens); + } + }); + } + CacheCamera() + { + TempCADFiler.Data = []; + app.Viewer.CameraCtrl.WriteFile(TempCADFiler); + } + Switch() + { + AppToaster.dismiss("vp"); + app.Viewer.OutlinePass.selectedObjects = []; + app.Editor.SelectCtrl.Cancel(); + const isLayout = app.Viewer.isLayout; + app.Viewer.SwitchLayout(); + + if (isLayout) + { + if (this.colorBak === undefined) + this.colorBak = app.Viewer.Renderer.getClearColor().getHex(); + app.Viewer.Renderer.setClearColor(0xcccccc, 1); + this.CacheCamera(); + app.Editor.SetUCSLookAt(new Vector3(0, 0, -1)); + app.Viewer.ViewToTop(); + app.Viewer.ZoomAll(); + } + else + { + app.Viewer.Renderer.setClearColor(this.colorBak); + app.Viewer.CameraCtrl.ReadFile(TempCADFiler); + app.Viewer.UpdateRender(); + AppToaster.clear(); + } + } + get CurrentSpace() + { + if (app.Viewer.isLayout) + { + return app.Database.LayoutSpace; + } + else + { + return app.Database.ModelSpace; + } + } + AppendDatabaseSpace(en: Entity, changeColor = true) + { + if (app.Viewer.isLayout) + { + app.Database.LayoutSpace.Append(en); + if (changeColor && en.ColorIndex === 7) + en.ColorIndex = 256; + } + else + { + app.Database.ModelSpace.Append(en); + } + } + RemoveDatabaseSpace(en: Entity) + { + if (app.Viewer.isLayout) + { + app.Database.LayoutSpace.Remove(en); + } + else + { + app.Database.ModelSpace.Remove(en); + } + } + ShowViewportEntitys(ens?: Entity[]) + { + let v = app.Viewer.CurrentViewport; + + let vps = v ? [v] : app.Viewer.ViewPorts; + + for (let vp of vps) + { + if (ens) + { + for (let en of ens) + { + if (en instanceof Hole) continue; + vp.hideObjectIds.delete(en.Id); + vp.AppendEntity(en); + } + } + else + { + for (let id of vp.hideObjectIds) + { + let en = id.Object as Entity; + vp.hideObjectIds.delete(id); + vp.AppendEntity(en); + } + } + } + } + HideViewportEntitys(selects: Entity[]) + { + let vp = app.Viewer.CurrentViewport; + + let vps = vp ? [vp] : app.Viewer.ViewPorts; + + for (let en of selects) + { + if (en instanceof ViewportEntity) continue; + + for (let vp of vps) + { + let e = en.Id ? en : en.TempData?.Entity; + if (!vp.hideObjectIds.has(e.Id)) + { + vp.hideObjectIds.add(e.Id); + vp.RemoveEntity(e); + } + } + } + } + ChangeViewportEntitys(ens: Entity[]) + { + for (let vp of app.Viewer.ViewPorts) + { + for (let en of ens) + { + if (en instanceof Hole) continue; + arrayRemoveIf(vp.scene.children, o => o.name === en.Id.Index.toString()); + vp.AppendEntity(en); + } + } + } +} diff --git a/src/Editor/SelectControls.ts b/src/Editor/SelectControls.ts index 360330775..5a13cba47 100644 --- a/src/Editor/SelectControls.ts +++ b/src/Editor/SelectControls.ts @@ -1,11 +1,11 @@ -import { Curve, Matrix4, Vector3 } from 'three'; +import { Curve, Matrix4, Vector3, MathUtils } from 'three'; import { end } from 'xaop'; import { app } from '../ApplicationServices/Application'; import { InputState } from '../Common/InputState'; import { KeyBoard, KeyCode, MouseKey } from '../Common/KeyEnum'; import { GetEntity } from '../Common/Utils'; import { Entity } from '../DatabaseServices/Entity/Entity'; -import { GetBox } from '../Geometry/GeUtils'; +import { GetBox, IsBetweenA2B } from '../Geometry/GeUtils'; import { CursorMode } from '../GraphicsSystem/Cursor'; import { Viewer } from '../GraphicsSystem/Viewer'; import { SelectMarquee } from '../UI/JsPlugin/SelectMarquee'; @@ -17,6 +17,7 @@ import { Filter } from './SelectFilter'; import { SelectPick } from './SelectPick'; import { SelectSet } from './SelectSet'; import { TransMode } from './TranstrolControl/TransformServices'; +import { IViewer } from '../GraphicsSystem/IView'; export class SelectControls implements EditorService { @@ -131,16 +132,30 @@ export class SelectControls implements EditorService LeftClick(checkPick = true) { let pt = this._Editor.MouseCtrl._CurMousePointVCS; + + const vp = app.Viewer.CurrentViewport; + + if (vp) + { + if (!IsBetweenA2B(pt.x, vp.ViewData.left, vp.ViewData.left + vp.ViewWidth)) + return; + if (!IsBetweenA2B(pt.y, vp.ViewData.bottom, vp.ViewData.bottom + vp.ViewHeight)) + return; + } + let isRemove = app.Editor.KeyCtrl.KeyIsDown(KeyCode.ShiftLeft); //如果还没选择 那么 if ((this._Editor.InputState & InputState.SelectIng) === InputState.None) { if (checkPick) { - let selectObj = PointPickOneObject(pt, this._Viewer, this.Filter); + let clonePt = pt.clone(); + let iViewer = this._Viewer.GetIViewer([clonePt]); + + let selectObj = PointPickOneObject(clonePt, iViewer, this.Filter); if (selectObj) { - let selectData = new SelectPick(this._Viewer, pt.clone()); + let selectData = new SelectPick(this._Viewer, clonePt.clone()); selectData._SelectList.add(selectObj); if (isRemove) this.RemoveSelect(selectData); @@ -178,7 +193,8 @@ export class SelectControls implements EditorService SelectByCss() { - let selectBox = new SelectBox(this._Viewer, this._SelectCss.start, this._SelectCss.end); + let iViewer: IViewer = this._Viewer.GetIViewer([this._SelectCss.start, this._SelectCss.end]); + let selectBox = new SelectBox(iViewer, this._SelectCss.start, this._SelectCss.end); if (this._SelectType !== SelectType.None) selectBox._SelectType = this._SelectType; else @@ -192,7 +208,16 @@ export class SelectControls implements EditorService if (this._Editor.InputState === InputState.SelectIng) { let pt = this._Editor.MouseCtrl._CurMousePointVCS; - this._SelectCss.SetEnd(pt.x, pt.y); + let x = pt.x; + let y = pt.y; + let vp = app.Viewer.CurrentViewport; + if (vp) + { + x = MathUtils.clamp(x, vp.ViewData.left, vp.ViewData.left + vp.ViewWidth); + y = MathUtils.clamp(y, vp.ViewData.bottom, vp.ViewData.bottom + vp.ViewHeight); + } + + this._SelectCss.SetEnd(x, y); } } diff --git a/src/GLSL/GoodchSimple2.fs b/src/GLSL/GoodchSimple2.fs new file mode 100644 index 000000000..83b5d768e --- /dev/null +++ b/src/GLSL/GoodchSimple2.fs @@ -0,0 +1,7 @@ + +uniform vec3 SurfaceColor; + +void main(void) +{ + gl_FragColor = vec4 (SurfaceColor, 1.0); +} diff --git a/src/Geometry/GeUtils.ts b/src/Geometry/GeUtils.ts index 2eb538fbe..70d993124 100644 --- a/src/Geometry/GeUtils.ts +++ b/src/Geometry/GeUtils.ts @@ -398,3 +398,8 @@ export function SelectNearP(pts: Vector3[], refPt: Vector3): Vector3 } return pts[0]; } + +export function IsBetweenA2B(n: number, A: number, B: number) +{ + return n >= A && n <= B; +} diff --git a/src/GraphicsSystem/CameraUpdate.ts b/src/GraphicsSystem/CameraUpdate.ts index 290d87f97..b5a03d745 100644 --- a/src/GraphicsSystem/CameraUpdate.ts +++ b/src/GraphicsSystem/CameraUpdate.ts @@ -87,6 +87,14 @@ export class CameraUpdate this._Width = width; this._Height = height; } + get Width() + { + return this._Width; + } + get Height() + { + return this._Height; + } /** * 平移相机. diff --git a/src/GraphicsSystem/Cursor.ts b/src/GraphicsSystem/Cursor.ts index ff18d59c9..4663f937a 100644 --- a/src/GraphicsSystem/Cursor.ts +++ b/src/GraphicsSystem/Cursor.ts @@ -211,4 +211,8 @@ export class Cursor )); } } + set Color(n: number) + { + [this._SquareObject, this._CrossLineObject, this._OutsideCrossLineObject].forEach(o => o.material = ColorMaterial.GetLineMaterial(n)); + } } diff --git a/src/GraphicsSystem/Viewer.ts b/src/GraphicsSystem/Viewer.ts index 57f8f5571..a0f63e3c6 100644 --- a/src/GraphicsSystem/Viewer.ts +++ b/src/GraphicsSystem/Viewer.ts @@ -1,4 +1,4 @@ -import { Box3, Matrix4, Object3D, Scene, Vector3, WebGLRenderer } from 'three'; +import { Box3, Matrix4, Object3D, Scene, Vector3, WebGLRenderer, Vector2, AmbientLight } from 'three'; import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer"; import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass"; import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass"; @@ -21,6 +21,8 @@ import { GripScene } from './GripScene'; import { OutlinePass } from './OutlinePass'; import { PreViewer } from './PreViewer'; import { RenderType } from './RenderType'; +import { ViewportEntity } from '../DatabaseServices/ViewportEntity'; +import { IViewer } from './IView'; export class Viewer { @@ -51,6 +53,10 @@ export class Viewer private _Width: number; private _Height: number; private needUpdateEnts = new Set(); + isLayout = false; + ViewPorts: ViewportEntity[] = []; + LayoutScene = new Scene(); + CurrentViewport: ViewportEntity; //构造 constructor(canvasContainer: HTMLElement) @@ -102,19 +108,29 @@ export class Viewer get Scene() { - return this._Scene; + if (this.CurrentViewport) + return this.CurrentViewport.scene; + + if (this.isLayout) + return this.LayoutScene; + else + return this._Scene; } set Scene(s: Scene) { - this._Scene = s; + if (this.isLayout) + this.LayoutScene = s; + else + this._Scene = s; + this.RenderPass.scene = s; this.OutlinePass.renderScene = s; } get Camera() { - return this.CameraCtrl.Camera; + return this.Control.Camera; } get Width() { @@ -124,7 +140,6 @@ export class Viewer { return this._Height; } - set AAType(type: AAType) { if (type !== this._AAType) @@ -217,7 +232,7 @@ export class Viewer StartRender = () => { requestAnimationFrame(this.StartRender); - if (this._Scene && this.NeedUpdate) + if (this.Scene && this.NeedUpdate) { this.Render(); this.NeedUpdate = false; @@ -236,6 +251,48 @@ export class Viewer this.needUpdateEnts.clear(); + if (this.isLayout) + { + this.Renderer.clear(); + for (let viewport of this.ViewPorts) + { + if (viewport.IsErase || !viewport.Visible) continue; + let p1 = new Vector3(viewport.Left, viewport.Bottom + viewport.Height); + this.WorldToScreen(p1); + + let p2 = new Vector3(viewport.Left + viewport.Width, viewport.Bottom); + this.WorldToScreen(p2); + + let width = Math.abs(p2.x - p1.x); + let height = Math.abs(p2.y - p1.y); + + if (width <= 0 || height <= 0) + continue; + + viewport.camera.SetSize(width, height); + viewport.camera.Update(); + + let bottom = this.Height - p2.y; + + viewport.ViewData.left = p1.x; + viewport.ViewData.bottom = p1.y; + + let scale = 2; + this.Renderer.setViewport(p1.x, bottom, width, height); + this.Renderer.setScissor(p1.x + scale / 2, bottom + scale / 2, width - scale, height - scale); + this.Renderer.setScissorTest(true); + this.Renderer.render(viewport.scene, viewport.camera.Camera); + } + + this.Renderer.setClearColor(this.Renderer.getClearColor(), 1); + this.Renderer.setViewport(0, 0, this.Width, this.Height); + this.Renderer.setScissor(0, 0, this.Width, this.Height); + if (this.UsePass) + this.Composer.setSize(this.Width, this.Height); + this.Renderer.render(this.LayoutScene, this.CameraCtrl.Camera); + return; + } + if (this.UsePass) this.Composer.render(); else @@ -257,8 +314,8 @@ export class Viewer if (!planNormal) planNormal = new Vector3().setFromMatrixColumn(app.Editor.UCSMatrix, 2); - if (isPerpendicularityTo(this.CameraCtrl.Direction, planNormal)) - planNormal = this.CameraCtrl.Direction; + if (isPerpendicularityTo(this.Control.Direction, planNormal)) + planNormal = this.Control.Direction; //变换和求交点 let plan = new PlaneExt(planNormal, constant); @@ -320,6 +377,7 @@ export class Viewer IsLookSelect = false; StartLookSelect() { + if (this.isLayout) return; if (this.OutlinePass.selectedObjects.length > 0 && userConfig.RenderType !== RenderType.Physical) { this.UsePass = false; @@ -335,25 +393,38 @@ export class Viewer this.UpdateRender(); } } - + /**当前相机控制 */ + get Control() + { + if (this.CurrentViewport) + return this.CurrentViewport.camera; + return this.CameraCtrl; + } Rotate(mouseMove: Vector3) { - this.CameraCtrl.Rotate(mouseMove, this.LookTarget); + if (this.isLayout && !this.CurrentViewport) return; + this.Control.Rotate(mouseMove, this.LookTarget); this.UpdateRender(); } Pan(mouseMove: Vector3) { - this.CameraCtrl.Pan(mouseMove); + this.Control.Pan(mouseMove); this.UpdateRender(); } Zoom(scale: number, center?: Vector3) { - this.CameraCtrl.Zoom(scale, center); + this.Control.Zoom(scale, center); this.UpdateRender(); } ZoomAll(UpdateRender = true) { - let box = GetBox(this._Scene, true); + if (this.CurrentViewport) + { + this.CurrentViewport.ZoomAll(); + this.UpdateRender(); + return; + } + let box = GetBox(this.Scene, true); if (box.isEmpty()) box.set(new Vector3(), new Vector3(1000 * (this.Width / this.Height), 1000, 1000)); this.CameraCtrl.ZoomExtensBox3(box); @@ -397,7 +468,7 @@ export class Viewer if (renderObjects.length > 0) return renderObjects; - let renderList = this.Renderer.renderLists.get(this._Scene, this.CameraCtrl.Camera); + let renderList = this.Renderer.renderLists.get(this.Scene, this.Camera); return [...renderList.transparent.map(o => o.object), ...renderList.opaque.map(o => o.object)]; } @@ -439,6 +510,10 @@ export class Viewer i = 0; } } + + for (let en of db.LayoutSpace.Entitys) + this.AddViewport(en); + down.progress = 1; //灯光 for (let l of db.Lights.Entitys) @@ -463,6 +538,9 @@ export class Viewer //灯光 for (let l of db.Lights.Entitys) this._Scene.add(l.DrawObject); + //布局 + for (let en of db.LayoutSpace.Entitys) + this.AddViewport(en); begin(db.ModelSpace, db.ModelSpace.AppendEvent, (e: Entity) => { @@ -512,5 +590,75 @@ export class Viewer renderEntitys(); this.GripScene.Clear(); }); + + begin(db.LayoutSpace, db.LayoutSpace.AppendEvent, (en: Entity) => + { + this.AddViewport(en, true); + }); + begin(db.LayoutSpace, db.LayoutSpace.Destroy, () => + { + for (let en of db.LayoutSpace.Entitys) + en.GoodBye(); + }); + } + SwitchLayout() + { + this.Renderer.autoClear = !this.isLayout; + if (this.isLayout) + { + this.PreViewer.Cursor.Color = 256; + this.RenderPass.scene = this.LayoutScene; + this.OutlinePass.renderScene = this.LayoutScene; + this.LayoutScene.add(this.GripScene); + } + else + { + this.PreViewer.Cursor.Color = 7; + this.RenderPass.scene = this._Scene; + this.OutlinePass.renderScene = this._Scene; + this._Scene.add(this.GripScene); + this.Renderer.setScissorTest(false); + } + } + AddViewport(en: Entity, isZoom = false) + { + if (en instanceof ViewportEntity && en.Id && !en.IsErase && en.Db) + { + en.scene.add(new AmbientLight(0xffffff, 3)); + + en.Db.ModelSpace.Entitys.forEach(e => + { + en.AppendEntity(e); + }); + this.LayoutScene.add(en.DrawObject); + if (isZoom) + en.ZoomAll(); + this.ViewPorts.push(en); + } + else + this.LayoutScene.add(en.DrawObject); + } + ViewportPoint(pt: Vector3 | Vector2, viewport: ViewportEntity) + { + let p1 = new Vector3(viewport.Left, viewport.Bottom + viewport.Height); + this.WorldToScreen(p1); + pt.x -= p1.x; + pt.y -= p1.y; + } + GetIViewer(pts: (Vector3 | Vector2)[]) + { + let iViewer: IViewer = { + Camera: this.Camera, + Width: this.Width, + Height: this.Height, + Scene: this.Scene, + }; + if (this.CurrentViewport) + { + pts.forEach(p => this.ViewportPoint(p, this.CurrentViewport)); + iViewer.Width = this.CurrentViewport.ViewWidth; + iViewer.Height = this.CurrentViewport.ViewHeight; + } + return iViewer; } } diff --git a/src/Reactor/CommandReactor.ts b/src/Reactor/CommandReactor.ts index 06b22de67..ef073c8c6 100644 --- a/src/Reactor/CommandReactor.ts +++ b/src/Reactor/CommandReactor.ts @@ -28,6 +28,12 @@ export class CommandReactor this._createObejcts.push(e); }); + begin(app.Database.LayoutSpace, app.Database.LayoutSpace.AppendEvent, (e: Entity) => + { + if (CommandState.CommandIng && this._commandEndListeners.length > 0) + this._createObejcts.push(e); + }); + begin(commandMachine, commandMachine.CommandEndEvent, (hasRecord: boolean) => { if (this._commandEndListeners.length === 0) diff --git a/src/UI/Components/CameraControlButton/CameraControlBtn.tsx b/src/UI/Components/CameraControlButton/CameraControlBtn.tsx index 8a61ae1d3..51604fd8e 100644 --- a/src/UI/Components/CameraControlButton/CameraControlBtn.tsx +++ b/src/UI/Components/CameraControlButton/CameraControlBtn.tsx @@ -185,10 +185,19 @@ export class CameraControlBtn extends React.Component<{ store: CameraControlBtnS style={btnStyle} key={data.title} text={`[${data.title}]`} - onClick={() => userConfig.RenderType = data.type} + onClick={() => commandMachine.ExecCommand(data.cmd)} /> ) } + { + (DownPanelStore.GetInstance() as DownPanelStore).isLayout && +