diff --git a/forge-core/src/main/java/forge/util/ImageUtil.java b/forge-core/src/main/java/forge/util/ImageUtil.java index 8848b529246..2d05393f20b 100644 --- a/forge-core/src/main/java/forge/util/ImageUtil.java +++ b/forge-core/src/main/java/forge/util/ImageUtil.java @@ -232,7 +232,9 @@ public class ImageUtil { String versionParam = useArtCrop ? "art_crop" : "normal"; String faceParam = ""; if (cp.getRules().getOtherPart() != null) { - faceParam = (face.equals("back") ? "&face=back" : "&face=front"); + faceParam = (face.equals("back") && cp.getRules().getSplitType() != CardSplitType.Flip + ? "&face=back" + : "&face=front"); } else if (cp.getRules().getSplitType() == CardSplitType.Meld && !cardCollectorNumber.endsWith("a") && !cardCollectorNumber.endsWith("b")) { diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index cdb0f16d5cf..3b95bb328c7 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -142,9 +142,8 @@ public class CardView extends GameEntityView { } public boolean isFlipped() { - return get(TrackableProperty.Flipped); // getCurrentState().getState() == CardStateName.Flipped; + return get(TrackableProperty.Flipped); } - public boolean isSplitCard() { return get(TrackableProperty.SplitCard); } @@ -1027,6 +1026,7 @@ public class CardView extends GameEntityView { set(TrackableProperty.Cloned, c.isCloned()); set(TrackableProperty.SplitCard, isSplitCard); set(TrackableProperty.FlipCard, c.isFlipCard()); + set(TrackableProperty.Flipped, c.getCurrentStateName() == CardStateName.Flipped); set(TrackableProperty.Facedown, c.isFaceDown()); set(TrackableProperty.Foretold, c.isForetold()); set(TrackableProperty.Secondary, c.hasState(CardStateName.Secondary)); diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java b/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java index ca4dd75cee0..eaf302f7684 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java @@ -17,7 +17,8 @@ */ package forge.gui; -import java.awt.BorderLayout; +import java.awt.*; +import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.WritableRaster; @@ -67,7 +68,7 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb public Object getDisplayed() { return displayed; } public void setItem(final InventoryItem item) { - setImage(item, true); + setImage(item, true, false); } public void setItem(final BufferedImage image) { @@ -82,10 +83,14 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb } public void setCard(final CardStateView c, final boolean mayView) { - setImage(c, mayView); + setCard(c, mayView, false); } - private void setImage(final Object display, final boolean mayView) { + public void setCard(final CardStateView c, final boolean mayView, boolean isFlipped) { + setImage(c, mayView, isFlipped); + } + + private void setImage(final Object display, final boolean mayView, final boolean isFlipped) { this.displayed = display; this.mayView = mayView; @@ -98,7 +103,7 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb final BufferedImage displayedimage = new BufferedImage(cm, raster, isAlphaPremultiplied, null) .getSubimage(0, 0, image.getWidth(), image.getHeight()); this.currentImage = displayedimage; - this.panel.setImage(displayedimage, getAutoSizeImageMode()); + this.panel.setImage(isFlipped ? rotateImage180(displayedimage) : image, getAutoSizeImageMode()); PaperCard card = (PaperCard) displayed; if (FModel.getPreferences().getPrefBoolean(FPref.UI_OVERLAY_FOIL_EFFECT)) { if (card.isFoil()) { @@ -108,7 +113,7 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb } } else { this.currentImage = image; - this.panel.setImage(image, getAutoSizeImageMode()); + this.panel.setImage(isFlipped ? rotateImage180(image) : image, getAutoSizeImageMode()); } } } @@ -140,7 +145,7 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb @Override public void onImageFetched() { - setImage(displayed, mayView); + setImage(displayed, mayView, false); repaint(); } @@ -157,4 +162,25 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb } public void showAsEnabled(){ this.panel.setAlpha(0.0f); } + + private BufferedImage rotateImage180(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + + // Create a new image to hold the rotated version + BufferedImage rotated = new BufferedImage(width, height, image.getType()); + + // Graphics2D to draw the rotated image + Graphics2D g2d = rotated.createGraphics(); + + // Rotate 180 degrees around the center of the image + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(180), width / 2.0, height / 2.0); + + // Draw the original image onto the rotated canvas + g2d.drawImage(image, transform, null); + g2d.dispose(); + + return rotated; + } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java index e9e05c49b7f..2c98f294152 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java @@ -69,8 +69,12 @@ public class CPicture implements ICDoc { */ void showCard(final CardView c, final boolean isInAltState, final boolean mayView, final boolean mayFlip) { final CardStateView toShow = c != null && mayView ? c.getState(isInAltState) : null; + boolean showFlipped = c != null && c.isFlipped(); + if (c != null && c.isFlipCard() && isInAltState) { + showFlipped = !showFlipped; + } flipIndicator.setVisible(toShow != null && mayFlip); - picturePanel.setCard(toShow, mayView); + picturePanel.setCard(toShow, mayView, showFlipped); zoomer.setCard(toShow, mayFlip); } diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java index e36f767f890..2c79dd1ba6a 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java @@ -239,6 +239,10 @@ public enum CardZoomer { return thisCard.getCard().isFaceDown() || isSplitRotated ? 0 : isAftermath ? 270 : 90; // rotate Aftermath splits the other way to correctly show the right split (graveyard) half } + if (thisCard.getCard().isFlipped()) { + return 180; + } + return thisCard.getType().isPlane() || thisCard.getType().isPhenomenon() ? 90 : 0; } diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index d2c9b2c25d3..bc0d2ac3239 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -820,7 +820,22 @@ public class CardImageRenderer { croppedArea = 0.975f; minusxy = 0.135f * radius; } - if (canshow && CardRendererUtils.needsRotation(ForgePreferences.FPref.UI_ROTATE_PLANE_OR_PHENOMENON, card, altState)) { + if (canshow && card.isFlipped()) { + if (Forge.enableUIMask.equals("Full")) { + if (ImageCache.getInstance().isFullBorder(image)) + g.drawCardRoundRect(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, 180); + else { + g.drawRotatedImage(FSkin.getBorders().get(0), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, 180); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, 180); + if (CardRendererUtils.drawFoil(card)) + g.drawFoil(new_x, new_y, new_w, new_h, modR, false); + } + } else if (Forge.enableUIMask.equals("Crop")) { + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, 180); + } else { + g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, 180); + } + } else if (canshow && CardRendererUtils.needsRotation(ForgePreferences.FPref.UI_ROTATE_PLANE_OR_PHENOMENON, card, altState)) { if (Forge.enableUIMask.equals("Full")) { if (ImageCache.getInstance().isFullBorder(image)) g.drawCardRoundRect(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 367953207a2..627dd19b46d 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -662,8 +662,9 @@ public class CardRenderer { else g.drawCardImage(image, crack_overlay, x, y, w, h, CardRendererUtils.drawGray(card), CardRendererUtils.drawCracks(card, magnify)); } else { - if (needsRotation) { - float rotation = CardRendererUtils.hasAftermath(card) ? 90 : -90; + if (card.isFlipped() || needsRotation) { + float rotation = card.isFlipped() ? 180 + : CardRendererUtils.hasAftermath(card) ? 90 : -90; if (Forge.enableUIMask.equals("Full")) { if (ImageCache.getInstance().isFullBorder(image)) g.drawCardRoundRect(image, x, y, w, h, x + w / 2, y + h / 2, rotation); @@ -671,7 +672,6 @@ public class CardRenderer { g.drawRotatedImage(FSkin.getBorders().get(0), x, y, w, h, x + w / 2, y + h / 2, rotation); g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.3f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea, (x + radius / 2.3f - minusxy) + (w * croppedArea) / 2, (y + radius / 2 - minusxy) + (h * croppedArea) / 2, rotation); } - } else if (Forge.enableUIMask.equals("Crop")) { g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h, x + w / 2, y + h / 2, rotation); } else @@ -789,7 +789,6 @@ public class CardRenderer { float otherSymbolsSize = w / 4f; final float combatXSymbols = (x + (w / 4)) - otherSymbolsSize / 2 - 10; - final float stateXSymbols = (x + (w / 2)) - otherSymbolsSize / 2 - 10; final float ySymbols = (y + h) - (h / 12) - otherSymbolsSize / 2; if (card.isAttacking()) { @@ -1225,7 +1224,6 @@ public class CardRenderer { } private static void drawCounterTabs(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) { - int fontSize = Math.max(11, Math.min(22, (int) (h * 0.08))); BitmapFont font = Forge.getAssets().counterFonts().get(fontSize); @@ -1244,7 +1242,6 @@ public class CardRenderer { int currentCounter = 0; if (CounterDisplayType.from(FModel.getPreferences().getPref(FPref.UI_CARD_COUNTER_DISPLAY_TYPE)) == CounterDisplayType.OLD_WHEN_SMALL) { - int maxCounters = 0; for (Integer numberOfCounters : card.getCounters().values()) { maxCounters = Math.max(maxCounters, numberOfCounters); @@ -1289,7 +1286,6 @@ public class CardRenderer { private static final int GL_BLEND = GL20.GL_BLEND; private static void drawText(Graphics g, String text, BitmapFont font, Color color, float x, float y, float w, float h, int horizontalAlignment) { - if (color.a < 1) { //enable blending so alpha colored shapes work properly Gdx.gl.glEnable(GL_BLEND); } @@ -1312,7 +1308,6 @@ public class CardRenderer { } private static void drawCounterImage(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) { - int number = 0; if (card.getCounters() != null) { for (final Integer i : card.getCounters().values()) { @@ -1335,11 +1330,9 @@ public class CardRenderer { } else if (counters > 3) { CardFaceSymbols.drawSymbol("countersMulti", g, xCounters, yCounters, countersSize, countersSize); } - } private static void drawMarkersTabs(final List markers, final Graphics g, final float x, final float y, final float w, final float h, boolean larger) { - int fontSize = larger ? Math.max(9, Math.min(22, (int) (h * 0.08))) : Math.max(8, Math.min(22, (int) (h * 0.05))); BitmapFont font = Forge.getAssets().counterFonts().get(fontSize); @@ -1442,7 +1435,6 @@ public class CardRenderer { //TODO Make FSkinFont accept more than one kind of font and merge this with it private static void generateFontForCounters(final int fontSize) { - FileHandle ttfFile = Gdx.files.absolute(ForgeConstants.COMMON_FONTS_DIR).child("Roboto-Bold.ttf"); if (!ttfFile.exists()) { @@ -1491,10 +1483,7 @@ public class CardRenderer { generator.dispose(); packer.dispose(); - } }); - } - }