diff options
Diffstat (limited to 'src/mbgl/map')
-rw-r--r-- | src/mbgl/map/map.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 57 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 13 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.hpp | 1 |
5 files changed, 68 insertions, 10 deletions
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index a7beb0f1e2..d81544eed5 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -747,6 +747,11 @@ void Map::Impl::onInvalidate() { } void Map::Impl::onUpdate() { + // Don't load/render anything in still mode until explicitly requested. + if (mode != MapMode::Continuous && !stillImageRequest) { + return; + } + TimePoint timePoint = mode == MapMode::Continuous ? Clock::now() : Clock::time_point::max(); transform.updateTransitions(timePoint); diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 105adf0400..da8e243d91 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -594,13 +594,10 @@ void Transform::startTransition(const CameraOptions& camera, animation.transitionFrameFn(t); } observer.onCameraIsChanging(); + return false; } else { - transitionFinishFn(); - transitionFinishFn = nullptr; - - // This callback gets destroyed here, - // we can only return after this point. - transitionFrameFn = nullptr; + // Indicate that we need to terminate this transition + return true; } }; @@ -615,7 +612,14 @@ void Transform::startTransition(const CameraOptions& camera, }; if (!isAnimated) { - transitionFrameFn(Clock::now()); + auto update = std::move(transitionFrameFn); + auto finish = std::move(transitionFinishFn); + + transitionFrameFn = nullptr; + transitionFinishFn = nullptr; + + update(Clock::now()); + finish(); } } @@ -624,8 +628,43 @@ bool Transform::inTransition() const { } void Transform::updateTransitions(const TimePoint& now) { - if (transitionFrameFn) { - transitionFrameFn(now); + + // Use a temporary function to ensure that the transitionFrameFn lambda is + // called only once per update. + + // This addresses the symptoms of https://github.com/mapbox/mapbox-gl-native/issues/11180 + // where setting a shape source to nil (or similar) in the `onCameraIsChanging` + // observer function causes `Map::Impl::onUpdate()` to be called which + // in turn calls this function (before the current iteration has completed), + // leading to an infinite loop. See https://github.com/mapbox/mapbox-gl-native/issues/5833 + // for a similar, related, issue. + // + // By temporarily nulling the `transitionFrameFn` (and then restoring it + // after the temporary has been called) we stop this recursion. + // + // It's important to note that the scope of this change is stop the above + // crashes. It doesn't address any potential deeper issue (for example + // user error, how often and when transition callbacks are called). + + auto transition = std::move(transitionFrameFn); + transitionFrameFn = nullptr; + + if (transition && transition(now)) { + // If the transition indicates that it is complete, then we should call + // the finish lambda (going via a temporary as above) + auto finish = std::move(transitionFinishFn); + + transitionFinishFn = nullptr; + transitionFrameFn = nullptr; + + if (finish) { + finish(); + } + } else if (!transitionFrameFn) { + // We have to check `transitionFrameFn` is nil here, since a new transition + // may have been triggered in a user callback (from the transition call + // above) + transitionFrameFn = std::move(transition); } } diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index d429c57661..bff44a2dcd 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -165,7 +165,7 @@ private: TimePoint transitionStart; Duration transitionDuration; - std::function<void(const TimePoint)> transitionFrameFn; + std::function<bool(const TimePoint)> transitionFrameFn; std::function<void()> transitionFinishFn; }; diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 18d2c24aee..a85b251fb4 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -421,4 +421,17 @@ float TransformState::getCameraToTileDistance(const UnwrappedTileID& tileID) con return projectedCenter[3]; } +float TransformState::maxPitchScaleFactor() const { + if (size.isEmpty()) { + return {}; + } + auto latLng = screenCoordinateToLatLng({ 0, static_cast<float>(getSize().height) }); + mat4 mat = coordinatePointMatrix(getZoom()); + Point<double> pt = Projection::project(latLng, scale) / double(util::tileSize); + vec4 p = {{ pt.x, pt.y, 0, 1 }}; + vec4 topPoint; + matrix::transformMat4(topPoint, p, mat); + return topPoint[3] / getCameraToCenterDistance(); +} + } // namespace mbgl diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 451802034d..b6f8ae4424 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -87,6 +87,7 @@ public: } float getCameraToTileDistance(const UnwrappedTileID&) const; + float maxPitchScaleFactor() const; private: bool rotatedNorth() const; |