UNPKG

@itwin/frontend-devtools

Version:

Debug menu and supporting UI widgets

496 lines • 18.4 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Tools */ import { BeDuration } from "@itwin/core-bentley"; import { ColorDef, Hilite } from "@itwin/core-common"; import { DrawingViewState, FlashMode, FlashSettings, IModelApp, TileBoundingBoxes, Tool, } from "@itwin/core-frontend"; import { parseArgs } from "./parseArgs"; import { parseToggle } from "./parseToggle"; /** Base class for a tool that toggles some aspect of a Viewport. * @beta */ export class ViewportToggleTool extends Tool { static get minArgs() { return 0; } static get maxArgs() { return 1; } async run(enable) { const vp = IModelApp.viewManager.selectedView; if (undefined !== vp) await this.toggle(vp, enable); return true; } async parseAndRun(...args) { const enable = parseToggle(args[0]); if (typeof enable !== "string") await this.run(enable); return true; } } /** Freeze or unfreeze the scene for the selected viewport. While the scene is frozen, no new tiles will be selected for drawing within the viewport. * @beta */ export class FreezeSceneTool extends ViewportToggleTool { static toolId = "FreezeScene"; async toggle(vp, enable) { if (undefined === enable || enable !== vp.freezeScene) vp.freezeScene = !vp.freezeScene; return Promise.resolve(); } } const boundingVolumeNames = [ "none", "volume", "content", "both", "children", "sphere", "solid", ]; /** Set the tile bounding volume decorations to display in the selected viewport. * Omitting the argument turns on Volume bounding boxes if bounding boxes are currently off; otherwise, toggles them off. * Allowed inputs are "none", "volume", "content", "both" (volume and content), "children", and "sphere". * @beta */ export class ShowTileVolumesTool extends Tool { static toolId = "ShowTileVolumes"; static get minArgs() { return 0; } static get maxArgs() { return 1; } async run(boxes) { const vp = IModelApp.viewManager.selectedView; if (undefined === vp) return true; if (undefined === boxes) boxes = TileBoundingBoxes.None === vp.debugBoundingBoxes ? TileBoundingBoxes.Volume : TileBoundingBoxes.None; vp.debugBoundingBoxes = boxes; return true; } async parseAndRun(...args) { let boxes; if (0 !== args.length) { const arg = args[0].toLowerCase(); for (let i = 0; i < boundingVolumeNames.length; i++) { if (arg === boundingVolumeNames[i]) { boxes = i; break; } } if (undefined === boxes) return true; } return this.run(boxes); } } /** Sets or unsets or flips the deactivated state of one or more tile tree references within the selected viewport. * Deactivated tile tree references are omitted from the scene. * This is useful for isolating particular tile trees or tiles for debugging. * @beta */ export class ToggleTileTreeReferencesTool extends Tool { static toolId = "ToggleTileTreeReferences"; static get minArgs() { return 1; } static get maxArgs() { return 3; } _modelIds; _which; _deactivate; async parseAndRun(...args) { const which = args[0].toLowerCase(); switch (which) { case "all": case "animated": case "primary": case "section": this._which = which; break; default: this._which = which.split(",").map((x) => Number.parseInt(x, 10)).filter((x) => !Number.isNaN(x)); } let modelIds = args[2]; let deactivate = parseToggle(args[1]); if (typeof deactivate !== "string") { if (typeof deactivate === "boolean") deactivate = !deactivate; this._deactivate = deactivate; } else { modelIds = args[1]; } if (modelIds) this._modelIds = modelIds.toLowerCase().split(","); return this.run(); } async run() { const vp = IModelApp.viewManager.selectedView; if (!vp || !this._which || !vp.view.isSpatialView()) return false; vp.view.setTileTreeReferencesDeactivated(this._modelIds, this._deactivate, this._which); vp.invalidateScene(); return true; } } /** This tool sets the aspect ratio skew for the selected viewport. * @beta */ export class SetAspectRatioSkewTool extends Tool { static toolId = "SetAspectRatioSkew"; static get minArgs() { return 0; } static get maxArgs() { return 1; } /** This method runs the tool, setting the aspect ratio skew for the selected viewport. * @param skew the aspect ratio (x/y) skew value; 1.0 or undefined removes any skew */ async run(skew) { if (undefined === skew) skew = 1.0; const vp = IModelApp.viewManager.selectedView; if (undefined !== vp) { vp.view.setAspectRatioSkew(skew); vp.synchWithView(); } return true; } /** Executes this tool's run method. * @param args the first entry of this array contains the `skew` argument * @see [[run]] */ async parseAndRun(...args) { const skew = args.length > 0 ? parseFloat(args[0]) : 1.0; return !Number.isNaN(skew) && this.run(skew); } } /** Changes the [ModelSubCategoryHiliteMode]($frontend) for the [HiliteSet]($frontend) associated with the selected Viewport. * @beta */ export class ChangeHiliteModeTool extends Tool { static get minArgs() { return 1; } static get maxArgs() { return 1; } static toolId = "ChangeHiliteMode"; async run(mode) { const hilites = IModelApp.viewManager.selectedView?.iModel.hilited; if (!hilites) return false; if (mode === "union" || mode === "intersection") hilites.modelSubCategoryMode = mode; return true; } async parseAndRun(...args) { return this.run(args[0]); } } /** Changes the selected viewport's hilite or emphasis settings. * @beta */ export class ChangeHiliteTool extends Tool { static get minArgs() { return 0; } static get maxArgs() { return 6; } async run(settings) { const vp = IModelApp.viewManager.selectedView; if (undefined !== vp) this.apply(vp, settings); return true; } async parseAndRun(...inputArgs) { if (0 === inputArgs.length) return this.run(); const vp = IModelApp.viewManager.selectedView; if (undefined === vp) return true; const cur = this.getCurrentSettings(vp); const colors = cur.color.colors; let visible = cur.visibleRatio; let hidden = cur.hiddenRatio; let silhouette = cur.silhouette; const args = parseArgs(inputArgs); const parseColorComponent = (c) => { const num = args.getInteger(c); if (undefined !== num) colors[c] = Math.floor(Math.max(0, Math.min(255, num))); }; parseColorComponent("r"); parseColorComponent("g"); parseColorComponent("b"); const silhouetteArg = args.getInteger("s"); if (undefined !== silhouetteArg && silhouetteArg >= Hilite.Silhouette.None && silhouetteArg <= Hilite.Silhouette.Thick) silhouette = silhouetteArg; const v = args.getFloat("v"); if (undefined !== v && v >= 0 && v <= 1) visible = v; const h = args.getFloat("h"); if (undefined !== h && h >= 0 && h <= 1) hidden = h; if (undefined === silhouette) silhouette = cur.silhouette; if (undefined === visible) visible = cur.visibleRatio; if (undefined === hidden) hidden = cur.hiddenRatio; const settings = { color: ColorDef.from(colors.r, colors.g, colors.b), silhouette, visibleRatio: visible, hiddenRatio: hidden, }; return this.run(settings); } } /** Changes the selected viewport's hilite settings, or resets to defaults. * @beta */ export class ChangeHiliteSettingsTool extends ChangeHiliteTool { static toolId = "ChangeHiliteSettings"; getCurrentSettings(vp) { return vp.hilite; } apply(vp, settings) { vp.hilite = undefined !== settings ? settings : new Hilite.Settings(); } } /** Changes the selected viewport's emphasis settings. * @beta */ export class ChangeEmphasisSettingsTool extends ChangeHiliteTool { static toolId = "ChangeEmphasisSettings"; getCurrentSettings(vp) { return vp.emphasisSettings; } apply(vp, settings) { if (undefined !== settings) vp.emphasisSettings = settings; } } /** Changes the [FlashSettings]($frontend) for the selected [Viewport]($frontend). * @beta */ export class ChangeFlashSettingsTool extends Tool { static toolId = "ChangeFlashSettings"; static get minArgs() { return 0; } static get maxArgs() { return 3; } async run(settings) { const vp = IModelApp.viewManager.selectedView; if (vp) vp.flashSettings = settings ?? new FlashSettings(); return true; } async parseAndRun(...inputArgs) { const vp = IModelApp.viewManager.selectedView; if (!vp) return true; if (1 === inputArgs.length && "default" === inputArgs[0].toLowerCase()) return this.run(); const options = {}; const args = parseArgs(inputArgs); const intensity = args.getFloat("i"); if (undefined !== intensity) options.maxIntensity = intensity; const mode = args.get("m"); if (mode) { switch (mode[0].toLowerCase()) { case "b": options.litMode = FlashMode.Brighten; break; case "h": options.litMode = FlashMode.Hilite; break; default: return false; } } const duration = args.getFloat("d"); if (undefined !== duration) options.duration = BeDuration.fromSeconds(duration); return this.run(vp.flashSettings.clone(options)); } } /** Enables or disables fade-out transparency mode for the selected viewport. * @beta */ export class FadeOutTool extends ViewportToggleTool { static toolId = "FadeOut"; async toggle(vp, enable) { if (undefined === enable || enable !== vp.isFadeOutActive) vp.isFadeOutActive = !vp.isFadeOutActive; return Promise.resolve(); } } /** Sets the default tile size modifier used for all viewports that don't explicitly override it. * @beta */ export class DefaultTileSizeModifierTool extends Tool { static toolId = "DefaultTileSizeMod"; static get minArgs() { return 1; } static get maxArgs() { return 1; } /** This method runs the tool, setting the default tile size modifier used for all viewports that don't explicitly override it. * @param modifier the tile size modifier to use; if undefined, do not set modifier */ async run(modifier) { if (undefined !== modifier) IModelApp.tileAdmin.defaultTileSizeModifier = modifier; return true; } /** Executes this tool's run method with args[0] containing `modifier`. * @see [[run]] */ async parseAndRun(...args) { return this.run(Number.parseFloat(args[0])); } } /** Sets or clears the tile size modifier override for the selected viewport. * @beta */ export class ViewportTileSizeModifierTool extends Tool { static toolId = "ViewportTileSizeMod"; static get minArgs() { return 1; } static get maxArgs() { return 1; } /** This method runs the tool, setting the tile size modifier used for the selected viewport. * @param modifier the tile size modifier to use; if undefined, reset the modifier */ async run(modifier) { const vp = IModelApp.viewManager.selectedView; if (undefined !== vp) vp.setTileSizeModifier(modifier); return true; } /** Executes this tool's run method with args[0] containing the `modifier` argument or the string "reset" in order to reset the modifier. * @see [[run]] */ async parseAndRun(...args) { const arg = args[0].toLowerCase(); const modifier = "reset" === arg ? undefined : Number.parseFloat(args[0]); return this.run(modifier); } } /** This tool adds a reality model to the viewport. * @beta */ export class ViewportAddRealityModel extends Tool { static toolId = "ViewportAddRealityModel"; static get minArgs() { return 1; } static get maxArgs() { return 1; } /** This method runs the tool, adding a reality model to the viewport * @param url the URL which points to the reality model tileset */ async run(url) { const vp = IModelApp.viewManager.selectedView; if (undefined !== vp) vp.displayStyle.attachRealityModel({ tilesetUrl: url }); return true; } /** Executes this tool's run method with args[0] containing the `url` argument. * @see [[run]] */ async parseAndRun(...args) { return this.run(args[0]); } } /** Changes the `allow3dManipulations` flag for the selected viewport if the viewport is displaying a `ViewState3d`. * @beta */ export class Toggle3dManipulationsTool extends ViewportToggleTool { static toolId = "Toggle3dManipulations"; async toggle(vp, allow) { if (!vp.view.is3d()) return Promise.resolve(); if (undefined === allow) allow = !vp.view.allow3dManipulations(); if (allow !== vp.view.allow3dManipulations()) { vp.view.setAllow3dManipulations(allow); // eslint-disable-next-line @typescript-eslint/no-floating-promises IModelApp.toolAdmin.startDefaultTool(); } return Promise.resolve(); } } /** Toggles display of view attachments in sheet views. * @beta */ export class ToggleViewAttachmentsTool extends ViewportToggleTool { static toolId = "ToggleViewAttachments"; async toggle(vp, enable) { if (undefined === enable || enable !== vp.wantViewAttachments) vp.wantViewAttachments = !vp.wantViewAttachments; return Promise.resolve(); } } /** Toggle display of view attachment boundaries in sheet views. * @beta */ export class ToggleViewAttachmentBoundariesTool extends ViewportToggleTool { static toolId = "ToggleViewAttachmentBoundaries"; async toggle(vp, enable) { if (undefined === enable || enable !== vp.wantViewAttachmentBoundaries) vp.wantViewAttachmentBoundaries = !vp.wantViewAttachmentBoundaries; return Promise.resolve(); } } /** Toggle display of view attachment clip shapes in sheet views. * @beta */ export class ToggleViewAttachmentClipShapesTool extends ViewportToggleTool { static toolId = "ToggleViewAttachmentClipShapes"; async toggle(vp, enable) { if (undefined === enable || enable !== vp.wantViewAttachmentClipShapes) vp.wantViewAttachmentClipShapes = !vp.wantViewAttachmentClipShapes; return Promise.resolve(); } } /** Toggles display of 2d graphics in a [DrawingViewState]($frontend). This setting affects all drawing views until it is reset. * @beta */ export class ToggleDrawingGraphicsTool extends ViewportToggleTool { static toolId = "ToggleDrawingGraphics"; async toggle(vp, enable) { if (undefined === enable || enable !== DrawingViewState.hideDrawingGraphics) { DrawingViewState.hideDrawingGraphics = !DrawingViewState.hideDrawingGraphics; vp.invalidateScene(); } return Promise.resolve(); } } /** Toggles whether a [SectionDrawing]($backend)'s spatial view is always displayed along with the 2d graphics by a [DrawingViewState]($frontend), even * if it otherwise would not be. This setting affects all section drawing views until it is reset. * @beta */ export class ToggleSectionDrawingSpatialViewTool extends ViewportToggleTool { static toolId = "ToggleSectionDrawingSpatialView"; async toggle(vp, enable) { if (undefined === enable || enable !== DrawingViewState.alwaysDisplaySpatialView) { DrawingViewState.alwaysDisplaySpatialView = !DrawingViewState.alwaysDisplaySpatialView; if (vp.view instanceof DrawingViewState) { // Force the view to update its section drawing attachment. const view = vp.view.clone(); await view.changeViewedModel(view.baseModelId); await view.load(); vp.changeView(view); } } } } /** Change the camera settings of the selected viewport. * @beta */ export class ChangeCameraTool extends Tool { static get minArgs() { return 1; } static get maxArgs() { return 2; } static toolId = "ChangeCamera"; async run(camera) { const vp = IModelApp.viewManager.selectedView; if (camera && vp && vp.view.is3d()) { const view = vp.view.clone(); view.camera.setFrom(camera); vp.changeView(view); } return true; } async parseAndRun(...inArgs) { const vp = IModelApp.viewManager.selectedView; if (!vp || !vp.view.is3d()) return false; const camera = vp.view.camera.clone(); const args = parseArgs(inArgs); const lens = args.getFloat("l"); if (undefined !== lens) camera.lens.setDegrees(lens); const focusDist = args.getFloat("d"); if (undefined !== focusDist) camera.focusDist = focusDist; return this.run(camera); } } //# sourceMappingURL=ViewportTools.js.map