From 8012d9dca7943507a2bf6d79ad23e1362357ad14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 23 Oct 2026 23:15:05 +0200 Subject: [PATCH] Settings: Use ChoiceGroup on the remaining tabs Each ItemHeader becomes a ChoiceGroup with that title, and the items under it are added to the group, as on the audio tab. Co-Authored-By: Claude Opus 5.5 (1M context) --- UI/GameSettingsScreen.cpp | 460 +++++++++++++++++++------------------- 1 file changed, 230 insertions(+), 230 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2f07aefc3d..2fffa45d70 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -299,13 +299,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) using namespace UI; - graphicsSettings->Add(new ItemHeader(gr->T("Rendering Mode"))); + ChoiceGroup *renderingSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Rendering Mode"))); Draw::DrawContext *draw = screenManager()->getDrawContext(); #if !PPSSPP_PLATFORM(UWP) static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan", "Metal" }; - PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *renderingBackendChoice = renderingSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager())); renderingBackendChoice->SetPreOpenCallback([this](UI::PopupMultiChoice *choice) { // Don't filter until the last possible moment, since it involves trying to initialize Vulkan, if we were // started in OpenGL mode on Android. @@ -331,7 +331,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) #if (PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(TVOS)) || PPSSPP_PLATFORM(ANDROID) // Showing the game there needs a second swapchain. Otherwise the system mirrors the screen. static const char *externalDisplayModes[] = { "Show the game", "Mirror the screen" }; - PopupMultiChoice *externalDisplayChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iExternalDisplay, gr->T("External display"), externalDisplayModes, 0, ARRAY_SIZE(externalDisplayModes), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *externalDisplayChoice = renderingSettings->Add(new PopupMultiChoice(&g_Config.iExternalDisplay, gr->T("External display"), externalDisplayModes, 0, ARRAY_SIZE(externalDisplayModes), I18NCat::GRAPHICS, screenManager())); externalDisplayChoice->SetEnabled(draw->GetDeviceCaps().multipleSwapchains); // Picking the current value again would rebuild the TV's output for nothing (iOS starts over on a change). externalDisplayChoice->OnChoice.Add([previous = g_Config.iExternalDisplay](UI::EventParams &e) mutable { @@ -347,13 +347,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) if (draw->GetDeviceList().size() > 1) { std::string *deviceNameSetting = GPUDeviceNameSetting(); if (deviceNameSetting) { - PopupMultiChoiceDynamic *deviceChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(deviceNameSetting, gr->T("Device"), draw->GetDeviceList(), I18NCat::NONE, screenManager())); + PopupMultiChoiceDynamic *deviceChoice = renderingSettings->Add(new PopupMultiChoiceDynamic(deviceNameSetting, gr->T("Device"), draw->GetDeviceList(), I18NCat::NONE, screenManager())); deviceChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingDevice); } } static const char *internalResolutions[] = { "Auto (1:1)", "1x PSP", "2x PSP", "3x PSP", "4x PSP", "5x PSP", "6x PSP", "7x PSP", "8x PSP", "9x PSP", "10x PSP" }; - PopupMultiChoice *resolutionChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInternalResolution, gr->T("Rendering Resolution"), internalResolutions, 0, ARRAY_SIZE(internalResolutions), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *resolutionChoice = renderingSettings->Add(new PopupMultiChoice(&g_Config.iInternalResolution, gr->T("Rendering Resolution"), internalResolutions, 0, ARRAY_SIZE(internalResolutions), I18NCat::GRAPHICS, screenManager())); resolutionChoice->OnChoice.Add([](UI::EventParams &e) { if (g_Config.iAndroidHwScale == 1) { System_RecreateActivity(); @@ -368,13 +368,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); if (deviceType != DEVICE_TYPE_VR) { - CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (slow)"))); + CheckBox *softwareGPU = renderingSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (slow)"))); softwareGPU->SetEnabled(!PSP_IsInited()); } if (draw->GetDeviceCaps().multiSampleLevelsMask != 1) { static const char *msaaModes[] = { "Off", "2x", "4x", "8x", "16x" }; - auto msaaChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iMultiSampleLevel, gr->T("Antialiasing (MSAA)"), msaaModes, 0, ARRAY_SIZE(msaaModes), I18NCat::GRAPHICS, screenManager())); + auto msaaChoice = renderingSettings->Add(new PopupMultiChoice(&g_Config.iMultiSampleLevel, gr->T("Antialiasing (MSAA)"), msaaModes, 0, ARRAY_SIZE(msaaModes), I18NCat::GRAPHICS, screenManager())); msaaChoice->OnChoice.Add([&](UI::EventParams &) -> void { System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); }); @@ -405,7 +405,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) if (max_res_temp == 3) max_res_temp = 4; // At least allow 2x int max_res = std::min(max_res_temp, (int)ARRAY_SIZE(deviceResolutions)); - UI::PopupMultiChoice *hwscale = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAndroidHwScale, gr->T("Display Resolution (HW scaler)"), deviceResolutions, 0, max_res, I18NCat::GRAPHICS, screenManager())); + UI::PopupMultiChoice *hwscale = renderingSettings->Add(new PopupMultiChoice(&g_Config.iAndroidHwScale, gr->T("Display Resolution (HW scaler)"), deviceResolutions, 0, max_res, I18NCat::GRAPHICS, screenManager())); hwscale->OnChoice.Add([](UI::EventParams &) { System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); @@ -416,18 +416,18 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); - graphicsSettings->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures"))); + renderingSettings->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures"))); - graphicsSettings->Add(new ItemHeader(gr->T("Display"))); + ChoiceGroup *displaySettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Display"))); if (deviceType != DEVICE_TYPE_VR) { #if !defined(MOBILE_DEVICE) - CheckBox *fullscreenCheckbox = graphicsSettings->Add(new CheckBox(&g_Config.bFullScreen, gr->T("Full screen"))); + CheckBox *fullscreenCheckbox = displaySettings->Add(new CheckBox(&g_Config.bFullScreen, gr->T("Full screen"))); fullscreenCheckbox->OnClick.Add([](UI::EventParams &e) { System_ApplyFullscreenState(); }); if (draw->GetDeviceCaps().fullScreenExclusiveSupported) { - CheckBox* fullscreenExclusive = graphicsSettings->Add(new CheckBox(&g_Config.bAllowFullScreenExclusive, gr->T("Allow exclusive fullscreen"))); + CheckBox* fullscreenExclusive = displaySettings->Add(new CheckBox(&g_Config.bAllowFullScreenExclusive, gr->T("Allow exclusive fullscreen"))); fullscreenExclusive->SetEnabledFunc([] { return g_Config.bFullScreen && !g_Config.bFullScreenMulti; }); @@ -439,7 +439,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) }); } if (System_GetPropertyInt(SYSPROP_DISPLAY_COUNT) > 1) { - CheckBox *fullscreenMulti = graphicsSettings->Add(new CheckBox(&g_Config.bFullScreenMulti, gr->T("Use all displays"))); + CheckBox *fullscreenMulti = displaySettings->Add(new CheckBox(&g_Config.bFullScreenMulti, gr->T("Use all displays"))); fullscreenMulti->SetEnabledFunc([] { return g_Config.bFullScreen && !g_Config.bAllowFullScreenExclusive; }); @@ -449,7 +449,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) } #endif // Display Layout Editor: To avoid overlapping touch controls on large tablets, meet geeky demands for integer zoom/unstretched image etc. - Choice *displayEditor = graphicsSettings->Add(new Choice(gr->T("Display layout & effects"))); + Choice *displayEditor = displaySettings->Add(new Choice(gr->T("Display layout & effects"))); displayEditor->OnClick.Add([&](UI::EventParams &) -> void { screenManager()->push(new DisplayLayoutScreen(gamePath_)); }); @@ -459,13 +459,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) if (CountSetBits((u32)draw->GetDeviceCaps().presentModesSupported) > 1) { // Immediate means non-synchronized, tearing. if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::IMMEDIATE) { - CheckBox *vSync = graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync"))); + CheckBox *vSync = displaySettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync"))); vSync->OnClick.Add([=](EventParams &e) { NativeResized(); // TODO: Remove }); } if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::MAILBOX) { - CheckBox *lowLatency = graphicsSettings->Add(new CheckBox(&g_Config.bLowLatencyPresent, gr->T("Low latency display"))); + CheckBox *lowLatency = displaySettings->Add(new CheckBox(&g_Config.bLowLatencyPresent, gr->T("Low latency display"))); lowLatency->OnClick.Add([=](EventParams &e) { NativeResized(); // TODO: Remove }); @@ -477,39 +477,39 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) } } - graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control"))); + ChoiceGroup *frameRateSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Frame Rate Control"))); - PopupSliderChoice *altSpeed1 = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent1, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed", "Alternative speed"), 5, screenManager(), gr->T("%, 0:unlimited"))); + PopupSliderChoice *altSpeed1 = frameRateSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent1, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed", "Alternative speed"), 5, screenManager(), gr->T("%, 0:unlimited"))); altSpeed1->SetFormat("%i%%"); altSpeed1->SetZeroLabel(gr->T("Unlimited")); altSpeed1->SetNegativeDisable(gr->T("Disabled")); - PopupSliderChoice *altSpeed2 = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent2, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed 2", "Alternative speed 2 (in %, 0 = unlimited)"), 5, screenManager(), gr->T("%, 0:unlimited"))); + PopupSliderChoice *altSpeed2 = frameRateSettings->Add(new PopupSliderChoice(&g_Config.iAltSpeedPercent2, 0, 1000, UI::NO_DEFAULT_INT, gr->T("Alternative Speed 2", "Alternative speed 2 (in %, 0 = unlimited)"), 5, screenManager(), gr->T("%, 0:unlimited"))); altSpeed2->SetFormat("%i%%"); altSpeed2->SetZeroLabel(gr->T("Unlimited")); altSpeed2->SetNegativeDisable(gr->T("Disabled")); if (analogSpeedMapped_) { - PopupSliderChoice *analogSpeed = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iAnalogAltSpeedPercent, 1, 1000, UI::NO_DEFAULT_INT, gr->T("Analog alternative speed", "Analog alternative speed (in %)"), 5, screenManager(), "%")); + PopupSliderChoice *analogSpeed = frameRateSettings->Add(new PopupSliderChoice(&g_Config.iAnalogAltSpeedPercent, 1, 1000, UI::NO_DEFAULT_INT, gr->T("Analog alternative speed", "Analog alternative speed (in %)"), 5, screenManager(), "%")); analogSpeed->SetFormat("%i%%"); } - graphicsSettings->Add(new ItemHeader(gr->T("Speed Hacks", "Speed Hacks (can cause rendering errors!)"))); + ChoiceGroup *speedHackSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Speed Hacks", "Speed Hacks (can cause rendering errors!)"))); static const char *frameSkip[] = {"Off", "1", "2", "3", "4"}; - PopupMultiChoice *frameSkipping = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *frameSkipping = speedHackSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), I18NCat::GRAPHICS, screenManager())); frameSkipping->SetChoicesUntranslated(1, (int)ARRAY_SIZE(frameSkip) - 1); frameSkipping->SetEnabledFunc([] { return !g_Config.bAutoFrameSkip; }); - CheckBox *frameSkipAuto = graphicsSettings->Add(new CheckBox(&g_Config.bAutoFrameSkip, gr->T("Auto FrameSkip"))); + CheckBox *frameSkipAuto = speedHackSettings->Add(new CheckBox(&g_Config.bAutoFrameSkip, gr->T("Auto FrameSkip"))); frameSkipAuto->OnClick.Add([](UI::EventParams &e) { g_Config.UpdateAfterSettingAutoFrameSkip(); }); - CheckBox *skipBufferEffects = graphicsSettings->Add(new CheckBox(&g_Config.bSkipBufferEffects, gr->T("Skip Buffer Effects"))); - graphicsSettings->Add(new SettingHint(gr->T("RenderingMode NonBuffered Tip", "Faster, but graphics may be missing in some games"), skipBufferEffects)); + CheckBox *skipBufferEffects = speedHackSettings->Add(new CheckBox(&g_Config.bSkipBufferEffects, gr->T("Skip Buffer Effects"))); + speedHackSettings->Add(new SettingHint(gr->T("RenderingMode NonBuffered Tip", "Faster, but graphics may be missing in some games"), skipBufferEffects)); skipBufferEffects->OnClick.Add([=](EventParams &e) { if (g_Config.bSkipBufferEffects) { g_Config.bAutoFrameSkip = false; @@ -522,13 +522,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) static const char *skipGpuReadbackModes[] = { "No", "Skip", "Copy to texture" }; - PopupMultiChoice *skipGPUReadbacks = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iSkipGPUReadbackMode, gr->T("Skip GPU Readbacks"), skipGpuReadbackModes, 0, ARRAY_SIZE(skipGpuReadbackModes), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *skipGPUReadbacks = speedHackSettings->Add(new PopupMultiChoice(&g_Config.iSkipGPUReadbackMode, gr->T("Skip GPU Readbacks"), skipGpuReadbackModes, 0, ARRAY_SIZE(skipGpuReadbackModes), I18NCat::GRAPHICS, screenManager())); skipGPUReadbacks->SetDisabledPtr(&g_Config.bSoftwareRendering); skipGPUReadbacks->SetDefault(0); static const char *depthRasterModes[] = { "Auto", "Low", "Off", "Always on" }; - PopupMultiChoice *depthRasterMode = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iDepthRasterMode, gr->T("Lens flare occlusion"), depthRasterModes, 0, ARRAY_SIZE(depthRasterModes), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *depthRasterMode = speedHackSettings->Add(new PopupMultiChoice(&g_Config.iDepthRasterMode, gr->T("Lens flare occlusion"), depthRasterModes, 0, ARRAY_SIZE(depthRasterModes), I18NCat::GRAPHICS, screenManager())); depthRasterMode->SetDisabledPtr(&g_Config.bSoftwareRendering); depthRasterMode->SetChoiceIcon(3, ImageID("I_WARNING")); // It's a performance trap. depthRasterMode->SetDefault(DefaultDepthRaster()); @@ -536,30 +536,30 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) depthRasterMode->HideChoice(3); static const char *bloomHackOptions[] = {"Off", "Safe", "Balanced", "Aggressive"}; - PopupMultiChoice *bloomHack = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *bloomHack = speedHackSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), I18NCat::GRAPHICS, screenManager())); bloomHack->SetEnabledFunc([] { return !g_Config.bSoftwareRendering && g_Config.iInternalResolution != 1; }); - graphicsSettings->Add(new SettingHint(gr->T("Reduces artifacts"), bloomHack)); + speedHackSettings->Add(new SettingHint(gr->T("Reduces artifacts"), bloomHack)); - graphicsSettings->Add(new ItemHeader(gr->T("Performance"))); - CheckBox *frameDuplication = graphicsSettings->Add(new CheckBox(&g_Config.bRenderDuplicateFrames, gr->T("Render duplicate frames to 60hz"))); + ChoiceGroup *performanceSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Performance"))); + CheckBox *frameDuplication = performanceSettings->Add(new CheckBox(&g_Config.bRenderDuplicateFrames, gr->T("Render duplicate frames to 60hz"))); frameDuplication->SetEnabledFunc([] { return !g_Config.bSkipBufferEffects && g_Config.iFrameSkip == 0; }); - graphicsSettings->Add(new SettingHint(gr->T("RenderDuplicateFrames Tip", "Can make framerate smoother in games that run at lower framerates"), frameDuplication)); + performanceSettings->Add(new SettingHint(gr->T("RenderDuplicateFrames Tip", "Can make framerate smoother in games that run at lower framerates"), frameDuplication)); if (draw->GetDeviceCaps().setMaxFrameLatencySupported) { static const char *bufferOptions[] = { "No buffer", "Up to 1" }; - PopupMultiChoice *inflightChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInflightFrames, gr->T("Buffer graphics commands"), bufferOptions, 1, ARRAY_SIZE(bufferOptions), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *inflightChoice = performanceSettings->Add(new PopupMultiChoice(&g_Config.iInflightFrames, gr->T("Buffer graphics commands"), bufferOptions, 1, ARRAY_SIZE(bufferOptions), I18NCat::GRAPHICS, screenManager())); inflightChoice->OnChoice.Handle(this, &GameSettingsScreen::OnInflightFramesChoice); - graphicsSettings->Add(new SettingHint(gr->T("Faster, input lag"), inflightChoice)); // TODO: This hint could use improvement. + performanceSettings->Add(new SettingHint(gr->T("Faster, input lag"), inflightChoice)); // TODO: This hint could use improvement. } - graphicsSettings->Add(new ItemHeader(gr->T("Texture upscaling"))); + ChoiceGroup *upscalingSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Texture upscaling"))); if (GetGPUBackend() == GPUBackend::VULKAN || GetGPUBackend() == GPUBackend::METAL) { - ChoiceWithValueDisplay *textureShaderChoice = graphicsSettings->Add(new ChoiceWithValueDisplay(&g_Config.sTextureShaderName, gr->T("GPU texture upscaler (fast)"), &TextureTranslateName)); + ChoiceWithValueDisplay *textureShaderChoice = upscalingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sTextureShaderName, gr->T("GPU texture upscaler (fast)"), &TextureTranslateName)); textureShaderChoice->OnClick.Add([this](UI::EventParams &e) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); auto shaderScreen = new TextureShaderScreen(gr->T("GPU texture upscaler (fast)")); @@ -582,37 +582,37 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) #endif static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", }; - PopupMultiChoice *texScalingType = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingType, gr->T("CPU texture upscaler (slow)"), texScaleAlgos, 0, ARRAY_SIZE(texScaleAlgos), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *texScalingType = upscalingSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingType, gr->T("CPU texture upscaler (slow)"), texScaleAlgos, 0, ARRAY_SIZE(texScaleAlgos), I18NCat::GRAPHICS, screenManager())); texScalingType->SetEnabledFunc([]() { return !g_Config.bSoftwareRendering && !UsingHardwareTextureScaling(); }); - PopupMultiChoice *texScalingChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingLevel, gr->T("Upscale Level"), texScaleLevels, 1, ARRAY_SIZE(texScaleLevels), I18NCat::GRAPHICS, screenManager())); - graphicsSettings->Add(new SettingHint(gr->T("UpscaleLevel Tip", "CPU heavy - some scaling may be delayed to avoid stutter"), texScalingChoice)); + PopupMultiChoice *texScalingChoice = upscalingSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingLevel, gr->T("Upscale Level"), texScaleLevels, 1, ARRAY_SIZE(texScaleLevels), I18NCat::GRAPHICS, screenManager())); + upscalingSettings->Add(new SettingHint(gr->T("UpscaleLevel Tip", "CPU heavy - some scaling may be delayed to avoid stutter"), texScalingChoice)); texScalingChoice->SetEnabledFunc([]() { return !g_Config.bSoftwareRendering && !UsingHardwareTextureScaling(); }); - CheckBox *deposterize = graphicsSettings->Add(new CheckBox(&g_Config.bTexDeposterize, gr->T("Deposterize"))); + CheckBox *deposterize = upscalingSettings->Add(new CheckBox(&g_Config.bTexDeposterize, gr->T("Deposterize"))); deposterize->SetEnabledFunc([]() { return !g_Config.bSoftwareRendering && !UsingHardwareTextureScaling(); }); - graphicsSettings->Add(new SettingHint(gr->T("Deposterize Tip", "Fixes visual banding glitches in upscaled textures"), deposterize)); + upscalingSettings->Add(new SettingHint(gr->T("Deposterize Tip", "Fixes visual banding glitches in upscaled textures"), deposterize)); - graphicsSettings->Add(new ItemHeader(gr->T("Texture Filtering"))); + ChoiceGroup *filteringSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Texture Filtering"))); static const char *anisoLevels[] = { "Off", "2x", "4x", "8x", "16x" }; - PopupMultiChoice *anisoFiltering = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAnisotropyLevel, gr->T("Anisotropic Filtering"), anisoLevels, 0, ARRAY_SIZE(anisoLevels), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *anisoFiltering = filteringSettings->Add(new PopupMultiChoice(&g_Config.iAnisotropyLevel, gr->T("Anisotropic Filtering"), anisoLevels, 0, ARRAY_SIZE(anisoLevels), I18NCat::GRAPHICS, screenManager())); anisoFiltering->SetDisabledPtr(&g_Config.bSoftwareRendering); anisoFiltering->OnChoice.Add([](UI::EventParams &e) { System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); }); static const char *texFilters[] = { "Auto", "Nearest", "Linear", "Auto Max Quality"}; - PopupMultiChoice *filters = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexFiltering, gr->T("Texture Filter"), texFilters, 1, ARRAY_SIZE(texFilters), I18NCat::GRAPHICS, screenManager())); + PopupMultiChoice *filters = filteringSettings->Add(new PopupMultiChoice(&g_Config.iTexFiltering, gr->T("Texture Filter"), texFilters, 1, ARRAY_SIZE(texFilters), I18NCat::GRAPHICS, screenManager())); filters->SetDisabledPtr(&g_Config.bSoftwareRendering); - CheckBox *smartFiltering = graphicsSettings->Add(new CheckBox(&g_Config.bSmart2DTexFiltering, gr->T("Smart 2D texture filtering"))); + CheckBox *smartFiltering = filteringSettings->Add(new CheckBox(&g_Config.bSmart2DTexFiltering, gr->T("Smart 2D texture filtering"))); smartFiltering->SetDisabledPtr(&g_Config.bSoftwareRendering); #if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) @@ -622,23 +622,23 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) bool showCardboardSettings = config.bEnableCardboardVR; #endif if (showCardboardSettings) { - graphicsSettings->Add(new ItemHeader(gr->T("Cardboard VR Settings", "Cardboard VR Settings"))); - graphicsSettings->Add(new CheckBox(&config.bEnableCardboardVR, gr->T("Enable Cardboard VR", "Enable Cardboard VR"))); - PopupSliderChoice *cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardScreenSize, 30, 150, 50, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport"))); + ChoiceGroup *cardboardSettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Cardboard VR Settings", "Cardboard VR Settings"))); + cardboardSettings->Add(new CheckBox(&config.bEnableCardboardVR, gr->T("Enable Cardboard VR", "Enable Cardboard VR"))); + PopupSliderChoice *cardboardScreenSize = cardboardSettings->Add(new PopupSliderChoice(&config.iCardboardScreenSize, 30, 150, 50, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport"))); cardboardScreenSize->SetEnabledPtr(&config.bEnableCardboardVR); - PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardXShift, -150, 150, 0, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); + PopupSliderChoice *cardboardXShift = cardboardSettings->Add(new PopupSliderChoice(&config.iCardboardXShift, -150, 150, 0, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); cardboardXShift->SetEnabledPtr(&config.bEnableCardboardVR); - PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&config.iCardboardYShift, -100, 100, 0, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); + PopupSliderChoice *cardboardYShift = cardboardSettings->Add(new PopupSliderChoice(&config.iCardboardYShift, -100, 100, 0, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void"))); cardboardYShift->SetEnabledPtr(&config.bEnableCardboardVR); } - graphicsSettings->Add(new ItemHeader(gr->T("Overlay Information"))); - graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::FPS_COUNTER, gr->T("Show FPS Counter"))); - graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::SPEED_COUNTER, gr->T("Show Speed"))); + ChoiceGroup *overlaySettings = graphicsSettings->Add(new ChoiceGroup(gr->T("Overlay Information"))); + overlaySettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::FPS_COUNTER, gr->T("Show FPS Counter"))); + overlaySettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::SPEED_COUNTER, gr->T("Show Speed"))); if (System_GetPropertyBool(SYSPROP_CAN_READ_BATTERY_PERCENTAGE)) { - graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::BATTERY_PERCENT, gr->T("Show Battery %"))); + overlaySettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::BATTERY_PERCENT, gr->T("Show Battery %"))); } - AddOverlayList(graphicsSettings, screenManager()); + AddOverlayList(overlaySettings, screenManager()); } void GameSettingsScreen::CreateAudioSettings(UI::ViewGroup *audioSettings) { @@ -820,24 +820,24 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); - controlsSettings->Add(new ItemHeader(ms->T("Controls"))); - controlsSettings->Add(new Choice(co->T("Control mapping")))->OnClick.Add([this](UI::EventParams &e) { + ChoiceGroup *generalSettings = controlsSettings->Add(new ChoiceGroup(ms->T("Controls"))); + generalSettings->Add(new Choice(co->T("Control mapping")))->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new ControlMappingScreen(gamePath_)); }); - controlsSettings->Add(new Choice(co->T("Calibrate analog stick")))->OnClick.Add([this](UI::EventParams &e) { + generalSettings->Add(new Choice(co->T("Calibrate analog stick")))->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new AnalogCalibrationScreen(gamePath_)); }); #if (PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)) || (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) - controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys"))); + generalSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys"))); #endif #if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) - controlsSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused"))); + generalSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused"))); #endif if (System_GetPropertyBool(SYSPROP_HAS_ACCELEROMETER)) { // Show the tilt type on the item. - Choice *customizeTilt = controlsSettings->Add(new ChoiceWithCallbackValueDisplay(co->T("Tilt control setup"), []() -> std::string { + Choice *customizeTilt = generalSettings->Add(new ChoiceWithCallbackValueDisplay(co->T("Tilt control setup"), []() -> std::string { if (g_Config.bTiltInputEnabled && (u32)g_Config.iTiltInputType < (u32)g_numTiltTypes) { auto co = GetI18NCategory(I18NCat::CONTROLS); return std::string(co->T(g_tiltTypes[g_Config.iTiltInputType])); @@ -850,85 +850,85 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) screenManager()->push(new TiltAnalogSettingsScreen(gamePath_)); }); } else if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_VR) { // TODO: This seems like a regression - controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); + generalSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); } - controlsSettings->Add(new ItemHeader(co->T("Analog to digital mapping"))); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogTriggerThreshold, 0.02f, 0.98f, 0.75f, co->T("Analog trigger threshold"), screenManager())); - controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogStickThreshold, 0.2f, 0.98f, 0.75f, co->T("Analog stick threshold"), screenManager())); + ChoiceGroup *analogSettings = controlsSettings->Add(new ChoiceGroup(co->T("Analog to digital mapping"))); + analogSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogTriggerThreshold, 0.02f, 0.98f, 0.75f, co->T("Analog trigger threshold"), screenManager())); + analogSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogStickThreshold, 0.2f, 0.98f, 0.75f, co->T("Analog stick threshold"), screenManager())); // TVs don't have touch control, at least not yet. if ((deviceType != DEVICE_TYPE_TV) && (deviceType != DEVICE_TYPE_VR)) { - controlsSettings->Add(new ItemHeader(co->T("On-screen touch controls"))); - controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, co->T("On-screen touch controls"))); - Choice *layoutEditorChoice = controlsSettings->Add(new Choice(co->T("Edit touch control layout"))); + ChoiceGroup *touchSettings = controlsSettings->Add(new ChoiceGroup(co->T("On-screen touch controls"))); + touchSettings->Add(new CheckBox(&g_Config.bShowTouchControls, co->T("On-screen touch controls"))); + Choice *layoutEditorChoice = touchSettings->Add(new Choice(co->T("Edit touch control layout"))); layoutEditorChoice->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new TouchControlLayoutScreen(gamePath_)); }); layoutEditorChoice->SetEnabledPtr(&g_Config.bShowTouchControls); - Choice *gesture = controlsSettings->Add(new Choice(co->T("Gesture mapping"))); + Choice *gesture = touchSettings->Add(new Choice(co->T("Gesture mapping"))); gesture->OnClick.Add([=](EventParams &e) { screenManager()->push(new GestureMappingScreen(gamePath_)); }); gesture->SetEnabledPtr(&g_Config.bShowTouchControls); static const char *touchControlStyles[] = { "Classic", "Thin borders", "Glowing borders" }; - View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), I18NCat::CONTROLS, screenManager())); + View *style = touchSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), I18NCat::CONTROLS, screenManager())); style->SetEnabledPtr(&g_Config.bShowTouchControls); - PopupSliderChoice *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, 65, co->T("Button Opacity"), screenManager(), "%")); + PopupSliderChoice *opacity = touchSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, 65, co->T("Button Opacity"), screenManager(), "%")); opacity->SetEnabledPtr(&g_Config.bShowTouchControls); opacity->SetFormat("%i%%"); - PopupSliderChoice *autoHide = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonHideSeconds, 0, 300, 20, co->T("Auto-hide buttons after delay"), screenManager(), di->T("seconds, 0:off"))); + PopupSliderChoice *autoHide = touchSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonHideSeconds, 0, 300, 20, co->T("Auto-hide buttons after delay"), screenManager(), di->T("seconds, 0:off"))); autoHide->SetEnabledPtr(&g_Config.bShowTouchControls); autoHide->SetFormat(di->T("%d seconds")); autoHide->SetZeroLabel(co->T("Off")); - CheckBox *touchGliding = controlsSettings->Add(new CheckBox(&g_Config.bTouchGliding, co->T("Keep first touched button pressed when dragging"))); + CheckBox *touchGliding = touchSettings->Add(new CheckBox(&g_Config.bTouchGliding, co->T("Keep first touched button pressed when dragging"))); touchGliding->SetEnabledPtr(&g_Config.bShowTouchControls); TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation()); // Hide stick background, useful when increasing the size - CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&touch.bHideStickBackground, co->T("Hide touch analog stick background circle"))); + CheckBox *hideStickBackground = touchSettings->Add(new CheckBox(&touch.bHideStickBackground, co->T("Hide touch analog stick background circle"))); hideStickBackground->SetEnabledPtr(&g_Config.bShowTouchControls); // Sticky D-pad. - CheckBox *stickyDpad = controlsSettings->Add(new CheckBox(&g_Config.bStickyTouchDPad, co->T("Sticky D-Pad"))); + CheckBox *stickyDpad = touchSettings->Add(new CheckBox(&g_Config.bStickyTouchDPad, co->T("Sticky D-Pad"))); stickyDpad->SetEnabledPtr(&g_Config.bShowTouchControls); - controlsSettings->Add(new SettingHint(co->T("Easier sweeping movements"), stickyDpad)); + touchSettings->Add(new SettingHint(co->T("Easier sweeping movements"), stickyDpad)); // Re-centers itself to the touch location on touch-down. - CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); + CheckBox *floatingAnalog = touchSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { - controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); + touchSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); } // The pause button is now a regular on-screen button. - CheckBox *disableDiags = controlsSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, co->T("Disable D-Pad diagonals (4-way touch)"))); + CheckBox *disableDiags = touchSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, co->T("Disable D-Pad diagonals (4-way touch)"))); disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls); } #if PPSSPP_PLATFORM(WINDOWS) - controlsSettings->Add(new ItemHeader(co->T("Control input sources"))); - controlsSettings->Add(new CheckBox(&g_Config.bAllowHIDInput, co->T("HID input"))); - controlsSettings->Add(new CheckBox(&g_Config.bAllowXInput, co->T("XInput"))); - controlsSettings->Add(new CheckBox(&g_Config.bAllowDInput, co->T("DirectInput"))); + ChoiceGroup *inputSourceSettings = controlsSettings->Add(new ChoiceGroup(co->T("Control input sources"))); + inputSourceSettings->Add(new CheckBox(&g_Config.bAllowHIDInput, co->T("HID input"))); + inputSourceSettings->Add(new CheckBox(&g_Config.bAllowXInput, co->T("XInput"))); + inputSourceSettings->Add(new CheckBox(&g_Config.bAllowDInput, co->T("DirectInput"))); #endif if (deviceType != DEVICE_TYPE_VR) { - controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings"))); + ChoiceGroup *keyboardSettings = controlsSettings->Add(new ChoiceGroup(co->T("Keyboard", "Keyboard Control Settings"))); #if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) - controlsSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, co->T("Ignore Windows Key"))); + keyboardSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, co->T("Ignore Windows Key"))); #endif PopupSliderChoiceFloat *analogLimiter = new PopupSliderChoiceFloat(&g_Config.fAnalogLimiterDeadzone, 0.0f, 1.0f, 0.6f, co->T("Analog Limiter"), 0.10f, screenManager(), "/ 1.0"); - controlsSettings->Add(analogLimiter); - controlsSettings->Add(new SettingHint(co->T("AnalogLimiter Tip", "When the analog limiter button is pressed"), analogLimiter)); - controlsSettings->Add(new PopupSliderChoice(&g_Config.iRapidFireInterval, 1, 10, 5, co->T("Rapid fire interval"), screenManager(), "frames")); + keyboardSettings->Add(analogLimiter); + keyboardSettings->Add(new SettingHint(co->T("AnalogLimiter Tip", "When the analog limiter button is pressed"), analogLimiter)); + keyboardSettings->Add(new PopupSliderChoice(&g_Config.iRapidFireInterval, 1, 10, 5, co->T("Rapid fire interval"), screenManager(), "frames")); #if PPSSPP_PLATFORM(WINDOWS) || defined(SDL) || PPSSPP_PLATFORM(ANDROID) bool enableMouseSettings = true; #if PPSSPP_PLATFORM(ANDROID) @@ -941,20 +941,20 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) #endif if (enableMouseSettings) { // The mousewheel button-release setting is independent of actual mouse delta control. - controlsSettings->Add(new ItemHeader(co->T("Mouse", "Mouse settings"))); - auto wheelUpDelaySlider = controlsSettings->Add(new PopupSliderChoice(&g_Config.iMouseWheelUpDelayMs, 10, 300, 1, co->T("Mouse wheel button-release delay"), screenManager())); + ChoiceGroup *mouseSettings = controlsSettings->Add(new ChoiceGroup(co->T("Mouse", "Mouse settings"))); + auto wheelUpDelaySlider = mouseSettings->Add(new PopupSliderChoice(&g_Config.iMouseWheelUpDelayMs, 10, 300, 1, co->T("Mouse wheel button-release delay"), screenManager())); wheelUpDelaySlider->SetFormat(di->T("%d ms")); - CheckBox *mouseControl = controlsSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control"))); - controlsSettings->Add(new SettingHint(co->T("MouseControl Tip", "You can now map mouse in control mapping screen by pressing the 'M' icon."), mouseControl)); + CheckBox *mouseControl = mouseSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control"))); + mouseSettings->Add(new SettingHint(co->T("MouseControl Tip", "You can now map mouse in control mapping screen by pressing the 'M' icon."), mouseControl)); #if !PPSSPP_PLATFORM(ANDROID) - controlsSettings->Add(new CheckBox(&g_Config.bMouseConfine, co->T("Confine Mouse", "Trap mouse within window/display area")))->SetEnabledPtr(&g_Config.bMouseControl); + mouseSettings->Add(new CheckBox(&g_Config.bMouseConfine, co->T("Confine Mouse", "Trap mouse within window/display area")))->SetEnabledPtr(&g_Config.bMouseControl); #endif - auto sensitivitySlider = controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSensitivity, 0.01f, 1.0f, 0.1f, co->T("Mouse sensitivity"), 0.01f, screenManager(), "x")); + auto sensitivitySlider = mouseSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSensitivity, 0.01f, 1.0f, 0.1f, co->T("Mouse sensitivity"), 0.01f, screenManager(), "x")); sensitivitySlider->SetEnabledPtr(&g_Config.bMouseControl); sensitivitySlider->SetLiveUpdate(true); - auto smoothingSlider = controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSmoothing, 0.0f, 0.95f, 0.9f, co->T("Mouse smoothing"), 0.05f, screenManager(), "x")); + auto smoothingSlider = mouseSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSmoothing, 0.0f, 0.95f, 0.9f, co->T("Mouse smoothing"), 0.05f, screenManager(), "x")); smoothingSlider->SetEnabledPtr(&g_Config.bMouseControl); smoothingSlider->SetLiveUpdate(true); } @@ -1033,9 +1033,9 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti auto ms = GetI18NCategory(I18NCat::MAINSETTINGS); auto di = GetI18NCategory(I18NCat::DIALOG); - networkingSettings->Add(new ItemHeader(ms->T("Networking"))); + ChoiceGroup *generalSettings = networkingSettings->Add(new ChoiceGroup(ms->T("Networking"))); - Choice *quickstart = networkingSettings->Add(new Choice(n->T("Quick start guide for multiplayer"), ImageID("I_LINK_OUT"))); + Choice *quickstart = generalSettings->Add(new Choice(n->T("Quick start guide for multiplayer"), ImageID("I_LINK_OUT"))); quickstart->OnClick.Add([](EventParams &e) { auto n = GetI18NCategory(I18NCat::NETWORKING); std::string url(n->T("MultiplayerQuickStartURL", "https://www.ppsspp.org/docs/multiplayer/quickstart/")); @@ -1050,10 +1050,10 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti } }; - networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")))->OnClick.Add(requestLocalNetwork); - networkingSettings->Add(new MacAddressChooser(GetRequesterToken(), gamePath_, &g_Config.sMACAddress, n->T("MAC address"), screenManager())); + generalSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")))->OnClick.Add(requestLocalNetwork); + generalSettings->Add(new MacAddressChooser(GetRequesterToken(), gamePath_, &g_Config.sMACAddress, n->T("MAC address"), screenManager())); - networkingSettings->Add(new ItemHeader(n->T("Ad Hoc multiplayer"))); + ChoiceGroup *adhocSettings = networkingSettings->Add(new ChoiceGroup(n->T("Ad Hoc multiplayer"))); auto launchAdhocServerScreen = [this](UI::EventParams &) { auto n = GetI18NCategory(I18NCat::NETWORKING); @@ -1061,7 +1061,7 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti }; if (AdhocServerNameIsCustom()) { - LinearLayout *serverRow = networkingSettings->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + LinearLayout *serverRow = adhocSettings->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); serverRow->SetSpacing(0.0f); serverRow->Add(new ChoiceWithValueDisplay(&g_Config.sProAdhocServer, n->T("Ad hoc server address"), I18NCat::NONE, new LinearLayoutParams(1.0f)))->OnClick.Add(launchAdhocServerScreen); serverRow->Add(new Choice(ImageID("I_EDIT_TEXT"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([this](UI::EventParams &) { @@ -1070,58 +1070,58 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti } else if (!g_Config.sProAdhocServer.empty()) { AdhocServerListEntry entry; if (AdhocGetServerByHost(g_Config.sProAdhocServer, &entry)) { - networkingSettings->Add(new ChoiceWithFixedValueDisplay(ApplySafeSubstitutions("%1 (%2)", entry.name, entry.host), n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); - Choice *status = networkingSettings->Add(new Choice(ApplySafeSubstitutions(n->T("Server status: %1"), entry.name))); + adhocSettings->Add(new ChoiceWithFixedValueDisplay(ApplySafeSubstitutions("%1 (%2)", entry.name, entry.host), n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); + Choice *status = adhocSettings->Add(new Choice(ApplySafeSubstitutions(n->T("Server status: %1"), entry.name))); status->SetIconLeft(ImageID("I_INFO")); status->OnClick.Add([this, entry](UI::EventParams &) { screenManager()->push(new AdhocServerInfoScreen(entry)); }); } else { // This case happens when updating from a previous version, as well as clicking on one of the local addresses - networkingSettings->Add(new ChoiceWithFixedValueDisplay(g_Config.sProAdhocServer, n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); + adhocSettings->Add(new ChoiceWithFixedValueDisplay(g_Config.sProAdhocServer, n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); } } else { - networkingSettings->Add(new ChoiceWithFixedValueDisplay(g_Config.sProAdhocServer, n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); + adhocSettings->Add(new ChoiceWithFixedValueDisplay(g_Config.sProAdhocServer, n->T("Ad hoc server address")))->OnClick.Add(launchAdhocServerScreen); } static const char *relayModes[] = {"Auto", "Yes", "No"}; - PopupMultiChoice *relayModePopup = networkingSettings->Add(new PopupMultiChoice(&g_Config.iAdhocServerRelayMode, n->T("Try to use server-provided packet relay"), relayModes, 0, ARRAY_SIZE(relayModes), I18NCat::DIALOG, screenManager())); + PopupMultiChoice *relayModePopup = adhocSettings->Add(new PopupMultiChoice(&g_Config.iAdhocServerRelayMode, n->T("Try to use server-provided packet relay"), relayModes, 0, ARRAY_SIZE(relayModes), I18NCat::DIALOG, screenManager())); relayModePopup->SetEnabled(!PSP_IsInited()); - networkingSettings->Add(new SettingHint(n->T("PacketRelayHint", "Available on servers that provide 'aemu_postoffice' packet relay, like socom.cc. Disable this for LAN or VPN play. Can be more reliable, but sometimes slower."), relayModePopup)); + adhocSettings->Add(new SettingHint(n->T("PacketRelayHint", "Available on servers that provide 'aemu_postoffice' packet relay, like socom.cc. Disable this for LAN or VPN play. Can be more reliable, but sometimes slower."), relayModePopup)); - View *nicknameChoice = AddNicknameChoice(networkingSettings); - networkingSettings->Add(new SettingHint(n->T("Try to pick a unique nickname for ad hoc play"), nicknameChoice)); + View *nicknameChoice = AddNicknameChoice(adhocSettings); + adhocSettings->Add(new SettingHint(n->T("Try to pick a unique nickname for ad hoc play"), nicknameChoice)); - networkingSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in ad hoc server")))->OnClick.Add(requestLocalNetwork); + adhocSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in ad hoc server")))->OnClick.Add(requestLocalNetwork); - CheckBox *relay_mode_enet = networkingSettings->Add(new CheckBox(&g_Config.bAdhocUseUdp, n->T("Connect to adhoc server using UDP (ENet) instead of TCP"))); + CheckBox *relay_mode_enet = adhocSettings->Add(new CheckBox(&g_Config.bAdhocUseUdp, n->T("Connect to adhoc server using UDP (ENet) instead of TCP"))); relay_mode_enet->SetEnabled(!PSP_IsInited()); - networkingSettings->Add(new SettingHint(n->T("Try switching between TCP/UDP if you suffer frequent adhoc server disconnects. Some network environments favor TCP and some UDP."), relay_mode_enet)); + adhocSettings->Add(new SettingHint(n->T("Try switching between TCP/UDP if you suffer frequent adhoc server disconnects. Some network environments favor TCP and some UDP."), relay_mode_enet)); - CheckBox *relay_mode_enet_pdp_reliable = networkingSettings->Add(new CheckBox(&g_Config.bAdhocRelayModeEnetPdpReliable, n->T("Reliable datagram packet delivery on packet relay in UDP mode"))); + CheckBox *relay_mode_enet_pdp_reliable = adhocSettings->Add(new CheckBox(&g_Config.bAdhocRelayModeEnetPdpReliable, n->T("Reliable datagram packet delivery on packet relay in UDP mode"))); relay_mode_enet_pdp_reliable->SetEnabledFunc([] { return !PSP_IsInited() && g_Config.bAdhocUseUdp; }); - networkingSettings->Add(new SettingHint(n->T("When disabled, packet loss on datagram adhoc sockets will be exposed to game's netcode. Keep this enabled if you don't know what that means."), relay_mode_enet_pdp_reliable)); + adhocSettings->Add(new SettingHint(n->T("When disabled, packet loss on datagram adhoc sockets will be exposed to game's netcode. Keep this enabled if you don't know what that means."), relay_mode_enet_pdp_reliable)); - networkingSettings->Add(new ItemHeader(n->T("Infrastructure"))); + ChoiceGroup *infrastructureSettings = networkingSettings->Add(new ChoiceGroup(n->T("Infrastructure"))); if (g_Config.sInfrastructureUsername.empty()) { - networkingSettings->Add(new NoticeView(NoticeLevel::WARN, n->T("To play in Infrastructure Mode, you must enter a username"), ""))->SetWrapText(true); + infrastructureSettings->Add(new NoticeView(NoticeLevel::WARN, n->T("To play in Infrastructure Mode, you must enter a username"), ""))->SetWrapText(true); } - PopupTextInputChoice *usernameChoice = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sInfrastructureUsername, di->T("Username"), "", 16, screenManager())); + PopupTextInputChoice *usernameChoice = infrastructureSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sInfrastructureUsername, di->T("Username"), "", 16, screenManager())); usernameChoice->SetRestriction(StringRestriction::AlphaNumDashUnderscore, 3); usernameChoice->OnChange.Add([this](UI::EventParams &e) { RecreateViews(); }); - networkingSettings->Add(new CheckBox(&g_Config.bInfrastructureAutoDNS, n->T("Autoconfigure"))); - auto *dnsServer = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sInfrastructureDNSServer, n->T("DNS server"), "", 32, screenManager())); + infrastructureSettings->Add(new CheckBox(&g_Config.bInfrastructureAutoDNS, n->T("Autoconfigure"))); + auto *dnsServer = infrastructureSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sInfrastructureDNSServer, n->T("DNS server"), "", 32, screenManager())); dnsServer->SetDisabledPtr(&g_Config.bInfrastructureAutoDNS); - networkingSettings->Add(new ItemHeader(n->T("UPnP (port-forwarding)"))); + ChoiceGroup *upnpSettings = networkingSettings->Add(new ChoiceGroup(n->T("UPnP (port-forwarding)"))); // Only togglable outside a game - sceNet latches settings like UPnPUseOriginalPort at boot, // and a game that's already mapped its ports wouldn't cope with them disappearing. - CheckBox *enableUPnP = networkingSettings->Add(new CheckBox(&g_Config.bEnableUPnP, n->T("Enable UPnP", "Enable UPnP (need a few seconds to detect)"))); + CheckBox *enableUPnP = upnpSettings->Add(new CheckBox(&g_Config.bEnableUPnP, n->T("Enable UPnP", "Enable UPnP (need a few seconds to detect)"))); enableUPnP->SetEnabled(!PSP_IsInited()); enableUPnP->OnClick.Add([requestLocalNetwork](UI::EventParams &e) { requestLocalNetwork(e); @@ -1129,49 +1129,49 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti // away, instead of waiting for a port request that may never come. UPnP_Notify(); }); - auto *useOriPort = networkingSettings->Add(new CheckBox(&g_Config.bUPnPUseOriginalPort, n->T("UPnP use original port", "UPnP use original port (Enabled = PSP compatibility)"))); - networkingSettings->Add(new SettingHint(n->T("UseOriginalPort Tip", "May not work for all devices or games, see wiki."), useOriPort)); + auto *useOriPort = upnpSettings->Add(new CheckBox(&g_Config.bUPnPUseOriginalPort, n->T("UPnP use original port", "UPnP use original port (Enabled = PSP compatibility)"))); + upnpSettings->Add(new SettingHint(n->T("UseOriginalPort Tip", "May not work for all devices or games, see wiki."), useOriPort)); useOriPort->SetEnabledPtr(&g_Config.bEnableUPnP); - networkingSettings->Add(new ItemHeader(n->T("Chat"))); - networkingSettings->Add(new CheckBox(&g_Config.bEnableNetworkChat, n->T("Enable network chat"))); + ChoiceGroup *chatSettings = networkingSettings->Add(new ChoiceGroup(n->T("Chat"))); + chatSettings->Add(new CheckBox(&g_Config.bEnableNetworkChat, n->T("Enable network chat"))); static const char *chatButtonPositions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right", "None" }; - networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatButtonPosition, n->T("Chat Button Position"), chatButtonPositions, 0, ARRAY_SIZE(chatButtonPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); + chatSettings->Add(new PopupMultiChoice(&g_Config.iChatButtonPosition, n->T("Chat Button Position"), chatButtonPositions, 0, ARRAY_SIZE(chatButtonPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); static const char *chatScreenPositions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right" }; - networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatScreenPosition, n->T("Chat Screen Position"), chatScreenPositions, 0, ARRAY_SIZE(chatScreenPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); - networkingSettings->Add(new CheckBox(&g_Config.bChatTimestamps, n->T("Show timestamps in chat")))->SetEnabledPtr(&g_Config.bEnableNetworkChat); + chatSettings->Add(new PopupMultiChoice(&g_Config.iChatScreenPosition, n->T("Chat Screen Position"), chatScreenPositions, 0, ARRAY_SIZE(chatScreenPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); + chatSettings->Add(new CheckBox(&g_Config.bChatTimestamps, n->T("Show timestamps in chat")))->SetEnabledPtr(&g_Config.bEnableNetworkChat); - networkingSettings->Add(new ItemHeader(n->T("Quick chat"))); - CheckBox *qc = networkingSettings->Add(new CheckBox(&g_Config.bEnableQuickChat, n->T("Enable quick chat"))); + ChoiceGroup *quickChatSettings = networkingSettings->Add(new ChoiceGroup(n->T("Quick chat"))); + CheckBox *qc = quickChatSettings->Add(new CheckBox(&g_Config.bEnableQuickChat, n->T("Enable quick chat"))); qc->SetEnabledPtr(&g_Config.bEnableNetworkChat); for (int i = 0; i < 5; i++) { - PopupTextInputChoice *qc1 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat[i], ApplySafeSubstitutions(n->T("Quick chat %1"), i + 1), "", 32, screenManager())); + PopupTextInputChoice *qc1 = quickChatSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat[i], ApplySafeSubstitutions(n->T("Quick chat %1"), i + 1), "", 32, screenManager())); qc1->SetEnabledFunc([] { return g_Config.bEnableQuickChat && g_Config.bEnableNetworkChat; }); } - networkingSettings->Add(new ItemHeader(n->T("Misc", "Misc (default = compatibility)"))); - Choice *wiki = networkingSettings->Add(new Choice(n->T("Open PPSSPP Multiplayer Wiki Page"), ImageID("I_LINK_OUT"))); + ChoiceGroup *miscSettings = networkingSettings->Add(new ChoiceGroup(n->T("Misc", "Misc (default = compatibility)"))); + Choice *wiki = miscSettings->Add(new Choice(n->T("Open PPSSPP Multiplayer Wiki Page"), ImageID("I_LINK_OUT"))); wiki->OnClick.Add([](EventParams &e) { auto n = GetI18NCategory(I18NCat::NETWORKING); std::string url(n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP")); System_LaunchUrl(LaunchUrlType::BROWSER_URL, url); }); static const char *wlanChannels[] = {"Auto", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}; - auto wlanChannelChoice = networkingSettings->Add(new PopupMultiChoice(&g_Config.iWlanAdhocChannel, n->T("WLAN Channel"), wlanChannels, 0, ARRAY_SIZE(wlanChannels), I18NCat::NETWORKING, screenManager())); + auto wlanChannelChoice = miscSettings->Add(new PopupMultiChoice(&g_Config.iWlanAdhocChannel, n->T("WLAN Channel"), wlanChannels, 0, ARRAY_SIZE(wlanChannels), I18NCat::NETWORKING, screenManager())); wlanChannelChoice->SetChoicesUntranslated(1, (int)ARRAY_SIZE(wlanChannels) - 1); for (int i = 0; i < 4; i++) { wlanChannelChoice->HideChoice(i + 2); wlanChannelChoice->HideChoice(i + 7); } - PopupSliderChoice *portOffset = networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, 10000, n->T("Port offset"), 100, screenManager())); - networkingSettings->Add(new SettingHint(n->T("PortOffsetHint"), portOffset)); - networkingSettings->Add(new PopupSliderChoice(&g_Config.iMinTimeout, 0, 15000, 0, n->T("Minimum Timeout", "Minimum Timeout (override in ms, 0 = default)"), 50, screenManager()))->SetFormat(di->T("%d ms")); - networkingSettings->Add(new CheckBox(&g_Config.bForcedFirstConnect, n->T("Forced First Connect", "Forced First Connect (faster Connect)"))); - networkingSettings->Add(new CheckBox(&g_Config.bAllowSpeedControlWhileConnected, n->T("Allow speed control while connected (not recommended)"))); + PopupSliderChoice *portOffset = miscSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, 10000, n->T("Port offset"), 100, screenManager())); + miscSettings->Add(new SettingHint(n->T("PortOffsetHint"), portOffset)); + miscSettings->Add(new PopupSliderChoice(&g_Config.iMinTimeout, 0, 15000, 0, n->T("Minimum Timeout", "Minimum Timeout (override in ms, 0 = default)"), 50, screenManager()))->SetFormat(di->T("%d ms")); + miscSettings->Add(new CheckBox(&g_Config.bForcedFirstConnect, n->T("Forced First Connect", "Forced First Connect (faster Connect)"))); + miscSettings->Add(new CheckBox(&g_Config.bAllowSpeedControlWhileConnected, n->T("Allow speed control while connected (not recommended)"))); if (Discord::IsAvailable()) { - networkingSettings->Add(new CheckBox(&g_Config.bDiscordRichPresence, n->T("Send Discord Presence information"))); + miscSettings->Add(new CheckBox(&g_Config.bDiscordRichPresence, n->T("Send Discord Presence information"))); } } @@ -1184,11 +1184,11 @@ void GameSettingsScreen::CreateToolsSettings(UI::ViewGroup *tools) { auto dev = GetI18NCategory(I18NCat::DEVELOPER); auto ri = GetI18NCategory(I18NCat::REMOTEISO); - tools->Add(new ItemHeader(ms->T("Tools"))); + ChoiceGroup *toolsGroup = tools->Add(new ChoiceGroup(ms->T("Tools"))); const bool showRetroAchievements = System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_VR; if (showRetroAchievements) { - auto retro = tools->Add(new Choice(sy->T("RetroAchievements"))); + auto retro = toolsGroup->Add(new Choice(sy->T("RetroAchievements"))); retro->OnClick.Add([=](UI::EventParams &) -> void { screenManager()->push(new RetroAchievementsSettingsScreen(gamePath_)); }); @@ -1196,19 +1196,19 @@ void GameSettingsScreen::CreateToolsSettings(UI::ViewGroup *tools) { } // These were moved here so use the wrong translation objects, to avoid having to change all inis... This isn't a sustainable situation :P - tools->Add(new Choice(sa->T("Savedata Manager")))->OnClick.Add([=](UI::EventParams &) { + toolsGroup->Add(new Choice(sa->T("Savedata Manager")))->OnClick.Add([=](UI::EventParams &) { screenManager()->push(new SavedataScreen(gamePath_)); }); - tools->Add(new Choice(dev->T("System Information")))->OnClick.Add([=](UI::EventParams &) { + toolsGroup->Add(new Choice(dev->T("System Information")))->OnClick.Add([=](UI::EventParams &) { screenManager()->push(new SystemInfoScreen(gamePath_)); }); - tools->Add(new Choice(sy->T("Developer Tools")))->OnClick.Add([=](UI::EventParams &) { + toolsGroup->Add(new Choice(sy->T("Developer Tools")))->OnClick.Add([=](UI::EventParams &) { screenManager()->push(new DeveloperToolsScreen(gamePath_)); }); - tools->Add(new Choice(ri->T("Remote disc streaming")))->OnClick.Add([=](UI::EventParams &) { + toolsGroup->Add(new Choice(ri->T("Remote disc streaming")))->OnClick.Add([=](UI::EventParams &) { screenManager()->push(new RemoteISOScreen(gamePath_)); }); - tools->Add(new Choice(sy->T("PSP Firmware")))->OnClick.Add([=](UI::EventParams &) { + toolsGroup->Add(new Choice(sy->T("PSP Firmware")))->OnClick.Add([=](UI::EventParams &) { screenManager()->push(new FirmwareScreen(gamePath_)); }); } @@ -1222,7 +1222,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { auto th = GetI18NCategory(I18NCat::THEMES); auto psps = GetI18NCategory(I18NCat::PSPSETTINGS); // TODO: Should move more into this section. - systemSettings->Add(new ItemHeader(sy->T("UI"))); + ChoiceGroup *uiSettings = systemSettings->Add(new ChoiceGroup(sy->T("UI"))); auto langCodeToName = [](std::string_view value) -> std::string { auto &mapping = GetLangValuesMapping(); @@ -1233,7 +1233,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { return std::string(value); }; - systemSettings->Add(new ChoiceWithValueDisplay(&g_Config.sLanguageIni, sy->T("Language"), langCodeToName))->OnClick.Add([&](UI::EventParams &e) { + uiSettings->Add(new ChoiceWithValueDisplay(&g_Config.sLanguageIni, sy->T("Language"), langCodeToName))->OnClick.Add([&](UI::EventParams &e) { auto sy = GetI18NCategory(I18NCat::SYSTEM); auto langScreen = new NewLanguageScreen(sy->T("Language")); // The actual switching is handled in OnCompleted in NewLanguageScreen. @@ -1247,7 +1247,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { "Swipe once to switch app (indicator auto-hides)", "Swipe twice to switch app (indicator stays visible)" }; - PopupMultiChoice *switchMode = systemSettings->Add(new PopupMultiChoice(&g_Config.iAppSwitchMode, sy->T("App switching mode"), indicator, 0, ARRAY_SIZE(indicator), I18NCat::SYSTEM, screenManager())); + PopupMultiChoice *switchMode = uiSettings->Add(new PopupMultiChoice(&g_Config.iAppSwitchMode, sy->T("App switching mode"), indicator, 0, ARRAY_SIZE(indicator), I18NCat::SYSTEM, screenManager())); switchMode->OnChoice.Add([](EventParams &e) { System_Notify(SystemNotification::APP_SWITCH_MODE_CHANGED); }); @@ -1255,7 +1255,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { { // Note: On iPhone, iOS hides the status bar in landscape no matter what this is set to. DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); - systemSettings->Add(new CheckBox(&config.bImmersiveMode, sy->T("Hide status bar")))->OnClick.Add([](EventParams &e) { + uiSettings->Add(new CheckBox(&config.bImmersiveMode, sy->T("Hide status bar")))->OnClick.Add([](EventParams &e) { System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE); }); } @@ -1265,11 +1265,11 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { // Hide Immersive Mode on pre-kitkat Android if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 19) { DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(GetDeviceOrientation()); - systemSettings->Add(new CheckBox(&config.bImmersiveMode, sy->T("Hide navigation bar")))->OnClick.Handle(this, &GameSettingsScreen::OnImmersiveModeChange); + uiSettings->Add(new CheckBox(&config.bImmersiveMode, sy->T("Hide navigation bar")))->OnClick.Handle(this, &GameSettingsScreen::OnImmersiveModeChange); } #endif - PopupSliderChoice *uiScale = systemSettings->Add(new PopupSliderChoice(&g_Config.iUIScaleFactor, -8, 8, 0, sy->T("UI size adjustment (DPI)"), screenManager())); + PopupSliderChoice *uiScale = uiSettings->Add(new PopupSliderChoice(&g_Config.iUIScaleFactor, -8, 8, 0, sy->T("UI size adjustment (DPI)"), screenManager())); uiScale->SetZeroLabel(sy->T("Off")); UIContext *ctx = screenManager()->getUIContext(); uiScale->OnChange.Add([ctx](UI::EventParams &e) { @@ -1283,25 +1283,25 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { const Path bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) / "background.jpg"; Choice *backgroundChoice = nullptr; if (File::Exists(bgPng) || File::Exists(bgJpg)) { - backgroundChoice = systemSettings->Add(new Choice(sy->T("Clear UI background"))); + backgroundChoice = uiSettings->Add(new Choice(sy->T("Clear UI background"))); } else if (System_GetPropertyBool(SYSPROP_HAS_IMAGE_BROWSER) || System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { - backgroundChoice = systemSettings->Add(new Choice(sy->T("Set UI background..."))); + backgroundChoice = uiSettings->Add(new Choice(sy->T("Set UI background..."))); } if (backgroundChoice) { backgroundChoice->OnClick.Handle(this, &GameSettingsScreen::OnChangeBackground); } - systemSettings->Add(new CheckBox(&g_Config.bTransparentBackground, sy->T("Transparent UI background"))); + uiSettings->Add(new CheckBox(&g_Config.bTransparentBackground, sy->T("Transparent UI background"))); // Shared with achievements. static const char *positions[] = { "None", "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iNotificationPos, sy->T("Notification screen position"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager())); + uiSettings->Add(new PopupMultiChoice(&g_Config.iNotificationPos, sy->T("Notification screen position"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager())); static const char *backgroundAnimations[] = { "No animation", "Floating symbols", "Recent games", "Waves", "Moving background", "Bouncing icon", "Colored floating symbols" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iBackgroundAnimation, sy->T("UI background animation"), backgroundAnimations, 0, ARRAY_SIZE(backgroundAnimations), I18NCat::SYSTEM, screenManager())); + uiSettings->Add(new PopupMultiChoice(&g_Config.iBackgroundAnimation, sy->T("UI background animation"), backgroundAnimations, 0, ARRAY_SIZE(backgroundAnimations), I18NCat::SYSTEM, screenManager())); - PopupMultiChoiceDynamic *theme = systemSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sThemeName, sy->T("Theme"), GetThemeInfoNames(), I18NCat::THEMES, screenManager())); + PopupMultiChoiceDynamic *theme = uiSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sThemeName, sy->T("Theme"), GetThemeInfoNames(), I18NCat::THEMES, screenManager())); theme->OnChoice.Add([](EventParams &e) { UpdateTheme(); // Reset the tint/saturation if the theme changed. @@ -1318,17 +1318,17 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { PopupSliderChoiceFloat *tint = new PopupSliderChoiceFloat(&g_Config.fUITint, 0.0f, 1.0f, 0.0f, sy->T("Color tint"), 0.01f, screenManager()); tint->SetHasDropShadow(false); tint->SetLiveUpdate(true); - systemSettings->Add(tint); + uiSettings->Add(tint); PopupSliderChoiceFloat *saturation = new PopupSliderChoiceFloat(&g_Config.fUISaturation, 0.0f, 2.0f, 1.0f, sy->T("Color saturation"), 0.01f, screenManager()); saturation->SetHasDropShadow(false); saturation->SetLiveUpdate(true); - systemSettings->Add(saturation); + uiSettings->Add(saturation); } - systemSettings->Add(new ItemHeader(sy->T("PSP Memory Stick"))); + ChoiceGroup *memstickSettings = systemSettings->Add(new ChoiceGroup(sy->T("PSP Memory Stick"))); if (System_GetPropertyBool(SYSPROP_HAS_OPEN_DIRECTORY)) { - systemSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Add([](UI::EventParams &p) { + memstickSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Add([](UI::EventParams &p) { System_LaunchUrl(LaunchUrlType::LOCAL_FOLDER, g_Config.memStickDirectory.ToString()); }); } @@ -1342,7 +1342,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { } #endif if (showItHere) { - systemSettings->Add(new Choice(sy->T("Set Memory Stick folder")))->OnClick.Add( + memstickSettings->Add(new Choice(sy->T("Set Memory Stick folder")))->OnClick.Add( [=](UI::EventParams &) { SetMemStickDirDarwin(GetRequesterToken()); }); @@ -1351,7 +1351,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { #if PPSSPP_PLATFORM(ANDROID) if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_VR) { - auto memstickPath = systemSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() { + auto memstickPath = memstickSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() { return g_Config.memStickDirectory.ToVisualString(); })); memstickPath->SetEnabled(!PSP_IsInited()); @@ -1359,152 +1359,152 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { } #elif defined(_WIN32) #if PPSSPP_PLATFORM(UWP) - auto memstickPath = systemSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() { + auto memstickPath = memstickSettings->Add(new ChoiceWithCallbackValueDisplay(sy->T("Memory Stick folder"), []() { return g_Config.memStickDirectory.ToVisualString(); })); memstickPath->SetEnabled(!PSP_IsInited()); memstickPath->OnClick.Handle(this, &GameSettingsScreen::OnShowMemstickScreen); #else - CheckBox *myDocsChoice = systemSettings->Add(new CheckBox(&installed_, sy->T("Memory Stick in My Documents"))); + CheckBox *myDocsChoice = memstickSettings->Add(new CheckBox(&installed_, sy->T("Memory Stick in My Documents"))); myDocsChoice->SetEnabledPtr(&memstickMyDocEnabled_); myDocsChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickMyDoc); - CheckBox *otherChoice = systemSettings->Add(new CheckBox(&otherinstalled_, sy->T("Memory Stick in installed.txt"))); + CheckBox *otherChoice = memstickSettings->Add(new CheckBox(&otherinstalled_, sy->T("Memory Stick in installed.txt"))); otherChoice->SetEnabledPtr(&memstickOtherEnabled_); otherChoice->OnClick.Handle(this, &GameSettingsScreen::OnMemoryStickOther); if (!System_GetPropertyBool(SYSPROP_CAN_GET_FREE_SPACE_FAST)) { // It might be slow, so use an option. - systemSettings->Add(new CheckBox(&g_Config.bReportAccurateFreeStorageSpace, sy->T("Report free storage space accurately"))); + memstickSettings->Add(new CheckBox(&g_Config.bReportAccurateFreeStorageSpace, sy->T("Report free storage space accurately"))); } #endif #endif - systemSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted"))); - UI::PopupSliderChoice *sizeChoice = systemSettings->Add(new PopupSliderChoice(&g_Config.iMemStickSizeGB, 1, 32, 16, sy->T("Memory Stick size", "Memory Stick size"), screenManager(), "GB")); + memstickSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted"))); + UI::PopupSliderChoice *sizeChoice = memstickSettings->Add(new PopupSliderChoice(&g_Config.iMemStickSizeGB, 1, 32, 16, sy->T("Memory Stick size", "Memory Stick size"), screenManager(), "GB")); sizeChoice->SetFormat("%d GB"); - systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team"))); + ChoiceGroup *helpSettings = systemSettings->Add(new ChoiceGroup(sy->T("Help the PPSSPP team"))); CheckBox *enableReportsCheckbox; enableReportsCheckbox = new CheckBox(&enableReports_, sy->T("Enable Compatibility Server Reports")); enableReportsCheckbox->SetEnabledFunc([]() { return Reporting::IsSupported(); }); - systemSettings->Add(enableReportsCheckbox); + helpSettings->Add(enableReportsCheckbox); - systemSettings->Add(new ItemHeader(sy->T("Emulation"))); + ChoiceGroup *emulationSettings = systemSettings->Add(new ChoiceGroup(sy->T("Emulation"))); - systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting); - systemSettings->Add(new CheckBox(&g_Config.bIgnoreBadMemAccess, sy->T("Ignore bad memory accesses"))); + emulationSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting); + emulationSettings->Add(new CheckBox(&g_Config.bIgnoreBadMemAccess, sy->T("Ignore bad memory accesses"))); static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays", "Simulate UMD slow reading speed"}; - View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("I/O timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), I18NCat::SYSTEM, screenManager())); - systemSettings->Add(new CheckBox(&g_Config.bForceLagSync, sy->T("Force real clock sync (slower, less lag)")))->SetDisabledPtr(&g_Config.bAutoFrameSkip); - PopupSliderChoice *lockedMhz = systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, 0, sy->T("Change CPU Clock", "Change CPU Clock (unstable)"), screenManager(), sy->T("MHz, 0:default"))); + View *ioTimingMethod = emulationSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("I/O timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), I18NCat::SYSTEM, screenManager())); + emulationSettings->Add(new CheckBox(&g_Config.bForceLagSync, sy->T("Force real clock sync (slower, less lag)")))->SetDisabledPtr(&g_Config.bAutoFrameSkip); + PopupSliderChoice *lockedMhz = emulationSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, 0, sy->T("Change CPU Clock", "Change CPU Clock (unstable)"), screenManager(), sy->T("MHz, 0:default"))); lockedMhz->SetZeroLabel(sy->T("Auto")); auto sa = GetI18NCategory(I18NCat::SAVEDATA); - systemSettings->Add(new ItemHeader(sa->T("Save states"))); // Borrow this string from the savedata manager + ChoiceGroup *saveStateSettings = systemSettings->Add(new ChoiceGroup(sa->T("Save states"))); // Borrow this string from the savedata manager - systemSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups"))); - systemSettings->Add(new CheckBox(&g_Config.bConfirmLoadState, sy->T("Ask to confirm on load"))); + saveStateSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups"))); + saveStateSettings->Add(new CheckBox(&g_Config.bConfirmLoadState, sy->T("Ask to confirm on load"))); - PopupSliderChoice* savestateSlotCount = systemSettings->Add(new PopupSliderChoice(&g_Config.iSaveStateSlotCount, 1, 30, 5, sy->T("Savestate slot count"), screenManager())); + PopupSliderChoice* savestateSlotCount = saveStateSettings->Add(new PopupSliderChoice(&g_Config.iSaveStateSlotCount, 1, 30, 5, sy->T("Savestate slot count"), screenManager())); savestateSlotCount->OnChange.Add([](UI::EventParams &e) { System_Notify(SystemNotification::UI); }); // NOTE: We will soon support more states, but we'll keep this niche feature limited to the first five. static const char *autoLoadSaveStateChoices[] = {"Off", "Oldest Save", "Newest Save", "Slot 1", "Slot 2", "Slot 3", "Slot 4", "Slot 5"}; - PopupMultiChoice *autoloadSaveState = systemSettings->Add(new PopupMultiChoice(&g_Config.iAutoLoadSaveState, sy->T("Auto load savestate"), autoLoadSaveStateChoices, 0, ARRAY_SIZE(autoLoadSaveStateChoices), I18NCat::SYSTEM, screenManager())); + PopupMultiChoice *autoloadSaveState = saveStateSettings->Add(new PopupMultiChoice(&g_Config.iAutoLoadSaveState, sy->T("Auto load savestate"), autoLoadSaveStateChoices, 0, ARRAY_SIZE(autoLoadSaveStateChoices), I18NCat::SYSTEM, screenManager())); if (g_Config.iAutoLoadSaveState != 1) { autoloadSaveState->HideChoice(1); // Hide "Oldest Save" if not using that mode. It doesn't make sense. } - PopupSliderChoice *rewindInterval = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindSnapshotInterval, 0, 60, 0, sy->T("Rewind Snapshot Interval"), screenManager(), di->T("seconds, 0:off"))); + PopupSliderChoice *rewindInterval = saveStateSettings->Add(new PopupSliderChoice(&g_Config.iRewindSnapshotInterval, 0, 60, 0, sy->T("Rewind Snapshot Interval"), screenManager(), di->T("seconds, 0:off"))); rewindInterval->SetFormat(di->T("%d seconds")); rewindInterval->SetZeroLabel(sy->T("Off")); - systemSettings->Add(new ItemHeader(sy->T("General"))); + ChoiceGroup *generalSettings = systemSettings->Add(new ChoiceGroup(sy->T("General"))); - PopupSliderChoice *exitConfirmation = systemSettings->Add(new PopupSliderChoice(&g_Config.iAskForExitConfirmationAfterSeconds, 0, 1200, 300, sy->T("Ask for exit confirmation after seconds"), screenManager(), "s")); + PopupSliderChoice *exitConfirmation = generalSettings->Add(new PopupSliderChoice(&g_Config.iAskForExitConfirmationAfterSeconds, 0, 1200, 300, sy->T("Ask for exit confirmation after seconds"), screenManager(), "s")); exitConfirmation->SetZeroLabel(sy->T("Off")); if (System_GetPropertyBool(SYSPROP_CAN_RESTRICT_ORIENTATION)) { auto co = GetI18NCategory(I18NCat::CONTROLS); // Display rotation - AddRotationPicker(screenManager(), systemSettings, true); + AddRotationPicker(screenManager(), generalSettings, true); } if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) { - systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange); + generalSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange); } - systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); + generalSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) - systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Use system native keyboard"))); + generalSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Use system native keyboard"))); if (System_GetPropertyBool(SYSPROP_ENOUGH_RAM_FOR_FULL_ISO)) { - systemSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, sy->T("Cache full ISO in RAM")))->SetEnabled(!PSP_IsInited()); + generalSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, sy->T("Cache full ISO in RAM")))->SetEnabled(!PSP_IsInited()); } - CheckBox *checkForUpdate = systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP"))); + CheckBox *checkForUpdate = generalSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP"))); checkForUpdate->OnClick.Add([](UI::EventParams &e) { // Reset the dismissed version so it will check again. if (g_Config.bCheckForNewVersion) { g_Config.sDismissedVersion.clear(); } }); - systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG"))); + generalSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG"))); static const char *screenshotModeChoices[] = { "Final processed image", "Raw game image" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenshotMode, sy->T("Screenshot mode"), screenshotModeChoices, 0, ARRAY_SIZE(screenshotModeChoices), I18NCat::SYSTEM, screenManager())); + generalSettings->Add(new PopupMultiChoice(&g_Config.iScreenshotMode, sy->T("Screenshot mode"), screenshotModeChoices, 0, ARRAY_SIZE(screenshotModeChoices), I18NCat::SYSTEM, screenManager())); // TODO: Make this setting available on Mac too. #if PPSSPP_PLATFORM(WINDOWS) || (defined (SDL) && !defined(MOBILE_DEVICE)) - systemSettings->Add(new CheckBox(&g_Config.bPauseOnLostFocus, sy->T("Pause when not focused"))); + generalSettings->Add(new CheckBox(&g_Config.bPauseOnLostFocus, sy->T("Pause when not focused"))); #endif auto gr = GetI18NCategory(I18NCat::GRAPHICS); std::vector cameraList = Camera::getDeviceList(); if (cameraList.size() >= 1) { - systemSettings->Add(new ItemHeader(gr->T("Camera"))); - PopupMultiChoiceDynamic *cameraChoice = systemSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sCameraDevice, gr->T("Camera Device"), cameraList, I18NCat::NONE, screenManager())); + ChoiceGroup *cameraSettings = systemSettings->Add(new ChoiceGroup(gr->T("Camera"))); + PopupMultiChoiceDynamic *cameraChoice = cameraSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sCameraDevice, gr->T("Camera Device"), cameraList, I18NCat::NONE, screenManager())); cameraChoice->OnChoice.Add([](UI::EventParams &e) { Camera::onCameraDeviceChange(); }); #if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) - systemSettings->Add(new CheckBox(&g_Config.bCameraMirrorHorizontal, gr->T("Mirror camera image"))); + cameraSettings->Add(new CheckBox(&g_Config.bCameraMirrorHorizontal, gr->T("Mirror camera image"))); #endif } - systemSettings->Add(new ItemHeader(sy->T("Cheats", "Cheats"))); - systemSettings->Add(new CheckBox(&g_Config.bEnableCheats, sy->T("Enable Cheats"))); - systemSettings->Add(new CheckBox(&g_Config.bEnablePlugins, sy->T("Enable plugins"))); + ChoiceGroup *cheatSettings = systemSettings->Add(new ChoiceGroup(sy->T("Cheats", "Cheats"))); + cheatSettings->Add(new CheckBox(&g_Config.bEnableCheats, sy->T("Enable Cheats"))); + cheatSettings->Add(new CheckBox(&g_Config.bEnablePlugins, sy->T("Enable plugins"))); - systemSettings->Add(new ItemHeader(sy->T("PSP Settings"))); + ChoiceGroup *pspSettings = systemSettings->Add(new ChoiceGroup(sy->T("PSP Settings"))); // The ordering here is simply mapping directly to PSP_SYSTEMPARAM_LANGUAGE_*. static const char *defaultLanguages[] = { "Auto", "Japanese", "English", "French", "Spanish", "German", "Italian", "Dutch", "Portuguese", "Russian", "Korean", "Chinese (traditional)", "Chinese (simplified)" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iLanguage, psps->T("Game language"), defaultLanguages, -1, ARRAY_SIZE(defaultLanguages), I18NCat::PSPSETTINGS, screenManager())); + pspSettings->Add(new PopupMultiChoice(&g_Config.iLanguage, psps->T("Game language"), defaultLanguages, -1, ARRAY_SIZE(defaultLanguages), I18NCat::PSPSETTINGS, screenManager())); static const char *models[] = { "PSP-1000", "PSP-2000/3000" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited()); - UI::View *nicknameChoice = AddNicknameChoice(systemSettings); - systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, sy->T("Daylight savings"))); + pspSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited()); + UI::View *nicknameChoice = AddNicknameChoice(pspSettings); + pspSettings->Add(new CheckBox(&g_Config.bDayLightSavings, sy->T("Daylight savings"))); static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, sy->T("Date Format"), dateFormat, 0, ARRAY_SIZE(dateFormat), I18NCat::SYSTEM, screenManager())); + pspSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, sy->T("Date Format"), dateFormat, 0, ARRAY_SIZE(dateFormat), I18NCat::SYSTEM, screenManager())); static const char *timeFormat[] = { "24HR", "12HR" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iTimeFormat, sy->T("Time Format"), timeFormat, 0, ARRAY_SIZE(timeFormat), I18NCat::SYSTEM, screenManager())); + pspSettings->Add(new PopupMultiChoice(&g_Config.iTimeFormat, sy->T("Time Format"), timeFormat, 0, ARRAY_SIZE(timeFormat), I18NCat::SYSTEM, screenManager())); static const char *buttonPref[] = { "Use O to confirm", "Use X to confirm" }; - PopupMultiChoice *buttonPrefChoice = systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, sy->T("Confirmation Button"), buttonPref, 0, ARRAY_SIZE(buttonPref), I18NCat::SYSTEM, screenManager())); + PopupMultiChoice *buttonPrefChoice = pspSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, sy->T("Confirmation Button"), buttonPref, 0, ARRAY_SIZE(buttonPref), I18NCat::SYSTEM, screenManager())); buttonPrefChoice->OnChoice.Add([](UI::EventParams &e) { KeyMap::UpdateNativeMenuKeys(); }); #if defined(_WIN32) - systemSettings->Add(new ItemHeader(sy->T("Recording"))); - systemSettings->Add(new CheckBox(&g_Config.bDumpFrames, sy->T("Record Display"))); - systemSettings->Add(new CheckBox(&g_Config.bUseFFV1, sy->T("Use Lossless Video Codec (FFV1)"))); - systemSettings->Add(new CheckBox(&g_Config.bDumpVideoOutput, sy->T("Use output buffer (with overlay) for recording"))); - systemSettings->Add(new CheckBox(&g_Config.bDumpAudio, sy->T("Record Audio"))); - systemSettings->Add(new CheckBox(&g_Config.bSaveLoadResetsAVdumping, sy->T("Reset Recording on Save/Load State"))); + ChoiceGroup *recordingSettings = systemSettings->Add(new ChoiceGroup(sy->T("Recording"))); + recordingSettings->Add(new CheckBox(&g_Config.bDumpFrames, sy->T("Record Display"))); + recordingSettings->Add(new CheckBox(&g_Config.bUseFFV1, sy->T("Use Lossless Video Codec (FFV1)"))); + recordingSettings->Add(new CheckBox(&g_Config.bDumpVideoOutput, sy->T("Use output buffer (with overlay) for recording"))); + recordingSettings->Add(new CheckBox(&g_Config.bDumpAudio, sy->T("Record Audio"))); + recordingSettings->Add(new CheckBox(&g_Config.bSaveLoadResetsAVdumping, sy->T("Reset Recording on Save/Load State"))); #endif } @@ -1515,27 +1515,27 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); if (deviceType == DEVICE_TYPE_VR) { - vrSettings->Add(new ItemHeader(vr->T("Virtual reality"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality"))); - vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableImmersiveVR, vr->T("Enable immersive mode"))); + ChoiceGroup *vrGeneralSettings = vrSettings->Add(new ChoiceGroup(vr->T("Virtual reality"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bEnableImmersiveVR, vr->T("Enable immersive mode"))); if (IsPassthroughSupported()) { - vrSettings->Add(new CheckBox(&g_Config.bPassthrough, vr->T("Enable passthrough"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bPassthrough, vr->T("Enable passthrough"))); } - vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update"))); + vrGeneralSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update"))); } - vrSettings->Add(new ItemHeader(vr->T("VR camera"))); + ChoiceGroup *vrCameraSettings = vrSettings->Add(new ChoiceGroup(vr->T("VR camera"))); if (deviceType == DEVICE_TYPE_VR) { - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); + vrCameraSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); + vrCameraSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); } - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, 100.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV"))); - vrSettings->Add(new CheckBox(&g_Config.bRescaleHUD, vr->T("Heads-up display detection"))); - PopupSliderChoiceFloat* vrHudScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, 0.3f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); + vrCameraSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, 100.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV"))); + vrCameraSettings->Add(new CheckBox(&g_Config.bRescaleHUD, vr->T("Heads-up display detection"))); + PopupSliderChoiceFloat* vrHudScale = vrCameraSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, 0.3f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); vrHudScale->SetEnabledPtr(&g_Config.bRescaleHUD); - vrSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); + vrCameraSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); } void GameSettingsScreen::OnImmersiveModeChange(UI::EventParams &e) {