mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- 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:
@@ -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
|
||||||
*   Graphics object
|
*   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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user