Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow CompositeLayer to filter sub layers during redraw #5820

Merged
merged 3 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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