summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
authorTobrun <tobrun@mapbox.com>2017-05-26 16:04:09 +0200
committerGitHub <noreply@github.com>2017-05-26 16:04:09 +0200
commit5716bd3aecc777813161292e104ac9ceba3f230a (patch)
treed9a791ddbb1821e90fe7efcd1578dea0402af07a /platform/android
parentc392c678ab4ea560cefca59d14b215e2d4c79ecb (diff)
downloadqtlocation-mapboxgl-5716bd3aecc777813161292e104ac9ceba3f230a.tar.gz
[android] - add binding support for Light (#9013)
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java15
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java181
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java81
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs121
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java162
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs128
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java78
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_paint.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_building_layer.xml30
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_extrusion_test.xml18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_building.xml12
-rw-r--r--platform/android/config.cmake4
-rw-r--r--platform/android/scripts/generate-style-code.js93
-rwxr-xr-xplatform/android/src/jni.cpp3
-rwxr-xr-xplatform/android/src/native_map_view.cpp11
-rwxr-xr-xplatform/android/src/native_map_view.hpp3
-rw-r--r--platform/android/src/style/conversion/position.hpp37
-rw-r--r--platform/android/src/style/conversion/types.hpp7
-rw-r--r--platform/android/src/style/conversion/types_string_values.hpp14
-rw-r--r--platform/android/src/style/light.cpp146
-rw-r--r--platform/android/src/style/light.cpp.ejs123
-rw-r--r--platform/android/src/style/light.hpp57
-rw-r--r--platform/android/src/style/light.hpp.ejs59
-rw-r--r--platform/android/src/style/position.cpp34
-rw-r--r--platform/android/src/style/position.hpp29
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