GUI - new card hints window features:

* new help window can be opened from a player panel;
* it collect and show all visible game hints from all players and all zones;
* it updates in real time on game update;
* allows to customize visible data;
* allows to open multiple windows (current limit is 5 windows, can be slow to render);
* allows to minimize opened windows;
* workable card popup on mouse move over card name or card id;
* filter modes:
  * all - show hints from all players;
  * player - show hints from single player;
* group mode:
  * by hints - show same hints as one with all used cards;
  * by cards - show full cards list with own hints;
* search mode:
  * allows to filter card hints by player name, card name, card id or card hint;
  * allows to search multiple words (equals to "or")
* current limitation:
  * card popup shows a card instead a real object, e.g. miss card hints in it (relelated to game logs problem);
  * unsupport of emblems, dungeons and other non card objects from a command zone;
  * unsupport of revealed and library's top cards;

GUI - player's panel improves:
* added hints helper button;
* added player hithlight as possible target in choose dialogs;
* improved player name button in small mode;
* fixed wrong height in small mode;

Other fixes:
* game logs: added card popup support for logs with custom object name;
This commit is contained in:
Oleg Agafonov 2023-11-18 14:48:25 +04:00
parent ca80849249
commit 2bbe2b3c43
16 changed files with 1229 additions and 75 deletions

View file

@ -86,6 +86,8 @@ public final class GamePanel extends javax.swing.JPanel {
private final Map<String, CardInfoWindowDialog> sideboardWindows = new HashMap<>();
private final ArrayList<ShowCardsDialog> pickTarget = new ArrayList<>();
private final ArrayList<PickPileDialog> pickPile = new ArrayList<>();
private final Map<String, CardHintsHelperDialog> cardHintsWindows = new LinkedHashMap<>();
private UUID gameId;
private UUID playerId; // playerId of the player
GamePane gamePane;
@ -275,6 +277,10 @@ public final class GamePanel extends javax.swing.JPanel {
windowDialog.cleanUp();
windowDialog.removeDialog();
}
for (CardHintsHelperDialog windowDialog : cardHintsWindows.values()) {
windowDialog.cleanUp();
windowDialog.removeDialog();
}
clearPickDialogs();
@ -350,6 +356,9 @@ public final class GamePanel extends javax.swing.JPanel {
for (CardInfoWindowDialog windowDialog : sideboardWindows.values()) {
windowDialog.changeGUISize();
}
for (CardHintsHelperDialog windowDialog : cardHintsWindows.values()) {
windowDialog.changeGUISize();
}
for (ShowCardsDialog windowDialog : pickTarget) {
windowDialog.changeGUISize();
}
@ -886,16 +895,25 @@ public final class GamePanel extends javax.swing.JPanel {
GameManager.instance.setStackSize(lastGameData.game.getStack().size());
displayStack(lastGameData.game, bigCard, feedbackPanel, gameId);
// auto-show exile views
for (ExileView exile : lastGameData.game.getExile()) {
if (!exiles.containsKey(exile.getId())) {
CardInfoWindowDialog newExile = new CardInfoWindowDialog(ShowType.EXILE, exile.getName());
exiles.put(exile.getId(), newExile);
MageFrame.getDesktop().add(newExile, JLayeredPane.PALETTE_LAYER);
newExile.show();
CardInfoWindowDialog exileWindow = exiles.getOrDefault(exile.getId(), null);
if (exileWindow == null) {
exileWindow = new CardInfoWindowDialog(ShowType.EXILE, exile.getName());
exiles.put(exile.getId(), exileWindow);
MageFrame.getDesktop().add(exileWindow, JLayeredPane.PALETTE_LAYER);
exileWindow.show();
}
exiles.get(exile.getId()).loadCards(exile, bigCard, gameId);
exileWindow.loadCards(exile, bigCard, gameId);
}
// update open or remove closed card hints windows
clearClosedCardHintsWindows();
cardHintsWindows.forEach((s, windowDialog) -> {
// TODO: optimize for multiple windows (prepare data here and send it for filters/groups)
windowDialog.loadHints(lastGameData.game);
});
// reveal and look at dialogs can unattached, so windows opened by game doesn't have it
showRevealed(lastGameData.game);
showLookedAt(lastGameData.game);
@ -1197,24 +1215,28 @@ public final class GamePanel extends javax.swing.JPanel {
// Called if the game frame is deactivated because the tabled the deck editor or other frames go to foreground
public void deactivated() {
// hide the non modal windows (because otherwise they are shown on top of the new active pane)
// TODO: is it need to hide other dialogs like graveyards (CardsView)?
for (CardInfoWindowDialog windowDialog : exiles.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : graveyardWindows.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : revealed.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : lookedAt.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : graveyardWindows.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : companion.values()) {
windowDialog.hideDialog();
}
for (CardInfoWindowDialog windowDialog : sideboardWindows.values()) {
windowDialog.hideDialog();
}
for (CardHintsHelperDialog windowDialog : cardHintsWindows.values()) {
windowDialog.hideDialog();
}
}
// Called if the game frame comes to front again
@ -1223,21 +1245,24 @@ public final class GamePanel extends javax.swing.JPanel {
for (CardInfoWindowDialog windowDialog : exiles.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : graveyardWindows.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : revealed.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : lookedAt.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : graveyardWindows.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : companion.values()) {
windowDialog.show();
}
for (CardInfoWindowDialog windowDialog : sideboardWindows.values()) {
windowDialog.show();
}
for (CardHintsHelperDialog windowDialog : cardHintsWindows.values()) {
windowDialog.show();
}
}
public void openGraveyardWindow(String playerName) {
@ -1257,6 +1282,29 @@ public final class GamePanel extends javax.swing.JPanel {
newGraveyard.loadCards(graveyards.get(playerName), bigCard, gameId, false);
}
private void clearClosedCardHintsWindows() {
cardHintsWindows.entrySet().removeIf(entry -> entry.getValue().isClosed());
}
public void openCardHintsWindow(String code) {
// clear closed
clearClosedCardHintsWindows();
// too many dialogs can cause bad GUI performance, so limit it
if (cardHintsWindows.size() > CardHintsHelperDialog.GUI_MAX_CARD_HINTS_DIALOGS_PER_GAME) {
// show last one instead
cardHintsWindows.values().stream().reduce((a, b) -> b).ifPresent(CardHintsHelperDialog::show);
return;
}
// open new
CardHintsHelperDialog newDialog = new CardHintsHelperDialog();
newDialog.setGameData(this.lastGameData.game, this.gameId, this.bigCard);
cardHintsWindows.put(code + UUID.randomUUID(), newDialog);
MageFrame.getDesktop().add(newDialog, JLayeredPane.PALETTE_LAYER);
newDialog.loadHints(lastGameData.game);
}
public void openSideboardWindow(UUID playerId) {
if (lastGameData == null) {
return;