mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-05 04:53:54 -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
|
|
@ -1,11 +1,10 @@
|
|||
#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 <QAction>
|
||||
|
|
@ -233,7 +232,26 @@ void CardZone::moveAllToZone()
|
|||
player->sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
QPointF CardZone::closestGridPoint(const QPointF &point)
|
||||
bool CardZone::dragEnter(CardDragItem *dragItem, const QPointF &pos)
|
||||
{
|
||||
return 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,26 @@ 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<CardDragItem *> &dragItem, CardZone *startZone, const QPoint &dropPoint) = 0;
|
||||
CardZone(Player *_player,
|
||||
|
|
@ -114,7 +134,6 @@ public:
|
|||
return views;
|
||||
}
|
||||
virtual void reorganizeCards() = 0;
|
||||
virtual QPointF closestGridPoint(const QPointF &point);
|
||||
bool getIsView() const
|
||||
{
|
||||
return isView;
|
||||
|
|
|
|||
|
|
@ -118,9 +118,66 @@ 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<CardDragItem *> &dragItems, CardZone *startZone, const QPoint &dropPoint)
|
||||
{
|
||||
handleDropEventByGrid(dragItems, startZone, mapToGrid(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()));
|
||||
}
|
||||
}
|
||||
|
||||
void TableZone::handleDropEventByGrid(const QList<CardDragItem *> &dragItems,
|
||||
|
|
@ -260,12 +317,6 @@ 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.
|
||||
|
|
@ -366,18 +417,36 @@ 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, gridPointY);
|
||||
return QPoint((gridPointX / 3) * 3, gridPointY);
|
||||
}
|
||||
|
||||
QPointF TableZone::closestGridPoint(const QPointF &point)
|
||||
void TableZone::updateFeedback(CardDragItem *dragItem, const QPointF &point)
|
||||
{
|
||||
QPoint gridPoint = mapToGrid(point);
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
int TableZone::clampValidTableRow(const int row)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ private:
|
|||
*/
|
||||
bool active;
|
||||
|
||||
QGraphicsPathItem *m_feedbackItem = nullptr;
|
||||
|
||||
bool isInverted() const;
|
||||
|
||||
private slots:
|
||||
|
|
@ -118,6 +120,14 @@ 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
|
||||
*/
|
||||
|
|
@ -133,13 +143,6 @@ 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);
|
||||
|
||||
/**
|
||||
|
|
@ -184,6 +187,8 @@ 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
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue