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.Set;
import forge.game.spellability.SpellAbility;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate;
@@ -821,7 +822,7 @@ public class CardView extends GameEntityView {
updateZoneText(c);
updateDamage(c);
if (getBackup() == null && !c.isFaceDown() && c.hasBackSide()) {
if (getBackup() == null && !c.isFaceDown() && (c.hasBackSide()||c.isFlipCard())) {
set(TrackableProperty.PaperCardBackup, c.getPaperCard());
}
@@ -1300,6 +1301,37 @@ public class CardView extends GameEntityView {
public boolean 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() {
return get(TrackableProperty.AbilityText);
@@ -1333,6 +1365,7 @@ public class CardView extends GameEntityView {
set(TrackableProperty.HasInfect, c.hasKeyword(Keyword.INFECT, state));
set(TrackableProperty.HasStorm, c.hasKeyword(Keyword.STORM, state));
set(TrackableProperty.HasLandwalk, c.hasKeyword(Keyword.LANDWALK, state));
set(TrackableProperty.HasAftermath, c.hasKeyword(Keyword.AFTERMATH, state));
updateAbilityText(c, state);
//set protectionKey for Icons
set(TrackableProperty.ProtectionKey, c.getProtectionKey());
@@ -1340,6 +1373,84 @@ public class CardView extends GameEntityView {
set(TrackableProperty.HexproofKey, c.getHexproofKey());
//keywordkey
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() {
@@ -1375,6 +1486,12 @@ public class CardView extends GameEntityView {
public boolean isIsland() {
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

View File

@@ -111,6 +111,18 @@ public enum TrackableProperty {
HasChangedColors(TrackableTypes.BooleanType),
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),
HasDeathtouch(TrackableTypes.BooleanType),
HasDevoid(TrackableTypes.BooleanType),
@@ -132,6 +144,7 @@ public enum TrackableProperty {
HasTrample(TrackableTypes.BooleanType),
HasVigilance(TrackableTypes.BooleanType),
HasLandwalk(TrackableTypes.BooleanType),
HasAftermath(TrackableTypes.BooleanType),
//protectionkey
ProtectionKey(TrackableTypes.StringType),
//hexproofkey

View File

@@ -472,6 +472,12 @@ public class Graphics {
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) {
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
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, 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.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.math.Matrix4;
@@ -44,8 +45,30 @@ public abstract class FBufferedImage extends FImageComplex {
return 0;
}
@Override
public TextureRegion getTextureRegion() {
return new TextureRegion(checkFrameBuffer().getColorBufferTexture());
}
@Override
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) {
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);
}
return frameBuffer.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
}
});
}
return frameBuffer;
}
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.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import forge.Graphics;
//Special wrapper for a texture to be loaded later when it's needed
@@ -32,6 +33,14 @@ public class FDelayLoadImage extends FImageComplex {
return texture;
}
@Override
public TextureRegion getTextureRegion() {
if (texture == null) {
texture = new Texture(Gdx.files.absolute(filename));
}
return new TextureRegion(texture);
}
@Override
public int getRegionX() {
return 0;

View File

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

View File

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

View File

@@ -217,9 +217,12 @@ public class FSkin {
final FileHandle f11 = getSkinFile(ForgeConstants.SPRITE_BUTTONS_FILE);
final FileHandle f12 = getSkinFile(ForgeConstants.SPRITE_START_FILE);
final FileHandle f13 = getDefaultSkinFile(ForgeConstants.SPRITE_DECKBOX_FILE);
/*TODO Themeable
final FileHandle f14 = getDefaultSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE);
final FileHandle f15 = getSkinFile(ForgeConstants.SPRITE_SETLOGO_FILE);
final FileHandle f16 = getDefaultSkinFile(ForgeConstants.SPRITE_WATERMARK_FILE);
*/
try {
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_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
TAP (FSkinProp.IMG_TAP, SourceFile.MANAICONS),
UNTAP (FSkinProp.IMG_UNTAP, SourceFile.MANAICONS),
@@ -439,6 +461,7 @@ public enum FSkinImage implements FImage {
MANAICONS(ForgeConstants.SPRITE_MANAICONS_FILE),
SETLOGOS(ForgeConstants.SPRITE_SETLOGO_FILE),
WATERMARKS(ForgeConstants.SPRITE_WATERMARK_FILE),
CARDBG(ForgeConstants.SPRITE_CARDBG_FILE),
PLANAR_CONQUEST(ForgeConstants.SPRITE_PLANAR_CONQUEST_FILE);
private final String filename;

View File

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

View File

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

View File

@@ -32,7 +32,7 @@ public class CardAvatarImage implements FImage {
@Override
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
image = CardRenderer.getCardArt(imageKey, false, false, false);
image = CardRenderer.getCardArt(imageKey, false, false, false, false, false, false, false, false);
if (image == null) {
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);
if (image == null) {
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
}
}
if (image == ImageCache.defaultImage) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top);
if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top, true);
}
else {
if (Forge.enableUIMask.equals("Full")) {

View File

@@ -6,6 +6,9 @@ import static forge.card.CardRenderer.isModernFrame;
import java.util.ArrayList;
import java.util.List;
import forge.ImageKeys;
import forge.assets.*;
import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.graphics.Color;
@@ -15,15 +18,6 @@ import com.google.common.collect.ImmutableList;
import forge.Forge;
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.mana.ManaCost;
import forge.game.GameView;
@@ -48,6 +42,10 @@ public class CardImageRenderer {
private static float prevImageWidth, prevImageHeight;
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() {
//force static fields to be updated the next time a card image is rendered
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) {
//try to draw the card sleeves first
if (FSkin.getSleeves().get(card.getOwner()) != null)
g.drawImage(FSkin.getSleeves().get(card.getOwner()), x, y, w, h);
FImage sleeves = MatchController.getPlayerSleeve(card.getOwner());
if (sleeves != null)
g.drawImage(sleeves, x, y, w, h);
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);
float blackBorderThickness = w * BLACK_BORDER_THICKNESS_RATIO;
@@ -94,8 +96,16 @@ public class CardImageRenderer {
w -= 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);
//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) {
drawFaceDownCard(card, g, x, y, w, h);
@@ -104,14 +114,12 @@ public class CardImageRenderer {
//determine colors for borders
final List<DetailColors> borderColors;
final boolean isFaceDown = card.isFaceDown();
if (isFaceDown) {
borderColors = ImmutableList.of(DetailColors.FACE_DOWN);
}
else {
borderColors = !altState ? ImmutableList.of(DetailColors.FACE_DOWN) : !useCardBGTexture ? ImmutableList.of(DetailColors.FACE_DOWN) : CardDetailUtil.getBorderColors(state, canShow);
} else {
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 outerBorderThickness = 2 * blackBorderThickness - artInset;
@@ -122,7 +130,7 @@ public class CardImageRenderer {
//draw header containing name and mana cost
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
boolean onTop = (pos == CardStackPosition.Top);
@@ -156,53 +164,95 @@ public class CardImageRenderer {
//draw art box with Forge icon
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;
}
//draw type line
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight);
y += typeBoxHeight;
if (isSaga) {
//draw text box
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
Color[] textBoxColors = FSkinColor.tintColors(Color.WHITE, colors, CardRenderer.TEXT_BOX_TINT);
drawTextBox(g, card, state, textBoxColors, x + artInset, y, w - 2 * artInset, textBoxHeight, onTop);
y += textBoxHeight;
//draw type line
drawTypeLine(g, card, state, canShow, headerColors, x, y, w, typeBoxHeight, noText);
y += typeBoxHeight;
} 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
if (onTop && ptBoxHeight > 0) {
//only needed if on top since otherwise P/T will be hidden
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);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
float padding = h / 8;
//draw mana cost for card
float manaCostWidth = 0;
ManaCost mainManaCost = state.getManaCost();
if (card.isSplitCard() && card.getAlternateState() != null) {
//handle rendering both parts of split card
mainManaCost = card.getLeftSplitState().getManaCost();
ManaCost otherManaCost = card.getAlternateState().getManaCost();
manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING;
CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
//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);
if (!noText) {
//draw mana cost for card
ManaCost mainManaCost = state.getManaCost();
if (card.isSplitCard() && card.getAlternateState() != null) {
//handle rendering both parts of split card
mainManaCost = card.getLeftSplitState().getManaCost();
ManaCost otherManaCost = card.getRightSplitState().getManaCost();
manaCostWidth = CardFaceSymbols.getWidth(otherManaCost, MANA_SYMBOL_SIZE) + HEADER_PADDING;
CardFaceSymbols.drawManaCost(g, otherManaCost, x + w - manaCostWidth, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
//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
x += 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;
@@ -221,12 +271,95 @@ public class CardImageRenderer {
};
}
private static void drawArt(Graphics g, float x, float y, float w, float h) {
g.drawImage(forgeArt, x, y, w, h);
private static void drawArt(CardView cv, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) {
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);
}
private static void drawTypeLine(Graphics g, CardView card, CardStateView state, boolean canShow, Color[] colors, float x, float y, float w, float h) {
private static void drawSplitCard(CardView card, FImageComplex cardArt, Graphics g, float x, float y, float w, float h, boolean altState, boolean isFaceDown) {
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);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
@@ -252,6 +385,8 @@ public class CardImageRenderer {
}
//draw type
if (noText)
return;
x += padding;
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
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()) {
DetailColors modColors = DetailColors.WHITE;
if (state.isBasicLand()) {
@@ -273,49 +410,137 @@ public class CardImageRenderer {
modColors = DetailColors.BLACK;
else if (state.isPlains())
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 {
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);
if (!onTop) { return; } //remaining rendering only needed if card on top
if (state.isBasicLand()) {
//draw icons for basic lands
FSkinImage image;
switch (state.getName().replaceFirst("^Snow-Covered ", "")) {
case "Plains":
image = FSkinImage.WATERMARK_W;
break;
case "Island":
image = FSkinImage.WATERMARK_U;
break;
case "Swamp":
image = FSkinImage.WATERMARK_B;
break;
case "Mountain":
image = FSkinImage.WATERMARK_R;
break;
case "Forest":
image = FSkinImage.WATERMARK_G;
break;
default:
//draw watermark
FSkinImage image = null;
if (state.origCanProduceColoredMana() == 1 && !state.origProduceManaC()) {
if (state.isPlains())
image = FSkinImage.WATERMARK_W;
else if (state.isIsland())
image = FSkinImage.WATERMARK_U;
else if (state.isSwamp())
image = FSkinImage.WATERMARK_B;
else if (state.isMountain())
image = FSkinImage.WATERMARK_R;
else if (state.isForest())
image = FSkinImage.WATERMARK_G;
} else if (state.origProduceManaC()) {
image = FSkinImage.WATERMARK_C;
break;
}
float iconSize = h * 0.75f;
g.drawImage(image, x + (w - iconSize) / 2, y + (h - iconSize) / 2, iconSize, iconSize);
}
else {
if (image != null) {
float iconSize = h * 0.75f;
g.drawImage(image, x + (w - iconSize) / 2, y + (h - iconSize) / 2, iconSize, iconSize);
}
} else {
boolean needTranslation = true;
if (card.isToken()) {
if (card.getCloneOrigin() == null)
needTranslation = false;
}
if (noText)
return;
final String text = !card.isSplitCard() ?
card.getText(state, needTranslation ? CardTranslation.getTranslationTexts(state.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);
}
}
private static void drawPtBox(Graphics g, CardView card, CardStateView state, Color[] colors, float x, float y, float w, float h) {
private static void drawAlphaLines(Color[] colors, Graphics g, float x, float y, float w, float h, float thickness, float mod) {
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<>();
if (state.isCreature()) {
pieces.add(String.valueOf(state.getPower()));
@@ -369,6 +610,8 @@ public class CardImageRenderer {
fillColorBackground(g, colors, x, y, w, h);
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
if (noText)
return;
x += (boxWidth - totalPieceWidth) / 2;
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);
@@ -399,8 +642,8 @@ public class CardImageRenderer {
return;
}
if (image == ImageCache.defaultImage) { //support drawing card image manually if card image not found
drawCardImage(g, card, altState, x, y, w, h, CardStackPosition.Top);
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, true);
} else {
float radius = (h - w)/8;
float wh_Adj = ForgeConstants.isGdxPortLandscape && isCurrentCard ? 1.38f:1.0f;
@@ -517,11 +760,79 @@ public class CardImageRenderer {
Color[] colors = new Color[backColors.size()];
for (int i = 0; i < colors.length; 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);
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) {
switch (colors.length) {
case 1:

View File

@@ -207,15 +207,15 @@ public class CardRenderer {
public static FImageComplex getCardArt(IPaperCard pc, boolean backFace) {
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) {
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);
if (cardArt == null) {
Texture image = new RendererCachedCardImage(imageKey, true).getImage();
@@ -227,12 +227,36 @@ public class CardRenderer {
float x, y;
float w = image.getWidth();
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;
y = 0; //delay adjusting y and h until drawn
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 artW = 350f, artH = 156f;
float srcW = 430f, srcH = 300f;
@@ -241,8 +265,7 @@ public class CardRenderer {
y = h * 40f / srcH;
w *= artW / srcW;
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;
y = h * (srcW - artW - artX) / srcW;
w *= artH / srcH;
@@ -251,8 +274,7 @@ public class CardRenderer {
cardArtCache.put(imageKey, cardArt);
return cardArt;
}
}
else {
} else {
x = w * 0.1f;
y = h * 0.11f;
w -= 2 * x;
@@ -262,8 +284,7 @@ public class CardRenderer {
float dw = w * (ratioRatio - 1);
w -= dw;
x += dw / 2;
}
else { //if too tall, shrink height
} else { //if too tall, shrink height
float dh = h * (1 - ratioRatio);
h -= dh;
y += dh / 2;
@@ -290,16 +311,15 @@ public class CardRenderer {
if (image != null) {
if (image == ImageCache.defaultImage) {
cardArt = CardImageRenderer.forgeArt;
}
else {
} else {
float x, y;
float w = image.getWidth();
float h = image.getHeight();
//allow rotated image for split cards
x = w * 138f / 250f;
y = h * 210f / 370f; //delay adjusting y and h until drawn
w *= 68f / 250f;
h *= 128f / 370f;
x = w * 138f / 250f;
y = h * 210f / 370f; //delay adjusting y and h until drawn
w *= 68f / 250f;
h *= 128f / 370f;
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;
}
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) {
final CardStateView state = card.getCurrentState();
if (card.getId() > 0) {
@@ -457,8 +523,8 @@ public class CardRenderer {
minusxy = 0.135f*radius;
}
if (image != null) {
if (image == ImageCache.defaultImage) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos);
if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos, true);
} else {
if (Forge.enableUIMask.equals("Full")) {
if (ImageCache.isBorderlessCardArt(image))
@@ -482,13 +548,13 @@ public class CardRenderer {
}
} else {
//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) {
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 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());
@@ -501,8 +567,8 @@ public class CardRenderer {
minusxy = 0.135f*radius;
}
if (image != null) {
if (image == ImageCache.defaultImage) {
CardImageRenderer.drawCardImage(g, card, false, x, y, w, h, pos);
if (image == ImageCache.defaultImage || Forge.enableUIMask.equals("Art")) {
CardImageRenderer.drawCardImage(g, card, showAltState, x, y, w, h, pos, true, false, isChoiceList);
} else if (showsleeves) {
if (!card.isForeTold())
g.drawImage(sleeves, x, y, w, h);
@@ -544,7 +610,7 @@ public class CardRenderer {
drawFoilEffect(g, card, x, y, w, h, false);
} else {
//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();
float cx, cy, cw, ch;
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
x += padding;
@@ -684,7 +750,7 @@ public class CardRenderer {
multiplier = 0.150f;
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)) {
float manaSymbolSize = w / 4.5f;

View File

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

View File

@@ -16,6 +16,7 @@ import com.badlogic.gdx.utils.Align;
import forge.Forge;
import forge.Forge.KeyInputAdapter;
import forge.Graphics;
import forge.ImageKeys;
import forge.assets.FImage;
import forge.assets.FImageComplex;
import forge.assets.FSkin;
@@ -24,17 +25,15 @@ import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
import forge.assets.ImageCache;
import forge.card.CardFaceSymbols;
import forge.card.CardRenderer;
import forge.card.*;
import forge.card.CardRenderer.CardStackPosition;
import forge.card.CardZoom;
import forge.card.ColorSet;
import forge.deck.ArchetypeDeckGenerator;
import forge.deck.CardThemedDeckGenerator;
import forge.deck.CommanderDeckGenerator;
import forge.deck.DeckProxy;
import forge.deck.FDeckViewer;
import forge.deck.io.DeckPreferences;
import forge.game.card.CardView;
import forge.gamemodes.planarconquest.ConquestCommander;
import forge.item.InventoryItem;
import forge.item.PaperCard;
@@ -54,6 +53,7 @@ import forge.toolbox.FEvent.FEventHandler;
import forge.toolbox.FLabel;
import forge.toolbox.FScrollPane;
import forge.toolbox.FTextField;
import forge.util.ImageUtil;
import forge.util.Localizer;
import forge.util.TextUtil;
import forge.util.Utils;
@@ -1016,8 +1016,20 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
} else {
//commander bg
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
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 {
if (!dp.isGeneratedDeck()){
//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);
FImageComplex cardArt = CardRenderer.getCardArt(deckImageKey, false, false, false);
PaperCard paperCard = dp.getDeck().getCommanders().isEmpty() ? dp.getHighestCMCCard() : dp.getDeck().getCommanders().get(0);
FImageComplex cardArt = CardRenderer.getCardArt(paperCard);
//draw the deckbox
if (cardArt == null){
//draw generic box if null or still loading

View File

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

View File

@@ -105,8 +105,11 @@ public class LoadGameMenu extends FPopupMenu {
protected void buildMenu() {
FScreen currentScreen = Forge.getCurrentScreen();
for (LoadGameScreen lgs : LoadGameScreen.values()) {
addItem(lgs.item);
lgs.item.setSelected(currentScreen == lgs.screen);
//fixes the overlapping menu items when the user suddenly switch from load game screen index to another 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,
localizer.getMessage("lblBorderMaskOption"),
localizer.getMessage("nlBorderMaskOption"),
new String[]{"Off", "Crop", "Full"}) {
new String[]{"Off", "Crop", "Full", "Art"}) {
@Override
public void valueChanged(String newValue) {
super.valueChanged(newValue);

View File

@@ -393,7 +393,7 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
boolean showAlt = false;
if(cardView.hasAlternateState()){
if(cardView.hasBackSide())
showAlt = value.contains(cardView.getBackSideName());
showAlt = value.contains(cardView.getBackSideName()) || cardView.getAlternateState().getAbilityText().contains(value);
else if (cardView.isAdventureCard())
showAlt = value.equals(cardView.getAlternateState().getAbilityText());
else if (cardView.isSplitCard()) {
@@ -520,9 +520,12 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
@Override
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
CardView cv = ((IHasCardView)value).getCardView().isFaceDown() && ((IHasCardView)value).getCardView().isInZone(EnumSet.of(ZoneType.Exile)) ? ((IHasCardView)value).getCardView().getBackup() : ((IHasCardView)value).getCardView();
boolean showAlternate = showAlternate(cv, value.toString());
CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true);
CardView cv = ((IHasCardView)value).getCardView();
if (cv != null) {
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;
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()) {
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());
}
}

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_SETLOGO_FILE = "sprite_setlogo.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 SPLASH_BG_FILE = "bg_splash.png";
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_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_FAV2 (new int[] {100, 0, 100, 100}, PropType.FAVICON),
IMG_FAV3 (new int[] {200, 0, 100, 100}, PropType.FAVICON),
@@ -514,6 +536,7 @@ public enum FSkinProp {
DECKBOX,
SETLOGO,
WATERMARKS,
CARDBG,
FAVICON
}
}