* UI: improved cards appearance:

* added colorized PT values (boosted is green, unboosted is red);
  * added toughness with damage calcs (damaged is red);
  * image render: now title and PT texts are readable/big in small cards;
  * mtgo render: improved image quality (less pixelated now);
  * mtgo render: improved PT font (bold now);
This commit is contained in:
Oleg Agafonov 2019-05-10 10:01:51 +04:00
parent 060766bb0a
commit 5c48803ef9
9 changed files with 268 additions and 89 deletions

View file

@ -107,9 +107,6 @@
</AuxValues>
</Component>
<Component class="javax.swing.JSlider" name="sliderSize">
<Properties>
<Property name="value" type="int" value="25"/>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="sliderSizeStateChanged"/>
</Events>

View file

@ -29,6 +29,8 @@ import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
@ -67,18 +69,25 @@ public class TestCardRenderDialog extends MageDialog {
this.removeDialog();
}
private PermanentView createCard(Game game, UUID controllerId, String code, String cardNumber, int damage) {
private PermanentView createCard(Game game, UUID controllerId, String code, String cardNumber, int power, int toughness, int damage) {
CardInfo cardInfo = CardRepository.instance.findCard(code, cardNumber);
ExpansionInfo setInfo = ExpansionRepository.instance.getSetByCode(code);
CardSetInfo testSet = new CardSetInfo(cardInfo.getName(), setInfo.getCode(), cardNumber, cardInfo.getRarity(),
new CardGraphicInfo(cardInfo.getFrameStyle(), cardInfo.usesVariousArt()));
Card card = CardImpl.createCard(cardInfo.getClassName(), testSet);
Set<Card> cardsList = new HashSet<>();
cardsList.add(card);
game.loadCards(cardsList, controllerId);
PermanentCard perm = new PermanentCard(card, controllerId, game);
if (damage > 0) {
perm.damage(damage, null, game);
}
if (damage > 0) perm.damage(damage, controllerId, game);
if (power > 0) perm.getPower().setValue(power);
if (toughness > 0) perm.getToughness().setValue(toughness);
perm.removeSummoningSickness();
if (perm.isTransformable()) {
perm.setTransformed(true);
}
PermanentView cardView = new PermanentView(perm, card, controllerId, game);
cardView.setInViewerOnly(true);
@ -97,11 +106,17 @@ public class TestCardRenderDialog extends MageDialog {
BigCard big = new BigCard();
CardsView view = new CardsView();
PermanentView card;
card = createCard(game, player.getId(), "RNA", "263", 0); // mountain
card = createCard(game, player.getId(), "RNA", "263", 0, 0, 0); // mountain
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "185", 0); // Judith, the Scourge Diva
card = createCard(game, player.getId(), "RNA", "185", 0, 0, 0); // Judith, the Scourge Diva
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "14", 1); // Knight of Sorrows
card = createCard(game, player.getId(), "RNA", "78", 125, 89, 0); // Noxious Groodion
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "14", 3, 5, 2); // Knight of Sorrows
view.put(card.getId(), card);
card = createCard(game, player.getId(), "DKA", "140", 5, 2, 2); // Huntmaster of the Fells, transforms
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "221", 0, 0, 0); // Bedeck // Bedazzle
view.put(card.getId(), card);
cardsPanel.setCustomCardSize(new Dimension(getCardWidth(), getCardHeight()));
@ -162,7 +177,6 @@ public class TestCardRenderDialog extends MageDialog {
}
});
sliderSize.setValue(25);
sliderSize.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
sliderSizeStateChanged(evt);

View file

