Skip to content

Commit

Permalink
Allow CompositeLayer to filter sub layers during redraw (visgl#5820)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress authored May 28, 2021
1 parent 9c72708 commit e225cd3
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 32 deletions.
12 changes: 12 additions & 0 deletions modules/core/src/lib/composite-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ export default class CompositeLayer extends Layer {
return null;
}

/**
* Filters sub layers at draw time
* @param {Layer} context.layer - sub layer instance
* @param {Viewport} context.viewport - the viewport being rendered in
* @param {Boolean} context.isPicking - whether it is a picking pass
* @param {String} context.pass - the current pass
* @return {Boolean} true if the sub layer should be drawn
*/
filterSubLayer(context) {
return true;
}

// Returns true if sub layer needs to be rendered
shouldRenderSubLayer(id, data) {
const {_subLayerProps: overridingProps} = this.props;
Expand Down
44 changes: 29 additions & 15 deletions modules/core/src/passes/layers-pass.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@ export default class LayersPass extends Pass {
_getDrawLayerParams(viewport, {layers, pass, layerFilter, effects, moduleParameters}) {
const drawLayerParams = [];
const indexResolver = layerIndexResolver();
const drawContext = {
viewport,
isPicking: pass.startsWith('picking'),
renderPass: pass
};
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
const layer = layers[layerIndex];
// Check if we should draw layer
const shouldDrawLayer = this._shouldDrawLayer(layer, viewport, pass, layerFilter);
const shouldDrawLayer = this._shouldDrawLayer(layer, drawContext, layerFilter);

// This is the "logical" index for ordering this layer in the stack
// used to calculate polygon offsets
Expand Down Expand Up @@ -164,23 +169,32 @@ export default class LayersPass extends Pass {
}

/* Private */
_shouldDrawLayer(layer, viewport, pass, layerFilter) {
let shouldDrawLayer = this.shouldDrawLayer(layer) && layer.props.visible;

if (shouldDrawLayer && layerFilter) {
shouldDrawLayer = layerFilter({
layer,
viewport,
isPicking: pass.startsWith('picking'),
renderPass: pass
});
_shouldDrawLayer(layer, drawContext, layerFilter) {
const shouldDrawLayer = this.shouldDrawLayer(layer) && layer.props.visible;

if (!shouldDrawLayer) {
return false;
}
if (shouldDrawLayer) {
// If a layer is drawn, update its viewportChanged flag
layer.activateViewport(viewport);

drawContext.layer = layer;

if (layerFilter && !layerFilter(drawContext)) {
return false;
}

return shouldDrawLayer;
let parent = layer.parent;
while (parent) {
if (!parent.filterSubLayer(drawContext)) {
return false;
}
drawContext.layer = parent;
parent = parent.parent;
}

// If a layer is drawn, update its viewportChanged flag
layer.activateViewport(drawContext.viewport);

return true;
}

_getModuleParameters(layer, effects, pass, overrides) {
Expand Down
27 changes: 14 additions & 13 deletions modules/geo-layers/src/tile-layer/tile-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,6 @@ export default class TileLayer extends CompositeLayer {
renderLayers() {
const {visible} = this.props;
return this.state.tileset.tiles.map(tile => {
// For a tile to be visible:
// - parent layer must be visible
// - tile must be visible in the current viewport
const isVisible = visible && tile.isVisible;
const highlightedObjectIndex = this.getHighlightedObjectIndex(tile);
// cache the rendered layer in the tile
if (!tile.isLoaded) {
Expand All @@ -227,24 +223,29 @@ export default class TileLayer extends CompositeLayer {
...this.props,
id: `${this.id}-${tile.x}-${tile.y}-${tile.z}`,
data: tile.data,
visible: isVisible,
visible,
_offset: 0,
tile,
highlightedObjectIndex
tile
});
tile.layers = flatten(layers, Boolean);
tile.layers = flatten(layers, Boolean).map(layer =>
layer.clone({
tile,
highlightedObjectIndex
})
);
} else if (
tile.layers[0] &&
(tile.layers[0].props.visible !== isVisible ||
tile.layers[0].props.highlightedObjectIndex !== highlightedObjectIndex)
tile.layers[0].props.highlightedObjectIndex !== highlightedObjectIndex
) {
tile.layers = tile.layers.map(layer =>
layer.clone({visible: isVisible, highlightedObjectIndex})
);
tile.layers = tile.layers.map(layer => layer.clone({highlightedObjectIndex}));
}
return tile.layers;
});
}

filterSubLayer({layer}) {
return layer.props.tile.isVisible;
}
}

TileLayer.layerName = 'TileLayer';
Expand Down
19 changes: 15 additions & 4 deletions test/modules/geo-layers/tile-layer/tile-layer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ test('TileLayer', async t => {
t.is(subLayers.length, 2, 'Rendered sublayers');
t.is(getTileDataCalled, 2, 'Fetched tile data');
t.ok(layer.isLoaded, 'Layer is loaded');
t.ok(subLayers.every(l => l.props.visible), 'Sublayers at z=2 are visible');
t.ok(
subLayers.every(l => layer.filterSubLayer({layer: l})),
'Sublayers at z=2 are visible'
);
}
}
},
Expand All @@ -109,7 +112,9 @@ test('TileLayer', async t => {
t.is(subLayers.length, 4, 'Rendered new sublayers');
t.is(getTileDataCalled, 4, 'Fetched tile data');
t.ok(
subLayers.filter(l => l.props.tile.z === 3).every(l => l.props.visible),
subLayers
.filter(l => l.props.tile.z === 3)
.every(l => layer.filterSubLayer({layer: l})),
'Sublayers at z=3 are visible'
);
}
Expand All @@ -122,7 +127,9 @@ test('TileLayer', async t => {
t.is(subLayers.length, 4, 'Rendered cached sublayers');
t.is(getTileDataCalled, 4, 'Used cached data');
t.ok(
subLayers.filter(l => l.props.tile.z === 3).every(l => !l.props.visible),
subLayers
.filter(l => l.props.tile.z === 3)
.every(l => !layer.filterSubLayer({layer: l})),
'Sublayers at z=3 are hidden'
);
}
Expand Down Expand Up @@ -186,7 +193,11 @@ test('TileLayer#MapView:repeat', async t => {
},
onAfterUpdate: ({layer, subLayers}) => {
if (layer.isLoaded) {
t.is(subLayers.filter(l => l.props.visible).length, 4, 'Should contain 4 visible tiles');
t.is(
subLayers.filter(l => layer.filterSubLayer({layer: l})).length,
4,
'Should contain 4 visible tiles'
);
}
}
}
Expand Down

0 comments on commit e225cd3

Please sign in to comment.