diff --git a/src/Add-on/DrawViewport.ts b/src/Add-on/DrawViewport.ts index 4917e1c90..6ffaa0fe7 100644 --- a/src/Add-on/DrawViewport.ts +++ b/src/Add-on/DrawViewport.ts @@ -14,6 +14,7 @@ import { Board } from "../DatabaseServices/Entity/Board"; import { BoardOpenDir } from "../UI/Store/BoardInterface"; import { HardwareCompositeEntity } from "../DatabaseServices/Hardware/HardwareCompositeEntity"; import { Hole } from "../DatabaseServices/3DSolid/Hole"; +import { RenderType } from "../GraphicsSystem/RenderType"; async function GetViewportInfo() @@ -149,28 +150,8 @@ export class Draw4Viewport implements Command } } -export function Get4Viewport(p1: Vector3, p2: Vector3, ens: Entity[], isHideDoor = false) +function GetEntityIds(ens: Entity[]) { - 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); - let ids: ObjectId[] = []; let noDoorIds: ObjectId[] = []; let doorIds: ObjectId[] = []; @@ -202,6 +183,32 @@ export function Get4Viewport(p1: Vector3, p2: Vector3, ens: Entity[], isHideDoor noDoorIds.push(en.Id); } } + return { ids, doorIds, noDoorIds }; +} + +export function Get4Viewport(p1: Vector3, p2: Vector3, ens: Entity[], isHideDoor = false) +{ + 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); + + let { ids, doorIds, noDoorIds } = GetEntityIds(ens); vp1.AppendShowObjects(ids); vp2.AppendShowObjects(ids); @@ -384,3 +391,30 @@ export class Draw3Viewport implements Command AppToaster.dismiss('layout'); } } + + +export interface ICustomViewportInfo +{ + renderType: RenderType, + dir: Vector3; + width: number; + height: number; + position: Vector3; +} + +export function DrawCustomViewports(infos: ICustomViewportInfo[], ens: Entity[]) +{ + let { ids } = GetEntityIds(ens); + + let vps: ViewportEntity[] = []; + for (let info of infos) + { + let vp = new ViewportEntity(info.width, info.height); + vp.camera.LookAt(info.dir); + vp.Position = info.position; + vp.RenderType = info.renderType; + vp.AppendShowObjects(ids); + vps.push(vp); + } + return vps; +} diff --git a/src/Add-on/Viewport/OneKeyLayout.ts b/src/Add-on/Viewport/OneKeyLayout.ts index 1bc2e29c8..8e8422431 100644 --- a/src/Add-on/Viewport/OneKeyLayout.ts +++ b/src/Add-on/Viewport/OneKeyLayout.ts @@ -12,8 +12,8 @@ import { ToplineUrls } from "../../Common/HostUrl"; import { AppToaster } from "../../UI/Components/Toaster"; import { Intent } from "@blueprintjs/core"; import { inflate, GroupFileIn } from "../../Common/SerializeMaterial"; -import { Box3, Vector3 } from "three"; -import { Get4Viewport } from "../DrawViewport"; +import { Box3, Object3D, Vector3 } from "three"; +import { DrawCustomViewports, Get4Viewport, ICustomViewportInfo } from "../DrawViewport"; import { ViewportEntity } from "../../DatabaseServices/ViewportEntity"; import { GroupRecord } from "../../DatabaseServices/GroupTableRecord"; import { Log } from "../../Common/Log"; @@ -21,9 +21,17 @@ import { Sleep } from "../../Common/Sleep"; import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension"; import { PromptStatus } from "../../Editor/PromptResult"; import { DownPanelStore } from "../../UI/Store/DownPanelStore"; +import { SelectBox, SelectType } from "../../Editor/SelectBox"; +import { AsVector2 } from "../../Geometry/GeUtils"; +import { Polyline } from "../../DatabaseServices/Entity/Polyline"; +import { IRectInfo, IsRect } from "../../Common/CurveUtils"; +import { Text } from "../../DatabaseServices/Text/Text"; +import { RenderType } from "../../GraphicsSystem/RenderType"; +import { EBoardKeyList } from "../../Common/BoardKeyList"; export class OneKeyLayout implements Command { + private _cacheRect = new WeakSet(); async exec() { if (!app.Viewer.isLayout) @@ -32,23 +40,39 @@ export class OneKeyLayout implements Command return; } - let curves: Entity[]; + let curves: Entity[] = []; let frameWidth: number; let p1: Vector3; let p2: Vector3; + let basePt = new Vector3(); + let originObjects: Object3D[] = []; + let specialTexts = new Set(); + let texts: Text[] = []; const handleEntitys = (ens: Entity[]) => { let box = new Box3(); - ens.reduce((b, e) => + for (let en of ens) { - return b.union(e.BoundingBox); - }, box); + if (en instanceof Polyline) + originObjects.push(en.DrawObject); + let cloneC = en.Clone(); + cloneC.TempData = en; + if (cloneC instanceof Text) + { + if (cloneC.TextString.startsWith("@")) + texts.push(en as Text); + if (cloneC.TextString.startsWith("$")) + specialTexts.add(cloneC); + } + else + box.union(en.BoundingBox); + curves.push(cloneC); + } - curves = ens; - let basePt = box.min; + basePt.copy(box.min); frameWidth = box.getSize(new Vector3).x; - ens.forEach(e => e.Position = e.Position.sub(basePt)); + curves.forEach(e => e.Position = e.Position.sub(basePt)); if (p1) { p1.sub(basePt); @@ -68,8 +92,9 @@ export class OneKeyLayout implements Command }); if (gRes.Status === PromptStatus.OK) { - let ens = (gRes.Entity.GroupId.Object as GroupRecord).Entitys.map(i => i.Object.Clone()) as Entity[]; - handleEntitys(ens); + let originEns = (gRes.Entity.GroupId.Object as GroupRecord).Entitys.map(i => i.Object) as Entity[]; + + handleEntitys(originEns); break; } else if (gRes.Status > PromptStatus.None) @@ -198,6 +223,16 @@ export class OneKeyLayout implements Command vpsHeight = Math.abs(p1.y - p2.y); } + let selectP1 = new Vector3(left + vpsWidth + 1, bottom - 1).add(basePt); + let selectP2 = new Vector3(left - 1, bottom + vpsHeight + 1).add(basePt); + app.Viewer.WorldToScreen(selectP1); + app.Viewer.WorldToScreen(selectP2); + + let selectBox = new SelectBox(app.Viewer, AsVector2(selectP2), AsVector2(selectP1), SelectType.W); + selectBox.Select(originObjects, { filterErase: false }); + let selectEns = selectBox.SelectEntityList; + let vpInfos: ICustomViewportInfo[] = this.GetVpInfos([...selectEns, ...texts], basePt); + const Total_Length = frameWidth + DIST; let vps: ViewportEntity[] = []; @@ -213,14 +248,39 @@ export class OneKeyLayout implements Command let i = 0; for (let [, bs] of boxBoardMap) { - let x = left + i * Total_Length; - vps.push(...Get4Viewport(new Vector3(x, bottom), new Vector3(x + vpsWidth, bottom + vpsHeight), bs, true)); + if (vpInfos.length > 0) + { + const newInfos: ICustomViewportInfo[] = []; + for (let info of vpInfos) + { + let newInfo = { ...info }; + newInfo.position = info.position.clone(); + newInfo.position.x += i * Total_Length; + newInfos.push(newInfo); + } + + vps.push(...DrawCustomViewports(newInfos, bs)); + } + else + { + let x = left + i * Total_Length; + vps.push(...Get4Viewport(new Vector3(x, bottom), new Vector3(x + vpsWidth, bottom + vpsHeight), bs, true)); + } let g = new GroupRecord(); g.Name = "图框"; app.Database.GroupTable.Add(g); + + let board = bs.find(b => b instanceof Board) as Board; for (let c of curves) { + if (this._cacheRect.has(c.TempData)) continue; let cloneC = c.Clone(); + if (specialTexts.has(c)) + { + this.HandleTextMetaData(cloneC as Text, board); + if (!(cloneC).TextString) + continue; + } app.LayoutTool.AppendDatabaseSpace(cloneC); g.Entitys.push(cloneC.Id); cloneC.Position = cloneC.Position.add(new Vector3(i * Total_Length)); @@ -242,4 +302,158 @@ export class OneKeyLayout implements Command AppToaster.dismiss('onekey'); Entity.__ReadFileIng__ = false; } + private GetVpInfos = (selectEns: Entity[], basePt: Vector3) => + { + let vpInfos: ICustomViewportInfo[] = []; + let vpRects: IRectInfo[] = []; + let renderTypeTexts: Text[] = []; + let dirTexts: Text[] = []; + + const GetRenderType = (txt: string) => + { + switch (txt) + { + case "线框": + case "二维线框": + case "二维": + return RenderType.Wireframe; + case "概念": + return RenderType.Conceptual; + case "真实": + return RenderType.Physical; + case "真实带线框": + return RenderType.Physical2; + default: + return RenderType.Print; + } + }; + + const GetDir = (txt: string) => + { + switch (txt) + { + case "左": + case "左视": + return new Vector3(1); + case "右": + case "右视": + return new Vector3(-1); + case "俯": + case "俯视": + return new Vector3(0, 0, -1); + case "仰": + case "仰视": + return new Vector3(0, 0, 1); + case "前": + case "前视": + return new Vector3(0, 1); + case "后": + case "后视": + return new Vector3(0, -1); + case "西南": + case "西南等轴侧": + case "西南等轴测": + return new Vector3(1, 1, -1); + default: + return new Vector3(0, 0, -1); + } + }; + + for (let en of selectEns) + { + if (en instanceof Polyline) + { + let res = IsRect(en); + if (res.isRect && res.size.x > 50 && res.size.y > 50) + { + this._cacheRect.add(en); + vpRects.push(res); + } + } + else if (en instanceof Text) + { + if (en.TextString.startsWith("@@")) + { + renderTypeTexts.push(en); + } + else if (en.TextString.startsWith("@")) + { + dirTexts.push(en); + } + } + } + + const useCache = new WeakSet(); + + for (let info of vpRects) + { + let vpInfo: ICustomViewportInfo = { + width: info.size.x, + height: info.size.y, + dir: new Vector3(), + position: info.box.min.clone().sub(basePt), + renderType: RenderType.Print, + }; + + let box = info.box.clone(); + box.max.setZ(0); + box.min.setZ(0); + + for (let text of dirTexts) + { + let pos = text.Position.setZ(0); + if (!useCache.has(text) && box.containsPoint(pos)) + { + vpInfo.dir.copy(GetDir(text.TextString.slice(1))); + useCache.add(text); + this._cacheRect.add(text); + break; + } + } + for (let text of renderTypeTexts) + { + let pos = text.Position.setZ(0); + if (!useCache.has(text) && box.containsPoint(pos)) + { + vpInfo.renderType = GetRenderType(text.TextString.slice(2)); + useCache.add(text); + this._cacheRect.add(text); + break; + } + } + vpInfos.push(vpInfo); + } + return vpInfos; + }; + private HandleTextMetaData(text: Text, en?: Board) + { + let metaData = text.TextString.slice(1); + if (en) + { + const option = en.BoardProcessOption; + + switch (metaData) + { + case "房名": + case "房间名": + text.TextString = option[EBoardKeyList.RoomName]; + break; + case "柜名": + text.TextString = option[EBoardKeyList.CabinetName]; + break; + case "板材名": + text.TextString = option[EBoardKeyList.BrMat]; + break; + case "材料": + text.TextString = option[EBoardKeyList.Mat]; + break; + case "颜色": + text.TextString = option[EBoardKeyList.Color]; + break; + default: + break; + } + } + + } }