diff --git a/.gitattributes b/.gitattributes
index 6bd5a992322..4589f890809 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -12465,6 +12465,7 @@ src/main/java/forge/gui/match/ControlWinLose.java -text
src/main/java/forge/gui/match/GauntletWinLose.java -text
src/main/java/forge/gui/match/QuestWinLoseCardViewer.java -text
src/main/java/forge/gui/match/QuestWinLoseHandler.java -text
+src/main/java/forge/gui/match/TargetingOverlay.java -text
src/main/java/forge/gui/match/VMatchUI.java -text
src/main/java/forge/gui/match/ViewWinLose.java -text
src/main/java/forge/gui/match/controllers/CAntes.java -text
diff --git a/res/skins/default/sprite_icons.png b/res/skins/default/sprite_icons.png
index a0394df0de3..d26a57eb927 100644
Binary files a/res/skins/default/sprite_icons.png and b/res/skins/default/sprite_icons.png differ
diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java
index 7d440e49abd..113b5a03237 100644
--- a/src/main/java/forge/control/FControl.java
+++ b/src/main/java/forge/control/FControl.java
@@ -256,11 +256,12 @@ public enum FControl {
/** Sizes children of JLayeredPane to fully fit their layers. */
private void sizeChildren() {
Component[] children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
- if (children.length == 0) { return; }
- children[0].setSize(display.getSize());
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
+
+ children = display.getComponentsInLayer(FView.TARGETING_LAYER);
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
children = display.getComponentsInLayer(JLayeredPane.MODAL_LAYER);
- if (children.length == 0) { return; }
- children[0].setSize(display.getSize());
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
}
}
diff --git a/src/main/java/forge/gui/match/TargetingOverlay.java b/src/main/java/forge/gui/match/TargetingOverlay.java
new file mode 100644
index 00000000000..2df29d7e77e
--- /dev/null
+++ b/src/main/java/forge/gui/match/TargetingOverlay.java
@@ -0,0 +1,157 @@
+/*
+ * Forge: Play Magic: the Gathering.
+ * Copyright (C) 2011 Forge Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package forge.gui.match;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JPanel;
+
+import forge.Card;
+import forge.control.FControl;
+import forge.gui.match.nonsingleton.CField;
+import forge.gui.toolbox.FSkin;
+import forge.model.FModel;
+import forge.properties.ForgePreferences.FPref;
+import forge.view.FView;
+import forge.view.arcane.CardPanel;
+import forge.view.arcane.PlayArea;
+
+/**
+ * Semi-transparent overlay panel. Should be used with layered panes.
+ *
+ */
+
+@SuppressWarnings("serial")
+public enum TargetingOverlay {
+ /** */
+ SINGLETON_INSTANCE;
+
+ private final JPanel pnl = new OverlayPanel();
+ private final List playAreas;
+ private List cardPanels;
+ private final List arcs = new ArrayList();
+
+ /**
+ * Semi-transparent overlay panel. Should be used with layered panes.
+ */
+ private TargetingOverlay() {
+ playAreas = new ArrayList();
+ cardPanels = new ArrayList();
+
+ for (CField f : CMatchUI.SINGLETON_INSTANCE.getFieldControls()) {
+ playAreas.add(f.getView().getTabletop());
+ }
+
+ pnl.setOpaque(false);
+ pnl.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA));
+ }
+
+ /** @return {@link javax.swing.JPanel} */
+ public JPanel getPanel() {
+ return this.pnl;
+ }
+
+ // TODO - this is called every repaint, regardless if card
+ // positions have changed or not. Could perform better if
+ // it checked for a state change. Doublestrike 28-09-12
+ private void assembleArcs() {
+ arcs.clear();
+ cardPanels.clear();
+ cardPanels.addAll(playAreas.get(0).getCardPanels());
+ cardPanels.addAll(playAreas.get(1).getCardPanels());
+
+ final Point docOffsets = FView.SINGLETON_INSTANCE.getLpnDocument().getLocationOnScreen();
+ // Locations of arc endpoint, per card, with ID as primary key.
+ final Map endpoints = new HashMap();
+
+ // Assemble card locations for easy reference
+ 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)
+ ));
+ }
+
+ List temp = new ArrayList();
+ for (CardPanel c : cardPanels) {
+ if (!c.isShowing()) { continue; }
+ temp = c.getCard().getEnchantedBy();
+ for (Card enchantingCard : temp) {
+ arcs.add(new Point[] {
+ endpoints.get(c.getCard().getUniqueNumber()),
+ endpoints.get(enchantingCard.getUniqueNumber())
+ });
+ }
+ }
+
+ temp.clear();
+ endpoints.clear();
+ }
+
+ private class OverlayPanel extends JPanel {
+ /**
+ * 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
+ public void paintComponent(final Graphics g) {
+ // No need for this except in match view
+ if (FControl.SINGLETON_INSTANCE.getState() != 1) {
+ return;
+ }
+ else if (!Boolean.valueOf(FModel.SINGLETON_INSTANCE.getPreferences().getPref(FPref.UI_TARGETING_OVERLAY))) {
+ return;
+ }
+
+ super.paintComponent(g);
+ // 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();
+ int w, h, x, y;
+
+ for (Point[] p : arcs) {
+ w = Math.abs((int) p[1].getX() - (int) p[0].getX());
+ h = Math.abs((int) p[1].getY() - (int) p[0].getY());
+ x = (Math.min((int) p[1].getX(), (int) p[0].getX()) - w);
+ y = (Math.min((int) p[1].getY(), (int) p[0].getY()));
+
+ g2d.drawArc(x, y, 2 * w, 2 * h, 0, 90);
+ 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);
+ }
+ }
+ }
+}
diff --git a/src/main/java/forge/gui/match/controllers/CDock.java b/src/main/java/forge/gui/match/controllers/CDock.java
index e4df86cef64..8678e727ec2 100644
--- a/src/main/java/forge/gui/match/controllers/CDock.java
+++ b/src/main/java/forge/gui/match/controllers/CDock.java
@@ -47,11 +47,14 @@ import forge.gui.ForgeAction;
import forge.gui.SOverlayUtils;
import forge.gui.framework.ICDoc;
import forge.gui.framework.SLayoutIO;
+import forge.gui.match.TargetingOverlay;
import forge.gui.match.views.VDock;
import forge.gui.toolbox.FOverlay;
import forge.gui.toolbox.SaveOpenDialog;
import forge.gui.toolbox.SaveOpenDialog.Filetypes;
import forge.item.CardPrinted;
+import forge.model.FModel;
+import forge.properties.ForgePreferences.FPref;
import forge.properties.NewConstants;
import forge.view.FView;
@@ -141,25 +144,39 @@ public enum CDock implements ICDoc {
private void viewDeckList() {
new DeckListAction(NewConstants.Lang.GuiDisplay.HUMAN_DECKLIST).actionPerformed(null);
}
-
- /** Attack with everyone */
+
+ /** Attack with everyone. */
public void alphaStrike() {
- PhaseHandler ph = Singletons.getModel().getGameState().getPhaseHandler();
-
- Player human = AllZone.getHumanPlayer();
-
+ final PhaseHandler ph = Singletons.getModel().getGameState().getPhaseHandler();
+
+ final Player human = AllZone.getHumanPlayer();
+
if (ph.is(PhaseType.COMBAT_DECLARE_ATTACKERS, human)) {
- for(Card c : human.getCardsIn(ZoneType.Battlefield).filter(Presets.CREATURES)) {
+ for (Card c : human.getCardsIn(ZoneType.Battlefield).filter(Presets.CREATURES)) {
if (!c.isAttacking() && CombatUtil.canAttack(c, AllZone.getCombat())) {
AllZone.getCombat().addAttacker(c);
}
}
//human.updateObservers();
+
// TODO Is this redrawing immediately?
FView.SINGLETON_INSTANCE.getFrame().repaint();
}
}
+ /** Toggle targeting overlay painting. */
+ public void toggleTargeting() {
+ if (Boolean.valueOf(FModel.SINGLETON_INSTANCE.getPreferences().getPref(FPref.UI_TARGETING_OVERLAY))) {
+ FModel.SINGLETON_INSTANCE.getPreferences().setPref(FPref.UI_TARGETING_OVERLAY, "false");
+ }
+ else {
+ FModel.SINGLETON_INSTANCE.getPreferences().setPref(FPref.UI_TARGETING_OVERLAY, "true");
+ }
+
+ FModel.SINGLETON_INSTANCE.getPreferences().save();
+ TargetingOverlay.SINGLETON_INSTANCE.getPanel().repaint();
+ }
+
/**
* Receives click and programmatic requests for viewing a player's library
* (typically used in dev mode). Allows copy of the cardlist to clipboard.
@@ -282,11 +299,16 @@ public enum CDock implements ICDoc {
.addMouseListener(new MouseAdapter() { @Override
public void mousePressed(final MouseEvent e) {
saveLayout(); } });
-
+
VDock.SINGLETON_INSTANCE.getBtnAlphaStrike()
.addMouseListener(new MouseAdapter() { @Override
public void mousePressed(final MouseEvent e) {
alphaStrike(); } });
+
+ VDock.SINGLETON_INSTANCE.getBtnTargeting()
+ .addMouseListener(new MouseAdapter() { @Override
+ public void mousePressed(final MouseEvent e) {
+ toggleTargeting(); } });
}
/* (non-Javadoc)
diff --git a/src/main/java/forge/gui/match/views/VDock.java b/src/main/java/forge/gui/match/views/VDock.java
index bcc5f842bce..59b042f1302 100644
--- a/src/main/java/forge/gui/match/views/VDock.java
+++ b/src/main/java/forge/gui/match/views/VDock.java
@@ -67,6 +67,8 @@ public enum VDock implements IVDoc {
new DockButton(FSkin.getIcon(FSkin.DockIcons.ICO_SAVELAYOUT), "Save Layout");
private final JLabel btnAlphaStrike =
new DockButton(FSkin.getIcon(FSkin.DockIcons.ICO_ALPHASTRIKE), "Alpha Strike");
+ private final JLabel btnTargeting =
+ new DockButton(FSkin.getIcon(FSkin.DockIcons.ICO_TARGETING), "Show Targeting Arcs");
//========= Overridden methods
@@ -88,6 +90,7 @@ public enum VDock implements IVDoc {
pnl.add(btnOpenLayout);
pnl.add(btnSaveLayout);
pnl.add(btnAlphaStrike);
+ pnl.add(btnTargeting);
}
/* (non-Javadoc)
@@ -172,6 +175,11 @@ public enum VDock implements IVDoc {
return btnAlphaStrike;
}
+ /** @return {@link javax.swing.JLabel} */
+ public JLabel getBtnTargeting() {
+ return btnTargeting;
+ }
+
//========= Custom class handling
/**
* Buttons in Dock. JLabels are used to allow hover effects.
diff --git a/src/main/java/forge/gui/toolbox/FSkin.java b/src/main/java/forge/gui/toolbox/FSkin.java
index 0f0b0ecf689..e350c86f08a 100644
--- a/src/main/java/forge/gui/toolbox/FSkin.java
+++ b/src/main/java/forge/gui/toolbox/FSkin.java
@@ -227,7 +227,8 @@ public enum FSkin {
ICO_OPENLAYOUT (new int[] {0, 800, 80, 80}), /** */
ICO_SAVELAYOUT (new int[] {80, 800, 80, 80}), /** */
ICO_DECKLIST (new int[] {400, 640, 80, 80}), /** */
- ICO_ALPHASTRIKE (new int[] {160, 800, 80, 80});
+ ICO_ALPHASTRIKE (new int[] {160, 800, 80, 80}), /** */
+ ICO_TARGETING (new int[] {240, 800, 80, 80});
private int[] coords;
/** @param xy int[] coordinates */
diff --git a/src/main/java/forge/properties/ForgePreferences.java b/src/main/java/forge/properties/ForgePreferences.java
index 82a036002a0..03a868d8400 100644
--- a/src/main/java/forge/properties/ForgePreferences.java
+++ b/src/main/java/forge/properties/ForgePreferences.java
@@ -67,6 +67,7 @@ public class ForgePreferences {
UI_MANABURN("false"), /** */
UI_SKIN ("default"), /** */
UI_PREFERRED_AVATARS_ONLY ("false"), /** */
+ UI_TARGETING_OVERLAY ("false"), /** */
SUBMENU_CURRENTMENU (EMenuItem.CONSTRUCTED.toString()), /** */
SUBMENU_SANCTIONED ("false"), /** */
diff --git a/src/main/java/forge/view/FView.java b/src/main/java/forge/view/FView.java
index 203da9b9389..987e4c2c1ed 100644
--- a/src/main/java/forge/view/FView.java
+++ b/src/main/java/forge/view/FView.java
@@ -24,6 +24,7 @@ import forge.gui.framework.EDocID;
import forge.gui.framework.SLayoutConstants;
import forge.gui.home.CMainMenu;
import forge.gui.home.VHomeUI;
+import forge.gui.match.TargetingOverlay;
import forge.gui.match.VMatchUI;
import forge.gui.toolbox.FOverlay;
import forge.gui.toolbox.FPanel;
@@ -33,6 +34,9 @@ import forge.gui.toolbox.FSkin;
public enum FView {
/** */
SINGLETON_INSTANCE;
+
+ /** */
+ public static final Integer TARGETING_LAYER = JLayeredPane.MODAL_LAYER - 1;
private final List allCells = new ArrayList();
private SplashFrame splash;
@@ -73,6 +77,10 @@ public enum FView {
lpnDocument.add(pnlPreview, (Integer) 2);
lpnDocument.add(pnlTabOverflow, (Integer) 3);
lpnDocument.add(FOverlay.SINGLETON_INSTANCE.getPanel(), JLayeredPane.MODAL_LAYER);
+ // Note: when adding new panels here, keep in mind that the layered pane
+ // has a null layout, so new components will be (0,0) - gotcha!
+ // FControl has a method called "sizeComponents" which will fix this.
+ lpnDocument.add(TargetingOverlay.SINGLETON_INSTANCE.getPanel(), TARGETING_LAYER);
pnlInsets.add(pnlContent, BorderLayout.CENTER);
pnlInsets.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));