* GUI: added card icon for commander on battlefield;

Card icons: added support of custom card icon colors;
This commit is contained in:
Oleg Agafonov 2021-07-23 19:51:45 +04:00
parent 06ae494c5b
commit 4d1985476f
17 changed files with 327 additions and 116 deletions

View file

@ -1,5 +1,6 @@
package mage.client.cards;
import mage.abilities.icon.CardIconColor;
import mage.abilities.icon.CardIconOrder;
import mage.abilities.icon.CardIconPosition;
import mage.abilities.icon.CardIconRenderSettings;
@ -49,6 +50,7 @@ public class CardArea extends JPanel implements CardEventProducer {
private int customXOffsetBetweenCardsOrColumns = 0;
private CardIconPosition customCardIconPosition = null;
private CardIconOrder customCardIconOrder = null;
private CardIconColor customCardIconColor = null;
private int customCardIconsMaxVisibleCount = 0;
/**
@ -188,6 +190,7 @@ public class CardArea extends JPanel implements CardEventProducer {
.withDebugMode(true)
.withCustomPosition(customCardIconPosition)
.withCustomOrder(customCardIconOrder)
.withCustomColor(customCardIconColor)
.withCustomMaxVisibleCount(customCardIconsMaxVisibleCount)
.withCustomIconSizePercent(30);
MageCard cardPanel = Plugins.instance.getMageCard(card, bigCard, customIconsRender, cardDimension, gameId, true, true,
@ -294,6 +297,10 @@ public class CardArea extends JPanel implements CardEventProducer {
this.customCardIconOrder = panelOrder;
}
public void setCustomCardIconsPanelColor(CardIconColor cardIconColor) {
this.customCardIconColor = cardIconColor;
}
public void setCustomCardIconsMaxVisibleCount(int maxVisibleCount) {
this.customCardIconsMaxVisibleCount = maxVisibleCount;
}

View file

@ -28,8 +28,9 @@ public class CardIconsPanel extends JPanel {
private static final CardIconPosition DEFAULT_POSITION = CardIconPosition.LEFT;
private static final CardIconOrder DEFAULT_ORDER = CardIconOrder.START;
private static final CardIconColor DEFAULT_COLOR = CardIconColor.DEFAULT; // from theme
private static final int DEFAULT_MAX_VISIBLE_COUNT = 5;
private static final int DEFAULT_ICON_SIZE_PERCENT = 30;
private static final int DEFAULT_ICON_SIZE_PERCENT = 30; // TODO: add support of big icons (current: wrong align, wrong size)
private static final int MINIMUM_ICON_SIZE = 32; // TODO: not working?
private static final int KEEP_ICON_IN_CARD_INSIDE_PERCENT = 70; // example: 66% - 2/3 keep inside and 1/3 keep outside
@ -37,6 +38,7 @@ public class CardIconsPanel extends JPanel {
private final CardIconPosition position;
private final CardIconOrder order;
private final CardIconColor color;
private final int iconSizePercent; // icons size, related to card's width
private final List<CardIcon> icons;
private final int cellsMaxCount; // split card side to cells, can be 1, 3, 5, 7 (x left + 1x center + x right)
@ -57,18 +59,20 @@ public class CardIconsPanel extends JPanel {
public CardIconsPanel(CardIconRenderSettings render) {
this(render.getCustomPosition() != null ? render.getCustomPosition() : DEFAULT_POSITION,
render.getCustomOrder() != null ? render.getCustomOrder() : DEFAULT_ORDER,
render.getCustomColor() != null ? render.getCustomColor() : DEFAULT_COLOR,
render.getCustomMaxVisibleCount() > 0 ? render.getCustomMaxVisibleCount() : DEFAULT_MAX_VISIBLE_COUNT,
render.getCustomIconSizePercent() > 0 ? render.getCustomIconSizePercent() : DEFAULT_ICON_SIZE_PERCENT
);
}
public CardIconsPanel(CardIconPosition position, CardIconOrder order, int cellsVisibleCount, int iconSizePercent) {
this(position, order, cellsVisibleCount, iconSizePercent, new ArrayList<>(), new Rectangle(100, 100));
public CardIconsPanel(CardIconPosition position, CardIconOrder order, CardIconColor color, int cellsVisibleCount, int iconSizePercent) {
this(position, order, color, cellsVisibleCount, iconSizePercent, new ArrayList<>(), new Rectangle(100, 100));
}
public CardIconsPanel(CardIconPosition position, CardIconOrder order, int cellsVisibleCount, int iconSizePercent, List<CardIcon> icons, Rectangle startingCardSize) {
public CardIconsPanel(CardIconPosition position, CardIconOrder order, CardIconColor color, int cellsVisibleCount, int iconSizePercent, List<CardIcon> icons, Rectangle startingCardSize) {
super(null);
this.position = position != null ? position : DEFAULT_POSITION;
this.position = (position != null ? position : DEFAULT_POSITION);
this.color = (color != null ? color : DEFAULT_COLOR);
this.iconSizePercent = iconSizePercent;
this.icons = icons;
@ -289,7 +293,7 @@ public class CardIconsPanel extends JPanel {
//BufferedImage iconImage = ImageManagerImpl.instance.getCardIcon(icon.getIconType().getResourceName(), this.halfSize * 2);
// cached call
BufferedImage iconImageCached = ImageCache.getCardIconImage(icon.getIconType().getResourceName(), this.halfSize * 2);
BufferedImage iconImageCached = ImageCache.getCardIconImage(icon.getIconType().getResourceName(), this.halfSize * 2, color.toString());
if (iconImageCached != null && this.font != null) {
BufferedImage iconImageWithText = ImageManagerImpl.deepCopy(iconImageCached); // must copy cached value before modify
@ -299,7 +303,7 @@ public class CardIconsPanel extends JPanel {
label.setToolTipText("<html>" + ManaSymbols.replaceSymbolsWithHTML(icon.getHint(), ManaSymbols.Type.CARD_ICON_HINT));
if (!icon.getText().isEmpty()) {
Graphics2D g2d = iconImageWithText.createGraphics();
g2d.setColor(PreferencesDialog.getCurrentTheme().getCardIconsTextColor());
g2d.setColor(PreferencesDialog.getCurrentTheme().getCardIconsTextColor(this.color));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Rectangle rect = CardRendererUtils.reduceRect(new Rectangle(0, 0, iconImageWithText.getWidth(), iconImageWithText.getHeight()), 0.8f);
CardRendererUtils.drawCenteredText(g2d, icon.getText(), rect, this.font, true);

View file

@ -1,5 +1,6 @@
package mage.client.cards;
import mage.abilities.icon.CardIconColor;
import mage.abilities.icon.CardIconOrder;
import mage.abilities.icon.CardIconPosition;
import mage.abilities.icon.CardIconRenderSettings;
@ -15,6 +16,7 @@ public class CardIconsPanelFactory {
return new CardIconsPanel(
CardIconPosition.LEFT,
CardIconOrder.CENTER,
CardIconColor.DEFAULT,
5,
30
);
@ -24,11 +26,23 @@ public class CardIconsPanelFactory {
return new CardIconsPanel(
CardIconPosition.CORNER_BOTTOM_LEFT,
CardIconOrder.CENTER,
CardIconColor.DEFAULT,
1,
30
);
}
public static CardIconsPanel createCommanderPanel() {
// must be x2 bigger than normal icons
return new CardIconsPanel(
CardIconPosition.TOP,
CardIconOrder.CENTER,
CardIconColor.RED,
1,
30 * 2 // TODO: big size doesn't work due icons same size limits, see CardIconsPanel
);
}
public static CardIconsPanel createDebugPanel(CardIconRenderSettings render) {
return new CardIconsPanel(render);
}

View file

@ -39,6 +39,10 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="comboTheme" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="labelCardColor" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="comboCardColor" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="labelSize" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sliderSize" min="-2" pref="100" max="-2" attributes="0"/>
@ -63,6 +67,10 @@
<Component id="labelSize" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="comboTheme" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelTheme" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="3" groupAlignment="3" attributes="0">
<Component id="comboCardColor" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelCardColor" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="sliderSize" min="-2" max="-2" attributes="0"/>
<Component id="checkBoxGenerateManyCards" min="-2" max="-2" attributes="0"/>
@ -70,7 +78,7 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="panelCardIcons" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cardsPanel" pref="401" max="32767" attributes="0"/>
<Component id="cardsPanel" pref="405" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="buttonCancel" min="-2" pref="30" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -157,7 +165,7 @@
<Component id="labelCardIconsAdditionalAmount" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spinnerCardIconsAdditionalAmount" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace pref="188" max="32767" attributes="0"/>
<EmptySpace pref="305" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -277,5 +285,26 @@
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="labelCardColor">
<Properties>
<Property name="text" type="java.lang.String" value="Card color:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="comboCardColor">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="1">
<StringItem index="0" value="loading..."/>
</StringArray>
</Property>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="comboCardColorItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View file

@ -45,6 +45,7 @@ import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.*;
import mage.abilities.icon.CardIconColor;
/**
* App GUI: debug only, testing card renders and manipulations
@ -73,6 +74,10 @@ public class TestCardRenderDialog extends MageDialog {
this.comboTheme.setModel(new DefaultComboBoxModel(ThemeType.values()));
this.comboTheme.setSelectedItem(PreferencesDialog.getCurrentTheme());
// init card icon colors list
this.comboCardColor.setModel(new DefaultComboBoxModel(CardIconColor.values()));
this.comboCardColor.setSelectedItem(CardIconColor.DEFAULT);
// debug logs to show current component
/*
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@ -206,6 +211,7 @@ public class TestCardRenderDialog extends MageDialog {
cardsPanel.setCustomXOffsetBetweenCardsOrColumns(10);
cardsPanel.setCustomCardIconsPanelPosition(CardIconPosition.fromString((String) comboCardIconsPosition.getSelectedItem()));
cardsPanel.setCustomCardIconsPanelOrder(CardIconOrder.fromString((String) comboCardIconsOrder.getSelectedItem()));
cardsPanel.setCustomCardIconsPanelColor((CardIconColor) comboCardColor.getSelectedItem());
cardsPanel.setCustomCardIconsMaxVisibleCount((Integer) spinnerCardIconsMaxVisible.getValue());
int needAdditionalIcons = Math.min(99, Math.max(0, (Integer) spinnerCardIconsAdditionalAmount.getValue()));
@ -400,6 +406,8 @@ public class TestCardRenderDialog extends MageDialog {
comboCardIconsOrder = new javax.swing.JComboBox<>();
labelTheme = new javax.swing.JLabel();
comboTheme = new javax.swing.JComboBox<>();
labelCardColor = new javax.swing.JLabel();
comboCardColor = new javax.swing.JComboBox<>();
buttonCancel.setText("Close");
buttonCancel.addActionListener(new java.awt.event.ActionListener() {
@ -417,7 +425,7 @@ public class TestCardRenderDialog extends MageDialog {
labelRenderMode.setText("Render mode:");
comboRenderMode.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"MTGO", "Image"}));
comboRenderMode.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "MTGO", "Image" }));
comboRenderMode.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
comboRenderModeItemStateChanged(evt);
@ -441,7 +449,7 @@ public class TestCardRenderDialog extends MageDialog {
labelCardIconsPosition.setText("Card icons position:");
comboCardIconsPosition.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"TOP", "LEFT", "RIGHT", "BOTTOM", "CORNER_TOP_LEFT", "CORNER_TOP_RIGHT", "CORNER_BOTTOM_LEFT", "CORNER_BOTTOM_RIGHT"}));
comboCardIconsPosition.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "TOP", "LEFT", "RIGHT", "BOTTOM", "CORNER_TOP_LEFT", "CORNER_TOP_RIGHT", "CORNER_BOTTOM_LEFT", "CORNER_BOTTOM_RIGHT" }));
comboCardIconsPosition.setSelectedIndex(1);
comboCardIconsPosition.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -469,7 +477,7 @@ public class TestCardRenderDialog extends MageDialog {
labelCardIconsOrder.setText("Order:");
comboCardIconsOrder.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"START", "CENTER", "END"}));
comboCardIconsOrder.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "START", "CENTER", "END" }));
comboCardIconsOrder.setSelectedIndex(2);
comboCardIconsOrder.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -497,7 +505,7 @@ public class TestCardRenderDialog extends MageDialog {
.addComponent(labelCardIconsAdditionalAmount)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerCardIconsAdditionalAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(188, Short.MAX_VALUE))
.addContainerGap(305, Short.MAX_VALUE))
);
panelCardIconsLayout.setVerticalGroup(
panelCardIconsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -514,7 +522,7 @@ public class TestCardRenderDialog extends MageDialog {
labelTheme.setText("Theme:");
comboTheme.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"loading..."}));
comboTheme.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "loading..." }));
comboTheme.setToolTipText("WARNING, selected theme will be applied to full app, not render dialog only");
comboTheme.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -522,6 +530,16 @@ public class TestCardRenderDialog extends MageDialog {
}
});
labelCardColor.setText("Card color:");
comboCardColor.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "loading..." }));
comboCardColor.setToolTipText("");
comboCardColor.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
comboCardColorItemStateChanged(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
@ -545,6 +563,10 @@ public class TestCardRenderDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(comboTheme, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelCardColor)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(comboCardColor, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelSize)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sliderSize, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -564,13 +586,16 @@ public class TestCardRenderDialog extends MageDialog {
.addComponent(comboRenderMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelSize)
.addComponent(comboTheme, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelTheme))
.addComponent(labelTheme)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(comboCardColor, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelCardColor)))
.addComponent(sliderSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(checkBoxGenerateManyCards))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(panelCardIcons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cardsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
.addComponent(cardsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(buttonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
@ -630,15 +655,24 @@ public class TestCardRenderDialog extends MageDialog {
}
}//GEN-LAST:event_comboThemeItemStateChanged
private void comboCardColorItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_comboCardColorItemStateChanged
// card icon colors list are loading on show dialog, so must ignore change event on startup
if (this.isVisible()) {
reloadCards();
}
}//GEN-LAST:event_comboCardColorItemStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonReloadCards;
private mage.client.cards.CardArea cardsPanel;
private javax.swing.JCheckBox checkBoxGenerateManyCards;
private javax.swing.JComboBox<String> comboCardColor;
private javax.swing.JComboBox<String> comboCardIconsOrder;
private javax.swing.JComboBox<String> comboCardIconsPosition;
private javax.swing.JComboBox<String> comboRenderMode;
private javax.swing.JComboBox<String> comboTheme;
private javax.swing.JLabel labelCardColor;
private javax.swing.JLabel labelCardIconsAdditionalAmount;
private javax.swing.JLabel labelCardIconsMaxVisible;
private javax.swing.JLabel labelCardIconsOrder;

View file

@ -1,6 +1,7 @@
package mage.client.themes;
import mage.abilities.hint.HintUtils;
import mage.abilities.icon.CardIconColor;
import org.mage.card.arcane.SvgUtils;
import java.awt.*;
@ -304,29 +305,29 @@ public enum ThemeType {
}
}
public Color getCardIconsFillColor() {
return this.cardIconsFillColor;
public Color getCardIconsFillColor(CardIconColor cardIconColor) {
return cardIconColor.getFillColor() != null ? cardIconColor.getFillColor() : this.cardIconsFillColor;
}
public Color getCardIconsStrokeColor() {
return cardIconsStrokeColor;
public Color getCardIconsStrokeColor(CardIconColor cardIconColor) {
return cardIconColor.getStrokeColor() != null ? cardIconColor.getStrokeColor() : this.cardIconsStrokeColor;
}
public Color getCardIconsTextColor() {
return cardIconsTextColor;
public Color getCardIconsTextColor(CardIconColor cardIconColor) {
return cardIconColor.getTextColor() != null ? cardIconColor.getTextColor() : this.cardIconsTextColor;
}
public String getCardIconsResourcePath(String resourceName) {
return "/card/icons/" + resourceName;
}
public String getCardIconsCssFile() {
return "card-icons-svg-settings.css";
public String getCardIconsCssFile(CardIconColor cardIconColor) {
return String.format("card-icons-svg-settings-%s.css", cardIconColor.toString());
}
public String getCardIconsCssSettings() {
String fillColorVal = HintUtils.colorToHtml(this.getCardIconsFillColor());
String strokeColorVal = HintUtils.colorToHtml(this.getCardIconsStrokeColor());
public String getCardIconsCssSettings(CardIconColor cardIconColor) {
String fillColorVal = HintUtils.colorToHtml(this.getCardIconsFillColor(cardIconColor));
String strokeColorVal = HintUtils.colorToHtml(this.getCardIconsStrokeColor(cardIconColor));
return String.format(""
+ "fill: %s;"
@ -343,6 +344,8 @@ public enum ThemeType {
*/
public void reload() {
// reload card icons css file (run it all the time, even on svg unsupport mode)
SvgUtils.prepareCss(this.getCardIconsCssFile(), this.getCardIconsCssSettings(), true);
for (CardIconColor cardIconColor : CardIconColor.values()) {
SvgUtils.prepareCss(this.getCardIconsCssFile(cardIconColor), this.getCardIconsCssSettings(cardIconColor), true);
}
}
}

