Qt/Input: add keyboard stick interpolation

This commit is contained in:
Megamouse 2018-12-29 15:56:18 +01:00
parent a77bd41b50
commit 632b0f489c
7 changed files with 338 additions and 84 deletions

View File

@ -340,6 +340,9 @@ struct pad_config final : cfg::node
cfg::_int<0, 500> mouse_acceleration_x{ this, "Mouse Acceleration X Axis", 200 };
cfg::_int<0, 500> mouse_acceleration_y{ this, "Mouse Acceleration Y Axis", 250 };
cfg::_int<0, 100> l_stick_lerp_factor{ this, "Left Stick Lerp Factor", 100 };
cfg::_int<0, 100> r_stick_lerp_factor{ this, "Right Stick Lerp Factor", 100 };
bool load()
{
if (fs::file cfg_file{ cfg_name, fs::read })

View File

@ -67,17 +67,17 @@
"exitOnStop": "Automatically close RPCS3 when closing a game, or when a game closes itself.",
"alwaysStart": "Leave this enabled unless you are a developer.",
"startGameFullscreen": "Automatically puts the game window in fullscreen.\nDouble click on the game window or press alt+enter to toggle fullscreen and windowed mode.",
"showFPSInTitle": "Shows the framerate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.",
"showFPSInTitle": "Shows the frame rate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.",
"gs_resizeOnBoot": "Automatically resizes the game window on boot.\nThis does not change the internal game resolution.",
"showTrophyPopups": "Show trophy popups when a trophy is unlocked.",
"gs_disableMouse": "Disables the activation of fullscreen mode per doubleclick while the game screen is active.\nCheck this if you want to play with mouse and keyboard (for example with UCR).",
"showTrophyPopups": "Show trophy pop-ups when a trophy is unlocked.",
"gs_disableMouse": "Disables the activation of fullscreen mode per double-click while the game screen is active.\nCheck this if you want to play with mouse and keyboard (for example with UCR).",
"maxLLVMThreads": "Limits the maximum number of threads used for PPU Module compilation.\nLower this in order to increase performance of other open applications.\nThe default uses all available threads.",
"showShaderCompilationHint": "Show shader compilation hints using the native overlay.",
"useNativeInterface": "Enables use of native HUD within the game window that can interact with game controllers.\nWhen disabled, regular Qt dialogs are used instead.\nCurrently, only the English language is supported."
},
"overlay": {
"perfOverlayEnabled": "Enables or disables the performance overlay.",
"perfOverlayPosition": "Sets the on-screen position (quadrant) of the perfomance overlay.",
"perfOverlayPosition": "Sets the on-screen position (quadrant) of the performance overlay.",
"perfOverlayDetailLevel": "Controls the amount of information displayed on the performance overlay.",
"perfOverlayUpdateInterval": "Sets the time interval in which the performance overlay is being updated (measured in milliseconds).",
"perfOverlayFontSize": "Sets the font size of the performance overlay (measured in pixels).",
@ -101,7 +101,7 @@
"graphicsAdapterBox": "On multi GPU systems select which GPU to use in RPCS3 when using Vulkan or DirectX 12.\nThis is not needed when using OpenGL.",
"graphicsAdapterBox_Linux": "On multi GPU systems select which GPU to use in RPCS3 when using Vulkan.\nThis is not needed when using OpenGL.",
"aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well, especially if you use a resolution that is not 720p.",
"frameLimitBox": "Off is the best option as it performs faster.\nUsing the frame limiter will add extra overhead and slow down the game.\nHowever, some games will crash if the framerate is too high.\nIf that happens, set value to anything other than Off.",
"frameLimitBox": "Off is the best option as it performs faster.\nUsing the frame limiter will add extra overhead and slow down the game.\nHowever, some games will crash if the frame rate is too high.\nIf that happens, set value to anything other than Off.",
"anisotropicFilterOverride": "Higher values increase sharpness of textures on sloped surfaces at the cost of GPU resources.\nModern GPUs can handle this setting just fine even at 16x.\nKeep this on Automatic if you want to use the original setting used by a real PS3."
},
"sliders": {
@ -127,7 +127,7 @@
},
"input": {
"padHandlerBox": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nIf you have an Xbox controller, or another compatible device, use XInput.\nOlder controllers such as PS2 controllers with an adapter usually work fine with MMJoystick.\nCheck button mappings in the Windows control panel.",
"padHandlerBox_Linux": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nevdev input is WIP.",
"padHandlerBox_Linux": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.",
"keyboardHandlerBox": "Some games support native keyboard input.\nBasic will work in these cases.",
"mouseHandlerBox": "Some games support native mouse input.\nBasic will work in these cases.",
"cameraBox": "Camera support is not implemented, leave this on null.",
@ -141,6 +141,6 @@
"sysLangBox": "Some games may fail to boot if the system language is not available in the game itself.\nOther games will switch language automatically to what is selected here.\nIt is recommended leaving this on a language supported by the game.",
"enterButtonAssignment": "The button used for enter/accept/confirm in system dialogs.\nChange this to use the circle button instead, which is the default configuration on Japanese systems and in many Japanese games.\nIn these cases having the cross button assigned can often lead to confusion.",
"enableHostRoot": "Required for some Homebrew.\nIf unsure, don't use this option.",
"limitCacheSize": "Automatically removes older files from disk cache on boot if it grows larger than the specified value.\nGames can use the cache folder to temporarily store data outside of system memory. It is not used for long term storage."
"limitCacheSize": "Automatically removes older files from disk cache on boot if it grows larger than the specified value.\nGames can use the cache folder to temporarily store data outside of system memory. It is not used for long-term storage."
}
}

