From 55a2f75d16511bad70e4689c9ac85af86ec797b2 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 7 Mar 2023 01:41:08 +0100 Subject: [PATCH] Make cards rounded (#4765) * Make cards rounded Magic cards have rounded corners, and playing cards tend to have rounded corners as well, but Cockatrice currently displays rectangular cards. This can cause visual glitches when using image scans where the border does not extend in the corner, and for this reason Cockatrice always draws a (rectangular) border around the card to try and make it look a bit better. In this patch I take a different approach: rather than try to make rounded pegs, er, cards, go into a square hole, the hole is now rounded. More precisely, the AbstractCardItem now has a rounded rectangular shape (with a corner of 5% of the width of the card, identical to that of modern M:TG physical cards). As a side effect, the card drawing gets a bit simplified by getting rid of transformPainter() when drawing the card outline and using the QPainter::drawPixmap overloads that takes a target QRectF instead. This means we no longer have to bother about card rotation when painting since that's taken care of by the Graphics View framework (which transformPainter() undoes). * format * Also give PileZone rounded corners * Forgot untap status + bits of CardDragItem * fix deckviewcard calculations * Rounded CardInfoPicture --- cockatrice/src/abstractcarddragitem.cpp | 9 ++++++- cockatrice/src/abstractcarddragitem.h | 1 + cockatrice/src/abstractcarditem.cpp | 32 ++++++++++--------------- cockatrice/src/abstractcarditem.h | 1 + cockatrice/src/carddragitem.cpp | 2 +- cockatrice/src/cardinfopicture.cpp | 14 +++++++---- cockatrice/src/carditem.cpp | 8 +++---- cockatrice/src/deckview.cpp | 3 ++- cockatrice/src/pilezone.cpp | 11 +++++++-- cockatrice/src/pilezone.h | 1 + 10 files changed, 48 insertions(+), 34 deletions(-) diff --git a/cockatrice/src/abstractcarddragitem.cpp b/cockatrice/src/abstractcarddragitem.cpp index 7c2b0c3f..d3d830c7 100644 --- a/cockatrice/src/abstractcarddragitem.cpp +++ b/cockatrice/src/abstractcarddragitem.cpp @@ -45,12 +45,19 @@ AbstractCardDragItem::~AbstractCardDragItem() delete childDrags[i]; } +QPainterPath AbstractCardDragItem::shape() const +{ + QPainterPath shape; + shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH); + return shape; +} + void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { item->paint(painter, option, widget); // adds a mask to the card so it looks like the card hasnt been placed yet - painter->fillRect(boundingRect(), GHOST_MASK); + painter->fillPath(shape(), GHOST_MASK); } void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/abstractcarddragitem.h b/cockatrice/src/abstractcarddragitem.h index 39ff7115..4f379e87 100644 --- a/cockatrice/src/abstractcarddragitem.h +++ b/cockatrice/src/abstractcarddragitem.h @@ -31,6 +31,7 @@ public: { return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); } + QPainterPath shape() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); AbstractCardItem *getItem() const { diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index ef44a9f1..dcbbcd03 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -34,6 +34,13 @@ QRectF AbstractCardItem::boundingRect() const return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); } +QPainterPath AbstractCardItem::shape() const +{ + QPainterPath shape; + shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH); + return shape; +} + void AbstractCardItem::pixmapUpdated() { update(); @@ -113,24 +120,14 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS if (paintImage) { painter->save(); - transformPainter(painter, translatedSize, angle); - painter->drawPixmap(QPointF(1, 1), translatedPixmap); + painter->setClipPath(shape()); + painter->drawPixmap(boundingRect(), translatedPixmap, QRectF({0, 0}, translatedPixmap.size())); painter->restore(); } else { painter->setBrush(bgColor); + painter->drawPath(shape()); } - QPen pen(Qt::black); - pen.setJoinStyle(Qt::MiterJoin); - const int penWidth = 2; - pen.setWidth(penWidth); - painter->setPen(pen); - - if (!angle) - painter->drawRect(QRectF(0, 0, CARD_WIDTH - 1, CARD_HEIGHT - penWidth)); - else - painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 1.5)); - if (translatedPixmap.isNull() || SettingsCache::instance().getDisplayCardNames() || facedown) { painter->save(); transformPainter(painter, translatedSize, angle); @@ -158,9 +155,7 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * QSizeF translatedSize = getTranslatedSize(painter); paintPicture(painter, translatedSize, tapAngle); - painter->save(); painter->setRenderHint(QPainter::Antialiasing, false); - transformPainter(painter, translatedSize, tapAngle); if (isSelected() || isHovered) { QPen pen; @@ -168,15 +163,12 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * pen.setColor(Qt::yellow); if (isSelected()) pen.setColor(Qt::red); - const int penWidth = 1; - pen.setWidth(penWidth); + pen.setWidth(0); // Cosmetic pen painter->setPen(pen); - painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth)); + painter->drawPath(shape()); } painter->restore(); - - painter->restore(); } void AbstractCardItem::setName(const QString &_name) diff --git a/cockatrice/src/abstractcarditem.h b/cockatrice/src/abstractcarditem.h index 20215ae5..7800eb8f 100644 --- a/cockatrice/src/abstractcarditem.h +++ b/cockatrice/src/abstractcarditem.h @@ -54,6 +54,7 @@ public: QGraphicsItem *parent = nullptr); ~AbstractCardItem(); QRectF boundingRect() const; + QPainterPath shape() const override; QSizeF getTranslatedSize(QPainter *painter) const; void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); diff --git a/cockatrice/src/carddragitem.cpp b/cockatrice/src/carddragitem.cpp index f70e1e9c..a91ea7fc 100644 --- a/cockatrice/src/carddragitem.cpp +++ b/cockatrice/src/carddragitem.cpp @@ -24,7 +24,7 @@ void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti AbstractCardDragItem::paint(painter, option, widget); if (occupied) - painter->fillRect(boundingRect(), QColor(200, 0, 0, 100)); + painter->fillPath(shape(), QColor(200, 0, 0, 100)); } void CardDragItem::updatePosition(const QPointF &cursorScenePos) diff --git a/cockatrice/src/cardinfopicture.cpp b/cockatrice/src/cardinfopicture.cpp index 2f255378..1e712c3a 100644 --- a/cockatrice/src/cardinfopicture.cpp +++ b/cockatrice/src/cardinfopicture.cpp @@ -4,8 +4,7 @@ #include "main.h" #include "pictureloader.h" -#include -#include +#include #include CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true) @@ -55,6 +54,13 @@ void CardInfoPicture::paintEvent(QPaintEvent *) if (pixmapDirty) loadPixmap(); - QPainter painter(this); - style()->drawItemPixmap(&painter, rect(), Qt::AlignHCenter, resizedPixmap); + QSize scaledSize = resizedPixmap.size().scaled(size(), Qt::KeepAspectRatio); + QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2}; + qreal radius = 0.05 * scaledSize.width(); + + QStylePainter painter(this); + QPainterPath shape; + shape.addRoundedRect(QRect(topLeft, scaledSize), radius, radius); + painter.setClipPath(shape); + painter.drawItemPixmap(QRect(topLeft, scaledSize), Qt::AlignCenter, resizedPixmap); } diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index de3a0458..59bd9feb 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -141,21 +141,19 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, } if (getBeingPointedAt()) { - painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100))); + painter->fillPath(shape(), QBrush(QColor(255, 0, 0, 100))); } if (doesntUntap) { painter->save(); painter->setRenderHint(QPainter::Antialiasing, false); - transformPainter(painter, translatedSize, tapAngle); QPen pen; pen.setColor(Qt::magenta); - const int penWidth = 1; - pen.setWidth(penWidth); + pen.setWidth(0); // Cosmetic pen painter->setPen(pen); - painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth)); + painter->drawPath(shape()); painter->restore(); } diff --git a/cockatrice/src/deckview.cpp b/cockatrice/src/deckview.cpp index 94f1e43b..252d655c 100644 --- a/cockatrice/src/deckview.cpp +++ b/cockatrice/src/deckview.cpp @@ -89,7 +89,8 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti pen.setJoinStyle(Qt::MiterJoin); pen.setColor(originZone == DECK_ZONE_MAIN ? Qt::green : Qt::red); painter->setPen(pen); - painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2.5)); + qreal cardRadius = 0.05 * (CARD_WIDTH - 3); + painter->drawRoundedRect(QRectF(1.5, 1.5, CARD_WIDTH - 3., CARD_HEIGHT - 3.), cardRadius, cardRadius); painter->restore(); } diff --git a/cockatrice/src/pilezone.cpp b/cockatrice/src/pilezone.cpp index 770cdf8d..fcd8bb8b 100644 --- a/cockatrice/src/pilezone.cpp +++ b/cockatrice/src/pilezone.cpp @@ -28,13 +28,20 @@ QRectF PileZone::boundingRect() const return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); } +QPainterPath PileZone::shape() const +{ + QPainterPath shape; + shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH); + return shape; +} + void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { + painter->drawPath(shape()); + if (!cards.isEmpty()) cards.at(0)->paintPicture(painter, cards.at(0)->getTranslatedSize(painter), 90); - painter->drawRect(QRectF(0.5, 0.5, CARD_WIDTH - 1, CARD_HEIGHT - 1)); - painter->translate((float)CARD_WIDTH / 2, (float)CARD_HEIGHT / 2); painter->rotate(-90); painter->translate((float)-CARD_WIDTH / 2, (float)-CARD_HEIGHT / 2); diff --git a/cockatrice/src/pilezone.h b/cockatrice/src/pilezone.h index 37b15c7f..9c2e5cd3 100644 --- a/cockatrice/src/pilezone.h +++ b/cockatrice/src/pilezone.h @@ -19,6 +19,7 @@ public: bool _contentsKnown, QGraphicsItem *parent = nullptr); QRectF boundingRect() const; + QPainterPath shape() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void reorganizeCards(); void handleDropEvent(const QList &dragItems, CardZone *startZone, const QPoint &dropPoint);