/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : commando * * * * $Archive:: /Commando/Code/Commando/dlgconfigperformancetab.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 1/08/02 3:03p $* * * * $Revision:: 11 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "dlgconfigperformancetab.h" #include "resource.h" #include "registry.h" #include "comboboxctrl.h" #include "sliderctrl.h" #include "rendobj.h" #include "phys.h" #include "ww3d.h" #include "pscene.h" #include "combat.h" #include "dx8wrapper.h" #include "dx8caps.h" #include "surfaceeffects.h" #include "_globals.h" #include "translatedb.h" #include "string_ids.h" ///////////////////////////////////////////////////////////////////////////// // Structures and typedefs ///////////////////////////////////////////////////////////////////////////// typedef struct _PERFORMANCE_SETTING { int ctrl_id; int value; } PERFORMANCE_SETTING; ///////////////////////////////////////////////////////////////////////////// // Constants ///////////////////////////////////////////////////////////////////////////// const int MAX_PERFORMANCE_LEVELS = 4; const int MAX_EXPERT_OPTIONS = 7; PERFORMANCE_SETTING _PerformanceLevels[MAX_PERFORMANCE_LEVELS][MAX_EXPERT_OPTIONS] = { // // Low detail // { {IDC_CHAR_SHADOWS_SLIDER, 0}, {IDC_TEXTURE_DETAIL_SLIDER, 0}, {IDC_PARTICLE_DETAIL_SLIDER, 0}, {IDC_SURFACE_DETAIL_SLIDER, 0}, {IDC_GEOMETRY_DETAIL_SLIDER, 0}, {IDC_TERRAIN_SHADOW_CHECK, 0}, {IDC_NPATCH_CHECK, 0} }, { {IDC_CHAR_SHADOWS_SLIDER, 1}, {IDC_TEXTURE_DETAIL_SLIDER, 1}, {IDC_PARTICLE_DETAIL_SLIDER, 0}, {IDC_SURFACE_DETAIL_SLIDER, 0}, {IDC_GEOMETRY_DETAIL_SLIDER, 0}, {IDC_TERRAIN_SHADOW_CHECK, 0}, {IDC_NPATCH_CHECK, 0} }, { {IDC_CHAR_SHADOWS_SLIDER, 2}, {IDC_TEXTURE_DETAIL_SLIDER, 2}, {IDC_PARTICLE_DETAIL_SLIDER, 1}, {IDC_SURFACE_DETAIL_SLIDER, 1}, {IDC_GEOMETRY_DETAIL_SLIDER, 1}, {IDC_TERRAIN_SHADOW_CHECK, 1}, {IDC_NPATCH_CHECK, 0} }, // // High detail // { {IDC_CHAR_SHADOWS_SLIDER, 3}, {IDC_TEXTURE_DETAIL_SLIDER, 2}, {IDC_PARTICLE_DETAIL_SLIDER, 2}, {IDC_SURFACE_DETAIL_SLIDER, 2}, {IDC_GEOMETRY_DETAIL_SLIDER, 2}, {IDC_TERRAIN_SHADOW_CHECK, 1}, {IDC_NPATCH_CHECK, 0} }, }; const char *VALUE_NAME_DYN_LOD = "Dynamic_LOD_Budget"; const char *VALUE_NAME_STATIC_LOD = "Static_LOD_Budget"; const char *VALUE_NAME_DYN_SHADOWS = "Dynamic_Projectors"; const char *VALUE_NAME_SHADOW_MODE = "Shadow_Mode"; const char *VALUE_NAME_STATIC_SHADOWS = "Static_Projectors"; const char *VALUE_NAME_TEXTURE_RES = "Texture_Resolution"; const char *VALUE_NAME_PARTICLE_DETAIL = "Particle_Detail"; const char *VALUE_NAME_NPATCHES = "NPatches"; const int MAX_LOD_HIGH = 10000; const int MAX_LOD_MED = 5000; const int MAX_LOD_LOW = 0; //////////////////////////////////////////////////////////////// // // DlgConfigPerformanceTabClass // //////////////////////////////////////////////////////////////// DlgConfigPerformanceTabClass::DlgConfigPerformanceTabClass (void) : ChildDialogClass (IDD_CONFIG_PERFORMANCE) { return ; } //////////////////////////////////////////////////////////////// // // ~DlgConfigPerformanceTabClass // //////////////////////////////////////////////////////////////// DlgConfigPerformanceTabClass::~DlgConfigPerformanceTabClass (void) { return ; } //////////////////////////////////////////////////////////////// // // On_Init_Dialog // //////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::On_Init_Dialog (void) { // // Configure the dialog controls // Setup_Controls (); Load_Values (); Determine_Performance_Setting (); // // Set the visibility of the expert windows controls // Build_Expert_Window_List (); Display_Expert_Settings (false); ChildDialogClass::On_Init_Dialog (); return ; } ///////////////////////////////////////////////////////////////////////////// // // Build_Expert_Window_List // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Build_Expert_Window_List (void) { ExpertWindowList.Delete_All (); // // Find the y-position of the expert mode checkbox // RectClass rect = Get_Dlg_Item (IDC_EXPERT_CHECK)->Get_Window_Rect (); float y_pos = rect.Top; // // Loop over all the controls of the dialog // for ( int index = 0; index < Get_Control_Count (); index ++) { DialogControlClass *control = Get_Control (index); // // If this control is below the expert checkbox then its // part of the expert settings // rect = control->Get_Window_Rect (); if (rect.Top > y_pos) { ExpertWindowList.Add (control); } } return ; } ///////////////////////////////////////////////////////////////////////////// // // Display_Expert_Settings // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Display_Expert_Settings (bool onoff) { // // Loop over all the expert settings controls and either // show or hide them... // for (int index = 0; index < ExpertWindowList.Count (); index ++) { ExpertWindowList[index]->Show (onoff); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Setup_Controls // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Setup_Controls (void) { // // Configure the main performance slider // SliderCtrlClass *performance_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_PERFORMANCE_SLIDER); performance_slider->Set_Range (0, MAX_PERFORMANCE_LEVELS - 1); // // Configure the individual detail-setting sliders // ((SliderCtrlClass *)Get_Dlg_Item (IDC_GEOMETRY_DETAIL_SLIDER))->Set_Range (0, 2); ((SliderCtrlClass *)Get_Dlg_Item (IDC_CHAR_SHADOWS_SLIDER))->Set_Range (0, 3); ((SliderCtrlClass *)Get_Dlg_Item (IDC_TEXTURE_DETAIL_SLIDER))->Set_Range (0, 2); ((SliderCtrlClass *)Get_Dlg_Item (IDC_SURFACE_DETAIL_SLIDER))->Set_Range (0, 2); ((SliderCtrlClass *)Get_Dlg_Item (IDC_PARTICLE_DETAIL_SLIDER))->Set_Range (0, 2); const WCHAR *PRELIT_MODE_NAMES[] = { TRANSLATE (IDS_MENU_VERTEX), TRANSLATE (IDS_MENU_MP_LIGHTMAPS), TRANSLATE (IDS_MENU_MT_LIGHTMAPS) }; Set_Dlg_Item_Text (IDC_LIGHTING_MODE, PRELIT_MODE_NAMES [WW3D::Get_Prelit_Mode()]); Enable_Dlg_Item (IDC_LIGHTING_MODE, false); const WCHAR *TEXTURE_FILTER_NAMES[] = { TRANSLATE (IDS_BILINEAR), TRANSLATE (IDS_TRILINEAR), TRANSLATE (IDS_ANISOTROPIC) }; Set_Dlg_Item_Text (IDC_TEXTURE_FILTER, TEXTURE_FILTER_NAMES [WW3D::Get_Texture_Filter()]); Enable_Dlg_Item (IDC_TEXTURE_FILTER, false); // // Disable the checkbox if NPatches aren't supported // if (DX8Wrapper::Get_Current_Caps() && DX8Wrapper::Get_Current_Caps()->Support_NPatches () == false) { Check_Dlg_Button (IDC_NPATCH_CHECK, false); Enable_Dlg_Item (IDC_NPATCH_CHECK, false); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Load_Values // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Load_Values (void) { SliderCtrlClass *geometry_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_GEOMETRY_DETAIL_SLIDER); SliderCtrlClass *char_shadows_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_CHAR_SHADOWS_SLIDER); SliderCtrlClass *texture_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_TEXTURE_DETAIL_SLIDER); SliderCtrlClass *surface_effect_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_SURFACE_DETAIL_SLIDER); SliderCtrlClass *particle_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_PARTICLE_DETAIL_SLIDER); // // Attempt to open the registry key // RegistryClass registry (APPLICATION_SUB_KEY_NAME_SYSTEM_SETTINGS); if (registry.Is_Valid ()) { // // Read the values from the registry // int static_shadows = registry.Get_Int (VALUE_NAME_STATIC_SHADOWS, 1); int shadow_mode = registry.Get_Int (VALUE_NAME_SHADOW_MODE, PhysicsSceneClass::SHADOW_MODE_BLOBS_PLUS); int texture_red = registry.Get_Int (VALUE_NAME_TEXTURE_RES, 0); int particle_detail = registry.Get_Int (VALUE_NAME_PARTICLE_DETAIL, 1); int npatches = registry.Get_Int (VALUE_NAME_NPATCHES, 0); // // Get the surface effect mode // int surface_effect = SurfaceEffectsManager::Get_Mode (); // // Get the LOD settings // int dynamic_lod = 0; int static_lod = 0; PhysicsSceneClass::Get_Instance()->Get_Polygon_Budgets (&static_lod, &dynamic_lod); // // Set the slider's positions to reflect the loaded values // char_shadows_slider->Set_Pos (min (shadow_mode, 3)); texture_slider->Set_Pos (max (2 - texture_red, 0)); surface_effect_slider->Set_Pos (surface_effect); particle_slider->Set_Pos (particle_detail); // // Choose a setting for the geometry slider based on // the dynamic and static LOD budgets // if (dynamic_lod < (MAX_LOD_LOW + 1000)) { geometry_slider->Set_Pos (0); } else if (dynamic_lod <= MAX_LOD_MED) { geometry_slider->Set_Pos (1); } else { geometry_slider->Set_Pos (2); } // // Check the checkbox controls (if necessary) // Check_Dlg_Button (IDC_TERRAIN_SHADOW_CHECK, bool(static_shadows != 0)); Check_Dlg_Button (IDC_NPATCH_CHECK, bool(npatches != 0)); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Determine_Performance_Setting // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Determine_Performance_Setting (void) { float option_levels[MAX_EXPERT_OPTIONS] = { 0 }; int count_per_option[MAX_EXPERT_OPTIONS] = { 0 }; // // Get the current values of each setting // DynamicVectorClass option_values; Get_Settings (option_values); // // Find out which level each option is currently set at // for (int level = MAX_PERFORMANCE_LEVELS - 1; level >= 0; level --) { for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // If the values match, then record the current level for this option // if (option_values[index] == _PerformanceLevels[level][index].value) { option_levels[index] += level; count_per_option[index] ++; } } } // // Add up all the levels // float level_sum = 0; for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { level_sum += (option_levels[index] / count_per_option[index]); } // // Take the average rating // float level_rating = level_sum / MAX_EXPERT_OPTIONS; // // Set the slider's position // SliderCtrlClass *slider_ctrl = (SliderCtrlClass *)Get_Dlg_Item (IDC_PERFORMANCE_SLIDER); slider_ctrl->Set_Pos (min (int(level_rating + 0.4F), MAX_EXPERT_OPTIONS - 1), false); return ; } ////////////////////////////////////////////////////////////////////// // // On_Command // ////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::On_Command (int ctrl_id, int message_id, DWORD param) { switch (ctrl_id) { case IDC_EXPERT_CHECK: { bool enabled = Is_Dlg_Button_Checked (IDC_EXPERT_CHECK); Display_Expert_Settings (enabled); break; } } ChildDialogClass::On_Command (ctrl_id, message_id, param); return ; } ///////////////////////////////////////////////////////////////////////////// // // Get_Settings // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Get_Settings (DynamicVectorClass &settings) { // // Determine what the value of each control is // for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // Determine what the value of this control is // int curr_value = 0; int ctrl_id = _PerformanceLevels[0][index].ctrl_id; switch (ctrl_id) { // // Read any of the slider positions // case IDC_GEOMETRY_DETAIL_SLIDER: case IDC_CHAR_SHADOWS_SLIDER: case IDC_TEXTURE_DETAIL_SLIDER: case IDC_PARTICLE_DETAIL_SLIDER: case IDC_SURFACE_DETAIL_SLIDER: { SliderCtrlClass *slider_ctrl = (SliderCtrlClass *)Get_Dlg_Item (ctrl_id); curr_value = slider_ctrl->Get_Pos (); break; } // // Read the values from either checkbox // case IDC_TERRAIN_SHADOW_CHECK: case IDC_NPATCH_CHECK: curr_value = Is_Dlg_Button_Checked (ctrl_id); break; } // // Add this value to the list // settings.Add (curr_value); } return ; } ///////////////////////////////////////////////////////////////////////////// // // Update_Expert_Controls // ///////////////////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::Update_Expert_Controls (int level) { for (int index = 0; index < MAX_EXPERT_OPTIONS; index ++) { // // Determine which control we are updating // int ctrl_id = _PerformanceLevels[level][index].ctrl_id; switch (ctrl_id) { // // Update any of the sliders via the same mechanism // case IDC_GEOMETRY_DETAIL_SLIDER: case IDC_CHAR_SHADOWS_SLIDER: case IDC_TEXTURE_DETAIL_SLIDER: case IDC_PARTICLE_DETAIL_SLIDER: case IDC_SURFACE_DETAIL_SLIDER: { SliderCtrlClass *slider_ctrl = (SliderCtrlClass *)Get_Dlg_Item (ctrl_id); slider_ctrl->Set_Pos (_PerformanceLevels[level][index].value); break; } // // Update any of the check boxes via the same mechanism // case IDC_TERRAIN_SHADOW_CHECK: case IDC_NPATCH_CHECK: Check_Dlg_Button (ctrl_id, bool(_PerformanceLevels[level][index].value == 1)); break; } } return ; } //////////////////////////////////////////////////////////////// // // On_SliderCtrl_Pos_Changed // //////////////////////////////////////////////////////////////// void DlgConfigPerformanceTabClass::On_SliderCtrl_Pos_Changed ( SliderCtrlClass * slider_ctrl, int ctrl_id, int new_pos ) { if (ctrl_id == IDC_PERFORMANCE_SLIDER) { Update_Expert_Controls (new_pos); } return ; } ///////////////////////////////////////////////////////////////////////////// // // On_Apply // ///////////////////////////////////////////////////////////////////////////// bool DlgConfigPerformanceTabClass::On_Apply (void) { SliderCtrlClass *geometry_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_GEOMETRY_DETAIL_SLIDER); SliderCtrlClass *char_shadows_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_CHAR_SHADOWS_SLIDER); SliderCtrlClass *texture_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_TEXTURE_DETAIL_SLIDER); SliderCtrlClass *surface_effect_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_SURFACE_DETAIL_SLIDER); SliderCtrlClass *particle_slider = (SliderCtrlClass *)Get_Dlg_Item (IDC_PARTICLE_DETAIL_SLIDER); // // Attempt to open the registry key // RegistryClass registry (APPLICATION_SUB_KEY_NAME_SYSTEM_SETTINGS); if (registry.Is_Valid ()) { // // Get the current settings from the dialog // int geometry_detail = geometry_slider->Get_Pos (); int shadow_mode = char_shadows_slider->Get_Pos (); int texture_red = texture_slider->Get_Pos (); int surface_effect = surface_effect_slider->Get_Pos (); int particle_detail = particle_slider->Get_Pos (); int static_shadows = Is_Dlg_Button_Checked (IDC_TERRAIN_SHADOW_CHECK); int npatches = Is_Dlg_Button_Checked (IDC_NPATCH_CHECK); // // Determine a good LOD budget to use // int lod_budget = 0; if (geometry_detail == 0) { lod_budget = 0; } else if (geometry_detail == 1) { lod_budget = MAX_LOD_MED; } else if (geometry_detail == 2) { lod_budget = MAX_LOD_HIGH; } // // Store the values in the registry // registry.Set_Int (VALUE_NAME_DYN_LOD, lod_budget); registry.Set_Int (VALUE_NAME_STATIC_LOD, lod_budget); registry.Set_Int (VALUE_NAME_DYN_SHADOWS, (shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE)); registry.Set_Int (VALUE_NAME_STATIC_SHADOWS, static_shadows); registry.Set_Int (VALUE_NAME_SHADOW_MODE, shadow_mode); registry.Set_Int (VALUE_NAME_TEXTURE_RES, max (2 - texture_red, 0)); registry.Set_Int (VALUE_NAME_PARTICLE_DETAIL, particle_detail); if (DX8Wrapper::Get_Current_Caps() && DX8Wrapper::Get_Current_Caps()->Support_NPatches ()) { registry.Set_Int (VALUE_NAME_NPATCHES, npatches); } // // Pass the values onto the game // COMBAT_SCENE->Set_Polygon_Budgets (lod_budget, lod_budget); COMBAT_SCENE->Enable_Dynamic_Projectors ((shadow_mode != PhysicsSceneClass::SHADOW_MODE_NONE)); COMBAT_SCENE->Enable_Static_Projectors ((static_shadows != 0)); // Note! It is important to invalidate all textures when // changing the amount of render targets, as render target // creation may have problems if the card is running low on // texture memory! if (COMBAT_SCENE->Get_Shadow_Mode()!=(PhysicsSceneClass::ShadowEnum)shadow_mode) { WW3D::_Invalidate_Textures(); COMBAT_SCENE->Set_Shadow_Mode ((PhysicsSceneClass::ShadowEnum)shadow_mode); } WW3D::Set_Texture_Reduction (max (2 - texture_red, 0)); SurfaceEffectsManager::Set_Mode ((SurfaceEffectsManager::MODE)surface_effect); } return true; }