package view;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.input.Mouse;
import com.threed.jpct.Camera;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.KeyMapper;
import com.threed.jpct.util.KeyState;
import config.GameConfig;
public class SpaceCamera2 {
private Camera camera;
private List<Object3D> sceneObjects;
private KeyMapper keyMapper;
private GameConfig config;
private float distance;
private boolean rotateMode;
private boolean PAGE_UP_PRESSED;
private boolean PAGE_DOWN_PRESSED;
private boolean UP_PRESSED;
private boolean DOWN_PRESSED;
private boolean LEFT_PRESSED;
private boolean RIGHT_PRESSED;
public SpaceCamera2(World world, GameConfig config){
setCamera(world.getCamera());
setDefaultScene();
keyMapper = new KeyMapper();
this.config = config;
distance = config.getDefaultCameraDist();
setDefaultPosition();
lookAtCenter();
}
private void lookAtCenter(){
camera.lookAt(new SimpleVector(0,0,0));
}
private void setDefaultScene(){
this.sceneObjects = new ArrayList<Object3D>();
}
private void setDefaultPosition(){
camera.setPosition(new SimpleVector(0, 0, distance));
}
/**
* Updates camera position by using mouse and keyboard
*/
public void update(){
handleKeys();
zoom();
rotate();
}
/**
* Rotates camera
*/
public void rotate(){
/*Checking if right mouse button is clicked and held*/
if(rotateMode && Mouse.isButtonDown(1)){
int dx = Mouse.getDX();
int dy = Mouse.getDY();
rotateSceneObjects(-dx,dy);
}
/*Checking if right mouse button was held and now released*/
else if(rotateMode && !Mouse.isButtonDown(1)){
rotateMode = false;
}
/*Checking if right mouse button is just clicked but not held*/
else if(!rotateMode && Mouse.isButtonDown(1)){
rotateMode = true;
}
/*Checking if some of arrow buttons is pushed*/
if(RIGHT_PRESSED){
rotateSceneObjects(-config.getDefaultRotateDx(), 0);
}
if(LEFT_PRESSED){
rotateSceneObjects(config.getDefaultRotateDx(), 0);
}
if(DOWN_PRESSED){
rotateSceneObjects(0, -config.getDefaultRotateDy());
}
if(UP_PRESSED){
rotateSceneObjects(0, config.getDefaultRotateDy());
}
}
private boolean checkDistanceLimits(float distance, float zoom){
float newDistance = distance - zoom;
if((Math.abs(newDistance) <= config.getMaxZoom() && Math.abs(newDistance) >= config.getMinZoom())){
distance = newDistance;
return true;
}
return false;
}
public void zoom(){
float zoom = Mouse.getDWheel()/100*config.getDefaultZoomDist();
if(checkDistanceLimits(distance, zoom)){
distance -= zoom;
}
setDefaultPosition();
if(PAGE_DOWN_PRESSED && checkDistanceLimits(distance, config.getDefaultZoomDist())){
distance += config.getDefaultZoomDist();
}
if(PAGE_UP_PRESSED && checkDistanceLimits(distance, config.getDefaultZoomDist())){
distance -= config.getDefaultZoomDist();
}
}
/**
* Checking if some keys were pressed or released
*/
public void handleKeys(){
KeyState state = null;
while((state = keyMapper.poll()) != KeyState.NONE){
int code = state.getKeyCode();
if(code == KeyEvent.VK_DOWN){
DOWN_PRESSED = state.getState();
}
else if(code == KeyEvent.VK_UP){
UP_PRESSED = state.getState();
}
else if(code == KeyEvent.VK_LEFT){
LEFT_PRESSED = state.getState();
}
else if(code == KeyEvent.VK_RIGHT){
RIGHT_PRESSED = state.getState();
}
else if(code == KeyEvent.VK_PAGE_DOWN){
PAGE_DOWN_PRESSED = state.getState();
}
else if(code == KeyEvent.VK_PAGE_UP){
PAGE_UP_PRESSED = state.getState();
}
}
}
/**
* Rotates all objects added to scene
* @param dx - it is change of horizontal position in 2D
* @param dy - it is change of vertical position in 2D
*/
public void rotateSceneObjects(int dx, int dy){
for(int i=0; i<sceneObjects.size(); i++){
sceneObjects.get(i).rotateX(config.getAnglePerPixel()*dy);
sceneObjects.get(i).rotateY(config.getAnglePerPixel()*dx);
}
}
public void addObjectToScene(Object3D object3D){
this.sceneObjects.add(object3D);
}
public Camera getCamera() {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
public List<Object3D> getSceneObjects() {
return sceneObjects;
}
public void setSceneObjects(List<Object3D> sceneObjects) {
this.sceneObjects = sceneObjects;
}
public float getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
}