diff --git a/racevisionGame/src/main/java/shared/model/CompoundMark.java b/racevisionGame/src/main/java/shared/model/CompoundMark.java index 4fa2599c..a9a84a2a 100644 --- a/racevisionGame/src/main/java/shared/model/CompoundMark.java +++ b/racevisionGame/src/main/java/shared/model/CompoundMark.java @@ -98,7 +98,7 @@ public class CompoundMark extends XMLCompoundMark{ * @return The second mark of the compound mark. */ public Mark getMark2() { - return mark2; + return mark2 == null? mark1 : mark2; } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java index 4af633e9..d00f8d96 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java @@ -15,12 +15,17 @@ import javafx.scene.input.KeyEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.paint.Material; +import javafx.scene.paint.PhongMaterial; import javafx.scene.shape.MeshView; +import javafx.scene.shape.Shape3D; import javafx.scene.shape.Sphere; import javafx.scene.transform.Translate; import javafx.util.Callback; import network.Messages.Enums.RaceStatusEnum; import shared.dataInput.RaceDataSource; +import shared.model.CompoundMark; import shared.model.Leg; import shared.model.Mark; import visualiser.app.App; @@ -224,7 +229,7 @@ public class RaceController extends Controller { view3D.setItems(viewSubjects); // Position and add each mark to view for(Mark mark: race.getVisualiserRaceState().getMarks()) { - Subject3D subject = new Subject3D(new Sphere(2)); + Subject3D subject = new Subject3D(new Sphere(2), mark.getSourceID()); subject.setX(gpsConverter.convertGPS(mark.getPosition()).getX()); subject.setZ(gpsConverter.convertGPS(mark.getPosition()).getY()); @@ -233,7 +238,7 @@ public class RaceController extends Controller { // Position and add each boat to view for(VisualiserBoat boat: race.getVisualiserRaceState().getBoats()) { MeshView mesh = new MeshView(importer.getImport()); - Subject3D subject = new Subject3D(mesh); + Subject3D subject = new Subject3D(mesh, boat.getSourceID()); viewSubjects.add(subject); // Track this boat's movement with the new subject @@ -247,10 +252,11 @@ public class RaceController extends Controller { }; trackBoat.start(); - System.out.println(boat.getCurrentLeg().getEndCompoundMark().toString()); - boat.legProperty().addListener((o, prev, curr) -> { - System.out.println(curr.getEndCompoundMark().toString()); - }); + Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1)); + CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark(); + view3D.getShape(nextMark.getMark1().getSourceID()).setMaterial(markColor); + view3D.getShape(nextMark.getMark2().getSourceID()).setMaterial(markColor); + boat.legProperty().addListener((o, prev, curr) -> swapColours(curr)); } // Fix initial bird's-eye position view3D.updatePivot(new Translate(250, 0, 210)); @@ -300,8 +306,27 @@ public class RaceController extends Controller { }); } - - + /** + * Swap the colour of the next mark to pass with the last mark passed + * @param leg boat has started on + */ + private void swapColours(Leg leg) { + CompoundMark start = leg.getStartCompoundMark(); + CompoundMark end = leg.getEndCompoundMark(); + + Shape3D start1 = view3D.getShape(start.getMark1().getSourceID()); + Shape3D start2 = view3D.getShape(start.getMark2().getSourceID()); + Shape3D end1 = view3D.getShape(end.getMark1().getSourceID()); + Shape3D end2 = view3D.getShape(end.getMark2().getSourceID()); + + Material nextMark = start1.getMaterial(); + Material lastMark = end1.getMaterial(); + + start1.setMaterial(lastMark); + start2.setMaterial(lastMark); + end1.setMaterial(nextMark); + end2.setMaterial(nextMark); + } /** * Initialises the frame rate functionality. This allows for toggling the frame rate, and connect the fps label to the race's fps property. diff --git a/racevisionGame/src/main/java/visualiser/layout/Subject3D.java b/racevisionGame/src/main/java/visualiser/layout/Subject3D.java index af76f4f4..6bcf60b2 100644 --- a/racevisionGame/src/main/java/visualiser/layout/Subject3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/Subject3D.java @@ -12,6 +12,10 @@ public class Subject3D { * Rendered mesh */ private Shape3D mesh; + /** + * Source ID of subject in game model + */ + private int sourceID; /** * Position translation updated by state listeners @@ -27,8 +31,9 @@ public class Subject3D { * Constructor for view subject wrapper * @param mesh to be rendered */ - public Subject3D(Shape3D mesh) { + public Subject3D(Shape3D mesh, int sourceID) { this.mesh = mesh; + this.sourceID = sourceID; this.position = new Translate(); this.heading = new Rotate(0, Rotate.Y_AXIS); @@ -39,6 +44,10 @@ public class Subject3D { return mesh; } + public int getSourceID() { + return sourceID; + } + public Translate getPosition() { return this.position; } diff --git a/racevisionGame/src/main/java/visualiser/layout/View3D.java b/racevisionGame/src/main/java/visualiser/layout/View3D.java index 27fe6086..cc36f492 100644 --- a/racevisionGame/src/main/java/visualiser/layout/View3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/View3D.java @@ -33,7 +33,11 @@ public class View3D extends Pane { /** * Map for selecting Subject3D from Shape3D */ - private Map selectionMap; + private Map shapeMap; + /** + * Map for selecting Shape3D from source ID + */ + private Map sourceMap; /** * Subject tracked by camera */ @@ -92,7 +96,8 @@ public class View3D extends Pane { */ public View3D() { this.world = new Group(); - this.selectionMap = new HashMap<>(); + this.shapeMap = new HashMap<>(); + this.sourceMap = new HashMap<>(); this.target = null; this.scene = new SubScene(world, 300, 300); @@ -140,17 +145,23 @@ public class View3D extends Pane { if (c.wasRemoved() || c.wasAdded()) { for (Subject3D shape : c.getRemoved()) { world.getChildren().remove(shape.getMesh()); - selectionMap.remove(shape.getMesh()); + shapeMap.remove(shape.getMesh()); + sourceMap.remove(shape.getSourceID()); } for (Subject3D shape : c.getAddedSubList()) { world.getChildren().add(shape.getMesh()); - selectionMap.put(shape.getMesh(), shape); + shapeMap.put(shape.getMesh(), shape); + sourceMap.put(shape.getSourceID(), shape.getMesh()); } } } }); } + public Shape3D getShape(int sourceID) { + return sourceMap.get(sourceID); + } + /** * Intercept mouse clicks on subjects in view. The applied listener cannot be removed. */ @@ -158,7 +169,7 @@ public class View3D extends Pane { scene.setOnMousePressed(e -> { PickResult result = e.getPickResult(); if(result != null && result.getIntersectedNode() != null && result.getIntersectedNode() instanceof Shape3D) { - trackSubject(selectionMap.get(result.getIntersectedNode())); + trackSubject(shapeMap.get(result.getIntersectedNode())); } }); }