UNPKG

@itwin/core-frontend

Version:
118 lines 6.85 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 Views */ import { FeatureAppearance, PlanarClipMaskMode, PlanarClipMaskPriority, PlanarClipMaskSettings } from "@itwin/core-common"; import { FeatureSymbology } from "./render/FeatureSymbology"; import { Range3d } from "@itwin/core-geometry"; /** The State of Planar Clip Mask applied to a reality model or background map. * Handles loading models and their associated tiles for models that are used by masks but may not be otherwise loaded or displayed. * @beta */ export class PlanarClipMaskState { settings; _tileTreeRefs; _allLoaded = false; _usingViewportOverrides = false; _overridesModelVisibility = false; _maskRange = Range3d.createNull(); constructor(settings) { this.settings = settings; } static create(settings) { return new PlanarClipMaskState(settings); } static fromJSON(props) { return this.create(PlanarClipMaskSettings.fromJSON(props)); } get usingViewportOverrides() { return this._usingViewportOverrides; } ; /** @internal */ get overridesModelVisibility() { return this._overridesModelVisibility; } discloseTileTrees(trees) { if (this._tileTreeRefs) this._tileTreeRefs.forEach((treeRef) => treeRef.discloseTileTrees(trees)); } // Returns the TileTreeReferences for the models that need to be drawn to create the planar clip mask, and extend the maskRange if needed. getTileTrees(context, classifiedModelId, maskRange) { if (this.settings.mode === PlanarClipMaskMode.Priority) { // For priority mode we simply want refs for all viewed models if the priority is higher than the mask priority. // For this case, we don't need a maskRange so leave it as null. const viewTrees = new Array(); const thisPriority = this.settings.priority === undefined ? PlanarClipMaskPriority.RealityModel : this.settings.priority; for (const ref of context.viewport.getTileTreeRefs()) { const tree = ref.treeOwner.load(); if (tree && tree.modelId !== classifiedModelId && ref.planarClipMaskPriority > thisPriority) viewTrees.push(ref); } return viewTrees; } // For all other modes we need to let the tree refs in the view state decide which refs need to be drawn // since batched tiles cannot turn on/off individual models just by their tile tree refs. // Keep calling this until loaded so that the range is valid. if (!this._allLoaded) { this._tileTreeRefs = new Array(); if (this.settings.modelIds && context.viewport.view.isSpatialView()) { context.viewport.view.collectMaskRefs(this.settings.modelIds, this._tileTreeRefs, maskRange); } this._allLoaded = this._tileTreeRefs.every((treeRef) => treeRef.treeOwner.load() !== undefined); maskRange.clone(this._maskRange); } else // If already loaded, just set the maskRange to the saved maskRange. this._maskRange.clone(maskRange); return this._allLoaded ? this._tileTreeRefs : undefined; } // Returns any potential FeatureSymbology overrides for drawing the planar clip mask. getPlanarClipMaskSymbologyOverrides(context, featureSymbologySource) { this._usingViewportOverrides = this._overridesModelVisibility = false; // First obtain a list of models that will need to be turned off for drawing the planar clip mask (only used for batched tile trees). const overrideModels = context.viewport.view.isSpatialView() ? context.viewport.view.getModelsNotInMask(this.settings.modelIds, PlanarClipMaskMode.Priority === this.settings.mode) : undefined; const noSubCategoryOrElementIds = !this.settings.subCategoryOrElementIds; if (noSubCategoryOrElementIds && !overrideModels) return undefined; const ovrBasedOnContext = PlanarClipMaskMode.Priority === this.settings.mode || PlanarClipMaskMode.Models === this.settings.mode || noSubCategoryOrElementIds; const viewport = overrideModels && ovrBasedOnContext ? context.viewport : undefined; const overrides = FeatureSymbology.Overrides.withSource(featureSymbologySource, viewport); if (overrideModels) { this._overridesModelVisibility = true; // overrideModels is used for batched models. For those, we need to create model overrides to turn off models that are // not wanted in the mask (using transparency) no matter what mask mode is being used. const appOff = FeatureAppearance.fromTransparency(1.0); // For Priority or Models mode, we need to start with the current overrides and modify them if (ovrBasedOnContext) { this._usingViewportOverrides = true; // Set flag to use listener since context.viewport might change afterwards. overrides.addInvisibleElementOverridesToNeverDrawn(); // need this for fully trans element overrides to not participate in mask overrideModels.forEach((modelId) => { overrides.override({ modelId, appearance: appOff, onConflict: "replace" }); }); return overrides; } // Otherwise, we just start with a default overrides and modify it. overrideModels.forEach((modelId) => { overrides.override({ modelId, appearance: appOff, onConflict: "replace" }); }); } // Add overrides to turn things on or off based on the subcategories or elements in the mask settings. switch (this.settings.mode) { case PlanarClipMaskMode.IncludeElements: { overrides.setAlwaysDrawnSet(this.settings.subCategoryOrElementIds, true); return overrides; } case PlanarClipMaskMode.ExcludeElements: { overrides.ignoreSubCategory = true; overrides.setNeverDrawnSet(this.settings.subCategoryOrElementIds); return overrides; } case PlanarClipMaskMode.IncludeSubCategories: { for (const subCategoryId of this.settings.subCategoryOrElementIds) overrides.setVisibleSubCategory(subCategoryId); return overrides; } } return undefined; } } //# sourceMappingURL=PlanarClipMaskState.js.map