update map position animation at beginning of each frame
This commit is contained in:
parent
6cfc776911
commit
0a2bb1026e
@ -253,13 +253,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
// get current MapPosition, set mBoxCoords (mapping of screen to model
|
|
||||||
// coordinates)
|
|
||||||
MapPosition pos = mMapPosition;
|
MapPosition pos = mMapPosition;
|
||||||
|
|
||||||
synchronized (mMapViewPosition) {
|
synchronized (mMapViewPosition) {
|
||||||
|
// update MapPosition
|
||||||
mMapViewPosition.updateAnimation();
|
mMapViewPosition.updateAnimation();
|
||||||
|
|
||||||
|
// get current MapPosition
|
||||||
changed = mMapViewPosition.getMapPosition(pos);
|
changed = mMapViewPosition.getMapPosition(pos);
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
|
|||||||
@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.view;
|
package org.oscim.view;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import org.oscim.core.BoundingBox;
|
import org.oscim.core.BoundingBox;
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
@ -28,11 +26,7 @@ import org.oscim.utils.FastMath;
|
|||||||
import org.oscim.utils.Matrix4;
|
import org.oscim.utils.Matrix4;
|
||||||
|
|
||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
|
||||||
|
|
||||||
public class MapViewPosition {
|
public class MapViewPosition {
|
||||||
private static final String TAG = MapViewPosition.class.getName();
|
private static final String TAG = MapViewPosition.class.getName();
|
||||||
@ -90,8 +84,6 @@ public class MapViewPosition {
|
|||||||
// scale map plane at VIEW_DISTANCE to near plane
|
// scale map plane at VIEW_DISTANCE to near plane
|
||||||
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
||||||
|
|
||||||
private final AnimationHandler mHandler;
|
|
||||||
|
|
||||||
MapViewPosition(MapView mapView) {
|
MapViewPosition(MapView mapView) {
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
|
|
||||||
@ -103,8 +95,6 @@ public class MapViewPosition {
|
|||||||
mTilt = 0;
|
mTilt = 0;
|
||||||
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
|
|
||||||
mHandler = new AnimationHandler(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePosition() {
|
private void updatePosition() {
|
||||||
@ -433,10 +423,9 @@ public class MapViewPosition {
|
|||||||
*/
|
*/
|
||||||
public synchronized void moveMap(float mx, float my) {
|
public synchronized void moveMap(float mx, float my) {
|
||||||
// stop animation
|
// stop animation
|
||||||
mHandler.cancel();
|
animCancel();
|
||||||
|
|
||||||
PointD p = applyRotation(mx, my);
|
PointD p = applyRotation(mx, my);
|
||||||
|
|
||||||
move(p.x, p.y);
|
move(p.x, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +488,7 @@ public class MapViewPosition {
|
|||||||
*/
|
*/
|
||||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||||
// stop animation
|
// stop animation
|
||||||
mHandler.cancel();
|
animCancel();
|
||||||
|
|
||||||
// just sanitize input
|
// just sanitize input
|
||||||
scale = FastMath.clamp(scale, 0.5f, 2);
|
scale = FastMath.clamp(scale, 0.5f, 2);
|
||||||
@ -595,7 +584,7 @@ public class MapViewPosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
// TODO move to MapAnimator:
|
// TODO move to MapAnimator
|
||||||
|
|
||||||
private double mScrollX;
|
private double mScrollX;
|
||||||
private double mScrollY;
|
private double mScrollY;
|
||||||
@ -611,10 +600,11 @@ public class MapViewPosition {
|
|||||||
private float mDuration = 500;
|
private float mDuration = 500;
|
||||||
private final static double LOG4 = Math.log(4);
|
private final static double LOG4 = Math.log(4);
|
||||||
|
|
||||||
|
private long mAnimEnd = -1;
|
||||||
|
|
||||||
private boolean mAnimMove;
|
private boolean mAnimMove;
|
||||||
private boolean mAnimFling;
|
private boolean mAnimFling;
|
||||||
private boolean mAnimScale;
|
private boolean mAnimScale;
|
||||||
private final AccelerateDecelerateInterpolator mDecInterpolator = new AccelerateDecelerateInterpolator();
|
|
||||||
|
|
||||||
public synchronized void animateTo(BoundingBox bbox) {
|
public synchronized void animateTo(BoundingBox bbox) {
|
||||||
|
|
||||||
@ -656,9 +646,7 @@ public class MapViewPosition {
|
|||||||
mAnimMove = true;
|
mAnimMove = true;
|
||||||
mAnimScale = true;
|
mAnimScale = true;
|
||||||
mAnimFling = false;
|
mAnimFling = false;
|
||||||
mDuration = 500;
|
animStart(500);
|
||||||
|
|
||||||
mHandler.start((int) mDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void animateTo(GeoPoint geoPoint) {
|
public synchronized void animateTo(GeoPoint geoPoint) {
|
||||||
@ -676,23 +664,31 @@ public class MapViewPosition {
|
|||||||
mAnimMove = true;
|
mAnimMove = true;
|
||||||
mAnimScale = false;
|
mAnimScale = false;
|
||||||
mAnimFling = false;
|
mAnimFling = false;
|
||||||
|
animStart(300);
|
||||||
|
}
|
||||||
|
|
||||||
mDuration = 300;
|
private void animStart(float duration) {
|
||||||
mHandler.start(mDuration);
|
mDuration = duration;
|
||||||
|
|
||||||
|
mAnimEnd = System.currentTimeMillis() + (long) duration;
|
||||||
|
mMapView.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animCancel() {
|
||||||
|
mAnimEnd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized boolean fling(float adv) {
|
synchronized boolean fling(float adv) {
|
||||||
|
|
||||||
//float delta = (mDuration - millisLeft) / mDuration;
|
|
||||||
adv = (float) Math.sqrt(adv);
|
adv = (float) Math.sqrt(adv);
|
||||||
//adv = Interpolation.pow2Out.apply(adv);
|
|
||||||
float dx = mVelocityX * adv;
|
float dx = mVelocityX * adv;
|
||||||
float dy = mVelocityY * adv;
|
float dy = mVelocityY * adv;
|
||||||
|
|
||||||
if (dx != 0 || dy != 0) {
|
if (dx != 0 || dy != 0) {
|
||||||
moveMap((float) (dx - mScrollX), (float) (dy - mScrollY));
|
PointD p = applyRotation((float) (dx - mScrollX), (float) (dy - mScrollY));
|
||||||
|
move(p.x, p.y);
|
||||||
|
|
||||||
mMapView.redrawMap(true);
|
|
||||||
mScrollX = dx;
|
mScrollX = dx;
|
||||||
mScrollY = dy;
|
mScrollY = dy;
|
||||||
}
|
}
|
||||||
@ -705,55 +701,66 @@ public class MapViewPosition {
|
|||||||
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 < 3600)
|
if (velocityX * velocityX + velocityY * velocityY < 4096)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mScrollX = 0;
|
mScrollX = 0;
|
||||||
mScrollY = 0;
|
mScrollY = 0;
|
||||||
|
|
||||||
mDuration = 500;
|
float duration = 500;
|
||||||
|
|
||||||
mVelocityX = velocityX * (mDuration / 1000);
|
// pi times thumb..
|
||||||
mVelocityY = velocityY * (mDuration / 1000);
|
float flingFactor = (duration / 2500);
|
||||||
|
mVelocityX = velocityX * flingFactor;
|
||||||
|
mVelocityY = velocityY * flingFactor;
|
||||||
FastMath.clamp(mVelocityX, minX, maxX);
|
FastMath.clamp(mVelocityX, minX, maxX);
|
||||||
FastMath.clamp(mVelocityY, minY, maxY);
|
FastMath.clamp(mVelocityY, minY, maxY);
|
||||||
|
|
||||||
// mScroller.fling(0, 0, velocityX, velocityY, minX, maxX, minY, maxY);
|
|
||||||
mAnimFling = true;
|
mAnimFling = true;
|
||||||
mAnimMove = false;
|
mAnimMove = false;
|
||||||
mAnimScale = false;
|
mAnimScale = false;
|
||||||
|
animStart(duration);
|
||||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
|
|
||||||
|
|
||||||
mHandler.start(mDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void animateZoom(float scale) {
|
public synchronized void animateZoom(float scale) {
|
||||||
mStartScale = mAbsScale;
|
mStartScale = mAbsScale;
|
||||||
mEndScale = mAbsScale * scale - mAbsScale;
|
mEndScale = mAbsScale * scale - mAbsScale;
|
||||||
|
animStart(300);
|
||||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
|
|
||||||
|
|
||||||
mDuration = 300;
|
|
||||||
mHandler.start(mDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by GLRenderer at begin of each frame.
|
||||||
|
*/
|
||||||
public void updateAnimation() {
|
public void updateAnimation() {
|
||||||
//scroll();
|
if (mAnimEnd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long millisLeft = mAnimEnd - System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (millisLeft <= 0) {
|
||||||
|
// set final position
|
||||||
|
if (mAnimMove) {
|
||||||
|
moveAbs(mStartX + mEndX, mStartY + mEndY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAnimScale) {
|
||||||
|
mAbsScale = mStartScale + mEndScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePosition();
|
||||||
|
mMapView.redrawMap(true);
|
||||||
|
|
||||||
|
mAnimEnd = -1;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTick(long millisLeft) {
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
float adv = (1.0f - millisLeft / mDuration);
|
float adv = (1.0f - millisLeft / mDuration);
|
||||||
adv = mDecInterpolator.getInterpolation(adv);
|
|
||||||
|
|
||||||
if (mAnimScale) {
|
if (mAnimScale) {
|
||||||
if (mEndScale > 0)
|
if (mEndScale > 0)
|
||||||
// double s = (1 + adv * adv * mEndScale);
|
|
||||||
// mAbsScale = mStartScale * s;
|
|
||||||
// Log.d(TAG, "scale: " + s + " " + mAbsScale + " " + mStartScale);
|
|
||||||
//}
|
|
||||||
mAbsScale = mStartScale + (mEndScale * (Math.pow(2, adv) - 1));
|
mAbsScale = mStartScale + (mEndScale * (Math.pow(2, adv) - 1));
|
||||||
else
|
else
|
||||||
mAbsScale = mStartScale + (mEndScale * adv);
|
mAbsScale = mStartScale + (mEndScale * adv);
|
||||||
@ -778,96 +785,13 @@ public class MapViewPosition {
|
|||||||
if (mAnimFling && fling(adv))
|
if (mAnimFling && fling(adv))
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
if (changed)
|
// continue animation
|
||||||
|
if (changed) {
|
||||||
|
// inform other layers that position has changed
|
||||||
mMapView.redrawMap(true);
|
mMapView.redrawMap(true);
|
||||||
}
|
|
||||||
|
|
||||||
void onFinish() {
|
|
||||||
|
|
||||||
if (mAnimMove) {
|
|
||||||
moveAbs(mStartX + mEndX, mStartY + mEndY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAnimScale) {
|
|
||||||
mAbsScale = mStartScale + mEndScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePosition();
|
|
||||||
|
|
||||||
//mMapView.mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
|
||||||
|
|
||||||
mMapView.redrawMap(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* below is borrowed from CountDownTimer class:
|
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
|
||||||
*/
|
|
||||||
static class AnimationHandler extends Handler {
|
|
||||||
private final WeakReference<MapViewPosition> mMapViewPosition;
|
|
||||||
private static final int MSG = 1;
|
|
||||||
|
|
||||||
long mMillisInFuture;
|
|
||||||
|
|
||||||
long mInterval = 16;
|
|
||||||
|
|
||||||
long mStopTimeInFuture;
|
|
||||||
|
|
||||||
AnimationHandler(MapViewPosition mapAnimator) {
|
|
||||||
mMapViewPosition = new WeakReference<MapViewPosition>(mapAnimator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized final void start(float millis) {
|
|
||||||
mMillisInFuture = (int) millis;
|
|
||||||
MapViewPosition animator = mMapViewPosition.get();
|
|
||||||
if (animator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mMillisInFuture <= 0) {
|
|
||||||
animator.onFinish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
|
|
||||||
removeMessages(MSG);
|
|
||||||
sendMessage(obtainMessage(MSG));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void cancel() {
|
|
||||||
removeMessages(MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
MapViewPosition animator = mMapViewPosition.get();
|
|
||||||
if (animator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
final long millisLeft = mStopTimeInFuture
|
|
||||||
- SystemClock.elapsedRealtime();
|
|
||||||
|
|
||||||
if (millisLeft <= 0) {
|
|
||||||
animator.onFinish();
|
|
||||||
} else if (millisLeft < mInterval) {
|
|
||||||
// no tick, just delay until done
|
|
||||||
sendMessageDelayed(obtainMessage(MSG), millisLeft);
|
|
||||||
} else {
|
} else {
|
||||||
long lastTickStart = SystemClock.elapsedRealtime();
|
// just render next frame
|
||||||
animator.onTick(millisLeft);
|
mMapView.render();
|
||||||
|
|
||||||
// take into account user's onTick taking time to
|
|
||||||
// execute
|
|
||||||
long delay = lastTickStart + mInterval
|
|
||||||
- SystemClock.elapsedRealtime();
|
|
||||||
|
|
||||||
// special case: user's onTick took more than interval
|
|
||||||
// to
|
|
||||||
// complete, skip to next interval
|
|
||||||
while (delay < 0)
|
|
||||||
delay += mInterval;
|
|
||||||
|
|
||||||
sendMessageDelayed(obtainMessage(MSG), delay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user