Skip to content

Commit b162368

Browse files
committed
Addendum to 86ad47c & dc0fb96
1 parent a2d20ba commit b162368

File tree

7 files changed

+382
-129
lines changed

7 files changed

+382
-129
lines changed

Client/core/CGUI.cpp

Lines changed: 94 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ CLocalGUI::CLocalGUI()
4444

4545
m_LastSettingsRevision = -1;
4646
m_LocaleChangeCounter = 0;
47+
m_bHasQueuedLocaleChange = false;
4748
}
4849

4950
CLocalGUI::~CLocalGUI()
@@ -123,8 +124,15 @@ void CLocalGUI::ChangeLocale(const char* szName)
123124
CClientVariables* cvars = CCore::GetSingleton().GetCVars();
124125
m_LastSettingsRevision = cvars->GetRevision();
125126

126-
g_pLocalization->SetCurrentLanguage();
127-
m_LastLocaleName = szName;
127+
g_pLocalization->SetCurrentLanguage(szName ? szName : "");
128+
129+
SString strCanonicalLocale = g_pLocalization->GetLanguageCode();
130+
if (strCanonicalLocale.empty())
131+
strCanonicalLocale = CVARS_GET_VALUE<SString>("locale");
132+
if (strCanonicalLocale.empty() && szName)
133+
strCanonicalLocale = szName;
134+
135+
m_LastLocaleName = strCanonicalLocale;
128136

129137
if (guiWasLoaded)
130138
{
@@ -211,6 +219,78 @@ void CLocalGUI::DestroyObjects()
211219
SAFE_DELETE(m_pLabelVersionTag);
212220
}
213221

222+
void CLocalGUI::RequestLocaleChange(const SString& strLocale)
223+
{
224+
if (strLocale.empty())
225+
return;
226+
227+
if (m_bHasQueuedLocaleChange && strLocale == m_QueuedLocaleChange)
228+
return;
229+
230+
const SString strCurrentLocale = CVARS_GET_VALUE<SString>("locale");
231+
if (!m_bHasQueuedLocaleChange && strLocale == strCurrentLocale && strLocale == m_LastLocaleName)
232+
return;
233+
234+
if (m_LocaleChangeCounter > 0)
235+
CCore::GetSingleton().RemoveMessageBox();
236+
237+
m_QueuedLocaleChange = strLocale;
238+
m_bHasQueuedLocaleChange = true;
239+
m_LocaleChangeCounter = 0;
240+
241+
// Keep the cvar at the last applied locale so dependent systems remain stable while we rebuild UI
242+
if (!m_LastLocaleName.empty() && strCurrentLocale != m_LastLocaleName)
243+
CVARS_SET("locale", m_LastLocaleName);
244+
}
245+
246+
void CLocalGUI::ApplyQueuedLocale()
247+
{
248+
if (!m_bHasQueuedLocaleChange)
249+
return;
250+
251+
CClientVariables* cvars = CCore::GetSingleton().GetCVars();
252+
253+
if (m_QueuedLocaleChange.empty())
254+
{
255+
m_bHasQueuedLocaleChange = false;
256+
m_LocaleChangeCounter = 0;
257+
CCore::GetSingleton().RemoveMessageBox();
258+
return;
259+
}
260+
261+
if (CCore::GetSingleton().GetModManager()->IsLoaded())
262+
{
263+
CCore::GetSingleton().GetConsole()->Printf("Please disconnect before changing language");
264+
if (cvars)
265+
cvars->Set("locale", m_LastLocaleName);
266+
267+
m_bHasQueuedLocaleChange = false;
268+
m_QueuedLocaleChange.clear();
269+
m_LocaleChangeCounter = 0;
270+
CCore::GetSingleton().RemoveMessageBox();
271+
return;
272+
}
273+
274+
ChangeLocale(m_QueuedLocaleChange);
275+
276+
m_bHasQueuedLocaleChange = false;
277+
SString strAppliedLocale = m_LastLocaleName;
278+
m_QueuedLocaleChange.clear();
279+
m_LocaleChangeCounter = 0;
280+
281+
if (!strAppliedLocale.empty())
282+
{
283+
SString strCurrentLocale = CVARS_GET_VALUE<SString>("locale");
284+
if (strCurrentLocale != strAppliedLocale)
285+
CVARS_SET("locale", strAppliedLocale);
286+
}
287+
288+
if (cvars)
289+
m_LastSettingsRevision = cvars->GetRevision();
290+
291+
CCore::GetSingleton().RemoveMessageBox();
292+
}
293+
214294
void CLocalGUI::DoPulse()
215295
{
216296
m_pVersionUpdater->DoPulse();
@@ -247,33 +327,21 @@ void CLocalGUI::DoPulse()
247327
{
248328
m_LastLocaleName = currentLocaleName;
249329
}
250-
if (currentLocaleName != m_LastLocaleName)
330+
else if (!m_bHasQueuedLocaleChange && currentLocaleName != m_LastLocaleName)
251331
{
252-
m_LocaleChangeCounter++;
253-
if (m_LocaleChangeCounter < 5)
254-
{
255-
// Do GUI stuff for first 5 frames
256-
// Force pulse next time
257-
m_LastSettingsRevision = cvars->GetRevision() - 1;
332+
RequestLocaleChange(currentLocaleName);
333+
}
334+
}
258335

259-
if (m_LocaleChangeCounter == 2)
260-
CCore::GetSingleton().ShowMessageBox(_E("CC99"), ("Changing language, please wait..."), MB_ICON_INFO);
261-
}
262-
else
263-
{
264-
// Do actual locale change
265-
m_LocaleChangeCounter = 0;
266-
CCore::GetSingleton().RemoveMessageBox();
336+
if (m_bHasQueuedLocaleChange)
337+
{
338+
m_LocaleChangeCounter++;
267339

268-
if (!CCore::GetSingleton().GetModManager()->IsLoaded())
269-
ChangeLocale(currentLocaleName);
270-
else
271-
{
272-
CCore::GetSingleton().GetConsole()->Printf("Please disconnect before changing language");
273-
cvars->Set("locale", m_LastLocaleName);
274-
}
275-
}
276-
}
340+
if (m_LocaleChangeCounter == 2)
341+
CCore::GetSingleton().ShowMessageBox(_E("CC99"), ("Changing language, please wait..."), MB_ICON_INFO);
342+
343+
if (m_LocaleChangeCounter >= 5)
344+
ApplyQueuedLocale();
277345
}
278346
}
279347

