[App] Add notifications for hotkeys & XNotifyQueueUI
This commit is contained in:
parent
9c8a575b76
commit
1a9ff8fe67
|
@ -1606,6 +1606,9 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
|||
}
|
||||
}
|
||||
|
||||
std::string notificationTitle = "";
|
||||
std::string notificationDesc = "";
|
||||
|
||||
EmulatorWindow::ControllerHotKey button_combination = it->second;
|
||||
|
||||
switch (button_combination.function) {
|
||||
|
@ -1630,45 +1633,81 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
|||
GpuClearCaches();
|
||||
}
|
||||
|
||||
notificationTitle = "Toggle Clear Memory Page State";
|
||||
notificationDesc =
|
||||
cvars::clear_memory_page_state ? "Enabled" : "Disabled";
|
||||
|
||||
// Extra Sleep
|
||||
xe::threading::Sleep(delay);
|
||||
break;
|
||||
case ButtonFunctions::ReadbackResolve:
|
||||
ToggleGPUSetting(gpu_cvar::ReadbackResolve);
|
||||
|
||||
notificationTitle = "Toggle Readback Resolve";
|
||||
notificationDesc = cvars::d3d12_readback_resolve ? "Enabled" : "Disabled";
|
||||
|
||||
// Extra Sleep
|
||||
xe::threading::Sleep(delay);
|
||||
break;
|
||||
case ButtonFunctions::CpuTimeScalarSetHalf:
|
||||
CpuTimeScalarSetHalf();
|
||||
|
||||
notificationTitle = "Time Scalar";
|
||||
notificationDesc =
|
||||
fmt::format("Decreased to {}", Clock::guest_time_scalar());
|
||||
break;
|
||||
case ButtonFunctions::CpuTimeScalarSetDouble:
|
||||
CpuTimeScalarSetDouble();
|
||||
|
||||
notificationTitle = "Time Scalar";
|
||||
notificationDesc =
|
||||
fmt::format("Increased to {}", Clock::guest_time_scalar());
|
||||
break;
|
||||
case ButtonFunctions::CpuTimeScalarReset:
|
||||
CpuTimeScalarReset();
|
||||
|
||||
notificationTitle = "Time Scalar";
|
||||
notificationDesc = fmt::format("Reset to {}", Clock::guest_time_scalar());
|
||||
break;
|
||||
case ButtonFunctions::ClearGPUCache:
|
||||
GpuClearCaches();
|
||||
|
||||
// Extra Sleep
|
||||
xe::threading::Sleep(delay);
|
||||
break;
|
||||
case ButtonFunctions::ToggleControllerVibration:
|
||||
ToggleControllerVibration();
|
||||
notificationTitle = "Clear GPU Cache";
|
||||
notificationDesc = "Complete";
|
||||
|
||||
// Extra Sleep
|
||||
xe::threading::Sleep(delay);
|
||||
break;
|
||||
case ButtonFunctions::ToggleControllerVibration: {
|
||||
ToggleControllerVibration();
|
||||
|
||||
bool vibration = false;
|
||||
|
||||
auto input_sys = emulator()->input_system();
|
||||
if (input_sys) {
|
||||
vibration = input_sys->GetVibrationCvar();
|
||||
}
|
||||
|
||||
notificationTitle = "Toggle Controller Vibration";
|
||||
notificationDesc = vibration ? "Enabled" : "Disabled";
|
||||
|
||||
// Extra Sleep
|
||||
xe::threading::Sleep(delay);
|
||||
} break;
|
||||
case ButtonFunctions::IncTitleSelect:
|
||||
selected_title_index++;
|
||||
break;
|
||||
case ButtonFunctions::DecTitleSelect:
|
||||
selected_title_index--;
|
||||
break;
|
||||
case ButtonFunctions::ToggleLogging:
|
||||
case ButtonFunctions::ToggleLogging: {
|
||||
logging::internal::ToggleLogLevel();
|
||||
break;
|
||||
|
||||
notificationTitle = "Toggle Logging";
|
||||
|
||||
LogLevel level = static_cast<LogLevel>(logging::internal::GetLogLevel());
|
||||
notificationDesc = level == LogLevel::Disabled ? "Disabled" : "Enabled";
|
||||
} break;
|
||||
case ButtonFunctions::Unknown:
|
||||
default:
|
||||
break;
|
||||
|
@ -1704,6 +1743,13 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
|
|||
title);
|
||||
}
|
||||
|
||||
if (!notificationTitle.empty()) {
|
||||
app_context_.CallInUIThread([&]() {
|
||||
new xe::ui::HostNotificationWindow(imgui_drawer(), notificationTitle,
|
||||
notificationDesc, 0);
|
||||
});
|
||||
}
|
||||
|
||||
xe::threading::Sleep(delay);
|
||||
|
||||
return it->second;
|
||||
|
|
|
@ -482,6 +482,7 @@ bool logging::internal::ShouldLog(LogLevel log_level, uint32_t log_mask) {
|
|||
return static_cast<int32_t>(log_level) <= cvars::log_level &&
|
||||
(log_mask & cvars::log_mask) == 0;
|
||||
}
|
||||
uint32_t logging::internal::GetLogLevel() { return cvars::log_level; }
|
||||
|
||||
std::pair<char*, size_t> logging::internal::GetThreadBuffer() {
|
||||
return {thread_log_buffer_, sizeof(thread_log_buffer_)};
|
||||
|
|
|
@ -86,6 +86,7 @@ void ToggleLogLevel();
|
|||
|
||||
bool ShouldLog(LogLevel log_level,
|
||||
uint32_t log_mask = xe::LogSrc::Uncategorized);
|
||||
uint32_t GetLogLevel();
|
||||
std::pair<char*, size_t> GetThreadBuffer();
|
||||
XE_NOALIAS
|
||||
void AppendLogLine(LogLevel log_level, const char prefix_char, size_t written);
|
||||
|
|
|
@ -140,6 +140,8 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
|
|||
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
bool InputSystem::GetVibrationCvar() { return cvars::vibration; }
|
||||
|
||||
void InputSystem::ToggleVibration() {
|
||||
OVERRIDE_bool(vibration, !cvars::vibration);
|
||||
// Send instant update to vibration state to prevent awaiting for next tick.
|
||||
|
|
|
@ -47,6 +47,8 @@ class InputSystem {
|
|||
X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||
X_INPUT_KEYSTROKE* out_keystroke);
|
||||
|
||||
bool GetVibrationCvar();
|
||||
|
||||
void ToggleVibration();
|
||||
|
||||
const std::bitset<max_allowed_controllers> GetConnectedSlots() const {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "xenia/kernel/xam/xam_private.h"
|
||||
#include "xenia/ui/imgui_dialog.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
#include "xenia/ui/imgui_guest_notification.h"
|
||||
#include "xenia/ui/window.h"
|
||||
#include "xenia/ui/windowed_app_context.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
@ -398,8 +399,8 @@ dword_result_t XNotifyQueueUI_entry(dword_t exnq, dword_t dwUserIndex,
|
|||
qword_t qwAreas,
|
||||
lpu16string_t displayText_ptr,
|
||||
lpvoid_t contextData) {
|
||||
std::string title_text = "XNotifyQueueUI";
|
||||
std::string displayText = "";
|
||||
const uint8_t position_id = static_cast<uint8_t>(qwAreas);
|
||||
|
||||
if (displayText_ptr) {
|
||||
displayText = xe::to_utf8(displayText_ptr.value());
|
||||
|
@ -407,23 +408,11 @@ dword_result_t XNotifyQueueUI_entry(dword_t exnq, dword_t dwUserIndex,
|
|||
|
||||
XELOGI("XNotifyQueueUI: {}", displayText);
|
||||
|
||||
if (cvars::headless) {
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
auto close = [](MessageBoxDialog* dialog) -> X_RESULT {
|
||||
dialog->chosen_button();
|
||||
return X_ERROR_SUCCESS;
|
||||
};
|
||||
|
||||
std::vector<std::string> buttons(1, "OK");
|
||||
|
||||
const Emulator* emulator = kernel_state()->emulator();
|
||||
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
|
||||
|
||||
xeXamDispatchDialog<MessageBoxDialog>(
|
||||
new MessageBoxDialog(imgui_drawer, title_text, displayText, buttons, 0),
|
||||
close, false);
|
||||
new xe::ui::XNotifyWindow(imgui_drawer, "", displayText, dwUserIndex,
|
||||
position_id);
|
||||
|
||||
// XNotifyQueueUI -> XNotifyQueueUIEx -> XMsgProcessRequest ->
|
||||
// XMsgStartIORequestEx & XMsgInProcessCall
|
||||
|
|
|
@ -180,5 +180,82 @@ void AchievementNotificationWindow::OnDraw(ImGuiIO& io) {
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void XNotifyWindow::OnDraw(ImGuiIO& io) {
|
||||
UpdateNotificationState();
|
||||
|
||||
if (IsNotificationExpired()) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string longest_notification_text_line =
|
||||
GetTitle().size() > GetDescription().size() ? GetTitle().c_str()
|
||||
: GetDescription().c_str();
|
||||
|
||||
const ImVec2 screen_size = io.DisplaySize;
|
||||
const float window_scale =
|
||||
std::fminf(screen_size.x / default_drawing_resolution.x,
|
||||
screen_size.y / default_drawing_resolution.y);
|
||||
const float font_scale = default_font_size / io.Fonts->Fonts[0]->FontSize;
|
||||
const ImVec2 text_size = io.Fonts->Fonts[0]->CalcTextSizeA(
|
||||
default_font_size * default_notification_text_scale * window_scale,
|
||||
FLT_MAX, -1.0f, longest_notification_text_line.c_str());
|
||||
|
||||
const ImVec2 final_notification_size =
|
||||
CalculateNotificationSize(text_size, window_scale);
|
||||
|
||||
const ImVec2 notification_position = CalculateNotificationScreenPosition(
|
||||
screen_size, final_notification_size, GetPositionId());
|
||||
|
||||
if (isnan(notification_position.x) || isnan(notification_position.y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImVec2 current_notification_size = final_notification_size;
|
||||
current_notification_size.x *= notification_draw_progress_;
|
||||
current_notification_size.x = std::floorf(current_notification_size.x);
|
||||
|
||||
// Initialize position and window size
|
||||
ImGui::SetNextWindowSize(current_notification_size);
|
||||
ImGui::SetNextWindowPos(notification_position);
|
||||
|
||||
// Set new window style before drawing window
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding,
|
||||
default_notification_rounding * window_scale);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg,
|
||||
default_notification_background_color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Separator,
|
||||
default_notification_background_color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, default_notification_border_color);
|
||||
|
||||
ImGui::Begin("Notification Window", NULL, NOTIFY_TOAST_FLAGS);
|
||||
{
|
||||
ImGui::SetWindowFontScale(default_notification_text_scale * font_scale *
|
||||
window_scale);
|
||||
// Set offset to image to prevent it from being right on border.
|
||||
ImGui::SetCursorPos(ImVec2(final_notification_size.x * 0.005f,
|
||||
final_notification_size.y * 0.05f));
|
||||
// Elements of window
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(
|
||||
GetDrawer()->GetNotificationIcon(GetUserIndex())),
|
||||
ImVec2(default_notification_icon_size.x * window_scale,
|
||||
default_notification_icon_size.y * window_scale));
|
||||
|
||||
// Set offset to image to prevent it from being right on border.
|
||||
// ImGui::SetCursorPos(ImVec2(final_notification_size.x * 0.1f,
|
||||
// final_notification_size.y * 0.2f));
|
||||
|
||||
ImGui::SameLine();
|
||||
if (notification_draw_progress_ > 0.5f) {
|
||||
ImGui::TextColored(white_color, GetDescription().c_str());
|
||||
}
|
||||
}
|
||||
// Restore previous style
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xe
|
|
@ -76,6 +76,17 @@ class AchievementNotificationWindow final : ImGuiGuestNotification {
|
|||
void OnDraw(ImGuiIO& io) override;
|
||||
};
|
||||
|
||||
class XNotifyWindow final : ImGuiGuestNotification {
|
||||
public:
|
||||
XNotifyWindow(ui::ImGuiDrawer* imgui_drawer, std::string title,
|
||||
std::string description, uint8_t user_index,
|
||||
uint8_t position_id = 0)
|
||||
: ImGuiGuestNotification(imgui_drawer, title, description, user_index,
|
||||
position_id) {};
|
||||
|
||||
void OnDraw(ImGuiIO& io) override;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
|
|
Loading…
Reference in New Issue