diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-12-11 16:04:40 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-12-16 11:03:32 -0800 |
commit | 8a17d30c50f46b5c702807a840bbfb6395eb456e (patch) | |
tree | 94952de29122f9694ca07c032073697dcd0e0fc9 | |
parent | e304033552fd423db5324545216f9cf3a1e62150 (diff) | |
download | qtlocation-mapboxgl-8a17d30c50f46b5c702807a840bbfb6395eb456e.tar.gz |
[android] Custom layer bindings
12 files changed, 272 insertions, 1 deletions
diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java new file mode 100644 index 0000000000..f6fb297dc6 --- /dev/null +++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/CustomLayer.java @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.layers; + +public class CustomLayer { + public CustomLayer(String id, + long context, + long initializeFunction, + long renderFunction, + long deinitializeFunction) { + this.mID = id; + this.mContext = context; + this.mInitializeFunction = initializeFunction; + this.mRenderFunction = renderFunction; + this.mDeinitializeFunction = deinitializeFunction; + } + + public String mID; + public long mContext; + public long mInitializeFunction; + public long mRenderFunction; + public long mDeinitializeFunction; +} diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java new file mode 100644 index 0000000000..fda1a493e2 --- /dev/null +++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/layers/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains classes to add and manage layers in your map. + */ +package com.mapbox.mapboxsdk.layers; diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java index 94cfe23f86..157f1ae955 100644 --- a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java +++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java @@ -74,6 +74,7 @@ import com.mapbox.mapboxsdk.geometry.BoundingBox; import com.mapbox.mapboxsdk.geometry.CoordinateBounds; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngZoom; +import com.mapbox.mapboxsdk.layers.CustomLayer; import com.mapbox.mapboxsdk.utils.ApiAccess; import java.lang.annotation.Retention; @@ -3782,6 +3783,11 @@ public final class MapView extends FrameLayout { mAttributionsView.setVisibility(visibility); } + @UiThread + public void addCustomLayer(CustomLayer customLayer, String before) { + mNativeMapView.addCustomLayer(customLayer, before); + } + private void setWidgetGravity(@NonNull final View view, int gravity) { LayoutParams layoutParams = (LayoutParams) view.getLayoutParams(); layoutParams.gravity = gravity; diff --git a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java index f09d0e9027..c142670775 100644 --- a/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java +++ b/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/NativeMapView.java @@ -11,6 +11,7 @@ import com.mapbox.mapboxsdk.geometry.BoundingBox; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngZoom; import com.mapbox.mapboxsdk.geometry.ProjectedMeters; +import com.mapbox.mapboxsdk.layers.CustomLayer; import java.lang.ref.WeakReference; import java.util.List; @@ -449,6 +450,10 @@ final class NativeMapView { return nativeGetTopOffsetPixelsForAnnotationSymbol(mNativeMapViewPtr, symbolName); } + public void addCustomLayer(CustomLayer customLayer, String before) { + nativeAddCustomLayer(mNativeMapViewPtr, customLayer, before); + } + // // Callbacks // @@ -629,4 +634,6 @@ final class NativeMapView { private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, PointF pixel); private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName); + + private native void nativeAddCustomLayer(long nativeMapViewPtr, CustomLayer customLayer, String before); } diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java new file mode 100644 index 0000000000..e6c7992145 --- /dev/null +++ b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ExampleCustomLayer.java @@ -0,0 +1,12 @@ +package com.mapbox.mapboxsdk.testapp; + +public class ExampleCustomLayer { + static { + System.loadLibrary("example-custom-layer"); + } + + public native static long createContext(); + public static long InitializeFunction; + public static long RenderFunction; + public static long DeinitializeFunction; +} diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java index c303d94cdc..c6ec8cbd77 100644 --- a/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java +++ b/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java @@ -34,6 +34,7 @@ import com.mapbox.mapboxsdk.constants.MyBearingTracking; import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.layers.CustomLayer; import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil; import com.mapbox.mapboxsdk.utils.ApiAccess; import com.mapbox.mapboxsdk.views.MapView; @@ -395,6 +396,10 @@ public class MainActivity extends AppCompatActivity { startActivity(new Intent(getApplicationContext(), PolylineActivity.class)); return true; + case R.id.action_custom_layer: + addCustomLayer(); + return true; + default: return changeMapStyle(menuItem.getItemId()); } @@ -570,6 +575,16 @@ public class MainActivity extends AppCompatActivity { mMapView.removeAllAnnotations(); } + private void addCustomLayer() { + mMapView.addCustomLayer( + new CustomLayer("custom", + ExampleCustomLayer.createContext(), + ExampleCustomLayer.InitializeFunction, + ExampleCustomLayer.RenderFunction, + ExampleCustomLayer.DeinitializeFunction), + null); + } + // Called when FPS changes private class MyOnFpsChangedListener implements MapView.OnFpsChangedListener { diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml b/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml index bfd70a936f..9a81182837 100644 --- a/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml +++ b/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml @@ -138,6 +138,12 @@ android:icon="@drawable/ic_trending_up_24dp" android:title="@string/activity_polyline" /> + <item + android:id="@+id/action_custom_layer" + android:checkable="false" + android:icon="@drawable/ic_trending_up_24dp" + android:title="@string/activity_custom_layer" /> + </menu> </item> diff --git a/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml index 8cc299e39f..10d622d38f 100644 --- a/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml +++ b/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ <string name="activity_user_tracking_mode">User tracking mode</string> <string name="activity_polyline">Polyline Activity</string> <string name="activity_animate_coordinate_change">Animate Coordinate Change</string> + <string name="activity_custom_layer">Custom Layer</string> <string name="navdrawer_menu_title_mainactivity_controls">Main Activity Controls</string> <string name="navdrawer_menu_title_mainactivity_styles">Main Activity Styles</string> diff --git a/platform/android/example_custom_layer.cpp b/platform/android/example_custom_layer.cpp new file mode 100644 index 0000000000..e853545358 --- /dev/null +++ b/platform/android/example_custom_layer.cpp @@ -0,0 +1,104 @@ +#include <jni.h> +#include <GLES2/gl2.h> + +static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }"; +static const GLchar * fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"; + +class ExampleCustomLayer { +public: + ~ExampleCustomLayer() { + if (program) { + glDeleteBuffers(1, &buffer); + glDetachShader(program, vertexShader); + glDetachShader(program, fragmentShader); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + glDeleteProgram(program); + } + } + + void initialize() { + program = glCreateProgram(); + vertexShader = glCreateShader(GL_VERTEX_SHADER); + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); + glCompileShader(vertexShader); + glAttachShader(program, vertexShader); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); + glCompileShader(fragmentShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + a_pos = glGetAttribLocation(program, "a_pos"); + + GLfloat background[] = { -1,-1, 1,-1, -1,1, 1,1 }; + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW); + } + + void render() { + glUseProgram(program); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glEnableVertexAttribArray(a_pos); + glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + + GLuint program = 0; + GLuint vertexShader = 0; + GLuint fragmentShader = 0; + GLuint buffer = 0; + GLuint a_pos = 0; +}; + +jlong JNICALL nativeCreateContext(JNIEnv*, jobject) { + return reinterpret_cast<jlong>(new ExampleCustomLayer()); +} + +void nativeInitialize(void *context) { + reinterpret_cast<ExampleCustomLayer*>(context)->initialize(); +} + +void nativeRender(void *context) { + reinterpret_cast<ExampleCustomLayer*>(context)->render(); +} + +void nativeDenitialize(void *context) { + delete reinterpret_cast<ExampleCustomLayer*>(context); +} + +extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + JNIEnv *env = nullptr; + vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6); + + jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/ExampleCustomLayer"); + + JNINativeMethod methods[] = { + {"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)} + }; + + if (env->RegisterNatives(customLayerClass, methods, 1) < 0) { + env->ExceptionDescribe(); + return JNI_ERR; + } + + env->SetStaticLongField(customLayerClass, + env->GetStaticFieldID(customLayerClass, "InitializeFunction", "J"), + reinterpret_cast<jlong>(nativeInitialize)); + + env->SetStaticLongField(customLayerClass, + env->GetStaticFieldID(customLayerClass, "RenderFunction", "J"), + reinterpret_cast<jlong>(nativeRender)); + + env->SetStaticLongField(customLayerClass, + env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"), + reinterpret_cast<jlong>(nativeDenitialize)); + + return JNI_VERSION_1_6; +} + +extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *) { +} diff --git a/platform/android/jni.cpp b/platform/android/jni.cpp index acefc87f31..fc657a6cb0 100644 --- a/platform/android/jni.cpp +++ b/platform/android/jni.cpp @@ -111,6 +111,13 @@ jclass httpRequestClass = nullptr; jmethodID httpRequestStartId = nullptr; jmethodID httpRequestCancelId = nullptr; +jclass customLayerClass = nullptr; +jfieldID customLayerIdId = nullptr; +jfieldID customLayerContextId = nullptr; +jfieldID customLayerInitializeFunctionId = nullptr; +jfieldID customLayerRenderFunctionId = nullptr; +jfieldID customLayerDeinitializeFunctionId = nullptr; + bool throw_jni_error(JNIEnv *env, const char *msg) { if (env->ThrowNew(runtimeExceptionClass, msg) < 0) { env->ExceptionDescribe(); @@ -1471,6 +1478,19 @@ jdouble JNICALL nativeGetTopOffsetPixelsForAnnotationSymbol(JNIEnv *env, jobject return nativeMapView->getMap().getTopOffsetPixelsForAnnotationIcon(std_string_from_jstring(env, symbolName)); } +void JNICALL nativeAddCustomLayer(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject customLayer, jstring before) { + mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddCustomLayer"); + assert(nativeMapViewPtr != 0); + NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); + nativeMapView->getMap().addCustomLayer( + std_string_from_jstring(env, reinterpret_cast<jstring>(env->GetObjectField(customLayer, customLayerIdId))), + reinterpret_cast<mbgl::CustomLayerInitializeFunction>(env->GetLongField(customLayer, customLayerInitializeFunctionId)), + reinterpret_cast<mbgl::CustomLayerRenderFunction>(env->GetLongField(customLayer, customLayerRenderFunctionId)), + reinterpret_cast<mbgl::CustomLayerDeinitializeFunction>(env->GetLongField(customLayer, customLayerDeinitializeFunctionId)), + reinterpret_cast<void*>(env->GetLongField(customLayer, customLayerContextId)), + before ? std_string_from_jstring(env, before).c_str() : nullptr); +} + } @@ -1848,6 +1868,36 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { env->ExceptionDescribe(); } + customLayerClass = env->FindClass("com/mapbox/mapboxsdk/layers/CustomLayer"); + if (customLayerClass == nullptr) { + env->ExceptionDescribe(); + } + + customLayerIdId = env->GetFieldID(customLayerClass, "mID", "Ljava/lang/String;"); + if (customLayerIdId == nullptr) { + env->ExceptionDescribe(); + } + + customLayerContextId = env->GetFieldID(customLayerClass, "mContext", "J"); + if (customLayerContextId == nullptr) { + env->ExceptionDescribe(); + } + + customLayerInitializeFunctionId = env->GetFieldID(customLayerClass, "mInitializeFunction", "J"); + if (customLayerInitializeFunctionId == nullptr) { + env->ExceptionDescribe(); + } + + customLayerRenderFunctionId = env->GetFieldID(customLayerClass, "mRenderFunction", "J"); + if (customLayerRenderFunctionId == nullptr) { + env->ExceptionDescribe(); + } + + customLayerDeinitializeFunctionId = env->GetFieldID(customLayerClass, "mDeinitializeFunction", "J"); + if (customLayerDeinitializeFunctionId == nullptr) { + env->ExceptionDescribe(); + } + const std::vector<JNINativeMethod> methods = { {"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J", reinterpret_cast<void *>(&nativeCreate)}, @@ -1965,6 +2015,8 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { reinterpret_cast<void *>(&nativeLatLngForPixel)}, {"nativeGetTopOffsetPixelsForAnnotationSymbol", "(JLjava/lang/String;)D", reinterpret_cast<void *>(&nativeGetTopOffsetPixelsForAnnotationSymbol)}, + {"nativeAddCustomLayer", "(JLcom/mapbox/mapboxsdk/layers/CustomLayer;Ljava/lang/String;)V", + reinterpret_cast<void *>(&nativeAddCustomLayer)}, }; if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) { diff --git a/platform/android/mapboxgl-app.gypi b/platform/android/mapboxgl-app.gypi index 8080b29cd8..ced569a4bc 100644 --- a/platform/android/mapboxgl-app.gypi +++ b/platform/android/mapboxgl-app.gypi @@ -59,11 +59,46 @@ ], }, + { 'target_name': 'example-custom-layer-lib', + 'product_name': 'example-custom-layer', + 'type': 'shared_library', + 'hard_dependency': 1, + + 'sources': [ + './example_custom_layer.cpp', + ], + + 'variables': { + 'ldflags': [ + '-llog', + '-landroid', + '-lEGL', + '-lGLESv2', + '-lstdc++', + '-latomic', + ], + }, + + 'conditions': [ + ['OS == "mac"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': [ '<@(ldflags)' ], + } + }, { + 'libraries': [ '<@(ldflags)' ], + }] + ], + }, { 'target_name': 'androidapp', 'type': 'none', 'hard_dependency': 1, + 'dependencies': [ + 'android-lib', + 'example-custom-layer-lib', + ], + 'variables': { 'pwd': '<!(pwd)', }, @@ -85,11 +120,17 @@ 'actions': [ { - 'action_name': 'Strip dynamic library', + 'action_name': 'Strip mapbox library', 'inputs': [ '<(PRODUCT_DIR)/lib.target/libmapbox-gl.so' ], 'outputs': [ '<(pwd)/../android/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ], 'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ] }, + { + 'action_name': 'Strip example custom layer library', + 'inputs': [ '<(PRODUCT_DIR)/lib.target/libexample-custom-layer.so' ], + 'outputs': [ '<(pwd)/../android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/$(JNIDIR)/libexample-custom-layer.so' ], + 'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ] + } ], }, ], diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 179df004a7..96f4a68d9b 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -285,6 +285,8 @@ double MapContext::getTopOffsetPixelsForAnnotationIcon(const std::string& name) void MapContext::addLayer(std::unique_ptr<StyleLayer> layer, mapbox::util::optional<std::string> after) { style->addLayer(std::move(layer), after); + updateFlags |= Update::Classes; + asyncUpdate.send(); } void MapContext::setSourceTileCacheSize(size_t size) { |