#include "player_graphics_item.h" #include "../../game/player/player_actions.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/abstract_card_item.h" #include "../board/counter_general.h" #include "../hand_counter.h" #include "../zones/hand_zone.h" #include "../zones/pile_zone.h" #include "../zones/stack_zone.h" #include "../zones/table_zone.h" #include "menu/player_menu.h" #include "player_dialogs.h" #include PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) { connect(&SettingsCache::instance(), &SettingsCache::horizontalHandChanged, this, &PlayerGraphicsItem::rearrangeZones); connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, &PlayerGraphicsItem::rearrangeZones); connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); connect(player, &PlayerLogic::activeChanged, this, &PlayerGraphicsItem::onPlayerActiveChanged); connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); playerMenu = new PlayerMenu(this); connect(playerMenu, &PlayerMenu::shortcutsActivated, this, [this]() { for (auto *ctr : counterWidgets) { ctr->setShortcutsActive(); } }); connect(playerMenu, &PlayerMenu::shortcutsDeactivated, this, [this]() { for (auto *ctr : counterWidgets) { ctr->setShortcutsInactive(); } }); connect(playerMenu, &PlayerMenu::retranslateRequested, this, [this]() { for (auto *ctr : counterWidgets) { ctr->retranslateUi(); } }); playerDialogs = new PlayerDialogs(this, player->getPlayerActions()); connect(playerDialogs, &PlayerDialogs::requestDialogSemaphore, player, &PlayerLogic::setDialogSemaphore); playerArea = new PlayerArea(this); playerTarget = new PlayerTarget(player, playerArea); qreal avatarMargin = (counterAreaWidth + CardDimensions::HEIGHT_F + 15 - playerTarget->boundingRect().width()) / 2.0; playerTarget->setPos(QPointF(avatarMargin, avatarMargin)); initializeZones(); connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, &PlayerGraphicsItem::onCustomZoneAdded); playerMenu->setMenusForGraphicItems(); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); updateBoundingRect(); rearrangeZones(); retranslateUi(); } void PlayerGraphicsItem::retranslateUi() { playerMenu->retranslateUi(); QMapIterator zoneIterator(player->getZones()); while (zoneIterator.hasNext()) { emit zoneIterator.next().value()->retranslateUi(); } } void PlayerGraphicsItem::onPlayerActiveChanged(bool _active) { tableZoneGraphicsItem->setActive(_active); } void PlayerGraphicsItem::initializeZones() { deckZoneGraphicsItem = new PileZone(player->getDeckZone(), this); auto base = QPointF(counterAreaWidth + (CardDimensions::HEIGHT_F - CardDimensions::WIDTH_F + 15) / 2.0, 10 + playerTarget->boundingRect().height() + 5 - (CardDimensions::HEIGHT_F - CardDimensions::WIDTH_F) / 2.0); deckZoneGraphicsItem->setPos(base); qreal h = deckZoneGraphicsItem->boundingRect().width() + 5; sideboardGraphicsItem = new PileZone(player->getSideboardZone(), this); player->getSideboardZone()->setGraphicsVisibility(false); auto *handCounter = new HandCounter(playerArea); handCounter->setPos(base + QPointF(0, h + 10)); qreal h2 = handCounter->boundingRect().height(); graveyardZoneGraphicsItem = new PileZone(player->getGraveZone(), this); graveyardZoneGraphicsItem->setPos(base + QPointF(0, h + h2 + 10)); rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this); rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10)); tableZoneGraphicsItem = new TableZone(player->getTableZone(), mirrored, this); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); connect(this, &PlayerGraphicsItem::mirroredChanged, tableZoneGraphicsItem, &TableZone::setMirrored); stackZoneGraphicsItem = new StackZone(player->getStackZone(), static_cast(tableZoneGraphicsItem->boundingRect().height()), this); handZoneGraphicsItem = new HandZone(player->getHandZone(), static_cast(tableZoneGraphicsItem->boundingRect().height()), this); connect(player->getPlayerActions(), &PlayerActions::requestSortHand, handZoneGraphicsItem, &HandZone::sortHand); connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter, &HandCounter::updateNumber); connect(handCounter, &HandCounter::showContextMenu, handZoneGraphicsItem, &HandZone::showContextMenu); zoneGraphicsItems.insert(player->getDeckZone()->getName(), deckZoneGraphicsItem); zoneGraphicsItems.insert(player->getGraveZone()->getName(), graveyardZoneGraphicsItem); zoneGraphicsItems.insert(player->getRfgZone()->getName(), rfgZoneGraphicsItem); zoneGraphicsItems.insert(player->getSideboardZone()->getName(), sideboardGraphicsItem); zoneGraphicsItems.insert(player->getTableZone()->getName(), tableZoneGraphicsItem); zoneGraphicsItems.insert(player->getStackZone()->getName(), stackZoneGraphicsItem); zoneGraphicsItems.insert(player->getHandZone()->getName(), handZoneGraphicsItem); } void PlayerGraphicsItem::onCustomZoneAdded(QString customZoneName) { zoneGraphicsItems.insert(customZoneName, nullptr); // Custom zone view goes here, if we ever implement it. } QRectF PlayerGraphicsItem::boundingRect() const { return bRect; } qreal PlayerGraphicsItem::getMinimumWidth() const { qreal result = tableZoneGraphicsItem->getMinimumWidth() + CardDimensions::HEIGHT_F + 15 + counterAreaWidth + stackZoneGraphicsItem->boundingRect().width(); if (!SettingsCache::instance().getHorizontalHand()) { result += handZoneGraphicsItem->boundingRect().width(); } return result; } void PlayerGraphicsItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { } void PlayerGraphicsItem::processSceneSizeChange(int newPlayerWidth) { // Extend table (and hand, if horizontal) to accommodate the new player width. qreal tableWidth = newPlayerWidth - CardDimensions::HEIGHT_F - 15 - counterAreaWidth - stackZoneGraphicsItem->boundingRect().width(); if (!SettingsCache::instance().getHorizontalHand()) { tableWidth -= handZoneGraphicsItem->boundingRect().width(); } tableZoneGraphicsItem->setWidth(tableWidth); handZoneGraphicsItem->setWidth(tableWidth + stackZoneGraphicsItem->boundingRect().width()); } void PlayerGraphicsItem::setMirrored(bool _mirrored) { if (mirrored != _mirrored) { mirrored = _mirrored; emit mirroredChanged(mirrored); rearrangeZones(); } } void PlayerGraphicsItem::onCounterAdded(CounterState *state) { AbstractCounter *widget; if (state->getName() == "life") { widget = playerTarget->addCounter(state); } else { widget = new GeneralCounter(state, player, true, this); } counterWidgets.insert(state->getId(), widget); if (playerMenu->getCountersMenu() && widget->getMenu()) { playerMenu->getCountersMenu()->addMenu(widget->getMenu()); } if (playerMenu->getShortcutsActive()) { widget->setShortcutsActive(); } rearrangeCounters(); } void PlayerGraphicsItem::onCounterRemoved(int counterId) { auto *widget = counterWidgets.take(counterId); if (!widget) { return; } if (playerMenu->getCountersMenu() && widget->getMenu()) { playerMenu->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); } widget->delCounter(); rearrangeCounters(); } void PlayerGraphicsItem::rearrangeCounters() { qreal ySize = boundingRect().y() + 80; constexpr qreal padding = 5; for (auto *ctr : counterWidgets.values()) { if (!ctr->getShownInCounterArea()) { continue; } QRectF br = ctr->boundingRect(); ctr->setPos((counterAreaWidth - br.width()) / 2, ySize); ySize += br.height() + padding; } } void PlayerGraphicsItem::rearrangeZones() { auto base = QPointF(CardDimensions::HEIGHT_F + counterAreaWidth + 15, 0); if (SettingsCache::instance().getHorizontalHand()) { if (mirrored) { if (player->getHandZone()->contentsKnown()) { handVisible = true; handZoneGraphicsItem->setPos(base); base += QPointF(0, handZoneGraphicsItem->boundingRect().height()); } else { handVisible = false; } stackZoneGraphicsItem->setPos(base); base += QPointF(stackZoneGraphicsItem->boundingRect().width(), 0); tableZoneGraphicsItem->setPos(base); } else { stackZoneGraphicsItem->setPos(base); tableZoneGraphicsItem->setPos(base.x() + stackZoneGraphicsItem->boundingRect().width(), 0); base += QPointF(0, tableZoneGraphicsItem->boundingRect().height()); if (player->getHandZone()->contentsKnown()) { handVisible = true; handZoneGraphicsItem->setPos(base); } else { handVisible = false; } } handZoneGraphicsItem->setWidth(tableZoneGraphicsItem->getWidth() + stackZoneGraphicsItem->boundingRect().width()); } else { handVisible = true; handZoneGraphicsItem->setPos(base); base += QPointF(handZoneGraphicsItem->boundingRect().width(), 0); stackZoneGraphicsItem->setPos(base); base += QPointF(stackZoneGraphicsItem->boundingRect().width(), 0); tableZoneGraphicsItem->setPos(base); } handZoneGraphicsItem->setVisible(handVisible); handZoneGraphicsItem->updateOrientation(); tableZoneGraphicsItem->reorganizeCards(); updateBoundingRect(); rearrangeCounters(); } void PlayerGraphicsItem::updateBoundingRect() { prepareGeometryChange(); qreal width = CardDimensions::HEIGHT_F + 15 + counterAreaWidth + stackZoneGraphicsItem->boundingRect().width(); if (SettingsCache::instance().getHorizontalHand()) { qreal handHeight = handVisible ? handZoneGraphicsItem->boundingRect().height() : 0; bRect = QRectF(0, 0, width + tableZoneGraphicsItem->boundingRect().width(), tableZoneGraphicsItem->boundingRect().height() + handHeight); } else { bRect = QRectF( 0, 0, width + handZoneGraphicsItem->boundingRect().width() + tableZoneGraphicsItem->boundingRect().width(), tableZoneGraphicsItem->boundingRect().height()); } playerArea->setSize(CardDimensions::HEIGHT_F + counterAreaWidth + 15, bRect.height()); emit sizeChanged(); }