Made grid size fully dynamic (prep for visual beams)

* A lot of refactoring
This commit is contained in:
2020-07-10 23:54:34 +02:00
parent a3ceed42a0
commit 7af60bfaa0
12 changed files with 213 additions and 262 deletions

View File

@@ -188,11 +188,12 @@ public class WhatAStorage {
public boolean deliverProduct(int questIndex, int x, int y) {
if (canDeliverProduct(questIndex, x, y)) {
Product product = storage.get(x, y).front();
int z = storage.get(x, y).pop();
addTransaction(Balance.Transaction.DELIVER, quests.get(questIndex).getReward());
quests.remove(questIndex);
visual.onQuestRemoved(questIndex);
visual.onProductCleared(x, y, z);
visual.onProductCleared(x, y, z, product);
return true;
}
return false;
@@ -239,17 +240,18 @@ public class WhatAStorage {
int z1 = storage.get(x1, y1).pop();
addTransaction(Balance.Transaction.MOVE, -100);
visual.onProductCleared(x1, y1, z1);
visual.onProductCleared(x1, y1, z1, product);
visual.onProductSet(x2, y2, z2, product);
}
}
}
public void destroyProduct(int x, int y) {
Product product = storage.get(x, y).front();
int z = storage.get(x, y).pop();
if (z >= 0) {
addTransaction(Balance.Transaction.DESTROY, -500);
visual.onProductCleared(x, y, z);
visual.onProductCleared(x, y, z, product);
}
}
}

View File

@@ -36,14 +36,18 @@ public class StorageSlot {
}
public int pop() {
for (int i = products.length - 1; i >= 0; i--) {
Product product = products[i];
if (product != null) {
products[i] = null;
return i;
}
}
if (products[0] == null)
return -1;
int d = 0;
for (int i = 1; i < products.length; i++) {
if (products[i] == null) {
products[i - 1] = null;
return d;
}
d += products[i - 1].getDepth();
}
products[products.length - 1] = null;
return d;
}
public boolean fits(@NotNull Product product) {
@@ -71,7 +75,7 @@ public class StorageSlot {
}
if (i < products.length && product.getDepth() <= depth - blocked) {
products[i] = product;
return i;
return blocked;
}
return -1;
}

View File

@@ -175,7 +175,7 @@ public class CanvasVisual implements Visual {
}
@Override
public void onProductCleared(int x, int y, int z) {
public void onProductCleared(int x, int y, int z, Product product) {
}
}

View File

