From 9075d2a9091a7fac1e0a034ea5e011ed66e680b8 Mon Sep 17 00:00:00 2001 From: Calum Date: Thu, 28 Sep 2017 03:17:33 +1300 Subject: [PATCH] Added a minimap to the race view. #implement #story[1273] --- .../java/seng302/visualiser/GameView3D.java | 9 +- .../java/seng302/visualiser/MapPreview.java | 2 +- src/main/java/seng302/visualiser/MiniMap.java | 82 ++++ .../controllers/RaceViewController.java | 397 ++---------------- .../fxObjects/MarkArrowFactory.java | 10 +- .../fxObjects/assets_3D/BoatModel.java | 4 +- .../fxObjects/assets_3D/ModelFactory.java | 17 +- src/main/resources/views/RaceView.fxml | 254 +++++------ 8 files changed, 236 insertions(+), 539 deletions(-) create mode 100644 src/main/java/seng302/visualiser/MiniMap.java diff --git a/src/main/java/seng302/visualiser/GameView3D.java b/src/main/java/seng302/visualiser/GameView3D.java index 275a3d37..fbc473d8 100644 --- a/src/main/java/seng302/visualiser/GameView3D.java +++ b/src/main/java/seng302/visualiser/GameView3D.java @@ -2,7 +2,6 @@ package seng302.visualiser; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,7 +23,11 @@ import javafx.scene.transform.Scale; import javafx.scene.transform.Translate; import org.fxyz3d.scene.Skybox; import seng302.gameServer.messages.RoundingSide; -import seng302.model.*; +import seng302.model.ClientYacht; +import seng302.model.GameKeyBind; +import seng302.model.KeyAction; +import seng302.model.Limit; +import seng302.model.ScaledPoint; import seng302.model.mark.CompoundMark; import seng302.model.mark.Corner; import seng302.model.mark.Mark; @@ -47,7 +50,7 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType; * Collection of animated3D assets that displays a race. */ -public class GameView3D extends GameView{ +public class GameView3D extends GameView { private final double FOV = 60; private final double DEFAULT_CAMERA_X = 0; diff --git a/src/main/java/seng302/visualiser/MapPreview.java b/src/main/java/seng302/visualiser/MapPreview.java index a733967a..4c2c3a38 100644 --- a/src/main/java/seng302/visualiser/MapPreview.java +++ b/src/main/java/seng302/visualiser/MapPreview.java @@ -29,7 +29,7 @@ import seng302.visualiser.fxObjects.assets_2D.Marker2D; public class MapPreview extends GameView { private Polygon raceBorder = new CourseBoundary(); - private Map markerObjects; + protected Map markerObjects; public MapPreview(List marks, List course, List border) { this.compoundMarks = marks; diff --git a/src/main/java/seng302/visualiser/MiniMap.java b/src/main/java/seng302/visualiser/MiniMap.java new file mode 100644 index 00000000..5776f867 --- /dev/null +++ b/src/main/java/seng302/visualiser/MiniMap.java @@ -0,0 +1,82 @@ +package seng302.visualiser; + +import java.util.HashMap; +import java.util.List; +import javafx.application.Platform; +import javafx.geometry.Point2D; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Polygon; +import seng302.model.ClientYacht; +import seng302.model.Limit; +import seng302.model.mark.CompoundMark; +import seng302.model.mark.Corner; +import seng302.model.mark.Mark; +import seng302.utilities.Sounds; + +/** + * Created by cir27 on 28/09/17. + */ +public class MiniMap extends MapPreview { + + private HashMap boatIcons = new HashMap<>(); + private Polygon playerBoat; + private double playerRotation; + private List boats; + private ClientYacht player; + + public MiniMap (List marks, List course, List border, List boats, ClientYacht player) { + super(marks, course, border); + this.boats = boats; + this.player = player; + setBoats(boats); +// player.addMarkRoundingListener(this::updateMarkArrows); + } + + public void setBoats(List yachts) { + for (ClientYacht yacht : yachts) { + Circle boatIcon = new Circle(0, 0, 4); + boatIcon.setStroke(Color.BLACK); + boatIcon.setFill(Color.GRAY); + boatIcon.setFill(yacht.getColour()); + boatIcon.setFill(yacht.getColour()); + boatIcons.put(yacht, boatIcon); + yacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> { + Circle bi = boatIcons.get(boat); + Point2D p2d = scaledPoint.findScaledXY(lat, lon); + bi.setCenterX(p2d.getX()); + bi.setCenterY(p2d.getY()); + }); + } + Platform.runLater(() -> { + gameObjects.getChildren().addAll(boatIcons.values()); + }); + } + + private void updateMarkArrows (ClientYacht yacht, int legNumber) { + CompoundMark compoundMark; + if (legNumber - 1 >= 0) { + Sounds.playMarkRoundingSound(); + compoundMark = course.get(legNumber-1); + for (Mark mark : compoundMark.getMarks()) { + markerObjects.get(mark).showNextExitArrow(); + } + } + CompoundMark nextMark = null; + if (legNumber < course.size() - 1) { + Sounds.playMarkRoundingSound(); + nextMark = course.get(legNumber); + for (Mark mark : nextMark.getMarks()) { + markerObjects.get(mark).showNextEnterArrow(); + } + } + if (legNumber - 2 >= 0) { + CompoundMark lastMark = course.get(Math.max(0, legNumber - 2)); + if (lastMark != nextMark) { + for (Mark mark : lastMark.getMarks()) { + markerObjects.get(mark).hideAllArrows(); + } + } + } + } +} diff --git a/src/main/java/seng302/visualiser/controllers/RaceViewController.java b/src/main/java/seng302/visualiser/controllers/RaceViewController.java index ea778aa9..12ea48d0 100644 --- a/src/main/java/seng302/visualiser/controllers/RaceViewController.java +++ b/src/main/java/seng302/visualiser/controllers/RaceViewController.java @@ -4,67 +4,38 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialog; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.TimeUnit; import javafx.animation.RotateTransition; -import javafx.animation.Timeline; import javafx.application.Platform; import javafx.beans.property.ReadOnlyBooleanProperty; -import javafx.collections.FXCollections; -import javafx.collections.ListChangeListener; -import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; -import javafx.geometry.Point2D; -import javafx.scene.Scene; import javafx.scene.SubScene; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.XYChart.Series; -import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ComboBox; import javafx.scene.control.Label; -import javafx.scene.control.Slider; import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; import javafx.scene.paint.Paint; -import javafx.scene.shape.Line; -import javafx.scene.shape.Polyline; -import javafx.scene.text.Text; -import javafx.stage.Stage; -import javafx.stage.StageStyle; import javafx.util.Duration; import seng302.model.ClientYacht; import seng302.model.RaceState; -import seng302.model.mark.CompoundMark; -import seng302.model.mark.Mark; import seng302.model.stream.xml.parser.RaceXMLData; import seng302.model.token.TokenType; import seng302.utilities.Sounds; import seng302.visualiser.GameView3D; -import seng302.visualiser.controllers.annotations.ImportantAnnotationController; -import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate; -import seng302.visualiser.controllers.annotations.ImportantAnnotationsState; +import seng302.visualiser.MiniMap; import seng302.visualiser.controllers.dialogs.FinishDialogController; import seng302.visualiser.fxObjects.ChatHistory; -import seng302.visualiser.fxObjects.assets_2D.WindArrow; -import seng302.visualiser.fxObjects.assets_3D.BoatObject; /** * Controller class that manages the display of a race */ -public class RaceViewController extends Thread implements ImportantAnnotationDelegate { +public class RaceViewController extends Thread { private final int CHAT_LIMIT = 128; private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6; @@ -75,39 +46,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel @FXML private ImageView loadingScreen; @FXML - private Pane basePane; - @FXML private JFXButton chatSend; @FXML private Pane chatHistoryHolder; @FXML private TextField chatInput; @FXML - private LineChart raceSparkLine; - @FXML - private NumberAxis sparklineYAxis; - @FXML - private VBox positionVbox; - @FXML - private CheckBox toggleFps; - @FXML private Label timerLabel; @FXML private StackPane contentStackPane; - - private GridPane contentGridPane; @FXML - private AnchorPane rvAnchorPane; - @FXML - private AnchorPane windArrowHolder; - @FXML - private Slider annotationSlider; - @FXML - private Button selectAnnotationBtn; - @FXML - private ComboBox yachtSelectionComboBox; - @FXML - private Text fpsDisplay; + private Pane miniMapPane; @FXML private ImageView windImageView; @FXML @@ -118,33 +67,24 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel private Label positionLabel, boatSpeedLabel, boatHeadingLabel; @FXML private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon; + @FXML + private JFXButton miniMapButton; - //Race Data - private Map participants; - private Map markers; - private RaceXMLData courseData; private GameView3D gameView; private RaceState raceState; - private ChatHistory chatHistory; - - private Timeline timerTimeline; - private Timer timer = new Timer(); - private List> sparkLineData = new ArrayList<>(); - private ImportantAnnotationsState importantAnnotations; - private Polyline windArrow = new WindArrow(Color.LIGHTGRAY); - private ObservableList selectionComboBoxList = FXCollections.observableArrayList(); + private Timer timer = new Timer(); private ClientYacht player; private JFXDialog finishScreenDialog; private FinishDialogController finishDialogController; - - //Icon stuff private Timer blinkingTimer = new Timer(); private ImageView iconToDisplay; - private Double lastWindDirection; + private MiniMap miniMap; public void initialize() { + miniMapPane.setVisible(false); + miniMapButton.setVisible(false); contentStackPane.setVisible(false); Image loadingImage = new Image("PP.png"); loadingScreen.setImage(loadingImage); @@ -204,7 +144,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel public void showView(){ loadingScreenPane.setVisible(false); contentStackPane.setVisible(true); - + miniMapPane.setVisible(true); + miniMapButton.setVisible(true); Platform.runLater(new Runnable() { @Override public void run() { @@ -238,31 +179,35 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel Map participants, RaceXMLData raceData, RaceState raceState, ClientYacht player) { - this.participants = participants; - this.courseData = raceData; - this.markers = raceData.getCompoundMarks(); this.raceState = raceState; this.player = player; - raceState.getPlayerPositions().addListener((ListChangeListener) c -> { - while (c.next()) { - if (c.wasPermutated()) { - updateOrder(raceState.getPlayerPositions()); - } - } - }); - player.addPowerUpListener(this::displayPowerUpIcon); player.addPowerDownListener(this::removeIcon); - updateOrder(raceState.getPlayerPositions()); gameView = new GameView3D(); + miniMap = new MiniMap( + new ArrayList<>(raceData.getCompoundMarks().values()), + raceData.getMarkSequence(), raceData.getCourseLimit(), + new ArrayList<>(participants.values()), player + ); + miniMapButton.setOnMouseClicked((event) -> { + if (miniMapPane.visibleProperty().get()) { + miniMapPane.setVisible(false); + miniMapButton.setText("✕"); + } else { + miniMapPane.setVisible(true); + miniMapButton.setText("✓"); + } + }); + Platform.runLater(() -> { contentStackPane.getChildren().add(0, gameView.getAssets()); ((SubScene) gameView.getAssets()).widthProperty() .bind(ViewManager.getInstance().getStage().widthProperty()); ((SubScene) gameView.getAssets()).heightProperty() .bind(ViewManager.getInstance().getStage().heightProperty()); + miniMapPane.getChildren().add(miniMap.getAssets()); }); gameView.setBoats(new ArrayList<>(participants.values())); gameView.updateBorder(raceData.getCourseLimit()); @@ -350,45 +295,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel } } - - /** - * The important annotations have been changed, update this view - * - * @param importantAnnotationsState The current state of the selected annotations - */ - public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) { - this.importantAnnotations = importantAnnotationsState; - setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations - } - - - /** - * Loads the "select annotations" view in a new window - */ - private void loadSelectAnnotationView() { - try { - FXMLLoader fxmlLoader = new FXMLLoader(); - Stage stage = new Stage(); - // Set controller - ImportantAnnotationController controller = new ImportantAnnotationController( - this, stage - ); - fxmlLoader.setController(controller); - // Load FXML and set CSS - fxmlLoader.setLocation( - getClass().getResource("/views/importantAnnotationSelectView.fxml") - ); - Scene scene = new Scene(fxmlLoader.load(), 469, 298); - scene.getStylesheets().add(getClass().getResource("/css/master.css").toString()); - stage.initStyle(StageStyle.UNDECORATED); - stage.setScene(scene); - stage.show(); - controller.loadState(importantAnnotations); - } catch (IOException e) { - e.printStackTrace(); - } - } - /** * Initialises a timer which updates elements of the RaceView such as wind direction, yacht * orderings etc.. which are dependent on the info from the stream parser constantly. @@ -406,35 +312,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel }, 0, 1000); } - /** - * Iterates over all corners until ones SeqID matches with the yachts current leg number. - * Then it gets the compoundMarkID of that corner and uses it to fetch the appropriate mark - * Returns null if no next mark found. - * @param bg The BoatGroup to find the next mark of - * @return The next Mark or null if none found - */ - private Mark getNextMark(BoatObject bg) { - // TODO: 1/08/17 Move to GameView -// -// Integer legNumber = bg.getClientYacht().getLegNumber(); -// List markSequence = courseData.getMarkSequence(); -// -// if (legNumber == 0) { -// return null; -// } else if (legNumber == markSequence.size() - 1) { -// return null; -// } -// -// for (Corner corner : markSequence) { -// if (legNumber + 2 == corner.getSeqID()) { -// return courseData.getCompoundMarks().get(corner.getCompoundMarkID()); -// } -// } -// return null; - return null; - } - - /** * Updates the wind direction arrow and text as from info from the StreamParser * @param direction the from north angle of the wind. @@ -516,226 +393,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel boatHeadingLabel.setText(String.format("Boat Heading:\n%.1f°", player.getHeading())); } - /** - * Updates the order of the yachts as from the StreamParser and sets them in the yacht order - * section - */ - private void updateOrder(ObservableList yachts) { -// List vboxEntries = new ArrayList<>(); -// -// for (int i = 0; i < yachts.size(); i++) { -//// System.out.println("yacht == null " + String.valueOf(yacht == null)); -// if (yachts.get(i).getBoatStatus() == BoatStatus.FINISHED -// .getCode()) { // 3 is finish status -// Text textToAdd = new Text(i + 1 + ". " + -// yachts.get(i).getShortName() + " (Finished)"); -// textToAdd.setFill(Paint.valueOf("#d3d3d3")); -// vboxEntries.add(textToAdd); -// -// } else { -// Text textToAdd = new Text(i + 1 + ". " + -// yachts.get(i).getShortName() + " "); -// textToAdd.setFill(Paint.valueOf("#d3d3d3")); -// textToAdd.setStyle(""); -// vboxEntries.add(textToAdd); -// } -// } -// Platform.runLater(() -> -// positionVbox.getChildren().setAll(vboxEntries) -// ); - } - - - private void updateLaylines(BoatObject bg) { - // TODO: 1/08/17 move to GameView -// -// Mark nextMark = getNextMark(bg); -// Boolean isUpwind = null; -// // Can only calc leg direction if there is a next mark and it is a gate mark -// if (nextMark != null) { -// if (nextMark instanceof GateMark) { -// if (bg.isUpwindLeg(gameViewController, nextMark)) { -// isUpwind = true; -// } else { -// isUpwind = false; -// } -// -// for(MarkObject mg : gameViewController.getMarkGroups()) { -// -// mg.removeLaylines(); -// -// if (mg.getMainMark().getId() == nextMark.getId()) { -// -// SingleMark singleMark1 = ((GateMark) nextMark).getSingleMark1(); -// SingleMark singleMark2 = ((GateMark) nextMark).getSingleMark2(); -// Point2D markPoint1 = gameViewController -// .findScaledXY(singleMark1.getLatitude(), singleMark1.getLongitude()); -// Point2D markPoint2 = gameViewController -// .findScaledXY(singleMark2.getLatitude(), singleMark2.getLongitude()); -// HashMap angleAndSpeed; -// if (isUpwind) { -// angleAndSpeed = PolarTable.getOptimalUpwindVMG(StreamParser.getWindSpeed()); -// } else { -// angleAndSpeed = PolarTable.getOptimalDownwindVMG(StreamParser.getWindSpeed()); -// } -// -// Double resultingAngle = angleAndSpeed.keySet().iterator().next(); -// -// -// Point2D yachtCurrentPos = new Point2D(bg.getBoatLayoutX(), bg.getBoatLayoutY()); -// Point2D gateMidPoint = markPoint1.midpoint(markPoint2); -// Integer lineFuncResult = GeoUtility.lineFunction(yachtCurrentPos, gateMidPoint, markPoint2); -// Line rightLayline = new Line(); -// Line leftLayline = new Line(); -// if (lineFuncResult == 1) { -// rightLayline = makeRightLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection()); -// leftLayline = makeLeftLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection()); -// } else if (lineFuncResult == -1) { -// rightLayline = makeRightLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection()); -// leftLayline = makeLeftLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection()); -// } -// -// leftLayline.setStrokeWidth(0.5); -// leftLayline.setStroke(bg.getBoat().getColour()); -// -// rightLayline.setStrokeWidth(0.5); -// rightLayline.setStroke(bg.getBoat().getColour()); -// -// bg.setLaylines(leftLayline, rightLayline); -// mg.addLaylines(leftLayline, rightLayline); -// -// } -// } -// } -// } - } - - - private Point2D getPointRotation(Point2D ref, Double distance, Double angle) { - Double newX = ref.getX() + (ref.getX() + distance - ref.getX()) * Math.cos(angle) - - (ref.getY() + distance - ref.getY()) * Math.sin(angle); - Double newY = ref.getY() + (ref.getX() + distance - ref.getX()) * Math.sin(angle) - + (ref.getY() + distance - ref.getY()) * Math.cos(angle); - - return new Point2D(newX, newY); - } - - - public Line makeLeftLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) { - Point2D ep = getPointRotation(startPoint, 50.0, baseAngle + layLineAngle); - Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY()); - return line; - - } - - - public Line makeRightLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) { - - Point2D ep = getPointRotation(startPoint, 50.0, baseAngle - layLineAngle); - Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY()); - return line; - - } - - - /** - * Initialised the combo box with any yachts currently in the race and adds the required listener - * for the combobox to take action upon selection - */ - private void initialiseBoatSelectionComboBox() { -// yachtSelectionComboBox.setItems( -// FXCollections.observableArrayList(participants.values()) -// ); -// //Null check is if the listener is fired but nothing selected -// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> { -// if (selectedBoat != null) { -// gameView.selectBoat(selectedBoat); -// } -// }); - - //TODO uncomment out -// selectionComboBoxList.setAll(participants.values()); -// yachtSelectionComboBox.setItems(selectionComboBoxList); -// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> { -// if (selectedBoat != null) { -// gameView.selectBoat(selectedBoat); -// } -// }); - } - - /** - * Display the list of yachts in the order they finished the race - */ - private void loadRaceResultView() { - FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml")); - - try { - contentGridPane.getChildren().removeAll(); - contentGridPane.getChildren().clear(); - contentGridPane.getChildren().addAll((Pane) loader.load()); - - } catch (javafx.fxml.LoadException e) { - System.err.println(e.getCause().toString()); - } catch (IOException e) { - System.err.println(e.toString()); - } - } - - private String getMillisToFormattedTime(long milliseconds) { - return String.format("%02d:%02d:%02d", - TimeUnit.MILLISECONDS.toHours(milliseconds), - TimeUnit.MILLISECONDS.toMinutes(milliseconds) % 60, //Modulus 60 minutes per hour - TimeUnit.MILLISECONDS.toSeconds(milliseconds) % 60 //Modulus 60 seconds per minute - ); - } - - private void setAnnotations(Integer annotationLevel) { -// switch (annotationLevel) { -// // No Annotations -// case 0: -// gameView.setAnnotationVisibilities( -// false, false, false, false, false, false -// ); -// break; -// // Important Annotations -// case 1: -// gameView.setAnnotationVisibilities( -// importantAnnotations.getAnnotationState(Annotation.NAME), -// importantAnnotations.getAnnotationState(Annotation.SPEED), -// importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK), -// importantAnnotations.getAnnotationState(Annotation.LEGTIME), -// importantAnnotations.getAnnotationState(Annotation.TRACK), -// importantAnnotations.getAnnotationState(Annotation.WAKE) -// ); -// break; -// // All Annotations -// case 2: -// gameView.setAnnotationVisibilities( -// true, true, true, true, true, true -// ); -// break; -// } - } - - - /** - * Sets all the annotations of the selected yacht to be visible and all others to be hidden - * - * @param yacht The yacht for which we want to view all annotations - */ - private void setSelectedBoat(ClientYacht yacht) { -// for (BoatObject bg : gameViewController.getBoatGroups()) { -// //We need to iterate over all race groups to get the matching yacht group belonging to this yacht if we -// //are to toggle its annotations, there is no other backwards knowledge of a yacht to its yachtgroup. -// if (bg.getBoat().getHullID().equals(yacht.getHullID())) { -//// updateLaylines(bg); -// bg.setIsSelected(true); -//// selectedBoat = yacht; -// } else { -// bg.setIsSelected(false); -// } -// } - } public void updateTokens(RaceXMLData raceData) { gameView.updateTokens(raceData.getTokens()); diff --git a/src/main/java/seng302/visualiser/fxObjects/MarkArrowFactory.java b/src/main/java/seng302/visualiser/fxObjects/MarkArrowFactory.java index ccc307eb..4f871801 100644 --- a/src/main/java/seng302/visualiser/fxObjects/MarkArrowFactory.java +++ b/src/main/java/seng302/visualiser/fxObjects/MarkArrowFactory.java @@ -29,11 +29,11 @@ public class MarkArrowFactory { STARBOARD, } - public static final double MARK_ARROW_SEPARATION = 15; - public static final double ARROW_LENGTH = 75; - public static final double ARROW_HEAD_DEPTH = 10; - public static final double ARROW_HEAD_WIDTH = 6; - public static final double STROKE_WIDTH = 3; + public static final double MARK_ARROW_SEPARATION = 8; + public static final double ARROW_LENGTH = 20; + public static final double ARROW_HEAD_DEPTH = 5; + public static final double ARROW_HEAD_WIDTH = 3; + public static final double STROKE_WIDTH = 1; public static Model constructEntryArrow3D ( RoundingSide roundingSide, double angle, ModelType type) { diff --git a/src/main/java/seng302/visualiser/fxObjects/assets_3D/BoatModel.java b/src/main/java/seng302/visualiser/fxObjects/assets_3D/BoatModel.java index e056b14d..27cc923d 100644 --- a/src/main/java/seng302/visualiser/fxObjects/assets_3D/BoatModel.java +++ b/src/main/java/seng302/visualiser/fxObjects/assets_3D/BoatModel.java @@ -60,7 +60,9 @@ public class BoatModel extends Model { */ public void changeColour(Color newColour) { changeColourChild(HULL_INDEX, newColour); - changeColourChild(MAST_INDEX, newColour); + if (meshType != BoatMeshType.PARROT) { + changeColourChild(MAST_INDEX, newColour); + } } private void changeColourChild(int index, Color newColour) { diff --git a/src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java b/src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java index 8ca060c6..70a2897d 100644 --- a/src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java +++ b/src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java @@ -117,12 +117,7 @@ public class ModelFactory { Group boatAssets = new Group(); MeshView hull = importSTL(boatType.hullFile); hull.setMaterial(new PhongMaterial(primaryColour)); - MeshView sail = importSTL(boatType.sailFile); - sail.setMaterial( - new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE) - ); - - boatAssets.getChildren().addAll(hull, sail); + boatAssets.getChildren().addAll(hull); if (boatType.mastFile != null) { MeshView mast = importSTL(boatType.mastFile); @@ -130,10 +125,16 @@ public class ModelFactory { boatAssets.getChildren().add(mast); } + MeshView sail = importSTL(boatType.sailFile); + sail.setMaterial( + new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE) + ); + boatAssets.getChildren().addAll(sail); + if (boatType.jibFile != null) { MeshView jib = importSTL(boatType.jibFile); - sail.setMaterial( - new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE) + jib.setMaterial( + new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE) ); boatAssets.getChildren().add(jib); } diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml index 56ca5ad5..a11b1fd0 100644 --- a/src/main/resources/views/RaceView.fxml +++ b/src/main/resources/views/RaceView.fxml @@ -1,7 +1,5 @@ - - @@ -25,284 +23,238 @@ - - - + + + - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - - - + + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + - + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + - - - - - - + + + + + + + + - - + +