diff --git a/cockatrice/src/game_graphics/deckview/deck_view_container.cpp b/cockatrice/src/game_graphics/deckview/deck_view_container.cpp index aae2e59a5..23ed4316d 100644 --- a/cockatrice/src/game_graphics/deckview/deck_view_container.cpp +++ b/cockatrice/src/game_graphics/deckview/deck_view_container.cpp @@ -310,29 +310,16 @@ void DeckViewContainer::resolveAndSendPlaymat() const auto &settings = SettingsCache::instance().userInterface(); const auto fallbackBehavior = static_cast(settings.getPlaymatFallbackBehavior()); - PlaymatResolution resolved; - QList fallbackList = settings.getPlaymatFallbackList(); + QList fallbackList = settings.getPlaymatFallbackList(); // In random mode with 2+ entries, remove the last-resolved mat to avoid repeats. - if (fallbackBehavior == PlaymatFallbackMode::Random && fallbackList.size() > 1) { + if (fallbackBehavior == PlaymatFallbackModeRandom && fallbackList.size() > 1) { fallbackList.removeAll(lastResolvedPlaymat); } - switch (settings.getPlaymatMode()) { - case 0: { // Override deck playmat — always use collection - DeckList emptyDeck; - resolved = resolveEffectivePlaymat(emptyDeck, {}, fallbackList, fallbackBehavior, playmatRotationIndex); - break; - } - case 1: // Fallback if deck has none — deck > collection > none - resolved = resolveEffectivePlaymat(currentDeck, {}, fallbackList, fallbackBehavior, playmatRotationIndex); - break; - case 2: // Deck only, ignore collection - resolved = currentDeck.getPlaymat(); - break; - default: - break; - } + const PlaymatInfo resolved = + resolvePlaymatForDeck(currentDeck, fallbackList, static_cast(settings.getPlaymatMode()), + fallbackBehavior, playmatRotationIndex); lastResolvedPlaymat = resolved; diff --git a/cockatrice/src/game_graphics/deckview/deck_view_container.h b/cockatrice/src/game_graphics/deckview/deck_view_container.h index 66c610a45..b5317c39a 100644 --- a/cockatrice/src/game_graphics/deckview/deck_view_container.h +++ b/cockatrice/src/game_graphics/deckview/deck_view_container.h @@ -57,9 +57,9 @@ private: VisualDeckStorageWidget *visualDeckStorageWidget; TabGame *parentGame; int playerId; - int playmatRotationIndex = 0; ///< Per-match cursor for round-robin playmat mode. - DeckList currentDeck; ///< Cached deck for live settings re-resolution. - PlaymatResolution lastResolvedPlaymat; ///< Tracks last sent playmat to avoid repeats in random mode. + int playmatRotationIndex = 0; ///< Per-match cursor for round-robin playmat mode. + DeckList currentDeck; ///< Cached deck for live settings re-resolution. + PlaymatInfo lastResolvedPlaymat; ///< Tracks last sent playmat to avoid repeats in random mode. void tryCreateVisualDeckStorageWidget(); void sendReadyStartCommand(bool ready); diff --git a/cockatrice/src/game_graphics/player/player_graphics_item.cpp b/cockatrice/src/game_graphics/player/player_graphics_item.cpp index 9751f0320..026e00588 100644 --- a/cockatrice/src/game_graphics/player/player_graphics_item.cpp +++ b/cockatrice/src/game_graphics/player/player_graphics_item.cpp @@ -372,13 +372,13 @@ void PlayerGraphicsItem::updatePlaymat() int visibility = SettingsCache::instance().userInterface().getPlaymatVisibility(); // "Don't use playmats" — never show - if (visibility == 0) { + if (visibility == PlaymatVisibilityNone) { clearPlaymat(); return; } // "Show own playmat only" — hide playmats for remote players - if (visibility == 1 && !player->getPlayerInfo()->getLocal()) { + if (visibility == PlaymatVisibilityOwnOnly && !player->getPlayerInfo()->getLocal()) { clearPlaymat(); return; } @@ -394,38 +394,15 @@ void PlayerGraphicsItem::updatePlaymat() // Local player without a server broadcast yet: apply the full // settings-based resolution chain (mode, fallback list, behavior). const auto &settings = SettingsCache::instance().userInterface(); - const DeckList &deck = player->getDeck(); - const auto fallbackBehavior = static_cast(settings.getPlaymatFallbackBehavior()); - - switch (settings.getPlaymatMode()) { - case 0: { // Override deck playmat — always use collection - DeckList emptyDeck; - const PlaymatResolution resolved = - resolveEffectivePlaymat(emptyDeck, {}, settings.getPlaymatFallbackList(), fallbackBehavior, 0); - playmatCard = resolved.card; - params = resolved.params; - break; - } - case 1: { // Fallback if deck has none — deck > collection > none - const PlaymatResolution resolved = - resolveEffectivePlaymat(deck, {}, settings.getPlaymatFallbackList(), fallbackBehavior, 0); - playmatCard = resolved.card; - params = resolved.params; - break; - } - case 2: { // Deck only, ignore collection - const PlaymatResolution &deckPlaymat = deck.getPlaymat(); - if (!deckPlaymat.card.isEmpty()) { - playmatCard = deckPlaymat.card; - params = deckPlaymat.params; - } - break; - } - } + const PlaymatInfo resolved = resolvePlaymatForDeck( + player->getDeck(), settings.getPlaymatFallbackList(), static_cast(settings.getPlaymatMode()), + static_cast(settings.getPlaymatFallbackBehavior()), 0); + playmatCard = resolved.card; + params = resolved.params; } else { // Opponent without a server broadcast: use the deck-embedded playmat. const DeckList &deck = player->getDeck(); - const PlaymatResolution &deckPlaymat = deck.getPlaymat(); + const PlaymatInfo &deckPlaymat = deck.getPlaymat(); if (!deckPlaymat.card.isEmpty()) { playmatCard = deckPlaymat.card; params = deckPlaymat.params; diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index 05129369c..14defc8e9 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -453,7 +453,7 @@ void DeckEditorDeckDockWidget::writeBannerCard(int index) void DeckEditorDeckDockWidget::openPlaymatSettings() { - PlaymatResolution current = deckStateManager->getMetadata().playmat; + PlaymatInfo current = deckStateManager->getMetadata().playmat; PlaymatSettingsDialog dialog(current.card, current.params, this); if (dialog.exec() == QDialog::Accepted) { @@ -461,7 +461,7 @@ void DeckEditorDeckDockWidget::openPlaymatSettings() PlaymatParams newParams = dialog.params(); if (newCard.isEmpty()) { - deckStateManager->setPlaymat(PlaymatResolution{}); + deckStateManager->setPlaymat(PlaymatInfo{}); } else { deckStateManager->setPlaymat({newCard, newParams}); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp index 23f305723..eda741728 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp @@ -142,9 +142,9 @@ void DeckStateManager::setBannerCard(const CardRef &bannerCard) doMetadataModified(); } -void DeckStateManager::setPlaymat(const PlaymatResolution &playmat) +void DeckStateManager::setPlaymat(const PlaymatInfo &playmat) { - PlaymatResolution previous = deckList->getPlaymat(); + PlaymatInfo previous = deckList->getPlaymat(); if (previous == playmat) { return; } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h index af9b1e7ed..b9c99903e 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h @@ -171,7 +171,7 @@ public: void setName(const QString &name); void setComments(const QString &comments); void setBannerCard(const CardRef &bannerCard); - void setPlaymat(const PlaymatResolution &playmat); + void setPlaymat(const PlaymatInfo &playmat); void setTags(const QStringList &tags); void setFormat(const QString &format); ///@} diff --git a/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.cpp b/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.cpp index 483d096bf..e970f8413 100644 --- a/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.cpp +++ b/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.cpp @@ -38,7 +38,7 @@ void PlaymatCollectionDialog::setupUi() playmats = interfaceSettings.getPlaymatFallbackList(); playmatList = new QListWidget; - for (const PlaymatResolution &entry : playmats) { + for (const PlaymatInfo &entry : playmats) { playmatList->addItem(entry.card.name); } connect(playmatList, &QListWidget::itemSelectionChanged, this, &PlaymatCollectionDialog::selectionChanged); @@ -69,9 +69,9 @@ void PlaymatCollectionDialog::setupUi() listRow->addLayout(listButtons); modeCombo = new QComboBox; - modeCombo->addItem(QString(), 0); - modeCombo->addItem(QString(), 1); - modeCombo->addItem(QString(), 2); + modeCombo->addItem(QString(), PlaymatFallbackModeFixed); + modeCombo->addItem(QString(), PlaymatFallbackModeRoundRobin); + modeCombo->addItem(QString(), PlaymatFallbackModeRandom); const int modeIndex = modeCombo->findData(interfaceSettings.getPlaymatFallbackBehavior()); if (modeIndex >= 0) { modeCombo->setCurrentIndex(modeIndex); @@ -111,7 +111,7 @@ void PlaymatCollectionDialog::addPlaymat() if (dialog.exec() == QDialog::Accepted) { const CardRef card = dialog.card(); if (!card.isEmpty()) { - PlaymatResolution res = {card, dialog.params()}; + PlaymatInfo res = {card, dialog.params()}; playmats.append(res); playmatList->addItem(res.card.name); playmatList->setCurrentRow(playmatList->count() - 1); @@ -126,7 +126,7 @@ void PlaymatCollectionDialog::editPlaymat() return; } - const PlaymatResolution ¤t = playmats.at(row); + const PlaymatInfo ¤t = playmats.at(row); PlaymatSettingsDialog dialog(current.card, current.params, this); if (dialog.exec() == QDialog::Accepted) { const CardRef card = dialog.card(); diff --git a/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.h b/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.h index fb9e715a9..167893f8e 100644 --- a/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.h +++ b/cockatrice/src/interface/widgets/playmat/playmat_collection_dialog.h @@ -40,7 +40,7 @@ private: void retranslateUi(); int currentRow() const; - QList playmats; ///< Working copy edited by the dialog. + QList playmats; ///< Working copy edited by the dialog. QListWidget *playmatList; QComboBox *modeCombo; QLabel *modeLabel; diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp index dd4108290..149395194 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -329,9 +329,9 @@ AppearanceSettingsPage::AppearanceSettingsPage() tableGroupBox->setLayout(tableGrid); // Playmat settings - playmatVisibilityCombo.addItem(tr("Show all playmats"), 2); - playmatVisibilityCombo.addItem(tr("Show own playmat only"), 1); - playmatVisibilityCombo.addItem(tr("Don't use playmats"), 0); + playmatVisibilityCombo.addItem(tr("Show all playmats"), PlaymatVisibilityAll); + playmatVisibilityCombo.addItem(tr("Show own playmat only"), PlaymatVisibilityOwnOnly); + playmatVisibilityCombo.addItem(tr("Don't use playmats"), PlaymatVisibilityNone); int visIdx = playmatVisibilityCombo.findData(settings.userInterface().getPlaymatVisibility()); if (visIdx >= 0) { playmatVisibilityCombo.setCurrentIndex(visIdx); @@ -342,9 +342,9 @@ AppearanceSettingsPage::AppearanceSettingsPage() playmatVisibilityLabel.setBuddy(&playmatVisibilityCombo); // Playmat mode: Override / Fallback / Deck-only - playmatModeCombo.addItem(tr("Override deck playmat"), 0); - playmatModeCombo.addItem(tr("Fallback if deck has none"), 1); - playmatModeCombo.addItem(tr("Deck only, ignore collection"), 2); + playmatModeCombo.addItem(tr("Override deck playmat"), PlaymatModeOverrideDeck); + playmatModeCombo.addItem(tr("Fallback if deck has none"), PlaymatModeFallback); + playmatModeCombo.addItem(tr("Deck only, ignore collection"), PlaymatModeDeckOnly); int modeIdx = playmatModeCombo.findData(settings.userInterface().getPlaymatMode()); if (modeIdx >= 0) { playmatModeCombo.setCurrentIndex(modeIdx); diff --git a/libcockatrice_deck_list/CMakeLists.txt b/libcockatrice_deck_list/CMakeLists.txt index 813e80d98..c7a54a390 100644 --- a/libcockatrice_deck_list/CMakeLists.txt +++ b/libcockatrice_deck_list/CMakeLists.txt @@ -35,4 +35,7 @@ add_dependencies(libcockatrice_deck_list libcockatrice_protocol) target_include_directories(libcockatrice_deck_list PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(libcockatrice_deck_list PUBLIC libcockatrice_protocol libcockatrice_utility ${QT_CORE_MODULE}) +target_link_libraries( + libcockatrice_deck_list PUBLIC libcockatrice_interfaces libcockatrice_protocol libcockatrice_utility + ${QT_CORE_MODULE} +) diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index 55edc23a5..4ffc1bab7 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -82,7 +82,7 @@ bool DeckList::readElement(QXmlStreamReader *xml) QString vOffStr = xml->attributes().value("verticalOffset").toString(); QString zoomStr = xml->attributes().value("zoom").toString(); QString cardName = xml->readElementText(); - PlaymatResolution playmat; + PlaymatInfo playmat; playmat.card = {cardName, providerId}; // Clamp to the same ranges as the settings dialog and the remote // player-properties path so malformed deck files cannot produce diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index c5a90f14e..475d99560 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -70,7 +70,7 @@ public: CardRef bannerCard; ///< Optional representative card for the deck. QStringList tags; ///< User-defined tags for deck classification. QString lastLoadedTimestamp; ///< Timestamp string of last load. - PlaymatResolution playmat; ///< Optional playmat background for table+stack zones. + PlaymatInfo playmat; ///< Optional playmat background for table+stack zones. /** * @brief Checks if all values (except for lastLoadedTimestamp) in the metadata is empty. @@ -116,7 +116,7 @@ public: { metadata.bannerCard = _bannerCard; } - void setPlaymat(const PlaymatResolution &_playmat = {}) + void setPlaymat(const PlaymatInfo &_playmat = {}) { metadata.playmat = _playmat; } @@ -175,7 +175,7 @@ public: { return metadata.bannerCard; } - PlaymatResolution getPlaymat() const + PlaymatInfo getPlaymat() const { return metadata.playmat; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.cpp index bd5e1302d..fd72fea0b 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.cpp @@ -2,17 +2,17 @@ #include -PlaymatResolution resolveEffectivePlaymat(const DeckList &deck, - const PlaymatResolution &force, - const QList &fallbackList, - PlaymatFallbackMode fallbackMode, - int rotationIndex) +PlaymatInfo resolveEffectivePlaymat(const DeckList &deck, + const PlaymatInfo &force, + const QList &fallbackList, + PlaymatFallbackMode fallbackMode, + int rotationIndex) { if (!force.card.isEmpty()) { return force; } - const PlaymatResolution &deckPlaymat = deck.getPlaymat(); + const PlaymatInfo &deckPlaymat = deck.getPlaymat(); if (!deckPlaymat.card.isEmpty()) { return deckPlaymat; } @@ -22,13 +22,33 @@ PlaymatResolution resolveEffectivePlaymat(const DeckList &deck, } switch (fallbackMode) { - case PlaymatFallbackMode::Fixed: + case PlaymatFallbackModeFixed: return fallbackList.first(); - case PlaymatFallbackMode::RoundRobin: + case PlaymatFallbackModeRoundRobin: return fallbackList.at(rotationIndex % fallbackList.size()); - case PlaymatFallbackMode::Random: + case PlaymatFallbackModeRandom: return fallbackList.at(QRandomGenerator::global()->bounded(fallbackList.size())); } return {}; } + +PlaymatInfo resolvePlaymatForDeck(const DeckList &deck, + const QList &fallbackList, + PlaymatMode mode, + PlaymatFallbackMode fallbackBehavior, + int rotationIndex) +{ + switch (mode) { + case PlaymatModeOverrideDeck: { + const DeckList emptyDeck; + return resolveEffectivePlaymat(emptyDeck, {}, fallbackList, fallbackBehavior, rotationIndex); + } + case PlaymatModeFallback: + return resolveEffectivePlaymat(deck, {}, fallbackList, fallbackBehavior, rotationIndex); + case PlaymatModeDeckOnly: + return deck.getPlaymat(); + } + + return {}; +} diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.h b/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.h index c48a8bb8b..59bc449c8 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/playmat_resolver.h @@ -3,16 +3,7 @@ #include "deck_list.h" -/** - * @brief How the user-level fallback playmat list is consulted when a deck has - * no playmat configured. - */ -enum class PlaymatFallbackMode -{ - Fixed = 0, ///< Always use the first entry of the fallback list. - RoundRobin = 1, ///< Cycle through the list, advancing one entry per resolution. - Random = 2 ///< Pick a random entry per resolution. -}; +#include /** * @brief Resolves the effective playmat for a deck per the resolution chain: @@ -20,19 +11,37 @@ enum class PlaymatFallbackMode * * @param deck The deck to resolve a playmat for. * @param force An optional user-level override; wins over everything. Pass an - * empty @ref PlaymatResolution::card to skip it. + * empty @ref PlaymatInfo::card to skip it. * @param fallbackList User-level fallback playmats, consulted only when the * deck has no configured playmat. * @param fallbackMode How @p fallbackList is consulted (ignored when empty). - * @param rotationIndex In/out cursor for @c PlaymatFallbackMode::RoundRobin; + * @param rotationIndex In/out cursor for @c PlaymatFallbackModeRoundRobin; * advanced once per call. Unused for the other modes. - * @return The effective playmat; an empty @ref PlaymatResolution::card when + * @return The effective playmat; an empty @ref PlaymatInfo::card when * nothing in the chain resolves. */ -PlaymatResolution resolveEffectivePlaymat(const DeckList &deck, - const PlaymatResolution &force, - const QList &fallbackList, - PlaymatFallbackMode fallbackMode, - int rotationIndex); +PlaymatInfo resolveEffectivePlaymat(const DeckList &deck, + const PlaymatInfo &force, + const QList &fallbackList, + PlaymatFallbackMode fallbackMode, + int rotationIndex); + +/** + * @brief Resolves the playmat to display for a deck according to the user's + * collection mode (@ref PlaymatMode), combining the deck with the + * given fallback list. + * + * @param deck The deck to resolve a playmat for. + * @param fallbackList User-level fallback playmats. + * @param mode How the collection interacts with the deck-configured playmat. + * @param fallbackBehavior How @p fallbackList is picked from. + * @param rotationIndex Cursor for @c PlaymatFallbackModeRoundRobin. + * @return The effective playmat; an empty @ref PlaymatInfo::card when nothing resolves. + */ +PlaymatInfo resolvePlaymatForDeck(const DeckList &deck, + const QList &fallbackList, + PlaymatMode mode, + PlaymatFallbackMode fallbackBehavior, + int rotationIndex); #endif // COCKATRICE_PLAYMAT_RESOLVER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_interface_settings_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_interface_settings_provider.h index 8f291332d..bc2118cb3 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_interface_settings_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_interface_settings_provider.h @@ -6,6 +6,36 @@ #include #include +/** + * @brief Whether playmats are rendered in-game, and for whom. + */ +enum PlaymatVisibility +{ + PlaymatVisibilityNone = 0, ///< Don't use playmats. + PlaymatVisibilityOwnOnly = 1, ///< Show the local player's playmat only. + PlaymatVisibilityAll = 2 ///< Show playmats for all players. +}; + +/** + * @brief How the user-level playmat collection interacts with the deck-configured playmat. + */ +enum PlaymatMode +{ + PlaymatModeOverrideDeck = 0, ///< Always use the collection, ignoring any deck-configured playmat. + PlaymatModeFallback = 1, ///< Prefer the deck-configured playmat; fall back to the collection when absent. + PlaymatModeDeckOnly = 2 ///< Use only the deck-configured playmat, ignoring the collection. +}; + +/** + * @brief How the user-level fallback playmat list is consulted when a deck has no playmat configured. + */ +enum PlaymatFallbackMode +{ + PlaymatFallbackModeFixed = 0, ///< Always use the first entry of the fallback list. + PlaymatFallbackModeRoundRobin = 1, ///< Cycle through the list, advancing one entry per resolution. + PlaymatFallbackModeRandom = 2 ///< Pick a random entry per resolution. +}; + class IInterfaceSettingsProvider { public: @@ -45,17 +75,20 @@ public: [[nodiscard]] virtual bool getLifeCounterAnimationsEnabled() const = 0; [[nodiscard]] virtual bool getBattlefieldFlashEnabled() const = 0; [[nodiscard]] virtual QStringList getUserListExpandedSections() const = 0; + + /** @brief Who gets playmats rendered: @ref PlaymatVisibility. */ [[nodiscard]] virtual int getPlaymatVisibility() const = 0; /** @brief User-level playmat collection. Used either as a forced playmat - * (mode == Always) or as a fallback when a deck has none (mode == Fallback). */ - [[nodiscard]] virtual QList getPlaymatFallbackList() const = 0; + * (mode == @ref PlaymatModeOverrideDeck) or as a fallback when a deck has none + * (mode == @ref PlaymatModeFallback). */ + [[nodiscard]] virtual QList getPlaymatFallbackList() const = 0; - /** @brief How the fallback list is applied: Always (0), Fallback (1), Never (2). */ + /** @brief How the fallback list is applied: @ref PlaymatMode. */ [[nodiscard]] virtual int getPlaymatMode() const = 0; - /** @brief How the fallback list is picked from when mode is Fallback - * (0 Fixed, 1 Round-robin, 2 Random). */ + /** @brief How the fallback list is picked from when mode is @ref PlaymatModeFallback: + * @ref PlaymatFallbackMode. */ [[nodiscard]] virtual int getPlaymatFallbackBehavior() const = 0; }; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index 84729984e..cafa33c07 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -618,7 +618,7 @@ Server_Player::cmdSetPlaymat(const Command_SetPlaymat &cmd, ResponseContainer &r if (rawName.length() > MAX_NAME_LENGTH || rawProviderId.length() > MAX_NAME_LENGTH) { return Response::RespInvalidData; } - PlaymatResolution playmat; + PlaymatInfo playmat; playmat.card.name = rawName; playmat.card.providerId = rawProviderId; playmat.params.marginPctL = qBound(0.0, pp.margin_pct_l(), 0.95); diff --git a/libcockatrice_settings/libcockatrice/settings/interface_settings.cpp b/libcockatrice_settings/libcockatrice/settings/interface_settings.cpp index 44572685d..b92a5fdec 100644 --- a/libcockatrice_settings/libcockatrice/settings/interface_settings.cpp +++ b/libcockatrice_settings/libcockatrice/settings/interface_settings.cpp @@ -2,9 +2,9 @@ namespace { -const QChar PLAYMAT_FIELD_SEP = QChar(0x1F); ///< Separator between PlaymatResolution fields. +const QChar PLAYMAT_FIELD_SEP = QChar(0x1F); ///< Separator between PlaymatInfo fields. -QString encodePlaymatResolution(const PlaymatResolution &res) +QString encodePlaymatInfo(const PlaymatInfo &res) { return res.card.name + PLAYMAT_FIELD_SEP + res.card.providerId + PLAYMAT_FIELD_SEP + QString::number(res.params.marginPctL, 'f', 4) + PLAYMAT_FIELD_SEP + @@ -13,13 +13,13 @@ QString encodePlaymatResolution(const PlaymatResolution &res) QString::number(res.params.zoom, 'f', 4); } -PlaymatResolution decodePlaymatResolution(const QString &encoded) +PlaymatInfo decodePlaymatInfo(const QString &encoded) { const QStringList fields = encoded.split(PLAYMAT_FIELD_SEP); if (fields.size() != 6) { return {}; } - PlaymatResolution res; + PlaymatInfo res; res.card.name = fields.at(0); res.card.providerId = fields.at(1); res.params.marginPctL = fields.at(2).toDouble(); @@ -192,16 +192,16 @@ bool InterfaceSettings::getShowGameSelectorFilterToolbar() const int InterfaceSettings::getPlaymatVisibility() const { - return getValue("playmatvisibility", QString(), QString(), 2).toInt(); + return qBound(0, getValue("playmatvisibility", QString(), QString(), 2).toInt(), 2); } -QList InterfaceSettings::getPlaymatFallbackList() const +QList InterfaceSettings::getPlaymatFallbackList() const { const QStringList entries = getValue("playmatFallbackList", QString(), QString(), QStringList()).toStringList(); - QList result; + QList result; result.reserve(entries.size()); for (const QString &entry : entries) { - const PlaymatResolution res = decodePlaymatResolution(entry); + const PlaymatInfo res = decodePlaymatInfo(entry); if (!res.card.isEmpty()) { result.append(res); } @@ -411,12 +411,12 @@ void InterfaceSettings::setPlaymatVisibility(int _visibility) emit playmatVisibilityChanged(_visibility); } -void InterfaceSettings::setPlaymatFallbackList(const QList &_fallbackList) +void InterfaceSettings::setPlaymatFallbackList(const QList &_fallbackList) { QStringList entries; entries.reserve(_fallbackList.size()); - for (const PlaymatResolution &res : _fallbackList) { - entries.append(encodePlaymatResolution(res)); + for (const PlaymatInfo &res : _fallbackList) { + entries.append(encodePlaymatInfo(res)); } setValue(entries, "playmatFallbackList"); emit playmatSettingsChanged(); diff --git a/libcockatrice_settings/libcockatrice/settings/interface_settings.h b/libcockatrice_settings/libcockatrice/settings/interface_settings.h index a46213f81..6b226f307 100644 --- a/libcockatrice_settings/libcockatrice/settings/interface_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/interface_settings.h @@ -43,7 +43,7 @@ public: [[nodiscard]] bool getShowShortcuts() const override; [[nodiscard]] bool getShowGameSelectorFilterToolbar() const override; [[nodiscard]] int getPlaymatVisibility() const override; - [[nodiscard]] QList getPlaymatFallbackList() const override; + [[nodiscard]] QList getPlaymatFallbackList() const override; [[nodiscard]] int getPlaymatMode() const override; [[nodiscard]] int getPlaymatFallbackBehavior() const override; [[nodiscard]] bool getLifeCounterAnimationsEnabled() const override; @@ -82,7 +82,7 @@ public: void setShowShortcuts(bool _showShortcuts); void setShowGameSelectorFilterToolbar(bool _showGameSelectorFilterToolbar); void setPlaymatVisibility(int _visibility); - void setPlaymatFallbackList(const QList &_fallbackList); + void setPlaymatFallbackList(const QList &_fallbackList); void setPlaymatMode(int _mode); void setPlaymatFallbackBehavior(int _behavior); void setLifeCounterAnimationsEnabled(bool _lifeCounterAnimationsEnabled); diff --git a/libcockatrice_utility/libcockatrice/utility/playmat_params.h b/libcockatrice_utility/libcockatrice/utility/playmat_params.h index 0219b9f9d..c64a6f2ae 100644 --- a/libcockatrice_utility/libcockatrice/utility/playmat_params.h +++ b/libcockatrice_utility/libcockatrice/utility/playmat_params.h @@ -34,16 +34,16 @@ struct PlaymatParams }; /** - * @struct PlaymatResolution + * @struct PlaymatInfo * @ingroup Decks * @brief A resolved playmat (card + positioning parameters). */ -struct PlaymatResolution +struct PlaymatInfo { CardRef card; ///< The card whose art is used as playmat. PlaymatParams params; ///< Positioning parameters for the playmat card image. - bool operator==(const PlaymatResolution &other) const + bool operator==(const PlaymatInfo &other) const { return card == other.card && params == other.params; } diff --git a/tests/playmat_resolver_test.cpp b/tests/playmat_resolver_test.cpp index 21a9f0ecd..a931c0647 100644 --- a/tests/playmat_resolver_test.cpp +++ b/tests/playmat_resolver_test.cpp @@ -5,11 +5,11 @@ namespace { -PlaymatResolution makeResolution(const QString &name, const QString &providerId = QString()) +PlaymatInfo makePlaymatInfo(const QString &name, const QString &providerId = QString()) { - PlaymatResolution resolution; - resolution.card = {name, providerId}; - return resolution; + PlaymatInfo info; + info.card = {name, providerId}; + return info; } } // namespace @@ -17,7 +17,7 @@ PlaymatResolution makeResolution(const QString &name, const QString &providerId TEST(PlaymatResolverTest, EmptyChainReturnsEmpty) { DeckList deck; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, {}, PlaymatFallbackMode::Fixed, 0); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, {}, PlaymatFallbackModeFixed, 0); EXPECT_TRUE(resolved.card.isEmpty()); } @@ -26,10 +26,10 @@ TEST(PlaymatResolverTest, OverrideWinsOverDeckAndFallback) DeckList deck; deck.setPlaymat({{QStringLiteral("Deck Mat"), QStringLiteral("deck-provider")}, {}}); - const PlaymatResolution force = makeResolution(QStringLiteral("Force Mat"), QStringLiteral("force-provider")); - const QList fallback = {makeResolution(QStringLiteral("Fallback Mat"))}; + const PlaymatInfo force = makePlaymatInfo(QStringLiteral("Force Mat"), QStringLiteral("force-provider")); + const QList fallback = {makePlaymatInfo(QStringLiteral("Fallback Mat"))}; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, force, fallback, PlaymatFallbackMode::Fixed, 0); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, force, fallback, PlaymatFallbackModeFixed, 0); EXPECT_EQ(resolved.card.name, QStringLiteral("Force Mat")); EXPECT_EQ(resolved.card.providerId, QStringLiteral("force-provider")); } @@ -39,9 +39,9 @@ TEST(PlaymatResolverTest, DeckWinsOverFallback) DeckList deck; deck.setPlaymat({{QStringLiteral("Deck Mat"), QStringLiteral("deck-provider")}, {0.1, 0.2, 0.3, 1.5}}); - const QList fallback = {makeResolution(QStringLiteral("Fallback Mat"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("Fallback Mat"))}; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::Fixed, 0); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeFixed, 0); EXPECT_EQ(resolved.card.name, QStringLiteral("Deck Mat")); EXPECT_EQ(resolved.card.providerId, QStringLiteral("deck-provider")); EXPECT_DOUBLE_EQ(resolved.params.marginPctL, 0.1); @@ -51,20 +51,20 @@ TEST(PlaymatResolverTest, DeckWinsOverFallback) TEST(PlaymatResolverTest, FallbackUsedWhenDeckHasNone) { DeckList deck; - const QList fallback = {makeResolution(QStringLiteral("Fallback Mat"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("Fallback Mat"))}; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::Fixed, 0); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeFixed, 0); EXPECT_EQ(resolved.card.name, QStringLiteral("Fallback Mat")); } TEST(PlaymatResolverTest, FixedAlwaysUsesFirst) { DeckList deck; - const QList fallback = {makeResolution(QStringLiteral("First")), - makeResolution(QStringLiteral("Second"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("First")), + makePlaymatInfo(QStringLiteral("Second"))}; for (int i = 0; i < 5; ++i) { - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::Fixed, i); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeFixed, i); EXPECT_EQ(resolved.card.name, QStringLiteral("First")); } } @@ -72,15 +72,14 @@ TEST(PlaymatResolverTest, FixedAlwaysUsesFirst) TEST(PlaymatResolverTest, RoundRobinCyclesAndWraps) { DeckList deck; - const QList fallback = {makeResolution(QStringLiteral("First")), - makeResolution(QStringLiteral("Second")), - makeResolution(QStringLiteral("Third"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("First")), + makePlaymatInfo(QStringLiteral("Second")), + makePlaymatInfo(QStringLiteral("Third"))}; const QStringList expected = {QStringLiteral("First"), QStringLiteral("Second"), QStringLiteral("Third"), QStringLiteral("First"), QStringLiteral("Second"), QStringLiteral("Third")}; for (int i = 0; i < expected.size(); ++i) { - const PlaymatResolution resolved = - resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::RoundRobin, i); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeRoundRobin, i); EXPECT_EQ(resolved.card.name, expected.at(i)); } } @@ -88,22 +87,22 @@ TEST(PlaymatResolverTest, RoundRobinCyclesAndWraps) TEST(PlaymatResolverTest, RoundRobinRespectsCursor) { DeckList deck; - const QList fallback = {makeResolution(QStringLiteral("First")), - makeResolution(QStringLiteral("Second"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("First")), + makePlaymatInfo(QStringLiteral("Second"))}; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::RoundRobin, 5); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeRoundRobin, 5); EXPECT_EQ(resolved.card.name, QStringLiteral("Second")); // 5 % 2 == 1 } TEST(PlaymatResolverTest, RandomStaysWithinList) { DeckList deck; - const QList fallback = {makeResolution(QStringLiteral("First")), - makeResolution(QStringLiteral("Second")), - makeResolution(QStringLiteral("Third"))}; + const QList fallback = {makePlaymatInfo(QStringLiteral("First")), + makePlaymatInfo(QStringLiteral("Second")), + makePlaymatInfo(QStringLiteral("Third"))}; for (int i = 0; i < 50; ++i) { - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackMode::Random, i); + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, {}, fallback, PlaymatFallbackModeRandom, i); ASSERT_FALSE(resolved.card.name.isEmpty()); EXPECT_TRUE(fallback.contains(resolved)); } @@ -115,8 +114,8 @@ TEST(PlaymatResolverTest, ForceWithEmptyCardIgnoresFallbackParamsButNotFallback) deck.setPlaymat({{QStringLiteral("Deck Mat")}, {}}); // An empty force entry must not mask the deck-configured playmat. - const PlaymatResolution emptyForce; - const PlaymatResolution resolved = resolveEffectivePlaymat(deck, emptyForce, {}, PlaymatFallbackMode::Fixed, 0); + const PlaymatInfo emptyForce; + const PlaymatInfo resolved = resolveEffectivePlaymat(deck, emptyForce, {}, PlaymatFallbackModeFixed, 0); EXPECT_EQ(resolved.card.name, QStringLiteral("Deck Mat")); }