[Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem (#6944)

* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 48 seconds

* Drop early return.

Took 1 hour 13 minutes


Took 2 minutes

Took 1 minute

* Delete player view.

Took 37 seconds

* Restore card counter color in menu.

Took 5 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-06-09 08:05:39 +02:00 committed by Vasco Guerreiro Vintém Morais
parent 1416ef0ea5
commit 90a49936d7
28 changed files with 538 additions and 368 deletions

View file

@ -44,6 +44,11 @@ signals:
void deleteCardInfoPopup(QString cardName); void deleteCardInfoPopup(QString cardName);
void sigPixmapUpdated(); void sigPixmapUpdated();
void cardShiftClicked(QString cardName); void cardShiftClicked(QString cardName);
void rightClicked(AbstractCardItem *card, QPoint screenPos);
void playSelected(AbstractCardItem *card);
void playSelectedFaceDown(AbstractCardItem *card);
void hideSelected(AbstractCardItem *card);
void selectionChanged(AbstractCardItem *card, bool selected);
public: public:
enum enum

View file

@ -44,7 +44,7 @@ void CardItem::prepareDelete()
{ {
if (owner != nullptr) { if (owner != nullptr) {
if (owner->getGame()->getActiveCard() == this) { if (owner->getGame()->getActiveCard() == this) {
owner->getPlayerMenu()->updateCardMenu(nullptr); emit owner->requestCardMenuUpdate(nullptr);
owner->getGame()->setActiveCard(nullptr); owner->getGame()->setActiveCard(nullptr);
} }
owner = nullptr; owner = nullptr;
@ -403,8 +403,11 @@ void CardItem::playCard(bool faceDown)
emit tz->toggleTapped(); emit tz->toggleTapped();
} else { } else {
if (SettingsCache::instance().getClickPlaysAllSelected()) { if (SettingsCache::instance().getClickPlaysAllSelected()) {
faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown() if (faceDown) {
: state->getZone()->getPlayer()->getPlayerActions()->actPlay(); emit playSelectedFaceDown(this);
} else {
emit playSelected(this);
}
} else { } else {
state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown); state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown);
} }
@ -464,7 +467,7 @@ void CardItem::handleClickedToPlay(bool shiftHeld)
{ {
if (isUnwritableRevealZone(state->getZone())) { if (isUnwritableRevealZone(state->getZone())) {
if (SettingsCache::instance().getClickPlaysAllSelected()) { if (SettingsCache::instance().getClickPlaysAllSelected()) {
state->getZone()->getPlayer()->getPlayerActions()->actHide(); emit hideSelected(this);
} else { } else {
state->getZone()->removeCard(this); state->getZone()->removeCard(this);
} }
@ -475,17 +478,11 @@ void CardItem::handleClickedToPlay(bool shiftHeld)
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::RightButton) { if (event->button() == Qt::RightButton && owner != nullptr) {
emit rightClicked(this, event->screenPos());
if (owner != nullptr) { }
owner->getGame()->setActiveCard(this); if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
if (QMenu *cardMenu = owner->getPlayerMenu()->updateCardMenu(this)) { (!SettingsCache::instance().getDoubleClickToPlay())) {
cardMenu->popup(event->screenPos());
return;
}
}
} else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
(!SettingsCache::instance().getDoubleClickToPlay())) {
handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier)); handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier));
} }
@ -600,14 +597,14 @@ bool CardItem::animationEvent()
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value) QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
{ {
if ((change == ItemSelectedHasChanged) && owner != nullptr) { if ((change == ItemSelectedHasChanged) && owner != nullptr) {
if (value == true) { bool selected = value.toBool();
owner->getGame()->setActiveCard(this);
owner->getPlayerMenu()->updateCardMenu(this);
} else if (owner->getGameScene()->selectedItems().isEmpty()) {
owner->getGame()->setActiveCard(nullptr); if (selected) {
owner->getPlayerMenu()->updateCardMenu(nullptr); owner->getGame()->setActiveCard(this);
} }
emit selectionChanged(this, selected);
} }
return AbstractCardItem::itemChange(change, value); return AbstractCardItem::itemChange(change, value);
} }

View file

@ -4,9 +4,11 @@
#include "../game_graphics/zones/select_zone.h" #include "../game_graphics/zones/select_zone.h"
#include "../game_graphics/zones/view_zone.h" #include "../game_graphics/zones/view_zone.h"
#include "../game_graphics/zones/view_zone_widget.h" #include "../game_graphics/zones/view_zone_widget.h"
#include "abstract_game.h"
#include "board/card_item.h" #include "board/card_item.h"
#include "keyboard_card_navigator.h" #include "keyboard_card_navigator.h"
#include "phases_toolbar.h" #include "phases_toolbar.h"
#include "player/player_actions.h"
#include "player/player_graphics_item.h" #include "player/player_graphics_item.h"
#include "player/player_logic.h" #include "player/player_logic.h"
@ -76,6 +78,80 @@ QList<CardItem *> GameScene::selectedCards() const
return selectedCards; return selectedCards;
} }
void GameScene::onCardSelectionChanged(AbstractCardItem *abstractCard, bool selected)
{
CardItem *card = qobject_cast<CardItem *>(abstractCard);
if (!card || !card->getOwner()) {
return;
}
auto *owner = card->getOwner();
if (selected) {
owner->requestCardMenuUpdate(card);
return;
}
if (selectedItems().isEmpty()) {
owner->getGame()->setActiveCard(nullptr);
owner->requestCardMenuUpdate(nullptr);
}
}
void GameScene::onCardRightClicked(AbstractCardItem *abstractCard, QPoint screenPos)
{
auto *card = qobject_cast<CardItem *>(abstractCard);
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
auto *view = playerViews.value(card->getOwner()->getPlayerInfo()->getId());
if (!view) {
return;
}
card->getOwner()->getGame()->setActiveCard(card);
if (auto *menu = view->getPlayerMenu()->updateCardMenu(card)) {
menu->popup(screenPos);
}
}
void GameScene::playSelected(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actPlay(selectedCards());
}
void GameScene::playSelectedFaceDown(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actPlayFacedown(selectedCards());
}
void GameScene::hideSelected(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actHide(selectedCards());
}
/** /**
* @brief Adds a player to the scene and stores their graphics item. * @brief Adds a player to the scene and stores their graphics item.
* @param player Player to add. * @param player Player to add.
@ -86,9 +162,11 @@ void GameScene::addPlayer(PlayerLogic *player)
{ {
qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName(); qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName();
playerViews.insert(player->getPlayerInfo()->getId(), player->getGraphicsItem()); auto *view = new PlayerGraphicsItem(player);
addItem(player->getGraphicsItem());
connect(player->getGraphicsItem(), &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange); playerViews.insert(player->getPlayerInfo()->getId(), view);
addItem(view);
connect(view, &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange);
connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) {
if (conceded) { if (conceded) {
@ -97,6 +175,8 @@ void GameScene::addPlayer(PlayerLogic *player)
rearrange(); rearrange();
}); });
connect(player, &PlayerLogic::requestZoneViewToggle, this, &GameScene::toggleZoneView);
connect(player, &PlayerLogic::requestRevealedZoneView, this, &GameScene::addRevealedZoneView);
connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow); connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow);
connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow); connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow);
connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion); connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion);
@ -127,6 +207,7 @@ void GameScene::removePlayer(PlayerLogic *player)
} }
auto *view = playerViews.take(player->getPlayerInfo()->getId()); auto *view = playerViews.take(player->getPlayerInfo()->getId());
removeItem(view); removeItem(view);
view->deleteLater();
rearrange(); rearrange();
} }
@ -208,7 +289,7 @@ QList<PlayerLogic *> GameScene::collectActivePlayers(int &firstPlayerIndex) cons
bool firstPlayerFound = false; bool firstPlayerFound = false;
for (auto *pgItem : playerViews.values()) { for (auto *pgItem : playerViews.values()) {
PlayerLogic *p = pgItem->getPlayer(); PlayerLogic *p = pgItem->getLogic();
if (p && !p->getConceded()) { if (p && !p->getConceded()) {
activePlayers.append(p); activePlayers.append(p);
if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) { if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) {
@ -279,12 +360,12 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList<PlayerLogic *> &pl
for (int j = 0; j < rowsInColumn; ++j) { for (int j = 0; j < rowsInColumn; ++j) {
PlayerLogic *player = playersIter.next(); PlayerLogic *player = playersIter.next();
if (col == 0) { if (col == 0) {
playersByColumn[col].prepend(player->getGraphicsItem()); playersByColumn[col].prepend(playerViews.value(player->getPlayerInfo()->getId()));
} else { } else {
playersByColumn[col].append(player->getGraphicsItem()); playersByColumn[col].append(playerViews.value(player->getPlayerInfo()->getId()));
} }
auto *pgItem = player->getGraphicsItem(); auto *pgItem = playerViews.value(player->getPlayerInfo()->getId());
thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing; thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing;
columnWidth[col] = std::max(columnWidth[col], (int)pgItem->boundingRect().width()); columnWidth[col] = std::max(columnWidth[col], (int)pgItem->boundingRect().width());
} }
@ -379,7 +460,8 @@ void GameScene::addArrow(QSharedPointer<ArrowData> data)
return; return;
} }
auto *startZone = startView->getPlayer()->getZones().value(data->startZone); PlayerLogic *startLogic = startView->getLogic();
auto *startZone = startLogic->getZones().value(data->startZone);
if (!startZone) { if (!startZone) {
return; return;
} }
@ -393,7 +475,8 @@ void GameScene::addArrow(QSharedPointer<ArrowData> data)
if (data->isPlayerTargeted()) { if (data->isPlayerTargeted()) {
targetItem = targetView->getPlayerTarget(); targetItem = targetView->getPlayerTarget();
} else { } else {
if (auto *zone = targetView->getPlayer()->getZones().value(data->targetZone)) { auto *zone = targetView->getLogic()->getZones().value(data->targetZone);
if (zone) {
targetItem = zone->getCard(data->targetCardId); targetItem = zone->getCard(data->targetCardId);
} }
} }

View file

@ -99,6 +99,16 @@ public:
*/ */
void removePlayer(PlayerLogic *player); void removePlayer(PlayerLogic *player);
QMap<int, PlayerGraphicsItem *> getPlayers() const
{
return playerViews;
}
PlayerGraphicsItem *viewForPlayer(int playerId)
{
return playerViews.value(playerId);
}
/** /**
* @brief Adjusts the global rotation offset for player layout. * @brief Adjusts the global rotation offset for player layout.
* @param rotationAdjustment Number of positions to rotate. * @param rotationAdjustment Number of positions to rotate.
@ -190,6 +200,11 @@ public:
void stopRubberBand(); void stopRubberBand();
public slots: public slots:
void onCardSelectionChanged(AbstractCardItem *card, bool selected);
void onCardRightClicked(AbstractCardItem *card, QPoint screenPos);
void playSelected(AbstractCardItem *card);
void playSelectedFaceDown(AbstractCardItem *card);
void hideSelected(AbstractCardItem *card);
/** @brief Toggles a zone view for a player. */ /** @brief Toggles a zone view for a player. */
void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false); void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false);

View file

