[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.
This commit is contained in:
Minh Nguyễn
2015-12-16 09:29:54 -08:00
committed by John Firebaugh
parent 8a17d30c50
commit ec9a4cd328
5 changed files with 149 additions and 0 deletions

View File

@@ -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',

View File

@@ -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

View File

@@ -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"

View File

@@ -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)

View File

@@ -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