diff options
author | Tobrun <tobrun@mapbox.com> | 2017-05-26 16:04:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-26 16:04:09 +0200 |
commit | 5716bd3aecc777813161292e104ac9ceba3f230a (patch) | |
tree | d9a791ddbb1821e90fe7efcd1578dea0402af07a /platform/android | |
parent | c392c678ab4ea560cefca59d14b215e2d4c79ecb (diff) | |
download | qtlocation-mapboxgl-5716bd3aecc777813161292e104ac9ceba3f230a.tar.gz |
[android] - add binding support for Light (#9013)
Diffstat (limited to 'platform/android')
30 files changed, 1557 insertions, 22 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle index 05037c6be7..e0bc076d3d 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle +++ b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle @@ -15,6 +15,7 @@ task checkstyle(type: Checkstyle) { exclude '**/style/layers/Property.java' exclude '**/style/layers/PropertyFactory.java' exclude '**/style/layers/*Layer.java' + exclude '**/style/light/Light.java' classpath = files() ignoreFailures = false } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index 96603355f1..0bfa74d1c0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -41,6 +41,7 @@ import com.mapbox.mapboxsdk.location.LocationSource; import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings; import com.mapbox.mapboxsdk.style.layers.Filter; import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.light.Light; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.services.android.telemetry.location.LocationEngine; import com.mapbox.services.commons.geojson.Feature; @@ -568,6 +569,20 @@ public final class MapboxMap { } // + // + // + + /** + * Get the global light source used to change lighting conditions on extruded fill layers. + * + * @return the global light source + */ + @Nullable + public Light getLight() { + return nativeMapView.getLight(); + } + + // // Camera API // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index cf8faa9012..008a1971cc 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -26,6 +26,7 @@ import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException; import com.mapbox.mapboxsdk.style.layers.Filter; import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.light.Light; import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.services.commons.geojson.Feature; @@ -885,6 +886,13 @@ final class NativeMapView { fileSource.setApiBaseUrl(baseUrl); } + public Light getLight() { + if (isDestroyedOn("getLight")) { + return null; + } + return nativeGetLight(); + } + public float getPixelRatio() { return pixelRatio; } @@ -1120,6 +1128,8 @@ final class NativeMapView { String[] layerIds, Object[] filter); + private native Light nativeGetLight(); + int getWidth() { if (isDestroyedOn("")) { return 0; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java index 48e0ec5de3..5e345268f9 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java @@ -467,6 +467,27 @@ public final class Property { @Retention(RetentionPolicy.SOURCE) public @interface FILL_EXTRUSION_TRANSLATE_ANCHOR {} + // ANCHOR: Whether extruded geometries are lit relative to the map or viewport. + + /** + * The position of the light source is aligned to the rotation of the map. + */ + public static final String ANCHOR_MAP = "map"; + /** + * The position of the light source is aligned to the rotation of the viewport. + */ + public static final String ANCHOR_VIEWPORT = "viewport"; + + /** + * Whether extruded geometries are lit relative to the map or viewport. + */ + @StringDef({ + ANCHOR_MAP, + ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ANCHOR {} + private Property() { } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java new file mode 100644 index 0000000000..b66a50b8a4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java @@ -0,0 +1,181 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +package com.mapbox.mapboxsdk.style.light; + +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.UiThread; + +import com.mapbox.mapboxsdk.style.layers.Property; +import com.mapbox.mapboxsdk.style.layers.PropertyFactory; +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; + +/** + * The global light source. + * + * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#light>">The online documentation</a> + */ +@UiThread +public class Light { + + private long nativePtr; + + /** + * Creates a Light. + * + * @param nativePtr pointer used by core + */ + public Light(long nativePtr) { + this.nativePtr = nativePtr; + } + + /** + * Set the Anchor property. Whether extruded geometries are lit relative to the map or viewport. + * + * @param anchor as String + */ + public void setAnchor(@Property.ANCHOR String anchor) { + nativeSetAnchor(anchor); + } + + /** + * Get the Anchor property. Whether extruded geometries are lit relative to the map or viewport. + * + * @return anchor as String + */ + @Property.ANCHOR public String getAnchor() { + return nativeGetAnchor(); + } + + /** + * Set the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0° (0° when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0° when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0°, directly above, to 180°, directly below). + * + * @param position of the light + */ + public void setPosition(@NonNull Position position) { + nativeSetPosition(position); + } + + /** + * Get the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0° (0° when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0° when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0°, directly above, to 180°, directly below). + * + * @return position as Position + */ + public Position getPosition() { + return nativeGetPosition(); + } + + /** + * Get the Position property transition options. + * + * @return transition options for position + */ + public TransitionOptions getPositionTransition() { + return nativeGetPositionTransition(); + } + + /** + * Set the Position property transition options. + * + * @param options transition options for position + */ + public void setPositionTransition(TransitionOptions options) { + nativeSetPositionTransition(options.getDuration(), options.getDelay()); + } + + /** + * Set the Color property. Color tint for lighting extruded geometries. + * + * @param color as int + */ + public void setColor(@ColorInt int color) { + nativeSetColor(PropertyFactory.colorToRgbaString(color)); + } + + /** + * Set the Color property. Color tint for lighting extruded geometries. + * + * @param color as String + */ + public void setColor(String color) { + nativeSetColor(color); + } + + /** + * Get the Color property. Color tint for lighting extruded geometries. + * + * @return color as String + */ + public String getColor() { + return nativeGetColor(); + } + + /** + * Get the Color property transition options. + * + * @return transition options for color + */ + public TransitionOptions getColorTransition() { + return nativeGetColorTransition(); + } + + /** + * Set the Color property transition options. + * + * @param options transition options for color + */ + public void setColorTransition(TransitionOptions options) { + nativeSetColorTransition(options.getDuration(), options.getDelay()); + } + + /** + * Set the Intensity property. Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast. + * + * @param intensity as Float + */ + public void setIntensity(float intensity) { + nativeSetIntensity(intensity); + } + + /** + * Get the Intensity property. Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast. + * + * @return intensity as Float + */ + public float getIntensity() { + return nativeGetIntensity(); + } + + /** + * Get the Intensity property transition options. + * + * @return transition options for intensity + */ + public TransitionOptions getIntensityTransition() { + return nativeGetIntensityTransition(); + } + + /** + * Set the Intensity property transition options. + * + * @param options transition options for intensity + */ + public void setIntensityTransition(TransitionOptions options) { + nativeSetIntensityTransition(options.getDuration(), options.getDelay()); + } + + private native void nativeSetAnchor(String anchor); + private native String nativeGetAnchor(); + private native void nativeSetPosition(Position position); + private native Position nativeGetPosition(); + private native TransitionOptions nativeGetPositionTransition(); + private native void nativeSetPositionTransition(long duration, long delay); + private native void nativeSetColor(String color); + private native String nativeGetColor(); + private native TransitionOptions nativeGetColorTransition(); + private native void nativeSetColorTransition(long duration, long delay); + private native void nativeSetIntensity(float intensity); + private native float nativeGetIntensity(); + private native TransitionOptions nativeGetIntensityTransition(); + private native void nativeSetIntensityTransition(long duration, long delay); +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java new file mode 100644 index 0000000000..215db03ad2 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java @@ -0,0 +1,81 @@ +package com.mapbox.mapboxsdk.style.light; + +/** + * Position of the light source relative to lit (extruded) geometries. + * <p> + * The position is constructed out of a radial coordinate, an azimuthal angle and a polar angle. + * where the radial coordinate indicates the distance from the center of the base of an object to its light, the + * azimuthal angle indicates the position of the light relative to 0° (0° when + * {@link com.mapbox.mapboxsdk.style.layers.Property.ANCHOR} is set to viewport corresponds to the top of the + * viewport, or 0° when {@link com.mapbox.mapboxsdk.style.layers.Property.ANCHOR} is set to map corresponds to due + * north, and degrees proceed clockwise), and polar indicates the height of the light + * (from 0°, directly above, to 180°, directly below). + */ +public class Position { + + private float radialCoordinate; + private float azimuthalAngle; + private float polarAngle; + + /** + * Creates a Position from a radial coordinate, an azimuthal angle & a polar angle. + * + * @param radialCoordinate the distance from the center of the base of an object to its light + * @param azimuthalAngle the position of the light relative to 0° + * @param polarAngle the height of the light + */ + public Position(float radialCoordinate, float azimuthalAngle, float polarAngle) { + this.radialCoordinate = radialCoordinate; + this.azimuthalAngle = azimuthalAngle; + this.polarAngle = polarAngle; + } + + /** + * Returns a Position from a radial coordinate, an azimuthal angle & a polar angle + * + * @param radialCoordinate the radial coordinate + * @param azimuthalAngle the azimuthal angle + * @param polarAngle the polar angle + * @return the created Position object + */ + public static Position fromPosition(float radialCoordinate, float azimuthalAngle, float polarAngle) { + return new Position(radialCoordinate, azimuthalAngle, polarAngle); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Position position = (Position) o; + + if (Float.compare(position.radialCoordinate, radialCoordinate) != 0) { + return false; + } + if (Float.compare(position.azimuthalAngle, azimuthalAngle) != 0) { + return false; + } + return Float.compare(position.polarAngle, polarAngle) == 0; + } + + @Override + public int hashCode() { + int result = (radialCoordinate != +0.0f ? Float.floatToIntBits(radialCoordinate) : 0); + result = 31 * result + (azimuthalAngle != +0.0f ? Float.floatToIntBits(azimuthalAngle) : 0); + result = 31 * result + (polarAngle != +0.0f ? Float.floatToIntBits(polarAngle) : 0); + return result; + } + + @Override + public String toString() { + return "Position{" + + "radialCoordinate=" + radialCoordinate + + ", azimuthalAngle=" + azimuthalAngle + + ", polarAngle=" + polarAngle + + '}'; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs new file mode 100644 index 0000000000..067efe1092 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs @@ -0,0 +1,121 @@ +<% + const properties = locals.properties; + const doc = locals.doc; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +package com.mapbox.mapboxsdk.style.light; + +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.UiThread; + +import com.mapbox.mapboxsdk.style.layers.Property; +import com.mapbox.mapboxsdk.style.layers.PropertyFactory; +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; + +/** + * The global light source. + * + * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#light>">The online documentation</a> + */ +@UiThread +public class Light { + + private long nativePtr; + + /** + * Creates a Light. + * + * @param nativePtr pointer used by core + */ + public Light(long nativePtr) { + this.nativePtr = nativePtr; + } +<% for (const property of properties) { -%> +<% if (property.name == "position") {-%> + + /** + * Set the <%- camelize(property.name) %> property. <%- property.doc %> + * + * @param position of the light + */ + public void set<%- camelize(property.name) %>(@NonNull Position position) { + nativeSet<%- camelize(property.name) %>(position); + } + + /** + * Get the <%- camelize(property.name) %> property. <%- property.doc %> + * + * @return <%- property.name %> as Position + */ + public Position get<%- camelize(property.name) %>() { + return nativeGet<%- camelize(property.name) %>(); + } +<% } else { -%> +<% if (property.name == "color") {-%> + + /** + * Set the <%- camelize(property.name) %> property. <%- property.doc %> + * + * @param <%- property.name %> as int + */ + public void set<%- camelize(property.name) %>(@ColorInt int <%- property.name %>) { + nativeSet<%- camelize(property.name) %>(PropertyFactory.colorToRgbaString(<%- property.name %>)); + } +<% } -%> + + /** + * Set the <%- camelize(property.name) %> property. <%- property.doc %> + * + * @param <%- property.name %> as <%- propertyType(property) %> + */ + public void set<%- camelize(property.name) %>(<%- propertyTypeAnnotation(property) %><%- iff(() => propertyTypeAnnotation(property), " ") %><%- propertyJavaType(property) %> <%- property.name %>) { + nativeSet<%- camelize(property.name) %>(<%- property.name %>); + } + + /** + * Get the <%- camelize(property.name) %> property. <%- property.doc %> + * + * @return <%- property.name %> as <%- propertyType(property) %> + */ + <%- propertyTypeAnnotation(property) %> public <%- propertyJavaType(property) %> get<%- camelize(property.name) %>() { + return nativeGet<%- camelize(property.name) %>(); + } +<% } -%> +<% if (property.transition) { -%> + + /** + * Get the <%- camelize(property.name) %> property transition options. + * + * @return transition options for <%- property.name %> + */ + public TransitionOptions get<%- camelize(property.name) %>Transition() { + return nativeGet<%- camelize(property.name) %>Transition(); + } + + /** + * Set the <%- camelize(property.name) %> property transition options. + * + * @param options transition options for <%- property.name %> + */ + public void set<%- camelize(property.name) %>Transition(TransitionOptions options) { + nativeSet<%- camelize(property.name) %>Transition(options.getDuration(), options.getDelay()); + } +<% } -%> +<% } -%> + +<% for (const property of properties) { -%> +<% if (property.name == "position") {-%> + private native void nativeSet<%- camelize(property.name) %>(Position position); + private native Position nativeGet<%- camelize(property.name) %>(); +<% } else { -%> + private native void nativeSet<%- camelize(property.name) %>(<%- propertyJavaType(property) -%> <%- property.name %>); + private native <%- propertyJavaType(property) -%> nativeGet<%- camelize(property.name) %>(); +<% } -%> +<% if (property.transition) { -%> + private native TransitionOptions nativeGet<%- camelize(property.name) %>Transition(); + private native void nativeSet<%- camelize(property.name) %>Transition(long duration, long delay); +<% } -%> +<% } -%> +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java new file mode 100644 index 0000000000..36833fb4ee --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java @@ -0,0 +1,162 @@ +package com.mapbox.mapboxsdk.testapp.style; + +import android.graphics.Color; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.runner.AndroidJUnit4; +import android.view.View; + +import com.mapbox.mapboxsdk.style.light.Light; +import com.mapbox.mapboxsdk.style.functions.Function; +import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops; +import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer; +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; +import com.mapbox.mapboxsdk.style.light.Position; +import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest; +import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity; + +import timber.log.Timber; + +import org.hamcrest.Matcher; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static com.mapbox.mapboxsdk.style.layers.Filter.eq; +import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + +@RunWith(AndroidJUnit4.class) +public class LightTest extends BaseActivityTest { + + private Light light; + + @Test + public void testAnchor() { + validateTestSetup(); + setupLayer(); + Timber.i("anchor"); + assertNotNull(light); + // Set and Get + light.setAnchor(ANCHOR_MAP); + assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor()); + } + + @Test + public void testPositionTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("positionTransitionOptions"); + assertNotNull(light); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + light.setPositionTransition(options); + assertEquals("Transition options should match", options, light.getPositionTransition()); + } + + @Test + public void testPosition() { + validateTestSetup(); + setupLayer(); + Timber.i("position"); + assertNotNull(light); + + // Set and Get + Position position = new Position(1,2,3); + light.setPosition(position); + assertEquals("Position should match", position, light.getPosition()); + } + + @Test + public void testColorTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("colorTransitionOptions"); + assertNotNull(light); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + light.setColorTransition(options); + assertEquals("Transition options should match", options, light.getColorTransition()); + } + + @Test + public void testColor() { + validateTestSetup(); + setupLayer(); + Timber.i("color"); + assertNotNull(light); + // Set and Get + light.setColor("rgba(0, 0, 0, 1)"); + assertEquals("Color should match", "rgba(0, 0, 0, 1)".replaceAll("\\s+",""), light.getColor()); + } + + @Test + public void testIntensityTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("intensityTransitionOptions"); + assertNotNull(light); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + light.setIntensityTransition(options); + assertEquals("Transition options should match", options, light.getIntensityTransition()); + } + + @Test + public void testIntensity() { + validateTestSetup(); + setupLayer(); + Timber.i("intensity"); + assertNotNull(light); + // Set and Get + light.setIntensity(0.3f); + assertEquals("Intensity should match", 0.3f, light.getIntensity()); + } + + private void setupLayer() { + onView(withId(R.id.mapView)).perform(new ViewAction() { + @Override + public Matcher<View> getConstraints() { + return isDisplayed(); + } + + @Override + public String getDescription() { + return getClass().getSimpleName(); + } + + @Override + public void perform(UiController uiController, View view) { + light = mapboxMap.getLight(); + FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite"); + fillExtrusionLayer.setSourceLayer("building"); + fillExtrusionLayer.setFilter(eq("extrude", "true")); + fillExtrusionLayer.setMinZoom(15); + fillExtrusionLayer.setProperties( + fillExtrusionColor(Color.LTGRAY), + fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())), + fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())), + fillExtrusionOpacity(0.6f) + ); + mapboxMap.addLayer(fillExtrusionLayer); + } + }); + } + + @Override + protected Class getActivityClass() { + return FillExtrusionStyleTestActivity.class; + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs new file mode 100644 index 0000000000..cb3ba58100 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs @@ -0,0 +1,128 @@ +<% + const properties = locals.properties; +-%> +package com.mapbox.mapboxsdk.testapp.style; + +import android.graphics.Color; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.runner.AndroidJUnit4; +import android.view.View; + +import com.mapbox.mapboxsdk.style.light.Light; +import com.mapbox.mapboxsdk.style.functions.Function; +import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops; +import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer; +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; +import com.mapbox.mapboxsdk.style.light.Position; +import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest; +import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity; + +import timber.log.Timber; + +import org.hamcrest.Matcher; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static com.mapbox.mapboxsdk.style.layers.Filter.eq; +import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + +@RunWith(AndroidJUnit4.class) +public class LightTest extends BaseActivityTest { + + private Light light; +<% for (const property of properties) { -%> +<% if (property.transition) { -%> + + @Test + public void test<%- camelize(property.name) %>Transition() { + validateTestSetup(); + setupLayer(); + Timber.i("<%- property.name %>TransitionOptions"); + assertNotNull(light); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + light.set<%- camelize(property.name) %>Transition(options); + assertEquals("Transition options should match", options, light.get<%- camelize(property.name) %>Transition()); + } +<% } -%> +<% if (property.name == "position") { -%> + + @Test + public void test<%- camelize(property.name) %>() { + validateTestSetup(); + setupLayer(); + Timber.i("<%- property.name %>"); + assertNotNull(light); + + // Set and Get + Position position = new Position(1,2,3); + light.set<%- camelize(property.name) %>(position); + assertEquals("Position should match", position, light.get<%- camelize(property.name) %>()); + } +<% } else { -%> + + @Test + public void test<%- camelize(property.name) %>() { + validateTestSetup(); + setupLayer(); + Timber.i("<%- property.name %>"); + assertNotNull(light); + // Set and Get + light.set<%- camelize(property.name) %>(<%- defaultValueJava(property) %>); +<% if (property.name == 'color') { -%> + assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>.replaceAll("\\s+",""), light.get<%- camelize(property.name) %>()); +<% } else { -%> + assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>, light.get<%- camelize(property.name) %>()); +<% } -%> + } +<% } -%> +<% } -%> + + private void setupLayer() { + onView(withId(R.id.mapView)).perform(new ViewAction() { + @Override + public Matcher<View> getConstraints() { + return isDisplayed(); + } + + @Override + public String getDescription() { + return getClass().getSimpleName(); + } + + @Override + public void perform(UiController uiController, View view) { + light = mapboxMap.getLight(); + FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite"); + fillExtrusionLayer.setSourceLayer("building"); + fillExtrusionLayer.setFilter(eq("extrude", "true")); + fillExtrusionLayer.setMinZoom(15); + fillExtrusionLayer.setProperties( + fillExtrusionColor(Color.LTGRAY), + fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())), + fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())), + fillExtrusionOpacity(0.6f) + ); + mapboxMap.addLayer(fillExtrusionLayer); + } + }); + } + + @Override + protected Class getActivityClass() { + return FillExtrusionStyleTestActivity.class; + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index 9ede763533..1a70e4548a 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -661,7 +661,9 @@ <activity android:name=".activity.espresso.EspressoTestActivity" android:screenOrientation="portrait"/> - + <activity + android:name=".activity.style.FillExtrusionStyleTestActivity" + android:screenOrientation="portrait"/> <!-- Configuration Settings --> <meta-data android:name="com.mapbox.TestEventsServer" diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java index f444aa40f0..def7d1678a 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java @@ -4,6 +4,9 @@ import android.graphics.Color; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; @@ -11,6 +14,10 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.style.functions.Function; import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops; import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer; +import com.mapbox.mapboxsdk.style.layers.Property; +import com.mapbox.mapboxsdk.style.layers.PropertyFactory; +import com.mapbox.mapboxsdk.style.light.Light; +import com.mapbox.mapboxsdk.style.light.Position; import com.mapbox.mapboxsdk.testapp.R; import static com.mapbox.mapboxsdk.style.layers.Filter.eq; @@ -25,6 +32,13 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpa public class BuildingFillExtrusionActivity extends AppCompatActivity { private MapView mapView; + private MapboxMap mapboxMap; + private Light light; + + private boolean isMapAnchorLight; + private boolean isLowIntensityLight; + private boolean isRedColor; + private boolean isInitPosition; @Override public void onCreate(Bundle savedInstanceState) { @@ -35,21 +49,72 @@ public class BuildingFillExtrusionActivity extends AppCompatActivity { mapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(@NonNull final MapboxMap map) { - FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite"); - fillExtrusionLayer.setSourceLayer("building"); - fillExtrusionLayer.setFilter(eq("extrude", "true")); - fillExtrusionLayer.setMinZoom(15); - fillExtrusionLayer.setProperties( - fillExtrusionColor(Color.LTGRAY), - fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())), - fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())), - fillExtrusionOpacity(0.6f) - ); - map.addLayer(fillExtrusionLayer); + mapboxMap = map; + setupBuildings(); + setupLight(); } }); } + private void setupBuildings() { + FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite"); + fillExtrusionLayer.setSourceLayer("building"); + fillExtrusionLayer.setFilter(eq("extrude", "true")); + fillExtrusionLayer.setMinZoom(15); + fillExtrusionLayer.setProperties( + fillExtrusionColor(Color.LTGRAY), + fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())), + fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())), + fillExtrusionOpacity(0.9f) + ); + mapboxMap.addLayer(fillExtrusionLayer); + } + + private void setupLight() { + light = mapboxMap.getLight(); + + findViewById(R.id.fabLightPosition).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isInitPosition = !isInitPosition; + if (isInitPosition) { + light.setPosition(new Position(1.5f, 90, 80)); + } else { + light.setPosition(new Position(1.15f, 210, 30)); + } + } + }); + + findViewById(R.id.fabLightColor).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isRedColor = !isRedColor; + light.setColor(PropertyFactory.colorToRgbaString(isRedColor ? Color.RED : Color.BLUE)); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_building, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (light != null) { + int id = item.getItemId(); + if (id == R.id.menu_action_anchor) { + isMapAnchorLight = !isMapAnchorLight; + light.setAnchor(isMapAnchorLight ? Property.ANCHOR_MAP : Property.ANCHOR_VIEWPORT); + } else if (id == R.id.menu_action_intensity) { + isLowIntensityLight = !isLowIntensityLight; + light.setIntensity(isLowIntensityLight ? 0.35f : 1.0f); + } + } + return super.onOptionsItemSelected(item); + } + @Override protected void onStart() { super.onStart(); @@ -91,5 +156,4 @@ public class BuildingFillExtrusionActivity extends AppCompatActivity { super.onDestroy(); mapView.onDestroy(); } - } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java new file mode 100644 index 0000000000..1ff0b0e8e1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java @@ -0,0 +1,78 @@ +package com.mapbox.mapboxsdk.testapp.activity.style; + + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.testapp.R; + +public class FillExtrusionStyleTestActivity extends AppCompatActivity { + + public MapView mapView; + private MapboxMap mapboxMap; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_extrusion_test); + + // Initialize map as normal + mapView = (MapView) findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(new OnMapReadyCallback() { + @Override + public void onMapReady(MapboxMap mapboxMap) { + FillExtrusionStyleTestActivity.this.mapboxMap = mapboxMap; + } + }); + } + + public MapboxMap getMapboxMap() { + return mapboxMap; + } + + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_paint.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_paint.xml new file mode 100644 index 0000000000..f9e55e1480 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_paint.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M18,4V3c0,-0.55 -0.45,-1 -1,-1H5c-0.55,0 -1,0.45 -1,1v4c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1V6h1v4H9v11c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-9h8V4h-3z"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_building_layer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_building_layer.xml index d9a10871b5..fa37c485d7 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_building_layer.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_building_layer.xml @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> + android:layout_height="match_parent"> <com.mapbox.mapboxsdk.maps.MapView android:id="@id/mapView" @@ -13,6 +12,27 @@ app:mapbox_cameraTargetLng="-74.0066" app:mapbox_cameraTilt="45" app:mapbox_cameraZoom="15" - app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"/> + app:mapbox_styleUrl="@string/mapbox_style_dark"/> -</RelativeLayout> + <android.support.design.widget.FloatingActionButton + android:id="@+id/fabLightPosition" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_marginBottom="82dp" + android:layout_marginRight="@dimen/fab_margin" + android:layout_marginEnd="@dimen/fab_margin" + android:src="@drawable/ic_my_location" + app:backgroundTint="@color/accent" + app:layout_anchorGravity="top"/> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fabLightColor" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_margin="@dimen/fab_margin" + android:src="@drawable/ic_paint" + app:backgroundTint="@color/primary"/> + +</FrameLayout> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_extrusion_test.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_extrusion_test.xml new file mode 100644 index 0000000000..d9a10871b5 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_extrusion_test.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:mapbox_cameraTargetLat="40.7135" + app:mapbox_cameraTargetLng="-74.0066" + app:mapbox_cameraTilt="45" + app:mapbox_cameraZoom="15" + app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"/> + +</RelativeLayout> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_building.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_building.xml new file mode 100644 index 0000000000..92d1dd5380 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_building.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/menu_action_intensity" + android:title="Change intensity" + app:showAsAction="never"/> + <item + android:id="@+id/menu_action_anchor" + android:title="Change Anchor" + app:showAsAction="never"/> +</menu> diff --git a/platform/android/config.cmake b/platform/android/config.cmake index c111744ed0..84591d644b 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -168,6 +168,10 @@ add_library(mbgl-android STATIC platform/android/src/style/functions/identity_stops.hpp platform/android/src/style/functions/interval_stops.cpp platform/android/src/style/functions/interval_stops.hpp + platform/android/src/style/position.cpp + platform/android/src/style/position.hpp + platform/android/src/style/light.cpp + platform/android/src/style/light.hpp # FileSource holder platform/android/src/file_source.cpp diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js index 5d8fc4cc6d..bb04e3ba2a 100644 --- a/platform/android/scripts/generate-style-code.js +++ b/platform/android/scripts/generate-style-code.js @@ -8,6 +8,13 @@ const _ = require('lodash'); require('../../../scripts/style-code'); // Specification parsing // +const lightProperties = Object.keys(spec[`light`]).reduce((memo, name) => { + var property = spec[`light`][name]; + property.name = name; + property['light-property'] = true; + memo.push(property); + return memo; +}, []); // Collect layer types from spec var layers = Object.keys(spec.layer.type.values).map((type) => { @@ -37,7 +44,7 @@ var layers = Object.keys(spec.layer.type.values).map((type) => { // Process all layer properties const layoutProperties = _(layers).map('layoutProperties').flatten().value(); const paintProperties = _(layers).map('paintProperties').flatten().value(); -const allProperties = _(layoutProperties).union(paintProperties).value(); +const allProperties = _(layoutProperties).union(paintProperties).union(lightProperties).value(); const enumProperties = _(allProperties).filter({'type': 'enum'}).value(); global.propertyType = function propertyType(property) { @@ -59,12 +66,31 @@ global.propertyType = function propertyType(property) { } } +global.propertyJavaType = function propertyType(property) { + switch (property.type) { + case 'boolean': + return 'boolean'; + case 'number': + return 'float'; + case 'string': + return 'String'; + case 'enum': + return 'String'; + case 'color': + return 'String'; + case 'array': + return `${propertyJavaType({type:property.value})}[]`; + default: + throw new Error(`unknown type for ${property.name}`); + } + } + global.propertyJNIType = function propertyJNIType(property) { switch (property.type) { case 'boolean': return 'jboolean'; - case 'jfloat': - return 'Float'; + case 'number': + return 'jfloat'; case 'String': return 'String'; case 'enum': @@ -93,6 +119,9 @@ global.propertyNativeType = function (property) { case 'string': return 'std::string'; case 'enum': + if(property['light-property']){ + return `Light${camelize(property.name)}Type`; + } return `${camelize(property.name)}Type`; case 'color': return `Color`; @@ -215,6 +244,53 @@ global.propertyValueDoc = function (property, value) { return doc; }; +global.isDataDriven = function (property) { + return property['property-function'] === true; +}; + +global.isLightProperty = function (property) { + return property['light-property'] === true; +}; + +global.propertyValueType = function (property) { + if (isDataDriven(property)) { + return `DataDrivenPropertyValue<${evaluatedType(property)}>`; + } else { + return `PropertyValue<${evaluatedType(property)}>`; + } +}; + +global.evaluatedType = function (property) { + if (/-translate-anchor$/.test(property.name)) { + return 'TranslateAnchorType'; + } + if (/-(rotation|pitch|illumination)-alignment$/.test(property.name)) { + return 'AlignmentType'; + } + if (/position/.test(property.name)) { + return 'Position'; + } + switch (property.type) { + case 'boolean': + return 'bool'; + case 'number': + return 'float'; + case 'string': + return 'std::string'; + case 'enum': + return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`; + case 'color': + return `Color`; + case 'array': + if (property.length) { + return `std::array<${evaluatedType({type: property.value})}, ${property.length}>`; + } else { + return `std::vector<${evaluatedType({type: property.value})}>`; + } + default: throw new Error(`unknown type for ${property.name}`) + } +}; + global.supportsZoomFunction = function (property) { return property['zoom-function'] === true; }; @@ -225,6 +301,16 @@ global.supportsPropertyFunction = function (property) { // Template processing // +// Java + JNI Light (Peer model) +const lightHpp = ejs.compile(fs.readFileSync('platform/android/src/style/light.hpp.ejs', 'utf8'), {strict: true});; +const lightCpp = ejs.compile(fs.readFileSync('platform/android/src/style/light.cpp.ejs', 'utf8'), {strict: true});; +const lightJava = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs', 'utf8'), {strict: true}); +const lightJavaUnitTests = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs', 'utf8'), {strict: true}); +writeIfModified(`platform/android/src/style/light.hpp`, lightHpp({properties: lightProperties})); +writeIfModified(`platform/android/src/style/light.cpp`, lightCpp({properties: lightProperties})); +writeIfModified(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java`, lightJava({properties: lightProperties})); +writeIfModified(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java`, lightJavaUnitTests({properties: lightProperties})); + // Java + JNI Layers (Peer model) const layerHpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.hpp.ejs', 'utf8'), {strict: true}); const layerCpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.cpp.ejs', 'utf8'), {strict: true}); @@ -238,7 +324,6 @@ for (const layer of layers) { writeIfModified(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/${camelize(layer.type)}LayerTest.java`, layerJavaUnitTests(layer)); } - // Java PropertyFactory const propertiesTemplate = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs', 'utf8'), {strict: true}); writeIfModified( diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 53691acb39..6c490fad5c 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -45,6 +45,7 @@ #include "style/functions/stop.hpp" #include "style/layers/layers.hpp" #include "style/sources/sources.hpp" +#include "style/light.hpp" namespace mbgl { namespace android { @@ -153,6 +154,8 @@ void registerNatives(JavaVM *vm) { TransitionOptions::registerNative(env); registerNativeLayers(env); registerNativeSources(env); + Light::registerNative(env); + Position::registerNative(env); Stop::registerNative(env); CategoricalStops::registerNative(env); ExponentialStops::registerNative(env); diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 1012a0e9d8..0a57d3e6b4 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -46,6 +46,7 @@ #include "java/util.hpp" #include "geometry/lat_lng_bounds.hpp" #include "map/camera_position.hpp" +#include "style/light.hpp" namespace mbgl { namespace android { @@ -819,6 +820,15 @@ jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesFo return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); } +jni::Object<Light> NativeMapView::getLight(JNIEnv& env) { + mbgl::style::Light* light = map->getLight(); + if (light) { + return jni::Object<Light>(Light::createJavaLightPeer(env, *map, *light)); + } else { + return jni::Object<Light>(); + } +} + jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) { // Get the core layers @@ -1533,6 +1543,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::queryPointAnnotations, "nativeQueryPointAnnotations"), METHOD(&NativeMapView::queryRenderedFeaturesForPoint, "nativeQueryRenderedFeaturesForPoint"), METHOD(&NativeMapView::queryRenderedFeaturesForBox, "nativeQueryRenderedFeaturesForBox"), + METHOD(&NativeMapView::getLight, "nativeGetLight"), METHOD(&NativeMapView::getLayers, "nativeGetLayers"), METHOD(&NativeMapView::getLayer, "nativeGetLayer"), METHOD(&NativeMapView::addLayer, "nativeAddLayer"), diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index e5fcb9badd..df43ad08b7 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -24,6 +24,7 @@ #include "style/sources/sources.hpp" #include "geometry/lat_lng_bounds.hpp" #include "map/camera_position.hpp" +#include "style/light.hpp" #include <exception> #include <string> @@ -230,6 +231,8 @@ public: jni::jfloat, jni::Array<jni::String>, jni::Array<jni::Object<>> jfilter); + jni::Object<Light> getLight(JNIEnv&); + jni::Array<jni::Object<Layer>> getLayers(JNIEnv&); jni::Object<Layer> getLayer(JNIEnv&, jni::String); diff --git a/platform/android/src/style/conversion/position.hpp b/platform/android/src/style/conversion/position.hpp new file mode 100644 index 0000000000..f32a892c0c --- /dev/null +++ b/platform/android/src/style/conversion/position.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "../../conversion/conversion.hpp" + +#include <jni/jni.hpp> +#include <mbgl/style/position.hpp> +#include "../../jni/local_object.hpp" +#include "../position.hpp" + +namespace mbgl { +namespace android { +namespace conversion { + +template<> +struct Converter<jni::Object<Position>, mbgl::style::Position> { + Result<jni::Object<Position>> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const { + std::array<float, 3> cartPosition = value.getSpherical(); + return Position::fromPosition(env, cartPosition[0], cartPosition[1], cartPosition[2]); + } +}; + +template<> +struct Converter<mbgl::style::Position, jni::Object<Position>> { + Result<mbgl::style::Position> operator()(jni::JNIEnv &env, const jni::Object<Position> &value) const { + float radialCoordinate = Position::getRadialCoordinate(env, value); + float azimuthalAngle = Position::getAzimuthalAngle(env, value); + float polarAngle = Position::getPolarAngle(env, value); + std::array<float, 3> cartPosition {{radialCoordinate, azimuthalAngle, polarAngle}}; + mbgl::style::Position position{}; + position.set(cartPosition); + return position; + } +}; + +} +} +}
\ No newline at end of file diff --git a/platform/android/src/style/conversion/types.hpp b/platform/android/src/style/conversion/types.hpp index d9921e582e..a00f668c24 100644 --- a/platform/android/src/style/conversion/types.hpp +++ b/platform/android/src/style/conversion/types.hpp @@ -92,6 +92,13 @@ struct Converter<jni::jobject*, mbgl::style::CirclePitchScaleType> { } }; +template <> +struct Converter<jni::jobject*, mbgl::style::LightAnchorType> { + Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::LightAnchorType& value) const { + return convert<jni::jobject*, std::string>(env, toString(value)); + } +}; + } // namespace conversion } // namespace android diff --git a/platform/android/src/style/conversion/types_string_values.hpp b/platform/android/src/style/conversion/types_string_values.hpp index e3108fdf5b..e96de3b01e 100644 --- a/platform/android/src/style/conversion/types_string_values.hpp +++ b/platform/android/src/style/conversion/types_string_values.hpp @@ -206,6 +206,20 @@ namespace conversion { } } + // anchor + inline std::string toString(mbgl::style::LightAnchorType value) { + switch (value) { + case mbgl::style::LightAnchorType::Map: + return "map"; + break; + case mbgl::style::LightAnchorType::Viewport: + return "viewport"; + break; + default: + throw std::runtime_error("Not implemented"); + } + } + } // namespace conversion } // namespace android diff --git a/platform/android/src/style/light.cpp b/platform/android/src/style/light.cpp new file mode 100644 index 0000000000..71f1cb076e --- /dev/null +++ b/platform/android/src/style/light.cpp @@ -0,0 +1,146 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#include <mbgl/map/map.hpp> +#include "light.hpp" +#include "conversion/transition_options.hpp" +#include "conversion/position.hpp" + +namespace mbgl { +namespace android { + +Light::Light(mbgl::Map& coreMap, mbgl::style::Light& coreLight) + : light(coreLight) , map(&coreMap) { +} + +static Light* initializeLightPeer(mbgl::Map& map, mbgl::style::Light& coreLight) { + return new Light(map, coreLight); +} + +jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { + std::unique_ptr<Light> peerLight = std::unique_ptr<Light>(initializeLightPeer(map, coreLight)); + jni::jobject* result = peerLight->createJavaPeer(env); + peerLight.release(); + return result; +} + +jni::Class<Light> Light::javaClass; + +jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { + static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); + return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); +} + +void Light::setAnchor(jni::JNIEnv& env, jni::String property) { + std::string anchorStr = jni::Make<std::string>(env, property); + if (anchorStr.compare("map") == 0) { + light.setAnchor(LightAnchorType::Map); + } else if (anchorStr.compare("viewport") == 0) { + light.setAnchor(LightAnchorType::Viewport); + } +} + +jni::String Light::getAnchor(jni::JNIEnv& env) { + auto anchorType = light.getAnchor(); + if (anchorType == LightAnchorType::Map) { + return jni::Make<jni::String>(env, "map"); + } else { + return jni::Make<jni::String>(env, "viewport"); + } +} + +void Light::setPosition(jni::JNIEnv& env, jni::Object<Position> jposition) { + using namespace mbgl::android::conversion; + auto position = *convert<mbgl::style::Position>(env, jposition); + light.setPosition(position); +} + +jni::Object<Position> Light::getPosition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::Position position = light.getPosition().asConstant(); + return *convert<jni::Object<Position>>(env, position); +} + +jni::Object<TransitionOptions> Light::getPositionTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = light.getPositionTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); +} + +void Light::setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + light.setPositionTransition(options); +} + +void Light::setColor(jni::JNIEnv& env, jni::String property) { + auto color = Color::parse(jni::Make<std::string>(env, property)); + if (color) { + light.setColor(color.value()); + } +} + +jni::String Light::getColor(jni::JNIEnv &env) { + auto color = light.getColor().asConstant(); + return jni::Make<jni::String>(env, color.stringify()); +} + +jni::Object<TransitionOptions> Light::getColorTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = light.getColorTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); +} + +void Light::setColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + light.setColorTransition(options); +} + +void Light::setIntensity(jni::JNIEnv&, jni::jfloat property) { + light.setIntensity(property); +} + +jni::jfloat Light::getIntensity(jni::JNIEnv&) { + return light.getIntensity().asConstant(); +} + +jni::Object<TransitionOptions> Light::getIntensityTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = light.getIntensityTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); +} + +void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + light.setIntensityTransition(options); +} + +void Light::registerNative(jni::JNIEnv& env) { + // Lookup the class + Light::javaClass = *jni::Class<Light>::Find(env).NewGlobalRef(env).release(); + +#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + // Register the peer + jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr", + METHOD(&Light::getAnchor, "nativeGetAnchor"), + METHOD(&Light::setAnchor, "nativeSetAnchor"), + METHOD(&Light::getPositionTransition, "nativeGetPositionTransition"), + METHOD(&Light::setPositionTransition, "nativeSetPositionTransition"), + METHOD(&Light::getPosition, "nativeGetPosition"), + METHOD(&Light::setPosition, "nativeSetPosition"), + METHOD(&Light::getColorTransition, "nativeGetColorTransition"), + METHOD(&Light::setColorTransition, "nativeSetColorTransition"), + METHOD(&Light::getColor, "nativeGetColor"), + METHOD(&Light::setColor, "nativeSetColor"), + METHOD(&Light::getIntensityTransition, "nativeGetIntensityTransition"), + METHOD(&Light::setIntensityTransition, "nativeSetIntensityTransition"), + METHOD(&Light::getIntensity, "nativeGetIntensity"), + METHOD(&Light::setIntensity, "nativeSetIntensity")); +} + +} // namespace android +} // namespace mb diff --git a/platform/android/src/style/light.cpp.ejs b/platform/android/src/style/light.cpp.ejs new file mode 100644 index 0000000000..17f0bba09d --- /dev/null +++ b/platform/android/src/style/light.cpp.ejs @@ -0,0 +1,123 @@ +<% + const properties = locals.properties; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#include <mbgl/map/map.hpp> +#include "light.hpp" +#include "conversion/transition_options.hpp" +#include "conversion/position.hpp" + +namespace mbgl { +namespace android { + +Light::Light(mbgl::Map& coreMap, mbgl::style::Light& coreLight) + : light(coreLight) , map(&coreMap) { +} + +static Light* initializeLightPeer(mbgl::Map& map, mbgl::style::Light& coreLight) { + return new Light(map, coreLight); +} + +jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { + std::unique_ptr<Light> peerLight = std::unique_ptr<Light>(initializeLightPeer(map, coreLight)); + jni::jobject* result = peerLight->createJavaPeer(env); + peerLight.release(); + return result; +} + +jni::Class<Light> Light::javaClass; + +jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { + static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); + return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); +} + +<% for (const property of properties) { -%> +<% if (property.name == "position") { -%> +void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::Object<<%- camelize(property.name) %>> j<%- property.name %>) { + using namespace mbgl::android::conversion; + auto position = *convert<mbgl::style::<%- camelize(property.name) %>>(env, jposition); + light.set<%- camelize(property.name) %>(<%- property.name %>); +} + +jni::Object<Position> Light::get<%- camelize(property.name) %>(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::<%- camelize(property.name) %> <%- property.name %> = light.get<%- camelize(property.name) %>().asConstant(); + return *convert<jni::Object<<%- camelize(property.name) %>>>(env, <%- property.name %>); +} +<% } else { -%> +<% if(property.name == "color") {-%> +void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::<%- propertyJNIType(property) %> property) { + auto color = Color::parse(jni::Make<std::string>(env, property)); + if (color) { + light.set<%- camelize(property.name) %>(color.value()); + } +} + +jni::String Light::get<%- camelize(property.name) %>(jni::JNIEnv &env) { + auto color = light.get<%- camelize(property.name) %>().asConstant(); + return jni::Make<jni::String>(env, color.stringify()); +} +<% } else if(property.name == "anchor"){ -%> +void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::<%- propertyJNIType(property) %> property) { + std::string anchorStr = jni::Make<std::string>(env, property); + if (anchorStr.compare("map") == 0) { + light.setAnchor(LightAnchorType::Map); + } else if (anchorStr.compare("viewport") == 0) { + light.setAnchor(LightAnchorType::Viewport); + } +} + +jni::String Light::getAnchor(jni::JNIEnv& env) { + auto anchorType = light.getAnchor(); + if (anchorType == LightAnchorType::Map) { + return jni::Make<jni::String>(env, "map"); + } else { + return jni::Make<jni::String>(env, "viewport"); + } +} +<% } else { -%> +void Light::set<%- camelize(property.name) %>(jni::JNIEnv&, jni::<%- propertyJNIType(property) %> property) { + light.set<%- camelize(property.name) %>(property); +} + +jni::<%- propertyJNIType(property) %> Light::get<%- camelize(property.name) %>(jni::JNIEnv&) { + return light.get<%- camelize(property.name) %>().asConstant(); +} +<% } -%> +<% } -%> + +<% if (property.transition) { -%> +jni::Object<TransitionOptions> Light::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = light.get<%- camelize(property.name) %>Transition(); + return *convert<jni::Object<TransitionOptions>>(env, options); +} + +void Light::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + light.set<%- camelize(property.name) %>Transition(options); +} + +<% } -%> +<% } -%> +void Light::registerNative(jni::JNIEnv& env) { + // Lookup the class + Light::javaClass = *jni::Class<Light>::Find(env).NewGlobalRef(env).release(); + +#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + // Register the peer + jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> +<% if (properties[i].transition) { -%> + METHOD(&Light::get<%- camelize(properties[i].name) %>Transition, "nativeGet<%- camelize(properties[i].name) %>Transition"), + METHOD(&Light::set<%- camelize(properties[i].name) %>Transition, "nativeSet<%- camelize(properties[i].name) %>Transition"), +<% } -%> + METHOD(&Light::get<%- camelize(properties[i].name) %>, "nativeGet<%- camelize(properties[i].name) %>"), + METHOD(&Light::set<%- camelize(properties[i].name) %>, "nativeSet<%- camelize(properties[i].name) %>")<% if(i != (properties.length -1)) {-%>,<% } -%><% } -%>); +} + +} // namespace android +} // namespace mb diff --git a/platform/android/src/style/light.hpp b/platform/android/src/style/light.hpp new file mode 100644 index 0000000000..2c314067be --- /dev/null +++ b/platform/android/src/style/light.hpp @@ -0,0 +1,57 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#pragma once + +#include <mbgl/util/noncopyable.hpp> + +#include <jni/jni.hpp> +#include <mbgl/style/light.hpp> +#include "transition_options.hpp" +#include "position.hpp" +#include <mbgl/style/types.hpp> +#include <mbgl/style/property_value.hpp> + +namespace mbgl { +namespace android { + +using namespace style; + +class Light : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Light"; }; + + static jni::Class<Light> javaClass; + + static void registerNative(jni::JNIEnv&); + + static jni::jobject* createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); + + Light(mbgl::Map&, mbgl::style::Light&); + + void setAnchor(jni::JNIEnv&, jni::String); + jni::String getAnchor(jni::JNIEnv&); + void setPosition(jni::JNIEnv&, jni::Object<Position>); + jni::Object<Position> getPosition(jni::JNIEnv&); + void setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getPositionTransition(jni::JNIEnv&); + void setColor(jni::JNIEnv&, jni::String); + jni::String getColor(jni::JNIEnv&); + void setColorTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getColorTransition(jni::JNIEnv&); + void setIntensity(jni::JNIEnv&, jni::jfloat); + jni::jfloat getIntensity(jni::JNIEnv&); + void setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getIntensityTransition(jni::JNIEnv&); + jni::jobject* createJavaPeer(jni::JNIEnv&); + +protected: + + // Raw reference to the light + mbgl::style::Light& light; + + // Map is set when the light is retrieved + mbgl::Map* map; +}; +} // namespace android +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/light.hpp.ejs b/platform/android/src/style/light.hpp.ejs new file mode 100644 index 0000000000..18f961b9e0 --- /dev/null +++ b/platform/android/src/style/light.hpp.ejs @@ -0,0 +1,59 @@ +<% + const properties = locals.properties; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#pragma once + +#include <mbgl/util/noncopyable.hpp> + +#include <jni/jni.hpp> +#include <mbgl/style/light.hpp> +#include "transition_options.hpp" +#include "position.hpp" +#include <mbgl/style/types.hpp> +#include <mbgl/style/property_value.hpp> + +namespace mbgl { +namespace android { + +using namespace style; + +class Light : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Light"; }; + + static jni::Class<Light> javaClass; + + static void registerNative(jni::JNIEnv&); + + static jni::jobject* createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); + + Light(mbgl::Map&, mbgl::style::Light&); + +<% for (const property of properties) { -%> +<% if (property.name=="position") {-%> + void set<%- camelize(property.name) %>(jni::JNIEnv&, jni::Object<Position>); + jni::Object<<%- camelize(property.name) %>> get<%- camelize(property.name) %>(jni::JNIEnv&); +<% } else { -%> + void set<%- camelize(property.name) %>(jni::JNIEnv&, jni::<%- propertyJNIType(property) %>); + jni::<%- propertyJNIType(property) %> get<%- camelize(property.name) %>(jni::JNIEnv&); +<% } -%> +<% if (property.transition) { -%> + void set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); +<% } -%> +<% } -%> + jni::jobject* createJavaPeer(jni::JNIEnv&); + +protected: + + // Raw reference to the light + mbgl::style::Light& light; + + // Map is set when the light is retrieved + mbgl::Map* map; +}; +} // namespace android +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/position.cpp b/platform/android/src/style/position.cpp new file mode 100644 index 0000000000..0bbcefcbcd --- /dev/null +++ b/platform/android/src/style/position.cpp @@ -0,0 +1,34 @@ +#include "position.hpp" + +namespace mbgl { +namespace android { + +jni::Object<Position> Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { + static auto method = Position::javaClass.GetStaticMethod<jni::Object<Position> (jfloat, jfloat, jfloat)>(env, "fromPosition"); + return Position::javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); +} + +void Position::registerNative(jni::JNIEnv& env) { + // Lookup the class + Position::javaClass = *jni::Class<Position>::Find(env).NewGlobalRef(env).release(); +} + +jni::Class<Position> Position::javaClass; + +float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object<Position> position){ + static auto field = Position::javaClass.GetField<jfloat>(env, "radialCoordinate"); + return position.Get(env, field); +} + +float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object<Position> position){ + static auto field = Position::javaClass.GetField<jfloat>(env, "azimuthalAngle"); + return position.Get(env, field); +} + +float Position::getPolarAngle(jni::JNIEnv& env, jni::Object<Position> position){ + static auto field = Position::javaClass.GetField<jfloat>(env, "polarAngle"); + return position.Get(env, field); +} + +} // namespace andr[oid +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/position.hpp b/platform/android/src/style/position.hpp new file mode 100644 index 0000000000..4aafa853db --- /dev/null +++ b/platform/android/src/style/position.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <mbgl/util/noncopyable.hpp> + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class Position : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Position"; }; + + static jni::Object<Position> fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); + + static jni::Class<Position> javaClass; + + static void registerNative(jni::JNIEnv&); + + static float getRadialCoordinate(jni::JNIEnv&, jni::Object<Position>); + static float getAzimuthalAngle(jni::JNIEnv&, jni::Object<Position>); + static float getPolarAngle(jni::JNIEnv&, jni::Object<Position>); + +}; + + +} // namespace android +} // namespace mbgl
\ No newline at end of file |