mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- Improved the visual appearance of targeting arrows.
- Targeting overlay now displays arrows for creatures attacking planeswalkers. - Combat arrows (blocking creatures, attacking planeswalkers) are now displayed in red while non-combat arrows are displayed in the more neutral theme-based color. - Optimized the display of targeting arrows in "always on" mode (should be somewhat faster when many arrows are displayed at once). - Some refactoring and minor fixes in targeting overlay code.
This commit is contained in:
@@ -50,7 +50,8 @@ public enum TargetingOverlay {
|
|||||||
|
|
||||||
private final OverlayPanel pnl = new OverlayPanel();
|
private final OverlayPanel pnl = new OverlayPanel();
|
||||||
private final List<CardPanel> cardPanels = new ArrayList<CardPanel>();
|
private final List<CardPanel> cardPanels = new ArrayList<CardPanel>();
|
||||||
private final List<Point[]> arcs = new ArrayList<Point[]>();
|
private final List<Point[]> arcsCombat = new ArrayList<Point[]>();
|
||||||
|
private final List<Point[]> arcsOther = new ArrayList<Point[]>();
|
||||||
|
|
||||||
private CardPanel activePanel = null;
|
private CardPanel activePanel = null;
|
||||||
|
|
||||||
@@ -74,6 +75,9 @@ public enum TargetingOverlay {
|
|||||||
// it checked for a state change. Doublestrike 28-09-12
|
// it checked for a state change. Doublestrike 28-09-12
|
||||||
private void assembleArcs(Combat combat) {
|
private void assembleArcs(Combat combat) {
|
||||||
//List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews();
|
//List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews();
|
||||||
|
arcsCombat.clear();
|
||||||
|
arcsOther.clear();
|
||||||
|
cardPanels.clear();
|
||||||
|
|
||||||
switch (CDock.SINGLETON_INSTANCE.getArcState()) {
|
switch (CDock.SINGLETON_INSTANCE.getArcState()) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -112,162 +116,147 @@ public enum TargetingOverlay {
|
|||||||
cardLocOnScreen = c.getCardLocationOnScreen();
|
cardLocOnScreen = c.getCardLocationOnScreen();
|
||||||
endpoints.put(c.getCard().getUniqueNumber(), new Point(
|
endpoints.put(c.getCard().getUniqueNumber(), new Point(
|
||||||
(int) (cardLocOnScreen.getX() - locOnScreen.getX() + c.getWidth() / 4),
|
(int) (cardLocOnScreen.getX() - locOnScreen.getX() + c.getWidth() / 4),
|
||||||
(int) (cardLocOnScreen.getY() - locOnScreen.getY() + c.getHeight() / 4)
|
(int) (cardLocOnScreen.getY() - locOnScreen.getY() + c.getHeight() / 2)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Card> temp = new ArrayList<Card>();
|
|
||||||
|
|
||||||
if (CDock.SINGLETON_INSTANCE.getArcState() == 1) {
|
if (CDock.SINGLETON_INSTANCE.getArcState() == 1) {
|
||||||
// Only work with the active panel
|
// Only work with the active panel
|
||||||
Card c = activePanel.getCard();
|
Card c = activePanel.getCard();
|
||||||
|
addArcsForCard(c, endpoints, combat);
|
||||||
Card enchanting = c.getEnchantingCard();
|
|
||||||
Card equipping = c.getEquippingCard();
|
|
||||||
Card fortifying = c.getFortifyingCard();
|
|
||||||
List<Card> enchantedBy = c.getEnchantedBy();
|
|
||||||
List<Card> equippedBy = c.getEquippedBy();
|
|
||||||
List<Card> fortifiedBy = c.getFortifiedBy();
|
|
||||||
Card paired = c.getPairedWith();
|
|
||||||
|
|
||||||
if (null != enchanting) {
|
|
||||||
if (!enchanting.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(enchanting.getUniqueNumber()),
|
|
||||||
endpoints.get(c.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != equipping) {
|
|
||||||
if (!equipping.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(equipping.getUniqueNumber()),
|
|
||||||
endpoints.get(c.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != fortifying) {
|
|
||||||
if (!fortifying.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(fortifying.getUniqueNumber()),
|
|
||||||
endpoints.get(c.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != enchantedBy) {
|
|
||||||
for (Card enc : enchantedBy) {
|
|
||||||
if (!enc.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(c.getUniqueNumber()),
|
|
||||||
endpoints.get(enc.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != equippedBy) {
|
|
||||||
for (Card eq : equippedBy) {
|
|
||||||
if (!eq.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(c.getUniqueNumber()),
|
|
||||||
endpoints.get(eq.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != fortifiedBy) {
|
|
||||||
for (Card eq : fortifiedBy) {
|
|
||||||
if (!eq.getController().equals(c.getController())) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(c.getUniqueNumber()),
|
|
||||||
endpoints.get(eq.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != paired) {
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(paired.getUniqueNumber()),
|
|
||||||
endpoints.get(c.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( null != combat ) {
|
|
||||||
for (Card attackingCard : combat.getAttackers()) {
|
|
||||||
temp = combat.getBlockers(attackingCard);
|
|
||||||
for (Card blockingCard : temp) {
|
|
||||||
if (!attackingCard.equals(c) && !blockingCard.equals(c)) { continue; }
|
|
||||||
arcs.add(new Point[] {
|
|
||||||
endpoints.get(attackingCard.getUniqueNumber()),
|
|
||||||
endpoints.get(blockingCard.getUniqueNumber())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Work with all card panels currently visible
|
// Work with all card panels currently visible
|
||||||
|
List<Card> visualized = new ArrayList<Card>();
|
||||||
// Global cards
|
|
||||||
for (CardPanel c : cardPanels) {
|
for (CardPanel c : cardPanels) {
|
||||||
if (!c.isShowing()) {
|
if (!c.isShowing()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Card card = c.getCard();
|
Card card = c.getCard();
|
||||||
|
if (visualized.contains(card)) { continue; }
|
||||||
|
|
||||||
// Enchantments
|
visualized.addAll(addArcsForCard(card, endpoints, combat));
|
||||||
Card enchanting = card.getEnchantingCard();
|
}
|
||||||
if (enchanting != null) {
|
}
|
||||||
if (enchanting.getController().equals(card.getController())) {
|
}
|
||||||
continue;
|
|
||||||
}
|
private List<Card> addArcsForCard(final Card c, final Map<Integer, Point> endpoints, final Combat combat) {
|
||||||
arcs.add(new Point[]{
|
List<Card> cardsVisualized = new ArrayList<Card>();
|
||||||
endpoints.get(enchanting.getUniqueNumber()),
|
cardsVisualized.add(c);
|
||||||
endpoints.get(card.getUniqueNumber())
|
|
||||||
});
|
Card enchanting = c.getEnchantingCard();
|
||||||
|
Card equipping = c.getEquippingCard();
|
||||||
|
Card fortifying = c.getFortifyingCard();
|
||||||
|
List<Card> enchantedBy = c.getEnchantedBy();
|
||||||
|
List<Card> equippedBy = c.getEquippedBy();
|
||||||
|
List<Card> fortifiedBy = c.getFortifiedBy();
|
||||||
|
Card paired = c.getPairedWith();
|
||||||
|
|
||||||
|
if (null != enchanting) {
|
||||||
|
if (!enchanting.getController().equals(c.getController())) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(enchanting.getUniqueNumber()),
|
||||||
|
endpoints.get(c.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(enchanting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != equipping) {
|
||||||
|
if (!equipping.getController().equals(c.getController())) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(equipping.getUniqueNumber()),
|
||||||
|
endpoints.get(c.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(equipping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != fortifying) {
|
||||||
|
if (!fortifying.getController().equals(c.getController())) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(fortifying.getUniqueNumber()),
|
||||||
|
endpoints.get(c.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(fortifying);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != enchantedBy) {
|
||||||
|
for (Card enc : enchantedBy) {
|
||||||
|
if (!enc.getController().equals(c.getController())) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(c.getUniqueNumber()),
|
||||||
|
endpoints.get(enc.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(enc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Combat cards
|
if (null != equippedBy) {
|
||||||
if ( null != combat )
|
for (Card eq : equippedBy) {
|
||||||
for (Card attackingCard : combat.getAttackers()) {
|
if (!eq.getController().equals(c.getController())) {
|
||||||
temp = combat.getBlockers(attackingCard);
|
arcsOther.add(new Point[] {
|
||||||
for (Card blockingCard : temp) {
|
endpoints.get(c.getUniqueNumber()),
|
||||||
arcs.add(new Point[]{
|
endpoints.get(eq.getUniqueNumber())
|
||||||
endpoints.get(attackingCard.getUniqueNumber()),
|
});
|
||||||
endpoints.get(blockingCard.getUniqueNumber())
|
cardsVisualized.add(eq);
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != fortifiedBy) {
|
||||||
|
for (Card eq : fortifiedBy) {
|
||||||
|
if (!eq.getController().equals(c.getController())) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(c.getUniqueNumber()),
|
||||||
|
endpoints.get(eq.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(eq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != paired) {
|
||||||
|
arcsOther.add(new Point[] {
|
||||||
|
endpoints.get(paired.getUniqueNumber()),
|
||||||
|
endpoints.get(c.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(paired);
|
||||||
|
}
|
||||||
|
if ( null != combat ) {
|
||||||
|
for (Card planeswalker : combat.getDefendingPlaneswalkers()) {
|
||||||
|
List<Card> cards = combat.getAttackersOf(planeswalker);
|
||||||
|
for (Card pwAttacker : cards) {
|
||||||
|
if (!planeswalker.equals(c) && !pwAttacker.equals(c)) { continue; }
|
||||||
|
arcsCombat.add(new Point[] {
|
||||||
|
endpoints.get(planeswalker.getUniqueNumber()),
|
||||||
|
endpoints.get(pwAttacker.getUniqueNumber())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cardsVisualized.add(planeswalker);
|
||||||
|
}
|
||||||
|
for (Card attackingCard : combat.getAttackers()) {
|
||||||
|
List<Card> cards = combat.getBlockers(attackingCard);
|
||||||
|
for (Card blockingCard : cards) {
|
||||||
|
if (!attackingCard.equals(c) && !blockingCard.equals(c)) { continue; }
|
||||||
|
arcsCombat.add(new Point[] {
|
||||||
|
endpoints.get(attackingCard.getUniqueNumber()),
|
||||||
|
endpoints.get(blockingCard.getUniqueNumber())
|
||||||
|
});
|
||||||
|
cardsVisualized.add(blockingCard);
|
||||||
|
}
|
||||||
|
cardsVisualized.add(attackingCard);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
temp.clear();
|
return cardsVisualized;
|
||||||
endpoints.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OverlayPanel extends SkinnedPanel {
|
private class OverlayPanel extends SkinnedPanel {
|
||||||
/**
|
|
||||||
* For some reason, the alpha channel background doesn't work properly on
|
|
||||||
* Windows 7, so the paintComponent override is required for a
|
|
||||||
* semi-transparent overlay.
|
|
||||||
*
|
|
||||||
* @param g
|
|
||||||
*   Graphics object
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Arrow drawing code by the MAGE team, used with permission.
|
// Arrow drawing code by the MAGE team, used with permission.
|
||||||
private Area getArrow(float length, float bendPercent) {
|
private Area getArrow(float length, float bendPercent) {
|
||||||
float p1x = 0, p1y = 0;
|
float p1x = 0, p1y = 0;
|
||||||
float p2x = length, p2y = 0;
|
float p2x = length, p2y = 0;
|
||||||
float cx = length / 2, cy = length / 8f * bendPercent;
|
float cx = length / 2, cy = length / 8f * bendPercent;
|
||||||
|
|
||||||
int bodyWidth = 10;
|
int bodyWidth = 15;
|
||||||
float headSize = 17;
|
float headSize = 20;
|
||||||
|
|
||||||
float adjSize, ex, ey, abs_e;
|
float adjSize, ex, ey, abs_e;
|
||||||
adjSize = (float) (bodyWidth / 2 / Math.sqrt(2));
|
adjSize = (float) (bodyWidth / 2 / Math.sqrt(2));
|
||||||
@@ -291,7 +280,7 @@ public enum TargetingOverlay {
|
|||||||
ey /= abs_e;
|
ey /= abs_e;
|
||||||
GeneralPath headPath = new GeneralPath();
|
GeneralPath headPath = new GeneralPath();
|
||||||
headPath.moveTo(p2x - (ey + ex) * adjSize, p2y + (ex - ey) * adjSize);
|
headPath.moveTo(p2x - (ey + ex) * adjSize, p2y + (ex - ey) * adjSize);
|
||||||
headPath.lineTo(p2x, p2y);
|
headPath.lineTo(p2x + headSize / 2, p2y);
|
||||||
headPath.lineTo(p2x + (ey - ex) * adjSize, p2y - (ex + ey) * adjSize);
|
headPath.lineTo(p2x + (ey - ex) * adjSize, p2y - (ex + ey) * adjSize);
|
||||||
headPath.closePath();
|
headPath.closePath();
|
||||||
|
|
||||||
@@ -300,7 +289,7 @@ public enum TargetingOverlay {
|
|||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawArrow(Graphics2D g2d, int startX, int startY, int endX, int endY, FSkin.SkinColor skinColor) {
|
private void drawArrow(Graphics2D g2d, int startX, int startY, int endX, int endY, Color color) {
|
||||||
float ex = endX - startX;
|
float ex = endX - startX;
|
||||||
float ey = endY - startY;
|
float ey = endY - startY;
|
||||||
if (ex == 0 && ey == 0) { return; }
|
if (ex == 0 && ey == 0) { return; }
|
||||||
@@ -317,8 +306,8 @@ public enum TargetingOverlay {
|
|||||||
|
|
||||||
g2d.translate(startX, startY);
|
g2d.translate(startX, startY);
|
||||||
g2d.rotate(Math.atan2(ey, ex));
|
g2d.rotate(Math.atan2(ey, ex));
|
||||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
|
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.60f));
|
||||||
FSkin.setGraphicsColor(g2d, skinColor);
|
g2d.setColor(color);
|
||||||
g2d.fill(arrow);
|
g2d.fill(arrow);
|
||||||
g2d.setColor(Color.BLACK);
|
g2d.setColor(Color.BLACK);
|
||||||
g2d.draw(arrow);
|
g2d.draw(arrow);
|
||||||
@@ -326,6 +315,30 @@ public enum TargetingOverlay {
|
|||||||
g2d.setTransform(af);
|
g2d.setTransform(af);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void drawArcs(Graphics2D g2d, Color color, List<Point[]> arcs) {
|
||||||
|
for (Point[] p : arcs) {
|
||||||
|
if (p[0] == null || p[1] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int endX = (int) p[0].getX();
|
||||||
|
int endY = (int) p[0].getY();
|
||||||
|
int startX = (int) p[1].getX();
|
||||||
|
int startY = (int) p[1].getY();
|
||||||
|
|
||||||
|
drawArrow(g2d, startX, startY, endX, endY, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For some reason, the alpha channel background doesn't work properly on
|
||||||
|
* Windows 7, so the paintComponent override is required for a
|
||||||
|
* semi-transparent overlay.
|
||||||
|
*
|
||||||
|
* @param g
|
||||||
|
*   Graphics object
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent(final Graphics g) {
|
public void paintComponent(final Graphics g) {
|
||||||
final Combat combat = Singletons.getControl().getObservedGame().getCombat(); // this will get deprecated too
|
final Combat combat = Singletons.getControl().getObservedGame().getCombat(); // this will get deprecated too
|
||||||
@@ -339,28 +352,18 @@ public enum TargetingOverlay {
|
|||||||
if (overlaystate == 0) { return; }
|
if (overlaystate == 0) { return; }
|
||||||
|
|
||||||
// Arc drawing
|
// Arc drawing
|
||||||
arcs.clear();
|
|
||||||
cardPanels.clear();
|
|
||||||
|
|
||||||
assembleArcs(combat);
|
assembleArcs(combat);
|
||||||
if (arcs.isEmpty()) { return; }
|
|
||||||
|
if (arcsCombat.isEmpty() && arcsOther.isEmpty()) { return; }
|
||||||
|
|
||||||
Graphics2D g2d = (Graphics2D) g;
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
FSkin.SkinColor skinColor = FSkin.getColor(FSkin.Colors.CLR_ACTIVE);
|
|
||||||
|
|
||||||
for (Point[] p : arcs) {
|
Color colorOther = FSkin.getColor(FSkin.Colors.CLR_ACTIVE).getColor();
|
||||||
if (p[0] == null || p[1] == null) {
|
Color colorCombat = Color.RED;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int endX = (int) p[0].getX();
|
drawArcs(g2d, colorOther, arcsOther);
|
||||||
int endY = (int) p[0].getY();
|
drawArcs(g2d, colorCombat, arcsCombat);
|
||||||
int startX = (int) p[1].getX();
|
|
||||||
int startY = (int) p[1].getY();
|
|
||||||
|
|
||||||
drawArrow(g2d, startX, startY, endX, endY, skinColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
|
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user