mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-02 03:23:56 -07:00
Display visual feedback of where cards will go (#5737)
This is part of the code from #4974, including an improved drag-and-drop API and its use to display visual feedback of card destination on the board. It does not include the improved logic for pushing cards around as I still need to figure out edge cases there - the logic for choosing where cards go is not changed, so some of the artifacts described in #4817 and #4975 (particularly around multi-card) are still present.
This commit is contained in:
parent
bd28e04635
commit
a7641a571f
6 changed files with 230 additions and 100 deletions
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#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>
|
||||
|
|
@ -15,104 +13,112 @@ CardDragItem::CardDragItem(CardItem *_item,
|
|||
const QPointF &_hotSpot,
|
||||
bool _faceDown,
|
||||
AbstractCardDragItem *parentDrag)
|
||||
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0)
|
||||
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), 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 (occupied)
|
||||
if (!isValid) {
|
||||
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<QGraphicsItem *> colliding =
|
||||
scene()->items(cursorScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder,
|
||||
scene()->items(centerScenePos, 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;
|
||||
if (!cursorZone)
|
||||
return;
|
||||
currentZone = cursorZone;
|
||||
CardZone *cardZone = nullptr;
|
||||
for (auto *item : colliding) {
|
||||
cardZone = qgraphicsitem_cast<CardZone *>(item);
|
||||
|
||||
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();
|
||||
if (cardZone) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cardZone != currentZone) {
|
||||
if (currentZone) {
|
||||
currentZone->dragLeave(this);
|
||||
currentZone = nullptr;
|
||||
}
|
||||
|
||||
if (cardZone && cardZone->dragEnter(this, centerScenePos - cardZone->scenePos())) {
|
||||
setValid(true);
|
||||
currentZone = cardZone;
|
||||
} else {
|
||||
setValid(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentZone) {
|
||||
currentZone->dragMove(this, centerScenePos - currentZone->scenePos());
|
||||
}
|
||||
|
||||
if (topLeftScenePos != pos()) {
|
||||
for (int i = 0; i < childDrags.size(); i++)
|
||||
childDrags[i]->setPos(topLeftScenePos + childDrags[i]->getHotSpot());
|
||||
setPos(topLeftScenePos);
|
||||
}
|
||||
}
|
||||
|
||||
void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
QGraphicsScene *sc = scene();
|
||||
QPointF sp = pos();
|
||||
sc->removeItem(this);
|
||||
|
||||
QList<CardDragItem *> dragItemList;
|
||||
CardZone *startZone = static_cast<CardItem *>(item)->getZone();
|
||||
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone))) {
|
||||
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)) &&
|
||||
!c->occupied) {
|
||||
dragItemList.append(c);
|
||||
}
|
||||
sc->removeItem(c);
|
||||
}
|
||||
for (auto *childDrag : childDrags) {
|
||||
sc->removeItem(childDrag);
|
||||
}
|
||||
|
||||
if (currentZone) {
|
||||
currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint());
|
||||
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;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
static_cast<CardItem *>(item)->deleteDragItem();
|
||||
AbstractCardDragItem::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
CardZone *CardDragItem::getStartZone() const
|
||||
{
|
||||
return static_cast<CardItem *>(item)->getZone();
|
||||
}
|
||||
|
||||
QList<CardDragItem *> CardDragItem::getValidItems()
|
||||
{
|
||||
QList<CardDragItem *> dragItemList;
|
||||
CardZone *startZone = getStartZone();
|
||||
if (!(static_cast<CardItem *>(item)->getAttachedTo() && startZone == currentZone)) {
|
||||
dragItemList.append(this);
|
||||
|
||||
for (int i = 0; i < childDrags.size(); i++) {
|
||||
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);
|
||||
if (!(static_cast<CardItem *>(c->item)->getAttachedTo() && startZone == currentZone)) {
|
||||
dragItemList.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dragItemList;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue