UNPKG

@itwin/core-frontend

Version:
336 lines • 11.6 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Views */ Object.defineProperty(exports, "__esModule", { value: true }); exports.SheetViewAttachments = void 0; const core_common_1 = require("@itwin/core-common"); const core_bentley_1 = require("@itwin/core-bentley"); const IModelApp_1 = require("../IModelApp"); const ViewAttachmentRenderer_1 = require("./ViewAttachmentRenderer"); const Frustum2d_1 = require("../Frustum2d"); /** Stateless state for a sheet that has no view attachments. */ class EmptyAttachments { // We only need one instance of this stateless class. static _instance; static get() { return this._instance ?? (this._instance = new EmptyAttachments()); } constructor() { } clone() { return this; } preload() { } async postload() { return this; } get attachmentIds() { return []; } } /** Holds the element Ids of the view attachments to be loaded for display. */ class AttachmentIds { _ids; constructor(ids) { this._ids = ids; } get attachmentIds() { return this._ids; } clone() { return new AttachmentIds([...this._ids]); } preload(request) { request.sheetViewAttachmentIds = core_bentley_1.CompressedId64Set.sortAndCompress(this._ids); request.viewStateLoadProps = { displayStyle: { omitScheduleScriptElementIds: !IModelApp_1.IModelApp.tileAdmin.enableFrontendScheduleScripts, compressExcludedElementIds: true, }, }; } async postload(response, iModel) { if (undefined === response.sheetViewViews || undefined === response.sheetViewAttachmentProps) { return this; } const viewStateProps = response.sheetViewViews; const promises = []; for (const viewProps of viewStateProps) { const loadView = async () => { try { if (viewProps === undefined) return undefined; const view = await iModel.views.convertViewStatePropsToViewState(viewProps); return view; } catch { return undefined; } }; promises.push(loadView()); } const views = await Promise.all(promises); const attachmentProps = response.sheetViewAttachmentProps; (0, core_bentley_1.assert)(views.length === attachmentProps.length); const infos = []; for (let i = 0; i < views.length; i++) { const view = views[i]; if (view && !(view.isSheetView())) { const props = attachmentProps[i]; props.attachedView = view; infos.push(props); } } return new AttachmentInfos(infos); } } /** Fully loaded view attachments. */ class AttachmentInfos { infos; constructor(infos) { this.infos = infos; } get attachmentIds() { return this.infos.map((x) => (0, core_bentley_1.expectDefined)(x.id)); } clone(iModel) { const infos = this.infos.map((info) => { return { ...info, attachedView: info.attachedView.clone(iModel), }; }); return new AttachmentInfos(infos); } preload() { // already loaded. } async postload() { // already loaded. return this; } } /** Reloads the attachments after a change to the database. */ async function reloadAttachments(sheetModelId, iModel) { const ecsql = `SELECT ECInstanceId as attachmentId FROM bis.ViewAttachment WHERE model.Id=${sheetModelId}`; const ids = []; for await (const row of iModel.createQueryReader(ecsql)) { ids.push(row[0]); } const attachmentProps = await iModel.elements.getProps(ids); const promises = []; for (const attachment of attachmentProps) { const loadView = async () => { try { const view = await iModel.views.load(attachment.view.id); return view; } catch { return undefined; } }; promises.push(loadView()); } const views = await Promise.all(promises); (0, core_bentley_1.assert)(views.length === attachmentProps.length); const infos = []; for (let i = 0; i < views.length; i++) { const view = views[i]; if (view && !view.isSheetView()) { const props = attachmentProps[i]; props.attachedView = view; infos.push(props); } } return new AttachmentInfos(infos); } function disposeRenderers(renderers) { if (renderers) { for (const renderer of renderers) { renderer[Symbol.dispose](); } } } /** Manages the set of ViewAttachment elements to be rendered by a SheetViewState. * Takes care of reloading them after ViewAttachment elements are modified, deleted, or inserted. */ class SheetViewAttachments { _impl; _reload; _maxDepth = Frustum2d_1.Frustum2d.minimumZDistance; _rendererArgs; _renderers; get maxDepth() { return this._maxDepth; } *getSecondaryViewports() { if (this._renderers) { for (const renderer of this._renderers) { if (renderer.viewport) { yield renderer.viewport; } } } } constructor(impl) { this._impl = impl; } [Symbol.dispose]() { disposeRenderers(this._renderers); this._renderers = this._rendererArgs = undefined; this._reload = undefined; } static create(attachmentIds) { const impl = attachmentIds.length === 0 ? EmptyAttachments.get() : new AttachmentIds([...attachmentIds]); return new this(impl); } get attachmentIds() { return this._impl.attachmentIds; } clone(iModel) { return new SheetViewAttachments(this._impl.clone(iModel)); } preload(request) { this._impl.preload(request); } async postload(response, iModel) { this._impl = await this._impl.postload(response, iModel); } async reload(sheetModelId, iModel) { const renderers = this._renderers; const reload = this._reload = reloadAttachments(sheetModelId, iModel); const impl = await this._reload; // We keep the previous renderers until reloading completes, to avoid drawing a blank view while waiting. // Afterward, always destroy the previous renderers. disposeRenderers(renderers); // If reload was not called again while we waited... if (this._reload === reload) { this._impl = impl; this._reload = this._renderers = undefined; if (this._rendererArgs) { // We are attached to a Viewport - reload the renderers. this.loadRenderers(); } } } attachToViewport(args) { (0, core_bentley_1.assert)(undefined === this._renderers); (0, core_bentley_1.assert)(undefined === this._rendererArgs); this._rendererArgs = args; this.loadRenderers(); } detachFromViewport() { (0, core_bentley_1.assert)(undefined !== this._rendererArgs); this._rendererArgs = undefined; disposeRenderers(this._renderers); this._renderers = undefined; } areAllTileTreesLoaded(displayedExtents) { if (this._reload) { return false; } else if (!this._renderers) { return true; } return this._renderers.every((renderer) => { const attachmentRange = core_common_1.Placement2d.fromJSON(renderer.viewAttachmentProps.placement).calculateRange(); return !attachmentRange.intersectsRangeXY(displayedExtents) || renderer.areAllTileTreesLoaded; }); } discloseTileTrees(trees) { for (const renderer of this.renderers()) { trees.disclose(renderer); } } collectStatistics(stats) { for (const renderer of this.renderers()) { renderer.collectStatistics(stats); } } addToScene(context) { for (const renderer of this.renderers()) { renderer.addToScene(context); } } getAttachmentViewport(args) { const renderer = args.viewAttachmentId ? this.findRendererById(args.viewAttachmentId) : undefined; if (!renderer) { return undefined; } return args.inSectionDrawingAttachment ? renderer.viewport?.view.getAttachmentViewport({ inSectionDrawingAttachment: true }) : renderer.viewport; } computeDisplayTransform(args) { const renderer = undefined !== args.viewAttachmentId ? this.findRendererById(args.viewAttachmentId) : undefined; const ortho = renderer?.ortho; const sheetTransform = ortho?.toSheet; if (!sheetTransform) { return undefined; } const sectionTransform = args.inSectionDrawingAttachment ? ortho.view.computeDisplayTransform(args) : undefined; if (!sectionTransform) { return sheetTransform.clone(args.output); } return sheetTransform.multiplyTransformTransform(sectionTransform, args.output); } /** Strictly for tests. */ areAllAttachmentsLoaded() { return !this._reload && (!this._renderers || this._renderers.every((x) => x.areAllTileTreesLoaded)); } /** Strictly for tests. */ get attachments() { return this._renderers; } /** Strictly for tests. */ get attachmentProps() { const infos = this._impl.infos; if (!infos) { return []; } return infos.map((x) => { return { ...x, attachedView: undefined, }; }); } /** Strictly for tests. */ get attachmentInfos() { const infos = this._impl.infos; return infos ?? this._impl.attachmentIds; } loadRenderers() { const args = this._rendererArgs; (0, core_bentley_1.assert)(undefined !== args); (0, core_bentley_1.assert)(undefined === this._renderers); this._maxDepth = Frustum2d_1.Frustum2d.minimumZDistance; const infos = this._impl.infos; if (!infos) { return; } this._renderers = infos.map((info) => { const renderer = (0, ViewAttachmentRenderer_1.createViewAttachmentRenderer)({ ...args, props: info, view: info.attachedView, }); this._maxDepth = Math.max(this._maxDepth, renderer.zDepth); return renderer; }); } *renderers() { if (this._renderers) { for (const renderer of this._renderers) { yield renderer; } } } findRendererById(id) { return this._renderers?.find((x) => x.viewAttachmentProps.id === id); } } exports.SheetViewAttachments = SheetViewAttachments; //# sourceMappingURL=SheetViewAttachments.js.map