Refresh localized text on gainFocus for RmlUI menus

This commit is contained in:
Zero
2026-06-12 15:06:50 +02:00
parent d33ac0e45e
commit 6399a965d6
6 changed files with 129 additions and 7 deletions

View File

@@ -20,6 +20,18 @@
#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)
@@ -36,7 +48,7 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
{
m_document->Show();
bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
UpdateLocalizedText();
// Change Skin: hide if not full version
if (!ProfileManager.IsFullVersion())
@@ -60,7 +72,8 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
m_document->GetElementById("credits")->AddEventListener(Rml::EventId::Click, this);
// Focus first visible button
m_document->GetElementById("change_skin")->Focus();
auto* elFirst = m_document->GetElementById("change_skin");
if (elFirst) elFirst->Focus();
}
else
{
@@ -200,8 +213,27 @@ 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)
{

View File

@@ -48,6 +48,8 @@ protected:
void OnSettings();
void OnCredits();
void UpdateLocalizedText();
private:
Rml::ElementDocument* m_document;
};

View File

@@ -21,6 +21,18 @@
#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_PauseMenu::UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLayer)
: UIScene(iPad, parentLayer)
, m_document(nullptr)
@@ -42,6 +54,9 @@ UIScene_PauseMenu::UIScene_PauseMenu(int iPad, void *initData, UILayer *parentLa
m_document->Show();
app.DebugPrintf("[RmlPauseMenu] Document shown, visible=%d, context docs=%d\n",
m_document->IsVisible(), ctx->GetNumDocuments());
UpdateLocalizedText();
m_document->GetElementById("resume")->AddEventListener(Rml::EventId::Click, this);
m_document->GetElementById("help_options")->AddEventListener(Rml::EventId::Click, this);
m_document->GetElementById("achievements")->AddEventListener(Rml::EventId::Click, this);
@@ -248,6 +263,32 @@ void UIScene_PauseMenu::ProcessEvent(Rml::Event& event)
}
}
void UIScene_PauseMenu::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("resume", IDS_RESUME_GAME);
setText("help_options", IDS_HELP_AND_OPTIONS);
setText("achievements", IDS_ACHIEVEMENTS);
setText("save_game", IDS_SAVE_GAME);
setText("exit_game", IDS_EXIT_GAME);
setText("exit_save", IDS_EXIT_GAME_SAVE);
setText("exit_nosave", IDS_EXIT_GAME_NO_SAVE);
setText("exit_cancel", IDS_CANCEL);
setText("save_cancel", IDS_CANCEL);
}
void UIScene_PauseMenu::updateComponents()
{
UpdateLocalizedText();
}
void UIScene_PauseMenu::ShowScene(bool show)
{
if (m_document)
@@ -310,6 +351,7 @@ void UIScene_PauseMenu::ShowSaveDialog(bool show)
if (saveText) saveText->SetInnerRML("Overwrite existing save?");
}
m_document->GetElementById("save_cancel")->SetInnerRML(WStringToUTF8(app.GetString(IDS_CANCEL)));
m_document->GetElementById("save_cancel")->Focus();
m_bSaveDialog = true;
}
@@ -387,19 +429,23 @@ void UIScene_PauseMenu::ShowExitDialog(bool show)
auto* exitCancel = m_document->GetElementById("exit_cancel");
auto* exitText = m_document->GetElementById("exit_text");
if (exitSave) exitSave->SetInnerRML(WStringToUTF8(app.GetString(IDS_EXIT_GAME_SAVE)));
if (exitCancel) exitCancel->SetInnerRML(WStringToUTF8(app.GetString(IDS_CANCEL)));
if (ProfileManager.IsFullVersion() && m_iPad == ProfileManager.GetPrimaryPad())
{
// Full version primary pad: show Save & Exit + Exit without Saving + Cancel
if (exitSave) exitSave->SetProperty("display", "inline-block");
if (exitNosave) exitNosave->SetProperty("display", "inline-block");
if (exitNosave) exitNosave->SetInnerRML(WStringToUTF8(app.GetString(IDS_EXIT_GAME_NO_SAVE)));
if (g_NetworkManager.GetPlayerCount() > 1)
{
if (exitText) exitText->SetInnerRML("Exit Game (disconnect other players)?");
if (exitText) exitText->SetInnerRML(WStringToUTF8(app.GetString(IDS_CONFIRM_EXIT_GAME_CONFIRM_DISCONNECT_SAVE)));
}
else
{
if (exitText) exitText->SetInnerRML("Exit Game?");
if (exitText) exitText->SetInnerRML(WStringToUTF8(app.GetString(IDS_CONFIRM_EXIT_GAME)));
}
if (exitCancel) exitCancel->Focus();
}
@@ -408,8 +454,8 @@ void UIScene_PauseMenu::ShowExitDialog(bool show)
// Trial version: simple OK/Cancel, "progress will be lost"
if (exitSave) exitSave->SetProperty("display", "none");
if (exitNosave) exitNosave->SetProperty("display", "inline-block");
if (exitNosave) exitNosave->SetInnerRML("Yes");
if (exitText) exitText->SetInnerRML("Exit Game (progress will be lost)?");
if (exitNosave) exitNosave->SetInnerRML(WStringToUTF8(app.GetString(IDS_YES)));
if (exitText) exitText->SetInnerRML(WStringToUTF8(app.GetString(IDS_CONFIRM_EXIT_GAME_PROGRESS_LOST)));
if (exitCancel) exitCancel->Focus();
}
@@ -424,7 +470,8 @@ void UIScene_PauseMenu::ShowExitDialog(bool show)
auto* exitSave = m_document->GetElementById("exit_save");
auto* exitNosave = m_document->GetElementById("exit_nosave");
if (exitSave) exitSave->SetProperty("display", "inline-block");
if (exitNosave) exitNosave->SetInnerRML("Exit without Saving");
if (exitSave) exitSave->SetInnerRML(WStringToUTF8(app.GetString(IDS_EXIT_GAME_SAVE)));
if (exitNosave) exitNosave->SetInnerRML(WStringToUTF8(app.GetString(IDS_EXIT_GAME_NO_SAVE)));
if (exitNosave) exitNosave->SetProperty("display", "inline-block");
m_document->GetElementById("exit_game")->Focus();

