Skip to content

Commit 4dfb7c0

Browse files
aleksprogergithub-actions[bot]
authored andcommitted
Support visibility in clip-layer (internal-9237)
GitOrigin-RevId: 30bf83053e59386fcb0680d67b25194b6210b125
1 parent 118fc88 commit 4dfb7c0

6 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/render/painter.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -938,15 +938,22 @@ class Painter {
938938
// This order is later used by fill-extrusion and instanced tree's rendering code to know
939939
// how to deal with landmarks.
940940
order = layerIdx;
941-
for (const mask of layer.layout.get('clip-layer-types')) {
942-
clipMask |= (mask === 'model' ? LayerTypeMask.Model : (mask === 'symbol' ? LayerTypeMask.Symbol : LayerTypeMask.FillExtrusion));
943-
}
944-
for (const scope of layer.layout.get('clip-layer-scope')) {
945-
clipScope.push(scope);
946-
}
947941
if (layer.isHidden(this.transform.zoom)) {
948942
addToSources = false;
949943
} else {
944+
// Hidden layers may not have been recalculated this frame, so `layer.layout`
945+
// can be undefined. Only access evaluated layout when we know the clip layer
946+
// is active for this frame.
947+
if (!layer.layout) {
948+
addToSources = false;
949+
continue;
950+
}
951+
for (const mask of layer.layout.get('clip-layer-types')) {
952+
clipMask |= (mask === 'model' ? LayerTypeMask.Model : (mask === 'symbol' ? LayerTypeMask.Symbol : LayerTypeMask.FillExtrusion));
953+
}
954+
for (const scope of layer.layout.get('clip-layer-scope')) {
955+
clipScope.push(scope);
956+
}
950957
clippingActiveThisFrame = true;
951958
}
952959
}

src/style-spec/reference/v8.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,30 @@
19041904
"interpolated": false
19051905
},
19061906
"property-type": "data-constant"
1907+
},
1908+
"visibility": {
1909+
"type": "enum",
1910+
"values": {
1911+
"visible": {
1912+
"doc": "The layer is shown."
1913+
},
1914+
"none": {
1915+
"doc": "The layer is not shown."
1916+
}
1917+
},
1918+
"default": "visible",
1919+
"doc": "Whether this layer is displayed.",
1920+
"sdk-support": {
1921+
"basic functionality": {
1922+
"js": "3.18.0",
1923+
"android": "11.18.0",
1924+
"ios": "11.18.0"
1925+
}
1926+
},
1927+
"expression": {
1928+
"interpolated": false
1929+
},
1930+
"property-type": "data-constant"
19071931
}
19081932
},
19091933
"layout_fill": {

src/style-spec/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,8 @@ export type ClipLayerSpecification = {
15331533
"filter"?: FilterSpecification,
15341534
"layout"?: {
15351535
"clip-layer-types"?: Array<"model" | "symbol"> | ExpressionSpecification,
1536-
"clip-layer-scope"?: Array<string> | ExpressionSpecification
1536+
"clip-layer-scope"?: Array<string> | ExpressionSpecification,
1537+
"visibility"?: "visible" | "none" | ExpressionSpecification
15371538
},
15381539
/**
15391540
* @experimental This property is experimental and subject to change in future versions.

src/style/style_layer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class StyleLayer extends Evented {
218218

219219
possiblyEvaluateVisibility() {
220220
if (!this._unevaluatedLayout._values.visibility) {
221-
// Early return for layers which don't have a visibility property, like clip-layer
221+
// Early return for layers which don't have a visibility property.
222222
return;
223223
}
224224
// @ts-expect-error - TS2322 - Type 'unknown' is not assignable to type '"none" | "visible"'. | TS2345 - Argument of type '{ zoom: number; }' is not assignable to parameter of type 'EvaluationParameters'.

src/style/style_layer/clip_style_layer_properties.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ import type {StylePropertySpecification} from '../../style-spec/style-spec';
1919
export type LayoutProps = {
2020
"clip-layer-types": DataConstantProperty<Array<"model" | "symbol">>;
2121
"clip-layer-scope": DataConstantProperty<Array<string>>;
22+
"visibility": DataConstantProperty<"visible" | "none">;
2223
};
2324
let layout: Properties<LayoutProps>;
2425
export const getLayoutProperties = (): Properties<LayoutProps> => layout || (layout = new Properties({
2526
"clip-layer-types": new DataConstantProperty(styleSpec["layout_clip"]["clip-layer-types"]),
2627
"clip-layer-scope": new DataConstantProperty(styleSpec["layout_clip"]["clip-layer-scope"]),
28+
"visibility": new DataConstantProperty(styleSpec["layout_clip"]["visibility"]),
2729
}));
2830

2931
export type PaintProps = {};

test/unit/style/style_layer.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ describe('StyleLayer#setLayoutProperty', () => {
207207
layer.setLayoutProperty('visibility', 'none');
208208
expect(layer.getLayoutProperty('visibility')).toEqual('none');
209209
});
210+
211+
test('updates visibility for clip layer', () => {
212+
const layer = createStyleLayer({
213+
id: 'clip',
214+
type: 'clip',
215+
source: 'composite',
216+
layout: {
217+
visibility: 'none'
218+
}
219+
});
220+
221+
expect(layer.getLayoutProperty('visibility')).toEqual('none');
222+
expect(layer.isHidden(0)).toBeTruthy();
223+
});
210224
});
211225

212226
describe('StyleLayer#serialize', () => {

0 commit comments

Comments
 (0)