Client/core/CGUI.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@ class CLocalGUI : public CSingleton<CLocalGUI>
9292
bool IsOptionalUpdateInfoRequired(const char* szHost) { return m_pVersionUpdater->IsOptionalUpdateInfoRequired(szHost); }
9393
void InitiateDataFilesFix() { m_pVersionUpdater->InitiateDataFilesFix(); }
9494

95+
void RequestLocaleChange(const SString& strLocale);
96+
9597
private:
9698
void UpdateCursor();
99+
void ApplyQueuedLocale();
97100

98101
DWORD TranslateScanCodeToGUIKey(DWORD dwCharacter);
99102

@@ -118,4 +121,6 @@ class CLocalGUI : public CSingleton<CLocalGUI>
118121
SString m_LastSkinName;
119122
SString m_LastLocaleName;
120123
uint m_LocaleChangeCounter;
124+
SString m_QueuedLocaleChange;
125+
bool m_bHasQueuedLocaleChange;
121126
};

Client/core/CLanguageSelector.cpp

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,18 @@ CLanguageSelector::~CLanguageSelector()
6161
if (!element)
6262
return;
6363

64-
if (pGUI)
65-
pGUI->DestroyElementRecursive(element);
64+
auto* elementToDestroy = element;
6665
element = nullptr;
66+
if (pGUI)
67+
pGUI->DestroyElementRecursive(elementToDestroy);
6768
};
6869

69-
destroyElement(m_pListWindow);
70-
destroyElement(m_pButtonWindow);
71-
70+
// Ensure callbacks see a safe state even if destruction triggers them re-entrantly
7271
m_ButtonItem = CLangListItem();
7372
m_ListItems.clear();
73+
74+
destroyElement(m_pListWindow);
75+
destroyElement(m_pButtonWindow);
7476
}
7577

