/******************************************************************************* * Copyright 2011 See 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. ******************************************************************************/ package com.badlogic.gdx.scenes.scene2d.utils; import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.input.GestureDetector.GestureAdapter; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Event; import com.badlogic.gdx.scenes.scene2d.EventListener; import com.badlogic.gdx.scenes.scene2d.InputEvent; /** Detects tap, long press, fling, pan, zoom, and pinch gestures on an actor. If there is only a need to detect tap, use * {@link ClickListener}. * @see GestureDetector * @author Nathan Sweet */ public class ActorGestureListener implements EventListener { static final Vector2 tmpCoords = new Vector2(), tmpCoords2 = new Vector2(); private final GestureDetector detector; InputEvent event; Actor actor, touchDownTarget; /** @see GestureDetector#GestureDetector(com.badlogic.gdx.input.GestureDetector.GestureListener) */ public ActorGestureListener () { this(20, 0.4f, 1.1f, 0.15f); } /** @see GestureDetector#GestureDetector(float, float, float, float, com.badlogic.gdx.input.GestureDetector.GestureListener) */ public ActorGestureListener (float halfTapSquareSize, float tapCountInterval, float longPressDuration, float maxFlingDelay) { detector = new GestureDetector(halfTapSquareSize, tapCountInterval, longPressDuration, maxFlingDelay, new GestureAdapter() { private final Vector2 initialPointer1 = new Vector2(), initialPointer2 = new Vector2(); private final Vector2 pointer1 = new Vector2(), pointer2 = new Vector2(); public boolean tap (float stageX, float stageY, int count, int button) { actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY)); ActorGestureListener.this.tap(event, tmpCoords.x, tmpCoords.y, count, button); return true; } public boolean longPress (float stageX, float stageY) { actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY)); return ActorGestureListener.this.longPress(actor, tmpCoords.x, tmpCoords.y); } public boolean fling (float velocityX, float velocityY, int button) { stageToLocalAmount(tmpCoords.set(velocityX, velocityY)); ActorGestureListener.this.fling(event, tmpCoords.x, tmpCoords.y, button); return true; } public boolean pan (float stageX, float stageY, float deltaX, float deltaY) { stageToLocalAmount(tmpCoords.set(deltaX, deltaY)); deltaX = tmpCoords.x; deltaY = tmpCoords.y; actor.stageToLocalCoordinates(tmpCoords.set(stageX, stageY)); ActorGestureListener.this.pan(event, tmpCoords.x, tmpCoords.y, deltaX, deltaY); return true; } public boolean zoom (float initialDistance, float distance) { ActorGestureListener.this.zoom(event, initialDistance, distance); return true; } public boolean pinch (Vector2 stageInitialPointer1, Vector2 stageInitialPointer2, Vector2 stagePointer1, Vector2 stagePointer2) { actor.stageToLocalCoordinates(initialPointer1.set(stageInitialPointer1)); actor.stageToLocalCoordinates(initialPointer2.set(stageInitialPointer2)); actor.stageToLocalCoordinates(pointer1.set(stagePointer1)); actor.stageToLocalCoordinates(pointer2.set(stagePointer2)); ActorGestureListener.this.pinch(event, initialPointer1, initialPointer2, pointer1, pointer2); return true; } private void stageToLocalAmount (Vector2 amount) { actor.stageToLocalCoordinates(amount); amount.sub(actor.stageToLocalCoordinates(tmpCoords2.set(0, 0))); } }); } public boolean handle (Event e) { if (!(e instanceof InputEvent)) return false; InputEvent event = (InputEvent)e; switch (event.getType()) { case touchDown: actor = event.getListenerActor(); touchDownTarget = event.getTarget(); detector.touchDown(event.getStageX(), event.getStageY(), event.getPointer(), event.getButton()); actor.stageToLocalCoordinates(tmpCoords.set(event.getStageX(), event.getStageY())); touchDown(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getButton()); return true; case touchUp: if (event.isTouchFocusCancel()) return false; this.event = event; actor = event.getListenerActor(); detector.touchUp(event.getStageX(), event.getStageY(), event.getPointer(), event.getButton()); actor.stageToLocalCoordinates(tmpCoords.set(event.getStageX(), event.getStageY())); touchUp(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getButton()); return true; case touchDragged: this.event = event; actor = event.getListenerActor(); detector.touchDragged(event.getStageX(), event.getStageY(), event.getPointer()); return true; } return false; } public void touchDown (InputEvent event, float x, float y, int pointer, int button) { } public void touchUp (InputEvent event, float x, float y, int pointer, int button) { } public void tap (InputEvent event, float x, float y, int count, int button) { } /** If true is returned, additional gestures will not be triggered. No event is provided because this event is triggered by time * passing, not by an InputEvent. */ public boolean longPress (Actor actor, float x, float y) { return false; } public void fling (InputEvent event, float velocityX, float velocityY, int button) { } /** The delta is the difference in stage coordinates since the last pan. */ public void pan (InputEvent event, float x, float y, float deltaX, float deltaY) { } public void zoom (InputEvent event, float initialDistance, float distance) { } public void pinch (InputEvent event, Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) { } public GestureDetector getGestureDetector () { return detector; } public Actor getTouchDownTarget () { return touchDownTarget; } }