/******************************************************************************* * 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 { 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(Vector2.tmp.set(stageX, stageY)); ActorGestureListener.this.tap(event, Vector2.tmp.x, Vector2.tmp.y, count, button); return true; } public boolean longPress(float stageX, float stageY) { actor.stageToLocalCoordinates(Vector2.tmp.set(stageX, stageY)); return ActorGestureListener.this.longPress(actor, Vector2.tmp.x, Vector2.tmp.y); } public boolean fling(float velocityX, float velocityY, int button) { ActorGestureListener.this.fling(event, velocityX, velocityY, button); return true; } public boolean pan(float stageX, float stageY, float deltaX, float deltaY) { actor.stageToLocalCoordinates(Vector2.tmp.set(stageX, stageY)); ActorGestureListener.this.pan(event, Vector2.tmp.x, Vector2.tmp.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; } }); } 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(Vector2.tmp.set(event.getStageX(), event.getStageY())); touchDown(event, Vector2.tmp.x, Vector2.tmp.y, event.getPointer(), event.getButton()); return true; case touchUp: this.event = event; actor = event.getListenerActor(); detector.touchUp(event.getStageX(), event.getStageY(), event.getPointer(), event.getButton()); actor.stageToLocalCoordinates(Vector2.tmp.set(event.getStageX(), event.getStageY())); touchUp(event, Vector2.tmp.x, Vector2.tmp.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; } }