[XAM] Implement XamShowSigninUI

This commit is contained in:
NicknineTheEagle
2024-10-09 22:48:20 +03:00
committed by Radosław Gliński
parent 842161ca9b
commit 060954f0c3
6 changed files with 489 additions and 219 deletions

View File

@@ -95,9 +95,6 @@ class EmulatorWindow {
void ToggleProfilesConfigDialog();
void SetHotkeysState(bool enabled) { disable_hotkeys_ = !enabled; }
// We need to store it somewhere so there will be no situation when there are
// multiple instances opened.
std::unique_ptr<CreateProfileDialog> profile_creation_dialog_;
// Types of button functions for hotkeys.
enum class ButtonFunctions {

View File

@@ -11,29 +11,36 @@
#include <algorithm>
#include "xenia/app/emulator_window.h"
#include "xenia/base/system.h"
#include "xenia/kernel/util/shim_utils.h"
namespace xe {
namespace kernel {
namespace xam {
extern bool xeDrawProfileContent(ui::ImGuiDrawer* imgui_drawer,
const uint64_t xuid, const uint8_t user_index,
const X_XAMACCOUNTINFO* account,
uint64_t* selected_xuid);
}
} // namespace kernel
namespace app {
void CreateProfileDialog::OnDraw(ImGuiIO& io) {
if (!has_opened_) {
ImGui::OpenPopup("Create Profile");
has_opened_ = true;
}
auto profile_manager = emulator_window_->emulator()
->kernel_state()
->xam_state()
->profile_manager();
const auto window_position =
ImVec2(GetIO().DisplaySize.x * 0.40f, GetIO().DisplaySize.y * 0.44f);
ImGui::SetNextWindowPos(window_position, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowBgAlpha(1.0f);
bool dialog_open = true;
if (!ImGui::Begin("Create Profile", &dialog_open,
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_HorizontalScrollbar)) {
ImGui::End();
emulator_window_->profile_creation_dialog_.reset();
if (!ImGui::BeginPopupModal("Create Profile", &dialog_open,
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_HorizontalScrollbar)) {
Close();
return;
}
@@ -43,33 +50,37 @@ void CreateProfileDialog::OnDraw(ImGuiIO& io) {
}
ImGui::TextUnformatted("Gamertag:");
ImGui::InputText("##Gamertag", gamertag, sizeof(gamertag));
ImGui::InputText("##Gamertag", gamertag_, sizeof(gamertag_));
const std::string gamertag_string = std::string(gamertag);
const std::string gamertag_string = std::string(gamertag_);
bool valid = profile_manager->IsGamertagValid(gamertag_string);
if (profile_manager->IsGamertagValid(gamertag_string)) {
if (ImGui::Button("Create")) {
if (profile_manager->CreateProfile(gamertag_string, migration) &&
migration) {
emulator_window_->emulator()->DataMigration(0xB13EBABEBABEBABE);
}
std::fill(std::begin(gamertag), std::end(gamertag), '\0');
dialog_open = false;
ImGui::BeginDisabled(!valid);
if (ImGui::Button("Create")) {
bool autologin = (profile_manager->GetProfilesCount() == 0);
if (profile_manager->CreateProfile(gamertag_string, autologin,
migration_) &&
migration_) {
emulator_window_->emulator()->DataMigration(0xB13EBABEBABEBABE);
}
ImGui::SameLine();
std::fill(std::begin(gamertag_), std::end(gamertag_), '\0');
dialog_open = false;
}
ImGui::EndDisabled();
ImGui::SameLine();
if (ImGui::Button("Cancel")) {
std::fill(std::begin(gamertag), std::end(gamertag), '\0');
std::fill(std::begin(gamertag_), std::end(gamertag_), '\0');
dialog_open = false;
}
if (!dialog_open) {
ImGui::End();
emulator_window_->profile_creation_dialog_.reset();
ImGui::CloseCurrentPopup();
Close();
ImGui::EndPopup();
return;
}
ImGui::End();
ImGui::EndPopup();
}
void NoProfileDialog::OnDraw(ImGuiIO& io) {
@@ -112,18 +123,14 @@ void NoProfileDialog::OnDraw(ImGuiIO& io) {
emulator_window_->emulator()->content_root());
if (content_files.empty()) {
if (ImGui::Button("Create Profile") &&
!emulator_window_->profile_creation_dialog_) {
emulator_window_->profile_creation_dialog_ =
std::make_unique<CreateProfileDialog>(
emulator_window_->imgui_drawer(), emulator_window_);
if (ImGui::Button("Create Profile")) {
new CreateProfileDialog(emulator_window_->imgui_drawer(),
emulator_window_);
}
} else {
if (ImGui::Button("Create profile & migrate data") &&
!emulator_window_->profile_creation_dialog_) {
emulator_window_->profile_creation_dialog_ =
std::make_unique<CreateProfileDialog>(
emulator_window_->imgui_drawer(), emulator_window_, true);
if (ImGui::Button("Create profile & migrate data")) {
new CreateProfileDialog(emulator_window_->imgui_drawer(),
emulator_window_, true);
}
}
@@ -183,7 +190,8 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) {
const uint8_t user_index =
profile_manager->GetUserIndexAssignedToProfile(xuid);
if (!DrawProfileContent(xuid, user_index, &account)) {
if (!kernel::xam::xeDrawProfileContent(imgui_drawer(), xuid, user_index,
&account, &selected_xuid_)) {
ImGui::PopID();
ImGui::End();
return;
@@ -196,11 +204,8 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) {
ImGui::Spacing();
if (ImGui::Button("Create Profile") &&
!emulator_window_->profile_creation_dialog_) {
emulator_window_->profile_creation_dialog_ =
std::make_unique<CreateProfileDialog>(emulator_window_->imgui_drawer(),
emulator_window_);
if (ImGui::Button("Create Profile")) {
new CreateProfileDialog(emulator_window_->imgui_drawer(), emulator_window_);
}
ImGui::End();
@@ -211,131 +216,5 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) {
}
}
bool ProfileConfigDialog::DrawProfileContent(const uint64_t xuid,
const uint8_t user_index,
const X_XAMACCOUNTINFO* account) {
auto profile_manager = emulator_window_->emulator()
->kernel_state()
->xam_state()
->profile_manager();
const float default_image_size = 75.0f;
auto position = ImGui::GetCursorPos();
const float selectable_height =
ImGui::GetTextLineHeight() *
5; // 3 is for amount of lines of text behind image/object.
const auto font = emulator_window_->imgui_drawer()->GetIO().Fonts->Fonts[0];
const auto text_size = font->CalcTextSizeA(
font->FontSize, FLT_MAX, -1.0f,
fmt::format("XUID: {:016X}\n", 0xB13EBABEBABEBABE).c_str());
const auto image_scale = selectable_height / default_image_size;
const auto image_size = ImVec2(default_image_size * image_scale,
default_image_size * image_scale);
// This includes 10% to include empty spaces between border and elements.
auto selectable_region_size =
ImVec2((image_size.x + text_size.x) * 1.10f, selectable_height);
if (ImGui::Selectable("##Selectable", selected_xuid_ == xuid,
ImGuiSelectableFlags_SpanAllColumns,
selectable_region_size)) {
selected_xuid_ = xuid;
}
if (ImGui::BeginPopupContextItem("Profile Menu")) {
if (user_index == static_cast<uint8_t>(-1)) {
if (ImGui::MenuItem("Login")) {
profile_manager->Login(xuid);
}
if (ImGui::BeginMenu("Login to slot:")) {
for (uint8_t i = 0; i < XUserMaxUserCount; i++) {
if (ImGui::MenuItem(fmt::format("slot {}", i).c_str())) {
profile_manager->Login(xuid, i);
}
}
ImGui::EndMenu();
}
} else {
if (ImGui::MenuItem("Logout")) {
profile_manager->Logout(user_index);
}
}
ImGui::MenuItem("Modify (unsupported)");
ImGui::MenuItem("Show Achievements (unsupported)");
if (ImGui::MenuItem("Show Content Directory")) {
const auto path = profile_manager->GetProfileContentPath(
xuid, emulator_window_->emulator()->kernel_state()->title_id());
if (!std::filesystem::exists(path)) {
std::filesystem::create_directories(path);
}
std::thread path_open(LaunchFileExplorer, path);
path_open.detach();
}
if (!emulator_window_->emulator()->is_title_open()) {
ImGui::Separator();
if (ImGui::BeginMenu("Delete Profile")) {
ImGui::BeginTooltip();
ImGui::TextUnformatted(
fmt::format("You're about to delete profile: {} (XUID: {:016X}). "
"This will remove all data assigned to this profile "
"including savefiles. Are you sure?",
account->GetGamertagString(), xuid)
.c_str());
ImGui::EndTooltip();
if (ImGui::MenuItem("Yes, delete it!")) {
profile_manager->DeleteProfile(xuid);
ImGui::EndMenu();
ImGui::EndPopup();
return false;
}
ImGui::EndMenu();
}
}
ImGui::EndPopup();
}
ImGui::SameLine();
ImGui::SetCursorPos(position);
// In the future it can be replaced with profile icon.
ImGui::Image(user_index < XUserMaxUserCount
? imgui_drawer()->GetNotificationIcon(user_index)
: nullptr,
ImVec2(default_image_size * image_scale,
default_image_size * image_scale));
ImGui::SameLine();
position = ImGui::GetCursorPos();
ImGui::TextUnformatted(
fmt::format("User: {}\n", account->GetGamertagString()).c_str());
ImGui::SameLine();
ImGui::SetCursorPos(position);
ImGui::SetCursorPosY(position.y + ImGui::GetTextLineHeight());
ImGui::TextUnformatted(fmt::format("XUID: {:016X}\n", xuid).c_str());
ImGui::SameLine();
ImGui::SetCursorPos(position);
ImGui::SetCursorPosY(position.y + 2 * ImGui::GetTextLineHeight());
if (user_index != static_cast<uint8_t>(-1)) {
ImGui::TextUnformatted(
fmt::format("Assigned to slot: {}\n", user_index + 1).c_str());
} else {
ImGui::TextUnformatted(fmt::format("Profile is not signed in").c_str());
}
return true;
}
} // namespace app
} // namespace xe

View File

@@ -26,15 +26,16 @@ class CreateProfileDialog final : public ui::ImGuiDialog {
bool with_migration = false)
: ui::ImGuiDialog(imgui_drawer),
emulator_window_(emulator_window),
migration(with_migration) {
memset(gamertag, 0, sizeof(gamertag));
migration_(with_migration) {
memset(gamertag_, 0, sizeof(gamertag_));
}
protected:
void OnDraw(ImGuiIO& io) override;
bool migration = false;
char gamertag[16] = "";
bool has_opened_ = false;
bool migration_ = false;
char gamertag_[16] = "";
EmulatorWindow* emulator_window_;
};
@@ -54,19 +55,13 @@ class ProfileConfigDialog final : public ui::ImGuiDialog {
public:
ProfileConfigDialog(ui::ImGuiDrawer* imgui_drawer,
EmulatorWindow* emulator_window)
: ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {
memset(gamertag, 0, sizeof(gamertag));
}
: ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {}
protected:
void OnDraw(ImGuiIO& io) override;
private:
bool DrawProfileContent(const uint64_t xuid, const uint8_t user_index,
const X_XAMACCOUNTINFO* account);
uint64_t selected_xuid_ = 0;
char gamertag[16] = "";
EmulatorWindow* emulator_window_;
};