[Game][Counters] Split counters into AbstractCounter (graphics) and CounterState (logic) (#6917)

* [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 <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-05-21 20:16:28 +02:00 committed by GitHub
parent 0549892092
commit bddf9bd818
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 273 additions and 199 deletions

View file

@ -66,6 +66,7 @@ set(cockatrice_SOURCES
src/game/board/card_list.cpp src/game/board/card_list.cpp
src/game/board/card_state.cpp src/game/board/card_state.cpp
src/game/board/counter_general.cpp src/game/board/counter_general.cpp
src/game/board/counter_state.cpp
src/game/board/translate_counter_name.cpp src/game/board/translate_counter_name.cpp
src/game/deckview/deck_view.cpp src/game/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp src/game/deckview/deck_view_container.cpp

View file

@ -9,6 +9,7 @@
#include <QAction> #include <QAction>
#include <QApplication> #include <QApplication>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMenu> #include <QMenu>
#include <QString> #include <QString>
@ -16,24 +17,24 @@
#include <libcockatrice/protocol/pb/command_set_counter.pb.h> #include <libcockatrice/protocol/pb/command_set_counter.pb.h>
#include <libcockatrice/utility/expression.h> #include <libcockatrice/utility/expression.h>
AbstractCounter::AbstractCounter(PlayerLogic *_player, AbstractCounter::AbstractCounter(CounterState *state,
int _id, PlayerLogic *_player,
const QString &_name,
bool _shownInCounterArea, bool _shownInCounterArea,
int _value,
bool _useNameForShortcut, bool _useNameForShortcut,
QGraphicsItem *parent) QGraphicsItem *parent)
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), : QGraphicsItem(parent), player(_player), id(state->getId()), name(state->getName()), value(state->getValue()),
useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false), color(state->getColor()), radius(state->getRadius()), useNameForShortcut(_useNameForShortcut),
deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea) shownInCounterArea(_shownInCounterArea)
{ {
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
shortcutActive = false; connect(state, &CounterState::valueChanged, this, [this](int, int newValue) {
value = newValue;
update();
});
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getPlayerInfo()->getLocalOrJudge()) {
QString displayName = TranslateCounterName::getDisplayName(_name); menu = new TearOffMenu(TranslateCounterName::getDisplayName(state->getName()));
menu = new TearOffMenu(displayName);
aSet = new QAction(this); aSet = new QAction(this);
connect(aSet, &QAction::triggered, this, &AbstractCounter::setCounter); connect(aSet, &QAction::triggered, this, &AbstractCounter::setCounter);
menu->addAction(aSet); menu->addAction(aSet);
@ -41,17 +42,18 @@ AbstractCounter::AbstractCounter(PlayerLogic *_player,
for (int i = 10; i >= -10; --i) { for (int i = 10; i >= -10; --i) {
if (i == 0) { if (i == 0) {
menu->addSeparator(); menu->addSeparator();
} else { continue;
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);
} }
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 { } else {
menu = nullptr; menu = nullptr;
@ -79,31 +81,26 @@ void AbstractCounter::delCounter()
void AbstractCounter::retranslateUi() void AbstractCounter::retranslateUi()
{ {
if (menu) { if (aSet) {
aSet->setText(tr("&Set counter...")); aSet->setText(tr("&Set counter..."));
} }
} }
void AbstractCounter::setShortcutsActive() void AbstractCounter::setShortcutsActive()
{ {
if (!menu) { if (!menu || !player->getPlayerInfo()->getLocal()) {
return; return;
} }
if (!player->getPlayerInfo()->getLocal()) { ShortcutsSettings &sc = SettingsCache::instance().shortcuts();
return; shortcutActive = true;
}
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
if (name == "life") { if (name == "life") {
shortcutActive = true; aSet->setShortcuts(sc.getShortcut("Player/aSet"));
aSet->setShortcuts(shortcuts.getShortcut("Player/aSet")); aDec->setShortcuts(sc.getShortcut("Player/aDec"));
aDec->setShortcuts(shortcuts.getShortcut("Player/aDec")); aInc->setShortcuts(sc.getShortcut("Player/aInc"));
aInc->setShortcuts(shortcuts.getShortcut("Player/aInc"));
} else if (useNameForShortcut) { } else if (useNameForShortcut) {
shortcutActive = true; aSet->setShortcuts(sc.getShortcut("Player/aSetCounter_" + name));
aSet->setShortcuts(shortcuts.getShortcut("Player/aSetCounter_" + name)); aDec->setShortcuts(sc.getShortcut("Player/aDecCounter_" + name));
aDec->setShortcuts(shortcuts.getShortcut("Player/aDecCounter_" + name)); aInc->setShortcuts(sc.getShortcut("Player/aIncCounter_" + name));
aInc->setShortcuts(shortcuts.getShortcut("Player/aIncCounter_" + name));
} }
} }
@ -128,45 +125,32 @@ void AbstractCounter::refreshShortcuts()
} }
} }
void AbstractCounter::setValue(int _value)
{
value = _value;
update();
}
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (isUnderMouse() && player->getPlayerInfo()->getLocalOrJudge()) { if (!isUnderMouse() || !player->getPlayerInfo()->getLocalOrJudge()) {
if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) { event->ignore();
if (menu) { return;
menu->exec(event->screenPos()); }
}
event->accept(); if (event->button() == Qt::MiddleButton || QApplication::keyboardModifiers() & Qt::ShiftModifier) {
} else if (event->button() == Qt::LeftButton) { if (menu) {
Command_IncCounter cmd; menu->exec(event->screenPos());
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();
} }
} else { } 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; hovered = true;
update(); update();
} }
void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{ {
hovered = false; hovered = false;
update(); update();
@ -174,35 +158,36 @@ void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
void AbstractCounter::incrementCounter() void AbstractCounter::incrementCounter()
{ {
const int delta = static_cast<QAction *>(sender())->data().toInt();
Command_IncCounter cmd; Command_IncCounter cmd;
cmd.set_counter_id(id); cmd.set_counter_id(id);
cmd.set_delta(delta); cmd.set_delta(static_cast<QAction *>(sender())->data().toInt());
player->getPlayerActions()->sendGameCommand(cmd); player->getPlayerActions()->sendGameCommand(cmd);
} }
void AbstractCounter::setCounter() void AbstractCounter::setCounter()
{ {
QWidget *parent = nullptr;
if (auto *view = scene() ? scene()->views().value(0) : nullptr) {
parent = view->window();
}
dialogSemaphore = true; dialogSemaphore = true;
AbstractCounterDialog dialog(name, QString::number(value), player->getGame()->getTab()); AbstractCounterDialog dlg(name, QString::number(value), parent);
const int ok = dialog.exec(); const int ok = dlg.exec();
dialogSemaphore = false;
if (deleteAfterDialog) { if (deleteAfterDialog) {
deleteLater(); deleteLater();
return; return;
} }
dialogSemaphore = false;
if (!ok) { if (!ok) {
return; return;
} }
Expression exp(value); Expression exp(value);
int newValue = static_cast<int>(exp.parse(dialog.textValue()));
Command_SetCounter cmd; Command_SetCounter cmd;
cmd.set_counter_id(id); cmd.set_counter_id(id);
cmd.set_value(newValue); cmd.set_value(static_cast<int>(exp.parse(dlg.textValue())));
player->getPlayerActions()->sendGameCommand(cmd); player->getPlayerActions()->sendGameCommand(cmd);
} }

View file

@ -9,6 +9,7 @@
#include "../../interface/widgets/menus/tearoff_menu.h" #include "../../interface/widgets/menus/tearoff_menu.h"
#include "../player/menu/abstract_player_component.h" #include "../player/menu/abstract_player_component.h"
#include "counter_state.h"
#include <QGraphicsItem> #include <QGraphicsItem>
#include <QInputDialog> #include <QInputDialog>
@ -29,18 +30,22 @@ protected:
int id; int id;
QString name; QString name;
int value; int value;
bool useNameForShortcut, hovered; QColor color;
int radius;
bool hovered = false;
bool useNameForShortcut;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private: private:
QAction *aSet, *aDec, *aInc; QAction *aSet = nullptr, *aDec = nullptr, *aInc = nullptr;
TearOffMenu *menu; TearOffMenu *menu = nullptr;
bool dialogSemaphore, deleteAfterDialog; bool dialogSemaphore = false;
bool deleteAfterDialog = false;
bool shownInCounterArea; bool shownInCounterArea;
bool shortcutActive; bool shortcutActive = false;
private slots: private slots:
void refreshShortcuts(); void refreshShortcuts();
@ -48,17 +53,14 @@ private slots:
void setCounter(); void setCounter();
public: public:
AbstractCounter(PlayerLogic *_player, AbstractCounter(CounterState *state,
int _id, PlayerLogic *player,
const QString &_name, bool shownInCounterArea,
bool _shownInCounterArea, bool useNameForShortcut = false,
int _value,
bool _useNameForShortcut = false,
QGraphicsItem *parent = nullptr); QGraphicsItem *parent = nullptr);
~AbstractCounter() override; ~AbstractCounter() override;
void retranslateUi() override; void retranslateUi() override;
void setValue(int _value);
void setShortcutsActive() override; void setShortcutsActive() override;
void setShortcutsInactive() override; void setShortcutsInactive() override;
void delCounter(); void delCounter();
@ -67,7 +69,6 @@ public:
{ {
return menu; return menu;
} }
int getId() const int getId() const
{ {
return id; return id;
@ -76,14 +77,22 @@ public:
{ {
return name; return name;
} }
bool getShownInCounterArea() const QColor getColor() const
{ {
return shownInCounterArea; return color;
}
int getRadius() const
{
return radius;
} }
int getValue() const int getValue() const
{ {
return value; return value;
} }
bool getShownInCounterArea() const
{
return shownInCounterArea;
}
}; };
class AbstractCounterDialog : public QInputDialog class AbstractCounterDialog : public QInputDialog

View file

@ -5,15 +5,8 @@
#include <QPainter> #include <QPainter>
GeneralCounter::GeneralCounter(PlayerLogic *_player, GeneralCounter::GeneralCounter(CounterState *state, PlayerLogic *player, bool useNameForShortcut, QGraphicsItem *parent)
int _id, : AbstractCounter(state, player, true, useNameForShortcut, parent)
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)
{ {
setCacheMode(DeviceCoordinateCache); setCacheMode(DeviceCoordinateCache);
} }

View file

@ -12,17 +12,10 @@
class GeneralCounter : public AbstractCounter class GeneralCounter : public AbstractCounter
{ {
Q_OBJECT Q_OBJECT
private:
QColor color;
int radius;
public: public:
GeneralCounter(PlayerLogic *_player, GeneralCounter(CounterState *state,
int _id, PlayerLogic *player,
const QString &_name,
const QColor &_color,
int _radius,
int _value,
bool useNameForShortcut = false, bool useNameForShortcut = false,
QGraphicsItem *parent = nullptr); QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override; QRectF boundingRect() const override;

View file

@ -0,0 +1,24 @@
#include "counter_state.h"
#include <libcockatrice/utility/color.h>
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);
}

View file

@ -0,0 +1,51 @@
#ifndef COCKATRICE_COUNTER_STATE_H
#define COCKATRICE_COUNTER_STATE_H
#include <QColor>
#include <QObject>
#include <QString>
#include <libcockatrice/protocol/pb/serverinfo_counter.pb.h>
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

View file

@ -97,10 +97,7 @@ void PlayerMenu::retranslateUi()
countersMenu->setTitle(tr("&Counters")); countersMenu->setTitle(tr("&Counters"));
} }
QMapIterator<int, AbstractCounter *> counterIterator(player->getCounters()); emit retranslateRequested();
while (counterIterator.hasNext()) {
counterIterator.next().value()->retranslateUi();
}
} }
void PlayerMenu::refreshShortcuts() void PlayerMenu::refreshShortcuts()
@ -120,30 +117,17 @@ void PlayerMenu::refreshShortcuts()
void PlayerMenu::setShortcutsActive() void PlayerMenu::setShortcutsActive()
{ {
shortcutsActive = true; shortcutsActive = true;
for (auto *c : managedComponents) {
for (auto *component : managedComponents) { c->setShortcutsActive();
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<int, AbstractCounter *> counterIterator(player->getCounters());
while (counterIterator.hasNext()) {
counterIterator.next().value()->setShortcutsActive();
} }
emit shortcutsActivated();
} }
void PlayerMenu::setShortcutsInactive() void PlayerMenu::setShortcutsInactive()
{ {
shortcutsActive = false; shortcutsActive = false;
for (auto *c : managedComponents) {
for (auto *component : managedComponents) { c->setShortcutsInactive();
component->setShortcutsInactive();
}
QMapIterator<int, AbstractCounter *> counterIterator(player->getCounters());
while (counterIterator.hasNext()) {
counterIterator.next().value()->setShortcutsInactive();
} }
emit shortcutsDeactivated();
} }

View file

@ -29,6 +29,9 @@ class PlayerMenu : public QObject
signals: signals:
void cardMenuUpdated(QMenu *cardMenu); void cardMenuUpdated(QMenu *cardMenu);
void shortcutsActivated();
void shortcutsDeactivated();
void retranslateRequested();
public slots: public slots:
void setMenusForGraphicItems(); void setMenusForGraphicItems();

View file

@ -246,7 +246,7 @@ void PlayerEventHandler::eventCreateCounter(const Event_CreateCounter &event)
void PlayerEventHandler::eventSetCounter(const Event_SetCounter &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) { if (!ctr) {
return; return;
} }

View file

@ -6,6 +6,7 @@
#include "../../game_graphics/zones/table_zone.h" #include "../../game_graphics/zones/table_zone.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../board/abstract_card_item.h" #include "../board/abstract_card_item.h"
#include "../board/counter_general.h"
#include "../hand_counter.h" #include "../hand_counter.h"
PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) 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::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::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); playerArea = new PlayerArea(this);
playerTarget = new PlayerTarget(player, playerArea); playerTarget = new PlayerTarget(player, playerArea);
@ -43,11 +63,6 @@ void PlayerGraphicsItem::retranslateUi()
while (zoneIterator.hasNext()) { while (zoneIterator.hasNext()) {
emit zoneIterator.next().value()->retranslateUi(); emit zoneIterator.next().value()->retranslateUi();
} }
QMapIterator<int, AbstractCounter *> counterIterator(player->getCounters());
while (counterIterator.hasNext()) {
counterIterator.next().value()->retranslateUi();
}
} }
void PlayerGraphicsItem::onPlayerActiveChanged(bool _active) 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() void PlayerGraphicsItem::rearrangeCounters()
{ {
qreal marginTop = 80; qreal ySize = boundingRect().y() + 80;
const qreal padding = 5; constexpr qreal padding = 5;
qreal ySize = boundingRect().y() + marginTop; for (auto *ctr : counterWidgets.values()) {
// Place objects
for (const auto &counter : player->getCounters()) {
AbstractCounter *ctr = counter;
if (!ctr->getShownInCounterArea()) { if (!ctr->getShownInCounterArea()) {
continue; continue;
} }
QRectF br = ctr->boundingRect(); QRectF br = ctr->boundingRect();
ctr->setPos((counterAreaWidth - br.width()) / 2, ySize); ctr->setPos((counterAreaWidth - br.width()) / 2, ySize);
ySize += br.height() + padding; ySize += br.height() + padding;

View file

@ -6,6 +6,7 @@
#ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H
#define COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H
#include "../board/abstract_counter.h"
#include "../game_scene.h" #include "../game_scene.h"
#include "player_logic.h" #include "player_logic.h"
@ -102,6 +103,9 @@ public:
public slots: public slots:
void onPlayerActiveChanged(bool _active); void onPlayerActiveChanged(bool _active);
void onCounterAdded(CounterState *state);
void onCounterRemoved(int counterId);
void rearrangeCounters();
void retranslateUi(); void retranslateUi();
signals: signals:
@ -112,6 +116,7 @@ private:
PlayerLogic *player; PlayerLogic *player;
PlayerArea *playerArea; PlayerArea *playerArea;
PlayerTarget *playerTarget; PlayerTarget *playerTarget;
QMap<int, AbstractCounter *> counterWidgets;
PileZone *deckZoneGraphicsItem; PileZone *deckZoneGraphicsItem;
PileZone *sideboardGraphicsItem; PileZone *sideboardGraphicsItem;
PileZone *graveyardZoneGraphicsItem; PileZone *graveyardZoneGraphicsItem;
@ -126,7 +131,6 @@ private:
private slots: private slots:
void updateBoundingRect(); void updateBoundingRect();
void rearrangeZones(); void rearrangeZones();
void rearrangeCounters();
}; };
#endif // COCKATRICE_PLAYER_GRAPHICS_ITEM_H #endif // COCKATRICE_PLAYER_GRAPHICS_ITEM_H

View file

@ -258,57 +258,52 @@ void PlayerLogic::setDeck(const DeckList &_deck)
emit deckChanged(); emit deckChanged();
} }
AbstractCounter *PlayerLogic::addCounter(const ServerInfo_Counter &counter) CounterState *PlayerLogic::addCounter(const ServerInfo_Counter &counter)
{ {
return addCounter(counter.id(), QString::fromStdString(counter.name()), return addCounter(counter.id(), QString::fromStdString(counter.name()),
convertColorToQColor(counter.counter_color()), counter.radius(), counter.count()); 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; return nullptr;
} }
auto *state = new CounterState(id, name, color, radius, value, this);
AbstractCounter *ctr; counters.insert(id, state);
if (name == "life") { emit counterAdded(state);
ctr = getGraphicsItem()->getPlayerTarget()->addCounter(counterId, name, value); return state;
} 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;
} }
void PlayerLogic::delCounter(int counterId) void PlayerLogic::delCounter(int id)
{ {
AbstractCounter *ctr = counters.value(counterId, 0); auto *state = counters.take(id);
if (!ctr) { if (!state) {
return; return;
} }
emit counterRemoved(id);
ctr->delCounter(); state->deleteLater();
counters.remove(counterId);
emit rearrangeCounters();
} }
void PlayerLogic::clearCounters() void PlayerLogic::clearCounters()
{ {
QMapIterator<int, AbstractCounter *> counterIterator(counters); for (int id : counters.keys()) {
while (counterIterator.hasNext()) { emit counterRemoved(id);
counterIterator.next().value()->delCounter();
} }
qDeleteAll(counters);
counters.clear(); counters.clear();
} }
CounterState *PlayerLogic::getLifeCounter() const
{
for (auto *s : counters.values()) {
if (s->getName() == "life") {
return s;
}
}
return nullptr;
}
void PlayerLogic::incrementAllCardCounters() void PlayerLogic::incrementAllCardCounters()
{ {
auto cardsToUpdate = getGameScene()->selectedCards(); 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) ArrowItem *PlayerLogic::addArrow(const ServerInfo_Arrow &arrow)
{ {
const QMap<int, PlayerLogic *> &playerList = game->getPlayerManager()->getPlayers(); const QMap<int, PlayerLogic *> &playerList = game->getPlayerManager()->getPlayers();

View file

@ -7,7 +7,6 @@
#ifndef PLAYER_H #ifndef PLAYER_H
#define PLAYER_H #define PLAYER_H
#include "../../game_graphics/board/abstract_graphics_item.h"
#include "../../interface/widgets/menus/tearoff_menu.h" #include "../../interface/widgets/menus/tearoff_menu.h"
#include "../interface/deck_loader/loaded_deck.h" #include "../interface/deck_loader/loaded_deck.h"
#include "../zones/hand_zone_logic.h" #include "../zones/hand_zone_logic.h"
@ -39,7 +38,6 @@ class Message;
} }
} // namespace google } // namespace google
class AbstractCardItem; class AbstractCardItem;
class AbstractCounter;
class AbstractGame; class AbstractGame;
class ArrowItem; class ArrowItem;
class ArrowTarget; class ArrowTarget;
@ -70,6 +68,8 @@ signals:
void openDeckEditor(const LoadedDeck &deck); void openDeckEditor(const LoadedDeck &deck);
void deckChanged(); void deckChanged();
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void counterAdded(CounterState *state);
void counterRemoved(int counterId);
void rearrangeCounters(); void rearrangeCounters();
void activeChanged(bool active); void activeChanged(bool active);
void zoneIdChanged(int zoneId); void zoneIdChanged(int zoneId);
@ -189,13 +189,13 @@ public:
return qobject_cast<HandZoneLogic *>(zones.value(ZoneNames::HAND)); return qobject_cast<HandZoneLogic *>(zones.value(ZoneNames::HAND));
} }
AbstractCounter *addCounter(const ServerInfo_Counter &counter); CounterState *addCounter(const ServerInfo_Counter &counter);
AbstractCounter *addCounter(int counterId, const QString &name, QColor color, int radius, int value); CounterState *addCounter(int id, const QString &name, const QColor &color, int radius, int value);
void delCounter(int counterId); void delCounter(int counterId);
void clearCounters(); void clearCounters();
void incrementAllCardCounters(); void incrementAllCardCounters();
QMap<int, AbstractCounter *> getCounters() QMap<int, CounterState *> getCounters() const
{ {
return counters; return counters;
} }
@ -203,7 +203,7 @@ public:
/** /**
* Gets the counter that represents the life total. * Gets the counter that represents the life total.
*/ */
AbstractCounter *getLifeCounter() const; CounterState *getLifeCounter() const;
ArrowItem *addArrow(const ServerInfo_Arrow &arrow); ArrowItem *addArrow(const ServerInfo_Arrow &arrow);
ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color); ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color);
@ -251,7 +251,7 @@ private:
int zoneId; int zoneId;
QMap<QString, CardZoneLogic *> zones; QMap<QString, CardZoneLogic *> zones;
QMap<int, AbstractCounter *> counters; QMap<int, CounterState *> counters;
QMap<int, ArrowItem *> arrows; QMap<int, ArrowItem *> arrows;
bool dialogSemaphore; bool dialogSemaphore;

