com.badlogic.gdx.graphics.g3d.utils.CameraInputController Maven / Gradle / Ivy
/*******************************************************************************
* 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.graphics.g3d.utils;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
public class CameraInputController extends GestureDetector {
/** The button for rotating the camera. */
public int rotateButton = Buttons.LEFT;
/** The angle to rotate when moved the full width or height of the screen. */
public float rotateAngle = 360f;
/** The button for translating the camera along the up/right plane */
public int translateButton = Buttons.RIGHT;
/** The units to translate the camera when moved the full width or height of the screen. */
public float translateUnits = 10f; // FIXME auto calculate this based on the target
/** The button for translating the camera along the direction axis */
public int forwardButton = Buttons.MIDDLE;
/** The key which must be pressed to activate rotate, translate and forward or 0 to always activate. */
public int activateKey = 0;
/** Indicates if the activateKey is currently being pressed. */
protected boolean activatePressed;
/** Whether scrolling requires the activeKey to be pressed (false) or always allow scrolling (true). */
public boolean alwaysScroll = true;
/** The weight for each scrolled amount. */
public float scrollFactor = -0.1f;
/** World units per screen size */
public float pinchZoomFactor = 10f;
/** Whether to update the camera after it has been changed. */
public boolean autoUpdate = true;
/** The target to rotate around. */
public Vector3 target = new Vector3();
/** Whether to update the target on translation */
public boolean translateTarget = true;
/** Whether to update the target on forward */
public boolean forwardTarget = true;
/** Whether to update the target on scroll */
public boolean scrollTarget = false;
public int forwardKey = Keys.W;
protected boolean forwardPressed;
public int backwardKey = Keys.S;
protected boolean backwardPressed;
public int rotateRightKey = Keys.A;
protected boolean rotateRightPressed;
public int rotateLeftKey = Keys.D;
protected boolean rotateLeftPressed;
/** The camera. */
public Camera camera;
/** The current (first) button being pressed. */
protected int button = -1;
private float startX, startY;
private final Vector3 tmpV1 = new Vector3();
private final Vector3 tmpV2 = new Vector3();
protected static class CameraGestureListener extends GestureAdapter {
public CameraInputController controller;
private float previousZoom;
@Override
public boolean touchDown (float x, float y, int pointer, int button) {
previousZoom = 0;
return false;
}
@Override
public boolean tap (float x, float y, int count, int button) {
return false;
}
@Override
public boolean longPress (float x, float y) {
return false;
}
@Override
public boolean fling (float velocityX, float velocityY, int button) {
return false;
}
@Override
public boolean pan (float x, float y, float deltaX, float deltaY) {
return false;
}
@Override
public boolean zoom (float initialDistance, float distance) {
float newZoom = distance - initialDistance;
float amount = newZoom - previousZoom;
previousZoom = newZoom;
float w = Gdx.graphics.getWidth(), h = Gdx.graphics.getHeight();
return controller.pinchZoom(amount / ((w > h) ? h : w));
}
@Override
public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
return false;
}
};
protected final CameraGestureListener gestureListener;
protected CameraInputController (final CameraGestureListener gestureListener, final Camera camera) {
super(gestureListener);
this.gestureListener = gestureListener;
this.gestureListener.controller = this;
this.camera = camera;
}
public CameraInputController (final Camera camera) {
this(new CameraGestureListener(), camera);
}
public void update () {
if (rotateRightPressed || rotateLeftPressed || forwardPressed || backwardPressed) {
final float delta = Gdx.graphics.getDeltaTime();
if (rotateRightPressed) camera.rotate(camera.up, -delta * rotateAngle);
if (rotateLeftPressed) camera.rotate(camera.up, delta * rotateAngle);
if (forwardPressed) {
camera.translate(tmpV1.set(camera.direction).scl(delta * translateUnits));
if (forwardTarget) target.add(tmpV1);
}
if (backwardPressed) {
camera.translate(tmpV1.set(camera.direction).scl(-delta * translateUnits));
if (forwardTarget) target.add(tmpV1);
}
if (autoUpdate) camera.update();
}
}
private int touched;
private boolean multiTouch;
@Override
public boolean touchDown (int screenX, int screenY, int pointer, int button) {
touched |= (1 << pointer);
multiTouch = !MathUtils.isPowerOfTwo(touched);
if (multiTouch)
this.button = -1;
else if (this.button < 0 && (activateKey == 0 || activatePressed)) {
startX = screenX;
startY = screenY;
this.button = button;
}
return super.touchDown(screenX, screenY, pointer, button) || activatePressed;
}
@Override
public boolean touchUp (int screenX, int screenY, int pointer, int button) {
touched &= -1 ^ (1 << pointer);
multiTouch = !MathUtils.isPowerOfTwo(touched);
if (button == this.button) this.button = -1;
return super.touchUp(screenX, screenY, pointer, button) || activatePressed;
}
protected boolean process (float deltaX, float deltaY, int button) {
if (button == rotateButton) {
tmpV1.set(camera.direction).crs(camera.up).y = 0f;
camera.rotateAround(target, tmpV1.nor(), deltaY * rotateAngle);
camera.rotateAround(target, Vector3.Y, deltaX * -rotateAngle);
} else if (button == translateButton) {
camera.translate(tmpV1.set(camera.direction).crs(camera.up).nor().scl(-deltaX * translateUnits));
camera.translate(tmpV2.set(camera.up).scl(-deltaY * translateUnits));
if (translateTarget) target.add(tmpV1).add(tmpV2);
} else if (button == forwardButton) {
camera.translate(tmpV1.set(camera.direction).scl(deltaY * translateUnits));
if (forwardTarget) target.add(tmpV1);
}
if (autoUpdate) camera.update();
return true;
}
@Override
public boolean touchDragged (int screenX, int screenY, int pointer) {
boolean result = super.touchDragged(screenX, screenY, pointer);
if (result || this.button < 0) return result;
final float deltaX = (screenX - startX) / Gdx.graphics.getWidth();
final float deltaY = (startY - screenY) / Gdx.graphics.getHeight();
startX = screenX;
startY = screenY;
return process(deltaX, deltaY, button);
}
@Override
public boolean scrolled (int amount) {
return zoom(amount * scrollFactor * translateUnits);
}
public boolean zoom (float amount) {
if (!alwaysScroll && activateKey != 0 && !activatePressed) return false;
camera.translate(tmpV1.set(camera.direction).scl(amount));
if (scrollTarget) target.add(tmpV1);
if (autoUpdate) camera.update();
return true;
}
protected boolean pinchZoom (float amount) {
return zoom(pinchZoomFactor * amount);
}
@Override
public boolean keyDown (int keycode) {
if (keycode == activateKey) activatePressed = true;
if (keycode == forwardKey)
forwardPressed = true;
else if (keycode == backwardKey)
backwardPressed = true;
else if (keycode == rotateRightKey)
rotateRightPressed = true;
else if (keycode == rotateLeftKey) rotateLeftPressed = true;
return false;
}
@Override
public boolean keyUp (int keycode) {
if (keycode == activateKey) {
activatePressed = false;
button = -1;
}
if (keycode == forwardKey)
forwardPressed = false;
else if (keycode == backwardKey)
backwardPressed = false;
else if (keycode == rotateRightKey)
rotateRightPressed = false;
else if (keycode == rotateLeftKey) rotateLeftPressed = false;
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy