@@ -1815,6 +1815,82 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
18151815 if (DoButton_CheckBox (&g_Config.m_SndHighlight , Localize (" Enable highlighted chat sound" ), g_Config.m_SndHighlight , &Button))
18161816 g_Config.m_SndHighlight ^= 1 ;
18171817
1818+ // Audio pack selection
1819+ {
1820+ MainView.HSplitTop (10 .0f , nullptr , &MainView);
1821+ MainView.HSplitTop (20 .0f , &Button, &MainView);
1822+ Ui ()->DoLabel (&Button, Localize (" Audio Pack" ), 14 .0f , TEXTALIGN_ML);
1823+
1824+ MainView.HSplitTop (5 .0f , nullptr , &MainView);
1825+ CUIRect ListBox;
1826+ MainView.HSplitTop (150 .0f , &ListBox, &MainView);
1827+
1828+ static std::vector<std::string> s_vAudioPacks;
1829+ static bool s_AudioPacksScanned = false ;
1830+ static int s_LastScanTime = 0 ;
1831+ int CurrentTime = time_get ();
1832+ // Rescan every 2 seconds
1833+ if (!s_AudioPacksScanned || CurrentTime - s_LastScanTime > time_freq () * 2 )
1834+ {
1835+ s_AudioPacksScanned = true ;
1836+ s_LastScanTime = CurrentTime;
1837+ s_vAudioPacks.clear ();
1838+ s_vAudioPacks.emplace_back (" " );
1839+
1840+ struct SAudioPackScanData
1841+ {
1842+ std::vector<std::string> *m_pPacks;
1843+ IStorage *m_pStorage;
1844+ } ScanData;
1845+ ScanData.m_pPacks = &s_vAudioPacks;
1846+ ScanData.m_pStorage = Storage ();
1847+
1848+ auto AudioPackScan = [](const char *pName, int IsDir, int Type, void *pUser) -> int {
1849+ if (!IsDir || pName[0 ] == ' .' )
1850+ return 0 ;
1851+ SAudioPackScanData *pData = static_cast <SAudioPackScanData *>(pUser);
1852+ char aBuf[IO_MAX_PATH_LENGTH];
1853+ str_format (aBuf, sizeof (aBuf), " audio_packs/%s/audio" , pName);
1854+ if (pData->m_pStorage ->FolderExists (aBuf, IStorage::TYPE_SAVE))
1855+ {
1856+ pData->m_pPacks ->push_back (std::string (pName));
1857+ }
1858+ return 0 ;
1859+ };
1860+
1861+ Storage ()->ListDirectory (IStorage::TYPE_SAVE, " audio_packs" , AudioPackScan, &ScanData);
1862+ }
1863+
1864+ static CListBox s_AudioPackListBox;
1865+ int OldSelected = -1 ;
1866+ for (size_t i = 0 ; i < s_vAudioPacks.size (); i++)
1867+ {
1868+ if (str_comp (s_vAudioPacks[i].c_str (), g_Config.m_ClAudioPack ) == 0 )
1869+ {
1870+ OldSelected = i;
1871+ break ;
1872+ }
1873+ }
1874+
1875+ s_AudioPackListBox.DoStart (20 .0f , s_vAudioPacks.size (), 1 , 3 , OldSelected, &ListBox);
1876+ for (size_t i = 0 ; i < s_vAudioPacks.size (); i++)
1877+ {
1878+ const CListboxItem Item = s_AudioPackListBox.DoNextItem (&s_vAudioPacks[i], OldSelected >= 0 && (size_t )OldSelected == i);
1879+ if (!Item.m_Visible )
1880+ continue ;
1881+
1882+ const char *pDisplayName = s_vAudioPacks[i].empty () ? Localize (" Default" ) : s_vAudioPacks[i].c_str ();
1883+ Ui ()->DoLabel (&Item.m_Rect , pDisplayName, 12 .0f , TEXTALIGN_ML);
1884+ }
1885+
1886+ const int NewSelected = s_AudioPackListBox.DoEnd ();
1887+ if (OldSelected != NewSelected && NewSelected >= 0 && (size_t )NewSelected < s_vAudioPacks.size ())
1888+ {
1889+ str_copy (g_Config.m_ClAudioPack , s_vAudioPacks[NewSelected].c_str (), sizeof (g_Config.m_ClAudioPack ));
1890+ GameClient ()->m_Sounds .ReloadSounds ();
1891+ }
1892+ }
1893+
18181894 // volume slider
18191895 {
18201896 MainView.HSplitTop (5 .0f , nullptr , &MainView);
0 commit comments