Add paused-state vignette border to game world view
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPen>
|
||||
#include <QPolygonF>
|
||||
#include <QRadialGradient>
|
||||
@@ -431,6 +432,7 @@ void GameWorldView::paintGL()
|
||||
drawBeams(painter);
|
||||
drawOverlays(painter);
|
||||
drawScreenSpace(painter);
|
||||
drawPauseBorder(painter);
|
||||
drawReplayOverlay(painter);
|
||||
}
|
||||
|
||||
@@ -1695,6 +1697,67 @@ void GameWorldView::drawScreenSpace(QPainter& /*painter*/)
|
||||
{
|
||||
}
|
||||
|
||||
void GameWorldView::drawPauseBorder(QPainter& painter)
|
||||
{
|
||||
if (m_gameSpeedMultiplier > 0.0) { return; }
|
||||
|
||||
// Border thickness in pixels, capped so it never exceeds half the viewport on
|
||||
// very small windows (which would leave no un-darkened center).
|
||||
const qreal borderPx = std::min<qreal>(
|
||||
100.0, std::min(width(), height()) / 2.0);
|
||||
if (borderPx <= 0.0) { return; }
|
||||
|
||||
const QColor edge(0, 0, 0, 128); // 50% black at the viewport edge
|
||||
const QColor inner(0, 0, 0, 0); // fully transparent toward the center
|
||||
|
||||
const qreal w = width();
|
||||
const qreal h = height();
|
||||
|
||||
painter.save();
|
||||
|
||||
// Each side is a linear gradient fading from `edge` at the viewport border to
|
||||
// `inner` toward the center. The four sides are clipped to trapezoids that meet
|
||||
// along the corner diagonals (a mitred picture frame), so the strips never
|
||||
// overlap and don't double-darken the corners. Because the border thickness is
|
||||
// the same on every side, both adjoining gradients evaluate equally along each
|
||||
// 45-degree diagonal and join seamlessly.
|
||||
const std::function<void(const QLinearGradient&, const QPolygonF&)> drawSide =
|
||||
[&](const QLinearGradient& gradient, const QPolygonF& trapezoid) {
|
||||
QPainterPath clip;
|
||||
clip.addPolygon(trapezoid);
|
||||
painter.save();
|
||||
painter.setClipPath(clip);
|
||||
painter.fillRect(QRectF(0, 0, w, h), gradient);
|
||||
painter.restore();
|
||||
};
|
||||
|
||||
QLinearGradient left(0, 0, borderPx, 0);
|
||||
left.setColorAt(0.0, edge);
|
||||
left.setColorAt(1.0, inner);
|
||||
drawSide(left, QPolygonF({ QPointF(0, 0), QPointF(borderPx, borderPx),
|
||||
QPointF(borderPx, h - borderPx), QPointF(0, h) }));
|
||||
|
||||
QLinearGradient right(w, 0, w - borderPx, 0);
|
||||
right.setColorAt(0.0, edge);
|
||||
right.setColorAt(1.0, inner);
|
||||
drawSide(right, QPolygonF({ QPointF(w, 0), QPointF(w - borderPx, borderPx),
|
||||
QPointF(w - borderPx, h - borderPx), QPointF(w, h) }));
|
||||
|
||||
QLinearGradient top(0, 0, 0, borderPx);
|
||||
top.setColorAt(0.0, edge);
|
||||
top.setColorAt(1.0, inner);
|
||||
drawSide(top, QPolygonF({ QPointF(0, 0), QPointF(w, 0),
|
||||
QPointF(w - borderPx, borderPx), QPointF(borderPx, borderPx) }));
|
||||
|
||||
QLinearGradient bottom(0, h, 0, h - borderPx);
|
||||
bottom.setColorAt(0.0, edge);
|
||||
bottom.setColorAt(1.0, inner);
|
||||
drawSide(bottom, QPolygonF({ QPointF(0, h), QPointF(w, h),
|
||||
QPointF(w - borderPx, h - borderPx), QPointF(borderPx, h - borderPx) }));
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
void GameWorldView::drawReplayOverlay(QPainter& painter)
|
||||
{
|
||||
if (!m_replayPlayer) { return; }
|
||||
|
||||
Reference in New Issue
Block a user