* Fixed that second or higher level of attachments was not shown correctly on battlefield (fixes #892 fixes #4539 fixes #785 fixes #258).

This commit is contained in:
LevelX2 2018-04-08 20:38:26 +02:00
parent ff14a26f24
commit ecbe7e68a6
6 changed files with 249 additions and 83 deletions

View file

@ -33,6 +33,25 @@
*/
package mage.client.game;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import mage.cards.MagePermanent;
import mage.client.cards.BigCard;
import mage.client.cards.Permanent;
@ -45,16 +64,6 @@ import mage.client.util.layout.impl.OldCardLayoutStrategy;
import mage.view.CounterView;
import mage.view.PermanentView;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.*;
import java.util.List;
import java.util.Map.Entry;
/**
*
* @author BetaSteward_at_googlemail.com
@ -155,12 +164,13 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
} else {
if (!changed) {
changed = oldMagePermanent.getOriginalPermanent().isCreature() != permanent.isCreature();
// Check if there was a chnage in the permanets that are the permanent attached to
if (!changed) {
int s1 = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size();
int s2 = oldMagePermanent.getLinks().size();
if (s1 != s2) {
int attachments = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size();
int attachmentsBefore = oldMagePermanent.getLinks().size();
if (attachments != attachmentsBefore) {
changed = true;
} else if (s1 > 0) {
} else if (attachments > 0) {
Set<UUID> attachmentIds = new HashSet<>(permanent.getAttachments());
for (MagePermanent magePermanent : oldMagePermanent.getLinks()) {
if (!attachmentIds.contains(magePermanent.getOriginalPermanent().getId())) {
@ -174,14 +184,16 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
}
}
}
// Check if permanents it now attached to another or no permanent
if (!changed) {
UUID u1 = oldMagePermanent.getOriginalPermanent().getAttachedTo();
UUID u2 = permanent.getAttachedTo();
if (u1 == null && u2 != null || u2 == null && u1 != null
|| (u1 != null && !u1.equals(u2))) {
UUID attachedToIdBefore = oldMagePermanent.getOriginalPermanent().getAttachedTo();
UUID attachedToId = permanent.getAttachedTo();
if (attachedToIdBefore == null && attachedToId != null || attachedToId == null && attachedToIdBefore != null
|| (attachedToIdBefore != null && !attachedToIdBefore.equals(attachedToId))) {
changed = true;
}
}
// Check for changes in the counters of the permanent
if (!changed) {
List<CounterView> counters1 = oldMagePermanent.getOriginalPermanent().getCounters();
List<CounterView> counters2 = permanent.getCounters();

View file

@ -2,7 +2,6 @@ package mage.client.plugins;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import javax.swing.*;
@ -33,7 +32,7 @@ public interface MagePlugins {
boolean isCounterPluginLoaded();
int sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> permanents, boolean topRow);
int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> permanents, boolean topRow);
void downloadSymbols();

View file

@ -3,12 +3,10 @@ package mage.client.plugins.impl;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.swing.JComponent;
import mage.cards.MageCard;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
@ -30,9 +28,8 @@ import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.impl.PluginManagerFactory;
import org.apache.log4j.Logger;
import org.mage.plugins.card.CardPluginImpl;
import org.mage.plugins.theme.ThemePluginImpl;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
import org.mage.plugins.theme.ThemePluginImpl;
public enum Plugins implements MagePlugins {
instance;
@ -47,7 +44,6 @@ public enum Plugins implements MagePlugins {
private static final MageActionCallback mageActionCallback = new MageActionCallback();
private final Map<String, String> sortingOptions = new HashMap<>();
@Override
public void loadPlugins() {
@ -125,7 +121,7 @@ public enum Plugins implements MagePlugins {
}
@Override
public int sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> permanents, boolean topRow) {
public int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> permanents, boolean topRow) {
if (this.cardPlugin != null) {
return this.cardPlugin.sortPermanents(ui, permanents, PreferencesDialog.getCachedValue("nonLandPermanentsInOnePile", "false").equals("true"), topRow);
}

View file

@ -1,6 +1,7 @@
package mage.client.util.layout.impl;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Map;
import java.util.UUID;
@ -30,72 +31,167 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
*/
private static final int ATTACHMENT_MIN_DY_OFFSET = 12;
final class AttachmentLayoutInfos {
private int columns;
private int attachments;
public AttachmentLayoutInfos(int columns, int attachments) {
this.columns = columns;
this.attachments = attachments;
}
public int getColumns() {
return columns;
}
public int getAttachments() {
return attachments;
}
public void increaseAttachments() {
attachments++;
}
public void increaseColumns() {
columns++;
}
}
@Override
public void doLayout(BattlefieldPanel battlefieldPanel, int width) {
Map<UUID, MagePermanent> permanents = battlefieldPanel.getPermanents();
JLayeredPane jPanel = battlefieldPanel.getMainPanel();
JLayeredPane mainPanel = battlefieldPanel.getMainPanel();
int height = Plugins.instance.sortPermanents(battlefieldPanel.getUiComponentsList(), permanents.values(), battlefieldPanel.isTopPanelBattlefield());
jPanel.setPreferredSize(new Dimension(width - 30, height));
// does the basic layout of rows and colums
int height = Plugins.instance.sortPermanents(battlefieldPanel.getUiComponentsList(), permanents, battlefieldPanel.isTopPanelBattlefield());
mainPanel.setPreferredSize(new Dimension(width - 30, height));
for (PermanentView permanent : battlefieldPanel.getBattlefield().values()) {
if (permanent.getAttachments() != null) {
groupAttachments(battlefieldPanel, jPanel, permanents, permanent);
if (permanent.getAttachments() != null && !permanent.isAttachedTo()) { // Layout only permanents that are not attached to other permanents itself
groupAttachments(battlefieldPanel, mainPanel, permanents, permanent);
}
}
}
private void groupAttachments(JLayeredPane jLayeredPane, JLayeredPane jPanel, Map<UUID, MagePermanent> permanents, PermanentView permanent) {
MagePermanent perm = permanents.get(permanent.getId());
if (perm == null) {
private void groupAttachments(BattlefieldPanel battlefieldPanel, JLayeredPane mainPanel, Map<UUID, MagePermanent> permanents, PermanentView permanentWithAttachmentsView) {
MagePermanent permWithAttachments = permanents.get(permanentWithAttachmentsView.getId());
if (permWithAttachments == null) {
return;
}
int position = jLayeredPane.getPosition(perm);
perm.getLinks().clear();
Rectangle rectangleBaseCard = perm.getBounds();
// Calculate how many vertical columns are needed and number of attachements
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(0, battlefieldPanel, permanents, permanentWithAttachmentsView);
int position = battlefieldPanel.getPosition(permWithAttachments); // relative position within the layer
// permWithAttachments.getLinks().clear();
Rectangle rectangleBaseCard = permWithAttachments.getBounds();
if (!Plugins.instance.isCardPluginLoaded()) {
for (UUID attachmentId : permanent.getAttachments()) {
permWithAttachments.getLinks().clear();
for (UUID attachmentId : permanentWithAttachmentsView.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
perm.getLinks().add(link);
permWithAttachments.getLinks().add(link);
rectangleBaseCard.translate(20, 20);
link.setBounds(rectangleBaseCard);
jLayeredPane.setPosition(link, ++position);
battlefieldPanel.setPosition(link, ++position);
}
}
} else {
int index = permanent.getAttachments().size();
for (UUID attachmentId : permanent.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
link.setBounds(rectangleBaseCard);
perm.getLinks().add(link);
int dyOffset = Math.max(perm.getHeight() / 10, ATTACHMENT_MIN_DY_OFFSET);
if (index == 1) {
rectangleBaseCard.translate(Math.max(perm.getWidth() / 10, ATTACHMENTS_MIN_DX_OFFSET), dyOffset); // do it once
} else {
rectangleBaseCard.translate(0, dyOffset);
}
perm.setBounds(rectangleBaseCard);
jLayeredPane.moveToFront(link);
jLayeredPane.moveToFront(perm);
jPanel.setComponentZOrder(link, index);
index--;
}
}
jPanel.setComponentZOrder(perm, index);
layoutAttachements(rectangleBaseCard.getX(), attachmentLayoutInfos.getColumns(),
attachmentLayoutInfos.getAttachments(), permanentWithAttachmentsView, permanents, battlefieldPanel, mainPanel, rectangleBaseCard);
mainPanel.setComponentZOrder(permWithAttachments, 0);
}
}
private void layoutAttachements(double baseX, // basic x position
int maxCul, // number of attachments levels
int ZOrder,
PermanentView permanentWithAttachmentsView,
Map<UUID, MagePermanent> permanents,
BattlefieldPanel battlefieldPanel,
JLayeredPane mainPanel,
Rectangle rectangleBaseCard) {
MagePermanent permWithAttachments = permanents.get(permanentWithAttachmentsView.getId());
if (permWithAttachments == null) {
return;
}
int col = getVerticalCul(permanentWithAttachmentsView, battlefieldPanel); // from right to left [2][1][0]
int currentAttachmentCol = col + 1;
permWithAttachments.getLinks().clear();
int VerticalIndex = permanentWithAttachmentsView.getAttachments().size();
for (UUID attachmentId : permanentWithAttachmentsView.getAttachments()) {
PermanentView attachedPermanentView = battlefieldPanel.getBattlefield().get(attachmentId);
if (attachedPermanentView != null && attachedPermanentView.getAttachments() != null && !attachedPermanentView.getAttachments().isEmpty()) {
layoutAttachements(baseX, maxCul, ZOrder, attachedPermanentView, permanents, battlefieldPanel, mainPanel, rectangleBaseCard);
}
MagePermanent attachedPermanent = permanents.get(attachmentId);
if (attachedPermanent != null) {
// reset x position
Point point = new Point();
point.setLocation(baseX + (maxCul - currentAttachmentCol) * Math.max(permWithAttachments.getWidth() / 10, ATTACHMENTS_MIN_DX_OFFSET), rectangleBaseCard.getY());
rectangleBaseCard.setLocation(point);
attachedPermanent.setBounds(rectangleBaseCard); // set position first to the same as of the permanent it is attached to
permWithAttachments.getLinks().add(attachedPermanent);
int dyOffset = Math.max(permWithAttachments.getHeight() / 10, ATTACHMENT_MIN_DY_OFFSET); // calculate y offset
if (VerticalIndex == 1) {
rectangleBaseCard.translate(Math.max(permWithAttachments.getWidth() / 10, ATTACHMENTS_MIN_DX_OFFSET), dyOffset); // do it once
} else {
rectangleBaseCard.translate(0, dyOffset);
}
permWithAttachments.setBounds(rectangleBaseCard);
battlefieldPanel.moveToFront(attachedPermanent);
battlefieldPanel.moveToFront(permWithAttachments);
mainPanel.setComponentZOrder(attachedPermanent, ZOrder--);
VerticalIndex--;
}
}
}
private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, BattlefieldPanel battlefieldPanel, Map<UUID, MagePermanent> permanents, PermanentView permanentWithAttachmentsView) {
int maxCol = ++currentCol;
int attachments = 0;
for (UUID attachmentId : permanentWithAttachmentsView.getAttachments()) {
PermanentView attachedPermanent = battlefieldPanel.getBattlefield().get(attachmentId);
if (attachedPermanent != null) {
attachments++;
if (attachedPermanent.getAttachments() != null && !attachedPermanent.getAttachments().isEmpty()) {
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol, battlefieldPanel, permanents, attachedPermanent);
if (attachmentLayoutInfos.getColumns() > maxCol) {
maxCol = attachmentLayoutInfos.getColumns();
attachments += attachmentLayoutInfos.getAttachments();
}
}
}
}
return new AttachmentLayoutInfos(maxCol, attachments);
}
// The root permanent is col 0. An attachment attached to the root is col 1. And an attachement attached to the first attachment is col 2. etc.
private int getVerticalCul(PermanentView permanentView, BattlefieldPanel battlefieldPanel) {
int cul = 0;
if (permanentView.isAttachedTo()) {
PermanentView attachedToPermanent = battlefieldPanel.getBattlefield().get(permanentView.getAttachedTo());
if (attachedToPermanent != null) {
cul = getVerticalCul(attachedToPermanent, battlefieldPanel);
}
cul++;
}
return cul;
}
@Override
public int getDefaultZOrder() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void onAdd(BattlefieldPanel jLayeredPane) {
public void onAdd(BattlefieldPanel jLayeredPane
) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

View file

@ -1,5 +1,21 @@
package org.mage.plugins.card;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLayeredPane;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
import mage.client.dialog.PreferencesDialog;
@ -25,15 +41,6 @@ import org.mage.plugins.card.dl.sources.ScryfallSymbolsSource;
import org.mage.plugins.card.images.ImageCache;
import org.mage.plugins.card.info.CardInfoPaneImpl;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* {@link CardPlugin} implementation.
*
@ -128,7 +135,7 @@ public class CardPluginImpl implements CardPlugin {
}
@Override
public int sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> permanents, boolean nonPermanentsOwnRow, boolean topPanel) {
public int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> permanents, boolean nonPermanentsOwnRow, boolean topPanel) {
//TODO: add caching
//requires to find out is position have been changed that includes:
//adding/removing permanents, type change
@ -149,7 +156,7 @@ public class CardPluginImpl implements CardPlugin {
outerLoop:
//
for (MagePermanent permanent : permanents) {
for (MagePermanent permanent : permanents.values()) {
if (!permanent.isLand() || permanent.isCreature()) {
continue;
}
@ -196,8 +203,13 @@ public class CardPluginImpl implements CardPlugin {
Stack stack = new Stack();
if (permanent.getOriginalPermanent().getAttachments() != null) {
stack.setMaxAttachedCount(permanent.getOriginalPermanent().getAttachments().size());
if (permanent.getOriginalPermanent().getAttachments() != null
&& !permanent.getOriginalPermanent().getAttachments().isEmpty()
&& !permanent.getOriginalPermanent().isAttachedTo()) {
// get the number of all attachements and sub attachments
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, permanents, permanent);
stack.setMaxAttachedCount(ali.getAttachments());
stack.setAttachmentColumns(ali.getColumns());
}
stack.add(permanent);
@ -411,6 +423,25 @@ public class CardPluginImpl implements CardPlugin {
return height - cardSpacingY + GUTTER_Y * 2;
}
private AttachmentLayoutInfos calculateNeededNumberOfVerticalColumns(int currentCol, Map<UUID, MagePermanent> permanents, MagePermanent permanentWithAttachments) {
int maxCol = ++currentCol;
int attachments = 0;
for (UUID attachmentId : permanentWithAttachments.getOriginalPermanent().getAttachments()) {
MagePermanent attachedPermanent = permanents.get(attachmentId);
if (attachedPermanent != null) {
attachments++;
if (attachedPermanent.getOriginalPermanent().getAttachments() != null && !attachedPermanent.getOriginalPermanent().getAttachments().isEmpty()) {
AttachmentLayoutInfos attachmentLayoutInfos = calculateNeededNumberOfVerticalColumns(currentCol, permanents, attachedPermanent);
if (attachmentLayoutInfos.getColumns() > maxCol) {
maxCol = attachmentLayoutInfos.getColumns();
attachments += attachmentLayoutInfos.getAttachments();
}
}
}
}
return new AttachmentLayoutInfos(maxCol, attachments);
}
private enum RowType {
land, creature, other, attached;
@ -438,13 +469,13 @@ public class CardPluginImpl implements CardPlugin {
super(16);
}
public Row(Collection<MagePermanent> permanents, RowType type) {
public Row(Map<UUID, MagePermanent> permanents, RowType type) {
this();
addAll(permanents, type);
}
private void addAll(Collection<MagePermanent> permanents, RowType type) {
for (MagePermanent permanent : permanents) {
private void addAll(Map<UUID, MagePermanent> permanents, RowType type) {
for (MagePermanent permanent : permanents.values()) {
if (!type.isType(permanent)) {
continue;
}
@ -455,7 +486,9 @@ public class CardPluginImpl implements CardPlugin {
Stack stack = new Stack();
stack.add(permanent);
if (permanent.getOriginalPermanent().getAttachments() != null) {
stack.setMaxAttachedCount(permanent.getOriginalPermanent().getAttachments().size());
AttachmentLayoutInfos ali = calculateNeededNumberOfVerticalColumns(0, permanents, permanent);
stack.setMaxAttachedCount(ali.getAttachments());
stack.setAttachmentColumns(ali.getColumns());
}
add(stack);
}
@ -499,13 +532,14 @@ public class CardPluginImpl implements CardPlugin {
* Max attached object count attached to single permanent in the stack.
*/
private int maxAttachedCount = 0;
private int attachmentColumns = 0;
public Stack() {
super(8);
}
private int getWidth() {
return cardWidth + (size() - 1) * stackSpacingX + cardSpacingX;
return cardWidth + (size() - 1) * stackSpacingX + cardSpacingX + (12 * attachmentColumns);
}
private int getHeight() {
@ -519,6 +553,37 @@ public class CardPluginImpl implements CardPlugin {
public void setMaxAttachedCount(int maxAttachedCount) {
this.maxAttachedCount = maxAttachedCount;
}
public void setAttachmentColumns(int attachmentColumns) {
this.attachmentColumns = attachmentColumns;
}
}
private final class AttachmentLayoutInfos {
private int columns;
private int attachments;
public AttachmentLayoutInfos(int columns, int attachments) {
this.columns = columns;
this.attachments = attachments;
}
public int getColumns() {
return columns;
}
public int getAttachments() {
return attachments;
}
public void increaseAttachments() {
attachments++;
}
public void increaseColumns() {
columns++;
}
}
/**
@ -552,8 +617,7 @@ public class CardPluginImpl implements CardPlugin {
for (DownloadJob job : it) {
g.getDownloader().add(job);
}
*/
*/
it = new DirectLinksForDownload();
for (DownloadJob job : it) {
g.getDownloader().add(job);

View file

@ -2,7 +2,6 @@ package mage.interfaces.plugin;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import javax.swing.*;
@ -27,7 +26,7 @@ public interface CardPlugin extends Plugin {
MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage);
int sortPermanents(Map<String, JComponent> ui, Collection<MagePermanent> cards, boolean nonPermanentsOwnRow, boolean topPanel);
int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> cards, boolean nonPermanentsOwnRow, boolean topPanel);
/**
* Download various symbols (mana, tap, set).