mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Qt: implement hover pam in game list
This commit is contained in:
parent
aae155e954
commit
4dfda3240c
@ -22,4 +22,13 @@ struct GameInfo
|
|||||||
u32 resolution = 0;
|
u32 resolution = 0;
|
||||||
|
|
||||||
u64 size_on_disk = umax;
|
u64 size_on_disk = umax;
|
||||||
|
|
||||||
|
std::string get_pam_path() const
|
||||||
|
{
|
||||||
|
if (icon_path.empty())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return icon_path.substr(0, icon_path.find_last_of("/")) + "/ICON1.PAM";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@ struct gui_game_info
|
|||||||
bool hasCustomConfig = false;
|
bool hasCustomConfig = false;
|
||||||
bool hasCustomPadConfig = false;
|
bool hasCustomPadConfig = false;
|
||||||
bool has_hover_gif = false;
|
bool has_hover_gif = false;
|
||||||
|
bool has_hover_pam = false;
|
||||||
movie_item_base* item = nullptr;
|
movie_item_base* item = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -614,6 +614,7 @@ void game_list_frame::OnParsingFinished()
|
|||||||
info.hasCustomConfig = fs::is_file(rpcs3::utils::get_custom_config_path(info.info.serial));
|
info.hasCustomConfig = fs::is_file(rpcs3::utils::get_custom_config_path(info.info.serial));
|
||||||
info.hasCustomPadConfig = fs::is_file(rpcs3::utils::get_custom_input_config_path(info.info.serial));
|
info.hasCustomPadConfig = fs::is_file(rpcs3::utils::get_custom_input_config_path(info.info.serial));
|
||||||
info.has_hover_gif = fs::is_file(game_icon_path + info.info.serial + "/hover.gif");
|
info.has_hover_gif = fs::is_file(game_icon_path + info.info.serial + "/hover.gif");
|
||||||
|
info.has_hover_pam = fs::is_file(info.info.get_pam_path());
|
||||||
|
|
||||||
m_games.push(std::make_shared<gui_game_info>(std::move(info)));
|
m_games.push(std::make_shared<gui_game_info>(std::move(info)));
|
||||||
};
|
};
|
||||||
|
@ -75,16 +75,16 @@ void game_list_grid::populate(
|
|||||||
item->setToolTip(tr("%0 [%1]\n\nNotes:\n%2").arg(title).arg(serial).arg(notes));
|
item->setToolTip(tr("%0 [%1]\n\nNotes:\n%2").arg(title).arg(serial).arg(notes));
|
||||||
}
|
}
|
||||||
|
|
||||||
item->set_icon_func([this, item, game](int)
|
item->set_icon_func([this, item, game](const QVideoFrame& frame)
|
||||||
{
|
{
|
||||||
if (!item || !game)
|
if (!item || !game)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::shared_ptr<QMovie> movie = item->movie(); movie && item->get_active())
|
if (const QPixmap pixmap = item->get_movie_image(frame); item->get_active() && !pixmap.isNull())
|
||||||
{
|
{
|
||||||
item->set_icon(gui::utils::get_centered_pixmap(movie->currentPixmap(), m_icon_size, 0, 0, 1.0, Qt::FastTransformation));
|
item->set_icon(gui::utils::get_centered_pixmap(pixmap, m_icon_size, 0, 0, 1.0, Qt::FastTransformation));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -92,21 +92,22 @@ void game_list_grid::populate(
|
|||||||
|
|
||||||
item->set_icon(game->pxmap);
|
item->set_icon(game->pxmap);
|
||||||
|
|
||||||
if (!game->has_hover_gif)
|
if (!game->has_hover_gif && !game->has_hover_pam)
|
||||||
{
|
{
|
||||||
game->pxmap = {};
|
game->pxmap = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movie)
|
item->stop_movie();
|
||||||
{
|
|
||||||
movie->stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (play_hover_movies && game->has_hover_gif)
|
if (play_hover_movies && game->has_hover_gif)
|
||||||
{
|
{
|
||||||
item->init_movie(game_icon_path % serial % "/hover.gif");
|
item->set_movie_path(game_icon_path % serial % "/hover.gif");
|
||||||
|
}
|
||||||
|
else if (play_hover_movies && game->has_hover_pam)
|
||||||
|
{
|
||||||
|
item->set_movie_path(QString::fromStdString(game->info.get_pam_path()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected_item_id == game->info.path + game->info.icon_path)
|
if (selected_item_id == game->info.path + game->info.icon_path)
|
||||||
|
@ -235,16 +235,16 @@ void game_list_table::populate(
|
|||||||
custom_table_widget_item* icon_item = new custom_table_widget_item;
|
custom_table_widget_item* icon_item = new custom_table_widget_item;
|
||||||
game->item = icon_item;
|
game->item = icon_item;
|
||||||
|
|
||||||
icon_item->set_icon_func([this, icon_item, game](int)
|
icon_item->set_icon_func([this, icon_item, game](const QVideoFrame& frame)
|
||||||
{
|
{
|
||||||
if (!icon_item || !game)
|
if (!icon_item || !game)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::shared_ptr<QMovie> movie = icon_item->movie(); movie && icon_item->get_active())
|
if (const QPixmap pixmap = icon_item->get_movie_image(frame); icon_item->get_active() && !pixmap.isNull())
|
||||||
{
|
{
|
||||||
icon_item->setData(Qt::DecorationRole, movie->currentPixmap().scaled(m_icon_size, Qt::KeepAspectRatio));
|
icon_item->setData(Qt::DecorationRole, pixmap.scaled(m_icon_size, Qt::KeepAspectRatio));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -252,15 +252,12 @@ void game_list_table::populate(
|
|||||||
|
|
||||||
icon_item->setData(Qt::DecorationRole, game->pxmap);
|
icon_item->setData(Qt::DecorationRole, game->pxmap);
|
||||||
|
|
||||||
if (!game->has_hover_gif)
|
if (!game->has_hover_gif && !game->has_hover_pam)
|
||||||
{
|
{
|
||||||
game->pxmap = {};
|
game->pxmap = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movie)
|
icon_item->stop_movie();
|
||||||
{
|
|
||||||
movie->stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -288,7 +285,11 @@ void game_list_table::populate(
|
|||||||
|
|
||||||
if (play_hover_movies && game->has_hover_gif)
|
if (play_hover_movies && game->has_hover_gif)
|
||||||
{
|
{
|
||||||
icon_item->init_movie(game_icon_path % serial % "/hover.gif");
|
icon_item->set_movie_path(game_icon_path % serial % "/hover.gif");
|
||||||
|
}
|
||||||
|
else if (play_hover_movies && game->has_hover_pam)
|
||||||
|
{
|
||||||
|
icon_item->set_movie_path(QString::fromStdString(game->info.get_pam_path()));
|
||||||
}
|
}
|
||||||
|
|
||||||
icon_item->setData(Qt::UserRole, index, true);
|
icon_item->setData(Qt::UserRole, index, true);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "movie_item_base.h"
|
#include "movie_item_base.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
movie_item_base::movie_item_base()
|
movie_item_base::movie_item_base()
|
||||||
{
|
{
|
||||||
init_pointers();
|
init_pointers();
|
||||||
@ -13,6 +15,11 @@ movie_item_base::~movie_item_base()
|
|||||||
m_movie->stop();
|
m_movie->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_media_player)
|
||||||
|
{
|
||||||
|
m_media_player->stop();
|
||||||
|
}
|
||||||
|
|
||||||
wait_for_icon_loading(true);
|
wait_for_icon_loading(true);
|
||||||
wait_for_size_on_disk_loading(true);
|
wait_for_size_on_disk_loading(true);
|
||||||
}
|
}
|
||||||
@ -25,18 +32,43 @@ void movie_item_base::init_pointers()
|
|||||||
|
|
||||||
void movie_item_base::set_active(bool active)
|
void movie_item_base::set_active(bool active)
|
||||||
{
|
{
|
||||||
if (!std::exchange(m_active, active) && active && m_movie)
|
if (!std::exchange(m_active, active) && active)
|
||||||
|
{
|
||||||
|
init_movie();
|
||||||
|
|
||||||
|
if (m_movie)
|
||||||
{
|
{
|
||||||
m_movie->jumpToFrame(1);
|
m_movie->jumpToFrame(1);
|
||||||
m_movie->start();
|
m_movie->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_media_player)
|
||||||
|
{
|
||||||
|
m_media_player->play();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void movie_item_base::init_movie(const QString& path)
|
void movie_item_base::init_movie()
|
||||||
{
|
{
|
||||||
if (path.isEmpty() || !m_icon_callback) return;
|
if (m_movie || m_media_player)
|
||||||
|
{
|
||||||
|
// Already initialized
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_movie.reset(new QMovie(path));
|
if (!m_icon_callback || m_movie_path.isEmpty() || !QFile::exists(m_movie_path))
|
||||||
|
{
|
||||||
|
m_movie_path.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString lower = m_movie_path.toLower();
|
||||||
|
|
||||||
|
if (lower.endsWith(".gif"))
|
||||||
|
{
|
||||||
|
m_movie.reset(new QMovie(m_movie_path));
|
||||||
|
m_movie_path.clear();
|
||||||
|
|
||||||
if (!m_movie->isValid())
|
if (!m_movie->isValid())
|
||||||
{
|
{
|
||||||
@ -44,14 +76,92 @@ void movie_item_base::init_movie(const QString& path)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject::connect(m_movie.get(), &QMovie::frameChanged, m_movie.get(), m_icon_callback);
|
QObject::connect(m_movie.get(), &QMovie::frameChanged, m_movie.get(), [this](int)
|
||||||
|
{
|
||||||
|
m_icon_callback({});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lower.endsWith(".pam"))
|
||||||
|
{
|
||||||
|
// We can't set PAM files as source of the video player, so we have to feed them as raw data.
|
||||||
|
QFile file(m_movie_path);
|
||||||
|
if (!file.open(QFile::OpenModeFlag::ReadOnly))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Decode the pam properly before pushing it to the player
|
||||||
|
m_movie_data = file.readAll();
|
||||||
|
if (m_movie_data.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_movie_buffer.reset(new QBuffer(&m_movie_data));
|
||||||
|
m_movie_buffer->open(QIODevice::ReadOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_video_sink.reset(new QVideoSink());
|
||||||
|
QObject::connect(m_video_sink.get(), &QVideoSink::videoFrameChanged, m_video_sink.get(), [this](const QVideoFrame& frame)
|
||||||
|
{
|
||||||
|
m_icon_callback(frame);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_media_player.reset(new QMediaPlayer());
|
||||||
|
m_media_player->setVideoSink(m_video_sink.get());
|
||||||
|
m_media_player->setLoops(QMediaPlayer::Infinite);
|
||||||
|
|
||||||
|
if (m_movie_buffer)
|
||||||
|
{
|
||||||
|
m_media_player->setSourceDevice(m_movie_buffer.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_media_player->setSource(m_movie_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void movie_item_base::stop_movie()
|
||||||
|
{
|
||||||
|
if (m_movie)
|
||||||
|
{
|
||||||
|
m_movie->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_video_sink.reset();
|
||||||
|
m_media_player.reset();
|
||||||
|
m_movie_buffer.reset();
|
||||||
|
m_movie_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap movie_item_base::get_movie_image(const QVideoFrame& frame) const
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_movie)
|
||||||
|
{
|
||||||
|
return m_movie->currentPixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!frame.isValid())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get image. This usually also converts the image to ARGB32.
|
||||||
|
return QPixmap::fromImage(frame.toImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
void movie_item_base::call_icon_func() const
|
void movie_item_base::call_icon_func() const
|
||||||
{
|
{
|
||||||
if (m_icon_callback)
|
if (m_icon_callback)
|
||||||
{
|
{
|
||||||
m_icon_callback(0);
|
m_icon_callback({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,11 +6,16 @@
|
|||||||
|
|
||||||
#include <QMovie>
|
#include <QMovie>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QMediaPlayer>
|
||||||
|
#include <QVideoSink>
|
||||||
|
#include <QVideoFrame>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using icon_callback_t = std::function<void(int)>;
|
using icon_callback_t = std::function<void(const QVideoFrame&)>;
|
||||||
using icon_load_callback_t = std::function<void(int)>;
|
using icon_load_callback_t = std::function<void(int)>;
|
||||||
using size_calc_callback_t = std::function<void()>;
|
using size_calc_callback_t = std::function<void()>;
|
||||||
|
|
||||||
@ -29,12 +34,14 @@ public:
|
|||||||
return m_active;
|
return m_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<QMovie> movie() const
|
void set_movie_path(QString path)
|
||||||
{
|
{
|
||||||
return m_movie;
|
m_movie_path = std::move(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_movie(const QString& path);
|
void init_movie();
|
||||||
|
void stop_movie();
|
||||||
|
QPixmap get_movie_image(const QVideoFrame& frame) const;
|
||||||
|
|
||||||
void call_icon_func() const;
|
void call_icon_func() const;
|
||||||
void set_icon_func(const icon_callback_t& func);
|
void set_icon_func(const icon_callback_t& func);
|
||||||
@ -71,6 +78,11 @@ public:
|
|||||||
shared_mutex pixmap_mutex;
|
shared_mutex pixmap_mutex;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QString m_movie_path;
|
||||||
|
QByteArray m_movie_data{};
|
||||||
|
std::unique_ptr<QBuffer> m_movie_buffer;
|
||||||
|
std::unique_ptr<QMediaPlayer> m_media_player;
|
||||||
|
std::shared_ptr<QVideoSink> m_video_sink;
|
||||||
std::shared_ptr<QMovie> m_movie;
|
std::shared_ptr<QMovie> m_movie;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user