From d4ad6f42581b83eae7e49317e53b1eac41936516 Mon Sep 17 00:00:00 2001 From: Jon ESA Date: Wed, 1 Apr 2026 22:13:50 +0100 Subject: [PATCH] Panel hit detection but broken available games, thats enough for tonight --- PanelsPanel.cpp | 81 ++++++++++++++++++++++++++++++++++------- PanelsPanel.h | 2 + WebSocketController.cpp | 11 ++++++ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/PanelsPanel.cpp b/PanelsPanel.cpp index 2690d13..ca9c440 100644 --- a/PanelsPanel.cpp +++ b/PanelsPanel.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ void PanelsPanel::setRnpCount(int count) { m_count = count; m_colors.clear(); + m_hits.clear(); m_statusLabel->setText(count > 0 ? QString("%1 panel%2").arg(count).arg(count == 1 ? "" : "s") : "No panels reported"); @@ -36,10 +38,21 @@ void PanelsPanel::setPanelColor(int index, const QColor &color) update(); } +void PanelsPanel::impactPanel(int index, int power) +{ + m_hits[index] = power; + update(); + QTimer::singleShot(3000, this, [this, index]() { + m_hits.remove(index); + update(); + }); +} + void PanelsPanel::reset() { m_count = 0; m_colors.clear(); + m_hits.clear(); m_statusLabel->setText("Connect to load panels..."); update(); } @@ -59,44 +72,84 @@ void PanelsPanel::paintEvent(QPaintEvent *) const double outerR = side / 2.0; const double innerR = outerR * 0.44; - const QRectF outerRect(cx - outerR, cy - outerR, side, side); - const QRectF innerRect(cx - innerR, cy - innerR, innerR * 2, innerR * 2); + const QRectF outerRect(cx - outerR, cy - outerR, side, side); + const QRectF innerRect(cx - innerR, cy - innerR, innerR * 2, innerR * 2); const double gapDeg = (m_count > 1) ? 3.0 : 0.0; const double segSpan = (360.0 - m_count * gapDeg) / m_count; static const QColor kDefault(100, 140, 180); + static const QColor kHit(220, 40, 40); for (int i = 0; i < m_count; ++i) { + const bool isHit = m_hits.contains(i); const double startAngle = 90.0 - i * (segSpan + gapDeg); const double sweep = -segSpan; + // --- Segment path --- QPainterPath path; path.arcMoveTo(outerRect, startAngle); path.arcTo(outerRect, startAngle, sweep); path.arcTo(innerRect, startAngle + sweep, -sweep); path.closeSubpath(); - p.setBrush(m_colors.value(i, kDefault)); - p.setPen(QPen(Qt::white, 2)); + QColor segColor = isHit ? kHit : m_colors.value(i, kDefault); + p.setBrush(segColor); + p.setPen(QPen(Qt::white, isHit ? 3 : 2)); p.drawPath(path); - // Label at segment midpoint + // --- Midpoint for label / hit circle --- const double midAngle = startAngle + sweep / 2.0; const double midAngleRad = qDegreesToRadians(midAngle); const double midR = (outerR + innerR) / 2.0; - const QPointF tc(cx + midR * qCos(midAngleRad), - cy - midR * qSin(midAngleRad)); + const QPointF mid(cx + midR * qCos(midAngleRad), + cy - midR * qSin(midAngleRad)); - QFont font = p.font(); - font.setBold(true); - font.setPointSize(qMax(7, qMin(12, static_cast(outerR / (m_count * 0.55 + 2))))); - p.setFont(font); - p.setPen(Qt::white); - p.drawText(QRectF(tc.x() - 22, tc.y() - 11, 44, 22), Qt::AlignCenter, QString::number(i)); + if (isHit) { + // ---- Red glow halo ring around segment ---- + QPen haloPen(QColor(255, 80, 80, 120), 6); + p.setBrush(Qt::NoBrush); + p.setPen(haloPen); + p.drawPath(path); + + // ---- Red filled circle centred on segment ---- + const double circR = qMin(outerR - innerR, midR * 0.38) * 0.9; + const QRectF circRect(mid.x() - circR, mid.y() - circR, circR * 2, circR * 2); + + // drop shadow + p.setBrush(QColor(0, 0, 0, 60)); + p.setPen(Qt::NoPen); + p.drawEllipse(circRect.adjusted(2, 3, 2, 3)); + + // circle fill: radial gradient (bright centre → dark red) + QRadialGradient grad(mid, circR, QPointF(mid.x() - circR*0.3, mid.y() - circR*0.3)); + grad.setColorAt(0.0, QColor(255, 100, 100)); + grad.setColorAt(1.0, QColor(160, 10, 10)); + p.setBrush(grad); + p.setPen(QPen(QColor(255, 200, 200), 1.5)); + p.drawEllipse(circRect); + + // power value text + QFont pf = p.font(); + pf.setBold(true); + pf.setPointSize(qMax(6, qMin(11, static_cast(circR * 0.72)))); + p.setFont(pf); + p.setPen(Qt::white); + p.drawText(circRect, Qt::AlignCenter, QString::number(m_hits[i])); + + } else { + // ---- Normal index label ---- + QFont font = p.font(); + font.setBold(true); + font.setPointSize(qMax(7, qMin(12, static_cast(outerR / (m_count * 0.55 + 2))))); + p.setFont(font); + p.setPen(Qt::white); + p.drawText(QRectF(mid.x() - 22, mid.y() - 11, 44, 22), + Qt::AlignCenter, QString::number(i)); + } } - // Centre hole: total count + // --- Centre hole: total count --- QFont cf = p.font(); cf.setBold(true); cf.setPointSize(qMax(8, static_cast(innerR * 0.45))); diff --git a/PanelsPanel.h b/PanelsPanel.h index 10034d4..22bdc14 100644 --- a/PanelsPanel.h +++ b/PanelsPanel.h @@ -13,6 +13,7 @@ public: void setRnpCount(int count); void setPanelColor(int index, const QColor &color); + void impactPanel(int index, int power); void reset(); protected: @@ -21,5 +22,6 @@ protected: private: int m_count = 0; QMap m_colors; + QMap m_hits; // panel index → impact power (active for 3 s) QLabel *m_statusLabel = nullptr; }; diff --git a/WebSocketController.cpp b/WebSocketController.cpp index ff107c6..2cebbed 100644 --- a/WebSocketController.cpp +++ b/WebSocketController.cpp @@ -176,6 +176,17 @@ void WebSocketController::handleProtocol(const QString &msg) return; } + // ---- IMP (panel impact) ---- + // Format: IMP + if (cmd == "IMP" && tokens.size() >= 3) { + bool idxOk = false, pwrOk = false; + const int idx = tokens[1].toInt(&idxOk); + const int power = tokens[2].toInt(&pwrOk); + if (idxOk && pwrOk && m_panelsPanel) + m_panelsPanel->impactPanel(idx, power); + return; + } + // ---- GAM listall ---- if (cmd == "GAM" && tokens.size() >= 2 && tokens[1] == "listall") { if (m_gamesPanel) m_gamesPanel->loadAllFromResponse(msg);