View File

@ -89,7 +89,17 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
m_stick_min[i] = pressed ? normalized_value : 0;
if (is_max || is_min)
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
{
m_stick_val[i] = m_stick_max[i] - m_stick_min[i];
const f32 stick_lerp_factor = (i < 2) ? m_l_stick_lerp_factor : m_r_stick_lerp_factor;
// to get the fastest response time possible we don't wanna use any lerp with factor 1
if (stick_lerp_factor >= 1.0f)
{
pad->m_sticks[i].m_value = m_stick_val[i];
}
}
}
}
}
@ -515,8 +525,10 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
m_deadzone_x = p_profile->mouse_deadzone_x;
m_deadzone_y = p_profile->mouse_deadzone_y;
m_multi_x = p_profile->mouse_acceleration_x / 100;
m_multi_y = p_profile->mouse_acceleration_y / 100;
m_multi_x = (double)p_profile->mouse_acceleration_x / 100.0;
m_multi_y = (double)p_profile->mouse_acceleration_y / 100.0;
m_l_stick_lerp_factor = p_profile->l_stick_lerp_factor / 100.0f;
m_r_stick_lerp_factor = p_profile->r_stick_lerp_factor / 100.0f;
auto find_key = [&](const cfg::string& name)
{
@ -579,7 +591,6 @@ void keyboard_pad_handler::ThreadProc()
{
if (last_connection_status[i] == false)
{
//QThread::msleep(100); // Hack Simpsons. It calls a seemingly useless cellPadGetInfo at boot that would swallow the first CELL_PAD_STATUS_ASSIGN_CHANGES otherwise
bindings[i]->m_port_status |= CELL_PAD_STATUS_CONNECTED;
bindings[i]->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES;
last_connection_status[i] = true;
@ -590,32 +601,61 @@ void keyboard_pad_handler::ThreadProc()
static std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
now = std::chrono::steady_clock::now();
double elapsed_left = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_left).count() / 1000.0;
double elapsed_right = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_right).count() / 1000.0;
double elapsed_up = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_up).count() / 1000.0;
double elapsed_down = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_down).count() / 1000.0;
const double elapsed_left = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_left).count() / 1000.0;
const double elapsed_right = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_right).count() / 1000.0;
const double elapsed_up = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_up).count() / 1000.0;
const double elapsed_down = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_down).count() / 1000.0;
const double elapsed_stick = std::chrono::duration_cast<std::chrono::microseconds>(now - m_stick_time).count() / 1000.0;
const double mouse_interval = 30.0;
const double stick_interval = 10.0;
// roughly 1-2 frames to process the next mouse move
if (elapsed_left > 30.0)
if (elapsed_left > mouse_interval)
{
Key(mouse::move_left, 0);
m_last_mouse_move_left = now;
}
if (elapsed_right > 30.0)
if (elapsed_right > mouse_interval)
{
Key(mouse::move_right, 0);
m_last_mouse_move_right = now;
}
if (elapsed_up> 30.0)
if (elapsed_up > mouse_interval)
{
Key(mouse::move_up, 0);
m_last_mouse_move_up = now;
}
if (elapsed_down > 30.0)
if (elapsed_down > mouse_interval)
{
Key(mouse::move_down, 0);
m_last_mouse_move_down = now;
}
if (elapsed_stick > stick_interval)
{
for (int j = 0; j < static_cast<int>(bindings[i]->m_sticks.size()); j++)
{
const f32 stick_lerp_factor = (j < 2) ? m_l_stick_lerp_factor : m_r_stick_lerp_factor;
// we already applied the following values on keypress if we used factor 1
if (stick_lerp_factor < 1.0f)
{
const f32 v0 = (f32)bindings[i]->m_sticks[j].m_value;
const f32 v1 = (f32)m_stick_val[j];
// linear interpolation from the current stick value v0 to the desired stick value v1
f32 res = lerp(v0, v1, stick_lerp_factor);
// round to the correct direction to prevent sticky sticks on small factors
res = (v0 <= v1) ? std::ceil(res) : std::floor(res);
bindings[i]->m_sticks[j].m_value = (u16)res;
}
}
m_stick_time = now;
}
}
}
}

