Shadows, Zoom, Icons added

This commit is contained in:
2026-05-11 14:29:41 +02:00
parent 92b3024d57
commit bcdc129e67
4 changed files with 206 additions and 86 deletions
@@ -14,8 +14,6 @@ public class ClientLauncherGUI extends Application {
@Override
public void start(Stage stage) {
Font.loadFont(getClass().getResourceAsStream("/Fonts/InknutAntiqua-Regular.ttf"), 14);
LoginView loginView = new LoginView();
GUI view = new GUI(stage);
@@ -8,16 +8,26 @@ import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Model.PlayableCard;
import it.polimi.ingsw.gc14.Model.Player;
import it.polimi.ingsw.gc14.Model.Slot;
import javafx.animation.ScaleTransition;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.stage.Popup;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class MainFXMLController {
@@ -42,6 +52,7 @@ public class MainFXMLController {
private Game model;
private ClientController controller;
private String username;
private final Map<String, ImageView> cardCache = new HashMap<>();
public void setModel(Game model) {this.model = model;}
public void setController(ClientController controller) {this.controller = controller;}
@@ -52,7 +63,8 @@ public class MainFXMLController {
@FXML
public void initialize() {
// Reapply CSS
// Import font and apply CSS
Font.loadFont(getClass().getResourceAsStream("/Fonts/InknutAntiqua-Regular.ttf"), 14);
mainHBox.sceneProperty().addListener((obs, oldScene, newScene) -> {
if (newScene != null) {
newScene.getRoot().applyCss();
@@ -73,6 +85,80 @@ public class MainFXMLController {
renderSidePanel();
}
// ==== HELPER ====
private ImageView createSlot(Slot slot) {
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);
return img;
}
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 {
img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + id + ".png")));
cardCache.put(id, img);
}
img.setFitHeight(200);
img.setPreserveRatio(true);
Rectangle clip = new Rectangle();
clip.setWidth(img.getBoundsInLocal().getWidth());
clip.setHeight(200);
clip.setArcWidth(20);
clip.setArcHeight(20);
img.setClip(clip);
StackPane wrapper = new StackPane(img);
if (withShadow) {
addShadow(wrapper);
}
if (withZoom) {
addHoverZoom(wrapper);
}
return wrapper;
}
private void addHoverZoom(Node node) {
ScaleTransition scaleUp = new ScaleTransition(Duration.millis(150), node);
scaleUp.setToX(1.1);
scaleUp.setToY(1.1);
ScaleTransition scaleDown = new ScaleTransition(Duration.millis(150), node);
scaleDown.setToX(1.0);
scaleDown.setToY(1.0);
node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> { scaleUp.play(); node.setCursor(Cursor.HAND); });
node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> { scaleDown.play(); node.setCursor(Cursor.DEFAULT); });
}
private void addShadow(Node node) {
DropShadow shadow = new DropShadow();
shadow.setColor(Color.rgb(0, 0, 0, 0.3));
shadow.setRadius(6);
shadow.setOffsetX(2);
shadow.setOffsetY(2);
node.setEffect(shadow);
node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> {
shadow.setRadius(16);
shadow.setOffsetX(4);
shadow.setOffsetY(4);
shadow.setColor(Color.rgb(0, 0, 0, 0.5));
});
node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
shadow.setRadius(6);
shadow.setOffsetX(2);
shadow.setOffsetY(2);
shadow.setColor(Color.rgb(0, 0, 0, 0.3));
});
}
@@ -93,41 +179,15 @@ public class MainFXMLController {
}
// UPPER, LOWER AND BOARD
private ImageView createCard(PlayableCard card) {
ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Fronts/card-" + card.getIdIMG() + ".png")));
img.setFitHeight(200);
img.setPreserveRatio(true);
Rectangle clip = new Rectangle();
clip.setWidth(img.getBoundsInLocal().getWidth());
clip.setHeight(200);
clip.setArcWidth(20);
clip.setArcHeight(20);
img.setClip(clip);
return img;
}
private ImageView createSlot(Slot slot) {
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);
return img;
}
private void renderUpper() {
upperList.setSpacing(6);
upperList.setSpacing(14);
upperList.setAlignment(Pos.CENTER);
upperList.getChildren().clear();
int i = 0;
for (TribeCard card : model.getUpperListTribeCards()) {
final int index = i;
ImageView img = createCard(card);
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperTribeCard(username, index));
upperList.getChildren().add(img);
i++;
@@ -135,14 +195,14 @@ public class MainFXMLController {
i = 0;
for (BuildingCard card : model.getUpperListBuilding()) {
final int index = i;
ImageView img = createCard(card);
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(username, index));
upperList.getChildren().add(img);
i++;
}
}
private void renderBoard() {
board.setSpacing(6);
board.setSpacing(14);
board.setAlignment(Pos.CENTER);
board.getChildren().clear();
@@ -157,14 +217,14 @@ public class MainFXMLController {
}
}
private void renderLower() {
lowerList.setSpacing(6);
lowerList.setSpacing(14);
lowerList.setAlignment(Pos.CENTER);
lowerList.getChildren().clear();
int i = 0;
for (TribeCard card : model.getLowerListTribeCards()) {
final int index = i;
ImageView img = createCard(card);
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerTribeCard(username, index));
lowerList.getChildren().add(img);
i++;
@@ -172,7 +232,7 @@ public class MainFXMLController {
i = 0;
for (BuildingCard card : model.getLowerListBuilding()) {
final int index = i;
ImageView img = createCard(card);
StackPane img = createCard(card, true, true);
img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(username, index));
lowerList.getChildren().add(img);
i++;
@@ -180,32 +240,9 @@ public class MainFXMLController {
}
// MY HAND
private void drawMyHandList(HBox myHand, ArrayList<? extends PlayableCard> cardList) {
if (!cardList.isEmpty()) {
ImageView img = createCard(cardList.getLast());
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);
StackPane stack = new StackPane(img, label);
stack.setClip(null);
stack.setOnMouseClicked(e -> openPopup(cardList));
myHand.getChildren().add(stack);
} 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 renderMyHand() {
myHand.getChildren().clear();
myHand.setSpacing(6);
myHand.setSpacing(14);
myHand.setAlignment(Pos.CENTER);
drawMyHandList(myHand, model.getPlayerByUsername(username).artists);
@@ -216,16 +253,36 @@ public class MainFXMLController {
drawMyHandList(myHand, model.getPlayerByUsername(username).hunters);
drawMyHandList(myHand, model.getPlayerByUsername(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);
sidePanel.setAlignment(Pos.CENTER);
era.setText(Integer.toString(model.getCurrentState().getEra()));
round.setText(Integer.toString(model.getCurrentState().getRound()));
player.setText(model.getCurrentState().getCurrentPlayer().getUserName());
VBox.setMargin(info, new Insets(5, 5, 5, 5));
sidePanel.getChildren().add(info);
renderPlayers(sidePanel);
@@ -249,42 +306,104 @@ public class MainFXMLController {
foodLabel.getStyleClass().add("label-small");
Label prestigeLabel = new Label("Prestige: " + player.getPrestigeValue());
prestigeLabel.getStyleClass().add("label-small");
card.getChildren().addAll(usernameLabel, foodLabel, prestigeLabel);
HBox icons = new HBox();
icons.setSpacing(6);
icons.setAlignment(Pos.CENTER);
renderIcons(icons, player);
card.getChildren().addAll(usernameLabel, foodLabel, prestigeLabel, icons);
ArrayList<PlayableCard> playerCard = new ArrayList<>();
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).artists);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).gatherers);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).inventors);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).builders);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).shamans);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).hunters);
playerCard.addAll(model.getPlayerByUsername(player.getUserName()).buildingCards);
card.setOnMouseClicked(e -> openPopup(playerCard));
playersHand.getChildren().add(card);
}
}
private void renderIcons(HBox icons, Player player) {
String[][] iconTypes = {
{"Artist", "artists"},
{"Gatherer", "gatherers"},
{"Inventor", "inventors"},
{"Builder", "builders"},
{"Shaman", "shamans"},
{"Hunter", "hunters"}
};
for (String[] type : iconTypes) {
String iconName = type[0];
String fieldName = type[1];
ImageView icon = new ImageView();
icon.setFitWidth(28);
icon.setFitHeight(28);
icon.setPreserveRatio(true);
icon.setImage(new Image(getClass().getResourceAsStream("/GUIImages/Icons/" + iconName + ".png")));
ArrayList<PlayableCard> cards = getPlayerCards(player.getUserName(), fieldName);
if (cards.isEmpty()) {
ColorAdjust grayscale = new ColorAdjust();
grayscale.setSaturation(-1.0);
icon.setEffect(grayscale);
icon.setOpacity(0.5);
} else {
icon.setOnMouseClicked(e -> openPopup(cards));
addHoverZoom(icon);
}
icons.getChildren().add(icon);
}
}
private ArrayList<PlayableCard> getPlayerCards(String username, String type) {
Player p = model.getPlayerByUsername(username);
return switch (type) {
case "artists" -> new ArrayList<>(p.artists);
case "gatherers" -> new ArrayList<>(p.gatherers);
case "inventors" -> new ArrayList<>(p.inventors);
case "builders" -> new ArrayList<>(p.builders);
case "shamans" -> new ArrayList<>(p.shamans);
case "hunters" -> new ArrayList<>(p.hunters);
default -> new ArrayList<>();
};
}
// POPUP
private void initPopup() {
popupCards = new HBox(10);
popupCards.setAlignment(Pos.CENTER);
popupCards.setPadding(new Insets(10));
popupCards.getStyleClass().add("popup");
popupCards.setStyle(
"-fx-background-color: #b42224;" +
"-fx-border-color: black;" +
"-fx-border-width: 2;" +
"-fx-border-radius: 10;" +
"-fx-background-radius: 10;"
);
Rectangle clip = new Rectangle();
clip.setArcWidth(20);
clip.setArcHeight(20);
clip.widthProperty().bind(popupCards.widthProperty());
clip.heightProperty().bind(popupCards.heightProperty());
popupCards.setClip(clip);
popup = new Popup();
popup.getContent().add(popupCards);
popup.setAutoHide(true);
// Aspetta che la scena del popup esista, poi la rendi trasparente
popup.addEventHandler(javafx.event.Event.ANY, e -> {
if (popup.getScene() != null) {
popup.getScene().setFill(Color.TRANSPARENT);
}
});
}
private void openPopup(ArrayList<? extends PlayableCard> cardList) {
popupCards.getChildren().clear();
for (PlayableCard card : cardList) {
ImageView img = createCard(card);
StackPane img = createCard(card, false, false);
popupCards.getChildren().add(img);
}
javafx.stage.Window window = myHand.getScene().getWindow();
popup.show(window, (window.getWidth() - popup.getWidth()) / 2, (window.getHeight() - popup.getHeight()) / 2);
// La scena esiste solo dopo show()
popup.getScene().setFill(Color.TRANSPARENT);
}
}
+4 -4
View File
@@ -43,23 +43,23 @@
<Insets bottom="10" left="10" right="10" top="10" />
</HBox.margin>
<children>
<HBox fx:id="info" prefHeight="107.0" prefWidth="483.0">
<HBox fx:id="info" prefHeight="107.0" prefWidth="483.0" styleClass="frame">
<children>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-small" text="ERA" />
<Label styleClass="label-medium" text="Era" />
<Label fx:id="era" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-small" text="ROUND" />
<Label styleClass="label-medium" text="Round" />
<Label fx:id="round" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-small" text="PLAYER" />
<Label styleClass="label-medium" text="Player" />
<Label fx:id="player" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
+9 -6
View File
@@ -38,10 +38,13 @@
-fx-background-color: #b42224;
}
.popup {
-fx-background-color: #b42224;
-fx-border-color: black;
-fx-border-width: 2;
-fx-border-radius: 10;
-fx-background-radius: 10;
.frame {
-fx-background-color:
#8B6914,
#FFF8DC,
#8B6914,
#FFF8DC;
-fx-background-insets: 0, 5, 10, 15;
-fx-background-radius: 15, 12, 8, 4;
-fx-padding: 15 15 15 15;
}