Skip to content

Commit cfa6c44

Browse files
evil159jakra-mb
authored andcommitted
Rename screen shape (#3377)
### GL native * Rename screen shape to screen culling shape * Use Vec2 instead of screen coordinate * Remove culling shape from init options ### Maps iOS * Expose API to set screen culling shape | iOS | Android | | --- | --- | | <video src="https://github.com/user-attachments/assets/e3d4acb8-01b1-4c53-ba76-8e05ff085426"> | <video src="https://github.com/user-attachments/assets/33122660-65ba-4f31-8eae-d180fe630c14"> | Addresses: https://mapbox.atlassian.net/browse/MAPSIOS-1811 and https://mapbox.atlassian.net/browse/MAPSAND-2119 cc @mapbox/sdk-ci --------- Co-authored-by: Jan Krassnigg <[email protected]> GitOrigin-RevId: 68a34816e8e5bacf61a119eb2503fc2cba59337c
1 parent 71bb90e commit cfa6c44

File tree

11 files changed

+194
-3
lines changed

11 files changed

+194
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Mapbox welcomes participation and contributions from everyone.
55
# main
66
## Features ✨ and improvements 🏁
77
* Expose `RenderThreadStatsRecorder` as experimental API.
8+
* Expose an experimental API to define a non-rectangular screen culling shape(`MapboxMap.get/setScreenCullingShape`)
89

910

1011
# 11.12.0-rc.1

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ License: [The Apache Software License, Version 2.0](http://www.apache.org/licens
482482

483483
===========================================================================
484484

485-
### MapboxCoreMaps,11.13.0-SNAPSHOT-04-23--04-29.git-3eea307,Mapbox ToS,Mapbox,https://www.mapbox.com/
485+
### MapboxCoreMaps,11.13.0-SNAPSHOT-04-23--05-20.git-ad48dc8,Mapbox ToS,Mapbox,https://www.mapbox.com/
486486

487487
```
488488
Mapbox Core Maps version 11.0

app/src/main/java/com/mapbox/maps/testapp/examples/DebugModeActivity.kt

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
package com.mapbox.maps.testapp.examples
22

33
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.graphics.BlurMaskFilter
6+
import android.graphics.Canvas
7+
import android.graphics.Color
8+
import android.graphics.CornerPathEffect
9+
import android.graphics.Paint
10+
import android.graphics.Path
11+
import android.graphics.PorterDuff
12+
import android.graphics.PorterDuffXfermode
413
import android.os.Bundle
514
import android.view.Menu
615
import android.view.MenuItem
16+
import android.view.View
17+
import android.view.ViewGroup
718
import android.widget.TextView
819
import androidx.appcompat.app.AppCompatActivity
920
import com.google.android.material.snackbar.Snackbar
@@ -13,6 +24,7 @@ import com.mapbox.maps.MapboxMap
1324
import com.mapbox.maps.PerformanceSamplerOptions
1425
import com.mapbox.maps.PerformanceStatisticsOptions
1526
import com.mapbox.maps.Style
27+
import com.mapbox.maps.Vec2
1628
import com.mapbox.maps.debugoptions.MapViewDebugOptions
1729
import com.mapbox.maps.logE
1830
import com.mapbox.maps.logI
@@ -58,10 +70,40 @@ class DebugModeActivity : AppCompatActivity() {
5870

5971
mapboxMap.loadStyle(Style.STANDARD)
6072
setupPerformanceStatisticsCollection()
73+
setupScreenShapeButton()
6174
binding.mapView.compass.opacity = 0.5f
6275
binding.mapView.debugOptions = debugOptions
6376
registerListeners(mapboxMap)
6477
}
78+
private var overlayView: HexSpotlightView? = null
79+
80+
private fun setupScreenShapeButton() {
81+
binding.screenShapeButton.setOnClickListener {
82+
when (binding.screenShapeButton.text) {
83+
SCREEN_SHAPE_RECT -> {
84+
binding.screenShapeButton.text = SCREEN_SHAPE_CUSTOM
85+
86+
mapboxMap.setScreenCullingShape(emptyList())
87+
(overlayView?.parent as? ViewGroup)?.removeView(overlayView)
88+
}
89+
SCREEN_SHAPE_CUSTOM -> {
90+
val shape = listOf(
91+
Vec2(0.35, 0.34),
92+
Vec2(0.65, 0.34),
93+
Vec2(0.85, 0.50),
94+
Vec2(0.65, 0.66),
95+
Vec2(0.35, 0.66),
96+
Vec2(0.15, 0.50)
97+
)
98+
99+
overlayView = HexSpotlightView(this, shape)
100+
addContentView(overlayView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
101+
mapboxMap.setScreenCullingShape(shape)
102+
binding.screenShapeButton.text = SCREEN_SHAPE_RECT
103+
}
104+
}
105+
}
106+
}
65107

66108
private fun setupPerformanceStatisticsCollection() {
67109
binding.perfStatButton.setOnClickListener {
@@ -229,5 +271,71 @@ class DebugModeActivity : AppCompatActivity() {
229271
private const val TAG_PERFORMANCE_STATISTICS = "PerformanceStatistics"
230272
private const val PERF_STAT_STOP_COLLECT_BUTTON = "Stop collecting"
231273
private const val PERF_STAT_START_COLLECT_BUTTON = "Collect Perf Stats"
274+
private const val SCREEN_SHAPE_CUSTOM = "Hex screen"
275+
private const val SCREEN_SHAPE_RECT = "Rect screen"
276+
}
277+
}
278+
279+
@SuppressLint("ViewConstructor")
280+
class HexSpotlightView(context: Context, private val shape: List<Vec2>) : View(context) {
281+
282+
private val overlayPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
283+
color = Color.parseColor("#80000000") // dimmed background
284+
}
285+
286+
private val clearPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
287+
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
288+
}
289+
290+
private val strokePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
291+
color = Color.WHITE
292+
style = Paint.Style.STROKE
293+
strokeWidth = 4F * context.resources.displayMetrics.density
294+
strokeJoin = Paint.Join.ROUND
295+
pathEffect = CornerPathEffect(12F * context.resources.displayMetrics.density)
296+
}
297+
private var hexPath: Path = createPath(width.toFloat(), height.toFloat())
298+
299+
private val glowPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
300+
color = Color.WHITE
301+
style = Paint.Style.STROKE
302+
strokeWidth = 4F * context.resources.displayMetrics.density
303+
maskFilter = BlurMaskFilter(32F, BlurMaskFilter.Blur.OUTER)
304+
strokeJoin = Paint.Join.ROUND
305+
pathEffect = CornerPathEffect(12F * context.resources.displayMetrics.density)
306+
}
307+
308+
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
309+
super.onLayout(changed, left, top, right, bottom)
310+
311+
hexPath = createPath(width.toFloat(), height.toFloat())
312+
}
313+
314+
override fun onDraw(canvas: Canvas) {
315+
super.onDraw(canvas)
316+
317+
val layer = canvas.saveLayer(null, null)
318+
319+
// Draw full dim overlay
320+
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), overlayPaint)
321+
322+
// Draw hexagon cutout
323+
canvas.drawPath(hexPath, clearPaint)
324+
canvas.drawPath(hexPath, glowPaint)
325+
canvas.drawPath(hexPath, glowPaint)
326+
canvas.drawPath(hexPath, strokePaint)
327+
328+
canvas.restoreToCount(layer)
329+
}
330+
331+
private fun createPath(w: Float, h: Float): Path {
332+
val path = Path()
333+
shape.forEachIndexed { index, pt ->
334+
val x = pt.x * w
335+
val y = pt.y * h
336+
if (index == 0) path.moveTo(x.toFloat(), y.toFloat()) else path.lineTo(x.toFloat(), y.toFloat())
337+
}
338+
path.close()
339+
return path
232340
}
233341
}

app/src/main/res/layout/activity_debug.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,17 @@
5151
app:layout_constraintBottom_toBottomOf="parent"
5252
tools:ignore="HardcodedText" />
5353

54+
<Button
55+
android:id="@+id/screenShapeButton"
56+
android:layout_width="wrap_content"
57+
android:layout_height="wrap_content"
58+
android:padding="10dp"
59+
android:textSize="18sp"
60+
android:text="Hex screen"
61+
android:layout_marginEnd="12dp"
62+
android:layout_marginBottom="12dp"
63+
app:layout_constraintEnd_toEndOf="parent"
64+
app:layout_constraintBottom_toBottomOf="parent"
65+
tools:ignore="HardcodedText" />
66+
5467
</androidx.constraintlayout.widget.ConstraintLayout>

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ japicmp = "0.4.1"
3535
# Dependencies
3636

3737
# GlNative and Common are used by the convention plugin
38-
mapboxGlNative = "11.13.0-SNAPSHOT-04-23--04-29.git-3eea307"
39-
mapboxCommon = "24.13.0-SNAPSHOT-04-23--04-29.git-3eea307"
38+
mapboxGlNative = "11.13.0-SNAPSHOT-04-23--05-20.git-ad48dc8"
39+
mapboxCommon = "24.13.0-SNAPSHOT-04-23--05-20.git-ad48dc8"
4040

4141
mapboxBase = "0.11.0"
4242
mapboxGestures = "0.8.0"

maps-sdk/api/Release/metalava.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ package com.mapbox.maps {
226226
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @com.mapbox.maps.MapboxDelicateApi @com.mapbox.maps.MapboxExperimental public com.mapbox.maps.Map getNativeMap();
227227
method public byte getPrefetchZoomDelta();
228228
method public boolean getRenderWorldCopies();
229+
method @com.mapbox.maps.MapboxExperimental public java.util.List<com.mapbox.maps.Vec2> getScreenCullingShape();
229230
method public com.mapbox.maps.Size getSize();
230231
method public com.mapbox.maps.Style? getStyle();
231232
method public void getStyle(com.mapbox.maps.Style.OnStyleLoaded onStyleLoaded);
@@ -315,6 +316,7 @@ package com.mapbox.maps {
315316
method public void setNorthOrientation(com.mapbox.maps.NorthOrientation northOrientation);
316317
method public void setPrefetchZoomDelta(byte delta);
317318
method public void setRenderWorldCopies(boolean renderWorldCopies);
319+
method @com.mapbox.maps.MapboxExperimental public void setScreenCullingShape(java.util.List<com.mapbox.maps.Vec2> shape);
318320
method public void setTileCacheBudget(com.mapbox.maps.TileCacheBudget? tileCacheBudget);
319321
method public void setUserAnimationInProgress(boolean inProgress);
320322
method public void setViewportMode(com.mapbox.maps.ViewportMode viewportMode);

maps-sdk/api/maps-sdk.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ public final class com/mapbox/maps/MapboxMap : com/mapbox/maps/MapboxStyleManage
226226
public final fun getNativeMap ()Lcom/mapbox/maps/Map;
227227
public final fun getPrefetchZoomDelta ()B
228228
public final fun getRenderWorldCopies ()Z
229+
public final fun getScreenCullingShape ()Ljava/util/List;
229230
public fun getSize ()Lcom/mapbox/maps/Size;
230231
public final fun getStyle ()Lcom/mapbox/maps/Style;
231232
public final fun getStyle (Lcom/mapbox/maps/Style$OnStyleLoaded;)V
@@ -314,6 +315,7 @@ public final class com/mapbox/maps/MapboxMap : com/mapbox/maps/MapboxStyleManage
314315
public fun setNorthOrientation (Lcom/mapbox/maps/NorthOrientation;)V
315316
public final fun setPrefetchZoomDelta (B)V
316317
public final fun setRenderWorldCopies (Z)V
318+
public final fun setScreenCullingShape (Ljava/util/List;)V
317319
public final fun setTileCacheBudget (Lcom/mapbox/maps/TileCacheBudget;)V
318320
public fun setUserAnimationInProgress (Z)V
319321
public fun setViewportMode (Lcom/mapbox/maps/ViewportMode;)V

maps-sdk/src/main/java/com/mapbox/maps/MapboxMap.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,35 @@ class MapboxMap :
23232323
return nativeMap.getRenderWorldCopies()
23242324
}
23252325

2326+
/**
2327+
* A convex polygon that describes the shape of the screen in case it is non-rectangular.
2328+
* Every coordinate is in 0 to 1 range, with (0, 0) being the map view top-left and (1, 1) the bottom-right.
2329+
* The points have to be given in clockwise winding order. The polygon will be closed automatically, so for a rectangular shape, pass in 4 points.
2330+
* Use this, if the visible screen area is obscured enough that using a custom shape improves performance.
2331+
*
2332+
* @param shape shape of the screen
2333+
*
2334+
*/
2335+
@MapboxExperimental
2336+
fun setScreenCullingShape(shape: List<Vec2>) {
2337+
checkNativeMap("setScreenCullingShape")
2338+
return nativeMap.setScreenCullingShape(shape)
2339+
}
2340+
2341+
/**
2342+
* A convex polygon that describes the shape of the screen in case it is non-rectangular.
2343+
* Every screen-coordinate is in 0 to 1 range, with (0, 0) being top-left and (1, 1) bottom-right.
2344+
* The points have to be given in clockwise winding order. The polygon will be closed automatically, so for a rectangular shape, pass in 4 points.
2345+
* Use this if the visible screen area is obscured enough that using a custom shape improves performance.
2346+
*
2347+
* @return shape of the screen
2348+
*/
2349+
@MapboxExperimental
2350+
fun getScreenCullingShape(): List<Vec2> {
2351+
checkNativeMap("getScreenCullingShape")
2352+
return nativeMap.getScreenCullingShape()
2353+
}
2354+
23262355
/**
23272356
* Enable real-time collection of map rendering performance statistics, for development purposes. Use after `render()` has
23282357
* been called for the first time.

maps-sdk/src/main/java/com/mapbox/maps/NativeMapImpl.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,14 @@ internal class NativeMapImpl(val map: Map) {
706706
return map.centerAltitudeMode
707707
}
708708

709+
fun setScreenCullingShape(shape: List<Vec2>) {
710+
map.screenCullingShape = shape
711+
}
712+
713+
fun getScreenCullingShape(): List<Vec2> {
714+
return map.screenCullingShape
715+
}
716+
709717
fun startPerformanceStatisticsCollection(
710718
options: PerformanceStatisticsOptions,
711719
callback: PerformanceStatisticsCallback,

maps-sdk/src/test/java/com/mapbox/maps/MapboxMapTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,19 @@ class PixelForCoordinatesTest(
18871887
assertEquals(expected, screenCoordinates)
18881888
}
18891889

1890+
@Test
1891+
fun getScreenCullingShape() {
1892+
mapboxMap.getScreenCullingShape()
1893+
verify { nativeMap.getScreenCullingShape() }
1894+
}
1895+
1896+
@Test
1897+
fun setScreenShape() {
1898+
val shape = mockk<List<Vec2>>()
1899+
mapboxMap.setScreenCullingShape(shape)
1900+
verify { nativeMap.setScreenCullingShape(shape) }
1901+
}
1902+
18901903
@After
18911904
fun cleanUp() {
18921905
unmockkStatic(Map::class)

0 commit comments

Comments
 (0)