- 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.view.FView;
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.
@@ -54,6 +61,8 @@ public enum TargetingOverlay {
private final List<CardPanel> cardPanels = new ArrayList<CardPanel>();
private final List<Point[]> arcs = new ArrayList<Point[]>();
private Rectangle rectMouseOver = null;
/**
* Semi-transparent overlay panel. Should be used with layered panes.
*/
@@ -75,15 +84,19 @@ public enum TargetingOverlay {
cardPanels.clear();
List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews();
rectMouseOver = null;
switch (CDock.SINGLETON_INSTANCE.getArcState()) {
case 0:
return;
case 1:
// Draw only hovered card
for (CField f : CMatchUI.SINGLETON_INSTANCE.getFieldControls()) {
cardPanels.addAll(f.getView().getTabletop().getCardPanels());
}
for (VField f : fields) {
if (f.getTabletop().getCardFromMouseOverPanel() != null) {
cardPanels.add(f.getTabletop().getMouseOverPanel());
rectMouseOver = f.getTabletop().getMouseOverPanel().getVisibleRect();
break;
}
}
@@ -102,8 +115,8 @@ public enum TargetingOverlay {
for (CardPanel c : cardPanels) {
if (!c.isShowing()) { continue; }
endpoints.put(c.getCard().getUniqueNumber(), new Point(
(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().getX() + c.getCardLocation().getX() /* - docOffsets.getX() */ + c.getWidth() / 4),
(int) (c.getParent().getLocationOnScreen().getY() + c.getCardLocation().getY() /* - docOffsets.getY() */ + c.getHeight() / 4)
));
}
@@ -116,6 +129,9 @@ public enum TargetingOverlay {
// Enchantments
Card enchanting = c.getCard().getEnchantingCard();
if (enchanting != null) {
if (enchanting.getController().equals(c.getCard().getController())) {
continue;
}
arcs.add(new Point[] {
endpoints.get(enchanting.getUniqueNumber()),
endpoints.get(c.getCard().getUniqueNumber())
@@ -147,6 +163,71 @@ public enum TargetingOverlay {
* @param g
* &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
public void paintComponent(final Graphics g) {
// No need for this except in match view
@@ -160,38 +241,35 @@ public enum TargetingOverlay {
// Arc drawing
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(FSkin.getColor(FSkin.Colors.CLR_ACTIVE));
g2d.setStroke(new BasicStroke(3F));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
assembleArcs();
if (arcs.size() < 1) { return; }
for (Point[] p : arcs) {
if (p[0] == null || p[1] == null) {
continue;
}
double SX = p[0].getX();
double SY = p[0].getY();
double CX = p[0].getY() > p[1].getY() ?
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);
if (rectMouseOver != null) {
if ( !rectMouseOver.contains(p[0]) ) {
continue;
}
}
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);
g2d.fillOval((int) p[1].getX() - 4, (int) p[1].getY() - 4, 8, 8);
Color color = FSkin.getColor(FSkin.Colors.CLR_ACTIVE);
drawArrow(g2d, startX, startY, endX, endY, color);
}
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
}
}
}