UNPKG

@itwin/core-frontend

Version:
238 lines • 7.99 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 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