private StackInstanceDisplay(StackItemView stackInstance0, float width) { stackInstance = stackInstance0; CardView card = stackInstance.getSourceCard(); text = stackInstance.getText(); if (stackInstance.isOptionalTrigger() && stackInstance0 .getActivatingPlayer() .equals(MatchController.instance.getCurrentPlayer())) { text = "(OPTIONAL) " + text; } // TODO: A hacky workaround is currently used to make the game not leak the color information // for Morph cards. final CardStateView curState = card.getCurrentState(); final boolean isFaceDown = curState.getState() == CardStateName.FaceDown; final DetailColors color = isFaceDown ? CardDetailUtil.DetailColors.FACE_DOWN : CardDetailUtil.getBorderColor( card.getCurrentState(), true); // otherwise doesn't work correctly for face down Morphs backColor = FSkinColor.fromRGB(color.r, color.g, color.b); foreColor = FSkinColor.getHighContrastColor(backColor); width -= CARD_WIDTH; // account for card picture width -= 3 * PADDING + 2 * BORDER_THICKNESS; // account for left and right insets and gap between picture // and text float height = Math.max(CARD_HEIGHT, textRenderer.getWrappedBounds(text, FONT, width).height); height += 2 * (PADDING + BORDER_THICKNESS); preferredHeight = Math.round(height); }
@Override protected void drawOnContainer(Graphics g) { // draw target arrows immediately above stack for active item only if (activeItem != null) { Vector2 arrowOrigin = new Vector2( activeItem.getLeft() + VStack.CARD_WIDTH * FCardPanel.TARGET_ORIGIN_FACTOR_X + VStack.PADDING + VStack.BORDER_THICKNESS, activeItem.getTop() + VStack.CARD_HEIGHT * FCardPanel.TARGET_ORIGIN_FACTOR_Y + VStack.PADDING + VStack.BORDER_THICKNESS); PlayerView activator = activeStackInstance.getActivatingPlayer(); arrowOrigin = arrowOrigin.add(screenPos.x, screenPos.y); StackItemView instance = activeStackInstance; while (instance != null) { for (CardView c : instance.getTargetCards()) { TargetingOverlay.drawArrow(g, arrowOrigin, c, activator.isOpponentOf(c.getController())); } for (PlayerView p : instance.getTargetPlayers()) { TargetingOverlay.drawArrow(g, arrowOrigin, p, activator.isOpponentOf(p)); } instance = instance.getSubInstance(); } } }
// temporarily reveal zones targeted by active stack instance private void revealTargetZones() { if (activeStackInstance == null) { return; } final Set<ZoneType> zones = new HashSet<ZoneType>(); playersWithValidTargets = new HashMap<PlayerView, Object>(); for (final CardView c : activeStackInstance.getTargetCards()) { if (c.getZone() != null) { zones.add(c.getZone()); playersWithValidTargets.put(c.getController(), c); } } if (zones.isEmpty() || playersWithValidTargets.isEmpty()) { return; } MatchController.instance.openZones(zones, playersWithValidTargets); }
@Override public void draw(Graphics g) { float x = 0; float y = 0; float w = getWidth(); float h = preferredHeight; boolean needAlpha = (activeStackInstance != stackInstance); if (needAlpha) { // use alpha for non-active items on stack g.setAlphaComposite(ALPHA_COMPOSITE); } g.startClip(0, 0, w, getHeight()); // clip based on actual height g.fillRect(Color.BLACK, x, y, w, h); // draw rectangle for border x += BORDER_THICKNESS; y += BORDER_THICKNESS; w -= 2 * BORDER_THICKNESS; h -= 2 * BORDER_THICKNESS; g.fillRect(backColor, x, y, w, h); x += PADDING; y += PADDING; CardRenderer.drawCardWithOverlays( g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top); x += CARD_WIDTH + PADDING; w -= x + PADDING - BORDER_THICKNESS; h -= y + PADDING - BORDER_THICKNESS; textRenderer.drawText( g, text, FONT, foreColor, x, y, w, h, y, h, true, HAlignment.LEFT, true); g.endClip(); if (needAlpha) { g.resetAlphaComposite(); } }
@Override public boolean longPress(float x, float y) { CardZoom.show(stackInstance.getSourceCard()); return true; }
@Override public boolean tap(float x, float y, int count) { if (activeStackInstance != stackInstance) { // set as active stack instance if not already such activeStackInstance = stackInstance; restoreOldZones(); // restore old zones before changing active stack instance VStack.this.updateSizeAndPosition(); return true; } final GameView gameView = MatchController.instance.getGameView(); final IGuiGame gui = MatchController.instance; final IGameController controller = MatchController.instance.getGameController(); final PlayerView player = MatchController.instance.getCurrentPlayer(); if (player != null) { // don't show menu if tapping on art if (stackInstance.isAbility()) { FPopupMenu menu = new FPopupMenu() { @Override protected void buildMenu() { final String key = stackInstance.getKey(); final boolean autoYield = gui.shouldAutoYield(key); addItem( new FCheckBoxMenuItem( "Auto-Yield", autoYield, new FEventHandler() { @Override public void handleEvent(FEvent e) { gui.setShouldAutoYield(key, !autoYield); if (!autoYield && stackInstance.equals(gameView.peekStack())) { // auto-pass priority if ability is on top of stack controller.passPriority(); } } })); if (stackInstance.isOptionalTrigger() && stackInstance.getActivatingPlayer().equals(player)) { final int triggerID = stackInstance.getSourceTrigger(); addItem( new FCheckBoxMenuItem( "Always Yes", gui.shouldAlwaysAcceptTrigger(triggerID), new FEventHandler() { @Override public void handleEvent(FEvent e) { if (gui.shouldAlwaysAcceptTrigger(triggerID)) { gui.setShouldAlwaysAskTrigger(triggerID); } else { gui.setShouldAlwaysAcceptTrigger(triggerID); if (stackInstance.equals(gameView.peekStack())) { // auto-yes if ability is on top of stack controller.selectButtonOk(); } } } })); addItem( new FCheckBoxMenuItem( "Always No", gui.shouldAlwaysDeclineTrigger(triggerID), new FEventHandler() { @Override public void handleEvent(FEvent e) { if (gui.shouldAlwaysDeclineTrigger(triggerID)) { gui.setShouldAlwaysAskTrigger(triggerID); } else { gui.setShouldAlwaysDeclineTrigger(triggerID); if (stackInstance.equals(gameView.peekStack())) { // auto-no if ability is on top of stack controller.selectButtonOk(); } } } })); } addItem( new FMenuItem( "Zoom/Details", new FEventHandler() { @Override public void handleEvent(FEvent e) { CardZoom.show(stackInstance.getSourceCard()); } })); }; }; menu.show(this, x, y); return true; } } CardZoom.show(stackInstance.getSourceCard()); return true; }