@ -31,93 +31,92 @@ static QIcon createCircleIcon(const QColor &color)
return QIcon(pixmap); return QIcon(pixmap);
} }
CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive) template <typename Slot>
static QAction *makeAction(QObject *parent, Slot &&slot, bool checkable = false, bool checked = false)
{
auto *a = new QAction(parent);
a->setCheckable(checkable);
if (checkable) {
a->setChecked(checked);
}
QObject::connect(a, &QAction::triggered, parent, std::forward<Slot>(slot));
return a;
}
CardMenu::CardMenu(PlayerGraphicsItem *_player, const CardItem *_card, bool _shortcutsActive)
: player(_player), card(_card), shortcutsActive(_shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive)
{ {
auto playerActions = player->getPlayerActions(); const QList<PlayerLogic *> &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
const QList<PlayerLogic *> &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto playerToAdd : players) { for (auto playerToAdd : players) {
if (playerToAdd == player) { if (playerToAdd == player->getLogic()) {
continue; continue;
} }
playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId())); playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId()));
} }
connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &CardMenu::removePlayer); connect(player->getLogic()->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this,
&CardMenu::removePlayer);
aTap = new QAction(this); auto *actions = player->getLogic()->getPlayerActions();
aTap->setData(cmTap); auto *gameScene = player->getGameScene();
connect(aTap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction);
aDoesntUntap = new QAction(this); // Single selection resolver used by all lambdas — called at trigger time
aDoesntUntap->setData(cmDoesntUntap); auto sel = [gameScene]() { return gameScene->selectedCards(); };
aDoesntUntap->setCheckable(true);
aDoesntUntap->setChecked(card != nullptr && card->getDoesntUntap()); // Unified dispatcher for card menu actions
connect(aDoesntUntap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); auto invoke = [actions, sel](CardMenuActionType type) {
return [actions, sel, type]() { actions->cardMenuAction(sel(), type); };
};
// Actions using invoke (type dispatch, need selection)
aTap = makeAction(this, invoke(cmTap));
aDoesntUntap = makeAction(this, invoke(cmDoesntUntap), /*checkable=*/true, card && card->getDoesntUntap());
aFlip = makeAction(this, invoke(cmFlip));
aPeek = makeAction(this, invoke(cmPeek));
aClone = makeAction(this, invoke(cmClone));
// Actions using selection directly
aUnattach = makeAction(this, [actions, sel]() { actions->actUnattach(sel()); });
aSetAnnotation = makeAction(this, [actions, sel]() { actions->actSetAnnotation(sel()); });
aPlay = makeAction(this, [actions, sel]() { actions->actPlay(sel()); });
aPlayFacedown = makeAction(this, [actions, sel]() { actions->actPlayFacedown(sel()); });
aHide = makeAction(this, [actions, sel]() { actions->actHide(sel()); });
aReduceLifeByPower = makeAction(this, [actions, sel]() { actions->actReduceLifeByPower(sel()); });
// Actions that use activeCard, not selection — direct connection
aAttach = new QAction(this); aAttach = new QAction(this);
connect(aAttach, &QAction::triggered, playerActions, &PlayerActions::actAttach);
aUnattach = new QAction(this);
connect(aUnattach, &QAction::triggered, playerActions, &PlayerActions::actUnattach);
aDrawArrow = new QAction(this); aDrawArrow = new QAction(this);
connect(aDrawArrow, &QAction::triggered, playerActions, &PlayerActions::actDrawArrow);
aSetAnnotation = new QAction(this);
connect(aSetAnnotation, &QAction::triggered, playerActions, &PlayerActions::actSetAnnotation);
aFlip = new QAction(this);
aFlip->setData(cmFlip);
connect(aFlip, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aPeek = new QAction(this);
aPeek->setData(cmPeek);
connect(aPeek, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aClone = new QAction(this);
aClone->setData(cmClone);
connect(aClone, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aSelectAll = new QAction(this); aSelectAll = new QAction(this);
connect(aSelectAll, &QAction::triggered, playerActions, &PlayerActions::actSelectAll);
aSelectRow = new QAction(this); aSelectRow = new QAction(this);
connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow);
aSelectColumn = new QAction(this); aSelectColumn = new QAction(this);
connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn);
aReduceLifeByPower = new QAction(this); connect(aAttach, &QAction::triggered, actions, &PlayerActions::actAttach);
connect(aReduceLifeByPower, &QAction::triggered, playerActions, &PlayerActions::actReduceLifeByPower); connect(aDrawArrow, &QAction::triggered, actions, &PlayerActions::actDrawArrow);
connect(aSelectAll, &QAction::triggered, actions, &PlayerActions::actSelectAll);
aPlay = new QAction(this); connect(aSelectRow, &QAction::triggered, actions, &PlayerActions::actSelectRow);
connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); connect(aSelectColumn, &QAction::triggered, actions, &PlayerActions::actSelectColumn);
aHide = new QAction(this);
connect(aHide, &QAction::triggered, playerActions, &PlayerActions::actHide);
aPlayFacedown = new QAction(this);
connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown);
aRevealToAll = new QAction(this); aRevealToAll = new QAction(this);
mCardCounters = new QMenu; mCardCounters = new QMenu;
// Card counters
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i) {
QColor color = SettingsCache::instance().cardCounters().color(i); QColor color = SettingsCache::instance().cardCounters().color(i);
QIcon circleIcon = createCircleIcon(color); QIcon circleIcon = createCircleIcon(color);
auto *tempAddCounter = new QAction(this); auto *addAction = makeAction(this, [actions, sel, i]() { actions->actAddCardCounter(sel(), i); });
tempAddCounter->setIconVisibleInMenu(true); addAction->setIcon(circleIcon);
tempAddCounter->setIcon(circleIcon); aAddCounter.append(addAction);
auto *tempRemoveCounter = new QAction(this); auto *removeAction = makeAction(this, [actions, sel, i]() { actions->actRemoveCardCounter(sel(), i); });
tempRemoveCounter->setIconVisibleInMenu(true); removeAction->setIcon(circleIcon);
tempRemoveCounter->setIcon(circleIcon); aRemoveCounter.append(removeAction);
auto *tempSetCounter = new QAction(this); auto *setAction = makeAction(this, [actions, sel, i]() { actions->actSetCardCounter(sel(), i); });
tempSetCounter->setIconVisibleInMenu(true); setAction->setIcon(circleIcon);
tempSetCounter->setIcon(circleIcon); aSetCounter.append(setAction);
aAddCounter.append(tempAddCounter);
aRemoveCounter.append(tempRemoveCounter);
aSetCounter.append(tempSetCounter);
connect(tempAddCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actAddCardCounter(i); });
connect(tempRemoveCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actRemoveCardCounter(i); });
connect(tempSetCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actSetCardCounter(i); });
} }
setShortcutsActive(); setShortcutsActive();
@ -129,7 +128,7 @@ CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsA
} }
bool revealedCard = false; bool revealedCard = false;
bool writeableCard = player->getPlayerInfo()->getLocalOrJudge(); bool writeableCard = player->getLogic()->getPlayerInfo()->getLocalOrJudge();
if (auto *view = qobject_cast<ZoneViewZoneLogic *>(card->getZone())) { if (auto *view = qobject_cast<ZoneViewZoneLogic *>(card->getZone())) {
if (view->getRevealZone()) { if (view->getRevealZone()) {
if (view->getWriteableRevealZone()) { if (view->getWriteableRevealZone()) {
@ -313,7 +312,9 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard)
initContextualPlayersMenu(revealMenu, aRevealToAll); initContextualPlayersMenu(revealMenu, aRevealToAll);
connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); connect(revealMenu, &QMenu::triggered, this, [this](QAction *action) {
player->getLogic()->getPlayerActions()->actReveal(player->getGameScene()->selectedCards(), action);
});
addSeparator(); addSeparator();
addAction(aClone); addAction(aClone);
@ -398,8 +399,7 @@ void CardMenu::addRelatedCardView()
QAction *viewCard = viewRelatedCards->addAction(relatedCardName); QAction *viewCard = viewRelatedCards->addAction(relatedCardName);
Q_UNUSED(viewCard); Q_UNUSED(viewCard);
connect(viewCard, &QAction::triggered, player->getGame(), connect(viewCard, &QAction::triggered, this, [this, cardRef] { emit cardInfoRequested(cardRef); });
[this, cardRef] { player->getGame()->getTab()->viewCardInfo(cardRef); });
} }
} }
@ -461,7 +461,8 @@ void CardMenu::addRelatedCardActions()
auto *createRelated = new QAction(text, this); auto *createRelated = new QAction(text, this);
createRelated->setData(QVariant(index++)); createRelated->setData(QVariant(index++));
connect(createRelated, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateRelatedCard); connect(createRelated, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreateRelatedCard);
addAction(createRelated); addAction(createRelated);
} }
@ -470,7 +471,7 @@ void CardMenu::addRelatedCardActions()
createRelatedCards->setShortcuts( createRelatedCards->setShortcuts(
SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens")); SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens"));
} }
connect(createRelatedCards, &QAction::triggered, player->getPlayerActions(), connect(createRelatedCards, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreateAllRelatedCards); &PlayerActions::actCreateAllRelatedCards);
addAction(createRelatedCards); addAction(createRelatedCards);
} }

View file

@ -8,15 +8,20 @@
#define COCKATRICE_CARD_MENU_H #define COCKATRICE_CARD_MENU_H
#include <QMenu> #include <QMenu>
#include <libcockatrice/utility/card_ref.h>
class CardItem; class CardItem;
class PlayerGraphicsItem;
class PlayerLogic; class PlayerLogic;
class CardMenu : public QMenu class CardMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
signals:
void cardInfoRequested(const CardRef &cardRef);
public: public:
explicit CardMenu(PlayerLogic *player, const CardItem *card, bool shortcutsActive); explicit CardMenu(PlayerGraphicsItem *player, const CardItem *card, bool shortcutsActive);
void removePlayer(PlayerLogic *playerToRemove); void removePlayer(PlayerLogic *playerToRemove);
void createTableMenu(bool canModifyCard); void createTableMenu(bool canModifyCard);
void createStackMenu(bool canModifyCard); void createStackMenu(bool canModifyCard);
@ -41,7 +46,7 @@ public:
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter; QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
const CardItem *card; const CardItem *card;
QList<QPair<QString, int>> playersInfo; QList<QPair<QString, int>> playersInfo;
bool shortcutsActive; bool shortcutsActive;

View file

@ -2,12 +2,12 @@
#include "../player_logic.h" #include "../player_logic.h"
CustomZoneMenu::CustomZoneMenu(PlayerLogic *_player) : player(_player) CustomZoneMenu::CustomZoneMenu(PlayerGraphicsItem *_player) : player(_player)
{ {
menuAction()->setVisible(false); menuAction()->setVisible(false);
connect(player, &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); connect(player->getLogic(), &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu);
connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, connect(player->getLogic(), &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this,
&CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu); &CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu);
retranslateUi(); retranslateUi();
@ -17,7 +17,7 @@ void CustomZoneMenu::retranslateUi()
{ {
setTitle(tr("C&ustom Zones")); setTitle(tr("C&ustom Zones"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
for (auto aViewZone : actions()) { for (auto aViewZone : actions()) {
aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString())); aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString()));
@ -37,5 +37,5 @@ void CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu(QString zoneName)
QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName)); QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName));
aViewZone->setData(zoneName); aViewZone->setData(zoneName);
connect(aViewZone, &QAction::triggered, this, connect(aViewZone, &QAction::triggered, this,
[zoneName, this]() { player->getGameScene()->toggleZoneView(player, zoneName, -1); }); [zoneName, this]() { player->getGameScene()->toggleZoneView(player->getLogic(), zoneName, -1); });
} }

View file

@ -11,12 +11,12 @@
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class CustomZoneMenu : public QMenu, public AbstractPlayerComponent class CustomZoneMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CustomZoneMenu(PlayerLogic *player); explicit CustomZoneMenu(PlayerGraphicsItem *player);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override void setShortcutsActive() override
{ {
@ -26,7 +26,7 @@ public:
} }
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
private slots: private slots:
void clearCustomZonesMenu(); void clearCustomZonesMenu();
void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName);

View file

