mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-27 00:14:40 -07:00
Merge branch 'master' into tooomm-qt5
This commit is contained in:
commit
3bc08ef94c
357 changed files with 23069 additions and 2916 deletions
|
|
@ -11,6 +11,7 @@ set(HEADERS
|
|||
libcockatrice/deck_list/deck_list_history_manager.h
|
||||
libcockatrice/deck_list/deck_list_node_tree.h
|
||||
libcockatrice/deck_list/deck_list_memento.h
|
||||
libcockatrice/deck_list/playmat_resolver.h
|
||||
libcockatrice/deck_list/sideboard_plan.h
|
||||
)
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ add_library(
|
|||
libcockatrice/deck_list/deck_list.cpp
|
||||
libcockatrice/deck_list/deck_list_history_manager.cpp
|
||||
libcockatrice/deck_list/deck_list_node_tree.cpp
|
||||
libcockatrice/deck_list/playmat_resolver.cpp
|
||||
libcockatrice/deck_list/sideboard_plan.cpp
|
||||
)
|
||||
|
||||
|
|
@ -33,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}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ static const QString CURRENT_SIDEBOARD_PLAN_KEY = "";
|
|||
|
||||
bool DeckList::Metadata::isEmpty() const
|
||||
{
|
||||
return name.isEmpty() && comments.isEmpty() && bannerCard.isEmpty() && tags.isEmpty();
|
||||
return name.isEmpty() && comments.isEmpty() && bannerCard.isEmpty() && tags.isEmpty() && playmat.card.isEmpty();
|
||||
}
|
||||
|
||||
DeckList::DeckList()
|
||||
|
|
@ -66,6 +66,36 @@ bool DeckList::readElement(QXmlStreamReader *xml)
|
|||
QString providerId = xml->attributes().value("providerId").toString();
|
||||
QString cardName = xml->readElementText();
|
||||
metadata.bannerCard = {cardName, providerId};
|
||||
} else if (childName == "playmatCard") {
|
||||
QString providerId = xml->attributes().value("providerId").toString();
|
||||
bool ok;
|
||||
QString marginLStr = xml->attributes().value("marginPctL").toString();
|
||||
QString marginRStr = xml->attributes().value("marginPctR").toString();
|
||||
QString vOffStr = xml->attributes().value("verticalOffset").toString();
|
||||
QString zoomStr = xml->attributes().value("zoom").toString();
|
||||
QString cardName = xml->readElementText();
|
||||
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
|
||||
// degenerate art rectangles (e.g. a zoom of 0 dividing by zero).
|
||||
playmat.params.marginPctL = qBound(0.0, marginLStr.toDouble(&ok), 0.95);
|
||||
if (!ok) {
|
||||
playmat.params.marginPctL = 0.07;
|
||||
}
|
||||
playmat.params.marginPctR = qBound(0.0, marginRStr.toDouble(&ok), 0.95);
|
||||
if (!ok) {
|
||||
playmat.params.marginPctR = 0.07;
|
||||
}
|
||||
playmat.params.verticalOffset = qBound(0.0, vOffStr.toDouble(&ok), 1.0);
|
||||
if (!ok) {
|
||||
playmat.params.verticalOffset = 0.33;
|
||||
}
|
||||
playmat.params.zoom = qBound(0.1, zoomStr.toDouble(&ok), 4.0);
|
||||
if (!ok) {
|
||||
playmat.params.zoom = 1.0;
|
||||
}
|
||||
metadata.playmat = playmat;
|
||||
} else if (childName == "tags") {
|
||||
metadata.tags.clear(); // Clear existing tags
|
||||
while (xml->readNextStartElement()) {
|
||||
|
|
@ -96,6 +126,16 @@ static void writeMetadata(QXmlStreamWriter *xml, const DeckList::Metadata &metad
|
|||
xml->writeAttribute("providerId", metadata.bannerCard.providerId);
|
||||
xml->writeCharacters(metadata.bannerCard.name);
|
||||
xml->writeEndElement();
|
||||
if (!metadata.playmat.card.isEmpty()) {
|
||||
xml->writeStartElement("playmatCard");
|
||||
xml->writeAttribute("providerId", metadata.playmat.card.providerId);
|
||||
xml->writeAttribute("marginPctL", QString::number(metadata.playmat.params.marginPctL, 'f', 4));
|
||||
xml->writeAttribute("marginPctR", QString::number(metadata.playmat.params.marginPctR, 'f', 4));
|
||||
xml->writeAttribute("verticalOffset", QString::number(metadata.playmat.params.verticalOffset, 'f', 4));
|
||||
xml->writeAttribute("zoom", QString::number(metadata.playmat.params.zoom, 'f', 4));
|
||||
xml->writeCharacters(metadata.playmat.card.name);
|
||||
xml->writeEndElement();
|
||||
}
|
||||
xml->writeTextElement("comments", metadata.comments);
|
||||
|
||||
// Write tags
|
||||
|
|
@ -365,6 +405,10 @@ bool DeckList::loadFromFile_Plain(QIODevice *device, const std::function<QString
|
|||
bool DeckList::saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards) const
|
||||
{
|
||||
auto writeToStream = [&stream, prefixSideboardCards, slashTappedOutSplitCards](const auto node, const auto card) {
|
||||
// The maybeboard is scratch space and never exported.
|
||||
if (node->getName() == DECK_ZONE_MAYBEBOARD) {
|
||||
return;
|
||||
}
|
||||
if (prefixSideboardCards && node->getName() == DECK_ZONE_SIDE) {
|
||||
stream << "SB: ";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QtCore/QXmlStreamReader>
|
||||
#include <libcockatrice/utility/card_ref.h>
|
||||
#include <libcockatrice/utility/playmat_params.h>
|
||||
|
||||
class AbstractDecklistNode;
|
||||
class DecklistCardNode;
|
||||
|
|
@ -70,6 +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.
|
||||
PlaymatInfo playmat; ///< Optional playmat background for table+stack zones.
|
||||
|
||||
/**
|
||||
* @brief Checks if all values (except for lastLoadedTimestamp) in the metadata is empty.
|
||||
|
|
@ -115,6 +116,10 @@ public:
|
|||
{
|
||||
metadata.bannerCard = _bannerCard;
|
||||
}
|
||||
void setPlaymat(const PlaymatInfo &_playmat = {})
|
||||
{
|
||||
metadata.playmat = _playmat;
|
||||
}
|
||||
void setLastLoadedTimestamp(const QString &_lastLoadedTimestamp = QString())
|
||||
{
|
||||
metadata.lastLoadedTimestamp = _lastLoadedTimestamp;
|
||||
|
|
@ -170,6 +175,10 @@ public:
|
|||
{
|
||||
return metadata.bannerCard;
|
||||
}
|
||||
PlaymatInfo getPlaymat() const
|
||||
{
|
||||
return metadata.playmat;
|
||||
}
|
||||
QString getLastLoadedTimestamp() const
|
||||
{
|
||||
return metadata.lastLoadedTimestamp;
|
||||
|
|
|
|||
|
|
@ -41,13 +41,19 @@ QList<const DecklistCardNode *> DecklistNodeTree::getCardNodes(const QSet<QStrin
|
|||
{
|
||||
QList<const DecklistCardNode *> result;
|
||||
|
||||
for (auto *zoneNode : getZoneNodes(restrictToZones)) {
|
||||
for (auto *cardNode : *zoneNode) {
|
||||
auto *cardCardNode = dynamic_cast<DecklistCardNode *>(cardNode);
|
||||
if (cardCardNode) {
|
||||
result.append(cardCardNode);
|
||||
std::function<void(const InnerDecklistNode *)> collectCards = [&collectCards,
|
||||
&result](const InnerDecklistNode *node) {
|
||||
for (int i = 0; i < node->size(); i++) {
|
||||
if (auto *card = dynamic_cast<const DecklistCardNode *>(node->at(i))) {
|
||||
result.append(card);
|
||||
} else if (auto *inner = dynamic_cast<const InnerDecklistNode *>(node->at(i))) {
|
||||
collectCards(inner);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (auto *zoneNode : getZoneNodes(restrictToZones)) {
|
||||
collectCards(zoneNode);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -139,7 +145,8 @@ bool DecklistNodeTree::deleteNode(AbstractDecklistNode *node, InnerDecklistNode
|
|||
if (index != -1) {
|
||||
delete rootNode->takeAt(index);
|
||||
|
||||
if (rootNode->empty()) {
|
||||
// Empty custom zones are kept while empty board zones get pruned.
|
||||
if (rootNode->empty() && rootNode->getParent() == root) {
|
||||
deleteNode(rootNode, rootNode->getParent());
|
||||
}
|
||||
|
||||
|
|
@ -160,28 +167,179 @@ bool DecklistNodeTree::deleteNode(AbstractDecklistNode *node, InnerDecklistNode
|
|||
|
||||
void DecklistNodeTree::forEachCard(const std::function<void(InnerDecklistNode *, DecklistCardNode *)> &func) const
|
||||
{
|
||||
// Support for this is only possible if the internal structure
|
||||
// doesn't get more complicated.
|
||||
// Cards nested in custom zones are reported with their top-level board zone
|
||||
// so that callers can classify cards by board (main/side/maybeboard/tokens).
|
||||
std::function<void(InnerDecklistNode *, InnerDecklistNode *)> walk = [&func, &walk](InnerDecklistNode *boardZone,
|
||||
InnerDecklistNode *node) {
|
||||
for (int i = 0; i < node->size(); i++) {
|
||||
if (auto *card = dynamic_cast<DecklistCardNode *>(node->at(i))) {
|
||||
func(boardZone, card);
|
||||
} else if (auto *inner = dynamic_cast<InnerDecklistNode *>(node->at(i))) {
|
||||
walk(boardZone, inner);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < root->size(); i++) {
|
||||
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||
for (int j = 0; j < node->size(); j++) {
|
||||
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
|
||||
func(node, card);
|
||||
if (auto *zone = dynamic_cast<InnerDecklistNode *>(root->at(i))) {
|
||||
walk(zone, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the InnerDecklistNode that is the root node for the given zone, creating a new node if it doesn't exist.
|
||||
*
|
||||
* Top-level zones take precedence, then deck-unique custom zones nested under boards
|
||||
* are resolved. Unknown names create a new top-level zone (legacy behavior).
|
||||
*/
|
||||
InnerDecklistNode *DecklistNodeTree::getZoneObjFromName(const QString &zoneName) const
|
||||
{
|
||||
for (int i = 0; i < root->size(); i++) {
|
||||
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||
if (node->getName() == zoneName) {
|
||||
if (node && node->getName() == zoneName) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *customZone = findCustomZoneByName(zoneName)) {
|
||||
return customZone;
|
||||
}
|
||||
|
||||
return new InnerDecklistNode(zoneName, root);
|
||||
}
|
||||
|
||||
InnerDecklistNode *DecklistNodeTree::findBoardZone(const QString &boardZoneName) const
|
||||
{
|
||||
return dynamic_cast<InnerDecklistNode *>(root->findChild(boardZoneName));
|
||||
}
|
||||
|
||||
InnerDecklistNode *DecklistNodeTree::findOrCreateBoardZone(const QString &boardZoneName)
|
||||
{
|
||||
auto *boardZone = findBoardZone(boardZoneName);
|
||||
if (!boardZone &&
|
||||
(boardZoneName == DECK_ZONE_MAYBEBOARD || boardZoneName == DECK_ZONE_MAIN || boardZoneName == DECK_ZONE_SIDE)) {
|
||||
// The boards are lazy zones: they only exist once cards or custom zones need them.
|
||||
boardZone = new InnerDecklistNode(boardZoneName, root);
|
||||
}
|
||||
return boardZone;
|
||||
}
|
||||
|
||||
InnerDecklistNode *DecklistNodeTree::addCustomZone(const QString &boardZoneName, const QString &zoneName)
|
||||
{
|
||||
if (hasZoneName(zoneName)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *boardZone = findOrCreateBoardZone(boardZoneName);
|
||||
|
||||
if (!boardZone) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new InnerDecklistNode(zoneName, boardZone);
|
||||
}
|
||||
|
||||
bool DecklistNodeTree::renameCustomZone(const QString &oldZoneName, const QString &newZoneName)
|
||||
{
|
||||
if (hasZoneName(newZoneName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *zone = findCustomZoneByName(oldZoneName);
|
||||
if (!zone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zone->setName(newZoneName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecklistNodeTree::moveCustomZone(const QString &zoneName, const QString &newBoardZoneName)
|
||||
{
|
||||
auto *zone = findCustomZoneByName(zoneName);
|
||||
if (!zone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *currentBoardZone = zone->getParent();
|
||||
if (currentBoardZone && currentBoardZone->getName() == newBoardZoneName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *newBoardZone = findOrCreateBoardZone(newBoardZoneName);
|
||||
if (!newBoardZone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
currentBoardZone->removeOne(zone);
|
||||
newBoardZone->append(zone);
|
||||
zone->setParent(newBoardZone);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecklistNodeTree::removeCustomZone(const QString &zoneName)
|
||||
{
|
||||
auto *zone = findCustomZoneByName(zoneName);
|
||||
if (!zone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detach and delete without pruning the board zone.
|
||||
auto *boardZone = zone->getParent();
|
||||
boardZone->removeOne(zone);
|
||||
delete zone;
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<const InnerDecklistNode *> DecklistNodeTree::getCustomZones(const QString &boardZoneName) const
|
||||
{
|
||||
QList<const InnerDecklistNode *> result;
|
||||
|
||||
auto *boardZone = findBoardZone(boardZoneName);
|
||||
if (!boardZone) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < boardZone->size(); i++) {
|
||||
if (auto *customZone = dynamic_cast<InnerDecklistNode *>(boardZone->at(i))) {
|
||||
result.append(customZone);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
InnerDecklistNode *DecklistNodeTree::findCustomZoneByName(const QString &zoneName) const
|
||||
{
|
||||
for (int i = 0; i < root->size(); i++) {
|
||||
auto *boardZone = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||
if (!boardZone) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < boardZone->size(); j++) {
|
||||
auto *customZone = dynamic_cast<InnerDecklistNode *>(boardZone->at(j));
|
||||
if (customZone && customZone->getName() == zoneName) {
|
||||
return customZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DecklistNodeTree::hasZoneName(const QString &zoneName) const
|
||||
{
|
||||
// The standard zones are reserved names even before they are created lazily.
|
||||
if (zoneName == DECK_ZONE_MAIN || zoneName == DECK_ZONE_SIDE || zoneName == DECK_ZONE_MAYBEBOARD ||
|
||||
zoneName == DECK_ZONE_TOKENS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (root->findChild(zoneName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return findCustomZoneByName(zoneName) != nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,15 +78,57 @@ public:
|
|||
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Apply a function to every card in the deck tree. This can modify the cards.
|
||||
* @brief Creates a new custom zone nested under a board zone.
|
||||
*
|
||||
* @param func Function taking (zone node, card node).
|
||||
* Custom zone names must be unique across the whole deck so that cards can be
|
||||
* added to a custom zone without specifying its board zone.
|
||||
*
|
||||
* @param boardZoneName Name of the board zone (e.g. DECK_ZONE_MAIN).
|
||||
* @param zoneName Name of the custom zone.
|
||||
* @return The created zone node, or nullptr if the name is already in use.
|
||||
*/
|
||||
InnerDecklistNode *addCustomZone(const QString &boardZoneName, const QString &zoneName);
|
||||
|
||||
/**
|
||||
* @brief Renames a custom zone.
|
||||
* @return true on success, false if the zone was not found or the new name is taken.
|
||||
*/
|
||||
bool renameCustomZone(const QString &oldZoneName, const QString &newZoneName);
|
||||
|
||||
/**
|
||||
* @brief Moves a custom zone (and all its cards) to another board zone.
|
||||
* @return true on success, false if the zone or the new board zone was not found.
|
||||
*/
|
||||
bool moveCustomZone(const QString &zoneName, const QString &newBoardZoneName);
|
||||
|
||||
/**
|
||||
* @brief Removes a custom zone and all its cards.
|
||||
* @return true if the zone was found and removed.
|
||||
*/
|
||||
bool removeCustomZone(const QString &zoneName);
|
||||
|
||||
/**
|
||||
* @brief Gets all custom zones nested under a board zone.
|
||||
* @param boardZoneName Name of the board zone.
|
||||
* @return The custom zones, in insertion order.
|
||||
*/
|
||||
QList<const InnerDecklistNode *> getCustomZones(const QString &boardZoneName) const;
|
||||
|
||||
/**
|
||||
* @brief Applies a function to every card in the deck tree. This can modify the cards.
|
||||
*
|
||||
* @param func Function taking (top-level board zone node, card node). Cards nested
|
||||
* in custom zones are reported with their board zone.
|
||||
*/
|
||||
void forEachCard(const std::function<void(InnerDecklistNode *, DecklistCardNode *)> &func) const;
|
||||
|
||||
private:
|
||||
// Helpers for traversing the tree
|
||||
InnerDecklistNode *getZoneObjFromName(const QString &zoneName) const;
|
||||
InnerDecklistNode *findBoardZone(const QString &boardZoneName) const;
|
||||
InnerDecklistNode *findOrCreateBoardZone(const QString &boardZoneName);
|
||||
InnerDecklistNode *findCustomZoneByName(const QString &zoneName) const;
|
||||
bool hasZoneName(const QString &zoneName) const;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_DECKLIST_NODE_TREE_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
#include "playmat_resolver.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
|
||||
PlaymatInfo resolveEffectivePlaymat(const DeckList &deck,
|
||||
const PlaymatInfo &force,
|
||||
const QList<PlaymatInfo> &fallbackList,
|
||||
PlaymatFallbackMode fallbackMode,
|
||||
int rotationIndex)
|
||||
{
|
||||
if (!force.card.isEmpty()) {
|
||||
return force;
|
||||
}
|
||||
|
||||
const PlaymatInfo &deckPlaymat = deck.getPlaymat();
|
||||
if (!deckPlaymat.card.isEmpty()) {
|
||||
return deckPlaymat;
|
||||
}
|
||||
|
||||
if (fallbackList.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
switch (fallbackMode) {
|
||||
case PlaymatFallbackModeFixed:
|
||||
return fallbackList.first();
|
||||
case PlaymatFallbackModeRoundRobin:
|
||||
return fallbackList.at(rotationIndex % fallbackList.size());
|
||||
case PlaymatFallbackModeRandom:
|
||||
return fallbackList.at(QRandomGenerator::global()->bounded(fallbackList.size()));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
PlaymatInfo resolvePlaymatForDeck(const DeckList &deck,
|
||||
const QList<PlaymatInfo> &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 {};
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef COCKATRICE_PLAYMAT_RESOLVER_H
|
||||
#define COCKATRICE_PLAYMAT_RESOLVER_H
|
||||
|
||||
#include "deck_list.h"
|
||||
|
||||
#include <libcockatrice/interfaces/interface_interface_settings_provider.h>
|
||||
|
||||
/**
|
||||
* @brief Resolves the effective playmat for a deck per the resolution chain:
|
||||
* force override > deck-configured playmat > fallback list > none.
|
||||
*
|
||||
* @param deck The deck to resolve a playmat for.
|
||||
* @param force An optional user-level override; wins over everything. Pass an
|
||||
* 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 PlaymatFallbackModeRoundRobin;
|
||||
* advanced once per call. Unused for the other modes.
|
||||
* @return The effective playmat; an empty @ref PlaymatInfo::card when
|
||||
* nothing in the chain resolves.
|
||||
*/
|
||||
PlaymatInfo resolveEffectivePlaymat(const DeckList &deck,
|
||||
const PlaymatInfo &force,
|
||||
const QList<PlaymatInfo> &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<PlaymatInfo> &fallbackList,
|
||||
PlaymatMode mode,
|
||||
PlaymatFallbackMode fallbackBehavior,
|
||||
int rotationIndex);
|
||||
|
||||
#endif // COCKATRICE_PLAYMAT_RESOLVER_H
|
||||
|
|
@ -142,6 +142,12 @@ public:
|
|||
return parent;
|
||||
}
|
||||
|
||||
/** @param newParent Reparent this node. The new parent takes ownership. */
|
||||
void setParent(InnerDecklistNode *newParent)
|
||||
{
|
||||
parent = newParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the depth of this node in the tree.
|
||||
* @return Distance from the root (root = 0, children = 1, etc.).
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ QString InnerDecklistNode::visibleNameFromName(const QString &_name)
|
|||
return QObject::tr("Sideboard");
|
||||
} else if (_name == DECK_ZONE_TOKENS) {
|
||||
return QObject::tr("Tokens");
|
||||
} else if (_name == DECK_ZONE_MAYBEBOARD) {
|
||||
return QObject::tr("Maybeboard");
|
||||
} else {
|
||||
return _name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#define DECK_ZONE_SIDE "side"
|
||||
/** @brief Constant for the "tokens" zone name. */
|
||||
#define DECK_ZONE_TOKENS "tokens"
|
||||
/** @brief Constant for the "maybeboard" zone name. */
|
||||
#define DECK_ZONE_MAYBEBOARD "maybeboard"
|
||||
|
||||
/**
|
||||
* @class InnerDecklistNode
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue