* UI: improved and fixed possible targets highlighting:

* added blockers highlighting on declare blockers step;
   * fixed that blocker targets highlights all attackers instead real;
   * fixed wrong attackers draw in images render mode;
This commit is contained in:
Oleg Agafonov 2019-03-28 09:29:15 +04:00
parent c58b28f94f
commit 0e6dbb4eed
7 changed files with 167 additions and 132 deletions

View file

@ -696,6 +696,13 @@ public final class GamePanel extends javax.swing.JPanel {
}
}
List<UUID> possibleBlockers = new ArrayList<>();
if (options != null && options.containsKey(Constants.Option.POSSIBLE_BLOCKERS)) {
if (options.get(Constants.Option.POSSIBLE_BLOCKERS) instanceof List) {
possibleBlockers.addAll((List) options.get(Constants.Option.POSSIBLE_BLOCKERS));
}
}
for (PlayerView player : game.getPlayers()) {
if (players.containsKey(player.getPlayerId())) {
if (!possibleAttackers.isEmpty()) {
@ -705,6 +712,13 @@ public final class GamePanel extends javax.swing.JPanel {
}
}
}
if (!possibleBlockers.isEmpty()) {
for (UUID permanentId : possibleBlockers) {
if (player.getBattlefield().containsKey(permanentId)) {
player.getBattlefield().get(permanentId).setCanBlock(true);
}
}
}
players.get(player.getPlayerId()).update(player);
if (player.getPlayerId().equals(playerId)) {
skipButtons.updateFromPlayer(player);

View file

@ -1,17 +1,5 @@
package org.mage.card.arcane;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.StringTokenizer;
import java.util.UUID;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.mage.plugins.card.images.ImageCache;
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
import mage.cards.action.ActionCallback;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
@ -25,6 +13,16 @@ import mage.view.CardView;
import mage.view.CounterView;
import mage.view.PermanentView;
import mage.view.StackAbilityView;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.mage.plugins.card.images.ImageCache;
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.StringTokenizer;
import java.util.UUID;
/**
* Class for drawing the mage card object by using a form based JComponent
@ -117,8 +115,9 @@ public class CardPanelComponentImpl extends CardPanel {
final boolean isChoosable;
final boolean isPlayable;
final boolean canAttack;
final boolean canBlock;
public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) {
public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack, boolean canBlock) {
this.width = width;
this.height = height;
this.cardWidth = cardWidth;
@ -130,6 +129,7 @@ public class CardPanelComponentImpl extends CardPanel {
this.isChoosable = isChoosable;
this.isPlayable = isPlayable;
this.canAttack = canAttack;
this.canBlock = canBlock;
}
@Override
@ -146,6 +146,7 @@ public class CardPanelComponentImpl extends CardPanel {
hash = 19 * hash + (this.isChoosable ? 1 : 0);
hash = 19 * hash + (this.isPlayable ? 1 : 0);
hash = 19 * hash + (this.canAttack ? 1 : 0);
hash = 19 * hash + (this.canBlock ? 1 : 0);
return hash;
}
@ -194,7 +195,7 @@ public class CardPanelComponentImpl extends CardPanel {
if (this.canAttack != other.canAttack) {
return false;
}
return true;
return this.canBlock == other.canBlock;
}
}
@ -202,20 +203,20 @@ public class CardPanelComponentImpl extends CardPanel {
IMAGE_CACHE = ImageCaches.register(SoftValuesLoadingCache.from(CardPanelComponentImpl::createImage));
}
static private boolean canShowCardIcons(int cardFullWidth, boolean cardHasImage){
static private boolean canShowCardIcons(int cardFullWidth, boolean cardHasImage) {
// cards without images show icons and text always
// TODO: apply "card names on card" setting to icon too?
// TODO: fix card min-max size to hide (compare to settings size, not direct 60 and 200)
return ((cardFullWidth > 60) && (cardFullWidth < 200)) || (!cardHasImage);
}
private static class CardSizes{
private static class CardSizes {
Rectangle rectFull;
Rectangle rectSelection;
Rectangle rectBorder;
Rectangle rectCard;
CardSizes(int offsetX, int offsetY, int fullWidth, int fullHeight){
CardSizes(int offsetX, int offsetY, int fullWidth, int fullHeight) {
int realBorderSizeX = Math.round(fullWidth * BLACK_BORDER_SIZE);
int realBorderSizeY = Math.round(fullWidth * BLACK_BORDER_SIZE);
@ -406,7 +407,8 @@ public class CardPanelComponentImpl extends CardPanel {
g2d.drawImage(
IMAGE_CACHE.getOrThrow(
new Key(getWidth(), getHeight(), getCardWidth(), getCardHeight(), getCardXOffset(), getCardYOffset(),
hasImage, isSelected(), isChoosable(), getGameCard().isPlayable(), getGameCard().isCanAttack())),
hasImage, isSelected(), isChoosable(), getGameCard().isPlayable(), getGameCard().isCanAttack(),
getGameCard().isCanBlock())),
0, 0, null);
g2d.dispose();
}
@ -442,6 +444,12 @@ public class CardPanelComponentImpl extends CardPanel {
g2d.fillRoundRect(sizes.rectSelection.x, sizes.rectSelection.y, sizes.rectSelection.width, sizes.rectSelection.height, cornerSizeSelection, cornerSizeSelection);
}
// draw attack or block border (?inner part of selection?)
if (key.canAttack || key.canBlock) {
g2d.setColor(new Color(255, 50, 50, 230));
g2d.fillRoundRect(sizes.rectSelection.x + 1, sizes.rectSelection.y + 1, sizes.rectSelection.width - 2, sizes.rectSelection.height - 2, cornerSizeSelection, cornerSizeSelection);
}
// draw empty card with border
if (!key.hasImage) {
// gray 1 px border
@ -452,12 +460,6 @@ public class CardPanelComponentImpl extends CardPanel {
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
}
// draw attack border (inner part of selection)
if (key.canAttack) {
g2d.setColor(new Color(0, 0, 255, 230));
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
}
// draw real card by component (see imagePanel and other layout's items)
//TODO:uncomment
@ -521,7 +523,7 @@ public class CardPanelComponentImpl extends CardPanel {
StringTokenizer tok = new StringTokenizer(manaCost, " ");
while (tok.hasMoreTokens()) {
tok.nextToken();
if(width != 0) {
if (width != 0) {
width += symbolMarginX;
}
width += getSymbolWidth();

View file

@ -1,17 +1,7 @@
package org.mage.card.arcane;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.mage.plugins.card.images.ImageCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import mage.cards.action.ActionCallback;
import mage.client.constants.Constants;
import mage.constants.CardType;
@ -21,6 +11,14 @@ import mage.view.CardView;
import mage.view.CounterView;
import mage.view.PermanentView;
import mage.view.StackAbilityView;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.mage.plugins.card.images.ImageCache;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public class CardPanelRenderImpl extends CardPanel {
@ -107,9 +105,7 @@ public class CardPanelRenderImpl extends CardPanel {
// are the same for a and b
return false;
}
if (aa.getDamage() != bb.getDamage()) {
return false;
}
return aa.getDamage() == bb.getDamage();
}
return true;
}
@ -143,6 +139,7 @@ public class CardPanelRenderImpl extends CardPanel {
sb.append((char) (isChoosable ? 1 : 0));
sb.append((char) (this.view.isPlayable() ? 1 : 0));
sb.append((char) (this.view.isCanAttack() ? 1 : 0));
sb.append((char) (this.view.isCanBlock() ? 1 : 0));
sb.append((char) (this.view.isFaceDown() ? 1 : 0));
sb.append((char) this.view.getFrameStyle().ordinal());
if (this.view instanceof PermanentView) {
@ -266,8 +263,8 @@ public class CardPanelRenderImpl extends CardPanel {
// Try to get card image from cache based on our card characteristics
ImageKey key
= new ImageKey(getGameCard(), artImage,
getCardWidth(), getCardHeight(),
isChoosable(), isSelected());
getCardWidth(), getCardHeight(),
isChoosable(), isSelected());
try {
cardImage = IMAGE_CACHE.get(key, this::renderCard);
} catch (ExecutionException e) {

View file

@ -5,24 +5,6 @@
*/
package org.mage.card.arcane;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.*;
import mage.ObjectColor;
import mage.cards.ArtRect;
import mage.cards.FrameStyle;
@ -34,6 +16,22 @@ import mage.util.SubTypeList;
import mage.view.CardView;
import mage.view.PermanentView;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
@ -56,9 +54,10 @@ import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
render.draw(g, cardWidth, cardHeight);
}
*/
/**
* @author stravant@gmail.com
*
* <p>
* Base rendering class for new border cards
*/
public class ModernCardRenderer extends CardRenderer {
@ -98,6 +97,7 @@ public class ModernCardRenderer extends CardRenderer {
}
return new Font("Arial", Font.PLAIN, 1);
}
public static final Font BASE_BELEREN_FONT = loadFont("beleren-bold");
public static final Paint BG_TEXTURE_WHITE = loadBackgroundTexture("white");
@ -275,7 +275,9 @@ public class ModernCardRenderer extends CardRenderer {
} else if (cardView.isPlayable()) {
borderColor = new Color(153, 102, 204, 200);
} else if (cardView.isCanAttack()) {
borderColor = new Color(0, 0, 255, 230);
borderColor = new Color(255, 50, 50, 230);
} else if (cardView.isCanBlock()) {
borderColor = new Color(255, 50, 50, 230);
} else {
borderColor = Color.BLACK;
}
@ -659,7 +661,7 @@ public class ModernCardRenderer extends CardRenderer {
}
public void drawZendikarCurvedFace(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2,
Color boxColor, Paint paint) {
Color boxColor, Paint paint) {
BufferedImage artToUse = faceArtImage;
boolean hadToUseFullArt = false;
@ -707,8 +709,8 @@ public class ModernCardRenderer extends CardRenderer {
}
public void drawBFZCurvedFace(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2,
int topxdelta, int endydelta,
Color boxColor, Paint paint) {
int topxdelta, int endydelta,
Color boxColor, Paint paint) {
BufferedImage artToUse = faceArtImage;
boolean hadToUseFullArt = false;
if (faceArtImage == null) {
@ -764,10 +766,10 @@ public class ModernCardRenderer extends CardRenderer {
}
public void drawUSTCurves(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2,
int topxdelta, int endydelta,
Color boxColor, Paint paint) {
int topxdelta, int endydelta,
Color boxColor, Paint paint) {
BufferedImage artToUse = artImage;
int srcW = x2;
int srcH = y2;
if (artToUse != null) {
@ -999,23 +1001,23 @@ public class ModernCardRenderer extends CardRenderer {
Polygon symbol = new Polygon(
new int[]{
x + w / 2,
(int) (x + w * 0.9),
x + w,
(int) (x + w * 0.6),
x + w / 2,
(int) (x + w * 0.4),
x,
(int) (x + w * 0.1),},
x + w / 2,
(int) (x + w * 0.9),
x + w,
(int) (x + w * 0.6),
x + w / 2,
(int) (x + w * 0.4),
x,
(int) (x + w * 0.1),},
new int[]{
y + h,
(int) (y + 0.8 * h),
y,
(int) (y - 0.2 * h),
y,
(int) (y - 0.2 * h),
y,
(int) (y + 0.8 * h),},
y + h,
(int) (y + 0.8 * h),
y,
(int) (y - 0.2 * h),
y,
(int) (y - 0.2 * h),
y,
(int) (y + 0.8 * h),},
8);
// Draw + stroke
@ -1124,7 +1126,7 @@ public class ModernCardRenderer extends CardRenderer {
drawBasicManaTextbox(g, x, y, w, h, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
return;
} else // Big circle in the middle for Zendikar lands
if (allRules.size() == 1) {
if (allRules.size() == 1) {
// Size of mana symbol = 9/4 * h, 3/4h above line
if (allRules.get(0) instanceof TextboxBasicManaRule) {
drawBasicManaSymbol(g, x + w / 2 - 9 * h / 8 + 1, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
@ -1278,45 +1280,45 @@ public class ModernCardRenderer extends CardRenderer {
if (loyaltyRule.loyaltyChange < 0 || loyaltyRule.loyaltyChange == TextboxLoyaltyRule.MINUS_X) {
symbol = new Polygon(
new int[]{
symbolX,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX + symbolWidth / 2,
symbolX,},
symbolX,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX + symbolWidth / 2,
symbolX,},
new int[]{
symbolY,
symbolY,
symbolY + symbolHeight - 3,
symbolY + symbolHeight + 3,
symbolY + symbolHeight - 3,},
symbolY,
symbolY,
symbolY + symbolHeight - 3,
symbolY + symbolHeight + 3,
symbolY + symbolHeight - 3,},
5);
} else if (loyaltyRule.loyaltyChange > 0) {
symbol = new Polygon(
new int[]{
symbolX,
symbolX + symbolWidth / 2,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX,},
symbolX,
symbolX + symbolWidth / 2,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX,},
new int[]{
symbolY + 3,
symbolY - 3,
symbolY + 3,
symbolY + symbolHeight,
symbolY + symbolHeight,},
symbolY + 3,
symbolY - 3,
symbolY + 3,
symbolY + symbolHeight,
symbolY + symbolHeight,},
5);
} else {
symbol = new Polygon(
new int[]{
symbolX,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX,},
symbolX,
symbolX + symbolWidth,
symbolX + symbolWidth,
symbolX,},
new int[]{
symbolY,
symbolY,
symbolY + symbolHeight,
symbolY + symbolHeight,},
symbolY,
symbolY,
symbolY + symbolHeight,
symbolY + symbolHeight,},
4);
}
g.setColor(new Color(0, 0, 0, 128));
@ -1610,13 +1612,13 @@ public class ModernCardRenderer extends CardRenderer {
Color[] translatedColors;
if (types.contains(CardType.LAND)) {
translatedColors = new Color[]{
getLandTextboxColor(twoColors.get(0)),
getLandTextboxColor(twoColors.get(1))
getLandTextboxColor(twoColors.get(0)),
getLandTextboxColor(twoColors.get(1))
};
} else {
translatedColors = new Color[]{
getTextboxColor(twoColors.get(0)),
getTextboxColor(twoColors.get(1))
getTextboxColor(twoColors.get(0)),
getTextboxColor(twoColors.get(1))
};
}