diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java index 15d3c55a603..b33de0d4874 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java @@ -523,7 +523,19 @@ public abstract class CardPanel extends MagePermanent implements MouseListener, */ @Override public void update(CardView card) { - this.setUpdateCard(card); + if (card == null) { + return; + } + + if (transformed && card.equals(this.temporary)) { + // update can be called from different places (after transform click, after selection change, etc) + // if card temporary transformed before (by icon click) then do not update full data (as example, after selection changed) + this.isChoosable = card.isChoosable(); + this.isSelected = card.isSelected(); + return; + } else { + this.setUpdateCard(card); + } // Animation update if (isPermanent && (card instanceof PermanentView)) { @@ -769,10 +781,18 @@ public abstract class CardPanel extends MagePermanent implements MouseListener, this.transformed = transformed; } + private void copySelections(CardView source, CardView dest) { + if (source != null && dest != null) { + dest.setSelected(source.isSelected()); + dest.setChoosable(source.isChoosable()); + } + } + @Override public void toggleTransformed() { this.transformed = !this.transformed; if (transformed) { + // show night card if (dayNightButton != null) { // if transformbable card is copied, button can be null BufferedImage night = ImageManagerImpl.instance.getNightImage(); dayNightButton.setIcon(new ImageIcon(night)); @@ -782,15 +802,19 @@ public abstract class CardPanel extends MagePermanent implements MouseListener, return; } if (!isPermanent) { // use only for custom transformation (when pressing day-night button) + copySelections(this.getGameCard(), this.getGameCard().getSecondCardFace()); this.setTemporary(this.getGameCard()); update(this.getGameCard().getSecondCardFace()); } } else { + // show day card if (dayNightButton != null) { // if transformbable card is copied, button can be null BufferedImage day = ImageManagerImpl.instance.getDayImage(); dayNightButton.setIcon(new ImageIcon(day)); } + if (!isPermanent) { // use only for custom transformation (when pressing day-night button) + copySelections(this.getGameCard().getSecondCardFace(), this.getGameCard()); update(this.getTemporary()); this.setTemporary(null); } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java index 9382cb9a526..da6646de851 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java @@ -15,11 +15,13 @@ public class CardPanelAttributes { public final int cardHeight; public final boolean isSelected; public final boolean isChoosable; - - public CardPanelAttributes(int cardWidth, int cardHeight, boolean isChoosable, boolean isSelected) { + public final boolean isTransformed; + + public CardPanelAttributes(int cardWidth, int cardHeight, boolean isChoosable, boolean isSelected, boolean isTransformed) { this.cardWidth = cardWidth; this.cardHeight = cardHeight; this.isChoosable = isChoosable; this.isSelected = isSelected; + this.isTransformed = isTransformed; } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java index 6b32b0b1d67..5af4e5c7f8a 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java @@ -775,11 +775,12 @@ public class CardPanelComponentImpl extends CardPanel { // Super super.update(card); - updatePTTexts(card); - setTitle(card); + // real card to show stores in getGameCard (e.g. after user clicks on night icon -- night card must be rendered) + updatePTTexts(getGameCard()); + setTitle(getGameCard()); // Summoning Sickness overlay - if (hasSickness() && card.isCreature() && isPermanent()) { + if (hasSickness() && getGameCard().isCreature() && isPermanent()) { getOverlayPanel().setVisible(true); } else { getOverlayPanel().setVisible(false); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java index fd4ddf7a9cb..16f001ff813 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java @@ -31,7 +31,7 @@ public class CardPanelRenderImpl extends CardPanel { if (a.getClass() != b.getClass()) { return false; } - if (!a.getName().equals(b.getName())) { + if (!a.getDisplayName().equals(b.getDisplayName())) { return false; } if (!a.getPower().equals(b.getPower())) { @@ -117,16 +117,18 @@ public class CardPanelRenderImpl extends CardPanel { final int height; final boolean isChoosable; final boolean isSelected; + final boolean isTransformed; final CardView view; final int hashCode; - public ImageKey(CardView view, BufferedImage artImage, int width, int height, boolean isChoosable, boolean isSelected) { + public ImageKey(CardView view, BufferedImage artImage, int width, int height, boolean isChoosable, boolean isSelected, boolean isTransformed) { this.view = view; this.artImage = artImage; this.width = width; this.height = height; this.isChoosable = isChoosable; this.isSelected = isSelected; + this.isTransformed = isTransformed; this.hashCode = hashCodeImpl(); } @@ -137,6 +139,7 @@ public class CardPanelRenderImpl extends CardPanel { sb.append((char) height); sb.append((char) (isSelected ? 1 : 0)); sb.append((char) (isChoosable ? 1 : 0)); + sb.append((char) (isTransformed ? 1 : 0)); sb.append((char) (this.view.isPlayable() ? 1 : 0)); sb.append((char) (this.view.isCanAttack() ? 1 : 0)); sb.append((char) (this.view.isCanBlock() ? 1 : 0)); @@ -146,7 +149,7 @@ public class CardPanelRenderImpl extends CardPanel { sb.append((char) (((PermanentView) this.view).hasSummoningSickness() ? 1 : 0)); sb.append((char) (((PermanentView) this.view).getDamage())); } - sb.append(this.view.getName()); + sb.append(this.view.getDisplayName()); sb.append(this.view.getPower()); sb.append(this.view.getToughness()); sb.append(this.view.getLoyalty()); @@ -237,7 +240,7 @@ public class CardPanelRenderImpl extends CardPanel { super(newGameCard, gameId, loadImage, callback, foil, dimension, needFullPermanentRender); // Renderer - cardRenderer = cardRendererFactory.create(getGameCard(), isTransformed()); + cardRenderer = cardRendererFactory.create(getGameCard()); // Draw the parts initialDraw(); @@ -261,11 +264,12 @@ public class CardPanelRenderImpl extends CardPanel { protected void paintCard(Graphics2D g) { // Render the card if we don't have an image ready to use if (cardImage == null) { + LOGGER.warn("new image: " + getGameCard().getDisplayName() + "; transformed " + (isTransformed() ? "yes" : "no")); + // Try to get card image from cache based on our card characteristics - ImageKey key - = new ImageKey(getGameCard(), artImage, + ImageKey key = new ImageKey(getGameCard(), artImage, getCardWidth(), getCardHeight(), - isChoosable(), isSelected()); + isChoosable(), isSelected(), isTransformed()); try { cardImage = IMAGE_CACHE.get(key, this::renderCard); } catch (ExecutionException e) { @@ -301,18 +305,18 @@ public class CardPanelRenderImpl extends CardPanel { g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - // Attributes - CardPanelAttributes attribs - = new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected()); - // Draw card itself - cardRenderer.draw(g2d, attribs, image); + cardRenderer.draw(g2d, getAttributes(), image); // Done g2d.dispose(); return image; } + private CardPanelAttributes getAttributes() { + return new CardPanelAttributes(getCardWidth(), getCardHeight(), isChoosable(), isSelected(), isTransformed()); + } + private int updateArtImageStamp; @Override @@ -382,7 +386,7 @@ public class CardPanelRenderImpl extends CardPanel { // Update renderer cardImage = null; - cardRenderer = cardRendererFactory.create(getGameCard(), isTransformed()); + cardRenderer = cardRendererFactory.create(getGameCard()); cardRenderer.setArtImage(artImage); cardRenderer.setFaceArtImage(faceArtImage); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java index 7b42ea47ab0..0c5081a8c48 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java @@ -60,9 +60,6 @@ public abstract class CardRenderer { // The card to be rendered protected final CardView cardView; - // Is the card transformed? - protected final boolean isTransformed; - // The card image protected BufferedImage artImage; @@ -123,10 +120,9 @@ public abstract class CardRenderer { // without knowing the dimensions that the card will be rendered at. // Then, the CardRenderer can be called on multiple times to render the // card at various sizes (for instance, during animation) - public CardRenderer(CardView card, boolean isTransformed) { + public CardRenderer(CardView card) { // Set base parameters this.cardView = card; - this.isTransformed = isTransformed; if (card.getArtRect() == ArtRect.SPLIT_FUSED) { parseRules(card.getLeftSplitRules(), textboxKeywords, textboxRules); @@ -218,7 +214,7 @@ public abstract class CardRenderer { drawBorder(g); drawBackground(g); drawArt(g); - drawFrame(g, image); + drawFrame(g, attribs, image); if (!cardView.isAbility()) { drawOverlays(g); drawCounters(g); @@ -233,7 +229,7 @@ public abstract class CardRenderer { protected abstract void drawArt(Graphics2D g); - protected abstract void drawFrame(Graphics2D g, BufferedImage image); + protected abstract void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image); // Template methods that are possible to override, but unlikely to be // overridden. diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererFactory.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererFactory.java index 39ba0670aab..4a78b7437d7 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererFactory.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererFactory.java @@ -7,17 +7,17 @@ import mage.view.CardView; * Created by StravantUser on 2017-03-30. */ public class CardRendererFactory { - public CardRendererFactory() { + public CardRendererFactory() { } - public CardRenderer create(CardView card, boolean isTransformed) { + public CardRenderer create(CardView card) { if (card.isSplitCard() && card.getArtRect() != ArtRect.SPLIT_FUSED) { // Split fused cards still render with the normal frame, showing all abilities // from both halves in one frame. - return new ModernSplitCardRenderer(card, isTransformed); + return new ModernSplitCardRenderer(card); } else { - return new ModernCardRenderer(card, isTransformed); + return new ModernCardRenderer(card); } } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java index 949ec311935..4caf65a93db 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -216,9 +216,9 @@ public class ModernCardRenderer extends CardRenderer { // Processed mana cost string protected final String manaCostString; - public ModernCardRenderer(CardView card, boolean isTransformed) { + public ModernCardRenderer(CardView card) { // Pass off to parent - super(card, isTransformed); + super(card); // Mana cost string manaCostString = ManaSymbols.getStringManaCost(cardView.getManaCost()); @@ -454,13 +454,13 @@ public class ModernCardRenderer extends CardRenderer { } @Override - protected void drawFrame(Graphics2D g, BufferedImage image) { + protected void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image) { // Get the card colors to base the frame on ObjectColor frameColors = getFrameObjectColor(); // Get the border paint - Color boxColor = getBoxColor(frameColors, cardView.getCardTypes(), isTransformed); - Color additionalBoxColor = getAdditionalBoxColor(frameColors, cardView.getCardTypes(), isTransformed); + Color boxColor = getBoxColor(frameColors, cardView.getCardTypes(), attribs.isTransformed); + Color additionalBoxColor = getAdditionalBoxColor(frameColors, cardView.getCardTypes(), attribs.isTransformed); Paint textboxPaint = getTextboxPaint(frameColors, cardView.getCardTypes(), cardWidth); Paint borderPaint = getBorderPaint(frameColors, cardView.getCardTypes(), cardWidth); @@ -547,19 +547,16 @@ public class ModernCardRenderer extends CardRenderer { cardWidth - totalContentInset - 1, typeLineY + boxHeight, 1, cardHeight - borderWidth * 3 - typeLineY - boxHeight); // Draw the type line - drawTypeLine(g, getCardTypeLine(), + drawTypeLine(g, attribs, getCardTypeLine(), totalContentInset, typeLineY, contentWidth, boxHeight, true); } // Draw the transform circle - int nameOffset = drawTransformationCircle(g, borderPaint); - - // Draw the transform circle - nameOffset = drawTransformationCircle(g, borderPaint); + int nameOffset = drawTransformationCircle(g, attribs, borderPaint); // Draw the name line - drawNameLine(g, cardView.getDisplayName(), manaCostString, + drawNameLine(g, attribs, cardView.getDisplayName(), manaCostString, totalContentInset + nameOffset, totalContentInset, contentWidth - nameOffset, boxHeight); @@ -625,10 +622,10 @@ public class ModernCardRenderer extends CardRenderer { x, y, w, h, contentInset, borderPaint, boxColor); - drawTypeLine(g, getCardSuperTypeLine(), + drawTypeLine(g, attribs, getCardSuperTypeLine(), totalContentInset + contentInset, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset, contentWidth / 2 - boxHeight, boxHeight - 4, false); - drawTypeLine(g, getCardSubTypeLine(), + drawTypeLine(g, attribs, getCardSubTypeLine(), totalContentInset + 4 * contentWidth / 7 + boxHeight, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset, 3 * contentWidth / 7 - boxHeight - contentInset, boxHeight - 4, true); drawRulesText(g, textboxKeywords, textboxRules, @@ -651,7 +648,7 @@ public class ModernCardRenderer extends CardRenderer { } // Draw the bottom right stuff - drawBottomRight(g, borderPaint, boxColor); + drawBottomRight(g, attribs, borderPaint, boxColor); } public void drawZendikarCurvedFace(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2, @@ -836,7 +833,7 @@ public class ModernCardRenderer extends CardRenderer { } // Draw the name line - protected void drawNameLine(Graphics2D g, String baseName, String manaCost, int x, int y, int w, int h) { + protected void drawNameLine(Graphics2D g, CardPanelAttributes attribs, String baseName, String manaCost, int x, int y, int w, int h) { // Width of the mana symbols int manaCostWidth; if (cardView.isAbility()) { @@ -873,7 +870,7 @@ public class ModernCardRenderer extends CardRenderer { } if (breakIndex > 0) { TextLayout layout = measure.getLayout(0, breakIndex); - g.setColor(getBoxTextColor()); + g.setColor(getBoxTextColor(attribs)); layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); } } @@ -885,7 +882,7 @@ public class ModernCardRenderer extends CardRenderer { } // Draw the type line (color indicator, types, and expansion symbol) - protected void drawTypeLine(Graphics2D g, String baseTypeLine, int x, int y, int w, int h, boolean withSymbol) { + protected void drawTypeLine(Graphics2D g, CardPanelAttributes attribs, String baseTypeLine, int x, int y, int w, int h, boolean withSymbol) { // Draw expansion symbol int expansionSymbolWidth = 0; if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_SET_SYMBOL, "false").equals("false")) { @@ -921,7 +918,7 @@ public class ModernCardRenderer extends CardRenderer { } if (breakIndex > 0) { TextLayout layout = measure.getLayout(0, breakIndex); - g.setColor(getBoxTextColor()); + g.setColor(getBoxTextColor(attribs)); layout.draw(g, x, y + (h - boxTextHeight) / 2 + boxTextHeight - 1); } } @@ -973,7 +970,7 @@ public class ModernCardRenderer extends CardRenderer { } // Draw the P/T and/or Loyalty boxes - protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) { + protected void drawBottomRight(Graphics2D g, CardPanelAttributes attribs, Paint borderPaint, Color fill) { // No bottom right for abilities if (cardView.isAbility()) { return; @@ -1030,7 +1027,7 @@ public class ModernCardRenderer extends CardRenderer { } defaultTextLight = true; } else { - defaultTextColor = getBoxTextColor(); + defaultTextColor = getBoxTextColor(attribs); defaultTextLight = !defaultTextColor.equals(Color.black); } g.setColor(defaultTextColor); @@ -1413,26 +1410,20 @@ public class ModernCardRenderer extends CardRenderer { return advance; } - // Draw the transformation circle if there is one, and return the - // horizontal width taken up into the content space by it. - protected boolean isNightCard() { - return isTransformed; + protected boolean isTransformCard(CardPanelAttributes attribs) { + return cardView.canTransform() || attribs.isTransformed; } - protected boolean isTransformCard() { - return cardView.canTransform() || isTransformed; - } - - protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) { + protected int drawTransformationCircle(Graphics2D g, CardPanelAttributes attribs, Paint borderPaint) { int transformCircleOffset = 0; - if (isTransformCard()) { + if (isTransformCard(attribs)) { transformCircleOffset = boxHeight - contentInset; g.setPaint(borderPaint); g.drawOval(borderWidth, totalContentInset, boxHeight - 1, boxHeight - 1); g.setColor(Color.black); g.fillOval(borderWidth + 1, totalContentInset + 1, boxHeight - 2, boxHeight - 2); g.setColor(Color.white); - if (isTransformed) { + if (attribs.isTransformed) { g.fillArc(borderWidth + 3, totalContentInset + 3, boxHeight - 6, boxHeight - 6, 90, 270); g.setColor(Color.black); g.fillArc(borderWidth + 3 + 3, totalContentInset + 3, boxHeight - 6 - 3, boxHeight - 6, 90, 270); @@ -1457,8 +1448,8 @@ public class ModernCardRenderer extends CardRenderer { } // Determine the color of the name / type line text - protected Color getBoxTextColor() { - if (isTransformed) { + protected Color getBoxTextColor(CardPanelAttributes attribs) { + if (attribs.isTransformed) { return Color.white; } else if (cardView.isAbility()) { return Color.white; diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java index 7e09c8a266c..367b5a4a5fc 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java @@ -47,8 +47,8 @@ public class ModernSplitCardRenderer extends ModernCardRenderer { private boolean isFuse = false; private boolean isAftermath = false; - public ModernSplitCardRenderer(CardView view, boolean isTransformed) { - super(view, isTransformed); + public ModernSplitCardRenderer(CardView view) { + super(view); rightHalf.manaCostString = ManaSymbols.getStringManaCost(cardView.getRightSplitCosts().getSymbols()); leftHalf.manaCostString = ManaSymbols.getStringManaCost(cardView.getLeftSplitCosts().getSymbols()); @@ -227,9 +227,9 @@ public class ModernSplitCardRenderer extends ModernCardRenderer { } } - protected void drawSplitHalfFrame(Graphics2D g, HalfCardProps half, int typeLineY) { + protected void drawSplitHalfFrame(Graphics2D g, CardPanelAttributes attribs, HalfCardProps half, int typeLineY) { // Get the border paint - Color boxColor = getBoxColor(half.color, cardView.getCardTypes(), isTransformed); + Color boxColor = getBoxColor(half.color, cardView.getCardTypes(), attribs.isTransformed); Paint textboxPaint = getTextboxPaint(half.color, cardView.getCardTypes(), cardWidth); Paint borderPaint = getBorderPaint(half.color, cardView.getCardTypes(), cardWidth); @@ -260,12 +260,12 @@ public class ModernSplitCardRenderer extends ModernCardRenderer { borderPaint, boxColor); // Draw the name line - drawNameLine(g, half.name, half.manaCostString, + drawNameLine(g, attribs, half.name, half.manaCostString, 0, 0, half.cw, boxHeight); // Draw the type line - drawTypeLine(g, half.typeLineString, + drawTypeLine(g, attribs, half.typeLineString, 0, typeLineY, half.cw, boxHeight - 4, true); @@ -306,13 +306,13 @@ public class ModernSplitCardRenderer extends ModernCardRenderer { } @Override - protected void drawFrame(Graphics2D g, BufferedImage image) { + protected void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image) { if (isAftermath()) { - drawSplitHalfFrame(getUnmodifiedHalfContext(g), leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC)); - drawSplitHalfFrame(getAftermathHalfContext(g), rightHalf, (rightHalf.ch - boxHeight) / 2); + drawSplitHalfFrame(getUnmodifiedHalfContext(g), attribs, leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC)); + drawSplitHalfFrame(getAftermathHalfContext(g), attribs, rightHalf, (rightHalf.ch - boxHeight) / 2); } else { - drawSplitHalfFrame(getLeftHalfContext(g), leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC)); - drawSplitHalfFrame(getRightHalfContext(g), rightHalf, (int) (rightHalf.ch * TYPE_LINE_Y_FRAC)); + drawSplitHalfFrame(getLeftHalfContext(g), attribs, leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC)); + drawSplitHalfFrame(getRightHalfContext(g), attribs, rightHalf, (int) (rightHalf.ch * TYPE_LINE_Y_FRAC)); if (isFuse()) { Graphics2D g2 = getRightHalfContext(g); int totalFuseBoxWidth = rightHalf.cw * 2 + 2 * borderWidth + dividerSize; @@ -323,7 +323,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer { totalFuseBoxWidth, boxHeight, contentInset, borderPaint, boxColor); - drawNameLine(g2, "Fuse (You may cast both halves from your hand)", "", + drawNameLine(g2, attribs, "Fuse (You may cast both halves from your hand)", "", 0, rightHalf.ch, totalFuseBoxWidth - 2 * borderWidth, boxHeight); }