Merge origin/master into pull2
1
.gitignore
vendored
|
@ -92,6 +92,7 @@ hs_err*.log
|
|||
*.txt
|
||||
Mage.Client/serverlist.txt
|
||||
/bin/
|
||||
/out/
|
||||
/target/
|
||||
|
||||
client_secrets.json
|
||||
|
|
|
@ -277,6 +277,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
try {
|
||||
UIManager.put("desktop", new Color(0, 0, 0, 0));
|
||||
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
|
||||
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
// stop JSplitPane from eating F6 and F8 or any other function keys
|
||||
{
|
||||
Object value = UIManager.get("SplitPane.ancestorInputMap");
|
||||
|
|
|
@ -92,6 +92,7 @@ import mage.view.CardView;
|
|||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.StackAbilityView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -191,7 +192,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
gSmall.drawImage(ImageHelper.scaleImage(image, Config.dimensions.frameWidth, Config.dimensions.frameHeight), 0, 0, this);
|
||||
|
||||
gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
|
||||
gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
|
||||
gImage.drawString(card.getName()+"TEST", CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
|
||||
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
||||
gImage.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_TEXT_MAX_LEFT, POWBOX_TEXT_MAX_TOP);
|
||||
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||
|
@ -205,9 +206,9 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
gImage.dispose();
|
||||
|
||||
gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.nameFontSize));
|
||||
gSmall.drawString(card.getName(), Config.dimensions.contentXOffset, Config.dimensions.nameYOffset);
|
||||
gSmall.drawString(card.getName()+"TEST2", Config.dimensions.contentXOffset, Config.dimensions.nameYOffset);
|
||||
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
||||
gSmall.drawString(card.getPower() + "/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
||||
gSmall.drawString(card.getPower() + "/-/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
||||
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||
gSmall.drawString(card.getLoyalty(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateImage() {
|
||||
public void updateArtImage() {
|
||||
|
||||
}
|
||||
|
||||
|
@ -319,6 +320,19 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
return sbType.toString();
|
||||
}
|
||||
|
||||
protected void drawDetailed(Graphics2D g) {
|
||||
// Get the size of the card
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.drawRoundRect(0, 0, width, height, 4, 4);
|
||||
g.setColor(Color.white);
|
||||
g.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
|
||||
g.drawString(card.getName(), 0, 0);
|
||||
Logger.getLogger(Card.class).info("Drawing");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
|
@ -355,6 +369,8 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
|
||||
@Override
|
||||
public void paintComponent(Graphics graphics) {
|
||||
drawDetailed((Graphics2D)graphics);
|
||||
/*
|
||||
Graphics2D g2 = (Graphics2D) graphics;
|
||||
g2.drawImage(small, 0, 0, this);
|
||||
|
||||
|
@ -365,6 +381,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
g2.setColor(Color.BLACK);
|
||||
}
|
||||
g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -114,7 +114,7 @@ public class Cards extends javax.swing.JPanel {
|
|||
setGUISize();
|
||||
for (MageCard mageCard : cards.values()) {
|
||||
mageCard.setCardBounds(0, 0, getCardDimension().width, getCardDimension().height);
|
||||
mageCard.updateImage();
|
||||
mageCard.updateArtImage();
|
||||
mageCard.doLayout();
|
||||
}
|
||||
layoutCards();
|
||||
|
|
|
@ -34,21 +34,16 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="panelControl" pref="703" max="32767" attributes="0"/>
|
||||
<Component id="panelCardArea" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="panelControl" alignment="0" pref="467" max="32767" attributes="0"/>
|
||||
<Component id="panelCardArea" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="panelControl" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="panelCardArea" pref="86" max="32767" attributes="0"/>
|
||||
<Component id="panelControl" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<Component id="panelCardArea" pref="179" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -81,15 +76,7 @@
|
|||
<Component id="lblLandCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblCreatureCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblSorceryCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblInstantCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblEnchantmentCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<Component id="lblArtifactCount" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkPiles" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="cbSortBy" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -97,7 +84,7 @@
|
|||
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jToggleCardView" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="62" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -109,11 +96,7 @@
|
|||
<Component id="lblCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblLandCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblCreatureCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblSorceryCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblInstantCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblEnchantmentCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkPiles" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblArtifactCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="cbSortBy" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -177,60 +160,6 @@
|
|||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblSorceryCount">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/type_sorcery.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="999"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Number of sorceries."/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblInstantCount">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/type_instant.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="999"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Number of instants."/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEnchantmentCount">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/type_enchantment.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="999"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Number of enchantments."/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkPiles">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Piles"/>
|
||||
|
@ -324,24 +253,6 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleCardViewActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblArtifactCount">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/type_artifact.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="999"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Number of artifacts"/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="panelCardArea">
|
||||
|
|
|
@ -211,7 +211,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
}
|
||||
});
|
||||
|
||||
mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, lblSorceryCount, lblInstantCount, lblEnchantmentCount, lblArtifactCount));
|
||||
mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, null, null, null, null));
|
||||
}
|
||||
|
||||
// if you use the deck ediot to build a free deck, numbers can be set directly in deck and sideboard
|
||||
|
@ -418,10 +418,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
this.lblCount.setText(Integer.toString(count));
|
||||
this.lblCreatureCount.setText(Integer.toString(creatureCount));
|
||||
this.lblLandCount.setText(Integer.toString(landCount));
|
||||
this.lblSorceryCount.setText(Integer.toString(sorceryCount));
|
||||
this.lblInstantCount.setText(Integer.toString(instantCount));
|
||||
this.lblEnchantmentCount.setText(Integer.toString(enchantmentCount));
|
||||
this.lblArtifactCount.setText(Integer.toString(artifactCount));
|
||||
}
|
||||
|
||||
private MageCard addCard(CardView card, BigCard bigCard, UUID gameId) {
|
||||
|
@ -482,14 +478,10 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
lblCount = new javax.swing.JLabel();
|
||||
lblLandCount = new javax.swing.JLabel();
|
||||
lblCreatureCount = new javax.swing.JLabel();
|
||||
lblSorceryCount = new javax.swing.JLabel();
|
||||
lblInstantCount = new javax.swing.JLabel();
|
||||
lblEnchantmentCount = new javax.swing.JLabel();
|
||||
chkPiles = new javax.swing.JCheckBox();
|
||||
cbSortBy = new javax.swing.JComboBox();
|
||||
jToggleListView = new javax.swing.JToggleButton();
|
||||
jToggleCardView = new javax.swing.JToggleButton();
|
||||
lblArtifactCount = new javax.swing.JLabel();
|
||||
panelCardArea = new javax.swing.JScrollPane();
|
||||
cardArea = new javax.swing.JLayeredPane();
|
||||
|
||||
|
@ -537,39 +529,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
lblCreatureCount.setRequestFocusEnabled(false);
|
||||
lblCreatureCount.setVerifyInputWhenFocusTarget(false);
|
||||
|
||||
lblSorceryCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
lblSorceryCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_sorcery.png"))); // NOI18N
|
||||
lblSorceryCount.setText("999");
|
||||
lblSorceryCount.setToolTipText("Number of sorceries.");
|
||||
lblSorceryCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
lblSorceryCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
lblSorceryCount.setFocusable(false);
|
||||
lblSorceryCount.setInheritsPopupMenu(false);
|
||||
lblSorceryCount.setRequestFocusEnabled(false);
|
||||
lblSorceryCount.setVerifyInputWhenFocusTarget(false);
|
||||
|
||||
lblInstantCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
lblInstantCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_instant.png"))); // NOI18N
|
||||
lblInstantCount.setText("999");
|
||||
lblInstantCount.setToolTipText("Number of instants.");
|
||||
lblInstantCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
lblInstantCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
lblInstantCount.setFocusable(false);
|
||||
lblInstantCount.setInheritsPopupMenu(false);
|
||||
lblInstantCount.setRequestFocusEnabled(false);
|
||||
lblInstantCount.setVerifyInputWhenFocusTarget(false);
|
||||
|
||||
lblEnchantmentCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
lblEnchantmentCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_enchantment.png"))); // NOI18N
|
||||
lblEnchantmentCount.setText("999");
|
||||
lblEnchantmentCount.setToolTipText("Number of enchantments.");
|
||||
lblEnchantmentCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
lblEnchantmentCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
lblEnchantmentCount.setFocusable(false);
|
||||
lblEnchantmentCount.setInheritsPopupMenu(false);
|
||||
lblEnchantmentCount.setRequestFocusEnabled(false);
|
||||
lblEnchantmentCount.setVerifyInputWhenFocusTarget(false);
|
||||
|
||||
chkPiles.setText("Piles");
|
||||
chkPiles.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
chkPiles.setMargin(new java.awt.Insets(3, 2, 2, 2));
|
||||
|
@ -619,17 +578,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
}
|
||||
});
|
||||
|
||||
lblArtifactCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
lblArtifactCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_artifact.png"))); // NOI18N
|
||||
lblArtifactCount.setText("999");
|
||||
lblArtifactCount.setToolTipText("Number of artifacts");
|
||||
lblArtifactCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
lblArtifactCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
lblArtifactCount.setFocusable(false);
|
||||
lblArtifactCount.setInheritsPopupMenu(false);
|
||||
lblArtifactCount.setRequestFocusEnabled(false);
|
||||
lblArtifactCount.setVerifyInputWhenFocusTarget(false);
|
||||
|
||||
javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl);
|
||||
panelControl.setLayout(panelControlLayout);
|
||||
panelControlLayout.setHorizontalGroup(
|
||||
|
@ -641,14 +589,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblCreatureCount)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblSorceryCount)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblInstantCount)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblEnchantmentCount)
|
||||
.addGap(4, 4, 4)
|
||||
.addComponent(lblArtifactCount)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(chkPiles)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
|
@ -656,7 +596,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 62, Short.MAX_VALUE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
panelControlLayout.setVerticalGroup(
|
||||
panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -666,11 +606,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
.addComponent(lblCount)
|
||||
.addComponent(lblLandCount)
|
||||
.addComponent(lblCreatureCount)
|
||||
.addComponent(lblSorceryCount)
|
||||
.addComponent(lblInstantCount)
|
||||
.addComponent(lblEnchantmentCount)
|
||||
.addComponent(chkPiles)
|
||||
.addComponent(lblArtifactCount))
|
||||
.addComponent(chkPiles))
|
||||
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
|
@ -686,21 +622,27 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(1, 1, 1)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(panelControl, javax.swing.GroupLayout.DEFAULT_SIZE, 703, Short.MAX_VALUE)
|
||||
.addComponent(panelCardArea)))
|
||||
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 467, Short.MAX_VALUE)
|
||||
.addComponent(panelCardArea)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE))
|
||||
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(2, 2, 2)
|
||||
.addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed
|
||||
currentView = this;
|
||||
panelCardArea.setViewportView(cardArea);
|
||||
cbSortBy.setEnabled(true);
|
||||
chkPiles.setEnabled(true);
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView");
|
||||
redrawCards();
|
||||
}//GEN-LAST:event_jToggleCardViewActionPerformed
|
||||
|
||||
private void jToggleListViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleListViewActionPerformed
|
||||
currentView = mainModel;
|
||||
panelCardArea.setViewportView(mainTable);
|
||||
|
@ -720,15 +662,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
drawCards(sortSetting);
|
||||
}//GEN-LAST:event_chkPilesActionPerformed
|
||||
|
||||
private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed
|
||||
currentView = this;
|
||||
panelCardArea.setViewportView(cardArea);
|
||||
cbSortBy.setEnabled(true);
|
||||
chkPiles.setEnabled(true);
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView");
|
||||
redrawCards();
|
||||
}//GEN-LAST:event_jToggleCardViewActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup bgView;
|
||||
private javax.swing.JLayeredPane cardArea;
|
||||
|
@ -736,13 +669,9 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
private javax.swing.JCheckBox chkPiles;
|
||||
private javax.swing.JToggleButton jToggleCardView;
|
||||
private javax.swing.JToggleButton jToggleListView;
|
||||
private javax.swing.JLabel lblArtifactCount;
|
||||
private javax.swing.JLabel lblCount;
|
||||
private javax.swing.JLabel lblCreatureCount;
|
||||
private javax.swing.JLabel lblEnchantmentCount;
|
||||
private javax.swing.JLabel lblInstantCount;
|
||||
private javax.swing.JLabel lblLandCount;
|
||||
private javax.swing.JLabel lblSorceryCount;
|
||||
private javax.swing.JScrollPane panelCardArea;
|
||||
private javax.swing.JPanel panelControl;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
|
|
@ -16,31 +16,26 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="deckAreaSplitPane" alignment="0" pref="740" max="32767" attributes="0"/>
|
||||
<Component id="deckAreaSplitPane" alignment="0" pref="918" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="deckAreaSplitPane" alignment="0" pref="568" max="32767" attributes="0"/>
|
||||
<Component id="deckAreaSplitPane" alignment="0" pref="377" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="deckAreaSplitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
<Property name="resizeWeight" type="double" value="0.8"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="resizeWeight" type="double" value="0.6"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="mage.client.cards.CardsList" name="deckList">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="mage.client.cards.CardsList" name="sideboardList">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
|
@ -48,6 +43,13 @@
|
|||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="mage.client.cards.CardsList" name="deckList">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
|
|
@ -118,23 +118,23 @@ public class DeckArea extends javax.swing.JPanel {
|
|||
private void initComponents() {
|
||||
|
||||
deckAreaSplitPane = new javax.swing.JSplitPane();
|
||||
deckList = new mage.client.cards.CardsList();
|
||||
sideboardList = new mage.client.cards.CardsList();
|
||||
deckList = new mage.client.cards.CardsList();
|
||||
|
||||
deckAreaSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
deckAreaSplitPane.setResizeWeight(0.8);
|
||||
deckAreaSplitPane.setLeftComponent(deckList);
|
||||
deckAreaSplitPane.setBorder(null);
|
||||
deckAreaSplitPane.setResizeWeight(0.6);
|
||||
deckAreaSplitPane.setRightComponent(sideboardList);
|
||||
deckAreaSplitPane.setLeftComponent(deckList);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE)
|
||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 918, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE)
|
||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public class UpdateCountsCallback {
|
|||
private final javax.swing.JLabel lblCount;
|
||||
private final javax.swing.JLabel lblCreatureCount;
|
||||
private final javax.swing.JLabel lblLandCount;
|
||||
private final javax.swing.JLabel lblSoerceryCount;
|
||||
private final javax.swing.JLabel lblSorceryCount;
|
||||
private final javax.swing.JLabel lblInstantCount;
|
||||
private final javax.swing.JLabel lblEnchantmentCount;
|
||||
private final javax.swing.JLabel lblArtifactCount;
|
||||
|
@ -20,19 +20,26 @@ public class UpdateCountsCallback {
|
|||
this.lblCount = count;
|
||||
this.lblCreatureCount = creatures;
|
||||
this.lblLandCount = lands;
|
||||
this.lblSoerceryCount = sorceries;
|
||||
this.lblSorceryCount = sorceries;
|
||||
this.lblInstantCount = instants;
|
||||
this.lblEnchantmentCount = enchantments;
|
||||
this.lblArtifactCount = artifacts;
|
||||
}
|
||||
|
||||
public void update(int count, int creatures, int lands, int sorceries, int instants, int enchantments, int artifacts) {
|
||||
if (this.lblCount != null)
|
||||
this.lblCount.setText(Integer.toString(count));
|
||||
if (this.lblCreatureCount != null)
|
||||
this.lblCreatureCount.setText(Integer.toString(creatures));
|
||||
if (this.lblLandCount != null)
|
||||
this.lblLandCount.setText(Integer.toString(lands));
|
||||
this.lblSoerceryCount.setText(Integer.toString(sorceries));
|
||||
if (this.lblSorceryCount != null)
|
||||
this.lblSorceryCount.setText(Integer.toString(sorceries));
|
||||
if (this.lblInstantCount != null)
|
||||
this.lblInstantCount.setText(Integer.toString(instants));
|
||||
if (this.lblEnchantmentCount != null)
|
||||
this.lblEnchantmentCount.setText(Integer.toString(enchantments));
|
||||
if (this.lblArtifactCount != null)
|
||||
this.lblArtifactCount.setText(Integer.toString(artifacts));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,11 @@
|
|||
<Component id="exitButton" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tabsPanel" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tabsPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
|
@ -146,7 +150,7 @@
|
|||
<Property name="toolTipText" type="java.lang.String" value="Write the card's name on the card to make the card name more recognizable."/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Standardcursor"/>
|
||||
<Color id="Default Cursor"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
|
@ -3945,7 +3949,7 @@
|
|||
<Component id="checkBoxEndTurnOthers" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="phases_stopSettings" pref="260" max="32767" attributes="0"/>
|
||||
<Component id="phases_stopSettings" pref="266" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -4147,11 +4151,12 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="panelCardImages" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="panelBackgroundImages" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="panelCardImages" max="32767" attributes="0"/>
|
||||
<Component id="jPanel1" max="32767" attributes="0"/>
|
||||
<Component id="panelBackgroundImages" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -4160,11 +4165,13 @@
|
|||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="panelCardImages" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="panelBackgroundImages" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="90" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="53" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -4189,23 +4196,20 @@
|
|||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtImageFolderPath" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnBrowseImageLocation" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="labelNumberOfDownloadThreads" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbNumberOfDownloadThreads" min="-2" pref="153" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="cbUseDefaultImageFolder" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbCheckForNewImages" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="147" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -4213,12 +4217,20 @@
|
|||
</Group>
|
||||
<Component id="cbSaveToZipFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="40" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="cbPreferedImageLanguage" min="-2" pref="153" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="labelNumberOfDownloadThreads" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbNumberOfDownloadThreads" min="-2" pref="153" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="251" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="231" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -4228,14 +4240,13 @@
|
|||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtImageFolderPath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnBrowseImageLocation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbSaveToZipFiles" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -4249,7 +4260,6 @@
|
|||
<Component id="cbPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="labelPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="48" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -4473,6 +4483,72 @@
|
|||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Card rendering:">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="cbCardRenderImageFallback" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbCardRenderShowReminderText" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbCardRenderHideSetSymbol" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbCardRenderImageFallback" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbCardRenderShowReminderText" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbCardRenderHideSetSymbol" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="cbCardRenderImageFallback">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Fall back to plain image based rendering"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCardRenderImageFallbackActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbCardRenderShowReminderText">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Show reminder text in rendered card textboxes"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCardRenderShowReminderTextActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbCardRenderHideSetSymbol">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Hide set symbols on cards (more space on the type line for card types)"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCardRenderHideSetSymbolActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="tabSounds">
|
||||
|
@ -5579,7 +5655,7 @@
|
|||
<Component id="jLabel17" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="111" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="91" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
|
|
@ -118,6 +118,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip";
|
||||
public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage";
|
||||
|
||||
public static final String KEY_CARD_RENDERING_FALLBACK = "cardRenderingFallback";
|
||||
public static final String KEY_CARD_RENDERING_REMINDER_TEXT = "cardRenderingReminderText";
|
||||
public static final String KEY_CARD_RENDERING_SET_SYMBOL = "cardRenderingSetSymbol";
|
||||
|
||||
public static final String KEY_BACKGROUND_IMAGE = "backgroundImage";
|
||||
public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage";
|
||||
public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault";
|
||||
|
@ -464,6 +468,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
cbUseRandomBattleImage = new javax.swing.JCheckBox();
|
||||
jLabel14 = new javax.swing.JLabel();
|
||||
jLabel15 = new javax.swing.JLabel();
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
cbCardRenderImageFallback = new javax.swing.JCheckBox();
|
||||
cbCardRenderShowReminderText = new javax.swing.JCheckBox();
|
||||
cbCardRenderHideSetSymbol = new javax.swing.JCheckBox();
|
||||
tabSounds = new javax.swing.JPanel();
|
||||
sounds_clips = new javax.swing.JPanel();
|
||||
cbEnableGameSounds = new javax.swing.JCheckBox();
|
||||
|
@ -1385,7 +1393,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(jLabelEndOfTurn)
|
||||
.add(checkBoxEndTurnOthers))
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)
|
||||
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
|
@ -1439,41 +1447,43 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.add(24, 24, 24)
|
||||
.addContainerGap()
|
||||
.add(txtImageFolderPath)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(btnBrowseImageLocation))
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(labelNumberOfDownloadThreads)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(cbUseDefaultImageFolder)
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.add(cbCheckForNewImages)
|
||||
.add(147, 147, 147))
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(labelPreferedImageLanguage))
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles))
|
||||
.add(40, 40, 40)
|
||||
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
|
||||
.add(0, 251, Short.MAX_VALUE)))
|
||||
.add(20, 20, 20)
|
||||
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(labelNumberOfDownloadThreads)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
|
||||
.add(cbUseDefaultImageFolder))
|
||||
.add(0, 231, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
panelCardImagesLayout.setVerticalGroup(
|
||||
panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(panelCardImagesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(cbUseDefaultImageFolder)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(txtImageFolderPath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.add(btnBrowseImageLocation))
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(cbCheckForNewImages)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbSaveToZipFiles)
|
||||
|
@ -1484,8 +1494,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.add(labelPreferedImageLanguage))
|
||||
.addContainerGap(48, Short.MAX_VALUE))
|
||||
.add(labelPreferedImageLanguage)))
|
||||
);
|
||||
|
||||
panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images setting:"));
|
||||
|
@ -1592,6 +1601,51 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(jLabel15)))
|
||||
);
|
||||
|
||||
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card rendering:"));
|
||||
|
||||
cbCardRenderImageFallback.setText("Fall back to plain image based rendering");
|
||||
cbCardRenderImageFallback.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbCardRenderImageFallbackActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbCardRenderShowReminderText.setText("Show reminder text in rendered card textboxes");
|
||||
cbCardRenderShowReminderText.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbCardRenderShowReminderTextActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbCardRenderHideSetSymbol.setText("Hide set symbols on cards (more space on the type line for card types)");
|
||||
cbCardRenderHideSetSymbol.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbCardRenderHideSetSymbolActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(jPanel1Layout.createSequentialGroup()
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(cbCardRenderImageFallback)
|
||||
.add(cbCardRenderShowReminderText)
|
||||
.add(cbCardRenderHideSetSymbol))
|
||||
.add(0, 0, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(jPanel1Layout.createSequentialGroup()
|
||||
.add(cbCardRenderImageFallback)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbCardRenderShowReminderText)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbCardRenderHideSetSymbol)
|
||||
.add(0, 0, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
org.jdesktop.layout.GroupLayout tabImagesLayout = new org.jdesktop.layout.GroupLayout(tabImages);
|
||||
tabImages.setLayout(tabImagesLayout);
|
||||
tabImagesLayout.setHorizontalGroup(
|
||||
|
@ -1600,6 +1654,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.addContainerGap()
|
||||
.add(tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(panelCardImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
@ -1607,10 +1662,12 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(tabImagesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(90, Short.MAX_VALUE))
|
||||
.addContainerGap(53, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
tabsPanel.addTab("Images", tabImages);
|
||||
|
@ -2220,7 +2277,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(connection_serversLayout.createSequentialGroup()
|
||||
.add(141, 141, 141)
|
||||
.add(jLabel17)))
|
||||
.addContainerGap(111, Short.MAX_VALUE))
|
||||
.addContainerGap(91, Short.MAX_VALUE))
|
||||
);
|
||||
connection_serversLayout.setVerticalGroup(
|
||||
connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
|
@ -2406,7 +2463,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.add(6, 6, 6))
|
||||
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
|
@ -2534,6 +2594,11 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
||||
// rendering
|
||||
save(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
||||
// sounds
|
||||
save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
@ -2806,6 +2871,14 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbAutoOrderTriggerActionPerformed
|
||||
|
||||
private void cbCardRenderImageFallbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderImageFallbackActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbCardRenderImageFallbackActionPerformed
|
||||
|
||||
private void cbCardRenderShowReminderTextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderShowReminderTextActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbCardRenderShowReminderTextActionPerformed
|
||||
|
||||
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
|
||||
|
@ -2831,6 +2904,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed
|
||||
|
||||
private void cbCardRenderHideSetSymbolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderHideSetSymbolActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbCardRenderHideSetSymbolActionPerformed
|
||||
|
||||
private void showProxySettings() {
|
||||
Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem();
|
||||
switch (proxyType) {
|
||||
|
@ -3004,6 +3081,11 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10"));
|
||||
dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en"));
|
||||
|
||||
// rendering settings
|
||||
load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true");
|
||||
load(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true");
|
||||
load(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true");
|
||||
|
||||
//add background load precedure
|
||||
prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true");
|
||||
if (prop.equals("true")) {
|
||||
|
@ -3384,6 +3466,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
private javax.swing.JCheckBox cbAllowRequestToShowHandCards;
|
||||
private javax.swing.JCheckBox cbAskMoveToGraveOrder;
|
||||
private javax.swing.JCheckBox cbAutoOrderTrigger;
|
||||
private javax.swing.JCheckBox cbCardRenderHideSetSymbol;
|
||||
private javax.swing.JCheckBox cbCardRenderImageFallback;
|
||||
private javax.swing.JCheckBox cbCardRenderShowReminderText;
|
||||
private javax.swing.JCheckBox cbCheckForNewImages;
|
||||
private javax.swing.JCheckBox cbConfirmEmptyManaPool;
|
||||
private javax.swing.JCheckBox cbDraftLogAutoSave;
|
||||
|
@ -3443,6 +3528,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
private javax.swing.JLabel jLabelOpponentsTurn;
|
||||
private javax.swing.JLabel jLabelUpkeep;
|
||||
private javax.swing.JLabel jLabelYourTurn;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel10;
|
||||
private javax.swing.JPanel jPanel11;
|
||||
private javax.swing.JPanel jPanel12;
|
||||
|
|
|
@ -159,7 +159,7 @@ public abstract class Animation {
|
|||
|
||||
public static void transformCard(final CardPanel panel, final MagePermanent parent, final boolean transformed) {
|
||||
|
||||
new Animation(1200) {
|
||||
new Animation(600) {
|
||||
private boolean state = false;
|
||||
|
||||
@Override
|
||||
|
@ -256,7 +256,7 @@ public abstract class Animation {
|
|||
public void run() {
|
||||
if (placeholder != null) {
|
||||
placeholder.setDisplayEnabled(true);
|
||||
placeholder.setImage(animationPanel);
|
||||
placeholder.transferResources(animationPanel);
|
||||
}
|
||||
animationPanel.setVisible(false);
|
||||
animationPanel.repaint();
|
||||
|
@ -303,7 +303,7 @@ public abstract class Animation {
|
|||
public void run() {
|
||||
if (placeholder != null) {
|
||||
placeholder.setDisplayEnabled(true);
|
||||
placeholder.setImage(animationPanel);
|
||||
placeholder.transferResources(animationPanel);
|
||||
}
|
||||
animationPanel.setVisible(false);
|
||||
animationPanel.repaint();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
* Attributes of a card panel outside of the CardView itself that the renderer
|
||||
* needs to know in order to render a card.
|
||||
*/
|
||||
public class CardPanelAttributes {
|
||||
public final int cardWidth;
|
||||
public final int cardHeight;
|
||||
public final boolean isSelected;
|
||||
public final boolean isChoosable;
|
||||
|
||||
public CardPanelAttributes(int cardWidth, int cardHeight, boolean isChoosable, boolean isSelected) {
|
||||
this.cardWidth = cardWidth;
|
||||
this.cardHeight = cardHeight;
|
||||
this.isChoosable = isChoosable;
|
||||
this.isSelected = isSelected;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,711 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.ImageCaches;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.components.ImagePanel;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.utils.CardUtil;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.StackAbilityView;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||
|
||||
/**
|
||||
* Class for drawing the mage card object by using a form based JComponent approach
|
||||
*
|
||||
* @author arcane, nantuko, noxx, stravant
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class CardPanelComponentImpl extends CardPanel {
|
||||
|
||||
private static final long serialVersionUID = -3272134219262184411L;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanelComponentImpl.class);
|
||||
|
||||
private static final int WIDTH_LIMIT = 90; // card width limit to create smaller counter
|
||||
|
||||
private static final float ROUNDED_CORNER_SIZE = 0.1f;
|
||||
private static final float BLACK_BORDER_SIZE = 0.03f;
|
||||
private static final int TEXT_GLOW_SIZE = 6;
|
||||
private static final float TEXT_GLOW_INTENSITY = 3f;
|
||||
|
||||
public final ScaledImagePanel imagePanel;
|
||||
public ImagePanel overlayPanel;
|
||||
|
||||
public JPanel iconPanel;
|
||||
private JButton typeButton;
|
||||
|
||||
public JPanel counterPanel;
|
||||
private JLabel loyaltyCounterLabel;
|
||||
private JLabel plusCounterLabel;
|
||||
private JLabel otherCounterLabel;
|
||||
private JLabel minusCounterLabel;
|
||||
private int loyaltyCounter;
|
||||
private int plusCounter;
|
||||
private int otherCounter;
|
||||
private int minusCounter;
|
||||
private int lastCardWidth;
|
||||
|
||||
private final GlowText titleText;
|
||||
private final GlowText ptText;
|
||||
|
||||
private boolean hasImage = false;
|
||||
|
||||
private boolean displayTitleAnyway;
|
||||
|
||||
private final static Map<Key, BufferedImage> IMAGE_CACHE;
|
||||
|
||||
class Key {
|
||||
|
||||
final int width;
|
||||
final int height;
|
||||
final int cardWidth;
|
||||
final int cardHeight;
|
||||
final int cardXOffset;
|
||||
final int cardYOffset;
|
||||
final boolean hasImage;
|
||||
final boolean isSelected;
|
||||
final boolean isChoosable;
|
||||
final boolean isPlayable;
|
||||
final boolean canAttack;
|
||||
|
||||
public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.cardWidth = cardWidth;
|
||||
this.cardHeight = cardHeight;
|
||||
this.cardXOffset = cardXOffset;
|
||||
this.cardYOffset = cardYOffset;
|
||||
this.hasImage = hasImage;
|
||||
this.isSelected = isSelected;
|
||||
this.isChoosable = isChoosable;
|
||||
this.isPlayable = isPlayable;
|
||||
this.canAttack = canAttack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 19 * hash + this.width;
|
||||
hash = 19 * hash + this.height;
|
||||
hash = 19 * hash + this.cardWidth;
|
||||
hash = 19 * hash + this.cardHeight;
|
||||
hash = 19 * hash + this.cardXOffset;
|
||||
hash = 19 * hash + this.cardYOffset;
|
||||
hash = 19 * hash + (this.hasImage ? 1 : 0);
|
||||
hash = 19 * hash + (this.isSelected ? 1 : 0);
|
||||
hash = 19 * hash + (this.isChoosable ? 1 : 0);
|
||||
hash = 19 * hash + (this.isPlayable ? 1 : 0);
|
||||
hash = 19 * hash + (this.canAttack ? 1 : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Key other = (Key) obj;
|
||||
if (this.width != other.width) {
|
||||
return false;
|
||||
}
|
||||
if (this.height != other.height) {
|
||||
return false;
|
||||
}
|
||||
if (this.cardWidth != other.cardWidth) {
|
||||
return false;
|
||||
}
|
||||
if (this.cardHeight != other.cardHeight) {
|
||||
return false;
|
||||
}
|
||||
if (this.cardXOffset != other.cardXOffset) {
|
||||
return false;
|
||||
}
|
||||
if (this.cardYOffset != other.cardYOffset) {
|
||||
return false;
|
||||
}
|
||||
if (this.hasImage != other.hasImage) {
|
||||
return false;
|
||||
}
|
||||
if (this.isSelected != other.isSelected) {
|
||||
return false;
|
||||
}
|
||||
if (this.isChoosable != other.isChoosable) {
|
||||
return false;
|
||||
}
|
||||
if (this.isPlayable != other.isPlayable) {
|
||||
return false;
|
||||
}
|
||||
if (this.canAttack != other.canAttack) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function<Key, BufferedImage>() {
|
||||
@Override
|
||||
public BufferedImage apply(Key key) {
|
||||
return createImage(key);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public CardPanelComponentImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||
// Call to super
|
||||
super(newGameCard, gameId, loadImage, callback, foil, dimension);
|
||||
|
||||
// Counter panel
|
||||
if (!newGameCard.isAbility()) {
|
||||
// panel to show counters on the card
|
||||
counterPanel = new JPanel();
|
||||
counterPanel.setLayout(null);
|
||||
counterPanel.setOpaque(false);
|
||||
add(counterPanel);
|
||||
|
||||
plusCounterLabel = new JLabel("");
|
||||
plusCounterLabel.setToolTipText("+1/+1");
|
||||
counterPanel.add(plusCounterLabel);
|
||||
|
||||
minusCounterLabel = new JLabel("");
|
||||
minusCounterLabel.setToolTipText("-1/-1");
|
||||
counterPanel.add(minusCounterLabel);
|
||||
|
||||
loyaltyCounterLabel = new JLabel("");
|
||||
loyaltyCounterLabel.setToolTipText("loyalty");
|
||||
counterPanel.add(loyaltyCounterLabel);
|
||||
|
||||
otherCounterLabel = new JLabel("");
|
||||
counterPanel.add(otherCounterLabel);
|
||||
|
||||
counterPanel.setVisible(false);
|
||||
}
|
||||
|
||||
// Ability icon
|
||||
if (newGameCard.isAbility()) {
|
||||
if (AbilityType.TRIGGERED.equals(newGameCard.getAbilityType())) {
|
||||
setTypeIcon(ImageManagerImpl.getInstance().getTriggeredAbilityImage(), "Triggered Ability");
|
||||
} else if (AbilityType.ACTIVATED.equals(newGameCard.getAbilityType())) {
|
||||
setTypeIcon(ImageManagerImpl.getInstance().getActivatedAbilityImage(), "Activated Ability");
|
||||
}
|
||||
}
|
||||
|
||||
// Token icon
|
||||
if (this.gameCard.isToken()) {
|
||||
setTypeIcon(ImageManagerImpl.getInstance().getTokenIconImage(), "Token Permanent");
|
||||
}
|
||||
|
||||
displayTitleAnyway = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_CARD_NAMES, "true").equals("true");
|
||||
|
||||
// Title Text
|
||||
titleText = new GlowText();
|
||||
setText(gameCard);
|
||||
// int fontSize = (int) cardHeight / 11;
|
||||
// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
titleText.setForeground(Color.white);
|
||||
titleText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
|
||||
titleText.setWrap(true);
|
||||
add(titleText);
|
||||
|
||||
// PT Text
|
||||
ptText = new GlowText();
|
||||
if (CardUtil.isCreature(gameCard)) {
|
||||
ptText.setText(gameCard.getPower() + "/" + gameCard.getToughness());
|
||||
} else if (CardUtil.isPlaneswalker(gameCard)) {
|
||||
ptText.setText(gameCard.getLoyalty());
|
||||
}
|
||||
// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
ptText.setForeground(Color.white);
|
||||
ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
|
||||
add(ptText);
|
||||
|
||||
// Sickness overlay
|
||||
BufferedImage sickness = ImageManagerImpl.getInstance().getSicknessImage();
|
||||
overlayPanel = new ImagePanel(sickness, ImagePanel.SCALED);
|
||||
overlayPanel.setOpaque(false);
|
||||
add(overlayPanel);
|
||||
|
||||
// Imagel panel
|
||||
imagePanel = new ScaledImagePanel();
|
||||
imagePanel.setBorder(BorderFactory.createLineBorder(Color.white));
|
||||
add(imagePanel);
|
||||
|
||||
// Do we need to load?
|
||||
if (loadImage) {
|
||||
initialDraw();
|
||||
} else {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
private void setTypeIcon(BufferedImage bufferedImage, String toolTipText) {
|
||||
iconPanel = new JPanel();
|
||||
iconPanel.setLayout(null);
|
||||
iconPanel.setOpaque(false);
|
||||
add(iconPanel);
|
||||
|
||||
typeButton = new JButton("");
|
||||
typeButton.setLocation(2, 2);
|
||||
typeButton.setSize(25, 25);
|
||||
|
||||
iconPanel.setVisible(true);
|
||||
typeButton.setIcon(new ImageIcon(bufferedImage));
|
||||
if (toolTipText != null) {
|
||||
typeButton.setToolTipText(toolTipText);
|
||||
}
|
||||
iconPanel.add(typeButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
super.cleanUp();
|
||||
this.counterPanel = null;
|
||||
}
|
||||
|
||||
private void setText(CardView card) {
|
||||
titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName());
|
||||
}
|
||||
|
||||
private void setImage(BufferedImage srcImage) {
|
||||
synchronized (imagePanel) {
|
||||
if (srcImage != null) {
|
||||
imagePanel.setImage(srcImage);
|
||||
} else {
|
||||
imagePanel.clearImage();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
doLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferResources(final CardPanel panelAbstract) {
|
||||
if (panelAbstract instanceof CardPanelComponentImpl) {
|
||||
CardPanelComponentImpl panel = (CardPanelComponentImpl)panelAbstract;
|
||||
synchronized (panel.imagePanel) {
|
||||
if (panel.imagePanel.hasImage()) {
|
||||
setImage(panel.imagePanel.getSrcImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean isSelected) {
|
||||
super.setSelected(isSelected);
|
||||
if (isSelected) {
|
||||
this.titleText.setGlowColor(Color.green);
|
||||
} else {
|
||||
this.titleText.setGlowColor(Color.black);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintCard(Graphics2D g2d) {
|
||||
float alpha = getAlpha();
|
||||
if (alpha != 1.0f) {
|
||||
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha);
|
||||
g2d.setComposite(composite);
|
||||
}
|
||||
|
||||
g2d.drawImage(
|
||||
IMAGE_CACHE.get(
|
||||
new Key(getWidth(), getHeight(), getCardWidth(), getCardHeight(), getCardXOffset(), getCardYOffset(),
|
||||
hasImage, isSelected(), isChoosable(), gameCard.isPlayable(), gameCard.isCanAttack())),
|
||||
0, 0, null);
|
||||
g2d.dispose();
|
||||
}
|
||||
|
||||
private static BufferedImage createImage(Key key) {
|
||||
int cardWidth = key.cardWidth;
|
||||
int cardHeight = key.cardHeight;
|
||||
int cardXOffset = key.cardXOffset;
|
||||
int cardYOffset = key.cardYOffset;
|
||||
|
||||
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(key.width, key.height);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
if (!key.hasImage) {
|
||||
g2d.setColor(new Color(30, 200, 200, 120));
|
||||
} else {
|
||||
g2d.setColor(new Color(0, 0, 0, 255));
|
||||
}
|
||||
|
||||
int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
|
||||
if (key.isSelected) {
|
||||
g2d.setColor(Color.green);
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
} else if (key.isChoosable) {
|
||||
g2d.setColor(new Color(250, 250, 0, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
} else if (key.isPlayable) {
|
||||
g2d.setColor(new Color(153, 102, 204, 200));
|
||||
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
if (key.canAttack) {
|
||||
g2d.setColor(new Color(0, 0, 255, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
//TODO:uncomment
|
||||
/*
|
||||
if (gameCard.isAttacking()) {
|
||||
g2d.setColor(new Color(200,10,10,200));
|
||||
g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize);
|
||||
}*/
|
||||
g2d.dispose();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren(Graphics g) {
|
||||
super.paintChildren(g);
|
||||
|
||||
if (getShowCastingCost() && !isAnimationPanel() && getCardWidth() < 200 && getCardWidth() > 60) {
|
||||
String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
|
||||
int width = getWidth(manaCost);
|
||||
if (hasImage) {
|
||||
ManaSymbols.draw(g, manaCost, getCardXOffset() + getCardWidth() - width - 5, getCardYOffset() + 5, getSymbolWidth());
|
||||
} else {
|
||||
ManaSymbols.draw(g, manaCost, getCardXOffset() + 8, getCardHeight() - 9, getSymbolWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getWidth(String manaCost) {
|
||||
int width = 0;
|
||||
manaCost = manaCost.replace("\\", "");
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
tok.nextToken();
|
||||
width += getSymbolWidth();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLayout() {
|
||||
super.doLayout();
|
||||
|
||||
int cardWidth = getCardWidth();
|
||||
int cardHeight = getCardHeight();
|
||||
int cardXOffset = getCardXOffset();
|
||||
int cardYOffset = getCardYOffset();
|
||||
int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE);
|
||||
imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
|
||||
if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) {
|
||||
overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
} else {
|
||||
overlayPanel.setVisible(false);
|
||||
}
|
||||
|
||||
if (iconPanel != null) {
|
||||
iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
}
|
||||
if (counterPanel != null) {
|
||||
counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
int size = cardWidth > WIDTH_LIMIT ? 40 : 20;
|
||||
|
||||
minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2);
|
||||
minusCounterLabel.setSize(size, size);
|
||||
|
||||
plusCounterLabel.setLocation(5, counterPanel.getHeight() - size * 2);
|
||||
plusCounterLabel.setSize(size, size);
|
||||
|
||||
loyaltyCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size);
|
||||
loyaltyCounterLabel.setSize(size, size);
|
||||
|
||||
otherCounterLabel.setLocation(5, counterPanel.getHeight() - size);
|
||||
otherCounterLabel.setSize(size, size);
|
||||
|
||||
}
|
||||
int fontHeight = Math.round(cardHeight * (27f / 680));
|
||||
boolean showText = (!isAnimationPanel() && fontHeight < 12);
|
||||
titleText.setVisible(showText);
|
||||
ptText.setVisible(showText);
|
||||
|
||||
if (showText) {
|
||||
int fontSize = (int) cardHeight / 11;
|
||||
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
|
||||
int titleX = Math.round(cardWidth * (20f / 480));
|
||||
int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset();
|
||||
titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY);
|
||||
|
||||
ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
Dimension ptSize = ptText.getPreferredSize();
|
||||
ptText.setSize(ptSize.width, ptSize.height);
|
||||
int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2;
|
||||
int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height;
|
||||
|
||||
int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f);
|
||||
|
||||
ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return gameCard.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCardBounds(int x, int y, int cardWidth, int cardHeight) {
|
||||
// Call to super
|
||||
super.setCardBounds(x, y, cardWidth, cardHeight);
|
||||
|
||||
// Update image
|
||||
if (imagePanel != null && imagePanel.getSrcImage() != null) {
|
||||
updateArtImage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
super.setAlpha(alpha);
|
||||
|
||||
// Update components
|
||||
if (alpha == 0) {
|
||||
this.ptText.setVisible(false);
|
||||
this.titleText.setVisible(false);
|
||||
} else if (alpha == 1.0f) {
|
||||
this.ptText.setVisible(true);
|
||||
this.titleText.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Image updating code
|
||||
private int updateArtImageStamp;
|
||||
|
||||
@Override
|
||||
public void updateArtImage() {
|
||||
tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
|
||||
flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0;
|
||||
|
||||
//final CardView gameCard = this.gameCard;
|
||||
final int stamp = ++updateArtImageStamp;
|
||||
|
||||
Util.threadPool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final BufferedImage srcImage;
|
||||
if (gameCard.isFaceDown()) {
|
||||
srcImage = getFaceDownImage();
|
||||
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(gameCard);
|
||||
}
|
||||
UI.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (stamp == updateArtImageStamp) {
|
||||
hasImage = srcImage != null;
|
||||
setText(gameCard);
|
||||
setImage(srcImage);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} catch (Error err) {
|
||||
err.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BufferedImage getFaceDownImage() {
|
||||
if (isPermanent()) {
|
||||
if (((PermanentView) gameCard).isMorphed()) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.getManifestImage();
|
||||
}
|
||||
} else if (this.gameCard instanceof StackAbilityView) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCardTitle() {
|
||||
displayTitleAnyway = true;
|
||||
setText(gameCard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(CardView card) {
|
||||
// Super
|
||||
super.update(card);
|
||||
|
||||
// Update card text
|
||||
if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) {
|
||||
ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")");
|
||||
} else if (CardUtil.isCreature(card)) {
|
||||
ptText.setText(card.getPower() + "/" + card.getToughness());
|
||||
} else if (CardUtil.isPlaneswalker(card)) {
|
||||
ptText.setText(card.getLoyalty());
|
||||
} else {
|
||||
ptText.setText("");
|
||||
}
|
||||
setText(card);
|
||||
|
||||
// Summoning Sickness overlay
|
||||
if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) {
|
||||
overlayPanel.setVisible(true);
|
||||
} else {
|
||||
overlayPanel.setVisible(false);
|
||||
}
|
||||
|
||||
// Update counters panel
|
||||
if (counterPanel != null) {
|
||||
updateCounters(card);
|
||||
}
|
||||
|
||||
// Finally, queue a repaint
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void updateCounters(CardView card) {
|
||||
if (card.getCounters() != null && !card.getCounters().isEmpty()) {
|
||||
String name = "";
|
||||
if (lastCardWidth != getCardWidth()) {
|
||||
lastCardWidth = getCardWidth();
|
||||
plusCounter = 0;
|
||||
minusCounter = 0;
|
||||
otherCounter = 0;
|
||||
loyaltyCounter = 0;
|
||||
}
|
||||
plusCounterLabel.setVisible(false);
|
||||
minusCounterLabel.setVisible(false);
|
||||
loyaltyCounterLabel.setVisible(false);
|
||||
otherCounterLabel.setVisible(false);
|
||||
for (CounterView counterView : card.getCounters()) {
|
||||
if (counterView.getCount() == 0) {
|
||||
continue;
|
||||
}
|
||||
switch (counterView.getName()) {
|
||||
case "+1/+1":
|
||||
if (counterView.getCount() != plusCounter) {
|
||||
plusCounter = counterView.getCount();
|
||||
plusCounterLabel.setIcon(getCounterImageWithAmount(plusCounter, ImageManagerImpl.getInstance().getCounterImageGreen(), getCardWidth()));
|
||||
}
|
||||
plusCounterLabel.setVisible(true);
|
||||
break;
|
||||
case "-1/-1":
|
||||
if (counterView.getCount() != minusCounter) {
|
||||
minusCounter = counterView.getCount();
|
||||
minusCounterLabel.setIcon(getCounterImageWithAmount(minusCounter, ImageManagerImpl.getInstance().getCounterImageRed(), getCardWidth()));
|
||||
}
|
||||
minusCounterLabel.setVisible(true);
|
||||
break;
|
||||
case "loyalty":
|
||||
if (counterView.getCount() != loyaltyCounter) {
|
||||
loyaltyCounter = counterView.getCount();
|
||||
loyaltyCounterLabel.setIcon(getCounterImageWithAmount(loyaltyCounter, ImageManagerImpl.getInstance().getCounterImageViolet(), getCardWidth()));
|
||||
}
|
||||
loyaltyCounterLabel.setVisible(true);
|
||||
break;
|
||||
default:
|
||||
if (name.isEmpty()) { // only first other counter is shown
|
||||
name = counterView.getName();
|
||||
otherCounter = counterView.getCount();
|
||||
otherCounterLabel.setToolTipText(name);
|
||||
otherCounterLabel.setIcon(getCounterImageWithAmount(otherCounter, ImageManagerImpl.getInstance().getCounterImageGrey(), getCardWidth()));
|
||||
otherCounterLabel.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
counterPanel.setVisible(true);
|
||||
} else {
|
||||
plusCounterLabel.setVisible(false);
|
||||
minusCounterLabel.setVisible(false);
|
||||
loyaltyCounterLabel.setVisible(false);
|
||||
otherCounterLabel.setVisible(false);
|
||||
counterPanel.setVisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static ImageIcon getCounterImageWithAmount(int amount, BufferedImage image, int cardWidth) {
|
||||
int factor = cardWidth > WIDTH_LIMIT ? 2 : 1;
|
||||
int xOffset = amount > 9 ? 2 : 5;
|
||||
int fontSize = factor == 1 ? amount < 10 ? 12 : amount < 100 ? 10 : amount < 1000 ? 7 : 6
|
||||
: amount < 10 ? 19 : amount < 100 ? 15 : amount < 1000 ? 12 : amount < 10000 ? 9 : 8;
|
||||
BufferedImage newImage;
|
||||
if (cardWidth > WIDTH_LIMIT) {
|
||||
newImage = ImageManagerImpl.deepCopy(image);
|
||||
} else {
|
||||
newImage = ImageHelper.getResizedImage(image, 20, 20);
|
||||
}
|
||||
Graphics graphics = newImage.getGraphics();
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.setFont(new Font("Arial Black", amount > 100 ? Font.PLAIN : Font.BOLD, fontSize));
|
||||
graphics.drawString(Integer.toString(amount), xOffset * factor, 11 * factor);
|
||||
return new ImageIcon(newImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage() {
|
||||
if (this.hasImage) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
return getFaceDownImage();
|
||||
} else {
|
||||
return ImageCache.getImageOriginal(gameCard);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.constants.CardType;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.StackAbilityView;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
|
||||
public class CardPanelRenderImpl extends CardPanel {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanelRenderImpl.class);
|
||||
|
||||
private static boolean cardViewEquals(CardView a, CardView b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (a.getClass() != b.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getName().equals(b.getName())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getPower().equals(b.getPower())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getToughness().equals(b.getToughness())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getLoyalty().equals(b.getLoyalty())) {
|
||||
return false;
|
||||
}
|
||||
if (0 != a.getColor().compareTo(b.getColor())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getCardTypes().equals(b.getCardTypes())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getSubTypes().equals(b.getSubTypes())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getSuperTypes().equals(b.getSuperTypes())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getManaCost().equals(b.getManaCost())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getRules().equals(b.getRules())) {
|
||||
return false;
|
||||
}
|
||||
if (!a.getExpansionSetCode().equals(b.getExpansionSetCode())) {
|
||||
return false;
|
||||
}
|
||||
if (a.getCounters() == null) {
|
||||
if (b.getCounters() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!a.getCounters().equals(b.getCounters())) {
|
||||
return false;
|
||||
}
|
||||
if (a.isFaceDown() != b.isFaceDown()) {
|
||||
return false;
|
||||
}
|
||||
if ((a instanceof PermanentView)) {
|
||||
PermanentView aa = (PermanentView) a;
|
||||
PermanentView bb = (PermanentView) b;
|
||||
if (aa.hasSummoningSickness() != bb.hasSummoningSickness()) {
|
||||
// Note: b must be a permanentview too as we aleady checked that classes
|
||||
// are the same for a and b
|
||||
return false;
|
||||
}
|
||||
if (aa.getDamage() != bb.getDamage()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class ImageKey {
|
||||
|
||||
final BufferedImage artImage;
|
||||
final int width;
|
||||
final int height;
|
||||
final boolean isChoosable;
|
||||
final boolean isSelected;
|
||||
final CardView view;
|
||||
final int hashCode;
|
||||
|
||||
public ImageKey(CardView view, BufferedImage artImage, int width, int height, boolean isChoosable, boolean isSelected) {
|
||||
this.view = view;
|
||||
this.artImage = artImage;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.isChoosable = isChoosable;
|
||||
this.isSelected = isSelected;
|
||||
this.hashCode = hashCodeImpl();
|
||||
}
|
||||
|
||||
private int hashCodeImpl() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append((char) (artImage != null ? 1 : 0));
|
||||
sb.append((char) width);
|
||||
sb.append((char) height);
|
||||
sb.append((char) (isSelected ? 1 : 0));
|
||||
sb.append((char) (isChoosable ? 1 : 0));
|
||||
sb.append((char) (this.view.isPlayable() ? 1 : 0));
|
||||
sb.append((char) (this.view.isCanAttack() ? 1 : 0));
|
||||
sb.append((char) (this.view.isFaceDown() ? 1 : 0));
|
||||
if (this.view instanceof PermanentView) {
|
||||
sb.append((char) (((PermanentView) this.view).hasSummoningSickness() ? 1 : 0));
|
||||
sb.append((char) (((PermanentView) this.view).getDamage()));
|
||||
}
|
||||
sb.append(this.view.getName());
|
||||
sb.append(this.view.getPower());
|
||||
sb.append(this.view.getToughness());
|
||||
sb.append(this.view.getLoyalty());
|
||||
sb.append(this.view.getColor().toString());
|
||||
sb.append(this.view.getExpansionSetCode());
|
||||
for (CardType type : this.view.getCardTypes()) {
|
||||
sb.append((char) type.ordinal());
|
||||
}
|
||||
for (String s : this.view.getSuperTypes()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s : this.view.getSubTypes()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s : this.view.getManaCost()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s : this.view.getRules()) {
|
||||
sb.append(s);
|
||||
}
|
||||
if (this.view.getCounters() != null) {
|
||||
for (CounterView v : this.view.getCounters()) {
|
||||
sb.append(v.getName()).append(v.getCount());
|
||||
}
|
||||
}
|
||||
return sb.toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// Initial checks
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (object == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(object instanceof ImageKey)) {
|
||||
return false;
|
||||
}
|
||||
final ImageKey other = (ImageKey) object;
|
||||
|
||||
// Compare
|
||||
if ((artImage != null) != (other.artImage != null)) {
|
||||
return false;
|
||||
}
|
||||
if (width != other.width) {
|
||||
return false;
|
||||
}
|
||||
if (height != other.height) {
|
||||
return false;
|
||||
}
|
||||
if (isChoosable != other.isChoosable) {
|
||||
return false;
|
||||
}
|
||||
if (isSelected != other.isSelected) {
|
||||
return false;
|
||||
}
|
||||
return cardViewEquals(view, other.view);
|
||||
}
|
||||
}
|
||||
|
||||
// Map of generated images
|
||||
private final static Map<ImageKey, BufferedImage> IMAGE_CACHE = new MapMaker().softValues().makeMap();
|
||||
|
||||
// The art image for the card, loaded in from the disk
|
||||
private BufferedImage artImage;
|
||||
|
||||
// The rendered card image, with or without the art image loaded yet
|
||||
// = null while invalid
|
||||
private BufferedImage cardImage;
|
||||
private CardRenderer cardRenderer;
|
||||
|
||||
public CardPanelRenderImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||
// Call to super
|
||||
super(newGameCard, gameId, loadImage, callback, foil, dimension);
|
||||
|
||||
// Renderer
|
||||
cardRenderer = new ModernCardRenderer(gameCard, isTransformed());
|
||||
|
||||
// Draw the parts
|
||||
initialDraw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferResources(CardPanel panel) {
|
||||
if (panel instanceof CardPanelRenderImpl) {
|
||||
CardPanelRenderImpl impl = (CardPanelRenderImpl) panel;
|
||||
|
||||
// Use the art image and current rendered image from the card
|
||||
artImage = impl.artImage;
|
||||
cardRenderer.setArtImage(artImage);
|
||||
cardImage = impl.cardImage;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintCard(Graphics2D g) {
|
||||
// Render the card if we don't have an image ready to use
|
||||
if (cardImage == null) {
|
||||
// Try to get card image from cache based on our card characteristics
|
||||
ImageKey key
|
||||
= new ImageKey(gameCard, artImage,
|
||||
getCardWidth(), getCardHeight(),
|
||||
isChoosable(), isSelected());
|
||||
cardImage = IMAGE_CACHE.get(key);
|
||||
|
||||
// No cached copy exists? Render one and cache it
|
||||
if (cardImage == null) {
|
||||
cardImage = renderCard();
|
||||
IMAGE_CACHE.put(key, cardImage);
|
||||
}
|
||||
}
|
||||
|
||||
// And draw the image we now have
|
||||
g.drawImage(cardImage, getCardXOffset(), getCardYOffset(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the card to a new BufferedImage at it's current dimensions
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private BufferedImage renderCard() {
|
||||
int cardWidth = getCardWidth();
|
||||
int cardHeight = getCardHeight();
|
||||
|
||||
// Create image to render to
|
||||
BufferedImage image
|
||||
= GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
|
||||
// Render with Antialialsing
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
// Attributes
|
||||
CardPanelAttributes attribs
|
||||
= new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected());
|
||||
|
||||
// Draw card itself
|
||||
cardRenderer.draw(g2d, attribs);
|
||||
|
||||
// Done
|
||||
g2d.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
private int updateArtImageStamp;
|
||||
|
||||
@Override
|
||||
public void updateArtImage() {
|
||||
// Invalidate
|
||||
artImage = null;
|
||||
cardImage = null;
|
||||
cardRenderer.setArtImage(null);
|
||||
|
||||
// Stop animation
|
||||
tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
|
||||
flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0;
|
||||
|
||||
// Schedule a repaint
|
||||
repaint();
|
||||
|
||||
// See if the image is already loaded
|
||||
//artImage = ImageCache.tryGetImage(gameCard, getCardWidth(), getCardHeight());
|
||||
//this.cardRenderer.setArtImage(artImage);
|
||||
// Submit a task to draw with the card art when it arrives
|
||||
if (artImage == null) {
|
||||
final int stamp = ++updateArtImageStamp;
|
||||
Util.threadPool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final BufferedImage srcImage;
|
||||
if (gameCard.isFaceDown()) {
|
||||
// Nothing to do
|
||||
srcImage = null;
|
||||
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(gameCard);
|
||||
}
|
||||
UI.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (stamp == updateArtImageStamp) {
|
||||
artImage = srcImage;
|
||||
cardRenderer.setArtImage(srcImage);
|
||||
if (srcImage != null) {
|
||||
// Invalidate and repaint
|
||||
cardImage = null;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} catch (Error err) {
|
||||
err.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(CardView card) {
|
||||
// Update super
|
||||
super.update(card);
|
||||
|
||||
// Update renderer
|
||||
cardImage = null;
|
||||
cardRenderer = new ModernCardRenderer(gameCard, isTransformed());
|
||||
cardRenderer.setArtImage(artImage);
|
||||
|
||||
// Repaint
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCardBounds(int x, int y, int cardWidth, int cardHeight) {
|
||||
int oldCardWidth = getCardWidth();
|
||||
int oldCardHeight = getCardHeight();
|
||||
|
||||
super.setCardBounds(x, y, cardWidth, cardHeight);
|
||||
|
||||
// Rerender if card size changed
|
||||
if (getCardWidth() != oldCardWidth || getCardHeight() != oldCardHeight) {
|
||||
cardImage = null;
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage getFaceDownImage() {
|
||||
if (isPermanent()) {
|
||||
if (((PermanentView) gameCard).isMorphed()) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.getManifestImage();
|
||||
}
|
||||
} else if (this.gameCard instanceof StackAbilityView) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage() {
|
||||
if (artImage != null) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
return getFaceDownImage();
|
||||
} else {
|
||||
return ImageCache.getImageOriginal(gameCard);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCardTitle() {
|
||||
// Nothing to do, rendered cards always have a title
|
||||
}
|
||||
}
|
374
Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
Normal file
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.CardType;
|
||||
import mage.utils.CardUtil;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Common base class for card renderers for each card frame / card type.
|
||||
*
|
||||
* Follows the template method pattern to implement a new renderer, implement
|
||||
* the following methods (they are called in the following order):
|
||||
*
|
||||
* * drawBorder() Draws the outermost border of the card, white border or black
|
||||
* border
|
||||
*
|
||||
* * drawBackground() Draws the background texture / color of the card
|
||||
*
|
||||
* * drawArt() Draws the card's art
|
||||
*
|
||||
* * drawFrame() Draws the card frame (over the art and background)
|
||||
*
|
||||
* * drawOverlays() Draws summoning sickness and possible other overlays
|
||||
*
|
||||
* * drawCounters() Draws counters on the card, such as +1/+1 and -1/-1
|
||||
* counters
|
||||
*
|
||||
* Predefined methods that the implementations can use:
|
||||
*
|
||||
* * drawRules(font, bounding box)
|
||||
*
|
||||
* * drawNameLine(font, bounding box)
|
||||
*
|
||||
* * drawTypeLine(font, bounding box)
|
||||
*
|
||||
*/
|
||||
public abstract class CardRenderer {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Common layout metrics between all cards
|
||||
// The card to be rendered
|
||||
protected final CardView cardView;
|
||||
|
||||
// Is the card transformed?
|
||||
protected final boolean isTransformed;
|
||||
|
||||
// The card image
|
||||
protected BufferedImage artImage;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Common layout metrics between all cards
|
||||
// Polygons for counters
|
||||
private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{
|
||||
0, 5, 10, 10, 5, 0
|
||||
}, new int[]{
|
||||
3, 0, 3, 10, 9, 10
|
||||
}, 6);
|
||||
private static final Polygon MINUS_COUNTER_POLY = new Polygon(new int[]{
|
||||
0, 5, 10, 10, 5, 0
|
||||
}, new int[]{
|
||||
0, 1, 0, 7, 10, 7
|
||||
}, 6);
|
||||
private static final Polygon TIME_COUNTER_POLY = new Polygon(new int[]{
|
||||
0, 10, 8, 10, 0, 2
|
||||
}, new int[]{
|
||||
0, 0, 5, 10, 10, 5
|
||||
}, 6);
|
||||
private static final Polygon OTHER_COUNTER_POLY = new Polygon(new int[]{
|
||||
1, 9, 9, 1
|
||||
}, new int[]{
|
||||
1, 1, 9, 9
|
||||
}, 4);
|
||||
|
||||
// Paint for a card back
|
||||
public static Paint BG_TEXTURE_CARDBACK = new Color(153, 102, 51);
|
||||
|
||||
// The size of the card
|
||||
protected int cardWidth;
|
||||
protected int cardHeight;
|
||||
|
||||
// Is it selectable / selected
|
||||
protected boolean isChoosable;
|
||||
protected boolean isSelected;
|
||||
|
||||
// Radius of the corners of the cards
|
||||
protected static float CORNER_RADIUS_FRAC = 0.1f; //x cardWidth
|
||||
protected static int CORNER_RADIUS_MIN = 3;
|
||||
protected int cornerRadius;
|
||||
|
||||
// The inset of the actual card from the black / white border around it
|
||||
protected static float BORDER_WIDTH_FRAC = 0.03f; //x cardWidth
|
||||
protected static float BORDER_WIDTH_MIN = 2;
|
||||
protected int borderWidth;
|
||||
|
||||
// The parsed text of the card
|
||||
protected ArrayList<TextboxRule> textboxRules = new ArrayList<>();
|
||||
protected ArrayList<TextboxRule> textboxKeywords = new ArrayList<>();
|
||||
|
||||
// The Construtor
|
||||
// The constructor should prepare all of the things that it can
|
||||
// without knowing the dimensions that the card will be rendered at.
|
||||
// Then, the CardRenderer can be called on multiple times to render the
|
||||
// card at various sizes (for instance, during animation)
|
||||
public CardRenderer(CardView card, boolean isTransformed) {
|
||||
// Set base parameters
|
||||
this.cardView = card;
|
||||
this.isTransformed = isTransformed;
|
||||
|
||||
// Translate the textbox text
|
||||
for (String rule : card.getRules()) {
|
||||
// Kill reminder text
|
||||
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_REMINDER_TEXT, "false").equals("false")) {
|
||||
rule = CardRendererUtils.killReminderText(rule).trim();
|
||||
}
|
||||
if (!rule.isEmpty()) {
|
||||
TextboxRule tbRule = TextboxRuleParser.parse(card, rule);
|
||||
if (tbRule.type == TextboxRuleType.SIMPLE_KEYWORD) {
|
||||
textboxKeywords.add(tbRule);
|
||||
} else if (tbRule.text.isEmpty()) {
|
||||
// Nothing to do, rule is empty
|
||||
} else {
|
||||
textboxRules.add(tbRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layout operation
|
||||
// Calculate common layout metrics that will be used by several
|
||||
// of the operations in the template method.
|
||||
protected void layout(int cardWidth, int cardHeight) {
|
||||
// Store the dimensions for the template methods to use
|
||||
this.cardWidth = cardWidth;
|
||||
this.cardHeight = cardHeight;
|
||||
|
||||
// Corner radius and border width
|
||||
cornerRadius = (int) Math.max(
|
||||
CORNER_RADIUS_MIN,
|
||||
CORNER_RADIUS_FRAC * cardWidth);
|
||||
|
||||
borderWidth = (int) Math.max(
|
||||
BORDER_WIDTH_MIN,
|
||||
BORDER_WIDTH_FRAC * cardWidth);
|
||||
}
|
||||
|
||||
// The Draw Method
|
||||
// The draw method takes the information caculated by the constructor
|
||||
// and uses it to draw to a concrete size of card and graphics.
|
||||
public void draw(Graphics2D g, CardPanelAttributes attribs) {
|
||||
// Pre template method layout, to calculate shared layout info
|
||||
layout(attribs.cardWidth, attribs.cardHeight);
|
||||
isSelected = attribs.isSelected;
|
||||
isChoosable = attribs.isChoosable;
|
||||
|
||||
// Call the template methods
|
||||
drawBorder(g);
|
||||
drawBackground(g);
|
||||
drawArt(g);
|
||||
drawFrame(g);
|
||||
if (!cardView.isAbility()) {
|
||||
drawOverlays(g);
|
||||
drawCounters(g);
|
||||
}
|
||||
}
|
||||
|
||||
// Template methods to be implemented by sub classes
|
||||
// For instance, for the Modern vs Old border card frames
|
||||
protected abstract void drawBorder(Graphics2D g);
|
||||
|
||||
protected abstract void drawBackground(Graphics2D g);
|
||||
|
||||
protected abstract void drawArt(Graphics2D g);
|
||||
|
||||
protected abstract void drawFrame(Graphics2D g);
|
||||
|
||||
// Template methods that are possible to override, but unlikely to be
|
||||
// overridden.
|
||||
// Draw the card back
|
||||
protected void drawCardBack(Graphics2D g) {
|
||||
g.setPaint(BG_TEXTURE_CARDBACK);
|
||||
g.fillRect(borderWidth, borderWidth,
|
||||
cardWidth - 2 * borderWidth, cardHeight - 2 * borderWidth);
|
||||
}
|
||||
|
||||
// Draw summoning sickness overlay, and possibly other overlays
|
||||
protected void drawOverlays(Graphics2D g) {
|
||||
if (CardUtil.isCreature(cardView) && cardView instanceof PermanentView) {
|
||||
if (((PermanentView) cardView).hasSummoningSickness()) {
|
||||
int x1 = (int) (0.2 * cardWidth);
|
||||
int x2 = (int) (0.8 * cardWidth);
|
||||
int y1 = (int) (0.2 * cardHeight);
|
||||
int y2 = (int) (0.8 * cardHeight);
|
||||
int xPoints[] = {
|
||||
x1, x2, x1, x2
|
||||
};
|
||||
int yPoints[] = {
|
||||
y1, y1, y2, y2
|
||||
};
|
||||
g.setColor(new Color(255, 255, 255, 200));
|
||||
g.setStroke(new BasicStroke(7));
|
||||
g.drawPolygon(xPoints, yPoints, 4);
|
||||
g.setColor(new Color(0, 0, 0, 200));
|
||||
g.setStroke(new BasicStroke(5));
|
||||
g.drawPolygon(xPoints, yPoints, 4);
|
||||
g.setStroke(new BasicStroke(1));
|
||||
int[] xPoints2 = {
|
||||
x1, x2, cardWidth / 2
|
||||
};
|
||||
int[] yPoints2 = {
|
||||
y1, y1, cardHeight / 2
|
||||
};
|
||||
g.setColor(new Color(0, 0, 0, 100));
|
||||
g.fillPolygon(xPoints2, yPoints2, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw +1/+1 and other counters
|
||||
protected void drawCounters(Graphics2D g) {
|
||||
int xPos = (int) (0.65 * cardWidth);
|
||||
int yPos = (int) (0.15 * cardHeight);
|
||||
if (cardView.getCounters() != null) {
|
||||
for (CounterView v : cardView.getCounters()) {
|
||||
// Don't render loyalty, we do that in the bottom corner
|
||||
if (!v.getName().equals("loyalty")) {
|
||||
Polygon p;
|
||||
if (v.getName().equals("+1/+1")) {
|
||||
p = PLUS_COUNTER_POLY;
|
||||
} else if (v.getName().equals("-1/-1")) {
|
||||
p = MINUS_COUNTER_POLY;
|
||||
} else if (v.getName().equals("time")) {
|
||||
p = TIME_COUNTER_POLY;
|
||||
} else {
|
||||
p = OTHER_COUNTER_POLY;
|
||||
}
|
||||
double scale = (0.1 * 0.25 * cardWidth);
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.translate(xPos, yPos);
|
||||
g2.scale(scale, scale);
|
||||
g2.setColor(Color.white);
|
||||
g2.fillPolygon(p);
|
||||
g2.setColor(Color.black);
|
||||
g2.drawPolygon(p);
|
||||
g2.setFont(new Font("Arial", Font.BOLD, 7));
|
||||
String cstr = "" + v.getCount();
|
||||
int strW = g2.getFontMetrics().stringWidth(cstr);
|
||||
g2.drawString(cstr, 5 - strW / 2, 8);
|
||||
g2.dispose();
|
||||
yPos += ((int) (0.30 * cardWidth));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw an expansion symbol, right justified, in a given region
|
||||
// Return the width of the drawn symbol
|
||||
protected int drawExpansionSymbol(Graphics2D g, int x, int y, int w, int h) {
|
||||
// Draw the expansion symbol
|
||||
Image setSymbol = ManaSymbols.getSetSymbolImage(cardView.getExpansionSetCode(), cardView.getRarity().getCode());
|
||||
int setSymbolWidth;
|
||||
if (setSymbol == null) {
|
||||
// Don't draw anything when we don't have a set symbol
|
||||
return 0;
|
||||
/*
|
||||
// Just draw the as a code
|
||||
String code = cardView.getExpansionSetCode();
|
||||
code = (code != null) ? code.toUpperCase() : "";
|
||||
FontMetrics metrics = g.getFontMetrics();
|
||||
setSymbolWidth = metrics.stringWidth(code);
|
||||
if (cardView.getRarity() == Rarity.COMMON) {
|
||||
g.setColor(Color.white);
|
||||
} else {
|
||||
g.setColor(Color.black);
|
||||
}
|
||||
g.fillRoundRect(
|
||||
x + w - setSymbolWidth - 1, y + 2,
|
||||
setSymbolWidth+2, h - 5,
|
||||
5, 5);
|
||||
g.setColor(getRarityColor());
|
||||
g.drawString(code, x + w - setSymbolWidth, y + h - 3);
|
||||
*/
|
||||
} else {
|
||||
// Draw the set symbol
|
||||
int height = setSymbol.getHeight(null);
|
||||
int scale = 1;
|
||||
if (height != -1) {
|
||||
while (height > h + 2) {
|
||||
scale *= 2;
|
||||
height /= 2;
|
||||
}
|
||||
}
|
||||
setSymbolWidth = setSymbol.getWidth(null) / scale;
|
||||
g.drawImage(setSymbol,
|
||||
x + w - setSymbolWidth, y + (h - height) / 2,
|
||||
setSymbolWidth, height,
|
||||
null);
|
||||
}
|
||||
return setSymbolWidth;
|
||||
}
|
||||
|
||||
private Color getRarityColor() {
|
||||
switch (cardView.getRarity()) {
|
||||
case RARE:
|
||||
return new Color(255, 191, 0);
|
||||
case UNCOMMON:
|
||||
return new Color(192, 192, 192);
|
||||
case MYTHIC:
|
||||
return new Color(213, 51, 11);
|
||||
case SPECIAL:
|
||||
return new Color(204, 0, 255);
|
||||
case BONUS:
|
||||
return new Color(129, 228, 228);
|
||||
case COMMON:
|
||||
default:
|
||||
return Color.black;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a string representing the type line
|
||||
protected String getCardTypeLine() {
|
||||
if (cardView.isAbility()) {
|
||||
if (AbilityType.TRIGGERED.equals(cardView.getAbilityType())) {
|
||||
return "Triggered Ability";
|
||||
} else if (AbilityType.ACTIVATED.equals(cardView.getAbilityType())) {
|
||||
return "Activated Ability";
|
||||
} else {
|
||||
return "??? Ability";
|
||||
}
|
||||
} else {
|
||||
StringBuilder sbType = new StringBuilder();
|
||||
for (String superType : cardView.getSuperTypes()) {
|
||||
sbType.append(superType).append(" ");
|
||||
}
|
||||
for (CardType cardType : cardView.getCardTypes()) {
|
||||
sbType.append(cardType.toString()).append(" ");
|
||||
}
|
||||
if (cardView.getSubTypes().size() > 0) {
|
||||
sbType.append("- ");
|
||||
for (String subType : cardView.getSubTypes()) {
|
||||
sbType.append(subType).append(" ");
|
||||
}
|
||||
}
|
||||
return sbType.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the card art image (CardPanel will give it to us when it
|
||||
// is loaded and ready)
|
||||
public void setArtImage(Image image) {
|
||||
artImage = CardRendererUtils.toBufferedImage(image);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Various static utilities for use in the card renderer
|
||||
*/
|
||||
public class CardRendererUtils {
|
||||
/**
|
||||
* Convert an abstract image, whose underlying implementation may or may
|
||||
* not be a BufferedImage into a BufferedImage by creating one and coping
|
||||
* the contents if it is not, and simply up-casting if it is.
|
||||
* @param img The image to convert
|
||||
* @return The converted image
|
||||
*/
|
||||
public static BufferedImage toBufferedImage(Image img) {
|
||||
// Null? No conversion to do
|
||||
if (img == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Already a buffered image?
|
||||
if (img instanceof BufferedImage) {
|
||||
return (BufferedImage) img;
|
||||
}
|
||||
|
||||
// Create a buffered image with transparency
|
||||
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
// Draw the image on to the buffered image
|
||||
Graphics2D bGr = bimage.createGraphics();
|
||||
bGr.drawImage(img, 0, 0, null);
|
||||
bGr.dispose();
|
||||
|
||||
// Return the buffered image
|
||||
return bimage;
|
||||
}
|
||||
|
||||
// Draw a rounded box with a 2-pixel border
|
||||
// Used on various card parts.
|
||||
public static void drawRoundedBox(Graphics2D g, int x, int y, int w, int h, int bevel, Paint border, Color fill) {
|
||||
g.setColor(new Color(0, 0, 0, 150));
|
||||
g.drawOval(x-1, y-1, bevel*2, h);
|
||||
g.setPaint(border);
|
||||
g.drawOval(x, y, bevel*2-1, h-1);
|
||||
g.drawOval(x + w - bevel*2, y, bevel*2-1, h-1);
|
||||
g.drawOval(x+1, y+1, bevel*2-3, h-3);
|
||||
g.drawOval(x+1 + w - bevel*2, y+1, bevel*2-3, h-3);
|
||||
g.drawRect(x + bevel, y, w - 2*bevel, h-1);
|
||||
g.drawRect(x+1 + bevel, y+1, w - 2*bevel-2, h-3);
|
||||
g.setColor(fill);
|
||||
g.fillOval(x+2, y+2, bevel*2-4, h-4);
|
||||
g.fillOval(x+2 + w - bevel*2, y+2, bevel*2-4, h-4);
|
||||
g.fillRect(x + bevel, y+2, w - 2*bevel, h-4);
|
||||
}
|
||||
|
||||
// Get the width of a mana cost rendered with ManaSymbols.draw
|
||||
public static int getManaCostWidth(String manaCost, int symbolSize) {
|
||||
int width = 0;
|
||||
manaCost = manaCost.replace("\\", "");
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
tok.nextToken();
|
||||
width += symbolSize;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
// Abbreviate a piece of rules text, making substitutions to decrease its
|
||||
// length. Also abbreviate reminder text.
|
||||
private static Pattern abbreviationPattern;
|
||||
private static Map<String, String> abbreviations = new HashMap<String, String>();
|
||||
private static Pattern killReminderTextPattern;
|
||||
static {
|
||||
// Available abbreviations
|
||||
abbreviations.put("enters the battlefield", "ETB");
|
||||
abbreviations.put("less than", "<");
|
||||
abbreviations.put("greater than", ">");
|
||||
|
||||
// Compile into regex
|
||||
String patternString = "(";
|
||||
Iterator<String> it = abbreviations.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
patternString += it.next();
|
||||
if (it.hasNext()) {
|
||||
patternString += "|";
|
||||
}
|
||||
}
|
||||
patternString += ")";
|
||||
abbreviationPattern = Pattern.compile(patternString);
|
||||
|
||||
// Reminder text killing
|
||||
killReminderTextPattern = Pattern.compile("\\([^\\)]*\\)");
|
||||
}
|
||||
public static String abbreviateRule(String rule) {
|
||||
StringBuffer build = new StringBuffer();
|
||||
Matcher match = abbreviationPattern.matcher(rule);
|
||||
while (match.find()) {
|
||||
match.appendReplacement(build, abbreviations.get(match.group(1)));
|
||||
}
|
||||
match.appendTail(build);
|
||||
return build.toString();
|
||||
}
|
||||
public static String killReminderText(String rule) {
|
||||
return killReminderTextPattern.matcher(rule).replaceAll("");
|
||||
}
|
||||
}
|
|
@ -2,20 +2,12 @@ package org.mage.card.arcane;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.LineBreakMeasurer;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
@ -23,10 +15,12 @@ import java.text.BreakIterator;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.swing.*;
|
||||
import mage.client.util.ImageCaches;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
|
||||
public class GlowText extends JLabel {
|
||||
|
||||
private static final long serialVersionUID = 1827677946939348001L;
|
||||
private int glowSize;
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -36,8 +30,8 @@ public class GlowText extends JLabel {
|
|||
private int lineCount = 0;
|
||||
private static Map<Key, BufferedImage> IMAGE_CACHE;
|
||||
|
||||
private final static class Key
|
||||
{
|
||||
private final static class Key {
|
||||
|
||||
final int width;
|
||||
final int height;
|
||||
final String text;
|
||||
|
@ -53,8 +47,9 @@ public class GlowText extends JLabel {
|
|||
|
||||
Font getFont() {
|
||||
Font res = this.originalFont.get();
|
||||
if(res == null)
|
||||
if (res == null) {
|
||||
res = Font.getFont(this.fontAttributes);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ManaSymbols {
|
|||
private static boolean smallSymbolsFound = false;
|
||||
private static boolean mediumSymbolsFound = false;
|
||||
|
||||
private static final Map<String, Image> setImages = new HashMap<>();
|
||||
private static final Map<String, Map<String, Image>> setImages = new HashMap<>();
|
||||
private static final Map<String, Dimension> setImagesExist = new HashMap<>();
|
||||
private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}");
|
||||
private static String cachedPath;
|
||||
|
@ -57,7 +57,13 @@ public class ManaSymbols {
|
|||
return;
|
||||
}
|
||||
for (String set : setCodes) {
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-C.jpg");
|
||||
String[] codes = new String[]{"C", "U", "R", "M"};
|
||||
|
||||
Map<String, Image> rarityImages = new HashMap<>();
|
||||
setImages.put(set, rarityImages);
|
||||
|
||||
for (String rarityCode: codes) {
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-" + rarityCode + ".jpg");
|
||||
try {
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
int width = image.getWidth(null);
|
||||
|
@ -66,16 +72,17 @@ public class ManaSymbols {
|
|||
if (h > 0) {
|
||||
Rectangle r = new Rectangle(21, (int) (h * 21.0f / width));
|
||||
BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||
setImages.put(set, resized);
|
||||
rarityImages.put(set, resized);
|
||||
}
|
||||
} else {
|
||||
setImages.put(set, image);
|
||||
rarityImages.put(rarityCode, image);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String[] codes = new String[]{"C", "U", "R", "M"};
|
||||
}
|
||||
|
||||
try {
|
||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
@ -298,14 +305,27 @@ public class ManaSymbols {
|
|||
}
|
||||
|
||||
public static Image getSetSymbolImage(String set) {
|
||||
return setImages.get(set);
|
||||
return getSetSymbolImage(set, "C");
|
||||
}
|
||||
|
||||
public static Image getSetSymbolImage(String set, String rarity) {
|
||||
Map<String, Image> rarityImages = setImages.get(set);
|
||||
if (rarityImages != null) {
|
||||
return rarityImages.get(rarity);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage getSizedManaSymbol(String symbol) {
|
||||
if (!manaImages.containsKey(GUISizeHelper.symbolDialogSize)) {
|
||||
loadSymbolsImages(GUISizeHelper.symbolDialogSize);
|
||||
return getSizedManaSymbol(symbol, GUISizeHelper.symbolDialogSize);
|
||||
}
|
||||
Map<String, BufferedImage> sizedSymbols = manaImages.get(GUISizeHelper.symbolDialogSize);
|
||||
|
||||
public static BufferedImage getSizedManaSymbol(String symbol, int size) {
|
||||
if (!manaImages.containsKey(size)) {
|
||||
loadSymbolsImages(size);
|
||||
}
|
||||
Map<String, BufferedImage> sizedSymbols = manaImages.get(size);
|
||||
return sizedSymbols.get(symbol);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*/
|
||||
public class TextboxKeywordRule extends TextboxRule {
|
||||
public TextboxKeywordRule(String text, List<AttributeRegion> regions) {
|
||||
super(text, regions, TextboxRuleType.SIMPLE_KEYWORD);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author StravantUser
|
||||
*
|
||||
* Level rule associated with leveler cards
|
||||
*/
|
||||
public class TextboxLevelRule extends TextboxRule {
|
||||
|
||||
// The levels that this rule applies to
|
||||
public int levelFrom;
|
||||
public int levelTo;
|
||||
|
||||
public static int AND_HIGHER = 100;
|
||||
|
||||
public TextboxLevelRule(String text, List<AttributeRegion> regions, int levelFrom, int levelTo) {
|
||||
super(text, regions, TextboxRuleType.LEVEL);
|
||||
this.levelFrom = levelFrom;
|
||||
this.levelTo = levelTo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author StravantUser
|
||||
*/
|
||||
public class TextboxLoyaltyRule extends TextboxRule {
|
||||
|
||||
public int loyaltyChange;
|
||||
|
||||
public static int MINUS_X = 100;
|
||||
|
||||
public String getChangeString() {
|
||||
if (loyaltyChange == MINUS_X) {
|
||||
return "-X";
|
||||
} else if (loyaltyChange > 0) {
|
||||
return "+" + loyaltyChange;
|
||||
} else {
|
||||
return "" + loyaltyChange;
|
||||
}
|
||||
}
|
||||
|
||||
public TextboxLoyaltyRule(String text, List<AttributeRegion> regions, int loyaltyChange) {
|
||||
super(text, regions, TextboxRuleType.LOYALTY);
|
||||
this.loyaltyChange = loyaltyChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Image;
|
||||
import java.awt.font.GraphicAttribute;
|
||||
import java.awt.font.ImageGraphicAttribute;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.text.AttributedString;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Class describing parsed & translated rules in the text box of a card, ready
|
||||
* to be rendered.
|
||||
*/
|
||||
public class TextboxRule {
|
||||
|
||||
// An attributed region in the text, which can be applied to an
|
||||
// attributed string.
|
||||
public interface AttributeRegion {
|
||||
|
||||
public void applyToAttributedString(AttributedString str, Font normal, Font italic);
|
||||
}
|
||||
|
||||
// A region of italics, or bold text in a
|
||||
public static class ItalicRegion implements AttributeRegion {
|
||||
|
||||
ItalicRegion(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
private final int start;
|
||||
private final int end;
|
||||
|
||||
@Override
|
||||
public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
|
||||
if (end > start + 1) {
|
||||
str.addAttribute(TextAttribute.FONT, italic, start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A special symbol embedded at some point in a string
|
||||
public static class EmbeddedSymbol implements AttributeRegion {
|
||||
|
||||
EmbeddedSymbol(String symbol, int location) {
|
||||
this.symbol = symbol;
|
||||
this.location = location;
|
||||
}
|
||||
private final String symbol;
|
||||
private final int location;
|
||||
|
||||
@Override
|
||||
public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
|
||||
Image symbolImage = ManaSymbols.getSizedManaSymbol(symbol.replace("/", ""), normal.getSize());
|
||||
if (symbolImage != null) {
|
||||
ImageGraphicAttribute imgAttr
|
||||
= new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT);
|
||||
str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String text;
|
||||
public TextboxRuleType type;
|
||||
|
||||
private List<AttributeRegion> regions;
|
||||
|
||||
protected TextboxRule(String text, List<AttributeRegion> regions, TextboxRuleType type) {
|
||||
this.text = text;
|
||||
this.type = type;
|
||||
this.regions = regions;
|
||||
}
|
||||
|
||||
public TextboxRule(String text, List<AttributeRegion> regions) {
|
||||
this(text, regions, TextboxRuleType.NORMAL);
|
||||
}
|
||||
|
||||
public AttributedString generateAttributedString(Font normal, Font italic) {
|
||||
// Build the final attributed text using the regions
|
||||
// Do it in reverse order for proper handling of regions where
|
||||
// there are multiple attributes stacked (EG: bold + italic)
|
||||
AttributedString attributedRule = new AttributedString(text);
|
||||
if (text.length() != 0) {
|
||||
attributedRule.addAttribute(TextAttribute.FONT, normal);
|
||||
for (int i = regions.size() - 1; i >= 0; --i) {
|
||||
regions.get(i).applyToAttributedString(attributedRule, normal, italic);
|
||||
}
|
||||
}
|
||||
return attributedRule;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import mage.view.CardView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author StravantUser
|
||||
*/
|
||||
public class TextboxRuleParser {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||
|
||||
private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)");
|
||||
private static final Pattern LoyaltyAbilityPattern = Pattern.compile("^(\\+|\\-)(\\d+|X): ");
|
||||
private static final Pattern SimpleKeywordPattern = Pattern.compile("^(\\w+( \\w+)?)\\s*(\\([^\\)]*\\))?\\s*$");
|
||||
|
||||
// Parse a given rule (given as a string) into a TextboxRule, replacing
|
||||
// symbol annotations, italics, etc, parsing out information such as
|
||||
// if the ability is a loyalty ability, and returning an TextboxRule
|
||||
// representing that information, which can be used to render the rule in
|
||||
// the textbox of a card.
|
||||
public static TextboxRule parse(CardView source, String rule) {
|
||||
// List of regions to apply
|
||||
ArrayList<TextboxRule.AttributeRegion> regions = new ArrayList<>();
|
||||
|
||||
// Leveler / loyalty
|
||||
boolean isLeveler = false;
|
||||
int levelFrom = 0;
|
||||
int levelTo = 0;
|
||||
|
||||
boolean isLoyalty = false;
|
||||
int loyaltyChange = 0;
|
||||
|
||||
// Parse the attributedString contents
|
||||
int index = 0;
|
||||
int outputIndex = 0;
|
||||
|
||||
// Is it a simple keyword ability?
|
||||
{
|
||||
Matcher simpleKeywordMatch = SimpleKeywordPattern.matcher(rule);
|
||||
if (simpleKeywordMatch.find()) {
|
||||
return new TextboxKeywordRule(simpleKeywordMatch.group(1), regions);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it's a loyalty ability. Must be right at the start of the rule
|
||||
{
|
||||
Matcher loyaltyMatch = LoyaltyAbilityPattern.matcher(rule);
|
||||
if (loyaltyMatch.find()) {
|
||||
// Get the loyalty change
|
||||
if (loyaltyMatch.group(2).equals("X")) {
|
||||
loyaltyChange = TextboxLoyaltyRule.MINUS_X;
|
||||
} else {
|
||||
loyaltyChange = Integer.parseInt(loyaltyMatch.group(2));
|
||||
if (loyaltyMatch.group(1).equals("-")) {
|
||||
loyaltyChange = -loyaltyChange;
|
||||
}
|
||||
}
|
||||
isLoyalty = true;
|
||||
|
||||
// Go past the match
|
||||
index = loyaltyMatch.group().length();
|
||||
}
|
||||
}
|
||||
|
||||
Deque<Integer> openingStack = new ArrayDeque<>();
|
||||
StringBuilder build = new StringBuilder();
|
||||
while (index < rule.length()) {
|
||||
int initialIndex = index;
|
||||
char ch = rule.charAt(index);
|
||||
switch (ch) {
|
||||
case '{': {
|
||||
// Handling for `{this}`
|
||||
int closeIndex = rule.indexOf('}', index);
|
||||
if (closeIndex == -1) {
|
||||
// Malformed input, nothing to do
|
||||
++index;
|
||||
++outputIndex;
|
||||
build.append(ch);
|
||||
} else {
|
||||
String contents = rule.substring(index + 1, closeIndex);
|
||||
if (contents.equals("this") || contents.equals("source")) {
|
||||
// Replace {this} with the card's name
|
||||
String cardName = source.getName();
|
||||
build.append(cardName);
|
||||
index += contents.length() + 2;
|
||||
outputIndex += cardName.length();
|
||||
} else {
|
||||
Image symbol = ManaSymbols.getSizedManaSymbol(contents.replace("/", ""), 10);
|
||||
if (symbol != null) {
|
||||
// Mana or other inline symbol
|
||||
build.append('#');
|
||||
regions.add(new TextboxRule.EmbeddedSymbol(contents, outputIndex));
|
||||
++outputIndex;
|
||||
index = closeIndex + 1;
|
||||
} else {
|
||||
// Bad entry
|
||||
build.append('{');
|
||||
build.append(contents);
|
||||
build.append('}');
|
||||
index = closeIndex + 1;
|
||||
outputIndex += (contents.length() + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '&':
|
||||
// Handling for `—`
|
||||
if (rule.startsWith("—", index)) {
|
||||
build.append('—');
|
||||
index += 7;
|
||||
++outputIndex;
|
||||
} else if (rule.startsWith("&bull", index)) {
|
||||
build.append('•');
|
||||
index += 5;
|
||||
++outputIndex;
|
||||
} else {
|
||||
LOGGER.error("Bad &...; sequence `" + rule.substring(index + 1, index + 10) + "` in rule.");
|
||||
build.append('&');
|
||||
++index;
|
||||
++outputIndex;
|
||||
}
|
||||
break;
|
||||
case '<': {
|
||||
// Handling for `<i>` and `<br/>`
|
||||
int closeIndex = rule.indexOf('>', index);
|
||||
if (closeIndex != -1) {
|
||||
// Is a tag
|
||||
String tag = rule.substring(index + 1, closeIndex);
|
||||
if (tag.charAt(tag.length() - 1) == '/') {
|
||||
// Pure closing tag (like <br/>)
|
||||
if (tag.equals("br/")) {
|
||||
build.append('\n');
|
||||
++outputIndex;
|
||||
} else {
|
||||
// Unknown
|
||||
build.append('<').append(tag).append('>');
|
||||
outputIndex += (tag.length() + 2);
|
||||
}
|
||||
} else if (tag.charAt(0) == '/') {
|
||||
// Opening index for the tag
|
||||
int openingIndex;
|
||||
if (openingStack.isEmpty()) {
|
||||
// Malformed input, just make an empty interval
|
||||
openingIndex = outputIndex;
|
||||
} else {
|
||||
openingIndex = openingStack.pop();
|
||||
}
|
||||
|
||||
// What tag is it?
|
||||
switch (tag) {
|
||||
case "/i":
|
||||
// Italics
|
||||
regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex));
|
||||
break;
|
||||
case "/b":
|
||||
// Bold, see if it's a level ability
|
||||
String content = build.substring(openingIndex);
|
||||
Matcher levelMatch = LevelAbilityPattern.matcher(content);
|
||||
if (levelMatch.find()) {
|
||||
try {
|
||||
levelFrom = Integer.parseInt(levelMatch.group(1));
|
||||
if (!levelMatch.group(2).equals("")) {
|
||||
levelTo = Integer.parseInt(levelMatch.group(2));
|
||||
}
|
||||
if (!levelMatch.group(3).equals("")) {
|
||||
levelTo = TextboxLevelRule.AND_HIGHER;
|
||||
}
|
||||
isLeveler = true;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Bad leveler levels in rule `" + rule + "`.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unknown
|
||||
build.append('<').append(tag).append('>');
|
||||
outputIndex += (tag.length() + 2);
|
||||
break;
|
||||
}
|
||||
} else // Is it a <br> tag special case? [Why can't it have a closing `/`... =( ]
|
||||
{
|
||||
if (tag.equals("br")) {
|
||||
build.append('\n');
|
||||
++outputIndex;
|
||||
} else {
|
||||
// Opening tag
|
||||
openingStack.push(outputIndex);
|
||||
}
|
||||
}
|
||||
// Skip characters
|
||||
index = closeIndex + 1;
|
||||
} else {
|
||||
// Malformed tag
|
||||
build.append('<');
|
||||
++outputIndex;
|
||||
++index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Normal character
|
||||
++index;
|
||||
++outputIndex;
|
||||
build.append(ch);
|
||||
break;
|
||||
}
|
||||
if (outputIndex != build.length()) {
|
||||
// Somehow our parsing code output symbols but didn't update the output index correspondingly
|
||||
LOGGER.error("The human is dead; mismatch! Failed on rule: `" + rule + "` due to not updating outputIndex properly.");
|
||||
|
||||
// Bail out
|
||||
build = new StringBuilder(rule);
|
||||
regions.clear();
|
||||
break;
|
||||
}
|
||||
if (index == initialIndex) {
|
||||
// Somehow our parsing failed to consume the
|
||||
LOGGER.error("Failed on rule `" + rule + "` due to not consuming a character.");
|
||||
|
||||
// Bail out
|
||||
build = new StringBuilder(rule);
|
||||
regions.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Build and return the rule
|
||||
rule = build.toString();
|
||||
if (isLoyalty) {
|
||||
return new TextboxLoyaltyRule(rule, regions, loyaltyChange);
|
||||
} else if (isLeveler) {
|
||||
return new TextboxLevelRule(rule, regions, levelFrom, levelTo);
|
||||
} else {
|
||||
return new TextboxRule(rule, regions);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*/
|
||||
public enum TextboxRuleType {
|
||||
/* Normal abilities, just rendered as lines of text with embedded symbols
|
||||
* replaced to the relevant images. */
|
||||
NORMAL,
|
||||
|
||||
/* Keyword ability. To be displayed in the comma separated list at the
|
||||
* very top of the rules box */
|
||||
SIMPLE_KEYWORD,
|
||||
|
||||
/* Loyalty abilities on planeswalkers */
|
||||
LOYALTY,
|
||||
|
||||
/* Levelup creature - static ability at a given level */
|
||||
LEVEL
|
||||
}
|
|
@ -17,6 +17,7 @@ import javax.swing.JDialog;
|
|||
import javax.swing.JLayeredPane;
|
||||
import mage.cards.MagePermanent;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.constants.Rarity;
|
||||
import mage.interfaces.plugin.CardPlugin;
|
||||
|
@ -31,6 +32,7 @@ import net.xeoh.plugins.base.annotations.meta.Author;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.Animation;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
import org.mage.card.arcane.CardPanelComponentImpl;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
import org.mage.plugins.card.dl.DownloadGui;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
|
@ -41,6 +43,7 @@ import org.mage.plugins.card.dl.sources.GathererSets;
|
|||
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
||||
import org.mage.card.arcane.CardPanelRenderImpl;
|
||||
|
||||
/**
|
||||
* {@link CardPlugin} implementation.
|
||||
|
@ -106,9 +109,22 @@ public class CardPluginImpl implements CardPlugin {
|
|||
cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary card rendering shim. Split card rendering isn't implemented yet, so
|
||||
* use old component based rendering for the split cards.
|
||||
*/
|
||||
private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension) {
|
||||
String fallback = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false");
|
||||
if (view.isSplitCard() || fallback.equals("true")) {
|
||||
return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
|
||||
} else {
|
||||
return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
||||
CardPanel cardPanel = new CardPanel(permanent, gameId, loadImage, callback, false, dimension);
|
||||
CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension);
|
||||
boolean implemented = !permanent.getRarity().equals(Rarity.NA);
|
||||
cardPanel.setShowCastingCost(implemented);
|
||||
return cardPanel;
|
||||
|
@ -116,7 +132,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
|
||||
@Override
|
||||
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
||||
CardPanel cardPanel = new CardPanel(cardView, gameId, loadImage, callback, false, dimension);
|
||||
CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension);
|
||||
boolean implemented = cardView.getRarity() != null && !cardView.getRarity().equals(Rarity.NA);
|
||||
cardPanel.setShowCastingCost(implemented);
|
||||
return cardPanel;
|
||||
|
|
|
@ -12,6 +12,7 @@ public class CardDownloadData {
|
|||
private String downloadName;
|
||||
private String set;
|
||||
private String tokenSetCode;
|
||||
private String tokenDescriptor;
|
||||
private String collectorId;
|
||||
private Integer type;
|
||||
private boolean token;
|
||||
|
@ -23,15 +24,15 @@ public class CardDownloadData {
|
|||
private boolean usesVariousArt;
|
||||
private boolean isType2;
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, false);
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, false);
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, boolean token) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, token, false, false);
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false);
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
this.name = name;
|
||||
this.set = set;
|
||||
this.collectorId = collectorId;
|
||||
|
@ -41,6 +42,7 @@ public class CardDownloadData {
|
|||
this.twoFacedCard = twoFacedCard;
|
||||
this.secondSide = secondSide;
|
||||
this.tokenSetCode = tokenSetCode;
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
}
|
||||
|
||||
public CardDownloadData(final CardDownloadData card) {
|
||||
|
@ -130,6 +132,13 @@ public class CardDownloadData {
|
|||
this.tokenSetCode = tokenSetCode;
|
||||
}
|
||||
|
||||
public String getTokenDescriptor() {
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
public void setTokenDescriptor(String tokenDescriptor) {
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
}
|
||||
public boolean isToken() {
|
||||
return token;
|
||||
}
|
||||
|
|
|
@ -239,7 +239,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
TFile file;
|
||||
for (CardInfo card : allCards) {
|
||||
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) {
|
||||
CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(),
|
||||
0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
file = new TFile(CardImageUtils.generateImagePath(url));
|
||||
if (!file.exists()) {
|
||||
return true;
|
||||
|
@ -285,7 +286,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
&& !ignoreUrls.contains(card.getSetCode())) {
|
||||
String cardName = card.getName();
|
||||
boolean isType2 = type2SetsFilter.contains(card.getSetCode());
|
||||
CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
if (url.getUsesVariousArt()) {
|
||||
url.setDownloadName(createDownloadName(card));
|
||||
}
|
||||
|
@ -299,7 +300,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (card.getSecondSideName() == null || card.getSecondSideName().trim().isEmpty()) {
|
||||
throw new IllegalStateException("Second side card can't have empty name.");
|
||||
}
|
||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), true);
|
||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true);
|
||||
url.setType2(isType2);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
|
@ -307,7 +308,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (card.getFlipCardName() == null || card.getFlipCardName().trim().isEmpty()) {
|
||||
throw new IllegalStateException("Flipped card can't have empty name.");
|
||||
}
|
||||
url = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
url = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
url.setFlipCard(true);
|
||||
url.setFlippedSide(true);
|
||||
url.setType2(isType2);
|
||||
|
@ -385,19 +386,19 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
}
|
||||
if (params[1].toLowerCase().equals("generate") && params[2].startsWith("TOK:")) {
|
||||
String set = params[2].substring(4);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", true);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM:")) {
|
||||
String set = params[2].substring(7);
|
||||
CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, "", true);
|
||||
CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, "", "", true);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM-:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type, "", true);
|
||||
CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type, "", "", true);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM!:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", true);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true);
|
||||
list.add(card);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ImageCache {
|
|||
/**
|
||||
* Common pattern for keys. Format: "<cardname>#<setname>#<collectorID>"
|
||||
*/
|
||||
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)");
|
||||
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)#(.*)");
|
||||
|
||||
static {
|
||||
IMAGE_CACHE = new MapMaker().softValues().makeComputingMap(new Function<String, BufferedImage>() {
|
||||
|
@ -56,12 +56,12 @@ public class ImageCache {
|
|||
try {
|
||||
|
||||
boolean usesVariousArt = false;
|
||||
if (key.endsWith("#usesVariousArt")) {
|
||||
if (key.matches(".*#usesVariousArt.*")) {
|
||||
usesVariousArt = true;
|
||||
key = key.replace("#usesVariousArt", "");
|
||||
}
|
||||
boolean thumbnail = false;
|
||||
if (key.endsWith("#thumb")) {
|
||||
if (key.matches(".*#thumb.*")) {
|
||||
thumbnail = true;
|
||||
key = key.replace("#thumb", "");
|
||||
}
|
||||
|
@ -76,8 +76,9 @@ public class ImageCache {
|
|||
collectorId = "0";
|
||||
}
|
||||
String tokenSetCode = m.group(5);
|
||||
String tokenDescriptor = m.group(6);
|
||||
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode);
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
|
||||
|
||||
String path;
|
||||
if (collectorId.isEmpty() || "0".equals(collectorId)) {
|
||||
|
@ -154,7 +155,7 @@ public class ImageCache {
|
|||
}
|
||||
|
||||
public static BufferedImage getMorphImage() {
|
||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK");
|
||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", "");
|
||||
info.setToken(true);
|
||||
String path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
|
@ -165,7 +166,7 @@ public class ImageCache {
|
|||
}
|
||||
|
||||
public static BufferedImage getManifestImage() {
|
||||
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF");
|
||||
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF", "");
|
||||
info.setToken(true);
|
||||
String path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
|
@ -201,6 +202,10 @@ public class ImageCache {
|
|||
return getImage(getKey(card, card.getName(), "#thumb"));
|
||||
}
|
||||
|
||||
public static BufferedImage tryGetThumbnail(CardView card) {
|
||||
return tryGetImage(getKey(card, card.getName(), "#thumb"));
|
||||
}
|
||||
|
||||
public static BufferedImage getImageOriginal(CardView card) {
|
||||
return getImage(getKey(card, card.getName(), ""));
|
||||
}
|
||||
|
@ -231,6 +236,18 @@ public class ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key only if it already exists
|
||||
* in the cache.
|
||||
*/
|
||||
private static BufferedImage tryGetImage(String key) {
|
||||
if (IMAGE_CACHE.containsKey(key)) {
|
||||
return IMAGE_CACHE.get(key);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map key for a card, without any suffixes for the image size.
|
||||
*/
|
||||
|
@ -238,8 +255,8 @@ public class ImageCache {
|
|||
return name + "#" + card.getExpansionSetCode() + "#" + card.getType() + "#" + card.getCardNumber() + "#"
|
||||
+ (card.getTokenSetCode() == null ? "" : card.getTokenSetCode())
|
||||
+ suffix
|
||||
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "");
|
||||
|
||||
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "")
|
||||
+ (card.getTokenDescriptor() != null ? "#" + card.getTokenDescriptor() : "#");
|
||||
}
|
||||
|
||||
// /**
|
||||
|
@ -344,6 +361,34 @@ public class ImageCache {
|
|||
return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image appropriate to display for a card in a picture panel, but
|
||||
* only it was ALREADY LOADED. That is, the call is immediate and will not block
|
||||
* on file IO.
|
||||
* @param card
|
||||
* @param width
|
||||
* @param height
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage tryGetImage(CardView card, int width, int height) {
|
||||
if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) {
|
||||
return tryGetThumbnail(card);
|
||||
}
|
||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
||||
BufferedImage original = tryGetImage(key);
|
||||
if (original == null) {
|
||||
LOGGER.debug(key + " not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight());
|
||||
if (scale >= 1) {
|
||||
return original;
|
||||
}
|
||||
|
||||
return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
|
||||
}
|
||||
|
||||
public static TFile getTFile(String path) {
|
||||
try {
|
||||
TFile file = new TFile(path);
|
||||
|
|
|
@ -50,6 +50,11 @@ public class CardImageUtils {
|
|||
String filename = generateImagePath(card);
|
||||
|
||||
TFile file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
filename = generateTokenDescriptorImagePath(card);
|
||||
}
|
||||
|
||||
file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
CardDownloadData updated = new CardDownloadData(card);
|
||||
updated.setName(card.getName() + " 1");
|
||||
|
@ -86,7 +91,7 @@ public class CardImageUtils {
|
|||
// return path;
|
||||
// }
|
||||
// }
|
||||
return "";
|
||||
return generateTokenDescriptorImagePath(card);
|
||||
}
|
||||
|
||||
public static String updateSet(String cardSet, boolean forUrl) {
|
||||
|
@ -113,6 +118,17 @@ public class CardImageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static String getTokenDescriptorImagePath(CardDownloadData card) {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String imagesPath = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesPath + TFile.separator + "TOK" + ".zip" + TFile.separator + card.getTokenDescriptor() + ".full.jpg";
|
||||
} else {
|
||||
return imagesPath + TFile.separator + "TOK" + TFile.separator + card.getTokenDescriptor() + ".full.jpg";
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildTokenPath(String imagesDir, String set) {
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesDir + TFile.separator + "TOK" + ".zip" + TFile.separator + set;
|
||||
|
@ -157,6 +173,30 @@ public class CardImageUtils {
|
|||
return imageDir + TFile.separator + imageName;
|
||||
}
|
||||
|
||||
public static String generateTokenDescriptorImagePath(CardDownloadData card) {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String imagesPath = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
|
||||
String straightImageFile = getTokenDescriptorImagePath(card);
|
||||
TFile file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
|
||||
straightImageFile = straightImageFile.replaceFirst("\\.[0-9]+\\.[0-9]+", ".X.X");
|
||||
file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
|
||||
straightImageFile = straightImageFile.replaceFirst("\\.X\\.X", ".S.S");
|
||||
file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static Proxy getProxyFromPreferences() {
|
||||
Preferences prefs = MageFrame.getPreferences();
|
||||
Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None"));
|
||||
|
|
After Width: | Height: | Size: 411 KiB |
After Width: | Height: | Size: 450 KiB |
After Width: | Height: | Size: 453 KiB |
After Width: | Height: | Size: 506 KiB |
After Width: | Height: | Size: 517 KiB |
After Width: | Height: | Size: 457 KiB |
After Width: | Height: | Size: 534 KiB |
After Width: | Height: | Size: 144 KiB |
BIN
Mage.Client/src/main/resources/cardrender/beleren-bold.ttf
Normal file
|
@ -18,15 +18,15 @@ public class TokensMtgImageSourceTest {
|
|||
public void generateTokenUrlTest() throws Exception {
|
||||
CardImageSource imageSource = TokensMtgImageSource.getInstance();
|
||||
|
||||
String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI"));
|
||||
String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url);
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI"));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI"));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url);
|
||||
}
|
||||
}
|
||||
|
|
28
Mage.Common/src/mage/cards/CardBorder.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
package mage.cards;
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Enum listing the possible card faces for a card
|
||||
*
|
||||
* Because of Time Spiral block's shifted cards it is
|
||||
* not sufficient to just look at a card's edition to
|
||||
* determine what the card face should be.
|
||||
*/
|
||||
public enum CardBorder {
|
||||
/* Old border card frames. ALPHA -> 8th ED */
|
||||
OLD,
|
||||
|
||||
/* Future Sight frames. FUT futureshifted */
|
||||
FUT,
|
||||
|
||||
/* Planar Chaos frames. PLC planeshifted */
|
||||
PLC,
|
||||
|
||||
/* Modern card frames. 8th ED -> M15 */
|
||||
MOD,
|
||||
|
||||
/* New border cards, M15 -> current */
|
||||
M15
|
||||
}
|
|
@ -32,7 +32,7 @@ public abstract class MageCard extends JPanel {
|
|||
|
||||
public abstract void update(CardView card);
|
||||
|
||||
public abstract void updateImage();
|
||||
public abstract void updateArtImage();
|
||||
|
||||
public abstract Image getImage();
|
||||
|
||||
|
|
|
@ -247,9 +247,9 @@ public class DeckBuilder {
|
|||
int type;
|
||||
if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
type = 10;
|
||||
} else if (card.getSubtype().contains("Equipment")) {
|
||||
} else if (card.getSubtype(null).contains("Equipment")) {
|
||||
type = 8;
|
||||
} else if (card.getSubtype().contains("Aura")) {
|
||||
} else if (card.getSubtype(null).contains("Aura")) {
|
||||
type = 5;
|
||||
} else if (card.getCardType().contains(CardType.INSTANT)) {
|
||||
type = 7;
|
||||
|
|
|
@ -68,10 +68,12 @@ public class CardView extends SimpleCardView {
|
|||
protected String power;
|
||||
protected String toughness;
|
||||
protected String loyalty;
|
||||
protected String startingLoyalty;
|
||||
protected List<CardType> cardTypes;
|
||||
protected List<String> subTypes;
|
||||
protected List<String> superTypes;
|
||||
protected ObjectColor color;
|
||||
protected ObjectColor frameColor;
|
||||
protected List<String> manaCost;
|
||||
protected int convertedManaCost;
|
||||
protected Rarity rarity;
|
||||
|
@ -159,7 +161,7 @@ public class CardView extends SimpleCardView {
|
|||
* @param storeZone if true the card zone will be set in the zone attribute.
|
||||
*/
|
||||
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null);
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor());
|
||||
// no information available for face down cards as long it's not a controlled face down morph card
|
||||
// TODO: Better handle this in Framework (but currently I'm not sure how to do it there) LevelX2
|
||||
boolean showFaceUp = true;
|
||||
|
@ -272,7 +274,7 @@ public class CardView extends SimpleCardView {
|
|||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = card.getCardType();
|
||||
this.subTypes = card.getSubtype();
|
||||
this.subTypes = card.getSubtype(game);
|
||||
this.superTypes = card.getSupertype();
|
||||
this.color = card.getColor(game);
|
||||
this.canTransform = card.canTransform();
|
||||
|
@ -291,6 +293,7 @@ public class CardView extends SimpleCardView {
|
|||
} else {
|
||||
// a created token
|
||||
this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode();
|
||||
this.tokenDescriptor = ((PermanentToken) card).getTokenDescriptor();
|
||||
}
|
||||
//
|
||||
// set code und card number for token copies to get the image
|
||||
|
@ -329,10 +332,16 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Frame color
|
||||
this.frameColor = card.getFrameColor(game);
|
||||
|
||||
// Get starting loyalty
|
||||
this.startingLoyalty = "" + card.getStartingLoyalty();
|
||||
}
|
||||
|
||||
public CardView(MageObject object) {
|
||||
super(object.getId(), "", "0", false, "", true);
|
||||
super(object.getId(), "", "0", false, "", true, "");
|
||||
this.name = object.getName();
|
||||
this.displayName = object.getName();
|
||||
if (object instanceof Permanent) {
|
||||
|
@ -346,7 +355,7 @@ public class CardView extends SimpleCardView {
|
|||
this.loyalty = "";
|
||||
}
|
||||
this.cardTypes = object.getCardType();
|
||||
this.subTypes = object.getSubtype();
|
||||
this.subTypes = object.getSubtype(null);
|
||||
this.superTypes = object.getSupertype();
|
||||
this.color = object.getColor(null);
|
||||
this.manaCost = object.getManaCost().getSymbols();
|
||||
|
@ -373,10 +382,14 @@ public class CardView extends SimpleCardView {
|
|||
this.expansionSetCode = stackAbility.getExpansionSetCode();
|
||||
}
|
||||
}
|
||||
// Frame color
|
||||
this.frameColor = object.getFrameColor(null);
|
||||
// Starting loyalty. Must be extracted from an ability
|
||||
this.startingLoyalty = "" + object.getStartingLoyalty();
|
||||
}
|
||||
|
||||
protected CardView() {
|
||||
super(null, "", "0", false, "", true);
|
||||
super(null, "", "0", false, "", true, "");
|
||||
}
|
||||
|
||||
public CardView(EmblemView emblem) {
|
||||
|
@ -393,7 +406,7 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
public CardView(boolean empty) {
|
||||
super(null, "", "0", false, "");
|
||||
super(null, "", "0", false, "", "");
|
||||
if (!empty) {
|
||||
throw new IllegalArgumentException("Not supported.");
|
||||
}
|
||||
|
@ -407,10 +420,12 @@ public class CardView extends SimpleCardView {
|
|||
this.power = "";
|
||||
this.toughness = "";
|
||||
this.loyalty = "";
|
||||
this.startingLoyalty = "";
|
||||
this.cardTypes = new ArrayList<>();
|
||||
this.subTypes = new ArrayList<>();
|
||||
this.superTypes = new ArrayList<>();
|
||||
this.color = new ObjectColor();
|
||||
this.frameColor = new ObjectColor();
|
||||
this.manaCost = new ArrayList<>();
|
||||
this.convertedManaCost = 0;
|
||||
|
||||
|
@ -442,7 +457,7 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
CardView(Token token) {
|
||||
super(token.getId(), "", "0", false, "");
|
||||
super(token.getId(), "", "0", false, "", "");
|
||||
this.isToken = true;
|
||||
this.id = token.getId();
|
||||
this.name = token.getName();
|
||||
|
@ -451,10 +466,12 @@ public class CardView extends SimpleCardView {
|
|||
this.power = token.getPower().toString();
|
||||
this.toughness = token.getToughness().toString();
|
||||
this.loyalty = "";
|
||||
this.startingLoyalty = "";
|
||||
this.cardTypes = token.getCardType();
|
||||
this.subTypes = token.getSubtype();
|
||||
this.subTypes = token.getSubtype(null);
|
||||
this.superTypes = token.getSupertype();
|
||||
this.color = token.getColor(null);
|
||||
this.frameColor = token.getFrameColor(null);
|
||||
this.manaCost = token.getManaCost().getSymbols();
|
||||
this.rarity = Rarity.NA;
|
||||
this.type = token.getTokenType();
|
||||
|
@ -518,6 +535,10 @@ public class CardView extends SimpleCardView {
|
|||
return loyalty;
|
||||
}
|
||||
|
||||
public String getStartingLoyalty() {
|
||||
return startingLoyalty;
|
||||
}
|
||||
|
||||
public List<CardType> getCardTypes() {
|
||||
return cardTypes;
|
||||
}
|
||||
|
@ -534,6 +555,10 @@ public class CardView extends SimpleCardView {
|
|||
return color;
|
||||
}
|
||||
|
||||
public ObjectColor getFrameColor() {
|
||||
return frameColor;
|
||||
}
|
||||
|
||||
public List<String> getManaCost() {
|
||||
return manaCost;
|
||||
}
|
||||
|
@ -765,3 +790,4 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -53,4 +53,21 @@ public class CounterView implements Serializable {
|
|||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(other instanceof CounterView)) {
|
||||
return false;
|
||||
}
|
||||
CounterView oth = (CounterView)other;
|
||||
return
|
||||
(count == oth.count) &&
|
||||
(name.equals(oth.name));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class LookedAtView implements Serializable {
|
|||
public LookedAtView(String name, Cards cards, Game game) {
|
||||
this.name = name;
|
||||
for (Card card: cards.getCards(game)) {
|
||||
this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode()));
|
||||
this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), card.getTokenDescriptor()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ public class PermanentView extends CardView {
|
|||
original = new CardView(((PermanentToken) permanent).getToken());
|
||||
original.expansionSetCode = permanent.getExpansionSetCode();
|
||||
tokenSetCode = original.getTokenSetCode();
|
||||
tokenDescriptor = original.getTokenDescriptor();
|
||||
} else {
|
||||
if (card != null) {
|
||||
// original may not be face down
|
||||
|
|
|
@ -39,16 +39,18 @@ public class SimpleCardView implements Serializable {
|
|||
protected UUID id;
|
||||
protected String expansionSetCode;
|
||||
protected String tokenSetCode;
|
||||
protected String tokenDescriptor;
|
||||
protected String cardNumber;
|
||||
protected boolean usesVariousArt;
|
||||
protected boolean gameObject;
|
||||
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode) {
|
||||
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false);
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) {
|
||||
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor);
|
||||
}
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject) {
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) {
|
||||
this.id = id;
|
||||
this.expansionSetCode = expansionSetCode;
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
this.cardNumber = cardNumber;
|
||||
this.usesVariousArt = usesVariousArt;
|
||||
this.tokenSetCode = tokenSetCode;
|
||||
|
@ -75,6 +77,10 @@ public class SimpleCardView implements Serializable {
|
|||
return tokenSetCode;
|
||||
}
|
||||
|
||||
public String getTokenDescriptor() {
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
public boolean isGameObject() {
|
||||
return gameObject;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ public class SimpleCardsView extends LinkedHashMap<UUID, SimpleCardView> {
|
|||
|
||||
public SimpleCardsView(Collection<Card> cards, boolean isGameObject) {
|
||||
for (Card card: cards) {
|
||||
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject));
|
||||
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject,
|
||||
card.getTokenDescriptor()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,12 +64,12 @@ public class StackAbilityView extends CardView {
|
|||
this.loyalty = "";
|
||||
|
||||
this.cardTypes = ability.getCardType();
|
||||
this.subTypes = ability.getSubtype();
|
||||
this.subTypes = ability.getSubtype(game);
|
||||
this.superTypes = ability.getSupertype();
|
||||
this.color = ability.getColor(game);
|
||||
this.manaCost = ability.getManaCost().getSymbols();
|
||||
this.cardTypes = ability.getCardType();
|
||||
this.subTypes = ability.getSubtype();
|
||||
this.subTypes = ability.getSubtype(game);
|
||||
this.superTypes = ability.getSupertype();
|
||||
this.color = ability.getColor(game);
|
||||
this.manaCost = ability.getManaCost().getSymbols();
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ArtificialScoringSystem {
|
|||
//score + =cardDefinition.getActivations().size()*50;
|
||||
//score += cardDefinition.getManaActivations().size()*80;
|
||||
} else {
|
||||
if (permanent.getSubtype().contains("Equipment")) {
|
||||
if (permanent.getSubtype(game).contains("Equipment")) {
|
||||
score += 100;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1340,9 +1340,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (Permanent permanent : game.getBattlefield().getActivePermanents(this.getId(), game)) {
|
||||
if (game.getOpponents(this.getId()).contains(permanent.getControllerId())
|
||||
&& permanent.getCardType().contains(CardType.CREATURE)
|
||||
&& permanent.getSubtype().size() > 0) {
|
||||
if (choice.getChoices().contains(permanent.getSubtype().get(0))) {
|
||||
choice.setChoice(permanent.getSubtype().get(0));
|
||||
&& permanent.getSubtype(game).size() > 0) {
|
||||
if (choice.getChoices().contains(permanent.getSubtype(game).get(0))) {
|
||||
choice.setChoice(permanent.getSubtype(game).get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1352,9 +1352,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (UUID opponentId : game.getOpponents(this.getId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
for (Card card : opponent.getGraveyard().getCards(game)) {
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype().get(0))) {
|
||||
choice.setChoice(card.getSubtype().get(0));
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype(game).get(0))) {
|
||||
choice.setChoice(card.getSubtype(game).get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1368,9 +1368,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
// choose a creature type of hand or library
|
||||
for (UUID cardId : this.getHand()) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype().get(0))) {
|
||||
choice.setChoice(card.getSubtype().get(0));
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype(game).get(0))) {
|
||||
choice.setChoice(card.getSubtype(game).get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1378,9 +1378,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
if (!choice.isChosen()) {
|
||||
for (UUID cardId : this.getLibrary().getCardList()) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype().get(0))) {
|
||||
choice.setChoice(card.getSubtype().get(0));
|
||||
if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) {
|
||||
if (choice.getChoices().contains(card.getSubtype(game).get(0))) {
|
||||
choice.setChoice(card.getSubtype(game).get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import java.io.InputStream;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class responsible for reading ratings from resources and rating gived cards.
|
||||
* Class responsible for reading ratings from resources and rating given cards.
|
||||
* Based on card relative ratings from resources and card parameters.
|
||||
*
|
||||
* @author nantuko
|
||||
|
@ -61,9 +61,9 @@ public class RateCard {
|
|||
type = 15;
|
||||
} else if (card.getCardType().contains(CardType.CREATURE)) {
|
||||
type = 10;
|
||||
} else if (card.getSubtype().contains("Equipment")) {
|
||||
} else if (card.getSubtype(null).contains("Equipment")) {
|
||||
type = 8;
|
||||
} else if (card.getSubtype().contains("Aura")) {
|
||||
} else if (card.getSubtype(null).contains("Aura")) {
|
||||
type = 5;
|
||||
} else if (card.getCardType().contains(CardType.INSTANT)) {
|
||||
type = 7;
|
||||
|
@ -78,7 +78,7 @@ public class RateCard {
|
|||
}
|
||||
|
||||
private static int isRemoval(Card card) {
|
||||
if (card.getSubtype().contains("Aura") || card.getCardType().contains(CardType.INSTANT)
|
||||
if (card.getSubtype(null).contains("Aura") || card.getCardType().contains(CardType.INSTANT)
|
||||
|| card.getCardType().contains(CardType.SORCERY)) {
|
||||
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
|
|
|
@ -37,7 +37,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.keyword.FearAbility;
|
||||
|
@ -98,7 +98,7 @@ class DamageOpponentsEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
DynamicValue amount = new CountersCount(CounterType.CHARGE);
|
||||
DynamicValue amount = new CountersSourceCount(CounterType.CHARGE);
|
||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
|
|
|
@ -34,7 +34,7 @@ import mage.abilities.costs.common.PayLifeCost;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.MultipliedValue;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
|
@ -61,7 +61,7 @@ public class Tornado extends CardImpl {
|
|||
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{G}")));
|
||||
// {2}{G}, Pay 3 life for each velocity counter on Tornado: Destroy target permanent and put a velocity counter on Tornado. Activate this ability only once each turn.
|
||||
Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{2}{G}"));
|
||||
DynamicValue lifeToPayAmount = new MultipliedValue(new CountersCount(CounterType.VELOCITY), 3);
|
||||
DynamicValue lifeToPayAmount = new MultipliedValue(new CountersSourceCount(CounterType.VELOCITY), 3);
|
||||
ability.addCost(new PayLifeCost(lifeToPayAmount, "3 life for each velocity counter on {source}"));
|
||||
ability.addTarget(new TargetPermanent());
|
||||
Effect effect = new AddCountersSourceEffect(CounterType.VELOCITY.createInstance());
|
||||
|
|
|
@ -120,7 +120,7 @@ class CantBeEnchantedAbility extends StaticAbility {
|
|||
|
||||
public boolean canTarget(MageObject source, Game game) {
|
||||
if (source.getCardType().contains(CardType.ENCHANTMENT) &&
|
||||
source.hasSubtype("Aura")) {
|
||||
source.hasSubtype("Aura", game)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -96,7 +96,7 @@ class PreventDamageToSourceBySubtypeEffect extends PreventAllDamageToSourceEffec
|
|||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (super.applies(event, source, game)) {
|
||||
if (game.getObject(event.getSourceId()).hasSubtype(subtype)){
|
||||
if (game.getObject(event.getSourceId()).hasSubtype(subtype, game)){
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ class GuardianBeastConditionalEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
|
||||
StackObject spell = game.getStack().getStackObject(event.getSourceId());
|
||||
if (event.getType() == EventType.LOSE_CONTROL || event.getType() == EventType.ATTACH || event.getType() == EventType.TARGET && spell != null && spell.getCardType().contains(CardType.ENCHANTMENT) && spell.getSubtype().contains("Aura")) {
|
||||
if (event.getType() == EventType.LOSE_CONTROL || event.getType() == EventType.ATTACH || event.getType() == EventType.TARGET && spell != null && spell.getCardType().contains(CardType.ENCHANTMENT) && spell.getSubtype(game).contains("Aura")) {
|
||||
for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
if (perm != null && perm.getId() == targetPermanent.getId() && !perm.getCardType().contains(CardType.CREATURE)) {
|
||||
return true;
|
||||
|
|
|
@ -142,7 +142,7 @@ class CavernOfSoulsManaCondition extends CreatureCastManaCondition {
|
|||
if (super.apply(game, source)) {
|
||||
// check: ... of the chosen type
|
||||
MageObject object = game.getObject(source.getSourceId());
|
||||
if (creatureType != null && object.hasSubtype(creatureType)) {
|
||||
if (creatureType != null && object.hasSubtype(creatureType, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class DefyDeathEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null && permanent.hasSubtype("Angel")) {
|
||||
if (permanent != null && permanent.hasSubtype("Angel", game)) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(2), game);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ class DescendantsPathEffect extends OneShotEffect {
|
|||
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
|
||||
boolean found = false;
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
|
||||
if (CardUtil.shareSubtypes(card, permanent)) {
|
||||
if (CardUtil.shareSubtypes(card, permanent, game)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ class DreadSlaverContiniousEffect extends ContinuousEffectImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
creature.getSubtype().add("Zombie");
|
||||
creature.getSubtype(game).add("Zombie");
|
||||
}
|
||||
break;
|
||||
case ColorChangingEffects_5:
|
||||
|
|
|
@ -99,7 +99,7 @@ class EatenBySpidersEffect extends OneShotEffect {
|
|||
|
||||
for (UUID attachmentId : attachments) {
|
||||
Permanent attachment = game.getPermanent(attachmentId);
|
||||
if (attachment.hasSubtype("Equipment")) {
|
||||
if (attachment.hasSubtype("Equipment", game)) {
|
||||
attachment.destroy(source.getSourceId(), game, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -62,7 +62,7 @@ public class FalkenrathExterminator extends CardImpl {
|
|||
// Whenever Falkenrath Exterminator deals combat damage to a player, put a +1/+1 counter on it.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false));
|
||||
// {2}{R}: Falkenrath Exterminator deals damage to target creature equal to the number of +1/+1 counters on Falkenrath Exterminator.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.P1P1)), new ManaCostsImpl("{2}{R}"));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), new ManaCostsImpl("{2}{R}"));
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ class HeraldOfWarCostReductionEffect extends CostModificationEffectImpl {
|
|||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
||||
Card sourceCard = game.getCard(abilityToModify.getSourceId());
|
||||
if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype("Angel") || sourceCard.hasSubtype("Human"))) {
|
||||
if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype("Angel", game) || sourceCard.hasSubtype("Human", game))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ class HolyJusticiarEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game.getPermanent(source.getFirstTarget());
|
||||
if (creature != null) {
|
||||
if (creature.hasSubtype("Zombie")) {
|
||||
if (creature.hasSubtype("Zombie", game)) {
|
||||
creature.tap(game);
|
||||
creature.moveToExile(source.getSourceId(), creature.getName(), source.getSourceId(), game);
|
||||
} else {
|
||||
|
|
|
@ -146,7 +146,7 @@ class AkoumHellkiteDamageEffect extends OneShotEffect {
|
|||
Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
Player player = game.getPlayer(source.getFirstTarget());
|
||||
if (land != null && player != null) {
|
||||
if (land.hasSubtype("Mountain")) {
|
||||
if (land.hasSubtype("Mountain", game)) {
|
||||
player.damage(2, source.getSourceId(), game, false, true);
|
||||
} else {
|
||||
player.damage(1, source.getSourceId(), game, false, true);
|
||||
|
@ -155,7 +155,7 @@ class AkoumHellkiteDamageEffect extends OneShotEffect {
|
|||
}
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (land != null && permanent != null) {
|
||||
if (land.hasSubtype("Mountain")) {
|
||||
if (land.hasSubtype("Mountain", game)) {
|
||||
permanent.damage(2, source.getSourceId(), game, false, true);
|
||||
} else {
|
||||
permanent.damage(1, source.getSourceId(), game, false, true);
|
||||
|
|
|
@ -109,7 +109,7 @@ class EmeriaShepherdReturnToHandTargetEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
Zone toZone = Zone.HAND;
|
||||
if (triggeringLand.getSubtype().contains("Plains")
|
||||
if (triggeringLand.getSubtype(game).contains("Plains")
|
||||
&& controller.chooseUse(Outcome.PutCardInPlay, "Put the card to battlefield instead?", source, game)) {
|
||||
toZone = Zone.BATTLEFIELD;
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ class GuardianOfTazeemEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
|
||||
if (land != null && targetCreature != null && land.hasSubtype("Island")) {
|
||||
if (land != null && targetCreature != null && land.hasSubtype("Island", game)) {
|
||||
ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect("that creature");
|
||||
effect.setTargetPointer(new FixedTarget(targetCreature, game));
|
||||
game.addEffect(effect, source);
|
||||
|
|
|
@ -96,7 +96,7 @@ class GuulDrazOverseerEffect extends OneShotEffect {
|
|||
Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
if (controller != null && land != null) {
|
||||
int boost = 1;
|
||||
if (land.getSubtype().contains("Swamp")) {
|
||||
if (land.getSubtype(game).contains("Swamp")) {
|
||||
boost = 2;
|
||||
}
|
||||
game.addEffect(new BoostControlledEffect(boost, 0, Duration.EndOfTurn, true), source);
|
||||
|
|
|
@ -144,7 +144,7 @@ class OranRiefHydraEffect extends OneShotEffect {
|
|||
Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (land != null && sourcePermanent != null) {
|
||||
if (land.hasSubtype("Forest")) {
|
||||
if (land.hasSubtype("Forest", game)) {
|
||||
sourcePermanent.addCounters(CounterType.P1P1.createInstance(2), game);
|
||||
} else {
|
||||
sourcePermanent.addCounters(CounterType.P1P1.createInstance(), game);
|
||||
|
|
|
@ -34,7 +34,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.costs.common.RemoveVariableCountersSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.mana.DynamicManaAbility;
|
||||
|
@ -68,7 +68,7 @@ public class PetalmaneBaku extends CardImpl {
|
|||
new RemovedCountersForCostValue(),
|
||||
new ManaCostsImpl<>("{1}"),
|
||||
"Add X mana of any one color to your mana pool",
|
||||
true, new CountersCount(CounterType.KI));
|
||||
true, new CountersSourceCount(CounterType.KI));
|
||||
ability.addCost(new RemoveVariableCountersSourceCost(CounterType.KI.createInstance(),
|
||||
"Remove X ki counters from {this}"));
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -208,7 +208,7 @@ class ShurikenControlEffect extends OneShotEffect {
|
|||
if (equipment != null) {
|
||||
Permanent creature = game.getPermanent(source.getSourceId());
|
||||
if (creature != null) {
|
||||
if (!creature.hasSubtype("Ninja")) {
|
||||
if (!creature.hasSubtype("Ninja", game)) {
|
||||
Permanent damagedCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
||||
if (damagedCreature == null) {
|
||||
damagedCreature = (Permanent) game.getLastKnownInformation(this.getTargetPointer().getFirst(game, source), Zone.BATTLEFIELD);
|
||||
|
|
|
@ -99,7 +99,7 @@ public class SlumberingTora extends CardImpl {
|
|||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
permanent.getSubtype().add("Cat");
|
||||
permanent.getSubtype(game).add("Cat");
|
||||
}
|
||||
break;
|
||||
case PTChangingEffects_7:
|
||||
|
|
|
@ -93,7 +93,7 @@ public class UncheckedGrowth extends CardImpl {
|
|||
int affectedTargets = 0;
|
||||
for (UUID permanentId : targetPointer.getTargets(game, source)) {
|
||||
Permanent permanent = game.getPermanent(permanentId);
|
||||
if (permanent != null && permanent.hasSubtype("Spirit")) {
|
||||
if (permanent != null && permanent.hasSubtype("Spirit", game)) {
|
||||
permanent.addAbility(TrampleAbility.getInstance(), game);
|
||||
affectedTargets++;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class EverflameEidolonEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (sourceObject != null) {
|
||||
if (sourceObject.getSubtype().contains("Aura")) {
|
||||
if (sourceObject.getSubtype(game).contains("Aura")) {
|
||||
new BoostEnchantedEffect(1, 0, Duration.EndOfTurn).apply(game, source);
|
||||
} else {
|
||||
game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source);
|
||||
|
|
|
@ -35,7 +35,7 @@ import mage.abilities.common.SimpleActivatedAbility;
|
|||
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.dynamicvalue.common.SignInversionDynamicValue;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
|
@ -75,7 +75,7 @@ public class BloodthirstyOgre extends CardImpl {
|
|||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.DEVOTION.createInstance()),new TapSourceCost()));
|
||||
|
||||
// {T}: Target creature gets -X/-X until end of turn, where X is the number of devotion counters on Bloodthirsty Ogre. Activate this ability only if you control a Demon.
|
||||
DynamicValue devotionCounters = new SignInversionDynamicValue(new CountersCount(CounterType.DEVOTION));
|
||||
DynamicValue devotionCounters = new SignInversionDynamicValue(new CountersSourceCount(CounterType.DEVOTION));
|
||||
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD,
|
||||
new BoostTargetEffect(devotionCounters,devotionCounters, Duration.EndOfTurn, true),
|
||||
new TapSourceCost(),
|
||||
|
|
|
@ -97,7 +97,7 @@ class ZuberasDiedWatcher extends Watcher {
|
|||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) {
|
||||
MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||
if (card != null && card.hasSubtype("Zubera")) {
|
||||
if (card != null && card.hasSubtype("Zubera", game)) {
|
||||
zuberasDiedThisTurn++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,9 @@ package mage.sets.championsofkamigawa;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttachableToRestrictedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -47,6 +47,7 @@ import mage.filter.common.FilterCreaturePermanent;
|
|||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
@ -56,7 +57,7 @@ import mage.util.CardUtil;
|
|||
*/
|
||||
public class KondasBanner extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent legendaryFilter = new FilterControlledCreaturePermanent("Legendary creatures");
|
||||
private static final FilterControlledCreaturePermanent legendaryFilter = new FilterControlledCreaturePermanent("legendary creatures");
|
||||
|
||||
static {
|
||||
legendaryFilter.add(new SupertypePredicate("Legendary"));
|
||||
|
@ -68,8 +69,9 @@ public class KondasBanner extends CardImpl {
|
|||
this.supertype.add("Legendary");
|
||||
this.subtype.add("Equipment");
|
||||
|
||||
Target target = new TargetControlledCreaturePermanent(1, 1, legendaryFilter, false);
|
||||
// Konda's Banner can be attached only to a legendary creature.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this} can be attached only to a legendary creature")));
|
||||
this.addAbility(new AttachableToRestrictedAbility(target));
|
||||
|
||||
// Creatures that share a color with equipped creature get +1/+1.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KondasBannerColorBoostEffect()));
|
||||
|
@ -78,10 +80,7 @@ public class KondasBanner extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KondasBannerTypeBoostEffect()));
|
||||
|
||||
// Equip {2}
|
||||
this.addAbility(new EquipAbility(
|
||||
Outcome.AddAbility,
|
||||
new GenericManaCost(2),
|
||||
new TargetControlledCreaturePermanent(1, 1, legendaryFilter, false)));
|
||||
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), target));
|
||||
|
||||
}
|
||||
|
||||
|
@ -116,7 +115,7 @@ class KondasBannerTypeBoostEffect extends BoostAllEffect {
|
|||
Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo());
|
||||
if (equipedCreature != null) {
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (CardUtil.shareSubtypes(perm, equipedCreature)) {
|
||||
if (CardUtil.shareSubtypes(perm, equipedCreature, game)) {
|
||||
perm.addPower(power.calculate(game, source, this));
|
||||
perm.addToughness(toughness.calculate(game, source, this));
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import mage.abilities.common.EntersBattlefieldAbility;
|
|||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -56,7 +56,7 @@ public class OrochiHatchery extends CardImpl {
|
|||
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance())));
|
||||
|
||||
// {5}, {T}: Put a 1/1 green Snake creature token onto the battlefield for each charge counter on Orochi Hatchery.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SnakeToken(), new CountersCount(CounterType.CHARGE)), new GenericManaCost(5));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SnakeToken(), new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(5));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ public class RyuseiTheFallingStar extends CardImpl {
|
|||
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
|
||||
}
|
||||
|
||||
public RyuseiTheFallingStar(UUID ownerID) {
|
||||
super(ownerID, 185, "Ryusei, the Falling Star", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}");
|
||||
public RyuseiTheFallingStar(UUID ownerId) {
|
||||
super(ownerId, 185, "Ryusei, the Falling Star", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}");
|
||||
this.expansionSetCode = "CHK";
|
||||
this.supertype.add("Legendary");
|
||||
this.subtype.add("Dragon");
|
||||
|
|
|
@ -106,7 +106,7 @@ class SeshiroTheAnointedAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event;
|
||||
Permanent p = game.getPermanent(event.getSourceId());
|
||||
if (damageEvent.isCombatDamage() && p != null && p.hasSubtype("Snake") && p.getControllerId().equals(controllerId)) {
|
||||
if (damageEvent.isCombatDamage() && p != null && p.hasSubtype("Snake", game) && p.getControllerId().equals(controllerId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -117,7 +117,7 @@ class SosukeSonOfSeshiroTriggeredAbility extends TriggeredAbilityImpl {
|
|||
Permanent sourceCreature = game.getPermanent(event.getSourceId());
|
||||
Permanent targetCreature = game.getPermanent(event.getTargetId());
|
||||
if (sourceCreature != null && sourceCreature.getControllerId().equals(this.getControllerId())
|
||||
&& targetCreature != null && sourceCreature.hasSubtype("Warrior")) {
|
||||
&& targetCreature != null && sourceCreature.hasSubtype("Warrior", game)) {
|
||||
this.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId()));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ class HaakonPlayKnightsFromGraveyardEffect extends AsThoughEffectImpl {
|
|||
if (affectedControllerId.equals(source.getControllerId())) {
|
||||
Card knightToCast = game.getCard(objectId);
|
||||
if (knightToCast != null
|
||||
&& knightToCast.hasSubtype("Knight")
|
||||
&& knightToCast.hasSubtype("Knight", game)
|
||||
&& knightToCast.getOwnerId().equals(source.getControllerId())
|
||||
&& game.getState().getZone(objectId) == Zone.GRAVEYARD) {
|
||||
return true;
|
||||
|
|
|
@ -110,7 +110,7 @@ class JokulmorderTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent land = game.getPermanent(event.getTargetId());
|
||||
return land.getSubtype().contains("Island")
|
||||
return land.getSubtype(game).contains("Island")
|
||||
&& land.getControllerId().equals(this.controllerId);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,11 +110,11 @@ class TargetCardInLibrarySharingLandType extends TargetCardInLibrary {
|
|||
if (landCard != null) {
|
||||
if (landTypes == null) {
|
||||
landTypes = new HashSet<>();
|
||||
landTypes.addAll(landCard.getSubtype());
|
||||
landTypes.addAll(landCard.getSubtype(game));
|
||||
} else {
|
||||
for (Iterator<String> iterator = landTypes.iterator(); iterator.hasNext();) {
|
||||
String next = iterator.next();
|
||||
if (!landCard.getSubtype().contains(next)) {
|
||||
if (!landCard.getSubtype(game).contains(next)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ class TargetCardInLibrarySharingLandType extends TargetCardInLibrary {
|
|||
if (card != null && landTypes != null) {
|
||||
for (Iterator<String> iterator = landTypes.iterator(); iterator.hasNext();) {
|
||||
String next = iterator.next();
|
||||
if (card.getSubtype().contains(next)) {
|
||||
if (card.getSubtype(game).contains(next)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,8 +158,8 @@ class NecromanticSelectionContinuousEffect extends ContinuousEffectImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (!creature.getSubtype().contains("Zombie")) {
|
||||
creature.getSubtype().add("Zombie");
|
||||
if (!creature.getSubtype(game).contains("Zombie")) {
|
||||
creature.getSubtype(game).add("Zombie");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -121,8 +121,8 @@ class BecomesColorlessForestLandEffect extends ContinuousEffectImpl {
|
|||
case TypeChangingEffects_4:
|
||||
permanent.getCardType().clear();
|
||||
permanent.getCardType().add(CardType.LAND);
|
||||
permanent.getSubtype().clear();
|
||||
permanent.getSubtype().add("Forest");
|
||||
permanent.getSubtype(game).clear();
|
||||
permanent.getSubtype(game).add("Forest");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -97,7 +97,7 @@ class KasetoEffect extends OneShotEffect {
|
|||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
game.addEffect(new CantBeBlockedTargetEffect(Duration.EndOfTurn), source);
|
||||
if (permanent.getSubtype().contains("Snake")) {
|
||||
if (permanent.getSubtype(game).contains("Snake")) {
|
||||
game.addEffect(new BoostTargetEffect(2,2,Duration.EndOfTurn), source);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -117,8 +117,8 @@ public class DragonsoulKnight extends CardImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
permanent.getSubtype().clear();
|
||||
permanent.getSubtype().add("Dragon");
|
||||
permanent.getSubtype(game).clear();
|
||||
permanent.getSubtype(game).add("Dragon");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
|||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -71,7 +71,7 @@ public class GoblinRazerunners extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// At the beginning of your end step, you may have Goblin Razerunners deal damage equal to the number of +1/+1 counters on it to target player.
|
||||
ability = new BeginningOfYourEndStepTriggeredAbility(new DamageTargetEffect(new CountersCount(CounterType.P1P1)), true);
|
||||
ability = new BeginningOfYourEndStepTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), true);
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -117,8 +117,8 @@ public class ParagonOfTheAmesha extends CardImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
permanent.getSubtype().clear();
|
||||
permanent.getSubtype().add("Angel");
|
||||
permanent.getSubtype(game).clear();
|
||||
permanent.getSubtype(game).add("Angel");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ class IgnitionTeamToken extends Token {
|
|||
public IgnitionTeamToken() {
|
||||
super("", "4/4 red Elemental creature");
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.getSubtype().add("Elemental");
|
||||
this.getSubtype(null).add("Elemental");
|
||||
this.color.setRed(true);
|
||||
|
||||
this.power = new MageInt(4);
|
||||
|
|
|
@ -103,7 +103,7 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((ZoneChangeEvent) event).isDiesEvent()) {
|
||||
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||
if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human")) {
|
||||
if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human", game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ class CallToTheKindredEffect extends OneShotEffect {
|
|||
if (!creature.getAbilities().contains(ChangelingAbility.getInstance())) {
|
||||
StringBuilder sb = new StringBuilder("creature card with at least one subtype from: ");
|
||||
ArrayList<Predicate<MageObject>> subtypes = new ArrayList<>();
|
||||
for (String subtype : creature.getSubtype()) {
|
||||
for (String subtype : creature.getSubtype(game)) {
|
||||
subtypes.add(new SubtypePredicate(subtype));
|
||||
sb.append(subtype).append(", ");
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class CurseOfMisfortunesEffect extends OneShotEffect {
|
|||
// get the names of attached Curses
|
||||
for (UUID attachmentId: targetPlayer.getAttachments()) {
|
||||
Permanent attachment = game.getPermanent(attachmentId);
|
||||
if (attachment != null && attachment.getSubtype().contains("Curse")) {
|
||||
if (attachment != null && attachment.getSubtype(game).contains("Curse")) {
|
||||
filter.add(Predicates.not(new NamePredicate(attachment.getName())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ class CursesAttachedCount implements DynamicValue {
|
|||
if (player != null) {
|
||||
for (UUID attachmentId: player.getAttachments()) {
|
||||
Permanent attachment = game.getPermanent(attachmentId);
|
||||
if (attachment != null && attachment.getSubtype().contains("Curse"))
|
||||
if (attachment != null && attachment.getSubtype(game).contains("Curse"))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class DeathsCaressEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent creature = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD);
|
||||
if (player != null && creature != null && creature.hasSubtype("Human")) {
|
||||
if (player != null && creature != null && creature.hasSubtype("Human", game)) {
|
||||
player.gainLife(creature.getToughness().getValue(), game);
|
||||
return true;
|
||||
}
|
||||
|
|