@itwin/frontend-devtools
Version:
Debug menu and supporting UI widgets
111 lines • 5.03 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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