From ce4dcb7a9b762afab5fb3f2a99dbb5f28f269f2e Mon Sep 17 00:00:00 2001 From: Adrian Cojocaru Date: Thu, 27 Feb 2025 13:42:13 +0200 Subject: [PATCH] Add iOS/macOS observer hooks (#3245) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers --- platform/darwin/bazel/files.bzl | 1 + platform/darwin/src/MLNTileOperation.h | 13 ++ platform/ios/MapLibre.docc/MapLibre.md | 1 + platform/ios/MapLibre.docc/ObserverExample.md | 113 +++++++++++++ .../Sources/MapLibreNavigationView.swift | 3 + .../app-swift/Sources/ObserverExample.swift | 112 +++++++++++++ platform/ios/app/MBXViewController.mm | 91 +++++++++++ platform/ios/sdk-files.json | 1 + platform/ios/src/MLNMapView+Impl.h | 15 ++ platform/ios/src/MLNMapView+Impl.mm | 86 ++++++++++ platform/ios/src/MLNMapView.mm | 106 ++++++++++++ platform/ios/src/MLNMapViewDelegate.h | 152 ++++++++++++++++++ platform/ios/src/MLNMapView_Private.h | 24 +++ .../MLNMapViewDelegateIntegrationTests.swift | 20 +++ platform/macos/sdk-files.json | 1 + platform/macos/src/MLNMapView+Impl.h | 15 ++ platform/macos/src/MLNMapView+Impl.mm | 86 ++++++++++ platform/macos/src/MLNMapView.mm | 107 ++++++++++++ platform/macos/src/MLNMapViewDelegate.h | 45 ++++++ platform/macos/src/MLNMapView_Private.h | 24 +++ 20 files changed, 1016 insertions(+) create mode 100644 platform/darwin/src/MLNTileOperation.h create mode 100644 platform/ios/MapLibre.docc/ObserverExample.md create mode 100644 platform/ios/app-swift/Sources/ObserverExample.swift diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index fb76746c4..facd90f72 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -93,6 +93,7 @@ MLN_DARWIN_OBJC_HEADERS = [ "src/MLNStyle.h", "src/MLNStyleLayer.h", "src/MLNStyleValue.h", + "src/MLNTileOperation.h", "src/MLNTilePyramidOfflineRegion.h", "src/MLNTileServerOptions.h", "src/MLNTileSource.h", diff --git a/platform/darwin/src/MLNTileOperation.h b/platform/darwin/src/MLNTileOperation.h new file mode 100644 index 000000000..f155f1e12 --- /dev/null +++ b/platform/darwin/src/MLNTileOperation.h @@ -0,0 +1,13 @@ +#import + +typedef NS_ENUM(NSInteger, MLNTileOperation) { + MLNTileOperationRequestedFromCache, ///< A read request from the cache + MLNTileOperationRequestedFromNetwork, ///< A read request from the online source + MLNTileOperationLoadFromNetwork, ///< Tile data from the network has been retrieved + MLNTileOperationLoadFromCache, ///< Tile data from the cache has been retrieved + MLNTileOperationStartParse, ///< Background processing of tile data has been initiated + MLNTileOperationEndParse, ///< Background processing of tile data has been completed + MLNTileOperationError, ///< An error occurred while loading the tile + MLNTileOperationCancelled, ///< Loading of a tile was cancelled + MLNTileOperationNullOp, ///< No operation has taken place +}; diff --git a/platform/ios/MapLibre.docc/MapLibre.md b/platform/ios/MapLibre.docc/MapLibre.md index 72a119db1..051fc8dff 100644 --- a/platform/ios/MapLibre.docc/MapLibre.md +++ b/platform/ios/MapLibre.docc/MapLibre.md @@ -51,6 +51,7 @@ Powerful, free and open-source mapping toolkit with full control over data sourc ### Advanced +- - ### Other Articles diff --git a/platform/ios/MapLibre.docc/ObserverExample.md b/platform/ios/MapLibre.docc/ObserverExample.md new file mode 100644 index 000000000..0df88adf3 --- /dev/null +++ b/platform/ios/MapLibre.docc/ObserverExample.md @@ -0,0 +1,113 @@ +# Observe Low-Level Events + +Learn about the ``MLNMapViewDelegate`` methods for observing map events. + +> Warning: These methods are not thread-safe. + +You can observe certain low-level events as they happen. Use these methods to collect metrics or investigate issues during map rendering. This feature is intended primarily for power users. We are always interested in improving observability, so if you have a special use case, feel free to [open an issue or pull request](https://github.com/maplibre/maplibre-native) to extend the types of observability methods. + +## Shader Events + +Observe shader compilation with ``MLNMapViewDelegate/mapView:shaderWillCompile:backend:defines:`` and ``MLNMapViewDelegate/mapView:shaderDidCompile:backend:defines:``. + + + +```swift +func mapView(_: MLNMapView, shaderWillCompile id: Int, backend: Int, defines: String) { + print("A new shader is being compiled - shaderID:\(id), backend type:\(backend), program configuration:\(defines)") + } + + func mapView(_: MLNMapView, shaderDidCompile id: Int, backend: Int, defines: String) { + print("A shader has been compiled - shaderID:\(id), backend type:\(backend), program configuration:\(defines)") + } +``` + +See also: ``MLNMapViewDelegate/mapView:shaderDidFailCompile:backend:defines:``. + +## Glyph Loading + +Observe glyph loading events with ``MLNMapViewDelegate/mapView:glyphsWillLoad:range:`` and ``MLNMapViewDelegate/mapView:glyphsDidLoad:range:``. + + + +```swift +func mapView(_: MLNMapView, glyphsWillLoad fontStack: [String], range: NSRange) { + print("Glyphs are being requested for the font stack \(fontStack), ranging from \(range.location) to \(range.location + range.length)") + } + + func mapView(_: MLNMapView, glyphsDidLoad fontStack: [String], range: NSRange) { + print("Glyphs have been loaded for the font stack \(fontStack), ranging from \(range.location) to \(range.location + range.length)") + } +``` + +See also: ``MLNMapViewDelegate/mapView:glyphsDidError:range:``. + +## Tile Events + +Monitor tile-related actions using the delegate method ``MLNMapViewDelegate/mapView:tileDidTriggerAction:x:y:z:wrap:overscaledZ:sourceID:`` with the ``MLNTileOperation`` type. + + + +```swift +func mapView(_: MLNMapView, tileDidTriggerAction operation: MLNTileOperation, + x: Int, + y: Int, + z: Int, + wrap: Int, + overscaledZ: Int, + sourceID: String) + { + let tileStr = String(format: "(x: %ld, y: %ld, z: %ld, wrap: %ld, overscaledZ: %ld, sourceID: %@)", + x, y, z, wrap, overscaledZ, sourceID) + + switch operation { + case MLNTileOperation.requestedFromCache: + print("Requesting tile \(tileStr) from cache") + + case MLNTileOperation.requestedFromNetwork: + print("Requesting tile \(tileStr) from network") + + case MLNTileOperation.loadFromCache: + print("Loading tile \(tileStr), requested from the cache") + + case MLNTileOperation.loadFromNetwork: + print("Loading tile \(tileStr), requested from the network") + + case MLNTileOperation.startParse: + print("Parsing tile \(tileStr)") + + case MLNTileOperation.endParse: + print("Completed parsing tile \(tileStr)") + + case MLNTileOperation.error: + print("An error occured during proccessing for tile \(tileStr)") + + case MLNTileOperation.cancelled: + print("Pending work on tile \(tileStr)") + + case MLNTileOperation.nullOp: + print("An unknown tile operation was emitted for tile \(tileStr)") + + @unknown default: + assertionFailure() + } + } +``` + +## Sprite Loading + +Observe sprite loading events with ``MLNMapViewDelegate/mapView:spriteWillLoad:url:`` and ``MLNMapViewDelegate/mapView:spriteDidLoad:url:``. + + + +```swift +func mapView(_: MLNMapView, spriteWillLoad id: String, url: String) { + print("The sprite \(id) has been requested from \(url)") + } + + func mapView(_: MLNMapView, spriteDidLoad id: String, url: String) { + print("The sprite \(id) has been loaded from \(url)") + } +``` + +See also: ``MLNMapViewDelegate/mapView:spriteDidError:url:``. diff --git a/platform/ios/app-swift/Sources/MapLibreNavigationView.swift b/platform/ios/app-swift/Sources/MapLibreNavigationView.swift index e08aa876e..a815f6a2c 100644 --- a/platform/ios/app-swift/Sources/MapLibreNavigationView.swift +++ b/platform/ios/app-swift/Sources/MapLibreNavigationView.swift @@ -34,6 +34,9 @@ struct MapLibreNavigationView: View { NavigationLink("AddMarkerExample") { AddMarkerSymbolExampleUIViewControllerRepresentable() } + NavigationLink("ObserverExample") { + ObserverExampleViewExampleUIViewControllerRepresentable() + } Group { NavigationLink("AnimatedLineExample") { AnimatedLineExampleUIViewControllerRepresentable() diff --git a/platform/ios/app-swift/Sources/ObserverExample.swift b/platform/ios/app-swift/Sources/ObserverExample.swift new file mode 100644 index 000000000..74938ac0e --- /dev/null +++ b/platform/ios/app-swift/Sources/ObserverExample.swift @@ -0,0 +1,112 @@ +import MapLibre +import SwiftUI +import UIKit + +class ObserverExampleView: UIViewController, MLNMapViewDelegate { + var mapView: MLNMapView! + + override func viewDidLoad() { + super.viewDidLoad() + + mapView = MLNMapView(frame: view.bounds, styleURL: AMERICANA_STYLE) + mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + mapView.setCenter( + CLLocationCoordinate2D(latitude: 45.5076, longitude: -122.6736), + zoomLevel: 11, + animated: false + ) + view.addSubview(mapView) + + mapView.delegate = self + } + + // #-example-code(ObserverExampleShaders) + func mapView(_: MLNMapView, shaderWillCompile id: Int, backend: Int, defines: String) { + print("A new shader is being compiled - shaderID:\(id), backend type:\(backend), program configuration:\(defines)") + } + + func mapView(_: MLNMapView, shaderDidCompile id: Int, backend: Int, defines: String) { + print("A shader has been compiled - shaderID:\(id), backend type:\(backend), program configuration:\(defines)") + } + + // #-end-example-code + + // #-example-code(ObserverExampleGlyphs) + func mapView(_: MLNMapView, glyphsWillLoad fontStack: [String], range: NSRange) { + print("Glyphs are being requested for the font stack \(fontStack), ranging from \(range.location) to \(range.location + range.length)") + } + + func mapView(_: MLNMapView, glyphsDidLoad fontStack: [String], range: NSRange) { + print("Glyphs have been loaded for the font stack \(fontStack), ranging from \(range.location) to \(range.location + range.length)") + } + + // #-end-example-code + + // #-example-code(ObserverExampleTiles) + func mapView(_: MLNMapView, tileDidTriggerAction operation: MLNTileOperation, + x: Int, + y: Int, + z: Int, + wrap: Int, + overscaledZ: Int, + sourceID: String) + { + let tileStr = String(format: "(x: %ld, y: %ld, z: %ld, wrap: %ld, overscaledZ: %ld, sourceID: %@)", + x, y, z, wrap, overscaledZ, sourceID) + + switch operation { + case MLNTileOperation.requestedFromCache: + print("Requesting tile \(tileStr) from cache") + + case MLNTileOperation.requestedFromNetwork: + print("Requesting tile \(tileStr) from network") + + case MLNTileOperation.loadFromCache: + print("Loading tile \(tileStr), requested from the cache") + + case MLNTileOperation.loadFromNetwork: + print("Loading tile \(tileStr), requested from the network") + + case MLNTileOperation.startParse: + print("Parsing tile \(tileStr)") + + case MLNTileOperation.endParse: + print("Completed parsing tile \(tileStr)") + + case MLNTileOperation.error: + print("An error occured during proccessing for tile \(tileStr)") + + case MLNTileOperation.cancelled: + print("Pending work on tile \(tileStr)") + + case MLNTileOperation.nullOp: + print("An unknown tile operation was emitted for tile \(tileStr)") + + @unknown default: + assertionFailure() + } + } + + // #-end-example-code + + // #-example-code(ObserverExampleSprites) + func mapView(_: MLNMapView, spriteWillLoad id: String, url: String) { + print("The sprite \(id) has been requested from \(url)") + } + + func mapView(_: MLNMapView, spriteDidLoad id: String, url: String) { + print("The sprite \(id) has been loaded from \(url)") + } + // #-end-example-code +} + +struct ObserverExampleViewExampleUIViewControllerRepresentable: UIViewControllerRepresentable { + typealias UIViewControllerType = ObserverExampleView + + func makeUIViewController(context _: Context) -> ObserverExampleView { + ObserverExampleView() + } + + func updateUIViewController(_: ObserverExampleView, context _: Context) {} +} diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index e15ec5457..46a446ef0 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -2274,6 +2274,97 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { // MARK: - MLNMapViewDelegate +- (void)mapView:(MLNMapView *)mapView + shaderWillCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines +{ + NSLog(@"A new shader is being compiled - shaderID:%ld, backend type:%ld, program configuration:%@", id, backend, defines); +} + +- (void)mapView:(MLNMapView *)mapView + shaderDidCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines +{ + NSLog(@"A shader has been compiled - shaderID:%ld, backend type:%ld, program configuration:%@", id, backend, defines); +} + +- (void)mapView:(MLNMapView *)mapView + glyphsWillLoad:(NSArray *)fontStack + range:(NSRange)range +{ + NSLog(@"Glyphs are being requested for the font stack %@, ranging from %ld to %ld", fontStack, range.location, range.location + range.length); +} + +- (void)mapView:(MLNMapView *)mapView + glyphsDidLoad:(NSArray *)fontStack + range:(NSRange)range +{ + NSLog(@"Glyphs have been loaded for the font stack %@, ranging from %ld to %ld", fontStack, range.location, range.location + range.length); +} + +- (void)mapView:(MLNMapView *)mapView + tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(NSString *)sourceID +{ + NSString* tileStr = [NSString stringWithFormat:@"(x: %ld, y: %ld, z: %ld, wrap: %ld, overscaledZ: %ld, sourceID: %@)", + x, y, z, wrap, overscaledZ, sourceID]; + + switch (operation) { + case MLNTileOperationRequestedFromCache: + NSLog(@"Requesting tile %@ from cache", tileStr); + break; + + case MLNTileOperationRequestedFromNetwork: + NSLog(@"Requesting tile %@ from network", tileStr); + break; + + case MLNTileOperationLoadFromCache: + NSLog(@"Loading tile %@, requested from the cache", tileStr); + break; + + case MLNTileOperationLoadFromNetwork: + NSLog(@"Loading tile %@, requested from the network", tileStr); + break; + + case MLNTileOperationStartParse: + NSLog(@"Parsing tile %@", tileStr); + break; + + case MLNTileOperationEndParse: + NSLog(@"Completed parsing tile %@", tileStr); + break; + + case MLNTileOperationError: + NSLog(@"An error occured during proccessing for tile %@", tileStr); + break; + + case MLNTileOperationCancelled: + NSLog(@"Pending work on tile %@", tileStr); + break; + + case MLNTileOperationNullOp: + NSLog(@"An unknown tile operation was emitted for tile %@", tileStr); + break; + } +} + +- (void)mapView:(MLNMapView *)mapView spriteWillLoad:(NSString *)id url:(NSString *)url +{ + NSLog(@"The sprite %@ has been requested from %@", id, url); +} + +- (void)mapView:(MLNMapView *)mapView spriteDidLoad:(NSString *)id url:(NSString *)url +{ + NSLog(@"The sprite %@ has been loaded from %@", id, url); +} + - (MLNAnnotationView *)mapView:(MLNMapView *)mapView viewForAnnotation:(id)annotation { if (annotation == mapView.userLocation) diff --git a/platform/ios/sdk-files.json b/platform/ios/sdk-files.json index 0a65d0a50..57464ddd8 100644 --- a/platform/ios/sdk-files.json +++ b/platform/ios/sdk-files.json @@ -183,6 +183,7 @@ "MLNMapCamera.h": "platform/darwin/src/MLNMapCamera.h", "MLNForegroundStyleLayer.h": "platform/darwin/src/MLNForegroundStyleLayer.h", "MLNOfflineRegion.h": "platform/darwin/src/MLNOfflineRegion.h", + "MLNTileOperation.h": "platform/darwin/src/MLNTileOperation.h", "MLNMapViewDelegate.h": "platform/ios/src/MLNMapViewDelegate.h", "MLNDistanceFormatter.h": "platform/darwin/src/MLNDistanceFormatter.h", "MLNCustomStyleLayer.h": "platform/darwin/src/MLNCustomStyleLayer.h", diff --git a/platform/ios/src/MLNMapView+Impl.h b/platform/ios/src/MLNMapView+Impl.h index ff413367e..ab4c3459f 100644 --- a/platform/ios/src/MLNMapView+Impl.h +++ b/platform/ios/src/MLNMapView+Impl.h @@ -72,6 +72,21 @@ class MLNMapViewImpl : public mbgl::MapObserver { void onDidBecomeIdle() override; void onStyleImageMissing(const std::string& imageIdentifier) override; bool onCanRemoveUnusedStyleImage(const std::string& imageIdentifier) override; + void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override; + void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onPostCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onShaderCompileFailed(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onGlyphsLoaded(const mbgl::FontStack&, const mbgl::GlyphRange&) override; + void onGlyphsError(const mbgl::FontStack&, const mbgl::GlyphRange&, std::exception_ptr) override; + void onGlyphsRequested(const mbgl::FontStack&, const mbgl::GlyphRange&) override; + void onTileAction(mbgl::TileOperation, const mbgl::OverscaledTileID&, + const std::string&) override; + void onSpriteLoaded(const std::optional&) override; + void onSpriteError(const std::optional&, std::exception_ptr) override; + void onSpriteRequested(const std::optional&) override; protected: /// Cocoa map view that this adapter bridges to. diff --git a/platform/ios/src/MLNMapView+Impl.mm b/platform/ios/src/MLNMapView+Impl.mm index 901a542f7..35ad18139 100644 --- a/platform/ios/src/MLNMapView+Impl.mm +++ b/platform/ios/src/MLNMapView+Impl.mm @@ -116,3 +116,89 @@ bool MLNMapViewImpl::onCanRemoveUnusedStyleImage(const std::string &imageIdentif NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()]; return [mapView shouldRemoveStyleImage:imageName]; } + +void MLNMapViewImpl::onRegisterShaders(mbgl::gfx::ShaderRegistry& shaders) { + +} + +void MLNMapViewImpl::onPreCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderWillCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onPostCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderDidCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onShaderCompileFailed(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderDidFailCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onGlyphsLoaded(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsDidLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onGlyphsError(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range, std::exception_ptr error) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsDidError:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onGlyphsRequested(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsWillLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onTileAction(mbgl::TileOperation operation, const mbgl::OverscaledTileID& tile, const std::string& sourceID) { + [mapView tileDidTriggerAction:MLNTileOperation(static_cast(operation)) + x:tile.canonical.x + y:tile.canonical.x + z:tile.canonical.z + wrap:tile.wrap + overscaledZ:tile.overscaledZ + sourceID:[NSString stringWithUTF8String:sourceID.c_str()]]; +} + +void MLNMapViewImpl::onSpriteLoaded(const std::optional& spriteID) { + if (!spriteID.has_value()) { + [mapView spriteDidLoad:nil url:nil]; + return; + } + + [mapView spriteDidLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} + +void MLNMapViewImpl::onSpriteError(const std::optional& spriteID, std::exception_ptr error) { + if (!spriteID.has_value()) { + [mapView spriteDidError:nil url:nil]; + return; + } + + [mapView spriteDidError:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} + +void MLNMapViewImpl::onSpriteRequested(const std::optional& spriteID) { + if (!spriteID.has_value()) { + [mapView spriteWillLoad:nil url:nil]; + return; + } + + [mapView spriteWillLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 16162ce10..e5329c809 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -6924,6 +6924,112 @@ static void *windowScreenContext = &windowScreenContext; return YES; } +- (void)shaderWillCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderWillCompile:backend:defines:)]) { + [self.delegate mapView:self shaderWillCompile:id backend:backend defines:defines]; + } +} + +- (void)shaderDidCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderDidCompile:backend:defines:)]) { + [self.delegate mapView:self shaderDidCompile:id backend:backend defines:defines]; + } +} + +- (void)shaderDidFailCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderDidFailCompile:backend:defines:)]) { + [self.delegate mapView:self shaderDidFailCompile:id backend:backend defines:defines]; + } +} + +- (void)glyphsWillLoad:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsWillLoad:range:)]) { + [self.delegate mapView:self glyphsWillLoad:fontStack range:range]; + } +} + +- (void)glyphsDidLoad:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsDidLoad:range:)]) { + [self.delegate mapView:self glyphsDidLoad:fontStack range:range]; + } +} + +- (void)glyphsDidError:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsDidError:range:)]) { + [self.delegate mapView:self glyphsDidError:fontStack range:range]; + } +} + +- (void)tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(nonnull NSString *)sourceID { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:tileDidTriggerAction:x:y:z:wrap:overscaledZ:sourceID:)]) { + [self.delegate mapView:self tileDidTriggerAction:operation x:x y:y z:z wrap:wrap overscaledZ:overscaledZ sourceID:sourceID]; + } +} + +- (void)spriteWillLoad:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteWillLoad:url:)]) { + [self.delegate mapView:self spriteWillLoad:id url:url]; + } +} + +- (void)spriteDidLoad:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteDidLoad:url:)]) { + [self.delegate mapView:self spriteDidLoad:id url:url]; + } +} + +- (void)spriteDidError:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteDidError:url:)]) { + [self.delegate mapView:self spriteDidError:id url:url]; + } +} + - (void)updateUserLocationAnnotationView { [self updateUserLocationAnnotationViewAnimatedWithDuration:0]; diff --git a/platform/ios/src/MLNMapViewDelegate.h b/platform/ios/src/MLNMapViewDelegate.h index 346dbc5fd..32ecf8909 100644 --- a/platform/ios/src/MLNMapViewDelegate.h +++ b/platform/ios/src/MLNMapViewDelegate.h @@ -1,5 +1,6 @@ #import +#import #import "MLNCameraChangeReason.h" #import "Mapbox.h" @@ -325,6 +326,157 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)mapView:(MLNMapView *)mapView shouldRemoveStyleImage:(NSString *)imageName; +// MARK: - Shader Compilation + +/** + Called when a shader is about to be compiled. + + @param mapView The ``MLNMapView`` instance invoking this delegate method. + @param id The unique identifier for the shader being compiled. + @param backend An integer representing the backend type used for shader compilation. + @param defines A string containing the shader program configuration definitions. + + > Warning: This method is not thread-safe. + */ +- (void)mapView:(MLNMapView *)mapView + shaderWillCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; + +/** +Called when a shader was successfully compiled. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param id The unique identifier for the shader that was compiled. +@param backend An integer representing the backend type used for shader compilation. +@param defines A string containing the shader program configuration definitions. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + shaderDidCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; + +/** +Called when a shader failed to compile. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param id The unique identifier for the shader that failed to compile. +@param backend An integer representing the backend type used for shader compilation. +@param defines A string containing the shader program configuration definitions. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + shaderDidFailCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; + +// MARK: - Glyph Requests + +/** +Called when glyphs for the specified font stack are about to be loaded. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param fontStack An array of strings identifying the requested font stack. +@param range The range of glyphs that are being requested. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + glyphsWillLoad:(NSArray *)fontStack + range:(NSRange)range; + +/** +Called when glyphs for the specified font stack have been successfully loaded. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param fontStack An array of strings identifying the requested font stack. +@param range The range of glyphs that were successfully loaded. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + glyphsDidLoad:(NSArray *)fontStack + range:(NSRange)range; + +/** +Called when an error occurred while loading glyphs for the specified font stack. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param fontStack An array of strings identifying the requested font stack. +@param range The range of glyphs for which loading failed. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + glyphsDidError:(NSArray *)fontStack + range:(NSRange)range; + +// MARK: - Tile Requests + +/** +Called when a tile-related action is triggered. + +This method notifies the delegate of various stages of tile processing, such as requesting from +cache or network, parsing, or encountering errors. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param operation The type of tile operation triggered. See ``MLNTileOperation``. +@param x The x-coordinate of the tile. +@param y The y-coordinate of the tile. +@param z The z (zoom) level of the tile. +@param wrap The wrap value for the tile. +@param overscaledZ The overscaled zoom level of the tile. +@param sourceID A string identifier for the tile source. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView + tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(NSString *)sourceID; + +// MARK: - Sprite Requests + +/** +Called when a sprite is about to be loaded. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param id The unique identifier for the sprite being loaded. +@param url The URL from which the sprite is being requested. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView spriteWillLoad:(NSString *)id url:(NSString *)url; + +/** +Called when a sprite has been successfully loaded. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param id The unique identifier for the sprite that was loaded. +@param url The URL from which the sprite was loaded. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView spriteDidLoad:(NSString *)id url:(NSString *)url; + +/** +Called when an error occurs while loading a sprite. + +@param mapView The ``MLNMapView`` instance invoking this delegate method. +@param id The unique identifier for the sprite for which loading failed. +@param url The URL from which the sprite was being requested. + +> Warning: This method is not thread-safe. +*/ +- (void)mapView:(MLNMapView *)mapView spriteDidError:(NSString *)id url:(NSString *)url; + // MARK: Tracking User Location /** diff --git a/platform/ios/src/MLNMapView_Private.h b/platform/ios/src/MLNMapView_Private.h index 6c7088d3c..632fe4938 100644 --- a/platform/ios/src/MLNMapView_Private.h +++ b/platform/ios/src/MLNMapView_Private.h @@ -1,5 +1,6 @@ #import "MLNAnnotationContainerView.h" #import "MLNMapView.h" +#import "MLNTileOperation.h" #import "MLNUserLocationAnnotationView.h" #include @@ -48,6 +49,29 @@ FOUNDATION_EXTERN MLN_EXPORT MLNExceptionName const _Nonnull MLNUnderlyingMapUna - (void)didFailToLoadImage:(nonnull NSString *)imageName; - (BOOL)shouldRemoveStyleImage:(nonnull NSString *)imageName; +- (void)shaderWillCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)shaderDidCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)shaderDidFailCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)glyphsWillLoad:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)glyphsDidLoad:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)glyphsDidError:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(nonnull NSString *)sourceID; +- (void)spriteWillLoad:(nullable NSString *)id url:(nullable NSString *)url; +- (void)spriteDidLoad:(nullable NSString *)id url:(nullable NSString *)url; +- (void)spriteDidError:(nullable NSString *)id url:(nullable NSString *)url; + - (CLLocationDistance)metersPerPointAtLatitude:(CLLocationDegrees)latitude zoomLevel:(double)zoomLevel; diff --git a/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift b/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift index f96b7dcfc..fcb33adef 100644 --- a/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift +++ b/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift @@ -103,4 +103,24 @@ extension MLNMapViewDelegateIntegrationTests: MLNMapViewDelegate { func mapView(_: MLNMapView, didChangeLocationManagerAuthorization _: MLNLocationManager) {} func mapView(styleForDefaultUserLocationAnnotationView _: MLNMapView) -> MLNUserLocationAnnotationViewStyle { MLNUserLocationAnnotationViewStyle() } + + func mapView(_: MLNMapView, shaderWillCompile _: Int, backend _: Int, defines _: String) {} + func mapView(_: MLNMapView, shaderDidCompile _: Int, backend _: Int, defines _: String) {} + func mapView(_: MLNMapView, shaderDidFailCompile _: Int, backend _: Int, defines _: String) {} + + func mapView(_: MLNMapView, glyphsWillLoad _: [String], range _: NSRange) {} + func mapView(_: MLNMapView, glyphsDidLoad _: [String], range _: NSRange) {} + func mapView(_: MLNMapView, glyphsDidError _: [String], range _: NSRange) {} + + func mapView(_: MLNMapView, tileDidTriggerAction _: MLNTileOperation, + x _: Int, + y _: Int, + z _: Int, + wrap _: Int, + overscaledZ _: Int, + sourceID _: String) {} + + func mapView(_: MLNMapView, spriteWillLoad _: String, url _: String) {} + func mapView(_: MLNMapView, spriteDidLoad _: String, url _: String) {} + func mapView(_: MLNMapView, spriteDidError _: String, url _: String) {} } diff --git a/platform/macos/sdk-files.json b/platform/macos/sdk-files.json index 91329e6dd..4dd33d2fd 100644 --- a/platform/macos/sdk-files.json +++ b/platform/macos/sdk-files.json @@ -124,6 +124,7 @@ "MLNOfflineRegion.h": "platform/darwin/src/MLNOfflineRegion.h", "MLNTilePyramidOfflineRegion.h": "platform/darwin/src/MLNTilePyramidOfflineRegion.h", "NSValue+MLNAdditions.h": "platform/darwin/src/NSValue+MLNAdditions.h", + "MLNTileOperation.h": "platform/darwin/src/MLNTileOperation.h", "MLNMapViewDelegate.h": "platform/macos/src/MLNMapViewDelegate.h", "MLNCluster.h": "platform/darwin/src/MLNCluster.h", "MLNFeature.h": "platform/darwin/src/MLNFeature.h", diff --git a/platform/macos/src/MLNMapView+Impl.h b/platform/macos/src/MLNMapView+Impl.h index bb66a2966..16a61fca4 100644 --- a/platform/macos/src/MLNMapView+Impl.h +++ b/platform/macos/src/MLNMapView+Impl.h @@ -38,6 +38,21 @@ class MLNMapViewImpl : public mbgl::MapObserver { void onSourceChanged(mbgl::style::Source& source) override; void onDidBecomeIdle() override; bool onCanRemoveUnusedStyleImage(const std::string& imageIdentifier) override; + void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override; + void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onPostCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onShaderCompileFailed(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, + const std::string&) override; + void onGlyphsLoaded(const mbgl::FontStack&, const mbgl::GlyphRange&) override; + void onGlyphsError(const mbgl::FontStack&, const mbgl::GlyphRange&, std::exception_ptr) override; + void onGlyphsRequested(const mbgl::FontStack&, const mbgl::GlyphRange&) override; + void onTileAction(mbgl::TileOperation, const mbgl::OverscaledTileID&, + const std::string&) override; + void onSpriteLoaded(const std::optional&) override; + void onSpriteError(const std::optional&, std::exception_ptr) override; + void onSpriteRequested(const std::optional&) override; protected: /// Cocoa map view that this adapter bridges to. diff --git a/platform/macos/src/MLNMapView+Impl.mm b/platform/macos/src/MLNMapView+Impl.mm index 423864f99..90ba411ad 100644 --- a/platform/macos/src/MLNMapView+Impl.mm +++ b/platform/macos/src/MLNMapView+Impl.mm @@ -112,3 +112,89 @@ bool MLNMapViewImpl::onCanRemoveUnusedStyleImage(const std::string &imageIdentif NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()]; return [mapView shouldRemoveStyleImage:imageName]; } + +void MLNMapViewImpl::onRegisterShaders(mbgl::gfx::ShaderRegistry& shaders) { + +} + +void MLNMapViewImpl::onPreCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderWillCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onPostCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderDidCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onShaderCompileFailed(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) { + NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()]; + [mapView shaderDidFailCompile:static_cast(shaderID) backend:static_cast(backend) defines:definesCopy]; +} + +void MLNMapViewImpl::onGlyphsLoaded(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsDidLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onGlyphsError(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range, std::exception_ptr error) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsDidError:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onGlyphsRequested(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) { + NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init]; + std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) { + [fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]]; + }); + + [mapView glyphsWillLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)]; +} + +void MLNMapViewImpl::onTileAction(mbgl::TileOperation operation, const mbgl::OverscaledTileID& tile, const std::string& sourceID) { + [mapView tileDidTriggerAction:MLNTileOperation(static_cast(operation)) + x:tile.canonical.x + y:tile.canonical.x + z:tile.canonical.z + wrap:tile.wrap + overscaledZ:tile.overscaledZ + sourceID:[NSString stringWithUTF8String:sourceID.c_str()]]; +} + +void MLNMapViewImpl::onSpriteLoaded(const std::optional& spriteID) { + if (!spriteID.has_value()) { + [mapView spriteDidLoad:nil url:nil]; + return; + } + + [mapView spriteDidLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} + +void MLNMapViewImpl::onSpriteError(const std::optional& spriteID, std::exception_ptr error) { + if (!spriteID.has_value()) { + [mapView spriteDidError:nil url:nil]; + return; + } + + [mapView spriteDidError:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} + +void MLNMapViewImpl::onSpriteRequested(const std::optional& spriteID) { + if (!spriteID.has_value()) { + [mapView spriteWillLoad:nil url:nil]; + return; + } + + [mapView spriteWillLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()] + url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]]; +} diff --git a/platform/macos/src/MLNMapView.mm b/platform/macos/src/MLNMapView.mm index cc4e25b5f..7a5281c9c 100644 --- a/platform/macos/src/MLNMapView.mm +++ b/platform/macos/src/MLNMapView.mm @@ -1000,6 +1000,113 @@ public: return YES; } +- (void)shaderWillCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderWillCompile:backend:defines:)]) { + [self.delegate mapView:self shaderWillCompile:id backend:backend defines:defines]; + } +} + +- (void)shaderDidCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderDidCompile:backend:defines:)]) { + [self.delegate mapView:self shaderDidCompile:id backend:backend defines:defines]; + } +} + +- (void)shaderDidFailCompile:(NSInteger)id backend:(NSInteger)backend defines:(nonnull NSString *)defines { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:shaderDidFailCompile:backend:defines:)]) { + [self.delegate mapView:self shaderDidFailCompile:id backend:backend defines:defines]; + } +} + +- (void)glyphsWillLoad:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsWillLoad:range:)]) { + [self.delegate mapView:self glyphsWillLoad:fontStack range:range]; + } +} + +- (void)glyphsDidLoad:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsDidLoad:range:)]) { + [self.delegate mapView:self glyphsDidLoad:fontStack range:range]; + } +} + +- (void)glyphsDidError:(nonnull NSArray*)fontStack range:(NSRange)range { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:glyphsDidError:range:)]) { + [self.delegate mapView:self glyphsDidError:fontStack range:range]; + } +} + +- (void)tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(nonnull NSString *)sourceID { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:tileDidTriggerAction:x:y:z:wrap:overscaledZ:sourceID:)]) { + [self.delegate mapView:self tileDidTriggerAction:operation x:x y:y z:z wrap:wrap overscaledZ:overscaledZ sourceID:sourceID]; + } +} + +- (void)spriteWillLoad:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteWillLoad:url:)]) { + [self.delegate mapView:self spriteWillLoad:id url:url]; + } +} + +- (void)spriteDidLoad:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteDidLoad:url:)]) { + [self.delegate mapView:self spriteDidLoad:id url:url]; + } +} + +- (void)spriteDidError:(nullable NSString *)id url:(nullable NSString *)url { + if (!_mbglMap) { + return; + } + + if ([self.delegate respondsToSelector:@selector(mapView:spriteDidError:url:)]) { + [self.delegate mapView:self spriteDidError:id url:url]; + } +} + + // MARK: Printing - (void)print:(__unused id)sender { diff --git a/platform/macos/src/MLNMapViewDelegate.h b/platform/macos/src/MLNMapViewDelegate.h index 90f36bf64..53057845b 100644 --- a/platform/macos/src/MLNMapViewDelegate.h +++ b/platform/macos/src/MLNMapViewDelegate.h @@ -1,5 +1,6 @@ #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -227,6 +228,50 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)mapView:(MLNMapView *)mapView shouldRemoveStyleImage:(NSString *)imageName; +// MARK: Shader Compilation + +- (void)mapView:(MLNMapView *)mapView + shaderWillCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; +- (void)mapView:(MLNMapView *)mapView + shaderDidCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; +- (void)mapView:(MLNMapView *)mapView + shaderDidFailCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(NSString *)defines; + +// MARK: Glyph Requests + +- (void)mapView:(MLNMapView *)mapView + glyphsWillLoad:(NSArray *)fontStack + range:(NSRange)range; +- (void)mapView:(MLNMapView *)mapView + glyphsDidLoad:(NSArray *)fontStack + range:(NSRange)range; +- (void)mapView:(MLNMapView *)mapView + glyphsDidError:(NSArray *)fontStack + range:(NSRange)range; + +// MARK: Tile Requests + +- (void)mapView:(MLNMapView *)mapView + tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(NSString *)sourceID; + +// MARK: Sprite Requests + +- (void)mapView:(MLNMapView *)mapView spriteWillLoad:(NSString *)id url:(NSString *)url; +- (void)mapView:(MLNMapView *)mapView spriteDidLoad:(NSString *)id url:(NSString *)url; +- (void)mapView:(MLNMapView *)mapView spriteDidError:(NSString *)id url:(NSString *)url; + // MARK: Managing the Appearance of Annotations /** diff --git a/platform/macos/src/MLNMapView_Private.h b/platform/macos/src/MLNMapView_Private.h index e496e84f3..12c04213d 100644 --- a/platform/macos/src/MLNMapView_Private.h +++ b/platform/macos/src/MLNMapView_Private.h @@ -1,4 +1,5 @@ #import "MLNMapView.h" +#import "MLNTileOperation.h" #include @@ -47,6 +48,29 @@ class Renderer; - (void)sourceDidChange:(nonnull MLNSource *)source; - (BOOL)shouldRemoveStyleImage:(nonnull NSString *)imageName; +- (void)shaderWillCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)shaderDidCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)shaderDidFailCompile:(NSInteger)id + backend:(NSInteger)backend + defines:(nonnull NSString *)defines; +- (void)glyphsWillLoad:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)glyphsDidLoad:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)glyphsDidError:(nonnull NSArray *)fontStack range:(NSRange)range; +- (void)tileDidTriggerAction:(MLNTileOperation)operation + x:(NSInteger)x + y:(NSInteger)y + z:(NSInteger)z + wrap:(NSInteger)wrap + overscaledZ:(NSInteger)overscaledZ + sourceID:(nonnull NSString *)sourceID; +- (void)spriteWillLoad:(nullable NSString *)id url:(nullable NSString *)url; +- (void)spriteDidLoad:(nullable NSString *)id url:(nullable NSString *)url; +- (void)spriteDidError:(nullable NSString *)id url:(nullable NSString *)url; + /// Asynchronously render a frame of the map. - (void)setNeedsRerender;