View File

@@ -38,6 +38,7 @@ protected:
virtual wstring getMoviePath() { return L""; }
virtual void handleLoseFocus() override;
virtual void updateComponents() override;
void ShowScene(bool show) override;
void SetIgnoreInput(bool ignoreInput) override { m_bIgnoreInput = ignoreInput; }
@@ -58,6 +59,8 @@ protected:
void ShowExitDialog(bool show);
void ShowSaveDialog(bool show);
void UpdateLocalizedText();
private:
Rml::ElementDocument* m_document;
bool m_bIgnoreInput;

View File

@@ -20,6 +20,18 @@
#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_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *parentLayer)
: UIScene(iPad, parentLayer)
, m_document(nullptr)
@@ -49,6 +61,8 @@ UIScene_SettingsMenu::UIScene_SettingsMenu(int iPad, void *initData, UILayer *pa
if (elGraphics) elGraphics->SetProperty("display", "none");
}
UpdateLocalizedText();
// Register button click listeners
m_document->GetElementById("options")->AddEventListener(Rml::EventId::Click, this);
m_document->GetElementById("audio")->AddEventListener(Rml::EventId::Click, this);
@@ -118,8 +132,30 @@ void UIScene_SettingsMenu::updateTooltips()
{
}
void UIScene_SettingsMenu::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("options", IDS_OPTIONS);
setText("audio", IDS_AUDIO);
setText("controls", IDS_CONTROLS);
setText("graphics", IDS_GRAPHICS);
setText("ui", IDS_USER_INTERFACE);
setText("reset_defaults", IDS_RESET_TO_DEFAULTS);
setText("confirm_yes", IDS_YES);
setText("confirm_no", IDS_NO);
}
void UIScene_SettingsMenu::updateComponents()
{
UpdateLocalizedText();
bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
if (bNotInGame)

View File

@@ -53,6 +53,8 @@ protected:
void ShowConfirmDialog(bool show);
void UpdateLocalizedText();
private:
Rml::ElementDocument* m_document;
bool m_bConfirmDialog;