diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index 81a2c15989..df13df0ff5 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -10,6 +10,8 @@ *****************************************************************************/ #include "StdInc.h" +#include +#include #include #include #include @@ -1683,6 +1685,15 @@ void CSettings::UpdateVideoTab() m_pPlayerMapImageCombo->SetSelectedItemByIndex(iVar); } +struct ResolutionData +{ + int width; + int height; + int depth; + int vidMode; + bool isWidescreen; +}; + // // PopulateResolutionComboBox // @@ -1696,47 +1707,86 @@ void CSettings::PopulateResolutionComboBox() bool bShowUnsafeResolutions = m_pCheckBoxShowUnsafeResolutions->GetSelected(); CGameSettings* gameSettings = CCore::GetSingleton().GetGame()->GetSettings(); + if (!gameSettings) + return; VideoMode vidModemInfo; int vidMode, numVidModes; + std::vector resolutions; + if (!m_pComboResolution) + return; + m_pComboResolution->Clear(); numVidModes = gameSettings->GetNumVideoModes(); for (vidMode = 0; vidMode < numVidModes; vidMode++) { - gameSettings->GetVideoModeInfo(&vidModemInfo, vidMode); + if (!gameSettings->GetVideoModeInfo(&vidModemInfo, vidMode)) + continue; // Remove resolutions that will make the gui unusable if (vidModemInfo.width < 640 || vidModemInfo.height < 480) continue; + // Check resolution is below desktop res unless that is allowed + if (gameSettings->IsUnsafeResolution(vidModemInfo.width, vidModemInfo.height) && !bShowUnsafeResolutions) + continue; + + if (!(vidModemInfo.flags & rwVIDEOMODEEXCLUSIVE)) + continue; + + ResolutionData resData; + resData.width = vidModemInfo.width; + resData.height = vidModemInfo.height; + resData.depth = vidModemInfo.depth; + resData.vidMode = vidMode; + resData.isWidescreen = (vidModemInfo.flags & rwVIDEOMODE_XBOX_WIDESCREEN) != 0; + // Check resolution hasn't already been added bool bDuplicate = false; - for (int i = 1; i < vidMode; i++) + for (const auto& existing : resolutions) { - VideoMode info; - gameSettings->GetVideoModeInfo(&info, i); - if (info.width == vidModemInfo.width && info.height == vidModemInfo.height && info.depth == vidModemInfo.depth) + if (existing.width == resData.width && existing.height == resData.height && existing.depth == resData.depth) + { bDuplicate = true; + break; + } } - if (bDuplicate) - continue; - - // Check resolution is below desktop res unless that is allowed - if (gameSettings->IsUnsafeResolution(vidModemInfo.width, vidModemInfo.height) && !bShowUnsafeResolutions) - continue; + + if (!bDuplicate) + resolutions.push_back(resData); + } - SString strMode("%lu x %lu x %lu", vidModemInfo.width, vidModemInfo.height, vidModemInfo.depth); + if (resolutions.empty()) + return; - if (vidModemInfo.flags & rwVIDEOMODEEXCLUSIVE) - m_pComboResolution->AddItem(strMode)->SetData((void*)vidMode); + // Sort resolutions by width (descending), then by height, then by depth + std::sort(resolutions.begin(), resolutions.end(), [](const ResolutionData& a, const ResolutionData& b) { + if (a.width != b.width) + return a.width > b.width; + if (a.height != b.height) + return a.height > b.height; + return a.depth > b.depth; + }); + + SString selectedText; + VideoMode currentInfo; + if (gameSettings->GetVideoModeInfo(¤tInfo, iNextVidMode)) + { + for (const auto& res : resolutions) + { + SString strMode("%d x %d x %d", res.width, res.height, res.depth); + CGUIListItem* pItem = m_pComboResolution->AddItem(strMode); + if (pItem) + pItem->SetData((void*)res.vidMode); - VideoMode currentInfo; - gameSettings->GetVideoModeInfo(¤tInfo, iNextVidMode); + if (currentInfo.width == res.width && currentInfo.height == res.height && currentInfo.depth == res.depth) + selectedText = strMode; + } - if (currentInfo.width == vidModemInfo.width && currentInfo.height == vidModemInfo.height && currentInfo.depth == vidModemInfo.depth) - m_pComboResolution->SetText(strMode); + if (!selectedText.empty()) + m_pComboResolution->SetText(selectedText); } }