always start animations with a common start time

fixes #134
This commit is contained in:
Konstantin Käfer
2014-04-14 19:30:09 -04:00
parent 2e86f2582f
commit 9bb88711b8
8 changed files with 50 additions and 55 deletions

View File

@@ -19,7 +19,7 @@ public:
// Animations
bool needsAnimation() const;
void updateAnimations();
void updateAnimations(double time);
void cancelAnimations();
// Map view changes.

View File

@@ -2,7 +2,6 @@
#define LLMR_UTIL_ANIMATION
#include <llmr/util/noncopyable.hpp>
#include <llmr/platform/platform.hpp>
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 <typename T>
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 {

View File

@@ -29,7 +29,7 @@ public:
// animations
void beginFadeInAnimation();
bool needsAnimation() const;
void updateAnimations();
void updateAnimations(double time);
public:
// loaded image dimensions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -3,6 +3,7 @@
#include <llmr/util/mat4.hpp>
#include <llmr/util/std.hpp>
#include <llmr/util/math.hpp>
#include <llmr/platform/platform.hpp>
#include <cstdio>
using namespace llmr;
@@ -24,9 +25,9 @@ bool Transform::needsAnimation() const {
return !animations.empty();
}
void Transform::updateAnimations() {
animations.remove_if([](const std::shared_ptr<util::animation>& animation) {
return animation->update() == util::animation::complete;
void Transform::updateAnimations(double time) {
animations.remove_if([time](const std::shared_ptr<util::animation>& 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<util::ease_animation>(x, xn, x, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(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<util::ease_animation>(x, xn, x, start, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(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<util::timeout<bool>>(false, panning, 0.2);
double start = platform::elapsed();
pan_timeout = std::make_shared<util::timeout<bool>>(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<util::timeout<bool>>(false, scaling, 0.2);
double start = platform::elapsed();
scale_timeout = std::make_shared<util::timeout<bool>>(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<util::ease_animation>(angle, new_angle, angle, duration));
double start = platform::elapsed();
animations.emplace_front(std::make_shared<util::ease_animation>(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<util::timeout<bool>>(false, rotating, 0.2);
double start = platform::elapsed();
rotate_timeout = std::make_shared<util::timeout<bool>>(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<util::ease_animation>(scale, new_scale, scale, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(x, xn, x, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(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<util::ease_animation>(scale, new_scale, scale, start, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(x, xn, x, start, duration));
animations.emplace_front(std::make_shared<util::ease_animation>(y, yn, y, start, duration));
}
const double s = scale * util::tileSize;

View File

@@ -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;

View File

@@ -3,6 +3,7 @@
#include <memory>
#include <cassert>
#include <llmr/platform/platform.hpp>
#include <llmr/platform/gl.hpp>
#include <png.h>
@@ -176,15 +177,16 @@ void Raster::bind(bool linear) {
}
void Raster::beginFadeInAnimation() {
fade_animation = std::make_shared<util::ease_animation>(opacity, 1.0, opacity, 0.25);
double start = platform::elapsed();
fade_animation = std::make_shared<util::ease_animation>(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;
}
}