Trophy overlay

This commit is contained in:
igor725 2024-05-05 14:36:49 +03:00
parent 91bc43b2d8
commit 8eab15adcd
No known key found for this signature in database
GPG Key ID: 46F13BBE46F8569D
11 changed files with 196 additions and 36 deletions

View File

@ -117,6 +117,7 @@ add_dependencies(psoff logging core psOff_utility)
target_link_libraries(psoff PRIVATE
core.lib
psOff_utility
libboost_filesystem
$<TARGET_OBJECTS:asmHelper>
)

View File

@ -6,6 +6,7 @@ add_library(videoout OBJECT
vulkan/vulkanHelper.cpp
overlay/overlay.cpp
overlay/overtrophy/overtrophy.cpp
)
add_dependencies(videoout third_party psOff_utility gamereport initParams config_emu psoff_render)
@ -13,4 +14,4 @@ add_dependencies(videoout third_party psOff_utility gamereport initParams config
target_include_directories(videoout PRIVATE
${Vulkan_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/third_party/src/third_party/include
)
)

View File

@ -1,6 +1,7 @@
#include "imageHandler.h"
#include "core/initParams/initParams.h"
#include "core/timer/timer.h"
#include "logging.h"
#include "vulkan/vulkanSetup.h"
@ -66,6 +67,8 @@ class ImageHandler: public IImageHandler {
void notify_done(ImageData const&) final;
void calc_fps(uint64_t proctime) final;
VkSwapchainKHR getSwapchain() const final { return m_swapchain; }
};
@ -220,6 +223,13 @@ void ImageHandler::notify_done(ImageData const& imageData) {
m_present_condVar.notify_all();
}
void ImageHandler::calc_fps(uint64_t proctime) {
auto& timer = accessTimer();
auto const curTime = (uint64_t)(1e6 * timer.getTimeS());
auto elapsed_us = curTime - proctime;
m_fps = (m_fps * 5.0 + (1e6 / (double)elapsed_us)) / 6.0;
}
void ImageHandler::init(vulkan::VulkanObj* obj, VkSurfaceKHR surface) {
LOG_USE_MODULE(ImageHandler);
@ -364,4 +374,4 @@ void ImageHandler::deinit() {
if (m_swapchain != nullptr) vkDestroySwapchainKHR(m_deviceInfo->device, m_swapchain, nullptr);
printf("deinit ImageHandler| done\n");
}
}

View File

@ -52,6 +52,8 @@ class IImageHandler {
ImageHandlerCB* m_callback;
double m_fps;
public:
virtual ~IImageHandler() = default;
@ -61,6 +63,8 @@ class IImageHandler {
auto getQueue() const { return m_queue; }
auto getFPS() const { return m_fps; }
virtual void init(vulkan::VulkanObj* obj, VkSurfaceKHR surface) = 0;
virtual void deinit() = 0;
@ -68,9 +72,10 @@ class IImageHandler {
virtual std::optional<ImageData> getImage_blocking() = 0;
virtual void notify_done(ImageData const&) = 0;
virtual void calc_fps(uint64_t proctime) = 0;
virtual VkSwapchainKHR getSwapchain() const = 0;
};
std::unique_ptr<IImageHandler> createImageHandler(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, VkExtent2D extentWindow, vulkan::QueueInfo* queue,
ImageHandlerCB* callback);
ImageHandlerCB* callback);

View File

@ -1,7 +1,7 @@
#include "overlay.h"
#include "../imageHandler.h"
#include "logging.h"
#include "overtrophy/overtrophy.h"
#include <imgui/imgui.h>
#include <imgui/imgui_impl_sdl2.h>
@ -12,6 +12,7 @@ LOG_DEFINE_MODULE(Overlay);
class OverlayHandler: public IOverlayHandler {
std::shared_ptr<vulkan::DeviceInfo> m_deviceInfo;
std::shared_ptr<IImageHandler> m_imageHandler;
VkDescriptorPool m_descriptorPool;
@ -21,8 +22,9 @@ class OverlayHandler: public IOverlayHandler {
void draw();
public:
OverlayHandler(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat)
: m_deviceInfo(deviceInfo) {
OverlayHandler(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, std::shared_ptr<IImageHandler>& imagehandler, SDL_Window* window, vulkan::QueueInfo* queue,
VkFormat displayFormat)
: m_deviceInfo(deviceInfo), m_imageHandler(imagehandler) {
init(window, queue, displayFormat);
}
@ -38,15 +40,15 @@ class OverlayHandler: public IOverlayHandler {
void submit(ImageData const& imageData) final;
void processEvent(SDL_Event const* event) final {
[[unlikely]] if (!m_isInit || !m_isStop)
[[unlikely]] if (!m_isInit || m_isStop)
return;
ImGui_ImplSDL2_ProcessEvent(event);
}
};
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue,
VkFormat displayFormat) {
return std::make_unique<OverlayHandler>(deviceInfo, window, queue, displayFormat);
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, std::shared_ptr<IImageHandler>& imagehandler,
SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat) {
return std::make_unique<OverlayHandler>(deviceInfo, imagehandler, window, queue, displayFormat);
}
void OverlayHandler::init(SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat) {
@ -85,6 +87,8 @@ void OverlayHandler::init(SDL_Window* window, vulkan::QueueInfo* queue, VkFormat
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = nullptr;
io.LogFilename = nullptr;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
@ -120,6 +124,7 @@ void OverlayHandler::init(SDL_Window* window, vulkan::QueueInfo* queue, VkFormat
};
ImGui_ImplVulkan_Init(&initInfo);
(void)accessTrophyOverlay(); // Should be called there to avoid initialization inside NewFrame()
m_isInit = true;
}
@ -131,7 +136,8 @@ void OverlayHandler::submit(ImageData const& imageData) {
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
draw();
ImGui::EndFrame();
ImGui::Render();
ImDrawData* drawData = ImGui::GetDrawData();
@ -162,4 +168,5 @@ void OverlayHandler::submit(ImageData const& imageData) {
void OverlayHandler::draw() {
// ImGui::ShowDemoWindow();
}
accessTrophyOverlay().draw(m_imageHandler->getFPS());
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "../imageHandler.h"
#include "../vulkan/vulkanSetup.h"
#include "core/videoout/vulkan/vulkanTypes.h"
#include "utility/utility.h"
@ -24,5 +25,5 @@ class IOverlayHandler {
virtual void processEvent(SDL_Event const* event) = 0;
};
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue,
VkFormat displayFormat);
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, std::shared_ptr<IImageHandler>& imageHandler,
SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat);

View File

@ -0,0 +1,132 @@
#include "overtrophy.h"
#include "core/trophies/trophies.h"
#include <imgui/imgui.h>
class OverTrophy: public IOverTrophy {
struct notify {
float slide = 1.0f;
float timer = 5.0f;
bool animdone = false;
uint8_t grade;
std::string title;
std::string subtext;
void* pngdata;
size_t pngsize;
~notify() {
if (pngdata != nullptr) ::free(pngdata);
}
};
std::vector<notify> m_notifications = {};
ImFont* m_defaultFont;
ImFont* m_titleFont;
ImFont* m_textFont;
ImFont* CreateFont(float px) {
ImGuiIO& io = ImGui::GetIO();
ImFontConfig cfg;
cfg.SizePixels = px;
cfg.OversampleH = cfg.OversampleV = 1;
cfg.PixelSnapH = true;
return io.Fonts->AddFontDefault(&cfg);
}
public:
OverTrophy() {
m_defaultFont = CreateFont(13);
m_titleFont = CreateFont(20);
m_textFont = CreateFont(15);
accessTrophies().addTrophyUnlockCallback([this](const void* data) {
auto unlock = (ITrophies::trp_unlock_data*)data;
addNotify(unlock->grade, unlock->name, unlock->descr);
if (unlock->platGained) addNotify('p', unlock->pname, unlock->pdescr);
});
}
void addNotify(uint8_t grade, std::string title, std::string details) {
m_notifications.emplace_back(0.0f, 5.0f, false, grade, std::move(title), std::move(details), nullptr, 0ull);
}
void draw(double fps) final {
fps = std::max(1.0, fps);
const double delta = (1 / fps);
const float dsw = ImGui::GetIO().DisplaySize.x;
const float slidemod = delta * 2.78f;
float wpos = 0.0f;
for (auto it = m_notifications.begin(); it != m_notifications.end();) {
auto& notify = *it;
if (notify.animdone == false) {
if (notify.slide < 1.0f) {
notify.slide += slidemod;
} else if (notify.slide > 1.0f) {
notify.animdone = true;
notify.slide = 1.0f;
}
} else {
if ((notify.timer -= delta) < 0.0f) {
if (notify.slide > 0.0f) {
notify.slide -= slidemod;
} else {
it = m_notifications.erase(it);
continue;
}
}
}
const char* title;
switch (notify.grade) {
case 'b': {
title = "Bronze trophy unlocked!";
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(199, 124, 48, 255));
} break;
case 's': {
title = "Silver trophy unlocked!";
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(150, 164, 182, 255));
} break;
case 'g': {
title = "Gold trophy unlocked!";
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(228, 194, 78, 255));
} break;
case 'p': {
title = "Platinum trophy unlocked!";
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(191, 191, 191, 255));
} break;
}
ImGui::PushFont(m_defaultFont);
ImGui::SetNextWindowPos(ImVec2(dsw - 360 * notify.slide, wpos + 10.0f));
ImGui::SetNextWindowSize(ImVec2(350, 0));
ImGui::Begin(title, nullptr,
ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoFocusOnAppearing);
ImGui::PopStyleColor();
ImGui::PushFont(m_titleFont);
ImGui::Text("%s", notify.title.c_str());
ImGui::PopFont();
ImGui::PushFont(m_textFont);
ImGui::TextWrapped("%s", notify.subtext.c_str());
ImGui::PopFont();
wpos += ImGui::GetWindowHeight() + 10.0f;
ImGui::End();
ImGui::PopFont();
++it;
}
}
};
IOverTrophy& accessTrophyOverlay() {
static OverTrophy ot;
return ot;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "utility/utility.h"
class IOverTrophy {
CLASS_NO_COPY(IOverTrophy);
CLASS_NO_MOVE(IOverTrophy);
public:
IOverTrophy() = default;
~IOverTrophy() = default;
virtual void draw(double fps) = 0;
};
IOverTrophy& accessTrophyOverlay();

View File

@ -220,7 +220,7 @@ class VideoOut: public IVideoOut, private IEventsGraphics {
std::unique_ptr<IGraphics> m_graphics;
std::unique_ptr<IImageHandler> m_imageHandler;
std::shared_ptr<IImageHandler> m_imageHandler;
std::unique_ptr<IOverlayHandler> m_overlayHandler;
std::thread m_threadSDL2;
@ -992,7 +992,7 @@ std::thread VideoOut::createSDLThread() {
m_imageHandler->init(m_vulkanObj, window.surface);
auto [format, _] = vulkan::getDisplayFormat(m_vulkanObj);
m_overlayHandler = createOverlay(m_vulkanObj->deviceInfo, window.window, queue, format);
m_overlayHandler = createOverlay(m_vulkanObj->deviceInfo, m_imageHandler, window.window, queue, format);
*item.result = 0;
} else {
@ -1019,18 +1019,12 @@ std::thread VideoOut::createSDLThread() {
lock.lock();
}
m_graphics->submitDone();
auto& timer = accessTimer();
auto const curTime = (uint64_t)(1e6 * timer.getTimeS());
auto const procTime = timer.queryPerformance();
auto elapsed_us = curTime - flipStatus.processTime;
m_imageHandler->calc_fps(flipStatus.processTime);
doFlip(window, 1 + handleIndex);
double const fps = (window.config.fps * 5.0 + (1e6 / (double)elapsed_us)) / 6.0;
auto title = getTitle(1 + handleIndex, flipStatus.count, round(fps), window.fliprate);
window.config.fps = fps;
window.config.fps = m_imageHandler->getFPS();
auto title = getTitle(1 + handleIndex, flipStatus.count, round(window.config.fps), window.fliprate);
SDL_SetWindowTitle(window.window, title.c_str());
func_pollSDL(window.window);

View File

@ -10,6 +10,7 @@
#include "core/timer/timer.h"
#include "core/videoout/videoout.h"
#include "logging.h"
#include "utility/progloc.h"
#include <chrono>
#include <filesystem>
@ -113,11 +114,12 @@ int main(int argc, char** argv) {
// -
std::filesystem::path const dirSaveFiles = [&] {
auto root = util::getProgramLoc();
auto value = systemContent.getString("TITLE_ID");
if (!value) {
return std::filesystem::path("GAMEFILES") / dirRoot;
return root / std::filesystem::path("GAMEFILES") / dirRoot;
}
return std::filesystem::path("GAMEFILES") / *value;
return root / std::filesystem::path("GAMEFILES") / *value;
}();
fileManager.setGameFilesDir(dirSaveFiles);

View File

@ -64,15 +64,6 @@ EXPORT SYSV_ABI int sceNpTrophyAbortHandle(SceNpTrophyHandle) {
//- Unused handles API
EXPORT SYSV_ABI int sceNpTrophyCreateContext(SceNpTrophyContext* context, int32_t userId, SceNpServiceLabel serviceLabel, uint64_t options) {
accessTrophies().addTrophyUnlockCallback([](const void* data) {
const auto* unlock = (ITrophies::trp_unlock_data*)data;
printf("Trophy \"%s\" unlocked!\n", unlock->name.c_str());
if (unlock->platGained) {
printf("========== PLATINUM TROPHY \"%s\" UNLOCKED ==========\n", unlock->pname.c_str());
}
});
*context = userId;
return accessTrophies().createContext(userId, (uint32_t)serviceLabel);
}