@ -181,10 +181,14 @@ public final class GuiDisplayUtil {
public static TextLines getTextLinesfromCardView(CardView card) {
TextLines textLines = new TextLines();
// rules
textLines.setLines(new ArrayList<>(card.getRules()));
for (String rule : card.getRules()) {
textLines.setBasicTextLength(textLines.getBasicTextLength() + rule.length());
}
// counters
if (card.getMageObjectType().canHaveCounters()) {
ArrayList<CounterView> counters = new ArrayList<>();
if (card instanceof PermanentView) {
@ -212,10 +216,12 @@ public final class GuiDisplayUtil {
textLines.setBasicTextLength(textLines.getBasicTextLength() + 50);
}
}
// damage
if (card.getMageObjectType().isPermanent() && card instanceof PermanentView) {
int damage = ((PermanentView) card).getDamage();
if (damage > 0) {
textLines.getLines().add("<span color='red'><b>Damage dealt:</b> " + damage + "</span>");
textLines.getLines().add("<span color='red'><b>Damage dealt:</b> " + damage + "</span>"); // TODO
textLines.setBasicTextLength(textLines.getBasicTextLength() + 50);
}
}

View file

@ -1,5 +1,6 @@
package org.mage.card.arcane;
import mage.MageInt;
import mage.cards.action.ActionCallback;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
@ -49,11 +50,16 @@ public class CardPanelComponentImpl extends CardPanel {
private static final int CARD_MIN_SIZE_FOR_ICONS = 60;
private static final int CARD_MAX_SIZE_FOR_ICONS = 200;
// text min size for image render mode
private static final int CARD_TITLE_FONT_MIN_SIZE = 13;
private static final int CARD_PT_FONT_MIN_SIZE = 17;
public final ScaledImagePanel imagePanel;
private ImagePanel overlayPanel;
private JPanel iconPanel;
private JButton typeButton;
private JPanel ptPanel;
private JPanel counterPanel;
private JLabel loyaltyCounterLabel;
@ -67,7 +73,9 @@ public class CardPanelComponentImpl extends CardPanel {
private int lastCardWidth;
private final GlowText titleText;
private final GlowText ptText;
private final GlowText ptText1;
private final GlowText ptText2;
private final GlowText ptText3;
private final JLabel fullImageText;
private String fullImagePath = null;
@ -280,7 +288,7 @@ public class CardPanelComponentImpl extends CardPanel {
// Title Text
titleText = new GlowText();
setText(getGameCard());
setTitle(getGameCard());
// int fontSize = (int) cardHeight / 11;
// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
titleText.setForeground(Color.white);
@ -295,16 +303,19 @@ public class CardPanelComponentImpl extends CardPanel {
add(fullImageText);
// PT Text
ptText = new GlowText();
if (getGameCard().isCreature()) {
ptText.setText(getGameCard().getPower() + '/' + getGameCard().getToughness());
} else if (getGameCard().isPlanesWalker()) {
ptText.setText(getGameCard().getLoyalty());
}
// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
ptText.setForeground(Color.white);
ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
add(ptText);
ptPanel = new JPanel();
ptPanel.setOpaque(false);
ptPanel.setLayout(new BoxLayout(ptPanel, BoxLayout.X_AXIS));
ptPanel.add(new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(Integer.MAX_VALUE, 0)));
ptText1 = new GlowText();
ptText2 = new GlowText();
ptText3 = new GlowText();
updatePTTexts(getGameCard());
ptPanel.add(ptText1);
ptPanel.add(ptText2);
ptPanel.add(ptText3);
//
add(ptPanel);
// Sickness overlay
BufferedImage sickness = ImageManagerImpl.instance.getSicknessImage();
@ -349,7 +360,7 @@ public class CardPanelComponentImpl extends CardPanel {
this.setCounterPanel(null);
}
private void setText(CardView card) {
private void setTitle(CardView card) {
titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName());
}
@ -585,12 +596,14 @@ public class CardPanelComponentImpl extends CardPanel {
boolean showText = !isAnimationPanel() && canShowCardIcons(cardWidth, hasImage);
titleText.setVisible(showText);
ptText.setVisible(showText);
ptText1.setVisible(showText && !ptText1.getText().isEmpty());
ptText2.setVisible(showText && !ptText2.getText().isEmpty());
ptText3.setVisible(showText && !ptText3.getText().isEmpty());
fullImageText.setVisible(fullImagePath != null);
if (showText) {
int fontSize = cardHeight / 13; // startup font size (it same size on all zoom levels)
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
titleText.setFont(getFont().deriveFont(Font.BOLD, Math.max(CARD_TITLE_FONT_MIN_SIZE, fontSize)));
// margins from card black border to text, not need? text show up good without margins
int titleMarginLeft = 0; //Math.round(28f / 672f * cardWidth);
@ -607,24 +620,58 @@ public class CardPanelComponentImpl extends CardPanel {
fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10));
fullImageText.setBounds(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
// life points location (font as title)
ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
Dimension ptSize = ptText.getPreferredSize();
ptText.setSize(ptSize.width, ptSize.height);
// PT (font as title)
prepareGlowFont(ptText1, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getPower(), false);
prepareGlowFont(ptText2, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), null, false);
prepareGlowFont(ptText3, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getToughness(), CardRendererUtils.isCardWithDamage(getGameCard()));
// right bottom corner with margin (sizes from any sample card)
int ptMarginRight = Math.round(64f / 672f * cardWidth);
int ptMarginBottom = Math.round(62f / 936f * cardHeight);
int ptX = cardXOffset + cardWidth - ptMarginRight - ptSize.width;
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptSize.height;
ptText.setLocation(ptX, ptY);
int ptWidth = cardWidth - ptMarginRight * 2;
int ptHeight = ptText2.getHeight();
int ptX = cardXOffset + ptMarginRight;
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptHeight;
ptPanel.setBounds(ptX, ptY, ptWidth, ptHeight);
// old version was with TEXT_GLOW_SIZE
//ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
}
}
private void prepareGlowFont(GlowText label, int fontSize, MageInt value, boolean drawAsDamaged) {
label.setFont(getFont().deriveFont(Font.BOLD, fontSize));
label.setForeground(CardRendererUtils.getCardTextColor(value, drawAsDamaged, titleText.getForeground(), true));
Dimension ptSize = label.getPreferredSize();
label.setSize(ptSize.width, ptSize.height);
}
private void updatePTTexts(CardView card) {
if (card.isCreature()) {
ptText1.setText(getGameCard().getPower());
ptText2.setText("/");
ptText3.setText(CardRendererUtils.getCardLifeWithDamage(getGameCard()));
} else if (card.isPlanesWalker()) {
ptText1.setText("");
ptText2.setText("");
ptText3.setText(getGameCard().getLoyalty());
} else {
ptText1.setText("");
ptText2.setText("");
ptText3.setText("");
}
ptText1.setForeground(Color.white);
ptText1.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
ptText2.setForeground(Color.white);
ptText2.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
ptText3.setForeground(Color.white);
ptText3.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
}
@Override
public String toString() {
return getGameCard().toString();
@ -647,10 +694,14 @@ public class CardPanelComponentImpl extends CardPanel {
// Update components
if (alpha == 0) {
this.ptText.setVisible(false);
this.ptText1.setVisible(false);
this.ptText2.setVisible(false);
this.ptText3.setVisible(false);
this.titleText.setVisible(false);
} else if (alpha == 1.0f) {
this.ptText.setVisible(true);
this.ptText1.setVisible(true);
this.ptText2.setVisible(true);
this.ptText3.setVisible(true);
this.titleText.setVisible(true);
}
}
@ -683,7 +734,7 @@ public class CardPanelComponentImpl extends CardPanel {
UI.invokeLater(() -> {
if (stamp == updateArtImageStamp) {
hasImage = srcImage != null;
setText(getGameCard());
setTitle(getGameCard());
setImage(srcImage);
}
});
@ -712,7 +763,7 @@ public class CardPanelComponentImpl extends CardPanel {
@Override
public void showCardTitle() {
displayTitleAnyway = true;
setText(getGameCard());
setTitle(getGameCard());
}
@Override
@ -720,17 +771,8 @@ public class CardPanelComponentImpl extends CardPanel {
// Super
super.update(card);
// Update card text
if (card.isCreature() && card.isPlanesWalker()) {
ptText.setText(card.getPower() + '/' + card.getToughness() + " (" + card.getLoyalty() + ')');
} else if (card.isCreature()) {
ptText.setText(card.getPower() + '/' + card.getToughness());
} else if (card.isPlanesWalker()) {
ptText.setText(card.getLoyalty());
} else {
ptText.setText("");
}
setText(card);
updatePTTexts(card);
setTitle(card);
// Summoning Sickness overlay
if (hasSickness() && card.isCreature() && isPermanent()) {

View file

@ -297,6 +297,8 @@ public class CardPanelRenderImpl extends CardPanel {
// Render with Antialialsing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// Attributes
CardPanelAttributes attribs

View file

@ -1,5 +1,9 @@
package org.mage.card.arcane;
import mage.MageInt;
import mage.view.CardView;
import mage.view.PermanentView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
@ -10,12 +14,18 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author stravant@gmail.com
* @author stravant@gmail.com, JayDi85
* <p>
* Various static utilities for use in the card renderer
*/
public final class CardRendererUtils {
// text colors for PT (mtgo and image render modes)
private static final Color CARD_TEXT_COLOR_GOOD_LIGHT = new Color(182, 235, 168);
private static final Color CARD_TEXT_COLOR_GOOD_DARK = new Color(52, 135, 88);
private static final Color CARD_TEXT_COLOR_BAD_LIGHT = new Color(234, 153, 153);
private static final Color CARD_TEXT_COLOR_BAD_DARK = new Color(200, 33, 33);
/**
* Convert an abstract image, whose underlying implementation may or may not
* be a BufferedImage into a BufferedImage by creating one and coping the
@ -53,9 +63,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
int plus_r = (int) ((255 - r) / 2);
int plus_g = (int) ((255 - g) / 2);
int plus_b = (int) ((255 - b) / 2);
int plus_r = (255 - r) / 2;
int plus_g = (255 - g) / 2;
int plus_b = (255 - b) / 2;
return new Color(r + plus_r,
g + plus_g,
@ -69,9 +79,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
int plus_r = (int) (Math.min(255 - r, r) / 2);
int plus_g = (int) (Math.min(255 - g, g) / 2);
int plus_b = (int) (Math.min(255 - b, b) / 2);
int plus_r = Math.min(255 - r, r) / 2;
int plus_g = Math.min(255 - g, g) / 2;
int plus_b = Math.min(255 - b, b) / 2;
return new Color(r - plus_r,
g - plus_g,
@ -195,4 +205,52 @@ public final class CardRendererUtils {
return null;
}
}
public static String getCardLifeWithDamage(CardView cardView) {
// life with damage
String originLife = cardView.getToughness();
if (cardView instanceof PermanentView) {
int damage = ((PermanentView) cardView).getDamage();
int life;
try {
life = Integer.parseInt(originLife);
originLife = String.valueOf(Math.max(0, life - damage));
} catch (NumberFormatException e) {
//
}
}
return originLife;
}
public static boolean isCardWithDamage(CardView cardView) {
boolean haveDamage = false;
if (cardView instanceof PermanentView) {
haveDamage = ((PermanentView) cardView).getDamage() > 0;
}
return haveDamage;
}
public static Color getCardTextColor(MageInt value, boolean drawAsDamaged, Color defaultColor, boolean textLight) {
if (drawAsDamaged) {
return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
}
// boost colorizing
if (value != null) {
int current = value.getValue();
int origin = value.getBaseValue();
if (origin != 0) {
if (current < origin) {
return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
} else if (current > origin) {
return textLight ? CARD_TEXT_COLOR_GOOD_LIGHT : CARD_TEXT_COLOR_GOOD_DARK;
} else {
return defaultColor;
}
}
}
return defaultColor;
}
}

View file

@ -1,5 +1,10 @@
package org.mage.card.arcane;
import mage.client.util.ImageCaches;
import mage.client.util.SoftValuesLoadingCache;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
@ -14,17 +19,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import javax.swing.*;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import mage.client.util.ImageCaches;
import mage.client.util.SoftValuesLoadingCache;
public class GlowText extends JLabel {
private static final long serialVersionUID = 1827677946939348001L;
@ -123,10 +117,7 @@ public class GlowText extends JLabel {
if (!Objects.equals(this.color, other.color)) {
return false;
}
if (!Objects.equals(this.glowColor, other.glowColor)) {
return false;
}
return true;
return Objects.equals(this.glowColor, other.glowColor);
}
}
@ -158,7 +149,11 @@ public class GlowText extends JLabel {
return;
}
g.drawImage(IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap)), 0, 0, null);
g.drawImage(getGlowImage(), 0, 0, null);
}
public BufferedImage getGlowImage() {
return IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap));
}
private static BufferedImage createGlowImage(Key key) {

View file

@ -1,8 +1,3 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.mage.card.arcane;
import mage.ObjectColor;
@ -56,13 +51,14 @@ import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
*/
/**
* @author stravant@gmail.com
* @author stravant@gmail.com, JayDi85
* <p>
* Base rendering class for new border cards
*/
public class ModernCardRenderer extends CardRenderer {
private static final Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
private static final GlowText glowTextRenderer = new GlowText();
///////////////////////////////////////////////////////////////////////////
// Textures for modern frame cards
@ -261,7 +257,7 @@ public class ModernCardRenderer extends CardRenderer {
ptTextHeight = getPTTextHeightForLineHeight(boxHeight);
ptTextOffset = (boxHeight - ptTextHeight) / 2;
// Beleren font does work well for numbers though
ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight);
ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.BOLD, ptTextHeight);
}
@Override
@ -933,6 +929,51 @@ public class ModernCardRenderer extends CardRenderer {
}
}
public void paintOutlineTextByGlow(Graphics2D g, String text, Color color, int x, int y) {
GlowText label = new GlowText();
label.setGlow(Color.black, 6, 3);
label.setText(text);
label.setFont(g.getFont().deriveFont(Font.BOLD));
label.setForeground(color);
Dimension ptSize = label.getPreferredSize();
label.setSize(ptSize.width, ptSize.height);
g.drawImage(label.getGlowImage(), x, y, null);
}
public void paintOutlineTextByStroke(Graphics2D g, String text, Color color, int x, int y) {
// https://stackoverflow.com/a/35222059/1276632
Color outlineColor = Color.black;
Color fillColor = color;
BasicStroke outlineStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// remember original settings
Color originalColor = g.getColor();
Stroke originalStroke = g.getStroke();
RenderingHints originalHints = g.getRenderingHints();
// create a glyph vector from your text
GlyphVector glyphVector = g.getFont().createGlyphVector(g.getFontRenderContext(), text);
// get the shape object
Shape textShape = glyphVector.getOutline(x, y);
// activate anti aliasing for text rendering (if you want it to look nice)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setColor(outlineColor);
g.setStroke(outlineStroke);
g.draw(textShape); // draw outline
g.setColor(fillColor);
g.fill(textShape); // fill the shape
// reset to original settings after painting
g.setColor(originalColor);
g.setStroke(originalStroke);
g.setRenderingHints(originalHints);
}
// Draw the P/T and/or Loyalty boxes
protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) {
// No bottom right for abilities
@ -966,24 +1007,44 @@ public class ModernCardRenderer extends CardRenderer {
partWidth - 2 * contentInset, 1);
// Draw text
Color textColor;
Color defaultTextColor;
boolean defaultTextLight;
if (isVehicle) {
boolean isAnimated = !(cardView instanceof PermanentView) || cardView.isCreature();
if (isAnimated) {
textColor = Color.white;
defaultTextColor = Color.white;
} else {
textColor = new Color(180, 180, 180);
defaultTextColor = new Color(180, 180, 180);
}
defaultTextLight = true;
} else {
textColor = getBoxTextColor();
defaultTextColor = getBoxTextColor();
defaultTextLight = !defaultTextColor.equals(Color.black);
}
g.setColor(textColor);
g.setColor(defaultTextColor);
g.setFont(ptTextFont);
String ptText = cardView.getPower() + '/' + cardView.getToughness();
int ptTextWidth = g.getFontMetrics().stringWidth(ptText);
g.drawString(ptText,
x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1);
// draws p/t by parts
String ptText1 = cardView.getPower();
String ptText2 = "/";
String ptText3 = CardRendererUtils.getCardLifeWithDamage(cardView);
int ptTextWidth1 = g.getFontMetrics().stringWidth(ptText1);
int ptTextWidth2 = g.getFontMetrics().stringWidth(ptText2);
// draws / by center, P and T from left/right sides of /
int ptCenterX = x + partWidth / 2;
// p
g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), false, defaultTextColor, defaultTextLight));
g.drawString(ptText1, ptCenterX - ptTextWidth2 / 2 - ptTextWidth1, curY - ptTextOffset - 1); // left
// /
g.setColor(defaultTextColor);
g.drawString(ptText2, ptCenterX - ptTextWidth2 / 2, curY - ptTextOffset - 1); // center
// t
g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), CardRendererUtils.isCardWithDamage(cardView), defaultTextColor, defaultTextLight));
g.drawString(ptText3, ptCenterX + ptTextWidth2 / 2, curY - ptTextOffset - 1); // right
//
g.setColor(defaultTextColor);
// Advance
curY -= boxHeight;

View file

@ -53,6 +53,10 @@ public class MageObjectReference implements Comparable<MageObjectReference>, Ser
public MageObjectReference(UUID sourceId, Game game) {
this.sourceId = sourceId;
if (sourceId == null) {
throw new IllegalArgumentException("MageObjectReference contains nullable sourceId");
}
MageObject mageObject = game.getObject(sourceId);
if (mageObject != null) {
this.zoneChangeCounter = mageObject.getZoneChangeCounter(game);