Home | History | Annotate | Download | only in utils
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.scenes.scene2d.utils;
     18 
     19 import com.badlogic.gdx.input.GestureDetector;
     20 import com.badlogic.gdx.input.GestureDetector.GestureAdapter;
     21 import com.badlogic.gdx.math.Vector2;
     22 import com.badlogic.gdx.scenes.scene2d.Actor;
     23 import com.badlogic.gdx.scenes.scene2d.Event;
     24 import com.badlogic.gdx.scenes.scene2d.EventListener;
     25 import com.badlogic.gdx.scenes.scene2d.InputEvent;
     26 
     27 /** Detects tap, long press, fling, pan, zoom, and pinch gestures on an actor. If there is only a need to detect tap, use
     28  * {@link ClickListener}.
     29  * @see GestureDetector
     30  * @author Nathan Sweet */
     31 public class ActorGestureListener implements EventListener {
     32 	static final Vector2 tmpCoords = new Vector2(), tmpCoords2 = new Vector2();
     33 
     34 	private final GestureDetector detector;
     35 	InputEvent event;
     36 	Actor actor, touchDownTarget;
     37 
     38 	/** @see GestureDetector#GestureDetector(com.badlogic.gdx.input.GestureDetector.GestureListener) */
     39 	public ActorGestureListener () {
     40 		this(20, 0.4f, 1.1f, 0.15f);
     41 	}
     42 
     43 	/** @see GestureDetector#GestureDetector(float, float, float, float, com.badlogic.gdx.input.GestureDetector.GestureListener) */
     44 	public ActorGestureListener (float halfTapSquareSize, float tapCountInterval, float longPressDuration, float maxFlingDelay) {
     45 		detector = new GestureDetector(halfTapSquareSize, tapCountInterval, longPressDuration, maxFlingDelay, new GestureAdapter() {
     46 			private final Vector2 initialPointer1 = new Vector2(), initialPointer2 = new Vector2();
     47 			private final Vector2 pointer1 = new Vector2(), pointer2 = new Vector2();
     48 
     49 			public boolean tap (float stageX, float stageY, int count, int button) {
     50 				actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY));
     51 				ActorGestureListener.this.tap(event, tmpCoords.x, tmpCoords.y, count, button);
     52 				return true;
     53 			}
     54 
     55 			public boolean longPress (float stageX, float stageY) {
     56 				actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY));
     57 				return ActorGestureListener.this.longPress(actor, tmpCoords.x, tmpCoords.y);
     58 			}
     59 
     60 			public boolean fling (float velocityX, float velocityY, int button) {
     61 				stageToLocalAmount(tmpCoords.set(velocityX, velocityY));
     62 				ActorGestureListener.this.fling(event, tmpCoords.x, tmpCoords.y, button);
     63 				return true;
     64 			}
     65 
     66 			public boolean pan (float stageX, float stageY, float deltaX, float deltaY) {
     67 				stageToLocalAmount(tmpCoords.set(deltaX, deltaY));
     68 				deltaX = tmpCoords.x;
     69 				deltaY = tmpCoords.y;
     70 				actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY));
     71 				ActorGestureListener.this.pan(event, tmpCoords.x, tmpCoords.y, deltaX, deltaY);
     72 				return true;
     73 			}
     74 
     75 			public boolean zoom (float initialDistance, float distance) {
     76 				ActorGestureListener.this.zoom(event, initialDistance, distance);
     77 				return true;
     78 			}
     79 
     80 			public boolean pinch (Vector2 stageInitialPointer1, Vector2 stageInitialPointer2, Vector2 stagePointer1,
     81 				Vector2 stagePointer2) {
     82 				actor.stageToLocalCoordinates(initialPointer1.set(stageInitialPointer1));
     83 				actor.stageToLocalCoordinates(initialPointer2.set(stageInitialPointer2));
     84 				actor.stageToLocalCoordinates(pointer1.set(stagePointer1));
     85 				actor.stageToLocalCoordinates(pointer2.set(stagePointer2));
     86 				ActorGestureListener.this.pinch(event, initialPointer1, initialPointer2, pointer1, pointer2);
     87 				return true;
     88 			}
     89 
     90 			private void stageToLocalAmount (Vector2 amount) {
     91 				actor.stageToLocalCoordinates(amount);
     92 				amount.sub(actor.stageToLocalCoordinates(tmpCoords2.set(0, 0)));
     93 			}
     94 		});
     95 	}
     96 
     97 	public boolean handle (Event e) {
     98 		if (!(e instanceof InputEvent)) return false;
     99 		InputEvent event = (InputEvent)e;
    100 
    101 		switch (event.getType()) {
    102 		case touchDown:
    103 			actor = event.getListenerActor();
    104 			touchDownTarget = event.getTarget();
    105 			detector.touchDown(event.getStageX(), event.getStageY(), event.getPointer(), event.getButton());
    106 			actor.stageToLocalCoordinates(tmpCoords.set(event.getStageX(), event.getStageY()));
    107 			touchDown(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getButton());
    108 			return true;
    109 		case touchUp:
    110 			if (event.isTouchFocusCancel()) return false;
    111 			this.event = event;
    112 			actor = event.getListenerActor();
    113 			detector.touchUp(event.getStageX(), event.getStageY(), event.getPointer(), event.getButton());
    114 			actor.stageToLocalCoordinates(tmpCoords.set(event.getStageX(), event.getStageY()));
    115 			touchUp(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getButton());
    116 			return true;
    117 		case touchDragged:
    118 			this.event = event;
    119 			actor = event.getListenerActor();
    120 			detector.touchDragged(event.getStageX(), event.getStageY(), event.getPointer());
    121 			return true;
    122 		}
    123 		return false;
    124 	}
    125 
    126 	public void touchDown (InputEvent event, float x, float y, int pointer, int button) {
    127 	}
    128 
    129 	public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
    130 	}
    131 
    132 	public void tap (InputEvent event, float x, float y, int count, int button) {
    133 	}
    134 
    135 	/** If true is returned, additional gestures will not be triggered. No event is provided because this event is triggered by time
    136 	 * passing, not by an InputEvent. */
    137 	public boolean longPress (Actor actor, float x, float y) {
    138 		return false;
    139 	}
    140 
    141 	public void fling (InputEvent event, float velocityX, float velocityY, int button) {
    142 	}
    143 
    144 	/** The delta is the difference in stage coordinates since the last pan. */
    145 	public void pan (InputEvent event, float x, float y, float deltaX, float deltaY) {
    146 	}
    147 
    148 	public void zoom (InputEvent event, float initialDistance, float distance) {
    149 	}
    150 
    151 	public void pinch (InputEvent event, Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
    152 	}
    153 
    154 	public GestureDetector getGestureDetector () {
    155 		return detector;
    156 	}
    157 
    158 	public Actor getTouchDownTarget () {
    159 		return touchDownTarget;
    160 	}
    161 }
    162