Back to project page webots-remote-control.
The source code is released under:
GNU Lesser General Public License
If you think the Android project webots-remote-control listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package org.black_mesa.webots_remote_control.utils; //from w w w . j a v a 2 s . c o m import java.util.Timer; import java.util.TimerTask; import org.black_mesa.webots_remote_control.listeners.CameraTouchListenerV2; import android.os.SystemClock; import android.view.MotionEvent; /** * Handles the touch events on a CameraView. Interaction mode: 2 virtual joysticks. * * @author Ilja Kroonen */ public class CameraTouchHandlerV2 { private static final int TIMER_TICK = 32; private static final float LEFT_JOYSTICK_CENTER_X = .25f; private static final float LEFT_JOYSTICK_CENTER_Y = .5f; private static final float LEFT_JOYSTICK_RADIUS = .2f; private static final float RIGHT_JOYSTICK_CENTER_X = .75f; private static final float RIGHT_JOYSTICK_CENTER_Y = .5f; private static final float RIGHT_JOYSTICK_RADIUS = .2f; /* * Right joystick pointer id, coordinates and last timestamp. Valid if mRightValid is true. */ private boolean mRightValid = false; private int mRightPointerId; private float mRightPointerX; private float mRightPointerY; private long mRightTimeStamp; /* * Left joystick pointer id, coordinates. Valid if mLeftValid is true. */ private boolean mLeftValid = false; private int mLeftPointerId; private float mLeftPointerX; private float mLeftPointerY; /* * Timer used in state DOUBLE and ONLY_RIGHT. */ private Timer mTimer = new Timer(); /* * Information about the touching surface. */ private final float mXMin; private final float mYMin; private final float mXMax; private final float mYMax; private final float mLeftCenterX; private final float mLeftCenterY; private final float mLeftRadius; private final float mRightCenterX; private final float mRightCenterY; private final float mRightRadius; /* * Listener for the generated events */ private CameraTouchListenerV2 mListener; /** * Instantiates the CameraTouchHandler. * * @param xMin * Start of the x axis of the window. * @param yMin * Start of the y axis of the window. * @param xMax * End of the x axis of the window. * @param yMax * End of the y axis of the window. * @param l * Listener that will be notified of the actions that need to be performed on the camera. */ public CameraTouchHandlerV2(final float xMin, final float yMin, final float xMax, final float yMax, final CameraTouchListenerV2 l) { // TODO // Coordinate problem ? mXMin = 0; mYMin = 0; mXMax = xMax; mYMax = yMax; mLeftCenterX = LEFT_JOYSTICK_CENTER_X * (mXMax - mXMin) + mXMin; mLeftCenterY = LEFT_JOYSTICK_CENTER_Y * (mYMax - mYMin) + mYMin; mLeftRadius = LEFT_JOYSTICK_RADIUS * (mXMax - mXMin) + mXMin; mRightCenterX = RIGHT_JOYSTICK_CENTER_X * (mXMax - mXMin) + mXMin; mRightCenterY = RIGHT_JOYSTICK_CENTER_Y * (mYMax - mYMin) + mYMin; mRightRadius = RIGHT_JOYSTICK_RADIUS * (mXMax - mXMin) + mXMin; mListener = l; mListener.onJoystickLeftCoordinateChanged(mLeftCenterX, mLeftCenterY, 50); mListener.onJoystickRightCoordinateChanged(mRightCenterX, mRightCenterY, 50); } /** * Has to be called at each touch event on the view. * * @param event * MotionEvent that was generated by Android. */ public final void onTouch(final MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: downHandler(event); break; case MotionEvent.ACTION_CANCEL: cancelHandler(event); break; case MotionEvent.ACTION_UP: upHandler(event); break; case MotionEvent.ACTION_POINTER_DOWN: pointerDownHandler(event); break; case MotionEvent.ACTION_POINTER_UP: pointerUpHandler(event); break; case MotionEvent.ACTION_MOVE: moveHandler(event); break; } } private void moveHandler(final MotionEvent event) { updateState(event); if (mLeftValid) { onOrientationChange(event); } updateAttributes(event); } private void pointerUpHandler(final MotionEvent event) { int id = event.getPointerId(event.getActionIndex()); if (id == mRightPointerId) { changeRightState(false); } if (id == mLeftPointerId) { changeLeftState(false); } } private void pointerDownHandler(final MotionEvent event) { updateState(event); updateAttributes(event); } private void upHandler(final MotionEvent event) { changeLeftState(false); changeRightState(false); } private void cancelHandler(final MotionEvent event) { changeLeftState(false); changeRightState(false); } private void downHandler(final MotionEvent event) { updateState(event); updateAttributes(event); } private void timerHandler() { if (mRightValid) { onPositionChange(); } } private void updateAttributes(final MotionEvent event) { if (mRightValid) { int i = event.findPointerIndex(mRightPointerId); mRightPointerX = event.getX(i); mRightPointerY = event.getY(i); mRightTimeStamp = event.getEventTime(); mListener.onJoystickRightCoordinateChanged(mRightPointerX, mRightPointerY, 50); } if (mLeftValid) { int i = event.findPointerIndex(mLeftPointerId); mLeftPointerX = event.getX(i); mLeftPointerY = event.getY(i); mListener.onJoystickLeftCoordinateChanged(mLeftPointerX, mLeftPointerY, 50); } } private void updateState(final MotionEvent event) { boolean leftValid = mLeftValid; if (leftValid) { int index = event.findPointerIndex(mLeftPointerId); if (!isOnLeftJoystick(event, index)) { leftValid = false; } } if (!leftValid) { int index = findLeftJoystickPointerIndex(event); if (index != -1) { mLeftPointerId = event.getPointerId(index); leftValid = true; } } changeLeftState(leftValid); boolean rightValid = mRightValid; if (rightValid) { int index = event.findPointerIndex(mRightPointerId); if (!isOnRightJoystick(event, index)) { rightValid = false; } } if (!rightValid) { int index = findRightJoystickPointerIndex(event); if (index != -1) { mRightPointerId = event.getPointerId(index); rightValid = true; } } changeRightState(rightValid); } private void changeLeftState(final boolean newState) { mLeftValid = newState; if (!mLeftValid) { mListener.onJoystickLeftCoordinateChanged(mLeftCenterX, mLeftCenterY, 50); } } private void changeRightState(final boolean newState) { if (newState == mRightValid) { return; } if (!newState) { mTimer.cancel(); } if (newState) { mTimer = new Timer(); mTimer.schedule(makeTask(), 0, TIMER_TICK); } mRightValid = newState; if (!mRightValid) { mListener.onJoystickRightCoordinateChanged(mRightCenterX, mRightCenterY, 50); } } private boolean isOnLeftJoystick(final MotionEvent event, final int pointerIndex) { float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); float d = distance(x, y, mLeftCenterX, mLeftCenterY); return d < mLeftRadius; } private boolean isOnRightJoystick(final MotionEvent event, final int pointerIndex) { float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); float d = distance(x, y, mRightCenterX, mRightCenterY); return d < mRightRadius; } private float distance(final float x1, final float y1, final float x2, final float y2) { return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } private int findLeftJoystickPointerIndex(final MotionEvent event) { for (int i = 0; i < event.getPointerCount(); i++) { if (isOnLeftJoystick(event, i)) { return i; } } return -1; } private int findRightJoystickPointerIndex(final MotionEvent event) { for (int i = 0; i < event.getPointerCount(); i++) { if (isOnRightJoystick(event, i)) { return i; } } return -1; } private TimerTask makeTask() { return new TimerTask() { @Override public void run() { timerHandler(); } }; } private void onOrientationChange(final MotionEvent event) { int index = event.findPointerIndex(mLeftPointerId); float dx = (event.getX(index) - mLeftPointerX) / (mXMax - mXMin); float dy = (event.getY(index) - mLeftPointerY) / (mYMax - mYMin); mListener.turnPitch(dx, dy); } private void onPositionChange() { float x = (mRightPointerX - mRightCenterX) / (mXMax - mXMin); float y = (mRightPointerY - mRightCenterY) / (mYMax - mYMin); long now = SystemClock.uptimeMillis(); long time = now - mRightTimeStamp; mRightTimeStamp = now; mListener.moveRightForward(x, y, time); } }