// 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_HelpAndOptionsMenu.h" #include "RmlManager.h" #include "../../Windows64/KeyboardMouseInput.h" #include #include #pragma pop_macro("GetFirstChild") #pragma pop_macro("GetNextSibling") #pragma pop_macro("byte") static std::string WStringToUTF8(LPCWSTR wstr) { if (!wstr) return {}; size_t wlen = wcslen(wstr); if (wlen == 0) return {}; int len = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)wlen, nullptr, 0, nullptr, nullptr); if (len <= 0) return {}; std::string result(len, '\0'); WideCharToMultiByte(CP_UTF8, 0, wstr, (int)wlen, &result[0], len, nullptr, nullptr); return result; } UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) , m_document(nullptr) { Rml::Context* ctx = RmlManager::Get().GetContext(); if (!ctx) { app.DebugPrintf("[RmlHelpAndOptions] No RmlUi context available\n"); return; } m_document = ctx->LoadDocument("HelpOptions.rml"); if (m_document) { m_document->Show(); UpdateLocalizedText(); // Change Skin: hide if not full version if (!ProfileManager.IsFullVersion()) { auto* el = m_document->GetElementById("change_skin"); if (el) el->SetProperty("display", "none"); } // Credits: hide in splitscreen if (app.GetLocalPlayerCount() > 1) { auto* el = m_document->GetElementById("credits"); if (el) el->SetProperty("display", "none"); } // Register button click listeners m_document->GetElementById("change_skin")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("how_to_play")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("controls")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("settings")->AddEventListener(Rml::EventId::Click, this); m_document->GetElementById("credits")->AddEventListener(Rml::EventId::Click, this); // Focus first visible button auto* elFirst = m_document->GetElementById("change_skin"); if (elFirst) elFirst->Focus(); } else { app.DebugPrintf("[RmlHelpAndOptions] Failed to load HelpOptions.rml\n"); } ui.HidePressStart(); TelemetryManager->RecordMenuShown(m_iPad, eUIScene_HelpAndOptionsMenu, 0); } UIScene_HelpAndOptionsMenu::~UIScene_HelpAndOptionsMenu() { if (m_document) { m_document->GetElementById("change_skin")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("how_to_play")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("controls")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("settings")->RemoveEventListener(Rml::EventId::Click, this); m_document->GetElementById("credits")->RemoveEventListener(Rml::EventId::Click, this); m_document->Close(); m_document = nullptr; } } void UIScene_HelpAndOptionsMenu::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_HelpAndOptionsMenu::handleLoseFocus() { if (m_document) m_document->Hide(); } void UIScene_HelpAndOptionsMenu::reloadMovie(bool force) { } void UIScene_HelpAndOptionsMenu::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_HelpAndOptionsMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport) { } void UIScene_HelpAndOptionsMenu::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: navigateBack(); handled = true; break; default: break; } } void UIScene_HelpAndOptionsMenu::ProcessEvent(Rml::Event& event) { const Rml::String& id = event.GetCurrentElement()->GetId(); if (event == Rml::EventId::Click) { if (id == "change_skin") OnChangeSkin(); else if (id == "how_to_play") OnHowToPlay(); else if (id == "controls") OnControls(); else if (id == "settings") OnSettings(); else if (id == "credits") OnCredits(); } } void UIScene_HelpAndOptionsMenu::updateTooltips() { } void UIScene_HelpAndOptionsMenu::UpdateLocalizedText() { if (!m_document) return; auto setText = [this](const Rml::String& id, int ids) { auto* el = m_document->GetElementById(id); if (el) el->SetInnerRML(WStringToUTF8(app.GetString(ids))); }; setText("change_skin", IDS_CHANGE_SKIN); setText("how_to_play", IDS_HOW_TO_PLAY); setText("controls", IDS_CONTROLS); setText("settings", IDS_SETTINGS); setText("credits", IDS_CREDITS); } void UIScene_HelpAndOptionsMenu::updateComponents() { UpdateLocalizedText(); 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_HelpAndOptionsMenu::navigateBack() { ui.PlayUISFX(eSFX_Back); UIScene::navigateBack(); } void UIScene_HelpAndOptionsMenu::OnChangeSkin() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SkinSelectMenu); } void UIScene_HelpAndOptionsMenu::OnHowToPlay() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_HowToPlayMenu); } void UIScene_HelpAndOptionsMenu::OnControls() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_ControlsMenu); } void UIScene_HelpAndOptionsMenu::OnSettings() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_SettingsMenu); } void UIScene_HelpAndOptionsMenu::OnCredits() { ui.PlayUISFX(eSFX_Press); ui.NavigateToScene(m_iPad, eUIScene_Credits); }