Skip to content

Commit

Permalink
[compose] Terrain support (mapbox#2427)
Browse files Browse the repository at this point in the history
* Compose Terrain support

* PR fixes

* Treat the terrain dem source fully as a layer

---------

Co-authored-by: Ramon <[email protected]>
  • Loading branch information
kiryldz and jush authored May 8, 2024
1 parent 58cd435 commit eaca4f4
Show file tree
Hide file tree
Showing 14 changed files with 627 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Mapbox welcomes participation and contributions from everyone.
## Features ✨ and improvements 🏁
* [compose] Add `StyleImage` to construct following image layer properties: `IconImage`, `FillPattern`, `LinePattern`, `BearingImage`, `ShadowImage`, `TopImage`.
* [compose] Add `ModelId` constructor to add model id and uri.
* [compose] Add `TerrainState` parameter to `GenericStyle`, `MapStyle` and `MapboxStandardStyle` composable functions.
* Add experimental `RasterParticleLayer` in Style DSL and Compose.

## Bug fixes 🐞
Expand Down
10 changes: 10 additions & 0 deletions compose-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,16 @@
android:name="@string/category"
android:value="@string/category_styles" />
</activity>
<activity
android:name=".examples.style.TerrainActivity"
android:description="@string/description_terrain"
android:exported="true"
android:label="@string/activity_terrain"
android:parentActivityName=".ExampleOverviewActivity">
<meta-data
android:name="@string/category"
android:value="@string/category_styles" />
</activity>
<activity
android:name=".examples.style.AnimatedImageSourceActivity"
android:description="@string/description_animated_image_source"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.mapbox.maps.compose.testapp.examples.style

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.mapbox.geojson.Point
import com.mapbox.maps.MapboxExperimental
import com.mapbox.maps.Style
import com.mapbox.maps.compose.testapp.ExampleScaffold
import com.mapbox.maps.compose.testapp.ui.theme.MapboxMapComposeTheme
import com.mapbox.maps.extension.compose.MapboxMap
import com.mapbox.maps.extension.compose.animation.viewport.MapViewportState
import com.mapbox.maps.extension.compose.style.GenericStyle
import com.mapbox.maps.extension.compose.style.sources.generated.TileSize
import com.mapbox.maps.extension.compose.style.sources.generated.Url
import com.mapbox.maps.extension.compose.style.sources.generated.rememberRasterDemSourceState
import com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration
import com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState
import com.mapbox.maps.extension.compose.style.terrain.generated.rememberTerrainState

/**
* Example to showcase usage of terrain.
*/
@OptIn(MapboxExperimental::class)
public class TerrainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {

val rasterDemSourceState = rememberRasterDemSourceState().apply {
url = Url(TERRAIN_URL_TILE_RESOURCE)
tileSize = TileSize(TILE_SIZE)
}

val customTerrainState = rememberTerrainState(rasterDemSourceState)

var currentTerrainState by rememberSaveable(stateSaver = TerrainState.Saver) {
mutableStateOf(customTerrainState)
}

MapboxMapComposeTheme {
ExampleScaffold(
floatingActionButton = {
Column {
FloatingActionButton(
modifier = Modifier.padding(bottom = 10.dp),
backgroundColor = if (currentTerrainState == TerrainState.disabled) Color.LightGray else MaterialTheme.colors.secondary,
onClick = {
val currentExaggeration =
(currentTerrainState.exaggeration.value.contents as? Double) ?: 1.0
currentTerrainState.exaggeration = Exaggeration(currentExaggeration + 0.2)
},
shape = RoundedCornerShape(16.dp),
) {
Text(modifier = Modifier.padding(10.dp), text = "Increase exaggeration")
}
FloatingActionButton(
modifier = Modifier.padding(bottom = 10.dp),
onClick = {
currentTerrainState = if (currentTerrainState == TerrainState.disabled) {
customTerrainState
} else {
TerrainState.disabled
}
},
shape = RoundedCornerShape(16.dp),
) {
Text(
modifier = Modifier.padding(10.dp),
text = if (currentTerrainState == TerrainState.disabled)
"Enable terrain"
else
"Disable terrain"
)
}
}
}
) {
MapboxMap(
Modifier.fillMaxSize(),
mapViewportState = MapViewportState().apply {
setCameraOptions {
zoom(ZOOM)
center(CENTER)
pitch(PITCH)
}
},
style = {
GenericStyle(
style = Style.SATELLITE_STREETS,
terrainState = currentTerrainState
)
}
)
}
}
}
}

private companion object {
private const val TILE_SIZE = 514L
private const val ZOOM: Double = 11.0
private const val PITCH: Double = 80.0
private val CENTER = Point.fromLngLat(138.7274, 35.3606)
private const val TERRAIN_URL_TILE_RESOURCE = "mapbox://mapbox.mapbox-terrain-dem-v1"
}
}
1 change: 1 addition & 0 deletions compose-app/src/main/res/values/example_descriptions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
<string name="description_model_layer">Showcase the usage of a 3D model layer.</string>
<string name="description_style_image_source">Use an image source to easily display images on the map.</string>
<string name="description_animated_image_source">Load a raster image to a style using ImageSource and display it on a map as animated weather data using RasterLayer.</string>
<string name="description_terrain">Add terrain on top of raster-dem source</string>
</resources>
1 change: 1 addition & 0 deletions compose-app/src/main/res/values/example_titles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
<string name="activity_model_layer">Display 3D model in a model layer</string>
<string name="activity_style_image_source_title">Use an image source</string>
<string name="activity_animated_image_source">Add animated weather data</string>
<string name="activity_terrain">Terrain</string>
</resources>
66 changes: 63 additions & 3 deletions extension-compose/api/Release/metalava.txt
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ package com.mapbox.maps.extension.compose.style {
}

public final class StyleKt {
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void GenericStyle(String style, com.mapbox.maps.extension.compose.style.SlotsContent slotsContent = com.mapbox.maps.extension.compose.style.SlotsContent(), com.mapbox.maps.extension.compose.style.LayerPositionedContent layerPositionedContent = com.mapbox.maps.extension.compose.style.LayerPositionedContent(), com.mapbox.maps.extension.compose.style.StyleImportsConfig styleImportsConfig = com.mapbox.maps.extension.compose.style.StyleImportsConfig(), com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default);
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void MapStyle(String style, com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default);
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void GenericStyle(String style, com.mapbox.maps.extension.compose.style.SlotsContent slotsContent = com.mapbox.maps.extension.compose.style.SlotsContent(), com.mapbox.maps.extension.compose.style.LayerPositionedContent layerPositionedContent = com.mapbox.maps.extension.compose.style.LayerPositionedContent(), com.mapbox.maps.extension.compose.style.StyleImportsConfig styleImportsConfig = com.mapbox.maps.extension.compose.style.StyleImportsConfig(), com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default, com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState terrainState = TerrainState.initial);
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void MapStyle(String style, com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default, com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState terrainState = TerrainState.initial);
method @com.mapbox.maps.MapboxExperimental public static com.mapbox.maps.extension.compose.style.LayerPositionedContent layerPositionedContent(kotlin.jvm.functions.Function1<? super com.mapbox.maps.extension.compose.style.LayerPositionedContent,kotlin.Unit> init);
method @com.mapbox.maps.MapboxExperimental public static com.mapbox.maps.extension.compose.style.SlotsContent slotsContent(kotlin.jvm.functions.Function1<? super com.mapbox.maps.extension.compose.style.SlotsContent,kotlin.Unit> init);
method @com.mapbox.maps.MapboxExperimental public static com.mapbox.maps.extension.compose.style.StyleImportsConfig styleImportsConfig(kotlin.jvm.functions.Function1<? super com.mapbox.maps.extension.compose.style.StyleImportsConfig,kotlin.Unit> init);
Expand Down Expand Up @@ -4862,7 +4862,67 @@ package com.mapbox.maps.extension.compose.style.standard {
}

public final class MapboxStandardStyleKt {
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void MapboxStandardStyle(kotlin.jvm.functions.Function0<kotlin.Unit>? topSlot = null, kotlin.jvm.functions.Function0<kotlin.Unit>? middleSlot = null, kotlin.jvm.functions.Function0<kotlin.Unit>? bottomSlot = null, com.mapbox.maps.extension.compose.style.standard.LightPreset lightPreset = LightPreset.default, com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default);
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental @com.mapbox.maps.extension.compose.style.MapboxStyleComposable public static void MapboxStandardStyle(kotlin.jvm.functions.Function0<kotlin.Unit>? topSlot = null, kotlin.jvm.functions.Function0<kotlin.Unit>? middleSlot = null, kotlin.jvm.functions.Function0<kotlin.Unit>? bottomSlot = null, com.mapbox.maps.extension.compose.style.standard.LightPreset lightPreset = LightPreset.default, com.mapbox.maps.extension.compose.style.projection.Projection projection = Projection.default, com.mapbox.maps.extension.compose.style.atmosphere.generated.AtmosphereState atmosphereState = AtmosphereState.default, com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState terrainState = TerrainState.initial);
}

}

