summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobrun <tobrun@mapbox.com>2017-06-02 23:41:14 +0200
committerGitHub <noreply@github.com>2017-06-02 23:41:14 +0200
commit2d039d3c6b0f62a7545563f7ef4e966aed8ba410 (patch)
tree353d2106c561c3329886691334a953d4b450840d
parente82649139b69a4794b944b4a61822dd82a4d6abc (diff)
downloadqtlocation-mapboxgl-2d039d3c6b0f62a7545563f7ef4e966aed8ba410.tar.gz
Merge release-ios-v3.6.0-android-v5.1.0 to master (#9170)
* [android] Update release script to support CircleCI builds (#8950) * update release script to trigger builds on circleci now * update release script to trigger builds on circleci now * [core] When a layer is added, reload its source's tiles * [android] - keep observer when timeout occurs, make observer param nullable, fixup log messages (#8919) * [android] - avoid crashing when deleting already deleted region (#8920) * [android] - update LOST to 2.3.0 (#8872) * [android] - update proguard config, allow debug mimification, update OkHttp to latest version (#8944) * [core, android, ios, macos, qt] v10 default styles Upgraded from v9 default styles to v10 wherever the developer expects to get the latest and greatest, as well as in a couple tests where it may be beneficial to ensure that we can handle a two-digit version number in the style URL. Cherry-picked from ed54849e9909e7f7cd8724b39b2bc94f16cf9a11. * [ios, macos] Updated documented default style version MGLStyleDefaultVersion is just for Streets now. Deleted style version documentation tests because not all styles are on the same version. Cherry-picked from ca97dd8cf4c70a5ed380c99700749fd3239715f0. * [ios, macos] Undeprecated unversioned style URL factory methods Undeprecated the unversioned style URL factory methods in MGLStyle for consistency with the Android and Qt SDKs. Added warnings about using them with the runtime styling API. Refactored mbgl::util::default_styles to track different versions for different styles. Cherry-picked from 9e384b78fbcf46d66d390122eefdf273f91b314e. * [core, android, ios, macos] Added Traffic Day/Night to default styles The Styles API section of the Mapbox API Documentation site now lists Traffic Day v2 and Traffic Night v2, so this change adds those styles to all the places where styles are listed. Also switched iosapp and macosapp to unversioned style factory methods since MGLStyleDefaultVersion is no longer applicable for all styles. Cherry-picked from 4d6f54553d277c0af24a0b8ff03d2dd7e9284ca2. * [android] Release android-v5.1.0-beta.2 (#8976) * [android] url getter on sources * [android] fix ui test filter in makefile * [android] - build SNAPSHOT from release branch (#8958) * [android] - update changelog for 5.1.0-beta.2 * [android] - bump version number * [android] - Camera change listener v2.0 * [core] allow filesource url transform reset * [android] Update attribution wordmark (#8774) * Update wordmark on android * Moved attribution i icon to the right of mapbox word (in mapview preview image) * update padding and margin * [android] update hardcoded branch name * revert version to 5.1.0-SNAPSHOT * [android] - MarkerView deselect events with OnMarkerViewClickListener integration (#8996) * [android] - publish SNAPSHOT from release 5.1.0 branch (#8995) * [ios, macos] edited identity interpolation mode documentation (#8657) * [ios, macos] Factored out tile URL template guide Factored out redundant tile URL template documentation from the MGLRasterSource and MGLVectorSource documentation into a jazzy guide. This documentation used to live in one place, on a method on MGLTileSource, but that method had to be moved to MGLTileSource’s concrete subclasses. A jazzy guide is easier to link to, in any case. * [ios] Telemetry button in modal view controllers (#9027) Fixes #8980. * [android] - bump tools and support lib version due to SNAPSHOT dependencies (#9046) * [android] - bump tools and support lib version for SNAPSHOT dependencies * revert unsupported Circle CI build tools version * [core] Make destructor virtual to avoid object splicing during destruction * [core] add error for non-virtual destructor deletes + add virtual dtors * [android] - remove marker from selected markers when removing marker from annotation manager. (#9047) * Observe layout guides (#7716) * [ios] observe layout guides * [ios] update changelog * [ios, macos] Change == to = in style function initializers * [ios] Add annotation view initializer with annotation and reuse id (#9029) * [ios] Remove annotation view from container view when annotation removed (#9025) The annotation container view keeps an array of annotation views that is separate from the array of subviews that is a property of the UIView parent class. This removes an annotation view from that container view array when the associated annotation is removed. This avoids issue related to previously removed annotation views continuing to be involved in map view logic around annotation view selection due to taps. * [android] - correct bearing conversion when animating the map with jumpTo, easeTo and animateTo. (#9050) * [ios, macos] Updated `maximumZoomLevel` description, cherry-picked #8818 (#8842) Cherry-picked from a3e4e67ea68c455178d5c5ef3d864972fcf41147. * [ios] Updated podspecs and changelog for v3.5.3 (#8870) Cherry-picked from 25c19902a22e240da4e7ebf1974125b7e67bd21e. * [ios] Update podspecs and changelog for iOS v3.5.4 Cherry-picked from db7bb509e95d737199efa73a47bdcc973966ed97. * [ios, macos] Updated changelogs * [ios, macos] changed TRUE -> 'true' (#9059) fixes #9056 * [ios, macos] Light property implementation in MGLStyle (#9043) * [ios, macos] Add MGLLight to MGLStyle * [ios, macos] Implement Objc bindings for Light object * [ios, macos] Remove rawLight from MGLLight and re-implement it as value class * [ios, macos] Fix build on macos * [ios, macos] Add MGLLight documentation, Move MGLLightPosition to MGLLight * [ios, macos] Add MGLLight tests. * [ios, macos] Update changelogs * [ios, macos] Fix misspelling * [ios, macos] Fix MGLLightAnchor enum property names * [ios, macos] Update documentation. Improve varialble naming. * [ios, macos] Rename MGLLightPosition to MGLSphericalPosition * [ios, macos] Update data types of MGLSphericalPosition * [android] - horizontally rotated in snapshot (#9083) * Cherry-pick arabic text to release branch v3.6.0 (#9071) * [core] Throttle tiles to redo symbol placement at most once every 300ms. Fixes issue #8435 and prepares for pitch-scaling changes in issue #8967. * [core] Disable letter-spacing for Arabic labels (issue #9057) * [ios,macos] multipolygon coordinate (#8713) * [ios] MGLMultiPolygon's coordinate property implemented * [ios,macos] Add polylabalel to project config * [ios,macos] Change coordinate property for MGLPolyline,MGLPolygon,MGLMultiPolygon * [macos] Change project configuration to support polilabel * [ios,macos] Add MGLLocationCoordinate2DFromPoint * [ios, macos] Update changelogs * [ios, macos] remove unnecesary variables * [ios, macos] Add radians conversions * [ios, macos] Add coordinate calc to MGLPolyline * [ios, macos] Move radian fuctions to MGLGeometry_Private.h * [ios, macos] Fix code style * [ios, macos] Fix code indentation * [ios, macos] Fix radian per meters constant * [ios, macos] Add test scenarios to testPolyline * [ios, macos] Fix test accuracy * [ios, macos] More robust Streets localization Added Arabic, Portuguese, and Simplified Chinese to the list of languages with specialized fields in the Mapbox Streets source. Rely on NSBundle to select the most appropriate locale based on the user’s preferred languages. * [ios] Fallback to Mapbox.bundle as the framework bundle (#9074) Fixes an issue where localizations could not be found when using static builds. Throws exception if our bundle can't be found. * [ios] Move image resources to an asset catalog & switch to PDFs * [ios, macos] Updated changelogs Reorganized the changelogs with a new packaging section. Added blurbs about #9062, #8713, #9060, and #9031. * [ios] Update pods spec for iOS v3.6.0-beta.1 * [macos] Enable View ‣ Traffic Night Enable the View ‣ Traffic Night menu item and check it when that style is active. * [android] - stop location updates when toggle MyLocationView state (#9099) * [android] - LatLngBounds bearing default value (#9102) * [ios, macos] Fix MGLLight.achor to accept style functions * [ios] Fix annotation initializers for subclasses of MGLAnnotationView (#9104) Use a common init function in both of the provided initializers so that subclasses of `MGLAnnotationView` written in Swift don't need to override `init(annotation, reuseIdentifier)` * [ios] Moved `MGLLight` in jazzy table of contents (#9111) * [android] - logo placement for creating a Mapview programatically (#9094) * [android] - Correct logo placement for creating a Mapview programatically, fixup non default placements * Fixed NIGHTY_TWO_DP typo to NINETY_TWO_DP * [android] - add binding support for Light (#9013) * [android] Update Lost to final version 3.0.0 (#9112) * update lost to final version 3.0.0 * bump MAS version to 2.1.1 * [android] - convert dp to pixels when getting meters per pixel at. (#9048) * Release Android v5.1.0-beta.3 (#9115) * [android] - Changelog update for Android release v5.1.0-beta.3 * update CI & version * reset release properties * [android] - harden orientation changes (#9128) * [ios] Remove filter of single metric event * [ios] remove layout guide observers * Migrate to GL JS–powered feedback form (#9078) * [ios, macos] Updated feedback URL * [ios, macos] Add referrer, heading, pitch to feedback URL * [ios, macos] Updated changelogs for feedback changes * [ios] Vary referrer by platform * [android] - javadoc update for 5.1.0 release (#9138) * [android] - javadoc update for 5.1.0 release * oxford comma * Grammar/spelling tweaks * grammar tweak * grammar tweak * Grammar tweaks * Grammar tweaks * [android] fix missing access token variable issue (#9151) * [ios] Update pods spec for iOS v3.6.0-beta.2 * [android] Cherry picking 9133 (#9145) * [android] Fix tracking mode + camera race condition (#9133) * [android] fix tracking mode + camera race condition * fix resetTrackingModesIfRequired bug (comparing current camera position with target camera position * cherry pick #9133 and update CHANGELOG * add null check to prevent null pointer exception * add null check in custom location engine activity to prevent null pointer exception (#9159) * [core] Make TransformState LatLngBounds optional * [ios] Make annotation view rotation alignment configurable (#9147) This commit adds `rotatesWithMap` property on `MGLAnnotationView`. This property, when set to `YES` fixes the annotation to a map such that view follows map's rotation angle. This is useful when user wants to display rotation-dependent annotations (e.g. sector lights). * [android] - validate if gestures should execute (#9173)
-rw-r--r--platform/android/CHANGELOG.md42
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle4
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle1
-rw-r--r--platform/android/MapboxGLAndroidSDK/proguard-rules.pro89
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java29
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java67
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java63
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java67
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java148
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java52
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java115
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java4
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java57
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java65
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java2
-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/layers/TransitionOptions.java28
-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/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java59
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro1
-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/camera/CameraPositionActivity.java31
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java10
-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/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java4
-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/layout/activity_press_for_marker.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_building.xml12
-rw-r--r--platform/android/build.gradle1
-rw-r--r--platform/android/config.cmake4
-rw-r--r--platform/android/dependencies.gradle14
-rw-r--r--platform/android/gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--platform/android/scripts/generate-style-code.js93
-rw-r--r--platform/android/scripts/release.py48
-rwxr-xr-xplatform/android/src/jni.cpp3
-rw-r--r--platform/android/src/map/camera_position.cpp7
-rwxr-xr-xplatform/android/src/native_map_view.cpp23
-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
-rw-r--r--platform/darwin/docs/guides/Tile URL Templates.md.ejs109
-rw-r--r--platform/darwin/scripts/generate-style-code.js13
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm31
-rw-r--r--platform/darwin/src/MGLAttributionInfo_Private.h18
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLGeometry_Private.h64
-rw-r--r--platform/darwin/src/MGLLight.h125
-rw-r--r--platform/darwin/src/MGLLight.mm113
-rw-r--r--platform/darwin/src/MGLLight_Private.h23
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm14
-rw-r--r--platform/darwin/src/MGLPolygon.mm20
-rw-r--r--platform/darwin/src/MGLPolyline.mm65
-rw-r--r--platform/darwin/src/MGLRasterSource.h91
-rw-r--r--platform/darwin/src/MGLStyle.h9
-rw-r--r--platform/darwin/src/MGLStyle.mm17
-rw-r--r--platform/darwin/src/MGLStyleValue.h6
-rw-r--r--platform/darwin/src/MGLStyleValue.mm6
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h14
-rw-r--r--platform/darwin/src/MGLTypes.h1
-rw-r--r--platform/darwin/src/MGLVectorSource.h91
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.h4
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.m33
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h29
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.m23
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h1
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm15
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m12
-rw-r--r--platform/darwin/test/MGLCodingTests.m119
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift2
-rw-r--r--platform/darwin/test/MGLLightTest.mm217
-rw-r--r--platform/ios/CHANGELOG.md22
-rw-r--r--platform/ios/Mapbox-iOS-SDK-symbols.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK.podspec2
-rw-r--r--platform/ios/app/MBXViewController.m21
-rw-r--r--platform/ios/docs/guides/Tile URL Templates.md99
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj116
-rw-r--r--platform/ios/jazzy.yml2
-rw-r--r--platform/ios/originals/compass.sketchbin0 -> 4881 bytes
-rw-r--r--platform/ios/resources/Compass.pngbin1139 -> 0 bytes
-rw-r--r--platform/ios/resources/Compass@2x.pngbin1892 -> 0 bytes
-rw-r--r--platform/ios/resources/Compass@3x.pngbin3398 -> 0 bytes
-rw-r--r--platform/ios/resources/Images.xcassets/Compass.imageset/Contents.json12
-rw-r--r--platform/ios/resources/Images.xcassets/Compass.imageset/compass.pdfbin0 -> 4574 bytes
-rw-r--r--platform/ios/resources/Images.xcassets/Contents.json6
-rw-r--r--platform/ios/resources/Images.xcassets/default_marker.imageset/Contents.json12
-rw-r--r--platform/ios/resources/Images.xcassets/default_marker.imageset/default_marker.pdfbin0 -> 2601 bytes
-rw-r--r--platform/ios/resources/Images.xcassets/mapbox.imageset/Contents.json12
-rw-r--r--platform/ios/resources/Images.xcassets/mapbox.imageset/mapbox.pdfbin0 -> 8823 bytes
-rw-r--r--platform/ios/resources/default_marker.pngbin1010 -> 0 bytes
-rw-r--r--platform/ios/resources/default_marker@2x.pngbin1995 -> 0 bytes
-rw-r--r--platform/ios/resources/default_marker@3x.pngbin2998 -> 0 bytes
-rw-r--r--platform/ios/resources/mapbox.pngbin2347 -> 0 bytes
-rw-r--r--platform/ios/resources/mapbox@2x.pngbin5290 -> 0 bytes
-rw-r--r--platform/ios/resources/mapbox@3x.pngbin8245 -> 0 bytes
-rw-r--r--platform/ios/src/MGLAPIClient.m2
-rw-r--r--platform/ios/src/MGLAnnotationView.h43
-rw-r--r--platform/ios/src/MGLAnnotationView.mm57
-rw-r--r--platform/ios/src/MGLMapView.mm253
-rw-r--r--platform/ios/src/MGLMapboxEvents.m7
-rw-r--r--platform/ios/src/MGLScaleBar.mm6
-rw-r--r--platform/ios/src/Mapbox.h1
-rw-r--r--platform/ios/test/MGLAnnotationViewIntegrationTests.swift23
-rw-r--r--platform/ios/test/MGLAnnotationViewTests.m23
-rw-r--r--platform/macos/CHANGELOG.md15
-rw-r--r--platform/macos/app/MGLVectorSource+MBXAdditions.h2
-rw-r--r--platform/macos/app/MGLVectorSource+MBXAdditions.m18
-rw-r--r--platform/macos/app/MapDocument.m8
-rw-r--r--platform/macos/docs/guides/Tile URL Templates.md98
-rw-r--r--platform/macos/jazzy.yml2
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj36
-rw-r--r--platform/macos/src/MGLMapView.mm15
-rw-r--r--platform/macos/src/Mapbox.h1
-rw-r--r--scripts/config.xcconfig.in1
148 files changed, 4058 insertions, 855 deletions
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 7807334c14..a9d31426c3 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -3,11 +3,51 @@
Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started.
## 5.1.0 - TBA
+* Fix tracking mode + camera race condition [#9133](https://github.com/mapbox/mapbox-gl-native/pull/9133)
+* Harden orientation changes [#9128](https://github.com/mapbox/mapbox-gl-native/pull/9128)
+
+## 5.1.0-beta.3 - May 26, 2017
+
+* Add binding support for Light [#9013](https://github.com/mapbox/mapbox-gl-native/pull/9013)
* Update attribution with new Mapbox wordmark [#8774](https://github.com/mapbox/mapbox-gl-native/pull/8774)
+* LatLngBounds bearing default value [#9102](https://github.com/mapbox/mapbox-gl-native/pull/9102)
+* Stop location updates when toggling MyLocationView [#9099](https://github.com/mapbox/mapbox-gl-native/pull/9099)
+* Horizontally rotated in snapshot [#9083](https://github.com/mapbox/mapbox-gl-native/pull/9083)
+* Disable letter spacing for Arabic text [#9071](https://github.com/mapbox/mapbox-gl-native/pull/9071)
+* Correct bearing conversion when animating the map [#9050](https://github.com/mapbox/mapbox-gl-native/pull/9050)
+* Don't leak selected markers when removing [#9047](https://github.com/mapbox/mapbox-gl-native/pull/9047)
+* Bump tools and support lib version [#9046](https://github.com/mapbox/mapbox-gl-native/pull/9046)
+* MarkerView deselect events with OnMarkerViewClickListener [#9047](https://github.com/mapbox/mapbox-gl-native/pull/9047)
+* LOST update to v3.0.0 [#9112](https://github.com/mapbox/mapbox-gl-native/pull/9112)
+* Convert dp to pixels for meters per pixel at latitude [#9048](https://github.com/mapbox/mapbox-gl-native/pull/9048)
+
+## 5.1.0-beta.2 - May 12, 2017
+
+5.1.0-beta.2 builds further on 5.1.0-beta.1 and adds:
+
+* When a layer is added, reload its source's tiles [#8963](https://github.com/mapbox/mapbox-gl-native/pull/8963)
+* Update release script to support CircleCI builds [#8950](https://github.com/mapbox/mapbox-gl-native/pull/8950)
+* URL getter on Sources [#8959](https://github.com/mapbox/mapbox-gl-native/pull/8959)
+* Build SNAPSHOT from release branch CI configuration [#8958](https://github.com/mapbox/mapbox-gl-native/pull/8958)
+* Fix UI test filter in Makefile [#8960](https://github.com/mapbox/mapbox-gl-native/pull/8960)
+* Bump & fixup dependencies [#8921](https://github.com/mapbox/mapbox-gl-native/pull/8921)
+* Ignore already deleted region [#8920](https://github.com/mapbox/mapbox-gl-native/pull/8920)
+* Keep offline observer when timeout occurs [#8919](https://github.com/mapbox/mapbox-gl-native/pull/8919)
+* Show error message when no browser installed [#8920](https://github.com/mapbox/mapbox-gl-native/pull/8920)
+* Reset observers of removed Sources and Layers [#8900](https://github.com/mapbox/mapbox-gl-native/pull/8900)
+* Only build custom layer .so for debug builds [#8885](https://github.com/mapbox/mapbox-gl-native/pull/8885)
+* Update localizations [#8883](https://github.com/mapbox/mapbox-gl-native/pull/8883)
+* Reset observers of removed Sources and Layers [#8862](https://github.com/mapbox/mapbox-gl-native/pull/8862)
+* Remove force style cascade [#8866](https://github.com/mapbox/mapbox-gl-native/pull/8866)
+* Update proguard config [#8944](https://github.com/mapbox/mapbox-gl-native/pull/8944)
+* Update LOST to 2.3.0-SNAPSHOT [#8872](https://github.com/mapbox/mapbox-gl-native/pull/8872)
+* Update logo [#8774](https://github.com/mapbox/mapbox-gl-native/pull/8774)
+* Camera change listener v2.0 [#8644](https://github.com/mapbox/mapbox-gl-native/pull/8644)
+* Allow filesource url transform reset [#8957](https://github.com/mapbox/mapbox-gl-native/pull/8957)
## 5.1.0-beta.1 - May 2, 2017
-5.1.0 builds further on 5.0.2 and adds:
+5.1.0-beta.1 builds further on 5.0.2 and adds:
* Support for FillExtrusionLayer [#8431](https://github.com/mapbox/mapbox-gl-native/pull/8431)
* Limit Viewport [#8622](https://github.com/mapbox/mapbox-gl-native/pull/8622)
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 40712da065..adbc7cad7f 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -95,6 +95,9 @@ android {
}
}
}
+
+ // proguard config for .aar
+ consumerProguardFiles 'proguard-rules.pro'
}
// avoid naming conflicts, force usage of prefix
@@ -126,7 +129,6 @@ android {
release {
// aar proguard configuration
- consumerProguardFiles 'proguard-rules.pro'
jniDebuggable false
}
}
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/proguard-rules.pro b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
index baecd80e50..8e47815451 100644
--- a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
@@ -2,89 +2,8 @@
# in ../sdk/tools/proguard/proguard-android.txt,
# contents of this file will be appended into proguard-android.txt
-keepattributes Signature, *Annotation*, EnclosingMethod
-
-# Square okio, ignoring warnings,
-# see https://github.com/square/okio/issues/60
--dontwarn okhttp3.**
--dontwarn okio.**
-
-# Gesture package
-keep class almeros.android.multitouch.gesturedetectors.** { *; }
-
-# Package annotations
--keep class com.mapbox.mapboxsdk.annotations.** { *; }
-
-# Package camera
--keep class com.mapbox.mapboxsdk.camera.** { *; }
-
-# Package geometry
--keep class com.mapbox.mapboxsdk.geometry.** { *; }
-
-# Package http
--keep class com.mapbox.mapboxsdk.http.** { *; }
-
-# Package maps
--keep class com.mapbox.mapboxsdk.maps.** { *; }
-
-# Package net
--keep class com.mapbox.mapboxsdk.net.** { *; }
-
-# Package offline
--keep class com.mapbox.mapboxsdk.offline.** { *; }
-
-# Package storage
--keep class com.mapbox.mapboxsdk.storage.** { *; }
-
-# Package style
--keep class com.mapbox.mapboxsdk.style.layers.** { *; }
--keep class com.mapbox.mapboxsdk.style.sources.** { *; }
--keep class com.mapbox.mapboxsdk.style.functions.** { *; }
-
-# Package telemetry
--keep class com.mapbox.mapboxsdk.telemetry.** { *; }
-
-#
-# Mapbox-java Proguard rules
-# We include these rules since libjava is a Jar file not AAR
-#
-
-# Retrofit 2
-# Platform calls Class.forName on types which do not exist on Android to determine platform.
--dontnote retrofit2.Platform
-# Platform used when running on RoboVM on iOS. Will not be used at runtime.
--dontnote retrofit2.Platform$IOS$MainThreadExecutor
-# Platform used when running on Java 8 VMs. Will not be used at runtime.
--dontwarn retrofit2.Platform$Java8
-# Retain generic type information for use by reflection by converters and adapters.
--keepattributes Signature
-# Retain declared checked exceptions for use by a Proxy instance.
--keepattributes Exceptions
-
-# For using GSON @Expose annotation
--keepattributes *Annotation*
-# Gson specific classes
--dontwarn sun.misc.**
-
-# Prevent proguard from stripping interface information from TypeAdapterFactory,
-# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
--keep class * implements com.google.gson.TypeAdapterFactory
--keep class * implements com.google.gson.JsonSerializer
--keep class * implements com.google.gson.JsonDeserializer
-
-# MAS Data Models
--keep class com.mapbox.services.commons.geojson.** { *; }
--keep class com.mapbox.services.mapmatching.v4.models.** { *; }
--keep class com.mapbox.services.distance.v1.models.** { *; }
--keep class com.mapbox.services.directions.v4.models.** { *; }
--keep class com.mapbox.services.directions.v5.models.** { *; }
--keep class com.mapbox.services.geocoding.v5.models.** { *; }
-
--dontwarn javax.annotation.**
-
--keepclassmembers class rx.internal.util.unsafe.** {
- long producerIndex;
- long consumerIndex;
-}
-
--keep class com.google.** { *; }
--dontwarn com.google.** \ No newline at end of file
+-keep class com.mapbox.mapboxsdk.** { *; }
+-keep interface com.mapbox.mapboxsdk.** { *; }
+-keep class com.mapbox.services.android.telemetry.** { *; }
+-keep class com.mapbox.services.commons.** { *;} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
index 8098ee4d86..81134e9497 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk;
+import android.app.Application;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -15,6 +16,14 @@ import com.mapbox.services.android.telemetry.MapboxTelemetry;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
+/**
+ * The entry point of the Mapbox Android SDK.
+ * <p>
+ * Obtain a reference by calling {@link #getInstance(Context, String)}. Usually this class is configured in
+ * {@link Application#onCreate()} and is responsible for the active access token, application context, and
+ * connectivity state.
+ * </p>
+ */
public final class Mapbox {
private static Mapbox INSTANCE;
@@ -25,7 +34,7 @@ public final class Mapbox {
/**
* Get an instance of Mapbox.
* <p>
- * This class manages the active access token, application context and connectivity state.
+ * This class manages the active access token, application context, and connectivity state.
* </p>
*
* @param context Android context which holds or is an application context
@@ -52,9 +61,9 @@ public final class Mapbox {
}
/**
- * Access Token for this application.
+ * Access token for this application.
*
- * @return Mapbox Access Token
+ * @return Mapbox access token
*/
public static String getAccessToken() {
validateMapbox();
@@ -72,7 +81,7 @@ public final class Mapbox {
}
/**
- * Runtime validation of Access Token.
+ * Runtime validation of access token.
*
* @throws MapboxConfigurationException exception thrown when not using a valid accessToken
*/
@@ -92,11 +101,11 @@ public final class Mapbox {
}
/**
- * Manually sets the connectivity state of the app. This is useful for apps that control their
+ * Manually sets the connectivity state of the app. This is useful for apps which control their
* own connectivity state and want to bypass any checks to the ConnectivityManager.
*
* @param connected flag to determine the connectivity state, true for connected, false for
- * disconnected, null for ConnectivityManager to determine.
+ * disconnected, and null for ConnectivityManager to determine.
*/
public static synchronized void setConnected(Boolean connected) {
// Connectivity state overridden by app
@@ -104,10 +113,10 @@ public final class Mapbox {
}
/**
- * Determines whether we have an Internet connection available. Please do not rely on this
- * method in your apps, this method is used internally by the SDK.
+ * Determines whether we have an internet connection available. Please do not rely on this
+ * method in your apps. This method is used internally by the SDK.
*
- * @return true if there is an Internet connection, false otherwise
+ * @return true if there is an internet connection, false otherwise
*/
public static synchronized Boolean isConnected() {
if (INSTANCE.connected != null) {
@@ -119,4 +128,4 @@ public final class Mapbox {
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return (activeNetwork != null && activeNetwork.isConnected());
}
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
index b1a05ec436..2ee17c227d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
@@ -1,15 +1,18 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
+import android.util.DisplayMetrics;
-import com.mapbox.mapboxsdk.maps.MapView;
+import java.nio.ByteBuffer;
/**
- * Icon is the visual representation of a {@link Marker} on a {@link MapView}.
+ * Icon is the visual representation of a Marker on a MapView.
*
* @see Marker
+ * @see IconFactory
*/
public class Icon {
+
private Bitmap mBitmap;
private String mId;
@@ -19,29 +22,67 @@ public class Icon {
}
/**
- * {@link String} identifier for this {@link Icon}.
+ * String identifier for this icon.
*
- * @return {@link String} identifier for this {@link Icon}.
+ * @return String identifier for this icon.
*/
public String getId() {
return mId;
}
/**
- * Get the {@link Bitmap} being used for this {@link Icon}.
+ * Get the bitmap being used for this icon.
*
- * @return The {@link Bitmap} being used for the {@link Icon}.
+ * @return The bitmap being used for the icon.
*/
public Bitmap getBitmap() {
+ if (mBitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ mBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
return mBitmap;
}
/**
- * Compares this {@link Icon} object with another {@link Icon} and determines if they match.
+ * Get the icon bitmap scale.
+ * <p>
+ * Requires the bitmap to be set before calling this method.
+ * </p>
+ *
+ * @return the scale of the bitmap
+ */
+ public float getScale() {
+ if (mBitmap == null) {
+ throw new IllegalStateException("Required to set a Icon before calling getScale");
+ }
+ float density = mBitmap.getDensity();
+ if (density == Bitmap.DENSITY_NONE) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ }
+ return density / DisplayMetrics.DENSITY_DEFAULT;
+ }
+
+ /**
+ * Get the icon bitmap bytes.
+ * <p>
+ * Requires the bitmap to be set before calling this method.
+ * </p>
*
- * @param object Another {@link Icon} to compare with this object.
- * @return True if the {@link Icon} being passed in matches this {@link Icon} object. Else,
- * false.
+ * @return the bytes of the bitmap
+ */
+ public byte[] toBytes() {
+ if (mBitmap == null) {
+ throw new IllegalStateException("Required to set a Icon before calling toBytes");
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(mBitmap.getRowBytes() * mBitmap.getHeight());
+ mBitmap.copyPixelsToBuffer(buffer);
+ return buffer.array();
+ }
+
+ /**
+ * Compares this icon object with another icon and determines if they match.
+ *
+ * @param object Another iconi to compare with this object.
+ * @return True if the icon being passed in matches this icon object. Else, false.
*/
@Override
public boolean equals(Object object) {
@@ -53,11 +94,7 @@ public class Icon {
}
Icon icon = (Icon) object;
-
- if (!mBitmap.equals(icon.mBitmap)) {
- return false;
- }
- return mId.equals(icon.mId);
+ return mBitmap.equals(icon.mBitmap) && mId.equals(icon.mId);
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
index 30336d4ebd..56e8cc4ce2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.annotations;
import android.support.annotation.FloatRange;
import android.support.annotation.Nullable;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -361,6 +362,9 @@ public class MarkerView extends Marker {
*/
@Override
public Icon getIcon() {
+ if (markerViewIcon == null) {
+ setIcon(IconFactory.getInstance(Mapbox.getApplicationContext()).defaultMarkerView());
+ }
return markerViewIcon;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
index 5e958ff565..66c261f1d0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
@@ -156,7 +156,7 @@ public final class CameraPosition implements Parcelable {
}
/**
- * Builder for composing {@link CameraPosition} objects.
+ * Builder for composing CameraPosition objects.
*/
public static final class Builder {
@@ -190,7 +190,7 @@ public final class CameraPosition implements Parcelable {
/**
* Create Builder with an existing CameraPosition data.
*
- * @param typedArray TypedArray containgin attribute values
+ * @param typedArray TypedArray containing attribute values
*/
public Builder(TypedArray typedArray) {
super();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
index 64b86054a0..8e1411e273 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
@@ -15,7 +15,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Factory for creating {@link CameraUpdate} objects.
+ * Factory for creating CameraUpdate objects.
*/
public final class CameraUpdateFactory {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
index f53c65d055..88c3bef673 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
@@ -16,7 +16,7 @@ import java.lang.annotation.RetentionPolicy;
public class MyBearingTracking {
/**
- * Indicates the parameter accepts one of the values from {@link MyBearingTracking}.
+ * Indicates that the parameter accepts one of the values from MyBearingTracking.
*/
@IntDef( {NONE, COMPASS, GPS, /**COMBINED**/})
@Retention(RetentionPolicy.SOURCE)
@@ -38,6 +38,4 @@ public class MyBearingTracking {
*/
public static final int GPS = 0x00000008;
- // public static final int COMBINED = 0x00000012;
-
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
index 39f653596f..a1744d701f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
@@ -17,7 +17,7 @@ import java.lang.annotation.RetentionPolicy;
public class MyLocationTracking {
/**
- * Indicates the parameter accepts one of the values from {@link MyLocationTracking}.
+ * Indicates the parameter accepts one of the values from MyLocationTracking.
*/
@IntDef( {TRACKING_NONE, TRACKING_FOLLOW})
@Retention(RetentionPolicy.SOURCE)
@@ -30,7 +30,7 @@ public class MyLocationTracking {
public static final int TRACKING_NONE = 0x00000000;
/**
- * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView}
+ * Tracking the location of the user. {@link MapView} will reposition to center of {@link MyLocationView}
*/
public static final int TRACKING_FOLLOW = 0x00000004;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
index 77d0929df3..31e6313509 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
@@ -19,7 +19,7 @@ public class Style {
/**
- * Indicates the parameter accepts one of the values from {@link Style}. Using one of these
+ * Indicates the parameter accepts one of the values from Style. Using one of these
* constants means your map style will always use the latest version and may change as we
* improve the style
*/
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java
index b795cf1d5b..4e934fa3cc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java
@@ -2,7 +2,7 @@ package com.mapbox.mapboxsdk.location;
import android.content.Context;
import android.location.Location;
-import android.util.Log;
+import android.support.annotation.NonNull;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
@@ -15,6 +15,8 @@ import com.mapzen.android.lost.api.LostApiClient;
import java.lang.ref.WeakReference;
+import timber.log.Timber;
+
/**
* Manages locational updates. Contains methods to register and unregister location listeners.
* <ul>
@@ -33,8 +35,6 @@ import java.lang.ref.WeakReference;
public class LocationSource extends LocationEngine implements
LostApiClient.ConnectionCallbacks, LocationListener {
- private static final String LOG_TAG = LocationSource.class.getSimpleName();
-
private static LocationEngine instance;
private WeakReference<Context> context;
@@ -48,7 +48,13 @@ public class LocationSource extends LocationEngine implements
.build();
}
- public static synchronized LocationEngine getLocationEngine(Context context) {
+ /**
+ * Get the LocationEngine instance.
+ *
+ * @param context a Context from which the application context is derived
+ * @return the LocationEngine instance
+ */
+ public static synchronized LocationEngine getLocationEngine(@NonNull Context context) {
if (instance == null) {
instance = new LocationSource(context.getApplicationContext());
}
@@ -56,6 +62,10 @@ public class LocationSource extends LocationEngine implements
return instance;
}
+ /**
+ * Activate the location engine which will connect whichever location provider you are using. You'll need to call
+ * this before requesting user location updates using {@link LocationEngine#requestLocationUpdates()}.
+ */
@Override
public void activate() {
if (lostApiClient != null && !lostApiClient.isConnected()) {
@@ -63,6 +73,11 @@ public class LocationSource extends LocationEngine implements
}
}
+ /**
+ * Disconnect the location engine which is useful when you no longer need location updates or requesting the users
+ * {@link LocationEngine#getLastLocation()}. Before deactivating, you'll need to stop request user location updates
+ * using {@link LocationEngine#removeLocationUpdates()}.
+ */
@Override
public void deactivate() {
if (lostApiClient != null && lostApiClient.isConnected()) {
@@ -70,11 +85,20 @@ public class LocationSource extends LocationEngine implements
}
}
+ /**
+ * Check if your location provider has been activated/connected. This is mainly used internally but is also useful in
+ * the rare case when you'd like to know if your location engine is connected or not.
+ *
+ * @return boolean true if the location engine has been activated/connected, else false.
+ */
@Override
public boolean isConnected() {
return lostApiClient.isConnected();
}
+ /**
+ * Invoked when the location provider has connected.
+ */
@Override
public void onConnected() {
for (LocationEngineListener listener : locationListeners) {
@@ -82,11 +106,19 @@ public class LocationSource extends LocationEngine implements
}
}
+ /**
+ * Invoked when the location provider connection has been suspended.
+ */
@Override
public void onConnectionSuspended() {
- Log.d(LOG_TAG, "Connection suspended.");
+ Timber.d("Connection suspended.");
}
+ /**
+ * Returns the Last known location is the location provider is connected and location permissions are granted.
+ *
+ * @return the last known location
+ */
@Override
public Location getLastLocation() {
if (lostApiClient.isConnected() && PermissionsManager.areLocationPermissionsGranted(context.get())) {
@@ -97,6 +129,9 @@ public class LocationSource extends LocationEngine implements
return null;
}
+ /**
+ * Request location updates to the location provider.
+ */
@Override
public void requestLocationUpdates() {
// Common params
@@ -122,6 +157,9 @@ public class LocationSource extends LocationEngine implements
}
}
+ /**
+ * Dismiss ongoing location update to the location provider.
+ */
@Override
public void removeLocationUpdates() {
if (lostApiClient.isConnected()) {
@@ -129,20 +167,15 @@ public class LocationSource extends LocationEngine implements
}
}
+ /**
+ * Invoked when the Location has changed.
+ *
+ * @param location the new location
+ */
@Override
public void onLocationChanged(Location location) {
for (LocationEngineListener listener : locationListeners) {
listener.onLocationChanged(location);
}
}
-
- @Override
- public void onProviderDisabled(String provider) {
- Log.d(LOG_TAG, "Provider disabled: " + provider);
- }
-
- @Override
- public void onProviderEnabled(String provider) {
- Log.d(LOG_TAG, "Provider enabled: " + provider);
- }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
index 9b6706b90c..7e7947047e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
@@ -100,6 +100,10 @@ class AnnotationManager {
if (annotation instanceof Marker) {
Marker marker = (Marker) annotation;
marker.hideInfoWindow();
+ if (selectedMarkers.contains(marker)) {
+ selectedMarkers.remove(marker);
+ }
+
if (marker instanceof MarkerView) {
markerViewManager.removeMarkerView((MarkerView) marker);
}
@@ -112,6 +116,10 @@ class AnnotationManager {
if (annotation instanceof Marker) {
Marker marker = (Marker) annotation;
marker.hideInfoWindow();
+ if (selectedMarkers.contains(marker)) {
+ selectedMarkers.remove(marker);
+ }
+
if (marker instanceof MarkerView) {
markerViewManager.removeMarkerView((MarkerView) marker);
}
@@ -124,6 +132,7 @@ class AnnotationManager {
Annotation annotation;
int count = annotationsArray.size();
long[] ids = new long[count];
+ selectedMarkers.clear();
for (int i = 0; i < count; i++) {
ids[i] = annotationsArray.keyAt(i);
annotation = annotationsArray.get(ids[i]);
@@ -383,12 +392,15 @@ class AnnotationManager {
for (Marker nearbyMarker : nearbyMarkers) {
for (Marker selectedMarker : selectedMarkers) {
if (nearbyMarker.equals(selectedMarker)) {
- if (onMarkerClickListener != null) {
- // end developer has provided a custom click listener
+ if (nearbyMarker instanceof MarkerView) {
+ handledDefaultClick = markerViewManager.onClickMarkerView((MarkerView) nearbyMarker);
+ } else if (onMarkerClickListener != null) {
handledDefaultClick = onMarkerClickListener.onMarkerClick(nearbyMarker);
- if (!handledDefaultClick) {
- deselectMarker(nearbyMarker);
- }
+ }
+
+ if (!handledDefaultClick) {
+ // only deselect marker if user didn't handle the click event themselves
+ deselectMarker(nearbyMarker);
}
return true;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
new file mode 100644
index 0000000000..bd028aecb6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
@@ -0,0 +1,67 @@
+package com.mapbox.mapboxsdk.maps;
+
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener;
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveCanceledListener;
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener;
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener;
+
+class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, MapboxMap.OnCameraMoveListener,
+ MapboxMap.OnCameraMoveCanceledListener, OnCameraIdleListener {
+
+ private boolean idle = true;
+
+ private OnCameraMoveStartedListener onCameraMoveStartedListener;
+ private OnCameraMoveCanceledListener onCameraMoveCanceledListener;
+ private OnCameraMoveListener onCameraMoveListener;
+ private OnCameraIdleListener onCameraIdleListener;
+
+ void setOnCameraMoveStartedListener(OnCameraMoveStartedListener onCameraMoveStartedListener) {
+ this.onCameraMoveStartedListener = onCameraMoveStartedListener;
+ }
+
+ void setOnCameraMoveCanceledListener(OnCameraMoveCanceledListener onCameraMoveCanceledListener) {
+ this.onCameraMoveCanceledListener = onCameraMoveCanceledListener;
+ }
+
+ void setOnCameraMoveListener(OnCameraMoveListener onCameraMoveListener) {
+ this.onCameraMoveListener = onCameraMoveListener;
+ }
+
+ void setOnCameraIdleListener(OnCameraIdleListener onCameraIdleListener) {
+ this.onCameraIdleListener = onCameraIdleListener;
+ }
+
+ @Override
+ public void onCameraMoveStarted(int reason) {
+ if (!idle) {
+ return;
+ }
+
+ idle = false;
+ if (onCameraMoveStartedListener != null) {
+ onCameraMoveStartedListener.onCameraMoveStarted(reason);
+ }
+ }
+
+ @Override
+ public void onCameraMove() {
+ if (onCameraMoveListener != null && !idle) {
+ onCameraMoveListener.onCameraMove();
+ }
+ }
+
+ @Override
+ public void onCameraMoveCanceled() {
+ if (onCameraMoveCanceledListener != null && !idle) {
+ onCameraMoveCanceledListener.onCameraMoveCanceled();
+ }
+ }
+
+ @Override
+ public void onCameraIdle() {
+ if (onCameraIdleListener != null && !idle) {
+ idle = true;
+ onCameraIdleListener.onCameraIdle();
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
index 006122a4e2..aec9a848b7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
@@ -2,6 +2,9 @@ package com.mapbox.mapboxsdk.maps;
import android.graphics.PointF;
+/**
+ * Interface definition of a callback that is invoked when the focal point will change.
+ */
public interface FocalPointChangeListener {
void onFocalPointChanged(PointF pointF);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
index c9d81a88bc..9f4171aee8 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
@@ -1,15 +1,14 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.Bitmap;
-import android.util.DisplayMetrics;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.exceptions.IconBitmapChangedException;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -41,118 +40,109 @@ class IconManager {
Icon loadIconForMarker(Marker marker) {
Icon icon = marker.getIcon();
-
- // calculating average before adding
- int iconSize = icons.size() + 1;
-
- // TODO replace former if case with anchor implementation,
- // current workaround for having extra pixels is diving height by 2
if (icon == null) {
- icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- marker.setIcon(icon);
- } else {
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- }
-
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
+ // TODO replace with anchor implementation, we are faking an anchor by adding extra pixels and diving height by 2
+ // TODO we can move this code afterwards to getIcon as with MarkerView.getIcon
+ icon = loadDefaultIconForMarker(marker);
} else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
+ updateAverageIconSize(icon);
}
+ addIcon(icon);
return icon;
}
- Icon loadIconForMarkerView(MarkerView marker) {
+ void loadIconForMarkerView(MarkerView marker) {
Icon icon = marker.getIcon();
- int iconSize = icons.size() + 1;
- if (icon == null) {
- icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView();
- marker.setIcon(icon);
- }
Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- if (!icons.contains(icon)) {
- icons.add(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
- return icon;
+ updateAverageIconSize(bitmap);
+ addIcon(icon, false);
}
int getTopOffsetPixelsForIcon(Icon icon) {
return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio());
}
- void loadIcon(Icon icon) {
+ int getAverageIconHeight() {
+ return averageIconHeight;
+ }
+
+ int getAverageIconWidth() {
+ return averageIconWidth;
+ }
+
+ private Icon loadDefaultIconForMarker(Marker marker) {
+ Icon icon = IconFactory.getInstance(Mapbox.getApplicationContext()).defaultMarker();
Bitmap bitmap = icon.getBitmap();
- String id = icon.getId();
- if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
- }
- ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
- bitmap.copyPixelsToBuffer(buffer);
+ updateAverageIconSize(bitmap.getWidth(), bitmap.getHeight() / 2);
+ marker.setIcon(icon);
+ return icon;
+ }
+
+ private void addIcon(Icon icon) {
+ addIcon(icon, true);
+ }
- float density = bitmap.getDensity();
- if (density == Bitmap.DENSITY_NONE) {
- density = DisplayMetrics.DENSITY_DEFAULT;
+ private void addIcon(Icon icon, boolean addIconToMap) {
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ if (addIconToMap) {
+ loadIcon(icon);
+ }
+ } else {
+ validateIconChanged(icon);
}
- float scale = density / DisplayMetrics.DENSITY_DEFAULT;
- nativeMapView.addAnnotationIcon(
- id,
+ }
+
+ private void updateAverageIconSize(Icon icon) {
+ updateAverageIconSize(icon.getBitmap());
+ }
+
+ private void updateAverageIconSize(Bitmap bitmap) {
+ updateAverageIconSize(bitmap.getWidth(), bitmap.getHeight());
+ }
+
+ private void updateAverageIconSize(int width, int height) {
+ int iconSize = icons.size() + 1;
+ averageIconHeight = averageIconHeight + (height - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (width - averageIconWidth) / iconSize;
+ }
+
+ private void loadIcon(Icon icon) {
+ Bitmap bitmap = icon.getBitmap();
+ nativeMapView.addAnnotationIcon(icon.getId(),
bitmap.getWidth(),
bitmap.getHeight(),
- scale, buffer.array());
+ icon.getScale(),
+ icon.toBytes());
}
void reloadIcons() {
- int count = icons.size();
- for (int i = 0; i < count; i++) {
- Icon icon = icons.get(i);
+ for (Icon icon : icons) {
loadIcon(icon);
}
}
+ private void validateIconChanged(Icon icon) {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+
void ensureIconLoaded(Marker marker, MapboxMap mapboxMap) {
Icon icon = marker.getIcon();
if (icon == null) {
- icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
- marker.setIcon(icon);
- }
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
+ icon = loadDefaultIconForMarker(marker);
}
+ addIcon(icon);
+ setTopOffsetPixels(marker, mapboxMap, icon);
+ }
+ private void setTopOffsetPixels(Marker marker, MapboxMap mapboxMap, Icon icon) {
// this seems to be a costly operation according to the profiler so I'm trying to save some calls
Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null;
if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) {
marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon));
}
}
-
- int getAverageIconHeight() {
- return averageIconHeight;
- }
-
- int getAverageIconWidth() {
- return averageIconWidth;
- }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
index 80fd6248bc..33e13c5ecc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
@@ -22,6 +22,8 @@ import com.mapbox.services.android.telemetry.MapboxTelemetry;
import com.mapbox.services.android.telemetry.utils.MathUtils;
import com.mapbox.services.android.telemetry.utils.TelemetryUtils;
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE;
+
/**
* Manages gestures events on a MapView.
* <p>
@@ -35,6 +37,7 @@ final class MapGestureDetector {
private final UiSettings uiSettings;
private final TrackingSettings trackingSettings;
private final AnnotationManager annotationManager;
+ private final CameraChangeDispatcher cameraChangeDispatcher;
private final GestureDetectorCompat gestureDetector;
private final ScaleGestureDetector scaleGestureDetector;
@@ -56,12 +59,14 @@ final class MapGestureDetector {
private boolean scaleGestureOccurred = false;
MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings,
- TrackingSettings trackingSettings, AnnotationManager annotationManager) {
+ TrackingSettings trackingSettings, AnnotationManager annotationManager,
+ CameraChangeDispatcher cameraChangeDispatcher) {
this.annotationManager = annotationManager;
this.transform = transform;
this.projection = projection;
this.uiSettings = uiSettings;
this.trackingSettings = trackingSettings;
+ this.cameraChangeDispatcher = cameraChangeDispatcher;
// Touch gesture detectors
gestureDetector = new GestureDetectorCompat(context, new GestureListener());
@@ -187,6 +192,7 @@ final class MapGestureDetector {
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapDragEndEvent(
getLocationFromGesture(event.getX(), event.getY()), transform));
scrollInProgress = false;
+ cameraChangeDispatcher.onCameraIdle();
}
twoTap = false;
@@ -273,6 +279,9 @@ final class MapGestureDetector {
break;
}
+ // notify camera change listener
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
+
// Single finger double tap
if (focalPoint != null) {
// User provided focal point
@@ -337,6 +346,7 @@ final class MapGestureDetector {
// and ignore when a scale gesture has occurred
return false;
}
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
float screenDensity = uiSettings.getPixelRatio();
@@ -362,9 +372,7 @@ final class MapGestureDetector {
long animationTime = (long) (velocityXY / 7 / tiltFactor + MapboxConstants.ANIMATION_DURATION_FLING_BASE);
// update transformation
- transform.setGestureInProgress(true);
transform.moveBy(offsetX, offsetY, animationTime);
- transform.setGestureInProgress(false);
if (onFlingListener != null) {
onFlingListener.onFling();
@@ -375,12 +383,6 @@ final class MapGestureDetector {
// Called for drags
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (!scrollInProgress) {
- scrollInProgress = true;
- MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
- getLocationFromGesture(e1.getX(), e1.getY()),
- MapboxEvent.GESTURE_PAN_START, transform));
- }
if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
return false;
}
@@ -389,10 +391,19 @@ final class MapGestureDetector {
return false;
}
+ if (!scrollInProgress) {
+ scrollInProgress = true;
+
+ // Cancel any animation
+ transform.cancelTransitions();
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
+ MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
+ getLocationFromGesture(e1.getX(), e1.getY()),
+ MapboxEvent.GESTURE_PAN_START, transform));
+ }
+
// reset tracking if needed
trackingSettings.resetTrackingModesIfRequired(true, false, false);
- // Cancel any animation
- transform.cancelTransitions();
// Scroll the map
transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/);
@@ -446,6 +457,8 @@ final class MapGestureDetector {
// If scale is large enough ignore a tap
scaleFactor *= detector.getScaleFactor();
if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
+ // notify camera change listener
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
zoomStarted = true;
}
@@ -465,9 +478,6 @@ final class MapGestureDetector {
return false;
}
- // Cancel any animation
- transform.cancelTransitions();
-
// Gesture is a quickzoom if there aren't two fingers
quickZoom = !twoTap;
@@ -512,6 +522,9 @@ final class MapGestureDetector {
return false;
}
+ // notify camera change listener
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
+
beginTime = detector.getEventTime();
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
getLocationFromGesture(detector.getFocusX(), detector.getFocusY()),
@@ -522,6 +535,7 @@ final class MapGestureDetector {
// Called when the fingers leave the screen
@Override
public void onRotateEnd(RotateGestureDetector detector) {
+ // notify camera change listener
beginTime = 0;
totalAngle = 0.0f;
started = false;
@@ -553,13 +567,8 @@ final class MapGestureDetector {
if (!started) {
return false;
}
-
- // Cancel any animation
- transform.cancelTransitions();
-
// rotation constitutes translation of anything except the center of
// rotation, so cancel both location and bearing tracking if required
-
trackingSettings.resetTrackingModesIfRequired(true, true, false);
// Get rotate value
@@ -593,6 +602,8 @@ final class MapGestureDetector {
return false;
}
+ // notify camera change listener
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
beginTime = detector.getEventTime();
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
getLocationFromGesture(detector.getFocusX(), detector.getFocusY()),
@@ -633,9 +644,6 @@ final class MapGestureDetector {
return false;
}
- // Cancel any animation
- transform.cancelTransitions();
-
// Get tilt value (scale and clamp)
double pitch = transform.getTilt();
pitch -= 0.1 * detector.getShovePixelsDelta();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 4f90b0a8fe..cf1841e180 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -131,6 +131,9 @@ public class MapView extends FrameLayout {
// callback for zooming in the camera
CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
+ // callback for camera change events
+ CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher();
+
// setup components for MapboxMap creation
Projection proj = new Projection(nativeMapView);
UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, view.findViewById(R.id.logoView));
@@ -145,13 +148,14 @@ public class MapView extends FrameLayout {
Polylines polylines = new PolylineContainer(nativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, annotationsArray,
markerViewManager, iconManager, annotations, markers, polygons, polylines);
- Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings);
+ Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings,
+ cameraChangeDispatcher);
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
- registerTouchListener, annotationManager);
+ registerTouchListener, annotationManager, cameraChangeDispatcher);
// user input
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
- annotationManager);
+ annotationManager, cameraChangeDispatcher);
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform);
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 5f1ed0755c..f60ddf616a 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;
@@ -69,6 +70,7 @@ public final class MapboxMap {
private final Transform transform;
private final AnnotationManager annotationManager;
private final MyLocationViewSettings myLocationViewSettings;
+ private final CameraChangeDispatcher cameraChangeDispatcher;
private final OnRegisterTouchListener onRegisterTouchListener;
@@ -76,7 +78,7 @@ public final class MapboxMap {
MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking,
MyLocationViewSettings myLocationView, Projection projection, OnRegisterTouchListener listener,
- AnnotationManager annotations) {
+ AnnotationManager annotations, CameraChangeDispatcher cameraChangeDispatcher) {
this.nativeMapView = map;
this.uiSettings = ui;
this.trackingSettings = tracking;
@@ -85,6 +87,7 @@ public final class MapboxMap {
this.annotationManager = annotations.bind(this);
this.transform = transform;
this.onRegisterTouchListener = listener;
+ this.cameraChangeDispatcher = cameraChangeDispatcher;
}
void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) {
@@ -566,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
//
@@ -1623,11 +1640,52 @@ public final class MapboxMap {
* To unset the callback, use null.
*/
@UiThread
+ @Deprecated
public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) {
transform.setOnCameraChangeListener(listener);
}
/**
+ * Sets a callback that is invoked when camera movement has ended.
+ *
+ * @param listener the listener to notify
+ */
+ @UiThread
+ public void setOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
+ cameraChangeDispatcher.setOnCameraIdleListener(listener);
+ }
+
+ /**
+ * Sets a callback that is invoked when camera movement was cancelled.
+ *
+ * @param listener the listener to notify
+ */
+ @UiThread
+ public void setOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
+ cameraChangeDispatcher.setOnCameraMoveCanceledListener(listener);
+ }
+
+ /**
+ * Sets a callback that is invoked when camera movement has started.
+ *
+ * @param listener the listener to notify
+ */
+ @UiThread
+ public void setOnCameraMoveStartedistener(@Nullable OnCameraMoveStartedListener listener) {
+ cameraChangeDispatcher.setOnCameraMoveStartedListener(listener);
+ }
+
+ /**
+ * Sets a callback that is invoked when camera position changes.
+ *
+ * @param listener the listener to notify
+ */
+ @UiThread
+ public void setOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
+ cameraChangeDispatcher.setOnCameraMoveListener(listener);
+ }
+
+ /**
* Sets a callback that's invoked on every frame rendered to the map view.
*
* @param listener The callback that's invoked on every frame rendered to the map view.
@@ -1941,7 +1999,12 @@ public final class MapboxMap {
/**
* Interface definition for a callback to be invoked when the camera changes position.
+ *
+ * @deprecated Replaced by {@link MapboxMap.OnCameraMoveStartedListener}, {@link MapboxMap.OnCameraMoveListener} and
+ * {@link MapboxMap.OnCameraIdleListener}. The order in which the deprecated onCameraChange method will be called in
+ * relation to the methods in the new camera change listeners is undefined.
*/
+ @Deprecated
public interface OnCameraChangeListener {
/**
* Called after the camera position has changed. During an animation,
@@ -1954,6 +2017,56 @@ public final class MapboxMap {
}
/**
+ * Interface definition for a callback to be invoked for when the camera motion starts.
+ */
+ public interface OnCameraMoveStartedListener {
+ int REASON_API_GESTURE = 1;
+ int REASON_DEVELOPER_ANIMATION = 2;
+ int REASON_API_ANIMATION = 3;
+
+ /**
+ * Called when the camera starts moving after it has been idle or when the reason for camera motion has changed.
+ *
+ * @param reason the reason for the camera change
+ */
+ void onCameraMoveStarted(int reason);
+ }
+
+ /**
+ * Interface definition for a callback to be invoked for when the camera changes position.
+ */
+ public interface OnCameraMoveListener {
+ /**
+ * Called repeatedly as the camera continues to move after an onCameraMoveStarted call.
+ * This may be called as often as once every frame and should not perform expensive operations.
+ */
+ void onCameraMove();
+ }
+
+ /**
+ * Interface definition for a callback to be invoked for when the camera's motion has been stopped or when the camera
+ * starts moving for a new reason.
+ */
+ public interface OnCameraMoveCanceledListener {
+ /**
+ * Called when the developer explicitly calls the cancelTransitions() method or if the reason for camera motion has
+ * changed before the onCameraIdle had a chance to fire after the previous animation.
+ * Do not update or animate the camera from within this method.
+ */
+ void onCameraMoveCanceled();
+ }
+
+ /**
+ * Interface definition for a callback to be invoked for when camera movement has ended.
+ */
+ public interface OnCameraIdleListener {
+ /**
+ * Called when camera movement has ended.
+ */
+ void onCameraIdle();
+ }
+
+ /**
* Interface definition for a callback to be invoked when a frame is rendered to the map view.
*
* @see MapboxMap#setOnFpsChangedListener(OnFpsChangedListener)
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
index 68603ab1a3..98f94ddb39 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
@@ -36,7 +36,7 @@ import java.util.Arrays;
public class MapboxMapOptions implements Parcelable {
private static final float FOUR_DP = 4f;
- private static final float EIGHTY_NINE_DP = 92f;
+ private static final float NINETY_TWO_DP = 92f;
private CameraPosition cameraPosition;
@@ -241,7 +241,7 @@ public class MapboxMapOptions implements Parcelable {
R.styleable.mapbox_MapView_mapbox_uiAttributionGravity, Gravity.BOTTOM));
mapboxMapOptions.attributionMargins(new int[] {
(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginLeft,
- EIGHTY_NINE_DP * pxlRatio)),
+ NINETY_TWO_DP * pxlRatio)),
(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginTop,
FOUR_DP * pxlRatio)),
(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginRight,
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 ae4a8ee8d2..6d9df8aebd 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
@@ -27,6 +27,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;
@@ -617,7 +618,7 @@ final class NativeMapView {
if (isDestroyedOn("getMetersPerPixelAtLatitude")) {
return 0;
}
- return nativeGetMetersPerPixelAtLatitude(lat, getZoom());
+ return nativeGetMetersPerPixelAtLatitude(lat, getZoom()) / pixelRatio;
}
public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
@@ -882,12 +883,15 @@ final class NativeMapView {
fileSource.setApiBaseUrl(baseUrl);
}
- public float getPixelRatio() {
- return pixelRatio;
+ public Light getLight() {
+ if (isDestroyedOn("getLight")) {
+ return null;
+ }
+ return nativeGetLight();
}
- public Context getContext() {
- return mapView.getContext();
+ public float getPixelRatio() {
+ return pixelRatio;
}
//
@@ -1117,6 +1121,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/maps/TrackingSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
index 09213934ae..7dcd84de75 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
@@ -282,8 +282,10 @@ public final class TrackingSettings {
*/
void resetTrackingModesIfRequired(CameraPosition currentCameraPosition, CameraPosition targetCameraPosition,
boolean isFromLocation) {
- resetTrackingModesIfRequired(!currentCameraPosition.target.equals(targetCameraPosition.target), false,
- isFromLocation);
+ if (currentCameraPosition.target != null) {
+ resetTrackingModesIfRequired(!currentCameraPosition.target.equals(targetCameraPosition.target), false,
+ isFromLocation);
+ }
}
Location getMyLocation() {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
index 507bec270d..7f44e0de07 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
@@ -16,6 +16,7 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import timber.log.Timber;
import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED;
+import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener;
/**
* Resembles the current Map transformation.
@@ -33,13 +34,18 @@ final class Transform implements MapView.OnMapChangedListener {
private CameraPosition cameraPosition;
private MapboxMap.CancelableCallback cameraCancelableCallback;
+
private MapboxMap.OnCameraChangeListener onCameraChangeListener;
- Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) {
+ private CameraChangeDispatcher cameraChangeDispatcher;
+
+ Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings,
+ CameraChangeDispatcher cameraChangeDispatcher) {
this.mapView = mapView;
this.markerViewManager = markerViewManager;
this.trackingSettings = trackingSettings;
this.myLocationView = trackingSettings.getMyLocationView();
+ this.cameraChangeDispatcher = cameraChangeDispatcher;
}
void initialise(@NonNull MapboxMap mapboxMap, @NonNull MapboxMapOptions options) {
@@ -79,6 +85,7 @@ final class Transform implements MapView.OnMapChangedListener {
cameraCancelableCallback.onFinish();
cameraCancelableCallback = null;
}
+ cameraChangeDispatcher.onCameraIdle();
mapView.removeOnMapChangedListener(this);
}
}
@@ -89,10 +96,12 @@ final class Transform implements MapView.OnMapChangedListener {
if (!cameraPosition.equals(this.cameraPosition)) {
trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, false);
cancelTransitions();
+ cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
if (callback != null) {
callback.onFinish();
}
+ cameraChangeDispatcher.onCameraIdle();
}
}
@@ -103,6 +112,8 @@ final class Transform implements MapView.OnMapChangedListener {
if (!cameraPosition.equals(this.cameraPosition)) {
trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, isDismissable);
cancelTransitions();
+ cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
+
if (callback != null) {
cameraCancelableCallback = callback;
mapView.addOnMapChangedListener(this);
@@ -118,8 +129,9 @@ final class Transform implements MapView.OnMapChangedListener {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (!cameraPosition.equals(this.cameraPosition)) {
trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, false);
-
cancelTransitions();
+ cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
+
if (callback != null) {
cameraCancelableCallback = callback;
mapView.addOnMapChangedListener(this);
@@ -134,7 +146,12 @@ final class Transform implements MapView.OnMapChangedListener {
@Nullable
CameraPosition invalidateCameraPosition() {
if (mapView != null) {
- cameraPosition = mapView.getCameraPosition();
+ CameraPosition cameraPosition = mapView.getCameraPosition();
+ if (this.cameraPosition != null && !this.cameraPosition.equals(cameraPosition)) {
+ cameraChangeDispatcher.onCameraMove();
+ }
+
+ this.cameraPosition = cameraPosition;
if (onCameraChangeListener != null) {
onCameraChangeListener.onCameraChange(this.cameraPosition);
}
@@ -143,10 +160,17 @@ final class Transform implements MapView.OnMapChangedListener {
}
void cancelTransitions() {
+ // notify user about cancel
+ cameraChangeDispatcher.onCameraMoveCanceled();
+
+ // notify animateCamera and easeCamera about cancelling
if (cameraCancelableCallback != null) {
+ cameraChangeDispatcher.onCameraIdle();
cameraCancelableCallback.onCancel();
cameraCancelableCallback = null;
}
+
+ // cancel ongoing transitions
mapView.cancelTransitions();
}
@@ -156,6 +180,10 @@ final class Transform implements MapView.OnMapChangedListener {
mapView.resetNorth();
}
+ //
+ // Camera change listener API
+ //
+
void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listener) {
this.onCameraChangeListener = listener;
}
@@ -171,9 +199,6 @@ final class Transform implements MapView.OnMapChangedListener {
}
void zoom(boolean zoomIn, @NonNull PointF focalPoint) {
- // Cancel any animation
- cancelTransitions();
-
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1));
@@ -186,6 +211,15 @@ final class Transform implements MapView.OnMapChangedListener {
}
void setZoom(double zoom, @NonNull PointF focalPoint, long duration) {
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(int change) {
+ if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
+ mapView.removeOnMapChangedListener(this);
+ cameraChangeDispatcher.onCameraIdle();
+ }
+ }
+ });
mapView.setZoom(zoom, focalPoint, duration);
}
@@ -277,6 +311,17 @@ final class Transform implements MapView.OnMapChangedListener {
}
void moveBy(double offsetX, double offsetY, long duration) {
+ if (duration > 0) {
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(int change) {
+ if (change == MapView.DID_FINISH_RENDERING_MAP_FULLY_RENDERED) {
+ mapView.removeOnMapChangedListener(this);
+ cameraChangeDispatcher.onCameraIdle();
+ }
+ }
+ });
+ }
mapView.moveBy(offsetX, offsetY, duration);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index 1bcf8a70b9..5f7b6c571b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -193,12 +193,16 @@ public final class UiSettings {
private void initialiseLogo(MapboxMapOptions options, Resources resources) {
setLogoEnabled(options.getLogoEnabled());
setLogoGravity(options.getLogoGravity());
- int[] logoMargins = options.getLogoMargins();
+ setLogoMargins(resources, options.getLogoMargins());
+ }
+
+ private void setLogoMargins(Resources resources, int[] logoMargins) {
if (logoMargins != null) {
setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]);
} else {
- int twoDp = (int) resources.getDimension(R.dimen.mapbox_two_dp);
- setLogoMargins(twoDp, twoDp, twoDp, twoDp);
+ // user did not specify margins when programmatically creating a map
+ int fourDp = (int) resources.getDimension(R.dimen.mapbox_four_dp);
+ setLogoMargins(fourDp, fourDp, fourDp, fourDp);
}
}
@@ -223,15 +227,23 @@ public final class UiSettings {
private void initialiseAttribution(Context context, MapboxMapOptions options) {
setAttributionEnabled(options.getAttributionEnabled());
setAttributionGravity(options.getAttributionGravity());
- int[] attributionMargins = options.getAttributionMargins();
+ setAttributionMargins(context, options.getAttributionMargins());
+ int attributionTintColor = options.getAttributionTintColor();
+ setAttributionTintColor(attributionTintColor != -1
+ ? attributionTintColor : ColorUtils.getPrimaryColor(context));
+ }
+
+ private void setAttributionMargins(Context context, int[] attributionMargins) {
if (attributionMargins != null) {
setAttributionMargins(attributionMargins[0], attributionMargins[1],
attributionMargins[2], attributionMargins[3]);
+ } else {
+ // user did not specify margins when programmatically creating a map
+ Resources resources = context.getResources();
+ int margin = (int) resources.getDimension(R.dimen.mapbox_four_dp);
+ int leftMargin = (int) resources.getDimension(R.dimen.mapbox_ninety_two_dp);
+ setAttributionMargins(leftMargin, margin, margin, margin);
}
-
- int attributionTintColor = options.getAttributionTintColor();
- setAttributionTintColor(attributionTintColor != -1
- ? attributionTintColor : ColorUtils.getPrimaryColor(context));
}
private void saveAttribution(Bundle outState) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
index db2a335453..f5ef46a5d3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
@@ -440,6 +440,7 @@ public class MyLocationView extends View {
} else {
// Disable location and user dot
location = null;
+ locationSource.removeLocationUpdates();
locationSource.removeLocationEngineListener(userLocationListener);
locationSource.deactivate();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
index 50ae6716e6..ce498da8f5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
@@ -47,7 +47,7 @@ public class OfflineManager {
/**
* This callback receives an asynchronous response containing a list of all
- * {@link OfflineRegion} in the database, or an error message otherwise.
+ * OfflineRegion in the database or an error message otherwise.
*/
public interface ListOfflineRegionsCallback {
/**
@@ -67,7 +67,7 @@ public class OfflineManager {
/**
* This callback receives an asynchronous response containing the newly created
- * {@link OfflineRegion} in the database, or an error message otherwise.
+ * OfflineRegion in the database or an error message otherwise.
*/
public interface CreateOfflineRegionCallback {
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
index 5ed6579e1c..fae53c2086 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
@@ -4,6 +4,7 @@ import android.os.Handler;
import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.LibraryLoader;
import com.mapbox.mapboxsdk.storage.FileSource;
@@ -37,6 +38,9 @@ public class OfflineRegion {
//Region id
private long id;
+ // delete status
+ private boolean isDeleted;
+
private OfflineRegionDefinition definition;
/**
@@ -95,7 +99,7 @@ public class OfflineRegion {
}
/**
- * This callback receives an asynchronous response containing the {@link OfflineRegionStatus}
+ * This callback receives an asynchronous response containing the OfflineRegionStatus
* of the offline region, or a {@link String} error message otherwise.
*/
public interface OfflineRegionStatusCallback {
@@ -248,7 +252,7 @@ public class OfflineRegion {
*
* @param observer the observer to be notified
*/
- public void setObserver(@NonNull final OfflineRegionObserver observer) {
+ public void setObserver(@Nullable final OfflineRegionObserver observer) {
setOfflineRegionObserver(new OfflineRegionObserver() {
@Override
public void onStatusChanged(final OfflineRegionStatus status) {
@@ -256,7 +260,9 @@ public class OfflineRegion {
getHandler().post(new Runnable() {
@Override
public void run() {
- observer.onStatusChanged(status);
+ if (observer != null) {
+ observer.onStatusChanged(status);
+ }
}
});
}
@@ -268,7 +274,9 @@ public class OfflineRegion {
getHandler().post(new Runnable() {
@Override
public void run() {
- observer.onError(error);
+ if (observer != null) {
+ observer.onError(error);
+ }
}
});
}
@@ -280,7 +288,9 @@ public class OfflineRegion {
getHandler().post(new Runnable() {
@Override
public void run() {
- observer.mapboxTileCountLimitExceeded(limit);
+ if (observer != null) {
+ observer.mapboxTileCountLimitExceeded(limit);
+ }
}
});
}
@@ -347,28 +357,31 @@ public class OfflineRegion {
* @param callback the callback to be invoked
*/
public void delete(@NonNull final OfflineRegionDeleteCallback callback) {
- deleteOfflineRegion(new OfflineRegionDeleteCallback() {
- @Override
- public void onDelete() {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onDelete();
- OfflineRegion.this.finalize();
- }
- });
- }
+ if (!isDeleted) {
+ deleteOfflineRegion(new OfflineRegionDeleteCallback() {
+ @Override
+ public void onDelete() {
+ isDeleted = true;
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onDelete();
+ OfflineRegion.this.finalize();
+ }
+ });
+ }
- @Override
- public void onError(final String error) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- callback.onError(error);
- }
- });
- }
- });
+ @Override
+ public void onError(final String error) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
+ });
+ }
+ });
+ }
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java
index af98a46a9b..eae83e8c1f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java
@@ -5,9 +5,15 @@ import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+/**
+ * Resource provides access to resource types.
+ */
public final class Resource {
// Note: Keep this in sync with include/mbgl/storage/resource.hpp
+ /**
+ * Resource type variants.
+ */
@IntDef( {UNKNOWN, STYLE, SOURCE, TILE, GLYPHS, SPRITE_IMAGE, SPRITE_JSON})
@Retention(RetentionPolicy.SOURCE)
public @interface Kind {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java
index 8ded7ecd34..15e4474105 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java
@@ -13,7 +13,7 @@ import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.Map;
/**
- * Composite functions combine {@link android.graphics.Camera} and {@link SourceFunction}s.
+ * Composite functions combine Camera and SourceFunctions.
* <p>
* Composite functions allow the appearance of a map feature to change with both its
* properties and zoom. Each stop is an array with two elements, the first is an object
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
index 643a126388..4dbb461e4c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
@@ -11,7 +11,7 @@ import java.util.Collections;
public class Filter {
/**
- * Base {@link Filter} statement. Subclassed to provide concrete statements.
+ * Base Filter statement. Subclassed to provide concrete statements.
*/
public abstract static class Statement {
protected final String operator;
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/layers/TransitionOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/TransitionOptions.java
index a46c11b35c..6e6e4ca613 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/TransitionOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/TransitionOptions.java
@@ -1,23 +1,51 @@
package com.mapbox.mapboxsdk.style.layers;
+/**
+ * Resembles transition property from the style specification.
+ *
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#transition">Transition documentation</a>
+ */
public class TransitionOptions {
private long duration;
private long delay;
+ /**
+ * Create a transition property based on duration and a delay.
+ *
+ * @param duration the duration of the transition
+ * @param delay the delay to start the transition
+ */
public TransitionOptions(long duration, long delay) {
this.duration = duration;
this.delay = delay;
}
+ /**
+ * Create a transition property based on duration and a delay.
+ *
+ * @param duration the duration of the transition
+ * @param delay the delay to start the transition
+ * @return a new transition property object
+ */
public static TransitionOptions fromTransitionOptions(long duration, long delay) {
return new TransitionOptions(duration, delay);
}
+ /**
+ * Get the transition duration.
+ *
+ * @return the transition duration
+ */
public long getDuration() {
return duration;
}
+ /**
+ * Get the transition delay.
+ *
+ * @return the transition delay
+ */
public long getDelay() {
return delay;
}
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/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/package-info.java
new file mode 100644
index 0000000000..a613bf9587
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Style Light API classes.
+ */
+package com.mapbox.mapboxsdk.style.light;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
index 7694604d9f..34c52c829b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
@@ -10,13 +10,31 @@ import android.support.annotation.Nullable;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.View;
+/**
+ * Animator utility class.
+ */
public class AnimatorUtils {
+ /**
+ * Animate a view from an animator resource.
+ *
+ * @param view the view to be animated
+ * @param animatorRes the animator resource to be loaded
+ * @param listener the animator end listener
+ */
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes,
@Nullable OnAnimationEndListener listener) {
animate(view, animatorRes, -1, listener);
}
+ /**
+ * Animate a view from an animator resource.
+ *
+ * @param view the view to be animated
+ * @param animatorRes the animator resource to be loaded
+ * @param duration the duration of the animator
+ * @param listener the animator end listener
+ */
public static void animate(final View view, @AnimatorRes int animatorRes, int duration,
@Nullable final OnAnimationEndListener listener) {
if (view == null) {
@@ -43,14 +61,33 @@ public class AnimatorUtils {
animator.start();
}
+ /**
+ * Animate a view from an animator resource.
+ *
+ * @param view the view to be animated
+ * @param animatorRes the animator resource to be loaded
+ */
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) {
animate(view, animatorRes, -1);
}
+ /**
+ * Animate a view from an animator resource.
+ *
+ * @param view the view to be animated
+ * @param animatorRes the animator resource to be loaded
+ * @param duration the duration of the animator
+ */
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) {
animate(view, animatorRes, duration, null);
}
+ /**
+ * Animate a view rotation property to a value.
+ *
+ * @param view the view to be rotated
+ * @param rotation the value to animate to
+ */
public static void rotate(@NonNull final View view, float rotation) {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation);
@@ -64,6 +101,12 @@ public class AnimatorUtils {
rotateAnimator.start();
}
+ /**
+ * Animate a view rotation property by a value.
+ *
+ * @param view the view to be rotated
+ * @param rotationBy the value to animate by
+ */
public static void rotateBy(@NonNull final View view, float rotationBy) {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.animate().rotationBy(rotationBy).setInterpolator(new FastOutSlowInInterpolator()).setListener(
@@ -76,6 +119,13 @@ public class AnimatorUtils {
});
}
+ /**
+ * Animate a view alpha property to a value.
+ *
+ * @param convertView the view to be animated
+ * @param alpha the value to animate to
+ * @param listener the animator end listener
+ */
public static void alpha(@NonNull final View convertView, float alpha,
@Nullable final OnAnimationEndListener listener) {
convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -99,10 +149,19 @@ public class AnimatorUtils {
rotateAnimator.start();
}
+ /**
+ * Animate a view alpha property to a value.
+ *
+ * @param convertView the view to be animated
+ * @param alpha the value to animate to
+ */
public static void alpha(@NonNull final View convertView, float alpha) {
alpha(convertView, alpha, null);
}
+ /**
+ * An interface definition that is invoked when an animation ends.
+ */
public interface OnAnimationEndListener {
void onAnimationEnd();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
index 2da2472d69..24c76243d9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
@@ -17,6 +17,9 @@ import com.mapbox.mapboxsdk.exceptions.ConversionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+/**
+ * Color utility class.
+ */
public class ColorUtils {
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
index ce20cb9a8b..8edbd47c29 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
@@ -13,6 +13,6 @@
<dimen name="mapbox_eight_dp">8dp</dimen>
<dimen name="mapbox_ten_dp">10dp</dimen>
<dimen name="mapbox_sixteen_dp">16dp</dimen>
- <dimen name="mapbox_ninety_five_dp">95dp</dimen>
+ <dimen name="mapbox_ninety_two_dp">92dp</dimen>
<dimen name="mapbox_my_locationview_outer_circle">18dp</dimen>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
index 5f6f6b6c6d..1c259af2d0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/annotations/IconTest.java
@@ -9,6 +9,7 @@ import org.mockito.MockitoAnnotations;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotSame;
+import static org.mockito.Mockito.when;
public class IconTest {
@@ -18,6 +19,7 @@ public class IconTest {
@Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.ARGB_8888);
}
@Test
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 7c263652af..656789fcdb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -57,10 +57,7 @@ dependencies {
}
// Support libraries
- compile rootProject.ext.dep.supportAnnotations
- compile rootProject.ext.dep.supportV4
compile rootProject.ext.dep.supportAppcompatV7
- compile rootProject.ext.dep.supportDesign
compile rootProject.ext.dep.supportRecyclerView
// Leak Canary
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
index 5d944b5dd4..f8243ca44f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
@@ -4,5 +4,6 @@
-dontwarn org.codehaus.**
-keep class com.google.**
-dontwarn com.google.**
+-dontwarn java.nio.**
-keep class com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer { *; }
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/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
index 08399f3b3e..60518239c8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
@@ -43,10 +43,35 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ mapboxMap.setOnCameraIdleListener(new MapboxMap.OnCameraIdleListener() {
@Override
- public void onCameraChange(CameraPosition position) {
- Timber.w("OnCameraChange: " + position);
+ public void onCameraIdle() {
+ Timber.e("OnCameraIdle");
+ }
+ });
+
+ mapboxMap.setOnCameraMoveCancelListener(new MapboxMap.OnCameraMoveCanceledListener() {
+ @Override
+ public void onCameraMoveCanceled() {
+ Timber.e("OnCameraMoveCanceled");
+ }
+ });
+
+ mapboxMap.setOnCameraMoveListener(new MapboxMap.OnCameraMoveListener() {
+ @Override
+ public void onCameraMove() {
+ Timber.e("OnCameraMove");
+ }
+ });
+
+ mapboxMap.setOnCameraMoveStartedistener(new MapboxMap.OnCameraMoveStartedListener() {
+
+ private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"};
+
+ @Override
+ public void onCameraMoveStarted(int reason) {
+ // reason ranges from 1 <-> 3
+ Timber.e("OnCameraMoveStarted: %s", REASONS[reason - 1]);
}
});
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
index be5d809457..344e9e140a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
@@ -274,22 +274,20 @@ public class OfflineActivity extends AppCompatActivity
}
// Debug
- Timber.d(String.format("%s/%s resources; %s bytes downloaded.",
+ Timber.d("%s/%s resources; %s bytes downloaded.",
String.valueOf(status.getCompletedResourceCount()),
String.valueOf(status.getRequiredResourceCount()),
- String.valueOf(status.getCompletedResourceSize())));
+ String.valueOf(status.getCompletedResourceSize()));
}
@Override
public void onError(OfflineRegionError error) {
- Timber.e("onError reason: " + error.getReason());
- Timber.e("onError message: " + error.getMessage());
- offlineRegion.setObserver(null);
+ Timber.e("onError: %s, %s", error.getReason(), error.getMessage());
}
@Override
public void mapboxTileCountLimitExceeded(long limit) {
- Timber.e("Mapbox tile count limit exceeded: " + limit);
+ Timber.e("Mapbox tile count limit exceeded: %s", limit);
}
});
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/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
index b87c723fda..b02b35b0d0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
@@ -63,7 +63,9 @@ public class MockLocationEngine extends LocationEngine {
@Override
public void removeLocationUpdates() {
- handler.removeCallbacksAndMessages(null);
+ if (handler != null) {
+ handler.removeCallbacksAndMessages(null);
+ }
}
private Location getNextLocation() {
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/layout/activity_press_for_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
index 9932803907..c2098b0f5b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
@@ -16,6 +16,6 @@
app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
app:mapbox_uiAttributionGravity="top|end"
app:mapbox_uiLogoGravity="top|end"
- app:mapbox_uiLogoMarginRight="10dp"/>
+ app:mapbox_uiLogoMarginRight="28dp"/>
</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/build.gradle b/platform/android/build.gradle
index 120c0219e4..bc90896812 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -12,6 +12,7 @@ buildscript {
allprojects {
repositories {
jcenter()
+ maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }
}
}
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/dependencies.gradle b/platform/android/dependencies.gradle
index 738f571c09..5e80e344e4 100644
--- a/platform/android/dependencies.gradle
+++ b/platform/android/dependencies.gradle
@@ -7,21 +7,21 @@ ext {
versionCode = 11
versionName = "5.0.0"
+ mapboxServicesVersion = "2.1.1"
supportLibVersion = "25.3.1"
- leakCanaryVersion = '1.5'
wearableVersion = '2.0.0'
-
espressoVersion = '2.2.2'
testRunnerVersion = '0.5'
+ leakCanaryVersion = '1.5'
dep = [
// mapbox
- mapboxJavaServices : 'com.mapbox.mapboxsdk:mapbox-java-services:2.1.0@jar',
- mapboxJavaGeoJSON : 'com.mapbox.mapboxsdk:mapbox-java-geojson:2.1.0@jar',
- mapboxAndroidTelemetry : 'com.mapbox.mapboxsdk:mapbox-android-telemetry:2.1.0@aar',
+ mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-java-services:${mapboxServicesVersion}@jar",
+ mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-java-geojson:${mapboxServicesVersion}@jar",
+ mapboxAndroidTelemetry : "com.mapbox.mapboxsdk:mapbox-android-telemetry:${mapboxServicesVersion}@aar",
// mapzen lost
- lost : 'com.mapzen.android:lost:2.2.0',
+ lost : 'com.mapzen.android:lost:3.0.0',
// unit test
junit : 'junit:junit:4.12',
@@ -47,7 +47,7 @@ ext {
// square crew
timber : 'com.jakewharton.timber:timber:4.5.1',
- okhttp3 : 'com.squareup.okhttp3:okhttp:3.6.0',
+ okhttp3 : 'com.squareup.okhttp3:okhttp:3.7.0',
leakCanaryDebug : "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}",
leakCanaryRelease : "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}",
leakCanaryTest : "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"
diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties
index c7ad166b13..1d35abd7b2 100644
--- a/platform/android/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip \ No newline at end of file
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/scripts/release.py b/platform/android/scripts/release.py
index 8abcccffdb..ce554d1362 100644
--- a/platform/android/scripts/release.py
+++ b/platform/android/scripts/release.py
@@ -1,5 +1,5 @@
'''
-Utility to schedule SDK builds in Bitrise.
+Utility to schedule SDK builds on CircleCI.
Examples:
@@ -33,7 +33,7 @@ Examples:
TODO:
-- Add a flag to wait until the release has been built (Bitrise) and published (Maven).
+- Add a flag to wait until the release has been built (CircleCI) and published (Maven).
'''
@@ -49,8 +49,8 @@ ALLOWED_STAGES = ['snapshot', 'beta', 'final']
# Get the version from GRADLE_PROPERTIES_PATH below
CURRENT_VERSION_TAG = 'current'
-# You can find the API token in https://www.bitrise.io/app/79cdcbdc42de4303#/code -> API token
-BITRISE_API_TOKEN_ENV_VAR = 'BITRISE_API_TOKEN'
+# You can add your API token on https://circleci.com/account/api
+CIRCLECI_API_TOKEN_ENV_VAR = 'CIRCLECI_API_TOKEN'
# In the future we might want to consider alpha, or rc.
ALLOWED_PRE_RELEASE = ['beta']
@@ -62,8 +62,8 @@ GRADLE_TOKEN = 'VERSION_NAME='
FABRIC_PROPERTIES_PATH = '%s/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties' % MAPBOX_GL_ANDROID_SDK_PATH
FABRIC_TOKEN = 'fabric-version='
-# Bitrise
-URL_BITRISE = 'https://www.bitrise.io/app/79cdcbdc42de4303/build/start.json'
+# Triggers a new build, returns a summary of the build
+URL_CIRCLECI = 'https://circleci.com/api/v1.1/project/github/mapbox/mapbox-gl-native/tree/' # + :branch
# We support three parameters: stage, branch, and version
@click.command()
@@ -129,7 +129,7 @@ def publish_snapshot(branch, version):
if dirty_gradle:
git_add(path=GRADLE_PROPERTIES_PATH)
git_commit_and_push(branch=branch, version=version)
- do_bitrise_request(build_params={'branch': branch, 'workflow_id': 'scheduled'})
+ do_circleci_request(branch=branch)
def publish_beta(branch, version):
click.echo('Publishing beta from branch: %s (version: %s).' % (branch, version))
@@ -137,7 +137,7 @@ def publish_beta(branch, version):
if dirty_gradle:
git_add(path=GRADLE_PROPERTIES_PATH)
git_commit_and_push(branch=branch, version=version)
- do_bitrise_request(build_params={'branch': branch, 'workflow_id': 'scheduled'})
+ do_circleci_request(branch=branch)
def publish_final(branch, version):
click.echo('Publishing final release from branch: %s (version: %s).' % (branch, version))
@@ -149,7 +149,7 @@ def publish_final(branch, version):
git_add(path=FABRIC_PROPERTIES_PATH)
if dirty_gradle or dirty_fabric:
git_commit_and_push(branch=branch, version=version)
- do_bitrise_request(build_params={'branch': branch, 'workflow_id': 'scheduled'})
+ do_circleci_request(branch=branch)
#
# Utils
@@ -166,26 +166,24 @@ def execute_call(command):
abort_with_message('Command failed: %s' % command)
#
-# Bitrise
+# CircleCI
#
-def get_bitrise_api_token():
- bitrise_api_token = os.environ.get(BITRISE_API_TOKEN_ENV_VAR)
- if not bitrise_api_token:
- abort_with_message('You need to set the BITRISE_API_TOKEN environment variable.')
- click.echo('Found Bitrise API token.')
- return bitrise_api_token
-
-def do_bitrise_request(build_params):
- data = {
- 'hook_info': {'type': 'bitrise', 'api_token': get_bitrise_api_token()},
- 'build_params' : build_params}
- click.echo('Bitrise request data: %s' % json.dumps(data))
+def get_circleci_api_token():
+ circleci_api_token = os.environ.get(CIRCLECI_API_TOKEN_ENV_VAR)
+ if not circleci_api_token:
+ abort_with_message('You need to set the CIRCLECI_API_TOKEN environment variable.')
+ click.echo('Found CircleCI API token.')
+ return circleci_api_token
+
+def do_circleci_request(branch):
+ url = URL_CIRCLECI + branch
+ params = {'circle-token': get_circleci_api_token()}
+ click.echo('CircleCI request to %s (params: %s)' % (url, json.dumps(params)))
click.confirm('\nDo you want to start a build?', abort=True)
- r = requests.post(URL_BITRISE, data=json.dumps(data))
- click.echo('- Bitrise response code: %s' % r.status_code)
- click.echo('- Bitrise response content: %s' % r.text)
+ r = requests.post(url, params=params)
+ click.echo('- CircleCI response code: %s' % r.status_code)
#
# Git
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/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp
index aa5873b273..d6f2cb83e8 100644
--- a/platform/android/src/map/camera_position.cpp
+++ b/platform/android/src/map/camera_position.cpp
@@ -11,8 +11,9 @@ jni::Object<CameraPosition> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp
auto center = options.center.value();
center.wrap();
- // convert bearing, core ranges from [−π rad, π rad], android from 0 to 360 degrees
- double bearing_degrees = options.angle.value_or(0) * 180.0 / M_PI;
+ // convert bearing, measured in radians counterclockwise from true north.
+ // Wrapped to [−π rad, π rad). Android binding from 0 to 360 degrees
+ double bearing_degrees = -options.angle.value_or(0) * util::RAD2DEG;
while (bearing_degrees > 360) {
bearing_degrees -= 360;
}
@@ -21,7 +22,7 @@ jni::Object<CameraPosition> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp
}
// convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60
- double tilt_degrees = options.pitch.value_or(0) * 180 / M_PI;
+ double tilt_degrees = options.pitch.value_or(0) * util::RAD2DEG;
return CameraPosition::javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees);
}
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 51ce9c031d..73a4f96549 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 {
@@ -385,12 +386,12 @@ void NativeMapView::moveBy(jni::JNIEnv&, jni::jdouble dx, jni::jdouble dy, jni::
void NativeMapView::jumpTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitude, jni::jdouble longitude, jni::jdouble pitch, jni::jdouble zoom) {
mbgl::CameraOptions options;
if (angle != -1) {
- options.angle = (-angle * M_PI) / 180;
+ options.angle = -angle * util::DEG2RAD;
}
options.center = mbgl::LatLng(latitude, longitude);
options.padding = insets;
if (pitch != -1) {
- options.pitch = pitch * M_PI / 180;
+ options.pitch = pitch * util::DEG2RAD;
}
if (zoom != -1) {
options.zoom = zoom;
@@ -402,12 +403,12 @@ void NativeMapView::jumpTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitu
void NativeMapView::easeTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitude, jni::jdouble longitude, jni::jlong duration, jni::jdouble pitch, jni::jdouble zoom, jni::jboolean easing) {
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = (-angle * M_PI) / 180;
+ cameraOptions.angle = -angle * util::DEG2RAD;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = insets;
if (pitch != -1) {
- cameraOptions.pitch = pitch * M_PI / 180;
+ cameraOptions.pitch = pitch * util::DEG2RAD;
}
if (zoom != -1) {
cameraOptions.zoom = zoom;
@@ -426,12 +427,12 @@ void NativeMapView::easeTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitu
void NativeMapView::flyTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitude, jni::jdouble longitude, jni::jlong duration, jni::jdouble pitch, jni::jdouble zoom) {
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = (-angle * M_PI) / 180 ;
+ cameraOptions.angle = -angle * util::DEG2RAD;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = insets;
if (pitch != -1) {
- cameraOptions.pitch = pitch * M_PI / 180;
+ cameraOptions.pitch = pitch * util::DEG2RAD;
}
if (zoom != -1) {
cameraOptions.zoom = zoom;
@@ -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
@@ -1535,6 +1545,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
diff --git a/platform/darwin/docs/guides/Tile URL Templates.md.ejs b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
new file mode 100644
index 0000000000..78fb297138
--- /dev/null
+++ b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
@@ -0,0 +1,109 @@
+<%
+ const os = locals.os;
+ const iOS = os === 'iOS';
+ //const macOS = os === 'macOS';
+ //const cocoaPrefix = iOS ? 'UI' : 'NS';
+-%>
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+# Tile URL Templates
+
+`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
+objects, can be created using an initializer that accepts an array of tile URL
+templates. Tile URL templates are strings that specify the URLs of the vector
+tiles or raster tile images to load. A template resembles an absolute URL, but
+with any number of placeholder strings that the source evaluates based on the
+tile it needs to load. For example:
+
+* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
+ evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
+* `http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png` could be
+ evaluated as `http://www.example.com/tiles/14/6/9@2x.png`.
+
+Tile URL templates are also used to define tilesets in TileJSON manifests or
+[`raster`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-raster-tiles)
+and
+[`vector`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-vector-tiles)
+sources in style JSON files. See the
+[TileJSON specification](https://github.com/mapbox/tilejson-spec/tree/master/2.2.0)
+for information about tile URL templates in the context of a TileJSON or style
+JSON file.
+
+Tile sources support the following placeholder strings in tile URL templates,
+all of which are optional:
+
+<table>
+<thead>
+<tr><th>Placeholder string</th><th>Description</th></tr>
+</thead>
+<tbody>
+<tr>
+ <td><code>{x}</code></td>
+ <td>The index of the tile along the map’s x axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s left edge corresponds
+ to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
+ the tile’s right edge corresponds to the 180th meridian east.</td>
+</tr>
+<tr>
+ <td><code>{y}</code></td>
+ <td>The index of the tile along the map’s y axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s tile edge corresponds
+ to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
+ is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
+ −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
+ inverted if the <code>options</code> parameter contains
+ <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
+ <code>MGLTileCoordinateSystemTMS</code>.</td>
+</tr>
+<tr>
+ <td><code>{z}</code></td>
+ <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
+ world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
+ <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
+ a <code>MGLRasterSource</code> object, whether the tile zoom level
+ matches the map’s current zoom level depends on the value of the
+ source’s tile size as specified in the
+ <code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
+ parameter.</td>
+</tr>
+<tr>
+ <td><code>{bbox-epsg-3857}</code></td>
+ <td>The tile’s bounding box, expressed as a comma-separated list of the
+ tile’s western, southern, eastern, and northern extents according to
+ Spherical Mercator (EPSG:3857) projection. The bounding box is typically
+ used with map services conforming to the
+ <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
+ protocol.</td>
+</tr>
+<tr>
+ <td><code>{quadkey}</code></td>
+ <td>A quadkey indicating both the tile’s location and its zoom level. The
+ quadkey is typically used with
+ <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
+ </td>
+</tr>
+<tr>
+ <td><code>{ratio}</code></td>
+ <td>A suffix indicating the resolution of the tile image. The suffix is the
+ empty string for standard resolution displays and <code>@2x</code> for
+<% if (iOS) { -%>
+ Retina displays, including displays for which <code>UIScreen.scale</code>
+ is 3.
+<% } else { -%>
+ Retina displays.
+<% } -%>
+ </td>
+</tr>
+<tr>
+ <td><code>{prefix}</code></td>
+ <td>Two hexadecimal digits chosen such that each visible tile has a
+ different prefix. The prefix is typically used for domain sharding.</td>
+</tr>
+</tbody>
+</table>
+
+For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
+consult the
+[OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 330a8f1d03..7efc8d441c 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -522,8 +522,9 @@ global.setSourceLayer = function() {
const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true });
const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true});
const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true});
-const guideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
+const forStyleAuthorsMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs', 'utf8'), { strict: true });
+const templatesMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Tile URL Templates.md.ejs', 'utf8'), { strict: true });
const layers = _(spec.layer.type.values).map((value, layerType) => {
const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => {
@@ -635,12 +636,12 @@ global.guideExample = function (guide, exampleId, os) {
return '```swift\n' + example + '\n```';
};
-fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, guideMD({
+fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
os: 'iOS',
renamedProperties: renamedPropertiesByLayerType,
layers: layers,
}));
-fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, guideMD({
+fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
os: 'macOS',
renamedProperties: renamedPropertiesByLayerType,
layers: layers,
@@ -651,3 +652,9 @@ fs.writeFileSync(`platform/ios/docs/guides/Using Style Functions at Runtime.md`,
fs.writeFileSync(`platform/macos/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({
os: 'macOS',
}));
+fs.writeFileSync(`platform/ios/docs/guides/Tile URL Templates.md`, templatesMD({
+ os: 'iOS',
+}));
+fs.writeFileSync(`platform/macos/docs/guides/Tile URL Templates.md`, templatesMD({
+ os: 'macOS',
+}));
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 7583244491..770aeb25e7 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -6,8 +6,10 @@
#import <Cocoa/Cocoa.h>
#endif
+#import "MGLAccountManager.h"
#import "MGLMapCamera.h"
#import "NSArray+MGLAdditions.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSString+MGLAdditions.h"
#include <string>
@@ -126,13 +128,34 @@
}
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel {
+ return [self feedbackURLForStyleURL:nil atCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:0 pitch:0];
+}
+
+- (nullable NSURL *)feedbackURLForStyleURL:(nullable NSURL *)styleURL atCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction pitch:(CGFloat)pitch {
if (!self.feedbackLink) {
return nil;
}
-
- NSURLComponents *components = [NSURLComponents componentsWithURL:self.URL resolvingAgainstBaseURL:NO];
- components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%i",
- centerCoordinate.longitude, centerCoordinate.latitude, (int)round(zoomLevel + 1)];
+
+ NSURLComponents *components = [NSURLComponents componentsWithString:@"https://www.mapbox.com/feedback/"];
+ components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%.2f/%.1f/%i",
+ centerCoordinate.longitude, centerCoordinate.latitude, zoomLevel,
+ direction, (int)round(pitch)];
+
+ NSURLQueryItem *referrerQueryItem = [NSURLQueryItem queryItemWithName:@"referrer"
+ value:[NSBundle mgl_applicationBundleIdentifier]];
+ NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray arrayWithObject:referrerQueryItem];
+ if ([styleURL.scheme isEqualToString:@"mapbox"] && [styleURL.host isEqualToString:@"styles"]) {
+ NSArray<NSString *> *stylePathComponents = styleURL.pathComponents;
+ if (stylePathComponents.count >= 3) {
+ [queryItems addObjectsFromArray:@[
+ [NSURLQueryItem queryItemWithName:@"owner" value:stylePathComponents[1]],
+ [NSURLQueryItem queryItemWithName:@"id" value:stylePathComponents[2]],
+ [NSURLQueryItem queryItemWithName:@"access_token" value:[MGLAccountManager accessToken]],
+ ]];
+ }
+ }
+ components.queryItems = queryItems;
+
return components.URL;
}
diff --git a/platform/darwin/src/MGLAttributionInfo_Private.h b/platform/darwin/src/MGLAttributionInfo_Private.h
index 08bc6bfc4d..c639752ac3 100644
--- a/platform/darwin/src/MGLAttributionInfo_Private.h
+++ b/platform/darwin/src/MGLAttributionInfo_Private.h
@@ -20,6 +20,24 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos;
+/**
+ Returns a copy of the `URL` property modified to account for the given style
+ URL, center coordinate, and zoom level.
+
+ @param styleURL The map’s style URL.
+ @param centerCoordinate The map’s center coordinate.
+ @param zoomLevel The map’s zoom level. See the `MGLMapView.zoomLevel` property
+ for more information.
+ @param direction The heading of the map, measured in degrees clockwise from
+ true north.
+ @param pitch Pitch toward the horizon measured in degrees, with 0 degrees
+ resulting in a two-dimensional map.
+ @return A modified URL containing a fragment that points to the specified
+ viewport. If the `feedbackLink` property is set to `NO`, this method returns
+ `nil`.
+ */
+- (nullable NSURL *)feedbackURLForStyleURL:(nullable NSURL *)styleURL atCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction pitch:(CGFloat)pitch;
+
@end
@interface NSMutableArray (MGLAttributionInfoAdditions)
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
index 84f6bedde4..c4fb9aa77e 100644
--- a/platform/darwin/src/MGLFillExtrusionStyleLayer.h
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
@@ -46,7 +46,7 @@ typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) {
layer.sourceLayerIdentifier = "building"
layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
- layer.predicate = NSPredicate(format: "extrude == TRUE")
+ layer.predicate = NSPredicate(format: "extrude == 'true'")
mapView.style?.addLayer(layer)
```
*/
diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h
index 3e029e8ee0..7ad8314a79 100644
--- a/platform/darwin/src/MGLGeometry_Private.h
+++ b/platform/darwin/src/MGLGeometry_Private.h
@@ -8,6 +8,26 @@
#import <mbgl/util/geo.hpp>
#import <mbgl/util/geometry.hpp>
+typedef double MGLLocationRadians;
+typedef double MGLRadianDistance;
+typedef double MGLRadianDirection;
+
+/** Defines the coordinate by a `MGLRadianCoordinate2D`. */
+typedef struct MGLRadianCoordinate2D {
+ MGLLocationRadians latitude;
+ MGLLocationRadians longitude;
+} MGLRadianCoordinate2D;
+
+/**
+ Creates a new `MGLRadianCoordinate2D` from the given latitudinal and longitudinal.
+ */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinate2DMake(MGLLocationRadians latitude, MGLLocationRadians longitude) {
+ MGLRadianCoordinate2D radianCoordinate;
+ radianCoordinate.latitude = latitude;
+ radianCoordinate.longitude = longitude;
+ return radianCoordinate;
+}
+
/// Returns the smallest rectangle that contains both the given rectangle and
/// the given point.
CGRect MGLExtendRect(CGRect rect, CGPoint point);
@@ -18,6 +38,10 @@ NS_INLINE mbgl::Point<double> MGLPointFromLocationCoordinate2D(CLLocationCoordin
return mbgl::Point<double>(coordinate.longitude, coordinate.latitude);
}
+NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromPoint(mbgl::Point<double> point) {
+ return CLLocationCoordinate2DMake(point.y, point.x);
+}
+
NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) {
return CLLocationCoordinate2DMake(latLng.latitude(), latLng.longitude());
}
@@ -59,3 +83,43 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo
@param size The size of the viewport.
@return A zero-based zoom level. */
double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size);
+
+/** Returns MGLRadianCoordinate2D, converted from CLLocationCoordinate2D. */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLocationCoordinate2D locationCoordinate) {
+ return MGLRadianCoordinate2DMake(MGLRadiansFromDegrees(locationCoordinate.latitude),
+ MGLRadiansFromDegrees(locationCoordinate.longitude));
+}
+
+/*
+ Returns the distance in radians given two coordinates.
+ */
+NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to)
+{
+ double a = pow(sin((to.latitude - from.latitude) / 2), 2)
+ + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude);
+
+ return 2 * atan2(sqrt(a), sqrt(1 - a));
+}
+
+/*
+ Returns direction in radians given two coordinates.
+ */
+NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) {
+ double a = sin(to.longitude - from.longitude) * cos(to.latitude);
+ double b = cos(from.latitude) * sin(to.latitude)
+ - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude);
+ return atan2(a, b);
+}
+
+/*
+ Returns coordinate at a given distance and direction away from coordinate.
+ */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoordinate2D coordinate,
+ MGLRadianDistance distance,
+ MGLRadianDirection direction) {
+ double otherLatitude = asin(sin(coordinate.latitude) * cos(distance)
+ + cos(coordinate.latitude) * sin(distance) * cos(direction));
+ double otherLongitude = coordinate.longitude + atan2(sin(direction) * sin(distance) * cos(coordinate.latitude),
+ cos(distance) - sin(coordinate.latitude) * sin(otherLatitude));
+ return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude);
+}
diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h
new file mode 100644
index 0000000000..ef9811bd33
--- /dev/null
+++ b/platform/darwin/src/MGLLight.h
@@ -0,0 +1,125 @@
+#import <CoreLocation/CoreLocation.h>
+
+#import "MGLFoundation.h"
+#import "MGLStyleValue.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+/** Options to specify extruded geometries are lit relative to the map or viewport. */
+typedef NS_ENUM(NSUInteger, MGLLightAnchor) {
+ /** The position of the light source is aligned to the rotation of the map. */
+ MGLLightAnchorMap,
+ /** The position of the light source is aligned to the rotation of the viewport. */
+ MGLLightAnchorViewport
+};
+
+/**
+ A structure containing information about the position of the light source
+ relative to lit geometries.
+ */
+typedef struct MGLSphericalPosition {
+ /** Distance from the center of the base of an object to its light. */
+ CLLocationDistance radial;
+ /** Position of the light relative to 0° (0° when `MGLLight.anchor` is set to viewport corresponds
+ to the top of the viewport, or 0° when `MGLLight.anchor` is set to map corresponds to due north,
+ and degrees proceed clockwise). */
+ CLLocationDirection azimuthal;
+ /** Indicates the height of the light (from 0°, directly above, to 180°, directly below). */
+ CLLocationDirection polar;
+} MGLSphericalPosition;
+
+/**
+ Creates a new `MGLSphericalPosition` from the given radial, azimuthal, polar.
+
+ @param radial The radial coordinate.
+ @param azimuthal The azimuthal angle.
+ @param polar The polar angle.
+
+ @return Returns a `MGLSphericalPosition` struct containing the position attributes.
+ */
+NS_INLINE MGLSphericalPosition MGLSphericalPositionMake(CLLocationDistance radial, CLLocationDirection azimuthal, CLLocationDirection polar) {
+ MGLSphericalPosition position;
+ position.radial = radial;
+ position.azimuthal = azimuthal;
+ position.polar = polar;
+
+ return position;
+}
+
+/**
+ An `MGLLight` object represents the light source for extruded geometries in `MGLStyle`.
+ */
+MGL_EXPORT
+@interface MGLLight : NSObject
+
+/**
+ `anchor` Whether extruded geometries are lit relative to the map or viewport.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-anchor"><code>anchor</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<NSValue *> *anchor;
+
+/**
+ Values describing animated transitions to `anchor` property.
+ */
+@property (nonatomic) MGLTransition anchorTransition;
+
+
+/**
+ Position of the light source relative to lit (extruded) geometries.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-position"><code>position</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<NSValue *> *position;
+
+/**
+ Values describing animated transitions to `position` property.
+ */
+@property (nonatomic) MGLTransition positionTransiton;
+
+
+#if TARGET_OS_IPHONE
+/**
+ Color tint for lighting extruded geometries.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-color"><code>color</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<UIColor *> *color;
+#else
+
+/**
+ Color tint for lighting extruded geometries.
+ */
+@property (nonatomic) MGLStyleValue<NSColor *> *color;
+#endif
+
+/**
+ Values describing animated transitions to `color` property.
+ */
+@property (nonatomic) MGLTransition colorTransiton;
+
+
+/**
+ Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-intensity"><code>intensity</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property(nonatomic) MGLStyleValue<NSNumber *> *intensity;
+
+/**
+ Values describing animated transitions to `intensity` property.
+ */
+@property (nonatomic) MGLTransition intensityTransition;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLLight.mm b/platform/darwin/src/MGLLight.mm
new file mode 100644
index 0000000000..262fad3b07
--- /dev/null
+++ b/platform/darwin/src/MGLLight.mm
@@ -0,0 +1,113 @@
+#import "MGLLight.h"
+
+#import "MGLTypes.h"
+#import "NSDate+MGLAdditions.h"
+#import "MGLStyleValue_Private.h"
+#import "NSValue+MGLAdditions.h"
+
+#import <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLLightAnchor, {
+ { MGLLightAnchorMap, "map" },
+ { MGLLightAnchorViewport, "viewport" },
+ });
+
+}
+
+NS_INLINE MGLTransition MGLTransitionFromOptions(const mbgl::style::TransitionOptions& options) {
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(options.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(options.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+NS_INLINE mbgl::style::TransitionOptions MGLOptionsFromTransition(MGLTransition transition) {
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ return options;
+}
+
+@interface MGLLight()
+
+@end
+
+@implementation MGLLight
+
+- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight
+{
+ if (self = [super init]) {
+ auto anchor = mbglLight->getAnchor();
+ MGLStyleValue<NSValue *> *anchorStyleValue;
+ if (anchor.isUndefined()) {
+ mbgl::style::PropertyValue<mbgl::style::LightAnchorType> defaultAnchor = mbglLight->getDefaultAnchor();
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumStyleValue(defaultAnchor);
+ } else {
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumStyleValue(anchor);
+ }
+
+ _anchor = anchorStyleValue;
+
+ _anchorTransition = MGLTransitionFromOptions(mbglLight->getAnchorTransition());
+
+ auto positionValue = mbglLight->getPosition();
+ if (positionValue.isUndefined()) {
+ _position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toStyleValue(mbglLight->getDefaultPosition());
+ } else {
+ _position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toStyleValue(positionValue);
+ }
+
+ _positionTransiton = MGLTransitionFromOptions(mbglLight->getPositionTransition());
+
+ auto colorValue = mbglLight->getColor();
+ if (colorValue.isUndefined()) {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(mbglLight->getDefaultColor());
+ } else {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(colorValue);
+ }
+
+ _colorTransiton = MGLTransitionFromOptions(mbglLight->getColorTransition());
+
+ auto intensityValue = mbglLight->getIntensity();
+ if (intensityValue.isUndefined()) {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(mbglLight->getDefaultIntensity());
+ } else {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(intensityValue);
+ }
+
+ _intensityTransition = MGLTransitionFromOptions(mbglLight->getIntensityTransition());
+ }
+
+ return self;
+}
+
+- (mbgl::style::Light)mbglLight
+{
+ mbgl::style::Light mbglLight;
+
+ auto anchor = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumPropertyValue(self.anchor);
+ mbglLight.setAnchor(anchor);
+
+ mbglLight.setAnchorTransition(MGLOptionsFromTransition(self.anchorTransition));
+
+ auto position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toInterpolatablePropertyValue(self.position);
+ mbglLight.setPosition(position);
+
+ mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransiton));
+
+ auto color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(self.color);
+ mbglLight.setColor(color);
+
+ mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransiton));
+
+ auto intensity = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(self.intensity);
+ mbglLight.setIntensity(intensity);
+
+ mbglLight.setIntensityTransition(MGLOptionsFromTransition(self.intensityTransition));
+
+ return mbglLight;
+}
+
+@end
diff --git a/platform/darwin/src/MGLLight_Private.h b/platform/darwin/src/MGLLight_Private.h
new file mode 100644
index 0000000000..dbc29c1eff
--- /dev/null
+++ b/platform/darwin/src/MGLLight_Private.h
@@ -0,0 +1,23 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLLight.h"
+
+namespace mbgl {
+ namespace style {
+ class Light;
+ }
+}
+
+@interface MGLLight (Private)
+
+/**
+ Initializes and returns a `MGLLight` associated with a style's light.
+ */
+- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight;
+
+/**
+ Returns an `mbgl::style::Light` representation of the `MGLLight`.
+ */
+- (mbgl::style::Light)mbglLight;
+
+@end
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 195ef3c36a..81774ad3cb 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -7,6 +7,7 @@
#import "MGLOfflinePack_Private.h"
#import "MGLOfflineRegion_Private.h"
#import "MGLTilePyramidOfflineRegion.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSValue+MGLAdditions.h"
#include <mbgl/util/string.hpp>
@@ -132,7 +133,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
appropriateForURL:nil
create:YES
error:nil];
- NSString *bundleIdentifier = [self bundleIdentifier];
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
if (!bundleIdentifier) {
// There’s no main bundle identifier when running in a unit test bundle.
bundleIdentifier = [NSBundle bundleForClass:self].bundleIdentifier;
@@ -166,7 +167,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
#elif TARGET_OS_MAC
// ~/Library/Caches/tld.app.bundle.id/offline.db
- NSString *bundleIdentifier = [self bundleIdentifier];
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
@@ -219,15 +220,6 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
return self;
}
-+ (NSString *)bundleIdentifier {
- NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
- if (!bundleIdentifier) {
- // There’s no main bundle identifier when running in a unit test bundle.
- bundleIdentifier = [NSBundle bundleForClass:self].bundleIdentifier;
- }
- return bundleIdentifier;
-}
-
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[MGLNetworkConfiguration sharedManager] removeObserver:self forKeyPath:@"apiBaseURL"];
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index ceafe873bf..d966ff13ce 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -6,6 +6,7 @@
#import "MGLPolygon+MGLAdditions.h"
#import <mbgl/util/geojson.hpp>
+#import <mapbox/polylabel.hpp>
@implementation MGLPolygon
@@ -54,6 +55,13 @@
return [super hash] + [[self geoJSONDictionary] hash];
}
+- (CLLocationCoordinate2D)coordinate {
+ // pole of inaccessibility
+ auto poi = mapbox::polylabel([self polygon]);
+
+ return MGLLocationCoordinate2DFromPoint(poi);
+}
+
- (mbgl::LinearRing<double>)ring {
NSUInteger count = self.pointCount;
CLLocationCoordinate2D *coordinates = self.coordinates;
@@ -155,11 +163,17 @@
return hash;
}
+- (CLLocationCoordinate2D)coordinate {
+ MGLPolygon *firstPolygon = self.polygons.firstObject;
+
+ return firstPolygon.coordinate;
+}
+
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
}
-- (mbgl::Geometry<double>)geometryObject {
+- (mbgl::MultiPolygon<double>)multiPolygon {
mbgl::MultiPolygon<double> multiPolygon;
multiPolygon.reserve(self.polygons.count);
for (MGLPolygon *polygon in self.polygons) {
@@ -173,6 +187,10 @@
return multiPolygon;
}
+- (mbgl::Geometry<double>)geometryObject {
+ return [self multiPolygon];
+}
+
- (NSDictionary *)geoJSONDictionary {
NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.polygons.count];
for (MGLPolygonFeature *feature in self.polygons) {
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index ae4fbe61de..fd75dc2795 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -6,6 +6,7 @@
#import "MGLPolyline+MGLAdditions.h"
#import <mbgl/util/geojson.hpp>
+#import <mapbox/polylabel.hpp>
@implementation MGLPolyline
@@ -52,6 +53,61 @@
return self == other || ([other isKindOfClass:[MGLPolyline class]] && [super isEqual:other]);
}
+- (CLLocationCoordinate2D)coordinate {
+ NSUInteger count = self.pointCount;
+ NSAssert(count > 0, @"Polyline must have coordinates");
+
+ CLLocationCoordinate2D *coordinates = self.coordinates;
+ CLLocationDistance middle = [self length] / 2.0;
+ CLLocationDistance traveled = 0.0;
+
+ if (count > 1 || middle > traveled) {
+ for (NSUInteger i = 0; i < count; i++) {
+
+ MGLRadianCoordinate2D from = MGLRadianCoordinateFromLocationCoordinate(coordinates[i]);
+ MGLRadianCoordinate2D to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1]);
+
+ if (traveled >= middle) {
+ double overshoot = middle - traveled;
+ if (overshoot == 0) {
+ return coordinates[i];
+ }
+ to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i - 1]);
+ CLLocationDirection direction = [self direction:from to:to] - 180;
+ MGLRadianCoordinate2D otherCoordinate = MGLRadianCoordinateAtDistanceFacingDirection(from,
+ overshoot/mbgl::util::EARTH_RADIUS_M,
+ MGLRadiansFromDegrees(direction));
+ return CLLocationCoordinate2DMake(MGLDegreesFromRadians(otherCoordinate.latitude),
+ MGLDegreesFromRadians(otherCoordinate.longitude));
+ }
+
+ traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * mbgl::util::EARTH_RADIUS_M);
+
+ }
+ }
+
+ return coordinates[count - 1];
+}
+
+- (CLLocationDistance)length
+{
+ CLLocationDistance length = 0.0;
+
+ NSUInteger count = self.pointCount;
+ CLLocationCoordinate2D *coordinates = self.coordinates;
+
+ for (NSUInteger i = 0; i < count - 1; i++) {
+ length += (MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinateFromLocationCoordinate(coordinates[i]), MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1])) * mbgl::util::EARTH_RADIUS_M);
+ }
+
+ return length;
+}
+
+- (CLLocationDirection)direction:(MGLRadianCoordinate2D)from to:(MGLRadianCoordinate2D)to
+{
+ return MGLDegreesFromRadians(MGLRadianCoordinatesDirection(from, to));
+}
+
@end
@interface MGLMultiPolyline ()
@@ -114,6 +170,15 @@
return hash;
}
+- (CLLocationCoordinate2D)coordinate {
+ MGLPolyline *polyline = self.polylines.firstObject;
+ CLLocationCoordinate2D *coordinates = polyline.coordinates;
+ NSAssert([polyline pointCount] > 0, @"Polyline must have coordinates");
+ CLLocationCoordinate2D firstCoordinate = coordinates[0];
+
+ return firstCoordinate;
+}
+
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
}
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h
index 519784f4f1..4f4b7c96c3 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterSource.h
@@ -108,96 +108,13 @@ MGL_EXPORT
Returns a raster source initialized an identifier, tile URL templates, and
options.
+ Tile URL templates are strings that specify the URLs of the raster tile images
+ to load. See the “<a href="../tile-url-templates.html">Tile URL Templates</a>”
+ guide for information about the format of a tile URL template.
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
- #### Tile URL templates
-
- Tile URL templates are strings that specify the URLs of the tile images to
- load. Each template resembles an absolute URL, but with any number of
- placeholder strings that the source evaluates based on the tile it needs to
- load. For example:
-
- <ul>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li>
- </ul>
-
- Tile sources support the following placeholder strings in tile URL templates,
- all of which are optional:
-
- <table>
- <thead>
- <tr><th>Placeholder string</th><th>Description</th></tr>
- </thead>
- <tbody>
- <tr>
- <td><code>{x}</code></td>
- <td>The index of the tile along the map’s x axis according to Spherical
- Mercator projection. If the value is 0, the tile’s left edge corresponds
- to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
- the tile’s right edge corresponds to the 180th meridian east.</td>
- </tr>
- <tr>
- <td><code>{y}</code></td>
- <td>The index of the tile along the map’s y axis according to Spherical
- Mercator projection. If the value is 0, the tile’s tile edge corresponds
- to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
- is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
- −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
- inverted if the <code>options</code> parameter contains
- <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
- <code>MGLTileCoordinateSystemTMS</code>.</td>
- </tr>
- <tr>
- <td><code>{z}</code></td>
- <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
- world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
- <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
- matches the map’s current zoom level depends on the value of the
- source’s tile size as specified in the
- <code>MGLTileSourceOptionTileSize</code> key of the
- <code>options</code> parameter.</td>
- </tr>
- <tr>
- <td><code>{bbox-epsg-3857}</code></td>
- <td>The tile’s bounding box, expressed as a comma-separated list of the
- tile’s western, southern, eastern, and northern extents according to
- Spherical Mercator (EPSG:3857) projection. The bounding box is typically
- used with map services conforming to the
- <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
- protocol.</td>
- </tr>
- <tr>
- <td><code>{quadkey}</code></td>
- <td>A quadkey indicating both the tile’s location and its zoom level. The
- quadkey is typically used with
- <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
- </td>
- </tr>
- <tr>
- <td><code>{ratio}</code></td>
- <td>A suffix indicating the resolution of the tile image. The suffix is the
- empty string for standard resolution displays and <code>@2x</code> for
- Retina displays, including displays for which
- <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code>
- is 3.</td>
- </tr>
- <tr>
- <td><code>{prefix}</code></td>
- <td>Two hexadecimal digits chosen such that each visible tile has a
- different prefix. The prefix is typically used for domain sharding.</td>
- </tr>
- </tbody>
- </table>
-
- For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
- consult the
- <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>.
-
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param tileURLTemplates An array of tile URL template strings. Only the first
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index ccec863236..6fb4a6cc6b 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -6,6 +6,7 @@
#import "MGLTypes.h"
@class MGLSource;
+@class MGLLight;
NS_ASSUME_NONNULL_BEGIN
@@ -548,6 +549,14 @@ MGL_EXPORT
*/
- (void)removeImageForName:(NSString *)name;
+
+#pragma mark Managing the Style's Light
+
+/**
+ Provides global light source for the style.
+ */
+@property (nonatomic, strong) MGLLight *light;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 5f26b4fed2..2e6f2bc29a 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -14,6 +14,7 @@
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
#import "MGLSource_Private.h"
+#import "MGLLight_Private.h"
#import "NSDate+MGLAdditions.h"
@@ -28,6 +29,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/style/image.hpp>
+#include <mbgl/style/light.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
@@ -556,6 +558,21 @@ static NSURL *MGLStyleURL_emerald;
return transition;
}
+#pragma mark Style light
+
+- (void)setLight:(MGLLight *)light
+{
+ std::unique_ptr<mbgl::style::Light> mbglLight = std::make_unique<mbgl::style::Light>([light mbglLight]);
+ self.mapView.mbglMap->setLight(std::move(mbglLight));
+}
+
+- (MGLLight *)light
+{
+ auto mbglLight = self.mapView.mbglMap->getLight();
+ MGLLight *light = [[MGLLight alloc] initWithMBGLLight:mbglLight];
+ return light;
+}
+
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>",
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index 70074c8a13..2bb3aca4f4 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -75,9 +75,9 @@ typedef NS_ENUM(NSUInteger, MGLInterpolationMode) {
*/
MGLInterpolationModeCategorical,
/**
- Values between two stops are not interpolated. Instead, values are set to their
- input value. Use identity interpolation mode to show attribute values that can be
- used as style values.
+ Values between two stops are not interpolated. Instead, for any given feature, the
+ style value matches a value in that feature’s attributes dictionary. Use identity
+ interpolation mode to show attribute values that can be used as style values.
*/
MGLInterpolationModeIdentity
};
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 33b6babadf..4dd6b550d8 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -128,7 +128,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
return {};
}
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
@@ -181,7 +181,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
_attributeName = attributeName;
@@ -251,7 +251,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
_attributeName = attributeName;
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 263b54d7e5..2155c657bd 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -3,11 +3,13 @@
#import "MGLStyleValue.h"
#import "NSValue+MGLStyleAttributeAdditions.h"
+#import "NSValue+MGLAdditions.h"
#import "MGLTypes.h"
#import "MGLConversion.h"
#include <mbgl/style/conversion/data_driven_property_value.hpp>
#include <mbgl/style/conversion.hpp>
+#import <mbgl/style/types.hpp>
#import <mbgl/util/enum.hpp>
@@ -415,6 +417,12 @@ private: // Private utilities for converting from mgl to mbgl values
mbglValue.push_back(mbglElement);
}
}
+
+ void getMBGLValue(NSValue *rawValue, mbgl::style::Position &mbglValue) {
+ auto spherical = rawValue.mgl_lightPositionArrayValue;
+ mbgl::style::Position position(spherical);
+ mbglValue = position;
+ }
// Enumerations
template <typename MBGLEnum = MBGLType,
@@ -473,6 +481,12 @@ private: // Private utilities for converting from mbgl to mgl values
}
return array;
}
+
+ static NSValue *toMGLRawStyleValue(const mbgl::style::Position &mbglStopValue) {
+ std::array<float, 3> spherical = mbglStopValue.getSpherical();
+ MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]);
+ return [NSValue valueWithMGLSphericalPosition:position];
+ }
// Enumerations
template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index c06fd8b0e7..16f510b5a6 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -1,4 +1,5 @@
#import <Foundation/Foundation.h>
+#import <CoreGraphics/CoreGraphics.h>
#import "MGLFoundation.h"
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h
index a48434f7a3..968be3c0e0 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorSource.h
@@ -74,96 +74,13 @@ MGL_EXPORT
Returns a vector source initialized an identifier, tile URL templates, and
options.
+ Tile URL templates are strings that specify the URLs of the vector tiles to
+ load. See the “<a href="../tile-url-templates.html">Tile URL Templates</a>”
+ guide for information about the format of a tile URL template.
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
- #### Tile URL templates
-
- Tile URL templates are strings that specify the URLs of the tile images to
- load. Each template resembles an absolute URL, but with any number of
- placeholder strings that the source evaluates based on the tile it needs to
- load. For example:
-
- <ul>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li>
- </ul>
-
- Tile sources support the following placeholder strings in tile URL templates,
- all of which are optional:
-
- <table>
- <thead>
- <tr><th>Placeholder string</th><th>Description</th></tr>
- </thead>
- <tbody>
- <tr>
- <td><code>{x}</code></td>
- <td>The index of the tile along the map’s x axis according to Spherical
- Mercator projection. If the value is 0, the tile’s left edge corresponds
- to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
- the tile’s right edge corresponds to the 180th meridian east.</td>
- </tr>
- <tr>
- <td><code>{y}</code></td>
- <td>The index of the tile along the map’s y axis according to Spherical
- Mercator projection. If the value is 0, the tile’s tile edge corresponds
- to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
- is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
- −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
- inverted if the <code>options</code> parameter contains
- <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
- <code>MGLTileCoordinateSystemTMS</code>.</td>
- </tr>
- <tr>
- <td><code>{z}</code></td>
- <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
- world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
- <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
- matches the map’s current zoom level depends on the value of the
- source’s tile size as specified in the
- <code>MGLTileSourceOptionTileSize</code> key of the
- <code>options</code> parameter.</td>
- </tr>
- <tr>
- <td><code>{bbox-epsg-3857}</code></td>
- <td>The tile’s bounding box, expressed as a comma-separated list of the
- tile’s western, southern, eastern, and northern extents according to
- Spherical Mercator (EPSG:3857) projection. The bounding box is typically
- used with map services conforming to the
- <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
- protocol.</td>
- </tr>
- <tr>
- <td><code>{quadkey}</code></td>
- <td>A quadkey indicating both the tile’s location and its zoom level. The
- quadkey is typically used with
- <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
- </td>
- </tr>
- <tr>
- <td><code>{ratio}</code></td>
- <td>A suffix indicating the resolution of the tile image. The suffix is the
- empty string for standard resolution displays and <code>@2x</code> for
- Retina displays, including displays for which
- <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code>
- is 3.</td>
- </tr>
- <tr>
- <td><code>{prefix}</code></td>
- <td>Two hexadecimal digits chosen such that each visible tile has a
- different prefix. The prefix is typically used for domain sharding.</td>
- </tr>
- </tbody>
- </table>
-
- For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
- consult the
- <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>.
-
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param tileURLTemplates An array of tile URL template strings. Only the first
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.h b/platform/darwin/src/NSBundle+MGLAdditions.h
index 1fc9e8b896..ad5e9d5369 100644
--- a/platform/darwin/src/NSBundle+MGLAdditions.h
+++ b/platform/darwin/src/NSBundle+MGLAdditions.h
@@ -36,9 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary;
-/// The relative path to the directory containing the SDK’s resource files, or
-/// `nil` if the files are located directly within the bundle’s root directory.
-@property (readonly, copy, nullable) NSString *mgl_resourcesDirectory;
++ (nullable NSString *)mgl_applicationBundleIdentifier;
@end
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.m b/platform/darwin/src/NSBundle+MGLAdditions.m
index 76d9cc0db7..f383a50300 100644
--- a/platform/darwin/src/NSBundle+MGLAdditions.m
+++ b/platform/darwin/src/NSBundle+MGLAdditions.m
@@ -6,12 +6,19 @@
+ (instancetype)mgl_frameworkBundle {
NSBundle *bundle = [self bundleForClass:[MGLAccountManager class]];
- if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"] && !bundle.mgl_resourcesDirectory) {
+
+ if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"]) {
// For static frameworks, the bundle is the containing application
- // bundle but the resources are still in the framework bundle.
- bundle = [NSBundle bundleWithPath:[bundle.privateFrameworksPath
- stringByAppendingPathComponent:@"Mapbox.framework"]];
+ // bundle but the resources are in Mapbox.bundle.
+ NSString *bundlePath = [bundle pathForResource:@"Mapbox" ofType:@"bundle"];
+ if (bundlePath) {
+ bundle = [self bundleWithPath:bundlePath];
+ } else {
+ [NSException raise:@"MGLBundleNotFoundException" format:
+ @"The Mapbox framework bundle could not be found. If using the Mapbox iOS SDK as a static framework, make sure that Mapbox.bundle is copied into the root of the app bundle."];
+ }
}
+
return bundle;
}
@@ -21,18 +28,16 @@
+ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary {
NSBundle *bundle = self.mgl_frameworkBundle;
- if (bundle.mgl_resourcesDirectory) {
- NSString *infoPlistPath = [bundle pathForResource:@"Info"
- ofType:@"plist"
- inDirectory:bundle.mgl_resourcesDirectory];
- return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
- } else {
- return bundle.infoDictionary;
- }
+ return bundle.infoDictionary;
}
-- (NSString *)mgl_resourcesDirectory {
- return [self pathForResource:@"Mapbox" ofType:@"bundle"] ? @"Mapbox.bundle" : nil;
++ (nullable NSString *)mgl_applicationBundleIdentifier {
+ NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+ if (!bundleIdentifier) {
+ // There’s no main bundle identifier when running in a unit test bundle.
+ bundleIdentifier = [NSBundle bundleForClass:[MGLAccountManager class]].bundleIdentifier;
+ }
+ return bundleIdentifier;
}
@end
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index e6755021d0..0aaa2a337a 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import "MGLGeometry.h"
+#import "MGLLight.h"
#import "MGLOfflinePack.h"
#import "MGLTypes.h"
@@ -87,6 +88,34 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (readonly) MGLTransition MGLTransitionValue;
+/**
+ Creates a new value object containing the given `MGLSphericalPosition`
+ structure.
+
+ @param lightPosition The value for the new object.
+ @return A new value object that contains the light position information.
+ */
++ (instancetype)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition;
+
+/**
+ The `MGLSphericalPosition` structure representation of the value.
+ */
+@property (readonly) MGLSphericalPosition MGLSphericalPositionValue;
+
+/**
+ Creates a new value object containing the given `MGLLightAnchor`
+ enum.
+
+ @param lightAnchor The value for the new object.
+ @return A new value object that contains the light anchor information.
+ */
++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor;
+
+/**
+ The `MGLLightAnchor` enum representation of the value.
+ */
+@property (readonly) MGLLightAnchor MGLLightAnchorValue;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m
index a95ef23941..ef894f0eb4 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.m
+++ b/platform/darwin/src/NSValue+MGLAdditions.m
@@ -58,4 +58,27 @@
return transition;
}
++ (NSValue *)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition
+{
+ return [NSValue value:&lightPosition withObjCType:@encode(MGLSphericalPosition)];
+}
+
+- (MGLSphericalPosition)MGLSphericalPositionValue
+{
+ MGLSphericalPosition lightPosition;
+ [self getValue:&lightPosition];
+ return lightPosition;
+}
+
++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor {
+ return [NSValue value:&lightAnchor withObjCType:@encode(MGLLightAnchor)];
+}
+
+- (MGLLightAnchor)MGLLightAnchorValue
+{
+ MGLLightAnchor achorType;
+ [self getValue:&achorType];
+ return achorType;
+}
+
@end
diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
index 60c1ee4075..0f1e511694 100644
--- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
+++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
@@ -9,5 +9,6 @@
- (std::array<float, 2>)mgl_offsetArrayValue;
- (std::array<float, 4>)mgl_paddingArrayValue;
+- (std::array<float, 3>)mgl_lightPositionArrayValue;
@end
diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
index e66145aec1..a41950b6b3 100644
--- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
+++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
@@ -1,5 +1,5 @@
#import "NSValue+MGLStyleAttributeAdditions.h"
-
+#import "MGLLight.h"
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#define MGLEdgeInsets UIEdgeInsets
@@ -61,4 +61,17 @@
};
}
+- (std::array<float, 3>)mgl_lightPositionArrayValue
+{
+ NSAssert(strcmp(self.objCType, @encode(MGLSphericalPosition)) == 0, @"Value does not represent an MGLSphericalPosition");
+ MGLSphericalPosition lightPosition;
+ [self getValue:&lightPosition];
+ // Style specification defines padding in clockwise order: top, right, bottom, left.
+ return {
+ static_cast<float>(lightPosition.radial),
+ static_cast<float>(lightPosition.azimuthal),
+ static_cast<float>(lightPosition.polar),
+ };
+}
+
@end
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index e258671c09..ed4927d44b 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -46,8 +46,18 @@
XCTAssertEqualObjects(infos[3].title.string, @"Improve this map");
XCTAssertEqualObjects(infos[3].URL, [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/"]);
XCTAssertTrue(infos[3].feedbackLink);
+ NSURL *styleURL = [MGLStyle satelliteStreetsStyleURLWithVersion:99];
+#if TARGET_OS_IPHONE
+ XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios#/77.63680/12.98108/14.00/0.0/0"]);
+ XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+#else
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
- [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/#/77.63680/12.98108/15"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL#/77.63680/12.98108/14.00/0.0/0"]);
+ XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+#endif
}
- (void)testStyle {
diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m
index ff0d674ad1..ac61672b76 100644
--- a/platform/darwin/test/MGLCodingTests.m
+++ b/platform/darwin/test/MGLCodingTests.m
@@ -66,12 +66,54 @@
[unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates];
XCTAssertNotEqualObjects(polyline, unarchivedPolyline);
+
+ CLLocationCoordinate2D multiLineCoordinates[] = {
+ CLLocationCoordinate2DMake(51.000000, 0.000000),
+ CLLocationCoordinate2DMake(51.000000, 1.000000),
+ CLLocationCoordinate2DMake(51.000000, 2.000000),
+ };
+
+ NSUInteger multiLineCoordinatesCount = sizeof(multiLineCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *multiLine = [MGLPolyline polylineWithCoordinates:multiLineCoordinates count:multiLineCoordinatesCount];
+ CLLocationCoordinate2D multiLineCenter = CLLocationCoordinate2DMake(51.000000, 1.000000);
+
+ XCTAssertEqual([multiLine coordinate].latitude, multiLineCenter.latitude);
+ XCTAssertEqual([multiLine coordinate].longitude, multiLineCenter.longitude);
+
+ CLLocationCoordinate2D segmentCoordinates[] = {
+ CLLocationCoordinate2DMake(35.040390, -85.311477),
+ CLLocationCoordinate2DMake(35.040390, -85.209510),
+ };
+
+ NSUInteger segmentCoordinatesCount = sizeof(segmentCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *segmentLine = [MGLPolyline polylineWithCoordinates:segmentCoordinates count:segmentCoordinatesCount];
+ CLLocationCoordinate2D segmentCenter = CLLocationCoordinate2DMake(35.0404006631, -85.2604935);
+
+ XCTAssertEqualWithAccuracy([segmentLine coordinate].latitude, segmentCenter.latitude, 0.0001);
+ XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 0.0001);
+
+ CLLocationCoordinate2D sfToBerkeleyCoordinates[] = {
+ CLLocationCoordinate2DMake(37.782440, -122.397111),
+ CLLocationCoordinate2DMake(37.818384, -122.352994),
+ CLLocationCoordinate2DMake(37.831401, -122.274545),
+ CLLocationCoordinate2DMake(37.862172, -122.262700),
+ };
+
+ NSUInteger sfToBerkeleyCoordinatesCount = sizeof(sfToBerkeleyCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *sfToBerkeleyLine = [MGLPolyline polylineWithCoordinates:sfToBerkeleyCoordinates count:sfToBerkeleyCoordinatesCount];
+ CLLocationCoordinate2D sfToBerkeleyCenter = CLLocationCoordinate2DMake(37.8230575118,-122.324867587);
+
+ XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].latitude, sfToBerkeleyCenter.latitude, 0.0001);
+ XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 0.0001);
+
}
- (void)testPolygon {
CLLocationCoordinate2D coordinates[] = {
- CLLocationCoordinate2DMake(0.664482398, 1.8865675),
- CLLocationCoordinate2DMake(2.13224687, 3.9984632)
+ CLLocationCoordinate2DMake(35.090745, -85.300259),
+ CLLocationCoordinate2DMake(35.092035, -85.298885),
+ CLLocationCoordinate2DMake(35.090639, -85.297416),
+ CLLocationCoordinate2DMake(35.089112, -85.298928)
};
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -84,8 +126,24 @@
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
+ [unarchivedPolygon coordinate];
XCTAssertEqualObjects(polygon, unarchivedPolygon);
+
+ CLLocationCoordinate2D squareCoordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ };
+
+ NSUInteger squareCoordinatesCount = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:squareCoordinatesCount];
+ CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5);
+
+ XCTAssertEqual([squarePolygon coordinate].latitude, squareCenter.latitude);
+ XCTAssertEqual([squarePolygon coordinate].longitude, squareCenter.longitude);
+
}
- (void)testPolygonWithInteriorPolygons {
@@ -169,6 +227,11 @@
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
MGLPointCollection *pointCollection = [MGLPointCollection pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
+ CLLocationCoordinate2D pointsCenter = CLLocationCoordinate2DMake(0, 1);
+
+ XCTAssertEqual([pointCollection coordinate].latitude, pointsCenter.latitude);
+ XCTAssertEqual([pointCollection coordinate].longitude, pointsCenter.longitude);
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollection class]];
[NSKeyedArchiver archiveRootObject:pointCollection toFile:filePath];
@@ -218,6 +281,30 @@
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
+
+ CLLocationCoordinate2D line1[] = {
+ CLLocationCoordinate2DMake(100, 40),
+ CLLocationCoordinate2DMake(105, 45),
+ CLLocationCoordinate2DMake(110, 55)
+ };
+
+ CLLocationCoordinate2D line2[] = {
+ CLLocationCoordinate2DMake(105, 40),
+ CLLocationCoordinate2DMake(110, 45),
+ CLLocationCoordinate2DMake(115, 55)
+ };
+
+ NSUInteger road1CoordinatesCount = sizeof(line1) / sizeof(CLLocationCoordinate2D);
+ NSUInteger road2CoordinatesCount = sizeof(line2) / sizeof(CLLocationCoordinate2D);
+
+ MGLPolyline *road1Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road1CoordinatesCount];
+ MGLPolyline *road2Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road2CoordinatesCount];
+
+ MGLMultiPolyline *roads = [MGLMultiPolyline multiPolylineWithPolylines:@[road1Polyline, road2Polyline]];
+ CLLocationCoordinate2D roadCenter = CLLocationCoordinate2DMake(100, 40);
+
+ XCTAssertEqual([roads coordinate].latitude, roadCenter.latitude);
+ XCTAssertEqual([roads coordinate].longitude, roadCenter.longitude);
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -248,6 +335,31 @@
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
+
+ CLLocationCoordinate2D outerSquare[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ };
+
+ CLLocationCoordinate2D innerSquare[] = {
+ CLLocationCoordinate2DMake(100.35, 0.35),
+ CLLocationCoordinate2DMake(100.65, 0.35),
+ CLLocationCoordinate2DMake(100.65, 0.65),
+ CLLocationCoordinate2DMake(100.35, 0.65),
+ };
+
+ NSUInteger outerCoordinatesCount = sizeof(outerSquare) / sizeof(CLLocationCoordinate2D);
+ NSUInteger innerCoordinatesCount = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D);
+
+ MGLPolygon *innerPolygonSquare = [MGLPolygon polygonWithCoordinates:innerSquare count:innerCoordinatesCount];
+ MGLPolygon *outerPolygonSquare = [MGLPolygon polygonWithCoordinates:outerSquare count:outerCoordinatesCount interiorPolygons:@[innerPolygonSquare]];
+ MGLMultiPolygon *squares = [MGLMultiPolygon multiPolygonWithPolygons:@[outerPolygonSquare, innerPolygonSquare]];
+ CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5);
+
+ XCTAssertEqual([squares coordinate].latitude, squareCenter.latitude);
+ XCTAssertEqual([squares coordinate].longitude, squareCenter.longitude);
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -265,9 +377,10 @@
MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
-
+
XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon);
XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon);
+
}
- (void)testShapeCollection {
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 6d2dc597a9..48e6b17f44 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -168,7 +168,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
layer.sourceLayerIdentifier = "building"
layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
- layer.predicate = NSPredicate(format: "extrude == TRUE")
+ layer.predicate = NSPredicate(format: "extrude == 'true'")
mapView.style?.addLayer(layer)
//#-end-example-code
diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm
new file mode 100644
index 0000000000..2c3d1c7bd1
--- /dev/null
+++ b/platform/darwin/test/MGLLightTest.mm
@@ -0,0 +1,217 @@
+#import <XCTest/XCTest.h>
+#import <Mapbox/Mapbox.h>
+
+#import "MGLLight_Private.h"
+
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@interface MGLLightTest : XCTestCase
+
+@end
+
+@implementation MGLLightTest
+
+- (void)testProperties {
+
+ MGLTransition defaultTransition = MGLTransitionMake(0, 0);
+ MGLTransition transition = MGLTransitionMake(6, 3);
+ mbgl::style::TransitionOptions transitionOptions { { MGLDurationFromTimeInterval(6) }, { MGLDurationFromTimeInterval(3) } };
+
+ // anchor
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+
+ NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue.");
+ NSValue *anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue;
+ XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorViewport);
+ XCTAssertEqual(mglLight.anchorTransition.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.anchorTransition.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLlight.getAnchor().asConstant());
+ auto anchorTransition = lightFromMGLlight.getAnchorTransition();
+ XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == defaultTransition.delay);
+ XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == defaultTransition.duration);
+
+ MGLStyleValue<NSValue *> *anchorStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLightAnchor:MGLLightAnchorMap]];
+ mglLight.anchor = anchorStyleValue;
+ mglLight.anchorTransition = transition;
+ NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue.");
+ anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue;
+
+ XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorMap);
+ XCTAssertEqual(mglLight.anchorTransition.delay, transition.delay);
+ XCTAssertEqual(mglLight.anchorTransition.duration, transition.duration);
+
+ mbgl::style::PropertyValue<mbgl::style::LightAnchorType> anchorProperty = { mbgl::style::LightAnchorType::Map };
+ light.setAnchor(anchorProperty);
+ light.setAnchorTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getAnchor().asConstant(), lightFromMGLlight.getAnchor().asConstant());
+ anchorTransition = lightFromMGLlight.getAnchorTransition();
+ XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == transition.delay);
+ XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == transition.duration);
+
+ }
+
+ // position
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue.");
+ NSValue *positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue;
+ auto positionArray = light.getDefaultPosition().getSpherical();
+ MGLSphericalPosition defaultPosition = MGLSphericalPositionMake(positionArray[0], positionArray[1], positionArray[2]);
+
+ XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial);
+ XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal);
+ XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar);
+ XCTAssertEqual(mglLight.positionTransiton.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.positionTransiton.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical());
+ auto positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == defaultTransition.delay);
+ XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == defaultTransition.duration);
+
+ defaultPosition = MGLSphericalPositionMake(6, 180, 90);
+ MGLStyleValue<NSValue *> *positionStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLSphericalPosition:defaultPosition]];
+ mglLight.position = positionStyleValue;
+ mglLight.positionTransiton = transition;
+
+ NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue.");
+ positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue;
+
+ XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial);
+ XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal);
+ XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar);
+ XCTAssertEqual(mglLight.positionTransiton.delay, transition.delay);
+ XCTAssertEqual(mglLight.positionTransiton.duration, transition.duration);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ positionArray = { { 6, 180, 90 } };
+ mbgl::style::Position position = { positionArray };
+ mbgl::style::PropertyValue<mbgl::style::Position> positionProperty = { position };
+ light.setPosition(positionProperty);
+ light.setPositionTransition(transitionOptions);
+
+ XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical());
+ positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == transition.delay);
+ XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == transition.duration);
+
+ }
+
+ // color
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue.");
+ MGLColor *colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue;
+ auto color = light.getDefaultColor();
+ const CGFloat *colorComponents = CGColorGetComponents(colorValue.CGColor);
+
+ XCTAssert(color.r == colorComponents[0] && color.g == colorComponents[1] && color.b == colorComponents[2] &&
+ color.a == colorComponents[3]);
+ XCTAssertEqual(mglLight.colorTransiton.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.colorTransiton.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(color, lightFromMGLlight.getColor().asConstant());
+ auto colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == defaultTransition.delay);
+ XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == defaultTransition.duration);
+
+ MGLStyleValue<MGLColor *> *colorStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor blackColor]];
+ mglLight.color = colorStyleValue;
+ mglLight.colorTransiton = transition;
+
+ NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue.");
+ colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue;
+
+ XCTAssertEqual([MGLColor blackColor], colorValue);
+ XCTAssertEqual(mglLight.colorTransiton.delay, transition.delay);
+ XCTAssertEqual(mglLight.colorTransiton.duration, transition.duration);
+
+ mbgl::style::PropertyValue<mbgl::Color> colorProperty = { { 0, 0, 0, 1 } };
+ light.setColor(colorProperty);
+ light.setColorTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ colorComponents = CGColorGetComponents(colorValue.CGColor);
+ color = lightFromMGLlight.getColor().asConstant();
+ XCTAssertEqual(light.getColor().asConstant(),lightFromMGLlight.getColor().asConstant());
+ colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == transition.delay);
+ XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == transition.duration);
+ }
+
+ // intensity
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue.");
+ NSNumber *intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue;
+ auto intensity = light.getDefaultIntensity();
+
+ XCTAssert(intensityNumber.floatValue == intensity);
+ XCTAssertEqual(mglLight.intensityTransition.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.intensityTransition.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(intensity, lightFromMGLlight.getIntensity().asConstant());
+ auto intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == defaultTransition.delay);
+ XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == defaultTransition.duration);
+
+ NSNumber *intensityValue = @0.4;
+ MGLStyleValue<NSNumber *> *intensityStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:intensityValue];
+ mglLight.intensity = intensityStyleValue;
+ mglLight.intensityTransition = transition;
+
+ NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue.");
+ intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue;
+ XCTAssert(intensityNumber.floatValue == intensityValue.floatValue);
+ XCTAssertEqual(mglLight.intensityTransition.delay, transition.delay);
+ XCTAssertEqual(mglLight.intensityTransition.duration, transition.duration);
+
+ mbgl::style::PropertyValue<float> intensityProperty = { 0.4 };
+ light.setIntensity(intensityProperty);
+ light.setIntensityTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getIntensity().asConstant(), lightFromMGLlight.getIntensity().asConstant());
+ intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == transition.delay);
+ XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == transition.duration);
+
+ }
+
+}
+
+- (void)testValueAdditions {
+ MGLSphericalPosition position = MGLSphericalPositionMake(1.15, 210, 30);
+
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.radial, position.radial);
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.azimuthal, position.azimuthal);
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.polar, position.polar);
+ XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorMap].MGLLightAnchorValue, MGLLightAnchorMap);
+ XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorViewport].MGLLightAnchorValue, MGLLightAnchorViewport);
+}
+
+@end
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index ceb371118d..977dd1b418 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,7 +2,13 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
-## master
+## 3.6.0
+
+### Packaging
+
+* Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775))
+* Fixed an issue in the static framework where localizations would never load. ([#9074](https://github.com/mapbox/mapbox-gl-native/pull/9074))
+* Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773))
* The previously-deprecated support for style classes has been removed. For interface compatibility, the API methods remain, but they are now non-functional.
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617))
@@ -16,26 +22,36 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Added class methods to MGLStyle that correspond to the new [Traffic Day and Traffic Night](https://www.mapbox.com/blog/live-traffic-maps/) styles. ([#6301](https://github.com/mapbox/mapbox-gl-native/pull/6301))
* MGLSymbolStyleLayer’s `iconImageName`, `iconScale`, `textFontSize`, `textOffset`, and `textRotation` properties can now be set to a source or composite function. ([#8544](https://github.com/mapbox/mapbox-gl-native/pull/8544), [#8590](https://github.com/mapbox/mapbox-gl-native/pull/8590), [#8592](https://github.com/mapbox/mapbox-gl-native/pull/8592), [#8593](https://github.com/mapbox/mapbox-gl-native/pull/8593))
* Fixed an issue where setting the `MGLVectorStyleLayer.predicate` property failed to take effect if the relevant source was not in use by a visible layer at the time. ([#8653](https://github.com/mapbox/mapbox-gl-native/pull/8653))
+* Fixed an issue preventing programmatically added style layers from appearing in already cached tiles. ([#8954](https://github.com/mapbox/mapbox-gl-native/pull/8954))
* Fixed an issue causing a composite function’s highest zoom level stop to be misinterpreted. ([#8613](https://github.com/mapbox/mapbox-gl-native/pull/8613), [#8790](https://github.com/mapbox/mapbox-gl-native/pull/8790))
* Fixed an issue where re-adding a layer that had been previously removed from a style would reset its paint properties. Moved initializers for `MGLTileSource`, `MGLStyleLayer`, and `MGLForegroundStyleLayer` to their concrete subclasses; because these classes were already intended for initialization only via concrete subclasses, this should have no developer impact. ([#8626](https://github.com/mapbox/mapbox-gl-native/pull/8626))
* Feature querying results now account for any changes to a feature’s size caused by a source or composite style function. ([#8665](https://github.com/mapbox/mapbox-gl-native/pull/8665))
+* Letter spacing is now disabled in Arabic text so that ligatures are drawn correctly. ([#9062](https://github.com/mapbox/mapbox-gl-native/pull/9062))
### Annotations
+* Added a new initializer to `MGLAnnotationView` so that it is possible to create a new instance with an associated annotation object. ([#9029](https://github.com/mapbox/mapbox-gl-native/pull/9029))
+* Added a new `rotatesToMatchCamera` property to `MGLAnnotationView` that, when set to true, causes the annotation view to rotate along with the map's rotation angle giving the appearance that the annoation view is pinned to the map. ([#9147](https://github.com/mapbox/mapbox-gl-native/pull/9147))
* Fixed an issue causing a view-backed annotation to disappear immediately instead of animating when the annotation’s `coordinate` property is set to a value outside the current viewport. ([#8565](https://github.com/mapbox/mapbox-gl-native/pull/8565))
* Fixed an issue in which `MGLMapView` overrode the tint colors of its annotation views. ([#8789](https://github.com/mapbox/mapbox-gl-native/pull/8789))
+* Fixed an issue causing annotation views to persist in the map’s annotation container view even after their associated annotations were removed. ([#9025](https://github.com/mapbox/mapbox-gl-native/pull/9025))
+* The `MGLPolyline.coordinate` and `MGLPolygon.coordinate` properties now return the midpoint and centroid, respectively, instead of the first coordinate. ([#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713))
### User interaction
* Added a scale bar to `MGLMapView` that indicates the scale of the map. ([#7631](https://github.com/mapbox/mapbox-gl-native/pull/7631))
* Fixed an issue where gesture recognizers associated with map view interactivity were not disabled when their related interactions were disabled. ([#8304](https://github.com/mapbox/mapbox-gl-native/pull/8304))
+* Fixed an issue preventing the Mapbox Telemetry confirmation dialog from appearing when opened from within a map view in a modal view controller. ([#9027](https://github.com/mapbox/mapbox-gl-native/pull/9027))
+* Corrected the size of MGLMapView’s compass. ([#9060](https://github.com/mapbox/mapbox-gl-native/pull/9060))
+* The Improve This Map button in the attribution action sheet now leads to a feedback tool that matches MGLMapView’s rotation and pitch. `-[MGLAttributionInfo feedbackURLAtCenterCoordinate:zoomLevel:]` no longer respects the feedback URL specified in TileJSON. ([#9078](https://github.com/mapbox/mapbox-gl-native/pull/9078))
### Other changes
-* Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775))
-* Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773))
+* Fixed a crash that occurred when accessing the `MGLMultiPolygon.coordinate` property. ([#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713))
* Fixed a crash or console spew when MGLMapView is initialized with a frame smaller than 64 points wide by 64 points tall. ([#8562](https://github.com/mapbox/mapbox-gl-native/pull/8562))
+* Fixed an issue that caused the compass and scale bar to underlap navigation and tab bars. ([#7716](https://github.com/mapbox/mapbox-gl-native/pull/7716))
* The error passed into `-[MGLMapViewDelegate mapViewDidFailLoadingMap:withError:]` now includes a more specific description and failure reason. ([#8418](https://github.com/mapbox/mapbox-gl-native/pull/8418))
+* Improved CPU and battery performance while animating a tilted map’s camera in an area with many labels. ([#9031](https://github.com/mapbox/mapbox-gl-native/pull/9031))
* Fixed an issue rendering polylines that contain duplicate vertices. ([#8808](https://github.com/mapbox/mapbox-gl-native/pull/8808))
## 3.5.4 - May 9, 2017
diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
index f8b20777fa..3116ede9f5 100644
--- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.6.0-alpha.1'
+ version = '3.6.0-beta.2'
m.name = 'Mapbox-iOS-SDK-symbols'
m.version = "#{version}-symbols"
diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec
index 15658e6241..f6bc3030ab 100644
--- a/platform/ios/Mapbox-iOS-SDK.podspec
+++ b/platform/ios/Mapbox-iOS-SDK.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.6.0-alpha.1'
+ version = '3.6.0-beta.2'
m.name = 'Mapbox-iOS-SDK'
m.version = version
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 7cbe9d594f..7f3adfb78b 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -1396,19 +1396,20 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
- (NSString *)bestLanguageForUser
{
- NSArray *supportedLanguages = @[ @"en", @"es", @"fr", @"de", @"ru", @"zh" ];
- NSArray<NSString *> *preferredLanguages = [NSLocale preferredLanguages];
- NSString *bestLanguage;
-
- for (NSString *language in preferredLanguages) {
- NSString *thisLanguage = [[NSLocale localeWithLocaleIdentifier:language] objectForKey:NSLocaleLanguageCode];
- if ([supportedLanguages containsObject:thisLanguage]) {
- bestLanguage = thisLanguage;
- break;
+ // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
+ NSArray *supportedLanguages = @[ @"ar", @"en", @"es", @"fr", @"de", @"pt", @"ru", @"zh", @"zh-Hans" ];
+ NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:supportedLanguages forPreferences:[NSLocale preferredLanguages]];
+ NSString *mostSpecificLanguage;
+
+ for (NSString *language in preferredLanguages)
+ {
+ if (language.length > mostSpecificLanguage.length)
+ {
+ mostSpecificLanguage = language;
}
}
- return bestLanguage ?: @"en";
+ return mostSpecificLanguage ?: @"en";
}
- (IBAction)startWorldTour
diff --git a/platform/ios/docs/guides/Tile URL Templates.md b/platform/ios/docs/guides/Tile URL Templates.md
new file mode 100644
index 0000000000..f61d2ea33a
--- /dev/null
+++ b/platform/ios/docs/guides/Tile URL Templates.md
@@ -0,0 +1,99 @@
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+# Tile URL Templates
+
+`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
+objects, can be created using an initializer that accepts an array of tile URL
+templates. Tile URL templates are strings that specify the URLs of the vector
+tiles or raster tile images to load. A template resembles an absolute URL, but
+with any number of placeholder strings that the source evaluates based on the
+tile it needs to load. For example:
+
+* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
+ evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
+* `http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png` could be
+ evaluated as `http://www.example.com/tiles/14/6/9@2x.png`.
+
+Tile URL templates are also used to define tilesets in TileJSON manifests or
+[`raster`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-raster-tiles)
+and
+[`vector`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-vector-tiles)
+sources in style JSON files. See the
+[TileJSON specification](https://github.com/mapbox/tilejson-spec/tree/master/2.2.0)
+for information about tile URL templates in the context of a TileJSON or style
+JSON file.
+
+Tile sources support the following placeholder strings in tile URL templates,
+all of which are optional:
+
+<table>
+<thead>
+<tr><th>Placeholder string</th><th>Description</th></tr>
+</thead>
+<tbody>
+<tr>
+ <td><code>{x}</code></td>
+ <td>The index of the tile along the map’s x axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s left edge corresponds
+ to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
+ the tile’s right edge corresponds to the 180th meridian east.</td>
+</tr>
+<tr>
+ <td><code>{y}</code></td>
+ <td>The index of the tile along the map’s y axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s tile edge corresponds
+ to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
+ is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
+ −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
+ inverted if the <code>options</code> parameter contains
+ <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
+ <code>MGLTileCoordinateSystemTMS</code>.</td>
+</tr>
+<tr>
+ <td><code>{z}</code></td>
+ <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
+ world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
+ <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
+ a <code>MGLRasterSource</code> object, whether the tile zoom level
+ matches the map’s current zoom level depends on the value of the
+ source’s tile size as specified in the
+ <code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
+ parameter.</td>
+</tr>
+<tr>
+ <td><code>{bbox-epsg-3857}</code></td>
+ <td>The tile’s bounding box, expressed as a comma-separated list of the
+ tile’s western, southern, eastern, and northern extents according to
+ Spherical Mercator (EPSG:3857) projection. The bounding box is typically
+ used with map services conforming to the
+ <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
+ protocol.</td>
+</tr>
+<tr>
+ <td><code>{quadkey}</code></td>
+ <td>A quadkey indicating both the tile’s location and its zoom level. The
+ quadkey is typically used with
+ <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
+ </td>
+</tr>
+<tr>
+ <td><code>{ratio}</code></td>
+ <td>A suffix indicating the resolution of the tile image. The suffix is the
+ empty string for standard resolution displays and <code>@2x</code> for
+ Retina displays, including displays for which <code>UIScreen.scale</code>
+ is 3.
+ </td>
+</tr>
+<tr>
+ <td><code>{prefix}</code></td>
+ <td>Two hexadecimal digits chosen such that each visible tile has a
+ different prefix. The prefix is typically used for domain sharding.</td>
+</tr>
+</tbody>
+</table>
+
+For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
+consult the
+[OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 215d31810d..b6d422d0fc 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -9,6 +9,13 @@
/* Begin PBXBuildFile section */
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
+ 1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; };
+ 1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; };
+ 1F7454931ECBB43F00021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 1F7454961ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; };
+ 1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; };
+ 1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */; };
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */; };
30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
@@ -165,6 +172,7 @@
408AA8571DAEDA1700022900 /* NSDictionary+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */; };
408AA8581DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; };
408AA8591DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; };
+ 409D0A0D1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409D0A0C1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift */; };
409F43FD1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409F43FC1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift */; };
40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */; };
40CFA6511D7875BB008103BD /* MGLShapeSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */; };
@@ -193,6 +201,8 @@
7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */; };
+ 960D0C361ECF5AAF008E151F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 960D0C351ECF5AAF008E151F /* Images.xcassets */; };
+ 960D0C371ECF5AAF008E151F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 960D0C351ECF5AAF008E151F /* Images.xcassets */; };
9620BB381E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */; };
9620BB391E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */; };
9620BB3A1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */; };
@@ -326,15 +336,6 @@
DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88484D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h */; };
DA88485D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA88484E1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m */; };
DA8848601CBAFC2E00AB86E3 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
- DA88486D1CBAFCC100AB86E3 /* Compass.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848631CBAFCC100AB86E3 /* Compass.png */; };
- DA88486E1CBAFCC100AB86E3 /* Compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848641CBAFCC100AB86E3 /* Compass@2x.png */; };
- DA88486F1CBAFCC100AB86E3 /* Compass@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848651CBAFCC100AB86E3 /* Compass@3x.png */; };
- DA8848701CBAFCC100AB86E3 /* default_marker.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848661CBAFCC100AB86E3 /* default_marker.png */; };
- DA8848711CBAFCC100AB86E3 /* default_marker@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848671CBAFCC100AB86E3 /* default_marker@2x.png */; };
- DA8848721CBAFCC100AB86E3 /* default_marker@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848681CBAFCC100AB86E3 /* default_marker@3x.png */; };
- DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848691CBAFCC100AB86E3 /* mapbox.png */; };
- DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */; };
- DA8848751CBAFCC100AB86E3 /* mapbox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */; };
DA8848841CBB033F00AB86E3 /* FABAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848801CBB033F00AB86E3 /* FABAttributes.h */; };
DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */; };
DA8848861CBB033F00AB86E3 /* Fabric+FABKits.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848821CBB033F00AB86E3 /* Fabric+FABKits.h */; };
@@ -348,15 +349,6 @@
DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BA1CCD2CA100E68420 /* Foundation.strings */; };
DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */; };
DA8933E01CCD31DF00E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA89339F1CCC951200E68420 /* Localizable.strings */; };
- DA8933E11CCD31DF00E68420 /* Compass.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848631CBAFCC100AB86E3 /* Compass.png */; };
- DA8933E21CCD31DF00E68420 /* Compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848641CBAFCC100AB86E3 /* Compass@2x.png */; };
- DA8933E31CCD31DF00E68420 /* Compass@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848651CBAFCC100AB86E3 /* Compass@3x.png */; };
- DA8933E41CCD31DF00E68420 /* default_marker.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848661CBAFCC100AB86E3 /* default_marker.png */; };
- DA8933E51CCD31DF00E68420 /* default_marker@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848671CBAFCC100AB86E3 /* default_marker@2x.png */; };
- DA8933E61CCD31DF00E68420 /* default_marker@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848681CBAFCC100AB86E3 /* default_marker@3x.png */; };
- DA8933E71CCD31DF00E68420 /* mapbox.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848691CBAFCC100AB86E3 /* mapbox.png */; };
- DA8933E81CCD31DF00E68420 /* mapbox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */; };
- DA8933E91CCD31DF00E68420 /* mapbox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */; };
DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */ = {isa = PBXBuildFile; fileRef = DA8933EF1CCD387900E68420 /* strip-frameworks.sh */; };
DA8963371CC549A100684375 /* glyphs in Resources */ = {isa = PBXBuildFile; fileRef = DA8963331CC549A100684375 /* glyphs */; };
DA8963381CC549A100684375 /* sprites in Resources */ = {isa = PBXBuildFile; fileRef = DA8963341CC549A100684375 /* sprites */; };
@@ -545,6 +537,10 @@
/* Begin PBXFileReference section */
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
+ 1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
+ 1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
+ 1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
+ 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = "<group>"; };
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
20DABE861DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = "<group>"; };
20DABE881DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -644,6 +640,7 @@
4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLTileSetTests.mm; path = ../../darwin/test/MGLTileSetTests.mm; sourceTree = "<group>"; };
408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MGLAdditions.h"; sourceTree = "<group>"; };
408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MGLAdditions.mm"; sourceTree = "<group>"; };
+ 409D0A0C1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLAnnotationViewIntegrationTests.swift; sourceTree = "<group>"; };
409F43FC1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLMapViewDelegateIntegrationTests.swift; sourceTree = "<group>"; };
40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = "<group>"; };
40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLShapeSourceTests.mm; path = ../../darwin/test/MGLShapeSourceTests.mm; sourceTree = "<group>"; };
@@ -668,6 +665,7 @@
7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = "<group>"; };
920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLSourceQueryTests.m; path = ../../darwin/test/MGLSourceQueryTests.m; sourceTree = "<group>"; };
+ 960D0C351ECF5AAF008E151F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSDKUpdateChecker.h; sourceTree = "<group>"; };
9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = MGLSDKUpdateChecker.mm; sourceTree = "<group>"; };
9660916B1E5BBFD700A9A03B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -836,15 +834,6 @@
DA88484D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFaux3DUserLocationAnnotationView.h; sourceTree = "<group>"; };
DA88484E1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLFaux3DUserLocationAnnotationView.m; sourceTree = "<group>"; };
DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mapbox.h; path = src/Mapbox.h; sourceTree = SOURCE_ROOT; };
- DA8848631CBAFCC100AB86E3 /* Compass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Compass.png; sourceTree = "<group>"; };
- DA8848641CBAFCC100AB86E3 /* Compass@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Compass@2x.png"; sourceTree = "<group>"; };
- DA8848651CBAFCC100AB86E3 /* Compass@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Compass@3x.png"; sourceTree = "<group>"; };
- DA8848661CBAFCC100AB86E3 /* default_marker.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = default_marker.png; sourceTree = "<group>"; };
- DA8848671CBAFCC100AB86E3 /* default_marker@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "default_marker@2x.png"; sourceTree = "<group>"; };
- DA8848681CBAFCC100AB86E3 /* default_marker@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "default_marker@3x.png"; sourceTree = "<group>"; };
- DA8848691CBAFCC100AB86E3 /* mapbox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mapbox.png; sourceTree = "<group>"; };
- DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mapbox@2x.png"; sourceTree = "<group>"; };
- DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mapbox@3x.png"; sourceTree = "<group>"; };
DA8848801CBB033F00AB86E3 /* FABAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FABAttributes.h; sourceTree = "<group>"; };
DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FABKitProtocol.h; sourceTree = "<group>"; };
DA8848821CBB033F00AB86E3 /* Fabric+FABKits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Fabric+FABKits.h"; sourceTree = "<group>"; };
@@ -1039,6 +1028,9 @@
35599DB81D46AD7F0048254D /* Categories */,
353933F01D3FB6BA003F57D7 /* Layers */,
35136D491D4277EA00C20EFD /* Sources */,
+ 1F0666881EC64F8E001C16D7 /* MGLLight.h */,
+ 1F0666891EC64F8E001C16D7 /* MGLLight.mm */,
+ 1F7454941ECD450D00021D39 /* MGLLight_Private.h */,
DAAF72291DA903C700312FA4 /* MGLStyleValue.h */,
DAAF722A1DA903C700312FA4 /* MGLStyleValue_Private.h */,
35599DEA1D46F14E0048254D /* MGLStyleValue.mm */,
@@ -1069,6 +1061,7 @@
children = (
3575798F1D513EF1000B822E /* Layers */,
40CFA64E1D78754A008103BD /* Sources */,
+ 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */,
357F09091DF84F3800941873 /* MGLStyleValueTests.h */,
3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */,
DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */,
@@ -1128,6 +1121,7 @@
isa = PBXGroup;
children = (
409F43FC1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift */,
+ 409D0A0C1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift */,
);
name = "Swift Integration";
sourceTree = "<group>";
@@ -1348,17 +1342,9 @@
DA8848621CBAFCC100AB86E3 /* Kit Resources */ = {
isa = PBXGroup;
children = (
+ 960D0C351ECF5AAF008E151F /* Images.xcassets */,
DA89339F1CCC951200E68420 /* Localizable.strings */,
DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */,
- DA8848631CBAFCC100AB86E3 /* Compass.png */,
- DA8848641CBAFCC100AB86E3 /* Compass@2x.png */,
- DA8848651CBAFCC100AB86E3 /* Compass@3x.png */,
- DA8848661CBAFCC100AB86E3 /* default_marker.png */,
- DA8848671CBAFCC100AB86E3 /* default_marker@2x.png */,
- DA8848681CBAFCC100AB86E3 /* default_marker@3x.png */,
- DA8848691CBAFCC100AB86E3 /* mapbox.png */,
- DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */,
- DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */,
DA8933EF1CCD387900E68420 /* strip-frameworks.sh */,
40599F001DEE1B2400182B5D /* api_mapbox_staging.der */,
40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */,
@@ -1657,6 +1643,7 @@
DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */,
7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */,
400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */,
+ 1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */,
4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */,
40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */,
4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */,
@@ -1705,6 +1692,7 @@
353933F21D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */,
DA8847F31CBAFA5100AB86E3 /* MGLMultiPoint.h in Headers */,
30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */,
+ 1F7454961ECD450D00021D39 /* MGLLight_Private.h in Headers */,
DAD1656C1CF41981001FF4B9 /* MGLFeature.h in Headers */,
40EDA1C01CFE0E0200D9EA68 /* MGLAnnotationContainerView.h in Headers */,
9620BB381E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */,
@@ -1783,6 +1771,7 @@
35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
DABFB8671CBE99E500D62B32 /* MGLPolygon.h in Headers */,
404C26E81D89C55D000AA13D /* MGLTileSource_Private.h in Headers */,
+ 1F7454931ECBB43F00021D39 /* MGLLight.h in Headers */,
DAAF722C1DA903C700312FA4 /* MGLStyleValue.h in Headers */,
DABFB8651CBE99E500D62B32 /* MGLOverlay.h in Headers */,
35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */,
@@ -1816,6 +1805,7 @@
DA35A2BC1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */,
35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */,
DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */,
+ 1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */,
DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */,
DA737EE21D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */,
DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */,
@@ -2073,18 +2063,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */,
DA8933BC1CCD2CA100E68420 /* Foundation.strings in Resources */,
- DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */,
DA8933A31CCC95B000E68420 /* Localizable.strings in Resources */,
- DA88486D1CBAFCC100AB86E3 /* Compass.png in Resources */,
- DA8848721CBAFCC100AB86E3 /* default_marker@3x.png in Resources */,
- DA88486F1CBAFCC100AB86E3 /* Compass@3x.png in Resources */,
- DA88486E1CBAFCC100AB86E3 /* Compass@2x.png in Resources */,
- DA8848701CBAFCC100AB86E3 /* default_marker.png in Resources */,
- DA8848711CBAFCC100AB86E3 /* default_marker@2x.png in Resources */,
+ 960D0C361ECF5AAF008E151F /* Images.xcassets in Resources */,
DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */,
- DA8848751CBAFCC100AB86E3 /* mapbox@3x.png in Resources */,
DAC49C5C1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */,
408982E91DEE208200754016 /* api_mapbox_staging.der in Resources */,
@@ -2098,16 +2080,8 @@
buildActionMask = 2147483647;
files = (
DA8933E01CCD31DF00E68420 /* Localizable.strings in Resources */,
- DA8933E11CCD31DF00E68420 /* Compass.png in Resources */,
- DA8933E21CCD31DF00E68420 /* Compass@2x.png in Resources */,
- DA8933E31CCD31DF00E68420 /* Compass@3x.png in Resources */,
- DA8933E41CCD31DF00E68420 /* default_marker.png in Resources */,
- DA8933E51CCD31DF00E68420 /* default_marker@2x.png in Resources */,
- DA8933E61CCD31DF00E68420 /* default_marker@3x.png in Resources */,
- DA8933E71CCD31DF00E68420 /* mapbox.png in Resources */,
- DA8933E81CCD31DF00E68420 /* mapbox@2x.png in Resources */,
- DA8933E91CCD31DF00E68420 /* mapbox@3x.png in Resources */,
DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */,
+ 960D0C371ECF5AAF008E151F /* Images.xcassets in Resources */,
DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */,
DAC49C5D1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */,
@@ -2166,6 +2140,7 @@
DAE7DEC21E245455007505A6 /* MGLNSStringAdditionsTests.m in Sources */,
4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */,
DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */,
+ 1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */,
357579851D502AF5000B822E /* MGLSymbolStyleLayerTests.mm in Sources */,
357579871D502AFE000B822E /* MGLLineStyleLayerTests.mm in Sources */,
357579891D502B06000B822E /* MGLCircleStyleLayerTests.mm in Sources */,
@@ -2176,6 +2151,7 @@
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */,
DD58A4C61D822BD000E1F038 /* MGLExpressionTests.mm in Sources */,
3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.mm in Sources */,
+ 409D0A0D1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift in Sources */,
DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */,
55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */,
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */,
@@ -2221,6 +2197,7 @@
3566C76E1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */,
DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */,
35136D4E1D4277FC00C20EFD /* MGLSource.mm in Sources */,
+ 1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */,
DA35A2B81CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */,
35136D451D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */,
@@ -2328,6 +2305,7 @@
DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */,
DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */,
FA68F14E1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm in Sources */,
+ 1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */,
404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */,
355AE0021E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */,
@@ -2681,7 +2659,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -2705,7 +2686,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -2733,7 +2717,10 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = framework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -2767,7 +2754,10 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = framework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -2818,7 +2808,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
BITCODE_GENERATION_MODE = bitcode;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(sqlite_cflags)",
@@ -2844,7 +2837,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
BITCODE_GENERATION_MODE = bitcode;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(sqlite_cflags)",
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index e0ce29beba..31380faa2c 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -23,6 +23,7 @@ custom_categories:
- Working with Mapbox Studio
- Working with GeoJSON Data
- For Style Authors
+ - Tile URL Templates
- Info.plist Keys
- Gesture Recognizers
- name: Maps
@@ -59,6 +60,7 @@ custom_categories:
children:
- MGLStyle
- MGLStyleValue
+ - MGLLight
- name: Style Primitives
children:
- MGLFeature
diff --git a/platform/ios/originals/compass.sketch b/platform/ios/originals/compass.sketch
new file mode 100644
index 0000000000..f5b848cd96
--- /dev/null
+++ b/platform/ios/originals/compass.sketch
Binary files differ
diff --git a/platform/ios/resources/Compass.png b/platform/ios/resources/Compass.png
deleted file mode 100644
index 08bed0591b..0000000000
--- a/platform/ios/resources/Compass.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/Compass@2x.png b/platform/ios/resources/Compass@2x.png
deleted file mode 100644
index 8473a2d1ec..0000000000
--- a/platform/ios/resources/Compass@2x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/Compass@3x.png b/platform/ios/resources/Compass@3x.png
deleted file mode 100644
index 9cf66ca483..0000000000
--- a/platform/ios/resources/Compass@3x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/Images.xcassets/Compass.imageset/Contents.json b/platform/ios/resources/Images.xcassets/Compass.imageset/Contents.json
new file mode 100644
index 0000000000..6065a93b4e
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/Compass.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "compass.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/ios/resources/Images.xcassets/Compass.imageset/compass.pdf b/platform/ios/resources/Images.xcassets/Compass.imageset/compass.pdf
new file mode 100644
index 0000000000..2048f96089
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/Compass.imageset/compass.pdf
Binary files differ
diff --git a/platform/ios/resources/Images.xcassets/Contents.json b/platform/ios/resources/Images.xcassets/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/ios/resources/Images.xcassets/default_marker.imageset/Contents.json b/platform/ios/resources/Images.xcassets/default_marker.imageset/Contents.json
new file mode 100644
index 0000000000..9bef658a11
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/default_marker.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "default_marker.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/ios/resources/Images.xcassets/default_marker.imageset/default_marker.pdf b/platform/ios/resources/Images.xcassets/default_marker.imageset/default_marker.pdf
new file mode 100644
index 0000000000..4e2e332301
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/default_marker.imageset/default_marker.pdf
Binary files differ
diff --git a/platform/ios/resources/Images.xcassets/mapbox.imageset/Contents.json b/platform/ios/resources/Images.xcassets/mapbox.imageset/Contents.json
new file mode 100644
index 0000000000..b49c53da84
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/mapbox.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "mapbox.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/ios/resources/Images.xcassets/mapbox.imageset/mapbox.pdf b/platform/ios/resources/Images.xcassets/mapbox.imageset/mapbox.pdf
new file mode 100644
index 0000000000..45111c31a6
--- /dev/null
+++ b/platform/ios/resources/Images.xcassets/mapbox.imageset/mapbox.pdf
Binary files differ
diff --git a/platform/ios/resources/default_marker.png b/platform/ios/resources/default_marker.png
deleted file mode 100644
index b112096c18..0000000000
--- a/platform/ios/resources/default_marker.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/default_marker@2x.png b/platform/ios/resources/default_marker@2x.png
deleted file mode 100644
index d05c82bfe2..0000000000
--- a/platform/ios/resources/default_marker@2x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/default_marker@3x.png b/platform/ios/resources/default_marker@3x.png
deleted file mode 100644
index 703b172c15..0000000000
--- a/platform/ios/resources/default_marker@3x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/mapbox.png b/platform/ios/resources/mapbox.png
deleted file mode 100644
index 00bc897a58..0000000000
--- a/platform/ios/resources/mapbox.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/mapbox@2x.png b/platform/ios/resources/mapbox@2x.png
deleted file mode 100644
index 206ed5883e..0000000000
--- a/platform/ios/resources/mapbox@2x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/mapbox@3x.png b/platform/ios/resources/mapbox@3x.png
deleted file mode 100644
index efd631b587..0000000000
--- a/platform/ios/resources/mapbox@3x.png
+++ /dev/null
Binary files differ
diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m
index 22ee5c55f5..124d436197 100644
--- a/platform/ios/src/MGLAPIClient.m
+++ b/platform/ios/src/MGLAPIClient.m
@@ -117,7 +117,7 @@ static NSString * const MGLAPIClientHTTPMethodPost = @"POST";
- (void)loadCertificate:(NSData **)certificate withResource:(NSString *)resource {
NSBundle *frameworkBundle = [NSBundle mgl_frameworkBundle];
- NSString *cerPath = [frameworkBundle pathForResource:resource ofType:@"der" inDirectory:frameworkBundle.mgl_resourcesDirectory];
+ NSString *cerPath = [frameworkBundle pathForResource:resource ofType:@"der"];
if (cerPath != nil) {
*certificate = [NSData dataWithContentsOfFile:cerPath];
}
diff --git a/platform/ios/src/MGLAnnotationView.h b/platform/ios/src/MGLAnnotationView.h
index 184efdb324..2802d31b05 100644
--- a/platform/ios/src/MGLAnnotationView.h
+++ b/platform/ios/src/MGLAnnotationView.h
@@ -74,6 +74,36 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
- (instancetype)initWithReuseIdentifier:(nullable NSString *)reuseIdentifier;
/**
+ Initializes and returns a new annotation view object.
+
+ Providing an annotation allows you to explicitly associate the annotation instance
+ with the new view and, in custom subclasses of `MGLAnnotationView`, customize the view
+ based on properties of the annotation instance in an overridden initializer. However,
+ annotation views that are reused will not necessarily be associated with the
+ same annotation they were initialized with. Also, annotation views that are in
+ the reuse queue will have a nil value for the annotation property. Passing an annotation
+ instance to the view is optional and the map view will automatically associate annotations
+ with views when views are provided to the map via the `-[MGLMapViewDelegate mapView:viewForAnnotation:]`
+ method.
+
+ The reuse identifier provides a way for you to improve performance by recycling
+ annotation views as they enter and leave the map’s viewport. As an annotation
+ leaves the viewport, the map view moves its associated view to a reuse queue.
+ When a new annotation becomes visible, you can request a view for that
+ annotation by passing the appropriate reuse identifier string to the
+ `-[MGLMapView dequeueReusableAnnotationViewWithIdentifier:]` method.
+
+ @param annotation The annotation object to associate with the new view.
+ @param reuseIdentifier A unique string identifier for this view that allows you
+ to reuse this view with multiple similar annotations. You can set this
+ parameter to `nil` if you don’t intend to reuse the view, but it is a good
+ idea in general to specify a reuse identifier to avoid creating redundant
+ views.
+ @return The initialized annotation view object.
+ */
+- (instancetype)initWithAnnotation:(nullable id<MGLAnnotation>)annotation reuseIdentifier:(nullable NSString *)reuseIdentifier;
+
+/**
Called when the view is removed from the reuse queue.
The default implementation of this method does nothing. You can override it in
@@ -141,6 +171,19 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
*/
@property (nonatomic, assign) BOOL scalesWithViewingDistance;
+/**
+ A Boolean value that determines whether the annotation view rotates together
+ with the map.
+
+ When the value of this property is `YES` and the map is rotated, the annotation
+ view rotates. This is also the behavior of `MGLAnnotationImage` objects. When the
+ value of this property is `NO` the annotation has its rotation angle fixed.
+
+ The default value of this property is `NO`. Set this property to `YES` if the
+ view’s rotation is important.
+ */
+@property (nonatomic, assign) BOOL rotatesToMatchCamera;
+
#pragma mark Managing the Selection State
/**
diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm
index 5e0ae3b848..94d0649413 100644
--- a/platform/ios/src/MGLAnnotationView.mm
+++ b/platform/ios/src/MGLAnnotationView.mm
@@ -11,6 +11,7 @@
@property (nonatomic, readwrite, nullable) NSString *reuseIdentifier;
@property (nonatomic, readwrite) CATransform3D lastAppliedScaleTransform;
+@property (nonatomic, readwrite) CATransform3D lastAppliedRotateTransform;
@property (nonatomic, weak) UIPanGestureRecognizer *panGestureRecognizer;
@property (nonatomic, weak) UILongPressGestureRecognizer *longPressRecognizer;
@property (nonatomic, weak) MGLMapView *mapView;
@@ -19,21 +20,32 @@
@implementation MGLAnnotationView
-- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
-{
- self = [self initWithFrame:CGRectZero];
- if (self)
- {
- _lastAppliedScaleTransform = CATransform3DIdentity;
- _reuseIdentifier = [reuseIdentifier copy];
- _scalesWithViewingDistance = YES;
- _enabled = YES;
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {
+ self = [super initWithFrame:CGRectZero];
+ if (self) {
+ [self commonInitWithAnnotation:nil reuseIdentifier:reuseIdentifier];
}
return self;
}
-+ (BOOL)supportsSecureCoding {
- return YES;
+- (instancetype)initWithAnnotation:(nullable id<MGLAnnotation>)annotation reuseIdentifier:(nullable NSString *)reuseIdentifier {
+ self = [super initWithFrame:CGRectZero];
+ if (self) {
+ [self commonInitWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
+ }
+ return self;
+}
+
+- (void)commonInitWithAnnotation:(nullable id<MGLAnnotation>)annotation reuseIdentifier:(nullable NSString *)reuseIdentifier {
+ _lastAppliedScaleTransform = CATransform3DIdentity;
+ _annotation = annotation;
+ _reuseIdentifier = [reuseIdentifier copy];
+ _scalesWithViewingDistance = YES;
+ _enabled = YES;
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
@@ -42,6 +54,7 @@
_annotation = [decoder decodeObjectOfClass:[NSObject class] forKey:@"annotation"];
_centerOffset = [decoder decodeCGVectorForKey:@"centerOffset"];
_scalesWithViewingDistance = [decoder decodeBoolForKey:@"scalesWithViewingDistance"];
+ _rotatesToMatchCamera = [decoder decodeBoolForKey:@"rotatesToMatchCamera"];
_selected = [decoder decodeBoolForKey:@"selected"];
_enabled = [decoder decodeBoolForKey:@"enabled"];
self.draggable = [decoder decodeBoolForKey:@"draggable"];
@@ -55,6 +68,7 @@
[coder encodeObject:_annotation forKey:@"annotation"];
[coder encodeCGVector:_centerOffset forKey:@"centerOffset"];
[coder encodeBool:_scalesWithViewingDistance forKey:@"scalesWithViewingDistance"];
+ [coder encodeBool:_rotatesToMatchCamera forKey:@"rotatesToMatchCamera"];
[coder encodeBool:_selected forKey:@"selected"];
[coder encodeBool:_enabled forKey:@"enabled"];
[coder encodeBool:_draggable forKey:@"draggable"];
@@ -98,6 +112,7 @@
super.center = center;
[self updateScaleTransformForViewingDistance];
+ [self updateRotateTransform];
}
- (void)setScalesWithViewingDistance:(BOOL)scalesWithViewingDistance
@@ -146,6 +161,26 @@
}
}
+- (void)setRotatesToMatchCamera:(BOOL)rotatesToMatchCamera
+{
+ if (_rotatesToMatchCamera != rotatesToMatchCamera)
+ {
+ _rotatesToMatchCamera = rotatesToMatchCamera;
+ [self updateRotateTransform];
+ }
+}
+
+- (void)updateRotateTransform
+{
+ if (self.rotatesToMatchCamera == NO) return;
+
+ CGFloat directionRad = self.mapView.direction * M_PI / 180.0;
+ CATransform3D newRotateTransform = CATransform3DMakeRotation(-directionRad, 0, 0, 1);
+ self.layer.transform = CATransform3DConcat(CATransform3DIdentity, newRotateTransform);
+
+ _lastAppliedRotateTransform = newRotateTransform;
+}
+
#pragma mark - Draggable
- (void)setDraggable:(BOOL)draggable
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index d97c0b6602..9a9f71d5c3 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -64,7 +64,7 @@
#import "MGLCompactCalloutView.h"
#import "MGLAnnotationContainerView.h"
#import "MGLAnnotationContainerView_Private.h"
-#import "MGLAttributionInfo.h"
+#import "MGLAttributionInfo_Private.h"
#include <algorithm>
#include <cstdlib>
@@ -131,6 +131,9 @@ const CGFloat MGLAnnotationImagePaddingForCallout = 1;
const CGSize MGLAnnotationAccessibilityElementMinimumSize = CGSizeMake(10, 10);
+// Context for KVO observing UILayoutGuides.
+static void * MGLLayoutGuidesUpdatedContext = &MGLLayoutGuidesUpdatedContext;
+
/// Unique identifier representing a single annotation in mbgl.
typedef uint32_t MGLAnnotationTag;
@@ -233,13 +236,9 @@ public:
@property (nonatomic) GLKView *glView;
@property (nonatomic) UIImageView *glSnapshotView;
@property (nonatomic, readwrite) MGLScaleBar *scaleBar;
-@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *scaleBarConstraints;
@property (nonatomic, readwrite) UIImageView *compassView;
-@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *compassViewConstraints;
@property (nonatomic, readwrite) UIImageView *logoView;
-@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *logoViewConstraints;
@property (nonatomic, readwrite) UIButton *attributionButton;
-@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints;
@property (nonatomic, readwrite) MGLStyle *style;
@property (nonatomic) UITapGestureRecognizer *singleTapGestureRecognizer;
@property (nonatomic) UITapGestureRecognizer *doubleTap;
@@ -294,7 +293,8 @@ public:
NSDate *_userLocationAnimationCompletionDate;
/// True if a willChange notification has been issued for shape annotation layers and a didChange notification is pending.
BOOL _isChangingAnnotationLayers;
-
+ BOOL _isObservingTopLayoutGuide;
+ BOOL _isObservingBottomLayoutGuide;
BOOL _isWaitingForRedundantReachableNotification;
BOOL _isTargetingInterfaceBuilder;
@@ -467,13 +467,11 @@ public:
// setup logo bug
//
- UIImage *logo = [MGLMapView resourceImageNamed:@"mapbox.png"];
+ UIImage *logo = [MGLMapView resourceImageNamed:@"mapbox"];
_logoView = [[UIImageView alloc] initWithImage:logo];
_logoView.accessibilityTraits = UIAccessibilityTraitStaticText;
_logoView.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"LOGO_A11Y_LABEL", nil, nil, @"Mapbox", @"Accessibility label");
- _logoView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_logoView];
- _logoViewConstraints = [NSMutableArray array];
// setup attribution
//
@@ -481,9 +479,7 @@ public:
_attributionButton.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"INFO_A11Y_LABEL", nil, nil, @"About this map", @"Accessibility label");
_attributionButton.accessibilityHint = NSLocalizedStringWithDefaultValue(@"INFO_A11Y_HINT", nil, nil, @"Shows credits, a feedback form, and more", @"Accessibility hint");
[_attributionButton addTarget:self action:@selector(showAttribution) forControlEvents:UIControlEventTouchUpInside];
- _attributionButton.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_attributionButton];
- _attributionButtonConstraints = [NSMutableArray array];
[_attributionButton addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:NULL];
// setup compass
@@ -495,16 +491,12 @@ public:
_compassView.accessibilityTraits = UIAccessibilityTraitButton;
_compassView.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_LABEL", nil, nil, @"Compass", @"Accessibility label");
_compassView.accessibilityHint = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_HINT", nil, nil, @"Rotates the map to face due north", @"Accessibility hint");
- _compassView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_compassView];
- _compassViewConstraints = [NSMutableArray array];
// setup scale control
//
_scaleBar = [[MGLScaleBar alloc] init];
- _scaleBar.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_scaleBar];
- _scaleBarConstraints = [NSMutableArray array];
// setup interaction
//
@@ -624,11 +616,11 @@ public:
- (UIImage *)compassImage
{
- UIImage *scaleImage = [MGLMapView resourceImageNamed:@"Compass.png"];
+ UIImage *scaleImage = [MGLMapView resourceImageNamed:@"Compass"];
UIGraphicsBeginImageContextWithOptions(scaleImage.size, NO, [UIScreen mainScreen].scale);
[scaleImage drawInRect:{ CGPointZero, scaleImage.size }];
- CGFloat northSize = 9;
+ CGFloat northSize = 11;
UIFont *northFont;
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)])
{
@@ -643,7 +635,7 @@ public:
NSForegroundColorAttributeName: [UIColor whiteColor],
}];
CGRect stringRect = CGRectMake((scaleImage.size.width - north.size.width) / 2,
- scaleImage.size.height * 0.45,
+ scaleImage.size.height * 0.435,
north.size.width, north.size.height);
[north drawInRect:stringRect];
@@ -664,6 +656,48 @@ public:
_isWaitingForRedundantReachableNotification = NO;
}
+- (void)willMoveToWindow:(UIWindow *)newWindow
+{
+ [super willMoveToWindow:newWindow];
+
+ if (newWindow) {
+ [self addLayoutGuideObserversIfNeeded];
+ } else {
+ [self removeLayoutGuideObserversIfNeeded];
+ }
+}
+
+- (void)addLayoutGuideObserversIfNeeded
+{
+ UIViewController *viewController = self.viewControllerForLayoutGuides;
+ BOOL useLayoutGuides = viewController.view && viewController.automaticallyAdjustsScrollViewInsets;
+
+ if (useLayoutGuides && viewController.topLayoutGuide && !_isObservingTopLayoutGuide) {
+ [(NSObject *)viewController.topLayoutGuide addObserver:self forKeyPath:@"bounds" options:0 context:(void *)&MGLLayoutGuidesUpdatedContext];
+ _isObservingTopLayoutGuide = YES;
+ }
+
+ if (useLayoutGuides && viewController.bottomLayoutGuide && !_isObservingBottomLayoutGuide) {
+ [(NSObject *)viewController.bottomLayoutGuide addObserver:self forKeyPath:@"bounds" options:0 context:(void *)&MGLLayoutGuidesUpdatedContext];
+ _isObservingBottomLayoutGuide = YES;
+ }
+}
+
+- (void)removeLayoutGuideObserversIfNeeded
+{
+ UIViewController *viewController = self.viewControllerForLayoutGuides;
+
+ if (_isObservingTopLayoutGuide) {
+ [(NSObject *)viewController.topLayoutGuide removeObserver:self forKeyPath:@"bounds" context:(void *)&MGLLayoutGuidesUpdatedContext];
+ _isObservingTopLayoutGuide = NO;
+ }
+
+ if (_isObservingBottomLayoutGuide) {
+ [(NSObject *)viewController.bottomLayoutGuide removeObserver:self forKeyPath:@"bounds" context:(void *)&MGLLayoutGuidesUpdatedContext];
+ _isObservingBottomLayoutGuide = NO;
+ }
+}
+
- (void)dealloc
{
[_reachability stopNotifier];
@@ -672,6 +706,8 @@ public:
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_attributionButton removeObserver:self forKeyPath:@"hidden"];
+ [self removeLayoutGuideObserversIfNeeded];
+
// Removing the annotations unregisters any outstanding KVO observers.
NSArray *annotations = self.annotations;
if (annotations)
@@ -697,11 +733,6 @@ public:
{
[EAGLContext setCurrentContext:nil];
}
-
- [self.logoViewConstraints removeAllObjects];
- self.logoViewConstraints = nil;
- [self.attributionButtonConstraints removeAllObjects];
- self.attributionButtonConstraints = nil;
}
- (void)setDelegate:(nullable id<MGLMapViewDelegate>)delegate
@@ -786,105 +817,13 @@ public:
- (void)updateConstraints
{
- // scale control
- //
- [self removeConstraints:self.scaleBarConstraints];
- [self.scaleBarConstraints removeAllObjects];
-
- [self.scaleBarConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self.scaleBar
- attribute:NSLayoutAttributeTop
- relatedBy:NSLayoutRelationEqual
- toItem:self
- attribute:NSLayoutAttributeTop
- multiplier:1
- constant:5+self.contentInset.top]];
-
- [self.scaleBarConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self.scaleBar
- attribute:NSLayoutAttributeLeading
- relatedBy:NSLayoutRelationEqual
- toItem:self
- attribute:NSLayoutAttributeLeading
- multiplier:1
- constant:8 + self.contentInset.left]];
-
- [self addConstraints:self.scaleBarConstraints];
-
- // compass
- //
- [self removeConstraints:self.compassViewConstraints];
- [self.compassViewConstraints removeAllObjects];
-
- [self.compassViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self.compassView
- attribute:NSLayoutAttributeTop
- relatedBy:NSLayoutRelationEqual
- toItem:self
- attribute:NSLayoutAttributeTop
- multiplier:1
- constant:5 + self.contentInset.top]];
-
- [self.compassViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self
- attribute:NSLayoutAttributeTrailing
- relatedBy:NSLayoutRelationEqual
- toItem:self.compassView
- attribute:NSLayoutAttributeTrailing
- multiplier:1
- constant:5 + self.contentInset.right]];
-
- [self addConstraints:self.compassViewConstraints];
-
- // logo bug
- //
- [self removeConstraints:self.logoViewConstraints];
- [self.logoViewConstraints removeAllObjects];
-
- [self.logoViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self
- attribute:NSLayoutAttributeBottom
- relatedBy:NSLayoutRelationEqual
- toItem:self.logoView
- attribute:NSLayoutAttributeBaseline
- multiplier:1
- constant:8 + self.contentInset.bottom]];
-
- [self.logoViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self.logoView
- attribute:NSLayoutAttributeLeading
- relatedBy:NSLayoutRelationEqual
- toItem:self
- attribute:NSLayoutAttributeLeading
- multiplier:1
- constant:8 + self.contentInset.left]];
- [self addConstraints:self.logoViewConstraints];
-
- // attribution button
- //
- [self removeConstraints:self.attributionButtonConstraints];
- [self.attributionButtonConstraints removeAllObjects];
-
- [self.attributionButtonConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self
- attribute:NSLayoutAttributeBottom
- relatedBy:NSLayoutRelationEqual
- toItem:self.attributionButton
- attribute:NSLayoutAttributeBaseline
- multiplier:1
- constant:8 + self.contentInset.bottom]];
-
- [self.attributionButtonConstraints addObject:
- [NSLayoutConstraint constraintWithItem:self
- attribute:NSLayoutAttributeTrailing
- relatedBy:NSLayoutRelationEqual
- toItem:self.attributionButton
- attribute:NSLayoutAttributeTrailing
- multiplier:1
- constant:8 + self.contentInset.right]];
- [self addConstraints:self.attributionButtonConstraints];
-
[super updateConstraints];
+
+ // If we have a view controller reference and its automaticallyAdjustsScrollViewInsets
+ // is set to YES, -[MGLMapView adjustContentInset] takes top and bottom layout
+ // guides into account. To get notified about changes to the layout guides,
+ // we need to observe their bounds and re-layout accordingly.
+ [self addLayoutGuideObserversIfNeeded];
}
- (BOOL)isOpaque
@@ -917,6 +856,8 @@ public:
[super layoutSubviews];
[self adjustContentInset];
+
+ [self layoutOrnaments];
if (!_isTargetingInterfaceBuilder) {
_mbglMap->setSize([self size]);
@@ -931,6 +872,39 @@ public:
[self updateUserLocationAnnotationView];
}
+- (void)layoutOrnaments
+{
+ // scale bar
+ self.scaleBar.frame = {
+ self.contentInset.left+8,
+ self.contentInset.top+5,
+ CGRectGetWidth(self.scaleBar.frame),
+ CGRectGetHeight(self.scaleBar.frame)
+ };
+
+ // compass
+ self.compassView.center = {
+ .x = CGRectGetWidth(self.bounds)-CGRectGetMidX(self.compassView.bounds)-self.contentInset.right-5,
+ .y = CGRectGetMidY(self.compassView.bounds)+self.contentInset.top+5
+ };
+
+ // logo bug
+ self.logoView.frame = {
+ self.contentInset.left+8,
+ CGRectGetHeight(self.bounds)-8-self.contentInset.bottom-CGRectGetHeight(self.logoView.bounds),
+ CGRectGetWidth(self.logoView.bounds),
+ CGRectGetHeight(self.logoView.bounds)
+ };
+
+ // attribution
+ self.attributionButton.frame = {
+ CGRectGetWidth(self.bounds)-CGRectGetWidth(self.attributionButton.bounds)-self.contentInset.right-8,
+ CGRectGetHeight(self.bounds)-CGRectGetHeight(self.attributionButton.bounds)-self.contentInset.bottom-8,
+ CGRectGetWidth(self.attributionButton.bounds),
+ CGRectGetHeight(self.attributionButton.bounds)
+ };
+}
+
/// Updates `contentInset` to reflect the current window geometry.
- (void)adjustContentInset
{
@@ -1000,7 +974,7 @@ public:
}
// Compass, logo and attribution button constraints needs to be updated.
- [self setNeedsUpdateConstraints];
+ [self setNeedsLayout];
}
/// Returns the frame of inset content within the map view.
@@ -1921,8 +1895,12 @@ public:
{
if (info.feedbackLink)
{
- url = [info feedbackURLAtCenterCoordinate:self.centerCoordinate
- zoomLevel:self.zoomLevel];
+ MGLMapCamera *camera = self.camera;
+ url = [info feedbackURLForStyleURL:self.styleURL
+ atCenterCoordinate:camera.centerCoordinate
+ zoomLevel:self.zoomLevel
+ direction:camera.heading
+ pitch:camera.pitch];
}
[[UIApplication sharedApplication] openURL:url];
}
@@ -1999,9 +1977,10 @@ public:
}];
[alertController addAction:participateAction];
- [self.window.rootViewController presentViewController:alertController
- animated:YES
- completion:NULL];
+ UIViewController *viewController = [self.window.rootViewController mgl_topMostViewController];
+ [viewController presentViewController:alertController
+ animated:YES
+ completion:NULL];
}
#pragma mark - Properties -
@@ -2065,6 +2044,10 @@ public:
[self updateCalloutView];
}
}
+ else if (context == MGLLayoutGuidesUpdatedContext && [keyPath isEqualToString:@"bounds"])
+ {
+ [self setNeedsLayout];
+ }
}
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingZoomEnabled
@@ -3501,6 +3484,7 @@ public:
annotationView.annotation = nil;
[annotationView removeFromSuperview];
+ [self.annotationContainerView.annotationViews removeObject:annotationView];
if (annotationTag == _selectedAnnotationTag)
{
@@ -5314,18 +5298,17 @@ public:
+ (UIImage *)resourceImageNamed:(NSString *)imageName
{
- NSString *extension = imageName.pathExtension.length ? imageName.pathExtension : @"png";
- NSBundle *bundle = [NSBundle mgl_frameworkBundle];
- NSString *path = [bundle pathForResource:imageName.stringByDeletingPathExtension
- ofType:extension
- inDirectory:bundle.mgl_resourcesDirectory];
- if ( ! path)
+ UIImage *image = [UIImage imageNamed:imageName
+ inBundle:[NSBundle mgl_frameworkBundle]
+ compatibleWithTraitCollection:nil];
+
+ if ( ! image)
{
- [NSException raise:@"Resource not found" format:
+ [NSException raise:@"MGLResourceNotFoundException" format:
@"The resource named “%@” could not be found in the Mapbox framework bundle.", imageName];
}
- return [UIImage imageWithContentsOfFile:path];
+ return image;
}
- (BOOL)isFullyLoaded
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index 7b28ccf1a8..4f1413d300 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -317,13 +317,6 @@ const NSTimeInterval MGLFlushInterval = 180;
return;
}
- if ([self.eventQueue count] <= 1) {
- [self.eventQueue removeAllObjects];
- [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
- _backgroundTaskIdentifier = UIBackgroundTaskInvalid;
- return;
- }
-
NSArray *events = [NSArray arrayWithArray:self.eventQueue];
[self.eventQueue removeAllObjects];
diff --git a/platform/ios/src/MGLScaleBar.mm b/platform/ios/src/MGLScaleBar.mm
index 1216e400b3..cd88c1e08e 100644
--- a/platform/ios/src/MGLScaleBar.mm
+++ b/platform/ios/src/MGLScaleBar.mm
@@ -220,6 +220,12 @@ static const CGFloat MGLFeetPerMeter = 3.28084;
self.row = [self preferredRow];
+ CGSize size = self.intrinsicContentSize;
+ self.frame = CGRectMake(CGRectGetMinX(self.frame),
+ CGRectGetMinY(self.frame),
+ size.width,
+ size.height);
+
[self invalidateIntrinsicContentSize];
[self setNeedsLayout];
}
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 9a9dc702ca..67a26e8ed4 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -19,6 +19,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLDistanceFormatter.h"
#import "MGLFeature.h"
#import "MGLGeometry.h"
+#import "MGLLight.h"
#import "MGLMapCamera.h"
#import "MGLMapView.h"
#import "MGLMapView+IBAdditions.h"
diff --git a/platform/ios/test/MGLAnnotationViewIntegrationTests.swift b/platform/ios/test/MGLAnnotationViewIntegrationTests.swift
new file mode 100644
index 0000000000..82a57a4009
--- /dev/null
+++ b/platform/ios/test/MGLAnnotationViewIntegrationTests.swift
@@ -0,0 +1,23 @@
+import XCTest
+import Mapbox
+
+class CustomAnnotationView: MGLAnnotationView {
+
+ override init(reuseIdentifier: String?) {
+ super.init(reuseIdentifier: reuseIdentifier)
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ }
+
+}
+
+class MGLAnnotationViewIntegrationTests: XCTestCase {
+
+ func testCreatingCustomAnnotationView() {
+ let customAnnotationView = CustomAnnotationView(reuseIdentifier: "resuse-id")
+ XCTAssertNotNil(customAnnotationView)
+ }
+
+}
diff --git a/platform/ios/test/MGLAnnotationViewTests.m b/platform/ios/test/MGLAnnotationViewTests.m
index c0978eaf65..fc4f35a9e1 100644
--- a/platform/ios/test/MGLAnnotationViewTests.m
+++ b/platform/ios/test/MGLAnnotationViewTests.m
@@ -3,11 +3,24 @@
static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer";
+@interface MGLCustomAnnotationView : MGLAnnotationView
+
+@end
+
+@implementation MGLCustomAnnotationView
+
+- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {
+ return [super initWithReuseIdentifier:@"reuse-id"];
+}
+
+@end
+
@interface MGLAnnotationView (Test)
+
@property (nonatomic) MGLMapView *mapView;
@property (nonatomic, readwrite) MGLAnnotationViewDragState dragState;
-
- (void)setDragState:(MGLAnnotationViewDragState)dragState;
+
@end
@interface MGLMapView (Test)
@@ -79,13 +92,19 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
XCTAssertNil(_annotationView.annotation, @"annotation property should be nil");
}
+- (void)testCustomAnnotationView
+{
+ MGLCustomAnnotationView *customAnnotationView = [[MGLCustomAnnotationView alloc] initWithReuseIdentifier:@"reuse-id"];
+ XCTAssertNotNil(customAnnotationView);
+}
+
- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAnnotation>)annotation
{
MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:MGLTestAnnotationReuseIdentifer];
if (!annotationView)
{
- annotationView = [[MGLAnnotationView alloc] initWithReuseIdentifier:MGLTestAnnotationReuseIdentifer];
+ annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MGLTestAnnotationReuseIdentifer];
}
_annotationView = annotationView;
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 579624f0e6..4301566258 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,6 +1,11 @@
# Changelog for Mapbox macOS SDK
-## master
+## 3.6.0
+
+### Packaging
+
+* Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775))
+* Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773))
* The previously-deprecated support for style classes has been removed. For interface compatibility, the API methods remain, but they are now non-functional.
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617))
@@ -14,17 +19,21 @@
* Added class methods to MGLStyle that correspond to the new [Traffic Day and Traffic Night](https://www.mapbox.com/blog/live-traffic-maps/) styles. ([#6301](https://github.com/mapbox/mapbox-gl-native/pull/6301))
* MGLSymbolStyleLayer’s `iconImageName`, `iconScale`, `textFontSize`, `textOffset`, and `textRotation` properties can now be set to a source or composite function. ([#8544](https://github.com/mapbox/mapbox-gl-native/pull/8544), [#8590](https://github.com/mapbox/mapbox-gl-native/pull/8590), [#8592](https://github.com/mapbox/mapbox-gl-native/pull/8592), [#8593](https://github.com/mapbox/mapbox-gl-native/pull/8593))
* Fixed an issue where setting the `MGLVectorStyleLayer.predicate` property failed to take effect if the relevant source was not in use by a visible layer at the time. ([#8653](https://github.com/mapbox/mapbox-gl-native/pull/8653))
+* Fixed an issue preventing programmatically added style layers from appearing in already cached tiles. ([#8954](https://github.com/mapbox/mapbox-gl-native/pull/8954))
* Fixed an issue causing a composite function’s highest zoom level stop to be misinterpreted. ([#8613](https://github.com/mapbox/mapbox-gl-native/pull/8613), [#8790](https://github.com/mapbox/mapbox-gl-native/pull/8790))
* Fixed an issue where re-adding a layer that had been previously removed from a style would reset its paint properties. Moved initializers for `MGLTileSource`, `MGLStyleLayer`, and `MGLForegroundStyleLayer` to their concrete subclasses; because these classes were already intended for initialization only via concrete subclasses, this should have no developer impact. ([#8626](https://github.com/mapbox/mapbox-gl-native/pull/8626))
* Feature querying results now account for any changes to a feature’s size caused by a source or composite style function. ([#8665](https://github.com/mapbox/mapbox-gl-native/pull/8665))
+* Letter spacing is now disabled in Arabic text so that ligatures are drawn correctly. ([#9062](https://github.com/mapbox/mapbox-gl-native/pull/9062))
### Other changes
-* Xcode 8.0 or higher is now recommended for using this SDK. ([#8775](https://github.com/mapbox/mapbox-gl-native/pull/8775))
-* Updated MGLMapView’s logo view to display [the new Mapbox logo](https://www.mapbox.com/blog/new-mapbox-logo/). ([#8771](https://github.com/mapbox/mapbox-gl-native/pull/8771), [#8773](https://github.com/mapbox/mapbox-gl-native/pull/8773))
+* Fixed a crash when calling `MGLMultiPolygon.coordinate` [#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713)
* Fixed an issue causing attribution button text to appear blue instead of black. ([#8701](https://github.com/mapbox/mapbox-gl-native/pull/8701))
* Fixed a crash or console spew when MGLMapView is initialized with a frame smaller than 64 points wide by 64 points tall. ([#8562](https://github.com/mapbox/mapbox-gl-native/pull/8562))
+* The Improve This Map button in the attribution action sheet now leads to a feedback tool that matches MGLMapView’s rotation and pitch. `-[MGLAttributionInfo feedbackURLAtCenterCoordinate:zoomLevel:]` no longer respects the feedback URL specified in TileJSON. ([#9078](https://github.com/mapbox/mapbox-gl-native/pull/9078))
* The error passed into `-[MGLMapViewDelegate mapViewDidFailLoadingMap:withError:]` now includes a more specific description and failure reason. ([#8418](https://github.com/mapbox/mapbox-gl-native/pull/8418))
+* The `MGLPolyline.coordinate` and `MGLPolygon.coordinate` properties now return the midpoint and centroid, respectively, instead of the first coordinate. ([#8713](https://github.com/mapbox/mapbox-gl-native/pull/8713))
+* Improved CPU and battery performance while animating a tilted map’s camera in an area with many labels. ([#9031](https://github.com/mapbox/mapbox-gl-native/pull/9031))
* Fixed an issue rendering polylines that contain duplicate vertices. ([#8808](https://github.com/mapbox/mapbox-gl-native/pull/8808))
## 0.4.1 - April 8, 2017
diff --git a/platform/macos/app/MGLVectorSource+MBXAdditions.h b/platform/macos/app/MGLVectorSource+MBXAdditions.h
index 312081ec51..1e25ee5a60 100644
--- a/platform/macos/app/MGLVectorSource+MBXAdditions.h
+++ b/platform/macos/app/MGLVectorSource+MBXAdditions.h
@@ -4,7 +4,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLVectorSource (MBXAdditions)
-+ (nullable NSString *)preferredMapboxStreetsLanguage;
++ (NSString *)preferredMapboxStreetsLanguage;
- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage;
diff --git a/platform/macos/app/MGLVectorSource+MBXAdditions.m b/platform/macos/app/MGLVectorSource+MBXAdditions.m
index 644b43a651..323bc74366 100644
--- a/platform/macos/app/MGLVectorSource+MBXAdditions.m
+++ b/platform/macos/app/MGLVectorSource+MBXAdditions.m
@@ -7,19 +7,23 @@
static dispatch_once_t onceToken;
static NS_SET_OF(NSString *) *mapboxStreetsLanguages;
dispatch_once(&onceToken, ^{
- mapboxStreetsLanguages = [NSSet setWithObjects:@"en", @"es", @"fr", @"de", @"ru", @"zh", nil];
+ // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
+ mapboxStreetsLanguages = [NSSet setWithObjects:@"ar", @"de", @"en", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans", nil];
});
return mapboxStreetsLanguages;
}
-+ (nullable NSString *)preferredMapboxStreetsLanguage {
- for (NSString *language in [NSLocale preferredLanguages]) {
- NSString *languageCode = [[NSLocale localeWithLocaleIdentifier:language] objectForKey:NSLocaleLanguageCode];
- if ([[MGLVectorSource mapboxStreetsLanguages] containsObject:languageCode]) {
- return languageCode;
++ (NSString *)preferredMapboxStreetsLanguage {
+ NSArray<NSString *> *supportedLanguages = [MGLVectorSource mapboxStreetsLanguages].allObjects;
+ NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:supportedLanguages
+ forPreferences:[NSLocale preferredLanguages]];
+ NSString *mostSpecificLanguage;
+ for (NSString *language in preferredLanguages) {
+ if (language.length > mostSpecificLanguage.length) {
+ mostSpecificLanguage = language;
}
}
- return nil;
+ return mostSpecificLanguage ?: @"en";
}
- (BOOL)isMapboxStreets {
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 59c1817f63..59844d363e 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -345,7 +345,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
- (void)updateLabels {
MGLStyle *style = self.mapView.style;
- NSString *preferredLanguage = _isLocalizingLabels ? ([MGLVectorSource preferredMapboxStreetsLanguage] ?: @"en") : nil;
+ NSString *preferredLanguage = _isLocalizingLabels ? [MGLVectorSource preferredMapboxStreetsLanguage] : nil;
NSMutableDictionary *localizedKeysByKeyBySourceIdentifier = [NSMutableDictionary dictionary];
for (MGLSymbolStyleLayer *layer in style.layers) {
if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
@@ -807,6 +807,9 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
case 7:
state = [styleURL isEqual:[MGLStyle trafficDayStyleURL]];
break;
+ case 8:
+ state = [styleURL isEqual:[MGLStyle trafficNightStyleURL]];
+ break;
default:
return NO;
}
@@ -855,8 +858,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.tag) {
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:[NSBundle mainBundle].developmentLocalization];
NSString *preferredLanguage = [MGLVectorSource preferredMapboxStreetsLanguage];
- menuItem.enabled = !!preferredLanguage;
- menuItem.title = [locale displayNameForKey:NSLocaleIdentifier value:preferredLanguage ?: @"Preferred Language"];
+ menuItem.title = [locale displayNameForKey:NSLocaleIdentifier value:preferredLanguage];
}
return YES;
}
diff --git a/platform/macos/docs/guides/Tile URL Templates.md b/platform/macos/docs/guides/Tile URL Templates.md
new file mode 100644
index 0000000000..01672c6686
--- /dev/null
+++ b/platform/macos/docs/guides/Tile URL Templates.md
@@ -0,0 +1,98 @@
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+# Tile URL Templates
+
+`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
+objects, can be created using an initializer that accepts an array of tile URL
+templates. Tile URL templates are strings that specify the URLs of the vector
+tiles or raster tile images to load. A template resembles an absolute URL, but
+with any number of placeholder strings that the source evaluates based on the
+tile it needs to load. For example:
+
+* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
+ evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
+* `http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png` could be
+ evaluated as `http://www.example.com/tiles/14/6/9@2x.png`.
+
+Tile URL templates are also used to define tilesets in TileJSON manifests or
+[`raster`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-raster-tiles)
+and
+[`vector`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-vector-tiles)
+sources in style JSON files. See the
+[TileJSON specification](https://github.com/mapbox/tilejson-spec/tree/master/2.2.0)
+for information about tile URL templates in the context of a TileJSON or style
+JSON file.
+
+Tile sources support the following placeholder strings in tile URL templates,
+all of which are optional:
+
+<table>
+<thead>
+<tr><th>Placeholder string</th><th>Description</th></tr>
+</thead>
+<tbody>
+<tr>
+ <td><code>{x}</code></td>
+ <td>The index of the tile along the map’s x axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s left edge corresponds
+ to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
+ the tile’s right edge corresponds to the 180th meridian east.</td>
+</tr>
+<tr>
+ <td><code>{y}</code></td>
+ <td>The index of the tile along the map’s y axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s tile edge corresponds
+ to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
+ is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
+ −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
+ inverted if the <code>options</code> parameter contains
+ <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
+ <code>MGLTileCoordinateSystemTMS</code>.</td>
+</tr>
+<tr>
+ <td><code>{z}</code></td>
+ <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
+ world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
+ <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
+ a <code>MGLRasterSource</code> object, whether the tile zoom level
+ matches the map’s current zoom level depends on the value of the
+ source’s tile size as specified in the
+ <code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
+ parameter.</td>
+</tr>
+<tr>
+ <td><code>{bbox-epsg-3857}</code></td>
+ <td>The tile’s bounding box, expressed as a comma-separated list of the
+ tile’s western, southern, eastern, and northern extents according to
+ Spherical Mercator (EPSG:3857) projection. The bounding box is typically
+ used with map services conforming to the
+ <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
+ protocol.</td>
+</tr>
+<tr>
+ <td><code>{quadkey}</code></td>
+ <td>A quadkey indicating both the tile’s location and its zoom level. The
+ quadkey is typically used with
+ <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
+ </td>
+</tr>
+<tr>
+ <td><code>{ratio}</code></td>
+ <td>A suffix indicating the resolution of the tile image. The suffix is the
+ empty string for standard resolution displays and <code>@2x</code> for
+ Retina displays.
+ </td>
+</tr>
+<tr>
+ <td><code>{prefix}</code></td>
+ <td>Two hexadecimal digits chosen such that each visible tile has a
+ different prefix. The prefix is typically used for domain sharding.</td>
+</tr>
+</tbody>
+</table>
+
+For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
+consult the
+[OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).
diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml
index 3c24b351cc..fcd4bfd301 100644
--- a/platform/macos/jazzy.yml
+++ b/platform/macos/jazzy.yml
@@ -20,6 +20,7 @@ custom_categories:
- Working with GeoJSON Data
- For Style Authors
- Using Style Functions at Runtime
+ - Tile URL Templates
- Info.plist Keys
- name: Maps
children:
@@ -45,6 +46,7 @@ custom_categories:
children:
- MGLStyle
- MGLStyleValue
+ - MGLLight
- name: Content Primitives
children:
- MGLFeature
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 9a18ce4a0e..564d81afb2 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -8,6 +8,10 @@
/* Begin PBXBuildFile section */
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; };
+ 1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; };
+ 1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A21ECFB00300021D39 /* MGLLight.mm */; };
+ 1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */; };
1F95931B1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */; };
30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */; };
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */; };
@@ -268,6 +272,10 @@
/* Begin PBXFileReference section */
1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
+ 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
+ 1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
+ 1F7454A21ECFB00300021D39 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
+ 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLightTest.mm; sourceTree = "<group>"; };
1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSImage+MGLAdditions.h"; path = "src/NSImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; };
3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = "<group>"; };
@@ -670,6 +678,9 @@
352742771D4C220900A1ECE6 /* MGLStyleValue.h */,
DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */,
3527429E1D4C25BD00A1ECE6 /* MGLStyleValue.mm */,
+ 1F7454A11ECFB00300021D39 /* MGLLight.h */,
+ 1F7454A21ECFB00300021D39 /* MGLLight.mm */,
+ 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */,
);
name = Styling;
sourceTree = "<group>";
@@ -810,6 +821,7 @@
children = (
DA8F257C1D51C5F40010E6B5 /* Layers */,
DA87A99A1DC9D88800810D09 /* Sources */,
+ 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */,
353722EB1DF850ED004D2F3F /* MGLStyleValueTests.h */,
3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */,
DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */,
@@ -1133,6 +1145,7 @@
DA8F258B1D51CA540010E6B5 /* MGLLineStyleLayer.h in Headers */,
35C6DF841E214C0400ACA483 /* MGLDistanceFormatter.h in Headers */,
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
+ 1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */,
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */,
DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */,
408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */,
@@ -1166,6 +1179,7 @@
DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */,
DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */,
352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */,
+ 1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */,
408AA8671DAEEE3900022900 /* NSDictionary+MGLAdditions.h in Headers */,
DAE6C3671CC31E0400DB3429 /* MGLStyle.h in Headers */,
);
@@ -1380,6 +1394,7 @@
DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */,
35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */,
DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */,
+ 1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */,
DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */,
3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */,
DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */,
@@ -1446,6 +1461,7 @@
DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */,
DAE6C3D41CC34C9900DB3429 /* MGLOfflineRegionTests.m in Sources */,
DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */,
+ 1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */,
DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */,
920A3E591E6F859D00C16EFC /* MGLSourceQueryTests.m in Sources */,
DA35A2B61CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
@@ -1763,7 +1779,10 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
@@ -1797,7 +1816,10 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = "$(SRCROOT)/sdk/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
@@ -1821,7 +1843,10 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
LIBRARY_SEARCH_PATHS = (
@@ -1850,7 +1875,10 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(polylabel_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
OTHER_CFLAGS = "-fvisibility=hidden";
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 98958f045d..c7f6e59c80 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -1,17 +1,18 @@
#import "MGLMapView_Private.h"
-#import "MGLAnnotationImage_Private.h"
+
#import "MGLAttributionButton.h"
-#import "MGLAttributionInfo.h"
#import "MGLCompassCell.h"
#import "MGLOpenGLLayer.h"
#import "MGLStyle.h"
+#import "MGLAnnotationImage_Private.h"
+#import "MGLAttributionInfo_Private.h"
#import "MGLFeature_Private.h"
+#import "MGLFoundation_Private.h"
#import "MGLGeometry_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
#import "MGLStyle_Private.h"
-#import "MGLFoundation_Private.h"
#import "MGLAccountManager.h"
#import "MGLMapCamera.h"
@@ -1735,11 +1736,15 @@ public:
}
- (IBAction)giveFeedback:(id)sender {
- CLLocationCoordinate2D centerCoordinate = self.centerCoordinate;
+ MGLMapCamera *camera = self.camera;
double zoomLevel = self.zoomLevel;
NSMutableArray *urls = [NSMutableArray array];
for (MGLAttributionInfo *info in [self.style attributionInfosWithFontSize:0 linkColor:nil]) {
- NSURL *url = [info feedbackURLAtCenterCoordinate:centerCoordinate zoomLevel:zoomLevel];
+ NSURL *url = [info feedbackURLForStyleURL:self.styleURL
+ atCenterCoordinate:camera.centerCoordinate
+ zoomLevel:zoomLevel
+ direction:camera.heading
+ pitch:camera.pitch];
if (url) {
[urls addObject:url];
}
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index dcb5b50b8f..0f47dace70 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -17,6 +17,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLDistanceFormatter.h"
#import "MGLFeature.h"
#import "MGLGeometry.h"
+#import "MGLLight.h"
#import "MGLMapCamera.h"
#import "MGLMapView.h"
#import "MGLMapView+IBAdditions.h"
diff --git a/scripts/config.xcconfig.in b/scripts/config.xcconfig.in
index eb6bc71b89..b70ff9d677 100644
--- a/scripts/config.xcconfig.in
+++ b/scripts/config.xcconfig.in
@@ -3,3 +3,4 @@
// mbgl-core
mbgl_core_INCLUDE_DIRECTORIES = "@mbgl_core_INCLUDE_DIRECTORIES@"
mbgl_core_LINK_LIBRARIES = "@mbgl_core_LINK_LIBRARIES@"
+polylabel_INCLUDE_DIRECTORIES = "@MASON_PACKAGE_polylabel_INCLUDE_DIRS@"