// Non-RmlUi includes that depend on Windows macros #include "UI.h" #include "../../Minecraft.h" // RmlUi includes (Windows macros temporarily suppressed) #pragma push_macro("byte") #pragma push_macro("GetNextSibling") #pragma push_macro("GetFirstChild") #undef byte #undef GetNextSibling #undef GetFirstChild #include "UIScene_SettingsMenu.h" #include "RmlManager.h" #include "../../Windows64/KeyboardMouseInput.h" #include #include #pragma pop_macro("GetFirstChild") #pragma pop_macro("GetNextSibling") #pragma pop_macro("byte") UIScene_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) , m_document(nullptr) { Rml::Context* ctx = RmlManager::Get().GetContext(); if (!ctx) { app.DebugPrintf("[RmlSettingsMenu] No RmlUi context available\n"); return; } m_document = ctx->LoadDocument("SettingsMenu.rml"); if (m_document) { m_document->Show(); // Apply conditional visibility matching original Iggy scene behavior bool bNotInGame = (Minecraft::GetInstance()->level == nullptr); // Audio and Graphics: hidden if not primary pad if (ProfileManager.GetPrimaryPad() != m_iPad) { auto* elAudio = m_document->GetElementById("audio"); if (elAudio) elAudio->SetProperty("display", "none"); auto* elGraphics = m_document->GetElementById("graphics"); if (elGraphics) elGraphics->SetProperty("display", "none"); } // Register button click listeners m_document->GetElementById("options")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("audio")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("controls")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("graphics")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("ui")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("reset_defaults")->AddEventListener(Rml::EventId::Click, this); // Focus first visible button m_document->GetElementById("options")->Focus(); } else { app.DebugPrintf("[RmlSettingsMenu] Failed to load SettingsMenu.rml\n"); } updateComponents(); ui.HidePressStart(); TelemetryManager->RecordMenuShown(m_iPad, eUIScene_SettingsMenu, 0); } UIScene_SettingsMenu::~UIScene_SettingsMenu() { if (m_document) { m_document->GetElementById("options")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("audio")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("controls")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("graphics")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("ui")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("reset_defaults")->RemoveEventListener(Rml::EventId::Click, this); m_document->Close(); m_document = nullptr; } } void UIScene_SettingsMenu::gainFocus() { if (!bHasFocus && stealsFocus()) { bHasFocus = true; updateTooltips(); updateComponents(); if (!m_bFocussedOnce) { } handleGainFocus(m_bFocussedOnce); if (bHasFocus) m_bFocussedOnce = true; if (m_document) m_document->Show(); } } void UIScene_SettingsMenu::handleLoseFocus() { if (m_document) m_document->Hide(); } void UIScene_SettingsMenu::updateTooltips() { } void UIScene_SettingsMenu::updateComponents() { bool bNotInGame = (Minecraft::GetInstance()->level == nullptr); if (bNotInGame) { m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true); m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true); } else { m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false); if (app.GetLocalPlayerCount() == 1) m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true); else m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false); } } void UIScene_SettingsMenu::reloadMovie(bool force) { } void UIScene_SettingsMenu::tick() { m_hasTickedOnce = true; UIScene::tick(); Rml::Context* ctx = RmlManager::Get().GetContext(); if (!ctx || !bHasFocus) return; ctx->ProcessMouseMove(g_KBMInput.GetMouseX(), g_KBMInput.GetMouseY(), 0); if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT)) ctx->ProcessMouseButtonDown(0, 0); if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT)) ctx->ProcessMouseButtonUp(0, 0); if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT)) ctx->ProcessMouseButtonDown(1, 0); if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT)) ctx->ProcessMouseButtonUp(1, 0); int wheelDelta = g_KBMInput.GetMouseWheel(); if (wheelDelta != 0) ctx->ProcessMouseWheel(wheelDelta / -120, 0); ctx->Update(); } void UIScene_SettingsMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport) { } void UIScene_SettingsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) { Rml::Context* ctx = RmlManager::Get().GetContext(); if (!ctx) return; if (!pressed) return; switch (key) { case ACTION_MENU_UP: ctx->ProcessKeyDown(Rml::Input::KI_UP, 0); handled = true; break; case ACTION_MENU_DOWN: ctx->ProcessKeyDown(Rml::Input::KI_DOWN, 0); handled = true; break; case ACTION_MENU_OK: if (g_KBMInput.IsKeyPressed(VK_RETURN)) { ctx->ProcessKeyDown(Rml::Input::KI_RETURN, 0); handled = true; } break; case ACTION_MENU_CANCEL: case ACTION_MENU_PAUSEMENU: app.CheckGameSettingsChanged(true, iPad); navigateBack(); handled = true; break; default: break; } } void UIScene_SettingsMenu::ProcessEvent(Rml::Event& event) { const Rml::String& id = event.GetCurrentElement()->GetId(); if (event == Rml::EventId::Click) { if (id == "options") OnOptions(); else if (id == "audio") OnAudio(); else if (id == "controls") OnControls(); else if (id == "graphics") OnGraphics(); else if (id == "ui") OnUI(); else if (id == "reset_defaults") OnResetToDefaults(); } } void UIScene_SettingsMenu::navigateBack() { ui.PlayUISFX(eSFX_Back); UIScene::navigateBack(); } void UIScene_SettingsMenu::OnOptions() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsOptionsMenu); } void UIScene_SettingsMenu::OnAudio() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsAudioMenu); } void UIScene_SettingsMenu::OnControls() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsControlMenu); } void UIScene_SettingsMenu::OnGraphics() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsGraphicsMenu); } void UIScene_SettingsMenu::OnUI() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsUIMenu); } void UIScene_SettingsMenu::OnResetToDefaults() { UINT uiIDA[2]; uiIDA[0]=IDS_CONFIRM_CANCEL; uiIDA[1]=IDS_CONFIRM_OK; ui.RequestAlertMessage(IDS_DEFAULTS_TITLE, IDS_DEFAULTS_TEXT, uiIDA, 2, m_iPad,&UIScene_SettingsMenu::ResetDefaultsDialogReturned,this); } int UIScene_SettingsMenu::ResetDefaultsDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) { UIScene_SettingsMenu* pClass = (UIScene_SettingsMenu*)pParam; // results switched for this dialog if(result==C4JStorage::EMessage_ResultDecline) { app.SetDefaultOptions(ProfileManager.GetDashboardProfileSettings(pClass->m_iPad),pClass->m_iPad); // if the profile data has been changed, then force a profile write // It seems we're allowed to break the 5 minute rule if it's the result of a user action app.CheckGameSettingsChanged(true,iPad); } return 0; }