#include #include #include #include #include #include "gamescene.h" #include "carditem.h" #include "carddragitem.h" #include "carddatabase.h" #include "cardzone.h" #include "zoneviewzone.h" #include "tablezone.h" #include "player.h" #include "arrowitem.h" #include "main.h" #include "settingscache.h" #include "tab_game.h" #include "pb/serverinfo_card.pb.h" CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _revealedCard, QGraphicsItem *parent) : AbstractCardItem(_name, _owner, _cardid, parent), zone(0), revealedCard(_revealedCard), attacking(false), destroyOnZoneChange(false), doesntUntap(false), dragItem(0), attachedTo(0) { owner->addCard(this); cardMenu = new QMenu; ptMenu = new QMenu; moveMenu = new QMenu; retranslateUi(); emit updateCardMenu(this); } CardItem::~CardItem() { prepareDelete(); if (scene()) static_cast(scene())->unregisterAnimationItem(this); delete cardMenu; delete ptMenu; delete moveMenu; deleteDragItem(); } void CardItem::prepareDelete() { if (owner) { if (owner->getCardMenu() == cardMenu) { owner->setCardMenu(0); owner->getGame()->setActiveCard(0); } owner = 0; } while (!attachedCards.isEmpty()) { attachedCards.first()->setZone(0); // so that it won't try to call reorganizeCards() attachedCards.first()->setAttachedTo(0); } if (attachedTo) { attachedTo->removeAttachedCard(this); attachedTo = 0; } } void CardItem::deleteLater() { prepareDelete(); AbstractCardItem::deleteLater(); } void CardItem::setZone(CardZone *_zone) { zone = _zone; emit updateCardMenu(this); } void CardItem::retranslateUi() { moveMenu->setTitle(tr("&Move to")); ptMenu->setTitle(tr("&Power / toughness")); } void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->save(); AbstractCardItem::paint(painter, option, widget); int i = 0; QMapIterator counterIterator(counters); while (counterIterator.hasNext()) { counterIterator.next(); QColor color; color.setHsv(counterIterator.key() * 60, 150, 255); paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter); ++i; } QSizeF translatedSize = getTranslatedSize(painter); qreal scaleFactor = translatedSize.width() / boundingRect().width(); if (!pt.isEmpty()) { painter->save(); transformPainter(painter, translatedSize, tapAngle); painter->setBackground(Qt::black); painter->setBackgroundMode(Qt::OpaqueMode); painter->setPen(Qt::white); painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignRight | Qt::AlignBottom, pt); painter->restore(); } if (!annotation.isEmpty()) { painter->save(); transformPainter(painter, translatedSize, tapAngle); painter->setBackground(Qt::black); painter->setBackgroundMode(Qt::OpaqueMode); painter->setPen(Qt::white); painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignCenter | Qt::TextWrapAnywhere, annotation); painter->restore(); } if (getBeingPointedAt()) painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100))); painter->restore(); } void CardItem::setAttacking(bool _attacking) { attacking = _attacking; update(); } void CardItem::setCounter(int _id, int _value) { if (_value) counters.insert(_id, _value); else counters.remove(_id); update(); } void CardItem::setAnnotation(const QString &_annotation) { annotation = _annotation; update(); } void CardItem::setDoesntUntap(bool _doesntUntap) { doesntUntap = _doesntUntap; } void CardItem::setPT(const QString &_pt) { pt = _pt; update(); } void CardItem::setAttachedTo(CardItem *_attachedTo) { if (attachedTo) attachedTo->removeAttachedCard(this); gridPoint.setX(-1); attachedTo = _attachedTo; if (attachedTo) { setParentItem(attachedTo->getZone()); attachedTo->addAttachedCard(this); if (zone != attachedTo->getZone()) attachedTo->getZone()->reorganizeCards(); } else setParentItem(zone); if (zone) zone->reorganizeCards(); emit updateCardMenu(this); } void CardItem::resetState() { attacking = false; facedown = false; counters.clear(); pt.clear(); annotation.clear(); attachedTo = 0; attachedCards.clear(); setTapped(false, false); setDoesntUntap(false); if (scene()) static_cast(scene())->unregisterAnimationItem(this); update(); } void CardItem::processCardInfo(const ServerInfo_Card &info) { counters.clear(); const int counterListSize = info.counter_list_size(); for (int i = 0; i < counterListSize; ++i) { const ServerInfo_CardCounter &counterInfo = info.counter_list(i); counters.insert(counterInfo.id(), counterInfo.value()); } setId(info.id()); setName(QString::fromStdString(info.name())); setAttacking(info.attacking()); setFaceDown(info.face_down()); setPT(QString::fromStdString(info.pt())); setAnnotation(QString::fromStdString(info.annotation())); setColor(QString::fromStdString(info.color())); setTapped(info.tapped()); setDestroyOnZoneChange(info.destroy_on_zone_change()); setDoesntUntap(info.doesnt_untap()); } CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown) { deleteDragItem(); dragItem = new CardDragItem(this, _id, _pos, faceDown); dragItem->setVisible(false); scene()->addItem(dragItem); dragItem->updatePosition(_scenePos); dragItem->setVisible(true); return dragItem; } void CardItem::deleteDragItem() { dragItem->deleteLater(); dragItem = NULL; } void CardItem::drawArrow(const QColor &arrowColor) { if (static_cast(owner->parent())->getSpectator()) return; Player *arrowOwner = static_cast(owner->parent())->getActiveLocalPlayer(); ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor); scene()->addItem(arrow); arrow->grabMouse(); QListIterator itemIterator(scene()->selectedItems()); while (itemIterator.hasNext()) { CardItem *c = qgraphicsitem_cast(itemIterator.next()); if (!c || (c == this)) continue; if (c->getZone() != zone) continue; ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor); scene()->addItem(childArrow); arrow->addChildArrow(childArrow); } } void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons().testFlag(Qt::RightButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance()) return; QColor arrowColor = Qt::red; if (event->modifiers().testFlag(Qt::ControlModifier)) arrowColor = Qt::yellow; else if (event->modifiers().testFlag(Qt::AltModifier)) arrowColor = Qt::blue; else if (event->modifiers().testFlag(Qt::ShiftModifier)) arrowColor = Qt::green; drawArrow(arrowColor); } else if (event->buttons().testFlag(Qt::LeftButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) return; if (zone->getIsView()) { const ZoneViewZone *const view = static_cast(zone); if (view->getRevealZone() && !view->getWriteableRevealZone()) return; } else if (!owner->getLocal()) return; bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier); createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown); dragItem->grabMouse(); QList sel = scene()->selectedItems(); int j = 0; for (int i = 0; i < sel.size(); i++) { CardItem *c = (CardItem *) sel.at(i); if ((c == this) || (c->getZone() != zone)) continue; ++j; QPointF childPos; if (zone->getHasCardAttr()) childPos = c->pos() - pos(); else childPos = QPointF(j * CARD_WIDTH / 2, 0); CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem); drag->setPos(dragItem->pos() + childPos); scene()->addItem(drag); } } setCursor(Qt::OpenHandCursor); } void CardItem::playCard(bool faceDown) { // Do nothing if the card belongs to another player if (!owner->getLocal()) return; TableZone *tz = qobject_cast(zone); if (tz) tz->toggleTapped(); else zone->getPlayer()->playCard(this, faceDown, info->getCipt()); } void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { if (cardMenu) if (!cardMenu->isEmpty()) cardMenu->exec(event->screenPos()); } else if ((event->button() == Qt::LeftButton) && !settingsCache->getDoubleClickToPlay()) { bool hideCard = false; if (zone->getIsView()) { ZoneViewZone *view = static_cast(zone); if (view->getRevealZone() && !view->getWriteableRevealZone()) hideCard = true; } if (hideCard) zone->removeCard(this); else playCard(event->modifiers().testFlag(Qt::ShiftModifier)); } setCursor(Qt::OpenHandCursor); AbstractCardItem::mouseReleaseEvent(event); } void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { if (settingsCache->getDoubleClickToPlay()) { if (revealedCard) zone->removeCard(this); else playCard(event->modifiers().testFlag(Qt::ShiftModifier)); } event->accept(); } bool CardItem::animationEvent() { int delta = 18; if (!tapped) delta *= -1; tapAngle += delta; setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); setHovered(false); update(); if ((tapped && (tapAngle >= 90)) || (!tapped && (tapAngle <= 0))) return false; return true; } QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value) { if ((change == ItemSelectedHasChanged) && owner) { if (value == true) { owner->setCardMenu(cardMenu); owner->getGame()->setActiveCard(this); } else if (owner->getCardMenu() == cardMenu) { owner->setCardMenu(0); owner->getGame()->setActiveCard(0); } } return QGraphicsItem::itemChange(change, value); }