View file

@ -61,6 +61,7 @@ public class MageLayer extends MageCard {
CardIconsPanel iconsDebugPanel;
CardIconsPanel iconsAbilitiesPanel;
CardIconsPanel iconsPlayablePanel;
CardIconsPanel iconsCommanderPanel;
public MageLayer(MageCard mainPanel, CardIconRenderSettings iconsRender) {
this.mainPanel = mainPanel;
@ -140,6 +141,7 @@ public class MageLayer extends MageCard {
this.iconsDebugPanel = null;
this.iconsAbilitiesPanel = null;
this.iconsPlayablePanel = null;
this.iconsCommanderPanel = null;
if (this.iconsRender.isDebugMode()) {
// DEBUG MODE -- only one debug panel
@ -148,9 +150,15 @@ public class MageLayer extends MageCard {
} else {
// NORMAL mode -- multiple panels
if (PreferencesDialog.getRenderIconsForAbilities()) {
// abilities
this.iconsAbilitiesPanel = CardIconsPanelFactory.createAbilitiesPanel();
this.iconsPanels.add(this.iconsAbilitiesPanel);
// commander
this.iconsCommanderPanel = CardIconsPanelFactory.createCommanderPanel();
this.iconsPanels.add(this.iconsCommanderPanel);
}
// playable amount
if (PreferencesDialog.getRenderIconsForPlayable()) {
this.iconsPlayablePanel = CardIconsPanelFactory.createPlayablePanel();
this.iconsPanels.add(this.iconsPlayablePanel);
@ -311,16 +319,25 @@ public class MageLayer extends MageCard {
// create panels
allIcons.forEach(cardIcon -> {
CardIconCategory category = cardIcon.getIconType().getCategory();
// debug must take all icons
// debug panel must take all icons (position depens on render settings)
if (iconsDebugPanel != null) {
newIcons.get(iconsDebugPanel).add(cardIcon);
}
// playable panel (bottom left corner)
if (iconsPlayablePanel != null && category == CardIconCategory.PLAYABLE_COUNT) {
newIcons.get(iconsPlayablePanel).add(cardIcon);
}
// abilities panel (left side)
if (iconsAbilitiesPanel != null && category == CardIconCategory.ABILITY) {
newIcons.get(iconsAbilitiesPanel).add(cardIcon);
}
// commander panel (top center)
if (iconsCommanderPanel != null && category == CardIconCategory.COMMANDER) {
newIcons.get(iconsCommanderPanel).add(cardIcon);
}
});
this.iconsPanels.forEach(panel -> panel.updateIcons(newIcons.get(panel)));
}

View file

@ -1,5 +1,6 @@
package org.mage.card.arcane;
import mage.abilities.icon.CardIconColor;
import mage.abilities.icon.abilities.FlyingAbilityIcon;
import mage.utils.StreamUtils;
import org.apache.batik.anim.dom.SVGDOMImplementation;
@ -216,7 +217,7 @@ public class SvgUtils {
public static boolean checkSvgSupport() {
// usa sample icon for svg support testing
// direct call, no needs in cache
BufferedImage sampleImage = ImageManagerImpl.instance.getCardIcon(FlyingAbilityIcon.instance.getIconType().getResourceName(), 32);
BufferedImage sampleImage = ImageManagerImpl.instance.getCardIcon(FlyingAbilityIcon.instance.getIconType().getResourceName(), 32, CardIconColor.DEFAULT);
haveSvgSupport = (sampleImage != null && sampleImage.getWidth() > 0);
if (!haveSvgSupport) {
logger.warn("WARNING, your system doesn't support svg images, so card icons will be disabled. Please, make a bug report in the github.");

View file

@ -2,6 +2,7 @@ package org.mage.plugins.card.images;
import com.google.common.base.Function;
import com.google.common.collect.ComputationException;
import mage.abilities.icon.CardIconColor;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
import mage.client.util.SoftValuesLoadingCache;
@ -52,7 +53,7 @@ public final class ImageCache {
* 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("(.*)#(.*)");
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
@ -232,7 +233,8 @@ public final class ImageCache {
if (m.matches()) {
int cardSize = Integer.parseInt(m.group(1));
String resourceName = m.group(2);
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize);
CardIconColor cardIconColor = CardIconColor.valueOf(m.group(3));
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize, cardIconColor);
return image;
} else {
throw new RuntimeException("Wrong card icons image key format: " + key);
@ -426,8 +428,8 @@ public final class ImageCache {
return getImage(getKey(card, card.getAlternateName(), ""));
}
public static BufferedImage getCardIconImage(String resourceName, int iconSize) {
return getCardIconImage(getCardIconKey(resourceName, iconSize));
public static BufferedImage getCardIconImage(String resourceName, int iconSize, String cardColorName) {
return getCardIconImage(getCardIconKey(resourceName, iconSize, cardColorName));
}
/**
@ -502,8 +504,8 @@ public final class ImageCache {
return name + '#' + set + "####";
}
private static String getCardIconKey(String resourceName, int size) {
return size + "#" + resourceName;
private static String getCardIconKey(String resourceName, int size, String cardColorName) {
return size + "#" + resourceName + "#" + cardColorName;
}
/**

View file

@ -1,5 +1,7 @@
package org.mage.plugins.card.utils;
import mage.abilities.icon.CardIconColor;
import java.awt.*;
import java.awt.image.BufferedImage;
@ -77,7 +79,7 @@ public interface ImageManager {
Image getToggleRecordMacroButtonImage();
BufferedImage getCardIcon(String resourceName, int size);
BufferedImage getCardIcon(String resourceName, int size, CardIconColor cardIconColor);
Image getPhaseImage(String phase);
}

View file

@ -1,5 +1,6 @@
package org.mage.plugins.card.utils.impl;
import mage.abilities.icon.CardIconColor;
import mage.client.dialog.PreferencesDialog;
import mage.client.util.gui.BufferedImageBuilder;
import org.apache.log4j.Logger;
@ -363,14 +364,14 @@ public enum ImageManagerImpl implements ImageManager {
}
@Override
public BufferedImage getCardIcon(String resourceName, int size) {
public BufferedImage getCardIcon(String resourceName, int size, CardIconColor cardIconColor) {
// 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(),
return SvgUtils.loadSVG(data, "card icon = " + resourceName + "; " + cardIconColor.toString(),
PreferencesDialog.getCurrentTheme().getCardIconsCssFile(cardIconColor),
PreferencesDialog.getCurrentTheme().getCardIconsCssSettings(cardIconColor),
size, size, false);
} catch (Exception e) {
logger.error("Can't load card icon: " + resourceName + " , reason: " + e.getMessage(), e);

View file

@ -11,6 +11,7 @@ import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.other.CommanderCardIcon;
import mage.abilities.icon.other.FaceDownCardIcon;
import mage.abilities.icon.other.VariableCostCardIcon;
import mage.abilities.keyword.AftermathAbility;
@ -31,6 +32,7 @@ import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.Token;
import mage.game.stack.Spell;
import mage.game.stack.StackAbility;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import mage.util.CardUtil;
@ -426,6 +428,11 @@ public class CardView extends SimpleCardView {
if (permanent.isFaceDown(game)) {
this.cardIcons.add(FaceDownCardIcon.instance);
}
// commander
Player owner = game.getPlayer(game.getOwnerId(permanent));
if (owner != null && game.isCommanderObject(owner, permanent)) {
this.cardIcons.add(CommanderCardIcon.instance);
}
} else {
if (card.isCopy()) {
this.mageObjectType = MageObjectType.COPY_CARD;

View file

@ -7,7 +7,8 @@ package mage.abilities.icon;
*/
public enum CardIconCategory {
ABILITY, // example: flying
PLAYABLE_COUNT,
SYSTEM
ABILITY, // example: flying (on left side)
PLAYABLE_COUNT, // on bottom left corner
SYSTEM, // example: too many icons combines in the one icon (on left side)
COMMANDER // example: commander (on top center icon)
}

View file

@ -0,0 +1,46 @@
package mage.abilities.icon;
import java.awt.*;
/**
* For GUI: custom color modification for card icons (e.g. for special card icons like commander)
* <p>
* Card icons uses svg, so all color settings must be predefined on app's loading
* <p>
* TODO: current version uses panels (initCardIconsPanels) to define custom colors,
* but it can be removed to single/dynamic icon in the future (example: r/g/b dynamic semaphore icon)
*
* @author JayDi85
*/
public enum CardIconColor {
DEFAULT(),
YELLOW(new Color(231, 203, 18), new Color(76, 76, 76), new Color(0, 0, 0)),
RED(new Color(255, 31, 75), new Color(76, 76, 76), new Color(229, 228, 228));
private final Color fillColor;
private final Color strokeColor;
private final Color textColor;
CardIconColor() {
this(null, null, null);
}
CardIconColor(Color fillColor, Color strokeColor, Color textColor) {
this.fillColor = fillColor;
this.strokeColor = strokeColor;
this.textColor = textColor;
}
public Color getFillColor() {
return fillColor;
}
public Color getStrokeColor() {
return strokeColor;
}
public Color getTextColor() {
return textColor;
}
}

View file

@ -10,6 +10,7 @@ public class CardIconRenderSettings {
// custom settings for test render dialog
CardIconPosition customPosition = null;
CardIconOrder customOrder = null;
CardIconColor customColor = null;
int customMaxVisibleCount = 0;
int customIconSizePercent = 0;
boolean debugMode = false;
@ -27,6 +28,11 @@ public class CardIconRenderSettings {
return this;
}
public CardIconRenderSettings withCustomColor(CardIconColor customColor) {
this.customColor = customColor;
return this;
}
public CardIconRenderSettings withCustomMaxVisibleCount(int customMaxVisibleCount) {
this.customMaxVisibleCount = customMaxVisibleCount;
return this;
@ -50,6 +56,10 @@ public class CardIconRenderSettings {
return customPosition;
}
public CardIconColor getCustomColor() {
return customColor;
}
public int getCustomIconSizePercent() {
return customIconSizePercent;
}

View file

@ -34,6 +34,8 @@ public enum CardIconType {
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),
//
COMMANDER("prepared/crown.svg", CardIconCategory.COMMANDER, 100), // TODO: fix big size, see CardIconsPanel
//
SYSTEM_COMBINED("prepared/square-fill.svg", CardIconCategory.SYSTEM, 1000), // inner usage, must use last order
SYSTEM_DEBUG("prepared/link.svg", CardIconCategory.SYSTEM, 1000); // used for test render dialog

View file

@ -0,0 +1,31 @@
package mage.abilities.icon.other;
import mage.abilities.icon.CardIcon;
import mage.abilities.icon.CardIconType;
/**
* @author JayDi85
*/
public enum CommanderCardIcon implements CardIcon {
instance;
@Override
public CardIconType getIconType() {
return CardIconType.COMMANDER;
}
@Override
public String getText() {
return "";
}
@Override
public String getHint() {
return "Card is commander";
}
@Override
public CardIcon copy() {
return instance;
}
}