@@ -164,56 +164,54 @@ void PerformanceOverlay::DrawSettings()
164164 ImGui::Indent ();
165165
166166 // Display options
167- if ( ImGui::CollapsingHeader (" Display Options" , ImGuiTreeNodeFlags_DefaultOpen)) {
168- ImGui::Indent ();
167+ ImGui::TextUnformatted (" Display Options" );
168+ ImGui::Separator ();
169169
170- ImGui::Checkbox (" Show FPS Counter" , &this ->settings .ShowFPS );
171- ImGui::Checkbox (" Show Draw Calls" , &this ->settings .ShowDrawCalls );
172- ImGui::Checkbox (" Show VRAM Usage" , &this ->settings .ShowVRAM );
170+ ImGui::Checkbox (" Show FPS Counter" , &this ->settings .ShowFPS );
171+ ImGui::Checkbox (" Show Draw Calls" , &this ->settings .ShowDrawCalls );
172+ ImGui::Checkbox (" Show VRAM Usage" , &this ->settings .ShowVRAM );
173173
174- bool isFrameGenerationActive = globals::features::upscaling.IsFrameGenerationActive ();
175- if (this ->settings .ShowFPS && isFrameGenerationActive) {
176- ImGui::Checkbox (" Show Pre-FG Frametime Graph" , &this ->settings .ShowPreFGFrameTimeGraph );
174+ bool isFrameGenerationActive = globals::features::upscaling.IsFrameGenerationActive ();
175+ if (this ->settings .ShowFPS && isFrameGenerationActive) {
176+ ImGui::Checkbox (" Show Pre-FG Frametime Graph" , &this ->settings .ShowPreFGFrameTimeGraph );
177177
178- ImGui::Checkbox (" Show Post-FG Frametime Graph" , &this ->settings .ShowPostFGFrameTimeGraph );
179- if (ImGui::IsItemHovered ()) {
180- if (auto _tt = Util::HoverTooltipWrapper ()) {
181- ImGui::Text (" FSR Frame Generation uses calculated timing data (2x Pre-FG).\n DLSS Frame Generation provides measured timing data." );
182- }
178+ ImGui::Checkbox (" Show Post-FG Frametime Graph" , &this ->settings .ShowPostFGFrameTimeGraph );
179+ if (ImGui::IsItemHovered ()) {
180+ if (auto _tt = Util::HoverTooltipWrapper ()) {
181+ ImGui::Text (" FSR Frame Generation uses calculated timing data (2x Pre-FG).\n DLSS Frame Generation provides measured timing data." );
183182 }
184- } else if (this ->settings .ShowFPS ) {
185- ImGui::Checkbox (" Show Frametime Graph" , &this ->settings .ShowPreFGFrameTimeGraph );
186183 }
187-
188- ImGui::Unindent ( );
184+ } else if ( this -> settings . ShowFPS ) {
185+ ImGui::Checkbox ( " Show Frametime Graph " , & this -> settings . ShowPreFGFrameTimeGraph );
189186 }
190187
191- // Appearance settings
192- if (ImGui::CollapsingHeader (" Appearance" , ImGuiTreeNodeFlags_DefaultOpen)) {
193- ImGui::Indent ();
194-
195- ImGui::SliderFloat (" Text Size" , &this ->settings .TextSize , 0 .8f , 1 .2f , " %.2f" );
196- ImGui::SliderFloat (" Background Opacity" , &this ->settings .BackgroundOpacity , 0 .0f , 1 .0f , " %.2f" );
197- ImGui::Checkbox (" Show Border" , &this ->settings .ShowBorder );
198- ImGui::SliderFloat (" Update Interval" , &this ->settings .UpdateInterval , 0 .001f , PerformanceOverlay::Settings::kMaxUpdateInterval , " %.2f seconds" );
199- ImGui::SliderInt (" Frame History Size" , &this ->settings .FrameHistorySize ,
200- this ->settings .kMinFrameHistorySize , this ->settings .kMaxFrameHistorySize );
201-
202- ImGui::Separator ();
203- ImGui::Text (" Position:" );
204- if (ImGui::Button (" Reset Position" )) {
205- this ->settings .PositionSet = false ;
206- }
207- ImGui::SameLine ();
208- if (ImGui::Button (" Restore Defaults" )) {
209- RestoreDefaultSettings ();
210- }
211- if (auto _tt = Util::HoverTooltipWrapper ()) {
212- ImGui::TextUnformatted (" Restores Performance Overlay settings to defaults, including graphs, appearance, and update intervals." );
213- }
188+ ImGui::Spacing ();
189+ ImGui::Spacing ();
214190
215- ImGui::Unindent ();
191+ // Appearance settings
192+ ImGui::TextUnformatted (" Appearance" );
193+ ImGui::Separator ();
194+
195+ ImGui::SliderFloat (" Text Size" , &this ->settings .TextSize , 0 .8f , 1 .2f , " %.2f" );
196+ ImGui::SliderFloat (" Background Opacity" , &this ->settings .BackgroundOpacity , 0 .0f , 1 .0f , " %.2f" );
197+ ImGui::Checkbox (" Show Border" , &this ->settings .ShowBorder );
198+ ImGui::SliderFloat (" Update Interval" , &this ->settings .UpdateInterval , 0 .001f , PerformanceOverlay::Settings::kMaxUpdateInterval , " %.2f seconds" );
199+ ImGui::SliderInt (" Frame History Size" , &this ->settings .FrameHistorySize ,
200+ this ->settings .kMinFrameHistorySize , this ->settings .kMaxFrameHistorySize );
201+
202+ ImGui::Separator ();
203+ ImGui::Text (" Position:" );
204+ if (ImGui::Button (" Reset Position" )) {
205+ this ->settings .PositionSet = false ;
206+ }
207+ ImGui::SameLine ();
208+ if (ImGui::Button (" Restore Defaults" )) {
209+ RestoreDefaultSettings ();
216210 }
211+ if (auto _tt = Util::HoverTooltipWrapper ()) {
212+ ImGui::TextUnformatted (" Restores Performance Overlay settings to defaults, including graphs, appearance, and update intervals." );
213+ }
214+
217215 ImGui::Unindent ();
218216 }
219217}
@@ -375,47 +373,26 @@ void PerformanceOverlay::DrawOverlay()
375373 // Update graph values
376374 this ->UpdateGraphValues ();
377375
378- // Check if we should show collapsible sections (should swallow input only)
379- bool showCollapsibleSections = Menu::GetSingleton ()->ShouldSwallowInput ();
380-
381376 // Show FPS counter if enabled
382377 if (this ->settings .ShowFPS ) {
383- static bool fpsExpanded = true ;
384- if (showCollapsibleSections) {
385- Util::DrawSectionHeader (" FPS & Frame Time" , false , true , &fpsExpanded);
386- }
387- if (fpsExpanded) {
388- DrawFPS ();
389- }
378+ DrawFPS ();
390379 }
391380
392381 // Show Draw Calls if enabled
393382 if (this ->settings .ShowDrawCalls ) {
394- static bool drawCallsExpanded = true ;
395- if (showCollapsibleSections) {
396- Util::DrawSectionHeader (" Draw Calls & Shader Performance" , false , true , &drawCallsExpanded);
397- }
398- if (drawCallsExpanded) {
399- DrawDrawCallsTable (mainRows, summaryRows);
400- }
383+ DrawDrawCallsTable (mainRows, summaryRows);
401384 }
402385
403386 // VRAM & GPU Usage
404387 if (this ->settings .ShowVRAM && menu->GetDXGIAdapter3 ()) {
405- static bool vramExpanded = true ;
406- if (showCollapsibleSections) {
407- Util::DrawSectionHeader (" VRAM Usage" , false , true , &vramExpanded);
408- }
409- if (vramExpanded) {
410- DrawVRAM ();
411- }
388+ DrawVRAM ();
412389 }
413390
414391 ImGui::PopStyleVar (); // ItemSpacing
415392 ImGui::SetWindowFontScale (1 .0f ); // Reset font scale
416393
417394 // --- A/B Test Section ---
418- DrawABTestSection (allRows, showCollapsibleSections );
395+ DrawABTestSection (allRows);
419396
420397 ImGui::End ();
421398 ImGui::PopStyleVar (); // WindowBorderSize
@@ -1160,9 +1137,8 @@ std::vector<ColumnConfig> PerformanceOverlay::BuildABTestResultsTableColumns(con
11601137 * - A/B test controls (clear results, show/hide settings diff)
11611138 *
11621139 * @param allRows The current draw call rows for data collection
1163- * @param showCollapsibleSections Whether to show collapsible section headers
11641140 */
1165- void PerformanceOverlay::DrawABTestSection (const std::vector<DrawCallRow>& allRows, bool showCollapsibleSections )
1141+ void PerformanceOverlay::DrawABTestSection (const std::vector<DrawCallRow>& allRows)
11661142{
11671143 auto * menu = Menu::GetSingleton ();
11681144 auto * abTestingManager = ABTestingManager::GetSingleton ();
@@ -1205,125 +1181,113 @@ void PerformanceOverlay::DrawABTestSection(const std::vector<DrawCallRow>& allRo
12051181
12061182 // Display A/B test results if available
12071183 if (aggregator.HasResults ()) {
1208- static bool abResultsExpanded = true ;
1209- if (showCollapsibleSections) {
1210- Util::DrawSectionHeader (" Aggregated A/B Test Results" , false , true , &abResultsExpanded);
1184+ this ->DrawABTestResultsTable ();
1185+ ImGui::Separator ();
1186+ // --- A/B Results Controls ---
1187+ static bool showSettingsDiff = false ;
1188+ ImGui::BeginGroup ();
1189+ if (ImGui::Button (showSettingsDiff ? " Hide Settings Diff" : " Show Settings Diff" )) {
1190+ showSettingsDiff = !showSettingsDiff;
12111191 }
1212- if (abResultsExpanded) {
1213- this ->DrawABTestResultsTable ();
1192+ ImGui::SameLine ();
1193+ if (ImGui::Button (" Clear A/B Test Results" )) {
1194+ aggregator.Clear ();
1195+ this ->settingsDiff .clear ();
1196+ this ->settingsDiffLoaded = false ;
1197+ showSettingsDiff = false ;
1198+ ImGui::EndGroup ();
12141199 ImGui::Separator ();
1215- // --- A/B Results Controls ---
1216- static bool showSettingsDiff = false ;
1217- ImGui::BeginGroup ();
1218- if (ImGui::Button (showSettingsDiff ? " Hide Settings Diff" : " Show Settings Diff" )) {
1219- showSettingsDiff = !showSettingsDiff;
1220- }
1221- ImGui::SameLine ();
1222- if (ImGui::Button (" Clear A/B Test Results" )) {
1223- aggregator.Clear ();
1224- this ->settingsDiff .clear ();
1225- this ->settingsDiffLoaded = false ;
1226- showSettingsDiff = false ;
1227- ImGui::EndGroup ();
1228- ImGui::Separator ();
1229- return ;
1200+ return ;
1201+ }
1202+ ImGui::EndGroup ();
1203+ // --- Settings diff section (inline, toggled) ---
1204+ if (showSettingsDiff) {
1205+ if (!this ->settingsDiffLoaded ) {
1206+ std::filesystem::path userPath = Util::PathHelpers::GetDataPath () / " SKSE/Plugins/CommunityShaders/SettingsUser.json" ;
1207+ std::filesystem::path testPath = Util::PathHelpers::GetDataPath () / " SKSE/Plugins/CommunityShaders/SettingsTest.json" ;
1208+ this ->settingsDiff = Util::FileSystem::LoadJsonDiff (userPath, testPath);
1209+ this ->settingsDiffLoaded = true ;
12301210 }
1231- ImGui::EndGroup ();
1232- // --- Settings diff section (inline, toggled) ---
1233- if (showSettingsDiff) {
1234- if (!this ->settingsDiffLoaded ) {
1235- std::filesystem::path userPath = Util::PathHelpers::GetDataPath () / " SKSE/Plugins/CommunityShaders/SettingsUser.json" ;
1236- std::filesystem::path testPath = Util::PathHelpers::GetDataPath () / " SKSE/Plugins/CommunityShaders/SettingsTest.json" ;
1237- this ->settingsDiff = Util::FileSystem::LoadJsonDiff (userPath, testPath);
1238- this ->settingsDiffLoaded = true ;
1239- }
1240- static bool settingsDiffExpanded = true ;
1241- if (showCollapsibleSections) {
1242- Util::DrawSectionHeader (" A/B Test Settings Differences" , false , true , &settingsDiffExpanded);
1243- }
1244- if (settingsDiffExpanded) {
1245- ImGui::TextUnformatted (" Differences between USER (A) and TEST (B) configs:" );
1246- if (this ->settingsDiff .empty ()) {
1247- ImGui::TextUnformatted (" No setting changes detected between USER (A) and TEST (B) configs." );
1248- } else if (ImGui::BeginTable (" ABSettingsDiffTable" , 3 , ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Sortable)) {
1249- ImGui::TableSetupColumn (" Setting Path" , ImGuiTableColumnFlags_DefaultSort);
1250- ImGui::TableSetupColumn (" A Value" );
1251- ImGui::TableSetupColumn (" B Value" );
1252- ImGui::TableHeadersRow ();
1253-
1254- // Determine which variant performed better based on Total row
1255- bool variantABetter = false ;
1256- bool variantBBetter = false ;
1257- auto results = aggregator.GetAggregatedResults ();
1258- for (const auto & stat : results) {
1259- auto maybeSpecialType = magic_enum::enum_cast<SpecialShaderType>(stat.shaderType );
1260- if (maybeSpecialType.has_value () && *maybeSpecialType == SpecialShaderType::Total) { // Total row
1261- if (stat.meanA < stat.meanB ) {
1262- variantABetter = true ; // A has lower frame time (better)
1263- } else if (stat.meanB < stat.meanA ) {
1264- variantBBetter = true ; // B has lower frame time (better)
1265- }
1266- break ;
1267- }
1211+ ImGui::TextUnformatted (" Differences between USER (A) and TEST (B) configs:" );
1212+ if (this ->settingsDiff .empty ()) {
1213+ ImGui::TextUnformatted (" No setting changes detected between USER (A) and TEST (B) configs." );
1214+ } else if (ImGui::BeginTable (" ABSettingsDiffTable" , 3 , ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Sortable)) {
1215+ ImGui::TableSetupColumn (" Setting Path" , ImGuiTableColumnFlags_DefaultSort);
1216+ ImGui::TableSetupColumn (" A Value" );
1217+ ImGui::TableSetupColumn (" B Value" );
1218+ ImGui::TableHeadersRow ();
1219+
1220+ // Determine which variant performed better based on Total row
1221+ bool variantABetter = false ;
1222+ bool variantBBetter = false ;
1223+ auto results = aggregator.GetAggregatedResults ();
1224+ for (const auto & stat : results) {
1225+ auto maybeSpecialType = magic_enum::enum_cast<SpecialShaderType>(stat.shaderType );
1226+ if (maybeSpecialType.has_value () && *maybeSpecialType == SpecialShaderType::Total) { // Total row
1227+ if (stat.meanA < stat.meanB ) {
1228+ variantABetter = true ; // A has lower frame time (better)
1229+ } else if (stat.meanB < stat.meanA ) {
1230+ variantBBetter = true ; // B has lower frame time (better)
12681231 }
1232+ break ;
1233+ }
1234+ }
12691235
1270- // Get theme for color coding
1271- const auto & theme = menu->GetTheme ();
1272-
1273- // Sort the settings diff if needed
1274- std::vector<SettingsDiffEntry> sortedDiff = this ->settingsDiff ;
1275- if (const ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs ()) {
1276- if (sortSpecs->SpecsCount > 0 ) {
1277- int sortCol = sortSpecs->Specs ->ColumnIndex ;
1278- bool sortAsc = sortSpecs->Specs ->SortDirection == ImGuiSortDirection_Ascending;
1279- std::sort (sortedDiff.begin (), sortedDiff.end (), [sortCol, sortAsc](const SettingsDiffEntry& a, const SettingsDiffEntry& b) {
1280- if (sortCol == 0 )
1281- return sortAsc ? (a.path < b.path ) : (a.path > b.path );
1282- if (sortCol == 1 )
1283- return sortAsc ? (a.aValue < b.aValue ) : (a.aValue > b.aValue );
1284- if (sortCol == 2 )
1285- return sortAsc ? (a.bValue < b.bValue ) : (a.bValue > b.bValue );
1286- return false ;
1287- });
1288- }
1289- }
1290- for (const auto & entry : sortedDiff) {
1291- ImGui::TableNextRow ();
1292- ImGui::TableSetColumnIndex (0 );
1293- ImGui::TextUnformatted (entry.path .c_str ());
1294- // Only show the path as text, no custom tooltip guessing
1295- ImGui::TableSetColumnIndex (1 );
1296- // Color A value based on performance
1297- if (variantABetter) {
1298- ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .SuccessColor );
1299- ImGui::TextUnformatted (entry.aValue .c_str ());
1300- ImGui::PopStyleColor ();
1301- } else if (variantBBetter) {
1302- ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .Error );
1303- ImGui::TextUnformatted (entry.aValue .c_str ());
1304- ImGui::PopStyleColor ();
1305- } else {
1306- ImGui::TextUnformatted (entry.aValue .c_str ());
1307- }
1308- ImGui::TableSetColumnIndex (2 );
1309- // Color B value based on performance
1310- if (variantBBetter) {
1311- ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .SuccessColor );
1312- ImGui::TextUnformatted (entry.bValue .c_str ());
1313- ImGui::PopStyleColor ();
1314- } else if (variantABetter) {
1315- ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .Error );
1316- ImGui::TextUnformatted (entry.bValue .c_str ());
1317- ImGui::PopStyleColor ();
1318- } else {
1319- ImGui::TextUnformatted (entry.bValue .c_str ());
1320- }
1321- }
1322- ImGui::EndTable ();
1236+ // Get theme for color coding
1237+ const auto & theme = menu->GetTheme ();
1238+
1239+ // Sort the settings diff if needed
1240+ std::vector<SettingsDiffEntry> sortedDiff = this ->settingsDiff ;
1241+ if (const ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs ()) {
1242+ if (sortSpecs->SpecsCount > 0 ) {
1243+ int sortCol = sortSpecs->Specs ->ColumnIndex ;
1244+ bool sortAsc = sortSpecs->Specs ->SortDirection == ImGuiSortDirection_Ascending;
1245+ std::sort (sortedDiff.begin (), sortedDiff.end (), [sortCol, sortAsc](const SettingsDiffEntry& a, const SettingsDiffEntry& b) {
1246+ if (sortCol == 0 )
1247+ return sortAsc ? (a.path < b.path ) : (a.path > b.path );
1248+ if (sortCol == 1 )
1249+ return sortAsc ? (a.aValue < b.aValue ) : (a.aValue > b.aValue );
1250+ if (sortCol == 2 )
1251+ return sortAsc ? (a.bValue < b.bValue ) : (a.bValue > b.bValue );
1252+ return false ;
1253+ });
13231254 }
13241255 }
1325- ImGui::Separator ();
1256+ for (const auto & entry : sortedDiff) {
1257+ ImGui::TableNextRow ();
1258+ ImGui::TableSetColumnIndex (0 );
1259+ ImGui::TextUnformatted (entry.path .c_str ());
1260+ // Only show the path as text, no custom tooltip guessing
1261+ ImGui::TableSetColumnIndex (1 );
1262+ // Color A value based on performance
1263+ if (variantABetter) {
1264+ ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .SuccessColor );
1265+ ImGui::TextUnformatted (entry.aValue .c_str ());
1266+ ImGui::PopStyleColor ();
1267+ } else if (variantBBetter) {
1268+ ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .Error );
1269+ ImGui::TextUnformatted (entry.aValue .c_str ());
1270+ ImGui::PopStyleColor ();
1271+ } else {
1272+ ImGui::TextUnformatted (entry.aValue .c_str ());
1273+ }
1274+ ImGui::TableSetColumnIndex (2 );
1275+ // Color B value based on performance
1276+ if (variantBBetter) {
1277+ ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .SuccessColor );
1278+ ImGui::TextUnformatted (entry.bValue .c_str ());
1279+ ImGui::PopStyleColor ();
1280+ } else if (variantABetter) {
1281+ ImGui::PushStyleColor (ImGuiCol_Text, theme.StatusPalette .Error );
1282+ ImGui::TextUnformatted (entry.bValue .c_str ());
1283+ ImGui::PopStyleColor ();
1284+ } else {
1285+ ImGui::TextUnformatted (entry.bValue .c_str ());
1286+ }
1287+ }
1288+ ImGui::EndTable ();
13261289 }
1290+ ImGui::Separator ();
13271291 }
13281292 }
13291293}
0 commit comments