From 5764c225ef22e916a578b5ada0f07e93d845a5bc Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Sat, 18 Jul 2026 10:32:27 -0500 Subject: [PATCH] save shine effect --- qtfred/src/ui/FredView.cpp | 69 ++++++++++++++++++++++++++++++++++++++ qtfred/src/ui/FredView.h | 3 ++ 2 files changed, 72 insertions(+) diff --git a/qtfred/src/ui/FredView.cpp b/qtfred/src/ui/FredView.cpp index 41062c6b5dc..3080f68a8a7 100644 --- a/qtfred/src/ui/FredView.cpp +++ b/qtfred/src/ui/FredView.cpp @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include @@ -89,6 +92,47 @@ void copyActionSettings(QAction* action, T* target) { action->setChecked(!!(*target)); } +// A translucent overlay that sweeps a soft white gleam left-to-right across +// the status bar as its progress goes 0 -> 1. Used to celebrate a mission save. +class StatusShineOverlay : public QWidget { +public: + explicit StatusShineOverlay(QWidget* parent) : QWidget(parent) { + setAttribute(Qt::WA_TransparentForMouseEvents); + setAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_TranslucentBackground); + } + + void setProgress(qreal p) { + _p = p; + update(); + } + +protected: + void paintEvent(QPaintEvent*) override { + if (_p <= 0.0 || _p >= 1.0 || width() <= 0) + return; + + const qreal w = width(); + const qreal bandW = w * 0.5; // width of the gleam + const qreal half = bandW / 2.0; + // The band center travels from fully off the left edge to fully off the + // right, so the gleam completely leaves the bar before the overlay vanishes. + const qreal center = -half + _p * (w + bandW); + + QLinearGradient grad(center - half, 0.0, center + half, 0.0); + + grad.setColorAt(0.0, QColor(255, 255, 255, 0)); + grad.setColorAt(0.5, QColor(255, 255, 255, 170)); + grad.setColorAt(1.0, QColor(255, 255, 255, 0)); + + QPainter painter(this); + painter.fillRect(rect(), grad); + } + +private: + qreal _p = 0.0; +}; + } namespace fso { @@ -930,11 +974,36 @@ void FredView::setLastSaved(const QDateTime& when) { if (when.isValid()) { _statusBarLastSaved->setText(tr("Last Saved: %1").arg(when.toString(QStringLiteral("MMM d, yyyy h:mm:ss AP")))); + triggerSaveShine(); } else { _statusBarLastSaved->setText(tr("Last Saved: Never")); } } +void FredView::triggerSaveShine() { + auto* bar = statusBar(); + if (!bar) + return; + + auto* overlay = new StatusShineOverlay(bar); + overlay->setGeometry(bar->rect()); + overlay->show(); + overlay->raise(); + + auto* anim = new QVariantAnimation(overlay); + anim->setStartValue(0.0); + anim->setEndValue(1.0); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::InOutSine); + connect(anim, &QVariantAnimation::valueChanged, overlay, [overlay](const QVariant& v) { + overlay->setProgress(v.toReal()); + }); + connect(anim, &QVariantAnimation::finished, overlay, [overlay]() { + overlay->deleteLater(); + }); + anim->start(QAbstractAnimation::DeleteWhenStopped); +} + // --------------------------------------------------------------------------- // Context toolbar (top, below the primary toolbar) // --------------------------------------------------------------------------- diff --git a/qtfred/src/ui/FredView.h b/qtfred/src/ui/FredView.h index 31e09e7665f..ad561a69ea9 100644 --- a/qtfred/src/ui/FredView.h +++ b/qtfred/src/ui/FredView.h @@ -255,6 +255,9 @@ class FredView: public QMainWindow, public IDialogProvider { // Updates the "Last Saved" status bar label: pass an empty time to show "Never". void setLastSaved(const QDateTime& when); + // Sweeps a brief white gleam across the status bar to celebrate a save. + void triggerSaveShine(); + SceneBrowserPanel* _browserPanel = nullptr; QMenu* _viewPopup = nullptr;