Display flipped cards correctly

This commit is contained in:
Eradev
2025-08-15 05:54:31 -04:00
parent 16155d3670
commit 98e9b8f28b
7 changed files with 66 additions and 26 deletions

View File

@@ -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")) {

View File

@@ -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));

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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<String> 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();
}
});
}
}