mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge remote-tracking branch 'origin/develop' into 1293_PowerUps
# Conflicts: # src/main/java/seng302/model/ServerYacht.java # src/main/resources/views/RaceView.fxml
This commit is contained in:
@@ -1,12 +1,35 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import seng302.gameServer.messages.*;
|
import seng302.gameServer.messages.BoatAction;
|
||||||
import seng302.model.*;
|
import seng302.gameServer.messages.BoatStatus;
|
||||||
|
import seng302.gameServer.messages.ChatterMessage;
|
||||||
|
import seng302.gameServer.messages.CustomizeRequestType;
|
||||||
|
import seng302.gameServer.messages.MarkRoundingMessage;
|
||||||
|
import seng302.gameServer.messages.MarkType;
|
||||||
|
import seng302.gameServer.messages.Message;
|
||||||
|
import seng302.gameServer.messages.RoundingBoatStatus;
|
||||||
|
import seng302.gameServer.messages.YachtEventCodeMessage;
|
||||||
|
import seng302.gameServer.messages.YachtEventType;
|
||||||
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.Limit;
|
||||||
|
import seng302.model.Player;
|
||||||
|
import seng302.model.PolarTable;
|
||||||
|
import seng302.model.ServerYacht;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.mark.MarkOrder;
|
import seng302.model.mark.MarkOrder;
|
||||||
@@ -14,10 +37,6 @@ import seng302.model.token.Token;
|
|||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
import seng302.utilities.XMLParser;
|
import seng302.utilities.XMLParser;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import java.util.*;
|
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -341,6 +360,12 @@ public class GameState implements Runnable {
|
|||||||
case DOWNWIND:
|
case DOWNWIND:
|
||||||
playerYacht.turnDownwind();
|
playerYacht.turnDownwind();
|
||||||
break;
|
break;
|
||||||
|
case CONTINUOUSLY_TURNING:
|
||||||
|
playerYacht.setContinuouslyTurning(true);
|
||||||
|
break;
|
||||||
|
case DEFAULT_TURNING:
|
||||||
|
playerYacht.setContinuouslyTurning(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ public enum BoatAction {
|
|||||||
TACK_GYBE(4),
|
TACK_GYBE(4),
|
||||||
UPWIND(5),
|
UPWIND(5),
|
||||||
DOWNWIND(6),
|
DOWNWIND(6),
|
||||||
MAINTAIN_HEADING(7);
|
MAINTAIN_HEADING(7),
|
||||||
|
CONTINUOUSLY_TURNING(8),
|
||||||
|
DEFAULT_TURNING(9);
|
||||||
|
|
||||||
private final int type;
|
private final int type;
|
||||||
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
|
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
|
||||||
|
public class GameKeyBind {
|
||||||
|
|
||||||
|
private static GameKeyBind instance;
|
||||||
|
private Map<KeyCode, KeyAction> keyToActionMap;
|
||||||
|
private Map<KeyAction, KeyCode> actionToKeyMap;
|
||||||
|
private Boolean continuouslyTurning;
|
||||||
|
|
||||||
|
|
||||||
|
private GameKeyBind() {
|
||||||
|
setToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToDefault() {
|
||||||
|
actionToKeyMap = new HashMap<>();
|
||||||
|
keyToActionMap = new HashMap<>();
|
||||||
|
continuouslyTurning = false;
|
||||||
|
// default key bindings
|
||||||
|
ArrayList<KeyCode> keys = new ArrayList<>();
|
||||||
|
keys.add(KeyCode.Z);
|
||||||
|
keys.add(KeyCode.X);
|
||||||
|
keys.add(KeyCode.SPACE);
|
||||||
|
keys.add(KeyCode.SHIFT);
|
||||||
|
keys.add(KeyCode.ENTER);
|
||||||
|
keys.add(KeyCode.PAGE_UP);
|
||||||
|
keys.add(KeyCode.PAGE_DOWN);
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
actionToKeyMap.put(KeyAction.getType(i + 1), keys.get(i));
|
||||||
|
keyToActionMap.put(keys.get(i), KeyAction.getType(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameKeyBind getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new GameKeyBind();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyCode getKeyCode(KeyAction keyAction) {
|
||||||
|
return instance.actionToKeyMap.get(keyAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a key to a key action
|
||||||
|
*
|
||||||
|
* @return true if successfully bind
|
||||||
|
*/
|
||||||
|
public boolean bindKeyToAction(KeyCode keyCode, KeyAction keyAction) {
|
||||||
|
if (instance.keyToActionMap.containsKey(keyCode)) {
|
||||||
|
// if the key has been bound to other action, return false
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
instance.keyToActionMap.put(keyCode, keyAction); // add key -> action
|
||||||
|
KeyCode oldKeyCode = instance.actionToKeyMap
|
||||||
|
.get(keyAction); // get old key for the action
|
||||||
|
instance.keyToActionMap.remove(oldKeyCode); // remove the old key -> action
|
||||||
|
instance.actionToKeyMap
|
||||||
|
.replace(keyAction, keyCode); // replace the old key by the newer one
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleTurningMode() {
|
||||||
|
continuouslyTurning = !continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isContinuouslyTurning() {
|
||||||
|
return continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public enum KeyAction {
|
||||||
|
ZOOM_IN(1),
|
||||||
|
ZOOM_OUT(2),
|
||||||
|
VMG(3),
|
||||||
|
SAILS_STATE(4),
|
||||||
|
TACK_GYBE(5),
|
||||||
|
UPWIND(6),
|
||||||
|
DOWNWIND(7);
|
||||||
|
|
||||||
|
private final int type;
|
||||||
|
private static final Map<Integer, KeyAction> intToTypeMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (KeyAction type : KeyAction.values()) {
|
||||||
|
intToTypeMap.put(type.getValue(), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyAction(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyAction getType(int value) {
|
||||||
|
return intToTypeMap.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package seng302.model;
|
package seng302.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -10,8 +11,6 @@ import seng302.model.token.TokenType;
|
|||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
||||||
* compared to the XMLParser boat class, also done outside Boat class because some old variables are
|
* compared to the XMLParser boat class, also done outside Boat class because some old variables are
|
||||||
@@ -59,6 +58,8 @@ public class ServerYacht {
|
|||||||
private Integer powerUpSpeedMultiplier;
|
private Integer powerUpSpeedMultiplier;
|
||||||
private Integer powerUpHandlingMultiplier;
|
private Integer powerUpHandlingMultiplier;
|
||||||
|
|
||||||
|
//turning mode
|
||||||
|
private Boolean continuouslyTurning;
|
||||||
|
|
||||||
public ServerYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
public ServerYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
||||||
String boatName, String country) {
|
String boatName, String country) {
|
||||||
@@ -81,10 +82,10 @@ public class ServerYacht {
|
|||||||
this.powerUp = null;
|
this.powerUp = null;
|
||||||
this.powerUpSpeedMultiplier = 1;
|
this.powerUpSpeedMultiplier = 1;
|
||||||
this.powerUpHandlingMultiplier = 1;
|
this.powerUpHandlingMultiplier = 1;
|
||||||
|
|
||||||
this.hasEnteredRoundingZone = false;
|
this.hasEnteredRoundingZone = false;
|
||||||
this.hasPassedLine = false;
|
this.hasPassedLine = false;
|
||||||
this.hasPassedThroughGate = false;
|
this.hasPassedThroughGate = false;
|
||||||
|
this.continuouslyTurning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -194,6 +195,9 @@ public class ServerYacht {
|
|||||||
public void turnUpwind() {
|
public void turnUpwind() {
|
||||||
disableAutoPilot();
|
disableAutoPilot();
|
||||||
Double normalizedHeading = normalizeHeading();
|
Double normalizedHeading = normalizeHeading();
|
||||||
|
if (continuouslyTurning) {
|
||||||
|
adjustHeading(turnStep);
|
||||||
|
} else {
|
||||||
if (normalizedHeading == 0) {
|
if (normalizedHeading == 0) {
|
||||||
if (lastHeading < 180) {
|
if (lastHeading < 180) {
|
||||||
adjustHeading(-turnStep);
|
adjustHeading(-turnStep);
|
||||||
@@ -212,10 +216,14 @@ public class ServerYacht {
|
|||||||
adjustHeading(turnStep);
|
adjustHeading(turnStep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void turnDownwind() {
|
public void turnDownwind() {
|
||||||
disableAutoPilot();
|
disableAutoPilot();
|
||||||
Double normalizedHeading = normalizeHeading();
|
Double normalizedHeading = normalizeHeading();
|
||||||
|
if (continuouslyTurning) {
|
||||||
|
adjustHeading(-turnStep);
|
||||||
|
} else {
|
||||||
if (normalizedHeading == 0) {
|
if (normalizedHeading == 0) {
|
||||||
if (lastHeading < 180) {
|
if (lastHeading < 180) {
|
||||||
adjustHeading(turnStep);
|
adjustHeading(turnStep);
|
||||||
@@ -234,6 +242,7 @@ public class ServerYacht {
|
|||||||
adjustHeading(-turnStep);
|
adjustHeading(-turnStep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes the VMG from the polartable for upwind or downwind depending on the boats direction,
|
* Takes the VMG from the polartable for upwind or downwind depending on the boats direction,
|
||||||
@@ -448,6 +457,10 @@ public class ServerYacht {
|
|||||||
return boatType;
|
return boatType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContinuouslyTurning(Boolean continuouslyTurning) {
|
||||||
|
this.continuouslyTurning = continuouslyTurning;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getPowerUpSpeedMultiplier() {
|
public Integer getPowerUpSpeedMultiplier() {
|
||||||
return powerUpSpeedMultiplier;
|
return powerUpSpeedMultiplier;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import seng302.gameServer.messages.BoatAction;
|
|||||||
import seng302.gameServer.messages.BoatStatus;
|
import seng302.gameServer.messages.BoatStatus;
|
||||||
import seng302.gameServer.messages.YachtEventType;
|
import seng302.gameServer.messages.YachtEventType;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
import seng302.model.RaceState;
|
import seng302.model.RaceState;
|
||||||
import seng302.model.stream.packets.StreamPacket;
|
import seng302.model.stream.packets.StreamPacket;
|
||||||
import seng302.model.stream.parser.MarkRoundingData;
|
import seng302.model.stream.parser.MarkRoundingData;
|
||||||
@@ -70,6 +72,8 @@ public class GameClient {
|
|||||||
|
|
||||||
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
|
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
|
||||||
|
|
||||||
|
private GameKeyBind gameKeyBind; // all the key binding setting.
|
||||||
|
|
||||||
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
|
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +83,7 @@ public class GameClient {
|
|||||||
*/
|
*/
|
||||||
public GameClient(Pane holder) {
|
public GameClient(Pane holder) {
|
||||||
this.holderPane = holder;
|
this.holderPane = holder;
|
||||||
|
this.gameKeyBind = GameKeyBind.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -372,16 +377,16 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (e.getCode()) {
|
|
||||||
case SPACE: // align with vmg
|
if (gameKeyBind.getKeyCode(KeyAction.VMG) == e.getCode()) { // align with vmg
|
||||||
socketThread.sendBoatAction(BoatAction.VMG); break;
|
socketThread.sendBoatAction(BoatAction.VMG);
|
||||||
case PAGE_UP: // upwind
|
} else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()) { // upwind
|
||||||
socketThread.sendBoatAction(BoatAction.UPWIND); break;
|
socketThread.sendBoatAction(BoatAction.UPWIND);
|
||||||
case PAGE_DOWN: // downwind
|
} else if (gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) { // downwind
|
||||||
socketThread.sendBoatAction(BoatAction.DOWNWIND); break;
|
socketThread.sendBoatAction(BoatAction.DOWNWIND);
|
||||||
case ENTER: // tack/gybe
|
} else if (gameKeyBind.getKeyCode(KeyAction.TACK_GYBE) == e.getCode()) { // tack/gybe
|
||||||
// if chat box is active take whatever is in there and send it to server
|
// if chat box is active take whatever is in there and send it to server
|
||||||
socketThread.sendBoatAction(BoatAction.TACK_GYBE); break;
|
socketThread.sendBoatAction(BoatAction.TACK_GYBE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,15 +395,13 @@ public class GameClient {
|
|||||||
if (raceView.isChatInputFocused()) {
|
if (raceView.isChatInputFocused()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (e.getCode()) {
|
|
||||||
//TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
|
if (gameKeyBind.getKeyCode(KeyAction.SAILS_STATE) == e.getCode()) { // sails in/sails out
|
||||||
case SHIFT: // sails in/sails out
|
|
||||||
socketThread.sendBoatAction(BoatAction.SAILS_IN);
|
socketThread.sendBoatAction(BoatAction.SAILS_IN);
|
||||||
allBoatsMap.get(socketThread.getClientId()).toggleSail();
|
allBoatsMap.get(socketThread.getClientId()).toggleSail();
|
||||||
break;
|
} else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()
|
||||||
case PAGE_UP:
|
|| gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) {
|
||||||
case PAGE_DOWN:
|
socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING);
|
||||||
socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,4 +503,14 @@ public class GameClient {
|
|||||||
public Map<Integer, ClientYacht> getAllBoatsMap() {
|
public Map<Integer, ClientYacht> getAllBoatsMap() {
|
||||||
return allBoatsMap;
|
return allBoatsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendToggleTurningModePacket() {
|
||||||
|
if (socketThread != null) {
|
||||||
|
if (gameKeyBind.isContinuouslyTurning()) {
|
||||||
|
socketThread.sendBoatAction(BoatAction.CONTINUOUSLY_TURNING);
|
||||||
|
} else {
|
||||||
|
socketThread.sendBoatAction(BoatAction.DEFAULT_TURNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,16 +91,16 @@ public class LobbyController implements Initializable {
|
|||||||
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
|
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
customizeButton.setOnMouseReleased(event -> {
|
||||||
|
customizationDialog = createCustomizeDialog();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
customizationDialog.show();
|
||||||
|
});
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
|
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
|
||||||
|
|
||||||
playersColor = Colors.getColor(playerId - 1);
|
playersColor = Colors.getColor(playerId - 1);
|
||||||
customizationDialog = createCustomizeDialog();
|
|
||||||
|
|
||||||
customizeButton.setOnMouseReleased(event -> {
|
|
||||||
Sounds.playButtonClick();
|
|
||||||
customizationDialog.show();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound());
|
leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound());
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private Label timerLabel;
|
private Label timerLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private StackPane contentAnchorPane;
|
private StackPane contentStackPane;
|
||||||
|
|
||||||
private GridPane contentGridPane;
|
private GridPane contentGridPane;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -149,8 +149,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
Sounds.stopMusic();
|
Sounds.stopMusic();
|
||||||
Sounds.playRaceMusic();
|
Sounds.playRaceMusic();
|
||||||
|
|
||||||
finishScreenDialog = createFinishDialog();
|
|
||||||
|
|
||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
//importantAnnotations = new ImportantAnnotationsState();
|
//importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
@@ -195,9 +193,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
|
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
|
||||||
// chatHistory.setScrollTop(Double.MAX_VALUE);
|
// chatHistory.setScrollTop(Double.MAX_VALUE);
|
||||||
// });
|
// });
|
||||||
rvAnchorPane.setOnMouseClicked((event) ->
|
|
||||||
rvAnchorPane.requestFocus()
|
contentStackPane.setOnMouseClicked(event -> {
|
||||||
);
|
contentStackPane.requestFocus();
|
||||||
|
});
|
||||||
|
|
||||||
//Makes the chat history non transparent when clicked on
|
//Makes the chat history non transparent when clicked on
|
||||||
chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() {
|
chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
@@ -215,26 +214,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
||||||
raceState.setRaceStarted(false);
|
raceState.setRaceStarted(false);
|
||||||
finishDialogController.setFinishedBoats(finishedBoats);
|
createFinishDialog(finishedBoats);
|
||||||
finishScreenDialog.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JFXDialog createFinishDialog() {
|
/**
|
||||||
|
* Create finishScreenDialog and set up finishDialogController.
|
||||||
|
*/
|
||||||
|
private void createFinishDialog(ArrayList<ClientYacht> finishedBoats) {
|
||||||
FXMLLoader dialog = new FXMLLoader(
|
FXMLLoader dialog = new FXMLLoader(
|
||||||
getClass().getResource("/views/dialogs/RaceFinishDialog.fxml"));
|
getClass().getResource("/views/dialogs/RaceFinishDialog.fxml"));
|
||||||
|
|
||||||
JFXDialog finishScreenDialog = null;
|
Platform.runLater(() -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
finishScreenDialog = new JFXDialog(contentAnchorPane, dialog.load(),
|
finishScreenDialog = new JFXDialog(contentStackPane, dialog.load(),
|
||||||
JFXDialog.DialogTransition.CENTER);
|
JFXDialog.DialogTransition.CENTER);
|
||||||
|
finishDialogController = dialog.getController();
|
||||||
|
finishDialogController.setFinishedBoats(finishedBoats);
|
||||||
|
finishScreenDialog.show();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
finishDialogController = dialog.getController();
|
|
||||||
|
|
||||||
return finishScreenDialog;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
gameView = new GameView3D();
|
gameView = new GameView3D();
|
||||||
// gameView.setFrameRateFXText(fpsDisplay);
|
// gameView.setFrameRateFXText(fpsDisplay);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
contentAnchorPane.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()
|
||||||
@@ -879,7 +879,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
public String readChatInput() {
|
public String readChatInput() {
|
||||||
String chat = chatInput.getText();
|
String chat = chatInput.getText();
|
||||||
chatInput.clear();
|
chatInput.clear();
|
||||||
rvAnchorPane.requestFocus();
|
contentStackPane.requestFocus();
|
||||||
return chat;
|
return chat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,16 +112,23 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
serverListVBox.getChildren().add(noServersFound);
|
serverListVBox.getChildren().add(noServersFound);
|
||||||
|
|
||||||
// Set up dialog for server creation
|
// Set up dialog for server creation
|
||||||
|
serverListHostButton.setOnAction(action -> {
|
||||||
|
showServerCreationDialog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows Server Creation Dialog when "Host" button is clicked.
|
||||||
|
*/
|
||||||
|
private void showServerCreationDialog() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
||||||
"/views/dialogs/ServerCreationDialog.fxml"));
|
"/views/dialogs/ServerCreationDialog.fxml"));
|
||||||
try {
|
try {
|
||||||
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
||||||
DialogTransition.CENTER);
|
DialogTransition.CENTER);
|
||||||
serverListHostButton.setOnAction(action -> {
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
Sounds.playButtonClick();
|
Sounds.playButtonClick();
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("Could not create Server Creation Dialog.");
|
logger.warn("Could not create Server Creation Dialog.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package seng302.visualiser.controllers;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXDecorator;
|
import com.jfoenix.controls.JFXDecorator;
|
||||||
|
import com.jfoenix.controls.JFXDialog;
|
||||||
|
import com.jfoenix.controls.JFXDialog.DialogTransition;
|
||||||
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
import com.jfoenix.svg.SVGGlyph;
|
import com.jfoenix.svg.SVGGlyph;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -15,6 +18,7 @@ import javafx.scene.Scene;
|
|||||||
import javafx.scene.SceneAntialiasing;
|
import javafx.scene.SceneAntialiasing;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -23,6 +27,7 @@ import seng302.gameServer.ServerAdvertiser;
|
|||||||
import seng302.utilities.BonjourInstallChecker;
|
import seng302.utilities.BonjourInstallChecker;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameClient;
|
import seng302.visualiser.GameClient;
|
||||||
|
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
|
||||||
|
|
||||||
public class ViewManager {
|
public class ViewManager {
|
||||||
|
|
||||||
@@ -32,12 +37,9 @@ public class ViewManager {
|
|||||||
private HashMap<String, String> properties; //TODO is this the best way to do this??
|
private HashMap<String, String> properties; //TODO is this the best way to do this??
|
||||||
private ObservableList<String> playerList;
|
private ObservableList<String> playerList;
|
||||||
private Logger logger = LoggerFactory.getLogger(ViewManager.class);
|
private Logger logger = LoggerFactory.getLogger(ViewManager.class);
|
||||||
|
|
||||||
public Stage getStage() {
|
|
||||||
return stage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
private JFXSnackbar jfxSnackbar;
|
||||||
|
private JFXDialog keyBindingDialog;
|
||||||
|
|
||||||
private ViewManager() {
|
private ViewManager() {
|
||||||
properties = new HashMap<>();
|
properties = new HashMap<>();
|
||||||
@@ -99,6 +101,8 @@ public class ViewManager {
|
|||||||
gameClient.stopGame();
|
gameClient.stopGame();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jfxSnackbar = new JFXSnackbar(decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,12 +123,31 @@ public class ViewManager {
|
|||||||
//Get the button box
|
//Get the button box
|
||||||
HBox btns = (HBox) decorator.getChildren().get(0);
|
HBox btns = (HBox) decorator.getChildren().get(0);
|
||||||
|
|
||||||
|
//Create settings button -- [WIP]
|
||||||
|
JFXButton btnKeyBinding = new JFXButton();
|
||||||
|
btnKeyBinding.setText(" Key Bindings");
|
||||||
|
btnKeyBinding.setStyle("-fx-text-fill:#fff");
|
||||||
|
btnKeyBinding.getStyleClass().add("jfx-decorator-button");
|
||||||
|
btnKeyBinding.setCursor(Cursor.HAND);
|
||||||
|
btnKeyBinding.setFocusTraversable(false);
|
||||||
|
|
||||||
|
btnKeyBinding.setOnMouseClicked(event -> Platform.runLater(() -> {
|
||||||
|
try {
|
||||||
|
if (!checkDialogOpened(decorator.getChildren())) {
|
||||||
|
showKeyBindingDialog();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Something went wrong when opening key bind dialog");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
//Create new button
|
//Create new button
|
||||||
JFXButton btnMute = new JFXButton();
|
JFXButton btnMute = new JFXButton();
|
||||||
btnMute.setText(" Toggle Sound");
|
btnMute.setText(" Toggle Sound");
|
||||||
btnMute.setStyle("-fx-text-fill:#fff");
|
btnMute.setStyle("-fx-text-fill:#fff");
|
||||||
btnMute.getStyleClass().add("jfx-decorator-button");
|
btnMute.getStyleClass().add("jfx-decorator-button");
|
||||||
btnMute.setCursor(Cursor.HAND);
|
btnMute.setCursor(Cursor.HAND);
|
||||||
|
btnMute.setFocusTraversable(false);
|
||||||
|
|
||||||
//Create Graphics
|
//Create Graphics
|
||||||
SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE);
|
SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE);
|
||||||
@@ -134,9 +157,13 @@ public class ViewManager {
|
|||||||
SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON",
|
SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON",
|
||||||
"M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z",
|
"M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z",
|
||||||
Color.WHITE);
|
Color.WHITE);
|
||||||
|
SVGGlyph keyBindingGlyph = new SVGGlyph(0, "KEY_BINDING",
|
||||||
|
"M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z",
|
||||||
|
Color.WHITE);
|
||||||
volumeOn.setSize(16, 16);
|
volumeOn.setSize(16, 16);
|
||||||
volumeOff.setSize(16, 16);
|
volumeOff.setSize(16, 16);
|
||||||
spacer.setSize(40, 16);
|
spacer.setSize(40, 16);
|
||||||
|
keyBindingGlyph.setSize(24, 16);
|
||||||
|
|
||||||
// Determine which graphic should go on the button
|
// Determine which graphic should go on the button
|
||||||
if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) {
|
if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) {
|
||||||
@@ -145,9 +172,12 @@ public class ViewManager {
|
|||||||
btnMute.setGraphic(volumeOn);
|
btnMute.setGraphic(volumeOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btnKeyBinding.setGraphic(keyBindingGlyph);
|
||||||
|
|
||||||
// Add Buttons
|
// Add Buttons
|
||||||
btns.getChildren().add(0, spacer);
|
btns.getChildren().add(0, spacer);
|
||||||
btns.getChildren().add(0, btnMute);
|
btns.getChildren().add(0, btnMute);
|
||||||
|
btns.getChildren().add(0, btnKeyBinding);
|
||||||
btnMute.setOnAction((action) -> {
|
btnMute.setOnAction((action) -> {
|
||||||
Sounds.toggleAllSounds();
|
Sounds.toggleAllSounds();
|
||||||
if (btnMute.getGraphic().equals(volumeOff)) {
|
if (btnMute.getGraphic().equals(volumeOff)) {
|
||||||
@@ -159,6 +189,63 @@ public class ViewManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively find JFXDialog given a starting node. Will traverse children of StackPane.
|
||||||
|
*
|
||||||
|
* @param nodes children nodes to be check.
|
||||||
|
* @return true if node contains JFXDialog.
|
||||||
|
*/
|
||||||
|
private Boolean checkDialogOpened(ObservableList<Node> nodes) {
|
||||||
|
boolean foundJFXDialog = false;
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node instanceof JFXDialog) {
|
||||||
|
return true;
|
||||||
|
} else if (node instanceof StackPane) {
|
||||||
|
foundJFXDialog = checkDialogOpened(((StackPane) node).getChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundJFXDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showKeyBindingDialog() throws IOException {
|
||||||
|
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
||||||
|
"/views/dialogs/KeyBindingDialog.fxml"));
|
||||||
|
for (Node node : decorator.getChildren()) {
|
||||||
|
if (node instanceof StackPane) {
|
||||||
|
keyBindingDialog = new JFXDialog((StackPane) node,
|
||||||
|
dialogContent.load(),
|
||||||
|
DialogTransition.CENTER);
|
||||||
|
|
||||||
|
KeyBindingDialogController keyBindingDialogController = dialogContent
|
||||||
|
.getController();
|
||||||
|
keyBindingDialogController.setGameClient(this.gameClient);
|
||||||
|
keyBindingDialog.show();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeKeyBindingDialog() {
|
||||||
|
keyBindingDialog.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a snackbar at the bottom of the app for 1 second.
|
||||||
|
*
|
||||||
|
* @param snackbarText text to be displayed.
|
||||||
|
*/
|
||||||
|
public void showSnackbar(String snackbarText, boolean isWarning) {
|
||||||
|
if (isWarning) {
|
||||||
|
decorator.getStylesheets()
|
||||||
|
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
|
||||||
|
} else {
|
||||||
|
if (decorator.getStylesheets().size() > 1) {
|
||||||
|
decorator.getStylesheets().remove(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jfxSnackbar.show(snackbarText, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a PC has compatibility with the bonjour protocol for server detection.
|
* Determines if a PC has compatibility with the bonjour protocol for server detection.
|
||||||
*/
|
*/
|
||||||
@@ -221,6 +308,7 @@ public class ViewManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the view to the Lobby Screen
|
* Change the view to the Lobby Screen
|
||||||
|
*
|
||||||
* @param disableReadyButton Boolean value so that clients can't try start a game.
|
* @param disableReadyButton Boolean value so that clients can't try start a game.
|
||||||
* @return A LobbyController object for the Lobby Screen.
|
* @return A LobbyController object for the Lobby Screen.
|
||||||
*/
|
*/
|
||||||
@@ -243,6 +331,7 @@ public class ViewManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the view for the race. Creating a new decorator and destroying the old one.
|
* Sets up the view for the race. Creating a new decorator and destroying the old one.
|
||||||
|
*
|
||||||
* @return A RaceViewController for the race view screen.
|
* @return A RaceViewController for the race view screen.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -267,15 +356,6 @@ public class ViewManager {
|
|||||||
scene.setOnKeyPressed(gameClient::keyPressed);
|
scene.setOnKeyPressed(gameClient::keyPressed);
|
||||||
scene.setOnKeyReleased(gameClient::keyReleased);
|
scene.setOnKeyReleased(gameClient::keyReleased);
|
||||||
|
|
||||||
// uncomment to make it full screen
|
|
||||||
// Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
|
|
||||||
// stage.setX(visualBounds.getMinX());
|
|
||||||
// stage.setY(visualBounds.getMinY());
|
|
||||||
// stage.setWidth(visualBounds.getWidth());
|
|
||||||
// stage.setHeight(visualBounds.getHeight());
|
|
||||||
// stage.setMaximized(true);
|
|
||||||
// stage.setFullScreen(true);
|
|
||||||
|
|
||||||
stage.setMinHeight(500);
|
stage.setMinHeight(500);
|
||||||
stage.setMinWidth(800);
|
stage.setMinWidth(800);
|
||||||
stage.setTitle("Party Parrots At Sea");
|
stage.setTitle("Party Parrots At Sea");
|
||||||
@@ -298,4 +378,9 @@ public class ViewManager {
|
|||||||
|
|
||||||
return loader.getController();
|
return loader.getController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stage getStage() {
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,185 @@
|
|||||||
|
package seng302.visualiser.controllers.dialogs;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXToggleButton;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
|
import seng302.visualiser.GameClient;
|
||||||
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
|
||||||
|
public class KeyBindingDialogController implements Initializable {
|
||||||
|
|
||||||
|
//--------FXML BEGIN--------//
|
||||||
|
@FXML
|
||||||
|
private Label keyBindingDialogHeader;
|
||||||
|
@FXML
|
||||||
|
private Label closeLabel;
|
||||||
|
@FXML
|
||||||
|
private JFXButton zoomInbtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton zoomOutBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton vmgBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton sailInOutBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton tackGybeBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton upwindBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton downwindBtn;
|
||||||
|
@FXML
|
||||||
|
private JFXButton resetBtn;
|
||||||
|
@FXML
|
||||||
|
private Label upwindLabel;
|
||||||
|
@FXML
|
||||||
|
private Label downwindLabel;
|
||||||
|
@FXML
|
||||||
|
private JFXToggleButton turningToggle;
|
||||||
|
//---------FXML END---------//
|
||||||
|
|
||||||
|
private GameKeyBind gameKeyBind;
|
||||||
|
private List<JFXButton> buttons = new ArrayList<>();
|
||||||
|
private Map<Button, KeyAction> buttonActionMap;
|
||||||
|
private GameClient gameClient; // to send turning mode packet
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
gameKeyBind = GameKeyBind.getInstance();
|
||||||
|
buttons = new ArrayList<>();
|
||||||
|
Collections.addAll(buttons,
|
||||||
|
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn);
|
||||||
|
bindButtonWithAction();
|
||||||
|
loadKeyBind();
|
||||||
|
|
||||||
|
buttons.forEach(button -> {
|
||||||
|
button.setOnMouseEntered(event -> mouseEnter(button));
|
||||||
|
button.setOnMousePressed(event -> buttonPressed(button));
|
||||||
|
button.setOnMouseExited(event -> mouseExit(button));
|
||||||
|
button.setOnKeyPressed(event -> keyPressed(event, button));
|
||||||
|
});
|
||||||
|
|
||||||
|
turningToggle.setOnMouseClicked(event -> toggleTurningMode());
|
||||||
|
|
||||||
|
resetBtn.setOnMouseClicked(event -> {
|
||||||
|
gameKeyBind.setToDefault();
|
||||||
|
loadKeyBind();
|
||||||
|
});
|
||||||
|
|
||||||
|
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
|
||||||
|
|
||||||
|
keyBindingDialogHeader.setFocusTraversable(true);
|
||||||
|
keyBindingDialogHeader.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set buttons' label according to GameKeyBind settings
|
||||||
|
*/
|
||||||
|
private void loadKeyBind() {
|
||||||
|
buttons.forEach(
|
||||||
|
button -> button
|
||||||
|
.setText(gameKeyBind.getKeyCode(buttonActionMap.get(button)).getName()));
|
||||||
|
turningToggle.setSelected(gameKeyBind.isContinuouslyTurning());
|
||||||
|
if (gameKeyBind.isContinuouslyTurning()) {
|
||||||
|
upwindLabel.setText("ClOCKWISE TURNING");
|
||||||
|
downwindLabel.setText("ANTICLOCKWISE TURNING");
|
||||||
|
} else {
|
||||||
|
upwindLabel.setText("UPWIND");
|
||||||
|
downwindLabel.setText("DOWNWIND");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind buttons with specific action in a map.
|
||||||
|
*/
|
||||||
|
private void bindButtonWithAction() {
|
||||||
|
buttonActionMap = new HashMap<>();
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
buttonActionMap.put(buttons.get(i), KeyAction.getType(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt success / failure message for reassigning key action
|
||||||
|
*/
|
||||||
|
private void showSnackBar(String message, Boolean isWarning) {
|
||||||
|
ViewManager.getInstance().showSnackbar(message, isWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a mouse enters the button, the color and font size should change to highlight
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void mouseEnter(Button button) {
|
||||||
|
button.setStyle(""
|
||||||
|
+ "-fx-background-color: -fx-pp-theme-color;"
|
||||||
|
+ "-fx-text-fill: -fx-pp-front-color;"
|
||||||
|
+ "-fx-font-size: 15;");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt "press key..." to inform users assign a new key bind by pressing a key
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void buttonPressed(Button button) {
|
||||||
|
button.setText("PRESS KEY...");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When mouse leaves the button, return the button to the normal state in terms of text,
|
||||||
|
* color and font size
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void mouseExit(Button button) {
|
||||||
|
button.setText(GameKeyBind.getInstance().getKeyCode(buttonActionMap.get(button)).getName());
|
||||||
|
button.setStyle(""
|
||||||
|
+ "-fx-background-color: -fx-pp-front-color; "
|
||||||
|
+ "-fx-text-fill: -fx-pp-theme-color; "
|
||||||
|
+ "-fx-font-size: 13;");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a key is pressed, check if the new binding conflicts to any existed settings, if not
|
||||||
|
* assign the selected action with the new key binding to GameKeyBind.
|
||||||
|
* @param event
|
||||||
|
* @param button
|
||||||
|
*/
|
||||||
|
private void keyPressed(KeyEvent event, Button button) {
|
||||||
|
event.consume();
|
||||||
|
KeyAction buttonAction = buttonActionMap.get(button);
|
||||||
|
if (gameKeyBind.bindKeyToAction(event.getCode(), buttonAction)) {
|
||||||
|
showSnackBar(button.getId() + " is set to " + event.getCode().getName(), false);
|
||||||
|
button.setText(gameKeyBind.getKeyCode(buttonAction).getName());
|
||||||
|
} else {
|
||||||
|
loadKeyBind();
|
||||||
|
showSnackBar(event.getCode().getName() + " is already in use", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the turning mode is toggled, update gameKeyBind and send out packet to notify the server
|
||||||
|
*/
|
||||||
|
private void toggleTurningMode() {
|
||||||
|
gameKeyBind.toggleTurningMode();
|
||||||
|
gameClient.sendToggleTurningModePacket();
|
||||||
|
loadKeyBind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGameClient(GameClient gameClient) {
|
||||||
|
this.gameClient = gameClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -44,6 +44,11 @@
|
|||||||
-fx-border-color: -fx-decorator-color;
|
-fx-border-color: -fx-decorator-color;
|
||||||
-fx-border-width: 0 4 4 4;
|
-fx-border-width: 0 4 4 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jfx-decorator-button {
|
||||||
|
-fx-focus-traversable: false; /* so decorator button will not be focused */
|
||||||
|
}
|
||||||
|
|
||||||
/********* customised scroll bar for scroll pane ***********/
|
/********* customised scroll bar for scroll pane ***********/
|
||||||
|
|
||||||
/* The main scrollbar **track** CSS class */
|
/* The main scrollbar **track** CSS class */
|
||||||
@@ -100,3 +105,15 @@
|
|||||||
.slider .track {
|
.slider .track {
|
||||||
-fx-background-color: -fx-pp-dark-text-color;
|
-fx-background-color: -fx-pp-dark-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-content {
|
||||||
|
-fx-background-color: -fx-pp-front-color;
|
||||||
|
-fx-padding: 0 5 0 5;
|
||||||
|
-fx-spacing: 0 5 0 5;
|
||||||
|
-fx-font-size: 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-font-size: 15;
|
||||||
|
}
|
||||||
@@ -48,6 +48,7 @@ GridPane .timer * {
|
|||||||
-fx-text-fill: -fx-pp-theme-color;
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
-fx-font-size: 13px;
|
-fx-font-size: 13px;
|
||||||
-fx-pref-height: 35px;
|
-fx-pref-height: 35px;
|
||||||
|
-fx-focus-traversable: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chatSend:hover {
|
#chatSend:hover {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
-fx-font-size: 20px;
|
-fx-font-size: 20px;
|
||||||
-fx-text-fill: -fx-pp-light-text-color;
|
-fx-text-fill: -fx-pp-light-text-color;
|
||||||
-fx-background-color: -fx-pp-theme-color;
|
-fx-background-color: -fx-pp-theme-color;
|
||||||
|
-fx-focus-traversable: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-rippler {
|
.jfx-rippler {
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#keyBindingDialogHeader {
|
||||||
|
-fx-font-size: 27px;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel {
|
||||||
|
-fx-font-size: 30;
|
||||||
|
-fx-text-fill: -fx-pp-dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeLabel:hover {
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-font-size: 33;
|
||||||
|
}
|
||||||
|
|
||||||
|
JFXButton {
|
||||||
|
-fx-background-color: -fx-pp-light-text-color;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
-fx-font-size: 15px;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
-fx-effect: -fx-pp-dropshadow-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
JFXToggleButton {
|
||||||
|
-jfx-toggle-color: -fx-pp-theme-color;
|
||||||
|
-fx-text-fill: -fx-pp-theme-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn {
|
||||||
|
-fx-background-color: -fx-pp-theme-color;
|
||||||
|
-fx-text-fill: -fx-pp-front-color;
|
||||||
|
-fx-effect: -fx-pp-dropshadow-light;
|
||||||
|
-fx-font-size: 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn:hover {
|
||||||
|
-fx-font-size: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-content {
|
||||||
|
-fx-background-color: #323232;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-snackbar-action {
|
||||||
|
-fx-text-fill: #ff4081;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/* a separate file to dynamically change snackbar's color */
|
||||||
|
.jfx-snackbar-toast {
|
||||||
|
-fx-text-fill: red !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
|
<?import com.jfoenix.controls.JFXToggleButton?>
|
||||||
|
<?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 fx:id="keyBindDialog" maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
|
minHeight="-Infinity" minWidth="-Infinity" prefHeight="580.0" prefWidth="500.0"
|
||||||
|
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="seng302.visualiser.controllers.dialogs.KeyBindingDialogController">
|
||||||
|
<children>
|
||||||
|
<GridPane>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="100.0"/>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="100.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="70.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<Label fx:id="keyBindingDialogHeader" text="CUSTOM KEYBIND" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||||
|
<Label text="ZOOM IN" GridPane.halignment="CENTER" GridPane.rowIndex="1"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label text="ZOOM OUT" GridPane.halignment="CENTER" GridPane.rowIndex="2"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label text="VMG" GridPane.halignment="CENTER" GridPane.rowIndex="3"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label text="SAILS IN/OUT" GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label text="TACK/GYBE" GridPane.halignment="CENTER" GridPane.rowIndex="5"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label fx:id="upwindLabel" text="UPWIND" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="6" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<Label fx:id="downwindLabel" text="DOWNWIND" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="7" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin></Label>
|
||||||
|
<JFXButton id="ZOOM IN" fx:id="zoomInbtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0" text="Z"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1"
|
||||||
|
GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="ZOOM OUT" fx:id="zoomOutBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0" text="X"
|
||||||
|
GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2"
|
||||||
|
GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="VMG" fx:id="vmgBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
|
||||||
|
text="SPACE" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="3" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="SAILS IN/OUT" fx:id="sailInOutBtn" buttonType="RAISED"
|
||||||
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity"
|
||||||
|
prefWidth="120.0" text="SHIFT" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="4" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="TACK/GYBE" fx:id="tackGybeBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
|
||||||
|
text="ENTER" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="5" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="UPWIND" fx:id="upwindBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
|
||||||
|
text="PAGE_UP" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="6" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXButton id="DOWNWIND" fx:id="downwindBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
|
||||||
|
text="PAGE_DOWN" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="7" GridPane.valignment="CENTER"/>
|
||||||
|
<JFXToggleButton fx:id="turningToggle" minHeight="-Infinity" prefHeight="35.0"
|
||||||
|
text="OFF / ON" GridPane.columnIndex="1" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="8"/>
|
||||||
|
<Label text="CONTINUOUSLY TURNING" GridPane.halignment="CENTER" GridPane.rowIndex="8"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity"
|
||||||
|
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0"
|
||||||
|
prefWidth="150.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="CENTER"
|
||||||
|
GridPane.rowIndex="9" GridPane.valignment="CENTER"/>
|
||||||
|
<Label fx:id="closeLabel" text="✖" translateY="-5.0" GridPane.columnIndex="1"
|
||||||
|
GridPane.halignment="RIGHT" GridPane.valignment="TOP"/>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
<stylesheets>
|
||||||
|
<URL value="@../../css/dialogs/KeyBindingDialog.css" />
|
||||||
|
<URL value="@../../css/Master.css" />
|
||||||
|
</stylesheets>
|
||||||
|
</JFXDialogLayout>
|
||||||
Reference in New Issue
Block a user