mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-02 23:42:43 +00:00
system/MsgDialog: RAII for MsgDialog ui
This commit is contained in:
parent
8c1a6fbb5e
commit
ad57ab8fee
@ -204,6 +204,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/system/commondialog.h
|
src/core/libraries/system/commondialog.h
|
||||||
src/core/libraries/system/msgdialog.cpp
|
src/core/libraries/system/msgdialog.cpp
|
||||||
src/core/libraries/system/msgdialog.h
|
src/core/libraries/system/msgdialog.h
|
||||||
|
src/core/libraries/system/msgdialog_ui.cpp
|
||||||
src/core/libraries/system/posix.cpp
|
src/core/libraries/system/posix.cpp
|
||||||
src/core/libraries/system/posix.h
|
src/core/libraries/system/posix.h
|
||||||
src/core/libraries/save_data/error_codes.h
|
src/core/libraries/save_data/error_codes.h
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#include "core/libraries/error_codes.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/imgui_layer.h"
|
|
||||||
#include "imgui/imgui_std.h"
|
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
|
|
||||||
namespace Libraries::MsgDialog {
|
namespace Libraries::MsgDialog {
|
||||||
@ -19,240 +17,16 @@ using CommonDialog::Error;
|
|||||||
using CommonDialog::Result;
|
using CommonDialog::Result;
|
||||||
using CommonDialog::Status;
|
using CommonDialog::Status;
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
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{};
|
|
||||||
Result result{Result::OK};
|
|
||||||
ButtonId buttonId{ButtonId::INVALID};
|
|
||||||
std::array<char, 32> reserved{};
|
|
||||||
};
|
|
||||||
|
|
||||||
static auto g_status = Status::NONE;
|
static auto g_status = Status::NONE;
|
||||||
|
static Param g_param{};
|
||||||
static MsgDialogResult g_result{};
|
static MsgDialogResult g_result{};
|
||||||
|
static MsgDialogUi g_msg_dialog_ui;
|
||||||
struct {
|
|
||||||
int count = 0;
|
|
||||||
const char* text1;
|
|
||||||
const char* text2;
|
|
||||||
} static constexpr button_texts[] = {
|
|
||||||
{1, "OK"}, // 0 OK
|
|
||||||
{2, "Yes", "No"}, // 1 YESNO
|
|
||||||
{0}, // 2 NONE
|
|
||||||
{2, "OK", "Cancel"}, // 3 OK_CANCEL
|
|
||||||
{}, // 4 !!NOP
|
|
||||||
{1, "Wait"}, // 5 WAIT
|
|
||||||
{2, "Wait", "Cancel"}, // 6 WAIT_CANCEL
|
|
||||||
{2, "Yes", "No"}, // 7 YESNO_FOCUS_NO
|
|
||||||
{2, "OK", "Cancel"}, // 8 OK_CANCEL_FOCUS_CANCEL
|
|
||||||
{0xFF}, // 9 TWO_BUTTONS
|
|
||||||
};
|
|
||||||
static_assert(std::size(button_texts) == static_cast<int>(ButtonType::TWO_BUTTONS) + 1);
|
|
||||||
|
|
||||||
static void Finish(ButtonId buttonId);
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
using namespace ImGui;
|
|
||||||
class MsgDialogGui final : public Layer {
|
|
||||||
const Param* param{};
|
|
||||||
s32 dialog_unique_id{};
|
|
||||||
|
|
||||||
void DrawUser(const UserMessageParam& user_message_param) {
|
|
||||||
constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f};
|
|
||||||
|
|
||||||
const auto ws = GetWindowSize();
|
|
||||||
SetCursorPosY(ws.y / 2.0f - 50.0f);
|
|
||||||
PushTextWrapPos(ws.x - 30.0f);
|
|
||||||
SetCursorPosX(
|
|
||||||
(ws.x - CalcTextSize(user_message_param.msg, nullptr, false, ws.x - 40.0f).x) / 2.0f);
|
|
||||||
Text("%s", user_message_param.msg);
|
|
||||||
PopTextWrapPos();
|
|
||||||
const auto button_type = user_message_param.buttonType;
|
|
||||||
ASSERT(user_message_param.buttonType <= ButtonType::TWO_BUTTONS);
|
|
||||||
auto [count, text1, text2] = button_texts[static_cast<u32>(button_type)];
|
|
||||||
if (count == 0xFF) { // TWO_BUTTONS -> User defined message
|
|
||||||
count = 2;
|
|
||||||
text1 = user_message_param.buttonsParam->msg1;
|
|
||||||
text2 = user_message_param.buttonsParam->msg2;
|
|
||||||
}
|
|
||||||
const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO;
|
|
||||||
SetCursorPos({
|
|
||||||
ws.x / 2.0f - BUTTON_SIZE.x / 2.0f * static_cast<float>(count),
|
|
||||||
ws.y - 10.0f - BUTTON_SIZE.y,
|
|
||||||
});
|
|
||||||
BeginGroup();
|
|
||||||
if (count > 0) {
|
|
||||||
// First button at the right, so we render the second button first
|
|
||||||
if (count == 2) {
|
|
||||||
PushID(2);
|
|
||||||
if (Button(text2, BUTTON_SIZE)) {
|
|
||||||
Finish(ButtonId::BUTTON2);
|
|
||||||
}
|
|
||||||
if (!focus_first) {
|
|
||||||
SetItemDefaultNav();
|
|
||||||
}
|
|
||||||
PopID();
|
|
||||||
SameLine();
|
|
||||||
}
|
|
||||||
PushID(1);
|
|
||||||
if (Button(text1, BUTTON_SIZE)) {
|
|
||||||
Finish(ButtonId::BUTTON1);
|
|
||||||
}
|
|
||||||
if (focus_first) {
|
|
||||||
SetItemDefaultNav();
|
|
||||||
}
|
|
||||||
PopID();
|
|
||||||
SameLine();
|
|
||||||
}
|
|
||||||
EndGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawProgressBar(const ProgressBarParam& progress_bar_param) {}
|
|
||||||
|
|
||||||
void DrawSystemMessage(const SystemMessageParam& system_message_param) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Draw() override {
|
|
||||||
if (g_status != Status::RUNNING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto& io = GetIO();
|
|
||||||
|
|
||||||
const ImVec2 window_size{
|
|
||||||
std::min(io.DisplaySize.x, 500.0f),
|
|
||||||
std::min(io.DisplaySize.y, 300.0f),
|
|
||||||
};
|
|
||||||
|
|
||||||
CentralizeWindow();
|
|
||||||
SetNextWindowSize(window_size);
|
|
||||||
SetNextWindowFocus();
|
|
||||||
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) {
|
|
||||||
case MsgDialogMode::USER_MSG:
|
|
||||||
DrawUser(*param->userMsgParam);
|
|
||||||
break;
|
|
||||||
case MsgDialogMode::PROGRESS_BAR:
|
|
||||||
DrawProgressBar(*param->progBarParam);
|
|
||||||
break;
|
|
||||||
case MsgDialogMode::SYSTEM_MSG:
|
|
||||||
DrawSystemMessage(*param->sysMsgParam);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
End();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldGrabGamepad() override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit MsgDialogGui(const Param* param = nullptr)
|
|
||||||
: param(param), dialog_unique_id([] {
|
|
||||||
static s32 last_id = 0;
|
|
||||||
return last_id++;
|
|
||||||
}()) {}
|
|
||||||
} g_msg_dialog_gui;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static void Finish(ButtonId buttonId) {
|
|
||||||
g_result.buttonId = buttonId;
|
|
||||||
g_status = Status::FINISHED;
|
|
||||||
Layer::RemoveLayer(&g_msg_dialog_gui);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error PS4_SYSV_ABI sceMsgDialogClose() {
|
Error PS4_SYSV_ABI sceMsgDialogClose() {
|
||||||
if (g_status != Status::RUNNING) {
|
if (g_status != Status::RUNNING) {
|
||||||
return Error::NOT_RUNNING;
|
return Error::NOT_RUNNING;
|
||||||
}
|
}
|
||||||
Finish(ButtonId::INVALID);
|
g_msg_dialog_ui.Finish(ButtonId::INVALID);
|
||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,12 +70,15 @@ Error PS4_SYSV_ABI sceMsgDialogOpen(const Param* 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) {
|
||||||
|
return Error::ARG_NULL;
|
||||||
|
}
|
||||||
ASSERT(param->size == sizeof(Param));
|
ASSERT(param->size == sizeof(Param));
|
||||||
ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam));
|
ASSERT(param->baseParam.size == sizeof(CommonDialog::BaseParam));
|
||||||
g_status = Status::RUNNING;
|
g_status = Status::RUNNING;
|
||||||
|
g_param = *param;
|
||||||
g_result = {};
|
g_result = {};
|
||||||
g_msg_dialog_gui = MsgDialogGui(param);
|
g_msg_dialog_ui = MsgDialogUi(&g_param, &g_status, &g_result);
|
||||||
Layer::AddLayer(&g_msg_dialog_gui);
|
|
||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "common/fixed_value.h"
|
#include "common/fixed_value.h"
|
||||||
#include "common/types.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;
|
||||||
@ -13,8 +14,120 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::MsgDialog {
|
namespace Libraries::MsgDialog {
|
||||||
|
|
||||||
struct MsgDialogResult;
|
using OrbisUserServiceUserId = s32;
|
||||||
struct Param;
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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{};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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(MsgDialogResult* result);
|
||||||
|
173
src/core/libraries/system/msgdialog_ui.cpp
Normal file
173
src/core/libraries/system/msgdialog_ui.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include "imgui/imgui_std.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "msgdialog.h"
|
||||||
|
|
||||||
|
using namespace ImGui;
|
||||||
|
using namespace Libraries::CommonDialog;
|
||||||
|
using namespace Libraries::MsgDialog;
|
||||||
|
|
||||||
|
static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int count = 0;
|
||||||
|
const char* text1;
|
||||||
|
const char* text2;
|
||||||
|
} static constexpr user_button_texts[] = {
|
||||||
|
{1, "OK"}, // 0 OK
|
||||||
|
{2, "Yes", "No"}, // 1 YESNO
|
||||||
|
{0}, // 2 NONE
|
||||||
|
{2, "OK", "Cancel"}, // 3 OK_CANCEL
|
||||||
|
{}, // 4 !!NOP
|
||||||
|
{1, "Wait"}, // 5 WAIT
|
||||||
|
{2, "Wait", "Cancel"}, // 6 WAIT_CANCEL
|
||||||
|
{2, "Yes", "No"}, // 7 YESNO_FOCUS_NO
|
||||||
|
{2, "OK", "Cancel"}, // 8 OK_CANCEL_FOCUS_CANCEL
|
||||||
|
{0xFF}, // 9 TWO_BUTTONS
|
||||||
|
};
|
||||||
|
static_assert(std::size(user_button_texts) == static_cast<int>(ButtonType::TWO_BUTTONS) + 1);
|
||||||
|
|
||||||
|
static void DrawCenteredText(const char* text) {
|
||||||
|
const auto ws = GetWindowSize();
|
||||||
|
SetCursorPosY(ws.y / 2.0f - 50.0f);
|
||||||
|
PushTextWrapPos(ws.x - 30.0f);
|
||||||
|
SetCursorPosX((ws.x - CalcTextSize(text, nullptr, false, ws.x - 40.0f).x) / 2.0f);
|
||||||
|
Text("%s", text);
|
||||||
|
PopTextWrapPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MsgDialogUi::DrawUser() {
|
||||||
|
const auto& [button_type, msg, btn_param, _] = *param->userMsgParam;
|
||||||
|
const auto ws = GetWindowSize();
|
||||||
|
DrawCenteredText(msg);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
const bool focus_first = button_type < ButtonType::YESNO_FOCUS_NO;
|
||||||
|
SetCursorPos({
|
||||||
|
ws.x / 2.0f - BUTTON_SIZE.x / 2.0f * static_cast<float>(count),
|
||||||
|
ws.y - 10.0f - BUTTON_SIZE.y,
|
||||||
|
});
|
||||||
|
BeginGroup();
|
||||||
|
if (count > 0) {
|
||||||
|
// First button at the right, so we render the second button first
|
||||||
|
if (count == 2) {
|
||||||
|
PushID(2);
|
||||||
|
if (Button(text2, BUTTON_SIZE)) {
|
||||||
|
Finish(ButtonId::BUTTON2);
|
||||||
|
}
|
||||||
|
if (!focus_first) {
|
||||||
|
SetItemDefaultNav();
|
||||||
|
}
|
||||||
|
PopID();
|
||||||
|
SameLine();
|
||||||
|
}
|
||||||
|
PushID(1);
|
||||||
|
if (Button(text1, BUTTON_SIZE)) {
|
||||||
|
Finish(ButtonId::BUTTON1);
|
||||||
|
}
|
||||||
|
if (focus_first) {
|
||||||
|
SetItemDefaultNav();
|
||||||
|
}
|
||||||
|
PopID();
|
||||||
|
SameLine();
|
||||||
|
}
|
||||||
|
EndGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MsgDialogUi::DrawProgressBar() {}
|
||||||
|
|
||||||
|
void MsgDialogUi::DrawSystemMessage() {}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (status && *status == Status::RUNNING) {
|
||||||
|
AddLayer(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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(status, other.status);
|
||||||
|
swap(result, other.result);
|
||||||
|
if (status && *status == Status::RUNNING) {
|
||||||
|
AddLayer(this);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MsgDialogUi::Finish(ButtonId buttonId) {
|
||||||
|
if (result) {
|
||||||
|
result->buttonId = buttonId;
|
||||||
|
}
|
||||||
|
if (status) {
|
||||||
|
*status = Status::FINISHED;
|
||||||
|
}
|
||||||
|
param = nullptr;
|
||||||
|
status = nullptr;
|
||||||
|
result = nullptr;
|
||||||
|
RemoveLayer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MsgDialogUi::Draw() {
|
||||||
|
if (status == nullptr || *status != Status::RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& io = GetIO();
|
||||||
|
|
||||||
|
const ImVec2 window_size{
|
||||||
|
std::min(io.DisplaySize.x, 500.0f),
|
||||||
|
std::min(io.DisplaySize.y, 300.0f),
|
||||||
|
};
|
||||||
|
|
||||||
|
CentralizeWindow();
|
||||||
|
SetNextWindowSize(window_size);
|
||||||
|
SetNextWindowFocus();
|
||||||
|
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) {
|
||||||
|
case MsgDialogMode::USER_MSG:
|
||||||
|
DrawUser();
|
||||||
|
break;
|
||||||
|
case MsgDialogMode::PROGRESS_BAR:
|
||||||
|
DrawProgressBar();
|
||||||
|
break;
|
||||||
|
case MsgDialogMode::SYSTEM_MSG:
|
||||||
|
DrawSystemMessage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user