Merge branch 'master' into 'master'

[Mobile] added "Art" Border Masking Option & Card BG Textures

See merge request core-developers/forge!5278
This commit is contained in:
Michael Kamensky
2021-09-03 19:37:41 +00:00
25 changed files with 783 additions and 147 deletions

View File

@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import forge.game.spellability.SpellAbility;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@@ -821,7 +822,7 @@ public class CardView extends GameEntityView {
updateZoneText(c); updateZoneText(c);
updateDamage(c); updateDamage(c);
if (getBackup() == null && !c.isFaceDown() && c.hasBackSide()) { if (getBackup() == null && !c.isFaceDown() && (c.hasBackSide()||c.isFlipCard())) {
set(TrackableProperty.PaperCardBackup, c.getPaperCard()); set(TrackableProperty.PaperCardBackup, c.getPaperCard());
} }
@@ -1300,6 +1301,37 @@ public class CardView extends GameEntityView {
public boolean hasLandwalk() { public boolean hasLandwalk() {
return get(TrackableProperty.HasLandwalk); return get(TrackableProperty.HasLandwalk);
} }
public boolean hasHasAftermath() {
return get(TrackableProperty.HasAftermath);
}
public boolean origProduceAnyMana() {
return get(TrackableProperty.OrigProduceAnyMana);
}
public boolean origProduceManaR() {
return get(TrackableProperty.OrigProduceManaR);
}
public boolean origProduceManaG() {
return get(TrackableProperty.OrigProduceManaG);
}
public boolean origProduceManaB() {
return get(TrackableProperty.OrigProduceManaB);
}
public boolean origProduceManaU() {
return get(TrackableProperty.OrigProduceManaU);
}
public boolean origProduceManaW() {
return get(TrackableProperty.OrigProduceManaW);
}
public boolean origProduceManaC() {
return get(TrackableProperty.OrigProduceManaC);
}
public int origCanProduceColoredMana() {
return get(TrackableProperty.CountOrigProduceColoredMana);
}
public int countBasicLandTypes() {
return get(TrackableProperty.CountBasicLandTypes);
}
public String getAbilityText() { public String getAbilityText() {
return get(TrackableProperty.AbilityText); return get(TrackableProperty.AbilityText);
@@ -1333,6 +1365,7 @@ public class CardView extends GameEntityView {
set(TrackableProperty.HasInfect, c.hasKeyword(Keyword.INFECT, state)); set(TrackableProperty.HasInfect, c.hasKeyword(Keyword.INFECT, state));
set(TrackableProperty.HasStorm, c.hasKeyword(Keyword.STORM, state)); set(TrackableProperty.HasStorm, c.hasKeyword(Keyword.STORM, state));
set(TrackableProperty.HasLandwalk, c.hasKeyword(Keyword.LANDWALK, state)); set(TrackableProperty.HasLandwalk, c.hasKeyword(Keyword.LANDWALK, state));
set(TrackableProperty.HasAftermath, c.hasKeyword(Keyword.AFTERMATH, state));
updateAbilityText(c, state); updateAbilityText(c, state);
//set protectionKey for Icons //set protectionKey for Icons
set(TrackableProperty.ProtectionKey, c.getProtectionKey()); set(TrackableProperty.ProtectionKey, c.getProtectionKey());
@@ -1340,6 +1373,84 @@ public class CardView extends GameEntityView {
set(TrackableProperty.HexproofKey, c.getHexproofKey()); set(TrackableProperty.HexproofKey, c.getHexproofKey());
//keywordkey //keywordkey
set(TrackableProperty.KeywordKey, c.getKeywordKey()); set(TrackableProperty.KeywordKey, c.getKeywordKey());
//update Trackable Mana Color for BG Colors
updateManaColorBG(state);
}
void updateManaColorBG(CardState state) {
boolean anyMana = false;
boolean rMana = false;
boolean gMana = false;
boolean bMana = false;
boolean uMana = false;
boolean wMana = false;
boolean cMana = false;
int count = 0;
int basicLandTypes = 0;
if (!state.getManaAbilities().isEmpty()) {
for (SpellAbility sa : state.getManaAbilities()) {
if (sa == null || sa.getManaPart() == null)
continue;
if (sa.getManaPart().isAnyMana()) {
anyMana = true;
}
switch (sa.getManaPart().getOrigProduced()) {
case "R":
if (!rMana) {
count += 1;
rMana = true;
}
break;
case "G":
if (!gMana) {
count += 1;
gMana = true;
}
break;
case "B":
if (!bMana) {
count += 1;
bMana = true;
}
break;
case "U":
if (!uMana) {
count += 1;
uMana = true;
}
break;
case "W":
if (!wMana) {
count += 1;
wMana = true;
}
break;
case "C":
if (!cMana) {
cMana = true;
}
break;
}
}
}
if (isForest())
basicLandTypes += 1;
if (isMountain())
basicLandTypes += 1;
if (isSwamp())
basicLandTypes += 1;
if (isPlains())
basicLandTypes += 1;
if (isIsland())
basicLandTypes += 1;
set(TrackableProperty.CountBasicLandTypes, basicLandTypes);
set(TrackableProperty.OrigProduceManaR, rMana);
set(TrackableProperty.OrigProduceManaG, gMana);
set(TrackableProperty.OrigProduceManaB, bMana);
set(TrackableProperty.OrigProduceManaU, uMana);
set(TrackableProperty.OrigProduceManaW, wMana);
set(TrackableProperty.OrigProduceManaC, cMana);
set(TrackableProperty.CountOrigProduceColoredMana, count);
set(TrackableProperty.OrigProduceAnyMana, anyMana);
} }
public boolean isBasicLand() { public boolean isBasicLand() {
@@ -1375,6 +1486,12 @@ public class CardView extends GameEntityView {
public boolean isIsland() { public boolean isIsland() {
return getType().hasSubtype("Island"); return getType().hasSubtype("Island");
} }
public boolean isVehicle() {
return getType().hasSubtype("Vehicle");
}
public boolean isArtifact() {
return getType().isArtifact();
}
} }
//special methods for updating card and player properties as needed and returning the new collection //special methods for updating card and player properties as needed and returning the new collection

View File

@@ -111,6 +111,18 @@ public enum TrackableProperty {
HasChangedColors(TrackableTypes.BooleanType), HasChangedColors(TrackableTypes.BooleanType),
ChangedTypes(TrackableTypes.StringMapType), ChangedTypes(TrackableTypes.StringMapType),
//check produce mana for BG
OrigProduceManaR(TrackableTypes.BooleanType),
OrigProduceManaG(TrackableTypes.BooleanType),
OrigProduceManaB(TrackableTypes.BooleanType),
OrigProduceManaU(TrackableTypes.BooleanType),
OrigProduceManaW(TrackableTypes.BooleanType),
OrigProduceManaC(TrackableTypes.BooleanType),
OrigProduceAnyMana(TrackableTypes.BooleanType),
CountOrigProduceColoredMana(TrackableTypes.IntegerType),
//number of basic landtypes
CountBasicLandTypes(TrackableTypes.IntegerType),
KeywordKey(TrackableTypes.StringType), KeywordKey(TrackableTypes.StringType),
HasDeathtouch(TrackableTypes.BooleanType), HasDeathtouch(TrackableTypes.BooleanType),
HasDevoid(TrackableTypes.BooleanType), HasDevoid(TrackableTypes.BooleanType),
@@ -132,6 +144,7 @@ public enum TrackableProperty {
HasTrample(TrackableTypes.BooleanType), HasTrample(TrackableTypes.BooleanType),
HasVigilance(TrackableTypes.BooleanType), HasVigilance(TrackableTypes.BooleanType),
HasLandwalk(TrackableTypes.BooleanType), HasLandwalk(TrackableTypes.BooleanType),
HasAftermath(TrackableTypes.BooleanType),
//protectionkey //protectionkey
ProtectionKey(TrackableTypes.StringType), ProtectionKey(TrackableTypes.StringType),
//hexproofkey //hexproofkey

View File

@@ -472,6 +472,12 @@ public class Graphics {
batch.begin(); batch.begin();
} }
public void drawRectLines(float thickness, Color color, float x, float y, float w, float h) {
drawLine(thickness, color, x, y, x+w, y);
drawLine(thickness, color, x+thickness/2f, y+thickness/2f, x+thickness/2f, y+h-thickness/2f);
drawLine(thickness, color, x, y+h, x+w, y+h);
drawLine(thickness, color, x+w-thickness/2f, y+thickness/2f, x+w-thickness/2f, y+h-thickness/2f);
}
public void fillRect(FSkinColor skinColor, float x, float y, float w, float h) { public void fillRect(FSkinColor skinColor, float x, float y, float w, float h) {
fillRect(skinColor.getColor(), x, y, w, h); fillRect(skinColor.getColor(), x, y, w, h);
@@ -850,6 +856,18 @@ public class Graphics {
//use nifty trick with multiple text renders to draw outlined text //use nifty trick with multiple text renders to draw outlined text
public void drawOutlinedText(String text, FSkinFont skinFont, Color textColor, Color outlineColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically) { public void drawOutlinedText(String text, FSkinFont skinFont, Color textColor, Color outlineColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically) {
drawOutlinedText(text, skinFont, textColor, outlineColor, x, y, w, h, wrap, horzAlignment, centerVertically, false);
}
public void drawOutlinedText(String text, FSkinFont skinFont, Color textColor, Color outlineColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically, boolean shadow) {
if (shadow) {
float oldAlpha = alphaComposite;
alphaComposite = 0.4f;
drawText(text, skinFont, outlineColor, x - 1.5f, y + 1.5f, w, h, wrap, horzAlignment, centerVertically);
drawText(text, skinFont, outlineColor, x + 1.5f, y + 1.5f, w, h, wrap, horzAlignment, centerVertically);
drawText(text, skinFont, outlineColor, x + 1.5f, y - 1.5f, w, h, wrap, horzAlignment, centerVertically);
drawText(text, skinFont, outlineColor, x - 1.5f, y - 1.5f, w, h, wrap, horzAlignment, centerVertically);
alphaComposite = oldAlpha;
}
drawText(text, skinFont, outlineColor, x - 1, y, w, h, wrap, horzAlignment, centerVertically); drawText(text, skinFont, outlineColor, x - 1, y, w, h, wrap, horzAlignment, centerVertically);
drawText(text, skinFont, outlineColor, x, y - 1, w, h, wrap, horzAlignment, centerVertically); drawText(text, skinFont, outlineColor, x, y - 1, w, h, wrap, horzAlignment, centerVertically);
drawText(text, skinFont, outlineColor, x - 1, y - 1, w, h, wrap, horzAlignment, centerVertically); drawText(text, skinFont, outlineColor, x - 1, y - 1, w, h, wrap, horzAlignment, centerVertically);

View File

@@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Matrix4;
@@ -44,8 +45,30 @@ public abstract class FBufferedImage extends FImageComplex {
return 0; return 0;
} }
@Override
public TextureRegion getTextureRegion() {
return new TextureRegion(checkFrameBuffer().getColorBufferTexture());
}
@Override @Override
public Texture getTexture() { public Texture getTexture() {
return checkFrameBuffer().getColorBufferTexture();
}
public void clear() {
final FrameBuffer fb = frameBuffer;
if (fb != null) {
frameBuffer = null;
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
fb.dispose(); //must be disposed on EDT thread
}
});
}
}
public FrameBuffer checkFrameBuffer() {
if (frameBuffer == null) { if (frameBuffer == null) {
Gdx.gl.glDisable(GL20.GL_SCISSOR_TEST); //prevent buffered image being clipped Gdx.gl.glDisable(GL20.GL_SCISSOR_TEST); //prevent buffered image being clipped
@@ -69,20 +92,7 @@ public abstract class FBufferedImage extends FImageComplex {
Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST); Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST);
} }
return frameBuffer.getColorBufferTexture(); return frameBuffer;
}
public void clear() {
final FrameBuffer fb = frameBuffer;
if (fb != null) {
frameBuffer = null;
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
fb.dispose(); //must be disposed on EDT thread
}
});
}
} }
protected abstract void draw(Graphics g, float w, float h); protected abstract void draw(Graphics g, float w, float h);

View File

@@ -3,6 +3,7 @@ package forge.assets;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import forge.Graphics; import forge.Graphics;
//Special wrapper for a texture to be loaded later when it's needed //Special wrapper for a texture to be loaded later when it's needed
@@ -32,6 +33,14 @@ public class FDelayLoadImage extends FImageComplex {
return texture; return texture;
} }
@Override
public TextureRegion getTextureRegion() {
if (texture == null) {
texture = new Texture(Gdx.files.absolute(filename));
}
return new TextureRegion(texture);
}
@Override @Override
public int getRegionX() { public int getRegionX() {
return 0; return 0;

View File

@@ -1,9 +1,11 @@
package forge.assets; package forge.assets;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public abstract class FImageComplex implements FImage { public abstract class FImageComplex implements FImage {
public abstract Texture getTexture(); public abstract Texture getTexture();
public abstract TextureRegion getTextureRegion();
public abstract int getRegionX(); public abstract int getRegionX();
public abstract int getRegionY(); public abstract int getRegionY();
} }

View File

@@ -2,6 +2,7 @@ package forge.assets;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import forge.Graphics; import forge.Graphics;
public class FRotatedImage extends FImageComplex { public class FRotatedImage extends FImageComplex {
@@ -33,6 +34,11 @@ public class FRotatedImage extends FImageComplex {
return texture; return texture;
} }
@Override
public TextureRegion getTextureRegion() {
return new TextureRegion(texture);
}
@Override @Override
public int getRegionX() { public int getRegionX() {
return srcX; return srcX;

View File

@@ -217,9 +217,12 @@ public class FSkin {
final FileHandle f11 = getSkinFile(ForgeConstants.SPRITE_BUTTONS_FILE); final FileHandle f11 = getSkinFile(ForgeConstants.SPRITE_BUTTONS_FILE);
final FileHandle f12 = getSkinFile(ForgeConstants.SPRITE_START_FILE); final FileHandle f12 = getSkinFile(ForgeConstants.SPRITE_START_FILE);
final FileHandle f13 = getDefaultSkinFile(ForgeConstants.SPRITE_DECKBOX_FILE); final FileHandle f13 = getDefaultSkinFile(ForgeConstants.SPRITE_DECKBOX_FILE);
/*TODO Themeable
final FileHandle f14 = getDefaultSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE); final FileHandle f14 = getDefaultSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE);
final FileHandle f15 = getSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE); final FileHandle f15 = getSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE);
final FileHandle f16 = getDefaultSkinFile(ForgeConstants.SPRITE_WATERMARK_FILE); final FileHandle f16 = getDefaultSkinFile(ForgeConstants.SPRITE_WATERMARK_FILE);
*/
try { try {
textures.put(f1.path(), new Texture(f1)); textures.put(f1.path(), new Texture(f1));

View File

@@ -115,6 +115,28 @@ public enum FSkinImage implements FImage {
WATERMARK_W (FSkinProp.IMG_WATERMARK_W, SourceFile.WATERMARKS), WATERMARK_W (FSkinProp.IMG_WATERMARK_W, SourceFile.WATERMARKS),
WATERMARK_C (FSkinProp.IMG_WATERMARK_C, SourceFile.WATERMARKS), WATERMARK_C (FSkinProp.IMG_WATERMARK_C, SourceFile.WATERMARKS),
//CardBG
CARDBG_A (FSkinProp.IMG_CARDBG_A, SourceFile.CARDBG),
CARDBG_B (FSkinProp.IMG_CARDBG_B, SourceFile.CARDBG),
CARDBG_BG (FSkinProp.IMG_CARDBG_BG, SourceFile.CARDBG),
CARDBG_BR (FSkinProp.IMG_CARDBG_BR, SourceFile.CARDBG),
CARDBG_C (FSkinProp.IMG_CARDBG_C, SourceFile.CARDBG),
CARDBG_G (FSkinProp.IMG_CARDBG_G, SourceFile.CARDBG),
CARDBG_L (FSkinProp.IMG_CARDBG_L, SourceFile.CARDBG),
CARDBG_M (FSkinProp.IMG_CARDBG_M, SourceFile.CARDBG),
CARDBG_R (FSkinProp.IMG_CARDBG_R, SourceFile.CARDBG),
CARDBG_RG (FSkinProp.IMG_CARDBG_RG, SourceFile.CARDBG),
CARDBG_U (FSkinProp.IMG_CARDBG_U, SourceFile.CARDBG),
CARDBG_UB (FSkinProp.IMG_CARDBG_UB, SourceFile.CARDBG),
CARDBG_UG (FSkinProp.IMG_CARDBG_UG, SourceFile.CARDBG),
CARDBG_UR (FSkinProp.IMG_CARDBG_UR, SourceFile.CARDBG),
CARDBG_V (FSkinProp.IMG_CARDBG_V, SourceFile.CARDBG),
CARDBG_W (FSkinProp.IMG_CARDBG_W, SourceFile.CARDBG),
CARDBG_WB (FSkinProp.IMG_CARDBG_WB, SourceFile.CARDBG),
CARDBG_WG (FSkinProp.IMG_CARDBG_WG, SourceFile.CARDBG),
CARDBG_WR (FSkinProp.IMG_CARDBG_WR, SourceFile.CARDBG),
CARDBG_WU (FSkinProp.IMG_CARDBG_WU, SourceFile.CARDBG),
//Gameplay //Gameplay
TAP (FSkinProp.IMG_TAP, SourceFile.MANAICONS), TAP (FSkinProp.IMG_TAP, SourceFile.MANAICONS),
UNTAP (FSkinProp.IMG_UNTAP, SourceFile.MANAICONS), UNTAP (FSkinProp.IMG_UNTAP, SourceFile.MANAICONS),
@@ -439,6 +461,7 @@ public enum FSkinImage implements FImage {
MANAICONS(ForgeConstants.SPRITE_MANAICONS_FILE), MANAICONS(ForgeConstants.SPRITE_MANAICONS_FILE),
SETLOGOS(ForgeConstants.SPRITE_SETLOGO_FILE), SETLOGOS(ForgeConstants.SPRITE_SETLOGO_FILE),
WATERMARKS(ForgeConstants.SPRITE_WATERMARK_FILE), WATERMARKS(ForgeConstants.SPRITE_WATERMARK_FILE),
CARDBG(ForgeConstants.SPRITE_CARDBG_FILE),
PLANAR_CONQUEST(ForgeConstants.SPRITE_PLANAR_CONQUEST_FILE); PLANAR_CONQUEST(ForgeConstants.SPRITE_PLANAR_CONQUEST_FILE);
private final String filename; private final String filename;

View File

@@ -2,6 +2,7 @@ package forge.assets;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import forge.Graphics; import forge.Graphics;
public class FTextureImage extends FImageComplex { public class FTextureImage extends FImageComplex {
@@ -26,6 +27,11 @@ public class FTextureImage extends FImageComplex {
return texture; return texture;
} }
@Override
public TextureRegion getTextureRegion() {
return new TextureRegion(texture);
}
@Override @Override
public int getRegionX() { public int getRegionX() {
return 0; return 0;

View File

@@ -27,6 +27,11 @@ public class FTextureRegionImage extends FImageComplex {
return textureRegion.getTexture(); return textureRegion.getTexture();
} }
@Override
public TextureRegion getTextureRegion() {
return textureRegion;
}
@Override @Override
public int getRegionX() { public int getRegionX() {
return textureRegion.getRegionX(); return textureRegion.getRegionX();

View File

@@ -32,7 +32,7 @@ public class CardAvatarImage implements FImage {
@Override @Override
public void draw(Graphics g, float x, float y, float w, float h) { public void draw(Graphics g, float x, float y, float w, float h) {
//force to get the avatar since the the cardartcache & loadingcache is always cleared on screen change or the battle bar will display black //force to get the avatar since the the cardartcache & loadingcache is always cleared on screen change or the battle bar will display black
image = CardRenderer.getCardArt(imageKey, false, false, false); image = CardRenderer.getCardArt(imageKey, false, false, false, false, false, false, false, false);
if (image == null) { if (image == null) {
return; //can't draw anything if can't be loaded yet return; //can't draw anything if can't be loaded yet
} }

View File

@@ -38,14 +38,14 @@ public class CardImage implements FImage {
image = ImageCache.getImage(card); image = ImageCache.getImage(card);
if (image == null) { if (image == null) {
if (!Forge.enableUIMask.equals("Off")) //render this if mask is still loading if (!Forge.enableUIMask.equals("Off")) //render this if mask is still loading
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top); CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top, Forge.enableUIMask.equals("Art"));
return; //can't draw anything if can't be loaded yet return; //can't draw anything if can't be loaded yet
} }
} }
if (image == ImageCache.defaultImage) { if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top); CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top, true);
} }
else { else {
if (Forge.enableUIMask.equals("Full")) { if (Forge.enableUIMask.equals("Full")) {

View File

@@ -6,6 +6,9 @@ import static forge.card.CardRenderer.isModernFrame;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import forge.ImageKeys;
import forge.assets.*;
import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
@@ -15,15 +18,6 @@ import com.google.common.collect.ImmutableList;
import forge.Forge; import forge.Forge;
import forge.Graphics; import forge.Graphics;
import forge.assets.FBufferedImage;
import forge.assets.FImage;
import forge.assets.FSkin;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
import forge.assets.FSkinTexture;
import forge.assets.ImageCache;
import forge.assets.TextRenderer;
import forge.card.CardRenderer.CardStackPosition; import forge.card.CardRenderer.CardStackPosition;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.GameView; import forge.game.GameView;
@@ -48,6 +42,10 @@ public class CardImageRenderer {
private static float prevImageWidth, prevImageHeight; private static float prevImageWidth, prevImageHeight;
private static final float BLACK_BORDER_THICKNESS_RATIO = 0.021f; private static final float BLACK_BORDER_THICKNESS_RATIO = 0.021f;
private static Color fromDetailColor(DetailColors detailColor) {
return FSkinColor.fromRGB(detailColor.r, detailColor.g, detailColor.b);
}
public static void forceStaticFieldUpdate() { public static void forceStaticFieldUpdate() {
//force static fields to be updated the next time a card image is rendered //force static fields to be updated the next time a card image is rendered
prevImageWidth = 0; prevImageWidth = 0;
@@ -78,13 +76,17 @@ public class CardImageRenderer {
public static void drawFaceDownCard(CardView card, Graphics g, float x, float y, float w, float h) { public static void drawFaceDownCard(CardView card, Graphics g, float x, float y, float w, float h) {
//try to draw the card sleeves first //try to draw the card sleeves first
if (FSkin.getSleeves().get(card.getOwner()) != null) FImage sleeves = MatchController.getPlayerSleeve(card.getOwner());
g.drawImage(FSkin.getSleeves().get(card.getOwner()), x, y, w, h); if (sleeves != null)
g.drawImage(sleeves, x, y, w, h);
else else
drawArt(g, x, y, w, h); drawArt(null, g, x, y, w, h, false, true);
} }
public static void drawCardImage(Graphics g, CardView card, boolean altState, float x, float y, float w, float h, CardStackPosition pos) { public static void drawCardImage(Graphics g, CardView card, boolean altState, float x, float y, float w, float h, CardStackPosition pos, boolean useCardBGTexture) {
drawCardImage(g, card, altState, x, y, w, h, pos, useCardBGTexture, false, false);
}
public static void drawCardImage(Graphics g, CardView card, boolean altState, float x, float y, float w, float h, CardStackPosition pos, boolean useCardBGTexture, boolean noText, boolean isChoiceList) {
updateStaticFields(w, h); updateStaticFields(w, h);
float blackBorderThickness = w * BLACK_BORDER_THICKNESS_RATIO; float blackBorderThickness = w * BLACK_BORDER_THICKNESS_RATIO;
@@ -94,8 +96,16 @@ public class CardImageRenderer {
w -= 2 * blackBorderThickness; w -= 2 * blackBorderThickness;
h -= 2 * blackBorderThickness; h -= 2 * blackBorderThickness;
final CardStateView state = card.getState(altState); CardStateView state = altState ? card.getAlternateState() : isChoiceList && card.isSplitCard() ? card.getLeftSplitState() : card.getCurrentState();
final boolean isFaceDown = card.isFaceDown();
final boolean canShow = MatchController.instance.mayView(card); final boolean canShow = MatchController.instance.mayView(card);
//override
if (isFaceDown && altState && card.isSplitCard())
state = card.getLeftSplitState();
boolean isSaga = state.getType().hasSubtype("Saga");
boolean isClass = state.getType().hasSubtype("Class");
boolean isDungeon = state.getType().isDungeon();
boolean drawDungeon = isDungeon && CardRenderer.getCardArt(card) != null;
if (!canShow) { if (!canShow) {
drawFaceDownCard(card, g, x, y, w, h); drawFaceDownCard(card, g, x, y, w, h);
@@ -104,14 +114,12 @@ public class CardImageRenderer {
//determine colors for borders //determine colors for borders
final List<DetailColors> borderColors; final List<DetailColors> borderColors;
final boolean isFaceDown = card.isFaceDown();
if (isFaceDown) { if (isFaceDown) {
borderColors = ImmutableList.of(DetailColors.FACE_DOWN); borderColors = !altState ? ImmutableList.of(DetailColors.FACE_DOWN) : !useCardBGTexture ? ImmutableList.of(DetailColors.FACE_DOWN) : CardDetailUtil.getBorderColors(state, canShow);
} } else {
else {
borderColors = CardDetailUtil.getBorderColors(state, canShow); borderColors = CardDetailUtil.getBorderColors(state, canShow);
} }
Color[] colors = fillColorBackground(g, borderColors, x, y, w, h); Color[] colors = useCardBGTexture ? drawCardBackgroundTexture(state, g, borderColors, x, y, w, h) : fillColorBackground(g, borderColors, x, y, w, h);
float artInset = blackBorderThickness * 0.5f; float artInset = blackBorderThickness * 0.5f;
float outerBorderThickness = 2 * blackBorderThickness - artInset; float outerBorderThickness = 2 * blackBorderThickness - artInset;
@@ -122,7 +130,7 @@ public class CardImageRenderer {
//draw header containing name and mana cost //draw header containing name and mana cost
Color[] headerColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.NAME_BOX_TINT); Color[] headerColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.NAME_BOX_TINT);
drawHeader(g, card, state, headerColors, x, y, w, headerHeight); drawHeader(g, card, state, headerColors, x, y, w, headerHeight, isFaceDown && !altState);
if (pos == CardStackPosition.BehindVert) { return; } //remaining rendering not needed if card is behind another card in a vertical stack if (pos == CardStackPosition.BehindVert) { return; } //remaining rendering not needed if card is behind another card in a vertical stack
boolean onTop = (pos == CardStackPosition.Top); boolean onTop = (pos == CardStackPosition.Top);
@@ -156,53 +164,95 @@ public class CardImageRenderer {
//draw art box with Forge icon //draw art box with Forge icon
if (artHeight > 0) { if (artHeight > 0) {
drawArt(g, x + artInset, y, artWidth, artHeight); if (isSaga)
drawArt(card, g, x + artInset+(artWidth/2), y, artWidth/2, artHeight+textBoxHeight, altState, isFaceDown);
else if (isClass)
drawArt(card, g, x + artInset, y, artWidth/2, artHeight+textBoxHeight, altState, isFaceDown);
else if (isDungeon) {
if (drawDungeon) {
drawArt(card, g, x + artInset, y, artWidth, artHeight+textBoxHeight, altState, isFaceDown);
y += textBoxHeight;
}
}
else
drawArt(card, g, x + artInset, y, artWidth, artHeight, altState, isFaceDown);
y += artHeight; y += artHeight;
} }
//draw type line if (isSaga) {
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight); //draw text box
y += typeBoxHeight; Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT);
drawTextBox(g, card, state, textBoxColors, x + artInset, y-artHeight, (w - 2 * artInset)/2, textBoxHeight+artHeight, onTop, useCardBGTexture, noText);
y += textBoxHeight;
//draw text box //draw type line
Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT); drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight, noText);
drawTextBox(g, card, state, textBoxColors, x + artInset, y, w - 2 * artInset, textBoxHeight, onTop); y += typeBoxHeight;
y += textBoxHeight; } else if (isClass) {
//draw text box
Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT);
drawTextBox(g, card, state, textBoxColors, x + artInset+(artWidth/2), y-artHeight, (w - 2 * artInset)/2, textBoxHeight+artHeight, onTop, useCardBGTexture, noText);
y += textBoxHeight;
//draw type line
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight, noText);
y += typeBoxHeight;
} else if (isDungeon) {
if (!drawDungeon) {
//draw textbox
Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT);
drawTextBox(g, card, state, textBoxColors, x + artInset, y-artHeight, (w - 2 * artInset), textBoxHeight+artHeight, onTop, useCardBGTexture, noText);
y += textBoxHeight;
}
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight, noText);
y += typeBoxHeight;
} else {
//draw type line
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight, noText);
y += typeBoxHeight;
//draw text box
Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT);
drawTextBox(g, card, state, textBoxColors, x + artInset, y, w - 2 * artInset, textBoxHeight, onTop, useCardBGTexture, noText);
y += textBoxHeight;
}
//draw P/T box //draw P/T box
if (onTop && ptBoxHeight > 0) { if (onTop && ptBoxHeight > 0) {
//only needed if on top since otherwise P/T will be hidden //only needed if on top since otherwise P/T will be hidden
Color[] ptColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.PT_BOX_TINT); Color[] ptColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.PT_BOX_TINT);
drawPtBox(g, card, state, ptColors, x, y - 2 * artInset, w, ptBoxHeight); drawPtBox(g, card, state, ptColors, x, y - 2 * artInset, w, ptBoxHeight, noText);
} }
} }
private static void drawHeader(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h) { private static void drawHeader(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h, boolean noText) {
fillColorBackground(g, colors, x, y, w, h); fillColorBackground(g, colors, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h); g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
float padding = h / 8; float padding = h / 8;
//draw mana cost for card
float manaCostWidth = 0; float manaCostWidth = 0;
ManaCost mainManaCost = state.getManaCost(); if (!noText) {
if (card.isSplitCard() && card.getAlternateState() != null) { //draw mana cost for card
//handle rendering both parts of split card ManaCost mainManaCost = state.getManaCost();
mainManaCost = card.getLeftSplitState().getManaCost(); if (card.isSplitCard() && card.getAlternateState() != null) {
ManaCost otherManaCost = card.getAlternateState().getManaCost(); //handle rendering both parts of split card
manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING; mainManaCost = card.getLeftSplitState().getManaCost();
CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE); ManaCost otherManaCost = card.getRightSplitState().getManaCost();
//draw "//" between two parts of mana cost manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING;
manaCostWidth += NAME_FONT.getBounds("//").width + HEADER_PADDING; CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
g.drawText("//", NAME_FONT, Color.BLACK, x + w - manaCostWidth, y, w, h, false, Align.left, true); //draw "//" between two parts of mana cost
manaCostWidth += NAME_FONT.getBounds("//").width + HEADER_PADDING;
g.drawText("//", NAME_FONT, Color.BLACK, x + w - manaCostWidth, y, w, h, false, Align.left, true);
}
manaCostWidth += CardFaceSymbols.getWidth(mainManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING;
CardFaceSymbols.drawManaCost(g, mainManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
} }
manaCostWidth += CardFaceSymbols.getWidth(mainManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING;
CardFaceSymbols.drawManaCost(g, mainManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
//draw name for card //draw name for card
x += padding; x += padding;
w -= 2 * padding; w -= 2 * padding;
g.drawText(CardTranslation.getTranslatedName(state.getName()), NAME_FONT, Color.BLACK, x, y, w - manaCostWidth - padding, h, false, Align.left, true); if (!noText)
g.drawText(CardTranslation.getTranslatedName(state.getName()), NAME_FONT, Color.BLACK, x, y, w - manaCostWidth - padding, h, false, Align.left, true);
} }
public static final FBufferedImage forgeArt; public static final FBufferedImage forgeArt;
@@ -221,12 +271,95 @@ public class CardImageRenderer {
}; };
} }
private static void drawArt(Graphics g, float x, float y, float w, float h) { private static void drawArt(CardView cv, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) {
g.drawImage(forgeArt, x, y, w, h); if (cv == null) {
if (isFaceDown) {
Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), false);
if (cardBack != null) {
g.drawImage(cardBack, x, y, w, h);
return;
}
}
//fallback
g.drawImage(forgeArt, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
return;
}
if (Forge.enableUIMask.equals("Art")) {
FImageComplex cardArt = CardRenderer.getCardArt(cv);
FImageComplex altArt = cardArt;
boolean isHidden = (cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD))
|| cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.FORETELL_IMAGE)));
if (cardArt != null) {
if (isHidden && !altState) {
g.drawImage(forgeArt, x, y, w, h);
} else if (cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.MANIFEST_IMAGE)) && !altState) {
altArt = CardRenderer.getAlternateCardArt(ImageKeys.getTokenKey(ImageKeys.MANIFEST_IMAGE), false);
g.drawImage(altArt, x, y, w, h);
} else if (cv.getCurrentState().getImageKey().equals(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE)) && !altState) {
altArt = CardRenderer.getAlternateCardArt(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE), false);
g.drawImage(altArt, x, y, w, h);
} else {
if (cv.hasAlternateState()) {
if (altState) {
if (cv.getAlternateState().isPlaneswalker())
altArt = CardRenderer.getAlternateCardArt(cv.getAlternateState().getImageKey(), cv.getAlternateState().isPlaneswalker());
else {
altArt = CardRenderer.getCardArt(cv.getAlternateState().getImageKey(), cv.isSplitCard(), cv.getAlternateState().isPlane() || cv.getAlternateState().isPhenomenon(), cv.getText().contains("Aftermath"),
cv.getAlternateState().getType().hasSubtype("Saga"), cv.getAlternateState().getType().hasSubtype("Class"), cv.getAlternateState().getType().isDungeon(), cv.isFlipCard(), cv.getAlternateState().isPlaneswalker());
}
}
}
if (cv.isSplitCard()) {
drawSplitCard(cv, altArt, g, x, y, w, h, altState, isFaceDown);
} else if (cv.isFlipCard()) {
drawFlipCard(isFaceDown ? altArt : cardArt, g, x, y, w, h, altState);
} else {
g.drawImage(altArt, x, y, w, h);
}
}
} else {
g.drawImage(forgeArt, x, y, w, h);
}
} else {
g.drawImage(forgeArt, x, y, w, h);
}
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h); g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
} }
private static void drawSplitCard(CardView card, FImageComplex cardArt, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) {
private static void drawTypeLine(Graphics g, CardView card, CardStateView state, boolean canShow, Color[] colors, float x, float y, float w, float h) { CardView alt = CardView.getCardForUi(ImageUtil.getPaperCardFromImageKey(card.getAlternateState().getImageKey()));
if (alt == null)
alt = card.getAlternateState().getCard();
CardView cv = altState && isFaceDown ? alt : card;
boolean isAftermath = altState ? cv.getAlternateState().hasHasAftermath(): cv.getRightSplitState().hasHasAftermath();
if (!isAftermath) {
CardEdition ed = FModel.getMagicDb().getEditions().get(cv.getCurrentState().getSetCode());
boolean isOldFrame = ed != null && !ed.isModern();
float modH = isOldFrame ? cardArt.getHeight()/12f : 0f;
float modW = !isOldFrame ? cardArt.getWidth()/12f : 0f;
float modW2 = !isOldFrame ? cardArt.getWidth()/6f : 0f;
float srcY = cardArt.getHeight() * 13f / 354f;
float srcHeight = cardArt.getHeight() * 190f / 354f;
float dh = srcHeight * (1 - cardArt.getWidth() / srcHeight / CardRenderer.CARD_ART_RATIO);
srcHeight -= dh;
srcY += dh / 2;
g.drawRotatedImage(cardArt.getTexture(), x, y, h+modH, w / 2, x + w / 2, y + w / 2, cardArt.getRegionX()+(int)modW, (int)srcY, (int)(cardArt.getWidth()-modW2), (int)srcHeight, -90);
g.drawRotatedImage(cardArt.getTexture(), x, y + w / 2, h+modH, w / 2, x + w / 2, y + w / 2, cardArt.getRegionX()+(int)modW, (int)cardArt.getHeight() - (int)(srcY + srcHeight), (int)(cardArt.getWidth()-modW2), (int)srcHeight, -90);
g.drawLine(BORDER_THICKNESS, Color.BLACK, x+w/2, y, x+w/2, y+h);
} else {
FImageComplex secondArt = CardRenderer.getAftermathSecondCardArt(cv.getCurrentState().getImageKey());
g.drawRotatedImage(cardArt.getTexture(), x, y, w, h / 2, x + w, y + h / 2, cardArt.getRegionX(), cardArt.getRegionY(), (int)cardArt.getWidth(), (int)cardArt.getHeight() /2, 0);
g.drawRotatedImage(secondArt.getTexture(), x - h / 2 , y + h / 2, h /2, w, x, y + h / 2, secondArt.getRegionX(), secondArt.getRegionY(), (int)secondArt.getWidth(), (int)secondArt.getHeight(), 90);
g.drawLine(BORDER_THICKNESS, Color.BLACK, x, y+h/2, x+w, y+h/2);
}
}
private static void drawFlipCard(FImageComplex cardArt, Graphics g, float x, float y, float w, float h, boolean altState) {
if (altState)
g.drawRotatedImage(cardArt.getTextureRegion(), x, y, w, h, x + w / 2, y + h / 2, 180);
else
g.drawImage(cardArt, x, y, w, h);
}
private static void drawTypeLine(Graphics g, CardView card, CardStateView state, boolean canShow, Color[] colors, float x, float y, float w, float h, boolean noText) {
fillColorBackground(g, colors, x, y, w, h); fillColorBackground(g, colors, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h); g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
@@ -252,6 +385,8 @@ public class CardImageRenderer {
} }
//draw type //draw type
if (noText)
return;
x += padding; x += padding;
g.drawText(CardDetailUtil.formatCardType(state, canShow), TYPE_FONT, Color.BLACK, x, y, w, h, false, Align.left, true); g.drawText(CardDetailUtil.formatCardType(state, canShow), TYPE_FONT, Color.BLACK, x, y, w, h, false, Align.left, true);
} }
@@ -259,7 +394,9 @@ public class CardImageRenderer {
//use text renderer to handle mana symbols and reminder text //use text renderer to handle mana symbols and reminder text
private static final TextRenderer cardTextRenderer = new TextRenderer(true); private static final TextRenderer cardTextRenderer = new TextRenderer(true);
private static void drawTextBox(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h, boolean onTop) { private static void drawTextBox(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h, boolean onTop, boolean useCardBGTexture, boolean noText) {
boolean fakeDuals = false;
//update land bg colors
if (state.isLand()) { if (state.isLand()) {
DetailColors modColors = DetailColors.WHITE; DetailColors modColors = DetailColors.WHITE;
if (state.isBasicLand()) { if (state.isBasicLand()) {
@@ -273,49 +410,137 @@ public class CardImageRenderer {
modColors = DetailColors.BLACK; modColors = DetailColors.BLACK;
else if (state.isPlains()) else if (state.isPlains())
modColors = DetailColors.LAND; modColors = DetailColors.LAND;
} if (state.origCanProduceColoredMana() == 2) {
//dual colors
Color[] colorPairs = new Color[2];
Color[] colorPairsBackup = new Color[2];
//init Color
colorPairs[0] = fromDetailColor(DetailColors.WHITE);
colorPairs[1] = fromDetailColor(DetailColors.WHITE);
//override
if (state.origProduceAnyMana()) {
colorPairs[0] = fromDetailColor(DetailColors.MULTICOLOR);
colorPairs[1] = fromDetailColor(DetailColors.MULTICOLOR);
} else {
fakeDuals = true;
if (state.origProduceManaW() && state.origProduceManaU()) {
colorPairs[0] = fromDetailColor(DetailColors.LAND);
colorPairs[1] = fromDetailColor(DetailColors.BLUE);
} else if (state.origProduceManaW() && state.origProduceManaB()) {
colorPairs[0] = fromDetailColor(DetailColors.LAND);
colorPairs[1] = fromDetailColor(DetailColors.BLACK);
} else if (state.origProduceManaW() && state.origProduceManaR()) {
colorPairs[0] = fromDetailColor(DetailColors.LAND);
colorPairs[1] = fromDetailColor(DetailColors.RED);
} else if (state.origProduceManaW() && state.origProduceManaG()) {
colorPairs[0] = fromDetailColor(DetailColors.LAND);
colorPairs[1] = fromDetailColor(DetailColors.GREEN);
} else if (state.origProduceManaU() && state.origProduceManaB()) {
colorPairs[0] = fromDetailColor(DetailColors.BLUE);
colorPairs[1] = fromDetailColor(DetailColors.BLACK);
} else if (state.origProduceManaU() && state.origProduceManaR()) {
colorPairs[0] = fromDetailColor(DetailColors.BLUE);
colorPairs[1] = fromDetailColor(DetailColors.RED);
} else if (state.origProduceManaU() && state.origProduceManaG()) {
colorPairs[0] = fromDetailColor(DetailColors.BLUE);
colorPairs[1] = fromDetailColor(DetailColors.GREEN);
} else if (state.origProduceManaB() && state.origProduceManaR()) {
colorPairs[0] = fromDetailColor(DetailColors.BLACK);
colorPairs[1] = fromDetailColor(DetailColors.RED);
} else if (state.origProduceManaB() && state.origProduceManaG()) {
colorPairs[0] = fromDetailColor(DetailColors.BLACK);
colorPairs[1] = fromDetailColor(DetailColors.GREEN);
} else if (state.origProduceManaR() && state.origProduceManaG()) {
colorPairs[0] = fromDetailColor(DetailColors.RED);
colorPairs[1] = fromDetailColor(DetailColors.GREEN);
}
}
colorPairsBackup = colorPairs;
colorPairs = FSkinColor.tintColors(Color.WHITE, colorPairs, 0.3f);
float oldAlpha = g.getfloatAlphaComposite();
if (!useCardBGTexture)
fillColorBackground(g, colorPairs, x, y, w, h);
else {
g.setAlphaComposite(0.95f);
fillColorBackground(g, colorPairs, x, y, w, h);
if (fakeDuals && state.countBasicLandTypes() == 2) {
float thickness = h/16f;
float mod = 2f*thickness/2f;
g.setAlphaComposite(0.2f);
drawAlphaLines(colorPairsBackup, g, x, y, w, h, thickness, mod);
}
g.setAlphaComposite(oldAlpha);
}
} else {
//override bg color
if (state.origCanProduceColoredMana() > 2 || state.origProduceAnyMana()) {
modColors = DetailColors.MULTICOLOR;
} else if (state.origCanProduceColoredMana() == 1) {
if (state.origProduceManaW())
modColors = DetailColors.LAND;
else if (state.origProduceManaB())
modColors = DetailColors.BLACK;
else if (state.origProduceManaG())
modColors = DetailColors.GREEN;
else if (state.origProduceManaR())
modColors = DetailColors.RED;
else if (state.origProduceManaU())
modColors = DetailColors.BLUE;
}
Color bgColor = fromDetailColor(modColors);
bgColor = FSkinColor.tintColor(Color.WHITE, bgColor, CardRenderer.NAME_BOX_TINT);
float oldAlpha = g.getfloatAlphaComposite();
if (!useCardBGTexture)
g.fillRect(bgColor, x, y, w, h);
else {
g.setAlphaComposite(0.95f);
g.fillRect(bgColor, x, y, w, h);
g.setAlphaComposite(oldAlpha);
}
} }
Color bgColor = FSkinColor.fromRGB(modColors.r, modColors.g, modColors.b);
bgColor = FSkinColor.tintColor(Color.WHITE, bgColor, CardRenderer.NAME_BOX_TINT);
g.fillRect(bgColor, x, y, w, h);
} else { } else {
fillColorBackground(g, colors, x, y, w, h); float oldAlpha = g.getfloatAlphaComposite();
if (!useCardBGTexture)
fillColorBackground(g, colors, x, y, w, h);
else {
g.setAlphaComposite(0.95f);
fillColorBackground(g, colors, x, y, w, h);
g.setAlphaComposite(oldAlpha);
}
} }
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h); g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
if (!onTop) { return; } //remaining rendering only needed if card on top if (!onTop) { return; } //remaining rendering only needed if card on top
if (state.isBasicLand()) { if (state.isBasicLand()) {
//draw icons for basic lands //draw watermark
FSkinImage image; FSkinImage image = null;
switch (state.getName().replaceFirst("^Snow-Covered ", "")) { if (state.origCanProduceColoredMana() == 1 && !state.origProduceManaC()) {
case "Plains": if (state.isPlains())
image = FSkinImage.WATERMARK_W; image = FSkinImage.WATERMARK_W;
break; else if (state.isIsland())
case "Island": image = FSkinImage.WATERMARK_U;
image = FSkinImage.WATERMARK_U; else if (state.isSwamp())
break; image = FSkinImage.WATERMARK_B;
case "Swamp": else if (state.isMountain())
image = FSkinImage.WATERMARK_B; image = FSkinImage.WATERMARK_R;
break; else if (state.isForest())
case "Mountain": image = FSkinImage.WATERMARK_G;
image = FSkinImage.WATERMARK_R; } else if (state.origProduceManaC()) {
break;
case "Forest":
image = FSkinImage.WATERMARK_G;
break;
default:
image = FSkinImage.WATERMARK_C; image = FSkinImage.WATERMARK_C;
break;
} }
float iconSize = h * 0.75f; if (image != null) {
g.drawImage(image, x + (w - iconSize) / 2, y + (h - iconSize) / 2, iconSize, iconSize); float iconSize = h * 0.75f;
} g.drawImage(image, x + (w - iconSize) / 2, y + (h - iconSize) / 2, iconSize, iconSize);
else { }
} else {
boolean needTranslation = true; boolean needTranslation = true;
if (card.isToken()) { if (card.isToken()) {
if (card.getCloneOrigin() == null) if (card.getCloneOrigin() == null)
needTranslation = false; needTranslation = false;
} }
if (noText)
return;
final String text = !card.isSplitCard() ? final String text = !card.isSplitCard() ?
card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null) : card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.getName(), "") : null) :
card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(card.getLeftSplitState().getName(), card.getRightSplitState().getName()) : null ); card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(card.getLeftSplitState().getName(), card.getRightSplitState().getName()) : null );
@@ -329,8 +554,24 @@ public class CardImageRenderer {
cardTextRenderer.drawText(g, text, TEXT_FONT, Color.BLACK, x, y, w, h, y, h, true, Align.left, true); cardTextRenderer.drawText(g, text, TEXT_FONT, Color.BLACK, x, y, w, h, y, h, true, Align.left, true);
} }
} }
private static void drawAlphaLines(Color[] colors, Graphics g, float x, float y, float w, float h, float thickness, float mod) {
private static void drawPtBox(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h) { g.drawRectLines(thickness, colors[1], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 4f*thickness/2f;
g.drawRectLines(thickness, colors[0], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 6f*thickness/2f;
g.drawRectLines(thickness, colors[1], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 8f*thickness/2f;
g.drawRectLines(thickness, colors[0], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 10f*thickness/2f;
g.drawRectLines(thickness, colors[1], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 12f*thickness/2f;
g.drawRectLines(thickness, colors[0], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 14f*thickness/2f;
g.drawRectLines(thickness, colors[1], x+mod, y+mod, w-(mod*2f), h-(mod*2f));
mod = 16f*thickness/2f;
g.drawLine(thickness, colors[1], x+mod, y+mod, x+w-mod, y+mod);
}
private static void drawPtBox(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h, boolean noText) {
List<String> pieces = new ArrayList<>(); List<String> pieces = new ArrayList<>();
if (state.isCreature()) { if (state.isCreature()) {
pieces.add(String.valueOf(state.getPower())); pieces.add(String.valueOf(state.getPower()));
@@ -369,6 +610,8 @@ public class CardImageRenderer {
fillColorBackground(g, colors, x, y, w, h); fillColorBackground(g, colors, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h); g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
if (noText)
return;
x += (boxWidth - totalPieceWidth) / 2; x += (boxWidth - totalPieceWidth) / 2;
for (int i = 0; i < pieces.size(); i++) { for (int i = 0; i < pieces.size(); i++) {
g.drawText(pieces.get(i), PT_FONT, Color.BLACK, x, y, w, h, false, Align.left, true); g.drawText(pieces.get(i), PT_FONT, Color.BLACK, x, y, w, h, false, Align.left, true);
@@ -399,8 +642,8 @@ public class CardImageRenderer {
return; return;
} }
if (image == ImageCache.defaultImage) { //support drawing card image manually if card image not found if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) { //support drawing card image manually if card image not found
drawCardImage(g, card, altState, x, y, w, h, CardStackPosition.Top); drawCardImage(g, card, altState, x, y, w, h, CardStackPosition.Top, true);
} else { } else {
float radius = (h - w)/8; float radius = (h - w)/8;
float wh_Adj = ForgeConstants.isGdxPortLandscape && isCurrentCard ? 1.38f:1.0f; float wh_Adj = ForgeConstants.isGdxPortLandscape && isCurrentCard ? 1.38f:1.0f;
@@ -517,11 +760,79 @@ public class CardImageRenderer {
Color[] colors = new Color[backColors.size()]; Color[] colors = new Color[backColors.size()];
for (int i = 0; i < colors.length; i++) { for (int i = 0; i < colors.length; i++) {
DetailColors dc = backColors.get(i); DetailColors dc = backColors.get(i);
colors[i] = FSkinColor.fromRGB(dc.r, dc.g, dc.b); colors[i] = fromDetailColor(dc);
} }
fillColorBackground(g, colors, x, y, w, h); fillColorBackground(g, colors, x, y, w, h);
return colors; return colors;
} }
public static Color[] drawCardBackgroundTexture(CardStateView state, Graphics g, List<DetailColors> backColors, float x, float y, float w, float h) {
boolean isHybrid = state.getManaCost().hasHybrid();
Color[] colors = new Color[backColors.size()];
for (int i = 0; i < colors.length; i++) {
DetailColors dc = backColors.get(i);
colors[i] = fromDetailColor(dc);
}
switch (backColors.size()) {
case 1:
if (backColors.get(0) == DetailColors.FACE_DOWN) {
g.drawImage(FSkinImage.CARDBG_C, x, y, w,h);
} else if (backColors.get(0) == DetailColors.LAND) {
g.drawImage(FSkinImage.CARDBG_L, x, y, w,h);
}else if (backColors.get(0) == DetailColors.MULTICOLOR) {
g.drawImage(FSkinImage.CARDBG_M, x, y, w,h);
} else if (backColors.get(0) == DetailColors.COLORLESS) {
if (state.isVehicle())
g.drawImage(FSkinImage.CARDBG_V, x, y, w,h);
else if (state.isArtifact())
g.drawImage(FSkinImage.CARDBG_A, x, y, w,h);
else
g.drawImage(FSkinImage.CARDBG_C, x, y, w,h);
} else if (backColors.get(0) == DetailColors.GREEN) {
g.drawImage(FSkinImage.CARDBG_G, x, y, w,h);
} else if (backColors.get(0) == DetailColors.RED) {
g.drawImage(FSkinImage.CARDBG_R, x, y, w,h);
} else if (backColors.get(0) == DetailColors.BLACK) {
g.drawImage(FSkinImage.CARDBG_B, x, y, w,h);
} else if (backColors.get(0) == DetailColors.BLUE) {
g.drawImage(FSkinImage.CARDBG_U, x, y, w,h);
} else if (backColors.get(0) == DetailColors.WHITE) {
g.drawImage(FSkinImage.CARDBG_W, x, y, w,h);
}
break;
case 2:
if (!isHybrid) {
g.drawImage(FSkinImage.CARDBG_M, x, y, w, h);
} else if (backColors.contains(DetailColors.WHITE) && backColors.contains(DetailColors.BLUE)) {
g.drawImage(FSkinImage.CARDBG_WU, x, y, w, h);
} else if (backColors.contains(DetailColors.WHITE) && backColors.contains(DetailColors.BLACK)) {
g.drawImage(FSkinImage.CARDBG_WB, x, y, w, h);
} else if (backColors.contains(DetailColors.WHITE) && backColors.contains(DetailColors.RED)) {
g.drawImage(FSkinImage.CARDBG_WR, x, y, w, h);
} else if (backColors.contains(DetailColors.WHITE) && backColors.contains(DetailColors.GREEN)) {
g.drawImage(FSkinImage.CARDBG_WG, x, y, w, h);
} else if (backColors.contains(DetailColors.BLUE) && backColors.contains(DetailColors.BLACK)) {
g.drawImage(FSkinImage.CARDBG_UB, x, y, w, h);
} else if (backColors.contains(DetailColors.BLUE) && backColors.contains(DetailColors.RED)) {
g.drawImage(FSkinImage.CARDBG_UR, x, y, w, h);
} else if (backColors.contains(DetailColors.BLUE) && backColors.contains(DetailColors.GREEN)) {
g.drawImage(FSkinImage.CARDBG_UG, x, y, w, h);
} else if (backColors.contains(DetailColors.BLACK) && backColors.contains(DetailColors.RED)) {
g.drawImage(FSkinImage.CARDBG_BR, x, y, w, h);
} else if (backColors.contains(DetailColors.BLACK) && backColors.contains(DetailColors.GREEN)) {
g.drawImage(FSkinImage.CARDBG_BG, x, y, w, h);
} else if (backColors.contains(DetailColors.RED) && backColors.contains(DetailColors.GREEN)) {
g.drawImage(FSkinImage.CARDBG_RG, x, y, w, h);
}
break;
case 3:
g.drawImage(FSkinImage.CARDBG_M, x, y, w, h);
break;
default:
g.drawImage(FSkinImage.CARDBG_C, x, y, w,h);
break;
}
return colors;
}
public static void fillColorBackground(Graphics g, Color[] colors, float x, float y, float w, float h) { public static void fillColorBackground(Graphics g, Color[] colors, float x, float y, float w, float h) {
switch (colors.length) { switch (colors.length) {
case 1: case 1:

View File

@@ -207,15 +207,15 @@ public class CardRenderer {
public static FImageComplex getCardArt(IPaperCard pc, boolean backFace) { public static FImageComplex getCardArt(IPaperCard pc, boolean backFace) {
CardType type = pc.getRules().getType(); CardType type = pc.getRules().getType();
return getCardArt(pc.getImageKey(backFace), pc.getRules().getSplitType() == CardSplitType.Split, type.isPlane() || type.isPhenomenon(),pc.getRules().getOracleText().contains("Aftermath")); return getCardArt(pc.getImageKey(backFace), pc.getRules().getSplitType() == CardSplitType.Split, type.isPlane() || type.isPhenomenon(),pc.getRules().getOracleText().contains("Aftermath"), type.hasSubtype("Saga"), type.hasSubtype("Class"), type.isDungeon(), CardSplitType.Flip.equals(pc.getRules().getSplitType()), type.isPlaneswalker());
} }
public static FImageComplex getCardArt(CardView card) { public static FImageComplex getCardArt(CardView card) {
CardTypeView type = card.getCurrentState().getType(); CardTypeView type = card.getCurrentState().getType();
return getCardArt(card.getCurrentState().getImageKey(), card.isSplitCard(), type.isPlane() || type.isPhenomenon(),card.getText().contains("Aftermath")); return getCardArt(card.getCurrentState().getImageKey(), card.isSplitCard(), type.isPlane() || type.isPhenomenon(),card.getText().contains("Aftermath"), type.hasSubtype("Saga"), type.hasSubtype("Class"), type.isDungeon(), card.isFlipCard(), type.isPlaneswalker());
} }
public static FImageComplex getCardArt(String imageKey, boolean isSplitCard, boolean isHorizontalCard, boolean isAftermathCard) { public static FImageComplex getCardArt(String imageKey, boolean isSplitCard, boolean isHorizontalCard, boolean isAftermathCard, boolean isSaga, boolean isClass, boolean isDungeon, boolean isFlipCard, boolean isPlanesWalker) {
FImageComplex cardArt = cardArtCache.get(imageKey); FImageComplex cardArt = cardArtCache.get(imageKey);
if (cardArt == null) { if (cardArt == null) {
Texture image = new RendererCachedCardImage(imageKey, true).getImage(); Texture image = new RendererCachedCardImage(imageKey, true).getImage();
@@ -227,12 +227,36 @@ public class CardRenderer {
float x, y; float x, y;
float w = image.getWidth(); float w = image.getWidth();
float h = image.getHeight(); float h = image.getHeight();
if (isSplitCard && !isAftermathCard) { //allow rotated image for split cards if (isPlanesWalker) {
x = w * 0.09f;
y = h * 0.11f;
w -= 2f * x;
h -= 5.71f * y;
} else if (isFlipCard) {
x = w * 0.09f;
y = h * 0.32f;
w -= 2f * x;
h -= 2.1f * y;
} else if (isDungeon) {
x = w * 0.09f;
y = h * 0.1f;
w -= 2f * x;
h -= 2.2f * y;
} else if (isClass) {
x = w * 0.09f;
y = h * 0.11f;
w -= 1.1f * x + w / 2;
h -= 2.45f * y;
} else if (isSaga) {
x = (w * 0.1f) + (w * 0.8f / 2);
y = h * 0.11f;
w -= 1.16f * x;
h -= 2.45f * y;
} else if (isSplitCard && !isAftermathCard) { //allow rotated image for split cards
x = w * 33f / 250f; x = w * 33f / 250f;
y = 0; //delay adjusting y and h until drawn y = 0; //delay adjusting y and h until drawn
w *= 106f / 250f; w *= 106f / 250f;
} } else if (isHorizontalCard) { //allow rotated image for horizontal cards
else if (isHorizontalCard) { //allow rotated image for horizontal cards
float artX = 40f, artY = 40f; float artX = 40f, artY = 40f;
float artW = 350f, artH = 156f; float artW = 350f, artH = 156f;
float srcW = 430f, srcH = 300f; float srcW = 430f, srcH = 300f;
@@ -241,8 +265,7 @@ public class CardRenderer {
y = h * 40f / srcH; y = h * 40f / srcH;
w *= artW / srcW; w *= artW / srcW;
h *= artH / srcH; h *= artH / srcH;
} } else { //rotate art clockwise if its not the correct orientation
else { //rotate art clockwise if its not the correct orientation
x = w * artY / srcH; x = w * artY / srcH;
y = h * (srcW - artW - artX) / srcW; y = h * (srcW - artW - artX) / srcW;
w *= artH / srcH; w *= artH / srcH;
@@ -251,8 +274,7 @@ public class CardRenderer {
cardArtCache.put(imageKey, cardArt); cardArtCache.put(imageKey, cardArt);
return cardArt; return cardArt;
} }
} } else {
else {
x = w * 0.1f; x = w * 0.1f;
y = h * 0.11f; y = h * 0.11f;
w -= 2 * x; w -= 2 * x;
@@ -262,8 +284,7 @@ public class CardRenderer {
float dw = w * (ratioRatio - 1); float dw = w * (ratioRatio - 1);
w -= dw; w -= dw;
x += dw / 2; x += dw / 2;
} } else { //if too tall, shrink height
else { //if too tall, shrink height
float dh = h * (1 - ratioRatio); float dh = h * (1 - ratioRatio);
h -= dh; h -= dh;
y += dh / 2; y += dh / 2;
@@ -290,16 +311,15 @@ public class CardRenderer {
if (image != null) { if (image != null) {
if (image == ImageCache.defaultImage) { if (image == ImageCache.defaultImage) {
cardArt = CardImageRenderer.forgeArt; cardArt = CardImageRenderer.forgeArt;
} } else {
else {
float x, y; float x, y;
float w = image.getWidth(); float w = image.getWidth();
float h = image.getHeight(); float h = image.getHeight();
//allow rotated image for split cards //allow rotated image for split cards
x = w * 138f / 250f; x = w * 138f / 250f;
y = h * 210f / 370f; //delay adjusting y and h until drawn y = h * 210f / 370f; //delay adjusting y and h until drawn
w *= 68f / 250f; w *= 68f / 250f;
h *= 128f / 370f; h *= 128f / 370f;
cardArt = new FTextureRegionImage(new TextureRegion(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h))); cardArt = new FTextureRegionImage(new TextureRegion(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h)));
@@ -310,6 +330,52 @@ public class CardRenderer {
return cardArt; return cardArt;
} }
public static FImageComplex getAlternateCardArt(final String imageKey, boolean isPlanesWalker) {
FImageComplex cardArt = cardArtCache.get("Alternate_"+imageKey);
if (cardArt == null) {
Texture image = new CachedCardImage(imageKey) {
@Override
public void onImageFetched() {
ImageCache.clear();
cardArtCache.remove("Alternate_" + imageKey);
}
}.getImage();
if (image != null) {
if (image == ImageCache.defaultImage) {
cardArt = CardImageRenderer.forgeArt;
} else {
float x, y;
float w = image.getWidth();
float h = image.getHeight();
if (isPlanesWalker) {
x = w * 0.09f;
y = h * 0.11f;
w -= 2f * x;
h -= 5.71f * y;
} else {
x = w * 0.1f;
y = h * 0.11f;
w -= 2 * x;
h *= CARD_ART_HEIGHT_PERCENTAGE;
float ratioRatio = w / h / CARD_ART_RATIO;
if (ratioRatio > 1) { //if too wide, shrink width
float dw = w * (ratioRatio - 1);
w -= dw;
x += dw / 2;
} else { //if too tall, shrink height
float dh = h * (1 - ratioRatio);
h -= dh;
y += dh / 2;
}
}
cardArt = new FTextureRegionImage(new TextureRegion(image, Math.round(x), Math.round(y), Math.round(w), Math.round(h)));
}
cardArtCache.put("Alternate_"+imageKey, cardArt);
}
}
return cardArt;
}
public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, CardView card, int count, String suffix, float x, float y, float w, float h, boolean compactMode) { public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, CardView card, int count, String suffix, float x, float y, float w, float h, boolean compactMode) {
final CardStateView state = card.getCurrentState(); final CardStateView state = card.getCurrentState();
if (card.getId() > 0) { if (card.getId() > 0) {
@@ -457,8 +523,8 @@ public class CardRenderer {
minusxy = 0.135f*radius; minusxy = 0.135f*radius;
} }
if (image != null) { if (image != null) {
if (image == ImageCache.defaultImage) { if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos); CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos, true);
} else { } else {
if (Forge.enableUIMask.equals("Full")) { if (Forge.enableUIMask.equals("Full")) {
if (ImageCache.isBorderlessCardArt(image)) if (ImageCache.isBorderlessCardArt(image))
@@ -482,13 +548,13 @@ public class CardRenderer {
} }
} else { } else {
//if card has invalid or no texture due to sudden changes in ImageCache, draw CardImageRenderer instead and wait for it to refresh automatically //if card has invalid or no texture due to sudden changes in ImageCache, draw CardImageRenderer instead and wait for it to refresh automatically
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos); CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos, Forge.enableUIMask.equals("Art"));
} }
} }
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate) { public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate) {
drawCard(g, card, x, y, w, h, pos, rotate, false); drawCard(g, card, x, y, w, h, pos, rotate, false, false);
} }
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate, boolean showAltState) { public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate, boolean showAltState, boolean isChoiceList) {
boolean canshow = MatchController.instance.mayView(card); boolean canshow = MatchController.instance.mayView(card);
boolean showsleeves = card.isFaceDown() && card.isInZone(EnumSet.of(ZoneType.Exile)); //fix facedown card image ie gonti lord of luxury boolean showsleeves = card.isFaceDown() && card.isInZone(EnumSet.of(ZoneType.Exile)); //fix facedown card image ie gonti lord of luxury
Texture image = new RendererCachedCardImage(card, false).getImage( showAltState ? card.getAlternateState().getImageKey() : card.getCurrentState().getImageKey()); Texture image = new RendererCachedCardImage(card, false).getImage( showAltState ? card.getAlternateState().getImageKey() : card.getCurrentState().getImageKey());
@@ -501,8 +567,8 @@ public class CardRenderer {
minusxy = 0.135f*radius; minusxy = 0.135f*radius;
} }
if (image != null) { if (image != null) {
if (image == ImageCache.defaultImage) { if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, card, false, x, y, w, h, pos); CardImageRenderer.drawCardImage(g, card, showAltState, x, y, w, h, pos, true, false, isChoiceList);
} else if (showsleeves) { } else if (showsleeves) {
if (!card.isForeTold()) if (!card.isForeTold())
g.drawImage(sleeves, x, y, w, h); g.drawImage(sleeves, x, y, w, h);
@@ -544,7 +610,7 @@ public class CardRenderer {
drawFoilEffect(g, card, x, y, w, h, false); drawFoilEffect(g, card, x, y, w, h, false);
} else { } else {
//if card has invalid or no texture due to sudden changes in ImageCache, draw CardImageRenderer instead and wait for it to refresh automatically //if card has invalid or no texture due to sudden changes in ImageCache, draw CardImageRenderer instead and wait for it to refresh automatically
CardImageRenderer.drawCardImage(g, card, false, x, y, w, h, pos); CardImageRenderer.drawCardImage(g, card, showAltState, x, y, w, h, pos, Forge.enableUIMask.equals("Art"), false, isChoiceList);
} }
} }
@@ -557,7 +623,7 @@ public class CardRenderer {
boolean unselectable = !MatchController.instance.isSelectable(card) && MatchController.instance.isSelecting(); boolean unselectable = !MatchController.instance.isSelectable(card) && MatchController.instance.isSelecting();
float cx, cy, cw, ch; float cx, cy, cw, ch;
cx = x; cy = y; cw = w; ch = h; cx = x; cy = y; cw = w; ch = h;
drawCard(g, card, x, y, w, h, pos, false, showAltState); drawCard(g, card, x, y, w, h, pos, false, showAltState, isChoiceList);
float padding = w * PADDING_MULTIPLIER; //adjust for card border float padding = w * PADDING_MULTIPLIER; //adjust for card border
x += padding; x += padding;
@@ -684,7 +750,7 @@ public class CardRenderer {
multiplier = 0.150f; multiplier = 0.150f;
break; break;
} }
g.drawOutlinedText(CardTranslation.getTranslatedName(details.getName()), FSkinFont.forHeight(h * multiplier), Color.WHITE, Color.BLACK, x + padding -1f, y + padding, w - 2 * padding, h * 0.4f, true, Align.left, false); g.drawOutlinedText(CardTranslation.getTranslatedName(details.getName()), FSkinFont.forHeight(h * multiplier), Color.WHITE, Color.BLACK, x + padding -1f, y + padding, w - 2 * padding, h * 0.4f, true, Align.left, false, true);
} }
if (showCardManaCostOverlay(card)) { if (showCardManaCostOverlay(card)) {
float manaSymbolSize = w / 4.5f; float manaSymbolSize = w / 4.5f;

View File

@@ -181,7 +181,7 @@ public class CardZoom extends FOverlay {
} }
if (flipIconBounds != null && flipIconBounds.contains(x, y)) { if (flipIconBounds != null && flipIconBounds.contains(x, y)) {
if (currentCard.isFaceDown() && currentCard.getBackup() != null) { if (currentCard.isFaceDown() && currentCard.getBackup() != null) {
if (currentCard.getBackup().hasBackSide()) { if (currentCard.getBackup().hasBackSide() || currentCard.getBackup().isFlipCard()) {
show(currentCard.getBackup()); show(currentCard.getBackup());
return true; return true;
} }

View File

@@ -16,6 +16,7 @@ import com.badlogic.gdx.utils.Align;
import forge.Forge; import forge.Forge;
import forge.Forge.KeyInputAdapter; import forge.Forge.KeyInputAdapter;
import forge.Graphics; import forge.Graphics;
import forge.ImageKeys;
import forge.assets.FImage; import forge.assets.FImage;
import forge.assets.FImageComplex; import forge.assets.FImageComplex;
import forge.assets.FSkin; import forge.assets.FSkin;
@@ -24,17 +25,15 @@ import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.assets.FSkinImage; import forge.assets.FSkinImage;
import forge.assets.ImageCache; import forge.assets.ImageCache;
import forge.card.CardFaceSymbols; import forge.card.*;
import forge.card.CardRenderer;
import forge.card.CardRenderer.CardStackPosition; import forge.card.CardRenderer.CardStackPosition;
import forge.card.CardZoom;
import forge.card.ColorSet;
import forge.deck.ArchetypeDeckGenerator; import forge.deck.ArchetypeDeckGenerator;
import forge.deck.CardThemedDeckGenerator; import forge.deck.CardThemedDeckGenerator;
import forge.deck.CommanderDeckGenerator; import forge.deck.CommanderDeckGenerator;
import forge.deck.DeckProxy; import forge.deck.DeckProxy;
import forge.deck.FDeckViewer; import forge.deck.FDeckViewer;
import forge.deck.io.DeckPreferences; import forge.deck.io.DeckPreferences;
import forge.game.card.CardView;
import forge.gamemodes.planarconquest.ConquestCommander; import forge.gamemodes.planarconquest.ConquestCommander;
import forge.item.InventoryItem; import forge.item.InventoryItem;
import forge.item.PaperCard; import forge.item.PaperCard;
@@ -54,6 +53,7 @@ import forge.toolbox.FEvent.FEventHandler;
import forge.toolbox.FLabel; import forge.toolbox.FLabel;
import forge.toolbox.FScrollPane; import forge.toolbox.FScrollPane;
import forge.toolbox.FTextField; import forge.toolbox.FTextField;
import forge.util.ImageUtil;
import forge.util.Localizer; import forge.util.Localizer;
import forge.util.TextUtil; import forge.util.TextUtil;
import forge.util.Utils; import forge.util.Utils;
@@ -1016,8 +1016,20 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
} else { } else {
//commander bg //commander bg
g.drawImage(FSkin.getDeckbox().get(0), FSkin.getDeckbox().get(0), x, y, w, h, Color.GREEN, selected); g.drawImage(FSkin.getDeckbox().get(0), FSkin.getDeckbox().get(0), x, y, w, h, Color.GREEN, selected);
TextureRegion tr = ImageCache.croppedBorderImage(dpImg);
g.drawImage(tr, x+(w-w*scale)/2, y+(h-h*scale)/1.5f, w*scale, h*scale); PaperCard paperCard = null;
String imageKey = item.getImageKey(false);
if (imageKey != null) {
if (imageKey.startsWith(ImageKeys.CARD_PREFIX))
paperCard = ImageUtil.getPaperCardFromImageKey(imageKey);
}
if (paperCard != null && Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(paperCard), false,
x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale, CardStackPosition.Top, true, false, false);
} else {
TextureRegion tr = ImageCache.croppedBorderImage(dpImg);
g.drawImage(tr, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale);
}
} }
//fake labelname shadow //fake labelname shadow
g.drawText(item.getName(), GROUP_HEADER_FONT, Color.BLACK, (x + PADDING)-1f, (y + PADDING*2)+1f, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false); g.drawText(item.getName(), GROUP_HEADER_FONT, Color.BLACK, (x + PADDING)-1f, (y + PADDING*2)+1f, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false);
@@ -1026,8 +1038,8 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
} else { } else {
if (!dp.isGeneratedDeck()){ if (!dp.isGeneratedDeck()){
//If deck has Commander, use it as cardArt reference //If deck has Commander, use it as cardArt reference
String deckImageKey = dp.getDeck().getCommanders().isEmpty() ? dp.getHighestCMCCard().getImageKey(false) : dp.getDeck().getCommanders().get(0).getImageKey(false); PaperCard paperCard = dp.getDeck().getCommanders().isEmpty() ? dp.getHighestCMCCard() : dp.getDeck().getCommanders().get(0);
FImageComplex cardArt = CardRenderer.getCardArt(deckImageKey, false, false, false); FImageComplex cardArt = CardRenderer.getCardArt(paperCard);
//draw the deckbox //draw the deckbox
if (cardArt == null){ if (cardArt == null){
//draw generic box if null or still loading //draw generic box if null or still loading

View File

@@ -161,6 +161,10 @@ public class HomeScreen extends FScreen {
return QuestCommander; return QuestCommander;
} }
public int getActiveButtonIndex() {
return activeButtonIndex;
}
public String getQuestWorld() { public String getQuestWorld() {
return QuestWorld; return QuestWorld;
} }

View File

@@ -105,8 +105,11 @@ public class LoadGameMenu extends FPopupMenu {
protected void buildMenu() { protected void buildMenu() {
FScreen currentScreen = Forge.getCurrentScreen(); FScreen currentScreen = Forge.getCurrentScreen();
for (LoadGameScreen lgs : LoadGameScreen.values()) { for (LoadGameScreen lgs : LoadGameScreen.values()) {
addItem(lgs.item); //fixes the overlapping menu items when the user suddenly switch from load game screen index to another screen
lgs.item.setSelected(currentScreen == lgs.screen); if (HomeScreen.instance.getActiveButtonIndex() == 1) {
addItem(lgs.item);
lgs.item.setSelected(currentScreen == lgs.screen);
}
} }
} }
} }

View File

@@ -521,7 +521,7 @@ public class SettingsPage extends TabPage<SettingsScreen> {
lstSettings.addItem(new CustomSelectSetting(FPref.UI_ENABLE_BORDER_MASKING, lstSettings.addItem(new CustomSelectSetting(FPref.UI_ENABLE_BORDER_MASKING,
localizer.getMessage("lblBorderMaskOption"), localizer.getMessage("lblBorderMaskOption"),
localizer.getMessage("nlBorderMaskOption"), localizer.getMessage("nlBorderMaskOption"),
new String[]{"Off", "Crop", "Full"}) { new String[]{"Off", "Crop", "Full", "Art"}) {
@Override @Override
public void valueChanged(String newValue) { public void valueChanged(String newValue) {
super.valueChanged(newValue); super.valueChanged(newValue);

View File

@@ -393,7 +393,7 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
boolean showAlt = false; boolean showAlt = false;
if(cardView.hasAlternateState()){ if(cardView.hasAlternateState()){
if(cardView.hasBackSide()) if(cardView.hasBackSide())
showAlt = value.contains(cardView.getBackSideName()); showAlt = value.contains(cardView.getBackSideName()) || cardView.getAlternateState().getAbilityText().contains(value);
else if (cardView.isAdventureCard()) else if (cardView.isAdventureCard())
showAlt = value.equals(cardView.getAlternateState().getAbilityText()); showAlt = value.equals(cardView.getAlternateState().getAbilityText());
else if (cardView.isSplitCard()) { else if (cardView.isSplitCard()) {
@@ -520,9 +520,12 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
@Override @Override
public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) {
//should fix NPE ie Thief of Sanity, Gonti... etc //should fix NPE ie Thief of Sanity, Gonti... etc
CardView cv = ((IHasCardView)value).getCardView().isFaceDown() && ((IHasCardView)value).getCardView().isInZone(EnumSet.of(ZoneType.Exile)) ? ((IHasCardView)value).getCardView().getBackup() : ((IHasCardView)value).getCardView(); CardView cv = ((IHasCardView)value).getCardView();
boolean showAlternate = showAlternate(cv, value.toString()); if (cv != null) {
CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); CardView render = cv.isFaceDown() && cv.isInZone(EnumSet.of(ZoneType.Exile)) ? cv.getBackup() : cv;
boolean showAlternate = showAlternate(render, value.toString());
CardRenderer.drawCardWithOverlays(g, render, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true);
}
float dx = VStack.CARD_WIDTH + FList.PADDING; float dx = VStack.CARD_WIDTH + FList.PADDING;
x += dx; x += dx;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@@ -256,7 +256,8 @@ public class DeckProxy implements InventoryItem {
for (final Entry <PaperCard, Integer> pc : getDeck().getAllCardsInASinglePool()) { for (final Entry <PaperCard, Integer> pc : getDeck().getAllCardsInASinglePool()) {
if (pc.getKey().getRules().getManaCost() != null) { if (pc.getKey().getRules().getManaCost() != null) {
if (pc.getKey().getRules().getSplitType() != CardSplitType.Split) if (pc.getKey().getRules().getType().hasSubtype("Saga") || pc.getKey().getRules().getType().hasSubtype("Class") || CardSplitType.Split.equals(pc.getKey().getRules().getSplitType()))
continue;
keyCMC.put(pc.getKey(),pc.getKey().getRules().getManaCost().getCMC()); keyCMC.put(pc.getKey(),pc.getKey().getRules().getManaCost().getCMC());
} }
} }

View File

@@ -122,6 +122,7 @@ public final class ForgeConstants {
public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png"; public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png";
public static final String SPRITE_SETLOGO_FILE = "sprite_setlogo.png"; public static final String SPRITE_SETLOGO_FILE = "sprite_setlogo.png";
public static final String SPRITE_WATERMARK_FILE = "sprite_watermark.png"; public static final String SPRITE_WATERMARK_FILE = "sprite_watermark.png";
public static final String SPRITE_CARDBG_FILE = "sprite_cardbg.png";
public static final String FONT_FILE = "font1.ttf"; public static final String FONT_FILE = "font1.ttf";
public static final String SPLASH_BG_FILE = "bg_splash.png"; public static final String SPLASH_BG_FILE = "bg_splash.png";
public static final String MATCH_BG_FILE = "bg_match.jpg"; public static final String MATCH_BG_FILE = "bg_match.jpg";

View File

@@ -410,6 +410,28 @@ public enum FSkinProp {
IMG_WATERMARK_W (new int[] {2, 1006, 500, 500}, PropType.WATERMARKS), IMG_WATERMARK_W (new int[] {2, 1006, 500, 500}, PropType.WATERMARKS),
IMG_WATERMARK_C (new int[] {504, 1006, 500, 500}, PropType.WATERMARKS), IMG_WATERMARK_C (new int[] {504, 1006, 500, 500}, PropType.WATERMARKS),
//FOR CARDBG
IMG_CARDBG_A (new int[] {2, 2, 339, 496}, PropType.CARDBG),
IMG_CARDBG_B (new int[] {343, 2, 339, 496}, PropType.CARDBG),
IMG_CARDBG_BG (new int[] {684, 2, 339, 496}, PropType.CARDBG),
IMG_CARDBG_BR (new int[] {1025, 2, 339, 496}, PropType.CARDBG),
IMG_CARDBG_C (new int[] {1366, 2, 339, 496}, PropType.CARDBG),
IMG_CARDBG_G (new int[] {2, 500, 339, 496}, PropType.CARDBG),
IMG_CARDBG_L (new int[] {343, 500, 339, 496}, PropType.CARDBG),
IMG_CARDBG_M (new int[] {684, 500, 339, 496}, PropType.CARDBG),
IMG_CARDBG_R (new int[] {1025, 500, 339, 496}, PropType.CARDBG),
IMG_CARDBG_RG (new int[] {1366, 500, 339, 496}, PropType.CARDBG),
IMG_CARDBG_U (new int[] {2, 998, 339, 496}, PropType.CARDBG),
IMG_CARDBG_UB (new int[] {343, 998, 339, 496}, PropType.CARDBG),
IMG_CARDBG_UG (new int[] {684, 998, 339, 496}, PropType.CARDBG),
IMG_CARDBG_UR (new int[] {1025, 998, 339, 496}, PropType.CARDBG),
IMG_CARDBG_V (new int[] {1366, 998, 339, 496}, PropType.CARDBG),
IMG_CARDBG_W (new int[] {2, 1496, 339, 496}, PropType.CARDBG),
IMG_CARDBG_WB (new int[] {343, 1496, 339, 496}, PropType.CARDBG),
IMG_CARDBG_WG (new int[] {684, 1496, 339, 496}, PropType.CARDBG),
IMG_CARDBG_WR (new int[] {1025, 1496, 339, 496}, PropType.CARDBG),
IMG_CARDBG_WU (new int[] {1366, 1496, 339, 496}, PropType.CARDBG),
IMG_FAV1 (new int[] {0, 0, 100, 100}, PropType.FAVICON), IMG_FAV1 (new int[] {0, 0, 100, 100}, PropType.FAVICON),
IMG_FAV2 (new int[] {100, 0, 100, 100}, PropType.FAVICON), IMG_FAV2 (new int[] {100, 0, 100, 100}, PropType.FAVICON),
IMG_FAV3 (new int[] {200, 0, 100, 100}, PropType.FAVICON), IMG_FAV3 (new int[] {200, 0, 100, 100}, PropType.FAVICON),
@@ -514,6 +536,7 @@ public enum FSkinProp {
DECKBOX, DECKBOX,
SETLOGO, SETLOGO,
WATERMARKS, WATERMARKS,
CARDBG,
FAVICON FAVICON
} }
} }