Rotate random art crop.

Took 3 hours 34 minutes

Took 9 seconds
This commit is contained in:
Lukas Brübach 2025-07-10 15:55:51 +02:00
parent 7bed1dc908
commit 3cdd3df666
9 changed files with 140 additions and 6 deletions

View file

@ -85,6 +85,7 @@ set(cockatrice_SOURCES
src/client/ui/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp src/client/ui/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp
src/client/ui/widgets/cards/card_info_display_widget.cpp src/client/ui/widgets/cards/card_info_display_widget.cpp
src/client/ui/widgets/cards/card_info_frame_widget.cpp src/client/ui/widgets/cards/card_info_frame_widget.cpp
src/client/ui/widgets/cards/card_info_picture_art_crop_widget.cpp
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
src/client/ui/widgets/cards/card_info_picture_widget.cpp src/client/ui/widgets/cards/card_info_picture_widget.cpp
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp

View file

@ -0,0 +1,41 @@
#include "card_info_picture_art_crop_widget.h"
#include "../../picture_loader/picture_loader.h"
CardInfoPictureArtCropWidget::CardInfoPictureArtCropWidget(QWidget *parent)
: CardInfoPictureWidget(parent, false, false)
{
hide();
}
QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &targetSize)
{
// Load the full-resolution card image, not a pre-scaled one
QPixmap fullResPixmap;
if (getInfo()) {
PictureLoader::getPixmap(fullResPixmap, getInfo(), QSize(745, 1040)); // or a high default size
} else {
PictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
}
// Fail-safe if loading failed
if (fullResPixmap.isNull()) {
return QPixmap(targetSize);
}
const QSize sz = fullResPixmap.size();
int marginX = sz.width() * 0.07;
int topMargin = sz.height() * 0.11;
int bottomMargin = sz.height() * 0.45;
QRect foilRect(marginX, topMargin, sz.width() - 2 * marginX, sz.height() - topMargin - bottomMargin);
foilRect = foilRect.intersected(fullResPixmap.rect()); // always clamp to source bounds
// Crop first, then scale for best quality
QPixmap cropped = fullResPixmap.copy(foilRect);
QPixmap scaled = cropped.scaled(targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
return scaled;
}

View file

@ -0,0 +1,17 @@
#ifndef CARD_INFO_PICTURE_ART_CROP_WIDGET_H
#define CARD_INFO_PICTURE_ART_CROP_WIDGET_H
#include "card_info_picture_widget.h"
class CardInfoPictureArtCropWidget : public CardInfoPictureWidget
{
Q_OBJECT
public:
explicit CardInfoPictureArtCropWidget(QWidget *parent = nullptr);
// Returns a processed (cropped & scaled) version of the pixmap
QPixmap getProcessedBackground(const QSize &targetSize);
};
#endif // CARD_INFO_PICTURE_ART_CROP_WIDGET_H

View file

@ -12,6 +12,12 @@ HomeStyledButton::HomeStyledButton(const QString &text, QPair<QColor, QColor> _g
setStyleSheet(generateButtonStylesheet(gradientColors)); setStyleSheet(generateButtonStylesheet(gradientColors));
} }
void HomeStyledButton::updateStylesheet(const QPair<QColor, QColor> &colors)
{
gradientColors = colors;
setStyleSheet(generateButtonStylesheet(gradientColors));
}
QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &colors) QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &colors)
{ {
QColor base1 = colors.first; QColor base1 = colors.first;

View file

@ -11,6 +11,7 @@ class HomeStyledButton : public QPushButton
Q_OBJECT Q_OBJECT
public: public:
HomeStyledButton(const QString &text, QPair<QColor, QColor> gradientColors, QWidget *parent = nullptr); HomeStyledButton(const QString &text, QPair<QColor, QColor> gradientColors, QWidget *parent = nullptr);
void updateStylesheet(const QPair<QColor, QColor> &colors);
QString generateButtonStylesheet(const QPair<QColor, QColor> &colors); QString generateButtonStylesheet(const QPair<QColor, QColor> &colors);
public slots: public slots:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;

View file

@ -1,5 +1,6 @@
#include "home_widget.h" #include "home_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../tabs/tab_supervisor.h" #include "../../../tabs/tab_supervisor.h"
#include "home_styled_button.h" #include "home_styled_button.h"
@ -11,8 +12,15 @@
HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
: QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice") : QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice")
{ {
setAttribute(Qt::WA_OpaquePaintEvent);
layout = new QGridLayout(this); layout = new QGridLayout(this);
backgroundSource = new CardInfoPictureArtCropWidget(this);
backgroundSource->setCard(CardDatabaseManager::getInstance()->getRandomCard());
background = backgroundSource->getProcessedBackground(size());
gradientColors = extractDominantColors(background); gradientColors = extractDominantColors(background);
layout->addWidget(createSettingsButtonGroup("Settings"), 0, 0, Qt::AlignTop | Qt::AlignLeft); layout->addWidget(createSettingsButtonGroup("Settings"), 0, 0, Qt::AlignTop | Qt::AlignLeft);
@ -26,6 +34,42 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
layout->setColumnStretch(2, 1); layout->setColumnStretch(2, 1);
setLayout(layout); setLayout(layout);
connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this,
&HomeWidget::startCardShuffleTimer);
if (CardDatabaseManager::getInstance()->getLoadStatus() == LoadStatus::Ok) {
startCardShuffleTimer();
}
}
void HomeWidget::startCardShuffleTimer()
{
cardChangeTimer = new QTimer(this);
connect(cardChangeTimer, &QTimer::timeout, this, &HomeWidget::updateRandomCard);
cardChangeTimer->start(5000); // 20 seconds
}
void HomeWidget::updateRandomCard()
{
CardInfoPtr newCard = CardDatabaseManager::getInstance()->getRandomCard();
if (!newCard)
return;
connect(newCard.data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties);
backgroundSource->setCard(newCard);
}
void HomeWidget::updateBackgroundProperties()
{
background = backgroundSource->getProcessedBackground(size());
gradientColors = extractDominantColors(background);
for (HomeStyledButton *button : findChildren<HomeStyledButton *>()) {
button->updateStylesheet(gradientColors);
button->update();
}
update(); // Triggers repaint
} }
QGroupBox *HomeWidget::createSettingsButtonGroup(const QString &title) QGroupBox *HomeWidget::createSettingsButtonGroup(const QString &title)
@ -197,13 +241,17 @@ void HomeWidget::paintEvent(QPaintEvent *event)
{ {
QPainter painter(this); QPainter painter(this);
// Draw zoomed background // Update background if we have a source
if (backgroundSource) {
background = backgroundSource->getProcessedBackground(size());
}
// Draw already-scaled background centered
QSize widgetSize = size(); QSize widgetSize = size();
QSize bgSize = background.size(); QSize bgSize = background.size();
QSize scaledSize = bgSize.scaled(widgetSize, Qt::KeepAspectRatioByExpanding); QPoint topLeft((widgetSize.width() - bgSize.width()) / 2, (widgetSize.height() - bgSize.height()) / 2);
QPoint topLeft((widgetSize.width() - scaledSize.width()) / 2, (widgetSize.height() - scaledSize.height()) / 2);
painter.drawPixmap(topLeft, painter.drawPixmap(topLeft, background);
background.scaled(scaledSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
// Draw translucent black overlay with rounded corners // Draw translucent black overlay with rounded corners
QRectF overlayRect(5, 5, width() - 10, height() - 10); // 5px inset QRectF overlayRect(5, 5, width() - 10, height() - 10); // 5px inset
@ -220,4 +268,4 @@ void HomeWidget::paintEvent(QPaintEvent *event)
painter.drawPixmap(center, overlay); painter.drawPixmap(center, overlay);
QWidget::paintEvent(event); QWidget::paintEvent(event);
} }

View file

@ -1,6 +1,7 @@
#ifndef HOME_WIDGET_H #ifndef HOME_WIDGET_H
#define HOME_WIDGET_H #define HOME_WIDGET_H
#include "../../../tabs/tab_supervisor.h" #include "../../../tabs/tab_supervisor.h"
#include "../cards/card_info_picture_art_crop_widget.h"
#include <QGridLayout> #include <QGridLayout>
#include <QGroupBox> #include <QGroupBox>
@ -13,6 +14,8 @@ class HomeWidget : public QWidget
public: public:
HomeWidget(QWidget *parent, TabSupervisor *tabSupervisor); HomeWidget(QWidget *parent, TabSupervisor *tabSupervisor);
void startCardShuffleTimer();
void updateRandomCard();
QGroupBox *createSettingsButtonGroup(const QString &title); QGroupBox *createSettingsButtonGroup(const QString &title);
QGroupBox *createUpdatesButtonGroup(const QString &title); QGroupBox *createUpdatesButtonGroup(const QString &title);
QGroupBox *createNavigationButtonGroup(const QString &title); QGroupBox *createNavigationButtonGroup(const QString &title);
@ -21,11 +24,14 @@ public:
public slots: public slots:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void updateBackgroundProperties();
private: private:
QGridLayout *layout; QGridLayout *layout;
QTimer *cardChangeTimer;
TabSupervisor *tabSupervisor; TabSupervisor *tabSupervisor;
QPixmap background; QPixmap background;
CardInfoPictureArtCropWidget *backgroundSource = nullptr;
QPixmap overlay; QPixmap overlay;
QPair<QColor, QColor> gradientColors; QPair<QColor, QColor> gradientColors;
}; };

