diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index acee714f24..60c49a60d7 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -832,6 +832,7 @@ + @@ -1671,6 +1672,7 @@ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DHAVE_SDL3 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 0bb0890b41..582e8ac59b 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -199,6 +199,9 @@ {2bb5cec5-5acb-40c0-a388-68db05dff305} + + {149c596b-83e7-43f8-b5db-6108694434ef} + @@ -1182,6 +1185,9 @@ Io\video + + Gui\widgets + @@ -1226,9 +1232,6 @@ Gui\utils - - Gui - Gui\user accounts @@ -1394,6 +1397,12 @@ Io\video + + Gui\widgets + + + Gui\widgets + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index 66c4fa3144..1c8875c372 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -113,6 +113,7 @@ add_library(rpcs3_ui STATIC vfs_dialog_usb_input.cpp vfs_dialog_usb_tab.cpp vfs_tool_dialog.cpp + video_label.cpp welcome_dialog.cpp about_dialog.ui diff --git a/rpcs3/rpcs3qt/qt_video_source.cpp b/rpcs3/rpcs3qt/qt_video_source.cpp index 263c1f2121..2338c09bf8 100644 --- a/rpcs3/rpcs3qt/qt_video_source.cpp +++ b/rpcs3/rpcs3qt/qt_video_source.cpp @@ -21,10 +21,16 @@ void qt_video_source::set_video_path(const std::string& path) void qt_video_source::set_active(bool active) { - if (!m_active.exchange(active) && active) + if (m_active.exchange(active) == active) return; + + if (active) { start_movie(); } + else + { + stop_movie(); + } } void qt_video_source::image_change_callback() const diff --git a/rpcs3/rpcs3qt/qt_video_source.h b/rpcs3/rpcs3qt/qt_video_source.h index 44cdebc034..f8b2267e5f 100644 --- a/rpcs3/rpcs3qt/qt_video_source.h +++ b/rpcs3/rpcs3qt/qt_video_source.h @@ -23,7 +23,7 @@ public: void get_image(std::vector& data, int& w, int& h, int& ch, int& bpp) override; bool has_new() const override { return m_has_new; } - void set_active(bool active); + virtual void set_active(bool active); [[nodiscard]] bool get_active() const { return m_active; diff --git a/rpcs3/rpcs3qt/save_manager_dialog.cpp b/rpcs3/rpcs3qt/save_manager_dialog.cpp index bdb085d7df..3460a43098 100644 --- a/rpcs3/rpcs3qt/save_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/save_manager_dialog.cpp @@ -2,11 +2,13 @@ #include "custom_table_widget_item.h" #include "qt_utils.h" +#include "qt_video_source.h" #include "gui_application.h" #include "gui_settings.h" #include "persistent_settings.h" #include "game_list_delegate.h" #include "progress_dialog.h" +#include "video_label.h" #include "Emu/System.h" #include "Emu/system_utils.hpp" @@ -107,7 +109,7 @@ void save_manager_dialog::Init() push_close->setAutoDefault(true); // Details - m_details_icon = new QLabel(this); + m_details_icon = new video_label(this); m_details_icon->setMinimumSize(320, 176); m_details_title = new QLabel(tr("Select an item to view details"), this); m_details_title->setWordWrap(true); @@ -640,7 +642,9 @@ void save_manager_dialog::UpdateDetails() { if (const int selected = m_list->selectionModel()->selectedRows().size(); selected != 1) { - m_details_icon->setPixmap(QPixmap()); + m_details_icon->set_thumbnail({}); + m_details_icon->set_active(false); + m_details_subtitle->setText(""); m_details_modified->setText(""); m_details_details->setText(""); @@ -664,7 +668,7 @@ void save_manager_dialog::UpdateDetails() const int row = m_list->currentRow(); QTableWidgetItem* item = m_list->item(row, SaveColumns::Name); - QTableWidgetItem* icon_item = m_list->item(row, SaveColumns::Icon); + movie_item* icon_item = static_cast(m_list->item(row, SaveColumns::Icon)); if (!item || !icon_item) { @@ -674,7 +678,14 @@ void save_manager_dialog::UpdateDetails() const int idx = item->data(Qt::UserRole).toInt(); const SaveDataEntry& save = ::at32(m_save_entries, idx); - m_details_icon->setPixmap(icon_item->data(Qt::UserRole).value()); + if (!icon_item->video_path().isEmpty()) + { + m_details_icon->set_video_path(icon_item->video_path().toStdString()); + } + + m_details_icon->set_thumbnail(icon_item->data(SaveUserRole::Pixmap).value()); + m_details_icon->set_active(false); + m_details_title->setText(QString::fromStdString(save.title)); m_details_subtitle->setText(QString::fromStdString(save.subtitle)); m_details_modified->setText(tr("Last modified: %1").arg(FormatTimestamp(save.mtime))); diff --git a/rpcs3/rpcs3qt/save_manager_dialog.h b/rpcs3/rpcs3qt/save_manager_dialog.h index aa23ccaaef..e685b2b6d5 100644 --- a/rpcs3/rpcs3qt/save_manager_dialog.h +++ b/rpcs3/rpcs3qt/save_manager_dialog.h @@ -1,6 +1,7 @@ #pragma once #include "game_list.h" + #include "Emu/Cell/Modules/cellSaveData.h" #include @@ -11,6 +12,7 @@ class gui_settings; class persistent_settings; +class video_label; class save_manager_dialog : public QDialog { @@ -59,7 +61,7 @@ private: QSize m_icon_size; QColor m_icon_color; - QLabel* m_details_icon = nullptr; + video_label* m_details_icon = nullptr; QLabel* m_details_title = nullptr; QLabel* m_details_subtitle = nullptr; QLabel* m_details_modified = nullptr; diff --git a/rpcs3/rpcs3qt/video_label.cpp b/rpcs3/rpcs3qt/video_label.cpp new file mode 100644 index 0000000000..bdf36a0e46 --- /dev/null +++ b/rpcs3/rpcs3qt/video_label.cpp @@ -0,0 +1,51 @@ +#include "stdafx.h" +#include "video_label.h" + +video_label::video_label(QWidget* parent) + : QLabel(parent), qt_video_source() +{ +} + +video_label::~video_label() +{ +} + +void video_label::set_thumbnail(const QPixmap& pxmap) +{ + m_current_pixmap = pxmap; +} + +void video_label::set_active(bool active) +{ + if (active) + { + set_image_change_callback([this](const QVideoFrame& frame) + { + if (const QPixmap pixmap = get_movie_image(frame); get_active() && !pixmap.isNull()) + { + setPixmap(pixmap); + } + }); + start_movie(); + } + else + { + set_image_change_callback({}); + stop_movie(); + setPixmap(m_current_pixmap); + } +} + +void video_label::enterEvent(QEnterEvent* event) +{ + set_active(true); + + QLabel::enterEvent(event); +} + +void video_label::leaveEvent(QEvent* event) +{ + set_active(false); + + QLabel::leaveEvent(event); +} diff --git a/rpcs3/rpcs3qt/video_label.h b/rpcs3/rpcs3qt/video_label.h new file mode 100644 index 0000000000..58f0bf8d21 --- /dev/null +++ b/rpcs3/rpcs3qt/video_label.h @@ -0,0 +1,22 @@ +#pragma once + +#include "qt_video_source.h" +#include +#include +#include + +class video_label : public QLabel, public qt_video_source +{ +public: + video_label(QWidget* parent = nullptr); + virtual ~video_label(); + + void set_thumbnail(const QPixmap& pxmap); + void set_active(bool active) override; + + void enterEvent(QEnterEvent* event) override; + void leaveEvent(QEvent* event) override; + +private: + QPixmap m_current_pixmap; +};