make empty layout cells pulse while module is selected
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "ShipLayoutDialog.h"
|
||||
#include "ShipStatsPanel.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include "DisplayName.h"
|
||||
@@ -12,8 +13,10 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QElapsedTimer>
|
||||
#include <QScrollArea>
|
||||
#include <QSignalMapper>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace
|
||||
@@ -21,6 +24,13 @@ namespace
|
||||
|
||||
const int kCellSize = 32;
|
||||
|
||||
// Empty ship tiles pulse between this grey and white at 1 Hz while a module is
|
||||
// selected, to draw the player's attention to where modules can be placed.
|
||||
const double kTwoPi = 6.283185307179586;
|
||||
const int kPulseIntervalMs = 33;
|
||||
const int kEmptyCellGrey = 240;
|
||||
const int kPulseAmplitude = 15;
|
||||
|
||||
std::vector<std::string> rotateMaskCW(const std::vector<std::string>& grid)
|
||||
{
|
||||
if (grid.empty())
|
||||
@@ -68,6 +78,10 @@ public:
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
m_pulseClock.start();
|
||||
m_pulseTimer = new QTimer(this);
|
||||
m_pulseTimer->setInterval(kPulseIntervalMs);
|
||||
connect(m_pulseTimer, &QTimer::timeout, this, [this]() { update(); });
|
||||
}
|
||||
|
||||
void setGridData(const std::vector<std::vector<ShipLayoutDialog::CellInfo>>* grid,
|
||||
@@ -87,6 +101,19 @@ public:
|
||||
{
|
||||
m_ghostModuleIdx = moduleIndex;
|
||||
m_ghostRotation = rotation;
|
||||
// Only animate the empty-tile pulse while a module is selected.
|
||||
if (moduleIndex.has_value())
|
||||
{
|
||||
if (!m_pulseTimer->isActive())
|
||||
{
|
||||
m_pulseClock.restart();
|
||||
m_pulseTimer->start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pulseTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -100,6 +127,19 @@ protected:
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
// While a module is selected, pulse empty tiles at 1 Hz around the base
|
||||
// grey (kEmptyCellGrey +/- kPulseAmplitude). All empty tiles share the
|
||||
// same phase, so compute it once.
|
||||
QColor emptyCellColor(kEmptyCellGrey, kEmptyCellGrey, kEmptyCellGrey);
|
||||
if (m_ghostModuleIdx.has_value())
|
||||
{
|
||||
const double seconds = m_pulseClock.elapsed() / 1000.0;
|
||||
const double oscillation = std::sin(seconds * kTwoPi);
|
||||
const int channel = kEmptyCellGrey
|
||||
+ static_cast<int>(std::lround(oscillation * kPulseAmplitude));
|
||||
emptyCellColor = QColor(channel, channel, channel);
|
||||
}
|
||||
|
||||
for (int r = 0; r < m_rows; ++r)
|
||||
{
|
||||
for (int c = 0; c < m_cols; ++c)
|
||||
@@ -131,7 +171,7 @@ protected:
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(cellRect, QColor(240, 240, 240));
|
||||
painter.fillRect(cellRect, emptyCellColor);
|
||||
}
|
||||
|
||||
painter.setPen(QColor(100, 100, 100));
|
||||
@@ -241,6 +281,8 @@ private:
|
||||
std::optional<int> m_ghostModuleIdx;
|
||||
Rotation m_ghostRotation = Rotation::East;
|
||||
QPoint m_hoverCell = QPoint(-1, -1);
|
||||
QTimer* m_pulseTimer = nullptr;
|
||||
QElapsedTimer m_pulseClock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user