Add fade out effect to the loading screen

This commit is contained in:
James Rowe 2019-01-21 09:20:16 -07:00
parent 3740adb6f5
commit 3ca0af8bb3
4 changed files with 158 additions and 94 deletions

View file

@ -5,6 +5,7 @@
#include <unordered_map> #include <unordered_map>
#include <QBuffer> #include <QBuffer>
#include <QByteArray> #include <QByteArray>
#include <QGraphicsOpacityEffect>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QIODevice> #include <QIODevice>
#include <QImage> #include <QImage>
@ -13,6 +14,7 @@
#include <QPalette> #include <QPalette>
#include <QPixmap> #include <QPixmap>
#include <QProgressBar> #include <QProgressBar>
#include <QPropertyAnimation>
#include <QStyleOption> #include <QStyleOption>
#include <QTime> #include <QTime>
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
@ -71,6 +73,25 @@ LoadingScreen::LoadingScreen(QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
setMinimumSize(1280, 720); setMinimumSize(1280, 720);
// Create a fade out effect to hide this loading screen widget.
// When fading opacity, it will fade to the parent widgets background color, which is why we
// create an internal widget named fade_widget that we use the effect on, while keeping the
// loading screen widget's background color black. This way we can create a fade to black effect
opacity_effect = new QGraphicsOpacityEffect(this);
opacity_effect->setOpacity(1);
ui->fade_parent->setGraphicsEffect(opacity_effect);
fadeout_animation = std::make_unique<QPropertyAnimation>(opacity_effect, "opacity");
fadeout_animation->setDuration(500);
fadeout_animation->setStartValue(1);
fadeout_animation->setEndValue(0);
fadeout_animation->setEasingCurve(QEasingCurve::OutBack);
// After the fade completes, hide the widget and reset the opacity
connect(fadeout_animation.get(), &QPropertyAnimation::finished, [this] {
hide();
opacity_effect->setOpacity(1);
emit Hidden();
});
connect(this, &LoadingScreen::LoadProgress, this, &LoadingScreen::OnLoadProgress, connect(this, &LoadingScreen::LoadProgress, this, &LoadingScreen::OnLoadProgress,
Qt::QueuedConnection); Qt::QueuedConnection);
qRegisterMetaType<VideoCore::LoadCallbackStage>(); qRegisterMetaType<VideoCore::LoadCallbackStage>();
@ -115,9 +136,14 @@ void LoadingScreen::Prepare(Loader::AppLoader& loader) {
ui->logo->setPixmap(map); ui->logo->setPixmap(map);
} }
slow_shader_compile_start = false;
OnLoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); OnLoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
} }
void LoadingScreen::OnLoadComplete() {
fadeout_animation->start(QPropertyAnimation::KeepWhenStopped);
}
void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value,
std::size_t total) { std::size_t total) {
using namespace std::chrono; using namespace std::chrono;
@ -125,6 +151,7 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size
// reset the timer if the stage changes // reset the timer if the stage changes
if (stage != previous_stage) { if (stage != previous_stage) {
ui->progress_bar->setStyleSheet(progressbar_style[stage]); ui->progress_bar->setStyleSheet(progressbar_style[stage]);
// Hide the progress bar during the prepare stage
if (stage == VideoCore::LoadCallbackStage::Prepare) { if (stage == VideoCore::LoadCallbackStage::Prepare) {
ui->progress_bar->hide(); ui->progress_bar->hide();
} else { } else {

View file

@ -27,7 +27,9 @@ enum class LoadCallbackStage;
class QBuffer; class QBuffer;
class QByteArray; class QByteArray;
class QGraphicsOpacityEffect;
class QMovie; class QMovie;
class QPropertyAnimation;
class LoadingScreen : public QWidget { class LoadingScreen : public QWidget {
Q_OBJECT Q_OBJECT
@ -45,14 +47,21 @@ public:
/// used resources such as the logo and banner. /// used resources such as the logo and banner.
void Clear(); void Clear();
/// Slot used to update the status of the progress bar
void OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total); void OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
/// Hides the LoadingScreen with a fade out effect
void OnLoadComplete();
// In order to use a custom widget with a stylesheet, you need to override the paintEvent // In order to use a custom widget with a stylesheet, you need to override the paintEvent
// See https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget // See https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
signals: signals:
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total); void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
/// Signals that this widget is completely hidden now and should be replaced with the other
/// widget
void Hidden();
private: private:
#ifndef YUZU_QT_MOVIE_MISSING #ifndef YUZU_QT_MOVIE_MISSING
@ -64,6 +73,9 @@ private:
std::size_t previous_total = 0; std::size_t previous_total = 0;
VideoCore::LoadCallbackStage previous_stage; VideoCore::LoadCallbackStage previous_stage;
QGraphicsOpacityEffect* opacity_effect = nullptr;
std::unique_ptr<QPropertyAnimation> fadeout_animation = nullptr;
// Definitions for the differences in text and styling for each stage // Definitions for the differences in text and styling for each stage
std::unordered_map<VideoCore::LoadCallbackStage, const char*> progressbar_style; std::unordered_map<VideoCore::LoadCallbackStage, const char*> progressbar_style;
std::unordered_map<VideoCore::LoadCallbackStage, QString> stage_translations; std::unordered_map<VideoCore::LoadCallbackStage, QString> stage_translations;

View file

@ -30,59 +30,77 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QLabel" name="logo"> <widget class="QWidget" name="fade_parent" native="true">
<property name="text"> <layout class="QVBoxLayout" name="verticalLayout_2">
<string/> <property name="spacing">
</property> <number>0</number>
<property name="alignment"> </property>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <property name="leftMargin">
</property> <number>0</number>
<property name="margin"> </property>
<number>30</number> <property name="topMargin">
</property> <number>0</number>
</widget> </property>
</item> <property name="rightMargin">
<item> <number>0</number>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,1"> </property>
<property name="spacing"> <property name="bottomMargin">
<number>15</number> <number>0</number>
</property> </property>
<property name="sizeConstraint"> <item alignment="Qt::AlignLeft|Qt::AlignTop">
<enum>QLayout::SetNoConstraint</enum> <widget class="QLabel" name="logo">
</property> <property name="text">
<item alignment="Qt::AlignHCenter|Qt::AlignBottom"> <string/>
<widget class="QLabel" name="stage"> </property>
<property name="sizePolicy"> <property name="alignment">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<horstretch>0</horstretch> </property>
<verstretch>0</verstretch> <property name="margin">
</sizepolicy> <number>30</number>
</property> </property>
<property name="styleSheet"> </widget>
<string notr="true">background-color: black; color: white; </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,1">
<property name="spacing">
<number>15</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<item alignment="Qt::AlignHCenter|Qt::AlignBottom">
<widget class="QLabel" name="stage">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">background-color: black; color: white;
font: 75 20pt &quot;Arial&quot;;</string> font: 75 20pt &quot;Arial&quot;;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Loading Shaders 387 / 1628</string> <string>Loading Shaders 387 / 1628</string>
</property> </property>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignHCenter|Qt::AlignTop"> <item alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QProgressBar" name="progress_bar"> <widget class="QProgressBar" name="progress_bar">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>500</width> <width>500</width>
<height>40</height> <height>40</height>
</size> </size>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QProgressBar { <string notr="true">QProgressBar {
color: white; color: white;
border: 2px solid white; border: 2px solid white;
outline-color: black; outline-color: black;
@ -92,45 +110,48 @@ QProgressBar::chunk {
background-color: white; background-color: white;
border-radius: 15px; border-radius: 15px;
}</string> }</string>
</property> </property>
<property name="value"> <property name="value">
<number>50</number> <number>50</number>
</property> </property>
<property name="textVisible"> <property name="textVisible">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="format"> <property name="format">
<string>Loading Shaders %v out of %m</string> <string>Loading Shaders %v out of %m</string>
</property> </property>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignHCenter|Qt::AlignTop"> <item alignment="Qt::AlignHCenter|Qt::AlignTop">
<widget class="QLabel" name="value"> <widget class="QLabel" name="value">
<property name="toolTip"> <property name="toolTip">
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">background-color: black; color: white; <string notr="true">background-color: black; color: white;
font: 75 15pt &quot;Arial&quot;;</string> font: 75 15pt &quot;Arial&quot;;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Stage 1 of 2. Estimate Time 5m 4s</string> <string>Stage 1 of 2. Estimate Time 5m 4s</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item alignment="Qt::AlignRight|Qt::AlignBottom"> <item alignment="Qt::AlignRight|Qt::AlignBottom">
<widget class="QLabel" name="banner"> <widget class="QLabel" name="banner">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">background-color: black;</string> <string notr="true">background-color: black;</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="margin"> <property name="margin">
<number>30</number> <number>30</number>
</property> </property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>

View file

@ -415,6 +415,13 @@ void GMainWindow::InitializeWidgets() {
loading_screen = new LoadingScreen(this); loading_screen = new LoadingScreen(this);
loading_screen->hide(); loading_screen->hide();
ui.horizontalLayout->addWidget(loading_screen); ui.horizontalLayout->addWidget(loading_screen);
connect(loading_screen, &LoadingScreen::Hidden, [&] {
loading_screen->Clear();
if (emulation_running) {
render_window->show();
render_window->setFocus();
}
});
// Create status bar // Create status bar
message_label = new QLabel(); message_label = new QLabel();
@ -1513,10 +1520,7 @@ void GMainWindow::OnStopGame() {
} }
void GMainWindow::OnLoadComplete() { void GMainWindow::OnLoadComplete() {
loading_screen->hide(); loading_screen->OnLoadComplete();
loading_screen->Clear();
render_window->show();
render_window->setFocus();
} }
void GMainWindow::OnMenuReportCompatibility() { void GMainWindow::OnMenuReportCompatibility() {