* GUI: new reworked GUI and card render engine, card icons and dozens of other fixes (see full list in related PR);

This commit is contained in:
Oleg Agafonov 2021-01-30 16:38:55 +04:00
parent df98cc3e62
commit a1da5ef437
304 changed files with 7266 additions and 5093 deletions

View file

@ -1,5 +1,6 @@
package org.mage.plugins.card;
import mage.cards.MageCard;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
import mage.client.util.GUISizeHelper;
@ -45,8 +46,8 @@ public class CardPluginImpl implements CardPlugin {
private static final Logger LOGGER = Logger.getLogger(CardPluginImpl.class);
private static final int GUTTER_Y = 15;
private static final int GUTTER_X = 5;
private static final int GUTTER_Y = 15; // top offset before cards
private static final int GUTTER_X = 15; // left offset before cards
static final float EXTRA_CARD_SPACING_X = 0.04f;
private static final float CARD_SPACING_Y = 0.03f;
private static final float STACK_SPACING_X = 0.07f;
@ -54,9 +55,10 @@ public class CardPluginImpl implements CardPlugin {
private static final float ATTACHMENT_SPACING_Y = 0.13f;
private static final int landStackMax = 5;
// private int cardWidthMin = 50, cardWidthMax = Constants.CARD_SIZE_FULL.width;
private int cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.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)
private static final int CARD_WIDTH_AUTO_FIT_INCREMENT = 10;
private static final boolean stackVertical = false;
@ -98,12 +100,12 @@ public class CardPluginImpl implements CardPlugin {
* Temporary card rendering shim. Split card rendering isn't implemented
* yet, so use old component based rendering for the split cards.
*/
private CardPanel makePanel(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) {
case 0:
return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender);
return new CardPanelRenderModeMTGO(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender);
case 1:
return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender);
return new CardPanelRenderModeImage(view, gameId, loadImage, callback, isFoil, dimension, needFullPermanentRender);
default:
throw new IllegalStateException("Unknown render mode " + renderMode);
@ -111,43 +113,45 @@ public class CardPluginImpl implements CardPlugin {
}
@Override
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender);
public MageCard getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makeCardPanel(permanent, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender);
cardPanel.setShowCastingCost(true);
return cardPanel;
}
@Override
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender);
public MageCard getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender) {
CardPanel cardPanel = makeCardPanel(cardView, gameId, loadImage, callback, false, dimension, renderMode, needFullPermanentRender);
cardPanel.setShowCastingCost(true);
return cardPanel;
}
@Override
public int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> permanents, boolean nonPermanentsOwnRow, boolean topPanel) {
//TODO: add caching
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("Error: no components");
}
JComponent component = ui.get("battlefieldPanel");
if (component == null) {
throw new RuntimeException("Error: battlefieldPanel is missing");
throw new RuntimeException("No battlefield ui for layout");
}
JLayeredPane battlefieldPanel = (JLayeredPane) component;
JComponent jPanel = ui.get("jPanel");
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:
//
for (MagePermanent permanent : permanents.values()) {
if (!permanent.isLand() || permanent.isCreature()) {
for (MageCard card : cards.values()) {
MagePermanent perm = (MagePermanent) card.getMainPanel(); // all cards must be MagePermanent on battlefield
if (!perm.isLand() || perm.isCreature()) {
continue;
}
@ -155,35 +159,36 @@ public class CardPluginImpl implements CardPlugin {
// Find already added lands with the same name.
for (int i = 0, n = rowAllLands.size(); i < n; i++) {
// stack contains main card panel, but for any size/order manipulation you must use top layer panel
Stack stack = rowAllLands.get(i);
MagePermanent firstPanel = stack.get(0);
if (firstPanel.getOriginal().getName().equals(permanent.getOriginal().getName())) {
MagePermanent firstPanelPerm = stack.get(0);
if (firstPanelPerm.getOriginal().getName().equals(perm.getOriginal().getName())) {
if (!empty(firstPanel.getOriginalPermanent().getAttachments())) {
if (!empty(firstPanelPerm.getOriginalPermanent().getAttachments())) {
// Put this land to the left of lands with the same name and attachments.
insertIndex = i;
break;
}
List<CounterView> counters = firstPanel.getOriginalPermanent().getCounters();
List<CounterView> counters = firstPanelPerm.getOriginalPermanent().getCounters();
if (counters != null && !counters.isEmpty()) {
// don't put to first panel if it has counters
insertIndex = i;
break;
}
if (!empty(permanent.getOriginalPermanent().getAttachments()) || stack.size() == landStackMax) {
if (!empty(perm.getOriginalPermanent().getAttachments()) || stack.size() == landStackMax) {
// If this land has attachments or the stack is full, put it to the right.
insertIndex = i + 1;
continue;
}
counters = permanent.getOriginalPermanent().getCounters();
counters = perm.getOriginalPermanent().getCounters();
if (counters != null && !counters.isEmpty()) {
// if a land has counter, put it to the right
insertIndex = i + 1;
continue;
}
// Add to stack.
stack.add(0, permanent);
stack.add(0, perm);
continue outerLoop;
}
if (insertIndex != -1) {
@ -193,22 +198,22 @@ public class CardPluginImpl implements CardPlugin {
Stack stack = new Stack();
if (permanent.getOriginalPermanent().getAttachments() != null
&& !permanent.getOriginalPermanent().getAttachments().isEmpty()
&& !permanent.getOriginalPermanent().isAttachedTo()) {
if (perm.getOriginalPermanent().getAttachments() != null
&& !perm.getOriginalPermanent().getAttachments().isEmpty()
&& !perm.getOriginalPermanent().isAttachedTo()) {
// get the number of all attachements and sub attachments
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, permanents, permanent);
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, cards, card);
stack.setMaxAttachedCount(ali.getAttachments());
stack.setAttachmentColumns(ali.getColumns());
}
stack.add(permanent);
stack.add(perm);
rowAllLands.add(insertIndex == -1 ? rowAllLands.size() : insertIndex, stack);
}
Row rowAllCreatures = new Row(permanents, RowType.creature);
Row rowAllOthers = new Row(permanents, RowType.other);
Row rowAllAttached = new Row(permanents, RowType.attached);
Row rowAllCreatures = new Row(cards, RowType.creature);
Row rowAllOthers = new Row(cards, RowType.other);
Row rowAllAttached = new Row(cards, RowType.attached);
boolean othersOnTheRight = true;
if (nonPermanentsOwnRow) {
@ -217,6 +222,7 @@ public class CardPluginImpl implements CardPlugin {
rowAllOthers.clear();
}
// try to auto-fit cards
cardWidth = cardWidthMax;
Rectangle rect = battlefieldPanel.getVisibleRect();
playAreaWidth = rect.width;
@ -226,7 +232,7 @@ public class CardPluginImpl implements CardPlugin {
// calculate values based on the card size that is changing with every iteration
cardHeight = Math.round(cardWidth * CardPanel.ASPECT_RATIO);
extraCardSpacingX = Math.round(cardWidth * EXTRA_CARD_SPACING_X);
cardSpacingX = cardHeight - cardWidth + extraCardSpacingX;
cardSpacingX = cardHeight - cardWidth + extraCardSpacingX; // need space for tap animation (horizontal position)
cardSpacingY = Math.round(cardHeight * CARD_SPACING_Y);
stackSpacingX = stackVertical ? 0 : Math.round(cardWidth * STACK_SPACING_X);
stackSpacingY = Math.round(cardHeight * STACK_SPACING_Y);
@ -248,7 +254,6 @@ public class CardPluginImpl implements CardPlugin {
addOthersIndex = rows.size();
wrap(lands, rows, rows.size());
wrap(others, rows, rows.size());
}
// Store the current rows and others.
@ -277,9 +282,7 @@ public class CardPluginImpl implements CardPlugin {
if (creatures.isEmpty() && lands.isEmpty() && others.isEmpty()) {
break;
}
//FIXME: -1 is too slow. why not binary search?
cardWidth -= 3;
cardWidth -= CARD_WIDTH_AUTO_FIT_INCREMENT;
}
// Get size of all the rows.
@ -297,7 +300,7 @@ public class CardPluginImpl implements CardPlugin {
maxRowWidth = Math.max(maxRowWidth, x);
}
// Position all card panels.
// Position all card panels
y = GUTTER_Y;
for (Row row : rows) {
int rowBottom = 0;
@ -312,21 +315,21 @@ public class CardPluginImpl implements CardPlugin {
}
}
for (int panelIndex = 0, panelCount = stack.size(); panelIndex < panelCount; panelIndex++) {
MagePermanent panel = stack.get(panelIndex);
MagePermanent panelPerm = stack.get(panelIndex); // it's original card panel, but you must change top layer
int stackPosition = panelCount - panelIndex - 1;
if (jPanel != null) {
jPanel.setComponentZOrder(panel, panelIndex);
if (cardsPanel != null) {
cardsPanel.setComponentZOrder(panelPerm.getTopPanelRef(), panelIndex);
}
int panelX = x + (stackPosition * stackSpacingX);
int panelY = y + (stackPosition * stackSpacingY);
try {
// may cause:
// java.lang.IllegalArgumentException: illegal component position 26 should be less then 26
battlefieldPanel.moveToFront(panel);
battlefieldPanel.moveToFront(panelPerm.getTopPanelRef());
} catch (Exception e) {
e.printStackTrace();
}
panel.setCardBounds(panelX, panelY, cardWidth, cardHeight);
panelPerm.getTopPanelRef().setCardBounds(panelX, panelY, cardWidth, cardHeight);
}
rowBottom = Math.max(rowBottom, y + stack.getHeight());
x += stack.getWidth();
@ -337,11 +340,14 @@ public class CardPluginImpl implements CardPlugin {
// we need this only for defining card size
// attached permanents will be handled separately
for (Stack stack : rowAllAttached) {
for (MagePermanent panel : stack) {
panel.setCardBounds(0, 0, cardWidth, cardHeight);
for (MagePermanent panelPerm : stack) {
panelPerm.getTopPanelRef().setCardBounds(0, 0, cardWidth, cardHeight);
}
}
// scrollbars speed
scrollPane.getVerticalScrollBar().setUnitIncrement(GUISizeHelper.getCardsScrollbarUnitInc(cardHeight));
return y;
}
@ -351,7 +357,7 @@ public class CardPluginImpl implements CardPlugin {
private int wrap(Row sourceRow, List<Row> rows, int insertIndex) {
// 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();
for (int i = 0, n = sourceRow.size() - 1; i <= n; i++) {
@ -413,15 +419,17 @@ public class CardPluginImpl implements CardPlugin {
return height - cardSpacingY + GUTTER_Y * 2;
}
private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, Map<UUID, MagePermanent> permanents, MagePermanent permanentWithAttachments) {
private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, Map<UUID, MageCard> cards, MageCard cardWithAttachments) {
int maxCol = ++currentCol;
int attachments = 0;
for (UUID attachmentId : permanentWithAttachments.getOriginalPermanent().getAttachments()) {
MagePermanent attachedPermanent = permanents.get(attachmentId);
if (attachedPermanent != null) {
MagePermanent permWithAttachments = (MagePermanent) cardWithAttachments.getMainPanel();
for (UUID attachmentId : permWithAttachments.getOriginalPermanent().getAttachments()) {
MageCard attachedCard = cards.get(attachmentId);
if (attachedCard != null) {
attachments++;
if (attachedPermanent.getOriginalPermanent().getAttachments() != null && !attachedPermanent.getOriginalPermanent().getAttachments().isEmpty()) {
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol, permanents, attachedPermanent);
MagePermanent attachedPerm = (MagePermanent) attachedCard.getMainPanel();
if (attachedPerm.getOriginalPermanent().getAttachments() != null && !attachedPerm.getOriginalPermanent().getAttachments().isEmpty()) {
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol, cards, attachedCard);
if (attachmentLayoutInfos.getColumns() > maxCol) {
maxCol = attachmentLayoutInfos.getColumns();
attachments += attachmentLayoutInfos.getAttachments();
@ -435,16 +443,16 @@ public class CardPluginImpl implements CardPlugin {
private enum RowType {
land, creature, other, attached;
public boolean isType(MagePermanent card) {
public boolean isType(MagePermanent permanent) {
switch (this) {
case land:
return card.isLand();
return permanent.isLand();
case creature:
return card.isCreature();
return permanent.isCreature();
case other:
return !card.isLand() && !card.isCreature();
return !permanent.isLand() && !permanent.isCreature();
case attached:
return card.getOriginalPermanent().isAttachedToPermanent();
return permanent.getOriginalPermanent().isAttachedToPermanent();
default:
throw new RuntimeException("Unhandled type: " + this);
}
@ -459,24 +467,26 @@ public class CardPluginImpl implements CardPlugin {
super(16);
}
public Row(Map<UUID, MagePermanent> permanents, RowType type) {
public Row(Map<UUID, MageCard> cards, RowType type) {
this();
addAll(permanents, type);
addAll(cards, type);
}
private void addAll(Map<UUID, MagePermanent> permanents, RowType type) {
for (MagePermanent permanent : permanents.values()) {
if (!type.isType(permanent)) {
private void addAll(Map<UUID, MageCard> cards, RowType type) {
for (MageCard card : cards.values()) {
MagePermanent perm = (MagePermanent) card.getMainPanel();
if (!type.isType(perm)) {
continue;
}
// all attached permanents are grouped separately later
if (type != RowType.attached && RowType.attached.isType(permanent)) {
if (type != RowType.attached && RowType.attached.isType(perm)) {
continue;
}
Stack stack = new Stack();
stack.add(permanent);
if (permanent.getOriginalPermanent().getAttachments() != null) {
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, permanents, permanent);
stack.add(perm);
if (perm.getOriginalPermanent().getAttachments() != null) {
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, cards, card);
stack.setMaxAttachedCount(ali.getAttachments());
stack.setAttachmentColumns(ali.getColumns());
}
@ -666,7 +676,7 @@ public class CardPluginImpl implements CardPlugin {
}
@Override
public void onAddCard(MagePermanent card, int count) {
public void onAddCard(MageCard card, int count) {
if (card != null) {
Animation.showCard(card, count > 0 ? count : 1);
try {
@ -680,7 +690,7 @@ public class CardPluginImpl implements CardPlugin {
}
@Override
public void onRemoveCard(MagePermanent card, int count) {
public void onRemoveCard(MageCard card, int count) {
if (card != null) {
Animation.hideCard(card, count > 0 ? count : 1);
try {

View file

@ -1,9 +1,3 @@
/**
* AbstractBoundBean.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans;

View file

@ -1,9 +1,3 @@
/**
* BoundBean.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans;

View file

@ -1,8 +1,3 @@
/**
* EventListenerList.java
*
* Created on 08.04.2010
*/
package org.mage.plugins.card.dl.beans;
import com.google.common.base.Function;

View file

@ -1,14 +1,5 @@
/**
* PropertyChangeSupport.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans;
/**
* The class PropertyChangeSupport.
*

View file

@ -1,9 +1,3 @@
/**
* ListenableCollections.java
*
* Created on 25.04.2010
*/
package org.mage.plugins.card.dl.beans.collections;

View file

@ -1,9 +1,3 @@
/**
* AbstractProperties.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties;
import java.util.ArrayList;

View file

@ -1,9 +1,3 @@
/**
* AbstractProperty.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties;

View file

@ -1,9 +1,3 @@
/**
* CompoundProperties.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties;

View file

@ -1,9 +1,3 @@
/**
* Properties.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties;

View file

@ -1,9 +1,3 @@
/**
* Property.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties;

View file

@ -1,9 +1,3 @@
/**
* BoundProperties.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties.basic;

View file

@ -1,9 +1,3 @@
/**
* BasicProperty.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans.properties.basic;

View file

@ -1,9 +1,3 @@
/**
* BoundProperties.java
*
* Created on 24.08.2010
*/
package org.mage.plugins.card.dl.beans.properties.bound;

View file

@ -1,9 +1,3 @@
/**
* BasicProperty.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans.properties.bound;

View file

@ -1,17 +1,8 @@
/**
* PropertyChangeListListener.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans.properties.bound;
import org.mage.plugins.card.dl.beans.PropertyChangeSupport;
import org.mage.plugins.card.dl.beans.collections.ListenableCollections.ListListener;
/**
* The class PropertyChangeListListener.
*

View file

@ -1,9 +1,3 @@
/**
* PropertyChangeMapListener.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans.properties.bound;

View file

@ -1,9 +1,3 @@
/**
* PropertyChangeSetListener.java
*
* Created on 16.07.2010
*/
package org.mage.plugins.card.dl.beans.properties.bound;

View file

@ -1,19 +1,11 @@
/**
* AbstractLaternaBean.java
* <p>
* Created on 25.08.2010
*/
package org.mage.plugins.card.dl.lm;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.beans.AbstractBoundBean;
import org.mage.plugins.card.dl.beans.EventListenerList;
import org.mage.plugins.card.dl.beans.properties.Properties;
import org.mage.plugins.card.dl.beans.properties.bound.BoundProperties;
/**
* The class AbstractLaternaBean.
*

View file

@ -1,9 +1,3 @@
/**
* GathererSymbols.java
* <p>
* Created on 25.08.2010
*/
package org.mage.plugins.card.dl.sources;
import mage.client.constants.Constants;

View file

@ -1,8 +1,3 @@
/**
* GathererSymbols.java
*
* Created on 25.08.2010
*/
package org.mage.plugins.card.dl.sources;
import com.google.common.collect.AbstractIterator;

View file

@ -13,6 +13,7 @@ import net.java.truevfs.access.TFileOutputStream;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
import org.mage.plugins.card.utils.CardImageUtils;
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
import javax.imageio.ImageIO;
import java.awt.*;
@ -45,14 +46,18 @@ public final class ImageCache {
private static final SoftValuesLoadingCache<String, BufferedImage> IMAGE_CACHE;
private static final SoftValuesLoadingCache<String, BufferedImage> FACE_IMAGE_CACHE;
private static final SoftValuesLoadingCache<String, BufferedImage> CARD_ICONS_CACHE;
/**
* Common pattern for keys. See ImageCache.getKey for structure info
*/
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)#(.*)");
private static final Pattern CARD_ICON_KEY_PATTERN = Pattern.compile("(.*)#(.*)");
static {
// softValues() = Specifies that each value (not key) stored in the map should be wrapped in a SoftReference (by default, strong references are used). Softly-referenced objects will be garbage-collected in a globally least-recently-used manner, in response to memory demand.
// softValues() = Specifies that each value (not key) stored in the map should be wrapped in a SoftReference
// (by default, strong references are used). Softly-referenced objects will be garbage-collected in a
// globally least-recently-used manner, in response to memory demand.
IMAGE_CACHE = SoftValuesLoadingCache.from(new Function<String, BufferedImage>() {
@Override
public BufferedImage apply(String key) {
@ -219,10 +224,33 @@ public final class ImageCache {
}
}
});
CARD_ICONS_CACHE = SoftValuesLoadingCache.from(key -> {
try {
Matcher m = CARD_ICON_KEY_PATTERN.matcher(key);
if (m.matches()) {
int cardSize = Integer.parseInt(m.group(1));
String resourceName = m.group(2);
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize);
return image;
} else {
throw new RuntimeException("Wrong card icons image key format: " + key);
}
} catch (Exception ex) {
if (ex instanceof ComputationException) {
throw (ComputationException) ex;
} else {
throw new ComputationException(ex);
}
}
});
}
public static void clearCache() {
IMAGE_CACHE.invalidateAll();
FACE_IMAGE_CACHE.invalidateAll();
CARD_ICONS_CACHE.invalidateAll();
}
public static String getFilePath(CardView card, int width) {
@ -335,7 +363,7 @@ public final class ImageCache {
BufferedImage cornerImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
// corner
float ROUNDED_CORNER_SIZE = 0.11f; // see CardPanelComponentImpl
float ROUNDED_CORNER_SIZE = 0.11f; // see CardPanelRenderModeImage
int cornerSizeBorder = Math.max(4, Math.round(image.getWidth() * ROUNDED_CORNER_SIZE));
// corner mask
@ -394,13 +422,14 @@ public final class ImageCache {
return getImage(getKey(card, card.getName(), ""));
}
// public static BufferedImage getImageFaceOriginal(CardView card) {
// return getFaceImage(getFaceKey(card, card.getName(), card.getExpansionSetCode()));
// }
public static BufferedImage getImageOriginalAlternateName(CardView card) {
return getImage(getKey(card, card.getAlternateName(), ""));
}
public static BufferedImage getCardIconImage(String resourceName, int iconSize) {
return getCardIconImage(getCardIconKey(resourceName, iconSize));
}
/**
* Returns the Image corresponding to the key
*/
@ -432,6 +461,18 @@ public final class ImageCache {
}
}
private static BufferedImage getCardIconImage(String key) {
try {
return CARD_ICONS_CACHE.getOrNull(key);
} catch (ComputationException ex) {
if (ex.getCause() instanceof NullPointerException) {
return null;
}
LOGGER.error(ex, ex);
return null;
}
}
/**
* Returns the Image corresponding to the key only if it already exists in
* the cache.
@ -461,13 +502,9 @@ public final class ImageCache {
return name + '#' + set + "####";
}
// /**
// * Returns the map key for the flip image of a card, without any suffixes for the image size.
// */
// private static String getKeyAlternateName(CardView card, String alternateName) {
// return alternateName + "#" + card.getExpansionSetCode() + "#" +card.getType()+ "#" + card.getCardNumber() + "#"
// + (card.getTokenSetCode() == null ? "":card.getTokenSetCode());
// }
private static String getCardIconKey(String resourceName, int size) {
return size + "#" + resourceName;
}
/**
* Load image from file

View file

@ -1,50 +1,83 @@
package org.mage.plugins.card.utils;
import java.awt.*;
import java.awt.image.BufferedImage;
public interface ImageManager {
Image getAppImage();
Image getAppSmallImage();
Image getAppFlashedImage();
Image getSicknessImage();
Image getDayImage();
Image getNightImage();
Image getTokenIconImage();
Image getTriggeredAbilityImage();
Image getActivatedAbilityImage();
Image getLookedAtImage();
Image getRevealedImage();
Image getExileImage();
Image getCopyInformIconImage();
Image getCounterImageViolet();
Image getCounterImageRed();
Image getCounterImageGreen();
Image getCounterImageGrey();
Image getDlgAcceptButtonImage();
Image getDlgActiveAcceptButtonImage();
Image getDlgCancelButtonImage();
Image getDlgActiveCancelButtonImage();
Image getDlgPrevButtonImage();
Image getDlgActivePrevButtonImage();
Image getDlgNextButtonImage();
Image getDlgActiveNextButtonImage();
Image getSwitchHandsButtonImage();
Image getStopWatchButtonImage();
Image getConcedeButtonImage();
Image getCancelSkipButtonImage();
Image getSkipNextTurnButtonImage();
Image getSkipEndTurnButtonImage();
Image getSkipMainButtonImage();
Image getSkipStackButtonImage();
Image getSkipEndStepBeforeYourTurnButtonImage();
Image getSkipYourNextTurnButtonImage();
Image getToggleRecordMacroButtonImage();
BufferedImage getCardIcon(String resourceName, int size);
Image getPhaseImage(String phase);
}

View file

@ -1,36 +1,34 @@
package org.mage.plugins.card.utils.impl;
import java.awt.Color;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.WritableRaster;
import mage.client.dialog.PreferencesDialog;
import mage.client.util.gui.BufferedImageBuilder;
import org.apache.log4j.Logger;
import org.mage.card.arcane.SvgUtils;
import org.mage.plugins.card.utils.ImageManager;
import org.mage.plugins.card.utils.Transparency;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.*;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.imageio.ImageIO;
import mage.client.dialog.PreferencesDialog;
import mage.client.util.gui.BufferedImageBuilder;
import org.mage.plugins.card.utils.ImageManager;
import org.mage.plugins.card.utils.Transparency;
public enum ImageManagerImpl implements ImageManager {
instance;
private static final Logger logger = Logger.getLogger(ImageManagerImpl.class);
ImageManagerImpl() {
init();
}
public void init() {
String[] phases = {"Untap", "Upkeep", "Draw", "Main1",
"Combat_Start", "Combat_Attack", "Combat_Block", "Combat_Damage", "Combat_End",
"Main2", "Cleanup", "Next_Turn"};
"Combat_Start", "Combat_Attack", "Combat_Block", "Combat_Damage", "Combat_End",
"Main2", "Cleanup", "Next_Turn"};
phasesImages = new HashMap<>();
for (String name : phases) {
Image image = getImageFromResource(
@ -224,6 +222,7 @@ public enum ImageManagerImpl implements ImageManager {
return imageDlgAcceptButton;
}
@Override
public Image getDlgActiveAcceptButtonImage() {
if (imageDlgActiveAcceptButton == null) {
@ -363,6 +362,22 @@ public enum ImageManagerImpl implements ImageManager {
return imageToggleRecordMacroButton;
}
@Override
public BufferedImage getCardIcon(String resourceName, int size) {
// icon must be same, but color can be changed by themes
InputStream data = ImageManager.class.getResourceAsStream(PreferencesDialog.getCurrentTheme().getCardIconsResourcePath(resourceName));
try {
// no need to resize svg (lib already do it on load)
return SvgUtils.loadSVG(data, "card icon = " + resourceName,
PreferencesDialog.getCurrentTheme().getCardIconsCssFile(),
PreferencesDialog.getCurrentTheme().getCardIconsCssSettings(),
size, size, false);
} catch (Exception e) {
logger.error("Can't load card icon: " + resourceName + " , reason: " + e.getMessage(), e);
return null;
}
}
protected static Image getImageFromResourceTransparent(String path, Color mask, Rectangle rec) {
BufferedImage image;
Image imageCardTransparent;