Add option to select cards from any Zone that can be shown (implemented in desktop GUI only for now)

This commit is contained in:
Peter F. Patel-Schneider
2019-01-06 10:47:20 -05:00
parent bf59d932f4
commit 234304f9ec
10 changed files with 156 additions and 47 deletions

View File

@@ -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<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> 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<PlayerZoneUpdate> 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<PlayerView> 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;
}
}

View File

@@ -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

View File

@@ -343,6 +343,16 @@ public class MatchController extends AbstractGuiGame {
view.updateZones(zonesToUpdate);
}
@Override
public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
return view.tempShowZones(controller, zonesToUpdate);
}
@Override
public void hideZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
view.hideZones(controller, zonesToUpdate);
}
@Override
public void updateCards(final Iterable<CardView> cards) {
for (final CardView card : cards) {

View File

@@ -468,6 +468,15 @@ public class MatchScreen extends FScreen {
}
}
public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> 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<PlayerZoneUpdate> zonesToUpdate) {
// pfps needs to actually do something
}
public void updateSingleCard(final CardView card) {
final CardAreaPanel pnl = CardAreaPanel.get(card);
if (pnl == null) { return; }

View File

@@ -47,6 +47,8 @@ public interface IGuiGame {
void showManaPool(PlayerView player);
void hideManaPool(PlayerView player);
void updateStack();
Iterable<PlayerZoneUpdate> tempShowZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate);
void hideZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateSingleCard(CardView card);
void updateCards(Iterable<CardView> cards);

View File

@@ -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<T extends GameEntity> extends InputSelectManyBase<T> {
private static final long serialVersionUID = -6609493252672573139L;
private final FCollectionView<T> validChoices;
protected final FCollection<T> selected = new FCollection<T>();
protected Iterable<PlayerZoneUpdate> zonesShown; // want to hide these zones when input done
public InputSelectEntitiesFromList(final PlayerControllerHuman controller, final int min, final int max, final FCollectionView<T> validChoices0) {
this(controller, min, max, validChoices0, null);
@@ -28,6 +33,17 @@ public class InputSelectEntitiesFromList<T extends GameEntity> 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<T extends GameEntity> 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();
}
}

View File

@@ -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),

View File

@@ -147,6 +147,18 @@ public class NetGuiGame extends AbstractGuiGame {
send(ProtocolMethod.updateZones, zonesToUpdate);
}
@Override
public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
updateGameView();
return sendAndWait(ProtocolMethod.tempShowZones, controller, zonesToUpdate);
}
@Override
public void hideZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
updateGameView();
send(ProtocolMethod.hideZones, controller, zonesToUpdate);
}
@Override
public void updateCards(final Iterable<CardView> cards) {
updateGameView();

View File

@@ -348,6 +348,30 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
return new CardCollection(inp.getSelected());
}
private boolean useSelectCardsInput(final FCollectionView<? extends GameEntity> 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<T> input = new InputSelectEntitiesFromList<T>(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<T> input = new InputSelectEntitiesFromList<T>(this, 0, optionList.size(),
optionList, sa);
input.setCancelAllowed(true);
input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer));
input.showAndWait();
endTempShowCards();
return (List<T>) input.getSelected();
}

View File

@@ -125,7 +125,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
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"),