- Targeting Overlay: much prettier targeting arrows (thanks to the MAGE team for permission for adaptation), some initial work for the "mouseover-only" mode fix (not enabled yet).

This commit is contained in:
Agetian
2012-11-25 10:24:47 +00:00
parent b0ad9063a9
commit 98825de96c

View File

@@ -39,6 +39,13 @@ import forge.gui.match.nonsingleton.VField;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
import forge.view.FView; import forge.view.FView;
import forge.view.arcane.CardPanel; import forge.view.arcane.CardPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
/** /**
* Semi-transparent overlay panel. Should be used with layered panes. * Semi-transparent overlay panel. Should be used with layered panes.
@@ -54,6 +61,8 @@ public enum TargetingOverlay {
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[]> arcs = new ArrayList<Point[]>();
private Rectangle rectMouseOver = null;
/** /**
* Semi-transparent overlay panel. Should be used with layered panes. * Semi-transparent overlay panel. Should be used with layered panes.
*/ */
@@ -75,15 +84,19 @@ public enum TargetingOverlay {
cardPanels.clear(); cardPanels.clear();
List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews(); List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews();
rectMouseOver = null;
switch (CDock.SINGLETON_INSTANCE.getArcState()) { switch (CDock.SINGLETON_INSTANCE.getArcState()) {
case 0: case 0:
return; return;
case 1: case 1:
// Draw only hovered card // Draw only hovered card
for (CField f : CMatchUI.SINGLETON_INSTANCE.getFieldControls()) {
cardPanels.addAll(f.getView().getTabletop().getCardPanels());
}
for (VField f : fields) { for (VField f : fields) {
if (f.getTabletop().getCardFromMouseOverPanel() != null) { if (f.getTabletop().getCardFromMouseOverPanel() != null) {
cardPanels.add(f.getTabletop().getMouseOverPanel()); rectMouseOver = f.getTabletop().getMouseOverPanel().getVisibleRect();
break; break;
} }
} }
@@ -102,8 +115,8 @@ public enum TargetingOverlay {
for (CardPanel c : cardPanels) { for (CardPanel c : cardPanels) {
if (!c.isShowing()) { continue; } if (!c.isShowing()) { continue; }
endpoints.put(c.getCard().getUniqueNumber(), new Point( endpoints.put(c.getCard().getUniqueNumber(), new Point(
(int) (c.getParent().getLocationOnScreen().getX() + c.getCardLocation().getX() - docOffsets.getX() + c.getWidth() / 4), (int) (c.getParent().getLocationOnScreen().getX() + c.getCardLocation().getX() /* - docOffsets.getX() */ + c.getWidth() / 4),
(int) (c.getParent().getLocationOnScreen().getY() + c.getCardLocation().getY() - docOffsets.getY() + c.getHeight() / 4) (int) (c.getParent().getLocationOnScreen().getY() + c.getCardLocation().getY() /* - docOffsets.getY() */ + c.getHeight() / 4)
)); ));
} }
@@ -116,6 +129,9 @@ public enum TargetingOverlay {
// Enchantments // Enchantments
Card enchanting = c.getCard().getEnchantingCard(); Card enchanting = c.getCard().getEnchantingCard();
if (enchanting != null) { if (enchanting != null) {
if (enchanting.getController().equals(c.getCard().getController())) {
continue;
}
arcs.add(new Point[] { arcs.add(new Point[] {
endpoints.get(enchanting.getUniqueNumber()), endpoints.get(enchanting.getUniqueNumber()),
endpoints.get(c.getCard().getUniqueNumber()) endpoints.get(c.getCard().getUniqueNumber())
@@ -147,6 +163,71 @@ public enum TargetingOverlay {
* @param g * @param g
* &emsp; Graphics object * &emsp; Graphics object
*/ */
// Arrow drawing code by the MAGE team, used with permission.
private Area getArrow (float length, float bendPercent) {
float p1x = 0, p1y = 0;
float p2x = length, p2y = 0;
float cx = length / 2, cy = length / 8f * bendPercent;
int bodyWidth = 10;
float headSize = 17;
float adjSize, ex, ey, abs_e;
adjSize = (float)(bodyWidth / 2 / Math.sqrt(2));
ex = p2x - cx;
ey = p2y - cy;
abs_e = (float)Math.sqrt(ex * ex + ey * ey);
ex /= abs_e;
ey /= abs_e;
GeneralPath bodyPath = new GeneralPath();
bodyPath.moveTo(p2x + (ey - ex) * adjSize, p2y - (ex + ey) * adjSize);
bodyPath.quadTo(cx, cy, p1x, p1y - bodyWidth / 2);
bodyPath.lineTo(p1x, p1y + bodyWidth / 2);
bodyPath.quadTo(cx, cy, p2x - (ey + ex) * adjSize, p2y + (ex - ey) * adjSize);
bodyPath.closePath();
adjSize = (float)(headSize / Math.sqrt(2));
ex = p2x - cx;
ey = p2y - cy;
abs_e = (float)Math.sqrt(ex * ex + ey * ey);
ex /= abs_e;
ey /= abs_e;
GeneralPath headPath = new GeneralPath();
headPath.moveTo(p2x - (ey + ex) * adjSize, p2y + (ex - ey) * adjSize);
headPath.lineTo(p2x, p2y);
headPath.lineTo(p2x + (ey - ex) * adjSize, p2y - (ex + ey) * adjSize);
headPath.closePath();
Area area = new Area(headPath);
area.add(new Area(bodyPath));
return area;
}
private void drawArrow(Graphics2D g2d, int startX, int startY, int endX, int endY, Color color) {
float ex = endX - startX;
float ey = endY - startY;
if (ex == 0 && ey == 0) { return; }
float length = (float)Math.sqrt(ex * ex + ey * ey);
float bendPercent = (float)Math.asin(ey / length);
if (endX > startX) bendPercent = -bendPercent;
Area arrow = getArrow(length, bendPercent);
AffineTransform af = g2d.getTransform();
g2d.translate(startX, startY);
g2d.rotate(Math.atan2(ey, ex));
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
g2d.setColor(color);
g2d.fill(arrow);
g2d.setColor(Color.BLACK);
g2d.draw(arrow);
g2d.setTransform(af);
}
@Override @Override
public void paintComponent(final Graphics g) { public void paintComponent(final Graphics g) {
// No need for this except in match view // No need for this except in match view
@@ -160,38 +241,35 @@ public enum TargetingOverlay {
// Arc drawing // Arc drawing
Graphics2D g2d = (Graphics2D) g; Graphics2D g2d = (Graphics2D) g;
g2d.setColor(FSkin.getColor(FSkin.Colors.CLR_ACTIVE));
g2d.setStroke(new BasicStroke(3F));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON); RenderingHints.VALUE_ANTIALIAS_ON);
assembleArcs(); assembleArcs();
if (arcs.size() < 1) { return; } if (arcs.size() < 1) { return; }
for (Point[] p : arcs) { for (Point[] p : arcs) {
if (p[0] == null || p[1] == null) { if (p[0] == null || p[1] == null) {
continue; continue;
} }
double SX = p[0].getX(); if (rectMouseOver != null) {
double SY = p[0].getY(); if ( !rectMouseOver.contains(p[0]) ) {
double CX = p[0].getY() > p[1].getY() ? continue;
Math.max(p[0].getX(), p[1].getX()) * 0.33 + }
Math.min(p[0].getX(), p[1].getX()) * 0.66 : }
Math.min(p[0].getX(), p[1].getX()) * 0.33 +
Math.max(p[0].getX(), p[1].getX()) * 0.66;
double CY = Math.min(p[0].getY(), p[1].getY());
double EX = p[1].getX();
double EY = p[1].getY();
QuadCurve2D curve = new QuadCurve2D.Double(SX, SY, CX, CY, EX, EY);
g2d.draw(curve); int endX = (int)p[0].getX();
int endY = (int)p[0].getY();
int startX = (int)p[1].getX();
int startY = (int)p[1].getY();
g2d.fillOval((int) p[0].getX() - 4, (int) p[0].getY() - 4, 8, 8); Color color = FSkin.getColor(FSkin.Colors.CLR_ACTIVE);
g2d.fillOval((int) p[1].getX() - 4, (int) p[1].getY() - 4, 8, 8); drawArrow(g2d, startX, startY, endX, endY, color);
} }
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
} }
} }
} }