Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Client/core/CGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ void CLocalGUI::ChangeLocale(const char* szName)

m_LastLocaleName = strCanonicalLocale;

// Attempt CEGUI cleanup
if (CGUI* pGUI = CCore::GetSingleton().GetGUI())
pGUI->Cleanup();

if (guiWasLoaded)
{
CreateWindows(guiWasLoaded);
Expand Down
50 changes: 25 additions & 25 deletions Client/core/CLocalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ CLocalization::CLocalization(const SString& strLocale, const SString& strLocaleP

CLocalization::~CLocalization()
{
for (auto iter : m_LanguageMap)
{
delete iter.second;
}
// m_LanguageMap now uses unique_ptr so cleanup is automatic
}

//
Expand Down Expand Up @@ -99,29 +96,32 @@ void CLocalization::SetCurrentLanguage(SString strLocale)
CLanguage* CLocalization::GetLanguage(SString strLocale)
{
strLocale = ValidateLocale(strLocale);
CLanguage* pLanguage = MapFindRef(m_LanguageMap, strLocale);
if (!pLanguage)
auto iter = m_LanguageMap.find(strLocale);
if (iter != m_LanguageMap.end())
{
return iter->second.get();
}

Language Lang = Language::from_name(strLocale);
Lang = Lang ? Lang : Language::from_name("en_US");

try
{
std::unique_ptr<CLanguage> pLanguage = std::make_unique<CLanguage>(m_DictManager.get_dictionary(Lang, MTA_LOCALE_TEXTDOMAIN), Lang.str(), Lang.get_name());
CLanguage* pLanguagePtr = pLanguage.get();
m_LanguageMap.emplace(strLocale, std::move(pLanguage));
return pLanguagePtr;
}
catch (const std::exception& ex)
{
WriteDebugEvent(SString("Localization failed to load dictionary for '%s': %s", strLocale.c_str(), ex.what()));
return (strLocale != "en_US") ? GetLanguage("en_US") : nullptr;
}
catch (...)
{
Language Lang = Language::from_name(strLocale);
Lang = Lang ? Lang : Language::from_name("en_US");

try
{
pLanguage = new CLanguage(m_DictManager.get_dictionary(Lang, MTA_LOCALE_TEXTDOMAIN), Lang.str(), Lang.get_name());
MapSet(m_LanguageMap, strLocale, pLanguage);
}
catch (const std::exception& ex)
{
WriteDebugEvent(SString("Localization failed to load dictionary for '%s': %s", strLocale.c_str(), ex.what()));
return (strLocale != "en_US") ? GetLanguage("en_US") : nullptr;
}
catch (...)
{
WriteDebugEvent(SString("Localization failed to load dictionary for '%s': unknown error", strLocale.c_str()));
return (strLocale != "en_US") ? GetLanguage("en_US") : nullptr;
}
WriteDebugEvent(SString("Localization failed to load dictionary for '%s': unknown error", strLocale.c_str()));
return (strLocale != "en_US") ? GetLanguage("en_US") : nullptr;
}
return pLanguage;
}

//
Expand Down
8 changes: 4 additions & 4 deletions Client/core/CLocalization.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ using namespace tinygettext;

#include <core/CLocalizationInterface.h>
#include "CLanguage.h"
#define MTA_LOCALE_DIR "MTA/locale/"
#define MTA_LOCALE_DIR "MTA/locale/"

#pragma once

Expand Down Expand Up @@ -42,7 +42,7 @@ class CLocalization : public CLocalizationInterface
static void LogCallback(const std::string& str);

private:
DictionaryManager m_DictManager;
std::map<SString, CLanguage*> m_LanguageMap;
CLanguage* m_pCurrentLang{};
DictionaryManager m_DictManager;
std::map<SString, std::unique_ptr<CLanguage>> m_LanguageMap;
CLanguage* m_pCurrentLang{};
};
33 changes: 30 additions & 3 deletions Client/gui/CGUI_Impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,17 @@ CGUI_Impl::~CGUI_Impl()
// DO NOT delete m_pRenderer - it's already deleted by System destructor
}

void CGUI_Impl::CreateRootWindow()
{
// Create dummy GUI root
m_pTop = reinterpret_cast<CEGUI::DefaultWindow*>(m_pWindowManager->createWindow("DefaultWindow", "guiroot"));
m_pSystem->setGUISheet(m_pTop);
}

void CGUI_Impl::SetSkin(const char* szName)
{
m_currentSkin = szName;

if (m_HasSchemeLoaded)
{
CEGUI::GlobalEventSet::getSingletonPtr()->removeAllEvents();
Expand All @@ -165,9 +174,8 @@ void CGUI_Impl::SetSkin(const char* szName)
// Destroy any windows we already have
CEGUI::WindowManager::getSingleton().destroyAllWindows();

// Create dummy GUI root
m_pTop = reinterpret_cast<CEGUI::DefaultWindow*>(m_pWindowManager->createWindow("DefaultWindow", "guiroot"));
m_pSystem->setGUISheet(m_pTop);
// Clean up CEGUI - this also re-creates the root window
Cleanup();

// Disable single click timeouts
m_pSystem->setSingleClickTimeout(100000000.0f);
Expand Down Expand Up @@ -1797,3 +1805,22 @@ CEGUI::Window* CGUI_Impl::GetMasterWindow(CEGUI::Window* wnd)
}
return wnd;
}

void CGUI_Impl::Cleanup()
{
try
{
CleanDeadPool();

if (m_pWindowManager)
m_pWindowManager->destroyAllWindows();

// Clear redraw structures that may reference old elements
m_RedrawQueue.clear();
m_RedrawRegistry.clear();

// Recreate the root window (destroyed above via destroyAllWindows)
CreateRootWindow();
}
catch (...) {}
}
6 changes: 6 additions & 0 deletions Client/gui/CGUI_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ class CGUI_Impl : public CGUI, public CGUITabList
CGUIWindow* LoadLayout(CGUIElement* pParent, const SString& strFilename);
bool LoadImageset(const SString& strFilename);

// Cleanup CEGUI active resources (dead pool)
void Cleanup();

private:
friend class CGUIElement_Impl;
CGUIButton* _CreateButton(CGUIElement_Impl* pParent = NULL, const char* szCaption = "");
Expand Down Expand Up @@ -361,4 +364,7 @@ class CGUI_Impl : public CGUI, public CGUITabList
bool m_HasSchemeLoaded;
SString m_CurrentSchemeName;
CElapsedTime m_RenderOkTimer;
const char* m_currentSkin;

void CreateRootWindow();
};
2 changes: 2 additions & 0 deletions Client/sdk/gui/CGUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,6 @@ class CGUI

virtual CGUIWindow* LoadLayout(CGUIElement* pParent, const SString& strFilename) = 0;
virtual bool LoadImageset(const SString& strFilename) = 0;

virtual void Cleanup() = 0;
};
Loading