diff --git a/src/core/libraries/np/np_profile_dialog/np_profile_dialog.cpp b/src/core/libraries/np/np_profile_dialog/np_profile_dialog.cpp index 0382d223c..6163a7096 100644 --- a/src/core/libraries/np/np_profile_dialog/np_profile_dialog.cpp +++ b/src/core/libraries/np/np_profile_dialog/np_profile_dialog.cpp @@ -7,19 +7,30 @@ #include "core/libraries/libs.h" #include "magic_enum/magic_enum.hpp" #include "np_profile_dialog.h" +#include "np_profile_dialog_ui.h" namespace Libraries::Np::NpProfileDialog { static auto g_status = Libraries::CommonDialog::Status::NONE; +static NpProfileDialogState g_state{}; +// static DialogResult g_result{}; +static int g_result = 0; // TODO use real result when implementing dialog +static NpProfileDialogUi g_profile_dialog_ui; -Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogOpen(void* param) { +Libraries::CommonDialog::Error PS4_SYSV_ABI +sceNpProfileDialogOpen(OrbisNpProfileDialogParam* param) { if (g_status != Libraries::CommonDialog::Status::INITIALIZED && g_status != Libraries::CommonDialog::Status::FINISHED) { LOG_INFO(Lib_NpProfileDialog, "called without initialize"); return Libraries::CommonDialog::Error::INVALID_STATE; } LOG_ERROR(Lib_NpProfileDialog, "(STUBBED) called"); // TODO open ui dialog + NpProfileDialogState state{}; + state.onlineId = std::string(param->targetOnlineId.data); + state.userId = param->userId; + g_state = state; g_status = Libraries::CommonDialog::Status::RUNNING; + g_profile_dialog_ui = NpProfileDialogUi(&g_state, &g_result); return Libraries::CommonDialog::Error::OK; } @@ -58,7 +69,7 @@ Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogInitialize() { return Libraries::CommonDialog::Error::OK; } -s32 PS4_SYSV_ABI sceNpProfileDialogOpenA() { +s32 PS4_SYSV_ABI sceNpProfileDialogOpenA(OrbisNpProfileDialogParamA* param) { LOG_ERROR(Lib_NpProfileDialog, "(STUBBED) called"); return ORBIS_OK; } diff --git a/src/core/libraries/np/np_profile_dialog/np_profile_dialog.h b/src/core/libraries/np/np_profile_dialog/np_profile_dialog.h index d991ce68c..db27d1e3f 100644 --- a/src/core/libraries/np/np_profile_dialog/np_profile_dialog.h +++ b/src/core/libraries/np/np_profile_dialog/np_profile_dialog.h @@ -4,7 +4,9 @@ #pragma once #include +#include #include "common/types.h" +#include "core/libraries/np/np_types.h" namespace Core::Loader { class SymbolsResolver; @@ -12,12 +14,48 @@ class SymbolsResolver; namespace Libraries::Np::NpProfileDialog { -Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogOpen(void* param); +enum class OrbisNpProfileDialogMode : u32 { + ORBIS_NP_PROFILE_DIALOG_MODE_INVALID = 0, + ORBIS_NP_PROFILE_DIALOG_MODE_NORMAL = 1, +}; + +struct OrbisNpProfileDialogParam { + CommonDialog::BaseParam baseParam; + u64 size; + OrbisNpProfileDialogMode mode; + Libraries::UserService::OrbisUserServiceUserId userId; + Libraries::Np::OrbisNpOnlineId targetOnlineId; + void* userData; + u8 reserved[32]; +}; + +struct OrbisNpProfileGriefReportParam { + s32 reportItem; + u8 reserved[28]; +}; + +struct OrbisNpProfileDialogParamA { + CommonDialog::BaseParam baseParam; + u64 size; + OrbisNpProfileDialogMode mode; + Libraries::UserService::OrbisUserServiceUserId userId; + Libraries::Np::OrbisNpAccountId targetAccountId; + int : 32; + void* userData; + union { + uint8_t reserved[32]; + OrbisNpProfileGriefReportParam griefReportParam; + }; +}; + + +Libraries::CommonDialog::Error PS4_SYSV_ABI +sceNpProfileDialogOpen(OrbisNpProfileDialogParam* param); Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogClose(); s32 PS4_SYSV_ABI sceNpProfileDialogGetResult(); Libraries::CommonDialog::Status PS4_SYSV_ABI sceNpProfileDialogGetStatus(); Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogInitialize(); -s32 PS4_SYSV_ABI sceNpProfileDialogOpenA(); +s32 PS4_SYSV_ABI sceNpProfileDialogOpenA(OrbisNpProfileDialogParamA* param); Libraries::CommonDialog::Error PS4_SYSV_ABI sceNpProfileDialogTerminate(); Libraries::CommonDialog::Status PS4_SYSV_ABI sceNpProfileDialogUpdateStatus(); diff --git a/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.cpp b/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.cpp new file mode 100644 index 000000000..1febed259 --- /dev/null +++ b/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.cpp @@ -0,0 +1,97 @@ +#include "common/logging/log.h" // optional, for debug +#include "np_profile_dialog_ui.h" +#include +#include + +#include +#include +using namespace ImGui; + +namespace Libraries::Np::NpProfileDialog { + +static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; + +NpProfileDialogUi::NpProfileDialogUi(NpProfileDialogState* state, int* result) + : state(state), result(result) { + if (state) { + first_render = true; + AddLayer(this); // register in Layer system + } +} + +NpProfileDialogUi::~NpProfileDialogUi() { + Finish(0); +} + +NpProfileDialogUi::NpProfileDialogUi(NpProfileDialogUi&& other) noexcept + : Layer(other), state(other.state), result(other.result) { + other.state = nullptr; + other.result = nullptr; +} + +NpProfileDialogUi& NpProfileDialogUi::operator=(NpProfileDialogUi other) { + using std::swap; + swap(state, other.state); + swap(result, other.result); + if (state) { + first_render = true; + AddLayer(this); + } + return *this; +} + +void NpProfileDialogUi::Finish(int result_code) { + if (result) { + *result = result_code; // 0 = OK + } + state = nullptr; + result = nullptr; + RemoveLayer(this); // unregister from Layer system +} + +void NpProfileDialogUi::Draw() { + if (!state) + return; + + const auto& io = GetIO(); + ImVec2 window_size{std::min(io.DisplaySize.x, 400.0f), std::min(io.DisplaySize.y, 200.0f)}; + + CentralizeNextWindow(); + SetNextWindowSize(window_size); + SetNextWindowCollapsed(false); + if (first_render || !io.NavActive) { + SetNextWindowFocus(); + } + KeepNavHighlight(); + + if (Begin("NP Profile##NpProfileDialog", nullptr, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { + + Text("Player Profile"); + Separator(); + Spacing(); + + Text("Online ID:"); + Text("%s", state->onlineId.c_str()); + + Spacing(); + SetCursorPos({ + window_size.x / 2.0f - BUTTON_SIZE.x / 2.0f, + window_size.y - 10.0f - BUTTON_SIZE.y, + }); + + if (Button("OK", BUTTON_SIZE)) { + Finish(0); + } + + if (first_render) { + SetItemCurrentNavFocus(); + } + } + + End(); + + first_render = false; +} + +} // namespace Libraries::Np::NpProfileDialog \ No newline at end of file diff --git a/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.h b/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.h new file mode 100644 index 000000000..d3efd1346 --- /dev/null +++ b/src/core/libraries/np/np_profile_dialog/np_profile_dialog_ui.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include "common/fixed_value.h" +#include "common/types.h" +#include "core/libraries/system/commondialog.h" +#include "imgui/imgui_layer.h" + +namespace Libraries::Np::NpProfileDialog { + +struct NpProfileDialogState { + std::string onlineId; + int userId{}; +}; + +class NpProfileDialogUi : public ImGui::Layer { +public: + explicit NpProfileDialogUi(NpProfileDialogState* state = nullptr, int* result = nullptr); + ~NpProfileDialogUi(); + + NpProfileDialogUi(const NpProfileDialogUi& other) = delete; + NpProfileDialogUi(NpProfileDialogUi&& other) noexcept; + NpProfileDialogUi& operator=(NpProfileDialogUi other); + + void Draw() override; + +private: + void Finish(int result_code); + + NpProfileDialogState* state{}; + int* result{}; + bool first_render{true}; +}; + +} // namespace Libraries::Np::NpProfileDialog