Include trophy rarity icons in pop up, remove newlines from viewer

Fix layout

Update platinum.png

Fix linux and apple
This commit is contained in:
rainmakerv2 2025-02-20 15:47:55 +08:00
parent cc583b6189
commit d42cc49dab
13 changed files with 118 additions and 25 deletions

View File

@ -25,6 +25,7 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-x86_64.AppImage --appdir AppDir
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
rsync -a "$GITHUB_WORKSPACE/Resources/" AppDir/
cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt ./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt

View File

@ -14,6 +14,8 @@ wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-checkrt/releases/downl
chmod a+x linuxdeploy-x86_64.AppImage chmod a+x linuxdeploy-x86_64.AppImage
chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
cp -a "$GITHUB_WORKSPACE/Resources" AppDir
# Build AppImage # Build AppImage
./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-x86_64.AppImage --appdir AppDir
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir

View File

@ -94,11 +94,14 @@ jobs:
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
- name: Move Files and Resources
run: "mkdir upload\n\t move build/Resources upload\nmove build/shadPS4.exe upload\n"
- name: Upload Windows SDL artifact - name: Upload Windows SDL artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
path: ${{github.workspace}}/build/shadPS4.exe path: upload/
windows-qt: windows-qt:
runs-on: windows-2025 runs-on: windows-2025
@ -148,10 +151,11 @@ jobs:
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
- name: Move Files and Resources
run: "mkdir upload\n\t move build/Resources upload\nmove build/shadPS4.exe upload\n"
- name: Deploy and Package - name: Deploy and Package
run: | run: |
mkdir upload
move build/shadPS4.exe upload
windeployqt --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe windeployqt --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe
Compress-Archive -Path upload/* -DestinationPath shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}.zip Compress-Archive -Path upload/* -DestinationPath shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}.zip
@ -201,10 +205,11 @@ jobs:
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
- name: Move Files and Resources
run: "mkdir upload\n\t mv ${{github.workspace}}/build/shadps4 upload\nmv ${{github.workspace}}/build/Resources upload\n"
- name: Package and Upload macOS SDL artifact - name: Package and Upload macOS SDL artifact
run: | run: |
mkdir upload
mv ${{github.workspace}}/build/shadps4 upload
cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload
tar cf shadps4-macos-sdl.tar.gz -C upload . tar cf shadps4-macos-sdl.tar.gz -C upload .
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
@ -262,10 +267,11 @@ jobs:
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu) run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
- name: Move Files and Resources
run: "mkdir upload\n\t mv ${{github.workspace}}/build/shadps4.app upload\n"
- name: Package and Upload macOS Qt artifact - name: Package and Upload macOS Qt artifact
run: | run: |
mkdir upload
mv ${{github.workspace}}/build/shadps4.app upload
macdeployqt upload/shadps4.app macdeployqt upload/shadps4.app
tar cf shadps4-macos-qt.tar.gz -C upload . tar cf shadps4-macos-qt.tar.gz -C upload .
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4

View File

@ -195,6 +195,7 @@ endif()
add_subdirectory(externals) add_subdirectory(externals)
include_directories(src) include_directories(src)
include_directories(Resources)
if(ENABLE_QT_GUI) if(ENABLE_QT_GUI)
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia) find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
@ -956,6 +957,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
) )
endif() endif()
set(RESOURCEFOLDER ${CMAKE_SOURCE_DIR}/Resources)
if (ENABLE_QT_GUI) if (ENABLE_QT_GUI)
qt_add_executable(shadps4 qt_add_executable(shadps4
${AUDIO_CORE} ${AUDIO_CORE}
@ -967,6 +970,7 @@ if (ENABLE_QT_GUI)
${SHADER_RECOMPILER} ${SHADER_RECOMPILER}
${VIDEO_CORE} ${VIDEO_CORE}
${EMULATOR} ${EMULATOR}
${RESOURCEFOLDER}
src/images/shadPS4.icns src/images/shadPS4.icns
) )
else() else()
@ -1144,3 +1148,19 @@ if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png") install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png")
install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps") install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps")
endif() endif()
# copy Resource folder (trophy images) inside Mac App bundle resources folder
if (ENABLE_QT_GUI AND APPLE)
add_custom_command(TARGET shadps4 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_SOURCE_DIR}/Resources"
"$<TARGET_FILE_DIR:shadps4>/../Resources"
)
else()
add_custom_target(copy-files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/Resources/
${CMAKE_BINARY_DIR}/Resources/
)
endif()

View File

@ -19,6 +19,10 @@ path = [
"documents/Screenshots/*", "documents/Screenshots/*",
"documents/Screenshots/Linux/*", "documents/Screenshots/Linux/*",
"externals/MoltenVK/MoltenVK_icd.json", "externals/MoltenVK/MoltenVK_icd.json",
"Resources/bronze.png",
"Resources/gold.png",
"Resources/platinum.png",
"Resources/silver.png",
"scripts/ps4_names.txt", "scripts/ps4_names.txt",
"src/images/about_icon.png", "src/images/about_icon.png",
"src/images/controller_icon.png", "src/images/controller_icon.png",

BIN
Resources/bronze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
Resources/gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
Resources/platinum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
Resources/silver.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -941,7 +941,7 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
std::filesystem::path current_icon_path = std::filesystem::path current_icon_path =
trophy_dir / "trophy00" / "Icons" / trophy_icon_file; trophy_dir / "trophy00" / "Icons" / trophy_icon_file;
AddTrophyToQueue(current_icon_path, current_trophy_name); AddTrophyToQueue(current_icon_path, current_trophy_name, current_trophy_type);
} }
} }
} }
@ -978,7 +978,7 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
trophy_dir / "trophy00" / "Icons" / platinum_icon_file; trophy_dir / "trophy00" / "Icons" / platinum_icon_file;
*platinumId = platinum_trophy_id; *platinumId = platinum_trophy_id;
AddTrophyToQueue(platinum_icon_path, platinum_trophy_name); AddTrophyToQueue(platinum_icon_path, platinum_trophy_name, "P");
} }
} }

View File

@ -17,14 +17,45 @@ std::optional<TrophyUI> current_trophy_ui;
std::queue<TrophyInfo> trophy_queue; std::queue<TrophyInfo> trophy_queue;
std::mutex queueMtx; std::mutex queueMtx;
TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName) TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
: trophy_name(trophyName) { const std::string_view& rarity)
: trophy_name(trophyName), trophy_type(rarity) {
if (std::filesystem::exists(trophyIconPath)) { if (std::filesystem::exists(trophyIconPath)) {
trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath); trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath);
} else { } else {
LOG_ERROR(Lib_NpTrophy, "Couldnt load trophy icon at {}", LOG_ERROR(Lib_NpTrophy, "Couldnt load trophy icon at {}",
fmt::UTF(trophyIconPath.u8string())); fmt::UTF(trophyIconPath.u8string()));
} }
std::filesystem::path trophyTypePath;
std::filesystem::path ResourceDir;
// covers Windows, Mac SDL, locally compiled builds
if (std::filesystem::exists(std::filesystem::current_path() / "Resources")) {
ResourceDir = std::filesystem::current_path() / "Resources";
} else {
#if defined(__linux__)
const char* AppDir = getenv("APPDIR");
ResourceDir = std::filesystem::path(AppDir);
#elif defined(__APPLE__)
// for testing on Mac QT
ResourceDir = std::filesystem::current_path().parent_path() / "Resources";
#endif
}
if (trophy_type == "P") {
trophyTypePath = ResourceDir / "platinum.png";
} else if (trophy_type == "G") {
trophyTypePath = ResourceDir / "gold.png";
} else if (trophy_type == "S") {
trophyTypePath = ResourceDir / "silver.png";
} else if (trophy_type == "B") {
trophyTypePath = ResourceDir / "bronze.png";
}
if (std::filesystem::exists(trophyTypePath))
trophy_type_icon = RefCountedTexture::DecodePngFile(trophyTypePath);
AddLayer(this); AddLayer(this);
} }
@ -42,27 +73,40 @@ void TrophyUI::Draw() {
float AdjustWidth = io.DisplaySize.x / 1280; float AdjustWidth = io.DisplaySize.x / 1280;
float AdjustHeight = io.DisplaySize.y / 720; float AdjustHeight = io.DisplaySize.y / 720;
const ImVec2 window_size{ const ImVec2 window_size{
std::min(io.DisplaySize.x, (300 * AdjustWidth)), std::min(io.DisplaySize.x, (350 * AdjustWidth)),
std::min(io.DisplaySize.y, (70 * AdjustHeight)), std::min(io.DisplaySize.y, (70 * AdjustHeight)),
}; };
SetNextWindowSize(window_size); SetNextWindowSize(window_size);
SetNextWindowCollapsed(false); SetNextWindowCollapsed(false);
SetNextWindowPos(ImVec2(io.DisplaySize.x - (300 * AdjustWidth), (50 * AdjustHeight))); SetNextWindowPos(ImVec2(io.DisplaySize.x - (350 * AdjustWidth), (50 * AdjustHeight)));
KeepNavHighlight(); KeepNavHighlight();
if (Begin("Trophy Window", nullptr, if (Begin("Trophy Window", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoInputs)) { ImGuiWindowFlags_NoInputs)) {
if (trophy_icon) { if (trophy_icon) {
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
Image(trophy_icon.GetTexture().im_id, ImVec2((50 * AdjustWidth), (50 * AdjustHeight))); Image(trophy_icon.GetTexture().im_id, ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
ImGui::SameLine();
} else { } else {
// placeholder // placeholder
const auto pos = GetCursorScreenPos(); const auto pos = GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f}, ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
GetColorU32(ImVec4{0.7f})); GetColorU32(ImVec4{0.7f}));
ImGui::Indent(60);
} }
ImGui::SameLine();
if (trophy_type_icon) {
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
Image(trophy_type_icon.GetTexture().im_id,
ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
} else {
// placeholder
const auto pos = GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
GetColorU32(ImVec4{0.7f}));
}
ImGui::SameLine();
SetWindowFontScale((1.2 * AdjustHeight)); SetWindowFontScale((1.2 * AdjustHeight));
TextWrapped("Trophy earned!\n%s", trophy_name.c_str()); TextWrapped("Trophy earned!\n%s", trophy_name.c_str());
} }
@ -74,14 +118,16 @@ void TrophyUI::Draw() {
if (!trophy_queue.empty()) { if (!trophy_queue.empty()) {
TrophyInfo next_trophy = trophy_queue.front(); TrophyInfo next_trophy = trophy_queue.front();
trophy_queue.pop(); trophy_queue.pop();
current_trophy_ui.emplace(next_trophy.trophy_icon_path, next_trophy.trophy_name); current_trophy_ui.emplace(next_trophy.trophy_icon_path, next_trophy.trophy_name,
next_trophy.trophy_type);
} else { } else {
current_trophy_ui.reset(); current_trophy_ui.reset();
} }
} }
} }
void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName) { void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
const std::string_view& rarity) {
std::lock_guard<std::mutex> lock(queueMtx); std::lock_guard<std::mutex> lock(queueMtx);
if (Config::getisTrophyPopupDisabled()) { if (Config::getisTrophyPopupDisabled()) {
@ -90,9 +136,10 @@ void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::st
TrophyInfo new_trophy; TrophyInfo new_trophy;
new_trophy.trophy_icon_path = trophyIconPath; new_trophy.trophy_icon_path = trophyIconPath;
new_trophy.trophy_name = trophyName; new_trophy.trophy_name = trophyName;
new_trophy.trophy_type = rarity;
trophy_queue.push(new_trophy); trophy_queue.push(new_trophy);
} else { } else {
current_trophy_ui.emplace(trophyIconPath, trophyName); current_trophy_ui.emplace(trophyIconPath, trophyName, rarity);
} }
} }

View File

@ -17,7 +17,8 @@ namespace Libraries::NpTrophy {
class TrophyUI final : public ImGui::Layer { class TrophyUI final : public ImGui::Layer {
public: public:
TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName); TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
const std::string_view& rarity);
~TrophyUI() override; ~TrophyUI() override;
void Finish(); void Finish();
@ -26,15 +27,19 @@ public:
private: private:
std::string trophy_name; std::string trophy_name;
std::string_view trophy_type;
float trophy_timer = 5.0f; float trophy_timer = 5.0f;
ImGui::RefCountedTexture trophy_icon; ImGui::RefCountedTexture trophy_icon;
ImGui::RefCountedTexture trophy_type_icon;
}; };
struct TrophyInfo { struct TrophyInfo {
std::filesystem::path trophy_icon_path; std::filesystem::path trophy_icon_path;
std::string trophy_name; std::string trophy_name;
std::string_view trophy_type;
}; };
void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName); void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
const std::string_view& rarity);
}; // namespace Libraries::NpTrophy }; // namespace Libraries::NpTrophy

View File

@ -115,10 +115,18 @@ void TrophyViewer::PopulateTrophyWidget(QString title) {
item->setData(Qt::DecorationRole, icon); item->setData(Qt::DecorationRole, icon);
item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setFlags(item->flags() & ~Qt::ItemIsEditable);
tableWidget->setItem(row, 1, item); tableWidget->setItem(row, 1, item);
std::string detailString = trophyDetails[row].toStdString();
std::size_t newline_pos = 0;
while ((newline_pos = detailString.find("\n", newline_pos)) != std::string::npos) {
detailString.replace(newline_pos, 1, " ");
++newline_pos;
}
if (!trophyNames.isEmpty() && !trophyDetails.isEmpty()) { if (!trophyNames.isEmpty() && !trophyDetails.isEmpty()) {
SetTableItem(tableWidget, row, 0, trpUnlocked[row]); SetTableItem(tableWidget, row, 0, trpUnlocked[row]);
SetTableItem(tableWidget, row, 2, trophyNames[row]); SetTableItem(tableWidget, row, 2, trophyNames[row]);
SetTableItem(tableWidget, row, 3, trophyDetails[row]); SetTableItem(tableWidget, row, 3, QString::fromStdString(detailString));
SetTableItem(tableWidget, row, 4, trpId[row]); SetTableItem(tableWidget, row, 4, trpId[row]);
SetTableItem(tableWidget, row, 5, trpHidden[row]); SetTableItem(tableWidget, row, 5, trpHidden[row]);
SetTableItem(tableWidget, row, 6, GetTrpType(trpType[row].at(0))); SetTableItem(tableWidget, row, 6, GetTrpType(trpType[row].at(0)));
@ -157,7 +165,7 @@ void TrophyViewer::SetTableItem(QTableWidget* parent, int row, int column, QStri
label->setGraphicsEffect(shadowEffect); // Apply shadow effect to the QLabel label->setGraphicsEffect(shadowEffect); // Apply shadow effect to the QLabel
layout->addWidget(label); layout->addWidget(label);
if (column != 1 && column != 2) if (column != 1 && column != 2 && column != 3)
layout->setAlignment(Qt::AlignCenter); layout->setAlignment(Qt::AlignCenter);
widget->setLayout(layout); widget->setLayout(layout);
parent->setItem(row, column, item); parent->setItem(row, column, item);