mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-03 16:02:26 +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
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/error_codes.h"
|
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/libraries/system/msgdialog.h"
|
#include "core/libraries/system/msgdialog.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
|
#include "msgdialog_ui.h"
|
||||||
|
|
||||||
namespace Libraries::MsgDialog {
|
namespace Libraries::MsgDialog {
|
||||||
|
|
||||||
@ -18,8 +18,8 @@ using CommonDialog::Result;
|
|||||||
using CommonDialog::Status;
|
using CommonDialog::Status;
|
||||||
|
|
||||||
static auto g_status = Status::NONE;
|
static auto g_status = Status::NONE;
|
||||||
static Param g_param{};
|
static MsgDialogState g_state{};
|
||||||
static MsgDialogResult g_result{};
|
static DialogResult g_result{};
|
||||||
static MsgDialogUi g_msg_dialog_ui;
|
static MsgDialogUi g_msg_dialog_ui;
|
||||||
|
|
||||||
Error PS4_SYSV_ABI sceMsgDialogClose() {
|
Error PS4_SYSV_ABI sceMsgDialogClose() {
|
||||||
@ -30,7 +30,7 @@ Error PS4_SYSV_ABI sceMsgDialogClose() {
|
|||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error PS4_SYSV_ABI sceMsgDialogGetResult(MsgDialogResult* result) {
|
Error PS4_SYSV_ABI sceMsgDialogGetResult(DialogResult* result) {
|
||||||
if (g_status != Status::FINISHED) {
|
if (g_status != Status::FINISHED) {
|
||||||
return Error::NOT_FINISHED;
|
return Error::NOT_FINISHED;
|
||||||
}
|
}
|
||||||
@ -66,19 +66,19 @@ Error PS4_SYSV_ABI sceMsgDialogInitialize() {
|
|||||||
return Error::OK;
|
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) {
|
if (g_status != Status::INITIALIZED && g_status != Status::FINISHED) {
|
||||||
return Error::INVALID_STATE;
|
return Error::INVALID_STATE;
|
||||||
}
|
}
|
||||||
if (param == nullptr) {
|
if (param == nullptr) {
|
||||||
return Error::ARG_NULL;
|
return Error::ARG_NULL;
|
||||||
}
|
}
|
||||||
ASSERT(param->size == sizeof(Param));
|
ASSERT(param->size == sizeof(OrbisParam));
|
||||||
ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam));
|
ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam));
|
||||||
g_status = Status::RUNNING;
|
|
||||||
g_param = *param;
|
|
||||||
g_result = {};
|
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;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,13 +86,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget ta
|
|||||||
if (g_status != Status::RUNNING) {
|
if (g_status != Status::RUNNING) {
|
||||||
return Error::NOT_RUNNING;
|
return Error::NOT_RUNNING;
|
||||||
}
|
}
|
||||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||||
return Error::NOT_SUPPORTED;
|
return Error::NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||||
return Error::PARAM_INVALID;
|
return Error::PARAM_INVALID;
|
||||||
}
|
}
|
||||||
g_msg_dialog_ui.SetProgressBarValue(delta, true);
|
g_state.GetState<MsgDialogState::ProgressState>().progress += delta;
|
||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,13 +101,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget
|
|||||||
if (g_status != Status::RUNNING) {
|
if (g_status != Status::RUNNING) {
|
||||||
return Error::NOT_RUNNING;
|
return Error::NOT_RUNNING;
|
||||||
}
|
}
|
||||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||||
return Error::NOT_SUPPORTED;
|
return Error::NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||||
return Error::PARAM_INVALID;
|
return Error::PARAM_INVALID;
|
||||||
}
|
}
|
||||||
g_param.progBarParam->msg = msg;
|
g_state.GetState<MsgDialogState::ProgressState>().msg = msg;
|
||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,13 +116,13 @@ Error PS4_SYSV_ABI sceMsgDialogProgressBarSetValue(OrbisMsgDialogProgressBarTarg
|
|||||||
if (g_status != Status::RUNNING) {
|
if (g_status != Status::RUNNING) {
|
||||||
return Error::NOT_RUNNING;
|
return Error::NOT_RUNNING;
|
||||||
}
|
}
|
||||||
if (g_param.mode != MsgDialogMode::PROGRESS_BAR) {
|
if (g_state.GetMode() != MsgDialogMode::PROGRESS_BAR) {
|
||||||
return Error::NOT_SUPPORTED;
|
return Error::NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
if (target != OrbisMsgDialogProgressBarTarget::DEFAULT) {
|
||||||
return Error::PARAM_INVALID;
|
return Error::PARAM_INVALID;
|
||||||
}
|
}
|
||||||
g_msg_dialog_ui.SetProgressBarValue(value, false);
|
g_state.GetState<MsgDialogState::ProgressState>().progress = value;
|
||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/fixed_value.h"
|
|
||||||
#include "common/types.h"
|
|
||||||
#include "core/libraries/system/commondialog.h"
|
#include "core/libraries/system/commondialog.h"
|
||||||
#include "imgui/imgui_layer.h"
|
|
||||||
|
|
||||||
namespace Core::Loader {
|
namespace Core::Loader {
|
||||||
class SymbolsResolver;
|
class SymbolsResolver;
|
||||||
@ -14,133 +11,15 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::MsgDialog {
|
namespace Libraries::MsgDialog {
|
||||||
|
|
||||||
using OrbisUserServiceUserId = s32;
|
struct DialogResult;
|
||||||
|
struct OrbisParam;
|
||||||
enum class MsgDialogMode : u32 {
|
enum class OrbisMsgDialogProgressBarTarget : 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogClose();
|
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::Status PS4_SYSV_ABI sceMsgDialogGetStatus();
|
||||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogInitialize();
|
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,
|
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarInc(OrbisMsgDialogProgressBarTarget,
|
||||||
u32 delta);
|
u32 delta);
|
||||||
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget,
|
CommonDialog::Error PS4_SYSV_ABI sceMsgDialogProgressBarSetMsg(OrbisMsgDialogProgressBarTarget,
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "imgui/imgui_std.h"
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "msgdialog.h"
|
#include "imgui/imgui_std.h"
|
||||||
|
#include "msgdialog_ui.h"
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
using namespace Libraries::CommonDialog;
|
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) {
|
static void DrawCenteredText(const char* text) {
|
||||||
const auto ws = GetWindowSize();
|
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);
|
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);
|
Text("%s", text);
|
||||||
PopTextWrapPos();
|
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() {
|
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();
|
const auto ws = GetWindowSize();
|
||||||
DrawCenteredText(msg);
|
DrawCenteredText(msg.c_str());
|
||||||
ASSERT(button_type <= ButtonType::TWO_BUTTONS);
|
ASSERT(button_type <= ButtonType::TWO_BUTTONS);
|
||||||
auto [count, text1, text2] = user_button_texts[static_cast<u32>(button_type)];
|
auto [count, text1, text2] = user_button_texts[static_cast<u32>(button_type)];
|
||||||
if (count == 0xFF) { // TWO_BUTTONS -> User defined message
|
if (count == 0xFF) { // TWO_BUTTONS -> User defined message
|
||||||
count = 2;
|
count = 2;
|
||||||
text1 = btn_param->msg1;
|
text1 = btn_param1.c_str();
|
||||||
text2 = btn_param->msg2;
|
text2 = btn_param2.c_str();
|
||||||
}
|
}
|
||||||
const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO;
|
const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO;
|
||||||
SetCursorPos({
|
SetCursorPos({
|
||||||
@ -74,8 +115,8 @@ void MsgDialogUi::DrawUser() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!focus_first) {
|
if (first_render && !focus_first) {
|
||||||
SetItemDefaultNav();
|
SetItemCurrentNavFocus();
|
||||||
}
|
}
|
||||||
PopID();
|
PopID();
|
||||||
SameLine();
|
SameLine();
|
||||||
@ -84,8 +125,8 @@ void MsgDialogUi::DrawUser() {
|
|||||||
if (Button(text1, BUTTON_SIZE)) {
|
if (Button(text1, BUTTON_SIZE)) {
|
||||||
Finish(ButtonId::BUTTON1);
|
Finish(ButtonId::BUTTON1);
|
||||||
}
|
}
|
||||||
if (focus_first) {
|
if (first_render && focus_first) {
|
||||||
SetItemDefaultNav();
|
SetItemCurrentNavFocus();
|
||||||
}
|
}
|
||||||
PopID();
|
PopID();
|
||||||
SameLine();
|
SameLine();
|
||||||
@ -94,25 +135,29 @@ void MsgDialogUi::DrawUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MsgDialogUi::DrawProgressBar() {
|
void MsgDialogUi::DrawProgressBar() {
|
||||||
const auto& [bar_type, msg, _] = *param->progBarParam;
|
const auto& [bar_type, msg, progress_bar_value] =
|
||||||
DrawCenteredText(msg);
|
state->GetState<MsgDialogState::ProgressState>();
|
||||||
|
DrawCenteredText(msg.c_str());
|
||||||
const auto ws = GetWindowSize();
|
const auto ws = GetWindowSize();
|
||||||
SetCursorPos({
|
SetCursorPos({
|
||||||
ws.x * ((1 - PROGRESS_BAR_WIDTH) / 2.0f),
|
ws.x * ((1 - PROGRESS_BAR_WIDTH) / 2.0f),
|
||||||
ws.y - 10.0f - BUTTON_SIZE.y,
|
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;
|
float bar_width = PROGRESS_BAR_WIDTH * ws.x;
|
||||||
if (has_cancel) {
|
if (has_cancel) {
|
||||||
bar_width -= BUTTON_SIZE.x - 10.0f;
|
bar_width -= BUTTON_SIZE.x - 10.0f;
|
||||||
}
|
}
|
||||||
BeginGroup();
|
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) {
|
if (has_cancel) {
|
||||||
SameLine();
|
SameLine();
|
||||||
if (Button("Cancel", BUTTON_SIZE)) {
|
if (Button("Cancel", BUTTON_SIZE)) {
|
||||||
Finish(ButtonId::INVALID, Result::USER_CANCELED);
|
Finish(ButtonId::INVALID, Result::USER_CANCELED);
|
||||||
}
|
}
|
||||||
|
if (first_render) {
|
||||||
|
SetItemCurrentNavFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EndGroup();
|
EndGroup();
|
||||||
}
|
}
|
||||||
@ -132,7 +177,7 @@ static_assert(std::size(system_message_texts) ==
|
|||||||
|
|
||||||
void MsgDialogUi::DrawSystemMessage() {
|
void MsgDialogUi::DrawSystemMessage() {
|
||||||
// TODO: Implement go to settings & user profile
|
// 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);
|
ASSERT(msg_type <= SystemMessageType::WARNING_PROFILE_PICTURE_AND_NAME_NOT_SHARED);
|
||||||
auto [msg] = system_message_texts[static_cast<u32>(msg_type)];
|
auto [msg] = system_message_texts[static_cast<u32>(msg_type)];
|
||||||
DrawCenteredText(msg);
|
DrawCenteredText(msg);
|
||||||
@ -144,15 +189,15 @@ void MsgDialogUi::DrawSystemMessage() {
|
|||||||
if (Button("OK", BUTTON_SIZE)) {
|
if (Button("OK", BUTTON_SIZE)) {
|
||||||
Finish(ButtonId::OK);
|
Finish(ButtonId::OK);
|
||||||
}
|
}
|
||||||
|
if (first_render) {
|
||||||
|
SetItemCurrentNavFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgDialogUi::MsgDialogUi(const Param* param, Status* status, MsgDialogResult* result)
|
MsgDialogUi::MsgDialogUi(MsgDialogState* state, Status* status, DialogResult* result)
|
||||||
: dialog_unique_id([] {
|
: state(state), status(status), result(result) {
|
||||||
static s32 last_id = 0;
|
|
||||||
return ++last_id;
|
|
||||||
}()),
|
|
||||||
param(param), status(status), result(result) {
|
|
||||||
if (status && *status == Status::RUNNING) {
|
if (status && *status == Status::RUNNING) {
|
||||||
|
first_render = true;
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,20 +205,18 @@ MsgDialogUi::~MsgDialogUi() {
|
|||||||
Finish(ButtonId::INVALID);
|
Finish(ButtonId::INVALID);
|
||||||
}
|
}
|
||||||
MsgDialogUi::MsgDialogUi(MsgDialogUi&& other) noexcept
|
MsgDialogUi::MsgDialogUi(MsgDialogUi&& other) noexcept
|
||||||
: Layer(other), dialog_unique_id(other.dialog_unique_id), param(other.param),
|
: Layer(other), state(other.state), status(other.status), result(other.result) {
|
||||||
status(other.status), result(other.result) {
|
other.state = nullptr;
|
||||||
other.dialog_unique_id = 0;
|
|
||||||
other.param = nullptr;
|
|
||||||
other.status = nullptr;
|
other.status = nullptr;
|
||||||
other.result = nullptr;
|
other.result = nullptr;
|
||||||
}
|
}
|
||||||
MsgDialogUi& MsgDialogUi::operator=(MsgDialogUi other) {
|
MsgDialogUi& MsgDialogUi::operator=(MsgDialogUi other) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(dialog_unique_id, other.dialog_unique_id);
|
swap(state, other.state);
|
||||||
swap(param, other.param);
|
|
||||||
swap(status, other.status);
|
swap(status, other.status);
|
||||||
swap(result, other.result);
|
swap(result, other.result);
|
||||||
if (status && *status == Status::RUNNING) {
|
if (status && *status == Status::RUNNING) {
|
||||||
|
first_render = true;
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -187,20 +230,12 @@ void MsgDialogUi::Finish(ButtonId buttonId, Result r) {
|
|||||||
if (status) {
|
if (status) {
|
||||||
*status = Status::FINISHED;
|
*status = Status::FINISHED;
|
||||||
}
|
}
|
||||||
param = nullptr;
|
state = nullptr;
|
||||||
status = nullptr;
|
status = nullptr;
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
RemoveLayer(this);
|
RemoveLayer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MsgDialogUi::SetProgressBarValue(u32 value, bool increment) {
|
|
||||||
if (increment) {
|
|
||||||
progress_bar_value += value;
|
|
||||||
} else {
|
|
||||||
progress_bar_value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MsgDialogUi::Draw() {
|
void MsgDialogUi::Draw() {
|
||||||
if (status == nullptr || *status != Status::RUNNING) {
|
if (status == nullptr || *status != Status::RUNNING) {
|
||||||
return;
|
return;
|
||||||
@ -218,14 +253,9 @@ void MsgDialogUi::Draw() {
|
|||||||
SetNextWindowCollapsed(false);
|
SetNextWindowCollapsed(false);
|
||||||
KeepNavHighlight();
|
KeepNavHighlight();
|
||||||
// Hack to allow every dialog to have a unique window
|
// Hack to allow every dialog to have a unique window
|
||||||
#define TITLE "Message Dialog##MD"
|
if (Begin("Message Dialog##MessageDialog", nullptr,
|
||||||
char id[sizeof(TITLE) + sizeof(int)] = TITLE "\0\0\0\0";
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
*reinterpret_cast<int*>(&id[sizeof(TITLE) - 1]) =
|
switch (state->GetMode()) {
|
||||||
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) {
|
|
||||||
case MsgDialogMode::USER_MSG:
|
case MsgDialogMode::USER_MSG:
|
||||||
DrawUser();
|
DrawUser();
|
||||||
break;
|
break;
|
||||||
@ -238,4 +268,6 @@ void MsgDialogUi::Draw() {
|
|||||||
}
|
}
|
||||||
End();
|
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;
|
GetCurrentContext()->NavDisableHighlight = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetItemDefaultNav() {
|
inline void SetItemCurrentNavFocus() {
|
||||||
if (IsWindowAppearing()) {
|
|
||||||
const auto ctx = GetCurrentContext();
|
const auto ctx = GetCurrentContext();
|
||||||
SetFocusID(ctx->LastItemData.ID, ctx->CurrentWindow);
|
SetFocusID(ctx->LastItemData.ID, ctx->CurrentWindow);
|
||||||
ctx->NavInitResult.Clear();
|
ctx->NavInitResult.Clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ImGui
|
} // namespace ImGui
|
||||||
|
Loading…
Reference in New Issue
Block a user