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