Merge pull request #100 from rubenpirreram/GUI-2.0

G UI 2.0
This commit is contained in:
rubenpirreram
2026-05-15 16:57:08 +02:00
committed by GitHub
12 changed files with 662 additions and 423 deletions
@@ -29,6 +29,7 @@ public class ClientController {
public String myUsername; public String myUsername;
/** /**
* Constructs the ClientController. * Constructs the ClientController.
* Initializes all attributes. * Initializes all attributes.
@@ -37,6 +38,7 @@ public class ClientController {
public ClientController(IView view) { public ClientController(IView view) {
this.view = view; this.view = view;
this.client = null; this.client = null;
this.miniModel = new MiniModel();
} }
@@ -54,7 +56,12 @@ public class ClientController {
* @param model the model to set * @param model the model to set
*/ */
public void setModel(MiniModel model) { public void setModel(MiniModel model) {
this.miniModel = model; this.miniModel.currentState=model.currentState;
this.miniModel.availableTotems=model.availableTotems;
this.miniModel.board=model.board;
this.miniModel.orderLogicCard= model.orderLogicCard;
this.miniModel.players=model.players;
this.miniModel.slotPlayerMap=model.slotPlayerMap;
view.setModel(miniModel); view.setModel(miniModel);
} }
@@ -176,8 +176,8 @@ public class Board implements Serializable {
tribeDeck_temp.addAll(era1); tribeDeck_temp.addAll(era1);
tribeDeck_temp.addAll(era2); tribeDeck_temp.addAll(era2);
tribeDeck_temp.addAll(era3); tribeDeck_temp.addAll(era3);
tribeDeck_temp.add(new Sustenance("95",3,3)); tribeDeck_temp.add(new Sustenance("095",3,3));
tribeDeck_temp.add(new ShamanicRitual("96",3,15,7)); tribeDeck_temp.add(new ShamanicRitual("096",3,15,7));
return tribeDeck_temp; return tribeDeck_temp;
} }
@@ -6,64 +6,82 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character;
import it.polimi.ingsw.gc14.Model.GamePackage.Board; import it.polimi.ingsw.gc14.Model.GamePackage.Board;
import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState;
import java.io.Serializable; import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.*; import java.util.*;
//TODO
public class MiniModel implements Serializable { public class MiniModel implements Serializable {
public Board board; public Board board;
public Map<Slot,Player> slotPlayerMap; public Map<Slot, Player> slotPlayerMap;
public OrderLogicCard orderLogicCard; public OrderLogicCard orderLogicCard;
public CurrentState currentState; public CurrentState currentState;
public Map<String,Player> players; public Map<String, Player> players;
public List<Totems>availableTotems; public List<Totems> availableTotems;
// --- Costruttori ---
public MiniModel() {
}
public MiniModel(Board board) { public MiniModel(Board board) {
this.board = board; this.board = board;
} }
public MiniModel(Board board, Map<Slot,Player> slotPlayerMap, OrderLogicCard orderLogicCard, CurrentState currentState, List<Player> players, List<Totems>availableTotems) {
public MiniModel(Board board, Map<Slot, Player> slotPlayerMap, OrderLogicCard orderLogicCard,
CurrentState currentState, List<Player> players, List<Totems> availableTotems) {
this.board = board; this.board = board;
this.slotPlayerMap = slotPlayerMap; this.slotPlayerMap = slotPlayerMap;
this.orderLogicCard = orderLogicCard; this.orderLogicCard = orderLogicCard;
this.currentState = currentState; this.currentState = currentState;
this.players=new HashMap<>(); this.players = new HashMap<>();
this.availableTotems=availableTotems; this.availableTotems = availableTotems;
setPlayers(players); setPlayers(players);
} }
// --- Setter ---
public void setBoard(Board board) { public void setBoard(Board board) {
this.board = board; this.board = board;
} }
public void setAvailableTotems(List<Totems>availableTotems) {
public void setAvailableTotems(List<Totems> availableTotems) {
this.availableTotems = availableTotems; this.availableTotems = availableTotems;
} }
public void setSlotPlayerMap(Map<Slot,Player> slotPlayerMap) {
public void setSlotPlayerMap(Map<Slot, Player> slotPlayerMap) {
this.slotPlayerMap = slotPlayerMap; this.slotPlayerMap = slotPlayerMap;
} }
public void setOrderLogicCard(OrderLogicCard orderLogicCard) { public void setOrderLogicCard(OrderLogicCard orderLogicCard) {
this.orderLogicCard = orderLogicCard; this.orderLogicCard = orderLogicCard;
} }
public void setCurrentState(CurrentState currentState) { public void setCurrentState(CurrentState currentState) {
this.currentState = currentState; this.currentState = currentState;
} }
public void setPlayers(List<Player> players) { public void setPlayers(List<Player> players) {
for (Player player : players) { for (Player player : players) {
this.players.put(player.getUserName(),player); this.players.put(player.getUserName(), player);
} }
} }
public void setPlayer(Player player)
{ public void setPlayer(Player player) {
players.put(player.getUserName(),player); players.put(player.getUserName(), player);
} }
public int getPositionByUsername(String username)
{
int i=0; public int getPositionByUsername(String username) {
for (Player player : players.values()) int i = 0;
{ for (Player player : players.values()) {
if(player.getUserName().equals(username)) if (player.getUserName().equals(username)) {
{
return i; return i;
} }
i++; i++;
} }
return -1; return -1;
} }
} }
@@ -20,12 +20,12 @@ public abstract class OrderLogicCard implements Serializable {
/** /**
* The queue of {@link Player Players} associated with this order logic card. * The queue of {@link Player Players} associated with this order logic card.
*/ */
protected Queue<Player> players; public Queue<Player> players;
/** /**
* The list of {@link Player Players} associated with this order logic card. * The list of {@link Player Players} associated with this order logic card.
*/ */
protected List<OrderPlayer> playerList; public List<OrderPlayer> playerList;
/** /**
@@ -256,7 +256,10 @@ public class ServerLauncher {
while (true) { while (true) {
try{ try{
this.doFirstEvent(); this.doFirstEvent();
this.view.fullRender(); if(view!=null)
{
view.fullRender();
}
} }
catch(InterruptedException e){ catch(InterruptedException e){
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@@ -45,7 +45,6 @@ public class GUI extends Application implements IView {
controllerLogin.setController(controller); controllerLogin.setController(controller);
loaderTotem = new FXMLLoader(getClass().getResource("/GUIScene/totem.fxml")); loaderTotem = new FXMLLoader(getClass().getResource("/GUIScene/totem.fxml"));
totemScene = new Scene(loaderTotem.load()); totemScene = new Scene(loaderTotem.load());
controllerTotem = loaderTotem.getController(); controllerTotem = loaderTotem.getController();
@@ -53,9 +52,13 @@ public class GUI extends Application implements IView {
loaderMain = new FXMLLoader(getClass().getResource("/GUIScene/main.fxml")); loaderMain = new FXMLLoader(getClass().getResource("/GUIScene/main.fxml"));
loaderMain.setControllerFactory(clazz -> {
MainFXMLController controllerMain = new MainFXMLController();
controllerMain.setController(controller);
return controllerMain;
});
mainScene = new Scene(loaderMain.load()); mainScene = new Scene(loaderMain.load());
controllerMain = loaderMain.getController(); controllerMain = loaderMain.getController();
controllerMain.setController(controller);
showLogin(); showLogin();
stage.setTitle("Mesos"); stage.setTitle("Mesos");
@@ -81,10 +84,13 @@ public class GUI extends Application implements IView {
Platform.runLater(() -> { Platform.runLater(() -> {
controllerTotem.render(); controllerTotem.render();
primaryStage.setScene(totemScene); primaryStage.setScene(totemScene);
primaryStage.setFullScreen(true);
}); });
} else { } else {
Platform.runLater(() -> { Platform.runLater(() -> {
controllerMain.render();
primaryStage.setScene(mainScene); primaryStage.setScene(mainScene);
primaryStage.setFullScreen(true);
}); });
} }
} }
@@ -4,7 +4,12 @@ import it.polimi.ingsw.gc14.Controller.ClientController;
import it.polimi.ingsw.gc14.Model.*; import it.polimi.ingsw.gc14.Model.*;
import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;
import it.polimi.ingsw.gc14.Model.Cards.TribeCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCard;
import it.polimi.ingsw.gc14.Model.GamePackage.Board;
import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState;
import it.polimi.ingsw.gc14.Model.GamePackage.GameStages;
import it.polimi.ingsw.gc14.Model.Orders.OrderPlayer;
import javafx.animation.ScaleTransition; import javafx.animation.ScaleTransition;
import javafx.application.Platform;
import javafx.event.Event; import javafx.event.Event;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets; import javafx.geometry.Insets;
@@ -24,9 +29,11 @@ import javafx.stage.Popup;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.util.Duration; import javafx.util.Duration;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap; import java.util.stream.Collectors;
import java.util.Map;
import static it.polimi.ingsw.gc14.Model.GamePackage.GameStages.RES_ACTIONS;
import static it.polimi.ingsw.gc14.Model.GamePackage.GameStages.SLOT_CHOICE;
public class MainFXMLController { public class MainFXMLController {
@@ -47,20 +54,24 @@ public class MainFXMLController {
private Popup popup; private Popup popup;
private HBox popupCards; private HBox popupCards;
private MiniModel model;
private ClientController controller; private ClientController controller;
private String username; private GameStages old_state_stage;
private final Map<String, ImageView> cardCache = new HashMap<>(); private String old_state_username;
public void setModel(MiniModel model) {this.model = model;}
public void setController(ClientController controller) {this.controller = controller;} public void setController(ClientController controller) {
public void setUsername(String username) {this.username = username;} this.controller = controller;
}
@FXML @FXML
public void initialize() { public void initialize() {
old_state_stage=null;
old_state_username="";
// Import font and apply CSS // Import font and apply CSS
Font.loadFont(getClass().getResourceAsStream("/Fonts/InknutAntiqua-Regular.ttf"), 14); Font.loadFont(getClass().getResourceAsStream("/Fonts/InknutAntiqua-Regular.ttf"), 14);
mainHBox.sceneProperty().addListener((obs, oldScene, newScene) -> { mainHBox.sceneProperty().addListener((obs, oldScene, newScene) -> {
@@ -74,95 +85,51 @@ public class MainFXMLController {
} }
public void render() { public void render() {
renderBackground();
renderUpper();
renderBoard();
renderLower();
renderMyHand();
renderSidePanel();
}
// ==== HELPER ==== if (old_state_stage==null) {
private StackPane createOrder(String num, boolean withZoom, boolean withShadow) { renderBackground();
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Orders/order-" + num + ".png"))); renderUpper();
img.setFitHeight(240); renderBoard();
img.setPreserveRatio(true); renderLower();
Rectangle clip = new Rectangle(); renderMyHand();
clip.setWidth(img.getBoundsInLocal().getWidth()); renderSidePanel();
clip.setHeight(240); } else if (old_state_stage==SLOT_CHOICE ) {
clip.setArcWidth(20); System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage());
clip.setArcHeight(20); System.out.println("RIDISEGNO BOARD\n");
img.setClip(clip); renderBoard();
StackPane wrapper = new StackPane(img); } else if (old_state_stage==RES_ACTIONS) {
if (withShadow) { System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage());
addShadow(wrapper); System.out.println("RIDISEGNO TUTTO. USERNAME: "+old_state_username);
} renderUpper();
if (withZoom) { renderBoard();
addHoverZoom(wrapper); renderLower();
} renderSidePanel();
return wrapper; if (Objects.equals(old_state_username, controller.myUsername)) {
} renderMyHand();
}
private StackPane createSlot(Slot slot, boolean withZoom, boolean withShadow) { // TODO: se sono io a pescare renderizzo myHand, altrimenti no (non è scontato)
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + slot.getSlotId() + ".png")));
img.setFitHeight(240);
img.setPreserveRatio(true);
Rectangle clip = new Rectangle();
clip.setWidth(img.getBoundsInLocal().getWidth());
clip.setHeight(240);
clip.setArcWidth(20);
clip.setArcHeight(20);
img.setClip(clip);
StackPane wrapper = new StackPane(img);
Player player = model.slotPlayerMap.get(slot);
if (player != null && model.getPositionByUsername(player.getUserName())!=-1) {
int index = model.getPositionByUsername(player.getUserName());
ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png")));
totem.setFitHeight(70);
totem.setPreserveRatio(true);
StackPane.setAlignment(totem, Pos.TOP_LEFT);
StackPane.setMargin(totem, new Insets(8, 0, 0, 57));
wrapper.getChildren().add(totem);
}
if (withShadow) {
addShadow(wrapper);
}
if (withZoom) {
addHoverZoom(wrapper);
}
return wrapper;
}
private StackPane createCard(PlayableCard card, boolean withZoom, boolean withShadow) {
String id = card.getIdIMG();
ImageView img;
if (cardCache.containsKey(id)) {
img = new ImageView(cardCache.get(id).getImage());
} else { } else {
img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + id + ".png"))); System.out.println("NON GESTITO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
cardCache.put(id, img);
} }
img.setFitHeight(200);
img.setPreserveRatio(true);
old_state_stage=controller.miniModel.currentState.getGameStage();
old_state_username=controller.miniModel.currentState.getCurrentPlayer().getUserName();
// TODO: le info in sidepanel non vengono aggiornate sempre aggiornate, bisogna prima capire dove metterle
}
// ==== EFFECTS ====
private void addClip(Node node) {
Rectangle clip = new Rectangle(); Rectangle clip = new Rectangle();
clip.setWidth(img.getBoundsInLocal().getWidth()); clip.setWidth(node.getBoundsInLocal().getWidth());
clip.setHeight(200); clip.setHeight(node.getBoundsInLocal().getHeight());
clip.setArcWidth(20); clip.setArcWidth(20);
clip.setArcHeight(20); clip.setArcHeight(20);
img.setClip(clip); node.setClip(clip);
StackPane wrapper = new StackPane(img);
if (withShadow) {
addShadow(wrapper);
}
if (withZoom) {
addHoverZoom(wrapper);
}
return wrapper;
} }
private void addHoverZoom(Node node) { private void addHoverZoom(Node node) {
ScaleTransition scaleUp = new ScaleTransition(Duration.millis(150), node); ScaleTransition scaleUp = new ScaleTransition(Duration.millis(150), node);
@@ -174,7 +141,6 @@ public class MainFXMLController {
node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> { scaleUp.play(); node.setCursor(Cursor.HAND); }); node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> { scaleUp.play(); node.setCursor(Cursor.HAND); });
node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { scaleDown.play(); node.setCursor(Cursor.DEFAULT); }); node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { scaleDown.play(); node.setCursor(Cursor.DEFAULT); });
} }
private void addShadow(Node node) { private void addShadow(Node node) {
DropShadow shadow = new DropShadow(); DropShadow shadow = new DropShadow();
shadow.setColor(Color.rgb(0, 0, 0, 0.3)); shadow.setColor(Color.rgb(0, 0, 0, 0.3));
@@ -197,237 +163,57 @@ public class MainFXMLController {
} }
// ==== ELEMENTS ====
// ==== RENDER METHODS ==== private StackPane createOrder(String num) {
// BACKGROUND ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Orders/order-" + num + ".png")));
private void renderBackground() { img.setFitHeight(240);
BackgroundSize size = new BackgroundSize( img.setPreserveRatio(true);
BackgroundSize.AUTO, BackgroundSize.AUTO, addClip(img);
false, false, true, true StackPane wrapper = new StackPane(img);
); return wrapper;
mainHBox.setBackground(new Background(new BackgroundImage(
new Image(getClass().getResourceAsStream("/GUIImages/Background.png")),
BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT,
BackgroundPosition.CENTER,
size
)));
} }
private StackPane createSlot(Slot slot, boolean withZoom, boolean withShadow) {
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + slot.getSlotId() + ".png")));
img.setFitHeight(240);
img.setPreserveRatio(true);
addClip(img);
StackPane wrapper = new StackPane(img);
// UPPER, LOWER AND BOARD Player player = controller.miniModel.slotPlayerMap.get(slot);
private void renderUpper() { if (player != null && controller.miniModel.getPositionByUsername(player.getUserName())!=-1) {
upperList.setSpacing(14); ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + player.totem.toString().toLowerCase(Locale.ROOT) + ".png")));
upperList.setAlignment(Pos.CENTER);
upperList.getChildren().clear();
int i = 0;
for (TribeCard card : model.board.upperListTribe) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperTribeCard(username, index));
upperList.getChildren().add(img);
i++;
}
i = 0;
for (BuildingCard card : model.board.upperListBuilding) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(username, index));
upperList.getChildren().add(img);
i++;
}
}
private void renderOrder() {
StackPane card = createOrder(Integer.toString(model.players.size()), false, false);
VBox overlay = new VBox(-20);
overlay.setPickOnBounds(false);
StackPane.setAlignment(overlay, Pos.TOP_LEFT);
StackPane.setMargin(overlay, new Insets(9, 0, 0, 57));
int i = 0;
for (Player player : model.players.values()) {
final int index = i;
ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png")));
totem.setFitHeight(70); totem.setFitHeight(70);
totem.setPreserveRatio(true); totem.setPreserveRatio(true);
if (!(model.orderLogicCard.getPosition(player.getUserName()) != -1 && !model.slotPlayerMap.containsValue(player))) { StackPane.setAlignment(totem, Pos.TOP_LEFT);
totem.setOpacity(0.0); StackPane.setMargin(totem, new Insets(8, 0, 0, 57));
} wrapper.getChildren().add(totem);
overlay.getChildren().add(totem);
i++;
} }
card.getChildren().add(overlay);
board.getChildren().add(card); if (withShadow) {
addShadow(wrapper);
}
if (withZoom) {
addHoverZoom(wrapper);
}
return wrapper;
} }
private void renderBoard() { private StackPane createCard(PlayableCard card, boolean withZoom, boolean withShadow) {
board.setSpacing(14); String id = card.getIdIMG();
board.setAlignment(Pos.CENTER); ImageView img;
board.getChildren().clear(); img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + id + ".png")));
img.setFitHeight(200);
img.setPreserveRatio(true);
addClip(img);
String path = ""; StackPane wrapper = new StackPane(img);
switch (model.currentState.getEra()) {
case 1 -> path = "/GUIImages/Backs/back-001.png"; if (withShadow) {
case 2 -> path = "/GUIImages/Backs/back-030.png"; addShadow(wrapper);
case 3 -> path = "/GUIImages/Backs/back-058.png";
} }
ImageView back = new ImageView(new Image(getClass().getResourceAsStream(path))); if (withZoom) {
back.setFitHeight(240); addHoverZoom(wrapper);
back.setPreserveRatio(true);
Rectangle clip = new Rectangle();
clip.setWidth(back.getBoundsInLocal().getWidth());
clip.setHeight(240);
clip.setArcWidth(20);
clip.setArcHeight(20);
back.setClip(clip);
addShadow(back);
addHoverZoom(back);
board.getChildren().add(back);
renderOrder();
int i = 0;
for (Map.Entry<Slot, Player> entry : model.slotPlayerMap.entrySet()) {
Slot slot = entry.getKey();
final int index = i;
StackPane img = createSlot(slot, true, true);
img.setOnMouseClicked(e -> controller.slotChoice(username, index));
board.getChildren().add(img);
i++;
} }
} return wrapper;
private void renderLower() {
lowerList.setSpacing(14);
lowerList.setAlignment(Pos.CENTER);
lowerList.getChildren().clear();
int i = 0;
for (TribeCard card : model.board.lowerListTribe) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerTribeCard(username, index));
lowerList.getChildren().add(img);
i++;
}
i = 0;
for (BuildingCard card : model.board.lowerListBuilding) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(username, index));
lowerList.getChildren().add(img);
i++;
}
}
// MY HAND
private void renderMyHand() {
myHand.getChildren().clear();
myHand.setSpacing(14);
myHand.setAlignment(Pos.CENTER);
drawMyHandList(myHand, model.players.get(username).artists);
drawMyHandList(myHand, model.players.get(username).gatherers);
drawMyHandList(myHand, model.players.get(username).inventors);
drawMyHandList(myHand, model.players.get(username).builders);
drawMyHandList(myHand, model.players.get(username).shamans);
drawMyHandList(myHand, model.players.get(username).hunters);
drawMyHandList(myHand, model.players.get(username).buildingCards);
}
private void drawMyHandList(HBox myHand, ArrayList<? extends PlayableCard> cardList) {
if (!cardList.isEmpty()) {
StackPane img = createCard(cardList.getLast(), true, true);
Label label = new Label(String.valueOf(cardList.size()));
label.setTranslateY(-55);
label.setTranslateX(10);
label.getStyleClass().add("label-large");
StackPane.setAlignment(label, Pos.TOP_RIGHT);
img.getChildren().add(label); // aggiungi il label dentro lo StackPane di createCard
img.setOnMouseClicked(e -> openPopup(cardList));
myHand.getChildren().add(img);
} else {
Region placeholder = new Region();
placeholder.setPrefHeight(200);
placeholder.setPrefWidth(200 * 0.675);
placeholder.setStyle("-fx-background-color: transparent;");
myHand.getChildren().add(placeholder);
}
}
// SIDE PANEL
private void renderSidePanel() {
sidePanel.getChildren().clear();
sidePanel.setSpacing(6);
era.setText(Integer.toString(model.currentState.getEra()));
round.setText(Integer.toString(model.currentState.getRound()));
player.setText(model.currentState.getCurrentPlayer().getUserName());
VBox.setMargin(info, new Insets(5, 5, 5, 5));
sidePanel.getChildren().add(info);
renderPlayers(sidePanel);
}
private void renderPlayers(VBox playersHand) {
for (Player player : model.players.values()) {
// Card container
VBox card = new VBox(3);
VBox.setMargin(card, new Insets(5));
card.getStyleClass().add("player-card");
card.setPadding(new Insets(8));
addHoverZoom(card);
addShadow(card);
// Riga 1: icona totem + nome
HBox headerRow = new HBox(8);
headerRow.setAlignment(Pos.CENTER);
int index = new ArrayList<>(model.players.values()).indexOf(player);
ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png")));
totem.setFitHeight(20);
totem.setPreserveRatio(true);
Label usernameLabel = new Label(player.getUserName());
usernameLabel.getStyleClass().add("label-medium");
if (player.getUserName().equals(username)) {
usernameLabel.setStyle("-fx-text-fill: #9d0208");
}
headerRow.getChildren().addAll(totem, usernameLabel);
// Riga 2: cibo + prestigio
HBox statsRow = new HBox(10);
statsRow.setAlignment(Pos.CENTER);
HBox foodBox = new HBox(4);
foodBox.setAlignment(Pos.CENTER);
ImageView foodIcon = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Icons/Food.png")));
foodIcon.setFitHeight(20);
foodIcon.setPreserveRatio(true);
Label foodLabel = new Label(String.valueOf(player.getFoodValue()));
foodLabel.getStyleClass().add("label-small");
foodBox.getChildren().addAll(foodIcon, foodLabel);
HBox prestigeBox = new HBox(1);
prestigeBox.setAlignment(Pos.CENTER);
ImageView PPIcon = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Icons/PrestigePoint.png")));
PPIcon.setFitHeight(35);
PPIcon.setPreserveRatio(true);
Label prestigeLabel = new Label(String.valueOf(player.getPrestigeValue()));
prestigeLabel.getStyleClass().add("label-small");
prestigeBox.getChildren().addAll(PPIcon, prestigeLabel);
statsRow.getChildren().addAll(foodBox, prestigeBox);
// Righe 3-4: icone carte (3 per riga)
HBox iconsRow1 = new HBox(6);
iconsRow1.setAlignment(Pos.CENTER);
HBox iconsRow2 = new HBox(6);
iconsRow2.setAlignment(Pos.CENTER);
renderIcons(iconsRow1, iconsRow2, player); // vedi sotto
card.getChildren().addAll(headerRow, statsRow, iconsRow1, iconsRow2);
playersHand.getChildren().add(card);
}
} }
private void renderIcons(HBox iconsRow1, HBox iconsRow2, Player player) { private void renderIcons(HBox iconsRow1, HBox iconsRow2, Player player) {
String[][] iconTypes = { String[][] iconTypes = {
@@ -452,7 +238,6 @@ public class MainFXMLController {
ArrayList<PlayableCard> cards = getPlayerCards(player.getUserName(), fieldName); ArrayList<PlayableCard> cards = getPlayerCards(player.getUserName(), fieldName);
if (cards.isEmpty()) { if (cards.isEmpty()) {
ColorAdjust grayscale = new ColorAdjust(); ColorAdjust grayscale = new ColorAdjust();
//grayscale.setSaturation(-1.0);
icon.setEffect(grayscale); icon.setEffect(grayscale);
icon.setOpacity(0.3); icon.setOpacity(0.3);
} else { } else {
@@ -465,7 +250,7 @@ public class MainFXMLController {
} }
} }
private ArrayList<PlayableCard> getPlayerCards(String username, String type) { private ArrayList<PlayableCard> getPlayerCards(String username, String type) {
Player p = model.players.get(username); Player p = controller.miniModel.players.get(username);
return switch (type) { return switch (type) {
case "artists" -> new ArrayList<>(p.artists); case "artists" -> new ArrayList<>(p.artists);
case "gatherers" -> new ArrayList<>(p.gatherers); case "gatherers" -> new ArrayList<>(p.gatherers);
@@ -478,6 +263,232 @@ public class MainFXMLController {
} }
// ==== GROUPS ====
private void renderUpper() {
upperList.setSpacing(14);
upperList.setAlignment(Pos.CENTER);
upperList.getChildren().clear();
int i = 0;
for (TribeCard card : controller.miniModel.board.upperListTribe) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperTribeCard(controller.myUsername, index));
upperList.getChildren().add(img);
i++;
}
i = 0;
for (BuildingCard card : controller.miniModel.board.upperListBuilding) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(controller.myUsername, index));
upperList.getChildren().add(img);
i++;
}
}
private void renderLower() {
lowerList.setSpacing(14);
lowerList.setAlignment(Pos.CENTER);
lowerList.getChildren().clear();
int i = 0;
for (TribeCard card : controller.miniModel.board.lowerListTribe) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerTribeCard(controller.myUsername, index));
lowerList.getChildren().add(img);
i++;
}
i = 0;
for (BuildingCard card : controller.miniModel.board.lowerListBuilding) {
final int index = i;
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(controller.myUsername, index));
lowerList.getChildren().add(img);
i++;
}
}
private void renderDeck() {
String path = "";
switch (controller.miniModel.currentState.getEra()) {
case 1 -> path = "/GUIImages/Backs/back-001.png";
case 2 -> path = "/GUIImages/Backs/back-030.png";
case 3 -> path = "/GUIImages/Backs/back-058.png";
}
ImageView back = new ImageView(new Image(getClass().getResourceAsStream(path)));
back.setFitHeight(240);
back.setPreserveRatio(true);
addClip(back);
addShadow(back);
addHoverZoom(back);
board.getChildren().add(back);
}
private void renderOrder() {
StackPane card = createOrder(Integer.toString(controller.miniModel.players.size()));
VBox overlay = new VBox(-20);
overlay.setPickOnBounds(false);
StackPane.setAlignment(overlay, Pos.TOP_LEFT);
StackPane.setMargin(overlay, new Insets(9, 0, 0, 57));
for (OrderPlayer player : controller.miniModel.orderLogicCard.playerList) {
ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + player.player.totem.toString().toLowerCase(Locale.ROOT) + ".png")));
totem.setFitHeight(70);
totem.setPreserveRatio(true);
if(controller.miniModel.slotPlayerMap.containsValue(player.player)) {
totem.setOpacity(0.5);
}
overlay.getChildren().add(totem);
}
card.getChildren().add(overlay);
board.getChildren().add(card);
}
private void renderSlotMap() {
int i = 0;
for (Map.Entry<Slot, Player> entry : controller.miniModel.slotPlayerMap.entrySet()) {
Slot slot = entry.getKey();
final int index = i;
StackPane img = createSlot(slot, true, true);
img.setOnMouseClicked(e -> controller.slotChoice(controller.myUsername, index));
board.getChildren().add(img);
i++;
}
}
private void drawMyHandList(ArrayList<? extends PlayableCard> cardList) {
if (!cardList.isEmpty()) {
StackPane img = createCard(cardList.getLast(), true, true);
Label label = new Label(String.valueOf(cardList.size()));
label.setTranslateY(-55);
label.setTranslateX(10);
label.getStyleClass().add("label-large");
StackPane.setAlignment(label, Pos.TOP_RIGHT);
img.getChildren().add(label);
img.setOnMouseClicked(e -> openPopup(cardList));
myHand.getChildren().add(img);
} else {
Region placeholder = new Region();
placeholder.setPrefHeight(200);
placeholder.setPrefWidth(200 * 0.675);
placeholder.setStyle("-fx-background-color: transparent;");
myHand.getChildren().add(placeholder);
}
}
private void renderPlayer(Player player) {
VBox card = new VBox(3);
VBox.setMargin(card, new Insets(5));
card.getStyleClass().add("player-card");
card.setPadding(new Insets(8));
addHoverZoom(card);
addShadow(card);
// Riga 1: icona totem + nome
HBox headerRow = new HBox(8);
headerRow.setAlignment(Pos.CENTER);
ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + player.totem.toString().toLowerCase(Locale.ROOT) + ".png")));
totem.setFitHeight(20);
totem.setPreserveRatio(true);
Label usernameLabel = new Label(player.getUserName());
usernameLabel.getStyleClass().add("label-medium");
if (player.getUserName().equals(controller.myUsername)) {
usernameLabel.setStyle("-fx-text-fill: #9d0208");
}
headerRow.getChildren().addAll(totem, usernameLabel);
// Riga 2: cibo + prestigio
HBox statsRow = new HBox(10);
statsRow.setAlignment(Pos.CENTER);
HBox foodBox = new HBox(4);
foodBox.setAlignment(Pos.CENTER);
ImageView foodIcon = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Icons/Food.png")));
foodIcon.setFitHeight(20);
foodIcon.setPreserveRatio(true);
Label foodLabel = new Label(String.valueOf(player.getFoodValue()));
foodLabel.getStyleClass().add("label-small");
foodBox.getChildren().addAll(foodIcon, foodLabel);
HBox prestigeBox = new HBox(1);
prestigeBox.setAlignment(Pos.CENTER);
ImageView PPIcon = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Icons/PrestigePoint.png")));
PPIcon.setFitHeight(35);
PPIcon.setPreserveRatio(true);
Label prestigeLabel = new Label(String.valueOf(player.getPrestigeValue()));
prestigeLabel.getStyleClass().add("label-small");
prestigeBox.getChildren().addAll(PPIcon, prestigeLabel);
statsRow.getChildren().addAll(foodBox, prestigeBox);
// Righe 3-4: icone carte (3 per riga)
HBox iconsRow1 = new HBox(6);
iconsRow1.setAlignment(Pos.CENTER);
HBox iconsRow2 = new HBox(6);
iconsRow2.setAlignment(Pos.CENTER);
renderIcons(iconsRow1, iconsRow2, player); // vedi sotto
card.getChildren().addAll(headerRow, statsRow, iconsRow1, iconsRow2);
sidePanel.getChildren().add(card);
}
// ==== ABSOLUTES ====
private void renderBackground() {
BackgroundSize size = new BackgroundSize(
BackgroundSize.AUTO, BackgroundSize.AUTO,
false, false, true, true
);
mainHBox.setBackground(new Background(new BackgroundImage(
new Image(getClass().getResourceAsStream("/GUIImages/Background.png")),
BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT,
BackgroundPosition.CENTER,
size
)));
}
private void renderBoard() {
board.setSpacing(14);
board.setAlignment(Pos.CENTER);
board.getChildren().clear();
renderDeck();
renderOrder();
renderSlotMap();
}
private void renderMyHand() {
myHand.getChildren().clear();
myHand.setSpacing(14);
myHand.setAlignment(Pos.CENTER);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).artists);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).gatherers);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).inventors);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).builders);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).shamans);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).hunters);
drawMyHandList(controller.miniModel.players.get(controller.myUsername).buildingCards);
}
private void renderSidePanel() {
sidePanel.getChildren().clear();
sidePanel.setSpacing(6);
era.setText(Integer.toString(controller.miniModel.currentState.getEra()));
round.setText(Integer.toString(controller.miniModel.currentState.getRound()));
player.setText(controller.miniModel.currentState.getCurrentPlayer().getUserName());
VBox.setMargin(info, new Insets(5, 5, 5, 5));
sidePanel.getChildren().add(info);
for (Player player : controller.miniModel.players.values()) {
renderPlayer(player);
}
}
// POPUP // POPUP
private void initPopup() { private void initPopup() {
popupCards = new HBox(10); popupCards = new HBox(10);
@@ -491,12 +502,7 @@ public class MainFXMLController {
"-fx-background-radius: 10;" "-fx-background-radius: 10;"
); );
Rectangle clip = new Rectangle(); addClip(popupCards);
clip.setArcWidth(20);
clip.setArcHeight(20);
clip.widthProperty().bind(popupCards.widthProperty());
clip.heightProperty().bind(popupCards.heightProperty());
popupCards.setClip(clip);
popup = new Popup(); popup = new Popup();
popup.getContent().add(popupCards); popup.getContent().add(popupCards);
@@ -1,49 +0,0 @@
package it.polimi.ingsw.gc14.View.GUI;
import it.polimi.ingsw.gc14.Controller.ClientController;
import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Model.MiniModel;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import java.io.IOException;
public class MainView {
private final Scene scene;
private final MainFXMLController fxmlController;
private MiniModel model;
private ClientController controller;
private String username;
public MainView() {
try {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/GUIScene/main.fxml")
);
scene = new Scene(loader.load(), 1920, 1080);
fxmlController = loader.getController();
} catch (IOException e) {
throw new RuntimeException("Impossibile caricare login.fxml", e);
}
}
public Scene getScene() { return scene; }
public void setModel(MiniModel model, ClientController controller, String username) {
this.model = model;
fxmlController.setModel(model);
this.controller = controller;
fxmlController.setController(controller);
this.username = username;
fxmlController.setUsername(username);
}
public void render() {
fxmlController.render();
}
}
@@ -1,39 +1,204 @@
package it.polimi.ingsw.gc14.View.GUI; package it.polimi.ingsw.gc14.View.GUI;
import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Controller.ClientController;
import it.polimi.ingsw.gc14.Controller.GameController;
import it.polimi.ingsw.gc14.Model.Totems; import it.polimi.ingsw.gc14.Model.Totems;
import javafx.animation.*;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.control.Button;
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.HBox; import javafx.scene.layout.*;
import javafx.stage.Screen;
import javafx.util.Duration;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
public class TotemFXMLController { public class TotemFXMLController {
public ImageView backgroundImage;
@FXML private HBox mainHBox; @FXML private HBox mainHBox;
@FXML private Label turnBanner;
@FXML private Button confirmButton;
private ClientController controller; private ClientController controller;
private int selectedIndex = -1;
private StackPane selectedFrame = null;
public void setController(ClientController controller) { public void setController(ClientController controller) {
this.controller=controller; this.controller = controller;
} }
@FXML @FXML
public void initialize() { public void initialize() {
Image img = new Image(getClass().getResourceAsStream("/GUIImages/Background.png"));
backgroundImage.setImage(img);
Rectangle2D screenBounds = Screen.getPrimary().getBounds();
backgroundImage.setFitWidth(screenBounds.getWidth());
backgroundImage.setFitHeight(screenBounds.getHeight());
} }
public void render() { public void render() {
for (Totems totem : controller.miniModel.availableTotems) { mainHBox.getChildren().clear();
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_"+ String.valueOf(totem).toLowerCase(Locale.ROOT) +".png"))); selectedIndex = -1;
img.setFitHeight(240); selectedFrame = null;
img.setPreserveRatio(true);
//img.setOnMouseClicked(e -> controller.totemChoice(controller.myUsername)); String chooser = controller.miniModel.currentState.getCurrentPlayer().getUserName(); // adatta al tuo campo
mainHBox.getChildren().add(img); boolean myTurn = chooser.equals(controller.myUsername);
updateBanner(chooser, myTurn);
updateConfirmButton(false);
for (int i = 0; i < controller.miniModel.availableTotems.size(); i++) {
Totems totem = controller.miniModel.availableTotems.get(i);
VBox card = buildCard(totem, i, myTurn);
mainHBox.getChildren().add(card);
card.setOpacity(0);
card.setTranslateY(14);
PauseTransition delay = new PauseTransition(Duration.millis(80 + i * 65));
delay.setOnFinished(e -> {
FadeTransition ft = new FadeTransition(Duration.millis(320), card);
ft.setToValue(1);
TranslateTransition tt = new TranslateTransition(Duration.millis(320), card);
tt.setToY(0);
new ParallelTransition(ft, tt).play();
});
delay.play();
} }
} }
private void updateBanner(String chooser, boolean myTurn) {
if (myTurn) {
turnBanner.setText("✦ It's your turn to choose ✦");
turnBanner.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 13; -fx-letter-spacing: 3;" +
"-fx-text-fill: #000000;" +
"-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);" +
"-fx-border-color: #000000; -fx-border-width: 1;" +
"-fx-border-radius: 3; -fx-background-radius: 3;" +
"-fx-padding: 10 28 10 28;" +
"-fx-effect: dropshadow(gaussian, rgba(244,192,90,0.3), 18, 0, 0, 0);"
);
} else {
turnBanner.setText("Waiting for" + chooser + " to choose his totem…");
turnBanner.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 11; -fx-letter-spacing: 2;" +
"-fx-text-fill: #000000;" +
"-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);" +
"-fx-border-color: #000000; -fx-border-width: 1;" +
"-fx-border-radius: 3; -fx-background-radius: 3;" +
"-fx-padding: 10 28 10 28;"
);
}
}
private VBox buildCard(Totems totem, int idx, boolean interactive) {
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + String.valueOf(totem).toLowerCase(Locale.ROOT) + ".png")));
img.setFitHeight(150);
img.setPreserveRatio(true);
StackPane frame = new StackPane(img);
frame.setPrefSize(100, 145);
frame.setBackground(Background.EMPTY);
img.setStyle(frameStyle(false));
Region base = new Region();
base.setPrefSize(100, 10);
Label name = new Label(capitalize(totem));
name.setStyle(nameStyle(false));
VBox card = new VBox(4, frame, base, name);
card.setAlignment(Pos.CENTER);
if (!interactive) {
card.setOpacity(0.35);
card.setCursor(Cursor.DEFAULT);
return card;
}
card.setCursor(Cursor.HAND);
card.setOnMouseEntered(e -> {
if (frame != selectedFrame) {
ScaleTransition st = new ScaleTransition(Duration.millis(140), card);
st.setToX(1.06); st.setToY(1.06); st.play();
}
});
card.setOnMouseExited(e -> {
if (frame != selectedFrame) {
ScaleTransition st = new ScaleTransition(Duration.millis(140), card);
st.setToX(1.0); st.setToY(1.0); st.play();
}
});
card.setOnMouseClicked(e -> {
// reset tutti
mainHBox.getChildren().forEach(n -> {
if (n instanceof VBox v) {
StackPane f = (StackPane) v.getChildren().get(0);
Label l = (Label) v.getChildren().get(2);
f.setStyle(frameStyle(false));
l.setStyle(nameStyle(false));
ScaleTransition st = new ScaleTransition(Duration.millis(130), v);
st.setToX(1.0); st.setToY(1.0); st.play();
}
});
frame.setStyle(frameStyle(true));
name.setStyle(nameStyle(true));
selectedFrame = frame;
selectedIndex = idx;
ScaleTransition pop = new ScaleTransition(Duration.millis(160), card);
pop.setToX(1.08); pop.setToY(1.08);
pop.setAutoReverse(true); pop.setCycleCount(2); pop.play();
updateConfirmButton(true);
});
return card;
}
private void updateConfirmButton(boolean enabled) {
confirmButton.setDisable(!enabled);
confirmButton.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 12; -fx-font-weight: bold;" +
"-fx-letter-spacing: 4; -fx-text-fill: #0c0601;" +
"-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);" +
"-fx-padding: 12 48 12 48; -fx-background-radius: 2;" +
"-fx-opacity: " + (enabled ? "1.0" : "0.3") + ";" +
"-fx-cursor: " + (enabled ? "hand" : "default") + ";"
);
}
private String frameStyle(boolean selected) {
return "-fx-border-color: " + (selected ? "#75FF79" : "rgba(200,120,20,0.28)") + ";" +
"-fx-border-width: " + (selected ? "0" : "0") + ";" +
"-fx-border-radius: 4 4 0 0; -fx-background-radius: 4 4 0 0;" +
(selected ? "-fx-effect: dropshadow(gaussian, #ffffff, 20, 0.33, 0, 0);" : "");
}
private String nameStyle(boolean selected) {
return "-fx-font-family: 'Cinzel'; -fx-font-size: 10; -fx-letter-spacing: 2;" +
"-fx-text-fill: " + (selected ? "#ffffff" : "ffffff") + ";";
}
private String capitalize(Totems t) {
String s = t.name().toLowerCase(Locale.ROOT);
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
} @FXML
private void onConfirm() {
if (selectedIndex >= 0) {
controller.totemChoice(controller.myUsername, selectedIndex);
}
}
}
+1
View File
@@ -5,6 +5,7 @@ module it.polimi.ingsw.gc14 {
requires java.rmi; requires java.rmi;
requires java.smartcardio; requires java.smartcardio;
requires com.google.gson; requires com.google.gson;
requires java.desktop;
opens it.polimi.ingsw.gc14 to javafx.fxml, com.google.gson; opens it.polimi.ingsw.gc14 to javafx.fxml, com.google.gson;
opens it.polimi.ingsw.gc14.Model to com.google.gson; opens it.polimi.ingsw.gc14.Model to com.google.gson;
+22 -8
View File
@@ -1,15 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<HBox fx:id="mainHBox"
<HBox fx:id="mainHBox" maxHeight="1080.0" maxWidth="1920.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/26" xmlns:fx="http://javafx.com/fxml/1" fx:controller="it.polimi.ingsw.gc14.View.GUI.MainFXMLController" stylesheets="@styles.css"> maxHeight="Infinity" maxWidth="Infinity"
prefHeight="1080.0" prefWidth="1920.0"
xmlns="http://javafx.com/javafx/26"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="it.polimi.ingsw.gc14.View.GUI.MainFXMLController"
stylesheets="@styles.css">
<children> <children>
<!-- VBox sinistra: si espande per riempire tutto lo spazio disponibile -->
<VBox prefHeight="1080.0" prefWidth="1486.0" fillWidth="false" alignment="CENTER"> <VBox alignment="CENTER"
fillWidth="false"
maxHeight="Infinity"
maxWidth="Infinity"
HBox.hgrow="ALWAYS">
<HBox.margin> <HBox.margin>
<Insets top="5" right="5" bottom="5" left="5" /> <Insets top="5" right="5" bottom="5" left="5" />
</HBox.margin> </HBox.margin>
@@ -37,8 +45,13 @@
</children> </children>
</VBox> </VBox>
<!-- VBox destra: dimensione fissa, non si espande -->
<VBox fx:id="sidePanel" prefWidth="250.0" styleClass="side-panel"> <VBox fx:id="sidePanel"
prefWidth="250.0"
maxWidth="250.0"
minWidth="250.0"
HBox.hgrow="NEVER"
styleClass="side-panel">
<HBox.margin> <HBox.margin>
<Insets bottom="10" left="10" right="10" top="10" /> <Insets bottom="10" left="10" right="10" top="10" />
</HBox.margin> </HBox.margin>
@@ -67,5 +80,6 @@
</HBox> </HBox>
</children> </children>
</VBox> </VBox>
</children> </children>
</HBox> </HBox>
+71 -3
View File
@@ -1,6 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<StackPane xmlns="http://javafx.com/javafx/21"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="it.polimi.ingsw.gc14.View.GUI.TotemFXMLController"
prefWidth="1280" prefHeight="720"
style="-fx-background-color: #09060300;">
<ImageView fx:id="backgroundImage" fitWidth="1920" fitHeight="1080" preserveRatio="false">
</ImageView>
<Region fx:id="cornerTL" prefWidth="52" prefHeight="52"
style="-fx-border-color: rgba(200,120,20,0.35); -fx-border-width: 1.5 0 0 1.5;"
StackPane.alignment="TOP_LEFT">
<StackPane.margin><Insets top="18" left="18"/></StackPane.margin>
</Region>
<Region fx:id="cornerTR" prefWidth="52" prefHeight="52"
style="-fx-border-color: rgba(200,120,20,0.35); -fx-border-width: 1.5 1.5 0 0;"
StackPane.alignment="TOP_RIGHT">
<StackPane.margin><Insets top="18" right="18"/></StackPane.margin>
</Region>
<Region fx:id="cornerBL" prefWidth="52" prefHeight="52"
style="-fx-border-color: rgba(200,120,20,0.35); -fx-border-width: 0 0 1.5 1.5;"
StackPane.alignment="BOTTOM_LEFT">
<StackPane.margin><Insets bottom="18" left="18"/></StackPane.margin>
</Region>
<Region fx:id="cornerBR" prefWidth="52" prefHeight="52"
style="-fx-border-color: rgba(200,120,20,0.35); -fx-border-width: 0 1.5 1.5 0;"
StackPane.alignment="BOTTOM_RIGHT">
<StackPane.margin><Insets bottom="18" right="18"/></StackPane.margin>
</Region>
<VBox alignment="CENTER" spacing="0" StackPane.alignment="CENTER">
<padding><Insets top="40" bottom="40" left="40" right="40"/></padding>
<!-- Banner turno -->
<Label fx:id="turnBanner" maxWidth="640" wrapText="true" textAlignment="CENTER"
style="-fx-font-family: 'Cinzel'; -fx-font-size: 12; -fx-letter-spacing: 3;
-fx-padding: 10 28 10 28; -fx-background-radius: 3; -fx-border-radius: 3;
-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a)">
<VBox.margin><Insets bottom="20"/></VBox.margin>
</Label>
<HBox fx:id="mainHBox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/26" xmlns:fx="http://javafx.com/fxml/1" fx:controller="it.polimi.ingsw.gc14.View.GUI.TotemFXMLController"> <Label text="Choose your totem"
</HBox> style="-fx-font-family: 'Cinzel Decorative'; -fx-font-size: 30; -fx-font-weight: bold;
-fx-text-fill: #f4c05a;
-fx-effect: dropshadow(gaussian, rgba(244,192,90,0.4), 30, 0, 0, 0);">
<VBox.margin><Insets top="6"/></VBox.margin>
</Label>
<Region prefHeight="1" prefWidth="260"
style="-fx-background-color: linear-gradient(to right, transparent, #c8791a, #f4c05a, #c8791a, transparent);">
<VBox.margin><Insets top="14" bottom="24"/></VBox.margin>
</Region>
<HBox fx:id="mainHBox" alignment="CENTER" spacing="20">
<VBox.margin><Insets bottom="18"/></VBox.margin>
</HBox>
<Button fx:id="confirmButton" text="CONFIRM" onAction="#onConfirm" disable="true"
style="-fx-font-family: 'Cinzel'; -fx-font-size: 12; -fx-font-weight: bold;
-fx-letter-spacing: 4; -fx-text-fill: #0c0601;
-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);
-fx-padding: 12 48 12 48; -fx-background-radius: 2; -fx-opacity: 0.3;
-fx-cursor: default;"/>
</VBox>
</StackPane>