View File

@ -89,8 +89,14 @@ protected:
private:
QWindow* m_target = nullptr;
std::vector<std::shared_ptr<Pad>> bindings;
// Stick Movements
std::chrono::steady_clock::time_point m_stick_time;
f32 m_l_stick_lerp_factor = 1.0f;
f32 m_r_stick_lerp_factor = 1.0f;
u8 m_stick_min[4] = { 0, 0, 0, 0 };
u8 m_stick_max[4] = { 128, 128, 128, 128 };
u8 m_stick_val[4] = { 128, 128, 128, 128 };
// Mouse Movements
std::chrono::steady_clock::time_point m_last_mouse_move_left;

View File

@ -478,12 +478,21 @@ void pad_settings_dialog::ReloadButtons()
// Enable Mouse Acceleration
std::vector<std::string> mouse_accel_range_x = m_handler_cfg.mouse_acceleration_x.to_list();
ui->mouse_accel_x->setRange(std::stod(mouse_accel_range_x.front()) / (double)100, std::stod(mouse_accel_range_x.back()) / (double)100);
ui->mouse_accel_x->setValue((double)m_handler_cfg.mouse_acceleration_x / (double)100);
ui->mouse_accel_x->setRange(std::stod(mouse_accel_range_x.front()) / 100.0, std::stod(mouse_accel_range_x.back()) / 100.0);
ui->mouse_accel_x->setValue((double)m_handler_cfg.mouse_acceleration_x / 100.0);
std::vector<std::string> mouse_accel_range_y = m_handler_cfg.mouse_acceleration_y.to_list();
ui->mouse_accel_y->setRange(std::stod(mouse_accel_range_y.front()) / (double)100, std::stod(mouse_accel_range_y.back()) / (double)100);
ui->mouse_accel_y->setValue((double)m_handler_cfg.mouse_acceleration_y / (double)100);
ui->mouse_accel_y->setRange(std::stod(mouse_accel_range_y.front()) / 100.0, std::stod(mouse_accel_range_y.back()) / 100.0);
ui->mouse_accel_y->setValue((double)m_handler_cfg.mouse_acceleration_y / 100.0);
// Enable Stick Lerp Factors
std::vector<std::string> left_stick_lerp_range = m_handler_cfg.l_stick_lerp_factor.to_list();
ui->left_stick_lerp->setRange(std::stod(left_stick_lerp_range.front()) / 100.0, std::stod(left_stick_lerp_range.back()) / 100.0);
ui->left_stick_lerp->setValue((double)m_handler_cfg.l_stick_lerp_factor / 100.0);
std::vector<std::string> right_stick_lerp_range = m_handler_cfg.r_stick_lerp_factor.to_list();
ui->right_stick_lerp->setRange(std::stod(right_stick_lerp_range.front()) / 100.0, std::stod(right_stick_lerp_range.back()) / 100.0);
ui->right_stick_lerp->setValue((double)m_handler_cfg.r_stick_lerp_factor / 100.0);
// Enable Vibration Checkboxes
m_enable_rumble = m_handler->has_rumble();
@ -726,6 +735,9 @@ void pad_settings_dialog::SwitchButtons(bool is_enabled)
ui->gb_vibration->setEnabled(is_enabled && m_enable_rumble);
ui->gb_sticks->setEnabled(is_enabled && m_enable_deadzones);
ui->gb_triggers->setEnabled(is_enabled && m_enable_deadzones);
ui->gb_mouse_accel->setEnabled(is_enabled && m_handler->m_type == pad_handler::keyboard);
ui->gb_mouse_dz->setEnabled(is_enabled && m_handler->m_type == pad_handler::keyboard);
ui->gb_stick_lerp->setEnabled(is_enabled && m_handler->m_type == pad_handler::keyboard);
for (int i = button_ids::id_pad_begin + 1; i < button_ids::id_pad_end; i++)
{
@ -847,7 +859,8 @@ void pad_settings_dialog::ChangeInputType()
const auto device_list = m_handler->ListDevices();
// change our contextual widgets
ui->stackedWidget->setCurrentIndex((m_handler->m_type == pad_handler::keyboard) ? 1 : 0);
ui->left_stack->setCurrentIndex((m_handler->m_type == pad_handler::keyboard) ? 1 : 0);
ui->right_stack->setCurrentIndex((m_handler->m_type == pad_handler::keyboard) ? 1 : 0);
// Refill the device combobox with currently available devices
switch (m_handler->m_type)
@ -1045,6 +1058,8 @@ void pad_settings_dialog::SaveProfile()
m_handler_cfg.mouse_acceleration_y.set(ui->mouse_accel_y->value() * 100);
m_handler_cfg.mouse_deadzone_x.set(ui->mouse_dz_x->value());
m_handler_cfg.mouse_deadzone_y.set(ui->mouse_dz_y->value());
m_handler_cfg.l_stick_lerp_factor.set(ui->left_stick_lerp->value() * 100);
m_handler_cfg.r_stick_lerp_factor.set(ui->right_stick_lerp->value() * 100);
}
m_handler_cfg.save();