7678
///////////////////////////////////////////////////////////////
@@ -230,6 +232,9 @@ CLangListItem CLanguageSelector::CreateGUILangItem(CGUIElement* pGUIParent, cons
230232
///////////////////////////////////////////////////////////////
231233
void CLanguageSelector::DoPulse()
232234
{
235+
if (!m_pButtonWindow)
236+
return;
237+
233238
if (CLocalGUI::GetSingleton().GetMainMenu()->GetIsIngame())
234239
{
235240
// Can't change locale when connected, so hide
@@ -245,12 +250,12 @@ void CLanguageSelector::DoPulse()
245250
fDeltaSeconds = Clamp(0.01f, fDeltaSeconds, 0.10f);
246251

247252
// Update current language button mouseover effect
248-
m_bListWasVisible = m_pListWindow->IsVisible();
253+
m_bListWasVisible = m_pListWindow && m_pListWindow->IsVisible();
249254
m_pButtonWindow->SetAlpha((m_bMouseOverButton || m_bListWasVisible) ? 1.f : 0.5f);
250255
m_pButtonWindow->SetVisible(true);
251256

252257
// Animate list items if list is visible
253-
if (m_bListWasVisible)
258+
if (m_bListWasVisible && m_pListWindow)
254259
{
255260
for (CLangListItem& item : m_ListItems)
256261
{
@@ -267,16 +272,6 @@ void CLanguageSelector::DoPulse()
267272
}
268273
}
269274

270-
bool CLanguageSelector::ConsumePendingLocale(SString& outLocale)
271-
{
272-
if (m_strPendingLocale.empty())
273-
return false;
274-
275-
outLocale = m_strPendingLocale;
276-
m_strPendingLocale.clear();
277-
return true;
278-
}
279-
280275
///////////////////////////////////////////////////////////////
281276
//
282277
// CLanguageSelector::SetLanguageListVisible
@@ -286,6 +281,9 @@ bool CLanguageSelector::ConsumePendingLocale(SString& outLocale)
286281
///////////////////////////////////////////////////////////////
287282
void CLanguageSelector::SetLanguageListVisible(bool bVisible)
288283
{
284+
if (!m_pListWindow)
285+
return;
286+
289287
if (bVisible)
290288
{
291289
m_pListWindow->BringToFront();
@@ -294,7 +292,6 @@ void CLanguageSelector::SetLanguageListVisible(bool bVisible)
294292
}
295293
m_pListWindow->SetVisible(bVisible);
296294
}
297-
298295
///////////////////////////////////////////////////////////////
299296
//
300297
// CLanguageSelector::GetListItemByIndex
@@ -393,12 +390,11 @@ bool CLanguageSelector::OnListItemClick(CGUIElement* pElement)
393390
if (pItem)
394391
{
395392
SetLanguageListVisible(false);
396-
SString strPrevLocale = CVARS_GET_VALUE<SString>("locale");
397-
SString strNewLocale = pItem->strLocale;
393+
const SString strPrevLocale = CVARS_GET_VALUE<SString>("locale");
394+
const SString strNewLocale = pItem->strLocale;
398395
if (strNewLocale != strPrevLocale)
399396
{
400-
// Defer locale change to avoid destroying GUI during callback stack
401-
m_strPendingLocale = strNewLocale;
397+
CLocalGUI::GetSingleton().RequestLocaleChange(strNewLocale);
402398

403399
// Update button label immediately so user sees their selection
404400
m_ButtonItem.strLocale = strNewLocale;

Client/core/CLanguageSelector.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ class CLanguageSelector
3030
CLanguageSelector(CGUIElement* pMainMenuCanvas);
3131
~CLanguageSelector();
3232
void DoPulse();
33-
bool ConsumePendingLocale(SString& outLocale);
3433

3534
protected:
3635
void CreateGUI(CGUIElement* pMainMenuCanvas);
@@ -52,5 +51,4 @@ class CLanguageSelector
5251
CTickCount m_LastTickCount;
5352
bool m_bMouseOverButton;
5453
bool m_bListWasVisible;
55-
SString m_strPendingLocale;
5654
};

Client/core/CLocalization.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,18 @@ void CLocalization::SetCurrentLanguage(SString strLocale)
7878

7979
// Update our locale setting with full country code, now that we've matched it
8080
if (g_pCore)
81-
CVARS_SET("locale", strLocale);
81+
{
82+
SString strCurrentLocale = CVARS_GET_VALUE<SString>("locale");
83+
if (strCurrentLocale != strLocale)
84+
CVARS_SET("locale", strLocale);
85+
}
86+
87+
SString strStoredLocale = GetApplicationSetting("locale");
88+
if (strStoredLocale != strLocale)
89+
SetApplicationSetting("locale", strLocale);
90+
91+
if (m_pCurrentLang && m_pCurrentLang->GetCode() == strLocale)
92+
return;
8293

8394
m_pCurrentLang = GetLanguage(strLocale);
8495
}

Client/core/CMainMenu.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -730,16 +730,6 @@ void CMainMenu::Update()
730730
m_ServerBrowser.Update();
731731
m_ServerInfo.DoPulse();
732732
m_pLanguageSelector->DoPulse();
733-
734-
if (m_pLanguageSelector)
735-
{
736-
SString strPendingLocale;
737-
if (m_pLanguageSelector->ConsumePendingLocale(strPendingLocale))
738-
{
739-
CVARS_SET("locale", strPendingLocale);
740-
SetApplicationSetting("locale", strPendingLocale);
741-
}
742-
}
743733
}
744734

745735
void CMainMenu::Show(bool bOverlay)

0 commit comments

Comments
 (0)