Merge branch '1273_Changing_Cameras' into 'develop'

1273 changing cameras

# Multiple Camera Views

## 3 Camera Views Implemented
1. Normal 3D (Isometric)
2. Top Down Perspective
3. Chase Cam (Over the Shoulder)

- Isometric and Top Down Perspectives can Pan within limits.
- Chase Cam rotates the camera around the boat. (While still following it)
- All camera views can Zoom.

# Testing

No testing completed other than manually testing myself. A proper manual test should be completed by the merger.

See merge request !76
This commit is contained in:
Michael Rausch
2017-09-26 18:36:59 +13:00
8 changed files with 487 additions and 41 deletions
+27 -1
View File
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import java.util.Timer;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.beans.property.ReadOnlyIntegerProperty; import javafx.beans.property.ReadOnlyIntegerProperty;
@@ -16,6 +17,7 @@ import javafx.scene.paint.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType; import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
/** /**
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses) * Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
@@ -57,12 +59,17 @@ public class ClientYacht extends Observable {
private Integer boatStatus; private Integer boatStatus;
private Double currentVelocity; private Double currentVelocity;
Timer t;
private BoatObject boatObject;
private List<YachtLocationListener> locationListeners = new ArrayList<>(); private List<YachtLocationListener> locationListeners = new ArrayList<>();
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>(); private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper(); private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper(); private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper(); private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper(); private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
private ReadOnlyDoubleWrapper headingProperty = new ReadOnlyDoubleWrapper();
private Color colour; private Color colour;
public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName, public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
@@ -75,6 +82,7 @@ public class ClientYacht extends Observable {
this.country = country; this.country = country;
this.location = new GeoPoint(57.670341, 11.826856); this.location = new GeoPoint(57.670341, 11.826856);
this.heading = 120.0; //In degrees this.heading = 120.0; //In degrees
this.headingProperty.set(this.heading);
this.currentVelocity = 0d; this.currentVelocity = 0d;
this.boatStatus = 1; this.boatStatus = 1;
this.colour = Color.rgb(0, 0, 0, 1.0); this.colour = Color.rgb(0, 0, 0, 1.0);
@@ -222,6 +230,7 @@ public class ClientYacht extends Observable {
public void setHeading(Double heading) { public void setHeading(Double heading) {
this.heading = heading; this.heading = heading;
setHeadingProperty();
} }
@Override @Override
@@ -250,10 +259,10 @@ public class ClientYacht extends Observable {
this.colour = colour; this.colour = colour;
} }
public void updateLocation(double lat, double lng, double heading, double velocity) { public void updateLocation(double lat, double lng, double heading, double velocity) {
setLocation(lat, lng); setLocation(lat, lng);
this.heading = heading; this.heading = heading;
setHeadingProperty();
this.currentVelocity = velocity; this.currentVelocity = velocity;
updateVelocityProperty(velocity); updateVelocityProperty(velocity);
for (YachtLocationListener yll : locationListeners) { for (YachtLocationListener yll : locationListeners) {
@@ -261,6 +270,10 @@ public class ClientYacht extends Observable {
} }
} }
private void setHeadingProperty() {
headingProperty.set(heading);
}
public void addLocationListener(YachtLocationListener listener) { public void addLocationListener(YachtLocationListener listener) {
locationListeners.add(listener); locationListeners.add(listener);
} }
@@ -289,4 +302,17 @@ public class ClientYacht extends Observable {
public Double getCurrentVelocity() { public Double getCurrentVelocity() {
return currentVelocity; return currentVelocity;
} }
public void setBoatObject(BoatObject newBoatObject) {
this.boatObject = newBoatObject;
}
public BoatObject getBoatObject() {
return this.boatObject;
}
public ReadOnlyDoubleWrapper getHeadingProperty() {
return headingProperty;
}
} }
@@ -52,6 +52,10 @@ public class GameKeyBind {
return instance.actionToKeyMap.get(keyAction); return instance.actionToKeyMap.get(keyAction);
} }
public KeyAction getKeyAction(KeyCode keyCode) {
return instance.keyToActionMap.get(keyCode);
}
/** /**
* Binds a key to a key action * Binds a key to a key action
* *
@@ -1,6 +1,7 @@
package seng302.visualiser; package seng302.visualiser;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -9,6 +10,7 @@ import javafx.animation.AnimationTimer;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.geometry.Point3D; import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.PerspectiveCamera; import javafx.scene.PerspectiveCamera;
@@ -21,7 +23,9 @@ import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate; import javafx.scene.transform.Translate;
import seng302.gameServer.messages.RoundingSide; import seng302.gameServer.messages.RoundingSide;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.GameKeyBind;
import seng302.model.GeoPoint; import seng302.model.GeoPoint;
import seng302.model.KeyAction;
import seng302.model.Limit; import seng302.model.Limit;
import seng302.model.mark.CompoundMark; import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner; import seng302.model.mark.Corner;
@@ -29,8 +33,12 @@ import seng302.model.mark.Mark;
import seng302.model.token.Token; import seng302.model.token.Token;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.utilities.Sounds; import seng302.utilities.Sounds;
import seng302.visualiser.cameras.ChaseCamera;
import seng302.visualiser.cameras.IsometricCamera;
import seng302.visualiser.cameras.RaceCamera;
import seng302.visualiser.cameras.TopDownCamera;
import seng302.visualiser.controllers.ViewManager;
import seng302.visualiser.fxObjects.MarkArrowFactory; import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatObject; import seng302.visualiser.fxObjects.assets_3D.BoatObject;
import seng302.visualiser.fxObjects.assets_3D.Marker3D; import seng302.visualiser.fxObjects.assets_3D.Marker3D;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory; import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
@@ -42,18 +50,19 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
public class GameView3D { public class GameView3D {
private final double FOV = 60; private final double FOV = 60;
private final double DEFAULT_CAMERA_DEPTH = -125;
private final double DEFAULT_CAMERA_X = 0; private final double DEFAULT_CAMERA_X = 0;
private final double DEFAULT_CAMERA_Y = 155; private final double DEFAULT_CAMERA_Y = 155;
private Group root3D; private Group root3D;
private SubScene view; private SubScene view;
// ParallelCamera camera;
private PerspectiveCamera camera;
private Group gameObjects; private Group gameObjects;
// Cameras
private PerspectiveCamera isometricCam;
private PerspectiveCamera topDownCam;
private PerspectiveCamera chaseCam;
private double bufferSize = 0; private double bufferSize = 0;
private double canvasWidth = 200; private double canvasWidth = 200;
private double canvasHeight = 200; private double canvasHeight = 200;
@@ -88,20 +97,22 @@ public class GameView3D {
} }
public GameView3D () { public GameView3D () {
camera = new PerspectiveCamera(true); isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y);
camera.getTransforms().addAll( topDownCam = new TopDownCamera();
new Translate(DEFAULT_CAMERA_X,DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH) chaseCam = new ChaseCamera();
);
camera.setFarClip(600); for (PerspectiveCamera pc : Arrays.asList(isometricCam, topDownCam, chaseCam)) {
camera.setNearClip(0.1); pc.setFarClip(600);
camera.setFieldOfView(FOV); pc.setNearClip(0.1);
pc.setFieldOfView(FOV);
}
gameObjects = new Group(); gameObjects = new Group();
root3D = new Group(camera, gameObjects); root3D = new Group(isometricCam, gameObjects);
view = new SubScene( view = new SubScene(
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
); );
view.setCamera(camera); view.setCamera(isometricCam);
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
gameObjects.getChildren().addAll( gameObjects.getChildren().addAll(
ModelFactory.importModel(ModelType.OCEAN).getAssets(), ModelFactory.importModel(ModelType.OCEAN).getAssets(),
@@ -112,6 +123,8 @@ public class GameView3D {
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement); scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement);
} }
}); });
} }
public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) { public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) {
@@ -336,7 +349,6 @@ public class GameView3D {
* it to distanceScaleFactor Returns the max horizontal distance of the map. * it to distanceScaleFactor Returns the max horizontal distance of the map.
*/ */
private double scaleRaceExtremities() { private double scaleRaceExtremities() {
double vertAngle = Math.abs( double vertAngle = Math.abs(
GeoUtility.getBearingRad(minLatPoint, maxLatPoint) GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
); );
@@ -404,40 +416,45 @@ public class GameView3D {
} }
public void cameraMovement(KeyEvent event) { public void cameraMovement(KeyEvent event) {
switch (event.getCode()) { GameKeyBind keyBinds = GameKeyBind.getInstance();
case NUMPAD8: KeyAction keyPressed = keyBinds.getKeyAction(event.getCode());
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(1,0,0))); switch (keyPressed) {
case ZOOM_IN:
((RaceCamera) view.getCamera()).zoomIn();
break; break;
case NUMPAD2: case ZOOM_OUT:
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(1,0,0))); ((RaceCamera) view.getCamera()).zoomOut();
break; break;
case NUMPAD4: case FORWARD:
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(0,1,0))); ((RaceCamera) view.getCamera()).panUp();
break; break;
case NUMPAD6: case BACKWARD:
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0))); ((RaceCamera) view.getCamera()).panDown();
break; break;
case Z: case LEFT:
camera.getTransforms().addAll(new Translate(0, 0, 1.5)); ((RaceCamera) view.getCamera()).panLeft();
break; break;
case X: case RIGHT:
camera.getTransforms().addAll(new Translate(0, 0, -1.5)); ((RaceCamera) view.getCamera()).panRight();
break; break;
case W: case VIEW:
camera.getTransforms().addAll(new Translate(0, -1, 0)); toggleCamera();
break;
case S:
camera.getTransforms().addAll(new Translate(0, 1, 0));
break;
case A:
camera.getTransforms().addAll(new Translate(-1, 0, 0));
break;
case D:
camera.getTransforms().addAll(new Translate(1, 0, 0));
break; break;
} }
} }
private void toggleCamera() {
Camera currCamera = view.getCamera();
if (currCamera.equals(isometricCam)) {
view.setCamera(topDownCam);
} else if (currCamera.equals(topDownCam)) {
view.setCamera(chaseCam);
} else {
view.setCamera(isometricCam);
}
}
/** /**
* Rescales the race to the size of the window. * Rescales the race to the size of the window.
* *
@@ -471,6 +488,12 @@ public class GameView3D {
Point2D p2d = findScaledXY(lat, lon); Point2D p2d = findScaledXY(lat, lon);
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir); bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
}); });
if (clientYacht.getSourceId().equals(
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
}
} }
Platform.runLater(() -> { Platform.runLater(() -> {
gameObjects.getChildren().addAll(wakes); gameObjects.getChildren().addAll(wakes);
@@ -0,0 +1,130 @@
package seng302.visualiser.cameras;
import java.util.Arrays;
import javafx.beans.property.DoubleProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Point3D;
import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
private final Double VERTICAL_PAN_LIMIT = 20.0;
private final Double NEAR_ZOOM_LIMIT = -15.0;
private final Double FAR_ZOOM_LIMIT = -125.0;
private final Double ZOOM_STEP = 2.5;
private final Double PAN_STEP = 2.5;
private ObservableList<Transform> transforms;
private BoatObject playerBoat;
private Double zoomFactor;
private Double horizontalPan;
private Double verticalPan;
public ChaseCamera() {
super(true);
transforms = this.getTransforms();
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
this.horizontalPan = 0.0;
this.verticalPan = 0.0;
}
/**
* Sets a player boat object to observe and update the camera with.
*
* @param playerBoat The player boat to be observed.
*/
public void setPlayerBoat(BoatObject playerBoat) {
this.playerBoat = playerBoat;
for (DoubleProperty o : Arrays
.asList(playerBoat.getRotationProperty(), playerBoat.layoutYProperty(),
playerBoat.layoutXProperty())) {
o.addListener((obs, oldVal, newVal) -> repositionCamera());
}
}
/**
* Moves the camera to a new position after some change (Zooming or Panning)
*/
private void repositionCamera() {
transforms.clear();
transforms.addAll(
new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), 0),
new Rotate(playerBoat.getRotationProperty().getValue() + horizontalPan,
new Point3D(0, 0, 1)),
new Rotate(60 + verticalPan, new Point3D(1, 0, 0)),
new Translate(0, 0, zoomFactor)
);
}
/**
* Adjusts the zoom amount (camera depth) by some adjustment value
* @param adjustment the adjustment to be made to the camera
*/
private void adjustZoomFactor(Double adjustment) {
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
zoomFactor = zoomFactor + adjustment;
repositionCamera();
}
}
/**
* Adjusts the Vertical Panning of the Camera
* @param adjustment the adjustment to be made to the camera
*/
private void adjustVerticalPan(Double adjustment) {
if (verticalPan + adjustment >= -VERTICAL_PAN_LIMIT
&& verticalPan + adjustment <= VERTICAL_PAN_LIMIT) {
verticalPan += adjustment;
repositionCamera();
}
}
/**
* Adjusts the Horizontal Panning of the Camera.
* @param adjustment the adjustment to be made to the camera
*/
private void adjustHorizontalPan(Double adjustment) {
this.horizontalPan += adjustment;
repositionCamera();
}
@Override
public void zoomIn() {
adjustZoomFactor(ZOOM_STEP);
}
@Override
public void zoomOut() {
adjustZoomFactor(-ZOOM_STEP);
}
@Override
public void panLeft() {
adjustHorizontalPan(-PAN_STEP);
}
@Override
public void panRight() {
adjustHorizontalPan(PAN_STEP);
}
@Override
public void panUp() {
adjustVerticalPan(-PAN_STEP);
}
@Override
public void panDown() {
adjustVerticalPan(PAN_STEP);
}
}
@@ -0,0 +1,113 @@
package seng302.visualiser.cameras;
import javafx.collections.ObservableList;
import javafx.geometry.Point3D;
import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
private final Double MIN_X = -120.0;
private final Double MAX_X = 125.0;
private final Double MIN_Y = 40.0;
private final Double MAX_Y = 170.0;
private final Double PAN_LIMIT = 160.0;
private final Double NEAR_ZOOM_LIMIT = -50.0;
private final Double FAR_ZOOM_LIMIT = -160.0;
private Double horizontalPan;
private Double verticalPan;
private Double zoomFactor;
private ObservableList<Transform> transforms;
public IsometricCamera(Double cameraStartX, Double cameraStartY) {
super(true);
transforms = this.getTransforms();
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
horizontalPan = cameraStartX;
verticalPan = cameraStartY;
updateCamera();
}
/**
* Moves the camera to a new position after some change (Zooming or Panning)
*/
private void updateCamera() {
transforms.clear();
transforms.addAll(
new Translate(horizontalPan, verticalPan, zoomFactor),
new Rotate(30, new Point3D(1, 0, 0))
);
}
/**
* Adjusts the zoom amount (camera depth) by some adjustment value
*
* @param adjustment the adjustment to be made to the camera
*/
private void adjustZoomFactor(Double adjustment) {
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
zoomFactor = zoomFactor + adjustment;
updateCamera();
}
}
/**
* Adjusts the Vertical Panning of the Camera
* @param adjustment the adjustment to be made to the camera
*/
private void adjustVerticalPan(Double adjustment) {
if (verticalPan + adjustment >= MIN_Y && verticalPan + adjustment <= MAX_Y) {
verticalPan += adjustment;
updateCamera();
}
}
/**
* Adjusts the Horizontal Panning of the Camera.
* @param adjustment the adjustment to be made to the camera
*/
private void adjustHorizontalPan(Double adjustment) {
if (horizontalPan + adjustment >= MIN_X && horizontalPan + adjustment <= MIN_Y) {
this.horizontalPan += adjustment;
updateCamera();
}
}
@Override
public void zoomIn() {
adjustZoomFactor(-2.5);
}
@Override
public void zoomOut() {
adjustZoomFactor(2.5);
}
@Override
public void panLeft() {
adjustHorizontalPan(-2.5);
}
@Override
public void panRight() {
adjustHorizontalPan(2.5);
}
@Override
public void panUp() {
adjustVerticalPan(-2.5);
}
@Override
public void panDown() {
adjustVerticalPan(2.5);
}
}
@@ -0,0 +1,18 @@
package seng302.visualiser.cameras;
public interface RaceCamera {
void zoomIn();
void zoomOut();
void panLeft();
void panRight();
void panUp();
void panDown();
}
@@ -0,0 +1,123 @@
package seng302.visualiser.cameras;
import java.util.Arrays;
import javafx.beans.property.DoubleProperty;
import javafx.collections.ObservableList;
import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
private final Double PAN_LIMIT = 30.0;
private final Double NEAR_ZOOM_LIMIT = -30.0;
private final Double FAR_ZOOM_LIMIT = -130.0;
private final Double ZOOM_STEP = 2.5;
private ObservableList<Transform> transforms;
private BoatObject playerBoat;
private Double zoomFactor;
private Double horizontalPan;
private Double verticalPan;
public TopDownCamera() {
super(true);
transforms = this.getTransforms();
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
horizontalPan = 0.0;
verticalPan = 0.0;
}
/**
* Sets a player boat object to observe and update the camera with.
*
* @param playerBoat The player boat to be observed.
*/
public void setPlayerBoat(BoatObject playerBoat) {
this.playerBoat = playerBoat;
for (DoubleProperty o : Arrays
.asList(playerBoat.layoutXProperty(), playerBoat.layoutYProperty())) {
o.addListener((obs, oldVal, newVal) -> updateCamera());
}
}
/**
* Moves the camera to a new position after some change (Zooming or Panning)
*/
private void updateCamera() {
transforms.clear();
transforms.addAll(
new Translate(playerBoat.getLayoutX() + horizontalPan,
playerBoat.getLayoutY() + verticalPan, zoomFactor)
);
}
/**
* Adjusts the zoom amount (camera depth) by some adjustment value
* @param adjustment the adjustment to be made to the camera
*/
private void adjustZoomFactor(Double adjustment) {
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
zoomFactor = zoomFactor + adjustment;
updateCamera();
}
}
/**
* Adjusts the Vertical Panning of the Camera
* @param adjustment the adjustment to be made to the camera
*/
private void adjustVerticalPan(Double adjustment) {
if (verticalPan + adjustment >= -PAN_LIMIT && verticalPan + adjustment <= PAN_LIMIT) {
verticalPan += adjustment;
updateCamera();
}
}
/**
* Adjusts the Horizontal Panning of the Camera.
* @param adjustment the adjustment to be made to the camera
*/
private void adjustHorizontalPan(Double adjustment) {
if (horizontalPan + adjustment >= -PAN_LIMIT && horizontalPan + adjustment <= PAN_LIMIT) {
horizontalPan += adjustment;
updateCamera();
}
}
@Override
public void zoomIn() {
adjustZoomFactor(ZOOM_STEP);
}
@Override
public void zoomOut() {
adjustZoomFactor(-ZOOM_STEP);
}
@Override
public void panLeft() {
adjustHorizontalPan(-1.0);
}
@Override
public void panRight() {
adjustHorizontalPan(1.0);
}
@Override
public void panUp() {
adjustVerticalPan(-1.0);
}
@Override
public void panDown() {
adjustVerticalPan(1.0);
}
}
@@ -3,6 +3,7 @@ package seng302.visualiser.fxObjects.assets_3D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.geometry.Point3D; import javafx.geometry.Point3D;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
@@ -30,12 +31,15 @@ public class BoatObject extends Group {
private Boolean isSelected = false; private Boolean isSelected = false;
private Rotate rotation = new Rotate(0, new Point3D(0,0,1)); private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
private ReadOnlyDoubleWrapper rotationProperty;
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>(); private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
/** /**
* Creates a BoatGroup with the default triangular boat polygon. * Creates a BoatGroup with the default triangular boat polygon.
*/ */
public BoatObject(BoatMeshType boatMeshType) { public BoatObject(BoatMeshType boatMeshType) {
rotationProperty = new ReadOnlyDoubleWrapper(0.0);
boatAssets = ModelFactory.boatGameView(boatMeshType, colour); boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
boatAssets.hideSail(); boatAssets.hideSail();
boatAssets.getAssets().getTransforms().addAll( boatAssets.getAssets().getTransforms().addAll(
@@ -83,6 +87,7 @@ public class BoatObject extends Group {
private void rotateTo(double heading, boolean sailsIn, double windDir) { private void rotateTo(double heading, boolean sailsIn, double windDir) {
rotationProperty.set(heading);
rotation.setAngle(heading); rotation.setAngle(heading);
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1))); wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
if (sailsIn) { if (sailsIn) {
@@ -130,4 +135,8 @@ public class BoatObject extends Group {
public void addSelectedBoatListener(SelectedBoatListener sbl) { public void addSelectedBoatListener(SelectedBoatListener sbl) {
selectedBoatListenerListeners.add(sbl); selectedBoatListenerListeners.add(sbl);
} }
public ReadOnlyDoubleWrapper getRotationProperty() {
return rotationProperty;
}
} }