@itwin/core-frontend
Version:
iTwin.js frontend components
238 lines • 7.99 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.LayerCommandLists = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const DrawCommand_1 = require("./DrawCommand");
class State {
map;
constructor(map) {
this.map = map;
}
executeTransition(newState, func) {
this.map.state = newState;
func();
newState.exit();
this.map.state = this;
}
exit() { }
throwStateError(operation) {
// Using assert because these are intended for developers.
(0, core_bentley_1.assert)(false, `Invalid layer command: operation '${operation}' unimplemented for state '${this.opcode}'`);
}
processLayers(_container, _func) {
this.throwStateError("processLayers");
}
pushAndPop(push, _pop, func) {
if ("pushBatch" === push.opcode)
this.processBatch(push, func);
else if ("pushBranch" === push.opcode)
this.processBranch(push, func);
else
this.throwStateError("unhandled push command");
}
processBranch(_push, _func) {
this.throwStateError("processBranch");
}
processBatch(_push, _func) {
this.throwStateError("processBatch");
}
set currentLayer(_layer) {
this.throwStateError("setCurrentLayer");
}
addCommands(_commands) {
this.throwStateError("addCommands");
}
}
class IdleState extends State {
get opcode() { return "Idle"; }
constructor(map) {
super(map);
}
processLayers(container, func) {
this.executeTransition(new ContainerState(this, container), func);
}
}
class ContainerState extends State {
elevation;
get opcode() { return "Container"; }
constructor(idle, container) {
super(idle.map);
this.elevation = container.elevation;
}
processBranch(push, func) {
this.executeTransition(new BranchState(this, push), func);
}
}
class BranchState extends State {
pushCommand;
containerState;
_layerCommands = new Set();
get opcode() { return "Branch"; }
constructor(containerState, pushCommand) {
super(containerState.map);
this.containerState = containerState;
this.pushCommand = pushCommand;
}
processBatch(push, func) {
this.executeTransition(new BatchState(this, push), func);
}
markLayer(cmds) {
if (!this._layerCommands.has(cmds)) {
cmds.commands.push(this.pushCommand);
this._layerCommands.add(cmds);
}
}
exit() {
for (const cmds of this._layerCommands)
cmds.commands.push(DrawCommand_1.PopBranchCommand.instance);
}
}
class BatchState extends State {
branchState;
pushCommand;
get opcode() { return "Batch"; }
constructor(branchState, pushCommand) {
super(branchState.map);
this.branchState = branchState;
this.pushCommand = pushCommand;
}
set currentLayer(layer) {
if (undefined === layer)
this.throwStateError("currentLayer = undefined");
else
this.map.state = new LayerState(this, layer);
}
}
class LayerState extends State {
_batchState;
commands;
get opcode() { return "Layer"; }
constructor(batchState, layer) {
super(batchState.map);
this._batchState = batchState;
this.commands = this.map.getCommands(layer, batchState.branchState.containerState.elevation);
this._batchState.branchState.markLayer(this.commands);
this.commands.commands.push(batchState.pushCommand);
}
set currentLayer(layer) {
if (undefined === layer) {
this.commands.commands.push(DrawCommand_1.PopBatchCommand.instance);
this.map.state = this._batchState;
}
else {
this.throwStateError("currentLayer != undefined");
}
}
pushAndPop(push, pop, func) {
this.commands.commands.push(push);
func();
this.commands.commands.push(pop);
}
addCommands(commands) {
for (const command of commands)
this.commands.commands.push(command);
}
}
/** DrawCommands associated with one Layer, drawn during the Layers render pass. */
class LayerCommands {
layerId;
priority;
elevation;
commands = [];
constructor(layerId, priority, elevation) {
this.layerId = layerId;
this.priority = priority;
this.elevation = elevation;
}
}
class LayerCommandMap extends core_bentley_1.SortedArray {
target;
state;
constructor(target) {
// Layers with different view Z draw in ascending order by Z.
// Layers with same elevation draw in ascending order by priority.
// Layers with same elevation and priority draw in indeterminate order.
super((lhs, rhs) => {
let cmp = (0, core_bentley_1.compareNumbers)(lhs.elevation, rhs.elevation);
if (0 === cmp) {
cmp = (0, core_bentley_1.compareNumbers)(lhs.priority, rhs.priority);
if (0 === cmp)
cmp = (0, core_bentley_1.compareStrings)(lhs.layerId, rhs.layerId);
}
return cmp;
});
this.target = target;
this.state = new IdleState(this);
}
clear() {
super.clear();
(0, core_bentley_1.assert)(this.state instanceof IdleState);
}
getCommands(layer, elevation) {
for (const entry of this._array)
if (entry.layerId === layer.layerId && entry.elevation === elevation)
return entry;
const cmds = new LayerCommands(layer.layerId, layer.getPriority(this.target), elevation);
this.insert(cmds);
return cmds;
}
outputCommands(cmds) {
for (const entry of this._array)
for (const cmd of entry.commands)
cmds.push(cmd);
}
}
/** @internal */
class LayerCommandLists {
_maps = [];
_renderCommands;
_activeMap;
constructor(cmds) {
this._renderCommands = cmds;
}
clear() {
this._maps.length = 0;
}
processLayers(container, func) {
(0, core_bentley_1.assert)(undefined === this._activeMap);
const pass = container.renderPass;
this._activeMap = this._maps[pass];
if (undefined === this._activeMap) {
this._activeMap = new LayerCommandMap(this._renderCommands.target);
this._maps[pass] = this._activeMap;
}
this._activeMap.state.processLayers(container, func);
this._activeMap = undefined;
}
set currentLayer(layer) {
(0, core_bentley_1.assert)(undefined !== this._activeMap);
this._activeMap.state.currentLayer = layer;
}
addCommands(cmds) {
(0, core_bentley_1.assert)(undefined !== this._activeMap);
this._activeMap.state.addCommands(cmds);
}
pushAndPop(push, pop, func) {
(0, core_bentley_1.assert)(undefined !== this._activeMap);
this._activeMap.state.pushAndPop(push, pop, func);
}
outputCommands() {
this.outputCommandsForPass(1 /* RenderPass.OpaqueLayers */);
this.outputCommandsForPass(7 /* RenderPass.TranslucentLayers */);
this.outputCommandsForPass(11 /* RenderPass.OverlayLayers */);
}
outputCommandsForPass(pass) {
const map = this._maps[pass];
if (undefined !== map)
map.outputCommands(this._renderCommands.getCommands(pass));
}
}
exports.LayerCommandLists = LayerCommandLists;
//# sourceMappingURL=LayerCommands.js.map