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
This commit is contained in:
Basile Clement 2023-03-07 01:41:08 +01:00 committed by GitHub
parent a416ee8f2b
commit 55a2f75d16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 48 additions and 34 deletions

View file

@ -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)

View file

@ -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
{

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -4,8 +4,7 @@
#include "main.h"
#include "pictureloader.h"
#include <QPainter>
#include <QStyle>
#include <QStylePainter>
#include <QWidget>
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);
}

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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);

View file

@ -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<CardDragItem *> &dragItems, CardZone *startZone, const QPoint &dropPoint);