From 1cc9056b7b81bbe47a8648a10e27d11764c5a25f Mon Sep 17 00:00:00 2001 From: drdev Date: Fri, 26 Sep 2014 10:32:09 +0000 Subject: [PATCH] Optimize card rendering behind other cards Fix issue with achievement tooltip not appearing at times --- .../src/forge/card/CardImageRenderer.java | 10 +++++-- .../src/forge/card/CardRenderer.java | 29 +++++++++++++------ .../src/forge/deck/AddBasicLandsDialog.java | 3 +- .../forge/itemmanager/views/ImageView.java | 11 ++++++- .../screens/match/views/VCardDisplayArea.java | 15 ++++++++++ .../src/forge/screens/match/views/VStack.java | 3 +- .../screens/settings/AchievementsPage.java | 5 ++-- .../src/forge/toolbox/FCardPanel.java | 8 ++++- .../src/forge/toolbox/FChoiceList.java | 3 +- .../src/forge/toolbox/FOptionPane.java | 3 +- .../java/forge/match/input/InputAttack.java | 24 +++++++++++++++ 11 files changed, 95 insertions(+), 19 deletions(-) diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 9c0c1e7e436..a2288dd0a26 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -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); diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index f71404ecc89..e67eb6cd067 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -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); } } diff --git a/forge-gui-mobile/src/forge/deck/AddBasicLandsDialog.java b/forge-gui-mobile/src/forge/deck/AddBasicLandsDialog.java index 4eeff5a0df3..91793e0d396 100644 --- a/forge-gui-mobile/src/forge/deck/AddBasicLandsDialog.java +++ b/forge-gui-mobile/src/forge/deck/AddBasicLandsDialog.java @@ -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); } } } diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java index 6dbb4e51186..d42c68c070a 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java @@ -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 extends ItemView { 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 extends ItemView { 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 extends ItemView { } } 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 extends ItemView { 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 extends ItemView { } 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); diff --git a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java index b58b4e0efb7..7308090a3ee 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java @@ -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; diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index 47688922313..e4ad2eab20e 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -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; diff --git a/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java b/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java index e38f78015f5..7250bc94f98 100644 --- a/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java @@ -146,7 +146,8 @@ public class AchievementsPage extends TabPage { @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 { x = startX; if (y >= getHeight()) { - return; + break; } } diff --git a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java index 1095790a1f8..b5cbc0fd733 100644 --- a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java +++ b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java @@ -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(); diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index ea9dc78bc6a..6f7af9189e9 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -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 extends FList { @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; diff --git a/forge-gui-mobile/src/forge/toolbox/FOptionPane.java b/forge-gui-mobile/src/forge/toolbox/FOptionPane.java index fd6de957421..ab8b0bf8f6a 100644 --- a/forge-gui-mobile/src/forge/toolbox/FOptionPane.java +++ b/forge-gui-mobile/src/forge/toolbox/FOptionPane.java @@ -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); diff --git a/forge-gui/src/main/java/forge/match/input/InputAttack.java b/forge-gui/src/main/java/forge/match/input/InputAttack.java index 5f485ece428..556a9ede3ce 100644 --- a/forge-gui/src/main/java/forge/match/input/InputAttack.java +++ b/forge-gui/src/main/java/forge/match/input/InputAttack.java @@ -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 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; }