Updated: Totem CHoice fxml and controller

This commit is contained in:
rubenpirreram
2026-05-15 15:11:07 +02:00
parent f965e8ee60
commit dbcefe254b
4 changed files with 265 additions and 15 deletions
@@ -265,7 +265,7 @@ public class ServerLauncher {
break; break;
} }
catch(RemoteException e){ catch(RemoteException e){
throw new RuntimeException(e); System.out.println("Exception:"+e.getMessage());
} }
} }
} }
@@ -84,11 +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(); controllerMain.render();
primaryStage.setScene(mainScene); primaryStage.setScene(mainScene);
primaryStage.setFullScreen(true);
}); });
} }
} }
@@ -1,40 +1,213 @@
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 Label selectedLabel;
@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() {
mainHBox.getChildren().clear(); mainHBox.getChildren().clear();
for (Totems totem : controller.miniModel.availableTotems) { selectedIndex = -1;
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_"+ String.valueOf(totem).toLowerCase(Locale.ROOT) +".png"))); selectedFrame = null;
img.setFitHeight(240); selectedLabel.setText("");
String chooser = controller.miniModel.currentState.getCurrentPlayer().getUserName(); // adatta al tuo campo
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 choice ✦");
turnBanner.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 13; -fx-letter-spacing: 3;" +
"-fx-text-fill: #f4c05a;" +
"-fx-background-color: rgba(244,192,90,0.1);" +
"-fx-border-color: rgba(244,192,90,0.45); -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 " + chooser + " chooses his totem…");
turnBanner.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 11; -fx-letter-spacing: 2;" +
"-fx-text-fill: rgba(200,155,90,0.6);" +
"-fx-background-color: rgba(120,60,10,0.18);" +
"-fx-border-color: rgba(200,120,20,0.22); -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); img.setPreserveRatio(true);
img.setOnMouseClicked(e -> controller.totemChoice(controller.myUsername, controller.miniModel.availableTotems.indexOf(totem)));
mainHBox.getChildren().add(img); 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();
selectedLabel.setText(capitalize(totem).toUpperCase() + " choice");
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 ? "#f4c05a" : "rgba(200,120,20,0.28)") + ";" +
"-fx-border-width: " + (selected ? "2" : "0") + ";" +
"-fx-border-radius: 4 4 0 0; -fx-background-radius: 4 4 0 0;" +
(selected ? "-fx-effect: dropshadow(gaussian, rgba(244,192,90,0.35), 22, 0, 0, 0);" : "");
}
private String nameStyle(boolean selected) {
return "-fx-font-family: 'Cinzel'; -fx-font-size: 10; -fx-letter-spacing: 2;" +
"-fx-text-fill: " + (selected ? "#f4c05a" : "rgba(200,175,130,0.65)") + ";";
}
private String capitalize(Totems t) {
String s = t.name().toLowerCase(Locale.ROOT);
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
private String totemElement(Totems t) {
return switch (t) {
default -> t.name();
};
}
@FXML
private void onConfirm() {
if (selectedIndex >= 0) {
controller.totemChoice(controller.myUsername, selectedIndex);
}
}
} }
+78 -3
View File
@@ -1,6 +1,81 @@
<?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>
<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"> <Region fx:id="cornerTL" prefWidth="52" prefHeight="52"
</HBox> 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;">
<VBox.margin><Insets bottom="20"/></VBox.margin>
</Label>
<Label text="Pre game totem choosing stage"
style="-fx-font-family: 'Cinzel'; -fx-font-size: 10; -fx-text-fill: #9a5c14;
-fx-letter-spacing: 5;"/>
<Label text="Choice your totem"
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>
<Label fx:id="selectedLabel" text=""
style="-fx-font-family: 'Cinzel'; -fx-font-size: 10; -fx-text-fill: rgba(200,120,20,0.75);
-fx-letter-spacing: 3;">
<VBox.margin><Insets bottom="10"/></VBox.margin>
</Label>
<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>