@ -4,7 +4,7 @@
#include "../player_actions.h" #include "../player_actions.h"
#include "../player_logic.h" #include "../player_logic.h"
MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to")) MoveMenu::MoveMenu(PlayerGraphicsItem *player) : QMenu(tr("Move to"))
{ {
aMoveToTopLibrary = new QAction(this); aMoveToTopLibrary = new QAction(this);
aMoveToTopLibrary->setData(cmMoveToTopLibrary); aMoveToTopLibrary->setData(cmMoveToTopLibrary);
@ -20,14 +20,23 @@ MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to"))
aMoveToExile = new QAction(this); aMoveToExile = new QAction(this);
aMoveToExile->setData(cmMoveToExile); aMoveToExile->setData(cmMoveToExile);
connect(aMoveToTopLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); auto *actions = player->getLogic()->getPlayerActions();
connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(), auto invoke = [player](CardMenuActionType type) {
&PlayerActions::actMoveCardXCardsFromTop); return [type, player]() {
connect(aMoveToTable, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); player->getLogic()->getPlayerActions()->cardMenuAction(player->getGameScene()->selectedCards(), type);
connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); };
connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); };
connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
connect(aMoveToTopLibrary, &QAction::triggered, actions, invoke(cmMoveToTopLibrary));
connect(aMoveToBottomLibrary, &QAction::triggered, actions, invoke(cmMoveToBottomLibrary));
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, actions, [player]() {
player->getLogic()->getPlayerActions()->actMoveCardXCardsFromTop(player->getGameScene()->selectedCards());
});
connect(aMoveToTable, &QAction::triggered, actions, invoke(cmMoveToTable));
connect(aMoveToHand, &QAction::triggered, actions, invoke(cmMoveToHand));
connect(aMoveToGraveyard, &QAction::triggered, actions, invoke(cmMoveToGraveyard));
connect(aMoveToExile, &QAction::triggered, actions, invoke(cmMoveToExile));
addAction(aMoveToTopLibrary); addAction(aMoveToTopLibrary);
addAction(aMoveToXfromTopOfLibrary); addAction(aMoveToXfromTopOfLibrary);

View file

@ -8,13 +8,13 @@
#define COCKATRICE_MOVE_MENU_H #define COCKATRICE_MOVE_MENU_H
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class MoveMenu : public QMenu class MoveMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MoveMenu(PlayerLogic *player); explicit MoveMenu(PlayerGraphicsItem *player);
void setShortcutsActive(); void setShortcutsActive();
void retranslateUi(); void retranslateUi();

View file

