From 7229d8d5962f8707bfa8cbc30b06b85e6f17d999 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 8 Jul 2013 11:48:35 +0200 Subject: [PATCH] move fling gesture detector to MapEventLayer --- .../android/input/AndroidMotionEvent.java | 5 + vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java | 51 +++++++- .../org/oscim/backend/input/MotionEvent.java | 2 + vtm/src/org/oscim/layers/InputLayer.java | 41 +++--- vtm/src/org/oscim/layers/MapEventLayer.java | 117 +++++++++++++++++- vtm/src/org/oscim/view/LayerManager.java | 63 ++++------ 6 files changed, 212 insertions(+), 67 deletions(-) diff --git a/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java b/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java index 3c3a0103..1db6c00a 100644 --- a/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java +++ b/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java @@ -52,5 +52,10 @@ public class AndroidMotionEvent extends MotionEvent { return mEvent.getPointerCount(); } + @Override + public long getTime() { + return mEvent.getEventTime(); + } + } diff --git a/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java b/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java index 76d85002..f50320b7 100644 --- a/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java +++ b/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java @@ -2,7 +2,10 @@ package org.oscim.gdx; import org.oscim.backend.input.MotionEvent; -public class GdxMotionEvent extends MotionEvent { +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.InputProcessor; + +public class GdxMotionEvent extends MotionEvent implements InputProcessor{ @Override public int getAction() { @@ -34,4 +37,50 @@ public class GdxMotionEvent extends MotionEvent { return 0; } + @Override + public long getTime() { + return 0; + } + + // -------- InputProcessor ---------- + @Override + public boolean keyDown(int keycode) { + return false; + } + + @Override + public boolean keyUp(int keycode) { + return false; + } + + @Override + public boolean keyTyped(char character) { + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + return false; + } + + @Override + public boolean scrolled(int amount) { + return false; + } + } diff --git a/vtm/src/org/oscim/backend/input/MotionEvent.java b/vtm/src/org/oscim/backend/input/MotionEvent.java index 39e7564d..2db18042 100644 --- a/vtm/src/org/oscim/backend/input/MotionEvent.java +++ b/vtm/src/org/oscim/backend/input/MotionEvent.java @@ -28,6 +28,8 @@ public abstract class MotionEvent { public static final int ACTION_POINTER_INDEX_MASK = 0xff00; public static final int ACTION_POINTER_INDEX_SHIFT = 8; + public abstract long getTime(); + public abstract int getAction(); public abstract float getX(); diff --git a/vtm/src/org/oscim/layers/InputLayer.java b/vtm/src/org/oscim/layers/InputLayer.java index b8dc4fb0..eb1aa01b 100644 --- a/vtm/src/org/oscim/layers/InputLayer.java +++ b/vtm/src/org/oscim/layers/InputLayer.java @@ -25,6 +25,7 @@ public abstract class InputLayer extends Layer { super(mapView); } + /** * By default does nothing (return false). If you handled the * Event, return true, otherwise return false. If @@ -146,26 +147,26 @@ public abstract class InputLayer extends Layer { return false; } - /** - * By default does nothing (return false). If you handled the - * Event, return true, otherwise return false. If - * you returned true none of the following Overlays or the - * underlying {@link MapView} has the chance to handle this event. - * - * @param pEvent1 - * ... - * @param pEvent2 - * ... - * @param pVelocityX - * ... - * @param pVelocityY - * ... - * @return ... - */ - public boolean onFling(MotionEvent pEvent1, MotionEvent pEvent2, - float pVelocityX, float pVelocityY) { - return false; - } + ///** + // * By default does nothing (return false). If you handled the + // * Event, return true, otherwise return false. If + // * you returned true none of the following Overlays or the + // * underlying {@link MapView} has the chance to handle this event. + // * + // * @param pEvent1 + // * ... + // * @param pEvent2 + // * ... + // * @param pVelocityX + // * ... + // * @param pVelocityY + // * ... + // * @return ... + // */ + //public boolean onFling(MotionEvent pEvent1, MotionEvent pEvent2, + // float pVelocityX, float pVelocityY) { + // return false; + //} /** * By default does nothing (return false). If you handled the diff --git a/vtm/src/org/oscim/layers/MapEventLayer.java b/vtm/src/org/oscim/layers/MapEventLayer.java index c6a382da..06540dbd 100644 --- a/vtm/src/org/oscim/layers/MapEventLayer.java +++ b/vtm/src/org/oscim/layers/MapEventLayer.java @@ -62,15 +62,20 @@ public class MapEventLayer extends InputLayer { protected static final float PINCH_TILT_THRESHOLD = 1f; private final MapViewPosition mMapPosition; + private final VelocityTracker mTracker; public MapEventLayer(MapView mapView) { super(mapView); mMapPosition = mapView.getMapViewPosition(); + mTracker = new VelocityTracker(); } + private long mPrevTime; @Override public boolean onTouchEvent(MotionEvent e) { + mPrevTime = e.getTime(); + int action = getAction(e); if (action == MotionEvent.ACTION_DOWN) { @@ -82,10 +87,13 @@ public class MapEventLayer extends InputLayer { mPrevX = e.getX(0); mPrevY = e.getY(0); - return true; //onActionDown(e); + + mTracker.start(mPrevX, mPrevY, e.getTime()); + return true; } else if (action == MotionEvent.ACTION_MOVE) { return onActionMove(e); } else if (action == MotionEvent.ACTION_UP) { + onFling(mTracker.getVelocityX(), mTracker.getVelocityY()); return true; } else if (action == MotionEvent.ACTION_CANCEL) { mDoubleTap = false; @@ -116,6 +124,8 @@ public class MapEventLayer extends InputLayer { float width = mMapView.getWidth(); float height = mMapView.getHeight(); + mTracker.update(x1, y1, e.getTime()); + // return if detect a new gesture, as indicated by a large jump if (Math.abs(mx) > JUMP_THRESHOLD || Math.abs(my) > JUMP_THRESHOLD) return true; @@ -133,6 +143,7 @@ public class MapEventLayer extends InputLayer { } if (e.getPointerCount() < 2) { + if (mx > 1 || mx < -1 || my > 1 || my < -1) { mMapPosition.moveMap(mx, my); mMapView.updateMap(true); @@ -281,9 +292,7 @@ public class MapEventLayer extends InputLayer { return false; } - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { + private boolean onFling(float velocityX, float velocityY) { if (mWasMulti) return true; @@ -303,7 +312,7 @@ public class MapEventLayer extends InputLayer { // float move = Math.min(mMapView.getWidth(), mMapView.getHeight()) * 2 / 3; // mMapPosition.animateTo(vx * move, vy * move, 250); //} else { - float s = (200 / CanvasAdapter.dpi); + float s = 1; //(200 / CanvasAdapter.dpi); mMapPosition.animateFling( Math.round(velocityX * s), @@ -320,4 +329,102 @@ public class MapEventLayer extends InputLayer { + " " + mBeginTilt); } + /******************************************************************************* + * Copyright 2011 See libgdx AUTHORS file. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + class VelocityTracker { + int sampleSize = 10; + float lastX, lastY; + float deltaX, deltaY; + long lastTime; + int numSamples; + float[] meanX = new float[sampleSize]; + float[] meanY = new float[sampleSize]; + long[] meanTime = new long[sampleSize]; + + public void start (float x, float y, long timeStamp) { + lastX = x; + lastY = y; + deltaX = 0; + deltaY = 0; + numSamples = 0; + for (int i = 0; i < sampleSize; i++) { + meanX[i] = 0; + meanY[i] = 0; + meanTime[i] = 0; + } + lastTime = timeStamp; + } + + public void update (float x, float y, long timeStamp) { + long currTime = timeStamp; + deltaX = x - lastX; + deltaY = y - lastY; + lastX = x; + lastY = y; + long deltaTime = currTime - lastTime; + lastTime = currTime; + int index = numSamples % sampleSize; + meanX[index] = deltaX; + meanY[index] = deltaY; + meanTime[index] = deltaTime; + numSamples++; + } + + public float getVelocityX () { + float meanX = getAverage(this.meanX, numSamples); + float meanTime = getAverage(this.meanTime, numSamples) / 1000.0f; + if (meanTime == 0) return 0; + return meanX / meanTime; + } + + public float getVelocityY () { + float meanY = getAverage(this.meanY, numSamples); + float meanTime = getAverage(this.meanTime, numSamples) / 1000.0f; + if (meanTime == 0) return 0; + return meanY / meanTime; + } + + private float getAverage (float[] values, int numSamples) { + numSamples = Math.min(sampleSize, numSamples); + float sum = 0; + for (int i = 0; i < numSamples; i++) { + sum += values[i]; + } + return sum / numSamples; + } + + private long getAverage (long[] values, int numSamples) { + numSamples = Math.min(sampleSize, numSamples); + long sum = 0; + for (int i = 0; i < numSamples; i++) { + sum += values[i]; + } + if (numSamples == 0) return 0; + return sum / numSamples; + } + + private float getSum (float[] values, int numSamples) { + numSamples = Math.min(sampleSize, numSamples); + float sum = 0; + for (int i = 0; i < numSamples; i++) { + sum += values[i]; + } + if (numSamples == 0) return 0; + return sum; + } + } + } diff --git a/vtm/src/org/oscim/view/LayerManager.java b/vtm/src/org/oscim/view/LayerManager.java index 9d146a4b..52d8c8e4 100644 --- a/vtm/src/org/oscim/view/LayerManager.java +++ b/vtm/src/org/oscim/view/LayerManager.java @@ -29,21 +29,14 @@ import org.oscim.layers.Layer; import org.oscim.layers.overlay.Overlay.Snappable; import org.oscim.renderer.RenderLayer; -public class LayerManager extends AbstractList - //implements OnGestureListener, - //OnDoubleTapListener - { +public class LayerManager extends AbstractList { private final static String TAG = LayerManager.class.getName(); private final static boolean debugInput = false; - //private final GestureDetector mGestureDetector; - private final CopyOnWriteArrayList mLayerList; LayerManager() { mLayerList = new CopyOnWriteArrayList(); - //mGestureDetector = new GestureDetector(context, this); - //mGestureDetector.setOnDoubleTapListener(this); } @Override @@ -109,7 +102,6 @@ public class LayerManager extends AbstractList } } - Layer[] mLayers; InputLayer[] mInputLayer; @@ -169,12 +161,12 @@ public class LayerManager extends AbstractList action == MotionEvent.ACTION_UP); } -// if (handleGesture) { -// if (mGestureDetector.onTouchEvent(e)) -// return true; -// -// mCancelGesture = false; -// } + // if (handleGesture) { + // if (mGestureDetector.onTouchEvent(e)) + // return true; + // + // mCancelGesture = false; + // } if (onTouchEvent(e)) return true; @@ -253,7 +245,6 @@ public class LayerManager extends AbstractList /* GestureDetector.OnDoubleTapListener */ - //@Override public boolean onDoubleTap(final MotionEvent e) { if (mDirtyLayers) @@ -269,7 +260,6 @@ public class LayerManager extends AbstractList return false; } - //@Override public boolean onDoubleTapEvent(final MotionEvent e) { if (mDirtyLayers) updateLayers(); @@ -284,7 +274,6 @@ public class LayerManager extends AbstractList return false; } - //@Override public boolean onSingleTapConfirmed(final MotionEvent e) { if (mDirtyLayers) updateLayers(); @@ -300,8 +289,6 @@ public class LayerManager extends AbstractList } /* OnGestureListener */ - - //@Override public boolean onDown(final MotionEvent pEvent) { if (mDirtyLayers) updateLayers(); @@ -316,23 +303,22 @@ public class LayerManager extends AbstractList return false; } - //@Override - public boolean onFling(final MotionEvent pEvent1, final MotionEvent pEvent2, - final float pVelocityX, final float pVelocityY) { - if (mDirtyLayers) - updateLayers(); + ////@Override + //public boolean onFling(final MotionEvent pEvent1, final MotionEvent pEvent2, + // final float pVelocityX, final float pVelocityY) { + // if (mDirtyLayers) + // updateLayers(); + // + // for (InputLayer o : mInputLayer) { + // if (o.onFling(pEvent1, pEvent2, pVelocityX, pVelocityY)) { + // if (debugInput) + // Log.d(TAG, "onFling\t" + o.getClass()); + // return true; + // } + // } + // return false; + //} - for (InputLayer o : mInputLayer) { - if (o.onFling(pEvent1, pEvent2, pVelocityX, pVelocityY)) { - if (debugInput) - Log.d(TAG, "onFling\t" + o.getClass()); - return true; - } - } - return false; - } - - //@Override public void onLongPress(final MotionEvent pEvent) { if (mCancelGesture) return; @@ -345,7 +331,6 @@ public class LayerManager extends AbstractList return; } - //@Override public boolean onScroll(final MotionEvent pEvent1, final MotionEvent pEvent2, final float pDistanceX, final float pDistanceY) { if (mDirtyLayers) @@ -361,7 +346,6 @@ public class LayerManager extends AbstractList return false; } - //@Override public void onShowPress(final MotionEvent pEvent) { if (mDirtyLayers) updateLayers(); @@ -371,7 +355,6 @@ public class LayerManager extends AbstractList } - //@Override public boolean onSingleTapUp(final MotionEvent pEvent) { if (mDirtyLayers) updateLayers(); @@ -386,8 +369,6 @@ public class LayerManager extends AbstractList return false; } - - // /** // * Gets the optional TilesLayer class. // *