servatrice/cockatrice/src/phasestoolbar.cpp
ebbit1q 6981cca2ae
use qt round for better cross platform consistency (#4518)
* use qt round for better cross platform consistency

* remove unnecessary casts
2022-01-08 16:01:15 -05:00

273 lines
8.2 KiB
C++

#include "phasestoolbar.h"
#include "pb/command_draw_cards.pb.h"
#include "pb/command_next_turn.pb.h"
#include "pb/command_set_active_phase.pb.h"
#include "pb/command_set_card_attr.pb.h"
#include "pixmapgenerator.h"
#include <QAction>
#include <QDebug>
#include <QPainter>
#include <QPen>
#include <QTimer>
PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_doubleClickAction, bool _highlightable)
: QObject(), QGraphicsItem(parent), name(_name), active(false), highlightable(_highlightable),
activeAnimationCounter(0), doubleClickAction(_doubleClickAction), width(50)
{
if (highlightable) {
activeAnimationTimer = new QTimer(this);
connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation()));
activeAnimationTimer->setSingleShot(false);
} else
activeAnimationCounter = 9;
setCacheMode(DeviceCoordinateCache);
}
QRectF PhaseButton::boundingRect() const
{
return {0, 0, width, width};
}
void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
QRectF iconRect = boundingRect().adjusted(3, 3, -3, -3);
QRectF translatedIconRect = painter->combinedTransform().mapRect(iconRect);
qreal scaleFactor = translatedIconRect.width() / iconRect.width();
QPixmap iconPixmap = PhasePixmapGenerator::generatePixmap(qRound(translatedIconRect.height()), name);
painter->setBrush(QColor(static_cast<int>(220 * (activeAnimationCounter / 10.0)),
static_cast<int>(220 * (activeAnimationCounter / 10.0)),
static_cast<int>(220 * (activeAnimationCounter / 10.0))));
painter->setPen(Qt::gray);
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
painter->save();
resetPainterTransform(painter);
painter->drawPixmap(iconPixmap.rect().translated(qRound(3 * scaleFactor), qRound(3 * scaleFactor)), iconPixmap,
iconPixmap.rect());
painter->restore();
painter->setBrush(QColor(0, 0, 0, static_cast<int>(255 * ((10 - activeAnimationCounter) / 15.0))));
painter->setPen(Qt::gray);
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
}
void PhaseButton::setWidth(double _width)
{
prepareGeometryChange();
width = _width;
}
void PhaseButton::setActive(bool _active)
{
if ((active == _active) || !highlightable)
return;
active = _active;
activeAnimationTimer->start(25);
}
void PhaseButton::updateAnimation()
{
if (!highlightable)
return;
if (active) {
if (++activeAnimationCounter >= 10)
activeAnimationTimer->stop();
} else {
if (--activeAnimationCounter <= 0)
activeAnimationTimer->stop();
}
update();
}
void PhaseButton::mousePressEvent(QGraphicsSceneMouseEvent * /*event*/)
{
emit clicked();
}
void PhaseButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/)
{
triggerDoubleClickAction();
}
void PhaseButton::triggerDoubleClickAction()
{
if (doubleClickAction)
doubleClickAction->trigger();
}
PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
: QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8)
{
auto *aUntapAll = new QAction(this);
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll()));
auto *aDrawCard = new QAction(this);
connect(aDrawCard, SIGNAL(triggered()), this, SLOT(actDrawCard()));
PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll);
PhaseButton *upkeepButton = new PhaseButton("upkeep", this);
PhaseButton *drawButton = new PhaseButton("draw", this, aDrawCard);
PhaseButton *main1Button = new PhaseButton("main1", this);
PhaseButton *combatStartButton = new PhaseButton("combat_start", this);
PhaseButton *combatAttackersButton = new PhaseButton("combat_attackers", this);
PhaseButton *combatBlockersButton = new PhaseButton("combat_blockers", this);
PhaseButton *combatDamageButton = new PhaseButton("combat_damage", this);
PhaseButton *combatEndButton = new PhaseButton("combat_end", this);
PhaseButton *main2Button = new PhaseButton("main2", this);
PhaseButton *cleanupButton = new PhaseButton("cleanup", this);
buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
for (auto &i : buttonList)
connect(i, SIGNAL(clicked()), this, SLOT(phaseButtonClicked()));
nextTurnButton = new PhaseButton("nextturn", this, nullptr, false);
connect(nextTurnButton, SIGNAL(clicked()), this, SLOT(actNextTurn()));
rearrangeButtons();
retranslateUi();
}
QRectF PhasesToolbar::boundingRect() const
{
return {0, 0, width, height};
}
void PhasesToolbar::retranslateUi()
{
for (int i = 0; i < buttonList.size(); ++i)
buttonList[i]->setToolTip(getLongPhaseName(i));
}
QString PhasesToolbar::getLongPhaseName(int phase) const
{
switch (phase) {
case 0:
return tr("Untap step");
case 1:
return tr("Upkeep step");
case 2:
return tr("Draw step");
case 3:
return tr("First main phase");
case 4:
return tr("Beginning of combat step");
case 5:
return tr("Declare attackers step");
case 6:
return tr("Declare blockers step");
case 7:
return tr("Combat damage step");
case 8:
return tr("End of combat step");
case 9:
return tr("Second main phase");
case 10:
return tr("End of turn step");
default:
return QString();
}
}
void PhasesToolbar::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
painter->fillRect(boundingRect(), QColor(50, 50, 50));
}
const double PhasesToolbar::marginSize = 3;
void PhasesToolbar::rearrangeButtons()
{
for (auto &i : buttonList)
i->setWidth(symbolSize);
nextTurnButton->setWidth(symbolSize);
double y = marginSize;
buttonList[0]->setPos(marginSize, y);
buttonList[1]->setPos(marginSize, y += symbolSize);
buttonList[2]->setPos(marginSize, y += symbolSize);
y += ySpacing;
buttonList[3]->setPos(marginSize, y += symbolSize);
y += ySpacing;
buttonList[4]->setPos(marginSize, y += symbolSize);
buttonList[5]->setPos(marginSize, y += symbolSize);
buttonList[6]->setPos(marginSize, y += symbolSize);
buttonList[7]->setPos(marginSize, y += symbolSize);
buttonList[8]->setPos(marginSize, y += symbolSize);
y += ySpacing;
buttonList[9]->setPos(marginSize, y += symbolSize);
y += ySpacing;
buttonList[10]->setPos(marginSize, y += symbolSize);
y += ySpacing;
y += ySpacing;
nextTurnButton->setPos(marginSize, y + symbolSize);
}
void PhasesToolbar::setHeight(double _height)
{
prepareGeometryChange();
height = _height;
ySpacing = (height - 2 * marginSize) / (buttonCount * 5 + spaceCount);
symbolSize = ySpacing * 5;
width = symbolSize + 2 * marginSize;
rearrangeButtons();
}
void PhasesToolbar::setActivePhase(int phase)
{
if (phase >= buttonList.size())
return;
for (int i = 0; i < buttonList.size(); ++i)
buttonList[i]->setActive(i == phase);
}
void PhasesToolbar::triggerPhaseAction(int phase)
{
if (0 <= phase && phase < buttonList.size()) {
buttonList[phase]->triggerDoubleClickAction();
}
}
void PhasesToolbar::phaseButtonClicked()
{
auto *button = qobject_cast<PhaseButton *>(sender());
if (button->getActive())
button->triggerDoubleClickAction();
Command_SetActivePhase cmd;
cmd.set_phase(static_cast<google::protobuf::uint32>(buttonList.indexOf(button)));
emit sendGameCommand(cmd, -1);
}
void PhasesToolbar::actNextTurn()
{
emit sendGameCommand(Command_NextTurn(), -1);
}
void PhasesToolbar::actUntapAll()
{
Command_SetCardAttr cmd;
cmd.set_zone("table");
cmd.set_attribute(AttrTapped);
cmd.set_attr_value("0");
emit sendGameCommand(cmd, -1);
}
void PhasesToolbar::actDrawCard()
{
Command_DrawCards cmd;
cmd.set_number(1);
emit sendGameCommand(cmd, -1);
}