summaryrefslogtreecommitdiff
path: root/src/mbgl/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/map')
-rw-r--r--src/mbgl/map/map.cpp5
-rw-r--r--src/mbgl/map/transform.cpp57
-rw-r--r--src/mbgl/map/transform.hpp2
-rw-r--r--src/mbgl/map/transform_state.cpp13
-rw-r--r--src/mbgl/map/transform_state.hpp1
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;