View File

@ -626,7 +626,7 @@
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<widget class="QStackedWidget" name="left_stack">
<property name="lineWidth">
<number>0</number>
</property>
@ -786,6 +786,18 @@
<string>Mouse Acceleration</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_27">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="mouse_accel_x_label">
<property name="text">
@ -794,7 +806,11 @@
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="mouse_accel_x"/>
<widget class="QDoubleSpinBox" name="mouse_accel_x">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_25">
@ -820,7 +836,11 @@
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="mouse_accel_y"/>
<widget class="QDoubleSpinBox" name="mouse_accel_y">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_26">
@ -847,6 +867,18 @@
<string>Mouse Deadzone</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_26">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="mouse_dz_x_label">
<property name="text">
@ -902,6 +934,22 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_445">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
@ -1933,60 +1981,202 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_sticks">
<property name="title">
<string>Analog Deadzones</string>
<widget class="QStackedWidget" name="right_stack">
<property name="currentIndex">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_22">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="gb_stick_left">
<item>
<widget class="QSlider" name="slider_stick_left">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QWidget" name="stick_page">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="gb_sticks">
<property name="title">
<string>Analog Deadzones</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_22">
<property name="leftMargin">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="preview_stick_left">
<property name="text">
<string/>
<property name="topMargin">
<number>5</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="gb_stick_right">
<item>
<widget class="QSlider" name="slider_stick_right">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="rightMargin">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="preview_stick_right">
<property name="text">
<string/>
<property name="bottomMargin">
<number>5</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<item>
<layout class="QVBoxLayout" name="gb_stick_left">
<item>
<widget class="QSlider" name="slider_stick_left">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="preview_stick_left">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="gb_stick_right">
<item>
<widget class="QSlider" name="slider_stick_right">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="preview_stick_right">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="smooth_page">
<layout class="QVBoxLayout" name="verticalLayout_14">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="gb_stick_lerp">
<property name="title">
<string>Stick Interpolation</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_28">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="left_stick_lerp_label">
<property name="text">
<string>Left</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="left_stick_lerp">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_27">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="right_stick_lerp_label">
<property name="text">
<string>Right</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="right_stick_lerp">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_28">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_444">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>

View File

@ -270,7 +270,7 @@
<item>
<layout class="QVBoxLayout" name="coreTabRightLayout" stretch="1,0">
<item>
<widget class="QGroupBox" name="groupBox_28">
<widget class="QGroupBox" name="gb_libs">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -349,7 +349,7 @@
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_41">
<widget class="QGroupBox" name="gb_description">
<property name="title">
<string>Description</string>
</property>
@ -388,7 +388,7 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QGroupBox" name="groupBox_26">
<widget class="QGroupBox" name="gb_renderer">
<property name="title">
<string>Renderer</string>
</property>
@ -400,7 +400,7 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_42">
<widget class="QGroupBox" name="gb_graphicsAdapter">
<property name="title">
<string>Graphics Device</string>
</property>
@ -414,7 +414,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,1">
<item>
<widget class="QGroupBox" name="groupBox_44">
<widget class="QGroupBox" name="gb_aspectRatio">
<property name="title">
<string>Aspect Ratio</string>
</property>
@ -426,7 +426,7 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_45">
<widget class="QGroupBox" name="gb_frameLimit">
<property name="title">
<string>Framelimit</string>
</property>
@ -1155,7 +1155,7 @@
<property name="title">
<string>Disk cache</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_73">
<layout class="QVBoxLayout" name="verticalLayout_75">
<item>
<widget class="QCheckBox" name="enableCacheClearing">
<property name="text">
@ -2275,7 +2275,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="buttonLayout">
<item alignment="Qt::AlignLeft">
<widget class="QPushButton" name="okButton">
<property name="text">