View file

@ -14,6 +14,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QRegularExpression> #include <QRegularExpression>
#include <algorithm> #include <algorithm>
#include <qrandom.h>
#include <utility> #include <utility>
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded) CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
@ -213,6 +214,17 @@ ExactCard CardDatabase::guessCard(const CardRef &cardRef) const
return ExactCard(temp, findPrintingWithId(temp, cardRef.providerId)); return ExactCard(temp, findPrintingWithId(temp, cardRef.providerId));
} }
CardInfoPtr CardDatabase::getRandomCard()
{
if (cards.isEmpty()) return nullptr;
const auto keys = cards.keys();
int randomIndex = QRandomGenerator::global()->bounded(keys.size());
const QString &randomKey = keys.at(randomIndex);
return getCardFromMap(cards, randomKey);
}
CardSetPtr CardDatabase::getSet(const QString &setName) CardSetPtr CardDatabase::getSet(const QString &setName)
{ {
if (sets.contains(setName)) { if (sets.contains(setName)) {

View file

@ -53,6 +53,7 @@ protected:
QVector<ICardDatabaseParser *> availableParsers; QVector<ICardDatabaseParser *> availableParsers;
private: private:
CardInfoPtr getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const;
void checkUnknownSets(); void checkUnknownSets();
void refreshCachedReverseRelatedCards(); void refreshCachedReverseRelatedCards();
@ -85,6 +86,7 @@ public:
ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const; ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
[[nodiscard]] ExactCard getRandomCard();
/* /*
* Get a card by its simple name. The name will be simplified in this * Get a card by its simple name. The name will be simplified in this