Comments.

Took 14 minutes

Took 8 seconds
This commit is contained in:
Lukas Brübach 2026-08-20 08:56:25 +02:00
parent 80d44da729
commit daaee6ac82
9 changed files with 83 additions and 55 deletions

View file

@ -252,17 +252,27 @@ void GameScene::adjustPlayerRotation(int rotationAdjustment)
*/
void GameScene::rearrange()
{
int firstPlayerIndex = 0;
auto playersPlaying = collectActivePlayers(firstPlayerIndex);
playersPlaying = rotatePlayers(playersPlaying, firstPlayerIndex);
if (rearranging) {
needsReArrange = true;
return;
}
rearranging = true;
do {
needsReArrange = false;
int columns = determineColumnCount(playersPlaying.size());
QSizeF sceneSize = computeSceneSizeAndPlayerLayout(playersPlaying, columns);
int firstPlayerIndex = 0;
auto playersPlaying = collectActivePlayers(firstPlayerIndex);
playersPlaying = rotatePlayers(playersPlaying, firstPlayerIndex);
phasesToolbar->setHeight(sceneSize.height());
setSceneRect(0, 0, sceneSize.width(), sceneSize.height());
int columns = determineColumnCount(playersPlaying.size());
QSizeF sceneSize = computeSceneSizeAndPlayerLayout(playersPlaying, columns);
processViewSizeChange(viewSize);
phasesToolbar->setHeight(sceneSize.height());
setSceneRect(0, 0, sceneSize.width(), sceneSize.height());
processViewSizeChange(viewSize);
} while (needsReArrange);
rearranging = false;
}
// ---------- View Size ----------

View file

@ -55,6 +55,8 @@ private:
QBasicTimer *animationTimer; ///< Timer for scene animations
QHash<QObject *, IAnimatedItem *> animatedItems; ///< Items currently animating
int playerRotation; ///< Rotation offset for player layout
bool rearranging = false; ///< Guard against re-entrant rearrange
bool needsReArrange = false; ///< Pending rearrange requested during a pass
/**
* @brief Updates which card is currently hovered based on scene coordinates.

View file

@ -114,6 +114,7 @@ void GameView::startRubberBand(const QPointF &_selectionOrigin)
}
selectionOrigin = _selectionOrigin;
previousBandRect = QRect();
rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), QSize(0, 0)));
rubberBand->show();
}
@ -131,11 +132,13 @@ void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
rubberBand->setGeometry(rect);
if (viewport()) {
// Repaint the whole viewport rather than just the band's old area: the
// vacated strip of a child widget is not reliably invalidated on all
// platforms (notably macOS), leaving stale pixels — including black
// scene background where the playmat should show — under the selection.
viewport()->update();
// Repaint the union of the previous and current band rects: the vacated
// strip of a child widget is not reliably invalidated on all platforms
// (notably macOS), leaving stale pixels under the selection.
QRect dirty = previousBandRect.isNull() ? rect : previousBandRect.united(rect);
dirty.adjust(-1, -1, 1, 1);
viewport()->update(dirty);
previousBandRect = rect;
}
if (!SettingsCache::instance().userInterface().getShowDragSelectionCount()) {
@ -179,12 +182,12 @@ void GameView::stopRubberBand()
return;
}
// Same rationale as resizeRubberBand: make sure the whole viewport is
// repainted once the band is gone, since some platforms skip the exposed
// region update of a hidden child widget.
// Same rationale as resizeRubberBand: repaint the last known band area
// since hiding a child widget doesn't reliably invalidate its region.
rubberBand->hide();
if (viewport()) {
viewport()->update();
if (viewport() && !previousBandRect.isNull()) {
viewport()->update(previousBandRect.adjusted(-1, -1, 1, 1));
previousBandRect = QRect();
}
dragCountLabel->hide();
}

View file

@ -27,6 +27,7 @@ private:
QWidget *tallyContainer;
QGridLayout *tallyLayout;
QPointF selectionOrigin;
QRect previousBandRect; ///< Last rubber-band rect for targeted repaint
QList<TallyRow> cachedTallyRows; ///< Cached entries to avoid redundant rebuilds
QSize rebuildTallyLabels(const QList<TallyRow> &entries);

View file

@ -18,6 +18,7 @@
#include <QGraphicsView>
#include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/deck_list/deck_list.h>
#include <libcockatrice/deck_list/playmat_resolver.h>
#include <libcockatrice/settings/interface_settings.h>
PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
@ -376,6 +377,12 @@ void PlayerGraphicsItem::updatePlaymat()
return;
}
// "Show own playmat only" — hide playmats for remote players
if (visibility == 1 && !player->getPlayerInfo()->getLocal()) {
clearPlaymat();
return;
}
CardRef playmatCard;
PlaymatParams params;
@ -383,8 +390,40 @@ void PlayerGraphicsItem::updatePlaymat()
// Prefer the server-confirmed playmat (updated by Command_SetPlaymat).
playmatCard = player->getRemotePlaymatCard();
params = player->getRemotePlaymatParams();
} else if (player->getPlayerInfo()->getLocal()) {
// 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<PlaymatFallbackMode>(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;
}
}
} else {
// Fall back to the locally baked-in deck playmat.
// Opponent without a server broadcast: use the deck-embedded playmat.
const DeckList &deck = player->getDeck();
const PlaymatResolution &deckPlaymat = deck.getPlaymat();
if (!deckPlaymat.card.isEmpty()) {

View file

@ -466,13 +466,6 @@ void DeckEditorDeckDockWidget::openPlaymatSettings()
deckStateManager->setPlaymat({newCard, newParams});
}
// "Also set as my default playmat": make this the fixed user-level
// fallback, so decks without a playmat of their own use it.
if (dialog.useAsDefault() && !newCard.isEmpty()) {
auto &interfaceSettings = SettingsCache::instance().userInterface();
interfaceSettings.setPlaymatFallbackList({{newCard, newParams}});
interfaceSettings.setPlaymatFallbackBehavior(0); // PlaymatFallbackMode::Fixed
}
updatePlaymatLabel();
}
}

View file

@ -7,7 +7,6 @@
#include "card_database_model.h"
#include "playmat_preview_widget.h"
#include <QCheckBox>
#include <QComboBox>
#include <QCompleter>
#include <QDialogButtonBox>
@ -67,11 +66,6 @@ PlaymatParams PlaymatSettingsDialog::params() const
return currentParams;
}
bool PlaymatSettingsDialog::useAsDefault() const
{
return useAsDefaultCheckBox->isChecked();
}
QDoubleSpinBox *PlaymatSettingsDialog::makeSpinBox(double min, double max, double value, double step)
{
auto *spin = new QDoubleSpinBox;
@ -143,9 +137,6 @@ void PlaymatSettingsDialog::setupUi()
controlsGroup = new QGroupBox;
controlsGroup->setLayout(form);
useAsDefaultCheckBox = new QCheckBox;
useAsDefaultCheckBox->setEnabled(false);
preview = new PlaymatPreviewWidget;
auto *previewLayout = new QVBoxLayout;
@ -166,7 +157,6 @@ void PlaymatSettingsDialog::setupUi()
auto *root = new QVBoxLayout;
root->addWidget(controlsGroup);
root->addWidget(useAsDefaultCheckBox);
root->addWidget(previewGroup);
root->addWidget(buttons);
setLayout(root);
@ -206,8 +196,6 @@ void PlaymatSettingsDialog::onCardNameChanged(const QString &name)
if (name.isEmpty()) {
currentPixmap = QPixmap();
preview->setPixmap(currentPixmap);
useAsDefaultCheckBox->setChecked(false);
useAsDefaultCheckBox->setEnabled(false);
return;
}
@ -216,13 +204,10 @@ void PlaymatSettingsDialog::onCardNameChanged(const QString &name)
currentPixmap = QPixmap();
preview->setPixmap(currentPixmap);
providerComboBox->clear();
useAsDefaultCheckBox->setChecked(false);
useAsDefaultCheckBox->setEnabled(false);
return;
}
currentCard.name = name;
useAsDefaultCheckBox->setEnabled(true);
populateProviderCombo(name);
@ -287,7 +272,6 @@ void PlaymatSettingsDialog::retranslateUi()
verticalOffsetLabel->setText(tr("Vertical offset:"));
zoomLabel->setText(tr("Zoom:"));
controlsGroup->setTitle(tr("Parameters"));
useAsDefaultCheckBox->setText(tr("Also set as my default playmat (for decks without one)"));
previewGroup->setTitle(tr("Preview"));
removeButton->setText(tr("Remove Playmat"));
}

View file

@ -5,7 +5,6 @@
#include <QPixmap>
#include <libcockatrice/deck_list/deck_list.h>
class QCheckBox;
class QComboBox;
class QCompleter;
class QDoubleSpinBox;
@ -39,12 +38,6 @@ public:
CardRef card() const;
PlaymatParams params() const;
/**
* @brief Whether the user also wants the configured playmat saved as the
* user-level default (fallback for decks without one).
*/
bool useAsDefault() const;
private slots:
void onCardNameChanged(const QString &name);
void reloadPreview();
@ -68,8 +61,6 @@ private:
QMetaObject::Connection pixmapUpdatedConnection;
QCheckBox *useAsDefaultCheckBox;
QLabel *cardNameLabel;
QLabel *printingLabel;
QLabel *leftMarginLabel;

