From 9bb88711b8933e711f99b0f1fa09371ac8149c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 14 Apr 2014 19:30:09 -0400 Subject: [PATCH] always start animations with a common start time fixes #134 --- include/llmr/map/transform.hpp | 2 +- include/llmr/util/animation.hpp | 23 +++++++++++------------ include/llmr/util/raster.hpp | 2 +- ios/MBXViewController.mm | 23 +++-------------------- src/map/map.cpp | 6 ++++-- src/map/transform.cpp | 33 +++++++++++++++++++++------------ src/util/animation.cpp | 8 ++++---- src/util/raster.cpp | 8 +++++--- 8 files changed, 50 insertions(+), 55 deletions(-) diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp index 522df01f2..7b4d59ee1 100644 --- a/include/llmr/map/transform.hpp +++ b/include/llmr/map/transform.hpp @@ -19,7 +19,7 @@ public: // Animations bool needsAnimation() const; - void updateAnimations(); + void updateAnimations(double time); void cancelAnimations(); // Map view changes. diff --git a/include/llmr/util/animation.hpp b/include/llmr/util/animation.hpp index d1915e3ee..0a172132b 100644 --- a/include/llmr/util/animation.hpp +++ b/include/llmr/util/animation.hpp @@ -2,7 +2,6 @@ #define LLMR_UTIL_ANIMATION #include -#include namespace llmr { namespace util { @@ -13,15 +12,15 @@ public: running, complete }; - animation(double duration) - : start(platform::elapsed()), + animation(double start, double duration) + : start(start), duration(duration) {} - double progress() const { - return (platform::elapsed() - start) / duration; + double progress(double time) const { + return (time - start) / duration; } - virtual state update() const = 0; + virtual state update(double time) const = 0; virtual ~animation(); protected: @@ -30,8 +29,8 @@ protected: class ease_animation : public animation { public: - ease_animation(double from, double to, double& value, double duration); - state update() const; + ease_animation(double from, double to, double& value, double start, double duration); + state update(double time) const; private: const double from, to; @@ -41,13 +40,13 @@ private: template class timeout : public animation { public: - timeout(T final_value, T& value, double duration) - : animation(duration), + timeout(T final_value, T& value, double start, double duration) + : animation(start, duration), final_value(final_value), value(value) {} - state update() const { - if (progress() >= 1) { + state update(double time) const { + if (progress(time) >= 1) { value = final_value; return complete; } else { diff --git a/include/llmr/util/raster.hpp b/include/llmr/util/raster.hpp index cf69663ce..9432e8cf6 100644 --- a/include/llmr/util/raster.hpp +++ b/include/llmr/util/raster.hpp @@ -29,7 +29,7 @@ public: // animations void beginFadeInAnimation(); bool needsAnimation() const; - void updateAnimations(); + void updateAnimations(double time); public: // loaded image dimensions diff --git a/ios/MBXViewController.mm b/ios/MBXViewController.mm index e7e45d322..2a0f64849 100644 --- a/ios/MBXViewController.mm +++ b/ios/MBXViewController.mm @@ -21,7 +21,6 @@ @property (nonatomic) CGFloat quickZoomStart; @property (nonatomic) BOOL debug; @property (nonatomic) UIView *palette; -@property (nonatomic) NSTimeInterval elapsed; @end @@ -183,8 +182,6 @@ MBXViewController *view = nullptr; - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - self.elapsed = CACurrentMediaTime(); - // Render the map map->resize(rect.size.width, rect.size.height, view.contentScaleFactor, view.drawableWidth, view.drawableHeight); @@ -220,7 +217,6 @@ MBXViewController *view = nullptr; - (void)unrotate { - self.elapsed = CACurrentMediaTime(); map->resetNorth(); } @@ -300,8 +296,6 @@ MBXViewController *view = nullptr; - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch { - self.elapsed = CACurrentMediaTime(); - map->cancelAnimations(); if (pinch.state == UIGestureRecognizerStateBegan) @@ -357,8 +351,6 @@ MBXViewController *view = nullptr; - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate { - self.elapsed = CACurrentMediaTime(); - map->cancelAnimations(); if (rotate.state == UIGestureRecognizerStateBegan) @@ -382,15 +374,11 @@ MBXViewController *view = nullptr; - (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap { - self.elapsed = CACurrentMediaTime(); - [self togglePalette]; } - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap { - self.elapsed = CACurrentMediaTime(); - map->cancelAnimations(); if (doubleTap.state == UIGestureRecognizerStateEnded) { @@ -403,8 +391,6 @@ MBXViewController *view = nullptr; - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap { - self.elapsed = CACurrentMediaTime(); - map->cancelAnimations(); if (twoFingerTap.state == UIGestureRecognizerStateEnded) { @@ -417,8 +403,6 @@ MBXViewController *view = nullptr; - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom { - self.elapsed = CACurrentMediaTime(); - map->cancelAnimations(); if (quickZoom.state == UIGestureRecognizerStateBegan) @@ -446,6 +430,8 @@ MBXViewController *view = nullptr; return ([validSimultaneousGestures containsObject:[gestureRecognizer class]] && [validSimultaneousGestures containsObject:[otherGestureRecognizer class]]); } +@end + namespace llmr { namespace platform { @@ -465,10 +451,7 @@ namespace llmr { } double elapsed() { - return view.elapsed; + return CACurrentMediaTime(); } } } - -@end - diff --git a/src/map/map.cpp b/src/map/map.cpp index 873daa2ba..73a89fca8 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -433,8 +433,10 @@ bool Map::updateTiles() { } bool Map::render() { + double animationTime = platform::elapsed(); + if (transform.needsAnimation()) { - transform.updateAnimations(); + transform.updateAnimations(animationTime); } if (*style.sprite->raster && !style.sprite->raster->textured) { @@ -469,7 +471,7 @@ bool Map::render() { tile.data->raster->beginFadeInAnimation(); } if (tile.data->use_raster && tile.data->raster->needsAnimation()) { - tile.data->raster->updateAnimations(); + tile.data->raster->updateAnimations(animationTime); } painter.render(tile); } diff --git a/src/map/transform.cpp b/src/map/transform.cpp index 5be4272ff..7bd06d995 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using namespace llmr; @@ -24,9 +25,9 @@ bool Transform::needsAnimation() const { return !animations.empty(); } -void Transform::updateAnimations() { - animations.remove_if([](const std::shared_ptr& animation) { - return animation->update() == util::animation::complete; +void Transform::updateAnimations(double time) { + animations.remove_if([time](const std::shared_ptr& animation) { + return animation->update(time) == util::animation::complete; }); } @@ -49,8 +50,10 @@ void Transform::moveBy(double dx, double dy, double duration) { x = xn; y = yn; } else { - animations.emplace_front(std::make_shared(x, xn, x, duration)); - animations.emplace_front(std::make_shared(y, yn, y, duration)); + // Use a common start time for all of the animations to avoid divergent animations. + double start = platform::elapsed(); + animations.emplace_front(std::make_shared(x, xn, x, start, duration)); + animations.emplace_front(std::make_shared(y, yn, y, start, duration)); } } @@ -59,7 +62,8 @@ void Transform::startPanning() { // Add a 200ms timeout for resetting this to false panning = true; - pan_timeout = std::make_shared>(false, panning, 0.2); + double start = platform::elapsed(); + pan_timeout = std::make_shared>(false, panning, start, 0.2); animations.emplace_front(pan_timeout); } @@ -90,7 +94,8 @@ void Transform::startScaling() { // Add a 200ms timeout for resetting this to false scaling = true; - scale_timeout = std::make_shared>(false, scaling, 0.2); + double start = platform::elapsed(); + scale_timeout = std::make_shared>(false, scaling, start, 0.2); animations.emplace_front(scale_timeout); } @@ -136,7 +141,8 @@ void Transform::setAngle(double new_angle, double duration) { if (duration == 0) { angle = new_angle; } else { - animations.emplace_front(std::make_shared(angle, new_angle, angle, duration)); + double start = platform::elapsed(); + animations.emplace_front(std::make_shared(angle, new_angle, angle, start, duration)); } } @@ -145,7 +151,8 @@ void Transform::startRotating() { // Add a 200ms timeout for resetting this to false rotating = true; - rotate_timeout = std::make_shared>(false, rotating, 0.2); + double start = platform::elapsed(); + rotate_timeout = std::make_shared>(false, rotating, start, 0.2); animations.emplace_front(rotate_timeout); } @@ -163,9 +170,11 @@ void Transform::setScaleXY(double new_scale, double xn, double yn, double durati x = xn; y = yn; } else { - animations.emplace_front(std::make_shared(scale, new_scale, scale, duration)); - animations.emplace_front(std::make_shared(x, xn, x, duration)); - animations.emplace_front(std::make_shared(y, yn, y, duration)); + // Use a common start time for all of the animations to avoid divergent animations. + double start = platform::elapsed(); + animations.emplace_front(std::make_shared(scale, new_scale, scale, start, duration)); + animations.emplace_front(std::make_shared(x, xn, x, start, duration)); + animations.emplace_front(std::make_shared(y, yn, y, start, duration)); } const double s = scale * util::tileSize; diff --git a/src/util/animation.cpp b/src/util/animation.cpp index 8624fc22a..6009bb018 100644 --- a/src/util/animation.cpp +++ b/src/util/animation.cpp @@ -8,15 +8,15 @@ UnitBezier ease(0.25, 0.1, 0.25, 1); animation::~animation() {} -ease_animation::ease_animation(double from, double to, double &value, double duration) - : animation(duration), +ease_animation::ease_animation(double from, double to, double &value, double start, double duration) + : animation(start, duration), from(from), to(to), value(value) { } -animation::state ease_animation::update() const { - double t = progress(); +animation::state ease_animation::update(double time) const { + double t = progress(time); if (t >= 1) { value = to; return complete; diff --git a/src/util/raster.cpp b/src/util/raster.cpp index 3263d254b..77199d606 100644 --- a/src/util/raster.cpp +++ b/src/util/raster.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -176,15 +177,16 @@ void Raster::bind(bool linear) { } void Raster::beginFadeInAnimation() { - fade_animation = std::make_shared(opacity, 1.0, opacity, 0.25); + double start = platform::elapsed(); + fade_animation = std::make_shared(opacity, 1.0, opacity, start, 0.25); } bool Raster::needsAnimation() const { return fade_animation != nullptr; } -void Raster::updateAnimations() { - if (fade_animation->update() == util::animation::complete) { +void Raster::updateAnimations(double time) { + if (fade_animation->update(time) == util::animation::complete) { fade_animation = nullptr; } }