/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.pancho3.controller.eventhandlers; import android.view.MotionEvent; import ch.ethz.dcg.jukefox.commons.utils.Pair; import ch.ethz.dcg.pancho3.view.tabs.opengl.MapRenderer; public class MapMultiTouchEventHandler { private float multiTouchPosX1 = -1; private float multiTouchPosX2 = -1; private float multiTouchPosY1 = -1; private float multiTouchPosY2 = -1; private float multiTouchDist = -1; private float startCamPosY = -1; private float startCamPosX = -1; private float startCamPosZ = -1; private float[] targetCamPosXY = null; private boolean inMultiTouch = false; private final MapRenderer mapRenderer; private final MapEventListener mapEventListener; private final boolean allowMultiTouchPanning; public MapMultiTouchEventHandler(MapRenderer mapRenderer, MapEventListener mapEventListener, boolean allowMultiTouchPanning) { this.mapRenderer = mapRenderer; this.mapEventListener = mapEventListener; this.allowMultiTouchPanning = allowMultiTouchPanning; } public boolean handleEvent(MotionEvent event) { if (event.getPointerCount() <= 1) { if (inMultiTouch) { // before we had two touch points // set start position of single touch event handler such that // the camera position keeps the same. mapEventListener.multiTouchFinished(event); inMultiTouch = false; return true; } inMultiTouch = false; // Let the normal touch handler handle the event return false; } // now we are in a multitouch event => set time used above inMultiTouch = true; mapEventListener.cancelRegionSelectHoldTimeTimer(); if (event.getAction() == MotionEvent.ACTION_POINTER_1_DOWN || event.getAction() == MotionEvent.ACTION_POINTER_2_DOWN) { // persHelper.mEventHandler.setClickTime(System.currentTimeMillis()); multiTouchPosX1 = event.getX(0); multiTouchPosY1 = event.getY(0); multiTouchPosX2 = event.getX(1); multiTouchPosY2 = event.getY(1); float diffX = multiTouchPosX1 - multiTouchPosX2; float diffY = multiTouchPosY1 - multiTouchPosY2; startCamPosY = mapRenderer.getCamera().getPosY(); // height startCamPosX = mapRenderer.getCamera().getPosX(); startCamPosZ = mapRenderer.getCamera().getPosZ(); multiTouchDist = (float) Math.sqrt(diffX * diffX + diffY * diffY); float[] screenXY = new float[2]; screenXY[0] = (event.getX(0) + event.getX(1)) / 2; screenXY[1] = (event.getY(0) + event.getY(1)) / 2; targetCamPosXY = getModelCoordsXY(screenXY, startCamPosX, startCamPosY, startCamPosZ); } float dX = event.getX(0) - event.getX(1); float dY = event.getY(0) - event.getY(1); float dist = (float) Math.sqrt(dX * dX + dY * dY); float ratio = multiTouchDist / dist; float newCamPosY = startCamPosY * ratio; // height // Do ugly offset correction // newCamPosY = newCamPosY - // activity.getMapRenderer().getCamera().getPosY(); // newCamPosY /= 4; // newCamPosY += activity.getMapRenderer().getCamera().getPosZ(); // persHelper.mPersRenderer.setZoomByZPos(newCamPosY); float diffX = (targetCamPosXY[0] - startCamPosX) * (1 - ratio); float diffZ = (targetCamPosXY[1] - startCamPosZ) * (1 - ratio); // persHelper.mViewSettings.posX = startCamPosX + diffX; // persHelper.mViewSettings.posZ = startCamPosZ + diffZ; float deltaX = 0; float deltaZ = 0; deltaX = (event.getX(0) + event.getX(1) - multiTouchPosX1 - multiTouchPosX2) / 2; deltaZ = (event.getY(0) + event.getY(1) - multiTouchPosY1 - multiTouchPosY2) / 2; Pair<Float, Float> cameraMovementDiff = MapEventListener.GET_MOVEMENT_FACTOR(mapRenderer, deltaX, deltaZ); float cameraMovementDiffX = 0; float cameraMovementDiffY = 0; if (Math.abs(cameraMovementDiff.first) > 0.1 && allowMultiTouchPanning) { cameraMovementDiffX = cameraMovementDiff.first; } if (Math.abs(cameraMovementDiff.second) > 0.1 && allowMultiTouchPanning) { cameraMovementDiffY = cameraMovementDiff.second; } mapRenderer.getCamera().setCameraPosition(startCamPosX + diffX + cameraMovementDiffX, newCamPosY, startCamPosZ + diffZ + cameraMovementDiffY, false); return true; } public float[] getModelCoordsXY(float[] p, float camPosX, float camPosY, float camPosZ) { float widthFactor = mapRenderer.getViewRatio() / mapRenderer.getCamera().getFrontClippingPlane(); float heightFactor = 1f / mapRenderer.getCamera().getFrontClippingPlane(); float screenMinX = camPosX - camPosY * widthFactor; float screenMaxX = camPosX + camPosY * widthFactor; float screenMinZ = camPosZ - camPosY * heightFactor; float screenMaxZ = camPosZ + camPosY * heightFactor; float[] coords = new float[2]; coords[0] = screenMinX + (screenMaxX - screenMinX) / mapRenderer.getViewWidth() * p[0]; coords[1] = screenMinZ + (screenMaxZ - screenMinZ) / mapRenderer.getViewHeight() * p[1]; return coords; } }