package com.mapbox.maps.extension.compose.style.terrain {

public final class TerrainStateApplierKt {
}

}

package com.mapbox.maps.extension.compose.style.terrain.generated {

@androidx.compose.runtime.Immutable @com.mapbox.maps.MapboxExperimental public final class Exaggeration {
ctor public Exaggeration(com.mapbox.bindgen.Value value);
ctor public Exaggeration(double value);
ctor public Exaggeration(com.mapbox.maps.extension.style.expressions.generated.Expression expression);
method public com.mapbox.bindgen.Value component1();
method public com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration copy(com.mapbox.bindgen.Value value);
method public com.mapbox.bindgen.Value getValue();
property public final com.mapbox.bindgen.Value value;
field public static final com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration.Companion Companion;
}

public static final class Exaggeration.Companion {
method public com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration getDefault();
property public final com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration default;
}

@com.mapbox.maps.MapboxExperimental public final class TerrainState {
ctor public TerrainState(com.mapbox.maps.extension.compose.style.sources.generated.RasterDemSourceState rasterDemSourceState, java.util.Map<java.lang.String,? extends com.mapbox.bindgen.Value> initialProperties = mapOf());
method public com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration getExaggeration();
method public void setExaggeration(com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration);
property public final com.mapbox.maps.extension.compose.style.terrain.generated.Exaggeration exaggeration;
field public static final com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState.Companion Companion;
}

public static final class TerrainState.Companion {
method public com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState getDisabled();
method public androidx.compose.runtime.saveable.Saver<com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState,com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState.Holder> getSaver();
property public final androidx.compose.runtime.saveable.Saver<com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState,com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState.Holder> Saver;
property public final com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState disabled;
}

@com.mapbox.maps.MapboxExperimental @kotlinx.parcelize.Parcelize @kotlinx.parcelize.TypeParceler public static final class TerrainState.Holder implements android.os.Parcelable {
ctor public TerrainState.Holder(com.mapbox.maps.extension.compose.style.sources.SourceState.Holder? rasterDemSourceStateHolder, java.util.Map<java.lang.String,? extends com.mapbox.bindgen.Value> cachedProperties, boolean initial);
method public com.mapbox.maps.extension.compose.style.sources.SourceState.Holder? component1();
method public java.util.Map<java.lang.String,com.mapbox.bindgen.Value> component2();
method public boolean component3();
method public com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState.Holder copy(com.mapbox.maps.extension.compose.style.sources.SourceState.Holder? rasterDemSourceStateHolder, java.util.Map<java.lang.String,? extends com.mapbox.bindgen.Value> cachedProperties, boolean initial);
method public java.util.Map<java.lang.String,com.mapbox.bindgen.Value> getCachedProperties();
method public boolean getInitial();
method public com.mapbox.maps.extension.compose.style.sources.SourceState.Holder? getRasterDemSourceStateHolder();
property public final java.util.Map<java.lang.String,com.mapbox.bindgen.Value> cachedProperties;
property public final boolean initial;
property public final com.mapbox.maps.extension.compose.style.sources.SourceState.Holder? rasterDemSourceStateHolder;
}

public final class TerrainStateKt {
method @androidx.compose.runtime.Composable @com.mapbox.maps.MapboxExperimental public static inline com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState rememberTerrainState(com.mapbox.maps.extension.compose.style.sources.generated.RasterDemSourceState rasterDemSourceState, String? key = null, kotlin.jvm.functions.Function1<? super com.mapbox.maps.extension.compose.style.terrain.generated.TerrainState,kotlin.Unit> init = {});
}

}
Expand Down
Loading

0 comments on commit eaca4f4

Please sign in to comment.