mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-21 20:14:45 +00:00
system/MsgDialog: copy all ui state to local memory
handles when game release memory before close extracted all UI code to it's own file use single window instead of creating new one every single dialogOpen
This commit is contained in:
parent
299711fc9e
commit
f1218ad9f5
5 changed files with 280 additions and 194 deletions
|
@ -6,10 +6,10 @@
|
|||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/system/msgdialog.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "msgdialog_ui.h"
|
||||
|
||||
namespace Libraries::MsgDialog {
|
||||
|
||||
|
@ -18,8 +18,8 @@ using CommonDialog::Result;
|
|||
using CommonDialog::Status;
|
||||
|
||||
static auto g_status = Status::NONE;
|
||||
static Param g_param{};
|
||||
static MsgDialogResult g_result{};
|
||||
static MsgDialogState g_state{};
|
||||
static DialogResult g_result{};
|
||||
static MsgDialogUi g_msg_dialog_ui;
|
||||
|
||||
Error PS4_SYSV_ABI sceMsgDialogClose() {
|
||||
|
@ -30,7 +30,7 @@ Error PS4_SYSV_ABI sceMsgDialogClose() {
|
|||
return Error::OK;
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceMsgDialogGetResult(MsgDialogResult* result) {
|
||||
Error PS4_SYSV_ABI sceMsgDialogGetResult(DialogResult* result) {
|
||||
if (g_status != Status::FINISHED) {
|
||||
return Error::NOT_FINISHED;
|
||||
}
|
||||
|
@ -66,19 +66,19 @@ Error PS4_SYSV_ABI sceMsgDialogInitialize() {
|
|||
return Error::OK;
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceMsgDialogOpen(const Param* param) {
|
||||
Error PS4_SYSV_ABI sceMsgDialogOpen(const OrbisParam* param) {
|
||||
if (g_status != Status::INITIALIZED && g_status != Status::FINISHED) {
|
||||
return Error::INVALID_STATE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return Error::ARG_NULL;
|
||||
}
|
||||
ASSERT(param->size == sizeof(Param));
|
||||
ASSERT(param->size == sizeof(OrbisParam));
|
||||
ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam));
|
||||
g_status = Status::RUNNING;
|
||||
g_param = *param;
|
||||
g_result = {};
|
||||
g_msg_dialog_ui = MsgDialogUi(&g_param, &g_status, &g_result);
|
||||
g_state = MsgDialogState{*param};
|
||||
g_status = Status::RUNNING;
|
||||
g_msg_dialog_ui = MsgDialogUi(&g_state, &g_status, &g_result);
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
|
@ -86,13 +86,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget ta
|
|||
if (g_status != Status::RUNNING) {
|
||||
return Error::NOT_RUNNING;
|
||||
}
|
||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
||||
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||
return Error::NOT_SUPPORTED;
|
||||
}
|
||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||
return Error::PARAM_INVALID;
|
||||
}
|
||||
g_msg_dialog_ui.SetProgressBarValue(delta, true);
|
||||
g_state.GetState<MsgDialogState::ProgressState>().progress += delta;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
|
@ -101,13 +101,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget
|
|||
if (g_status != Status::RUNNING) {
|
||||
return Error::NOT_RUNNING;
|
||||
}
|
||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
||||
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||
return Error::NOT_SUPPORTED;
|
||||
}
|
||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||
return Error::PARAM_INVALID;
|
||||
}
|
||||
g_param.progBarParam->msg = msg;
|
||||
g_state.GetState<MsgDialogState::ProgressState>().msg = msg;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
|
@ -116,13 +116,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarSetValue(OrbisMsgDialogProgressBarTarg
|
|||
if (g_status != Status::RUNNING) {
|
||||
return Error::NOT_RUNNING;
|
||||
}
|
||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
||||
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||
return Error::NOT_SUPPORTED;
|
||||
}
|
||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||
return Error::PARAM_INVALID;
|
||||
}
|
||||
g_msg_dialog_ui.SetProgressBarValue(value, false);
|
||||
g_state.GetState<MsgDialogState::ProgressState>().progress = value;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "common/fixed_value.h"
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/system/commondialog.h"
|
||||
#include "imgui/imgui_layer.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
|
@ -14,133 +11,15 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::MsgDialog {
|
||||
|
||||
using OrbisUserServiceUserId = s32;
|
||||
|
||||
enum class MsgDialogMode : u32 {
|
||||
USER_MSG = 1,
|
||||
PROGRESS_BAR = 2,
|
||||
SYSTEM_MSG = 3,
|
||||
};
|
||||
|
||||
enum class ButtonId : u32 {
|
||||
INVALID = 0,
|
||||
OK = 1,
|
||||
YES = 1,
|
||||
NO = 2,
|
||||
BUTTON1 = 1,
|
||||
BUTTON2 = 2,
|
||||
};
|
||||
|
||||
enum class ButtonType : u32 {
|
||||
OK = 0,
|
||||
YESNO = 1,
|
||||
NONE = 2,
|
||||
OK_CANCEL = 3,
|
||||
WAIT = 5,
|
||||
WAIT_CANCEL = 6,
|
||||
YESNO_FOCUS_NO = 7,
|
||||
OK_CANCEL_FOCUS_CANCEL = 8,
|
||||
TWO_BUTTONS = 9,
|
||||
};
|
||||
|
||||
enum class ProgressBarType : u32 {
|
||||
PERCENTAGE = 0,
|
||||
PERCENTAGE_CANCEL = 1,
|
||||
};
|
||||
|
||||
enum class SystemMessageType : u32 {
|
||||
TRC_EMPTY_STORE = 0,
|
||||
TRC_PSN_CHAT_RESTRICTION = 1,
|
||||
TRC_PSN_UGC_RESTRICTION = 2,
|
||||
CAMERA_NOT_CONNECTED = 4,
|
||||
WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED = 5,
|
||||
};
|
||||
|
||||
enum class OrbisMsgDialogProgressBarTarget : u32 {
|
||||
DEFAULT = 0,
|
||||
};
|
||||
|
||||
struct ButtonsParam {
|
||||
const char* msg1{};
|
||||
const char* msg2{};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
struct UserMessageParam {
|
||||
ButtonType buttonType{};
|
||||
s32 : 32;
|
||||
const char* msg{};
|
||||
ButtonsParam* buttonsParam{};
|
||||
std::array<char, 24> reserved{};
|
||||
};
|
||||
|
||||
struct ProgressBarParam {
|
||||
ProgressBarType barType{};
|
||||
s32 : 32;
|
||||
const char* msg{};
|
||||
std::array<char, 64> reserved{};
|
||||
};
|
||||
|
||||
struct SystemMessageParam {
|
||||
SystemMessageType sysMsgType{};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
struct Param {
|
||||
CommonDialog::BaseParam baseParam;
|
||||
std::size_t size;
|
||||
MsgDialogMode mode;
|
||||
s32 : 32;
|
||||
UserMessageParam* userMsgParam;
|
||||
ProgressBarParam* progBarParam;
|
||||
SystemMessageParam* sysMsgParam;
|
||||
OrbisUserServiceUserId userId;
|
||||
std::array<char, 40> reserved;
|
||||
s32 : 32;
|
||||
};
|
||||
|
||||
struct MsgDialogResult {
|
||||
FixedValue<u32, 0> mode{};
|
||||
CommonDialog::Result result{CommonDialog::Result::OK};
|
||||
ButtonId buttonId{ButtonId::INVALID};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
class MsgDialogUi final : public ImGui::Layer {
|
||||
s32 dialog_unique_id;
|
||||
const Param* param{};
|
||||
CommonDialog::Status* status{};
|
||||
MsgDialogResult* result{};
|
||||
u32 progress_bar_value{};
|
||||
|
||||
void DrawUser();
|
||||
void DrawProgressBar();
|
||||
void DrawSystemMessage();
|
||||
|
||||
public:
|
||||
explicit MsgDialogUi(const Param* param = nullptr, CommonDialog::Status* status = nullptr,
|
||||
MsgDialogResult* result = nullptr);
|
||||
~MsgDialogUi() override;
|
||||
MsgDialogUi(const MsgDialogUi& other) = delete;
|
||||
MsgDialogUi(MsgDialogUi&& other) noexcept;
|
||||
MsgDialogUi& operator=(MsgDialogUi other);
|
||||
|
||||
void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK);
|
||||
|
||||
void SetProgressBarValue(u32 value, bool increment);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
bool ShouldGrabGamepad() override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct DialogResult;
|
||||
struct OrbisParam;
|
||||
enum class OrbisMsgDialogProgressBarTarget : u32;
|
||||
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogClose();
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogGetResult(MsgDialogResult* result);
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogGetResult(DialogResult* result);
|
||||
CommonDialog::Status PS4_SYSV_ABI sceMsgDialogGetStatus();
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogInitialize();
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogOpen(const Param* param);
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogOpen(const OrbisParam* param);
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget,
|
||||
u32 delta);
|
||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget,
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui/imgui_std.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "msgdialog.h"
|
||||
#include "imgui/imgui_std.h"
|
||||
#include "msgdialog_ui.h"
|
||||
|
||||
using namespace ImGui;
|
||||
using namespace Libraries::CommonDialog;
|
||||
|
@ -34,23 +33,65 @@ static_assert(std::size(user_button_texts) == static_cast<int>(ButtonType::TWO_B
|
|||
|
||||
static void DrawCenteredText(const char* text) {
|
||||
const auto ws = GetWindowSize();
|
||||
SetCursorPosY(ws.y / 2.0f - 50.0f);
|
||||
const auto text_size = CalcTextSize(text, nullptr, false, ws.x - 40.0f);
|
||||
PushTextWrapPos(ws.x - 30.0f);
|
||||
SetCursorPosX((ws.x - CalcTextSize(text, nullptr, false, ws.x - 40.0f).x) / 2.0f);
|
||||
SetCursorPos({
|
||||
(ws.x - text_size.x) / 2.0f,
|
||||
(ws.y - text_size.y) / 2.0f - 50.0f,
|
||||
});
|
||||
Text("%s", text);
|
||||
PopTextWrapPos();
|
||||
}
|
||||
|
||||
MsgDialogState::MsgDialogState(const OrbisParam& param) {
|
||||
this->mode = param.mode;
|
||||
switch (mode) {
|
||||
case MsgDialogMode::USER_MSG: {
|
||||
ASSERT(param.userMsgParam);
|
||||
const auto& v = *param.userMsgParam;
|
||||
auto state = UserState{
|
||||
.type = v.buttonType,
|
||||
.msg = std::string(v.msg),
|
||||
};
|
||||
if (v.buttonType == ButtonType::TWO_BUTTONS) {
|
||||
ASSERT(v.buttonsParam);
|
||||
state.btn_param1 = std::string(v.buttonsParam->msg1);
|
||||
state.btn_param2 = std::string(v.buttonsParam->msg2);
|
||||
}
|
||||
this->state = state;
|
||||
} break;
|
||||
case MsgDialogMode::PROGRESS_BAR: {
|
||||
ASSERT(param.progBarParam);
|
||||
const auto& v = *param.progBarParam;
|
||||
this->state = ProgressState{
|
||||
.type = v.barType,
|
||||
.msg = std::string(v.msg),
|
||||
.progress = 0,
|
||||
};
|
||||
} break;
|
||||
case MsgDialogMode::SYSTEM_MSG: {
|
||||
ASSERT(param.sysMsgParam);
|
||||
const auto& v = *param.sysMsgParam;
|
||||
this->state = SystemState{
|
||||
.type = v.sysMsgType,
|
||||
};
|
||||
} break;
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown dialog mode");
|
||||
}
|
||||
}
|
||||
|
||||
void MsgDialogUi::DrawUser() {
|
||||
const auto& [button_type, msg, btn_param, _] = *param->userMsgParam;
|
||||
const auto& [button_type, msg, btn_param1, btn_param2] =
|
||||
state->GetState<MsgDialogState::UserState>();
|
||||
const auto ws = GetWindowSize();
|
||||
DrawCenteredText(msg);
|
||||
DrawCenteredText(msg.c_str());
|
||||
ASSERT(button_type <= ButtonType::TWO_BUTTONS);
|
||||
auto [count, text1, text2] = user_button_texts[static_cast<u32>(button_type)];
|
||||
if (count == 0xFF) { // TWO_BUTTONS -> User defined message
|
||||
count = 2;
|
||||
text1 = btn_param->msg1;
|
||||
text2 = btn_param->msg2;
|
||||
text1 = btn_param1.c_str();
|
||||
text2 = btn_param2.c_str();
|
||||
}
|
||||
const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO;
|
||||
SetCursorPos({
|
||||
|
@ -74,8 +115,8 @@ void MsgDialogUi::DrawUser() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!focus_first) {
|
||||
SetItemDefaultNav();
|
||||
if (first_render && !focus_first) {
|
||||
SetItemCurrentNavFocus();
|
||||
}
|
||||
PopID();
|
||||
SameLine();
|
||||
|
@ -84,8 +125,8 @@ void MsgDialogUi::DrawUser() {
|
|||
if (Button(text1, BUTTON_SIZE)) {
|
||||
Finish(ButtonId::BUTTON1);
|
||||
}
|
||||
if (focus_first) {
|
||||
SetItemDefaultNav();
|
||||
if (first_render && focus_first) {
|
||||
SetItemCurrentNavFocus();
|
||||
}
|
||||
PopID();
|
||||
SameLine();
|
||||
|
@ -94,25 +135,29 @@ void MsgDialogUi::DrawUser() {
|
|||
}
|
||||
|
||||
void MsgDialogUi::DrawProgressBar() {
|
||||
const auto& [bar_type, msg, _] = *param->progBarParam;
|
||||
DrawCenteredText(msg);
|
||||
const auto& [bar_type, msg, progress_bar_value] =
|
||||
state->GetState<MsgDialogState::ProgressState>();
|
||||
DrawCenteredText(msg.c_str());
|
||||
const auto ws = GetWindowSize();
|
||||
SetCursorPos({
|
||||
ws.x * ((1 - PROGRESS_BAR_WIDTH) / 2.0f),
|
||||
ws.y - 10.0f - BUTTON_SIZE.y,
|
||||
});
|
||||
bool has_cancel = bar_type == ProgressBarType::PERCENTAGE_CANCEL;
|
||||
const bool has_cancel = bar_type == ProgressBarType::PERCENTAGE_CANCEL;
|
||||
float bar_width = PROGRESS_BAR_WIDTH * ws.x;
|
||||
if (has_cancel) {
|
||||
bar_width -= BUTTON_SIZE.x - 10.0f;
|
||||
}
|
||||
BeginGroup();
|
||||
ProgressBar((float)progress_bar_value / 100.0f, {bar_width, BUTTON_SIZE.y});
|
||||
ProgressBar(static_cast<float>(progress_bar_value) / 100.0f, {bar_width, BUTTON_SIZE.y});
|
||||
if (has_cancel) {
|
||||
SameLine();
|
||||
if (Button("Cancel", BUTTON_SIZE)) {
|
||||
Finish(ButtonId::INVALID, Result::USER_CANCELED);
|
||||
}
|
||||
if (first_render) {
|
||||
SetItemCurrentNavFocus();
|
||||
}
|
||||
}
|
||||
EndGroup();
|
||||
}
|
||||
|
@ -132,7 +177,7 @@ static_assert(std::size(system_message_texts) ==
|
|||
|
||||
void MsgDialogUi::DrawSystemMessage() {
|
||||
// TODO: Implement go to settings & user profile
|
||||
const auto& [msg_type, _] = *param->sysMsgParam;
|
||||
const auto& [msg_type] = state->GetState<MsgDialogState::SystemState>();
|
||||
ASSERT(msg_type <= SystemMessageType::WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED);
|
||||
auto [msg] = system_message_texts[static_cast<u32>(msg_type)];
|
||||
DrawCenteredText(msg);
|
||||
|
@ -144,15 +189,15 @@ void MsgDialogUi::DrawSystemMessage() {
|
|||
if (Button("OK", BUTTON_SIZE)) {
|
||||
Finish(ButtonId::OK);
|
||||
}
|
||||
if (first_render) {
|
||||
SetItemCurrentNavFocus();
|
||||
}
|
||||
}
|
||||
|
||||
MsgDialogUi::MsgDialogUi(const Param* param, Status* status, MsgDialogResult* result)
|
||||
: dialog_unique_id([] {
|
||||
static s32 last_id = 0;
|
||||
return ++last_id;
|
||||
}()),
|
||||
param(param), status(status), result(result) {
|
||||
MsgDialogUi::MsgDialogUi(MsgDialogState* state, Status* status, DialogResult* result)
|
||||
: state(state), status(status), result(result) {
|
||||
if (status && *status == Status::RUNNING) {
|
||||
first_render = true;
|
||||
AddLayer(this);
|
||||
}
|
||||
}
|
||||
|
@ -160,20 +205,18 @@ MsgDialogUi::~MsgDialogUi() {
|
|||
Finish(ButtonId::INVALID);
|
||||
}
|
||||
MsgDialogUi::MsgDialogUi(MsgDialogUi&& other) noexcept
|
||||
: Layer(other), dialog_unique_id(other.dialog_unique_id), param(other.param),
|
||||
status(other.status), result(other.result) {
|
||||
other.dialog_unique_id = 0;
|
||||
other.param = nullptr;
|
||||
: Layer(other), state(other.state), status(other.status), result(other.result) {
|
||||
other.state = nullptr;
|
||||
other.status = nullptr;
|
||||
other.result = nullptr;
|
||||
}
|
||||
MsgDialogUi& MsgDialogUi::operator=(MsgDialogUi other) {
|
||||
using std::swap;
|
||||
swap(dialog_unique_id, other.dialog_unique_id);
|
||||
swap(param, other.param);
|
||||
swap(state, other.state);
|
||||
swap(status, other.status);
|
||||
swap(result, other.result);
|
||||
if (status && *status == Status::RUNNING) {
|
||||
first_render = true;
|
||||
AddLayer(this);
|
||||
}
|
||||
return *this;
|
||||
|
@ -187,20 +230,12 @@ void MsgDialogUi::Finish(ButtonId buttonId, Result r) {
|
|||
if (status) {
|
||||
*status = Status::FINISHED;
|
||||
}
|
||||
param = nullptr;
|
||||
state = nullptr;
|
||||
status = nullptr;
|
||||
result = nullptr;
|
||||
RemoveLayer(this);
|
||||
}
|
||||
|
||||
void MsgDialogUi::SetProgressBarValue(u32 value, bool increment) {
|
||||
if (increment) {
|
||||
progress_bar_value += value;
|
||||
} else {
|
||||
progress_bar_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
void MsgDialogUi::Draw() {
|
||||
if (status == nullptr || *status != Status::RUNNING) {
|
||||
return;
|
||||
|
@ -218,14 +253,9 @@ void MsgDialogUi::Draw() {
|
|||
SetNextWindowCollapsed(false);
|
||||
KeepNavHighlight();
|
||||
// Hack to allow every dialog to have a unique window
|
||||
#define TITLE "Message Dialog##MD"
|
||||
char id[sizeof(TITLE) + sizeof(int)] = TITLE "\0\0\0\0";
|
||||
*reinterpret_cast<int*>(&id[sizeof(TITLE) - 1]) =
|
||||
dialog_unique_id |
|
||||
0x80808080; // keep the MSB set to extend the string length (null terminated)
|
||||
#undef TITLE
|
||||
if (Begin(id, nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) {
|
||||
switch (param->mode) {
|
||||
if (Begin("Message Dialog##MessageDialog", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) {
|
||||
switch (state->GetMode()) {
|
||||
case MsgDialogMode::USER_MSG:
|
||||
DrawUser();
|
||||
break;
|
||||
|
@ -238,4 +268,6 @@ void MsgDialogUi::Draw() {
|
|||
}
|
||||
End();
|
||||
}
|
||||
|
||||
first_render = false;
|
||||
}
|
177
src/core/libraries/system/msgdialog_ui.h
Normal file
177
src/core/libraries/system/msgdialog_ui.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "common/fixed_value.h"
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/system/commondialog.h"
|
||||
#include "imgui/imgui_layer.h"
|
||||
|
||||
namespace Libraries::MsgDialog {
|
||||
|
||||
using OrbisUserServiceUserId = s32;
|
||||
|
||||
enum class MsgDialogMode : u32 {
|
||||
USER_MSG = 1,
|
||||
PROGRESS_BAR = 2,
|
||||
SYSTEM_MSG = 3,
|
||||
};
|
||||
|
||||
enum class ButtonId : u32 {
|
||||
INVALID = 0,
|
||||
OK = 1,
|
||||
YES = 1,
|
||||
NO = 2,
|
||||
BUTTON1 = 1,
|
||||
BUTTON2 = 2,
|
||||
};
|
||||
|
||||
enum class ButtonType : u32 {
|
||||
OK = 0,
|
||||
YESNO = 1,
|
||||
NONE = 2,
|
||||
OK_CANCEL = 3,
|
||||
WAIT = 5,
|
||||
WAIT_CANCEL = 6,
|
||||
YESNO_FOCUS_NO = 7,
|
||||
OK_CANCEL_FOCUS_CANCEL = 8,
|
||||
TWO_BUTTONS = 9,
|
||||
};
|
||||
|
||||
enum class ProgressBarType : u32 {
|
||||
PERCENTAGE = 0,
|
||||
PERCENTAGE_CANCEL = 1,
|
||||
};
|
||||
|
||||
enum class SystemMessageType : u32 {
|
||||
TRC_EMPTY_STORE = 0,
|
||||
TRC_PSN_CHAT_RESTRICTION = 1,
|
||||
TRC_PSN_UGC_RESTRICTION = 2,
|
||||
CAMERA_NOT_CONNECTED = 4,
|
||||
WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED = 5,
|
||||
};
|
||||
|
||||
enum class OrbisMsgDialogProgressBarTarget : u32 {
|
||||
DEFAULT = 0,
|
||||
};
|
||||
|
||||
struct ButtonsParam {
|
||||
const char* msg1{};
|
||||
const char* msg2{};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
struct UserMessageParam {
|
||||
ButtonType buttonType{};
|
||||
s32 : 32;
|
||||
const char* msg{};
|
||||
ButtonsParam* buttonsParam{};
|
||||
std::array<char, 24> reserved{};
|
||||
};
|
||||
|
||||
struct ProgressBarParam {
|
||||
ProgressBarType barType{};
|
||||
s32 : 32;
|
||||
const char* msg{};
|
||||
std::array<char, 64> reserved{};
|
||||
};
|
||||
|
||||
struct SystemMessageParam {
|
||||
SystemMessageType sysMsgType{};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
struct OrbisParam {
|
||||
CommonDialog::BaseParam baseParam;
|
||||
std::size_t size;
|
||||
MsgDialogMode mode;
|
||||
s32 : 32;
|
||||
UserMessageParam* userMsgParam;
|
||||
ProgressBarParam* progBarParam;
|
||||
SystemMessageParam* sysMsgParam;
|
||||
OrbisUserServiceUserId userId;
|
||||
std::array<char, 40> reserved;
|
||||
s32 : 32;
|
||||
};
|
||||
|
||||
struct DialogResult {
|
||||
FixedValue<u32, 0> mode{};
|
||||
CommonDialog::Result result{CommonDialog::Result::OK};
|
||||
ButtonId buttonId{ButtonId::INVALID};
|
||||
std::array<char, 32> reserved{};
|
||||
};
|
||||
|
||||
// State is used to copy all the data from the param struct
|
||||
class MsgDialogState {
|
||||
public:
|
||||
struct UserState {
|
||||
ButtonType type{};
|
||||
std::string msg{};
|
||||
std::string btn_param1{};
|
||||
std::string btn_param2{};
|
||||
};
|
||||
struct ProgressState {
|
||||
ProgressBarType type{};
|
||||
std::string msg{};
|
||||
u32 progress{};
|
||||
};
|
||||
struct SystemState {
|
||||
SystemMessageType type{};
|
||||
};
|
||||
|
||||
private:
|
||||
OrbisUserServiceUserId user_id{};
|
||||
MsgDialogMode mode{};
|
||||
std::variant<UserState, ProgressState, SystemState, std::monostate> state{std::monostate{}};
|
||||
|
||||
public:
|
||||
explicit MsgDialogState(const OrbisParam& param);
|
||||
MsgDialogState() = default;
|
||||
|
||||
[[nodiscard]] OrbisUserServiceUserId GetUserId() const {
|
||||
return user_id;
|
||||
}
|
||||
|
||||
[[nodiscard]] MsgDialogMode GetMode() const {
|
||||
return mode;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] T& GetState() {
|
||||
return std::get<T>(state);
|
||||
}
|
||||
};
|
||||
|
||||
class MsgDialogUi final : public ImGui::Layer {
|
||||
bool first_render{false};
|
||||
MsgDialogState* state{};
|
||||
CommonDialog::Status* status{};
|
||||
DialogResult* result{};
|
||||
|
||||
void DrawUser();
|
||||
void DrawProgressBar();
|
||||
void DrawSystemMessage();
|
||||
|
||||
public:
|
||||
explicit MsgDialogUi(MsgDialogState* state = nullptr, CommonDialog::Status* status = nullptr,
|
||||
DialogResult* result = nullptr);
|
||||
~MsgDialogUi() override;
|
||||
MsgDialogUi(const MsgDialogUi& other) = delete;
|
||||
MsgDialogUi(MsgDialogUi&& other) noexcept;
|
||||
MsgDialogUi& operator=(MsgDialogUi other);
|
||||
|
||||
void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK);
|
||||
|
||||
void SetProgressBarValue(u32 value, bool increment);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
bool ShouldGrabGamepad() override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace Libraries::MsgDialog
|
|
@ -18,12 +18,10 @@ inline void KeepNavHighlight() {
|
|||
GetCurrentContext()->NavDisableHighlight = false;
|
||||
}
|
||||
|
||||
inline void SetItemDefaultNav() {
|
||||
if (IsWindowAppearing()) {
|
||||
const auto ctx = GetCurrentContext();
|
||||
SetFocusID(ctx->LastItemData.ID, ctx->CurrentWindow);
|
||||
ctx->NavInitResult.Clear();
|
||||
}
|
||||
inline void SetItemCurrentNavFocus() {
|
||||
const auto ctx = GetCurrentContext();
|
||||
SetFocusID(ctx->LastItemData.ID, ctx->CurrentWindow);
|
||||
ctx->NavInitResult.Clear();
|
||||
}
|
||||
|
||||
} // namespace ImGui
|
||||
|
|
Loading…
Add table
Reference in a new issue