[XAM/UI] Implemented profile passcode UI
This commit is contained in:
parent
fe85be8817
commit
ceb94e019a
|
@ -180,6 +180,10 @@ class UserProfile {
|
|||
uint32_t GetSubscriptionTier() const {
|
||||
return account_info_.GetSubscriptionTier();
|
||||
}
|
||||
void GetPasscode(uint16_t* passcode) const {
|
||||
std::memcpy(passcode, account_info_.passcode,
|
||||
sizeof(account_info_.passcode));
|
||||
};
|
||||
|
||||
void AddSetting(std::unique_ptr<UserSetting> setting);
|
||||
UserSetting* GetSetting(uint32_t setting_id);
|
||||
|
|
|
@ -320,6 +320,119 @@ class MessageBoxDialog : public XamDialog {
|
|||
uint32_t chosen_button_ = 0;
|
||||
};
|
||||
|
||||
class ProfilePasscodeDialog : public XamDialog {
|
||||
public:
|
||||
const char* labelled_keys_[11] = {"None", "X", "Y", "RB", "LB", "LT",
|
||||
"RT", "Up", "Down", "Left", "Right"};
|
||||
|
||||
const std::map<std::string, uint16_t> keys_map_ = {
|
||||
{"None", 0},
|
||||
{"X", X_BUTTON_PASSCODE},
|
||||
{"Y", Y_BUTTON_PASSCODE},
|
||||
{"RB", RIGHT_BUMPER_PASSCODE},
|
||||
{"LB", LEFT_BUMPER_PASSCODE},
|
||||
{"LT", LEFT_TRIGGER_PASSCODE},
|
||||
{"RT", RIGHT_TRIGGER_PASSCODE},
|
||||
{"Up", DPAD_UP_PASSCODE},
|
||||
{"Down", DPAD_DOWN_PASSCODE},
|
||||
{"Left", DPAD_LEFT_PASSCODE},
|
||||
{"Right", DPAD_RIGHT_PASSCODE}};
|
||||
|
||||
ProfilePasscodeDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string& title,
|
||||
std::string& description, MESSAGEBOX_RESULT* result_ptr)
|
||||
: XamDialog(imgui_drawer),
|
||||
title_(title),
|
||||
description_(description),
|
||||
result_ptr_(result_ptr) {
|
||||
std::memset(result_ptr, 0, sizeof(MESSAGEBOX_RESULT));
|
||||
|
||||
if (title_.empty()) {
|
||||
title_ = "Enter Pass Code";
|
||||
}
|
||||
|
||||
if (description_.empty()) {
|
||||
description_ = "Enter your Xbox LIVE pass code.";
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPasscodeField(uint8_t key_id) {
|
||||
const std::string label = fmt::format("##Key {}", key_id);
|
||||
|
||||
if (ImGui::BeginCombo(label.c_str(),
|
||||
labelled_keys_[key_indexes_[key_id]])) {
|
||||
for (uint8_t key_index = 0; key_index < keys_map_.size(); key_index++) {
|
||||
bool is_selected = key_id == key_index;
|
||||
|
||||
if (ImGui::Selectable(labelled_keys_[key_index], is_selected)) {
|
||||
key_indexes_[key_id] = key_index;
|
||||
}
|
||||
|
||||
if (is_selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDraw(ImGuiIO& io) override {
|
||||
if (!has_opened_) {
|
||||
ImGui::OpenPopup(title_.c_str());
|
||||
has_opened_ = true;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal(title_.c_str(), nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (description_.size()) {
|
||||
ImGui::Text(description_.c_str());
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < passcode_length; i++) {
|
||||
DrawPasscodeField(i);
|
||||
// result_ptr_->Passcode[i] =
|
||||
// keys_map_.at(labelled_keys_[key_indexes_[i]]);
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
// We write each key on close to prevent simultaneous dialogs.
|
||||
if (ImGui::Button("Sign In")) {
|
||||
for (uint8_t i = 0; i < passcode_length; i++) {
|
||||
result_ptr_->Passcode[i] =
|
||||
keys_map_.at(labelled_keys_[key_indexes_[i]]);
|
||||
}
|
||||
|
||||
selected_signed_in_ = true;
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel")) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
virtual ~ProfilePasscodeDialog() {}
|
||||
|
||||
bool SelectedSignedIn() const { return selected_signed_in_; }
|
||||
|
||||
private:
|
||||
bool has_opened_ = false;
|
||||
bool selected_signed_in_ = false;
|
||||
std::string title_;
|
||||
std::string description_;
|
||||
|
||||
static const uint8_t passcode_length = sizeof(X_XAMACCOUNTINFO::passcode);
|
||||
int key_indexes_[passcode_length] = {0, 0, 0, 0};
|
||||
MESSAGEBOX_RESULT* result_ptr_;
|
||||
};
|
||||
|
||||
class GamertagModifyDialog final : public ui::ImGuiDialog {
|
||||
public:
|
||||
GamertagModifyDialog(ui::ImGuiDrawer* imgui_drawer,
|
||||
|
@ -783,7 +896,8 @@ class GamesInfoDialog final : public ui::ImGuiDialog {
|
|||
static dword_result_t XamShowMessageBoxUi(
|
||||
dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr,
|
||||
dword_t button_count, lpdword_t button_ptrs, dword_t active_button,
|
||||
dword_t flags, lpdword_t result_ptr, pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||
dword_t flags, pointer_t<MESSAGEBOX_RESULT> result_ptr,
|
||||
pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||
std::string title = title_ptr ? xe::to_utf8(title_ptr.value()) : "";
|
||||
std::string text = text_ptr ? xe::to_utf8(text_ptr.value()) : "";
|
||||
|
||||
|
@ -799,38 +913,53 @@ static dword_result_t XamShowMessageBoxUi(
|
|||
if (cvars::headless) {
|
||||
// Auto-pick the focused button.
|
||||
auto run = [result_ptr, active_button]() -> X_RESULT {
|
||||
*result_ptr = static_cast<uint32_t>(active_button);
|
||||
result_ptr->ButtonPressed = static_cast<uint32_t>(active_button);
|
||||
return X_ERROR_SUCCESS;
|
||||
};
|
||||
|
||||
result = xeXamDispatchHeadless(run, overlapped);
|
||||
} else {
|
||||
// TODO(benvanik): setup icon states.
|
||||
switch (flags & 0xF) {
|
||||
case 0:
|
||||
// config.pszMainIcon = nullptr;
|
||||
break;
|
||||
case 1:
|
||||
// config.pszMainIcon = TD_ERROR_ICON;
|
||||
break;
|
||||
case 2:
|
||||
// config.pszMainIcon = TD_WARNING_ICON;
|
||||
break;
|
||||
case 3:
|
||||
// config.pszMainIcon = TD_INFORMATION_ICON;
|
||||
break;
|
||||
case XMBox_NOICON: {
|
||||
} break;
|
||||
case XMBox_ERRORICON: {
|
||||
} break;
|
||||
case XMBox_WARNINGICON: {
|
||||
} break;
|
||||
case XMBox_ALERTICON: {
|
||||
} break;
|
||||
}
|
||||
auto close = [result_ptr](MessageBoxDialog* dialog) -> X_RESULT {
|
||||
*result_ptr = dialog->chosen_button();
|
||||
return X_ERROR_SUCCESS;
|
||||
};
|
||||
|
||||
const Emulator* emulator = kernel_state()->emulator();
|
||||
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
|
||||
|
||||
result = xeXamDispatchDialog<MessageBoxDialog>(
|
||||
new MessageBoxDialog(imgui_drawer, title, text, buttons,
|
||||
static_cast<uint32_t>(active_button)),
|
||||
close, overlapped);
|
||||
if (flags & XMBox_PASSCODEMODE || flags & XMBox_VERIFYPASSCODEMODE) {
|
||||
auto close = [result_ptr,
|
||||
active_button](ProfilePasscodeDialog* dialog) -> X_RESULT {
|
||||
if (dialog->SelectedSignedIn()) {
|
||||
// Logged in
|
||||
return X_ERROR_SUCCESS;
|
||||
} else {
|
||||
return X_ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
};
|
||||
|
||||
result = xeXamDispatchDialog<ProfilePasscodeDialog>(
|
||||
new ProfilePasscodeDialog(imgui_drawer, title, text, result_ptr),
|
||||
close, overlapped);
|
||||
} else {
|
||||
auto close = [result_ptr](MessageBoxDialog* dialog) -> X_RESULT {
|
||||
result_ptr->ButtonPressed = dialog->chosen_button();
|
||||
return X_ERROR_SUCCESS;
|
||||
};
|
||||
|
||||
result = xeXamDispatchDialog<MessageBoxDialog>(
|
||||
new MessageBoxDialog(imgui_drawer, title, text, buttons,
|
||||
static_cast<uint32_t>(active_button)),
|
||||
close, overlapped);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -838,7 +967,8 @@ static dword_result_t XamShowMessageBoxUi(
|
|||
dword_result_t XamShowMessageBoxUI_entry(
|
||||
dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr,
|
||||
dword_t button_count, lpdword_t button_ptrs, dword_t active_button,
|
||||
dword_t flags, lpdword_t result_ptr, pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||
dword_t flags, pointer_t<MESSAGEBOX_RESULT> result_ptr,
|
||||
pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||
return XamShowMessageBoxUi(user_index, title_ptr, text_ptr, button_count,
|
||||
button_ptrs, active_button, flags, result_ptr,
|
||||
overlapped);
|
||||
|
@ -848,7 +978,8 @@ DECLARE_XAM_EXPORT1(XamShowMessageBoxUI, kUI, kImplemented);
|
|||
dword_result_t XamShowMessageBoxUIEx_entry(
|
||||
dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr,
|
||||
dword_t button_count, lpdword_t button_ptrs, dword_t active_button,
|
||||
dword_t flags, dword_t unknown_unused, lpdword_t result_ptr,
|
||||
dword_t flags, dword_t unknown_unused,
|
||||
pointer_t<MESSAGEBOX_RESULT> result_ptr,
|
||||
pointer_t<XAM_OVERLAPPED> overlapped) {
|
||||
return XamShowMessageBoxUi(user_index, title_ptr, text_ptr, button_count,
|
||||
button_ptrs, active_button, flags, result_ptr,
|
||||
|
|
|
@ -664,8 +664,43 @@ struct X_PROFILEENUMRESULT {
|
|||
};
|
||||
static_assert_size(X_PROFILEENUMRESULT, 0x188);
|
||||
|
||||
} // namespace xe
|
||||
struct MESSAGEBOX_RESULT {
|
||||
union {
|
||||
xe::be<uint32_t> ButtonPressed;
|
||||
xe::be<uint16_t> Passcode[4];
|
||||
};
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define XMBox_NOICON 0x00000000
|
||||
#define XMBox_ERRORICON 0x00000001
|
||||
#define XMBox_WARNINGICON 0x00000002
|
||||
#define XMBox_ALERTICON 0x00000003
|
||||
|
||||
#define XMBox_PASSCODEMODE 0x00010000
|
||||
#define XMBox_VERIFYPASSCODEMODE 0x00020000
|
||||
|
||||
#define XMBox_WAITANIMATION 0x00001000
|
||||
#define XMBox_LIVEPASSCODEMODE 0x00030000
|
||||
#define XMBox_MODEMASK 0x00030000
|
||||
|
||||
#define XMBox_OK 1
|
||||
#define XMBox_CANCEL 2
|
||||
|
||||
#define X_BUTTON_PASSCODE 0x00005802
|
||||
#define Y_BUTTON_PASSCODE 0x00005803
|
||||
#define RIGHT_BUMPER_PASSCODE 0x00005804
|
||||
#define LEFT_BUMPER_PASSCODE 0x00005805
|
||||
#define LEFT_TRIGGER_PASSCODE 0x00005806
|
||||
#define RIGHT_TRIGGER_PASSCODE 0x00005807
|
||||
#define DPAD_UP_PASSCODE 0x00005810
|
||||
#define DPAD_DOWN_PASSCODE 0x00005811
|
||||
#define DPAD_LEFT_PASSCODE 0x00005812
|
||||
#define DPAD_RIGHT_PASSCODE 0x00005813
|
||||
|
||||
// clang-format on
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_XBOX_H_
|
||||
|
|
Loading…
Reference in New Issue