Cockatrice/cockatrice/src/game/board/card_drag_item.cpp
RickyRister 2fba5dcd20
[Game] Refactor CardDragItem faceDown logic (#6552)
* Rename properties and only pass forceFaceDown

* [Game] Refactor CardDragItem faceDown logic

* revert refactor

* leave face_down unset unless forced
2026-03-03 23:18:21 +01:00

135 lines
4.4 KiB
C++

#include "card_drag_item.h"
#include "../game_scene.h"
#include "../zones/card_zone.h"
#include "../zones/table_zone.h"
#include "../zones/view_zone.h"
#include "card_item.h"
#include <QCursor>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
CardDragItem::CardDragItem(CardItem *_item,
int _id,
const QPointF &_hotSpot,
bool _forceFaceDown,
AbstractCardDragItem *parentDrag)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), forceFaceDown(_forceFaceDown), occupied(false),
currentZone(0)
{
}
void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
AbstractCardDragItem::paint(painter, option, widget);
if (occupied)
painter->fillPath(shape(), QColor(200, 0, 0, 100));
}
void CardDragItem::updatePosition(const QPointF &cursorScenePos)
{
QList<QGraphicsItem *> colliding =
scene()->items(cursorScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder,
static_cast<GameScene *>(scene())->getViewTransform());
CardZone *cardZone = 0;
ZoneViewZone *zoneViewZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--) {
CardZone *temp = qgraphicsitem_cast<CardZone *>(colliding.at(i));
if (!cardZone)
cardZone = temp;
if (!zoneViewZone)
zoneViewZone = qobject_cast<ZoneViewZone *>(temp);
}
CardZone *cursorZone = 0;
if (zoneViewZone)
cursorZone = zoneViewZone;
else if (cardZone)
cursorZone = cardZone;
// Always update the current zone, even if its null, to cancel the drag
// instead of dropping cards into an non-intuitive location.
currentZone = cursorZone;
if (!cursorZone) {
// Avoid the cards getting stuck visually when not over
// any zone.
QPointF newPos = cursorScenePos - hotSpot;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
}
return;
}
QPointF zonePos = currentZone->scenePos();
QPointF cursorPosInZone = cursorScenePos - zonePos;
// 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<TableZone *>(cursorZone);
QPointF closestGridPoint;
if (tableZone)
closestGridPoint = tableZone->closestGridPoint(cursorPosInZone);
else
closestGridPoint = cursorPosInZone - hotSpot;
QPointF newPos = zonePos + closestGridPoint;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
bool newOccupied = false;
TableZone *table = qobject_cast<TableZone *>(cursorZone);
if (table)
if (table->getCardFromCoords(closestGridPoint))
newOccupied = true;
if (newOccupied != occupied) {
occupied = newOccupied;
update();
}
}
}
void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
setCursor(Qt::OpenHandCursor);
QGraphicsScene *sc = scene();
QPointF sp = pos();
sc->removeItem(this);
QList<CardDragItem *> dragItemList;
CardZoneLogic *startZone = static_cast<CardItem *>(item)->getZone();
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone->getLogic()))) {
if (!occupied) {
dragItemList.append(this);
}
for (int i = 0; i < childDrags.size(); i++) {
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);
if (!occupied &&
!(static_cast<CardItem *>(c->item)->getAttachedTo() && (startZone == currentZone->getLogic())) &&
!c->occupied) {
dragItemList.append(c);
}
sc->removeItem(c);
}
}
if (currentZone) {
currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint());
}
event->accept();
}