diff --git a/ios/maps/MCMapView.swift b/ios/maps/MCMapView.swift index a156ac837..7d51db33b 100644 --- a/ios/maps/MCMapView.swift +++ b/ios/maps/MCMapView.swift @@ -194,7 +194,11 @@ extension MCMapView: MTKViewDelegate { invalidate() } - public func draw(in view: MTKView) { + public func draw(in view: MTKView) { + draw(in: view, present: true) + } + + public func draw(in view: MTKView, present: Bool) { guard !backgroundDisable else { isPaused = true mapInterface.resetIsInvalidated() @@ -282,7 +286,7 @@ extension MCMapView: MTKViewDelegate { if self.renderToImage { commandBuffer.commit() commandBuffer.waitUntilCompleted() - } else { + } else if present { guard let drawable = view.currentDrawable else { self.renderSemaphore.signal() @@ -312,6 +316,9 @@ extension MCMapView: MTKViewDelegate { renderToImageQueue.async { @Sendable [weak mapInterface] in DispatchQueue.main.sync { MainActor.assumeIsolated { + // also need to set size + self.frame.size = size + // set the drawable size to get correctly sized texture self.drawableSize = size } @@ -512,7 +519,7 @@ private final class MCMapViewMapReadyCallbacks: Task { @MainActor in guard let delegate = self.delegate else { return } - delegate.draw(in: delegate) + delegate.draw(in: delegate, present: false) callbackQueue? .async { diff --git a/shared/src/map/camera/MapCamera2d.cpp b/shared/src/map/camera/MapCamera2d.cpp index 2a82db097..fe61e1c9d 100644 --- a/shared/src/map/camera/MapCamera2d.cpp +++ b/shared/src/map/camera/MapCamera2d.cpp @@ -55,6 +55,17 @@ void MapCamera2d::viewportSizeChanged() { zoom = std::clamp(zoom, zoomMax, zoomMin); } + // Apply pending bounding box if viewport size is now known + if (pendingBoundingBox.has_value() && viewportSize.x > 0 && viewportSize.y > 0) { + auto pending = pendingBoundingBox.value(); + bool frozenBefore = cameraFrozen; + cameraFrozen = false; + moveToBoundingBox(pending.boundingBox, pending.paddingPc, pending.animated, + pending.minZoom, pending.maxZoom); + cameraFrozen = frozenBefore; + pendingBoundingBox = std::nullopt; + } + notifyListeners(ListenerType::BOUNDS); } @@ -183,9 +194,14 @@ void MapCamera2d::moveToBoundingBox(const RectCoord &boundingBox, float paddingP Vec2I viewSize = mapInterface->getRenderingContext()->getViewportSize(); if (viewSize.x == 0 && viewSize.y == 0) { + // Viewport size not yet known, store parameters for later + pendingBoundingBox = PendingBoundingBox(boundingBox, paddingPc, animated, minZoom, maxZoom); return; } + // Clear any pending bounding box since we're applying it now + pendingBoundingBox = std::nullopt; + RectCoord mapSystemBBox = conversionHelper->convertRect(mapCoordinateSystem.identifier, boundingBox); float newLeft = mapSystemBBox.topLeft.x + paddingPc * (mapSystemBBox.topLeft.x - mapSystemBBox.bottomRight.x); float newRight = mapSystemBBox.bottomRight.x + paddingPc * (mapSystemBBox.bottomRight.x - mapSystemBBox.topLeft.x); @@ -576,6 +592,9 @@ void MapCamera2d::notifyListeners(const int &listenerType) { (listenerType & ListenerType::BOUNDS) ? std::optional(getVisibleRect()) : std::nullopt; double angle = this->angle; double zoom = this->zoom; + if (pendingBoundingBox) { + return; + } std::lock_guard lock(listenerMutex); for (auto listener : listeners) { if (listenerType & ListenerType::BOUNDS) { diff --git a/shared/src/map/camera/MapCamera2d.h b/shared/src/map/camera/MapCamera2d.h index 563c39977..078165115 100644 --- a/shared/src/map/camera/MapCamera2d.h +++ b/shared/src/map/camera/MapCamera2d.h @@ -185,6 +185,20 @@ class MapCamera2d : public MapCameraInterface, RectCoord bounds; + struct PendingBoundingBox { + RectCoord boundingBox; + float paddingPc; + bool animated; + std::optional minZoom; + std::optional maxZoom; + + PendingBoundingBox(const RectCoord &bbox, float padding, bool anim, + std::optional minZ, std::optional maxZ) + : boundingBox(bbox), paddingPc(padding), animated(anim), + minZoom(minZ), maxZoom(maxZ) {} + }; + std::optional pendingBoundingBox = std::nullopt; + std::recursive_mutex vpDataMutex; std::optional lastVpBounds = std::nullopt; std::optional lastVpRotation = std::nullopt; diff --git a/shared/src/map/camera/MapCamera3d.cpp b/shared/src/map/camera/MapCamera3d.cpp index b6b34df87..205256804 100644 --- a/shared/src/map/camera/MapCamera3d.cpp +++ b/shared/src/map/camera/MapCamera3d.cpp @@ -73,6 +73,14 @@ void MapCamera3d::viewportSizeChanged() { updateZoom(zoom); } + // Apply pending bounding box if viewport size is now known + if (pendingBoundingBox.has_value() && viewportSize.x > 0 && viewportSize.y > 0) { + auto pending = pendingBoundingBox.value(); + pendingBoundingBox = std::nullopt; + moveToBoundingBox(pending.boundingBox, pending.paddingPc, pending.animated, + pending.minZoom, pending.maxZoom); + } + updateMatrices(); notifyListeners(ListenerType::BOUNDS); @@ -241,6 +249,15 @@ void MapCamera3d::moveToBoundingBox(const RectCoord &boundingBox, float paddingP assert(boundingBox.topLeft.systemIdentifier == 4326); Vec2I sizeViewport = mapInterface->getRenderingContext()->getViewportSize(); + + if (sizeViewport.x == 0 && sizeViewport.y == 0) { + // Viewport size not yet known, store parameters for later + pendingBoundingBox = PendingBoundingBox(boundingBox, paddingPc, animated, minZoom, maxZoom); + return; + } + + // Clear any pending bounding box since we're applying it now + pendingBoundingBox = std::nullopt; auto distance = calculateDistance(boundingBox.topLeft.y, boundingBox.topLeft.x, boundingBox.bottomRight.y, boundingBox.bottomRight.x); diff --git a/shared/src/map/camera/MapCamera3d.h b/shared/src/map/camera/MapCamera3d.h index 3a9b39717..4c52ed481 100644 --- a/shared/src/map/camera/MapCamera3d.h +++ b/shared/src/map/camera/MapCamera3d.h @@ -232,6 +232,20 @@ class MapCamera3d : public MapCameraInterface, RectCoord bounds; + struct PendingBoundingBox { + RectCoord boundingBox; + float paddingPc; + bool animated; + std::optional minZoom; + std::optional maxZoom; + + PendingBoundingBox(const RectCoord &bbox, float padding, bool anim, + std::optional minZ, std::optional maxZ) + : boundingBox(bbox), paddingPc(padding), animated(anim), + minZoom(minZ), maxZoom(maxZ) {} + }; + std::optional pendingBoundingBox = std::nullopt; + std::optional lastVpBounds = std::nullopt; std::optional lastVpRotation = std::nullopt; std::optional lastVpZoom = std::nullopt;