From daaee6ac82a6d31f926dfdc1567ebd15ff73b7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Thu, 20 Aug 2026 08:56:25 +0200 Subject: [PATCH] Comments. Took 14 minutes Took 8 seconds --- cockatrice/src/game_graphics/game_scene.cpp | 26 ++++++++---- cockatrice/src/game_graphics/game_scene.h | 2 + cockatrice/src/game_graphics/game_view.cpp | 23 ++++++----- cockatrice/src/game_graphics/game_view.h | 1 + .../player/player_graphics_item.cpp | 41 ++++++++++++++++++- .../deck_editor_deck_dock_widget.cpp | 7 ---- .../playmat/playmat_settings_dialog.cpp | 16 -------- .../widgets/playmat/playmat_settings_dialog.h | 9 ---- .../server/remote/game/server_player.cpp | 13 ++++-- 9 files changed, 83 insertions(+), 55 deletions(-) diff --git a/cockatrice/src/game_graphics/game_scene.cpp b/cockatrice/src/game_graphics/game_scene.cpp index 02c2401d3..cd2b12828 100644 --- a/cockatrice/src/game_graphics/game_scene.cpp +++ b/cockatrice/src/game_graphics/game_scene.cpp @@ -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 ---------- diff --git a/cockatrice/src/game_graphics/game_scene.h b/cockatrice/src/game_graphics/game_scene.h index 7f01bf1f5..c12696189 100644 --- a/cockatrice/src/game_graphics/game_scene.h +++ b/cockatrice/src/game_graphics/game_scene.h @@ -55,6 +55,8 @@ private: QBasicTimer *animationTimer; ///< Timer for scene animations QHash 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. diff --git a/cockatrice/src/game_graphics/game_view.cpp b/cockatrice/src/game_graphics/game_view.cpp index f2dde4dd9..ed6355157 100644 --- a/cockatrice/src/game_graphics/game_view.cpp +++ b/cockatrice/src/game_graphics/game_view.cpp @@ -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(); } diff --git a/cockatrice/src/game_graphics/game_view.h b/cockatrice/src/game_graphics/game_view.h index 3f6b60dbc..a23655513 100644 --- a/cockatrice/src/game_graphics/game_view.h +++ b/cockatrice/src/game_graphics/game_view.h @@ -27,6 +27,7 @@ private: QWidget *tallyContainer; QGridLayout *tallyLayout; QPointF selectionOrigin; + QRect previousBandRect; ///< Last rubber-band rect for targeted repaint QList cachedTallyRows; ///< Cached entries to avoid redundant rebuilds QSize rebuildTallyLabels(const QList &entries); diff --git a/cockatrice/src/game_graphics/player/player_graphics_item.cpp b/cockatrice/src/game_graphics/player/player_graphics_item.cpp index ac0565fa8..9751f0320 100644 --- a/cockatrice/src/game_graphics/player/player_graphics_item.cpp +++ b/cockatrice/src/game_graphics/player/player_graphics_item.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include 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(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()) { 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 cc605fa0a..05129369c 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 @@ -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(); } } diff --git a/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.cpp b/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.cpp index de5c7542d..72c715e13 100644 --- a/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.cpp +++ b/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.cpp @@ -7,7 +7,6 @@ #include "card_database_model.h" #include "playmat_preview_widget.h" -#include #include #include #include @@ -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")); } diff --git a/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.h b/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.h index 9637ad771..7ccd1569d 100644 --- a/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.h +++ b/cockatrice/src/interface/widgets/playmat/playmat_settings_dialog.h @@ -5,7 +5,6 @@ #include #include -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; 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 a76f55af7..84729984e 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -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);