diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 0e13b5c3add..1cb0220a907 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -101,6 +101,7 @@ import forge.util.gui.SOptionPane; import forge.view.FView; import forge.view.arcane.CardPanel; import forge.view.arcane.FloatingCardArea; +import forge.match.input.*; /** * Constructs instance of match UI controller, used as a single point of @@ -395,7 +396,8 @@ public final class CMatchUI break; case Hand: updateHand = true; - //$FALL-THROUGH$ + updateZones = true; + break; default: updateZones = true; FloatingCardArea.refresh(owner, zone); @@ -424,6 +426,57 @@ public final class CMatchUI } } + @Override + public Iterable tempShowZones(final PlayerView controller, final Iterable zonesToUpdate) { + for (final PlayerZoneUpdate update : zonesToUpdate) { + final PlayerView player = update.getPlayer(); + for (final ZoneType zone : update.getZones()) { + switch (zone) { + case Battlefield: // always shown + break; + case Hand: // controller hand always shown + if (controller != player) { + FloatingCardArea.show(this,player,zone); + } + break; + case Library: + case Graveyard: + case Exile: + case Flashback: + case Command: + FloatingCardArea.show(this,player,zone); + break; + default: + break; + } + } + } + return zonesToUpdate; //pfps should return only the newly shown zones + } + + @Override + public void hideZones(final PlayerView controller, final Iterable zonesToUpdate) { + for (final PlayerZoneUpdate update : zonesToUpdate) { + final PlayerView player = update.getPlayer(); + for (final ZoneType zone : update.getZones()) { + switch (zone) { + case Battlefield: // always shown + break; + case Hand: // the controller's hand should never be temporarily shown, but ... + case Library: + case Graveyard: + case Exile: + case Flashback: + case Command: + FloatingCardArea.hide(this,player,zone); + break; + default: + break; + } + } + } + } + // Player's mana pool changes @Override public void updateManaPool(final Iterable manaPoolUpdate) { @@ -465,6 +518,7 @@ public final class CMatchUI } break; default: + FloatingCardArea.refresh(c.getController(),zone); // in case the card is visible in the zone break; } } diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingCardArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingCardArea.java index fc1365798bb..66b3428e906 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingCardArea.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingCardArea.java @@ -69,6 +69,10 @@ public class FloatingCardArea extends CardArea { final FloatingCardArea cardArea = _init(matchUI, player, zone); cardArea.showWindow(); } + public static void hide(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) { + final FloatingCardArea cardArea = _init(matchUI, player, zone); + cardArea.hideWindow(); + } private static FloatingCardArea _init(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) { final int key = getKey(player, zone); FloatingCardArea cardArea = floatingAreas.get(key); @@ -205,6 +209,11 @@ public class FloatingCardArea extends CardArea { window.setFocusableWindowState(false); // should probably do this earlier window.setVisible(true); } + private void hideWindow() { + onShow(); + window.setFocusableWindowState(false); // should probably do this earlier + window.setVisible(false); + } private void showOrHideWindow() { onShow(); window.setFocusableWindowState(false); // should probably do this earlier diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 4e7fb644f00..8ded7b6ff33 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -343,6 +343,16 @@ public class MatchController extends AbstractGuiGame { view.updateZones(zonesToUpdate); } + @Override + public Iterable tempShowZones(final PlayerView controller, final Iterable zonesToUpdate) { + return view.tempShowZones(controller, zonesToUpdate); + } + + @Override + public void hideZones(final PlayerView controller, final Iterable zonesToUpdate) { + view.hideZones(controller, zonesToUpdate); + } + @Override public void updateCards(final Iterable cards) { for (final CardView card : cards) { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 774d8c34355..9b710575c4a 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -468,6 +468,15 @@ public class MatchScreen extends FScreen { } } + public Iterable tempShowZones(final PlayerView controller, final Iterable zonesToUpdate) { + // pfps needs to actually do something + return zonesToUpdate; // pfps should return only those zones newly shown + } + + public void hideZones(final PlayerView controller, final Iterable zonesToUpdate) { + // pfps needs to actually do something + } + public void updateSingleCard(final CardView card) { final CardAreaPanel pnl = CardAreaPanel.get(card); if (pnl == null) { return; } diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java index 1abfe662f54..039b132e988 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java @@ -47,6 +47,8 @@ public interface IGuiGame { void showManaPool(PlayerView player); void hideManaPool(PlayerView player); void updateStack(); + Iterable tempShowZones(PlayerView controller, Iterable zonesToUpdate); + void hideZones(PlayerView controller, Iterable zonesToUpdate); void updateZones(Iterable zonesToUpdate); void updateSingleCard(CardView card); void updateCards(Iterable cards); diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java b/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java index 6448cafae29..f9e082a3624 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java @@ -11,12 +11,17 @@ import forge.player.PlayerControllerHuman; import forge.util.collect.FCollection; import forge.util.collect.FCollectionView; import forge.util.ITriggerEvent; +import forge.player.PlayerZoneUpdate; +import forge.player.PlayerZoneUpdates; +import forge.game.zone.Zone; +import forge.FThreads; public class InputSelectEntitiesFromList extends InputSelectManyBase { private static final long serialVersionUID = -6609493252672573139L; private final FCollectionView validChoices; protected final FCollection selected = new FCollection(); + protected Iterable zonesShown; // want to hide these zones when input done public InputSelectEntitiesFromList(final PlayerControllerHuman controller, final int min, final int max, final FCollectionView validChoices0) { this(controller, min, max, validChoices0, null); @@ -28,6 +33,17 @@ public class InputSelectEntitiesFromList extends InputSele if (min > validChoices.size()) { System.out.println(String.format("Trying to choose at least %d things from a list with only %d things!", min, validChoices.size())); } + PlayerZoneUpdates zonesToUpdate = new PlayerZoneUpdates(); + for (final GameEntity c : validChoices) { + final Zone cz = (c instanceof Card) ? ((Card) c).getZone() : null ; + zonesToUpdate.add(new PlayerZoneUpdate(cz.getPlayer().getView(),cz.getZoneType())); + } + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public void run() { + controller.getGui().updateZones(zonesToUpdate); + zonesShown = controller.getGui().tempShowZones(controller.getPlayer().getView(),zonesToUpdate); + } + }); } @Override @@ -93,4 +109,10 @@ public class InputSelectEntitiesFromList extends InputSele ? String.format(message, selected.size()) : String.format(message, max - selected.size()); } + + @Override + protected void onStop() { + getController().getGui().hideZones(getController().getPlayer().getView(),zonesShown); + super.onStop(); + } } diff --git a/forge-gui/src/main/java/forge/net/ProtocolMethod.java b/forge-gui/src/main/java/forge/net/ProtocolMethod.java index 11ff02380d9..85101da9108 100644 --- a/forge-gui/src/main/java/forge/net/ProtocolMethod.java +++ b/forge-gui/src/main/java/forge/net/ProtocolMethod.java @@ -49,6 +49,8 @@ public enum ProtocolMethod { hideManaPool (Mode.SERVER, Void.TYPE, PlayerView.class), updateStack (Mode.SERVER), updateZones (Mode.SERVER, Void.TYPE, Iterable/*PlayerZoneUpdate*/.class), + tempShowZones (Mode.SERVER, Iterable/*PlayerZoneUpdate*/.class, PlayerView.class, Iterable/*PlayerZoneUpdate*/.class), + hideZones (Mode.SERVER, Void.TYPE, PlayerView.class, Iterable/*PlayerZoneUpdate*/.class), updateCards (Mode.SERVER, Void.TYPE, Iterable/*CardView*/.class), updateManaPool (Mode.SERVER, Void.TYPE, Iterable/*PlayerView*/.class), updateLives (Mode.SERVER, Void.TYPE, Iterable/*PlayerView*/.class), @@ -184,4 +186,4 @@ public enum ProtocolMethod { throw new IllegalStateException(String.format("Protocol method %s: illegal return object type %s returned by client, expected %s", name(), value.getClass().getName(), getReturnType().getName())); } } -} \ No newline at end of file +} diff --git a/forge-gui/src/main/java/forge/net/server/NetGuiGame.java b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java index eb479e9352a..5635608fbd0 100644 --- a/forge-gui/src/main/java/forge/net/server/NetGuiGame.java +++ b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java @@ -147,6 +147,18 @@ public class NetGuiGame extends AbstractGuiGame { send(ProtocolMethod.updateZones, zonesToUpdate); } + @Override + public Iterable tempShowZones(final PlayerView controller, final Iterable zonesToUpdate) { + updateGameView(); + return sendAndWait(ProtocolMethod.tempShowZones, controller, zonesToUpdate); + } + + @Override + public void hideZones(final PlayerView controller, final Iterable zonesToUpdate) { + updateGameView(); + send(ProtocolMethod.hideZones, controller, zonesToUpdate); + } + @Override public void updateCards(final Iterable cards) { updateGameView(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index b26a3954f65..a745f973e6d 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -348,6 +348,30 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return new CardCollection(inp.getSelected()); } + private boolean useSelectCardsInput(final FCollectionView sourceList) { + // if UI_SELECT_FROM_ZONES not set use InputSelect only for battlefield and player hand + // if UI_SELECT_FROM_ZONES set use InputSelect for any zone that can be shown + for (final GameEntity c : sourceList) { + if (c instanceof Player) { + continue; + } + if (!(c instanceof Card)) { + return false; + } + final Zone cz = ((Card) c).getZone(); + final boolean useUiPointAtCard = + cz != null && + FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_ZONES) ? + (cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) || + cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) : + (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); + if (!useUiPointAtCard) { + return false; + } + } + return true; + } + @Override public CardCollectionView chooseCardsForEffect(final CardCollectionView sourceList, final SpellAbility sa, final String title, final int min, final int max, final boolean isOptional) { @@ -362,22 +386,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont getGui().setPanelSelection(CardView.get(sa.getHostCard())); - // try to use InputSelectCardsFromList when possible - boolean cardsAreInMyHandOrBattlefield = true; - for (final Card c : sourceList) { - final Zone z = c.getZone(); - if (z != null && (z.is(ZoneType.Battlefield) || z.is(ZoneType.Hand, player))) { - continue; - } - cardsAreInMyHandOrBattlefield = false; - break; - } - - if (cardsAreInMyHandOrBattlefield) { + if (useSelectCardsInput(sourceList)) { + tempShowCards(sourceList); final InputSelectCardsFromList sc = new InputSelectCardsFromList(this, min, max, sourceList, sa); sc.setMessage(title); sc.setCancelAllowed(isOptional); sc.showAndWait(); + endTempShowCards(); return new CardCollection(sc.getSelected()); } @@ -411,31 +426,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return Iterables.getFirst(optionList, null); } - boolean canUseSelectCardsInput = true; - for (final GameEntity c : optionList) { - if (c instanceof Player) { - continue; - } - final Zone cz = ((Card) c).getZone(); - // can point at cards in own hand and anyone's battlefield - final boolean canUiPointAtCards = cz != null - && (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); - if (!canUiPointAtCards) { - canUseSelectCardsInput = false; - break; - } - } - - if (canUseSelectCardsInput) { + if (useSelectCardsInput(optionList)) { if (delayedReveal != null) { reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix()); } + tempShow(optionList); final InputSelectEntitiesFromList input = new InputSelectEntitiesFromList(this, isOptional ? 0 : 1, 1, optionList, sa); input.setCancelAllowed(isOptional); input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer)); input.showAndWait(); + endTempShowCards(); return Iterables.getFirst(input.getSelected(), null); } @@ -475,31 +477,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return null; } - boolean canUseSelectCardsInput = true; - for (final GameEntity c : optionList) { - if (c instanceof Player) { - continue; - } - final Zone cz = ((Card) c).getZone(); - // can point at cards in own hand and anyone's battlefield - final boolean canUiPointAtCards = cz != null - && (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); - if (!canUiPointAtCards) { - canUseSelectCardsInput = false; - break; - } - } - - if (canUseSelectCardsInput) { + if (useSelectCardsInput(optionList)) { if (delayedReveal != null) { reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix()); } + tempShow(optionList); final InputSelectEntitiesFromList input = new InputSelectEntitiesFromList(this, 0, optionList.size(), optionList, sa); input.setCancelAllowed(true); input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer)); input.showAndWait(); + endTempShowCards(); return (List) input.getSelected(); } diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index 2d6af689171..b96037d9fca 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -125,7 +125,7 @@ public class ForgePreferences extends PreferencesStore { UI_DISABLE_IMAGES_EFFECT_CARDS("false"), UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"), UI_DEFAULT_FONT_SIZE("12"), - + UI_SELECT_FROM_ZONES("true"), UI_FOR_TOUCHSCREN("false"), UI_VIBRATE_ON_LIFE_LOSS("true"),