move debug app over to use of Cocoa API
This commit is contained in:
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "ios/MVKMapKit"]
|
||||
path = ios/MVKMapKit
|
||||
url = git@github.com:mapbox/MVKMapKit.git
|
||||
@@ -1,24 +1,14 @@
|
||||
#import "MBXViewController.h"
|
||||
|
||||
#import "../common/settings_nsuserdefaults.hpp"
|
||||
#import "../common/foundation_request.h"
|
||||
#import "MVKMapView.h"
|
||||
|
||||
#import "../common/settings_nsuserdefaults.hpp"
|
||||
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
#include <llmr/llmr.hpp>
|
||||
#include <llmr/platform/platform.hpp>
|
||||
#include <llmr/map/tile.hpp>
|
||||
@interface MBXViewController () <CLLocationManagerDelegate>
|
||||
|
||||
@interface MBXViewController () <UIGestureRecognizerDelegate, CLLocationManagerDelegate>
|
||||
|
||||
@property (nonatomic) EAGLContext *context;
|
||||
@property (nonatomic) CGPoint center;
|
||||
@property (nonatomic) CGFloat scale;
|
||||
@property (nonatomic) CGFloat angle;
|
||||
@property (nonatomic) CGFloat quickZoomStart;
|
||||
@property (nonatomic) MVKMapView *mapView;
|
||||
@property (nonatomic) BOOL debug;
|
||||
@property (nonatomic) UIView *palette;
|
||||
@property (nonatomic) CLLocationManager *locationManager;
|
||||
@@ -27,12 +17,7 @@
|
||||
|
||||
@implementation MBXViewController
|
||||
|
||||
class View;
|
||||
|
||||
llmr::Map *map = nullptr;
|
||||
View *viewObj = nullptr;
|
||||
llmr::Settings_NSUserDefaults *settings = nullptr;
|
||||
MBXViewController *viewController = nullptr;
|
||||
|
||||
#pragma mark - Setup
|
||||
|
||||
@@ -49,110 +34,52 @@ MBXViewController *viewController = nullptr;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
|
||||
if (!self.context)
|
||||
{
|
||||
NSLog(@"Failed to create OpenGL ES context");
|
||||
}
|
||||
|
||||
GLKView *view = [[GLKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:self.context];
|
||||
view.enableSetNeedsDisplay = NO;
|
||||
view.drawableStencilFormat = GLKViewDrawableStencilFormat8;
|
||||
view.drawableDepthFormat = GLKViewDrawableDepthFormat16;
|
||||
[view bindDrawable];
|
||||
|
||||
self.view = view;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
[self setupMap];
|
||||
[self setupInteraction];
|
||||
self.mapView = [[MVKMapView alloc] initWithFrame:self.view.bounds];
|
||||
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.view addSubview:self.mapView];
|
||||
|
||||
settings = new llmr::Settings_NSUserDefaults();
|
||||
[self restoreState];
|
||||
|
||||
[self setupDebugUI];
|
||||
|
||||
self.locationManager = [CLLocationManager new];
|
||||
self.locationManager.delegate = self;
|
||||
|
||||
map->start();
|
||||
}
|
||||
|
||||
- (void)setupMap
|
||||
{
|
||||
viewObj = new View(self);
|
||||
map = new llmr::Map(*viewObj);
|
||||
|
||||
// Load settings
|
||||
settings = new llmr::Settings_NSUserDefaults();
|
||||
[self restoreState];
|
||||
}
|
||||
|
||||
- (void)saveState
|
||||
{
|
||||
if (map && settings)
|
||||
if (self.mapView && settings)
|
||||
{
|
||||
map->getLonLatZoom(settings->longitude, settings->latitude, settings->zoom);
|
||||
settings->angle = map->getAngle();
|
||||
settings->debug = map->getDebug();
|
||||
settings->longitude = self.mapView.centerCoordinate.longitude;
|
||||
settings->latitude = self.mapView.centerCoordinate.latitude;
|
||||
settings->zoom = self.mapView.zoomLevel;
|
||||
settings->angle = self.mapView.direction;
|
||||
settings->debug = self.mapView.isDebugActive;
|
||||
settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)restoreState
|
||||
{
|
||||
if (map && settings) {
|
||||
if (self.mapView && settings) {
|
||||
settings->load();
|
||||
map->setLonLatZoom(settings->longitude, settings->latitude, settings->zoom);
|
||||
map->setAngle(settings->angle);
|
||||
map->setDebug(settings->debug);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupInteraction
|
||||
{
|
||||
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
|
||||
pan.delegate = self;
|
||||
[self.view addGestureRecognizer:pan];
|
||||
|
||||
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
|
||||
pinch.delegate = self;
|
||||
[self.view addGestureRecognizer:pinch];
|
||||
|
||||
UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotateGesture:)];
|
||||
rotate.delegate = self;
|
||||
[self.view addGestureRecognizer:rotate];
|
||||
|
||||
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
|
||||
singleTap.numberOfTapsRequired = 1;
|
||||
[self.view addGestureRecognizer:singleTap];
|
||||
|
||||
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapGesture:)];
|
||||
doubleTap.numberOfTapsRequired = 2;
|
||||
[self.view addGestureRecognizer:doubleTap];
|
||||
|
||||
[singleTap requireGestureRecognizerToFail:doubleTap];
|
||||
|
||||
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTapGesture:)];
|
||||
twoFingerTap.numberOfTouchesRequired = 2;
|
||||
[self.view addGestureRecognizer:twoFingerTap];
|
||||
|
||||
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
|
||||
{
|
||||
UILongPressGestureRecognizer *quickZoom = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleQuickZoomGesture:)];
|
||||
quickZoom.numberOfTapsRequired = 1;
|
||||
quickZoom.minimumPressDuration = 0.25;
|
||||
[self.view addGestureRecognizer:quickZoom];
|
||||
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO];
|
||||
self.mapView.direction = settings->angle;
|
||||
[self.mapView setDebugActive:settings->debug];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupDebugUI
|
||||
{
|
||||
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
|
||||
singleTap.numberOfTapsRequired = 1;
|
||||
[self.mapView addGestureRecognizer:singleTap];
|
||||
|
||||
NSArray *selectorNames = @[ @"unrotate", @"resetPosition", @"toggleDebug", @"toggleRaster", @"locateUser" ];
|
||||
CGFloat buttonSize = 40;
|
||||
CGFloat bufferSize = 20;
|
||||
@@ -182,32 +109,19 @@ MBXViewController *viewController = nullptr;
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
// We support everything; it's up to the embedding application to limit the orientations.
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
#pragma mark - Rendering delegates
|
||||
#pragma mark - Debugging UI
|
||||
|
||||
- (void)swap
|
||||
- (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap
|
||||
{
|
||||
if (map->needsSwap())
|
||||
if (singleTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
[(GLKView *)self.view display];
|
||||
map->swapped();
|
||||
[self togglePalette];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews
|
||||
{
|
||||
[super viewWillLayoutSubviews];
|
||||
|
||||
GLKView *view = (GLKView *)self.view;
|
||||
CGRect rect = [view bounds];
|
||||
map->resize(rect.size.width, rect.size.height, view.contentScaleFactor, view.drawableWidth, view.drawableHeight);
|
||||
}
|
||||
|
||||
#pragma mark - Debugging UI
|
||||
|
||||
- (void)togglePalette
|
||||
{
|
||||
if (self.palette.alpha < 1)
|
||||
@@ -232,24 +146,24 @@ MBXViewController *viewController = nullptr;
|
||||
|
||||
- (void)unrotate
|
||||
{
|
||||
map->resetNorth();
|
||||
[self.mapView resetNorth];
|
||||
}
|
||||
|
||||
- (void)resetPosition
|
||||
{
|
||||
map->resetPosition();
|
||||
[self.mapView resetPosition];
|
||||
}
|
||||
|
||||
- (void)toggleDebug
|
||||
{
|
||||
map->toggleDebug();
|
||||
[self.mapView toggleDebug];
|
||||
|
||||
self.debug = ! self.debug;
|
||||
}
|
||||
|
||||
- (void)toggleRaster
|
||||
{
|
||||
map->toggleRaster();
|
||||
[self.mapView toggleRaster];
|
||||
}
|
||||
|
||||
- (void)locateUser
|
||||
@@ -269,197 +183,10 @@ MBXViewController *viewController = nullptr;
|
||||
|
||||
if (settings)
|
||||
{
|
||||
// Save settings
|
||||
[self saveState];
|
||||
delete settings;
|
||||
settings = nullptr;
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
delete map;
|
||||
map = nullptr;
|
||||
}
|
||||
|
||||
if (viewObj)
|
||||
{
|
||||
delete viewObj;
|
||||
viewObj = nullptr;
|
||||
}
|
||||
|
||||
if ([[EAGLContext currentContext] isEqual:self.context])
|
||||
{
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UI gestures
|
||||
|
||||
- (void)cancelPreviousActions
|
||||
{
|
||||
map->cancelTransitions();
|
||||
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
}
|
||||
|
||||
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (pan.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
self.center = CGPointMake(0, 0);
|
||||
}
|
||||
else if (pan.state == UIGestureRecognizerStateChanged)
|
||||
{
|
||||
CGPoint delta = CGPointMake([pan translationInView:pan.view].x - self.center.x,
|
||||
[pan translationInView:pan.view].y - self.center.y);
|
||||
|
||||
map->moveBy(delta.x, delta.y);
|
||||
|
||||
self.center = CGPointMake(self.center.x + delta.x, self.center.y + delta.y);
|
||||
}
|
||||
else if (pan.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
if ([pan velocityInView:pan.view].x < 50 && [pan velocityInView:pan.view].y < 50)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CGPoint finalCenter = CGPointMake(self.center.x + (0.1 * [pan velocityInView:pan.view].x),
|
||||
self.center.y + (0.1 * [pan velocityInView:pan.view].y));
|
||||
|
||||
CGFloat duration = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? 0.3 : 0.5);
|
||||
|
||||
map->moveBy(finalCenter.x - self.center.x, finalCenter.y - self.center.y, duration);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (pinch.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
map->startScaling();
|
||||
|
||||
self.scale = map->getScale();
|
||||
}
|
||||
else if (pinch.state == UIGestureRecognizerStateChanged)
|
||||
{
|
||||
CGFloat tolerance = 2.5;
|
||||
CGFloat adjustment = 0;
|
||||
|
||||
if (pinch.scale > 1)
|
||||
{
|
||||
adjustment = (pinch.scale / tolerance) - (1 / tolerance);
|
||||
}
|
||||
else
|
||||
{
|
||||
adjustment = (-1 / pinch.scale) / tolerance + (1 / tolerance);
|
||||
}
|
||||
|
||||
CGFloat newZoom = log2f(self.scale) + adjustment;
|
||||
|
||||
map->scaleBy(powf(2, newZoom) / map->getScale(), [pinch locationInView:pinch.view].x, [pinch locationInView:pinch.view].y);
|
||||
}
|
||||
else if (pinch.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
map->stopScaling();
|
||||
|
||||
if (fabsf(pinch.velocity) < 20)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat finalZoom = log2f(map->getScale()) + (0.01 * pinch.velocity);
|
||||
|
||||
double scale = map->getScale();
|
||||
double new_scale = powf(2, finalZoom);
|
||||
|
||||
CGFloat duration = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? 0.3 : 0.5);
|
||||
|
||||
map->scaleBy(new_scale / scale, [pinch locationInView:pinch.view].x, [pinch locationInView:pinch.view].y, duration);
|
||||
}
|
||||
else if (pinch.state == UIGestureRecognizerStateCancelled)
|
||||
{
|
||||
map->stopScaling();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (rotate.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
map->startRotating();
|
||||
|
||||
self.angle = map->getAngle();
|
||||
}
|
||||
else if (rotate.state == UIGestureRecognizerStateChanged)
|
||||
{
|
||||
map->setAngle(self.angle + rotate.rotation, [rotate locationInView:rotate.view].x, [rotate locationInView:rotate.view].y);
|
||||
}
|
||||
else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled)
|
||||
{
|
||||
map->stopRotating();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap
|
||||
{
|
||||
if (singleTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
[self togglePalette];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (doubleTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
map->scaleBy(2, [doubleTap locationInView:doubleTap.view].x, [doubleTap locationInView:doubleTap.view].y, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (twoFingerTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
map->scaleBy(0.5, [twoFingerTap locationInView:twoFingerTap.view].x, [twoFingerTap locationInView:twoFingerTap.view].y, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom
|
||||
{
|
||||
[self cancelPreviousActions];
|
||||
|
||||
if (quickZoom.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
self.scale = map->getScale();
|
||||
|
||||
self.quickZoomStart = [quickZoom locationInView:quickZoom.view].y;
|
||||
}
|
||||
else if (quickZoom.state == UIGestureRecognizerStateChanged)
|
||||
{
|
||||
CGFloat distance = self.quickZoomStart - [quickZoom locationInView:quickZoom.view].y;
|
||||
|
||||
CGFloat newZoom = log2f(self.scale) + (distance / 100);
|
||||
|
||||
map->scaleBy(powf(2, newZoom) / map->getScale(), self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
||||
{
|
||||
NSArray *validSimultaneousGestures = @[ [UIPanGestureRecognizer class], [UIPinchGestureRecognizer class], [UIRotationGestureRecognizer class] ];
|
||||
|
||||
return ([validSimultaneousGestures containsObject:[gestureRecognizer class]] && [validSimultaneousGestures containsObject:[otherGestureRecognizer class]]);
|
||||
}
|
||||
|
||||
#pragma mark - User location
|
||||
@@ -468,24 +195,7 @@ MBXViewController *viewController = nullptr;
|
||||
{
|
||||
CLLocation *latestLocation = locations.lastObject;
|
||||
|
||||
map->setLonLatZoom(latestLocation.coordinate.longitude, latestLocation.coordinate.latitude, 17, 0.3);
|
||||
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(latestLocation.coordinate.latitude, latestLocation.coordinate.longitude) zoomLevel:17 animated:YES];
|
||||
}
|
||||
|
||||
class View : public llmr::View {
|
||||
public:
|
||||
View(MBXViewController *controller) : controller(controller) {}
|
||||
virtual ~View() {}
|
||||
|
||||
void make_active() {
|
||||
[EAGLContext setCurrentContext:controller.context];
|
||||
}
|
||||
|
||||
void swap() {
|
||||
[controller performSelectorOnMainThread:@selector(swap) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
|
||||
private:
|
||||
MBXViewController *controller = nullptr;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
1
ios/MVKMapKit
Submodule
1
ios/MVKMapKit
Submodule
Submodule ios/MVKMapKit added at 9c536c3b12
@@ -14,6 +14,8 @@
|
||||
"./MBXAppDelegate.m",
|
||||
"./MBXViewController.h",
|
||||
"./MBXViewController.mm",
|
||||
"./MVKMapKit/MVKMapKit/MVKMapView.h",
|
||||
"./MVKMapKit/MVKMapKit/MVKMapView.mm",
|
||||
"../common/settings_nsuserdefaults.hpp",
|
||||
"../common/settings_nsuserdefaults.mm",
|
||||
"../common/foundation_request.h",
|
||||
|
||||
Reference in New Issue
Block a user