diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 3dab527f..f7135661 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -37,6 +37,7 @@ HEADERS += src/counter.h \ src/setsmodel.h \ src/window_sets.h \ src/abstractgraphicsitem.h \ + src/abstractcarddragitem.h \ src/dlg_settings.h \ src/dlg_cardsearch.h \ src/phasestoolbar.h \ @@ -89,6 +90,7 @@ SOURCES += src/counter.cpp \ src/setsmodel.cpp \ src/window_sets.cpp \ src/abstractgraphicsitem.cpp \ + src/abstractcarddragitem.cpp \ src/dlg_settings.cpp \ src/dlg_cardsearch.cpp \ src/phasestoolbar.cpp \ diff --git a/cockatrice/src/abstractcarddragitem.cpp b/cockatrice/src/abstractcarddragitem.cpp new file mode 100644 index 00000000..7b4e93ef --- /dev/null +++ b/cockatrice/src/abstractcarddragitem.cpp @@ -0,0 +1,50 @@ +#include "abstractcarddragitem.h" +#include "carddatabase.h" +#include +#include + +AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag) + : QGraphicsItem(), item(_item), hotSpot(_hotSpot) +{ + if (parentDrag) { + parentDrag->addChildDrag(this); + setZValue(1000000000 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000); + } else { + if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) { + qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1()); + hotSpot = QPointF(); + } else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) { + qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1()); + hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT); + } + setCursor(Qt::ClosedHandCursor); + setZValue(1000000000); + } + if (item->getTapped()) + setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); + + setCacheMode(DeviceCoordinateCache); +} + +AbstractCardDragItem::~AbstractCardDragItem() +{ + qDebug("CardDragItem destructor"); + for (int i = 0; i < childDrags.size(); i++) + delete childDrags[i]; +} + +void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + item->paint(painter, option, widget); +} + +void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + event->accept(); + updatePosition(event->scenePos()); +} + +void AbstractCardDragItem::addChildDrag(AbstractCardDragItem *child) +{ + childDrags << child; +} diff --git a/cockatrice/src/abstractcarddragitem.h b/cockatrice/src/abstractcarddragitem.h new file mode 100644 index 00000000..c136b890 --- /dev/null +++ b/cockatrice/src/abstractcarddragitem.h @@ -0,0 +1,29 @@ +#ifndef ABSTRACTCARDDRAGITEM_H +#define ABSTRACTCARDDRAGITEM_H + +#include "abstractcarditem.h" + +class QGraphicsScene; +class CardZone; +class CardInfo; + +class AbstractCardDragItem : public QGraphicsItem { +protected: + AbstractCardItem *item; + QPointF hotSpot; + QList childDrags; +public: + enum { Type = typeCardDrag }; + int type() const { return Type; } + AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0); + ~AbstractCardDragItem(); + QRectF boundingRect() const { return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); } + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QPointF getHotSpot() const { return hotSpot; } + void addChildDrag(AbstractCardDragItem *child); + virtual void updatePosition(const QPointF &cursorScenePos) = 0; +protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); +}; + +#endif diff --git a/cockatrice/src/carddragitem.cpp b/cockatrice/src/carddragitem.cpp index ee537119..1524e9d0 100644 --- a/cockatrice/src/carddragitem.cpp +++ b/cockatrice/src/carddragitem.cpp @@ -1,42 +1,13 @@ #include "carddragitem.h" #include "cardzone.h" -#include "carddatabase.h" #include "tablezone.h" -#include +#include +#include +#include -CardDragItem::CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, CardDragItem *parentDrag) - : QGraphicsItem(), id(_id), item(_item), hotSpot(_hotSpot), faceDown(_faceDown), currentZone(0) +CardDragItem::CardDragItem(AbstractCardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag) + : AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), currentZone(0) { - if (parentDrag) { - parentDrag->addChildDrag(this); - setZValue(1000000000 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000); - } else { - if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) { - qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1()); - hotSpot = QPointF(); - } else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) { - qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1()); - hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT); - } - setCursor(Qt::ClosedHandCursor); - setZValue(1000000000); - } - if (item->getTapped()) - setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); - - setCacheMode(DeviceCoordinateCache); -} - -CardDragItem::~CardDragItem() -{ - qDebug("CardDragItem destructor"); - for (int i = 0; i < childDrags.size(); i++) - delete childDrags[i]; -} - -void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - item->paint(painter, option, widget); } void CardDragItem::updatePosition(const QPointF &cursorScenePos) @@ -56,8 +27,6 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos) QPointF cardTopLeft = cursorPosInZone - hotSpot; QPointF newPos = zonePos + cursorZone->closestGridPoint(cardTopLeft); -// qDebug(QString("cardTopLeft = %1, %2 cardCenter = %3, %4").arg((cardTopLeft).x()).arg((cardTopLeft).y()).arg(cardCenter.x()).arg(cardCenter.y()).toLatin1()); - if (newPos != pos()) { for (int i = 0; i < childDrags.size(); i++) childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); @@ -65,25 +34,18 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos) } } -void CardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - event->accept(); - updatePosition(event->scenePos()); -} - void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { setCursor(Qt::OpenHandCursor); QGraphicsScene *sc = scene(); QPointF sp = pos(); - qDebug(QString("sp: x=%1, y=%2").arg(sp.x()).arg(sp.y()).toLatin1()); sc->removeItem(this); if (currentZone) { CardZone *startZone = qgraphicsitem_cast(item->parentItem()); currentZone->handleDropEvent(id, startZone, (sp - currentZone->scenePos()).toPoint(), faceDown); for (int i = 0; i < childDrags.size(); i++) { - CardDragItem *c = childDrags[i]; + CardDragItem *c = static_cast(childDrags[i]); currentZone->handleDropEvent(c->id, startZone, (sp - currentZone->scenePos() + c->getHotSpot()).toPoint(), faceDown); sc->removeItem(c); } @@ -91,8 +53,3 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) event->accept(); } - -void CardDragItem::addChildDrag(CardDragItem *child) -{ - childDrags << child; -} diff --git a/cockatrice/src/carddragitem.h b/cockatrice/src/carddragitem.h index 594a8cc6..d1095f1d 100644 --- a/cockatrice/src/carddragitem.h +++ b/cockatrice/src/carddragitem.h @@ -1,33 +1,18 @@ #ifndef CARDDRAGITEM_H #define CARDDRAGITEM_H -#include "carditem.h" +#include "abstractcarddragitem.h" -class QGraphicsScene; -class CardZone; -class CardInfo; - -class CardDragItem : public QGraphicsItem { +class CardDragItem : public AbstractCardDragItem { private: int id; - CardItem *item; - QPointF hotSpot; bool faceDown; - QList childDrags; CardZone *currentZone; public: - enum { Type = typeCardDrag }; - int type() const { return Type; } - CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, CardDragItem *parentDrag = 0); - ~CardDragItem(); - QRectF boundingRect() const { return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); } - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - QPointF getHotSpot() const { return hotSpot; } - void addChildDrag(CardDragItem *child); + CardDragItem(AbstractCardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0); void updatePosition(const QPointF &cursorScenePos); protected: - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); }; -#endif +#endif \ No newline at end of file diff --git a/cockatrice/src/deckview.cpp b/cockatrice/src/deckview.cpp index 7dcb3e23..4b631653 100644 --- a/cockatrice/src/deckview.cpp +++ b/cockatrice/src/deckview.cpp @@ -5,13 +5,110 @@ #include "main.h" #include -DeckViewCard::DeckViewCard(const QString &_name, QGraphicsItem *parent) - : AbstractCardItem(_name, parent) +DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag) + : AbstractCardDragItem(_item, _hotSpot, parentDrag) { } +void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos) +{ + QList colliding = scene()->items(cursorScenePos); + + DeckViewCardContainer *cursorZone = 0; + for (int i = colliding.size() - 1; i >= 0; i--) + if ((cursorZone = qgraphicsitem_cast(colliding.at(i)))) + break; + if (!cursorZone) + return; + currentZone = cursorZone; + + QPointF newPos = cursorScenePos; + if (newPos != pos()) { + for (int i = 0; i < childDrags.size(); i++) + childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); + setPos(newPos); + } +} + +void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target) +{ + DeckViewCard *card = static_cast(item); + DeckViewCardContainer *start = static_cast(item->parentItem()); + start->removeCard(card); + target->addCard(card); + card->setParentItem(target); +} + +void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + setCursor(Qt::OpenHandCursor); + DeckViewScene *sc = static_cast(scene()); + QPointF sp = pos(); + sc->removeItem(this); + + if (currentZone) { + handleDrop(currentZone); + for (int i = 0; i < childDrags.size(); i++) { + DeckViewCardDragItem *c = static_cast(childDrags[i]); + c->handleDrop(currentZone); + sc->removeItem(c); + } + + sc->updateContents(); + } + + event->accept(); +} + +DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent) + : AbstractCardItem(_name, parent), originZone(_originZone), dragItem(0) +{ +} + +void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + AbstractCardItem::paint(painter, option, widget); + + painter->save(); + QPen pen(Qt::DotLine); + pen.setWidth(2); + if (originZone == "main") + pen.setColor(QColor(0, 255, 0)); + else + pen.setColor(QColor(255, 255, 0)); + painter->setPen(pen); + painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2)); + painter->restore(); +} + +void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) + return; + + delete dragItem; + dragItem = new DeckViewCardDragItem(this, event->pos()); + scene()->addItem(dragItem); + dragItem->updatePosition(event->scenePos()); + dragItem->grabMouse(); + + QList sel = scene()->selectedItems(); + int j = 0; + for (int i = 0; i < sel.size(); i++) { + DeckViewCard *c = static_cast(sel.at(i)); + if (c == this) + continue; + ++j; + QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0); + DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem); + drag->setPos(dragItem->pos() + childPos); + scene()->addItem(drag); + } + setCursor(Qt::OpenHandCursor); +} + DeckViewCardContainer::DeckViewCardContainer(const QString &_name) - : QGraphicsItem(), name(_name), width(0), height(0) + : QGraphicsItem(), name(_name), width(0), height(0), maxWidth(0) { QSettings settings; QString bgPath = settings.value("zonebg/table").toString(); @@ -41,23 +138,32 @@ void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsI f.setPixelSize(24); f.setWeight(QFont::Bold); painter->setFont(f); - painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name)); + painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size())); } void DeckViewCardContainer::addCard(DeckViewCard *card) { - cards.insertMulti(card->getInfo()->getMainCardType(), card); + cards.append(card); +} + +void DeckViewCardContainer::removeCard(DeckViewCard *card) +{ + cards.removeAt(cards.indexOf(card)); } void DeckViewCardContainer::rearrangeItems() { separatorY = 30; - QList cardTypeList = cards.uniqueKeys(); + QMap cardsByType; + for (int i = 0; i < cards.size(); ++i) + cardsByType.insertMulti(cards[i]->getInfo()->getMainCardType(), cards[i]); + + QList cardTypeList = cardsByType.uniqueKeys(); int rows = cardTypeList.size(); int cols = 0; for (int i = 0; i < rows; ++i) { - QList row = cards.values(cardTypeList[i]); + QList row = cardsByType.values(cardTypeList[i]); if (row.size() > cols) cols = row.size(); for (int j = 0; j < row.size(); ++j) { @@ -67,7 +173,8 @@ void DeckViewCardContainer::rearrangeItems() } prepareGeometryChange(); - width = cols * CARD_WIDTH; + if (cols * CARD_WIDTH > maxWidth) + width = maxWidth = cols * CARD_WIDTH; height = separatorY + 10 + rows * CARD_HEIGHT + rowSpacing * (rows - 1); } @@ -98,6 +205,7 @@ void DeckViewScene::setDeck(DeckList *_deck) deck = _deck; rebuildTree(); + applySideboardPlan(deck->getCurrentSideboardPlan()); rearrangeItems(); } @@ -120,7 +228,7 @@ void DeckViewScene::rebuildTree() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), container); + DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container); container->addCard(newCard); emit newCardAdded(newCard); } @@ -128,6 +236,32 @@ void DeckViewScene::rebuildTree() } } +void DeckViewScene::applySideboardPlan(const QList &plan) +{ + for (int i = 0; i < plan.size(); ++i) { + MoveCardToZone *m = plan[i]; + + DeckViewCardContainer *start = cardContainers.value(m->getStartZone()); + DeckViewCardContainer *target = cardContainers.value(m->getTargetZone()); + if (!start || !target) + continue; + + DeckViewCard *card = 0; + const QList &cardList = start->getCards(); + for (int j = 0; j < cardList.size(); ++j) + if (cardList[j]->getName() == m->getCardName()) { + card = cardList[j]; + break; + } + if (!card) + continue; + + start->removeCard(card); + target->addCard(card); + card->setParentItem(target); + } +} + void DeckViewScene::rearrangeItems() { const int spacing = CARD_HEIGHT / 3; @@ -148,17 +282,39 @@ void DeckViewScene::rearrangeItems() setSceneRect(QRectF(0, 0, totalWidth, totalHeight)); } +void DeckViewScene::updateContents() +{ + rearrangeItems(); + emit sideboardPlanChanged(); +} + +QList DeckViewScene::getSideboardPlan() const +{ + QList result; + QMapIterator containerIterator(cardContainers); + while (containerIterator.hasNext()) { + DeckViewCardContainer *cont = containerIterator.next().value(); + const QList cardList = cont->getCards(); + for (int i = 0; i < cardList.size(); ++i) + if (cardList[i]->getOriginZone() != cont->getName()) + result.append(new MoveCardToZone(cardList[i]->getName(), cardList[i]->getOriginZone(), cont->getName())); + } + return result; +} + DeckView::DeckView(QWidget *parent) : QGraphicsView(parent) { deckViewScene = new DeckViewScene(this); setBackgroundBrush(QBrush(QColor(0, 0, 0))); + setDragMode(RubberBandDrag); setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing/* | QPainter::SmoothPixmapTransform*/); setScene(deckViewScene); connect(deckViewScene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(updateSceneRect(const QRectF &))); connect(deckViewScene, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *))); + connect(deckViewScene, SIGNAL(sideboardPlanChanged()), this, SIGNAL(sideboardPlanChanged())); } void DeckView::resizeEvent(QResizeEvent *event) @@ -169,7 +325,6 @@ void DeckView::resizeEvent(QResizeEvent *event) void DeckView::updateSceneRect(const QRectF &rect) { - qDebug(QString("deckView::updateSceneRect = %1,%2").arg(rect.width()).arg(rect.height()).toLatin1()); fitInView(rect, Qt::KeepAspectRatio); } diff --git a/cockatrice/src/deckview.h b/cockatrice/src/deckview.h index ae686941..55365136 100644 --- a/cockatrice/src/deckview.h +++ b/cockatrice/src/deckview.h @@ -5,22 +5,45 @@ #include #include #include -#include "carditem.h" +#include "abstractcarditem.h" +#include "abstractcarddragitem.h" class DeckList; class InnerDecklistNode; class CardInfo; +class DeckViewCardContainer; +class DeckViewCardDragItem; +class MoveCardToZone; class DeckViewCard : public AbstractCardItem { +private: + QString originZone; + DeckViewCardDragItem *dragItem; public: - DeckViewCard(const QString &_name = QString(), QGraphicsItem *parent = 0); + DeckViewCard(const QString &_name = QString(), const QString &_originZone = QString(), QGraphicsItem *parent = 0); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + const QString &getOriginZone() const { return originZone; } +protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); +}; + +class DeckViewCardDragItem : public AbstractCardDragItem { +private: + DeckViewCardContainer *currentZone; + void handleDrop(DeckViewCardContainer *target); +public: + DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0); + void updatePosition(const QPointF &cursorScenePos); +protected: + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); }; class DeckViewCardContainer : public QGraphicsItem { private: QString name; - QMap cards; + QList cards; qreal width, height; + qreal maxWidth; qreal separatorY; QPixmap bgPixmap; static const int rowSpacing = 5; @@ -29,6 +52,9 @@ public: QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void addCard(DeckViewCard *card); + void removeCard(DeckViewCard *card); + const QList &getCards() const { return cards; } + const QString &getName() const { return name; } void rearrangeItems(); void setWidth(qreal _width); }; @@ -37,15 +63,19 @@ class DeckViewScene : public QGraphicsScene { Q_OBJECT signals: void newCardAdded(AbstractCardItem *card); + void sideboardPlanChanged(); private: DeckList *deck; QMap cardContainers; void rebuildTree(); + void applySideboardPlan(const QList &plan); void rearrangeItems(); public: DeckViewScene(QObject *parent = 0); ~DeckViewScene(); void setDeck(DeckList *_deck); + void updateContents(); + QList getSideboardPlan() const; }; class DeckView : public QGraphicsView { @@ -58,9 +88,11 @@ public slots: void updateSceneRect(const QRectF &rect); signals: void newCardAdded(AbstractCardItem *card); + void sideboardPlanChanged(); public: DeckView(QWidget *parent = 0); void setDeck(DeckList *_deck); + QList getSideboardPlan() const { return deckViewScene->getSideboardPlan(); } }; #endif diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 2171d206..accd1b00 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -286,9 +286,6 @@ void MessageLogWidget::logSetActivePhase(int phase) void MessageLogWidget::connectToPlayer(Player *player) { connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString))); - connect(player, SIGNAL(logDeckSelect(Player *, int)), this, SLOT(logDeckSelect(Player *, int))); - connect(player, SIGNAL(logReadyStart(Player *)), this, SLOT(logReadyStart(Player *))); - connect(player, SIGNAL(logConcede(Player *)), this, SLOT(logConcede(Player *))); connect(player, SIGNAL(logShuffle(Player *)), this, SLOT(logShuffle(Player *))); connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int))); connect(player, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString)), this, SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString))); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index b22bb8d4..56c3aacd 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -38,7 +38,7 @@ Player::Player(const QString &_name, int _id, bool _local, Client *_client, TabG PileZone *rfg = new PileZone(this, "rfg", false, true, this); rfg->setPos(base + QPointF(0, 2 * h)); - PileZone *sb = new PileZone(this, "sb", false, true, this); + PileZone *sb = new PileZone(this, "sb", false, false, this); sb->setVisible(false); table = new TableZone(this, this); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 74d31bdc..0ea38d58 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -40,6 +40,7 @@ TabGame::TabGame(Client *_client, int _gameId, const QString &_gameDescription, buttonHBox->addStretch(); deckView = new DeckView; connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); + connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged())); QVBoxLayout *deckViewLayout = new QVBoxLayout; deckViewLayout->addLayout(buttonHBox); deckViewLayout->addWidget(deckView); @@ -490,3 +491,9 @@ void TabGame::newCardAdded(AbstractCardItem *card) { connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *))); } + +void TabGame::sideboardPlanChanged() +{ + QList newPlan = deckView->getSideboardPlan(); + client->sendCommand(new Command_SetSideboardPlan(gameId, newPlan)); +} diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 943f7ad4..c5ac11f0 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -92,6 +92,7 @@ private slots: void readyStart(); void deckSelectFinished(ProtocolResponse *r); void newCardAdded(AbstractCardItem *card); + void sideboardPlanChanged(); void actConcede(); void actLeaveGame(); diff --git a/common/decklist.cpp b/common/decklist.cpp index 32167c32..376a3298 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -7,6 +7,41 @@ #include "decklist.h" #include +MoveCardToZone::MoveCardToZone(const QString &_cardName, const QString &_startZone, const QString &_targetZone) + : SerializableItem_Map("move_card_to_zone") +{ + insertItem(new SerializableItem_String("card_name", _cardName)); + insertItem(new SerializableItem_String("start_zone", _startZone)); + insertItem(new SerializableItem_String("target_zone", _targetZone)); +} + +MoveCardToZone::MoveCardToZone(MoveCardToZone *other) + : SerializableItem_Map("move_card_to_zone") +{ + insertItem(new SerializableItem_String("card_name", other->getCardName())); + insertItem(new SerializableItem_String("start_zone", other->getStartZone())); + insertItem(new SerializableItem_String("target_zone", other->getTargetZone())); +} + +SideboardPlan::SideboardPlan(const QString &_name, const QList &_moveList) + : SerializableItem_Map("sideboard_plan") +{ + insertItem(new SerializableItem_String("name", _name)); + + for (int i = 0; i < _moveList.size(); ++i) + itemList.append(_moveList[i]); +} + +void SideboardPlan::setMoveList(const QList &_moveList) +{ + for (int i = 0; i < itemList.size(); ++i) + delete itemList[i]; + itemList.clear(); + + for (int i = 0; i < _moveList.size(); ++i) + itemList.append(_moveList[i]); +} + AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent) : parent(_parent), currentItem(0) { @@ -197,20 +232,57 @@ const QStringList DeckList::fileNameFilters = QStringList() << QObject::tr("All files (*.*)"); DeckList::DeckList() - : SerializableItem("cockatrice_deck"), currentZone(0) + : SerializableItem("cockatrice_deck"), currentZone(0), currentSideboardPlan(0) { root = new InnerDecklistNode; } DeckList::DeckList(DeckList *other) - : SerializableItem("cockatrice_deck"), currentZone(0) + : SerializableItem("cockatrice_deck"), currentZone(0), currentSideboardPlan(0) { root = new InnerDecklistNode(other->getRoot()); + + QMapIterator spIterator(other->getSideboardPlans()); + while (spIterator.hasNext()) { + spIterator.next(); + QList newMoveList; + QList oldMoveList = spIterator.value()->getMoveList(); + for (int i = 0; i < oldMoveList.size(); ++i) + newMoveList.append(new MoveCardToZone(oldMoveList[i])); + sideboardPlans.insert(spIterator.key(), new SideboardPlan(spIterator.key(), newMoveList)); + } } DeckList::~DeckList() { delete root; + + QMapIterator i(sideboardPlans); + while (i.hasNext()) + delete i.next().value(); +} + +QList DeckList::getCurrentSideboardPlan() +{ + SideboardPlan *current = sideboardPlans.value(QString(), 0); + if (!current) + return QList(); + else + return current->getMoveList(); +} + +void DeckList::setCurrentSideboardPlan(const QList &plan) +{ + SideboardPlan *current = sideboardPlans.value(QString(), 0); + if (!current) { + current = new SideboardPlan; + sideboardPlans.insert(QString(), current); + } + + QList newList; + for (int i = 0; i < plan.size(); ++i) + newList.append(new MoveCardToZone(plan[i])); + current->setMoveList(newList); } bool DeckList::readElement(QXmlStreamReader *xml) @@ -218,6 +290,11 @@ bool DeckList::readElement(QXmlStreamReader *xml) if (currentZone) { if (currentZone->readElement(xml)) currentZone = 0; + } else if (currentSideboardPlan) { + if (currentSideboardPlan->readElement(xml)) { + sideboardPlans.insert(currentSideboardPlan->getName(), currentSideboardPlan); + currentSideboardPlan = 0; + } } else if (xml->isEndElement()) { if (xml->name() == "deckname") name = currentElementText; @@ -227,6 +304,8 @@ bool DeckList::readElement(QXmlStreamReader *xml) currentElementText.clear(); } else if (xml->isStartElement() && (xml->name() == "zone")) currentZone = new InnerDecklistNode(xml->attributes().value("name").toString(), root); + else if (xml->isStartElement() && (xml->name() == "sideboard_plan")) + currentSideboardPlan = new SideboardPlan; else if (xml->isCharacters() && !xml->isWhitespace()) currentElementText = xml->text().toString(); return SerializableItem::readElement(xml); @@ -240,6 +319,10 @@ void DeckList::writeElement(QXmlStreamWriter *xml) for (int i = 0; i < root->size(); i++) root->at(i)->writeElement(xml); + + QMapIterator i(sideboardPlans); + while (i.hasNext()) + i.next().value()->write(xml); } void DeckList::loadFromXml(QXmlStreamReader *xml) diff --git a/common/decklist.h b/common/decklist.h index 31d3df94..e55bba30 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -14,6 +14,25 @@ class QXmlStreamWriter; class InnerDecklistNode; +class MoveCardToZone : public SerializableItem_Map { +public: + MoveCardToZone(const QString &_cardName = QString(), const QString &_startZone = QString(), const QString &_targetZone = QString()); + MoveCardToZone(MoveCardToZone *other); + static SerializableItem *newItem() { return new MoveCardToZone; } + QString getCardName() const { return static_cast(itemMap.value("card_name"))->getData(); } + QString getStartZone() const { return static_cast(itemMap.value("start_zone"))->getData(); } + QString getTargetZone() const { return static_cast(itemMap.value("target_zone"))->getData(); } +}; + +class SideboardPlan : public SerializableItem_Map { +public: + SideboardPlan(const QString &_name = QString(), const QList &_moveList = QList()); + static SerializableItem *newItem() { return new SideboardPlan; } + QString getName() const { return static_cast(itemMap.value("name"))->getData(); } + QList getMoveList() const { return typecastItemList(); } + void setMoveList(const QList &_moveList); +}; + class AbstractDecklistNode { protected: InnerDecklistNode *parent; @@ -89,8 +108,10 @@ private: QString name, comments; QString lastFileName; FileFormat lastFileFormat; + QMap sideboardPlans; InnerDecklistNode *root; InnerDecklistNode *currentZone; + SideboardPlan *currentSideboardPlan; QString currentElementText; signals: void deckLoaded(); @@ -106,6 +127,9 @@ public: QString getComments() const { return comments; } QString getLastFileName() const { return lastFileName; } FileFormat getLastFileFormat() const { return lastFileFormat; } + QList getCurrentSideboardPlan(); + void setCurrentSideboardPlan(const QList &plan); + const QMap &getSideboardPlans() const { return sideboardPlans; } bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); diff --git a/common/protocol.cpp b/common/protocol.cpp index d78faf02..79be614a 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -14,6 +14,7 @@ void ProtocolItem::initializeHash() { initializeHashAuto(); + registerSerializableItem("move_card_to_zone", MoveCardToZone::newItem); registerSerializableItem("chat_channel", ServerInfo_ChatChannel::newItem); registerSerializableItem("chat_user", ServerInfo_ChatUser::newItem); registerSerializableItem("game", ServerInfo_Game::newItem); @@ -32,6 +33,7 @@ void ProtocolItem::initializeHash() registerSerializableItem("cmddeck_upload", Command_DeckUpload::newItem); registerSerializableItem("cmddeck_select", Command_DeckSelect::newItem); + registerSerializableItem("cmdset_sideboard_plan", Command_SetSideboardPlan::newItem); registerSerializableItem("resp", ProtocolResponse::newItem); ProtocolResponse::initializeHash(); @@ -170,6 +172,18 @@ DeckList *Command_DeckSelect::getDeck() const return static_cast(itemMap.value("cockatrice_deck")); } +Command_SetSideboardPlan::Command_SetSideboardPlan(int _gameId, const QList &_moveList) + : GameCommand("set_sideboard_plan", _gameId) +{ + for (int i = 0; i < _moveList.size(); ++i) + itemList.append(_moveList[i]); +} + +QList Command_SetSideboardPlan::getMoveList() const +{ + return typecastItemList(); +} + QHash ProtocolResponse::responseHash; ProtocolResponse::ProtocolResponse(int _cmdId, ResponseCode _responseCode, const QString &_itemName) diff --git a/common/protocol.h b/common/protocol.h index 85580cb6..337db848 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -17,12 +17,14 @@ class ProtocolResponse; class DeckList; class GameEvent; class GameEventContainer; +class MoveCardToZone; enum ItemId { ItemId_CommandContainer = ItemId_Other + 50, ItemId_GameEventContainer = ItemId_Other + 51, ItemId_Command_DeckUpload = ItemId_Other + 100, ItemId_Command_DeckSelect = ItemId_Other + 101, + ItemId_Command_SetSideboardPlan = ItemId_Other + 102, ItemId_Event_ListChatChannels = ItemId_Other + 200, ItemId_Event_ChatListPlayers = ItemId_Other + 201, ItemId_Event_ListGames = ItemId_Other + 202, @@ -164,6 +166,15 @@ public: int getDeckId() const { return static_cast(itemMap.value("deck_id"))->getData(); } }; +class Command_SetSideboardPlan : public GameCommand { + Q_OBJECT +public: + Command_SetSideboardPlan(int _gameId = -1, const QList &_moveList = QList()); + static SerializableItem *newItem() { return new Command_SetSideboardPlan; } + int getItemId() const { return ItemId_Command_SetSideboardPlan; } + QList getMoveList() const; +}; + // ----------------- // --- RESPONSES --- // ----------------- diff --git a/common/server_player.cpp b/common/server_player.cpp index cbd986e7..deb8d832 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -103,6 +103,34 @@ void Server_Player::setupZones() z->cards.append(new Server_Card(currentCard->getName(), nextCardId++, 0, 0)); } } + + const QList &sideboardPlan = deck->getCurrentSideboardPlan(); + for (int i = 0; i < sideboardPlan.size(); ++i) { + MoveCardToZone *m = sideboardPlan[i]; + + Server_CardZone *start, *target; + if (m->getStartZone() == "main") + start = deckZone; + else if (m->getStartZone() == "side") + start = sbZone; + else + continue; + if (m->getTargetZone() == "main") + target = deckZone; + else if (m->getTargetZone() == "side") + target = sbZone; + else + continue; + + for (int j = 0; j < start->cards.size(); ++j) + if (start->cards[j]->getName() == m->getCardName()) { + Server_Card *card = start->cards[j]; + start->cards.removeAt(j); + target->cards.append(card); + break; + } + } + deckZone->shuffle(); } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 14814a3a..133dfba0 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -85,6 +85,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm switch (command->getItemId()) { case ItemId_Command_DeckSelect: return cmdDeckSelect(qobject_cast(command), cont, game, player); + case ItemId_Command_SetSideboardPlan: return cmdSetSideboardPlan(qobject_cast(command), cont, game, player); case ItemId_Command_LeaveGame: return cmdLeaveGame(qobject_cast(command), cont, game, player); case ItemId_Command_ReadyStart: return cmdReadyStart(qobject_cast(command), cont, game, player); case ItemId_Command_Concede: return cmdConcede(qobject_cast(command), cont, game, player); @@ -351,6 +352,16 @@ ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, Comm return RespNothing; } +ResponseCode Server_ProtocolHandler::cmdSetSideboardPlan(Command_SetSideboardPlan *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) +{ + DeckList *deck = player->getDeck(); + if (!deck) + return RespContextError; + + deck->setCurrentSideboardPlan(cmd->getMoveList()); + return RespOk; +} + ResponseCode Server_ProtocolHandler::cmdConcede(Command_Concede * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { player->setConceded(true); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index be1b806a..73a316c1 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -51,6 +51,7 @@ private: ResponseCode cmdConcede(Command_Concede *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdReadyStart(Command_ReadyStart *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdDeckSelect(Command_DeckSelect *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); + ResponseCode cmdSetSideboardPlan(Command_SetSideboardPlan *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdSay(Command_Say *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdShuffle(Command_Shuffle *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdMulligan(Command_Mulligan *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);