Compare commits

...

38 Commits

Author SHA1 Message Date
Calum e1ebbc71c1 Added drawing to fx thread
#fix
2017-09-28 14:57:52 +13:00
William Muir c98297ea79 Merged dev changes back on to mini map
#story[1273]
2017-09-28 14:44:16 +13:00
William Muir a5eea10c87 Merge branch 'develop' into story1273_minimap
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
#	src/main/resources/meshes/boatSTLs/parrot_features.stl
2017-09-28 14:41:08 +13:00
Calum 597fbe935f Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 14:28:16 +13:00
Calum 7cfad28d6b Fixed parrot 2017-09-28 14:28:07 +13:00
Michael Rausch 3345734efd Fixed memory leak by forcing garbage collection 2017-09-28 14:22:33 +13:00
Haoming Yin 9795083d4d Added confirm button in keybinding dialog.
-  clicking confirm button will exit the dialog
- [WIP] exit without clicking confirm button will still save changes, which should be fixed in the future

tags: #story[1273]
2017-09-28 13:58:25 +13:00
Kusal Ekanayake f02208ba3a Loopty loop map added 2017-09-28 13:33:09 +13:00
William Muir b9a2d60115 Merged dev changes back on to mini map
#story[1273]
2017-09-28 12:58:19 +13:00
William Muir 076c4c9a40 Merge branch 'develop' into story1273_minimap
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
#	src/main/resources/views/RaceView.fxml
2017-09-28 12:54:12 +13:00
Calum 8d74c3b756 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 12:44:33 +13:00
Calum 3f666fa092 Made waka larger. 2017-09-28 12:44:24 +13:00
Haoming Yin 55d82298b6 Beautified the loading splash screen
- added 7-color rainbow spinners
- added background image
- added subtitle
- changed font size and color

tags: #story[1273]
2017-09-28 12:42:46 +13:00
William Muir 909407fe63 Merge branch '1293_PowerUps_TokenInfo' into develop 2017-09-28 12:31:14 +13:00
William Muir 499acb9733 Merge branch '1293_PowerUps_TokenInfo' into develop 2017-09-28 12:21:12 +13:00
Calum ddf5a96e0f Merge branch '1276_Next_Mark_Indicator' into develop 2017-09-28 12:03:30 +13:00
Calum 81b2d285e9 Changed arrow colour.
#fix
2017-09-28 12:02:24 +13:00
Calum 5d7f307260 Changed arrow colour.
#fix
2017-09-28 12:02:09 +13:00
Kusal Ekanayake 4ec23a1785 Fixed race fxml not showing other elements 2017-09-28 11:30:09 +13:00
Haoming Yin 37e4fe4ce7 Issue #83: Server creation dialog need to be polished
- rearranged the layout of all the nodes
- set CSS files for the dialog
- added close button

tags: #story[1273]
2017-09-28 11:13:02 +13:00
Calum e87931a8fc Merge branch 'develop' into story1273_minimap 2017-09-28 10:21:23 +13:00
Calum d1edbc4b8a Put the arrows into the minimap. Fixed the issue with curved section of port marks.
#fix #implement
2017-09-28 10:19:32 +13:00
Calum 275a2cbab7 Made continous turning the default. Added triangles to minimap. Made mark areas bigger
#fix #implement
2017-09-28 10:12:18 +13:00
Calum 0b8e2499a7 Fixed some internal stl faces on parrot
#fix
2017-09-28 03:35:28 +13:00
Calum 9075d2a909 Added a minimap to the race view.
#implement #story[1273]
2017-09-28 03:17:33 +13:00
alistairjmcintyre 00e2af9c14 - Fixed Merge Errors and some broken lighting AGAIN
#tags [1276]
2017-09-28 02:20:34 +13:00
alistairjmcintyre 73861b2ef3 Merge branch 'develop' into 1276_Next_Mark_Indicator 2017-09-28 02:06:18 +13:00
alistairjmcintyre 4018dd783e - Fixed Merge Errors and some broken lighting
#tags [1276]
2017-09-28 02:05:47 +13:00
Michael Rausch 8b7407bf89 Various bug fixes
- Closed socket when discovery server crashes, so it can be restarted
- Flattened water on terrain mesh
- Added checks to ensure server is started before connecting
- Added a check to ensure client has started  before connecting to the server
- Fixed concurrency issue in server-> client thread list

Tags: #story[1281]
2017-09-28 01:58:49 +13:00
alistairjmcintyre a08a38c985 - Fixed Merge Errors
#tags [1276]
2017-09-27 22:25:32 +13:00
alistairjmcintyre 810dde6a21 Merge branch 'develop' into 1276_Next_Mark_Indicator
# Conflicts:
#	src/main/java/seng302/visualiser/GameView3D.java
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelType.java
2017-09-27 22:15:02 +13:00
alistairjmcintyre 7a76efa2ce - Added ability to color the indicators.
#tags [1276]
2017-09-27 22:07:24 +13:00
alistairjmcintyre c5e6302f86 - Added circle to boat to indicate which boat is the players and to show where the arrow is pointing.
#tags [1276]
2017-09-27 21:31:02 +13:00
Alistair McIntyre be72062c8e Merge branch 'develop' into 1276_Next_Mark_Indicator
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
2017-09-27 19:25:08 +13:00
Alistair McIntyre 0d212a4a1d - Indicator works correctly, sits in the right place, rotates around the boat correctly and sits on top of the water now.
tags : #story[1276]
2017-09-27 19:20:33 +13:00
Alistair McIntyre 0e9b818071 - Indicator points towards the next mark. Seems to do some funny stuff when entering a compound mark(gate).
tags : #story[1276]
2017-09-27 18:50:38 +13:00
Alistair McIntyre 452e83c1c3 - Marker seems to be detecting the correct mark but somethings wrong with the maths.
tags : #story[1276]
2017-09-27 17:52:54 +13:00
Alistair McIntyre aded794a67 - Added new indicator for direction to next mark.
- Marker rotates towards a given heading.

tags : #story[1276]
2017-09-27 17:17:50 +13:00
43 changed files with 1393 additions and 1010 deletions
+20 -4
View File
@@ -13,6 +13,9 @@ import org.slf4j.LoggerFactory;
import seng302.discoveryServer.DiscoveryServer; import seng302.discoveryServer.DiscoveryServer;
import seng302.visualiser.controllers.ViewManager; import seng302.visualiser.controllers.ViewManager;
import java.util.Timer;
import java.util.TimerTask;
public class App extends Application { public class App extends Application {
private static Logger logger = LoggerFactory.getLogger(App.class); private static Logger logger = LoggerFactory.getLogger(App.class);
@@ -80,16 +83,29 @@ public class App extends Application {
ViewManager.getInstance().initialiseSplashScreen(primaryStage); ViewManager.getInstance().initialiseSplashScreen(primaryStage);
} }
private static void runDiscoveryServer(){ private static void runDiscoveryServer() throws Exception {
try{ while (true){
try {
new DiscoveryServer(); new DiscoveryServer();
} }
catch (Exception e){ catch (Exception ignored){
runDiscoveryServer(); ;
}
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
/*
* Do not trust Java to do garbage collection
*/
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.gc();
}
}, 0, 1200);
try { try {
parseArgs(args); parseArgs(args);
} catch (ParseException e) { } catch (ParseException e) {
@@ -11,11 +11,13 @@ import seng302.discoveryServer.util.ServerRepoStreamParser;
import seng302.discoveryServer.util.ServerTable; import seng302.discoveryServer.util.ServerTable;
import seng302.visualiser.ServerListener; import seng302.visualiser.ServerListener;
import java.io.IOException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Timer;
public class DiscoveryServer { public class DiscoveryServer {
public static final String ANSI_GREEN = "\u001B[32m"; public static final String ANSI_GREEN = "\u001B[32m";
@@ -27,6 +29,7 @@ public class DiscoveryServer {
private ServerTable serverTable; private ServerTable serverTable;
public static final Integer PORT_NUMBER = 9969; public static final Integer PORT_NUMBER = 9969;
private ServerSocket serverSocket;
private final Logger logger = LoggerFactory.getLogger(DiscoveryServer.class); private final Logger logger = LoggerFactory.getLogger(DiscoveryServer.class);
@@ -56,8 +59,6 @@ public class DiscoveryServer {
displayHeader(); displayHeader();
serverTable = new ServerTable(); serverTable = new ServerTable();
ServerSocket serverSocket;
try{ try{
serverSocket = new ServerSocket(PORT_NUMBER); serverSocket = new ServerSocket(PORT_NUMBER);
} }
@@ -69,6 +70,7 @@ public class DiscoveryServer {
logger.info("Started successfully - Now accepting connections"); logger.info("Started successfully - Now accepting connections");
try{
while (true){ while (true){
Socket clientSocket = serverSocket.accept(); Socket clientSocket = serverSocket.accept();
@@ -77,6 +79,10 @@ public class DiscoveryServer {
clientSocket.close(); clientSocket.close();
} }
} }
catch (Exception e){
close();
}
}
private void parseRequest(Socket clientSocket) throws Exception { private void parseRequest(Socket clientSocket) throws Exception {
@@ -147,6 +153,18 @@ public class DiscoveryServer {
tries++; tries++;
} }
if (serverToJoin != null && serverToJoin.isMaxPlayersReached()){
return null;
}
return serverToJoin; return serverToJoin;
} }
public void close(){
try {
serverSocket.close();
} catch (IOException ignored) {
;
}
}
} }
@@ -238,7 +238,7 @@ public class GameState implements Runnable {
if (System.currentTimeMillis() > startTime) { if (System.currentTimeMillis() > startTime) {
startSpawningTokens(); startSpawningTokens();
startUpdatingWind(); startUpdatingWind();
GameState.setCurrentStage(GameStages.RACING); GameState.currentStage = GameStages.RACING;
} }
} }
if (currentStage == GameStages.RACING) { if (currentStage == GameStages.RACING) {
@@ -299,8 +299,8 @@ public class GameState implements Runnable {
windSpeed += random.nextInt(500); windSpeed += random.nextInt(500);
} }
GameState.setWindSpeed(Double.valueOf(windSpeed)); GameState.windSpeed = Double.valueOf(windSpeed);
GameState.setWindDirection(direction.doubleValue()); GameState.windDirection = direction.doubleValue();
} }
@@ -40,6 +40,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
private boolean terminated; private boolean terminated;
private Thread thread; private Thread thread;
private boolean hasStarted = false;
private ServerSocket serverSocket = null; private ServerSocket serverSocket = null;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>(); private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
@@ -98,6 +99,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
new HeartbeatThread(this); new HeartbeatThread(this);
new ServerListenThread(serverSocket, this); new ServerListenThread(serverSocket, this);
hasStarted = true;
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app. //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
while (!terminated) { while (!terminated) {
if (GameState.getPlayerHasLeftFlag()) { if (GameState.getPlayerHasLeftFlag()) {
@@ -146,9 +149,11 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
} }
} }
try { try {
synchronized (this){
for (ServerToClientThread serverToClientThread : serverToClientThreads) { for (ServerToClientThread serverToClientThread : serverToClientThreads) {
serverToClientThread.terminate(); serverToClientThread.terminate();
} }
}
serverSocket.close(); serverSocket.close();
} catch (IOException e) { } catch (IOException e) {
System.out.println("IO error in server thread handler upon closing socket"); System.out.println("IO error in server thread handler upon closing socket");
@@ -450,4 +455,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
); );
} }
} }
public boolean hasStarted() {
return hasStarted;
}
} }
@@ -158,7 +158,13 @@ public abstract class Message {
* @return The current buffer as a byte array * @return The current buffer as a byte array
*/ */
public byte[] getBuffer(){ public byte[] getBuffer(){
return buffer.array(); byte[] bytes = buffer.array();
// buffer.reset();
// buffer.clear();
// buffer = null;
return bytes;
} }
/** /**
@@ -1,5 +1,14 @@
package seng302.visualiser; package seng302.visualiser;
import javafx.application.Platform;
import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.messages.*;
import seng302.model.stream.packets.PacketType;
import seng302.model.stream.packets.StreamPacket;
import seng302.utilities.XMLParser;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -42,6 +51,8 @@ import seng302.visualiser.controllers.ViewManager;
*/ */
public class ClientToServerThread implements Runnable { public class ClientToServerThread implements Runnable {
private boolean isStarted = false;
/** /**
* Functional interface for receiving packets from client socket. * Functional interface for receiving packets from client socket.
*/ */
@@ -117,6 +128,8 @@ public class ClientToServerThread implements Runnable {
* variable is false. * variable is false.
*/ */
public void run() { public void run() {
isStarted = true;
int sync1; int sync1;
int sync2; int sync2;
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop // TODO: 14/07/17 wmu16 - Work out how to fix this while loop
@@ -167,8 +180,10 @@ public class ClientToServerThread implements Runnable {
notifyDisconnectListeners("Connection to server was terminated"); notifyDisconnectListeners("Connection to server was terminated");
closeSocket(); closeSocket();
ViewManager.getInstance().goToStartView(); Platform.runLater(() -> {
ViewManager.getInstance().showErrorSnackBar("Server rejected connection."); ViewManager.getInstance().showErrorSnackBar("Server rejected connection.");
ViewManager.getInstance().goToStartView();
});
} }
public void sendCustomizationRequest(CustomizeRequestType reqType, byte[] payload) { public void sendCustomizationRequest(CustomizeRequestType reqType, byte[] payload) {
@@ -194,12 +209,6 @@ public class ClientToServerThread implements Runnable {
if (connectionErrorListener != null){ if (connectionErrorListener != null){
connectionErrorListener.notifyConnectionError(message); connectionErrorListener.notifyConnectionError(message);
} }
try {
this.socket.close();
} catch (IOException e) {
logger.error("Couldn't close socket");
}
} }
/** /**
@@ -390,9 +399,9 @@ public class ClientToServerThread implements Runnable {
} }
if (currentByte == -1) { if (currentByte == -1) {
notifyDisconnectListeners("Cannot read from server."); notifyDisconnectListeners("Cannot read from server.");
closeSocket();
logger.warn("InputStream reach end of stream", 1); logger.warn("InputStream reach end of stream", 1);
handleConnectionError("Could not connect to server. Server is no longer available."); handleConnectionError("Could not connect to server. Server is no longer available.");
closeSocket();
} }
return currentByte; return currentByte;
} }
@@ -435,4 +444,8 @@ public class ClientToServerThread implements Runnable {
).getBuffer() ).getBuffer()
); );
} }
public boolean hasStarted() {
return isStarted;
}
} }
@@ -49,12 +49,6 @@ import seng302.visualiser.controllers.RaceViewController;
import seng302.visualiser.controllers.ViewManager; import seng302.visualiser.controllers.ViewManager;
import seng302.visualiser.controllers.dialogs.PopupDialogController; import seng302.visualiser.controllers.dialogs.PopupDialogController;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
/** /**
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated * This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
* with a JavaFX Pane to insert itself into. * with a JavaFX Pane to insert itself into.
@@ -119,7 +113,7 @@ public class GameClient {
getServerThread().setConnectionErrorListener((eMessage) -> { getServerThread().setConnectionErrorListener((eMessage) -> {
ViewManager.getInstance().showErrorSnackBar(eMessage); ViewManager.getInstance().showErrorSnackBar(eMessage);
destroyClientToServerThread(); //destroyClientToServerThread();
}); });
this.lobbyController = ViewManager.getInstance().goToLobby(true); this.lobbyController = ViewManager.getInstance().goToLobby(true);
@@ -147,18 +141,45 @@ public class GameClient {
server = new MainServerThread(); server = new MainServerThread();
while (!server.hasStarted()){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try { try {
startClientToServerThread(ipAddress, 4942); startClientToServerThread(ipAddress, 4942);
} catch (IOException e) { } catch (IOException e) {
showConnectionError("Cannot connect to server as host"); showConnectionError("Cannot connect to server as host");
} }
// Wait for C2S thread
while (!socketThread.hasStarted()){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
socketThread.sendXML(race, serverName, numLegs, maxPlayers, tokensEnabled); socketThread.sendXML(race, serverName, numLegs, maxPlayers, tokensEnabled);
while (regattaData == null){
int triesLeft = 15;
while (regattaData == null && triesLeft > 0){
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
triesLeft--;
}
if (triesLeft <= 0){
showConnectionError("Could not launch server");
return null;
} }
this.lobbyController = ViewManager.getInstance().goToLobby(false); this.lobbyController = ViewManager.getInstance().goToLobby(false);
@@ -287,6 +308,7 @@ public class GameClient {
formatAndSendChatMessage(raceView.readChatInput()); formatAndSendChatMessage(raceView.readChatInput());
} }
}); });
gameKeyBind.toggleTurningMode();
sendToggleTurningModePacket(); // notify the server about player's steering mode sendToggleTurningModePacket(); // notify the server about player's steering mode
} }
} }
@@ -2,12 +2,12 @@ package seng302.visualiser;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.geometry.Point3D; import javafx.geometry.Point3D;
import javafx.scene.Camera; import javafx.scene.Camera;
@@ -24,7 +24,11 @@ import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate; import javafx.scene.transform.Translate;
import org.fxyz3d.scene.Skybox; import org.fxyz3d.scene.Skybox;
import seng302.gameServer.messages.RoundingSide; 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.CompoundMark;
import seng302.model.mark.Corner; import seng302.model.mark.Corner;
import seng302.model.mark.Mark; import seng302.model.mark.Mark;
@@ -47,7 +51,7 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
* Collection of animated3D assets that displays a race. * 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 FOV = 60;
private final double DEFAULT_CAMERA_X = 0; private final double DEFAULT_CAMERA_X = 0;
@@ -66,6 +70,8 @@ public class GameView3D extends GameView{
/* Note that if either of these is null then values for it have not been added and the other /* Note that if either of these is null then values for it have not been added and the other
should be used as the limits of the map. */ should be used as the limits of the map. */
private Map<Mark, Marker3D> markerObjects; private Map<Mark, Marker3D> markerObjects;
private BoatObject playerBoat;
private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>(); private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
private Group wakesGroup = new Group(); private Group wakesGroup = new Group();
private Group boatObjectGroup = new Group(); private Group boatObjectGroup = new Group();
@@ -331,9 +337,35 @@ public class GameView3D extends GameView{
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) { ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
((ChaseCamera) chaseCam).setPlayerBoat(newBoat); ((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
((TopDownCamera) topDownCam).setPlayerBoat(newBoat); ((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
newBoat.setMarkIndicator(ModelFactory.importSTL("mark_pointer.stl"));
playerBoat = newBoat;
} }
} }
Platform.runLater(() -> { Platform.runLater(() -> {
ClientYacht playerYacht = ViewManager.getInstance().getGameClient().getAllBoatsMap()
.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId());
for (ObservableValue o : Arrays
.asList(playerBoat.layoutXProperty(), playerBoat.layoutXProperty())) {
o.addListener((obs, oldVal, newVal) -> {
List<Mark> marks = course.get(playerYacht.getLegNumber()).getMarks();
Point2D midPoint = new Point2D(0, 0);
if (marks.size() == 1) {
midPoint = scaledPoint.findScaledXY(marks.get(0));
} else if (marks.size() == 2) {
midPoint = (scaledPoint.findScaledXY(marks.get(0)))
.midpoint(scaledPoint.findScaledXY(marks.get(1)));
}
if (midPoint != null) {
playerBoat.updateMarkIndicator(midPoint);
}
});
}
gameObjects.getChildren().addAll(wakes); gameObjects.getChildren().addAll(wakes);
gameObjects.getChildren().addAll(boatObjectGroup); gameObjects.getChildren().addAll(boatObjectGroup);
}); });
@@ -35,7 +35,7 @@ public class MapMaker {
private int index = 0; private int index = 0;
private XMLGenerator xmlGenerator = new XMLGenerator(); private XMLGenerator xmlGenerator = new XMLGenerator();
private List<String> maps = new ArrayList<>(Arrays.asList("default.xml", "horseshoe.xml")); private List<String> maps = new ArrayList<>(Arrays.asList("default.xml", "horseshoe.xml", "loop.xml"));
public static MapMaker getInstance() { public static MapMaker getInstance() {
if (instance == null) { if (instance == null) {
@@ -29,7 +29,7 @@ import seng302.visualiser.fxObjects.assets_2D.Marker2D;
public class MapPreview extends GameView { public class MapPreview extends GameView {
private Polygon raceBorder = new CourseBoundary(); private Polygon raceBorder = new CourseBoundary();
private Map<Mark, Marker2D> markerObjects; protected Map<Mark, Marker2D> markerObjects;
public MapPreview(List<CompoundMark> marks, List<Corner> course, List<Limit> border) { public MapPreview(List<CompoundMark> marks, List<Corner> course, List<Limit> border) {
this.compoundMarks = marks; this.compoundMarks = marks;
@@ -0,0 +1,86 @@
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.Polygon;
import javafx.scene.transform.Rotate;
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;
/**
* Class converts a map preview to a minimap by adding boats.
*/
public class MiniMap extends MapPreview {
private HashMap<ClientYacht, Polygon> boatIcons = new HashMap<>();
private Polygon playerBoat;
private double playerRotation;
private List<ClientYacht> boats;
private ClientYacht player;
public MiniMap (List<CompoundMark> marks, List<Corner> course, List<Limit> border, List<ClientYacht> boats, ClientYacht player) {
super(marks, course, border);
this.boats = boats;
this.player = player;
setBoats(boats);
player.addMarkRoundingListener(this::updateMarkArrows);
}
public void setBoats(List<ClientYacht> yachts) {
for (ClientYacht yacht : yachts) {
Polygon boatIcon = new Polygon(0, -3.5, 3.5, 3.5, -3.5, 3.5);
boatIcon.setStroke(Color.BLACK);
boatIcon.setFill(Color.GRAY);
boatIcon.setFill(yacht.getColour());
boatIcon.setFill(yacht.getColour());
boatIcons.put(yacht, boatIcon);
boatIcon.getTransforms().add(new Rotate(0));
yacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
Platform.runLater(() -> {
Polygon bi = boatIcons.get(boat);
Point2D p2d = scaledPoint.findScaledXY(lat, lon);
bi.setLayoutX(p2d.getX());
bi.setLayoutY(p2d.getY());
((Rotate) bi.getTransforms().get(0)).setAngle(heading);
});
});
}
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();
}
}
}
}
}
@@ -4,67 +4,38 @@ import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialog;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javafx.animation.RotateTransition; import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.SubScene; 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.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint; 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 javafx.util.Duration;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.RaceState; import seng302.model.RaceState;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
import seng302.model.stream.xml.parser.RaceXMLData; import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.token.TokenType; import seng302.model.token.TokenType;
import seng302.utilities.Sounds; import seng302.utilities.Sounds;
import seng302.visualiser.GameView3D; import seng302.visualiser.GameView3D;
import seng302.visualiser.controllers.annotations.ImportantAnnotationController; import seng302.visualiser.MiniMap;
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
import seng302.visualiser.controllers.dialogs.FinishDialogController; import seng302.visualiser.controllers.dialogs.FinishDialogController;
import seng302.visualiser.fxObjects.ChatHistory; 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 * 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 final int CHAT_LIMIT = 128;
private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6; private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6;
@@ -75,39 +46,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
@FXML @FXML
private ImageView loadingScreen; private ImageView loadingScreen;
@FXML @FXML
private Pane basePane;
@FXML
private JFXButton chatSend; private JFXButton chatSend;
@FXML @FXML
private Pane chatHistoryHolder; private Pane chatHistoryHolder;
@FXML @FXML
private TextField chatInput; private TextField chatInput;
@FXML @FXML
private LineChart<String, Double> raceSparkLine;
@FXML
private NumberAxis sparklineYAxis;
@FXML
private VBox positionVbox;
@FXML
private CheckBox toggleFps;
@FXML
private Label timerLabel; private Label timerLabel;
@FXML @FXML
private StackPane contentStackPane; private StackPane contentStackPane;
private GridPane contentGridPane;
@FXML @FXML
private AnchorPane rvAnchorPane; private Pane miniMapPane;
@FXML
private AnchorPane windArrowHolder;
@FXML
private Slider annotationSlider;
@FXML
private Button selectAnnotationBtn;
@FXML
private ComboBox<ClientYacht> yachtSelectionComboBox;
@FXML
private Text fpsDisplay;
@FXML @FXML
private ImageView windImageView; private ImageView windImageView;
@FXML @FXML
@@ -118,33 +67,24 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private Label positionLabel, boatSpeedLabel, boatHeadingLabel; private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
@FXML @FXML
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon; private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
@FXML
private JFXButton miniMapButton;
//Race Data
private Map<Integer, ClientYacht> participants;
private Map<Integer, CompoundMark> markers;
private RaceXMLData courseData;
private GameView3D gameView; private GameView3D gameView;
private RaceState raceState; private RaceState raceState;
private ChatHistory chatHistory; private ChatHistory chatHistory;
private Timeline timerTimeline;
private Timer timer = new Timer(); private Timer timer = new Timer();
private List<Series<String, Double>> sparkLineData = new ArrayList<>();
private ImportantAnnotationsState importantAnnotations;
private Polyline windArrow = new WindArrow(Color.LIGHTGRAY);
private ObservableList<ClientYacht> selectionComboBoxList = FXCollections.observableArrayList();
private ClientYacht player; private ClientYacht player;
private JFXDialog finishScreenDialog; private JFXDialog finishScreenDialog;
private FinishDialogController finishDialogController; private FinishDialogController finishDialogController;
//Icon stuff
private Timer blinkingTimer = new Timer(); private Timer blinkingTimer = new Timer();
private ImageView iconToDisplay; private ImageView iconToDisplay;
private Double lastWindDirection; private Double lastWindDirection;
private MiniMap miniMap;
public void initialize() { public void initialize() {
miniMapPane.setVisible(false);
miniMapButton.setVisible(false);
contentStackPane.setVisible(false); contentStackPane.setVisible(false);
Image loadingImage = new Image("PP.png"); Image loadingImage = new Image("PP.png");
loadingScreen.setImage(loadingImage); loadingScreen.setImage(loadingImage);
@@ -204,7 +144,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
public void showView(){ public void showView(){
loadingScreenPane.setVisible(false); loadingScreenPane.setVisible(false);
contentStackPane.setVisible(true); contentStackPane.setVisible(true);
miniMapPane.setVisible(true);
miniMapButton.setVisible(true);
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -238,31 +179,36 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState, Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
ClientYacht player) { ClientYacht player) {
this.participants = participants;
this.courseData = raceData;
this.markers = raceData.getCompoundMarks();
this.raceState = raceState; this.raceState = raceState;
this.player = player; this.player = player;
raceState.getPlayerPositions().addListener((ListChangeListener<ClientYacht>) c -> {
while (c.next()) {
if (c.wasPermutated()) {
updateOrder(raceState.getPlayerPositions());
}
}
});
player.addPowerUpListener(this::displayPowerUpIcon); player.addPowerUpListener(this::displayPowerUpIcon);
player.addPowerDownListener(this::removeIcon); player.addPowerDownListener(this::removeIcon);
updateOrder(raceState.getPlayerPositions());
gameView = new GameView3D(); 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(() -> { Platform.runLater(() -> {
contentStackPane.getChildren().add(0, gameView.getAssets()); contentStackPane.getChildren().add(0, gameView.getAssets());
((SubScene) gameView.getAssets()).widthProperty() ((SubScene) gameView.getAssets()).widthProperty()
.bind(ViewManager.getInstance().getStage().widthProperty()); .bind(ViewManager.getInstance().getStage().widthProperty());
((SubScene) gameView.getAssets()).heightProperty() ((SubScene) gameView.getAssets()).heightProperty()
.bind(ViewManager.getInstance().getStage().heightProperty()); .bind(ViewManager.getInstance().getStage().heightProperty());
miniMapPane.getChildren().add(miniMap.getAssets());
}); });
gameView.setBoats(new ArrayList<>(participants.values())); gameView.setBoats(new ArrayList<>(participants.values()));
gameView.updateBorder(raceData.getCourseLimit()); gameView.updateBorder(raceData.getCourseLimit());
@@ -350,45 +296,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 * 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. * orderings etc.. which are dependent on the info from the stream parser constantly.
@@ -406,35 +313,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}, 0, 1000); }, 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<Corner> 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 * Updates the wind direction arrow and text as from info from the StreamParser
* @param direction the from north angle of the wind. * @param direction the from north angle of the wind.
@@ -516,226 +394,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
boatHeadingLabel.setText(String.format("Boat Heading:\n%.1f°", player.getHeading())); 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<ClientYacht> yachts) {
// List<Text> 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<Double, Double> 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) { public void updateTokens(RaceXMLData raceData) {
gameView.updateTokens(raceData.getTokens()); gameView.updateTokens(raceData.getTokens());
@@ -1,24 +1,12 @@
package seng302.visualiser.controllers; package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXDecorator;
import com.jfoenix.controls.JFXSnackbar;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import seng302.gameServer.ServerAdvertiser;
import seng302.utilities.Sounds;
import seng302.visualiser.GameClient;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/** /**
* Created by Kusal on 26-Sep-17. * Created by Kusal on 26-Sep-17.
@@ -37,7 +25,7 @@ public class SplashScreenController implements Initializable{
class SplashScreen extends Thread { class SplashScreen extends Thread {
public void run(){ public void run(){
try { try {
Thread.sleep(2000); Thread.sleep(3000);
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -404,7 +404,9 @@ public class ViewManager {
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm()); .add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
JFXSnackbar bar = new JFXSnackbar(decorator); JFXSnackbar bar = new JFXSnackbar(decorator);
Platform.runLater(() -> {
bar.enqueue(new JFXSnackbar.SnackbarEvent(msg)); bar.enqueue(new JFXSnackbar.SnackbarEvent(msg));
});
} }
public Stage getStage() { public Stage getStage() {
@@ -27,7 +27,7 @@ public class KeyBindingDialogController implements Initializable {
@FXML @FXML
private Label closeLabel; private Label closeLabel;
@FXML @FXML
private JFXButton zoomInbtn; private JFXButton zoomInBtn;
@FXML @FXML
private JFXButton zoomOutBtn; private JFXButton zoomOutBtn;
@FXML @FXML
@@ -43,6 +43,8 @@ public class KeyBindingDialogController implements Initializable {
@FXML @FXML
private JFXButton resetBtn; private JFXButton resetBtn;
@FXML @FXML
private JFXButton confirmBtn;
@FXML
private Label upwindLabel; private Label upwindLabel;
@FXML @FXML
private Label downwindLabel; private Label downwindLabel;
@@ -70,7 +72,7 @@ public class KeyBindingDialogController implements Initializable {
gameKeyBind = GameKeyBind.getInstance(); gameKeyBind = GameKeyBind.getInstance();
buttons = new ArrayList<>(); buttons = new ArrayList<>();
Collections.addAll(buttons, Collections.addAll(buttons,
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn, zoomInBtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn,
viewButton, rightButton, leftButton, forwardButton, backwardButton); viewButton, rightButton, leftButton, forwardButton, backwardButton);
bindButtonWithAction(); bindButtonWithAction();
loadKeyBind(); loadKeyBind();
@@ -91,6 +93,7 @@ public class KeyBindingDialogController implements Initializable {
}); });
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog()); closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
confirmBtn.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
} }
/** /**
@@ -28,12 +28,12 @@ public class ServerCreationController implements Initializable {
@FXML @FXML
private JFXSlider maxPlayersSlider; private JFXSlider maxPlayersSlider;
@FXML @FXML
private Label maxPlayersLabel;
@FXML
private JFXButton submitBtn; private JFXButton submitBtn;
@FXML @FXML
private Label closeLabel; private Label closeLabel;
@FXML @FXML
private Label maxPlayersLabel;
@FXML
private JFXButton nextMapButton; private JFXButton nextMapButton;
@FXML @FXML
private JFXButton lastMapButton; private JFXButton lastMapButton;
@@ -47,11 +47,10 @@ public class ServerCreationController implements Initializable {
private JFXCheckBox pickupsCheckBox; private JFXCheckBox pickupsCheckBox;
@FXML @FXML
private AnchorPane mapHolder; private AnchorPane mapHolder;
//---------FXML END---------//
private MapMaker mapMaker = MapMaker.getInstance(); private MapMaker mapMaker = MapMaker.getInstance();
//---------FXML END---------//
private List<ServerCreationDialogListener> serverCreationDialogListeners; private List<ServerCreationDialogListener> serverCreationDialogListeners;
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
@@ -96,7 +95,7 @@ public class ServerCreationController implements Initializable {
mapHolder.getChildren().setAll(mapMaker.getCurrentGameView()); mapHolder.getChildren().setAll(mapMaker.getCurrentGameView());
mapNameLabel.setText(mapMaker.getCurrentRegatta().getCourseName()); mapNameLabel.setText(mapMaker.getCurrentRegatta().getCourseName());
pickupsCheckBox.setSelected(true); pickupsCheckBox.setSelected(true);
//closeLabel.setOnMouseClicked(event -> notifyListeners()); closeLabel.setOnMouseClicked(event -> notifyListeners());
} }
/** /**
@@ -119,6 +118,12 @@ public class ServerCreationController implements Initializable {
.runAsHost("localhost", 4941, serverName.getText(), (int) maxPlayersSlider .runAsHost("localhost", 4941, serverName.getText(), (int) maxPlayersSlider
.getValue(), mapMaker.getCurrentRacePath(), (int) legsSlider.getValue(), pickupsCheckBox.isSelected()); .getValue(), mapMaker.getCurrentRacePath(), (int) legsSlider.getValue(), pickupsCheckBox.isSelected());
if (serverDescription == null){
ViewManager.getInstance().getGameClient().getServerThread().closeSocket();
ViewManager.getInstance().getGameClient().stopGame();
return;
}
ViewManager.getInstance().setProperty("serverName", serverDescription.getName()); ViewManager.getInstance().setProperty("serverName", serverDescription.getName());
ViewManager.getInstance().setProperty("mapName", serverDescription.getMapName()); ViewManager.getInstance().setProperty("mapName", serverDescription.getMapName());
} }
@@ -128,7 +133,8 @@ public class ServerCreationController implements Initializable {
*/ */
private void updateMaxPlayerLabel() { private void updateMaxPlayerLabel() {
maxPlayersSlider.setValue(Math.floor(maxPlayersSlider.getValue())); maxPlayersSlider.setValue(Math.floor(maxPlayersSlider.getValue()));
maxPlayersLabel.setText(String.format("Max players: %.0f", maxPlayersSlider.getValue())); maxPlayersLabel.setText(String
.format("Only %.0f players are allowed into the game", maxPlayersSlider.getValue()));
} }
private void updateLegSliderLabel() { private void updateLegSliderLabel() {
@@ -29,11 +29,11 @@ public class MarkArrowFactory {
STARBOARD, STARBOARD,
} }
public static final double MARK_ARROW_SEPARATION = 15; public static final double MARK_ARROW_SEPARATION = 8;
public static final double ARROW_LENGTH = 75; public static final double ARROW_LENGTH = 20;
public static final double ARROW_HEAD_DEPTH = 10; public static final double ARROW_HEAD_DEPTH = 5;
public static final double ARROW_HEAD_WIDTH = 6; public static final double ARROW_HEAD_WIDTH = 3;
public static final double STROKE_WIDTH = 3; public static final double STROKE_WIDTH = 1;
public static Model constructEntryArrow3D ( public static Model constructEntryArrow3D (
RoundingSide roundingSide, double angle, ModelType type) { RoundingSide roundingSide, double angle, ModelType type) {
@@ -106,7 +106,7 @@ public class MarkArrowFactory {
Arc roundSection = new Arc( Arc roundSection = new Arc(
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION, 0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
//Where to start drawing arc from //Where to start drawing arc from
(roundingSide == RoundingSide.PORT ? 0 : angleOfEntry), (roundingSide == RoundingSide.PORT ? 180 + angleOfEntry : angleOfEntry),
//Which way to go around the mark. (clockwise vs anticlockwise) //Which way to go around the mark. (clockwise vs anticlockwise)
roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit) roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit)
); );
@@ -28,8 +28,7 @@ public class Marker2D extends Group {
mark.setRadius(5); mark.setRadius(5);
mark.setCenterX(0); mark.setCenterX(0);
mark.setCenterY(0); mark.setCenterY(0);
Platform.runLater(() -> this.getChildren() Platform.runLater(() -> this.getChildren().add(mark));
.addAll(mark, new Group())); //Empty group placeholder or arrows.
} }
/** /**
@@ -82,13 +81,9 @@ public class Marker2D extends Group {
private void showArrow(List<Group> arrowList, int arrowListIndex) { private void showArrow(List<Group> arrowList, int arrowListIndex) {
if (arrowListIndex < arrowList.size()) { if (arrowListIndex < arrowList.size()) {
if (arrowListIndex == 1) { Platform.runLater(() ->
; this.getChildren().setAll(mark, arrowList.get(arrowListIndex))
} );
Platform.runLater(() -> {
this.getChildren().remove(1);
this.getChildren().add(arrowList.get(arrowListIndex));
});
} }
} }
@@ -60,8 +60,10 @@ public class BoatModel extends Model {
*/ */
public void changeColour(Color newColour) { public void changeColour(Color newColour) {
changeColourChild(HULL_INDEX, newColour); changeColourChild(HULL_INDEX, newColour);
if (meshType != BoatMeshType.PARROT) {
changeColourChild(MAST_INDEX, newColour); changeColourChild(MAST_INDEX, newColour);
} }
}
private void changeColourChild(int index, Color newColour) { private void changeColourChild(int index, Color newColour) {
MeshView meshView = getMeshViewChild(index); MeshView meshView = getMeshViewChild(index);
@@ -4,10 +4,14 @@ 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.beans.property.ReadOnlyDoubleWrapper;
import javafx.geometry.Point2D;
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;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate; import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
/** /**
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 * BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
@@ -30,9 +34,10 @@ public class BoatObject extends Group {
private Color colour = Color.BLACK; private Color colour = Color.BLACK;
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 Rotate tilt = new Rotate(0, new Point3D(0, 1, 0));
private double previousRotation = 0;
// This stuff only matters to the players boat object.
private MeshView markIndicator;
private MeshView playerIndicator;
private ReadOnlyDoubleWrapper rotationProperty; private ReadOnlyDoubleWrapper rotationProperty;
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>(); private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
@@ -81,6 +86,19 @@ public class BoatObject extends Group {
}); });
} }
public void updateMarkIndicator(Point2D markPoint) {
Point2D boatLoc = new Point2D(this.getLayoutX(), this.getLayoutY());
Double angle = Math.toDegrees(
Math.atan2(boatLoc.getY() - markPoint.getY(), boatLoc.getX() - markPoint.getX())) - 90;
Double radius = 0.5;
markIndicator.getTransforms().clear();
markIndicator.getTransforms().addAll(
new Rotate(angle, new Point3D(0, 0, 1)),
new Translate(0, -radius, 0)
);
}
private Double normalizeHeading(double heading, double windDirection) { private Double normalizeHeading(double heading, double windDirection) {
Double normalizedHeading = heading - windDirection; Double normalizedHeading = heading - windDirection;
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L); normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
@@ -91,14 +109,6 @@ 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); rotationProperty.set(heading);
rotation.setAngle(heading); rotation.setAngle(heading);
// if (heading == previousRotation) {
// tilt.setAngle(0);
// } else if (heading < previousRotation) {
// tilt.setAngle(-10);
// } else {
// tilt.setAngle(10);
// }
// previousRotation = 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) {
boatAssets.showSail(); boatAssets.showSail();
@@ -128,6 +138,26 @@ public class BoatObject extends Group {
} }
} }
public void setMarkIndicator(MeshView indicator) {
this.markIndicator = indicator;
this.getChildren().add(markIndicator);
createPlayerIndicator();
setIndicatorColor();
}
private void createPlayerIndicator() {
MeshView torus = ModelFactory.importSTL("player_circle.stl");
playerIndicator = torus;
this.getChildren().add(torus);
}
public void setIndicatorColor() {
Platform.runLater(() -> {
markIndicator.setMaterial(new PhongMaterial(Color.DARKORANGE));
playerIndicator.setMaterial(new PhongMaterial(colour));
});
}
public Group getWake () { public Group getWake () {
return wake; return wake;
} }
@@ -91,35 +91,42 @@ public class ModelFactory {
private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) { private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = new Group(); Group boatAssets = new Group();
MeshView hull = importSTL(boatType.hullFile); MeshView hull = importBoatSTL(boatType.hullFile);
hull.setMaterial(new PhongMaterial(primaryColour)); hull.setMaterial(new PhongMaterial(primaryColour));
MeshView sail = importSTL(boatType.sailFile); boatAssets.getChildren().add(hull);
sail.setMaterial(
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE)
);
boatAssets.getChildren().addAll(hull, sail);
if (boatType.mastFile != null) { if (boatType.mastFile != null) {
MeshView mast = importSTL(boatType.mastFile); MeshView mast = importBoatSTL(boatType.mastFile);
mast.setMaterial(new PhongMaterial(primaryColour)); mast.setMaterial(new PhongMaterial(primaryColour));
boatAssets.getChildren().add(mast); boatAssets.getChildren().add(mast);
} else {
boatAssets.getChildren().add(new Group());
} }
if (boatType.jibFile != null) { MeshView sail = importBoatSTL(boatType.sailFile);
MeshView jib = importSTL(boatType.jibFile);
sail.setMaterial( sail.setMaterial(
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE) new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE)
); );
boatAssets.getChildren().add(sail);
if (boatType.jibFile != null) {
MeshView jib = importBoatSTL(boatType.jibFile);
jib.setMaterial(
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE)
);
boatAssets.getChildren().add(jib); boatAssets.getChildren().add(jib);
} }
return boatAssets; return boatAssets;
} }
private static MeshView importSTL(String fileName) { private static MeshView importBoatSTL(String fileName) {
return importSTL("boatSTLs/" + fileName);
}
public static MeshView importSTL(String fileName) {
StlMeshImporter importer = new StlMeshImporter(); StlMeshImporter importer = new StlMeshImporter();
importer.read(ModelFactory.class.getResource("/meshes/boatSTLs/" + fileName)); importer.read(ModelFactory.class.getResource("/meshes/" + fileName));
MeshView importedFile = new MeshView(importer.getImport()); MeshView importedFile = new MeshView(importer.getImport());
importedFile.setCache(true); importedFile.setCache(true);
importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE); importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE);
@@ -138,6 +145,10 @@ public class ModelFactory {
assets.setCacheHint(CacheHint.SCALE_AND_ROTATE); assets.setCacheHint(CacheHint.SCALE_AND_ROTATE);
} }
switch (tokenType) { switch (tokenType) {
case PLAYER_IDENTIFIER_TORUS:
return makeIdentifierTorus(assets);
case NEXT_MARK_INDICATOR:
return makeNextMarkIndicator(assets);
case VELOCITY_PICKUP: case VELOCITY_PICKUP:
case BUMPER_PICKUP: case BUMPER_PICKUP:
case RANDOM_PICKUP: case RANDOM_PICKUP:
@@ -172,6 +183,16 @@ public class ModelFactory {
} }
} }
private static Model makeIdentifierTorus(Group assets) {
// assets.getChildren().add(new AmbientLight());
return new Model(new Group(assets), null);
}
private static Model makeNextMarkIndicator(Group assets) {
// assets.getChildren().add(new AmbientLight());
return new Model(new Group(assets), null);
}
private static Model makeTokenPickup(Group assets) { private static Model makeTokenPickup(Group assets) {
Rotate animationRotate = new Rotate(0, new Point3D(0, 0, 1)); Rotate animationRotate = new Rotate(0, new Point3D(0, 0, 1));
assets.getTransforms().addAll( assets.getTransforms().addAll(
@@ -28,7 +28,9 @@ public enum ModelType {
START_ARROW ("start_arrow.dae"), START_ARROW ("start_arrow.dae"),
FINISH_ARROW ("finish_arrow.dae"), FINISH_ARROW ("finish_arrow.dae"),
LAND("land.dae"), LAND("land.dae"),
LAND_SMOOTH("land_smooth.dae"); LAND_SMOOTH("land_smooth.dae"),
NEXT_MARK_INDICATOR("indicator_arrow.dae"),
PLAYER_IDENTIFIER_TORUS("torus.dae");
final String filename; final String filename;
+45 -5
View File
@@ -1,10 +1,50 @@
#background { .root {
-fx-background-color: #E7F1F8; -fx-effect: -fx-pp-dropshadow-dark;
-fx-background-radius: 5;
-fx-padding: 10;
}
#rootPane {
-fx-background-image: url("/images/waves.png");
} }
#headText { #headText {
-fx-background-color: transparent;
-fx-font-size: 52px; -fx-font-size: 52px;
-fx-text-fill: -fx-pp-light-text-color; -fx-text-fill: rgb(30, 30, 30);
-fx-effect: -fx-pp-dropshadow-headers; -fx-effect: -fx-pp-dropshadow-dark;
}
#subHeadLabel {
-fx-text-fill: rgb(30, 30, 30);
-fx-effect: -fx-pp-dropshadow-dark;
-fx-font-size: 12px;
}
.materialDesign-purple .arc {
-fx-stroke: #ab47bc;
}
.materialDesign-blue .arc {
-fx-stroke: #2962ff;
}
.materialDesign-cyan .arc {
-fx-stroke: #00b8d4;
}
.materialDesign-green .arc {
-fx-stroke: #00c853;
}
.materialDesign-yellow .arc {
-fx-stroke: #ffd600;
}
.materialDesign-orange .arc {
-fx-stroke: #ff6d00;
}
.materialDesign-red .arc {
-fx-stroke: #d50000;
} }
@@ -35,14 +35,14 @@ JFXToggleButton {
-fx-text-fill: -fx-pp-theme-color; -fx-text-fill: -fx-pp-theme-color;
} }
#resetBtn { #resetBtn, #confirmBtn {
-fx-background-color: -fx-pp-theme-color; -fx-background-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-front-color; -fx-text-fill: -fx-pp-front-color;
-fx-effect: -fx-pp-dropshadow-light; -fx-effect: -fx-pp-dropshadow-light;
-fx-font-size: 18; -fx-font-size: 18;
} }
#resetBtn:hover { #resetBtn:hover, #confirmBtn:hover {
-fx-font-size: 20; -fx-font-size: 20;
} }
@@ -2,6 +2,14 @@
-fx-font-family: monospace !important; -fx-font-family: monospace !important;
} }
.sliderLabel {
-fx-text-fill: -fx-pp-dark-text-color;
}
.error-label * {
-fx-text-fill: red;
}
#submitBtn { #submitBtn {
-fx-background-color: -fx-pp-theme-color; -fx-background-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-light-text-color; -fx-text-fill: -fx-pp-light-text-color;
@@ -32,12 +40,7 @@
-fx-font-size: 16px; -fx-font-size: 16px;
} }
#maxPlayersLabel { .optionLabel {
-fx-text-fill: -fx-pp-dark-text-color;
-fx-font-size: 16px;
}
#maxPlayerPromptLabel {
-fx-text-fill: -fx-pp-dark-text-color; -fx-text-fill: -fx-pp-dark-text-color;
-fx-font-size: 16px; -fx-font-size: 16px;
} }
@@ -55,3 +58,8 @@
-fx-text-fill: red; -fx-text-fill: red;
-fx-font-size: 33px; -fx-font-size: 33px;
} }
JFXCheckBox {
-jfx-checked-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-dark-text-color;
}
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<RaceDefinition>
<CourseName> Loopty Loop </CourseName>
<CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 5 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
<Mark Lat="57.6675700" Lng="11.8359880"/>
<Mark Lat="57.667610" Lng="11.833473"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2">
<Mark Lat="57.670914" Lng="11.835263"/>
<Mark Lat="57.6699024" Lng="11.8353195"/>
</CompoundMark>
<CompoundMark CompoundMarkID="3">
<Mark Lat="57.6674596" Lng="11.8417500"/>
<Mark Lat="57.667473" Lng="11.84429"/>
</CompoundMark>
<CompoundMark CompoundMarkID="4">
<Mark Lat="57.6657945" Lng="11.8351409"/>
<Mark Lat="57.6643158" Lng="11.8352297"/>
</CompoundMark>
<CompoundMark CompoundMarkID="5">
<Mark Lat="57.667311" Lng="11.828857"/>
<Mark Lat="57.667334" Lng="11.825853"/>
</CompoundMark>
</Marks>
<Course>
<OpeningSegment>
<Corner CompoundMarkID="1" Rounding="PS"/>
<Corner CompoundMarkID="2" Rounding="P"/>
</OpeningSegment>
<RepeatingSegment>
<Corner CompoundMarkID="3" Rounding="SP"/>
<Corner CompoundMarkID="4" Rounding="PS"/>
</RepeatingSegment>
<ClosingSegment>
<Corner CompoundMarkID="5" Rounding="PS"/>
</ClosingSegment>
</Course>
<CourseLimit>
<Limit Lat="57.672937" Lng="11.836257" />
<Limit Lat="57.671239" Lng="11.843078" />
<Limit Lat="57.667128" Lng="11.848022" />
<Limit Lat="57.664512" Lng="11.844839" />
<Limit Lat="57.662515" Lng="11.835569" />
<Limit Lat="57.663939" Lng="11.827501" />
<Limit Lat="57.667542" Lng="11.822952" />
<Limit Lat="57.671123" Lng="11.826858" />
</CourseLimit>
</RaceDefinition>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<asset>
<contributor>
<author>Blender User</author>
<authoring_tool>Blender 2.79.0 commit date:2017-09-11, commit time:10:43, hash:5bd8ac9</authoring_tool>
</contributor>
<created>2017-09-28T01:59:46</created>
<modified>2017-09-28T01:59:46</modified>
<unit name="meter" meter="1"/>
<up_axis>Z_UP</up_axis>
</asset>
<library_images/>
<library_effects>
<effect id="Material_001-effect">
<profile_COMMON>
<technique sid="common">
<phong>
<emission>
<color sid="emission">0 0 0 1</color>
</emission>
<ambient>
<color sid="ambient">0 0 0 1</color>
</ambient>
<diffuse>
<color sid="diffuse">0 0.3215737 0.002428917 1</color>
</diffuse>
<specular>
<color sid="specular">0.1614584 0.1614584 0.1614584 1</color>
</specular>
<shininess>
<float sid="shininess">50</float>
</shininess>
<index_of_refraction>
<float sid="index_of_refraction">1</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_materials>
<material id="Material_001-material" name="Material_001">
<instance_effect url="#Material_001-effect"/>
</material>
</library_materials>
<library_geometries>
<geometry id="Cone-mesh" name="Cone">
<mesh>
<source id="Cone-mesh-positions">
<float_array id="Cone-mesh-positions-array" count="99">0 1 -1 0 0 1 0.1950902 0.9807853 -1 0.3826835 0.9238795 -1 0.5555703 0.8314696 -1 0.7071068 0.7071068 -1 0.8314697 0.5555702 -1 0.9238795 0.3826834 -1 0.9807853 0.1950902 -1 1 0 -1 0.9807853 -0.1950902 -1 0.9238796 -0.3826833 -1 0.8314697 -0.5555702 -1 0.7071068 -0.7071068 -1 0.5555702 -0.8314697 -1 0.3826833 -0.9238796 -1 0.1950901 -0.9807853 -1 -3.25841e-7 -1 -1 -0.1950907 -0.9807852 -1 -0.3826839 -0.9238793 -1 -0.5555707 -0.8314693 -1 -0.7071073 -0.7071064 -1 -0.83147 -0.5555697 -1 -0.9238799 -0.3826827 -1 -0.9807854 -0.1950893 -1 -1 9.65599e-7 -1 -0.9807851 0.1950913 -1 -0.9238791 0.3826845 -1 -0.8314689 0.5555713 -1 -0.7071059 0.7071077 -1 -0.5555691 0.8314704 -1 -0.3826821 0.9238801 -1 -0.1950888 0.9807856 -1</float_array>
<technique_common>
<accessor source="#Cone-mesh-positions-array" count="33" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cone-mesh-normals">
<float_array id="Cone-mesh-normals-array" count="117">0.08775347 0.8909768 0.4454884 0.2598883 0.8567371 0.4454883 0.4220357 0.7895733 0.4454883 0.5679644 0.6920669 0.4454883 0.6920669 0.5679644 0.4454883 0.7895736 0.4220353 0.4454883 0.8567369 0.2598885 0.4454883 0.8909768 0.08775347 0.4454884 0.8909768 -0.08775347 0.4454884 0.8567371 -0.2598881 0.4454883 0.7895734 -0.4220355 0.4454884 0.6920669 -0.5679644 0.4454883 0.5679644 -0.6920669 0.4454883 0.4220356 -0.7895734 0.4454883 0.2598879 -0.8567371 0.4454885 0.08775335 -0.8909768 0.4454884 -0.08775389 -0.8909767 0.4454883 -0.2598887 -0.8567368 0.4454883 -0.4220361 -0.7895731 0.4454884 -0.5679646 -0.6920668 0.4454883 -0.6920675 -0.5679637 0.4454884 -0.7895734 -0.4220355 0.4454884 -0.8567374 -0.2598869 0.4454883 -0.8909769 -0.08775287 0.4454884 -0.8909766 0.08775418 0.4454883 -0.8567367 0.2598895 0.4454884 -0.7895728 0.4220367 0.4454883 -0.6920663 0.5679652 0.4454883 -0.5679636 0.6920676 0.4454884 -0.4220345 0.789574 0.4454885 -0.259887 0.8567373 0.4454883 -0.08775269 0.8909768 0.4454884 0 0 -1 -3.97508e-6 0 -1 3.97512e-6 0 -1 3.88859e-7 0 -1 -1.36853e-6 0 -1 1.36853e-6 0 -1 -3.88857e-7 0 -1</float_array>
<technique_common>
<accessor source="#Cone-mesh-normals-array" count="39" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="Cone-mesh-vertices">
<input semantic="POSITION" source="#Cone-mesh-positions"/>
</vertices>
<triangles material="Material_001-material" count="62">
<input semantic="VERTEX" source="#Cone-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cone-mesh-normals" offset="1"/>
<p>0 0 1 0 2 0 2 1 1 1 3 1 3 2 1 2 4 2 4 3 1 3 5 3 5 4 1 4 6 4 6 5 1 5 7 5 7 6 1 6 8 6 8 7 1 7 9 7 9 8 1 8 10 8 10 9 1 9 11 9 11 10 1 10 12 10 12 11 1 11 13 11 13 12 1 12 14 12 14 13 1 13 15 13 15 14 1 14 16 14 16 15 1 15 17 15 17 16 1 16 18 16 18 17 1 17 19 17 19 18 1 18 20 18 20 19 1 19 21 19 21 20 1 20 22 20 22 21 1 21 23 21 23 22 1 22 24 22 24 23 1 23 25 23 25 24 1 24 26 24 26 25 1 25 27 25 27 26 1 26 28 26 28 27 1 27 29 27 29 28 1 28 30 28 30 29 1 29 31 29 31 30 1 30 32 30 32 31 1 31 0 31 16 32 24 32 8 32 32 32 0 32 2 32 2 32 3 32 4 32 4 32 5 32 6 32 6 32 7 32 4 32 8 32 9 32 10 32 10 32 11 32 8 32 12 32 13 32 16 32 14 32 15 32 16 32 16 32 17 32 18 32 18 32 19 32 20 32 20 32 21 32 22 32 22 33 23 33 24 33 24 34 25 34 26 34 26 32 27 32 28 32 28 32 29 32 32 32 30 32 31 32 32 32 32 35 2 35 8 35 4 36 7 36 8 36 8 37 11 37 12 37 13 32 14 32 16 32 16 32 18 32 24 32 20 32 22 32 24 32 24 38 26 38 32 38 29 32 30 32 32 32 2 32 4 32 8 32 8 32 12 32 16 32 18 32 20 32 24 32 26 32 28 32 32 32 32 32 8 32 24 32</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_controllers/>
<library_visual_scenes>
<visual_scene id="Scene" name="Scene">
<node id="Cone" name="Cone" type="NODE">
<matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 1.015816 0 0 0 1</matrix>
<instance_geometry url="#Cone-mesh" name="Cone">
<bind_material>
<technique_common>
<instance_material symbol="Material_001-material" target="#Material_001-material"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
+16 -7
View File
@@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.shape.*?>
<?import com.jfoenix.controls.*?> <?import com.jfoenix.controls.*?>
<?import java.lang.*?> <?import java.lang.*?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
@@ -294,15 +292,26 @@
</GridPane> </GridPane>
</children> </children>
</StackPane> </StackPane>
</children> <Pane fx:id="miniMapPane" maxHeight="200.0" maxWidth="200.0" minHeight="200.0" minWidth="200.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: white; -fx-opacity: 0.45; -fx-background-radius: 10;" StackPane.alignment="TOP_RIGHT">
<StackPane.margin>
<Insets right="15.0" top="15.0" />
</StackPane.margin>
</Pane>
<JFXButton fx:id="miniMapButton" style="-fx-background-color: white; -fx-opacity: 0.45; -fx-background-radius: 10;" text="✕" StackPane.alignment="TOP_RIGHT">
<font>
<Font size="15.0" />
</font>
<StackPane.margin>
<Insets right="15.0" top="15.0" />
</StackPane.margin>
</JFXButton>
<AnchorPane fx:id="loadingScreenPane"> <AnchorPane fx:id="loadingScreenPane">
<children>
<ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0" pickOnBounds="true" preserveRatio="true" /> <ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0" pickOnBounds="true" preserveRatio="true" />
<JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0" /> <JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0" />
</children>
</AnchorPane> </AnchorPane>
</children>
<stylesheets> <stylesheets>
<String fx:value="/css/Master.css"/> <String fx:value="/css/Master.css" />
<String fx:value="/css/RaceView.css"/> <String fx:value="/css/RaceView.css" />
</stylesheets> </stylesheets>
</StackPane> </StackPane>
+2 -2
View File
@@ -113,8 +113,8 @@
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="459.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="429.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="100.0" minHeight="100.0" prefHeight="100.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<stylesheets> <stylesheets>
<String fx:value="/css/Master.css" /> <String fx:value="/css/Master.css" />
+34 -17
View File
@@ -1,30 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXSpinner?>
<?import java.net.URL?> <?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?> <?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?> <StackPane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
<?import javafx.scene.text.Text?> minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8"
<StackPane id="background" fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.SplashScreenController"> xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.SplashScreenController">
<children> <children>
<ImageView fitHeight="296.0" fitWidth="295.0" pickOnBounds="true" preserveRatio="true" StackPane.alignment="TOP_CENTER"> <AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<children>
<Label fx:id="subHeadLabel" layoutX="225.0" layoutY="370.0"
text="MADE BY :PARTYPARROT:"/>
<StackPane layoutX="150.0" layoutY="10.0" prefHeight="150.0" prefWidth="200.0">
<children>
<ImageView fitHeight="190.0" fitWidth="190.0" pickOnBounds="true"
preserveRatio="true">
<image> <image>
<Image url="@../PP.png" /> <Image url="@../PP.png"/>
</image> </image>
<StackPane.margin>
<Insets top="20.0" />
</StackPane.margin>
</ImageView> </ImageView>
<Text fx:id="headText" strokeType="OUTSIDE" strokeWidth="0.0" text="Party Parrots at Sea" StackPane.alignment="BOTTOM_CENTER"> <JFXSpinner fx:id="materialDesignRed" radius="150.0" startingAngle="0.0"
<font> styleClass="materialDesign-red"/>
<Font name="System Bold" size="42.0" /> <JFXSpinner radius="140.0" startingAngle="20.0"
</font> styleClass="materialDesign-orange"/>
<StackPane.margin> <JFXSpinner radius="130.0" startingAngle="40.0"
<Insets bottom="20.0" /> styleClass="materialDesign-yellow"/>
</StackPane.margin> <JFXSpinner radius="120.0" startingAngle="60.0"
</Text> styleClass="materialDesign-green"/>
<JFXSpinner radius="110.0" startingAngle="80.0" styleClass="materialDesign-cyan"/>
<JFXSpinner radius="100.0" startingAngle="100.0"
styleClass="materialDesign-blue"/>
<JFXSpinner radius="90.0" startingAngle="120.0"
styleClass="materialDesign-purple"/>
</children>
</StackPane>
<Label fx:id="headText" layoutX="36.0" layoutY="295.0" text="PARTY PARROT AT SEA"/>
</children>
</AnchorPane>
</children> </children>
<stylesheets> <stylesheets>
<URL value="@../css/Master.css"/> <URL value="@../css/Master.css"/>
@@ -23,6 +23,7 @@
<GridPane> <GridPane>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="60.0" <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="60.0"
@@ -112,7 +113,7 @@
<Insets/> <Insets/>
</GridPane.margin> </GridPane.margin>
</Label> </Label>
<JFXButton id="ZOOM IN" fx:id="zoomInbtn" buttonType="RAISED" <JFXButton id="ZOOM IN" fx:id="zoomInBtn" buttonType="RAISED"
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
minWidth="-Infinity" prefWidth="120.0" text="Z" minWidth="-Infinity" prefWidth="120.0" text="Z"
GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.columnIndex="1" GridPane.halignment="CENTER"
@@ -223,8 +224,19 @@
GridPane.valignment="TOP"/> GridPane.valignment="TOP"/>
<JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity" <JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0"
prefWidth="150.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="CENTER" prefWidth="140.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="LEFT"
GridPane.rowIndex="2" GridPane.valignment="CENTER"/> GridPane.rowIndex="2" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets left="60.0"/>
</GridPane.margin>
</JFXButton>
<JFXButton fx:id="confirmBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="45.0" minWidth="140.0" prefHeight="45.0"
prefWidth="140.0" text="CONFIRM" GridPane.halignment="RIGHT" GridPane.rowIndex="2">
<GridPane.margin>
<Insets right="60.0"/>
</GridPane.margin>
</JFXButton>
</children> </children>
</GridPane> </GridPane>
</children> </children>
@@ -5,16 +5,18 @@
<?import com.jfoenix.controls.JFXDialogLayout?> <?import com.jfoenix.controls.JFXDialogLayout?>
<?import com.jfoenix.controls.JFXSlider?> <?import com.jfoenix.controls.JFXSlider?>
<?import com.jfoenix.controls.JFXTextField?> <?import com.jfoenix.controls.JFXTextField?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.dialogs.ServerCreationController"> minWidth="-Infinity" prefHeight="600.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.dialogs.ServerCreationController">
<children> <children>
<GridPane> <GridPane>
<children> <children>
@@ -36,9 +38,14 @@
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="-Infinity" minHeight="90.0" prefHeight="90.0"
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="-Infinity" minHeight="90.0" prefHeight="90.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="90.0" prefHeight="90.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="90.0" prefHeight="90.0"
vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<JFXTextField fx:id="serverName" promptText="SERVER NAME"> <JFXTextField fx:id="serverName" promptText="SERVER NAME">
@@ -46,29 +53,33 @@
<Insets left="15.0" right="15.0" /> <Insets left="15.0" right="15.0" />
</padding> </padding>
<GridPane.margin> <GridPane.margin>
<Insets left="35.0" right="35.0" /> <Insets left="20.0" right="35.0"/>
</GridPane.margin> </GridPane.margin>
</JFXTextField> </JFXTextField>
<GridPane fx:id="maxPlayersGridPane" GridPane.rowIndex="1"> <GridPane fx:id="maxPlayersGridPane" GridPane.rowIndex="1">
<children> <children>
<Label fx:id="maxPlayersLabel" text="20" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP"> <Label styleClass="optionLabel" text="MAX PLAYERS" translateY="5.0"
GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
<GridPane.margin> <GridPane.margin>
<Insets right="30.0" /> <Insets/>
</GridPane.margin> </GridPane.margin>
</Label> </Label>
<Label fx:id="maxPlayerPromptLabel" text="MAX PLAYERS" GridPane.halignment="LEFT" GridPane.valignment="BOTTOM"> <JFXSlider fx:id="maxPlayersSlider" blockIncrement="1.0"
majorTickUnit="2.0" max="20.0" min="1.0" minorTickCount="1"
snapToTicks="true" styleClass="maxPlayers" value="11.0"
GridPane.columnIndex="1" GridPane.valignment="BOTTOM">
<GridPane.margin> <GridPane.margin>
<Insets left="30.0" top="20.0" /> <Insets right="30.0"/>
</GridPane.margin>
</JFXSlider>
<Label fx:id="maxPlayersLabel" alignment="CENTER"
styleClass="sliderLabel" text="10" GridPane.columnIndex="1"
GridPane.halignment="CENTER" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets right="15.0"/>
</GridPane.margin> </GridPane.margin>
</Label> </Label>
<VBox alignment="BOTTOM_CENTER" prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<children>
<JFXSlider fx:id="maxPlayersSlider" blockIncrement="1.0" majorTickUnit="2.0" max="20.0" min="1.0" minorTickCount="1" snapToTicks="true" styleClass="maxPlayers" value="11.0" />
</children>
<GridPane.margin>
<Insets bottom="10.0" right="30.0" />
</GridPane.margin>
</VBox>
</children> </children>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
@@ -81,48 +92,68 @@
</GridPane> </GridPane>
<GridPane fx:id="maxPlayersGridPane1" GridPane.rowIndex="2"> <GridPane fx:id="maxPlayersGridPane1" GridPane.rowIndex="2">
<children> <children>
<Label fx:id="legsSliderLabel" text="20" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP">
<GridPane.margin>
<Insets right="30.0" />
</GridPane.margin>
</Label>
<VBox alignment="BOTTOM_CENTER" prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<children>
<JFXSlider fx:id="legsSlider" blockIncrement="1.0" majorTickUnit="2.0" max="20.0" min="1.0" minorTickCount="1" snapToTicks="true" styleClass="maxPlayers" value="11.0" />
</children>
<GridPane.margin>
<Insets bottom="10.0" right="30.0" />
</GridPane.margin>
</VBox>
<GridPane> <GridPane>
<children> <children>
<Label alignment="CENTER" text="NUMBER OF" GridPane.halignment="CENTER" /> <Label alignment="CENTER" styleClass="optionLabel"
<Label alignment="CENTER" text="REPEATING LEGS" GridPane.halignment="CENTER" GridPane.rowIndex="1" /> text="NUMBER OF" GridPane.halignment="CENTER"
GridPane.valignment="BOTTOM"/>
</children> </children>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
</GridPane> </GridPane>
<JFXCheckBox fx:id="pickupsCheckBox" text="Enable Pickups" GridPane.rowIndex="1"> <JFXSlider fx:id="legsSlider" blockIncrement="1.0"
majorTickUnit="2.0" max="20.0" min="1.0" minorTickCount="1"
snapToTicks="true" styleClass="maxPlayers" value="11.0"
GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.valignment="BOTTOM">
<GridPane.margin> <GridPane.margin>
<Insets left="5.0" /> <Insets right="30.0"/>
</GridPane.margin> </GridPane.margin>
</JFXCheckBox> </JFXSlider>
<Label alignment="CENTER" styleClass="optionLabel"
text="REPEATING LEGS" GridPane.halignment="CENTER"
GridPane.rowIndex="1"/>
<Label fx:id="legsSliderLabel" styleClass="sliderLabel" text="10"
GridPane.columnIndex="1" GridPane.rowIndex="1">
<GridPane.margin>
<Insets right="15.0"/>
</GridPane.margin>
</Label>
</children> </children>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="100.0" /> <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES"
minWidth="100.0" prefWidth="100.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" percentHeight="60.0" prefHeight="10.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="-Infinity" minHeight="10.0"
<RowConstraints minHeight="10.0" percentHeight="40.0" prefHeight="30.0" vgrow="SOMETIMES" /> percentHeight="60.0" prefHeight="100.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="10.0"
percentHeight="40.0" prefHeight="100.0" vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
</GridPane> </GridPane>
<GridPane GridPane.rowIndex="3">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
percentWidth="30.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0"
vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<JFXCheckBox fx:id="pickupsCheckBox" text=" "
GridPane.columnIndex="1"/>
<Label styleClass="optionLabel" text="ENABLE TOKENS"
GridPane.halignment="CENTER" GridPane.valignment="CENTER"/>
</children>
</GridPane>
</children> </children>
</GridPane> </GridPane>
<GridPane GridPane.columnIndex="1"> <GridPane GridPane.columnIndex="1">
@@ -152,7 +183,8 @@
<RowConstraints maxHeight="342.0" minHeight="10.0" prefHeight="336.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="342.0" minHeight="10.0" prefHeight="336.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label fx:id="mapNameLabel" text="MAP NAME" GridPane.halignment="CENTER" /> <Label fx:id="mapNameLabel" styleClass="optionLabel" text="MAP NAME"
GridPane.halignment="CENTER"/>
<AnchorPane fx:id="mapHolder" prefHeight="333.0" prefWidth="404.0" GridPane.rowIndex="1" /> <AnchorPane fx:id="mapHolder" prefHeight="333.0" prefWidth="404.0" GridPane.rowIndex="1" />
</children> </children>
</GridPane> </GridPane>
@@ -164,6 +196,8 @@
<font> <font>
<Font size="20.0" /> <Font size="20.0" />
</font></Label> </font></Label>
<Label fx:id="closeLabel" text="✖" translateY="-10.0" GridPane.halignment="RIGHT"
GridPane.valignment="TOP"/>
</children> </children>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
@@ -175,4 +209,8 @@
</rowConstraints> </rowConstraints>
</GridPane> </GridPane>
</children> </children>
<stylesheets>
<URL value="@../../css/Master.css"/>
<URL value="@../../css/dialogs/ServerCreation.css"/>
</stylesheets>
</JFXDialogLayout> </JFXDialogLayout>
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXDialogLayout?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="273.0" prefWidth="436.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.dialogs.TokenInfoDialogController">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="40.0" minHeight="30.0" prefHeight="40.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="80.0"
prefHeight="115.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="141.0" minHeight="34.0" prefHeight="73.0"
vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<JFXButton fx:id="optionButton" buttonType="RAISED" prefHeight="55.0"
prefWidth="150.0" text="Ok" GridPane.halignment="CENTER" GridPane.rowIndex="2"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin>
</JFXButton>
<Label fx:id="headerLabel" text="Popup header" GridPane.halignment="CENTER">
<font>
<Font size="15.0"/>
</font>
</Label>
<GridPane GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="270.0" minWidth="10.0"
prefWidth="270.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="225.0" minWidth="-Infinity"
prefWidth="138.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="100.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Pane fx:id="tokenPane" prefHeight="200.0" prefWidth="200.0"
GridPane.columnIndex="1"/>
<TextArea fx:id="contentText" nodeOrientation="RIGHT_TO_LEFT"
prefHeight="200.0" prefWidth="200.0" promptText="This is some text"
stylesheets="@../../css/TokenInfoDialog.css" wrapText="true">
<font>
<Font size="16.0"/>
</font>
</TextArea>
</children>
</GridPane>
</children>
</GridPane>
</children>
<stylesheets>
<URL value="@../../css/dialogs/Popup.css"/>
<URL value="@../../css/Master.css"/>
</stylesheets>
</JFXDialogLayout>