diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-04-02 16:38:08 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-04-02 16:38:08 -0700 |
commit | 3bd180dbe84748b51517163b7e45c48a21f0b252 (patch) | |
tree | 0dcaf8906d8e3b2df9b5c7481778ab176b7ae335 | |
parent | 7c05f941a8c001ad770a79fc2ae59093d0dcdcd2 (diff) | |
parent | 12c07b916b106272ba68f0fc85a10b774fd07a50 (diff) | |
download | qtlocation-mapboxgl-3bd180dbe84748b51517163b7e45c48a21f0b252.tar.gz |
Merge pull request #1155 from mapbox/1155-update-as-needed
Only run Style::updateProperties when required
-rw-r--r-- | android/cpp/jni.cpp | 48 | ||||
-rw-r--r-- | android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java | 36 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 16 | ||||
-rw-r--r-- | include/mbgl/map/transform.hpp | 28 | ||||
-rw-r--r-- | include/mbgl/map/transform_state.hpp | 1 | ||||
-rw-r--r-- | include/mbgl/map/update.hpp | 19 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 9 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 12 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 95 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 182 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/raster.cpp | 15 | ||||
-rw-r--r-- | src/mbgl/util/raster.hpp | 9 |
13 files changed, 163 insertions, 309 deletions
diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index ce61a01bf9..b6e46ed5ac 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -461,20 +461,6 @@ jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr return ret; } -void JNICALL nativeStartPanning(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStartPanning"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - nativeMapView->getMap().startPanning(); -} - -void JNICALL nativeStopPanning(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStopPanning"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - nativeMapView->getMap().stopPanning(); -} - void JNICALL nativeResetPosition(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetPosition"); assert(nativeMapViewPtr != 0); @@ -570,20 +556,6 @@ void JNICALL nativeResetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { nativeMapView->getMap().resetZoom(); } -void JNICALL nativeStartScaling(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStartScaling"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - nativeMapView->getMap().startScaling(); -} - -void JNICALL nativeStopScaling(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStopScaling"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - return nativeMapView->getMap().stopScaling(); -} - jdouble JNICALL nativeGetMinZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMinZoom"); assert(nativeMapViewPtr != 0); @@ -636,20 +608,6 @@ void JNICALL nativeResetNorth(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) nativeMapView->getMap().resetNorth(); } -void JNICALL nativeStartRotating(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStartRotating"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - nativeMapView->getMap().startRotating(); -} - -void JNICALL nativeStopRotating(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStopRotating"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr); - nativeMapView->getMap().stopRotating(); -} - void JNICALL nativeSetDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean debug) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDebug"); assert(nativeMapViewPtr != 0); @@ -1029,8 +987,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { reinterpret_cast<void *>(&nativeSetLatLng)}, {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;", reinterpret_cast<void *>(&nativeGetLatLng)}, - {"nativeStartPanning", "(J)V", reinterpret_cast<void *>(&nativeStartPanning)}, - {"nativeStopPanning", "(J)V", reinterpret_cast<void *>(&nativeStopPanning)}, {"nativeResetPosition", "(J)V", reinterpret_cast<void *>(&nativeResetPosition)}, {"nativeScaleBy", "(JDDDJ)V", reinterpret_cast<void *>(&nativeScaleBy)}, {"nativeSetScale", "(JDDDJ)V", reinterpret_cast<void *>(&nativeSetScale)}, @@ -1042,8 +998,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeGetLatLngZoom", "(J)Lcom/mapbox/mapboxgl/geometry/LatLngZoom;", reinterpret_cast<void *>(&nativeGetLatLngZoom)}, {"nativeResetZoom", "(J)V", reinterpret_cast<void *>(&nativeResetZoom)}, - {"nativeStartPanning", "(J)V", reinterpret_cast<void *>(&nativeStartScaling)}, - {"nativeStopPanning", "(J)V", reinterpret_cast<void *>(&nativeStopScaling)}, {"nativeGetMinZoom", "(J)D", reinterpret_cast<void *>(&nativeGetMinZoom)}, {"nativeGetMaxZoom", "(J)D", reinterpret_cast<void *>(&nativeGetMaxZoom)}, {"nativeRotateBy", "(JDDDDJ)V", reinterpret_cast<void *>(&nativeRotateBy)}, @@ -1057,8 +1011,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { &nativeSetBearing))}, {"nativeGetBearing", "(J)D", reinterpret_cast<void *>(&nativeGetBearing)}, {"nativeResetNorth", "(J)V", reinterpret_cast<void *>(&nativeResetNorth)}, - {"nativeStartRotating", "(J)V", reinterpret_cast<void *>(&nativeStartRotating)}, - {"nativeStopRotating", "(J)V", reinterpret_cast<void *>(&nativeStopRotating)}, {"nativeSetDebug", "(JZ)V", reinterpret_cast<void *>(&nativeSetDebug)}, {"nativeToggleDebug", "(J)V", reinterpret_cast<void *>(&nativeToggleDebug)}, {"nativeGetDebug", "(J)Z", reinterpret_cast<void *>(&nativeGetDebug)}, diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java index 186b391a84..d7ca950fbf 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java @@ -213,14 +213,6 @@ class NativeMapView { return nativeGetLatLng(mNativeMapViewPtr); } - public void startPanning() { - nativeStartPanning(mNativeMapViewPtr); - } - - public void stopPanning() { - nativeStopPanning(mNativeMapViewPtr); - } - public void resetPosition() { nativeResetPosition(mNativeMapViewPtr); } @@ -281,14 +273,6 @@ class NativeMapView { nativeResetZoom(mNativeMapViewPtr); } - public void startScaling() { - nativeStartScaling(mNativeMapViewPtr); - } - - public void stopScaling() { - nativeStopScaling(mNativeMapViewPtr); - } - public double getMinZoom() { return nativeGetMinZoom(mNativeMapViewPtr); } @@ -326,14 +310,6 @@ class NativeMapView { nativeResetNorth(mNativeMapViewPtr); } - public void startRotating() { - nativeStartRotating(mNativeMapViewPtr); - } - - public void stopRotating() { - nativeStopRotating(mNativeMapViewPtr); - } - public void setDebug(boolean debug) { nativeSetDebug(mNativeMapViewPtr, debug); } @@ -468,10 +444,6 @@ class NativeMapView { private native LatLng nativeGetLatLng(long nativeMapViewPtr); - private native void nativeStartPanning(long nativeMapViewPtr); - - private native void nativeStopPanning(long nativeMapViewPtr); - private native void nativeResetPosition(long nativeMapViewPtr); private native void nativeScaleBy(long nativeMapViewPtr, double ds, @@ -494,10 +466,6 @@ class NativeMapView { private native void nativeResetZoom(long nativeMapViewPtr); - private native void nativeStartScaling(long nativeMapViewPtr); - - private native void nativeStopScaling(long nativeMapViewPtr); - private native double nativeGetMinZoom(long nativeMapViewPtr); private native double nativeGetMaxZoom(long nativeMapViewPtr); @@ -515,10 +483,6 @@ class NativeMapView { private native void nativeResetNorth(long nativeMapViewPtr); - private native void nativeStartRotating(long nativeMapViewPtr); - - private native void nativeStopRotating(long nativeMapViewPtr); - private native void nativeSetDebug(long nativeMapViewPtr, boolean debug); private native void nativeToggleDebug(long nativeMapViewPtr); diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 83bb055214..cdcfa27e42 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -3,6 +3,7 @@ #include <mbgl/map/transform.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/map/update.hpp> #include <mbgl/util/geo.hpp> #include <mbgl/util/projection.hpp> #include <mbgl/util/noncopyable.hpp> @@ -76,14 +77,6 @@ public: void render(); // Notifies the Map thread that the state has changed and an update might be necessary. - using UpdateType = uint32_t; - enum class Update : UpdateType { - Nothing = 0, - StyleInfo = 1 << 0, - Debug = 1 << 1, - DefaultTransitionDuration = 1 << 2, - Classes = 1 << 3, - }; void triggerUpdate(Update = Update::Nothing); // Triggers a render. Can be called from any thread. @@ -107,13 +100,12 @@ public: // Transition void cancelTransitions(); + void setGestureInProgress(bool); // Position void moveBy(double dx, double dy, Duration = Duration::zero()); void setLatLng(LatLng latLng, Duration = Duration::zero()); LatLng getLatLng() const; - void startPanning(); - void stopPanning(); void resetPosition(); // Scale @@ -124,8 +116,6 @@ public: double getZoom() const; void setLatLngZoom(LatLng latLng, double zoom, Duration = Duration::zero()); void resetZoom(); - void startScaling(); - void stopScaling(); double getMinZoom() const; double getMaxZoom() const; @@ -135,8 +125,6 @@ public: void setBearing(double degrees, double cx, double cy); double getBearing() const; void resetNorth(); - void startRotating(); - void stopRotating(); // API void setAccessToken(const std::string &token); diff --git a/include/mbgl/map/transform.hpp b/include/mbgl/map/transform.hpp index b15c119c44..ef89a4eefa 100644 --- a/include/mbgl/map/transform.hpp +++ b/include/mbgl/map/transform.hpp @@ -3,6 +3,7 @@ #include <mbgl/map/transform_state.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/map/update.hpp> #include <mbgl/util/geo.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/vec.hpp> @@ -31,8 +32,6 @@ public: void setLatLng(LatLng latLng, Duration = Duration::zero()); void setLatLngZoom(LatLng latLng, double zoom, Duration = Duration::zero()); inline const LatLng getLatLng() const { return current.getLatLng(); } - void startPanning(); - void stopPanning(); // Zoom void scaleBy(double ds, double cx = -1, double cy = -1, Duration = Duration::zero()); @@ -40,8 +39,6 @@ public: void setZoom(double zoom, Duration = Duration::zero()); double getZoom() const; double getScale() const; - void startScaling(); - void stopScaling(); double getMinZoom() const; double getMaxZoom() const; @@ -50,14 +47,15 @@ public: void setAngle(double angle, Duration = Duration::zero()); void setAngle(double angle, double cx, double cy); double getAngle() const; - void startRotating(); - void stopRotating(); // Transitions bool needsTransition() const; - void updateTransitions(TimePoint now); + UpdateType updateTransitions(TimePoint now); void cancelTransitions(); + // Gesture + void setGestureInProgress(bool); + // Transform state const TransformState currentState() const; const TransformState finalState() const; @@ -69,13 +67,9 @@ private: void _setScale(double scale, double cx, double cy, Duration = Duration::zero()); void _setScaleXY(double new_scale, double xn, double yn, Duration = Duration::zero()); void _setAngle(double angle, Duration = Duration::zero()); - void _clearPanning(); - void _clearRotating(); - void _clearScaling(); void constrain(double& scale, double& y) const; -private: View &view; mutable std::recursive_mutex mtx; @@ -92,10 +86,14 @@ private: const double min_scale = std::pow(2, 0); const double max_scale = std::pow(2, 18); - std::forward_list<util::ptr<util::transition>> transitions; - util::ptr<util::transition> scale_timeout; - util::ptr<util::transition> rotate_timeout; - util::ptr<util::transition> pan_timeout; + void startTransition(std::function<Update(double)> frame, + std::function<void()> finish, + Duration); + + TimePoint transitionStart; + Duration transitionDuration; + std::function<Update(TimePoint)> transitionFrameFn; + std::function<void()> transitionFinishFn; }; } diff --git a/include/mbgl/map/transform_state.hpp b/include/mbgl/map/transform_state.hpp index 5f2dfa49e4..c1a324a899 100644 --- a/include/mbgl/map/transform_state.hpp +++ b/include/mbgl/map/transform_state.hpp @@ -77,6 +77,7 @@ private: bool rotating = false; bool scaling = false; bool panning = false; + bool gestureInProgress = false; // map position double x = 0, y = 0; diff --git a/include/mbgl/map/update.hpp b/include/mbgl/map/update.hpp new file mode 100644 index 0000000000..3aa871bf03 --- /dev/null +++ b/include/mbgl/map/update.hpp @@ -0,0 +1,19 @@ +#ifndef MBGL_MAP_UPDATE +#define MBGL_MAP_UPDATE + +namespace mbgl { + +using UpdateType = uint32_t; + +enum class Update : UpdateType { + Nothing = 0, + StyleInfo = 1 << 0, + Debug = 1 << 1, + DefaultTransitionDuration = 1 << 2, + Classes = 1 << 3, + Zoom = 1 << 4, +}; + +} + +#endif diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index fd9c701f92..7cedd634cd 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -212,7 +212,6 @@ void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset) scale = 1.0 / scale; } - view->map->startScaling(); view->map->scaleBy(scale, view->lastX, view->lastY); } @@ -231,14 +230,12 @@ void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modi if (button == GLFW_MOUSE_BUTTON_RIGHT || (button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) { view->rotating = action == GLFW_PRESS; - if (!view->rotating) { - view->map->stopRotating(); - } + view->map->setGestureInProgress(view->rotating); } else if (button == GLFW_MOUSE_BUTTON_LEFT) { view->tracking = action == GLFW_PRESS; + view->map->setGestureInProgress(view->tracking); if (action == GLFW_RELEASE) { - view->map->stopPanning(); double now = glfwGetTime(); if (now - view->lastClick < 0.4 /* ms */) { if (modifiers & GLFW_MOD_SHIFT) { @@ -258,11 +255,9 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) { double dx = x - view->lastX; double dy = y - view->lastY; if (dx || dy) { - view->map->startPanning(); view->map->moveBy(dx, dy); } } else if (view->rotating) { - view->map->startRotating(); view->map->rotateBy(view->lastX, view->lastY, x, y); } view->lastX = x; diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 4a55ada173..962e3a1126 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -615,6 +615,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; { [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan]; + mbglMap->setGestureInProgress(true); + self.centerPoint = CGPointMake(0, 0); self.userTrackingMode = MGLUserTrackingModeNone; @@ -651,6 +653,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; mbglMap->moveBy(offset.x, offset.y, secondsAsDuration(duration)); + mbglMap->setGestureInProgress(false); + if (duration) { self.animatingGesture = YES; @@ -694,7 +698,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; { [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch]; - mbglMap->startScaling(); + mbglMap->setGestureInProgress(true); self.scale = mbglMap->getScale(); @@ -712,7 +716,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; } else if (pinch.state == UIGestureRecognizerStateEnded || pinch.state == UIGestureRecognizerStateCancelled) { - mbglMap->stopScaling(); + mbglMap->setGestureInProgress(false); [self unrotateIfNeededAnimated:YES]; @@ -730,7 +734,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; { [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate]; - mbglMap->startRotating(); + mbglMap->setGestureInProgress(true); self.angle = [MGLMapView degreesToRadians:mbglMap->getBearing()] * -1; @@ -754,7 +758,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; } else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled) { - mbglMap->stopRotating(); + mbglMap->setGestureInProgress(false); [self unrotateIfNeededAnimated:YES]; diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 9dad7a58b3..509986a6d2 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -7,7 +7,6 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/map/annotation.hpp> #include <mbgl/map/sprite.hpp> -#include <mbgl/util/transition.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/clip_ids.hpp> #include <mbgl/util/string.hpp> @@ -72,7 +71,8 @@ Map::Map(View& view_, FileSource& fileSource_) texturePool(std::make_shared<TexturePool>()), painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas)), annotationManager(util::make_unique<AnnotationManager>()), - data(util::make_unique<MapData>()) + data(util::make_unique<MapData>()), + updated(static_cast<UpdateType>(Update::Nothing)) { view.initialize(this); } @@ -449,10 +449,13 @@ void Map::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, void Map::cancelTransitions() { transform.cancelTransitions(); - triggerUpdate(); } +void Map::setGestureInProgress(bool inProgress) { + transform.setGestureInProgress(inProgress); + triggerUpdate(); +} #pragma mark - Position @@ -470,21 +473,11 @@ LatLng Map::getLatLng() const { return state.getLatLng(); } -void Map::startPanning() { - transform.startPanning(); - triggerUpdate(); -} - -void Map::stopPanning() { - transform.stopPanning(); - triggerUpdate(); -} - void Map::resetPosition() { transform.setAngle(0); transform.setLatLng(LatLng(0, 0)); transform.setZoom(0); - triggerUpdate(); + triggerUpdate(Update::Zoom); } @@ -492,12 +485,12 @@ void Map::resetPosition() { void Map::scaleBy(double ds, double cx, double cy, Duration duration) { transform.scaleBy(ds, cx, cy, duration); - triggerUpdate(); + triggerUpdate(Update::Zoom); } void Map::setScale(double scale, double cx, double cy, Duration duration) { transform.setScale(scale, cx, cy, duration); - triggerUpdate(); + triggerUpdate(Update::Zoom); } double Map::getScale() const { @@ -506,7 +499,7 @@ double Map::getScale() const { void Map::setZoom(double zoom, Duration duration) { transform.setZoom(zoom, duration); - triggerUpdate(); + triggerUpdate(Update::Zoom); } double Map::getZoom() const { @@ -515,23 +508,13 @@ double Map::getZoom() const { void Map::setLatLngZoom(LatLng latLng, double zoom, Duration duration) { transform.setLatLngZoom(latLng, zoom, duration); - triggerUpdate(); + triggerUpdate(Update::Zoom); } void Map::resetZoom() { setZoom(0); } -void Map::startScaling() { - transform.startScaling(); - triggerUpdate(); -} - -void Map::stopScaling() { - transform.stopScaling(); - triggerUpdate(); -} - double Map::getMinZoom() const { return transform.getMinZoom(); } @@ -567,16 +550,6 @@ void Map::resetNorth() { triggerUpdate(); } -void Map::startRotating() { - transform.startRotating(); - triggerUpdate(); -} - -void Map::stopRotating() { - transform.stopRotating(); - triggerUpdate(); -} - #pragma mark - Access Token void Map::setAccessToken(const std::string &token) { @@ -802,44 +775,49 @@ void Map::loadStyleJSON(const std::string& json, const std::string& base) { const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken()); glyphStore->setURL(glyphURL); - triggerUpdate(); + triggerUpdate(Update::Zoom); } void Map::prepare() { assert(Environment::currentlyOn(ThreadType::Map)); - const auto u = updated.exchange(static_cast<UpdateType>(Update::Nothing)); - if ((u & static_cast<UpdateType>(Update::StyleInfo)) || !style) { + const auto now = Clock::now(); + data->setAnimationTime(now); + + auto u = updated.exchange(static_cast<UpdateType>(Update::Nothing)) | + transform.updateTransitions(now); + + if (!style) { + u |= static_cast<UpdateType>(Update::StyleInfo); + } + + state = transform.currentState(); + + if (u & static_cast<UpdateType>(Update::StyleInfo)) { reloadStyle(); } + if (u & static_cast<UpdateType>(Update::Debug)) { assert(painter); painter->setDebug(data->getDebug()); } - if (u & static_cast<UpdateType>(Update::DefaultTransitionDuration)) { - if (style) { + + if (style) { + if (u & static_cast<UpdateType>(Update::DefaultTransitionDuration)) { style->setDefaultTransitionDuration(data->getDefaultTransitionDuration()); } - } - if (u & static_cast<UpdateType>(Update::Classes)) { - if (style) { + + if (u & static_cast<UpdateType>(Update::Classes)) { style->cascade(data->getClasses()); } - } - - // Update transform transitions. - const auto animationTime = Clock::now(); - data->setAnimationTime(animationTime); - if (transform.needsTransition()) { - transform.updateTransitions(animationTime); - } - - state = transform.currentState(); + if (u & static_cast<UpdateType>(Update::StyleInfo) || + u & static_cast<UpdateType>(Update::Classes) || + u & static_cast<UpdateType>(Update::Zoom)) { + style->recalculate(state.getNormalizedZoom(), now); + } - if (style) { updateSources(); - style->recalculate(state.getNormalizedZoom(), animationTime); // Allow the sprite atlas to potentially pull new sprite images if needed. spriteAtlas->resize(state.getPixelRatio()); @@ -863,6 +841,7 @@ void Map::render() { assert(painter); painter->render(*style, activeSources, state, data->getAnimationTime()); + // Schedule another rerender when we definitely need a next frame. if (transform.needsTransition() || style->hasTransitions()) { triggerUpdate(); diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index dd0fd620b1..10f69e2edc 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -4,7 +4,8 @@ #include <mbgl/util/mat4.hpp> #include <mbgl/util/std.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/util/transition.hpp> +#include <mbgl/util/unitbezier.hpp> +#include <mbgl/util/interpolate.hpp> #include <mbgl/platform/platform.hpp> #include <cstdio> @@ -66,12 +67,19 @@ void Transform::_moveBy(const double dx, const double dy, const Duration duratio current.x = final.x; current.y = final.y; } else { - // Use a common start time for all of the transitions to avoid divergent transitions. - TimePoint start = Clock::now(); - transitions.emplace_front( - std::make_shared<util::ease_transition<double>>(current.x, final.x, current.x, start, duration)); - transitions.emplace_front( - std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration)); + const double startX = current.x; + const double startY = current.y; + current.panning = true; + + startTransition( + [=](double t) { + current.x = util::interpolate(startX, final.x, t); + current.y = util::interpolate(startY, final.y, t); + return Update::Nothing; + }, + [=] { + current.panning = false; + }, duration); } view.notifyMapChange(duration != Duration::zero() ? @@ -110,31 +118,6 @@ void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Dura _setScaleXY(new_scale, xn, yn, duration); } -void Transform::startPanning() { - std::lock_guard<std::recursive_mutex> lock(mtx); - - _clearPanning(); - - // Add a 200ms timeout for resetting this to false - current.panning = true; - TimePoint start = Clock::now(); - pan_timeout = std::make_shared<util::timeout<bool>>(false, current.panning, start, std::chrono::milliseconds(200)); - transitions.emplace_front(pan_timeout); -} - -void Transform::stopPanning() { - std::lock_guard<std::recursive_mutex> lock(mtx); - - _clearPanning(); -} - -void Transform::_clearPanning() { - current.panning = false; - if (pan_timeout) { - transitions.remove(pan_timeout); - pan_timeout.reset(); - } -} #pragma mark - Zoom @@ -177,24 +160,6 @@ double Transform::getScale() const { return final.scale; } -void Transform::startScaling() { - std::lock_guard<std::recursive_mutex> lock(mtx); - - _clearScaling(); - - // Add a 200ms timeout for resetting this to false - current.scaling = true; - TimePoint start = Clock::now(); - scale_timeout = std::make_shared<util::timeout<bool>>(false, current.scaling, start, std::chrono::milliseconds(200)); - transitions.emplace_front(scale_timeout); -} - -void Transform::stopScaling() { - std::lock_guard<std::recursive_mutex> lock(mtx); - - _clearScaling(); -} - double Transform::getMinZoom() const { double test_scale = current.scale; double test_y = current.y; @@ -207,16 +172,6 @@ double Transform::getMaxZoom() const { return std::log2(max_scale); } -void Transform::_clearScaling() { - // This is only called internally, so we don't need a lock here. - - current.scaling = false; - if (scale_timeout) { - transitions.remove(scale_timeout); - scale_timeout.reset(); - } -} - void Transform::_setScale(double new_scale, double cx, double cy, const Duration duration) { // This is only called internally, so we don't need a lock here. @@ -269,14 +224,23 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl current.x = final.x; current.y = final.y; } else { - // Use a common start time for all of the transitions to avoid divergent transitions. - TimePoint start = Clock::now(); - transitions.emplace_front(std::make_shared<util::ease_transition<double>>( - current.scale, final.scale, current.scale, start, duration)); - transitions.emplace_front( - std::make_shared<util::ease_transition<double>>(current.x, final.x, current.x, start, duration)); - transitions.emplace_front( - std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration)); + const double startS = current.scale; + const double startX = current.x; + const double startY = current.y; + current.panning = true; + current.scaling = true; + + startTransition( + [=](double t) { + current.scale = util::interpolate(startS, final.scale, t); + current.x = util::interpolate(startX, final.x, t); + current.y = util::interpolate(startY, final.y, t); + return Update::Zoom; + }, + [=] { + current.panning = false; + current.scaling = false; + }, duration); } const double s = final.scale * util::tileSize; @@ -376,9 +340,17 @@ void Transform::_setAngle(double new_angle, const Duration duration) { if (duration == Duration::zero()) { current.angle = final.angle; } else { - TimePoint start = Clock::now(); - transitions.emplace_front(std::make_shared<util::ease_transition<double>>( - current.angle, final.angle, current.angle, start, duration)); + const double startA = current.angle; + current.rotating = true; + + startTransition( + [=](double t) { + current.angle = util::interpolate(startA, final.angle, t); + return Update::Nothing; + }, + [=] { + current.rotating = false; + }, duration); } view.notifyMapChange(duration != Duration::zero() ? @@ -393,55 +365,61 @@ double Transform::getAngle() const { return final.angle; } -void Transform::startRotating() { - std::lock_guard<std::recursive_mutex> lock(mtx); - - _clearRotating(); - // Add a 200ms timeout for resetting this to false - current.rotating = true; - TimePoint start = Clock::now(); - rotate_timeout = std::make_shared<util::timeout<bool>>(false, current.rotating, start, std::chrono::milliseconds(200)); - transitions.emplace_front(rotate_timeout); -} +#pragma mark - Transition -void Transform::stopRotating() { - std::lock_guard<std::recursive_mutex> lock(mtx); +void Transform::startTransition(std::function<Update(double)> frame, + std::function<void()> finish, + Duration duration) { + if (transitionFinishFn) { + transitionFinishFn(); + } - _clearRotating(); -} + transitionStart = Clock::now(); + transitionDuration = duration; -void Transform::_clearRotating() { - // This is only called internally, so we don't need a lock here. + transitionFrameFn = [frame, this](TimePoint now) { + float t = std::chrono::duration<float>(now - transitionStart) / transitionDuration; + if (t >= 1.0) { + Update result = frame(1.0); + transitionFinishFn(); + transitionFrameFn = nullptr; + transitionFinishFn = nullptr; + return result; + } else { + util::UnitBezier ease(0, 0, 0.25, 1); + return frame(ease.solve(t, 0.001)); + } + }; - current.rotating = false; - if (rotate_timeout) { - transitions.remove(rotate_timeout); - rotate_timeout.reset(); - } + transitionFinishFn = finish; } - -#pragma mark - Transition - bool Transform::needsTransition() const { std::lock_guard<std::recursive_mutex> lock(mtx); + return !!transitionFrameFn; +} - return !transitions.empty(); +UpdateType Transform::updateTransitions(const TimePoint now) { + std::lock_guard<std::recursive_mutex> lock(mtx); + return static_cast<UpdateType>(transitionFrameFn ? transitionFrameFn(now) : Update::Nothing); } -void Transform::updateTransitions(const TimePoint now) { +void Transform::cancelTransitions() { std::lock_guard<std::recursive_mutex> lock(mtx); - transitions.remove_if([now](const util::ptr<util::transition> &transition) { - return transition->update(now) == util::transition::complete; - }); + if (transitionFinishFn) { + transitionFinishFn(); + } + + transitionFrameFn = nullptr; + transitionFinishFn = nullptr; } -void Transform::cancelTransitions() { +void Transform::setGestureInProgress(bool inProgress) { std::lock_guard<std::recursive_mutex> lock(mtx); - transitions.clear(); + current.gestureInProgress = inProgress; } #pragma mark - Transform state diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 8c007210e0..32ce184fa9 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -249,7 +249,7 @@ const LatLng TransformState::latLngForPixel(const vec2<double> pixel) const { #pragma mark - Changing bool TransformState::isChanging() const { - return rotating || scaling || panning; + return rotating || scaling || panning || gestureInProgress; } diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp index 7300c291e5..d0e305c33a 100644 --- a/src/mbgl/util/raster.cpp +++ b/src/mbgl/util/raster.cpp @@ -89,18 +89,3 @@ void Raster::bind(const GLuint custom_texture) { } } - -void Raster::beginFadeInTransition() { - TimePoint start = Clock::now(); - fade_transition = std::make_shared<util::ease_transition<double>>(opacity, 1.0, opacity, start, std::chrono::milliseconds(250)); -} - -bool Raster::needsTransition() const { - return fade_transition != nullptr; -} - -void Raster::updateTransitions(TimePoint now) { - if (fade_transition->update(now) == util::transition::complete) { - fade_transition = nullptr; - } -} diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp index 6e5a819916..f19ff7178a 100644 --- a/src/mbgl/util/raster.hpp +++ b/src/mbgl/util/raster.hpp @@ -1,7 +1,6 @@ #ifndef MBGL_UTIL_RASTER #define MBGL_UTIL_RASTER -#include <mbgl/util/transition.hpp> #include <mbgl/util/texture_pool.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/ptr.hpp> @@ -32,11 +31,6 @@ public: // loaded status bool isLoaded() const; - // transitions - void beginFadeInTransition(); - bool needsTransition() const; - void updateTransitions(TimePoint now); - public: // loaded image dimensions uint32_t width = 0, height = 0; @@ -64,9 +58,6 @@ private: // the raw pixels std::unique_ptr<util::Image> img; - - // fade in transition - util::ptr<util::transition> fade_transition = nullptr; }; } |