From bddf9bd818462b26abbc96495ddf0dcc9913c113 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 21 May 2026 20:16:28 +0200 Subject: [PATCH] [Game][Counters] Split counters into AbstractCounter (graphics) and CounterState (logic) (#6917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Counters] Split counters into graphics and logic states Took 22 minutes * Don't have widget hold pointer to state -> Copy what we need and subscribe to changes. Took 12 minutes Took 5 seconds * Sync value too. Took 3 minutes --------- Co-authored-by: Lukas BrĂ¼bach --- cockatrice/CMakeLists.txt | 1 + .../src/game/board/abstract_counter.cpp | 129 ++++++++---------- cockatrice/src/game/board/abstract_counter.h | 39 ++++-- cockatrice/src/game/board/counter_general.cpp | 11 +- cockatrice/src/game/board/counter_general.h | 11 +- cockatrice/src/game/board/counter_state.cpp | 24 ++++ cockatrice/src/game/board/counter_state.h | 51 +++++++ .../src/game/player/menu/player_menu.cpp | 30 +--- cockatrice/src/game/player/menu/player_menu.h | 3 + .../src/game/player/player_event_handler.cpp | 2 +- .../src/game/player/player_graphics_item.cpp | 71 ++++++++-- .../src/game/player/player_graphics_item.h | 6 +- cockatrice/src/game/player/player_logic.cpp | 65 ++++----- cockatrice/src/game/player/player_logic.h | 14 +- cockatrice/src/game/player/player_target.cpp | 10 +- cockatrice/src/game/player/player_target.h | 4 +- .../libcockatrice/utility/color.h | 1 + 17 files changed, 273 insertions(+), 199 deletions(-) create mode 100644 cockatrice/src/game/board/counter_state.cpp create mode 100644 cockatrice/src/game/board/counter_state.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 389577d4f..bd79b62c5 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -66,6 +66,7 @@ set(cockatrice_SOURCES src/game/board/card_list.cpp src/game/board/card_state.cpp src/game/board/counter_general.cpp + src/game/board/counter_state.cpp src/game/board/translate_counter_name.cpp src/game/deckview/deck_view.cpp src/game/deckview/deck_view_container.cpp diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index e0e801ab2..18787a0bc 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,24 +17,24 @@ #include #include -AbstractCounter::AbstractCounter(PlayerLogic *_player, - int _id, - const QString &_name, +AbstractCounter::AbstractCounter(CounterState *state, + PlayerLogic *_player, bool _shownInCounterArea, - int _value, bool _useNameForShortcut, QGraphicsItem *parent) - : QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), - useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false), - deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea) + : QGraphicsItem(parent), player(_player), id(state->getId()), name(state->getName()), value(state->getValue()), + color(state->getColor()), radius(state->getRadius()), useNameForShortcut(_useNameForShortcut), + shownInCounterArea(_shownInCounterArea) { setAcceptHoverEvents(true); - shortcutActive = false; + connect(state, &CounterState::valueChanged, this, [this](int, int newValue) { + value = newValue; + update(); + }); if (player->getPlayerInfo()->getLocalOrJudge()) { - QString displayName = TranslateCounterName::getDisplayName(_name); - menu = new TearOffMenu(displayName); + menu = new TearOffMenu(TranslateCounterName::getDisplayName(state->getName())); aSet = new QAction(this); connect(aSet, &QAction::triggered, this, &AbstractCounter::setCounter); menu->addAction(aSet); @@ -41,17 +42,18 @@ AbstractCounter::AbstractCounter(PlayerLogic *_player, for (int i = 10; i >= -10; --i) { if (i == 0) { menu->addSeparator(); - } else { - QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); - if (i == -1) { - aDec = aIncrement; - } else if (i == 1) { - aInc = aIncrement; - } - aIncrement->setData(i); - connect(aIncrement, &QAction::triggered, this, &AbstractCounter::incrementCounter); - menu->addAction(aIncrement); + continue; } + auto *a = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); + if (i == -1) { + aDec = a; + } + if (i == 1) { + aInc = a; + } + a->setData(i); + connect(a, &QAction::triggered, this, &AbstractCounter::incrementCounter); + menu->addAction(a); } } else { menu = nullptr; @@ -79,31 +81,26 @@ void AbstractCounter::delCounter() void AbstractCounter::retranslateUi() { - if (menu) { + if (aSet) { aSet->setText(tr("&Set counter...")); } } void AbstractCounter::setShortcutsActive() { - if (!menu) { + if (!menu || !player->getPlayerInfo()->getLocal()) { return; } - if (!player->getPlayerInfo()->getLocal()) { - return; - } - - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + ShortcutsSettings &sc = SettingsCache::instance().shortcuts(); + shortcutActive = true; if (name == "life") { - shortcutActive = true; - aSet->setShortcuts(shortcuts.getShortcut("Player/aSet")); - aDec->setShortcuts(shortcuts.getShortcut("Player/aDec")); - aInc->setShortcuts(shortcuts.getShortcut("Player/aInc")); + aSet->setShortcuts(sc.getShortcut("Player/aSet")); + aDec->setShortcuts(sc.getShortcut("Player/aDec")); + aInc->setShortcuts(sc.getShortcut("Player/aInc")); } else if (useNameForShortcut) { - shortcutActive = true; - aSet->setShortcuts(shortcuts.getShortcut("Player/aSetCounter_" + name)); - aDec->setShortcuts(shortcuts.getShortcut("Player/aDecCounter_" + name)); - aInc->setShortcuts(shortcuts.getShortcut("Player/aIncCounter_" + name)); + aSet->setShortcuts(sc.getShortcut("Player/aSetCounter_" + name)); + aDec->setShortcuts(sc.getShortcut("Player/aDecCounter_" + name)); + aInc->setShortcuts(sc.getShortcut("Player/aIncCounter_" + name)); } } @@ -128,45 +125,32 @@ void AbstractCounter::refreshShortcuts() } } -void AbstractCounter::setValue(int _value) -{ - value = _value; - update(); -} - void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (isUnderMouse() && player->getPlayerInfo()->getLocalOrJudge()) { - if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) { - if (menu) { - menu->exec(event->screenPos()); - } - event->accept(); - } else if (event->button() == Qt::LeftButton) { - Command_IncCounter cmd; - cmd.set_counter_id(id); - cmd.set_delta(1); - player->getPlayerActions()->sendGameCommand(cmd); - event->accept(); - } else if (event->button() == Qt::RightButton) { - Command_IncCounter cmd; - cmd.set_counter_id(id); - cmd.set_delta(-1); - player->getPlayerActions()->sendGameCommand(cmd); - event->accept(); + if (!isUnderMouse() || !player->getPlayerInfo()->getLocalOrJudge()) { + event->ignore(); + return; + } + + if (event->button() == Qt::MiddleButton || QApplication::keyboardModifiers() & Qt::ShiftModifier) { + if (menu) { + menu->exec(event->screenPos()); } } else { - event->ignore(); + Command_IncCounter cmd; + cmd.set_counter_id(id); + cmd.set_delta(event->button() == Qt::LeftButton ? 1 : -1); + player->getPlayerActions()->sendGameCommand(cmd); } + event->accept(); } -void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/) +void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent *) { hovered = true; update(); } - -void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) +void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { hovered = false; update(); @@ -174,35 +158,36 @@ void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) void AbstractCounter::incrementCounter() { - const int delta = static_cast(sender())->data().toInt(); Command_IncCounter cmd; cmd.set_counter_id(id); - cmd.set_delta(delta); + cmd.set_delta(static_cast(sender())->data().toInt()); player->getPlayerActions()->sendGameCommand(cmd); } void AbstractCounter::setCounter() { + QWidget *parent = nullptr; + if (auto *view = scene() ? scene()->views().value(0) : nullptr) { + parent = view->window(); + } + dialogSemaphore = true; - AbstractCounterDialog dialog(name, QString::number(value), player->getGame()->getTab()); - const int ok = dialog.exec(); + AbstractCounterDialog dlg(name, QString::number(value), parent); + const int ok = dlg.exec(); + dialogSemaphore = false; if (deleteAfterDialog) { deleteLater(); return; } - dialogSemaphore = false; - if (!ok) { return; } Expression exp(value); - int newValue = static_cast(exp.parse(dialog.textValue())); - Command_SetCounter cmd; cmd.set_counter_id(id); - cmd.set_value(newValue); + cmd.set_value(static_cast(exp.parse(dlg.textValue()))); player->getPlayerActions()->sendGameCommand(cmd); } diff --git a/cockatrice/src/game/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h index 7bc07d41f..57bc43856 100644 --- a/cockatrice/src/game/board/abstract_counter.h +++ b/cockatrice/src/game/board/abstract_counter.h @@ -9,6 +9,7 @@ #include "../../interface/widgets/menus/tearoff_menu.h" #include "../player/menu/abstract_player_component.h" +#include "counter_state.h" #include #include @@ -29,18 +30,22 @@ protected: int id; QString name; int value; - bool useNameForShortcut, hovered; + QColor color; + int radius; + bool hovered = false; + bool useNameForShortcut; void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; private: - QAction *aSet, *aDec, *aInc; - TearOffMenu *menu; - bool dialogSemaphore, deleteAfterDialog; + QAction *aSet = nullptr, *aDec = nullptr, *aInc = nullptr; + TearOffMenu *menu = nullptr; + bool dialogSemaphore = false; + bool deleteAfterDialog = false; bool shownInCounterArea; - bool shortcutActive; + bool shortcutActive = false; private slots: void refreshShortcuts(); @@ -48,17 +53,14 @@ private slots: void setCounter(); public: - AbstractCounter(PlayerLogic *_player, - int _id, - const QString &_name, - bool _shownInCounterArea, - int _value, - bool _useNameForShortcut = false, + AbstractCounter(CounterState *state, + PlayerLogic *player, + bool shownInCounterArea, + bool useNameForShortcut = false, QGraphicsItem *parent = nullptr); ~AbstractCounter() override; void retranslateUi() override; - void setValue(int _value); void setShortcutsActive() override; void setShortcutsInactive() override; void delCounter(); @@ -67,7 +69,6 @@ public: { return menu; } - int getId() const { return id; @@ -76,14 +77,22 @@ public: { return name; } - bool getShownInCounterArea() const + QColor getColor() const { - return shownInCounterArea; + return color; + } + int getRadius() const + { + return radius; } int getValue() const { return value; } + bool getShownInCounterArea() const + { + return shownInCounterArea; + } }; class AbstractCounterDialog : public QInputDialog diff --git a/cockatrice/src/game/board/counter_general.cpp b/cockatrice/src/game/board/counter_general.cpp index 7dd0b1f15..5147ede6b 100644 --- a/cockatrice/src/game/board/counter_general.cpp +++ b/cockatrice/src/game/board/counter_general.cpp @@ -5,15 +5,8 @@ #include -GeneralCounter::GeneralCounter(PlayerLogic *_player, - int _id, - const QString &_name, - const QColor &_color, - int _radius, - int _value, - bool useNameForShortcut, - QGraphicsItem *parent) - : AbstractCounter(_player, _id, _name, true, _value, useNameForShortcut, parent), color(_color), radius(_radius) +GeneralCounter::GeneralCounter(CounterState *state, PlayerLogic *player, bool useNameForShortcut, QGraphicsItem *parent) + : AbstractCounter(state, player, true, useNameForShortcut, parent) { setCacheMode(DeviceCoordinateCache); } diff --git a/cockatrice/src/game/board/counter_general.h b/cockatrice/src/game/board/counter_general.h index ac008fa49..db1ee2743 100644 --- a/cockatrice/src/game/board/counter_general.h +++ b/cockatrice/src/game/board/counter_general.h @@ -12,17 +12,10 @@ class GeneralCounter : public AbstractCounter { Q_OBJECT -private: - QColor color; - int radius; public: - GeneralCounter(PlayerLogic *_player, - int _id, - const QString &_name, - const QColor &_color, - int _radius, - int _value, + GeneralCounter(CounterState *state, + PlayerLogic *player, bool useNameForShortcut = false, QGraphicsItem *parent = nullptr); QRectF boundingRect() const override; diff --git a/cockatrice/src/game/board/counter_state.cpp b/cockatrice/src/game/board/counter_state.cpp new file mode 100644 index 000000000..6da18b662 --- /dev/null +++ b/cockatrice/src/game/board/counter_state.cpp @@ -0,0 +1,24 @@ +#include "counter_state.h" + +#include + +CounterState::CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent) + : QObject(parent), id(id), name(name), color(color), radius(radius), value(value) +{ +} + +CounterState *CounterState::fromProto(const ServerInfo_Counter &counter, QObject *parent) +{ + return new CounterState(counter.id(), QString::fromStdString(counter.name()), + convertColorToQColor(counter.counter_color()), counter.radius(), counter.count(), parent); +} + +void CounterState::setValue(int newValue) +{ + if (newValue == value) { + return; + } + int old = value; + value = newValue; + emit valueChanged(old, newValue); +} \ No newline at end of file diff --git a/cockatrice/src/game/board/counter_state.h b/cockatrice/src/game/board/counter_state.h new file mode 100644 index 000000000..0f2f16b55 --- /dev/null +++ b/cockatrice/src/game/board/counter_state.h @@ -0,0 +1,51 @@ +#ifndef COCKATRICE_COUNTER_STATE_H +#define COCKATRICE_COUNTER_STATE_H + +#include +#include +#include +#include + +class CounterState : public QObject +{ + Q_OBJECT +public: + CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent = nullptr); + + static CounterState *fromProto(const ServerInfo_Counter &counter, QObject *parent = nullptr); + + int getId() const + { + return id; + } + QString getName() const + { + return name; + } + QColor getColor() const + { + return color; + } + int getRadius() const + { + return radius; + } + int getValue() const + { + return value; + } + + void setValue(int newValue); + +signals: + void valueChanged(int oldValue, int newValue); + +private: + int id; + QString name; + QColor color; + int radius; + int value; +}; + +#endif // COCKATRICE_COUNTER_STATE_H diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index d04950c96..9e7b91923 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -97,10 +97,7 @@ void PlayerMenu::retranslateUi() countersMenu->setTitle(tr("&Counters")); } - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->retranslateUi(); - } + emit retranslateRequested(); } void PlayerMenu::refreshShortcuts() @@ -120,30 +117,17 @@ void PlayerMenu::refreshShortcuts() void PlayerMenu::setShortcutsActive() { shortcutsActive = true; - - for (auto *component : managedComponents) { - component->setShortcutsActive(); - } - - // Counters implement AbstractPlayerComponent but are iterated via Player::counters - // (the authoritative source) rather than managedComponents to avoid a redundant - // list that must stay in sync with the map. - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsActive(); + for (auto *c : managedComponents) { + c->setShortcutsActive(); } + emit shortcutsActivated(); } void PlayerMenu::setShortcutsInactive() { shortcutsActive = false; - - for (auto *component : managedComponents) { - component->setShortcutsInactive(); - } - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsInactive(); + for (auto *c : managedComponents) { + c->setShortcutsInactive(); } + emit shortcutsDeactivated(); } \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h index 7532ac225..78e810e62 100644 --- a/cockatrice/src/game/player/menu/player_menu.h +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -29,6 +29,9 @@ class PlayerMenu : public QObject signals: void cardMenuUpdated(QMenu *cardMenu); + void shortcutsActivated(); + void shortcutsDeactivated(); + void retranslateRequested(); public slots: void setMenusForGraphicItems(); diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 15c40c638..1345924b6 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -246,7 +246,7 @@ void PlayerEventHandler::eventCreateCounter(const Event_CreateCounter &event) void PlayerEventHandler::eventSetCounter(const Event_SetCounter &event) { - AbstractCounter *ctr = player->getCounters().value(event.counter_id(), 0); + CounterState *ctr = player->getCounters().value(event.counter_id(), nullptr); if (!ctr) { return; } diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index eea2434d2..0d4f8c3ed 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -6,6 +6,7 @@ #include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/abstract_card_item.h" +#include "../board/counter_general.h" #include "../hand_counter.h" PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) @@ -18,6 +19,25 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); + connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); + connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); + + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsActivated, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->setShortcutsActive(); + } + }); + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsDeactivated, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->setShortcutsInactive(); + } + }); + connect(player->getPlayerMenu(), &PlayerMenu::retranslateRequested, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->retranslateUi(); + } + }); + playerArea = new PlayerArea(this); playerTarget = new PlayerTarget(player, playerArea); @@ -43,11 +63,6 @@ void PlayerGraphicsItem::retranslateUi() while (zoneIterator.hasNext()) { emit zoneIterator.next().value()->retranslateUi(); } - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->retranslateUi(); - } } void PlayerGraphicsItem::onPlayerActiveChanged(bool _active) @@ -134,20 +149,48 @@ void PlayerGraphicsItem::setMirrored(bool _mirrored) } } +void PlayerGraphicsItem::onCounterAdded(CounterState *state) +{ + AbstractCounter *widget; + if (state->getName() == "life") { + widget = playerTarget->addCounter(state); + } else { + widget = new GeneralCounter(state, player, true, this); + } + counterWidgets.insert(state->getId(), widget); + + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->addMenu(widget->getMenu()); + } + + if (player->getPlayerMenu()->getShortcutsActive()) { + widget->setShortcutsActive(); + } + + rearrangeCounters(); +} + +void PlayerGraphicsItem::onCounterRemoved(int counterId) +{ + auto *widget = counterWidgets.take(counterId); + if (!widget) { + return; + } + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); + } + widget->delCounter(); + rearrangeCounters(); +} + void PlayerGraphicsItem::rearrangeCounters() { - qreal marginTop = 80; - const qreal padding = 5; - qreal ySize = boundingRect().y() + marginTop; - - // Place objects - for (const auto &counter : player->getCounters()) { - AbstractCounter *ctr = counter; - + qreal ySize = boundingRect().y() + 80; + constexpr qreal padding = 5; + for (auto *ctr : counterWidgets.values()) { if (!ctr->getShownInCounterArea()) { continue; } - QRectF br = ctr->boundingRect(); ctr->setPos((counterAreaWidth - br.width()) / 2, ySize); ySize += br.height() + padding; diff --git a/cockatrice/src/game/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h index 33c00be4f..264654e9c 100644 --- a/cockatrice/src/game/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -6,6 +6,7 @@ #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H +#include "../board/abstract_counter.h" #include "../game_scene.h" #include "player_logic.h" @@ -102,6 +103,9 @@ public: public slots: void onPlayerActiveChanged(bool _active); + void onCounterAdded(CounterState *state); + void onCounterRemoved(int counterId); + void rearrangeCounters(); void retranslateUi(); signals: @@ -112,6 +116,7 @@ private: PlayerLogic *player; PlayerArea *playerArea; PlayerTarget *playerTarget; + QMap counterWidgets; PileZone *deckZoneGraphicsItem; PileZone *sideboardGraphicsItem; PileZone *graveyardZoneGraphicsItem; @@ -126,7 +131,6 @@ private: private slots: void updateBoundingRect(); void rearrangeZones(); - void rearrangeCounters(); }; #endif // COCKATRICE_PLAYER_GRAPHICS_ITEM_H diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 2c09e3634..677cc0d91 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -258,57 +258,52 @@ void PlayerLogic::setDeck(const DeckList &_deck) emit deckChanged(); } -AbstractCounter *PlayerLogic::addCounter(const ServerInfo_Counter &counter) +CounterState *PlayerLogic::addCounter(const ServerInfo_Counter &counter) { return addCounter(counter.id(), QString::fromStdString(counter.name()), convertColorToQColor(counter.counter_color()), counter.radius(), counter.count()); } -AbstractCounter *PlayerLogic::addCounter(int counterId, const QString &name, QColor color, int radius, int value) +CounterState *PlayerLogic::addCounter(int id, const QString &name, const QColor &color, int radius, int value) { - if (counters.contains(counterId)) { + if (counters.contains(id)) { return nullptr; } - - AbstractCounter *ctr; - if (name == "life") { - ctr = getGraphicsItem()->getPlayerTarget()->addCounter(counterId, name, value); - } else { - ctr = new GeneralCounter(this, counterId, name, color, radius, value, true, graphicsItem); - } - counters.insert(counterId, ctr); - - if (playerMenu->getCountersMenu() && ctr->getMenu()) { - playerMenu->getCountersMenu()->addMenu(ctr->getMenu()); - } - if (playerMenu->getShortcutsActive()) { - ctr->setShortcutsActive(); - } - emit rearrangeCounters(); - return ctr; + auto *state = new CounterState(id, name, color, radius, value, this); + counters.insert(id, state); + emit counterAdded(state); + return state; } -void PlayerLogic::delCounter(int counterId) +void PlayerLogic::delCounter(int id) { - AbstractCounter *ctr = counters.value(counterId, 0); - if (!ctr) { + auto *state = counters.take(id); + if (!state) { return; } - - ctr->delCounter(); - counters.remove(counterId); - emit rearrangeCounters(); + emit counterRemoved(id); + state->deleteLater(); } void PlayerLogic::clearCounters() { - QMapIterator counterIterator(counters); - while (counterIterator.hasNext()) { - counterIterator.next().value()->delCounter(); + for (int id : counters.keys()) { + emit counterRemoved(id); } + qDeleteAll(counters); counters.clear(); } +CounterState *PlayerLogic::getLifeCounter() const +{ + for (auto *s : counters.values()) { + if (s->getName() == "life") { + return s; + } + } + return nullptr; +} + void PlayerLogic::incrementAllCardCounters() { auto cardsToUpdate = getGameScene()->selectedCards(); @@ -345,16 +340,6 @@ void PlayerLogic::incrementAllCardCounters() } } -AbstractCounter *PlayerLogic::getLifeCounter() const -{ - for (auto counter : counters.values()) { - if (counter->getName() == "life") { - return counter; - } - } - return nullptr; -} - ArrowItem *PlayerLogic::addArrow(const ServerInfo_Arrow &arrow) { const QMap &playerList = game->getPlayerManager()->getPlayers(); diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 55599f5e2..01d7052df 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -7,7 +7,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "../../game_graphics/board/abstract_graphics_item.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../interface/deck_loader/loaded_deck.h" #include "../zones/hand_zone_logic.h" @@ -39,7 +38,6 @@ class Message; } } // namespace google class AbstractCardItem; -class AbstractCounter; class AbstractGame; class ArrowItem; class ArrowTarget; @@ -70,6 +68,8 @@ signals: void openDeckEditor(const LoadedDeck &deck); void deckChanged(); void newCardAdded(AbstractCardItem *card); + void counterAdded(CounterState *state); + void counterRemoved(int counterId); void rearrangeCounters(); void activeChanged(bool active); void zoneIdChanged(int zoneId); @@ -189,13 +189,13 @@ public: return qobject_cast(zones.value(ZoneNames::HAND)); } - AbstractCounter *addCounter(const ServerInfo_Counter &counter); - AbstractCounter *addCounter(int counterId, const QString &name, QColor color, int radius, int value); + CounterState *addCounter(const ServerInfo_Counter &counter); + CounterState *addCounter(int id, const QString &name, const QColor &color, int radius, int value); void delCounter(int counterId); void clearCounters(); void incrementAllCardCounters(); - QMap getCounters() + QMap getCounters() const { return counters; } @@ -203,7 +203,7 @@ public: /** * Gets the counter that represents the life total. */ - AbstractCounter *getLifeCounter() const; + CounterState *getLifeCounter() const; ArrowItem *addArrow(const ServerInfo_Arrow &arrow); ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color); @@ -251,7 +251,7 @@ private: int zoneId; QMap zones; - QMap counters; + QMap counters; QMap arrows; bool dialogSemaphore; diff --git a/cockatrice/src/game/player/player_target.cpp b/cockatrice/src/game/player/player_target.cpp index 93f2c05d4..97fd51998 100644 --- a/cockatrice/src/game/player/player_target.cpp +++ b/cockatrice/src/game/player/player_target.cpp @@ -9,8 +9,8 @@ #include #include -PlayerCounter::PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent) - : AbstractCounter(_player, _id, _name, false, _value, false, parent) +PlayerCounter::PlayerCounter(CounterState *state, PlayerLogic *player, QGraphicsItem *parent) + : AbstractCounter(state, player, false, false, parent) { } @@ -150,18 +150,16 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o } } -AbstractCounter *PlayerTarget::addCounter(int _counterId, const QString &_name, int _value) +AbstractCounter *PlayerTarget::addCounter(CounterState *state) { if (playerCounter) { disconnect(playerCounter, nullptr, this, nullptr); playerCounter->delCounter(); } - - playerCounter = new PlayerCounter(owner, _counterId, _name, _value, this); + playerCounter = new PlayerCounter(state, owner, this); playerCounter->setPos(boundingRect().width() - playerCounter->boundingRect().width(), boundingRect().height() - playerCounter->boundingRect().height()); connect(playerCounter, &PlayerCounter::destroyed, this, &PlayerTarget::counterDeleted); - return playerCounter; } diff --git a/cockatrice/src/game/player/player_target.h b/cockatrice/src/game/player/player_target.h index 3dbc82336..0dd494ce3 100644 --- a/cockatrice/src/game/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -19,7 +19,7 @@ class PlayerCounter : public AbstractCounter { Q_OBJECT public: - PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent = nullptr); + PlayerCounter(CounterState *state, PlayerLogic *player, QGraphicsItem *parent); QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; }; @@ -48,7 +48,7 @@ public: QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - AbstractCounter *addCounter(int _counterId, const QString &_name, int _value); + AbstractCounter *addCounter(CounterState *state); }; #endif diff --git a/libcockatrice_utility/libcockatrice/utility/color.h b/libcockatrice_utility/libcockatrice/utility/color.h index 31bcb3734..6afe984bd 100644 --- a/libcockatrice_utility/libcockatrice/utility/color.h +++ b/libcockatrice_utility/libcockatrice/utility/color.h @@ -22,6 +22,7 @@ inline color convertQColorToColor(const QColor &c) return result; } +#include #include namespace GameSpecificColors