View file

@ -253,8 +253,8 @@ Server_Player::cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &r
event.mutable_player_properties()->set_deck_hash(deck->getDeckHash().toStdString());
const auto &playmat = deck->getPlaymat();
auto *playmatParams = event.mutable_player_properties()->mutable_playmat_params();
playmatParams->set_card_name(playmat.card.name.toStdString());
playmatParams->set_card_provider_id(playmat.card.providerId.toStdString());
playmatParams->set_card_name(playmat.card.name.left(MAX_NAME_LENGTH).toStdString());
playmatParams->set_card_provider_id(playmat.card.providerId.left(MAX_NAME_LENGTH).toStdString());
playmatParams->set_margin_pct_l(playmat.params.marginPctL);
playmatParams->set_margin_pct_r(playmat.params.marginPctR);
playmatParams->set_vertical_offset(playmat.params.verticalOffset);
@ -613,9 +613,14 @@ Server_Player::cmdSetPlaymat(const Command_SetPlaymat &cmd, ResponseContainer &r
}
const auto &pp = cmd.playmat_params();
const auto rawName = QString::fromStdString(pp.card_name());
const auto rawProviderId = QString::fromStdString(pp.card_provider_id());
if (rawName.length() > MAX_NAME_LENGTH || rawProviderId.length() > MAX_NAME_LENGTH) {
return Response::RespInvalidData;
}
PlaymatResolution playmat;
playmat.card.name = QString::fromStdString(pp.card_name());
playmat.card.providerId = QString::fromStdString(pp.card_provider_id());
playmat.card.name = rawName;
playmat.card.providerId = rawProviderId;
playmat.params.marginPctL = qBound(0.0, pp.margin_pct_l(), 0.95);
playmat.params.marginPctR = qBound(0.0, pp.margin_pct_r(), 0.95);
playmat.params.verticalOffset = qBound(0.0, pp.vertical_offset(), 1.0);