mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Make a basic trophy notification dialog (#3204)
* Make trophy notification dialog. * Fix bug where trophy state doesn't persist with game reboot.
This commit is contained in:
parent
779ed75a19
commit
b0737d1c90
17 changed files with 217 additions and 21 deletions
|
@ -16,6 +16,10 @@
|
|||
|
||||
logs::channel sceNpTrophy("sceNpTrophy");
|
||||
|
||||
TrophyNotificationBase::~TrophyNotificationBase()
|
||||
{
|
||||
}
|
||||
|
||||
struct trophy_context_t
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
|
@ -490,6 +494,40 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
|
|||
*platinumId = SCE_NP_TROPHY_INVALID_TROPHY_ID; // TODO
|
||||
}
|
||||
|
||||
if (g_cfg.misc.show_trophy_popups)
|
||||
{
|
||||
// Figure out how many zeros are needed for padding. (either 0, 1, or 2)
|
||||
std::string padding = "";
|
||||
if (trophyId < 10)
|
||||
{
|
||||
padding = "00";
|
||||
}
|
||||
else if (trophyId < 100)
|
||||
{
|
||||
padding = "0";
|
||||
}
|
||||
|
||||
// Get icon for the notification.
|
||||
std::string trophyIconPath = "/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name + "/TROP" + padding + std::to_string(trophyId) + ".PNG";
|
||||
fs::file trophyIconFile = fs::file(vfs::get(trophyIconPath));
|
||||
u32 iconSize = trophyIconFile.size();
|
||||
std::vector<uchar> trophyIconData;
|
||||
trophyIconFile.read(trophyIconData, iconSize);
|
||||
|
||||
vm::ptr<SceNpTrophyDetails> details = vm::make_var(SceNpTrophyDetails());
|
||||
vm::ptr<SceNpTrophyData> _ = vm::make_var(SceNpTrophyData());
|
||||
|
||||
s32 ret = sceNpTrophyGetTrophyInfo(context, handle, trophyId, details, _);
|
||||
if (ret != CELL_OK)
|
||||
{
|
||||
sceNpTrophy.error("Failed to get info for trophy dialog. Error code %x", ret);
|
||||
*details = SceNpTrophyDetails();
|
||||
}
|
||||
Emu.CallAfter([det = *details, trophyIconData]() {
|
||||
Emu.GetCallbacks().get_trophy_notification_dialog()->ShowTrophyNotification(det, trophyIconData);
|
||||
});
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,3 +137,14 @@ enum
|
|||
};
|
||||
|
||||
using SceNpTrophyStatusCallback = s32(u32 context, u32 status, s32 completed, s32 total, vm::ptr<void> arg);
|
||||
|
||||
// Forward declare this function since trophyunlock needs it
|
||||
error_code sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceNpTrophyDetails> details, vm::ptr<SceNpTrophyData> data);
|
||||
|
||||
class TrophyNotificationBase
|
||||
{
|
||||
public:
|
||||
virtual ~TrophyNotificationBase();
|
||||
|
||||
virtual s32 ShowTrophyNotification(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophyIconBfr) = 0;
|
||||
};
|
||||
|
|
|
@ -165,6 +165,7 @@ struct EmuCallbacks
|
|||
std::function<std::shared_ptr<class AudioThread>()> get_audio;
|
||||
std::function<std::shared_ptr<class MsgDialogBase>()> get_msg_dialog;
|
||||
std::function<std::unique_ptr<class SaveDialogBase>()> get_save_dialog;
|
||||
std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
|
||||
};
|
||||
|
||||
class Emulator final
|
||||
|
@ -402,6 +403,7 @@ struct cfg_root : cfg::node
|
|||
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"};
|
||||
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" };
|
||||
cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true};
|
||||
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true};
|
||||
cfg::_int<1, 65535> gdb_server_port{this, "Port", 2345};
|
||||
|
||||
} misc{this};
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"startGameFullscreen": "Automatically puts the game window in fullscreen.\nDouble click on the game window or press alt+enter to toggle fullscreen and windowed mode.",
|
||||
"showFPSInTitle": "Shows the framerate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.",
|
||||
"gs_resizeOnBoot": "Automatically resizes the game window on boot.\nThis does not change the internal game resolution.",
|
||||
"showTrophyPopups": "Show trophy popups when a trophy is unlocked.",
|
||||
"gs_disableMouse": "Disables the activation of fullscreen mode per doubleclick while the game screen is active.\nCheck this if you want to play with mouse and keyboard (for example with UCR)."
|
||||
}
|
||||
},
|
||||
|
|
|
@ -9,14 +9,12 @@ bool TROPUSRLoader::Load(const std::string& filepath, const std::string& configp
|
|||
{
|
||||
const std::string& path = vfs::get(filepath);
|
||||
|
||||
if (!Generate(filepath, configpath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_file.open(path, fs::read))
|
||||
{
|
||||
return false;
|
||||
if (!Generate(filepath, configpath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadHeader() || !LoadTableHeaders() || !LoadTables())
|
||||
|
|
|
@ -897,6 +897,8 @@
|
|||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp" />
|
||||
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp" />
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp" />
|
||||
<ClCompile Include="rpcs3qt\welcome_dialog.cpp" />
|
||||
|
@ -1431,6 +1433,8 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(NOINHERIT)\."</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_frame.h" />
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_helper.h" />
|
||||
<ClInclude Include="xinput_pad_handler.h" />
|
||||
<ClInclude Include="\rpcs3qt\*.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -60,7 +60,10 @@
|
|||
<Extensions>ui</Extensions>
|
||||
<ParseFiles>true</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Gui\saves">
|
||||
<Filter Include="Gui\trophy">
|
||||
<UniqueIdentifier>{d49ebf7f-ea65-4006-943a-2c47f25c9aa7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\save">
|
||||
<UniqueIdentifier>{31799965-1274-4c87-83a3-3bff31e8715d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\vfs">
|
||||
|
@ -426,16 +429,19 @@
|
|||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_list_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_save_manager_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
|
@ -548,6 +554,9 @@
|
|||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="\rpcs3qt\*.h">
|
||||
|
@ -581,7 +590,13 @@
|
|||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\save_data_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_helper.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_frame.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pad_thread.h">
|
||||
<Filter>Io</Filter>
|
||||
|
@ -649,13 +664,10 @@
|
|||
<Filter>Form Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_data_info_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_data_list_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_manager_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
<Filter>Gui\syntax highlighter</Filter>
|
||||
|
@ -723,6 +735,9 @@
|
|||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_manager_dialog.h">
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="rpcs3.ico" />
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include "rpcs3qt/gs_frame.h"
|
||||
#include "rpcs3qt/gl_gs_frame.h"
|
||||
|
||||
#include "Emu/Cell/Modules/sceNpTrophy.h"
|
||||
#include "rpcs3qt/trophy_notification_helper.h"
|
||||
|
||||
#include "Emu/Cell/Modules/cellSaveData.h"
|
||||
#include "rpcs3qt/save_data_dialog.h"
|
||||
|
||||
|
@ -241,6 +244,11 @@ void rpcs3_app::InitializeCallbacks()
|
|||
return std::make_unique<save_data_dialog>();
|
||||
};
|
||||
|
||||
callbacks.get_trophy_notification_dialog = [=]() -> std::unique_ptr<TrophyNotificationBase>
|
||||
{
|
||||
return std::make_unique<trophy_notification_helper>(gameWindow);
|
||||
};
|
||||
|
||||
callbacks.on_run = [=]() { OnEmulatorRun(); };
|
||||
callbacks.on_pause = [=]() { OnEmulatorPause(); };
|
||||
callbacks.on_resume = [=]() { OnEmulatorResume(); };
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
StartOnBoot,
|
||||
StartGameFullscreen,
|
||||
ShowFPSInTitle,
|
||||
ShowTrophyPopups,
|
||||
ShowWelcomeScreen,
|
||||
|
||||
// Network
|
||||
|
@ -236,6 +237,7 @@ private:
|
|||
{StartOnBoot, { "Miscellaneous", "Automatically start games after boot" }},
|
||||
{StartGameFullscreen, { "Miscellaneous", "Start games in fullscreen mode"}},
|
||||
{ShowFPSInTitle, { "Miscellaneous", "Show FPS counter in window title"}},
|
||||
{ShowTrophyPopups, { "Miscellaneous", "Show trophy popups"}},
|
||||
{ShowWelcomeScreen, { "Miscellaneous", "Show Welcome Screen"}},
|
||||
|
||||
// Networking
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
||||
#include "save_data_dialog.h"
|
||||
#include "save_data_list_dialog.h"
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/Cell/Modules/cellSaveData.h"
|
||||
|
||||
class save_data_dialog : public SaveDialogBase
|
||||
|
|
|
@ -715,6 +715,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||
xemu_settings->EnhanceCheckBox(ui->showFPSInTitle, emu_settings::ShowFPSInTitle);
|
||||
SubscribeTooltip(ui->showFPSInTitle, json_emu_misc["showFPSInTitle"].toString());
|
||||
|
||||
xemu_settings->EnhanceCheckBox(ui->showTrophyPopups, emu_settings::ShowTrophyPopups);
|
||||
SubscribeTooltip(ui->showTrophyPopups, json_emu_misc["showTrophyPopups"].toString());
|
||||
|
||||
if (game)
|
||||
{
|
||||
ui->gb_stylesheets->setEnabled(false);
|
||||
|
|
|
@ -1161,6 +1161,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showTrophyPopups">
|
||||
<property name="text">
|
||||
<string>Show trophy popups</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
65
rpcs3/rpcs3qt/trophy_notification_frame.cpp
Normal file
65
rpcs3/rpcs3qt/trophy_notification_frame.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "trophy_notification_frame.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
|
||||
static const int TROPHY_TIMEOUT_MS = 7500;
|
||||
|
||||
inline QString qstr(const std::string& _in) { return QString::fromUtf8(_in.data(), _in.size()); }
|
||||
|
||||
trophy_notification_frame::trophy_notification_frame(const std::vector<uchar>& imgBuffer, const SceNpTrophyDetails& trophy, int height) : QWidget()
|
||||
{
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
|
||||
// Fill the background with black
|
||||
QPalette black_background;
|
||||
black_background.setColor(QPalette::Window, Qt::black);
|
||||
black_background.setColor(QPalette::WindowText, Qt::white);
|
||||
|
||||
// Make the label
|
||||
QLabel* trophyImgLabel = new QLabel;
|
||||
trophyImgLabel->setAutoFillBackground(true);
|
||||
trophyImgLabel->setPalette(black_background);
|
||||
|
||||
QImage trophyImg;
|
||||
if (imgBuffer.size() > 0 && trophyImg.loadFromData((uchar*)&imgBuffer[0], imgBuffer.size(), "PNG"))
|
||||
{
|
||||
trophyImg = trophyImg.scaledToHeight(height); // I might consider adding ability to change size since on hidpi this will be rather small.
|
||||
trophyImgLabel->setPixmap(QPixmap::fromImage(trophyImg));
|
||||
}
|
||||
else
|
||||
{
|
||||
// This looks hideous, but it's a good placeholder.
|
||||
trophyImgLabel->setPixmap(QPixmap::fromImage(QImage(":/rpcs3.ico")));
|
||||
}
|
||||
|
||||
QLabel* trophyName = new QLabel;
|
||||
trophyName->setWordWrap(true);
|
||||
trophyName->setAlignment(Qt::AlignCenter);
|
||||
|
||||
QString trophyType = "";
|
||||
switch (trophy.trophyGrade)
|
||||
{
|
||||
case SCE_NP_TROPHY_GRADE_BRONZE: trophyType = "bronze"; break;
|
||||
case SCE_NP_TROPHY_GRADE_SILVER: trophyType = "silver"; break;
|
||||
case SCE_NP_TROPHY_GRADE_GOLD: trophyType = "gold"; break;
|
||||
case SCE_NP_TROPHY_GRADE_PLATINUM: trophyType = "platinum"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
trophyName->setText("You have earned the " + trophyType + " trophy\n" + qstr(trophy.name));
|
||||
trophyName->setAutoFillBackground(true);
|
||||
trophyName->setPalette(black_background);
|
||||
|
||||
QHBoxLayout* globalLayout = new QHBoxLayout;
|
||||
globalLayout->addWidget(trophyImgLabel);
|
||||
globalLayout->addWidget(trophyName);
|
||||
setLayout(globalLayout);
|
||||
setPalette(black_background);
|
||||
|
||||
// I may consider moving this code later to be done at a better location.
|
||||
QTimer::singleShot(TROPHY_TIMEOUT_MS, [this]() {
|
||||
deleteLater();
|
||||
});
|
||||
}
|
13
rpcs3/rpcs3qt/trophy_notification_frame.h
Normal file
13
rpcs3/rpcs3qt/trophy_notification_frame.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/Cell/Modules/sceNpTrophy.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class trophy_notification_frame : public QWidget
|
||||
{
|
||||
public:
|
||||
trophy_notification_frame(const std::vector<uchar>& imgBuffer, const SceNpTrophyDetails& trophy, int height);
|
||||
};
|
14
rpcs3/rpcs3qt/trophy_notification_helper.cpp
Normal file
14
rpcs3/rpcs3qt/trophy_notification_helper.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "trophy_notification_helper.h"
|
||||
|
||||
#include "trophy_notification_frame.h"
|
||||
|
||||
s32 trophy_notification_helper::ShowTrophyNotification(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophy_icon_buffer)
|
||||
{
|
||||
trophy_notification_frame* trophy_notification = new trophy_notification_frame(trophy_icon_buffer, trophy, m_game_window->frameGeometry().height()/10);
|
||||
|
||||
// Move notification to upper lefthand corner
|
||||
trophy_notification->move(m_game_window->mapToGlobal(QPoint(0, 0)));
|
||||
trophy_notification->show();
|
||||
|
||||
return 0;
|
||||
}
|
16
rpcs3/rpcs3qt/trophy_notification_helper.h
Normal file
16
rpcs3/rpcs3qt/trophy_notification_helper.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/Cell/Modules/sceNpTrophy.h"
|
||||
|
||||
#include <QWindow>
|
||||
|
||||
class trophy_notification_helper : public TrophyNotificationBase
|
||||
{
|
||||
public:
|
||||
trophy_notification_helper(QWindow* game_window) : m_game_window(game_window) { };
|
||||
s32 ShowTrophyNotification(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophy_icon_buffer) override;
|
||||
private:
|
||||
QWindow* m_game_window;
|
||||
};
|
Loading…
Add table
Reference in a new issue