/*
* Copyright (C) 2013-2015 F(X)yz,
* Sean Phillips, Jason Pollastrini and Jose Pereda
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fxyz.cameras.controllers;
import org.fxyz.utils.AnimationPreference;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import org.fxyz.utils.MathUtils;
/**
*
* @author Dub
*/
public class FPSController extends CameraController {
private boolean fwd, strafeL, strafeR, back, up, down, shift, mouseLookEnabled;
private double speed = 1.0;
private final double maxSpeed = 5.0, minSpeed = 1.0;
public FPSController() {
super(true, AnimationPreference.TIMER);
}
@Override
public void update() {
if (fwd && !back) {
moveForward();
}
if (strafeL) {
strafeLeft();
}
if (strafeR) {
strafeRight();
}
if (back && !fwd) {
moveBack();
}
if (up && !down) {
moveUp();
}
if (down && !up) {
moveDown();
}
}
@Override
public void handleKeyEvent(KeyEvent event, boolean handle) {
if (event.getEventType() == KeyEvent.KEY_PRESSED) {
switch (event.getCode()) {
case W:
fwd = true;
break;
case S:
back = true;
break;
case A:
strafeL = true;
break;
case D:
strafeR = true;
break;
case SHIFT:
shift = true;
if(up || down){
break;
}
speed = maxSpeed;
break;
case SPACE:
if (!shift) {
up = true;
} else if (shift) {
down = true;
}
break;
}
} else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
switch (event.getCode()) {
case W:
fwd = false;
break;
case S:
back = false;
break;
case A:
strafeL = false;
break;
case D:
strafeR = false;
break;
case SHIFT:
speed = minSpeed;
shift = false;
break;
case SPACE:
up = false;
down = false;
break;
}
}
}
@Override
protected void handlePrimaryMouseDrag(MouseEvent event, Point2D dragDelta, double modifier) {
if (!mouseLookEnabled) {
t.setX(getPosition().getX());
t.setY(getPosition().getY());
t.setZ(getPosition().getZ());
affine.setToIdentity();
rotateY.setAngle(
MathUtils.clamp(((rotateY.getAngle() + dragDelta.getX() * (1.0 * 0.25)) % 360 + 540) % 360 - 180, -360, 360)
); // horizontal
rotateX.setAngle(
MathUtils.clamp(((rotateX.getAngle() - dragDelta.getY() * (1.0 * 0.25)) % 360 + 540) % 360 - 180, -90, 90)
); // vertical
affine.prepend(t.createConcatenation(rotateY.createConcatenation(rotateX)));
}
}
@Override
protected void handleMiddleMouseDrag(MouseEvent event, Point2D dragDelta, double modifier) {
// do nothing for now
}
@Override
protected void handleSecondaryMouseDrag(MouseEvent event, Point2D dragDelta, double modifier) {
// do nothing for now
}
@Override
protected void handleMouseMoved(MouseEvent event, Point2D moveDelta, double speed) {
if (mouseLookEnabled) {
t.setX(getPosition().getX());
t.setY(getPosition().getY());
t.setZ(getPosition().getZ());
affine.setToIdentity();
rotateY.setAngle(
MathUtils.clamp(((rotateY.getAngle() + moveDelta.getX() * (speed * 0.05)) % 360 + 540) % 360 - 180, -360, 360)
); // horizontal
rotateX.setAngle(
MathUtils.clamp(((rotateX.getAngle() - moveDelta.getY() * (speed * 0.05)) % 360 + 540) % 360 - 180, -90, 90)
); // vertical
affine.prepend(t.createConcatenation(rotateY.createConcatenation(rotateX)));
}
}
@Override
protected void handleScrollEvent(ScrollEvent event) {
//do nothing for now, use for Zoom?
}
@Override
protected double getSpeedModifier(KeyEvent event) {
return speed;
}
@Override
public Node getTransformableNode() {
if (getCamera() != null) {
return getCamera();
} else {
throw new UnsupportedOperationException("Must have a Camera");
}
}
private void moveForward() {
affine.setTx(getPosition().getX() + speed * getForwardMatrixRow().x);
affine.setTy(getPosition().getY() + speed * getForwardMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * getForwardMatrixRow().z);
}
private void strafeLeft() {
affine.setTx(getPosition().getX() + speed * -getRightMatrixRow().x);
affine.setTy(getPosition().getY() + speed * -getRightMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * -getRightMatrixRow().z);
}
private void strafeRight() {
affine.setTx(getPosition().getX() + speed * getRightMatrixRow().x);
affine.setTy(getPosition().getY() + speed * getRightMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * getRightMatrixRow().z);
}
private void moveBack() {
affine.setTx(getPosition().getX() + speed * -getForwardMatrixRow().x);
affine.setTy(getPosition().getY() + speed * -getForwardMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * -getForwardMatrixRow().z);
}
private void moveUp() {
affine.setTx(getPosition().getX() + speed * -getUpMatrixRow().x);
affine.setTy(getPosition().getY() + speed * -getUpMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * -getUpMatrixRow().z);
}
private void moveDown() {
affine.setTx(getPosition().getX() + speed * getUpMatrixRow().x);
affine.setTy(getPosition().getY() + speed * getUpMatrixRow().y);
affine.setTz(getPosition().getZ() + speed * getUpMatrixRow().z);
}
public void setMouseLookEnabled(boolean b) {
mouseLookEnabled = b;
}
@Override
protected void handlePrimaryMouseClick(MouseEvent t) {
//System.out.println("Primary Button Clicked!");
}
@Override
protected void handleMiddleMouseClick(MouseEvent t) {
//System.out.println("Middle Button Clicked!");
}
@Override
protected void handleSecondaryMouseClick(MouseEvent t) {
//System.out.println("Secondary Button Clicked!");
}
@Override
protected void handlePrimaryMousePress(MouseEvent e) {
}
@Override
protected void handleSecondaryMousePress(MouseEvent e) {
}
@Override
protected void handleMiddleMousePress(MouseEvent e) {
}
@Override
protected void updateTransition(double now) {
}
}