QT Frontend: Add a Loading screen with progressbar
With shader caches on the horizon, one requirement is to provide visible feedback for the progress. The shader cache reportedly takes several minutes to load for large caches that were invalidated, and as such we should provide a loading screen with progress. Adds a loading screen widget that will be shown until the first frame of the game is swapped. This was chosen in case shader caches are not being used, several games still take more than a few seconds to launch and could benefit from a loading screen.master
parent
83f8d1aa2e
commit
08fcf41b0a
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMovie>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QWindow>
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
|
#include "ui_loading_screen.h"
|
||||||
|
#include "yuzu/loading_screen.h"
|
||||||
|
|
||||||
|
LoadingScreen::LoadingScreen(QWidget* parent)
|
||||||
|
: QWidget(parent), ui(std::make_unique<Ui::LoadingScreen>()) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
// Progress bar is hidden until we have a use for it.
|
||||||
|
ui->progress_bar->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadingScreen::~LoadingScreen() = default;
|
||||||
|
|
||||||
|
void LoadingScreen::Prepare(Loader::AppLoader& loader) {
|
||||||
|
std::vector<u8> buffer;
|
||||||
|
if (loader.ReadBanner(buffer) == Loader::ResultStatus::Success) {
|
||||||
|
backing_mem =
|
||||||
|
std::make_unique<QByteArray>(reinterpret_cast<char*>(buffer.data()), buffer.size());
|
||||||
|
backing_buf = std::make_unique<QBuffer>(backing_mem.get());
|
||||||
|
backing_buf->open(QIODevice::ReadOnly);
|
||||||
|
animation = std::make_unique<QMovie>(backing_buf.get(), QByteArray("GIF"));
|
||||||
|
animation->start();
|
||||||
|
ui->banner->setMovie(animation.get());
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
if (loader.ReadLogo(buffer) == Loader::ResultStatus::Success) {
|
||||||
|
QPixmap map;
|
||||||
|
map.loadFromData(buffer.data(), buffer.size());
|
||||||
|
ui->logo->setPixmap(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadingScreen::OnLoadProgress(std::size_t value, std::size_t total) {
|
||||||
|
if (total != previous_total) {
|
||||||
|
ui->progress_bar->setMaximum(total);
|
||||||
|
previous_total = total;
|
||||||
|
}
|
||||||
|
ui->progress_bar->setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadingScreen::paintEvent(QPaintEvent* event) {
|
||||||
|
QStyleOption opt;
|
||||||
|
opt.init(this);
|
||||||
|
QPainter p(this);
|
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||||
|
QWidget::paintEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadingScreen::Clear() {
|
||||||
|
animation.reset();
|
||||||
|
backing_buf.reset();
|
||||||
|
backing_mem.reset();
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class LoadingScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QBuffer;
|
||||||
|
class QByteArray;
|
||||||
|
class QMovie;
|
||||||
|
|
||||||
|
class LoadingScreen : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LoadingScreen(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
~LoadingScreen();
|
||||||
|
|
||||||
|
/// Call before showing the loading screen to load the widgets with the logo and banner for the
|
||||||
|
/// currently loaded application.
|
||||||
|
void Prepare(Loader::AppLoader& loader);
|
||||||
|
|
||||||
|
/// After the loading screen is hidden, the owner of this class can call this to clean up any
|
||||||
|
/// used resources such as the logo and banner.
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
// 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
|
||||||
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
|
void OnLoadProgress(std::size_t value, std::size_t total);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QMovie> animation;
|
||||||
|
std::unique_ptr<QBuffer> backing_buf;
|
||||||
|
std::unique_ptr<QByteArray> backing_mem;
|
||||||
|
std::unique_ptr<Ui::LoadingScreen> ui;
|
||||||
|
std::size_t previous_total = 0;
|
||||||
|
};
|
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>LoadingScreen</class>
|
||||||
|
<widget class="QWidget" name="LoadingScreen">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>746</width>
|
||||||
|
<height>495</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="logo">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>30</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progress_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">font-size: 26px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>Loading Shaders %v out of %m</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignRight|Qt::AlignBottom">
|
||||||
|
<widget class="QLabel" name="banner">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: black;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>30</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue