fix MapAnimator.animateTo()

- cleanups
This commit is contained in:
Hannes Janetzek 2013-09-19 21:29:38 +02:00
parent f6bb944907
commit 0107ade039
2 changed files with 56 additions and 75 deletions

View File

@ -19,6 +19,11 @@ public class MapAnimator {
mMap = map; mMap = map;
} }
private final int ANIM_NONE = 0;
private final int ANIM_MOVE = 1 << 1;
private final int ANIM_SCALE = 1 << 2;
private final int ANIM_FLING = 1 << 3;
private final Map mMap; private final Map mMap;
private final Viewport mViewport; private final Viewport mViewport;
@ -35,19 +40,17 @@ public class MapAnimator {
private float mDuration = 500; private float mDuration = 500;
private long mAnimEnd = -1; private long mAnimEnd = -1;
private boolean mAnimMove; private int mState = ANIM_NONE;
private boolean mAnimFling;
private boolean mAnimScale;
public synchronized void animateTo(BoundingBox bbox) { public synchronized void animateTo(BoundingBox bbox) {
// TODO for large distatance first scale out, then in // TODO for large distatance first scale out, then in
// calculate the maximum scale at which the bbox is completely visible // calculate the maximum scale at which the bbox is completely visible
double dx = Math.abs(MercatorProjection.longitudeToX(bbox.getMaxLongitude()) double dx = Math.abs(MercatorProjection.longitudeToX(bbox.getMaxLongitude())
- MercatorProjection.longitudeToX(bbox.getMinLongitude())); - MercatorProjection.longitudeToX(bbox.getMinLongitude()));
double dy = Math.abs(MercatorProjection.latitudeToY(bbox.getMinLatitude()) double dy = Math.abs(MercatorProjection.latitudeToY(bbox.getMinLatitude())
- MercatorProjection.latitudeToY(bbox.getMaxLatitude())); - MercatorProjection.latitudeToY(bbox.getMaxLatitude()));
double zx = mMap.getWidth() / (dx * Tile.SIZE); double zx = mMap.getWidth() / (dx * Tile.SIZE);
double zy = mMap.getHeight() / (dy * Tile.SIZE); double zy = mMap.getHeight() / (dy * Tile.SIZE);
@ -57,12 +60,12 @@ public class MapAnimator {
} }
public synchronized void animateTo(long duration, GeoPoint geoPoint, double scale, public synchronized void animateTo(long duration, GeoPoint geoPoint, double scale,
boolean relative) { boolean relative) {
mViewport.getMapPosition(mPos); mViewport.getMapPosition(mPos);
if (relative) { if (relative) {
if (mAnimEnd > 0 && mAnimScale) if (mAnimEnd > 0 && (mState & ANIM_SCALE) != 0)
scale = mDeltaPos.scale * scale; scale = mDeltaPos.scale * scale;
else else
scale = mPos.scale * scale; scale = mPos.scale * scale;
@ -86,9 +89,7 @@ public class MapAnimator {
mDeltaPos.x -= mStartPos.x; mDeltaPos.x -= mStartPos.x;
mDeltaPos.y -= mStartPos.y; mDeltaPos.y -= mStartPos.y;
mAnimMove = true; mState = ANIM_MOVE | ANIM_SCALE;
mAnimScale = true;
mAnimFling = false;
animStart(duration); animStart(duration);
} }
@ -97,7 +98,7 @@ public class MapAnimator {
mViewport.getMapPosition(mPos); mViewport.getMapPosition(mPos);
if (mAnimEnd > 0 && mAnimScale) if (mAnimEnd > 0 && (mState & ANIM_SCALE) != 0)
scale = mDeltaPos.scale * scale; scale = mDeltaPos.scale * scale;
else else
scale = mPos.scale * scale; scale = mPos.scale * scale;
@ -109,16 +110,13 @@ public class MapAnimator {
mScaleBy = mPos.scale * scale - mPos.scale; mScaleBy = mPos.scale * scale - mPos.scale;
mStartPos.scale = mPos.scale; mStartPos.scale = mPos.scale;
mStartPos.angle = mPos.angle; mStartPos.angle = mPos.angle;
mPivot.x = pivotX; mPivot.x = pivotX;
mPivot.y = pivotY; mPivot.y = pivotY;
mAnimScale = true; mState = ANIM_SCALE;
mAnimFling = false;
mAnimMove = false;
animStart(duration); animStart(duration);
} }
@ -128,7 +126,7 @@ public class MapAnimator {
} }
public synchronized void animateFling(int velocityX, int velocityY, public synchronized void animateFling(int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) { int minX, int maxX, int minY, int maxY) {
if (velocityX * velocityX + velocityY * velocityY < 2048) if (velocityX * velocityX + velocityY * velocityY < 2048)
return; return;
@ -147,54 +145,28 @@ public class MapAnimator {
FastMath.clamp(mVelocity.x, minX, maxX); FastMath.clamp(mVelocity.x, minX, maxX);
FastMath.clamp(mVelocity.y, minY, maxY); FastMath.clamp(mVelocity.y, minY, maxY);
mAnimFling = true; mState = ANIM_FLING;
mAnimMove = false;
mAnimScale = false;
animStart(duration); animStart(duration);
} }
private void animStart(float duration) { private void animStart(float duration) {
mDuration = duration; mDuration = duration;
mAnimEnd = System.currentTimeMillis() + (long) duration; mAnimEnd = System.currentTimeMillis() + (long) duration;
mMap.render(); mMap.render();
} }
private void animCancel() { private void animCancel() {
mAnimEnd = -1; mState = ANIM_NONE;
mAnimScale = false;
mAnimFling = false;
mAnimMove = false;
mPivot.x = 0; mPivot.x = 0;
mPivot.y = 0; mPivot.y = 0;
} }
private boolean fling(float adv) {
synchronized (mViewport) {
adv = (float) Math.sqrt(adv);
double dx = mVelocity.x * adv;
double dy = mVelocity.y * adv;
if (dx == 0 && dy == 0)
return false;
mViewport.moveMap((float) (dx - mScroll.x), (float) (dy - mScroll.y));
mScroll.x = dx;
mScroll.y = dy;
}
return true;
}
/** /**
* called by GLRenderer at begin of each frame. * called by GLRenderer at begin of each frame.
*/ */
public void updateAnimation() { public void updateAnimation() {
if (mAnimEnd < 0) if (mState == ANIM_NONE)
return; return;
long millisLeft = mAnimEnd - System.currentTimeMillis(); long millisLeft = mAnimEnd - System.currentTimeMillis();
@ -210,17 +182,18 @@ public class MapAnimator {
if (millisLeft <= 0) { if (millisLeft <= 0) {
// set final position // set final position
if (mAnimMove && !mAnimFling) if ((mState & ANIM_MOVE) != 0)
mViewport.moveInternal(mStartPos.x + mDeltaPos.x, mStartPos.y + mDeltaPos.y); mViewport.moveInternal(mStartPos.x + mDeltaPos.x,
mStartPos.y + mDeltaPos.y);
if (mAnimScale) { if ((mState & ANIM_SCALE) != 0) {
if (mScaleBy > 0) if (mScaleBy > 0)
doScale(mStartPos.scale + (mScaleBy - 1)); doScale(mStartPos.scale + (mScaleBy - 1));
else else
doScale(mStartPos.scale + mScaleBy); doScale(mStartPos.scale + mScaleBy);
} }
mMap.updateMap(true);
mMap.updateMap(true);
animCancel(); animCancel();
return; return;
} }
@ -229,7 +202,7 @@ public class MapAnimator {
float adv = (1.0f - millisLeft / mDuration); float adv = (1.0f - millisLeft / mDuration);
if (mAnimScale) { if ((mState & ANIM_SCALE) != 0) {
if (mScaleBy > 0) if (mScaleBy > 0)
doScale(mStartPos.scale + (mScaleBy * (Math.pow(2, adv) - 1))); doScale(mStartPos.scale + (mScaleBy * (Math.pow(2, adv) - 1)));
else else
@ -238,11 +211,9 @@ public class MapAnimator {
changed = true; changed = true;
} }
if (mAnimMove) { if ((mState & ANIM_MOVE) != 0) {
mViewport.moveInternal( mViewport.moveInternal(mStartPos.x + mDeltaPos.x * adv,
mStartPos.x + mDeltaPos.x * adv, mStartPos.y + mDeltaPos.y * adv);
mStartPos.y + mDeltaPos.y * adv);
changed = true; changed = true;
} }
@ -251,12 +222,22 @@ public class MapAnimator {
// updateMatrix(); // updateMatrix();
//} //}
if (mAnimFling && fling(adv)) if ((mState & ANIM_FLING) != 0) {
changed = true; adv = (float) Math.sqrt(adv);
double dx = mVelocity.x * adv;
double dy = mVelocity.y * adv;
if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) {
mViewport.moveMap((float) (dx - mScroll.x), (float) (dy - mScroll.y));
mScroll.x = dx;
mScroll.y = dy;
changed = true;
}
}
// continue animation // continue animation
if (changed) { if (changed) {
// inform other layers that position has changed // render and inform layers that position has changed
mMap.updateMap(true); mMap.updateMap(true);
} else { } else {
// just render next frame // just render next frame
@ -269,6 +250,7 @@ public class MapAnimator {
} }
private void doScale(double newScale) { private void doScale(double newScale) {
mViewport.scaleMap((float) (newScale / mPos.scale), (float)mPivot.x, (float)mPivot.y); mViewport.scaleMap((float) (newScale / mPos.scale),
(float) mPivot.x, (float) mPivot.y);
} }
} }

View File

@ -82,7 +82,7 @@ public class Viewport {
float[] tmp = new float[16]; float[] tmp = new float[16];
Matrix4.frustumM(tmp, 0, -s, s, Matrix4.frustumM(tmp, 0, -s, s,
aspect * s, -aspect * s, VIEW_NEAR, VIEW_FAR); aspect * s, -aspect * s, VIEW_NEAR, VIEW_FAR);
mProjMatrix.set(tmp); mProjMatrix.set(tmp);
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE); mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
@ -107,10 +107,10 @@ public class Viewport {
public synchronized boolean getMapPosition(MapPosition pos) { public synchronized boolean getMapPosition(MapPosition pos) {
boolean changed = (pos.scale != mPos.scale boolean changed = (pos.scale != mPos.scale
|| pos.x != mPos.x || pos.x != mPos.x
|| pos.y != mPos.y || pos.y != mPos.y
|| pos.angle != mPos.angle || pos.angle != mPos.angle
|| pos.tilt != mPos.tilt); || pos.tilt != mPos.tilt);
pos.angle = mPos.angle; pos.angle = mPos.angle;
pos.tilt = mPos.tilt; pos.tilt = mPos.tilt;
@ -295,8 +295,8 @@ public class Viewport {
public synchronized GeoPoint fromScreenPoint(float x, float y) { public synchronized GeoPoint fromScreenPoint(float x, float y) {
fromScreenPoint(x, y, mMovePoint); fromScreenPoint(x, y, mMovePoint);
return new GeoPoint( return new GeoPoint(
MercatorProjection.toLatitude(mMovePoint.y), MercatorProjection.toLatitude(mMovePoint.y),
MercatorProjection.toLongitude(mMovePoint.x)); MercatorProjection.toLongitude(mMovePoint.x));
} }
/** /**
@ -423,19 +423,18 @@ public class Viewport {
Point p = applyRotation(mx, my); Point p = applyRotation(mx, my);
double tileScale = mPos.scale * Tile.SIZE; double tileScale = mPos.scale * Tile.SIZE;
moveBy(p.x / tileScale, p.y / tileScale); moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale);
} }
/* used by MapAnimator */ /* used by MapAnimator */
void moveInternal(double mx, double my) { void moveInternal(double mx, double my) {
Point p = applyRotation(mx, my); Point p = applyRotation(mx, my);
moveBy(p.x, p.y); moveTo(p.x, p.y);
} }
/* used by MapAnimator */ private void moveTo(double x, double y) {
void moveBy(double mx, double my) { mPos.x = x;
mPos.x -= mx; mPos.y = y;
mPos.y -= my;
// clamp latitude // clamp latitude
mPos.y = FastMath.clamp(mPos.y, 0, 1); mPos.y = FastMath.clamp(mPos.y, 0, 1);
@ -447,7 +446,7 @@ public class Viewport {
mPos.x += 1; mPos.x += 1;
} }
Point applyRotation(double mx, double my) { private Point applyRotation(double mx, double my) {
if (mPos.angle == 0) { if (mPos.angle == 0) {
mMovePoint.x = mx; mMovePoint.x = mx;
mMovePoint.y = my; mMovePoint.y = my;
@ -489,7 +488,7 @@ public class Viewport {
if (pivotX != 0 || pivotY != 0) if (pivotX != 0 || pivotY != 0)
moveMap(pivotX * (1.0f - scale), moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale)); pivotY * (1.0f - scale));
return true; return true;
} }