mirror of
https://github.com/SysRay/psOff_public.git
synced 2024-10-07 03:43:54 +00:00
Trophy overlay
This commit is contained in:
parent
91bc43b2d8
commit
8eab15adcd
@ -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>
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
)
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
132
core/videoout/overlay/overtrophy/overtrophy.cpp
Normal file
132
core/videoout/overlay/overtrophy/overtrophy.cpp
Normal 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;
|
||||
}
|
16
core/videoout/overlay/overtrophy/overtrophy.h
Normal file
16
core/videoout/overlay/overtrophy/overtrophy.h
Normal 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();
|
@ -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);
|
||||
|
6
main.cpp
6
main.cpp
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user