@ -10,23 +10,26 @@
#include <libcockatrice/protocol/pb/command_reveal_cards.pb.h> #include <libcockatrice/protocol/pb/command_reveal_cards.pb.h>
PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player) PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_player)
{ {
connect(player->getLogic(), &PlayerLogic::requestCardMenuUpdate, this, &PlayerMenu::updateCardMenu);
connect(this, &PlayerMenu::cardInfoRequested, player, &PlayerGraphicsItem::cardInfoRequested);
playerMenu = new TearOffMenu(); playerMenu = new TearOffMenu();
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
handMenu = addManagedMenu<HandMenu>(player, player->getPlayerActions(), playerMenu); handMenu = addManagedMenu<HandMenu>(player->getLogic(), player->getLogic()->getPlayerActions(), playerMenu);
libraryMenu = addManagedMenu<LibraryMenu>(player, playerMenu); libraryMenu = addManagedMenu<LibraryMenu>(player->getLogic(), playerMenu);
} else { } else {
handMenu = nullptr; handMenu = nullptr;
libraryMenu = nullptr; libraryMenu = nullptr;
} }
graveMenu = addManagedMenu<GraveyardMenu>(player, playerMenu); graveMenu = addManagedMenu<GraveyardMenu>(player->getLogic(), playerMenu);
rfgMenu = addManagedMenu<RfgMenu>(player, playerMenu); rfgMenu = addManagedMenu<RfgMenu>(player->getLogic(), playerMenu);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
sideboardMenu = addManagedMenu<SideboardMenu>(player, playerMenu); sideboardMenu = addManagedMenu<SideboardMenu>(player->getLogic(), playerMenu);
customZonesMenu = addManagedMenu<CustomZoneMenu>(player); customZonesMenu = addManagedMenu<CustomZoneMenu>(player);
playerMenu->addSeparator(); playerMenu->addSeparator();
@ -40,8 +43,8 @@ PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
utilityMenu = nullptr; utilityMenu = nullptr;
} }
if (player->getPlayerInfo()->getLocal()) { if (player->getLogic()->getPlayerInfo()->getLocal()) {
sayMenu = addManagedMenu<SayMenu>(player); sayMenu = addManagedMenu<SayMenu>(player->getLogic());
} else { } else {
sayMenu = nullptr; sayMenu = nullptr;
} }
@ -55,13 +58,13 @@ PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
void PlayerMenu::setMenusForGraphicItems() void PlayerMenu::setMenusForGraphicItems()
{ {
player->getGraphicsItem()->getTableZoneGraphicsItem()->setMenu(playerMenu); player->getTableZoneGraphicsItem()->setMenu(playerMenu);
player->getGraphicsItem()->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard); player->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard);
player->getGraphicsItem()->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg); player->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
player->getGraphicsItem()->getHandZoneGraphicsItem()->setMenu(handMenu); player->getHandZoneGraphicsItem()->setMenu(handMenu);
player->getGraphicsItem()->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard); player->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard);
player->getGraphicsItem()->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu); player->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu);
} }
} }
@ -74,12 +77,14 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card)
// If is spectator (as spectators don't need card menus), return // If is spectator (as spectators don't need card menus), return
// only update the menu if the card is actually selected // only update the menu if the card is actually selected
if ((player->getGame()->getPlayerManager()->isSpectator() && !player->getGame()->getPlayerManager()->isJudge()) || if ((player->getLogic()->getGame()->getPlayerManager()->isSpectator() &&
player->getGame()->getActiveCard() != card) { !player->getLogic()->getGame()->getPlayerManager()->isJudge()) ||
player->getLogic()->getGame()->getActiveCard() != card) {
return nullptr; return nullptr;
} }
QMenu *menu = new CardMenu(player, card, shortcutsActive); CardMenu *menu = new CardMenu(player, card, shortcutsActive);
connect(menu, &CardMenu::cardInfoRequested, this, &PlayerMenu::cardInfoRequested);
emit cardMenuUpdated(menu); emit cardMenuUpdated(menu);
return menu; return menu;
@ -87,7 +92,7 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card)
void PlayerMenu::retranslateUi() void PlayerMenu::retranslateUi()
{ {
playerMenu->setTitle(tr("Player \"%1\"").arg(player->getPlayerInfo()->getName())); playerMenu->setTitle(tr("Player \"%1\"").arg(player->getLogic()->getPlayerInfo()->getName()));
for (auto *component : managedComponents) { for (auto *component : managedComponents) {
component->retranslateUi(); component->retranslateUi();
@ -104,7 +109,8 @@ void PlayerMenu::refreshShortcuts()
{ {
if (shortcutsActive) { if (shortcutsActive) {
// Judges get access to every player's menus but only want shortcuts to be set for their own. // Judges get access to every player's menus but only want shortcuts to be set for their own.
if (player->getPlayerInfo()->getLocalOrJudge() && !player->getPlayerInfo()->getLocal()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge() &&
!player->getLogic()->getPlayerInfo()->getLocal()) {
setShortcutsInactive(); setShortcutsInactive();
} else { } else {
setShortcutsActive(); setShortcutsActive();

View file

@ -8,7 +8,6 @@
#define COCKATRICE_PLAYER_MENU_H #define COCKATRICE_PLAYER_MENU_H
#include "../../../interface/widgets/menus/tearoff_menu.h" #include "../../../interface/widgets/menus/tearoff_menu.h"
#include "../player_logic.h"
#include "custom_zone_menu.h" #include "custom_zone_menu.h"
#include "grave_menu.h" #include "grave_menu.h"
#include "hand_menu.h" #include "hand_menu.h"
@ -23,29 +22,31 @@
#include <QObject> #include <QObject>
class CardItem; class CardItem;
class CardMenu;
class PlayerGraphicsItem;
class PlayerMenu : public QObject class PlayerMenu : public QObject
{ {
Q_OBJECT Q_OBJECT
signals: signals:
void cardMenuUpdated(QMenu *cardMenu); void cardMenuUpdated(CardMenu *cardMenu);
void cardInfoRequested(const CardRef &cardRef);
void shortcutsActivated(); void shortcutsActivated();
void shortcutsDeactivated(); void shortcutsDeactivated();
void retranslateRequested(); void retranslateRequested();
public slots: public slots:
void setMenusForGraphicItems(); void setMenusForGraphicItems();
QMenu *updateCardMenu(const CardItem *card);
private slots: private slots:
void refreshShortcuts(); void refreshShortcuts();
public: public:
explicit PlayerMenu(PlayerLogic *player); explicit PlayerMenu(PlayerGraphicsItem *player);
/** @brief Retranslate all user-visible strings. Called on language change. */ /** @brief Retranslate all user-visible strings. Called on language change. */
void retranslateUi(); void retranslateUi();
QMenu *updateCardMenu(const CardItem *card);
[[nodiscard]] QMenu *getPlayerMenu() const [[nodiscard]] QMenu *getPlayerMenu() const
{ {
return playerMenu; return playerMenu;
@ -77,7 +78,7 @@ public:
void setShortcutsInactive(); void setShortcutsInactive();
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
TearOffMenu *playerMenu; TearOffMenu *playerMenu;
QMenu *countersMenu; QMenu *countersMenu;
HandMenu *handMenu; HandMenu *handMenu;

View file

@ -3,30 +3,40 @@
#include "../player_actions.h" #include "../player_actions.h"
#include "../player_logic.h" #include "../player_logic.h"
PtMenu::PtMenu(PlayerLogic *player) : QMenu(tr("Power / toughness")) PtMenu::PtMenu(PlayerGraphicsItem *player) : QMenu(tr("Power / toughness"))
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
aIncP = new QAction(this); aIncP = new QAction(this);
connect(aIncP, &QAction::triggered, playerActions, &PlayerActions::actIncP); connect(aIncP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncP(player->getGameScene()->selectedCards()); });
aDecP = new QAction(this); aDecP = new QAction(this);
connect(aDecP, &QAction::triggered, playerActions, &PlayerActions::actDecP); connect(aDecP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecP(player->getGameScene()->selectedCards()); });
aIncT = new QAction(this); aIncT = new QAction(this);
connect(aIncT, &QAction::triggered, playerActions, &PlayerActions::actIncT); connect(aIncT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncT(player->getGameScene()->selectedCards()); });
aDecT = new QAction(this); aDecT = new QAction(this);
connect(aDecT, &QAction::triggered, playerActions, &PlayerActions::actDecT); connect(aDecT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecT(player->getGameScene()->selectedCards()); });
aIncPT = new QAction(this); aIncPT = new QAction(this);
connect(aIncPT, &QAction::triggered, playerActions, [playerActions] { playerActions->actIncPT(); }); connect(aIncPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncPT(player->getGameScene()->selectedCards()); });
aDecPT = new QAction(this); aDecPT = new QAction(this);
connect(aDecPT, &QAction::triggered, playerActions, &PlayerActions::actDecPT); connect(aDecPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecPT(player->getGameScene()->selectedCards()); });
aFlowP = new QAction(this); aFlowP = new QAction(this);
connect(aFlowP, &QAction::triggered, playerActions, &PlayerActions::actFlowP); connect(aFlowP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actFlowP(player->getGameScene()->selectedCards()); });
aFlowT = new QAction(this); aFlowT = new QAction(this);
connect(aFlowT, &QAction::triggered, playerActions, &PlayerActions::actFlowT); connect(aFlowT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actFlowT(player->getGameScene()->selectedCards()); });
aSetPT = new QAction(this); aSetPT = new QAction(this);
connect(aSetPT, &QAction::triggered, playerActions, &PlayerActions::actSetPT); connect(aSetPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actSetPT(player->getGameScene()->selectedCards()); });
aResetPT = new QAction(this); aResetPT = new QAction(this);
connect(aResetPT, &QAction::triggered, playerActions, &PlayerActions::actResetPT); connect(aResetPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actResetPT(player->getGameScene()->selectedCards()); });
addAction(aIncP); addAction(aIncP);
addAction(aDecP); addAction(aDecP);

View file

@ -8,14 +8,14 @@
#define COCKATRICE_PT_MENU_H #define COCKATRICE_PT_MENU_H
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class PtMenu : public QMenu class PtMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PtMenu(PlayerLogic *player); explicit PtMenu(PlayerGraphicsItem *player);
void retranslateUi(); void retranslateUi();
void setShortcutsActive(); void setShortcutsActive();

View file

@ -8,11 +8,14 @@
#include <libcockatrice/deck_list/tree/deck_list_card_node.h> #include <libcockatrice/deck_list/tree/deck_list_card_node.h>
#include <libcockatrice/deck_list/tree/inner_deck_list_node.h> #include <libcockatrice/deck_list/tree/inner_deck_list_node.h>
UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) UtilityMenu::UtilityMenu(PlayerGraphicsItem *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player)
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
connect(playerActions, &PlayerActions::requestEnableAndSetCreateAnotherTokenAction, this,
&UtilityMenu::setAndEnableCreateAnotherTokenAction);
connect(playerActions, &PlayerActions::requestSetLastToken, this, &UtilityMenu::setLastToken);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aUntapAll = new QAction(this); aUntapAll = new QAction(this);
connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll); connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll);
@ -23,19 +26,22 @@ UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(player
connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin); connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin);
aCreateToken = new QAction(this); aCreateToken = new QAction(this);
connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken); connect(aCreateToken, &QAction::triggered, playerActions,
[this]() { player->getLogic()->getPlayerActions()->actCreateToken(getPredefinedTokens()); });
aCreateAnotherToken = new QAction(this); aCreateAnotherToken = new QAction(this);
connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken); connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken);
aCreateAnotherToken->setEnabled(false); aCreateAnotherToken->setEnabled(false);
aIncrementAllCardCounters = new QAction(this); aIncrementAllCardCounters = new QAction(this);
connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, [this]() {
&PlayerActions::actIncrementAllCardCounters); player->getLogic()->getPlayerActions()->actIncrementAllCardCounters(
player->getGameScene()->selectedCards());
});
createPredefinedTokenMenu = new QMenu(QString()); createPredefinedTokenMenu = new QMenu(QString());
createPredefinedTokenMenu->setEnabled(false); createPredefinedTokenMenu->setEnabled(false);
connect(player, &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); connect(player->getLogic(), &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu);
playerMenu->addAction(aIncrementAllCardCounters); playerMenu->addAction(aIncrementAllCardCounters);
playerMenu->addSeparator(); playerMenu->addSeparator();
@ -66,7 +72,7 @@ void UtilityMenu::populatePredefinedTokensMenu()
clear(); clear();
setEnabled(false); setEnabled(false);
predefinedTokens.clear(); predefinedTokens.clear();
const DeckList &deckList = player->getDeck(); const DeckList &deckList = player->getLogic()->getDeck();
if (deckList.isEmpty()) { if (deckList.isEmpty()) {
return; return;
@ -84,14 +90,24 @@ void UtilityMenu::populatePredefinedTokensMenu()
if (i < 10) { if (i < 10) {
a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10))); a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10)));
} }
connect(a, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreatePredefinedToken); connect(a, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreatePredefinedToken);
} }
} }
} }
void UtilityMenu::setLastToken(CardInfoPtr lastToken)
{
if (!createAnotherTokenActionExists()) {
return;
}
player->getLogic()->getPlayerActions()->setLastTokenInfo(lastToken);
}
void UtilityMenu::retranslateUi() void UtilityMenu::retranslateUi()
{ {
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aIncrementAllCardCounters->setText(tr("Increment all card counters")); aIncrementAllCardCounters->setText(tr("Increment all card counters"));
aUntapAll->setText(tr("&Untap all permanents")); aUntapAll->setText(tr("&Untap all permanents"));
aRollDie->setText(tr("R&oll die...")); aRollDie->setText(tr("R&oll die..."));
@ -106,7 +122,7 @@ void UtilityMenu::setShortcutsActive()
{ {
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters")); aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters"));
aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll")); aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll"));
aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie")); aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie"));
@ -118,7 +134,7 @@ void UtilityMenu::setShortcutsActive()
void UtilityMenu::setShortcutsInactive() void UtilityMenu::setShortcutsInactive()
{ {
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aUntapAll->setShortcut(QKeySequence()); aUntapAll->setShortcut(QKeySequence());
aRollDie->setShortcut(QKeySequence()); aRollDie->setShortcut(QKeySequence());
aFlipCoin->setShortcut(QKeySequence()); aFlipCoin->setShortcut(QKeySequence());

View file

@ -10,19 +10,21 @@
#include "abstract_player_component.h" #include "abstract_player_component.h"
#include <QMenu> #include <QMenu>
#include <libcockatrice/card/card_info.h>
class PlayerLogic; class PlayerGraphicsItem;
class UtilityMenu : public QMenu, public AbstractPlayerComponent class UtilityMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public slots: public slots:
void populatePredefinedTokensMenu(); void populatePredefinedTokensMenu();
void setLastToken(CardInfoPtr lastToken);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override; void setShortcutsActive() override;
void setShortcutsInactive() override; void setShortcutsInactive() override;
public: public:
explicit UtilityMenu(PlayerLogic *player, QMenu *playerMenu); explicit UtilityMenu(PlayerGraphicsItem *player, QMenu *playerMenu);
[[nodiscard]] bool createAnotherTokenActionExists() const [[nodiscard]] bool createAnotherTokenActionExists() const
{ {
@ -31,7 +33,7 @@ public:
void setAndEnableCreateAnotherTokenAction(QString text) void setAndEnableCreateAnotherTokenAction(QString text)
{ {
aCreateAnotherToken->setText(text); aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(text));
aCreateAnotherToken->setEnabled(true); aCreateAnotherToken->setEnabled(true);
} }
@ -41,7 +43,7 @@ public:
} }
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
QStringList predefinedTokens; QStringList predefinedTokens;
QMenu *createPredefinedTokenMenu; QMenu *createPredefinedTokenMenu;

View file

@ -39,6 +39,8 @@ static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
PlayerActions::PlayerActions(PlayerLogic *_player) PlayerActions::PlayerActions(PlayerLogic *_player)
: QObject(_player), player(_player), lastTokenTableRow(0), movingCardsUntil(false) : QObject(_player), player(_player), lastTokenTableRow(0), movingCardsUntil(false)
{ {
connect(this, &PlayerActions::requestZoneViewToggle, player, &PlayerLogic::onRequestZoneViewToggle);
moveTopCardTimer = new QTimer(this); moveTopCardTimer = new QTimer(this);
moveTopCardTimer->setInterval(MOVE_TOP_CARD_UNTIL_INTERVAL); moveTopCardTimer->setInterval(MOVE_TOP_CARD_UNTIL_INTERVAL);
moveTopCardTimer->setSingleShot(true); moveTopCardTimer->setSingleShot(true);
@ -133,12 +135,12 @@ void PlayerActions::playCardToTable(const CardItem *card, bool faceDown)
void PlayerActions::actViewLibrary() void PlayerActions::actViewLibrary()
{ {
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, -1); emit requestZoneViewToggle(ZoneNames::DECK, -1);
} }
void PlayerActions::actViewHand() void PlayerActions::actViewHand()
{ {
player->getGameScene()->toggleZoneView(player, ZoneNames::HAND, -1); emit requestZoneViewToggle(ZoneNames::HAND, -1);
} }
/** /**
@ -170,7 +172,7 @@ void PlayerActions::actSortHand()
static QList defaultOptions = {CardList::SortByName, CardList::SortByPrinting}; static QList defaultOptions = {CardList::SortByName, CardList::SortByPrinting};
player->getGraphicsItem()->getHandZoneGraphicsItem()->sortHand(sortOptions + defaultOptions); emit requestSortHand(sortOptions + defaultOptions);
} }
void PlayerActions::actViewTopCards() void PlayerActions::actViewTopCards()
@ -182,7 +184,7 @@ void PlayerActions::actViewTopCards()
deckSize, 1, &ok); deckSize, 1, &ok);
if (ok) { if (ok) {
defaultNumberTopCards = number; defaultNumberTopCards = number;
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number); emit requestZoneViewToggle(ZoneNames::DECK, number);
} }
} }
@ -195,24 +197,24 @@ void PlayerActions::actViewBottomCards()
deckSize, 1, &ok); deckSize, 1, &ok);
if (ok) { if (ok) {
defaultNumberBottomCards = number; defaultNumberBottomCards = number;
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number, true); emit requestZoneViewToggle(ZoneNames::DECK, number, true);
} }
} }
void PlayerActions::actAlwaysRevealTopCard() void PlayerActions::actAlwaysRevealTopCard(bool alwaysRevealTopCard)
{ {
Command_ChangeZoneProperties cmd; Command_ChangeZoneProperties cmd;
cmd.set_zone_name(ZoneNames::DECK); cmd.set_zone_name(ZoneNames::DECK);
cmd.set_always_reveal_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysRevealTopCardChecked()); cmd.set_always_reveal_top_card(alwaysRevealTopCard);
sendGameCommand(cmd); sendGameCommand(cmd);
} }
void PlayerActions::actAlwaysLookAtTopCard() void PlayerActions::actAlwaysLookAtTopCard(bool alwaysRevealTopCard)
{ {
Command_ChangeZoneProperties cmd; Command_ChangeZoneProperties cmd;
cmd.set_zone_name(ZoneNames::DECK); cmd.set_zone_name(ZoneNames::DECK);
cmd.set_always_look_at_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysLookAtTopCardChecked()); cmd.set_always_look_at_top_card(alwaysRevealTopCard);
sendGameCommand(cmd); sendGameCommand(cmd);
} }
@ -224,17 +226,17 @@ void PlayerActions::actOpenDeckInDeckEditor()
void PlayerActions::actViewGraveyard() void PlayerActions::actViewGraveyard()
{ {
player->getGameScene()->toggleZoneView(player, ZoneNames::GRAVE, -1); emit requestZoneViewToggle(ZoneNames::GRAVE, -1);
} }
void PlayerActions::actViewRfg() void PlayerActions::actViewRfg()
{ {
player->getGameScene()->toggleZoneView(player, ZoneNames::EXILE, -1); emit requestZoneViewToggle(ZoneNames::EXILE, -1);
} }
void PlayerActions::actViewSideboard() void PlayerActions::actViewSideboard()
{ {
player->getGameScene()->toggleZoneView(player, ZoneNames::SIDEBOARD, -1); emit requestZoneViewToggle(ZoneNames::SIDEBOARD, -1);
} }
void PlayerActions::actShuffle() void PlayerActions::actShuffle()
@ -862,9 +864,9 @@ void PlayerActions::actFlipCoin()
sendGameCommand(cmd); sendGameCommand(cmd);
} }
void PlayerActions::actCreateToken() void PlayerActions::actCreateToken(const QStringList &predefinedTokens)
{ {
DlgCreateToken dlg(player->getPlayerMenu()->getUtilityMenu()->getPredefinedTokens(), player->getGame()->getTab()); DlgCreateToken dlg(predefinedTokens, player->getGame()->getTab());
if (!dlg.exec()) { if (!dlg.exec()) {
return; return;
} }
@ -880,8 +882,7 @@ void PlayerActions::actCreateToken()
} }
} }
player->getPlayerMenu()->getUtilityMenu()->setAndEnableCreateAnotherTokenAction( emit requestEnableAndSetCreateAnotherTokenAction(lastTokenInfo.name);
tr("C&reate another %1 token").arg(lastTokenInfo.name));
actCreateAnotherToken(); actCreateAnotherToken();
} }
@ -912,8 +913,12 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo)
return; return;
} }
UtilityMenu *utilityMenu = player->getPlayerMenu()->getUtilityMenu(); emit requestSetLastToken(cardInfo);
if (utilityMenu == nullptr || !utilityMenu->createAnotherTokenActionExists()) { }
void PlayerActions::setLastTokenInfo(CardInfoPtr cardInfo)
{
if (cardInfo == nullptr) {
return; return;
} }
@ -927,7 +932,7 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo)
lastTokenTableRow = TableZone::tableRowToGridY(cardInfo->getUiAttributes().tableRow); lastTokenTableRow = TableZone::tableRowToGridY(cardInfo->getUiAttributes().tableRow);
utilityMenu->setAndEnableCreateAnotherTokenAction(tr("C&reate another %1 token").arg(lastTokenInfo.name)); emit requestEnableAndSetCreateAnotherTokenAction(lastTokenInfo.name);
} }
void PlayerActions::actCreatePredefinedToken() void PlayerActions::actCreatePredefinedToken()
@ -1166,7 +1171,7 @@ void PlayerActions::actSayMessage()
sendGameCommand(cmd); sendGameCommand(cmd);
} }
void PlayerActions::actMoveCardXCardsFromTop() void PlayerActions::actMoveCardXCardsFromTop(QList<CardItem *> selectedCards)
{ {
int deckSize = player->getDeckZone()->getCards().size() + 1; // add the card to move to the deck int deckSize = player->getDeckZone()->getCards().size() + 1; // add the card to move to the deck
bool ok; bool ok;
@ -1182,7 +1187,7 @@ void PlayerActions::actMoveCardXCardsFromTop()
defaultNumberTopCardsToPlaceBelow = number; defaultNumberTopCardsToPlaceBelow = number;
QList<CardItem *> cardList = player->getGameScene()->selectedCards(); QList<CardItem *> cardList = selectedCards;
if (cardList.isEmpty()) { if (cardList.isEmpty()) {
return; return;
} }
@ -1213,12 +1218,12 @@ void PlayerActions::actMoveCardXCardsFromTop()
} }
} }
void PlayerActions::actIncPT(int deltaP, int deltaT) void PlayerActions::actIncPT(QList<CardItem *> selectedCards, int deltaP, int deltaT)
{ {
int playerid = player->getPlayerInfo()->getId(); int playerid = player->getPlayerInfo()->getId();
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : player->getGameScene()->selectedCards()) { for (auto card : selectedCards) {
QString pt = card->getPT(); QString pt = card->getPT();
const auto ptList = CardItem::parsePT(pt); const auto ptList = CardItem::parsePT(pt);
QString newpt; QString newpt;
@ -1246,11 +1251,11 @@ void PlayerActions::actIncPT(int deltaP, int deltaT)
player->getGame()->getGameEventHandler()->sendGameCommand(prepareGameCommand(commandList), playerid); player->getGame()->getGameEventHandler()->sendGameCommand(prepareGameCommand(commandList), playerid);
} }
void PlayerActions::actResetPT() void PlayerActions::actResetPT(QList<CardItem *> selectedCards)
{ {
int playerid = player->getPlayerInfo()->getId(); int playerid = player->getPlayerInfo()->getId();
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : player->getGameScene()->selectedCards()) { for (auto card : selectedCards) {
QString ptString; QString ptString;
if (!card->getFaceDown()) { // leave the pt empty if the card is face down if (!card->getFaceDown()) { // leave the pt empty if the card is face down
ExactCard ec = card->getCard(); ExactCard ec = card->getCard();
@ -1279,13 +1284,12 @@ void PlayerActions::actResetPT()
} }
} }
void PlayerActions::actSetPT() void PlayerActions::actSetPT(QList<CardItem *> selectedCards)
{ {
QString oldPT; QString oldPT;
int playerid = player->getPlayerInfo()->getId(); int playerid = player->getPlayerInfo()->getId();
auto cards = player->getGameScene()->selectedCards(); for (auto card : selectedCards) {
for (auto card : cards) {
if (!card->getPT().isEmpty()) { if (!card->getPT().isEmpty()) {
oldPT = card->getPT(); oldPT = card->getPT();
} }
@ -1303,7 +1307,7 @@ void PlayerActions::actSetPT()
bool empty = ptList.isEmpty(); bool empty = ptList.isEmpty();
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : cards) { for (auto card : selectedCards) {
auto *cmd = new Command_SetCardAttr; auto *cmd = new Command_SetCardAttr;
QString newpt = QString(); QString newpt = QString();
if (!empty) { if (!empty) {
@ -1347,47 +1351,47 @@ void PlayerActions::actDrawArrow()
} }
} }
void PlayerActions::actIncP() void PlayerActions::actIncP(QList<CardItem *> selectedCards)
{ {
actIncPT(1, 0); actIncPT(selectedCards, 1, 0);
} }
void PlayerActions::actDecP() void PlayerActions::actDecP(QList<CardItem *> selectedCards)
{ {
actIncPT(-1, 0); actIncPT(selectedCards, -1, 0);
} }
void PlayerActions::actIncT() void PlayerActions::actIncT(QList<CardItem *> selectedCards)
{ {
actIncPT(0, 1); actIncPT(selectedCards, 0, 1);
} }
void PlayerActions::actDecT() void PlayerActions::actDecT(QList<CardItem *> selectedCards)
{ {
actIncPT(0, -1); actIncPT(selectedCards, 0, -1);
} }
void PlayerActions::actIncPT() void PlayerActions::actIncPT(QList<CardItem *> selectedCards)
{ {
actIncPT(1, 1); actIncPT(selectedCards, 1, 1);
} }
void PlayerActions::actDecPT() void PlayerActions::actDecPT(QList<CardItem *> selectedCards)
{ {
actIncPT(-1, -1); actIncPT(selectedCards, -1, -1);
} }
void PlayerActions::actFlowP() void PlayerActions::actFlowP(QList<CardItem *> selectedCards)
{ {
actIncPT(1, -1); actIncPT(selectedCards, 1, -1);
} }
void PlayerActions::actFlowT() void PlayerActions::actFlowT(QList<CardItem *> selectedCards)
{ {
actIncPT(-1, 1); actIncPT(selectedCards, -1, 1);
} }
void PlayerActions::actReduceLifeByPower() void PlayerActions::actReduceLifeByPower(QList<CardItem *> selectedCards)
{ {
// find life counter // find life counter
auto lifeCounter = player->getLifeCounter(); auto lifeCounter = player->getLifeCounter();
@ -1395,10 +1399,9 @@ void PlayerActions::actReduceLifeByPower()
return; return;
} }
// calculate total power // calculate total power;
auto cards = player->getGameScene()->selectedCards();
int total = 0; int total = 0;
for (auto card : cards) { for (auto card : selectedCards) {
QVariantList parsed = CardItem::parsePT(card->getPT()); QVariantList parsed = CardItem::parsePT(card->getPT());
if (!parsed.isEmpty()) { if (!parsed.isEmpty()) {
int power = parsed.first().toInt(); // toInt will default to 0 if it's not an int int power = parsed.first().toInt(); // toInt will default to 0 if it's not an int
@ -1423,11 +1426,10 @@ void AnnotationDialog::keyPressEvent(QKeyEvent *event)
QInputDialog::keyPressEvent(event); QInputDialog::keyPressEvent(event);
} }
void PlayerActions::actSetAnnotation() void PlayerActions::actSetAnnotation(QList<CardItem *> selectedCards)
{ {
QString oldAnnotation; QString oldAnnotation;
auto cards = player->getGameScene()->selectedCards(); for (auto card : selectedCards) {
for (auto card : cards) {
if (!card->getAnnotation().isEmpty()) { if (!card->getAnnotation().isEmpty()) {
oldAnnotation = card->getAnnotation(); oldAnnotation = card->getAnnotation();
} }
@ -1447,7 +1449,7 @@ void PlayerActions::actSetAnnotation()
QString annotation = dialog->textValue().left(MAX_NAME_LENGTH); QString annotation = dialog->textValue().left(MAX_NAME_LENGTH);
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : cards) { for (auto card : selectedCards) {
auto *cmd = new Command_SetCardAttr; auto *cmd = new Command_SetCardAttr;
cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_zone(card->getZone()->getName().toStdString());
cmd->set_card_id(card->getId()); cmd->set_card_id(card->getId());
@ -1468,10 +1470,10 @@ void PlayerActions::actAttach()
card->drawAttachArrow(); card->drawAttachArrow();
} }
void PlayerActions::actUnattach() void PlayerActions::actUnattach(QList<CardItem *> selectedCards)
{ {
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : player->getGameScene()->selectedCards()) { for (auto card : selectedCards) {
if (!card->getAttachedTo()) { if (!card->getAttachedTo()) {
continue; continue;
} }
@ -1484,20 +1486,20 @@ void PlayerActions::actUnattach()
sendGameCommand(prepareGameCommand(commandList)); sendGameCommand(prepareGameCommand(commandList));
} }
void PlayerActions::actAddCardCounter(int counterId) void PlayerActions::actAddCardCounter(QList<CardItem *> selectedCards, int counterId)
{ {
offsetCardCounter(counterId, 1); offsetCardCounter(selectedCards, counterId, 1);
} }
void PlayerActions::actRemoveCardCounter(int counterId) void PlayerActions::actRemoveCardCounter(QList<CardItem *> selectedCards, int counterId)
{ {
offsetCardCounter(counterId, -1); offsetCardCounter(selectedCards, counterId, -1);
} }
void PlayerActions::offsetCardCounter(int counterId, int offset) void PlayerActions::offsetCardCounter(QList<CardItem *> selectedCards, int counterId, int offset)
{ {
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : player->getGameScene()->selectedCards()) { for (auto card : selectedCards) {
int oldValue = card->getCounters().value(counterId, 0); int oldValue = card->getCounters().value(counterId, 0);
int newValue = oldValue + offset; int newValue = oldValue + offset;
@ -1517,15 +1519,14 @@ void PlayerActions::offsetCardCounter(int counterId, int offset)
sendGameCommand(prepareGameCommand(commandList)); sendGameCommand(prepareGameCommand(commandList));
} }
void PlayerActions::actSetCardCounter(int counterId) void PlayerActions::actSetCardCounter(QList<CardItem *> selectedCards, int counterId)
{ {
player->setDialogSemaphore(true); player->setDialogSemaphore(true);
// If a single card is selected, we show the old value in the dialog. Otherwise, we show "x" // If a single card is selected, we show the old value in the dialog. Otherwise, we show "x"
QList<CardItem *> sel = player->getGameScene()->selectedCards();
QString oldValueForDlg = "x"; QString oldValueForDlg = "x";
if (sel.size() == 1) { if (selectedCards.size() == 1) {
auto *card = sel.first(); auto *card = selectedCards.first();
oldValueForDlg = QString::number(card->getCounters().value(counterId, 0)); oldValueForDlg = QString::number(card->getCounters().value(counterId, 0));
} }
@ -1541,7 +1542,7 @@ void PlayerActions::actSetCardCounter(int counterId)
} }
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
for (auto card : sel) { for (auto card : selectedCards) {
int oldValue = card->getCounters().value(counterId, 0); int oldValue = card->getCounters().value(counterId, 0);
Expression exp(oldValue); Expression exp(oldValue);
double parsed = exp.parse(dialog.textValue()); double parsed = exp.parse(dialog.textValue());
@ -1559,9 +1560,8 @@ void PlayerActions::actSetCardCounter(int counterId)
sendGameCommand(prepareGameCommand(commandList)); sendGameCommand(prepareGameCommand(commandList));
} }
void PlayerActions::actIncrementAllCardCounters() void PlayerActions::actIncrementAllCardCounters(QList<CardItem *> cardsToUpdate)
{ {
auto cardsToUpdate = player->getGameScene()->selectedCards();
if (cardsToUpdate.isEmpty()) { if (cardsToUpdate.isEmpty()) {
// If no cards selected, update all cards on table // If no cards selected, update all cards on table
cardsToUpdate = static_cast<QList<CardItem *>>(player->getTableZone()->getCards()); cardsToUpdate = static_cast<QList<CardItem *>>(player->getTableZone()->getCards());
@ -1607,10 +1607,8 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone)
return false; return false;
} }
void PlayerActions::playSelectedCards(const bool faceDown) void PlayerActions::playSelectedCards(QList<CardItem *> selectedCards, const bool faceDown)
{ {
QList<CardItem *> selectedCards = player->getGameScene()->selectedCards();
// CardIds will get shuffled downwards when cards leave the deck. // CardIds will get shuffled downwards when cards leave the deck.
// We need to iterate through the cards in reverse order so cardIds don't get changed out from under us as we play // We need to iterate through the cards in reverse order so cardIds don't get changed out from under us as we play
// out the cards one-by-one. // out the cards one-by-one.
@ -1624,19 +1622,19 @@ void PlayerActions::playSelectedCards(const bool faceDown)
} }
} }
void PlayerActions::actPlay() void PlayerActions::actPlay(QList<CardItem *> selectedCards)
{ {
playSelectedCards(false); playSelectedCards(selectedCards, false);
} }
void PlayerActions::actPlayFacedown() void PlayerActions::actPlayFacedown(QList<CardItem *> selectedCards)
{ {
playSelectedCards(true); playSelectedCards(selectedCards, true);
} }
void PlayerActions::actHide() void PlayerActions::actHide(QList<CardItem *> selectedCards)
{ {
for (const auto &item : player->getGameScene()->selectedCards()) { for (const auto &item : selectedCards) {
auto *card = static_cast<CardItem *>(item); auto *card = static_cast<CardItem *>(item);
if (card && isUnwritableRevealZone(card->getZone())) { if (card && isUnwritableRevealZone(card->getZone())) {
card->getZone()->removeCard(card); card->getZone()->removeCard(card);
@ -1644,7 +1642,7 @@ void PlayerActions::actHide()
} }
} }
void PlayerActions::actReveal(QAction *action) void PlayerActions::actReveal(QList<CardItem *> selectedCards, QAction *action)
{ {
const int otherPlayerId = action->data().toInt(); const int otherPlayerId = action->data().toInt();
@ -1653,7 +1651,7 @@ void PlayerActions::actReveal(QAction *action)
cmd.set_player_id(otherPlayerId); cmd.set_player_id(otherPlayerId);
} }
for (auto card : player->getGameScene()->selectedCards()) { for (auto card : selectedCards) {
if (!cmd.has_zone_name()) { if (!cmd.has_zone_name()) {
cmd.set_zone_name(card->getZone()->getName().toStdString()); cmd.set_zone_name(card->getZone()->getName().toStdString());
} }
@ -1735,15 +1733,14 @@ void PlayerActions::actRevealRandomGraveyardCard(int revealToPlayerId)
sendGameCommand(cmd); sendGameCommand(cmd);
} }
void PlayerActions::cardMenuAction() void PlayerActions::cardMenuAction(QList<CardItem *> selectedCards, CardMenuActionType type)
{ {
auto *a = dynamic_cast<QAction *>(sender()); QList<CardItem *> cardList = selectedCards;
QList<CardItem *> cardList = player->getGameScene()->selectedCards();
QList<const ::google::protobuf::Message *> commandList; QList<const ::google::protobuf::Message *> commandList;
if (a->data().toInt() <= (int)cmClone) { if (type <= cmClone) {
for (const auto &card : cardList) { for (const auto &card : cardList) {
switch (static_cast<CardMenuActionType>(a->data().toInt())) { switch (type) {
// Leaving both for compatibility with server // Leaving both for compatibility with server
case cmUntap: case cmUntap:
// fallthrough // fallthrough
@ -1824,7 +1821,7 @@ void PlayerActions::cardMenuAction()
idList.add_card()->set_card_id(i->getId()); idList.add_card()->set_card_id(i->getId());
} }
switch (static_cast<CardMenuActionType>(a->data().toInt())) { switch (type) {
case cmMoveToTopLibrary: { case cmMoveToTopLibrary: {
auto *cmd = new Command_MoveCard; auto *cmd = new Command_MoveCard;
cmd->set_start_player_id(startPlayerId); cmd->set_start_player_id(startPlayerId);

View file

@ -9,6 +9,7 @@
#define COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H
#include "../dialogs/dlg_create_token.h" #include "../dialogs/dlg_create_token.h"
#include "../dialogs/dlg_move_top_cards_until.h" #include "../dialogs/dlg_move_top_cards_until.h"
#include "card_menu_action_type.h"
#include "event_processing_options.h" #include "event_processing_options.h"
#include "player_logic.h" #include "player_logic.h"
@ -56,15 +57,22 @@ public:
return movingCardsUntil; return movingCardsUntil;
} }
signals:
void requestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed = false);
void requestSortHand(const QList<CardList::SortOption> &options);
void requestEnableAndSetCreateAnotherTokenAction(const QString &lastTokenName);
void requestSetLastToken(CardInfoPtr lastToken);
public slots: public slots:
void setLastToken(CardInfoPtr cardInfo); void setLastToken(CardInfoPtr cardInfo);
void setLastTokenInfo(CardInfoPtr cardInfo);
void playCard(CardItem *c, bool faceDown); void playCard(CardItem *c, bool faceDown);
void playCardToTable(const CardItem *c, bool faceDown); void playCardToTable(const CardItem *c, bool faceDown);
void actUntapAll(); void actUntapAll();
void actRollDie(); void actRollDie();
void actFlipCoin(); void actFlipCoin();
void actCreateToken(); void actCreateToken(const QStringList &predefinedTokens);
void actCreateAnotherToken(); void actCreateAnotherToken();
void actShuffle(); void actShuffle();
void actShuffleTop(); void actShuffleTop();
@ -77,9 +85,9 @@ public slots:
void actMulliganMinusOne(); void actMulliganMinusOne();
void doMulligan(int number); void doMulligan(int number);
void actPlay(); void actPlay(QList<CardItem *> selectedCards);
void actPlayFacedown(); void actPlayFacedown(QList<CardItem *> selectedCards);
void actHide(); void actHide(QList<CardItem *> selectedCards);
void actMoveTopCardToPlay(); void actMoveTopCardToPlay();
void actMoveTopCardToPlayFaceDown(); void actMoveTopCardToPlayFaceDown();
@ -111,8 +119,8 @@ public slots:
void actViewHand(); void actViewHand();
void actViewTopCards(); void actViewTopCards();
void actViewBottomCards(); void actViewBottomCards();
void actAlwaysRevealTopCard(); void actAlwaysRevealTopCard(bool alwaysRevealTopCard);
void actAlwaysLookAtTopCard(); void actAlwaysLookAtTopCard(bool alwaysRevealTopCard);
void actViewGraveyard(); void actViewGraveyard();
void actLendLibrary(int lendToPlayerId); void actLendLibrary(int lendToPlayerId);
void actRevealTopCards(int revealToPlayerId, int amount); void actRevealTopCards(int revealToPlayerId, int amount);
@ -127,37 +135,37 @@ public slots:
void actCreateRelatedCard(); void actCreateRelatedCard();
void actCreateAllRelatedCards(); void actCreateAllRelatedCards();
void actMoveCardXCardsFromTop(); void actMoveCardXCardsFromTop(QList<CardItem *> selectedCards);
void actRemoveCardCounter(int counterId); void actRemoveCardCounter(QList<CardItem *> selectedCards, int counterId);
void actAddCardCounter(int counterId); void actAddCardCounter(QList<CardItem *> selectedCards, int counterId);
void actSetCardCounter(int counterId); void actSetCardCounter(QList<CardItem *> selectedCards, int counterId);
void actIncrementAllCardCounters(); void actIncrementAllCardCounters(QList<CardItem *> cardsToUpdate);
void actAttach(); void actAttach();
void actUnattach(); void actUnattach(QList<CardItem *> selectedCards);
void actDrawArrow(); void actDrawArrow();
void actIncPT(int deltaP, int deltaT); void actIncPT(QList<CardItem *> selectedCards, int deltaP, int deltaT);
void actResetPT(); void actResetPT(QList<CardItem *> selectedCards);
void actSetPT(); void actSetPT(QList<CardItem *> selectedCards);
void actIncP(); void actIncP(QList<CardItem *> selectedCards);
void actDecP(); void actDecP(QList<CardItem *> selectedCards);
void actIncT(); void actIncT(QList<CardItem *> selectedCards);
void actDecT(); void actDecT(QList<CardItem *> selectedCards);
void actIncPT(); void actIncPT(QList<CardItem *> selectedCards);
void actDecPT(); void actDecPT(QList<CardItem *> selectedCards);
void actFlowP(); void actFlowP(QList<CardItem *> selectedCards);
void actFlowT(); void actFlowT(QList<CardItem *> selectedCards);
void actReduceLifeByPower(); void actReduceLifeByPower(QList<CardItem *> selectedCards);
void actSetAnnotation(); void actSetAnnotation(QList<CardItem *> selectedCards);
void actReveal(QAction *action); void actReveal(QList<CardItem *> selectedCards, QAction *action);
void actRevealHand(int revealToPlayerId); void actRevealHand(int revealToPlayerId);
void actRevealRandomHandCard(int revealToPlayerId); void actRevealRandomHandCard(int revealToPlayerId);
void actRevealLibrary(int revealToPlayerId); void actRevealLibrary(int revealToPlayerId);
void actSortHand(); void actSortHand();
void cardMenuAction(); void cardMenuAction(QList<CardItem *> selectedCards, CardMenuActionType type);
private: private:
PlayerLogic *player; PlayerLogic *player;
@ -185,12 +193,12 @@ private:
bool persistent = false); bool persistent = false);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation); bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
void playSelectedCards(bool faceDown = false); void playSelectedCards(QList<CardItem *> selectedCards, bool faceDown = false);
void cmdSetTopCard(Command_MoveCard &cmd); void cmdSetTopCard(Command_MoveCard &cmd);
void cmdSetBottomCard(Command_MoveCard &cmd); void cmdSetBottomCard(Command_MoveCard &cmd);
void offsetCardCounter(int counterId, int offset); void offsetCardCounter(QList<CardItem *> selectedCards, int counterId, int offset);
}; };
#endif // COCKATRICE_PLAYER_ACTIONS_H #endif // COCKATRICE_PLAYER_ACTIONS_H

View file

@ -6,7 +6,6 @@
#include "../board/arrow_item.h" #include "../board/arrow_item.h"
#include "../board/card_item.h" #include "../board/card_item.h"
#include "../board/card_list.h" #include "../board/card_list.h"
#include "libcockatrice/utility/color.h"
#include "player_actions.h" #include "player_actions.h"
#include "player_logic.h" #include "player_logic.h"
@ -33,10 +32,12 @@
#include <libcockatrice/protocol/pb/event_set_card_counter.pb.h> #include <libcockatrice/protocol/pb/event_set_card_counter.pb.h>
#include <libcockatrice/protocol/pb/event_set_counter.pb.h> #include <libcockatrice/protocol/pb/event_set_counter.pb.h>
#include <libcockatrice/protocol/pb/event_shuffle.pb.h> #include <libcockatrice/protocol/pb/event_shuffle.pb.h>
#include <libcockatrice/utility/color.h>
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>
PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player) PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player)
{ {
connect(this, &PlayerEventHandler::requestCardMenuUpdate, player, &PlayerLogic::requestCardMenuUpdate);
} }
void PlayerEventHandler::eventGameSay(const Event_GameSay &event) void PlayerEventHandler::eventGameSay(const Event_GameSay &event)
@ -252,7 +253,7 @@ void PlayerEventHandler::eventSetCardCounter(const Event_SetCardCounter &event)
int oldValue = card->getCounters().value(event.counter_id(), 0); int oldValue = card->getCounters().value(event.counter_id(), 0);
card->setCounter(event.counter_id(), event.counter_value()); card->setCounter(event.counter_id(), event.counter_value());
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
emit logSetCardCounter(player, card->getName(), event.counter_id(), event.counter_value(), oldValue); emit logSetCardCounter(player, card->getName(), event.counter_id(), event.counter_value(), oldValue);
} }
@ -370,7 +371,7 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv
targetZone->addCard(card, true, x, y); targetZone->addCard(card, true, x, y);
emit cardZoneChanged(card, startZone == targetZone); emit cardZoneChanged(card, startZone == targetZone);
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK && if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK &&
targetZone->getName() == ZoneNames::STACK) { targetZone->getName() == ZoneNames::STACK) {
@ -397,7 +398,7 @@ void PlayerEventHandler::eventFlipCard(const Event_FlipCard &event)
emit logFlipCard(player, card->getName(), event.face_down()); emit logFlipCard(player, card->getName(), event.face_down());
card->setFaceDown(event.face_down()); card->setFaceDown(event.face_down());
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
} }
void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event) void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event)
@ -466,7 +467,7 @@ void PlayerEventHandler::eventAttachCard(const Event_AttachCard &event)
} else { } else {
emit logUnattachCard(player, startCard->getName()); emit logUnattachCard(player, startCard->getName());
} }
player->getPlayerMenu()->updateCardMenu(startCard); emit requestCardMenuUpdate(startCard);
} }
void PlayerEventHandler::eventDrawCards(const Event_DrawCards &event) void PlayerEventHandler::eventDrawCards(const Event_DrawCards &event)
@ -552,7 +553,7 @@ void PlayerEventHandler::eventRevealCards(const Event_RevealCards &event, EventP
} }
if (!options.testFlag(SKIP_REVEAL_WINDOW) && showZoneView && !cardList.isEmpty()) { if (!options.testFlag(SKIP_REVEAL_WINDOW) && showZoneView && !cardList.isEmpty()) {
player->getGameScene()->addRevealedZoneView(player, zone, cardList, event.grant_write_access()); emit player->requestRevealedZoneView(player, zone, cardList, event.grant_write_access());
} }
emit logRevealCards(player, zone, cardId, cardName, otherPlayer, false, emit logRevealCards(player, zone, cardId, cardName, otherPlayer, false,

View file

@ -83,6 +83,7 @@ signals:
void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
void cardZoneChanged(CardItem *card, bool sameZone); void cardZoneChanged(CardItem *card, bool sameZone);
void requestCardMenuUpdate(const CardItem *card);
public: public:
PlayerEventHandler(PlayerLogic *player); PlayerEventHandler(PlayerLogic *player);

View file

@ -8,6 +8,9 @@
#include "../board/abstract_card_item.h" #include "../board/abstract_card_item.h"
#include "../board/counter_general.h" #include "../board/counter_general.h"
#include "../hand_counter.h" #include "../hand_counter.h"
#include "player_actions.h"
#include <QGraphicsView>
PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
{ {
@ -16,23 +19,26 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this,
&PlayerGraphicsItem::rearrangeZones); &PlayerGraphicsItem::rearrangeZones);
connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); 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::concededChanged, this, [this](int, bool c) { setVisible(!c); });
connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); });
connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded);
connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved);
connect(player->getPlayerMenu(), &PlayerMenu::shortcutsActivated, this, [this]() { playerMenu = new PlayerMenu(this);
connect(playerMenu, &PlayerMenu::shortcutsActivated, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->setShortcutsActive(); ctr->setShortcutsActive();
} }
}); });
connect(player->getPlayerMenu(), &PlayerMenu::shortcutsDeactivated, this, [this]() { connect(playerMenu, &PlayerMenu::shortcutsDeactivated, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->setShortcutsInactive(); ctr->setShortcutsInactive();
} }
}); });
connect(player->getPlayerMenu(), &PlayerMenu::retranslateRequested, this, [this]() { connect(playerMenu, &PlayerMenu::retranslateRequested, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->retranslateUi(); ctr->retranslateUi();
} }
@ -47,6 +53,8 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
initializeZones(); initializeZones();
playerMenu->setMenusForGraphicItems();
connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect);
updateBoundingRect(); updateBoundingRect();
@ -57,7 +65,7 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
void PlayerGraphicsItem::retranslateUi() void PlayerGraphicsItem::retranslateUi()
{ {
player->getPlayerMenu()->retranslateUi(); playerMenu->retranslateUi();
QMapIterator<QString, CardZoneLogic *> zoneIterator(player->getZones()); QMapIterator<QString, CardZoneLogic *> zoneIterator(player->getZones());
while (zoneIterator.hasNext()) { while (zoneIterator.hasNext()) {
@ -93,14 +101,16 @@ void PlayerGraphicsItem::initializeZones()
rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this); rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this);
rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10)); rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10));
tableZoneGraphicsItem = new TableZone(player->getTableZone(), this); tableZoneGraphicsItem = new TableZone(player->getTableZone(), mirrored, this);
connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect);
connect(this, &PlayerGraphicsItem::mirroredChanged, tableZoneGraphicsItem, &TableZone::setMirrored);
stackZoneGraphicsItem = stackZoneGraphicsItem =
new StackZone(player->getStackZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this); new StackZone(player->getStackZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this);
handZoneGraphicsItem = handZoneGraphicsItem =
new HandZone(player->getHandZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this); new HandZone(player->getHandZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this);
connect(player->getPlayerActions(), &PlayerActions::requestSortHand, handZoneGraphicsItem, &HandZone::sortHand);
connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter, connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter,
&HandCounter::updateNumber); &HandCounter::updateNumber);
@ -145,6 +155,7 @@ void PlayerGraphicsItem::setMirrored(bool _mirrored)
{ {
if (mirrored != _mirrored) { if (mirrored != _mirrored) {
mirrored = _mirrored; mirrored = _mirrored;
emit mirroredChanged(mirrored);
rearrangeZones(); rearrangeZones();
} }
} }
@ -159,11 +170,11 @@ void PlayerGraphicsItem::onCounterAdded(CounterState *state)
} }
counterWidgets.insert(state->getId(), widget); counterWidgets.insert(state->getId(), widget);
if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { if (playerMenu->getCountersMenu() && widget->getMenu()) {
player->getPlayerMenu()->getCountersMenu()->addMenu(widget->getMenu()); playerMenu->getCountersMenu()->addMenu(widget->getMenu());
} }
if (player->getPlayerMenu()->getShortcutsActive()) { if (playerMenu->getShortcutsActive()) {
widget->setShortcutsActive(); widget->setShortcutsActive();
} }
@ -176,8 +187,8 @@ void PlayerGraphicsItem::onCounterRemoved(int counterId)
if (!widget) { if (!widget) {
return; return;
} }
if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { if (playerMenu->getCountersMenu() && widget->getMenu()) {
player->getPlayerMenu()->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); playerMenu->getCountersMenu()->removeAction(widget->getMenu()->menuAction());
} }
widget->delCounter(); widget->delCounter();
rearrangeCounters(); rearrangeCounters();

View file

@ -55,11 +55,16 @@ public:
return static_cast<GameScene *>(scene()); return static_cast<GameScene *>(scene());
} }
PlayerLogic *getPlayer() const PlayerLogic *getLogic() const
{ {
return player; return player;
} }
[[nodiscard]] PlayerMenu *getPlayerMenu() const
{
return playerMenu;
}
PlayerArea *getPlayerArea() const PlayerArea *getPlayerArea() const
{ {
return playerArea; return playerArea;
@ -111,9 +116,12 @@ public slots:
signals: signals:
void sizeChanged(); void sizeChanged();
void playerCountChanged(); void playerCountChanged();
void mirroredChanged(bool isMirrored);
void cardInfoRequested(const CardRef &cardRef);
private: private:
PlayerLogic *player; PlayerLogic *player;
PlayerMenu *playerMenu;
PlayerArea *playerArea; PlayerArea *playerArea;
PlayerTarget *playerTarget; PlayerTarget *playerTarget;
QMap<int, AbstractCounter *> counterWidgets; QMap<int, AbstractCounter *> counterWidgets;

View file

@ -36,14 +36,6 @@ PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool
conceded(false), zoneId(0), dialogSemaphore(false) conceded(false), zoneId(0), dialogSemaphore(false)
{ {
initializeZones(); initializeZones();
playerMenu = new PlayerMenu(this);
graphicsItem = new PlayerGraphicsItem(this);
playerMenu->setMenusForGraphicItems();
connect(this, &PlayerLogic::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged);
connect(this, &PlayerLogic::openDeckEditor, game->getTab(), &TabGame::openDeckEditor);
} }
void PlayerLogic::initializeZones() void PlayerLogic::initializeZones()
@ -69,7 +61,6 @@ PlayerLogic::~PlayerLogic()
} }
zones.clear(); zones.clear();
delete playerMenu;
delete getPlayerInfo()->userInfo; delete getPlayerInfo()->userInfo;
} }
@ -330,22 +321,16 @@ void PlayerLogic::setActive(bool _active)
} }
emit activeChanged(active); emit activeChanged(active);
} }
void PlayerLogic::onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed)
{
emit requestZoneViewToggle(this, zoneName, numberCards, isReversed);
}
void PlayerLogic::updateZones() void PlayerLogic::updateZones()
{ {
getTableZone()->reorganizeCards(); getTableZone()->reorganizeCards();
} }
PlayerGraphicsItem *PlayerLogic::getGraphicsItem()
{
return graphicsItem;
}
GameScene *PlayerLogic::getGameScene()
{
return getGraphicsItem()->getGameScene();
}
void PlayerLogic::setGameStarted() void PlayerLogic::setGameStarted()
{ {
if (playerInfo->local) { if (playerInfo->local) {

View file

@ -67,8 +67,14 @@ class PlayerLogic : public QObject
signals: signals:
void openDeckEditor(const LoadedDeck &deck); void openDeckEditor(const LoadedDeck &deck);
void requestZoneViewToggle(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed);
void requestRevealedZoneView(PlayerLogic *player,
CardZoneLogic *zone,
const QList<const ServerInfo_Card *> &cardList,
bool withWritePermission);
void deckChanged(); void deckChanged();
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void requestCardMenuUpdate(const CardItem *card);
void counterAdded(CounterState *state); void counterAdded(CounterState *state);
void counterRemoved(int counterId); void counterRemoved(int counterId);
void rearrangeCounters(); void rearrangeCounters();
@ -85,6 +91,7 @@ signals:
public slots: public slots:
void setActive(bool _active); void setActive(bool _active);
void onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed);
public: public:
PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent);
@ -112,10 +119,6 @@ public:
return game; return game;
} }
GameScene *getGameScene();
[[nodiscard]] PlayerGraphicsItem *getGraphicsItem();
[[nodiscard]] PlayerActions *getPlayerActions() const [[nodiscard]] PlayerActions *getPlayerActions() const
{ {
return playerActions; return playerActions;
@ -131,11 +134,6 @@ public:
return playerInfo; return playerInfo;
} }
[[nodiscard]] PlayerMenu *getPlayerMenu() const
{
return playerMenu;
}
void setDeck(const DeckList &_deck); void setDeck(const DeckList &_deck);
[[nodiscard]] const DeckList &getDeck() const [[nodiscard]] const DeckList &getDeck() const
@ -236,8 +234,6 @@ private:
PlayerInfo *playerInfo; PlayerInfo *playerInfo;
PlayerEventHandler *playerEventHandler; PlayerEventHandler *playerEventHandler;
PlayerActions *playerActions; PlayerActions *playerActions;
PlayerMenu *playerMenu;
PlayerGraphicsItem *graphicsItem;
bool active; bool active;
bool conceded; bool conceded;

View file

@ -22,7 +22,8 @@ const QColor TableZone::FADE_MASK = QColor(0, 0, 0, 80);
const QColor TableZone::GRADIENT_COLOR = QColor(255, 255, 255, 150); const QColor TableZone::GRADIENT_COLOR = QColor(255, 255, 255, 150);
const QColor TableZone::GRADIENT_COLORLESS = QColor(255, 255, 255, 0); const QColor TableZone::GRADIENT_COLORLESS = QColor(255, 255, 255, 0);
TableZone::TableZone(TableZoneLogic *_logic, QGraphicsItem *parent) : SelectZone(_logic, parent), active(false) TableZone::TableZone(TableZoneLogic *_logic, bool _mirrored, QGraphicsItem *parent)
: SelectZone(_logic, parent), active(false), mirrored(_mirrored)
{ {
connect(_logic, &TableZoneLogic::contentSizeChanged, this, &TableZone::resizeToContents); connect(_logic, &TableZoneLogic::contentSizeChanged, this, &TableZone::resizeToContents);
connect(_logic, &TableZoneLogic::toggleTapped, this, &TableZone::toggleTapped); connect(_logic, &TableZoneLogic::toggleTapped, this, &TableZone::toggleTapped);
@ -50,12 +51,16 @@ QRectF TableZone::boundingRect() const
return QRectF(0, 0, width, height); return QRectF(0, 0, width, height);
} }
void TableZone::setMirrored(bool isMirrored)
{
mirrored = isMirrored;
update();
}
bool TableZone::isInverted() const bool TableZone::isInverted() const
{ {
return ((getLogic()->getPlayer()->getGraphicsItem()->getMirrored() && return ((mirrored && !SettingsCache::instance().getInvertVerticalCoordinate()) ||
!SettingsCache::instance().getInvertVerticalCoordinate()) || (!mirrored && SettingsCache::instance().getInvertVerticalCoordinate()));
(!getLogic()->getPlayer()->getGraphicsItem()->getMirrored() &&
SettingsCache::instance().getInvertVerticalCoordinate()));
} }
void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)

View file

@ -82,6 +82,7 @@ private:
If this TableZone is currently active If this TableZone is currently active
*/ */
bool active = false; bool active = false;
bool mirrored = false;
[[nodiscard]] bool isInverted() const; [[nodiscard]] bool isInverted() const;
@ -96,6 +97,7 @@ public slots:
Reorganizes CardItems in the TableZone Reorganizes CardItems in the TableZone
*/ */
void reorganizeCards() override; void reorganizeCards() override;
void setMirrored(bool isMirrored);
public: public:
/** /**
@ -104,7 +106,7 @@ public:
@param _p the Player @param _p the Player
@param parent defaults to null @param parent defaults to null
*/ */
explicit TableZone(TableZoneLogic *_logic, QGraphicsItem *parent = nullptr); explicit TableZone(TableZoneLogic *_logic, bool mirrored, QGraphicsItem *parent = nullptr);
/** /**
@return a QRectF of the TableZone bounding box. @return a QRectF of the TableZone bounding box.

View file

@ -1,6 +1,7 @@
#include "tab_game.h" #include "tab_game.h"
#include "../../../client/settings/cache_settings.h" #include "../../../client/settings/cache_settings.h"
#include "../../../game/player/menu/card_menu.h"
#include "../game/board/arrow_item.h" #include "../game/board/arrow_item.h"
#include "../game/board/card_item.h" #include "../game/board/card_item.h"
#include "../game/deckview/deck_view_container.h" #include "../game/deckview/deck_view_container.h"
@ -364,11 +365,10 @@ void TabGame::retranslateUi()
cardInfoFrameWidget->retranslateUi(); cardInfoFrameWidget->retranslateUi();
QMapIterator<int, PlayerLogic *> i(game->getPlayerManager()->getPlayers()); for (auto playerView : scene->getPlayers().values()) {
playerView->retranslateUi();
while (i.hasNext()) {
i.next().value()->getGraphicsItem()->retranslateUi();
} }
QMapIterator<int, TabbedDeckViewContainer *> j(deckViewContainers); QMapIterator<int, TabbedDeckViewContainer *> j(deckViewContainers);
while (j.hasNext()) { while (j.hasNext()) {
j.next().value()->playerDeckView->retranslateUi(); j.next().value()->playerDeckView->retranslateUi();
@ -655,8 +655,12 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer)
scene->addPlayer(newPlayer); scene->addPlayer(newPlayer);
auto *view = scene->viewForPlayer(newPlayer->getPlayerInfo()->getId());
connect(newPlayer, &PlayerLogic::newCardAdded, this, &TabGame::newCardAdded); connect(newPlayer, &PlayerLogic::newCardAdded, this, &TabGame::newCardAdded);
connect(newPlayer->getPlayerMenu(), &PlayerMenu::cardMenuUpdated, this, &TabGame::setCardMenu); connect(newPlayer, &PlayerLogic::openDeckEditor, this, &TabGame::openDeckEditor);
connect(view->getPlayerMenu(), &PlayerMenu::cardMenuUpdated, this, &TabGame::setCardMenu);
connect(view, &PlayerGraphicsItem::cardInfoRequested, this, &TabGame::viewCardInfo);
messageLog->connectToPlayerEventHandler(newPlayer->getPlayerEventHandler()); messageLog->connectToPlayerEventHandler(newPlayer->getPlayerEventHandler());
@ -669,7 +673,7 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer)
addLocalPlayer(newPlayer, newPlayer->getPlayerInfo()->getId()); addLocalPlayer(newPlayer, newPlayer->getPlayerInfo()->getId());
} }
gameMenu->insertMenu(playersSeparator, newPlayer->getPlayerMenu()->getPlayerMenu()); gameMenu->insertMenu(playersSeparator, view->getPlayerMenu()->getPlayerMenu());
createZoneForPlayer(newPlayer, newPlayer->getPlayerInfo()->getId()); createZoneForPlayer(newPlayer, newPlayer->getPlayerInfo()->getId());
@ -679,7 +683,7 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer)
void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId) void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId)
{ {
if (game->getGameState()->getClients().size() == 1) { if (game->getGameState()->getClients().size() == 1) {
newPlayer->getPlayerMenu()->setShortcutsActive(); scene->viewForPlayer(playerId)->getPlayerMenu()->setShortcutsActive();
} }
auto *deckView = new TabbedDeckViewContainer(playerId, this); auto *deckView = new TabbedDeckViewContainer(playerId, this);
@ -699,27 +703,24 @@ void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId)
void TabGame::processPlayerLeave(PlayerLogic *leavingPlayer) void TabGame::processPlayerLeave(PlayerLogic *leavingPlayer)
{ {
QString playerName = "@" + leavingPlayer->getPlayerInfo()->getName(); removePlayerFromAutoCompleteList("@" + leavingPlayer->getPlayerInfo()->getName());
removePlayerFromAutoCompleteList(playerName);
scene->removePlayer(leavingPlayer);
// When we inserted the playerMenu into the gameMenu earlier, Qt wrapped the playerMenu into a QAction*, which lives // When we inserted the playerMenu into the gameMenu earlier, Qt wrapped the playerMenu into a QAction*, which lives
// independently and does not get cleaned up when the source menu gets destroyed. We have to manually clean here. // independently and does not get cleaned up when the source menu gets destroyed. We have to manually clean here.
if (leavingPlayer->getPlayerMenu()) { auto *view = scene->viewForPlayer(leavingPlayer->getPlayerInfo()->getId());
QMenu *menu = leavingPlayer->getPlayerMenu()->getPlayerMenu(); if (view) {
if (menu) { // Find and remove the QAction pointing to this menu
// Find and remove the QAction pointing to this menu QMenu *menu = view->getPlayerMenu()->getPlayerMenu();
QList<QAction *> actions = gameMenu->actions(); for (QAction *act : gameMenu->actions()) {
for (QAction *act : actions) { if (act->menu() == menu) {
if (act->menu() == menu) { gameMenu->removeAction(act);
gameMenu->removeAction(act); delete act;
delete act; // deletes the QAction wrapper around the submenu break;
break;
}
} }
} }
} }
scene->removePlayer(leavingPlayer);
} }
void TabGame::processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName) void TabGame::processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName)
@ -871,12 +872,12 @@ PlayerLogic *TabGame::setActivePlayer(int id)
if (i.value() == player) { if (i.value() == player) {
i.value()->setActive(true); i.value()->setActive(true);
if (game->getGameState()->getClients().size() > 1) { if (game->getGameState()->getClients().size() > 1) {
i.value()->getPlayerMenu()->setShortcutsActive(); scene->viewForPlayer(i.value()->getPlayerInfo()->getId())->getPlayerMenu()->setShortcutsActive();
} }
} else { } else {
i.value()->setActive(false); i.value()->setActive(false);
if (game->getGameState()->getClients().size() > 1) { if (game->getGameState()->getClients().size() > 1) {
i.value()->getPlayerMenu()->setShortcutsInactive(); scene->viewForPlayer(i.value()->getPlayerInfo()->getId())->getPlayerMenu()->setShortcutsInactive();
} }
} }
} }
@ -892,8 +893,13 @@ void TabGame::setActivePhase(int phase)
void TabGame::newCardAdded(AbstractCardItem *card) void TabGame::newCardAdded(AbstractCardItem *card)
{ {
connect(card, &AbstractCardItem::rightClicked, scene, &GameScene::onCardRightClicked);
connect(card, &AbstractCardItem::playSelected, scene, &GameScene::playSelected);
connect(card, &AbstractCardItem::playSelectedFaceDown, scene, &GameScene::playSelectedFaceDown);
connect(card, &AbstractCardItem::hideSelected, scene, &GameScene::hideSelected);
connect(card, &AbstractCardItem::hovered, cardInfoFrameWidget, connect(card, &AbstractCardItem::hovered, cardInfoFrameWidget,
qOverload<AbstractCardItem *>(&CardInfoFrameWidget::setCard)); qOverload<AbstractCardItem *>(&CardInfoFrameWidget::setCard));
connect(card, &AbstractCardItem::selectionChanged, scene, &GameScene::onCardSelectionChanged);
connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup); connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup);
connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
connect(card, &AbstractCardItem::cardShiftClicked, this, &TabGame::linkCardToChat); connect(card, &AbstractCardItem::cardShiftClicked, this, &TabGame::linkCardToChat);
@ -937,7 +943,7 @@ QString TabGame::getTabText() const
/** /**
* @param menu The menu to set. Pass in nullptr to set the menu to empty. * @param menu The menu to set. Pass in nullptr to set the menu to empty.
*/ */
void TabGame::setCardMenu(QMenu *menu) void TabGame::setCardMenu(CardMenu *menu)
{ {
if (!aCardMenu) { if (!aCardMenu) {
return; return;

View file

@ -143,7 +143,7 @@ signals:
private slots: private slots:
void adminLockChanged(bool lock); void adminLockChanged(bool lock);
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void setCardMenu(QMenu *menu); void setCardMenu(CardMenu *menu);
void actGameInfo(); void actGameInfo();
void actConcede(); void actConcede();