summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2015-12-16 09:29:54 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-12-16 11:03:54 -0800
commitec9a4cd3285da280d43c7ddd0ca96fe37d9c5278 (patch)
tree1ae0849e18c6c42f42e453d641279d43a0a62367
parent8a17d30c50f46b5c702807a840bbfb6395eb456e (diff)
downloadqtlocation-mapboxgl-ec9a4cd3285da280d43c7ddd0ca96fe37d9c5278.tar.gz
[ios] Custom style layer
Exposed Map::addCustomLayer() publicly as an undocumented, block-based API. This change avoids the terms “layer”, “initialize”, “render”, and “altitude” because they overload existing terminology in the SDK, UIKit, or MapKit. (“Layer” is qualified as “style layer”.) There are outstanding questions about ARC memory management, but this approach works in both Objective-C and Swift for pure OpenGL programming. Added a demo to iosapp that draws a green layer below any labels in Mapbox Streets.
-rw-r--r--gyp/platform-ios.gypi1
-rw-r--r--include/mbgl/ios/MGLMapView+MGLCustomStyleLayerAdditions.h22
-rw-r--r--include/mbgl/ios/Mapbox.h1
-rw-r--r--ios/app/MBXViewController.mm59
-rw-r--r--platform/ios/MGLMapView.mm66
5 files changed, 149 insertions, 0 deletions
diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi
index d510d25c03..22a44dd31a 100644
--- a/gyp/platform-ios.gypi
+++ b/gyp/platform-ios.gypi
@@ -50,6 +50,7 @@
'../platform/ios/MGLMapboxEvents.m',
'../include/mbgl/ios/MGLMapView.h',
'../include/mbgl/ios/MGLMapView+IBAdditions.h',
+ '../include/mbgl/ios/MGLMapView+MGLCustomStyleLayerAdditions.h',
'../platform/ios/MGLMapView.mm',
'../include/mbgl/ios/MGLAccountManager.h',
'../platform/ios/MGLAccountManager_Private.h',
diff --git a/include/mbgl/ios/MGLMapView+MGLCustomStyleLayerAdditions.h b/include/mbgl/ios/MGLMapView+MGLCustomStyleLayerAdditions.h
new file mode 100644
index 0000000000..4785a36cfa
--- /dev/null
+++ b/include/mbgl/ios/MGLMapView+MGLCustomStyleLayerAdditions.h
@@ -0,0 +1,22 @@
+#import "MGLMapView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void (^MGLCustomStyleLayerPreparationHandler)(void);
+
+typedef void (^MGLCustomStyleLayerDrawingHandler)(CGSize size,
+ CLLocationCoordinate2D centerCoordinate,
+ double zoomLevel,
+ CLLocationDirection direction,
+ CGFloat pitch,
+ CGFloat perspectiveSkew);
+
+typedef void (^MGLCustomStyleLayerCompletionHandler)(void);
+
+@interface MGLMapView (MGLCustomStyleLayerAdditions)
+
+- (void)insertCustomStyleLayerWithIdentifier:(NSString *)identifier preparationHandler:(MGLCustomStyleLayerPreparationHandler)preparation drawingHandler:(MGLCustomStyleLayerDrawingHandler)drawing completionHandler:(MGLCustomStyleLayerCompletionHandler)completion belowStyleLayerWithIdentifier:(nullable NSString *)otherIdentifier;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/include/mbgl/ios/Mapbox.h b/include/mbgl/ios/Mapbox.h
index 004839059f..e8b3ead1d9 100644
--- a/include/mbgl/ios/Mapbox.h
+++ b/include/mbgl/ios/Mapbox.h
@@ -5,6 +5,7 @@
#import "MGLGeometry.h"
#import "MGLMapView.h"
#import "MGLMapView+IBAdditions.h"
+#import "MGLMapView+MGLCustomStyleLayerAdditions.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
#import "MGLPointAnnotation.h"
diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm
index 7e19382f9a..d5ef815351 100644
--- a/ios/app/MBXViewController.mm
+++ b/ios/app/MBXViewController.mm
@@ -4,6 +4,7 @@
#import <mbgl/util/default_styles.hpp>
#import <CoreLocation/CoreLocation.h>
+#import <OpenGLES/ES2/gl.h>
static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000];
@@ -150,6 +151,7 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
@"Add Test Shapes",
@"Start World Tour",
@"Remove Annotations",
+ @"Insert Custom Style Layer",
nil];
[sheet showFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];
@@ -260,6 +262,10 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
{
[self.mapView removeAnnotations:self.mapView.annotations];
}
+ else if (buttonIndex == actionSheet.firstOtherButtonIndex + 9)
+ {
+ [self insertCustomStyleLayer];
+ }
}
- (void)parseFeaturesAddingCount:(NSUInteger)featuresCount
@@ -302,6 +308,59 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = {
});
}
+- (void)insertCustomStyleLayer
+{
+ 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); }";
+
+ __block GLuint program = 0;
+ __block GLuint vertexShader = 0;
+ __block GLuint fragmentShader = 0;
+ __block GLuint buffer = 0;
+ __block GLuint a_pos = 0;
+ [self.mapView insertCustomStyleLayerWithIdentifier:@"mbx-custom" preparationHandler:^{
+ 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);
+ } drawingHandler:^(__unused CGSize size,
+ __unused CLLocationCoordinate2D centerCoordinate,
+ __unused double zoomLevel,
+ __unused CLLocationDirection direction,
+ __unused CGFloat pitch,
+ __unused CGFloat perspectiveSkew) {
+ 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);
+ } completionHandler:^{
+ if (program) {
+ glDeleteBuffers(1, &buffer);
+ glDetachShader(program, vertexShader);
+ glDetachShader(program, fragmentShader);
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ glDeleteProgram(program);
+ }
+ } belowStyleLayerWithIdentifier:@"housenum-label"];
+}
+
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPress
{
if (longPress.state == UIGestureRecognizerStateBegan)
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm
index 5d944e81fe..e9657f5616 100644
--- a/platform/ios/MGLMapView.mm
+++ b/platform/ios/MGLMapView.mm
@@ -1,5 +1,6 @@
#import "MGLMapView.h"
#import "MGLMapView+IBAdditions.h"
+#import "MGLMapView+MGLCustomStyleLayerAdditions.h"
#import <mbgl/platform/log.hpp>
#import <mbgl/platform/gl.hpp>
@@ -3472,6 +3473,8 @@ class MBGLView : public mbgl::View
@end
+#pragma mark - IBAdditions methods
+
@implementation MGLMapView (IBAdditions)
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingStyleURL__
@@ -3610,3 +3613,66 @@ class MBGLView : public mbgl::View
}
@end
+
+#pragma mark - MGLCustomStyleLayerAdditions methods
+
+class MGLCustomStyleLayerHandlers
+{
+public:
+ MGLCustomStyleLayerHandlers(MGLCustomStyleLayerPreparationHandler p,
+ MGLCustomStyleLayerDrawingHandler d,
+ MGLCustomStyleLayerCompletionHandler f)
+ : prepare(p), draw(d), finish(f) {}
+
+ MGLCustomStyleLayerPreparationHandler prepare;
+ MGLCustomStyleLayerDrawingHandler draw;
+ MGLCustomStyleLayerCompletionHandler finish;
+};
+
+void MGLPrepareCustomStyleLayer(void *context)
+{
+ MGLCustomStyleLayerPreparationHandler prepare = reinterpret_cast<MGLCustomStyleLayerHandlers *>(context)->prepare;
+ if (prepare)
+ {
+ prepare();
+ }
+}
+
+void MGLDrawCustomStyleLayer(void *context, const mbgl::CustomLayerRenderParameters &params)
+{
+ CGSize size = CGSizeMake(params.width, params.height);
+ CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude);
+ double zoomLevel = params.zoom;
+ CLLocationDirection direction = mbgl::util::wrap(params.bearing, 0., 360.);
+ CGFloat pitch = params.pitch;
+ CGFloat perspectiveSkew = params.altitude;
+ MGLCustomStyleLayerDrawingHandler draw = reinterpret_cast<MGLCustomStyleLayerHandlers *>(context)->draw;
+ if (draw)
+ {
+ draw(size, centerCoordinate, zoomLevel, direction, pitch, perspectiveSkew);
+ }
+}
+
+void MGLFinishCustomStyleLayer(void *context)
+{
+ MGLCustomStyleLayerHandlers *handlers = reinterpret_cast<MGLCustomStyleLayerHandlers *>(context);
+ MGLCustomStyleLayerCompletionHandler finish = handlers->finish;
+ if (finish)
+ {
+ finish();
+ }
+ delete handlers;
+}
+
+@implementation MGLMapView (MGLCustomStyleLayerAdditions)
+
+- (void)insertCustomStyleLayerWithIdentifier:(NSString *)identifier preparationHandler:(void (^)())preparation drawingHandler:(MGLCustomStyleLayerDrawingHandler)drawing completionHandler:(void (^)())completion belowStyleLayerWithIdentifier:(nullable NSString *)otherIdentifier
+{
+ NSAssert(identifier, @"Style layer needs an identifier");
+ MGLCustomStyleLayerHandlers *context = new MGLCustomStyleLayerHandlers(preparation, drawing, completion);
+ _mbglMap->addCustomLayer(identifier.UTF8String, MGLPrepareCustomStyleLayer,
+ MGLDrawCustomStyleLayer, MGLFinishCustomStyleLayer,
+ context, otherIdentifier.UTF8String);
+}
+
+@end