View file

@ -9,8 +9,8 @@
#include <QtMath> #include <QtMath>
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h> #include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
PlayerCounter::PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent) PlayerCounter::PlayerCounter(CounterState *state, PlayerLogic *player, QGraphicsItem *parent)
: AbstractCounter(_player, _id, _name, false, _value, false, 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) { if (playerCounter) {
disconnect(playerCounter, nullptr, this, nullptr); disconnect(playerCounter, nullptr, this, nullptr);
playerCounter->delCounter(); playerCounter->delCounter();
} }
playerCounter = new PlayerCounter(state, owner, this);
playerCounter = new PlayerCounter(owner, _counterId, _name, _value, this);
playerCounter->setPos(boundingRect().width() - playerCounter->boundingRect().width(), playerCounter->setPos(boundingRect().width() - playerCounter->boundingRect().width(),
boundingRect().height() - playerCounter->boundingRect().height()); boundingRect().height() - playerCounter->boundingRect().height());
connect(playerCounter, &PlayerCounter::destroyed, this, &PlayerTarget::counterDeleted); connect(playerCounter, &PlayerCounter::destroyed, this, &PlayerTarget::counterDeleted);
return playerCounter; return playerCounter;
} }

View file

@ -19,7 +19,7 @@ class PlayerCounter : public AbstractCounter
{ {
Q_OBJECT Q_OBJECT
public: 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; QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
}; };
@ -48,7 +48,7 @@ public:
QRectF boundingRect() const override; QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 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 #endif

View file

@ -22,6 +22,7 @@ inline color convertQColorToColor(const QColor &c)
return result; return result;
} }
#include <QMap>
#include <QSet> #include <QSet>
namespace GameSpecificColors namespace GameSpecificColors