@itwin/core-frontend
Version:
iTwin.js frontend components
438 lines • 16.3 kB
JavaScript
"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 WebGL
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GraphicsArray = exports.WorldDecorations = exports.AnimationTransformBranch = exports.Branch = exports.Batch = exports.PerTargetData = exports.PerTargetBatchData = exports.GraphicOwner = exports.Graphic = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const core_geometry_1 = require("@itwin/core-geometry");
const FeatureSymbology_1 = require("../../../render/FeatureSymbology");
const GraphicBranch_1 = require("../../../render/GraphicBranch");
const RenderGraphic_1 = require("../../../render/RenderGraphic");
const EdgeSettings_1 = require("./EdgeSettings");
const FeatureOverrides_1 = require("./FeatureOverrides");
const PlanarClassifier_1 = require("./PlanarClassifier");
const TextureDrape_1 = require("./TextureDrape");
const ThematicSensors_1 = require("./ThematicSensors");
const Contours_1 = require("./Contours");
/** @internal */
class Graphic extends RenderGraphic_1.RenderGraphic {
addHiliteCommands(_commands, _pass) { (0, core_bentley_1.assert)(false); }
toPrimitive() { return undefined; }
}
exports.Graphic = Graphic;
class GraphicOwner extends Graphic {
_graphic;
constructor(graphic) {
super();
this._graphic = graphic;
}
get graphic() { return this._graphic; }
_isDisposed = false;
get isDisposed() { return this._isDisposed; }
dispose() { this._isDisposed = true; }
disposeGraphic() {
this.graphic[Symbol.dispose]();
}
collectStatistics(stats) {
this.graphic.collectStatistics(stats);
}
unionRange(range) {
this.graphic.unionRange(range);
}
addCommands(commands) {
this._graphic.addCommands(commands);
}
get isPickable() {
return this._graphic.isPickable;
}
addHiliteCommands(commands, pass) {
this._graphic.addHiliteCommands(commands, pass);
}
toPrimitive() {
return this._graphic.toPrimitive();
}
}
exports.GraphicOwner = GraphicOwner;
/** @internal exported strictly for tests. */
class PerTargetBatchData {
target;
_featureOverrides = new Map();
_contours;
_thematicSensors;
constructor(target) {
this.target = target;
}
[Symbol.dispose]() {
this._thematicSensors = (0, core_bentley_1.dispose)(this._thematicSensors);
this._contours = this._contours?.[Symbol.dispose]();
for (const value of this._featureOverrides.values())
(0, core_bentley_1.dispose)(value);
this._featureOverrides.clear();
}
getThematicSensors(batch) {
if (this._thematicSensors && !this._thematicSensors.matchesTarget(this.target))
this._thematicSensors = (0, core_bentley_1.dispose)(this._thematicSensors);
if (!this._thematicSensors)
this._thematicSensors = ThematicSensors_1.ThematicSensors.create(this.target, batch.range);
this._thematicSensors.update(this.target.uniforms.frustum.viewMatrix);
return this._thematicSensors;
}
getFeatureOverrides(batch, provider) {
const source = this.target.currentFeatureSymbologyOverrides?.source;
let ovrs = this._featureOverrides.get(source);
if (!ovrs) {
const cleanup = source ? source.onSourceDisposed.addOnce(() => this.onSourceDisposed(source)) : undefined;
this._featureOverrides.set(source, ovrs = FeatureOverrides_1.FeatureOverrides.createFromTarget(this.target, batch.options, cleanup));
ovrs.initFromMap(batch.featureTable, provider);
}
ovrs.update(batch.featureTable, provider);
return ovrs;
}
getContours(batch) {
if (this._contours && !this._contours.matchesTargetAndFeatureCount(this.target, batch.featureTable))
this._contours = this._contours[Symbol.dispose]();
if (!this._contours) {
this._contours = Contours_1.Contours.createFromTarget(this.target, batch.options);
this._contours.initFromMap(batch.featureTable);
}
else {
this._contours.update(batch.featureTable);
}
return this._contours;
}
collectStatistics(stats) {
if (this._thematicSensors)
stats.addThematicTexture(this._thematicSensors.bytesUsed);
for (const ovrs of this._featureOverrides.values())
stats.addFeatureOverrides(ovrs.byteLength);
if (this._contours)
stats.addContours(this._contours.byteLength);
}
/** Exposed strictly for tests. */
get featureOverrides() { return this._featureOverrides; }
onSourceDisposed(source) {
const ovrs = this._featureOverrides.get(source);
if (ovrs) {
this._featureOverrides.delete(source);
ovrs[Symbol.dispose]();
}
}
}
exports.PerTargetBatchData = PerTargetBatchData;
/** @internal exported strictly for tests. */
class PerTargetData {
_batch;
_data = [];
constructor(batch) {
this._batch = batch;
}
[Symbol.dispose]() {
for (const data of this._data) {
data.target.onBatchDisposed(this._batch);
data[Symbol.dispose]();
}
this._data.length = 0;
}
get isDisposed() {
return this._data.length === 0;
}
/** Exposed strictly for tests. */
get data() { return this._data; }
onTargetDisposed(target) {
const index = this._data.findIndex((x) => x.target === target);
if (-1 === index)
return;
const data = this._data[index];
data[Symbol.dispose]();
this._data.splice(index, 1);
}
collectStatistics(stats) {
for (const data of this._data)
data.collectStatistics(stats);
}
getThematicSensors(target) {
return this.getBatchData(target).getThematicSensors(this._batch);
}
getFeatureOverrides(target, provider) {
return this.getBatchData(target).getFeatureOverrides(this._batch, provider);
}
getContours(target) {
return this.getBatchData(target).getContours(this._batch);
}
getBatchData(target) {
let data = this._data.find((x) => x.target === target);
if (!data) {
this._data.push(data = new PerTargetBatchData(target));
target.addBatch(this._batch);
}
return data;
}
}
exports.PerTargetData = PerTargetData;
/** @internal */
class Batch extends Graphic {
graphic;
featureTable;
range;
_context = { batchId: 0 };
/** Public strictly for tests. */
perTargetData = new PerTargetData(this);
options;
// Chiefly for debugging.
get tileId() {
return this.options.tileId;
}
get locateOnly() {
return true === this.options.locateOnly;
}
/** The following are valid only during a draw and reset afterward. */
get batchId() { return this._context.batchId; }
get batchIModel() { return this._context.iModel; }
get transformFromBatchIModel() { return this._context.transformFromIModel; }
get viewAttachmentId() { return this._context.viewAttachmentId; }
get inSectionDrawingAttachment() { return this._context.inSectionDrawingAttachment; }
setContext(batchId, branch) {
this._context.batchId = batchId;
this._context.iModel = branch.iModel;
this._context.transformFromIModel = branch.transformFromIModel;
this._context.viewAttachmentId = branch.viewAttachmentId;
this._context.inSectionDrawingAttachment = branch.inSectionDrawingAttachment;
}
resetContext() {
this._context.batchId = 0;
this._context.iModel = undefined;
this._context.transformFromIModel = undefined;
this._context.viewAttachmentId = undefined;
this._context.inSectionDrawingAttachment = undefined;
}
constructor(graphic, features, range, options) {
super();
this.graphic = graphic;
this.featureTable = features;
this.range = range;
this.options = options ?? {};
}
_isDisposed = false;
get isDisposed() {
return this._isDisposed && this.perTargetData.isDisposed;
}
// Note: This does not remove FeatureOverrides from the array, but rather disposes of the WebGL resources they contain
dispose() {
(0, core_bentley_1.dispose)(this.graphic);
this.perTargetData[Symbol.dispose]();
this._isDisposed = true;
}
collectStatistics(stats) {
this.graphic.collectStatistics(stats);
stats.addFeatureTable(this.featureTable.byteLength);
this.perTargetData.collectStatistics(stats);
}
unionRange(range) {
range.extendRange(this.range);
}
addCommands(commands) {
commands.addBatch(this);
}
get isPickable() {
return true;
}
getThematicSensors(target) {
(0, core_bentley_1.assert)(target.plan.thematic !== undefined, "thematic display settings must exist");
(0, core_bentley_1.assert)(target.plan.thematic.displayMode === core_common_1.ThematicDisplayMode.InverseDistanceWeightedSensors, "thematic display mode must be sensor-based");
(0, core_bentley_1.assert)(target.plan.thematic.sensorSettings.sensors.length > 0, "must have at least one sensor to process");
return this.perTargetData.getThematicSensors(target);
}
getOverrides(target, provider) {
return this.perTargetData.getFeatureOverrides(target, provider);
}
getContours(target) {
return this.perTargetData.getContours(target);
}
onTargetDisposed(target) {
this.perTargetData.onTargetDisposed(target);
}
}
exports.Batch = Batch;
/** @internal */
class Branch extends Graphic {
branch;
localToWorldTransform;
clips;
planarClassifier;
textureDrape;
layerClassifiers;
edgeSettings;
iModel; // used chiefly for readPixels to identify context of picked Ids.
frustum;
appearanceProvider;
secondaryClassifiers;
viewAttachmentId;
inSectionDrawingAttachment;
disableClipStyle;
transformFromExternalIModel;
contourLine;
constructor(branch, localToWorld, viewFlags, opts) {
super();
this.branch = branch;
this.localToWorldTransform = localToWorld;
if (undefined !== viewFlags)
branch.setViewFlags(viewFlags);
if (!opts)
return;
this.appearanceProvider = opts.appearanceProvider;
this.clips = opts.clipVolume;
this.iModel = opts.iModel;
this.frustum = opts.frustum;
this.viewAttachmentId = opts.viewAttachmentId;
this.inSectionDrawingAttachment = opts.inSectionDrawingAttachment;
this.disableClipStyle = opts.disableClipStyle;
this.transformFromExternalIModel = opts.transformFromIModel;
this.contourLine = opts.contours;
if (opts.hline)
this.edgeSettings = EdgeSettings_1.EdgeSettings.create(opts.hline);
if (opts.classifierOrDrape instanceof PlanarClassifier_1.PlanarClassifier)
this.planarClassifier = opts.classifierOrDrape;
else if (opts.classifierOrDrape instanceof TextureDrape_1.TextureDrape)
this.textureDrape = opts.classifierOrDrape;
if (opts.secondaryClassifiers) {
this.secondaryClassifiers = new Array();
opts.secondaryClassifiers.forEach((classifier) => {
if (classifier instanceof PlanarClassifier_1.PlanarClassifier)
this.secondaryClassifiers?.push(classifier);
});
}
}
get isDisposed() {
return 0 === this.branch.entries.length;
}
dispose() {
this.branch[Symbol.dispose]();
}
get isPickable() {
return this.branch.entries.some((gf) => gf.isPickable);
}
collectStatistics(stats) {
this.branch.collectStatistics(stats);
}
unionRange(range) {
const thisRange = new core_geometry_1.Range3d();
for (const graphic of this.branch.entries)
graphic.unionRange(thisRange);
this.localToWorldTransform.multiplyRange(thisRange, thisRange);
range.extendRange(thisRange);
}
shouldAddCommands(commands) {
const group = commands.target.currentBranch.groupNodeId;
if (undefined !== group && undefined !== this.branch.groupNodeId && this.branch.groupNodeId !== group)
return false;
const nodeId = commands.target.getAnimationTransformNodeId(this.branch.animationNodeId);
return undefined === nodeId || nodeId === commands.target.currentAnimationTransformNodeId;
}
addCommands(commands) {
if (this.shouldAddCommands(commands))
commands.addBranch(this);
}
addHiliteCommands(commands, pass) {
if (this.shouldAddCommands(commands))
commands.addHiliteBranch(this, pass);
}
}
exports.Branch = Branch;
/** @internal */
class AnimationTransformBranch extends Graphic {
nodeId;
graphic;
constructor(graphic, nodeId) {
super();
(0, core_bentley_1.assert)(graphic instanceof Graphic);
this.graphic = graphic;
this.nodeId = nodeId;
}
dispose() {
this.graphic[Symbol.dispose]();
}
get isDisposed() {
return this.graphic.isDisposed;
}
get isPickable() {
return this.graphic.isPickable;
}
collectStatistics(stats) {
this.graphic.collectStatistics(stats);
}
unionRange(range) {
this.graphic.unionRange(range);
}
addCommands(commands) {
commands.target.currentAnimationTransformNodeId = this.nodeId;
this.graphic.addCommands(commands);
commands.target.currentAnimationTransformNodeId = undefined;
}
addHiliteCommands(commands, pass) {
commands.target.currentAnimationTransformNodeId = this.nodeId;
this.graphic.addHiliteCommands(commands, pass);
commands.target.currentAnimationTransformNodeId = undefined;
}
}
exports.AnimationTransformBranch = AnimationTransformBranch;
/** @internal */
class WorldDecorations extends Branch {
constructor(viewFlags) {
super(new GraphicBranch_1.GraphicBranch(), core_geometry_1.Transform.identity, viewFlags);
// World decorations ignore all the symbology overrides for the "scene" geometry...
this.branch.symbologyOverrides = new FeatureSymbology_1.FeatureSymbology.Overrides();
// Make all subcategories visible.
this.branch.symbologyOverrides.ignoreSubCategory = true;
}
init(decs) {
this.branch.clear();
for (const dec of decs) {
this.branch.add(dec);
}
}
}
exports.WorldDecorations = WorldDecorations;
/** @internal */
class GraphicsArray extends Graphic {
graphics;
// Note: We assume the graphics array we get contains undisposed graphics to start
constructor(graphics) {
super();
this.graphics = graphics;
}
get isDisposed() { return 0 === this.graphics.length; }
get isPickable() {
return this.graphics.some((x) => x.isPickable);
}
dispose() {
for (const graphic of this.graphics)
(0, core_bentley_1.dispose)(graphic);
this.graphics.length = 0;
}
addCommands(commands) {
for (const graphic of this.graphics) {
graphic.addCommands(commands);
}
}
addHiliteCommands(commands, pass) {
for (const graphic of this.graphics) {
graphic.addHiliteCommands(commands, pass);
}
}
collectStatistics(stats) {
for (const graphic of this.graphics)
graphic.collectStatistics(stats);
}
unionRange(range) {
for (const graphic of this.graphics)
graphic.unionRange(range);
}
}
exports.GraphicsArray = GraphicsArray;
//# sourceMappingURL=Graphic.js.map