Optimize card rendering behind other cards

Fix issue with achievement tooltip not appearing at times
This commit is contained in:
drdev
2014-09-26 10:32:09 +00:00
parent 3f1f199537
commit 1cc9056b7b
11 changed files with 95 additions and 19 deletions

View File

@@ -16,6 +16,7 @@ import forge.assets.FSkinImage;
import forge.assets.FSkinTexture;
import forge.assets.TextRenderer;
import forge.card.CardDetailUtil.DetailColors;
import forge.card.CardRenderer.CardStackPosition;
import forge.card.mana.ManaCost;
import forge.screens.FScreen;
import forge.view.CardView;
@@ -56,7 +57,7 @@ public class CardImageRenderer {
prevImageHeight = h;
}
public static void drawCardImage(Graphics g, CardView card, float x, float y, float w, float h) {
public static void drawCardImage(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) {
updateStaticFields(w, h);
final CardStateView state = card.getOriginal();
@@ -94,6 +95,10 @@ public class CardImageRenderer {
Color headerColor1 = FSkinColor.tintColor(Color.WHITE, color1, CardRenderer.NAME_BOX_TINT);
Color headerColor2 = color2 == null ? null : FSkinColor.tintColor(Color.WHITE, color2, CardRenderer.NAME_BOX_TINT);
drawHeader(g, card, headerColor1, headerColor2, x, y, w, headerHeight);
if (pos == CardStackPosition.BehindVert) { return; } //remaining rendering not needed if card is behind another card in a vertical stack
boolean onTop = (pos == CardStackPosition.Top);
y += headerHeight;
float artWidth = w - 2 * artInset;
@@ -138,7 +143,8 @@ public class CardImageRenderer {
y += textBoxHeight;
//draw P/T box
if (ptBoxHeight > 0) {
if (onTop && ptBoxHeight > 0) {
//only needed if on top since otherwise P/T will be hidden
Color ptColor1 = FSkinColor.tintColor(Color.WHITE, color1, CardRenderer.PT_BOX_TINT);
Color ptColor2 = color2 == null ? null : FSkinColor.tintColor(Color.WHITE, color2, CardRenderer.PT_BOX_TINT);
drawPtBox(g, card, ptColor1, ptColor2, x, y - 2 * artInset, w, ptBoxHeight);

View File

@@ -40,6 +40,12 @@ import forge.view.CardView.CardStateView;
import forge.view.ViewUtil;
public class CardRenderer {
public enum CardStackPosition {
Top,
BehindHorz,
BehindVert
}
private static final FSkinFont NAME_FONT = FSkinFont.get(16);
private static final FSkinFont TYPE_FONT = FSkinFont.get(14);
private static final FSkinFont SET_FONT = TYPE_FONT;
@@ -94,7 +100,7 @@ public class CardRenderer {
w = h / FCardPanel.ASPECT_RATIO;
x += (oldWidth - w) / 2;
}
CardImageRenderer.drawCardImage(g, card, x, y, w, h);
CardImageRenderer.drawCardImage(g, card, x, y, w, h, CardStackPosition.Top);
drawFoilEffect(g, card, x, y, w, h);
return true;
}
@@ -495,11 +501,11 @@ public class CardRenderer {
g.drawText(ptText, PT_FONT, Color.BLACK, x, y, w, h, false, HAlignment.CENTER, true);
}
public static void drawCard(Graphics g, IPaperCard pc, float x, float y, float w, float h) {
public static void drawCard(Graphics g, IPaperCard pc, float x, float y, float w, float h, CardStackPosition pos) {
Texture image = ImageCache.getImage(pc);
if (image != null) {
if (image == ImageCache.defaultImage) {
CardImageRenderer.drawCardImage(g, ViewUtil.getCardForUi(pc), x, y, w, h);
CardImageRenderer.drawCardImage(g, ViewUtil.getCardForUi(pc), x, y, w, h, pos);
}
else {
g.drawImage(image, x, y, w, h);
@@ -516,11 +522,11 @@ public class CardRenderer {
g.fillRect(Color.BLACK, x, y, w, h);
}
}
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h) {
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) {
Texture image = ImageCache.getImage(card);
if (image != null) {
if (image == ImageCache.defaultImage) {
CardImageRenderer.drawCardImage(g, card, x, y, w, h);
CardImageRenderer.drawCardImage(g, card, x, y, w, h, pos);
}
else {
g.drawImage(image, x, y, w, h);
@@ -532,8 +538,8 @@ public class CardRenderer {
}
}
public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h) {
drawCard(g, card, x, y, w, h);
public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) {
drawCard(g, card, x, y, w, h, pos);
float padding = w * 0.021f; //adjust for card border
x += padding;
@@ -564,6 +570,9 @@ public class CardRenderer {
}
}
if (pos == CardStackPosition.BehindVert) { return; } //remaining rendering not needed if card is behind another card in a vertical stack
boolean onTop = (pos == CardStackPosition.Top);
if (showCardIdOverlay(card)) {
FSkinFont idFont = FSkinFont.forHeight(h * 0.12f);
float idHeight = idFont.getCapHeight();
@@ -612,7 +621,8 @@ public class CardRenderer {
}
}
if (details.isCreature() && card.isSick() && card.getZone() == ZoneType.Battlefield) {
if (onTop && details.isCreature() && card.isSick() && card.getZone() == ZoneType.Battlefield) {
//only needed if on top since otherwise symbol will be hidden
CardFaceSymbols.drawSymbol("summonsick", g, stateXSymbols, ySymbols, otherSymbolsSize, otherSymbolsSize);
}
@@ -625,7 +635,8 @@ public class CardRenderer {
CardFaceSymbols.drawSymbol("sacrifice", g, (x + (w / 2)) - sacSymbolSize / 2, (y + (h / 2)) - sacSymbolSize / 2, otherSymbolsSize, otherSymbolsSize);
}
if (showCardPowerOverlay(card)) { //make sure card p/t box appears on top
if (onTop && showCardPowerOverlay(card)) { //make sure card p/t box appears on top
//only needed if on top since otherwise P/T will be hidden
drawPtBox(g, card, details, color, x, y, w, h);
}
}

View File

@@ -26,6 +26,7 @@ import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
import forge.card.CardEdition;
import forge.card.CardRenderer;
import forge.card.CardRenderer.CardStackPosition;
import forge.card.CardRules;
import forge.card.CardZoom;
import forge.card.mana.ManaCostShard;
@@ -401,7 +402,7 @@ public class AddBasicLandsDialog extends FDialog {
@Override
public void draw(Graphics g) {
if (card == null) { return; }
CardRenderer.drawCard(g, card, 0, 0, getWidth(), getHeight());
CardRenderer.drawCard(g, card, 0, 0, getWidth(), getHeight(), CardStackPosition.Top);
}
}
}

View File

@@ -9,6 +9,7 @@ import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinFont;
import forge.assets.ImageCache;
import forge.card.CardRenderer;
import forge.card.CardRenderer.CardStackPosition;
import forge.card.CardZoom;
import forge.deck.DeckProxy;
import forge.item.IPaperCard;
@@ -474,6 +475,8 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
x = 0;
for (ItemInfo itemInfo : group.items) {
itemInfo.pos = CardStackPosition.Top;
if (pile.items.size() == columnCount) {
pile = new Pile();
x = 0;
@@ -500,9 +503,11 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
Pile pile = group.piles.get(j);
y = pileY;
for (ItemInfo itemInfo : pile.items) {
itemInfo.pos = CardStackPosition.BehindVert;
itemInfo.setBounds(x, y, itemWidth, itemHeight);
y += dy;
}
pile.items.get(pile.items.size() - 1).pos = CardStackPosition.Top;
pileHeight = y + itemHeight - dy - pileY;
if (pileHeight > maxPileHeight) {
maxPileHeight = pileHeight;
@@ -906,7 +911,10 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
}
}
if (skippedItem != null) {
CardStackPosition backupPos = skippedItem.pos;
skippedItem.pos = CardStackPosition.Top; //ensure skipped item rendered as if it was on top
skippedItem.draw(g);
skippedItem.pos = backupPos;
}
}
}
@@ -914,6 +922,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
private final T item;
private final Group group;
private int index;
private CardStackPosition pos;
private boolean selected;
private ItemInfo(T item0, Group group0) {
@@ -954,7 +963,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
}
if (item instanceof PaperCard) {
CardRenderer.drawCard(g, (PaperCard)item, x, y, w, h);
CardRenderer.drawCard(g, (PaperCard)item, x, y, w, h, pos);
}
else {
Texture img = ImageCache.getImage(item);

View File

@@ -12,6 +12,7 @@ import forge.FThreads;
import forge.Graphics;
import forge.GuiBase;
import forge.card.CardZoom;
import forge.card.CardRenderer.CardStackPosition;
import forge.match.MatchUtil;
import forge.toolbox.FCardPanel;
import forge.view.CardView;
@@ -213,6 +214,14 @@ public abstract class VCardDisplayArea extends VDisplayArea {
prevPanelInStack = prevPanelInStack0;
}
@Override
protected CardStackPosition getStackPosition() {
if (nextPanelInStack == null && attachedToPanel == null) {
return CardStackPosition.Top;
}
return CardStackPosition.BehindHorz;
}
//clear and reset all pointers from this panel
public void reset() {
if (!attachedPanels.isEmpty()) {
@@ -230,16 +239,22 @@ public abstract class VCardDisplayArea extends VDisplayArea {
@Override
public boolean tap(float x, float y, int count) {
if (renderedCardContains(x, y)) {
forge.FTrace.get("tap").start();
forge.FTrace.get("tap2").start();
FThreads.invokeInBackgroundThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown
@Override
public void run() {
forge.FTrace.get("selectCard").start();
if (!selectCard()) {
//if no cards in stack can be selected, just show zoom/details for card
CardZoom.show(getCard());
}
forge.FTrace.get("selectCard").end();
Gdx.graphics.requestRendering();
forge.FTrace.get("tap2").end();
}
});
forge.FTrace.get("tap").end();
return true;
}
return false;

View File

@@ -18,6 +18,7 @@ import forge.card.CardDetailUtil;
import forge.card.CardRenderer;
import forge.card.CardZoom;
import forge.card.CardDetailUtil.DetailColors;
import forge.card.CardRenderer.CardStackPosition;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.match.MatchUtil;
@@ -329,7 +330,7 @@ public class VStack extends FDropDown {
x += PADDING;
y += PADDING;
CardRenderer.drawCardWithOverlays(g, stackInstance.getSource(), x, y, CARD_WIDTH, CARD_HEIGHT);
CardRenderer.drawCardWithOverlays(g, stackInstance.getSource(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top);
x += CARD_WIDTH + PADDING;
w -= x + PADDING - BORDER_THICKNESS;

View File

@@ -146,7 +146,8 @@ public class AchievementsPage extends TabPage<SettingsScreen> {
@Override
public boolean longPress(float x, float y) {
return showCard(getAchievementAt(x, y));
selectedAchievement = getAchievementAt(x, y);
return showCard(selectedAchievement);
}
private boolean showCard(Achievement achievement) {
@@ -245,7 +246,7 @@ public class AchievementsPage extends TabPage<SettingsScreen> {
x = startX;
if (y >= getHeight()) {
return;
break;
}
}

View File

@@ -2,6 +2,7 @@ package forge.toolbox;
import forge.Graphics;
import forge.card.CardRenderer;
import forge.card.CardRenderer.CardStackPosition;
import forge.util.Utils;
import forge.view.CardView;
@@ -75,6 +76,11 @@ public class FCardPanel extends FDisplayObject {
return PADDING;
}
//allow overriding stack position
protected CardStackPosition getStackPosition() {
return CardStackPosition.Top;
}
@Override
public void draw(Graphics g) {
if (card == null) { return; }
@@ -93,7 +99,7 @@ public class FCardPanel extends FDisplayObject {
g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, tappedAngle);
}
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h);
CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition());
if (tapped) {
g.endTransform();

View File

@@ -14,6 +14,7 @@ import forge.assets.TextRenderer;
import forge.assets.FSkinColor.Colors;
import forge.card.CardRenderer;
import forge.card.CardZoom;
import forge.card.CardRenderer.CardStackPosition;
import forge.item.PaperCard;
import forge.screens.match.MatchController;
import forge.screens.match.views.VAvatar;
@@ -393,7 +394,7 @@ public class FChoiceList<T> extends FList<T> {
@Override
public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) {
SpellAbilityView spellAbility = (SpellAbilityView)value;
CardRenderer.drawCardWithOverlays(g, spellAbility.getHostCard(), x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT);
CardRenderer.drawCardWithOverlays(g, spellAbility.getHostCard(), x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top);
float dx = VStack.CARD_WIDTH + FList.PADDING;
x += dx;

View File

@@ -11,6 +11,7 @@ import forge.assets.FImage;
import forge.assets.FSkinImage;
import forge.card.CardRenderer;
import forge.card.CardZoom;
import forge.card.CardRenderer.CardStackPosition;
import forge.screens.match.views.VPrompt;
import forge.toolbox.FEvent.*;
import forge.util.Callback;
@@ -110,7 +111,7 @@ public class FOptionPane extends FDialog {
float x = (getWidth() - w) / 2;
float y = 0;
CardRenderer.drawCard(g, card, x, y, w, h);
CardRenderer.drawCard(g, card, x, y, w, h, CardStackPosition.Top);
}
};
cardDisplay.setHeight(Utils.SCREEN_HEIGHT / 2);

View File

@@ -169,17 +169,21 @@ public class InputAttack extends InputSyncronizedBase {
/** {@inheritDoc} */
@Override
protected final boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
forge.FTrace.get("onCardSelected").start();
final List<Card> att = combat.getAttackers();
if (triggerEvent != null && triggerEvent.getButton() == 3 && att.contains(card)) {
if (undeclareAttacker(card)) {
updateMessage();
forge.FTrace.get("onCardSelected").end();
return true;
}
}
forge.FTrace.get("isAttackingDefender").start();
if (combat.isAttacking(card, currentDefender)) {
boolean validAction = true;
if (isBandingPossible()) {
forge.FTrace.get("activateBand").start();
// Activate band by selecting/deselecting a band member
if (activeBand == null) {
activateBand(combat.getBandOfAttacker(card));
@@ -197,41 +201,61 @@ public class InputAttack extends InputSyncronizedBase {
validAction = false;
}
}
forge.FTrace.get("activateBand").end();
}
else {
//if banding not possible, just undeclare attacker
forge.FTrace.get("undeclareAttacker").start();
undeclareAttacker(card);
forge.FTrace.get("undeclareAttacker").end();
}
updateMessage();
forge.FTrace.get("isAttackingDefender").end();
forge.FTrace.get("onCardSelected").end();
return validAction;
}
forge.FTrace.get("isAttackingDefender").end();
forge.FTrace.get("isOpponentOf").start();
if (card.getController().isOpponentOf(playerAttacks)) {
if (defenders.contains(card)) { // planeswalker?
setCurrentDefender(card);
forge.FTrace.get("isOpponentOf").end();
forge.FTrace.get("onCardSelected").end();
return true;
}
}
forge.FTrace.get("isOpponentOf").end();
forge.FTrace.get("canAttack").start();
if (playerAttacks.getZone(ZoneType.Battlefield).contains(card) && CombatUtil.canAttack(card, currentDefender, combat)) {
if (activeBand != null && !activeBand.canJoinBand(card)) {
activateBand(null);
updateMessage();
flashIncorrectAction();
forge.FTrace.get("onCardSelected").end();
return false;
}
forge.FTrace.get("isAttacking").start();
if (combat.isAttacking(card)) {
combat.removeFromCombat(card);
}
forge.FTrace.get("isAttacking").end();
forge.FTrace.get("declareAttacker").start();
declareAttacker(card);
forge.FTrace.get("declareAttacker").end();
updateMessage();
forge.FTrace.get("canAttack").end();
forge.FTrace.get("onCardSelected").end();
return true;
}
forge.FTrace.get("canAttack").end();
flashIncorrectAction();
forge.FTrace.get("onCardSelected").end();
return false;
}