diff --git a/api/android-for-maptiler.api b/api/android-for-maptiler.api index 8cac437..fbed037 100644 --- a/api/android-for-maptiler.api +++ b/api/android-for-maptiler.api @@ -169,6 +169,7 @@ public final class com.mapconductor.maptiler.MapTilerOverlayStacking { public static final com.mapconductor.maptiler.MapTilerOverlayStacking INSTANCE; public final com.mapconductor.core.controller.OverlayStacking$Key key(com.mapconductor.core.controller.OverlayKind, int); public final com.mapconductor.core.controller.OverlayStacking$Key getMARKER_TILE(); + public final com.mapconductor.core.controller.OverlayStacking$Key getPOLYGON_TILE(); public final void add(com.maptiler.maptilersdk.map.style.MTStyle, com.maptiler.maptilersdk.map.style.layer.MTLayer, com.mapconductor.core.controller.OverlayStacking$Key); public final void remove(com.maptiler.maptilersdk.map.style.MTStyle, java.lang.String); public final void onIdle(com.maptiler.maptilersdk.map.style.MTStyle); diff --git a/src/main/java/com/mapconductor/maptiler/MapTilerMapViewController.kt b/src/main/java/com/mapconductor/maptiler/MapTilerMapViewController.kt index 2293d98..156bb05 100644 --- a/src/main/java/com/mapconductor/maptiler/MapTilerMapViewController.kt +++ b/src/main/java/com/mapconductor/maptiler/MapTilerMapViewController.kt @@ -17,7 +17,10 @@ import com.mapconductor.core.marker.MarkerState import com.mapconductor.core.marker.MarkerTilingOptions import com.mapconductor.core.marker.OnMarkerEventHandler import com.mapconductor.core.polygon.OnPolygonEventHandler +import com.mapconductor.core.polygon.POLYGON_TILE_LAYER_ID import com.mapconductor.core.polygon.PolygonCapableInterface +import com.mapconductor.core.polygon.PolygonTiler +import com.mapconductor.core.polygon.polygonTileRasterLayerState import com.mapconductor.core.polyline.OnPolylineEventHandler import com.mapconductor.core.polyline.PolylineCapableInterface import com.mapconductor.core.polyline.PolylineState @@ -316,6 +319,19 @@ class MapTilerMapViewController( registerOverlayController(polygonController) registerOverlayController(circleController) registerOverlayController(groundImageController) + + // Many polygons are drawn as raster tiles, shown through the same RasterLayer + // controller as the marker tiles (upsert / removeById, never the app's layers). + polygonController.tiler = + PolygonTiler().apply { + onTemplate = { template, tileSize -> + if (template != null) { + rasterLayerController.upsert(polygonTileRasterLayerState(template, tileSize)) + } else { + rasterLayerController.removeById(POLYGON_TILE_LAYER_ID) + } + } + } // ホルダーの同期投影にカメラを供給する。ホルダーはコントローラより先に作られるので // ここで繋ぐ。これが無いと toScreenOffset が常に null を返し、InfoBubble と // マーカー追従が理由も出ずに落ちる(android-for-longdo と同じ)。 diff --git a/src/main/java/com/mapconductor/maptiler/MapTilerOverlayStacking.kt b/src/main/java/com/mapconductor/maptiler/MapTilerOverlayStacking.kt index 41d5fe1..18f9e7c 100644 --- a/src/main/java/com/mapconductor/maptiler/MapTilerOverlayStacking.kt +++ b/src/main/java/com/mapconductor/maptiler/MapTilerOverlayStacking.kt @@ -49,6 +49,9 @@ internal object MapTilerOverlayStacking { /** マーカーのタイル: マーカーの帯の一番下。 */ val MARKER_TILE = key(OverlayKind.Marker, Int.MIN_VALUE) + /** ポリゴンのタイル: ポリゴンの帯の一番下。 */ + val POLYGON_TILE = key(OverlayKind.Polygon, Int.MIN_VALUE) + fun add( style: MTStyle, layer: MTLayer, diff --git a/src/main/java/com/mapconductor/maptiler/polygon/MapTilerPolygonController.kt b/src/main/java/com/mapconductor/maptiler/polygon/MapTilerPolygonController.kt index 49a1e87..743d080 100644 --- a/src/main/java/com/mapconductor/maptiler/polygon/MapTilerPolygonController.kt +++ b/src/main/java/com/mapconductor/maptiler/polygon/MapTilerPolygonController.kt @@ -18,6 +18,8 @@ class MapTilerPolygonController( * 既知のポリゴンを再適用する(地図 `ready` 後の復元用)。 */ fun reapply() { - renderer.reapply(polygonManager.allEntities().map { it.polygon }) + // Polygons drawn as tiles (PolygonController.tiler) have no handle. + @Suppress("USELESS_CAST") + renderer.reapply(polygonManager.allEntities().mapNotNull { it.polygon as MapTilerPolygonHandle? }) } } diff --git a/src/main/java/com/mapconductor/maptiler/raster/MapTilerRasterLayerOverlayRenderer.kt b/src/main/java/com/mapconductor/maptiler/raster/MapTilerRasterLayerOverlayRenderer.kt index 41740a5..1f79a5e 100644 --- a/src/main/java/com/mapconductor/maptiler/raster/MapTilerRasterLayerOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/maptiler/raster/MapTilerRasterLayerOverlayRenderer.kt @@ -1,6 +1,7 @@ package com.mapconductor.maptiler.raster import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.polygon.POLYGON_TILE_LAYER_ID import com.mapconductor.core.raster.RasterHeaderRuleSet import com.mapconductor.core.raster.RasterLayerEntityInterface import com.mapconductor.core.raster.RasterLayerOverlayRendererInterface @@ -56,7 +57,11 @@ class MapTilerRasterLayerOverlayRenderer( val next = params.current.state if (prev.state.source != next.source) { removeLayer(prev) - addLayer(next) + // Under new ids: the removal above is not applied before the + // add below, which then fails with "Source already exists" and + // leaves the layer gone. The marker and polygon tiles change + // source on every in-place change. + addLayer(next, generation = ++replacements) } else { updatePaint(prev.layer, next) prev.layer @@ -80,20 +85,32 @@ class MapTilerRasterLayerOverlayRenderer( } } + /** Counts source replacements, so each one gets ids of its own. */ + private var replacements = 0 + /** 層の id → zIndex(帯の中の順)。handle は公開型なので持たせずここで覚える。 */ private val zIndexByLayer = java.util.concurrent.ConcurrentHashMap() - /** ラスターの帯(一番下)。マーカーのタイルはマーカーの帯の一番下。 */ + /** + * ラスターの帯(一番下)。マーカーのタイルはマーカーの帯の一番下、 + * ポリゴンのタイルはポリゴンの帯の一番下(画像になったポリゴンであって、地図の画像ではない)。 + */ private fun stackKey(layerId: String) = if (layerId.startsWith("raster-layer-marker-tile-")) { MapTilerOverlayStacking.MARKER_TILE + } else if (layerId.startsWith("raster-layer-$POLYGON_TILE_LAYER_ID")) { + MapTilerOverlayStacking.POLYGON_TILE } else { MapTilerOverlayStacking.key(OverlayKind.RasterLayer, zIndexByLayer[layerId] ?: 0) } - private fun addLayer(state: RasterLayerState): MapTilerRasterLayerHandle? { - val sourceId = "raster-source-${state.id}" - val layerId = "raster-layer-${state.id}" + private fun addLayer( + state: RasterLayerState, + generation: Int = 0, + ): MapTilerRasterLayerHandle? { + val suffix = if (generation == 0) "" else "-$generation" + val sourceId = "raster-source-${state.id}$suffix" + val layerId = "raster-layer-${state.id}$suffix" zIndexByLayer[layerId] = state.zIndex val source = buildSource(sourceId, state.source) ?: return null @@ -140,6 +157,7 @@ class MapTilerRasterLayerOverlayRenderer( // id で外すと MTStyle の記録が残り、同じ id で戻せなくなる(MapTilerStyleRemoval.kt)。 // ソースを替えるとき(onChange)も同じ id で足し直すので、ここで記録まで消す。 MapTilerOverlayStacking.remove(style, handle.layer.identifier) + zIndexByLayer.remove(handle.layer.identifier) style.removeLayerAndForget(handle.layer) style.removeSourceAndForget(handle.source) }