UNPKG

@itwin/frontend-devtools

Version:

Debug menu and supporting UI widgets

111 lines 5.03 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 { ColorDef, LinePixels } from "@itwin/core-common"; import { GraphicType, IModelApp, OffScreenViewport, Tool, ViewRect } from "@itwin/core-frontend"; import { parseToggle } from "./parseToggle"; import { Id64, Logger } from "@itwin/core-bentley"; import { Transform, Vector2d } from "@itwin/core-geometry"; class ViewDefinitionDecoration { static _instance; _removeMe; constructor() { this._removeMe = IModelApp.viewManager.addDecorator(this); } stop() { if (this._removeMe) { this._removeMe(); this._removeMe = undefined; } } _viewId; _loading = false; _preloadedFrustum = []; async getFrustumForViewId(iModel, viewId, transform = Transform.createIdentity()) { return iModel.views.load(viewId).then((result) => { // Use the view extents/delta let vector; if (result.is2d()) vector = Vector2d.create(result.delta.x, result.delta.y); else vector = Vector2d.create(result.getExtents().x, result.getExtents().y); // create a viewport to the size of the extents to ensure the aspect is correct. const vp = OffScreenViewport.create({ view: result, viewRect: new ViewRect(0, 0, vector.x, vector.y) }); const frustum = vp.getFrustum(); this._preloadedFrustum.push(frustum.transformBy(transform)); }).catch((err) => { Logger.logException("FrontendDevTools", err); }); } preload(viewport) { this._loading = true; const iModel = viewport.iModel; const view = viewport.view; const viewId = view.id; const loadPromises = []; loadPromises.push(this.getFrustumForViewId(iModel, viewId)); if (view.isDrawingView() && view.sectionDrawingInfo.spatialView) loadPromises.push(this.getFrustumForViewId(iModel, view.sectionDrawingInfo.spatialView, view.sectionDrawingInfo.drawingToSpatialTransform.inverse())); void Promise.all(loadPromises).finally(() => { IModelApp.viewManager.invalidateCachedDecorationsAllViews(this); this._viewId = viewId; this._loading = false; }); } /** This will allow the render system to cache and reuse the decorations created by this decorator's decorate() method. */ useCachedDecorations = true; decorate(context) { if (context.viewport.view.id !== this._viewId && !this._loading) { this._preloadedFrustum.length = 0; // just clear the decoration if the view is not from a view definition if (Id64.isValidId64(context.viewport.view.id)) this.preload(context.viewport); } const builder = context.createGraphicBuilder(GraphicType.WorldDecoration); const purple = ColorDef.fromString("#800080"); // The current view's frustum is at the end of the array. builder.setSymbology(purple, purple, 5, LinePixels.Code0); const endIndex = this._preloadedFrustum.length - 1; const currentFrustum = this._preloadedFrustum[endIndex]; if (currentFrustum) builder.addFrustum(currentFrustum); // Add other frustums. builder.setSymbology(purple, purple, 4, LinePixels.Code2); const remainingFrustums = this._preloadedFrustum.slice(0, endIndex); remainingFrustums.forEach((frustum) => builder.addFrustum(frustum)); context.addDecorationFromBuilder(builder); } static toggle(enabled) { const instance = ViewDefinitionDecoration._instance; if (undefined !== enabled && (undefined !== instance) === enabled) return; if (undefined === instance) { ViewDefinitionDecoration._instance = new ViewDefinitionDecoration(); } else { instance.stop(); ViewDefinitionDecoration._instance = undefined; } } } /** Display in every viewport a green range graphic for each displayed tile tree, plus a red range graphic for each tile tree's content range if defined. * @beta */ export class ViewDefinitionDecorationTool extends Tool { static toolId = "ViewDefinitionDecorationTool"; static get minArgs() { return 0; } static get maxArgs() { return 1; } async run(enable) { ViewDefinitionDecoration.toggle(enable); return true; } async parseAndRun(...args) { const enable = parseToggle(args[0]); if (typeof enable !== "string") await this.run(enable); return true; } } //# sourceMappingURL=ViewDefinitionDecorator.js.map