GUI: added stacked feature for a non-creature tokens like Food and Treasure (#12242)

This commit is contained in:
grimreap124 2024-05-14 14:55:54 +10:00 committed by GitHub
parent 9f7b7654a4
commit 7e7287e7eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 92 additions and 51 deletions

View file

@ -55,10 +55,11 @@ public class CardPluginImpl implements CardPlugin {
private static final float STACK_SPACING_Y = 0.10f; private static final float STACK_SPACING_Y = 0.10f;
private static final float ATTACHMENT_SPACING_Y = 0.13f; private static final float ATTACHMENT_SPACING_Y = 0.13f;
private static final int landStackMax = 5; private static final int cardStackMax = 5;
private int cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth(); private int cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth();
private int cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth(); private int cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
// card width increment for auto-size searching (bigger value - faster draw speed on screen size, but not as accurate) // card width increment for auto-size searching (bigger value - faster draw
// speed on screen size, but not as accurate)
private static final int CARD_WIDTH_AUTO_FIT_INCREMENT = 10; private static final int CARD_WIDTH_AUTO_FIT_INCREMENT = 10;
private static final boolean stackVertical = false; private static final boolean stackVertical = false;
@ -101,12 +102,15 @@ public class CardPluginImpl implements CardPlugin {
* Temporary card rendering shim. Split card rendering isn't implemented * Temporary card rendering shim. Split card rendering isn't implemented
* yet, so use old component based rendering for the split cards. * yet, so use old component based rendering for the split cards.
*/ */
private CardPanel makeCardPanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension, int renderMode, boolean needFullPermanentRender) { private CardPanel makeCardPanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback,
boolean isFoil, Dimension dimension, int renderMode, boolean needFullPermanentRender) {
switch (renderMode) { switch (renderMode) {
case 0: case 0:
return new CardPanelRenderModeMTGO(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender); return new CardPanelRenderModeMTGO(view, gameId, loadImage, callback, isFoil, dimension,
needFullPermanentRender);
case 1: case 1:
return new CardPanelRenderModeImage(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender); return new CardPanelRenderModeImage(view, gameId, loadImage, callback, isFoil, dimension,
needFullPermanentRender);
default: default:
throw new IllegalStateException("Unknown render mode " + renderMode); throw new IllegalStateException("Unknown render mode " + renderMode);
@ -114,56 +118,53 @@ public class CardPluginImpl implements CardPlugin {
} }
@Override @Override
public MageCard getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) { public MageCard getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback,
CardPanel cardPanel = makeCardPanel(permanent, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender); boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makeCardPanel(permanent, gameId, loadImage, callback, false, dimension, renderMode,
needFullPermanentRender);
cardPanel.setShowCastingCost(true); cardPanel.setShowCastingCost(true);
return cardPanel; return cardPanel;
} }
@Override @Override
public MageCard getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) { public MageCard getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback,
CardPanel cardPanel = makeCardPanel(cardView, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender); boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makeCardPanel(cardView, gameId, loadImage, callback, false, dimension, renderMode,
needFullPermanentRender);
cardPanel.setShowCastingCost(true); cardPanel.setShowCastingCost(true);
return cardPanel; return cardPanel;
} }
@Override private Row createStacks(Map<UUID, MageCard> cards, Row workingRow, RowType rowType) {
public int sortPermanents(Map<String, JComponent> ui, Map<UUID, MageCard> cards, boolean nonPermanentsOwnRow, boolean topPanel) {
//requires to find out is position have been changed that includes:
//adding/removing permanents, type change
// must return new height, so battlefield scrolls can be enabled on too big sizes
if (ui == null) {
throw new RuntimeException("No battlefield ui for layout");
}
JLayeredPane battlefieldPanel = (JLayeredPane) ui.get("battlefieldPanel");
JComponent cardsPanel = ui.get("jPanel");
JScrollPane scrollPane = (JScrollPane) ui.get("scrollPane");
if (battlefieldPanel == null || cardsPanel == null || scrollPane == null) {
throw new RuntimeException("No battlefield components for layout");
}
Row rowAllLands = new Row();
outerLoop: outerLoop:
// //
for (MageCard card : cards.values()) { for (MageCard card : cards.values()) {
MagePermanent perm = (MagePermanent) card.getMainPanel(); // all cards must be MagePermanent on battlefield MagePermanent perm = (MagePermanent) card.getMainPanel(); // all cards must be MagePermanent on battlefield
if (!perm.isLand() || perm.isCreature()) { if (!rowType.isType(perm)) {
continue;
}
if ((!perm.isLand() && !perm.isToken())
|| perm.getOriginalPermanent().isAttachedToPermanent()
|| (perm.isCreature())) {
Stack newStack = new Stack();
newStack.add(perm);
workingRow.add(newStack);
continue; continue;
} }
int insertIndex = -1; int insertIndex = -1;
// Find already added lands with the same name. // Find already added to with the same name.
for (int i = 0, n = rowAllLands.size(); i < n; i++) { for (int i = 0, n = workingRow.size(); i < n; i++) {
// stack contains main card panel, but for any size/order manipulation you must use top layer panel // stack contains main card panel, but for any size/order manipulation you must
Stack stack = rowAllLands.get(i); // use top layer panel
Stack stack = workingRow.get(i);
MagePermanent firstPanelPerm = stack.get(0); MagePermanent firstPanelPerm = stack.get(0);
if (firstPanelPerm.getOriginal().getName().equals(perm.getOriginal().getName())) { if (firstPanelPerm.getOriginal().getName().equals(perm.getOriginal().getName())
&& firstPanelPerm.getOriginalPermanent().hasSummoningSickness() == perm.getOriginalPermanent()
.hasSummoningSickness()) {
if (!empty(firstPanelPerm.getOriginalPermanent().getAttachments())) { if (!empty(firstPanelPerm.getOriginalPermanent().getAttachments())) {
// Put this land to the left of lands with the same name and attachments. // Put this land to the left of lands with the same name and attachments.
@ -177,7 +178,7 @@ public class CardPluginImpl implements CardPlugin {
break; break;
} }
if (!empty(perm.getOriginalPermanent().getAttachments()) || stack.size() == landStackMax) { if (!empty(perm.getOriginalPermanent().getAttachments()) || stack.size() == cardStackMax) {
// If this land has attachments or the stack is full, put it to the right. // If this land has attachments or the stack is full, put it to the right.
insertIndex = i + 1; insertIndex = i + 1;
continue; continue;
@ -209,11 +210,39 @@ public class CardPluginImpl implements CardPlugin {
} }
stack.add(perm); stack.add(perm);
rowAllLands.add(insertIndex == -1 ? rowAllLands.size() : insertIndex, stack); workingRow.add(insertIndex == -1 ? workingRow.size() : insertIndex, stack);
} }
Row rowAllCreatures = new Row(cards, RowType.creature); return workingRow;
Row rowAllOthers = new Row(cards, RowType.other); }
@Override
public int sortPermanents(Map<String, JComponent> ui, Map<UUID, MageCard> cards, boolean nonPermanentsOwnRow,
boolean topPanel) {
// requires to find out is position have been changed that includes:
// adding/removing permanents, type change
// must return new height, so battlefield scrolls can be enabled on too big
// sizes
if (ui == null) {
throw new RuntimeException("No battlefield ui for layout");
}
JLayeredPane battlefieldPanel = (JLayeredPane) ui.get("battlefieldPanel");
JComponent cardsPanel = ui.get("jPanel");
JScrollPane scrollPane = (JScrollPane) ui.get("scrollPane");
if (battlefieldPanel == null || cardsPanel == null || scrollPane == null) {
throw new RuntimeException("No battlefield components for layout");
}
Row rowAllLands = new Row();
createStacks(cards, rowAllLands, RowType.land);
Row rowAllCreatures = new Row();
createStacks(cards, rowAllCreatures, RowType.creature);
Row rowAllOthers = new Row();
createStacks(cards, rowAllOthers, RowType.other);
Row rowAllAttached = new Row(cards, RowType.attached); Row rowAllAttached = new Row(cards, RowType.attached);
boolean othersOnTheRight = true; boolean othersOnTheRight = true;
@ -233,7 +262,8 @@ public class CardPluginImpl implements CardPlugin {
// calculate values based on the card size that is changing with every iteration // calculate values based on the card size that is changing with every iteration
cardHeight = Math.round(cardWidth * CardPanel.ASPECT_RATIO); cardHeight = Math.round(cardWidth * CardPanel.ASPECT_RATIO);
extraCardSpacingX = Math.round(cardWidth * EXTRA_CARD_SPACING_X); extraCardSpacingX = Math.round(cardWidth * EXTRA_CARD_SPACING_X);
cardSpacingX = cardHeight - cardWidth + extraCardSpacingX; // need space for tap animation (horizontal position) cardSpacingX = cardHeight - cardWidth + extraCardSpacingX; // need space for tap animation (horizontal
// position)
cardSpacingY = Math.round(cardHeight * CARD_SPACING_Y); cardSpacingY = Math.round(cardHeight * CARD_SPACING_Y);
stackSpacingX = stackVertical ? 0 : Math.round(cardWidth * STACK_SPACING_X); stackSpacingX = stackVertical ? 0 : Math.round(cardWidth * STACK_SPACING_X);
stackSpacingY = Math.round(cardHeight * STACK_SPACING_Y); stackSpacingY = Math.round(cardHeight * STACK_SPACING_Y);
@ -316,7 +346,8 @@ public class CardPluginImpl implements CardPlugin {
} }
} }
for (int panelIndex = 0, panelCount = stack.size(); panelIndex < panelCount; panelIndex++) { for (int panelIndex = 0, panelCount = stack.size(); panelIndex < panelCount; panelIndex++) {
MagePermanent panelPerm = stack.get(panelIndex); // it's original card panel, but you must change top layer MagePermanent panelPerm = stack.get(panelIndex); // it's original card panel, but you must change
// top layer
int stackPosition = panelCount - panelIndex - 1; int stackPosition = panelCount - panelIndex - 1;
if (cardsPanel != null) { if (cardsPanel != null) {
cardsPanel.setComponentZOrder(panelPerm.getTopPanelRef(), panelIndex); cardsPanel.setComponentZOrder(panelPerm.getTopPanelRef(), panelIndex);
@ -325,7 +356,8 @@ public class CardPluginImpl implements CardPlugin {
int panelY = y + (stackPosition * stackSpacingY); int panelY = y + (stackPosition * stackSpacingY);
try { try {
// may cause: // may cause:
// java.lang.IllegalArgumentException: illegal component position 26 should be less then 26 // java.lang.IllegalArgumentException: illegal component position 26 should be
// less then 26
battlefieldPanel.moveToFront(panelPerm.getTopPanelRef()); battlefieldPanel.moveToFront(panelPerm.getTopPanelRef());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -357,7 +389,8 @@ public class CardPluginImpl implements CardPlugin {
} }
private int wrap(Row sourceRow, List<Row> rows, int insertIndex) { private int wrap(Row sourceRow, List<Row> rows, int insertIndex) {
// The cards are sure to fit (with vertical scrolling) at the minimum card width. // The cards are sure to fit (with vertical scrolling) at the minimum card
// width.
boolean allowHeightOverflow = (cardWidth <= cardWidthMin); boolean allowHeightOverflow = (cardWidth <= cardWidthMin);
Row currentRow = new Row(); Row currentRow = new Row();
@ -420,7 +453,8 @@ public class CardPluginImpl implements CardPlugin {
return height - cardSpacingY + GUTTER_Y * 2; return height - cardSpacingY + GUTTER_Y * 2;
} }
private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, Map<UUID, MageCard> cards, MageCard cardWithAttachments) { private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, Map<UUID, MageCard> cards,
MageCard cardWithAttachments) {
int maxCol = ++currentCol; int maxCol = ++currentCol;
int attachments = 0; int attachments = 0;
MagePermanent permWithAttachments = (MagePermanent) cardWithAttachments.getMainPanel(); MagePermanent permWithAttachments = (MagePermanent) cardWithAttachments.getMainPanel();
@ -429,8 +463,10 @@ public class CardPluginImpl implements CardPlugin {
if (attachedCard != null) { if (attachedCard != null) {
attachments++; attachments++;
MagePermanent attachedPerm = (MagePermanent) attachedCard.getMainPanel(); MagePermanent attachedPerm = (MagePermanent) attachedCard.getMainPanel();
if (attachedPerm.getOriginalPermanent().getAttachments() != null && !attachedPerm.getOriginalPermanent().getAttachments().isEmpty()) { if (attachedPerm.getOriginalPermanent().getAttachments() != null
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol, cards, attachedCard); && !attachedPerm.getOriginalPermanent().getAttachments().isEmpty()) {
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol,
cards, attachedCard);
if (attachmentLayoutInfos.getColumns() > maxCol) { if (attachmentLayoutInfos.getColumns() > maxCol) {
maxCol = attachmentLayoutInfos.getColumns(); maxCol = attachmentLayoutInfos.getColumns();
attachments += attachmentLayoutInfos.getAttachments(); attachments += attachmentLayoutInfos.getAttachments();
@ -620,11 +656,12 @@ public class CardPluginImpl implements CardPlugin {
} }
/* /*
it = new CardFrames(imagesDir); // TODO: delete frames download (not need now) * it = new CardFrames(imagesDir); // TODO: delete frames download (not need
for (DownloadJob job : it) { * now)
g.getDownloader().add(job); * for (DownloadJob job : it) {
} * g.getDownloader().add(job);
*/ * }
*/
jobs = new DirectLinksForDownload(); jobs = new DirectLinksForDownload();
for (DownloadJob job : jobs) { for (DownloadJob job : jobs) {

View file

@ -18,4 +18,8 @@ public abstract class MagePermanent extends MageCard {
return getOriginal().isLand(); return getOriginal().isLand();
} }
public boolean isToken() {
return getOriginal().isToken();
}
} }