@@ -8,13 +8,13 @@ import de.siphalor.was.content.product.Product;
import de.siphalor.was.content.quest.Quest;
import de.siphalor.was.content.resource.Resource;
import de.siphalor.was.game.Balance;
import de.siphalor.was.util.PersistentInputStream;
import de.siphalor.was.visual.jfx.*;
import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
@@ -23,8 +23,10 @@ import javafx.scene.control.TableColumn;
import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.jetbrains.annotations.NotNull;
@@ -40,6 +42,8 @@ public class JFXVisual extends Application implements Visual {
private static Scene mainScene;
private static MainController controller;
private static GridPane storageGrid;
private static StorageSlot[][] storageSlots;
private static final Map<String, Image> CACHED_IMAGES = new HashMap<>();
@NotNull
@@ -83,8 +87,6 @@ public class JFXVisual extends Application implements Visual {
controller.totalIncomeLabel.setText(i18n.format("game.balance.total-income", totalIncome));
controller.totalLossLabel.setText(i18n.format("game.balance.total-loss", totalLoss));
ObservableList<XYChart.Data<Integer, Integer>> data = controller.budgetChartSeries.getData();
controller.chartQueue.add(budget);
if (controller.chartTab.isSelected()) {
@@ -142,7 +144,7 @@ public class JFXVisual extends Application implements Visual {
public void loadMainScene() {
primaryStage.setScene(mainScene);
prepareStorageGrid();
prepareStorageGrid(3, 3, 3);
AssetsManager.getStream("textures/bin_closed.png").ifPresent(inputStream -> {
controller.trash.setImage(new Image(inputStream));
@@ -190,36 +192,30 @@ public class JFXVisual extends Application implements Visual {
});
}
private void prepareStorageGrid() {
GridPane storageGrid = controller.storageGrid;
storageGrid.getChildren().clear();
private void prepareStorageGrid(int width, int height, int depth) {
storageGrid = new GridPane();
storageGrid.setId("storage-grid");
storageGrid.setPadding(new Insets(5D));
PersistentInputStream inputStream = new PersistentInputStream(AssetsManager.getStream("jfx/storage_slot.fxml").orElseThrow());
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(100D / width);
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(100D / height);
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
FXMLLoader loader = new FXMLLoader();
StorageSlotController storageSlotController = new StorageSlotController(x, y);
loader.setController(storageSlotController);
loader.setResources(I18n.getInstance());
try {
Parent parent = loader.load(inputStream);
inputStream.reset();
storageGrid.add(parent, x, y);
controller.storageSlotControllers[y][x] = storageSlotController;
} catch (IOException e) {
e.printStackTrace();
storageSlots = new StorageSlot[width][height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
StorageSlot storageSlot = new StorageSlot(x, y, depth);
storageSlots[y][x] = storageSlot;
storageGrid.add(storageSlot.getGrid(), x, y);
}
storageGrid.getRowConstraints().add(rowConstraints);
}
for (int x = 0; x < width; x++) {
storageGrid.getColumnConstraints().add(columnConstraints);
}
try {
inputStream.realClose();
} catch (IOException e) {
e.printStackTrace();
}
controller.storageTab.setContent(storageGrid);
}
@Override
@@ -227,25 +223,15 @@ public class JFXVisual extends Application implements Visual {
ContentManager contentManager = WhatAStorage.getInstance().getContentManager();
I18n i18n = I18n.getInstance();
StorageSlotController slot = controller.storageSlotControllers[y][x];
switch (z) {
default:
case 0:
slot.slot0.setImage(getProductImage(product, contentManager));
slot.slot0Title.setText(product.getName(i18n));
Tooltip.install(slot.slot0, createTooltip(product, i18n));
break;
case 1:
slot.slot1.setImage(getProductImage(product, contentManager));
slot.slot1Title.setText(product.getName(i18n));
Tooltip.install(slot.slot1, createTooltip(product, i18n));
break;
case 2:
slot.slot2.setImage(getProductImage(product, contentManager));
slot.slot2Title.setText(product.getName(i18n));
Tooltip.install(slot.slot2, createTooltip(product, i18n));
break;
}
StorageSlot slot = storageSlots[y][x];
int depth = product.getDepth();
int dz = z + depth - 1;
slot.getImages()[dz].setImage(getProductImage(product, contentManager));
slot.getImages()[dz].setTooltip(createTooltip(product, i18n));
slot.getLabels()[dz].setText(product.getName(i18n));
GridPane.setConstraints(slot.getImages()[dz], GridPane.getColumnIndex(slot.getImages()[dz]), dz - depth + 1, depth + 1, depth + 1);
}
private Tooltip createTooltip(Product product, I18n i18n) {
@@ -256,26 +242,14 @@ public class JFXVisual extends Application implements Visual {
}
@Override
public void onProductCleared(int x, int y, int z) {
StorageSlotController slot = controller.storageSlotControllers[y][x];
public void onProductCleared(int x, int y, int z, Product product) {
StorageSlot slot = storageSlots[y][x];
String empty = I18n.getInstance().getString("game.storage.empty");
switch (z) {
default:
case 0:
slot.slot0.setImage(null);
slot.slot0Title.setText(empty);
Tooltip.uninstall(slot.slot0, null);
break;
case 1:
slot.slot1.setImage(null);
slot.slot1Title.setText(empty);
Tooltip.uninstall(slot.slot1, null);
break;
case 2:
slot.slot2.setImage(null);
slot.slot2Title.setText(empty);
Tooltip.uninstall(slot.slot2, null);
break;
}
int dz = z + product.getDepth() - 1;
slot.getImages()[dz].setImage(null);
slot.getImages()[dz].setTooltip(null);
slot.getLabels()[dz].setText(empty);
GridPane.setConstraints(slot.getImages()[dz], GridPane.getColumnIndex(slot.getImages()[dz]), dz, 1, 1);
}
}

View File

@@ -17,5 +17,5 @@ public interface Visual {
void onProductSet(int x, int y, int z, Product product);
void onProductCleared(int x, int y, int z);
void onProductCleared(int x, int y, int z, Product product);
}

View File

@@ -15,7 +15,6 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import java.util.LinkedList;
@@ -25,6 +24,7 @@ import java.util.Queue;
public class MainController {
private final WhatAStorage was;
public Tab storageTab;
public Tab chartTab;
public Label budgetLabel;
public Label totalIncomeLabel;
@@ -39,9 +39,6 @@ public class MainController {
public VBox questBox;
public Button nextQuestButton;
public GridPane storageGrid;
public StorageSlotController[][] storageSlotControllers = new StorageSlotController[3][3];
public MainController(WhatAStorage was) {
this.was = was;
}

View File

@@ -0,0 +1,149 @@
package de.siphalor.was.visual.jfx;
import de.siphalor.was.WhatAStorage;
import de.siphalor.was.content.lang.I18n;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
@SuppressWarnings("unused")
public class StorageSlot {
private final int x;
private final int y;
private final int depth;
private final GridPane grid;
private final ScalingImagePane[] images;
private final Label[] labels;
public StorageSlot(int x, int y, int depth) {
this.x = x;
this.y = y;
this.depth = depth;
this.grid = new GridPane();
grid.setOnDragDetected(this::onDragDetected);
grid.setOnDragDropped(this::onDragDropped);
grid.setOnDragEntered(this::onDragEntered);
grid.setOnDragExited(this::onDragExited);
grid.setOnDragOver(this::onDragOver);
images = new ScalingImagePane[depth];
labels = new Label[depth];
String empty = I18n.getInstance().getString("game.storage.empty");
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(100D / (depth + 1));
rowConstraints.setMinHeight(10D);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(70D / (depth + 1));
columnConstraints.setMinWidth(10D);
for (int z = 0; z < depth; z++) {
ScalingImagePane imagePane = new ScalingImagePane();
grid.add(imagePane, depth - z - 1, z, 1, 1);
GridPane.setValignment(imagePane, VPos.TOP);
GridPane.setHalignment(imagePane, HPos.RIGHT);
Label label = new Label();
label.setText(empty);
label.getStyleClass().add("storage-slot-item-title");
grid.add(label, depth - z + 1, z + 1, Integer.MAX_VALUE, 1);
GridPane.setValignment(label, VPos.TOP);
images[z] = imagePane;
labels[z] = label;
grid.getRowConstraints().add(rowConstraints);
grid.getColumnConstraints().add(columnConstraints);
}
grid.getColumnConstraints().add(columnConstraints);
grid.getColumnConstraints().add(new ColumnConstraints(30D));
grid.getRowConstraints().add(rowConstraints);
}
public GridPane getGrid() {
return grid;
}
public ScalingImagePane[] getImages() {
return images;
}
public Label[] getLabels() {
return labels;
}
private boolean canDropHere(DragEvent dragEvent) {
if (dragEvent.getGestureSource() != grid && dragEvent.getDragboard().hasContent(DraggedProduct.FORMAT)) {
DraggedProduct origin = (DraggedProduct) dragEvent.getDragboard().getContent(DraggedProduct.FORMAT);
if (origin instanceof DraggedProduct.Quest) {
return WhatAStorage.getInstance().canStoreProduct(((DraggedProduct.Quest) origin).index, x, y);
} else if (origin instanceof DraggedProduct.Slot){
return WhatAStorage.getInstance().canMoveProduct(((DraggedProduct.Slot) origin).x, ((DraggedProduct.Slot) origin).y, x, y);
}
}
return false;
}
private void onDragDetected(MouseEvent event) {
int index;
Image image = null;
for (int z = depth - 1; z >= 0; z--) {
if (images[z].getImage() != null) {
image = images[z].getImage();
break;
}
}
if (image == null)
return;
Dragboard dragboard = grid.startDragAndDrop(TransferMode.MOVE);
dragboard.setDragView(JFXUtil.scaleTo(image, 100));
ClipboardContent content = new ClipboardContent();
content.put(DraggedProduct.FORMAT, new DraggedProduct.Slot(x, y));
dragboard.setContent(content);
event.consume();
}
private void onDragEntered(DragEvent dragEvent) {
JFXUtil.setStyleClass(grid, "drop-hover", canDropHere(dragEvent));
}
private void onDragExited(DragEvent dragEvent) {
JFXUtil.setStyleClass(grid, "drop-hover", false);
}
private void onDragOver(DragEvent dragEvent) {
if (canDropHere(dragEvent)) {
dragEvent.acceptTransferModes(TransferMode.MOVE);
}
dragEvent.consume();
}
private void onDragDropped(DragEvent dragEvent) {
if (dragEvent.getGestureSource() != grid && dragEvent.getDragboard().hasContent(DraggedProduct.FORMAT)) {
DraggedProduct origin = (DraggedProduct) dragEvent.getDragboard().getContent(DraggedProduct.FORMAT);
if (origin instanceof DraggedProduct.Quest) {
WhatAStorage.getInstance().storeProduct(((DraggedProduct.Quest) origin).index, x, y);
dragEvent.setDropCompleted(true);
return;
} else if (origin instanceof DraggedProduct.Slot) {
DraggedProduct.Slot slot = (DraggedProduct.Slot) origin;
WhatAStorage.getInstance().moveProduct(slot.x, slot.y, x, y);
dragEvent.setDropCompleted(true);
return;
}
}
dragEvent.setDropCompleted(false);
}
}

View File

@@ -1,103 +0,0 @@
package de.siphalor.was.visual.jfx;
import de.siphalor.was.WhatAStorage;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.input.*;
@SuppressWarnings("unused")
public class StorageSlotController {
private final int x;
private final int y;
@FXML
private Parent slot;
public ScalingImagePane slot0;
public Label slot0Title;
public ScalingImagePane slot1;
public Label slot1Title;
public ScalingImagePane slot2;
public Label slot2Title;
public StorageSlotController(int x, int y) {
this.x = x;
this.y = y;
}
private boolean canDropHere(DragEvent dragEvent) {
if (dragEvent.getGestureSource() != slot && dragEvent.getDragboard().hasContent(DraggedProduct.FORMAT)) {
DraggedProduct origin = (DraggedProduct) dragEvent.getDragboard().getContent(DraggedProduct.FORMAT);
if (origin instanceof DraggedProduct.Quest) {
return WhatAStorage.getInstance().canStoreProduct(((DraggedProduct.Quest) origin).index, x, y);
} else if (origin instanceof DraggedProduct.Slot){
return WhatAStorage.getInstance().canMoveProduct(((DraggedProduct.Slot) origin).x, ((DraggedProduct.Slot) origin).y, x, y);
}
}
return false;
}
@FXML
private void onDragDetected(MouseEvent event) {
int index;
Image image;
if (slot2.getImage() != null) {
image = JFXUtil.scaleTo(slot2.getImage(), 100);
} else if (slot1.getImage() != null) {
image = JFXUtil.scaleTo(slot1.getImage(), 100);
} else if (slot0.getImage() != null){
image = JFXUtil.scaleTo(slot0.getImage(), 100);
} else {
event.consume();
return;
}
Dragboard dragboard = slot.startDragAndDrop(TransferMode.MOVE);
dragboard.setDragView(image);
ClipboardContent content = new ClipboardContent();
content.put(DraggedProduct.FORMAT, new DraggedProduct.Slot(x, y));
dragboard.setContent(content);
event.consume();
}
@FXML
private void onDragEntered(DragEvent dragEvent) {
JFXUtil.setStyleClass(slot, "drop-hover", canDropHere(dragEvent));
}
@FXML
private void onDragExited(DragEvent dragEvent) {
JFXUtil.setStyleClass(slot, "drop-hover", false);
}
@FXML
private void onDragOver(DragEvent dragEvent) {
if (canDropHere(dragEvent)) {
dragEvent.acceptTransferModes(TransferMode.MOVE);
}
dragEvent.consume();
}
@FXML
private void onDragDropped(DragEvent dragEvent) {
if (dragEvent.getGestureSource() != slot && dragEvent.getDragboard().hasContent(DraggedProduct.FORMAT)) {
DraggedProduct origin = (DraggedProduct) dragEvent.getDragboard().getContent(DraggedProduct.FORMAT);
if (origin instanceof DraggedProduct.Quest) {
WhatAStorage.getInstance().storeProduct(((DraggedProduct.Quest) origin).index, x, y);
dragEvent.setDropCompleted(true);
return;
} else if (origin instanceof DraggedProduct.Slot) {
DraggedProduct.Slot slot = (DraggedProduct.Slot) origin;
WhatAStorage.getInstance().moveProduct(slot.x, slot.y, x, y);
dragEvent.setDropCompleted(true);
return;
}
}
dragEvent.setDropCompleted(false);
}
}

View File

@@ -91,25 +91,7 @@
</GridPane>
<TabPane minWidth="450.0" tabClosingPolicy="UNAVAILABLE" tabMaxHeight="Infinity" tabMaxWidth="Infinity">
<tabs>
<Tab text="%game.storage">
<content>
<GridPane id="storage-grid" fx:id="storageGrid" alignment="CENTER_LEFT" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="33.333" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>
</content>
</Tab>
<Tab fx:id="storageTab" text="%game.storage" />
<Tab text="%game.balance.history">
<content>
<TableView fx:id="balanceHistoryTable" prefHeight="200.0" prefWidth="200.0">

View File

@@ -100,6 +100,7 @@ Label.green {
.storage-slot-item-title {
-fx-padding: 0 0 0 5;
-fx-end-margin: 10;
-fx-font-weight: bold;
}
.storage-slot-item-image {
}

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import de.siphalor.was.visual.jfx.ScalingImagePane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<GridPane fx:id="slot" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" onDragDetected="#onDragDetected" onDragDropped="#onDragDropped" onDragEntered="#onDragEntered" onDragExited="#onDragExited" onDragOver="#onDragOver" GridPane.valignment="CENTER" alignment="CENTER_LEFT" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="30.0" percentWidth="15"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="30.0" percentWidth="15"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="30.0" percentWidth="15"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="30.0" percentWidth="15"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" percentWidth="40" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" percentHeight="25"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" percentHeight="25"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" percentHeight="25"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" percentHeight="25"/>
</rowConstraints>
<children>
<ScalingImagePane styleClass="storage-slot-item-image" fx:id="slot0" maxHeight="100" GridPane.columnIndex="2" GridPane.columnSpan="2" GridPane.rowSpan="2"/>
<ScalingImagePane styleClass="storage-slot-item-image" fx:id="slot1" maxHeight="100" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="1" GridPane.rowSpan="2"/>
<ScalingImagePane styleClass="storage-slot-item-image" fx:id="slot2" maxHeight="100" GridPane.columnSpan="2" GridPane.rowIndex="2" GridPane.rowSpan="2"/>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" GridPane.columnIndex="4" GridPane.rowIndex="1">
<children>
<Label fx:id="slot0Title" styleClass="storage-slot-item-title" text="%game.storage.empty">
<font>
<Font name="System Bold" size="15.0"/>
</font>
</Label>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" GridPane.columnIndex="3" GridPane.columnSpan="2147483647"
GridPane.rowIndex="2">
<children>
<Label fx:id="slot1Title" styleClass="storage-slot-item-title" text="%game.storage.empty">
<font>
<Font name="System Bold" size="15.0"/>
</font>
</Label>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" GridPane.columnIndex="2" GridPane.columnSpan="2147483647"
GridPane.rowIndex="3">
<children>
<Label fx:id="slot2Title" styleClass="storage-slot-item-title" text="%game.storage.empty">
<font>
<Font name="System Bold" size="15.0"/>
</font>
</Label>
</children>
</HBox>
</children>
</GridPane>

View File

@@ -43,7 +43,7 @@ public class DummyVisual implements Visual {
}
@Override
public void onProductCleared(int x, int y, int z) {
public void onProductCleared(int x, int y, int z, Product product) {
}
}