@itwin/core-frontend
Version:
iTwin.js frontend components
289 lines • 14.4 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 Tiles
*/
import { assert, BeTimePoint } from "@itwin/core-bentley";
import { Range3d } from "@itwin/core-geometry";
import { PlanarClipMaskPriority } from "@itwin/core-common";
import { TileDrawArgs, TileTreeLoadStatus, tileTreeReferenceFromRenderGraphic, } from "./internal";
/** Describes the type of graphics produced by a [[TileTreeReference]].
* @public
* @extensions
*/
export var TileGraphicType;
(function (TileGraphicType) {
/** Rendered behind all other geometry without depth. */
TileGraphicType[TileGraphicType["BackgroundMap"] = 0] = "BackgroundMap";
/** Rendered with normal scene graphics. */
TileGraphicType[TileGraphicType["Scene"] = 1] = "Scene";
/** Rendered in front of all other geometry. */
TileGraphicType[TileGraphicType["Overlay"] = 2] = "Overlay";
})(TileGraphicType || (TileGraphicType = {}));
/** A reference to a [[TileTree]] suitable for drawing within a [[Viewport]]. The reference does not *own* its tile tree - it merely refers to it by
* way of the tree's [[TileTreeOwner]].
* The specific [[TileTree]] referenced by this object may change based on the current state of the Viewport in which it is drawn - for example,
* as a result of changing the RenderMode, or animation settings, or classification settings, etc.
* A reference to a TileTree is typically associated with a [[ViewState]], a [[DisplayStyleState]], or a [[Viewport]].
* Multiple TileTreeReferences can refer to the same TileTree with different parameters and logic - for example, the same background map tiles can be displayed in two viewports with
* differing levels of transparency.
* @see [[TiledGraphicsProvider]] to supply custom [[TileTreeReference]]s to be drawn within a [[Viewport]].
* @public
* @extensions
*/
export class TileTreeReference /* implements RenderMemory.Consumer */ {
/** If set to true, tile geometry will be reprojected using the tile's reprojection transform when geometry is collected from the referenced TileTree.
* @internal
*/
reprojectGeometry;
/** Force a new tree owner / tile tree to be created for the current tile tree reference
* @internal
*/
resetTreeOwner() { }
/** Disclose *all* TileTrees use by this reference. This may include things like map tiles used for draping on terrain.
* Override this and call super if you have such auxiliary trees.
* @note Any tree *NOT* disclosed becomes a candidate for *purging* (being unloaded from memory along with all of its tiles and graphics).
*/
discloseTileTrees(trees) {
const tree = this.treeOwner.tileTree;
if (undefined !== tree)
trees.add(tree);
}
/** Adds this reference's graphics to the scene. By default this invokes [[draw]]. */
addToScene(context) {
const args = this.createDrawArgs(context);
if (undefined !== args)
this.draw(args);
}
/** Adds this reference's graphics to the scene. By default this invokes [[TileTree.draw]] on the referenced TileTree, if it is loaded. */
draw(args) {
args.tree.draw(args);
}
/** Return a tooltip describing the hit, or `undefined` if no tooltip can be supplied.
* If you override this method, make sure to check that `hit` represents an entity belonging to your tile tree, e.g., by checking `hit.modelId` and `hit.sourceId`.
* If you *don't* override this method, override [[canSupplyToolTip]] to return false.
* Callers who want to obtain a tooltip should prefer [[getToolTipPromise]].
*/
async getToolTip(_hit) { return undefined; }
/** Return whether this TileTreeReference can supply a tooltip describing the entity represented by the specified hit.
* [[getToolTipPromise]] calls [[getToolTip]] if and only if `canSupplyToolTip` returns `true`.
* If your tile tree never supplies tooltips, override this to return `false`.
*/
canSupplyToolTip(_hit) {
return true;
}
/** Obtain a tooltip describing the specified `hit`, or `undefined` if this tile tree reference cannot supply a tooltip for the hit. */
getToolTipPromise(hit) {
return this.canSupplyToolTip(hit) ? this.getToolTip(hit).catch(() => undefined) : undefined;
}
/** Optionally return a MapLayerFeatureInfo object describing the hit.].
* @alpha
*/
async getMapFeatureInfo(_hit, _options) { return undefined; }
/** Optionally add any decorations specific to this reference. For example, map tile trees may add a logo image and/or copyright attributions.
* @note This is currently only invoked for background maps and TiledGraphicsProviders - others have no decorations, but if they did implement this it would not be called.
*/
decorate(_context) { }
/** Unions this reference's range with the supplied range to help compute a volume in world space for fitting a viewport to its contents.
* Override this function if a reference's range should not be included in the fit range, or a range different from its tile tree's range should be used.
*/
unionFitRange(union) {
const contentRange = this.computeWorldContentRange();
if (!contentRange.isNull)
union.extendRange(contentRange);
}
/** Record graphics memory consumed by this tile tree reference. */
collectStatistics(stats) {
const tree = this.treeOwner.tileTree;
if (undefined !== tree)
tree.collectStatistics(stats);
}
/** Return true if the tile tree is fully loaded and ready to draw.
* The default implementation returns true if the tile tree loading process completed (whether it resulted in success or failure).
* @note Do *not* override this property - override [[_isLoadingComplete]] instead..
* @public
*/
get isLoadingComplete() {
switch (this.treeOwner.loadStatus) {
case TileTreeLoadStatus.NotLoaded:
case TileTreeLoadStatus.Loading:
return false;
case TileTreeLoadStatus.NotFound:
return true; // we tried, and failed, to load.
case TileTreeLoadStatus.Loaded:
return this._isLoadingComplete;
}
}
/** Override if additional asynchronous loading is required after the tile tree is successfully loaded, to indicate when that loading has completed.
* @public
*/
get _isLoadingComplete() {
return true;
}
/** Create context for drawing the tile tree, if it is ready for drawing.
* TileTreeReferences can override individual portions of the context, e.g. apply their own transform.
* Returns undefined if, e.g., the tile tree is not yet loaded.
*/
createDrawArgs(context) {
const tree = this.treeOwner.load();
if (undefined === tree)
return undefined;
return new TileDrawArgs({
context,
tree,
now: BeTimePoint.now(),
location: this.computeTransform(tree),
viewFlagOverrides: this.getViewFlagOverrides(tree),
clipVolume: this.getClipVolume(tree),
parentsAndChildrenExclusive: tree.parentsAndChildrenExclusive,
symbologyOverrides: this.getSymbologyOverrides(tree),
appearanceProvider: this.getAppearanceProvider(tree),
hiddenLineSettings: this.getHiddenLineSettings(tree),
animationTransformNodeId: this.getAnimationTransformNodeId(tree),
groupNodeId: this.getGroupNodeId(tree),
transformFromIModel: this.getTransformFromIModel(),
});
}
/** @beta */
getTransformFromIModel() { return undefined; }
/** @internal */
getAnimationTransformNodeId(_tree) {
return undefined;
}
/** @internal */
getGroupNodeId(_tree) {
return undefined;
}
/** Supply transform from this tile tree reference's location to iModel coordinate space.
* @returns undefined if the TileTree is not yet loaded.
*/
getLocation() {
const tree = this.treeOwner.load();
return undefined !== tree ? this.computeTransform(tree) : undefined;
}
/** Compute a transform from this tile tree reference's coordinate space to the [[IModelConnection]]'s coordinate space. */
computeTransform(tree) {
return tree.iModelTransform.clone();
}
/** Compute the range of this tile tree's contents in world coordinates.
* @returns The content range in world coodinates, or a null range if the tile tree is not loaded or has a null content range.
*/
computeWorldContentRange() {
const range = new Range3d();
const tree = this.treeOwner.tileTree;
if (undefined !== tree && !tree.rootTile.contentRange.isNull)
this.computeTransform(tree).multiplyRange(tree.rootTile.contentRange, range);
return range;
}
/** Return the clip volume applied to this reference's tile tree, if any. */
getClipVolume(tree) {
return tree.clipVolume;
}
/** Supply overrides that should be applied to the [[ViewState]]'s [ViewFlags]($common) when drawing this tile tree reference. */
getViewFlagOverrides(tree) {
return tree.viewFlagOverrides;
}
/** Return overrides that *replace* any defined for the view. */
getSymbologyOverrides(_tree) {
return undefined;
}
/** Return a provider that can supplement the view's symbology overrides. */
getAppearanceProvider(_tree) {
return undefined;
}
/** Return hidden line settings to replace those defined for the view. */
getHiddenLineSettings(_tree) {
return undefined;
}
/* Extend range to include transformed range of this tile tree.
* @internal
*/
accumulateTransformedRange(range, matrix, frustumPlanes) {
const tree = this.treeOwner.tileTree;
if (undefined === tree)
return;
const location = this.computeTransform(tree);
tree.accumulateTransformedRange(range, matrix, location, frustumPlanes);
}
/** @internal */
getTerrainHeight(_terrainHeights) { }
/** Return whether the geometry exposed by this tile tree reference should cast shadows on other geometry. */
get castsShadows() {
return true;
}
/** Return whether this reference has global coverage. Mapping data is global and some non-primary models such as the OSM building layer have global coverage */
get isGlobal() { return false; }
/** The [PlanarClipMaskPriority]($common) of this tile tree used to determine which tile trees contribute to a clip mask when
* using [PlanarClipMaskMode.Priority]($common).
* @beta
*/
get planarClipMaskPriority() { return PlanarClipMaskPriority.DesignModel; }
/** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [addAttributions] instead. */
addLogoCards(_cards, _vp) { }
/** Add attribution logo cards for the tile tree source logo cards to the viewport's logo div.
* @beta
*/
async addAttributions(cards, vp) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return Promise.resolve(this.addLogoCards(cards, vp));
}
/** Create a tile tree reference equivalent to this one that also supplies an implementation of [[GeometryTileTreeReference.collectTileGeometry]].
* Return `undefined` if geometry collection is not supported.
* @see [[createGeometryTreeReference]].
*/
_createGeometryTreeReference(_options) {
return undefined;
}
/** If defined, supplies the implementation of [[GeometryTileTreeReference.collectTileGeometry]].
*/
collectTileGeometry;
/** A function that can be assigned to [[collectTileGeometry]] to enable geometry collection for references to tile trees that support geometry collection.
*/
_collectTileGeometry(collector) {
const tree = this.treeOwner.load();
switch (this.treeOwner.loadStatus) {
case TileTreeLoadStatus.Loaded:
assert(undefined !== tree);
tree.collectTileGeometry(collector);
break;
case TileTreeLoadStatus.Loading:
collector.markLoading();
break;
}
}
/** Obtain a tile tree reference equivalent to this one that also supplies an implementation of [[GeometryTileTreeReference.collectTileGeometry]], or
* undefined if geometry collection is not supported.
* Currently, only terrain and reality model tiles support geometry collection.
* @note Do not override this method - override [[_createGeometryTreeReference]] instead.
*/
createGeometryTreeReference(options) {
if (this.collectTileGeometry) {
// Unclear why compiler doesn't detect that `this` satisfies the GeometryTileTreeReference interface...it must be looking only at the types, not this particular instance.
const ref = this;
ref.reprojectGeometry = options?.reprojectGeometry;
return ref;
}
return this._createGeometryTreeReference(options);
}
/** Create a [[TileTreeReference]] that displays a pre-defined [[RenderGraphic]].
* The reference can be used to add dynamic content to a [[Viewport]]'s scene as a [[TiledGraphicsProvider]], as in the following example:
* ```ts
* [[include:TileTreeReference_createFromRenderGraphic]]
*```
* Or, it can be used as a [[DynamicSpatialClassifier]] to contextualize a reality model, like so:
* ```ts
* [[include:TileTreeReference_DynamicClassifier]]
* ```
* It can also be used to mask out portions of the background map or terrain via [PlanarClipMaskSettings]($common), as shown below:
* ```ts
* [[include:TileTreeReference_DynamicClipMask]]
* ```
* @beta
*/
static createFromRenderGraphic(args) {
return tileTreeReferenceFromRenderGraphic(args);
}
}
//# sourceMappingURL=TileTreeReference.js.map