diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 648d6d10..ea6a3414 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -35,6 +35,7 @@ HEADERS += src/counter.h \ src/zoneviewzone.h \ src/zoneviewwidget.h \ src/pilezone.h \ + src/stackzone.h \ src/carddragitem.h \ src/carddatabasemodel.h \ src/window_deckeditor.h \ @@ -112,6 +113,7 @@ SOURCES += src/counter.cpp \ src/zoneviewzone.cpp \ src/zoneviewwidget.cpp \ src/pilezone.cpp \ + src/stackzone.cpp \ src/carddragitem.cpp \ src/carddatabasemodel.cpp \ src/window_deckeditor.cpp \ diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index b9058718..71fcee84 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -188,11 +188,6 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event) event->accept(); } -void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - emit deleteCardInfoPopup(); -} - void AbstractCardItem::processHoverEvent() { emit hovered(this); diff --git a/cockatrice/src/abstractcarditem.h b/cockatrice/src/abstractcarditem.h index 493f4dc6..87609e81 100644 --- a/cockatrice/src/abstractcarditem.h +++ b/cockatrice/src/abstractcarditem.h @@ -48,7 +48,6 @@ protected: QSizeF getTranslatedSize(QPainter *painter) const; void transformPainter(QPainter *painter, const QSizeF &translatedSize); void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent *event); QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); }; diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 0264b121..9869d382 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "cardinfowidget.h" #include "carditem.h" #include "carddatabase.h" @@ -157,3 +158,9 @@ void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/) updatePixmap(); } } + +void CardInfoWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if ((event->button() == Qt::MidButton) && (mode == ModePopUp)) + emit mouseReleased(); +} diff --git a/cockatrice/src/cardinfowidget.h b/cockatrice/src/cardinfowidget.h index e7d8a365..617acd56 100644 --- a/cockatrice/src/cardinfowidget.h +++ b/cockatrice/src/cardinfowidget.h @@ -9,6 +9,7 @@ class QPushButton; class AbstractCardItem; class CardInfo; class QResizeEvent; +class QMouseEvent; class CardInfoWidget : public QFrame { Q_OBJECT @@ -40,8 +41,11 @@ public slots: private slots: void updatePixmap(); void minimizeClicked(); +signals: + void mouseReleased(); protected: void resizeEvent(QResizeEvent *event); + void mouseReleaseEvent(QMouseEvent *event); }; #endif diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index f854d73b..76381500 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -369,9 +369,7 @@ void CardItem::playCard(QGraphicsSceneMouseEvent *event) bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier); bool tapped = info->getCipt(); - TableZone *table = zone->getPlayer()->getTable(); - QPoint gridPoint = QPoint(-1, 3 - info->getTableRow()); - table->handleDropEventByGrid(id, zone, gridPoint, faceDown, tapped); + zone->getPlayer()->playCard(this, faceDown, tapped); } } diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index bab79039..54059e3a 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -169,6 +169,8 @@ QPair MessageLogWidget::getFromStr(CardZone *zone, QString car fromStr = tr(" from library"); } else if (startName == "sb") fromStr = tr(" from sideboard"); + else if (startName == "stack") + fromStr = tr(" from the stack"); if (!cardNameContainsStartZone) cardName.clear(); @@ -209,6 +211,8 @@ void MessageLogWidget::logMoveCard(Player *player, QString cardName, CardZone *s finalStr = tr("%1 puts %2%3 into his library at position %4."); } else if (targetName == "sb") finalStr = tr("%1 moves %2%3 to sideboard."); + else if (targetName == "stack") + finalStr = tr("%1 plays %2%3."); QString cardStr; if (cardNameContainsStartZone) diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 5cfa5b83..a0a849d7 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -6,6 +6,7 @@ #include "zoneviewzone.h" #include "zoneviewwidget.h" #include "pilezone.h" +#include "stackzone.h" #include "tablezone.h" #include "handzone.h" #include "handcounter.h" @@ -15,6 +16,7 @@ #include "gamescene.h" #include "settingscache.h" #include "dlg_create_token.h" +#include "carddatabase.h" #include #include #include @@ -54,6 +56,8 @@ Player::Player(ServerInfo_User *info, int _id, bool _local, TabGame *_parent) table = new TableZone(this, this); connect(table, SIGNAL(sizeChanged()), this, SLOT(updateBoundingRect())); + stack = new StackZone(this, (int) table->boundingRect().height(), this); + hand = new HandZone(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()), (int) table->boundingRect().height(), this); connect(hand, SIGNAL(cardCountChanged()), handCounter, SLOT(updateNumber())); @@ -310,16 +314,29 @@ void Player::rearrangeZones() if (settingsCache->getHorizontalHand()) { if (mirrored) { - hand->setPos(counterAreaWidth + CARD_WIDTH + 5, base.y()); - table->setPos(base.x(), base.y() + hand->boundingRect().height()); - } else { + hand->setPos(base); + base += QPointF(0, hand->boundingRect().height()); + + stack->setPos(base); + base += QPointF(stack->boundingRect().width(), 0); + table->setPos(base); - hand->setPos(counterAreaWidth + CARD_WIDTH + 5, base.y() + table->boundingRect().height()); + } else { + stack->setPos(base); + + table->setPos(base.x() + stack->boundingRect().width(), 0); + base += QPointF(0, table->boundingRect().height()); + + hand->setPos(base); } - hand->setWidth(table->getWidth()); + hand->setWidth(table->getWidth() + stack->boundingRect().width()); } else { hand->setPos(base); base += QPointF(hand->boundingRect().width(), 0); + + stack->setPos(base); + base += QPointF(stack->boundingRect().width(), 0); + table->setPos(base); } hand->updateOrientation(); @@ -341,10 +358,11 @@ void Player::updateBgPixmap() void Player::updateBoundingRect() { prepareGeometryChange(); + qreal width = CARD_WIDTH + 5 + counterAreaWidth + stack->boundingRect().width(); if (settingsCache->getHorizontalHand()) - bRect = QRectF(0, 0, CARD_WIDTH + 5 + counterAreaWidth + table->boundingRect().width(), table->boundingRect().height() + hand->boundingRect().height()); + bRect = QRectF(0, 0, width + table->boundingRect().width(), table->boundingRect().height() + hand->boundingRect().height()); else - bRect = QRectF(0, 0, CARD_WIDTH + 5 + counterAreaWidth + hand->boundingRect().width() + table->boundingRect().width(), table->boundingRect().height()); + bRect = QRectF(0, 0, width + hand->boundingRect().width() + table->boundingRect().width(), table->boundingRect().height()); emit sizeChanged(); } @@ -1034,6 +1052,17 @@ void Player::processCardAttachment(ServerInfo_Player *info) } } +void Player::playCard(CardItem *c, bool faceDown, bool tapped) +{ + CardInfo *ci = c->getInfo(); + if (ci->getTableRow() == 3) + stack->handleDropEvent(c->getId(), c->getZone(), QPoint(), false); + else { + QPoint gridPoint = QPoint(-1, 2 - ci->getTableRow()); + table->handleDropEventByGrid(c->getId(), c->getZone(), gridPoint, faceDown, tapped); + } +} + void Player::addCard(CardItem *c) { emit newCardAdded(c); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 56589995..ee91934f 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -14,6 +14,7 @@ class TabGame; class Counter; class ArrowItem; class CardZone; +class StackZone; class TableZone; class HandZone; class PlayerTarget; @@ -136,6 +137,7 @@ private: QList cardsToDelete; QMap zones; + StackZone *stack; TableZone *table; HandZone *hand; PlayerTarget *playerTarget; @@ -178,6 +180,7 @@ public: QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void playCard(CardItem *c, bool faceDown, bool tapped); void addCard(CardItem *c); void deleteCard(CardItem *c); void addZone(CardZone *z); diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 61bdde1f..d44270f9 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -12,6 +12,7 @@ SettingsCache::SettingsCache() cardDatabasePath = settings->value("paths/carddatabase").toString(); handBgPath = settings->value("zonebg/hand").toString(); + stackBgPath = settings->value("zonebg/stack").toString(); tableBgPath = settings->value("zonebg/table").toString(); playerBgPath = settings->value("zonebg/playerarea").toString(); cardBackPicturePath = settings->value("paths/cardbackpicture").toString(); @@ -62,6 +63,13 @@ void SettingsCache::setHandBgPath(const QString &_handBgPath) emit handBgPathChanged(); } +void SettingsCache::setStackBgPath(const QString &_stackBgPath) +{ + stackBgPath = _stackBgPath; + settings->setValue("zonebg/stack", stackBgPath); + emit stackBgPathChanged(); +} + void SettingsCache::setTableBgPath(const QString &_tableBgPath) { tableBgPath = _tableBgPath; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 23ca8e36..607c9187 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -12,6 +12,7 @@ signals: void picsPathChanged(); void cardDatabasePathChanged(); void handBgPathChanged(); + void stackBgPathChanged(); void tableBgPathChanged(); void playerBgPathChanged(); void cardBackPicturePathChanged(); @@ -24,7 +25,7 @@ private: QString lang; QString deckPath, picsPath, cardDatabasePath; - QString handBgPath, tableBgPath, playerBgPath, cardBackPicturePath; + QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath; bool picDownload; bool doubleClickToPlay; bool cardInfoMinimized; @@ -40,6 +41,7 @@ public: QString getPicsPath() const { return picsPath; } QString getCardDatabasePath() const { return cardDatabasePath; } QString getHandBgPath() const { return handBgPath; } + QString getStackBgPath() const { return stackBgPath; } QString getTableBgPath() const { return tableBgPath; } QString getPlayerBgPath() const { return playerBgPath; } QString getCardBackPicturePath() const { return cardBackPicturePath; } @@ -58,6 +60,7 @@ public slots: void setPicsPath(const QString &_picsPath); void setCardDatabasePath(const QString &_cardDatabasePath); void setHandBgPath(const QString &_handBgPath); + void setStackBgPath(const QString &_stackBgPath); void setTableBgPath(const QString &_tableBgPath); void setPlayerBgPath(const QString &_playerBgPath); void setCardBackPicturePath(const QString &_cardBackPicturePath); diff --git a/cockatrice/src/stackzone.cpp b/cockatrice/src/stackzone.cpp new file mode 100644 index 00000000..4bad0634 --- /dev/null +++ b/cockatrice/src/stackzone.cpp @@ -0,0 +1,84 @@ +#include +#include "stackzone.h" +#include "settingscache.h" +#include "player.h" +#include "protocol_items.h" + +StackZone::StackZone(Player *_p, int _zoneHeight, QGraphicsItem *parent) + : CardZone(_p, "stack", false, false, true, parent), zoneHeight(_zoneHeight) +{ + connect(settingsCache, SIGNAL(stackBgPathChanged()), this, SLOT(updateBgPixmap())); + updateBgPixmap(); + setCacheMode(DeviceCoordinateCache); +} + +void StackZone::updateBgPixmap() +{ + QString bgPath = settingsCache->getStackBgPath(); + if (!bgPath.isEmpty()) + bgPixmap.load(bgPath); + update(); +} + +void StackZone::addCardImpl(CardItem *card, int x, int /*y*/) +{ + if (x == -1) + x = cards.size(); + cards.insert(x, card); + + if (!cards.getContentsKnown()) { + card->setId(-1); + card->setName(); + } + card->setParentItem(this); + card->resetState(); + card->setVisible(true); + card->update(); +} + +QRectF StackZone::boundingRect() const +{ + return QRectF(0, 0, 100, zoneHeight); +} + +void StackZone::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) +{ + if (bgPixmap.isNull()) + painter->fillRect(boundingRect(), Qt::darkBlue); + else + painter->fillRect(boundingRect(), QBrush(bgPixmap)); +} + +void StackZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint &/*dropPoint*/, bool /*faceDown*/) +{ + if (startZone == this) + return; + player->sendGameCommand(new Command_MoveCard(-1, startZone->getName(), cardId, getName(), 0, 0, false)); +} + +void StackZone::reorganizeCards() +{ + if (!cards.isEmpty()) { + const int cardCount = cards.size(); + qreal totalWidth = boundingRect().width(); + qreal totalHeight = boundingRect().height(); + qreal cardWidth = cards.at(0)->boundingRect().width(); + qreal cardHeight = cards.at(0)->boundingRect().height(); + qreal xspace = 5; + qreal x1 = xspace; + qreal x2 = totalWidth - xspace - cardWidth; + + for (int i = 0; i < cardCount; i++) { + CardItem *c = cards.at(i); + qreal x = i % 2 ? x2 : x1; + // If the total height of the cards is smaller than the available height, + // the cards do not need to overlap and are displayed in the center of the area. + if (cardHeight * cardCount > totalHeight) + c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1)); + else + c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2); + c->setZValue(i); + } + } + update(); +} diff --git a/cockatrice/src/stackzone.h b/cockatrice/src/stackzone.h new file mode 100644 index 00000000..7717a114 --- /dev/null +++ b/cockatrice/src/stackzone.h @@ -0,0 +1,24 @@ +#ifndef STACKZONE_H +#define STACKZONE_H + +#include "cardzone.h" + +class StackZone : public CardZone { + Q_OBJECT +private: + qreal zoneHeight; + QPixmap bgPixmap; +private slots: + void updateBgPixmap(); +public: + StackZone(Player *_p, int _zoneHeight, QGraphicsItem *parent = 0); + void handleDropEvent(int cardId, CardZone *startZone, const QPoint &dropPoint, bool faceDown); + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void reorganizeCards(); +protected: + void addCardImpl(CardItem *card, int x, int y); +}; + +#endif + diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index c99d70da..8d9a9511 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -693,6 +693,7 @@ Player *TabGame::getActiveLocalPlayer() const void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) { infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); + connect(infoPopup, SIGNAL(mouseReleased()), this, SLOT(deleteCardInfoPopup())); infoPopup->setCard(cardName); QRect screenRect = qApp->desktop()->screenGeometry(this); infoPopup->move( @@ -700,6 +701,7 @@ void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) ); infoPopup->show(); + infoPopup->grabMouse(); } void TabGame::deleteCardInfoPopup() diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index 0c139fb0..207a13b3 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -17,9 +17,9 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent) updateBgPixmap(); if (settingsCache->getEconomicalGrid()) - height = 2 * boxLineWidth + (int) (14.0 / 3 * CARD_HEIGHT + 3 * paddingY); + height = 2 * boxLineWidth + (int) (11.0 / 3 * CARD_HEIGHT + 2 * paddingY); else - height = 2 * boxLineWidth + 4 * CARD_HEIGHT + 3 * paddingY; + height = 2 * boxLineWidth + 3 * CARD_HEIGHT + 2 * paddingY; width = minWidth + 2 * marginX + 2 * boxLineWidth; currentMinimumWidth = minWidth; @@ -52,7 +52,7 @@ void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem */*optio else painter->fillRect(boundingRect(), QBrush(bgPixmap)); painter->setPen(QColor(255, 255, 255, 40)); - qreal separatorY = 3 * (CARD_HEIGHT + paddingY) + boxLineWidth - paddingY / 2; + qreal separatorY = 2 * (CARD_HEIGHT + paddingY) + boxLineWidth - paddingY / 2; if (isInverted()) separatorY = height - separatorY; painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY)); @@ -216,7 +216,7 @@ CardItem *TableZone::getCardFromCoords(const QPointF &point) const QPointF TableZone::mapFromGrid(const QPoint &gridPoint) const { qreal x, y; - if ((gridPoint.y() == 3) && (settingsCache->getEconomicalGrid())) { + if ((gridPoint.y() == 2) && (settingsCache->getEconomicalGrid())) { x = marginX + (CARD_WIDTH * gridPoint.x() + CARD_WIDTH * (gridPoint.x() / 3)) / 2; y = boxLineWidth + (CARD_HEIGHT + paddingY) * gridPoint.y() + (gridPoint.x() % 3 * CARD_HEIGHT) / 3; } else { @@ -251,10 +251,10 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const int resultY = (int) (y / (CARD_HEIGHT + paddingY)); - if ((resultY == 3) && (settingsCache->getEconomicalGrid())) + if ((resultY == 2) && (settingsCache->getEconomicalGrid())) return QPoint( (int) (x * 2 / CARD_WIDTH - floor(x / (2 * CARD_WIDTH))), - 3 + 2 ); else { int resultX = -1; diff --git a/common/server_player.cpp b/common/server_player.cpp index 4a6fd692..ebc34b43 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -64,6 +64,7 @@ void Server_Player::setupZones() addZone(sbZone); addZone(new Server_CardZone(this, "table", true, PublicZone)); addZone(new Server_CardZone(this, "hand", false, PrivateZone)); + addZone(new Server_CardZone(this, "stack", false, PublicZone)); addZone(new Server_CardZone(this, "grave", false, PublicZone)); addZone(new Server_CardZone(this, "rfg", false, PublicZone));