diff --git a/cockatrice/src/game/cards/card_drag_item.cpp b/cockatrice/src/game/cards/card_drag_item.cpp index 318aceefa..d21e9168b 100644 --- a/cockatrice/src/game/cards/card_drag_item.cpp +++ b/cockatrice/src/game/cards/card_drag_item.cpp @@ -2,6 +2,8 @@ #include "../game_scene.h" #include "../zones/card_zone.h" +#include "../zones/table_zone.h" +#include "../zones/view_zone.h" #include "card_item.h" #include @@ -13,68 +15,74 @@ CardDragItem::CardDragItem(CardItem *_item, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag) - : AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), currentZone(0) + : AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0) { } -CardDragItem::~CardDragItem() -{ - if (currentZone) { - currentZone->dragLeave(this); - currentZone = nullptr; - } -} - void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { AbstractCardDragItem::paint(painter, option, widget); - if (!isValid) { + if (occupied) painter->fillPath(shape(), QColor(200, 0, 0, 100)); - } } void CardDragItem::updatePosition(const QPointF &cursorScenePos) { - QPointF topLeftScenePos = cursorScenePos - hotSpot; - QPointF centerScenePos = topLeftScenePos + QPointF(CARD_WIDTH_HALF, CARD_HEIGHT_HALF); - - // Use center of the card for intersection. QList colliding = - scene()->items(centerScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder, + scene()->items(cursorScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder, static_cast(scene())->getViewTransform()); - CardZone *cardZone = nullptr; - for (auto *item : colliding) { - cardZone = qgraphicsitem_cast(item); - - if (cardZone) { - break; - } + CardZone *cardZone = 0; + ZoneViewZone *zoneViewZone = 0; + for (int i = colliding.size() - 1; i >= 0; i--) { + CardZone *temp = qgraphicsitem_cast(colliding.at(i)); + if (!cardZone) + cardZone = temp; + if (!zoneViewZone) + zoneViewZone = qobject_cast(temp); } + CardZone *cursorZone = 0; + if (zoneViewZone) + cursorZone = zoneViewZone; + else if (cardZone) + cursorZone = cardZone; + if (!cursorZone) + return; + currentZone = cursorZone; - if (cardZone != currentZone) { - if (currentZone) { - currentZone->dragLeave(this); - currentZone = nullptr; - } + QPointF zonePos = currentZone->scenePos(); + QPointF cursorPosInZone = cursorScenePos - zonePos; - if (cardZone && cardZone->dragEnter(this, centerScenePos - cardZone->scenePos())) { - setValid(true); - currentZone = cardZone; - } else { - setValid(false); - } - } + // If we are on a Table, we center the card around the cursor, because we + // snap it into place and no longer see it being dragged. + // + // For other zones (where we do display the card under the cursor), we use + // the hotspot to feel like the card was dragged at the corresponding + // position. + TableZone *tableZone = qobject_cast(cursorZone); + QPointF closestGridPoint; + if (tableZone) + closestGridPoint = tableZone->closestGridPoint(cursorPosInZone); + else + closestGridPoint = cursorPosInZone - hotSpot; - if (currentZone) { - currentZone->dragMove(this, centerScenePos - currentZone->scenePos()); - } + QPointF newPos = zonePos + closestGridPoint; - if (topLeftScenePos != pos()) { + if (newPos != pos()) { for (int i = 0; i < childDrags.size(); i++) - childDrags[i]->setPos(topLeftScenePos + childDrags[i]->getHotSpot()); - setPos(topLeftScenePos); + childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); + setPos(newPos); + + bool newOccupied = false; + TableZone *table = qobject_cast(cursorZone); + if (table) + if (table->getCardFromCoords(closestGridPoint)) + newOccupied = true; + if (newOccupied != occupied) { + occupied = newOccupied; + update(); + } } } @@ -82,43 +90,29 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { setCursor(Qt::OpenHandCursor); QGraphicsScene *sc = scene(); + QPointF sp = pos(); sc->removeItem(this); - for (auto *childDrag : childDrags) { - sc->removeItem(childDrag); - } - - if (currentZone) { - QPointF cursorScenePos = event->scenePos(); - QPointF topLeftScenePos = cursorScenePos - hotSpot; - QPointF centerScenePos = topLeftScenePos + QPointF(CARD_WIDTH_HALF, CARD_HEIGHT_HALF); - currentZone->dragAccept(this, centerScenePos - currentZone->scenePos()); - currentZone = nullptr; - } - - static_cast(item)->deleteDragItem(); - AbstractCardDragItem::mouseReleaseEvent(event); -} - -CardZone *CardDragItem::getStartZone() const -{ - return static_cast(item)->getZone(); -} - -QList CardDragItem::getValidItems() -{ QList dragItemList; - CardZone *startZone = getStartZone(); - if (!(static_cast(item)->getAttachedTo() && startZone == currentZone)) { - dragItemList.append(this); + CardZone *startZone = static_cast(item)->getZone(); + if (currentZone && !(static_cast(item)->getAttachedTo() && (startZone == currentZone))) { + if (!occupied) { + dragItemList.append(this); + } for (int i = 0; i < childDrags.size(); i++) { CardDragItem *c = static_cast(childDrags[i]); - if (!(static_cast(c->item)->getAttachedTo() && startZone == currentZone)) { + if (!occupied && !(static_cast(c->item)->getAttachedTo() && (startZone == currentZone)) && + !c->occupied) { dragItemList.append(c); } + sc->removeItem(c); } } - return dragItemList; + if (currentZone) { + currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint()); + } + + event->accept(); } diff --git a/cockatrice/src/game/cards/card_drag_item.h b/cockatrice/src/game/cards/card_drag_item.h index 19db2757f..794fd6ed3 100644 --- a/cockatrice/src/game/cards/card_drag_item.h +++ b/cockatrice/src/game/cards/card_drag_item.h @@ -11,7 +11,7 @@ class CardDragItem : public AbstractCardDragItem private: int id; bool faceDown; - bool isValid = true; + bool occupied; CardZone *currentZone; public: @@ -20,7 +20,6 @@ public: const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0); - virtual ~CardDragItem(); int getId() const { return id; @@ -32,18 +31,6 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void updatePosition(const QPointF &cursorScenePos) override; - void setValid(bool _valid) - { - if (_valid != isValid) { - isValid = _valid; - update(); - } - } - - CardZone *getStartZone() const; - - QList getValidItems(); - protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; }; diff --git a/cockatrice/src/game/zones/card_zone.cpp b/cockatrice/src/game/zones/card_zone.cpp index b4806a010..f3ebbd214 100644 --- a/cockatrice/src/game/zones/card_zone.cpp +++ b/cockatrice/src/game/zones/card_zone.cpp @@ -1,10 +1,11 @@ #include "card_zone.h" #include "../cards/card_database_manager.h" -#include "../cards/card_drag_item.h" #include "../cards/card_item.h" #include "../player/player.h" #include "pb/command_move_card.pb.h" +#include "pb/serverinfo_user.pb.h" +#include "pile_zone.h" #include "view_zone.h" #include @@ -232,26 +233,7 @@ void CardZone::moveAllToZone() player->sendGameCommand(cmd); } -bool CardZone::dragEnter(CardDragItem *dragItem, const QPointF &pos) +QPointF CardZone::closestGridPoint(const QPointF &point) { - Q_UNUSED(dragItem); - Q_UNUSED(pos); - - return true; -} - -void CardZone::dragMove(CardDragItem *dragItem, const QPointF &pos) -{ - Q_UNUSED(dragItem); - Q_UNUSED(pos); -} - -void CardZone::dragAccept(CardDragItem *dragItem, const QPointF &pos) -{ - handleDropEvent(dragItem->getValidItems(), dragItem->getStartZone(), pos.toPoint()); -} - -void CardZone::dragLeave(CardDragItem *dragItem) -{ - Q_UNUSED(dragItem); -} + return point; +} \ No newline at end of file diff --git a/cockatrice/src/game/zones/card_zone.h b/cockatrice/src/game/zones/card_zone.h index 4bb67435f..91cad179c 100644 --- a/cockatrice/src/game/zones/card_zone.h +++ b/cockatrice/src/game/zones/card_zone.h @@ -58,26 +58,6 @@ public: { return Type; } - - /* Called when a card is dragged on top of the zone. - - Return `true` to accept the drag, `false` otherwise. - */ - virtual bool dragEnter(CardDragItem *dragItem, const QPointF &pos); - - /* Called when a card that has been accepted by `dragEnter` is moved over - the zone. - */ - virtual void dragMove(CardDragItem *dragItem, const QPointF &pos); - - /* Called when a card that has been accepted by `dragEnter` is dropped onto - the zone. */ - virtual void dragAccept(CardDragItem *dragItem, const QPointF &pos); - - /* Called when a card that has been accepted by `dragEnter` leaves the zone. - */ - virtual void dragLeave(CardDragItem *dragItem); - virtual void handleDropEvent(const QList &dragItem, CardZone *startZone, const QPoint &dropPoint) = 0; CardZone(Player *_player, @@ -134,6 +114,7 @@ public: return views; } virtual void reorganizeCards() = 0; + virtual QPointF closestGridPoint(const QPointF &point); bool getIsView() const { return isView; diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game/zones/table_zone.cpp index 1c02bb077..71327b9ec 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game/zones/table_zone.cpp @@ -118,66 +118,9 @@ void TableZone::addCardImpl(CardItem *card, int _x, int _y) card->update(); } -bool TableZone::dragEnter(CardDragItem *dragItem, const QPointF &pos) -{ - if (!SelectZone::dragEnter(dragItem, pos)) { - return false; - } - - if (m_feedbackItem) { - scene()->removeItem(m_feedbackItem); - delete m_feedbackItem; - } - - m_feedbackItem = new QGraphicsPathItem(dragItem->getItem()->shape(), this); - m_feedbackItem->setBrush(QColor(176, 196, 222)); // lightsteelblue - m_feedbackItem->setPen(QColor(119, 136, 153)); // lightslategray - m_feedbackItem->setZValue(2000000005); - m_feedbackItem->setTransform(dragItem->getItem()->transform()); - updateFeedback(dragItem, pos); - - return true; -} - -void TableZone::dragMove(CardDragItem *dragItem, const QPointF &pos) -{ - if (m_feedbackItem) { - updateFeedback(dragItem, pos); - } - - SelectZone::dragMove(dragItem, pos); -} - -void TableZone::dragAccept(CardDragItem *dragItem, const QPointF &pos) -{ - SelectZone::dragAccept(dragItem, pos); - - if (m_feedbackItem) { - scene()->removeItem(m_feedbackItem); - delete m_feedbackItem; - m_feedbackItem = nullptr; - } -} - -void TableZone::dragLeave(CardDragItem *dragItem) -{ - SelectZone::dragLeave(dragItem); - - if (m_feedbackItem) { - scene()->removeItem(m_feedbackItem); - delete m_feedbackItem; - m_feedbackItem = nullptr; - } -} - void TableZone::handleDropEvent(const QList &dragItems, CardZone *startZone, const QPoint &dropPoint) { - Q_UNUSED(dropPoint); - - // Always use the position of the feedback item for consistency - if (m_feedbackItem && m_feedbackItem->isVisible()) { - handleDropEventByGrid(dragItems, startZone, mapToGrid(m_feedbackItem->pos())); - } + handleDropEventByGrid(dragItems, startZone, mapToGrid(dropPoint)); } void TableZone::handleDropEventByGrid(const QList &dragItems, @@ -317,6 +260,12 @@ CardItem *TableZone::getCardFromGrid(const QPoint &gridPoint) const return 0; } +CardItem *TableZone::getCardFromCoords(const QPointF &point) const +{ + QPoint gridPoint = mapToGrid(point); + return getCardFromGrid(gridPoint); +} + void TableZone::computeCardStackWidths() { // Each card stack is three grid points worth of card locations. @@ -417,36 +366,18 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const int xDiff = x - xStack; int gridPointX = stackCol * 3 + qMin(xDiff / STACKED_CARD_OFFSET_X, 2); - return QPoint((gridPointX / 3) * 3, gridPointY); + return QPoint(gridPointX, gridPointY); } -void TableZone::updateFeedback(CardDragItem *dragItem, const QPointF &point) +QPointF TableZone::closestGridPoint(const QPointF &point) { QPoint gridPoint = mapToGrid(point); - - for (int i = 0; i < 3; ++i) { - if (CardItem *existingCard = getCardFromGrid(gridPoint)) { - if (existingCard == dragItem->getItem()) { - // Dropping the card onto its existing position is a no-op, and - // we don't want to display the feedback item, but we don't want - // to display an invalid state either, because that'd be - // confusing. - dragItem->setValid(true); - m_feedbackItem->hide(); - return; - } - - gridPoint.setX(gridPoint.x() + 1); - } else { - dragItem->setValid(true); - m_feedbackItem->show(); - m_feedbackItem->setPos(mapFromGrid(gridPoint)); - return; - } - } - - dragItem->setValid(false); - m_feedbackItem->hide(); + gridPoint.setX((gridPoint.x() / 3) * 3); + if (getCardFromGrid(gridPoint)) + gridPoint.setX(gridPoint.x() + 1); + if (getCardFromGrid(gridPoint)) + gridPoint.setX(gridPoint.x() + 1); + return mapFromGrid(gridPoint); } int TableZone::clampValidTableRow(const int row) diff --git a/cockatrice/src/game/zones/table_zone.h b/cockatrice/src/game/zones/table_zone.h index a10a05306..271276967 100644 --- a/cockatrice/src/game/zones/table_zone.h +++ b/cockatrice/src/game/zones/table_zone.h @@ -77,8 +77,6 @@ private: */ bool active; - QGraphicsPathItem *m_feedbackItem = nullptr; - bool isInverted() const; private slots: @@ -120,14 +118,6 @@ public: */ void toggleTapped(); - bool dragEnter(CardDragItem *dragItem, const QPointF &pos) override; - - void dragMove(CardDragItem *dragItem, const QPointF &pos) override; - - void dragAccept(CardDragItem *dragItem, const QPointF &pos) override; - - void dragLeave(CardDragItem *dragItem) override; - /** See HandleDropEventByGrid */ @@ -143,6 +133,13 @@ public: */ CardItem *getCardFromGrid(const QPoint &gridPoint) const; + /** + @return CardItem from coordinate location + */ + CardItem *getCardFromCoords(const QPointF &point) const; + + QPointF closestGridPoint(const QPointF &point) override; + static int clampValidTableRow(const int row); /** @@ -187,8 +184,6 @@ private: void paintZoneOutline(QPainter *painter); void paintLandDivider(QPainter *painter); - void updateFeedback(CardDragItem *dragItem, const QPointF &point); - /* Calculates card stack widths so mapping functions work properly */