cd1743cb92
The default widgets only implement the settings for the `default` "app_name" The game specific widgets sub-class the default widgets and implement whatever they additionally need locally. Remove multiple calls to save config and save when the game settings gets hidden.
334 lines
13 KiB
Python
334 lines
13 KiB
Python
from abc import abstractmethod
|
|
from enum import Enum, IntEnum
|
|
from logging import getLogger
|
|
from typing import List, Dict, Tuple, Any, Union
|
|
|
|
from PyQt5.QtCore import QCoreApplication, pyqtSignal
|
|
from PyQt5.QtGui import QIntValidator, QDoubleValidator, QShowEvent
|
|
from PyQt5.QtWidgets import QGroupBox, QCheckBox, QLineEdit, QComboBox
|
|
|
|
from rare.shared import LegendaryCoreSingleton
|
|
from rare.ui.components.tabs.settings.widgets.overlay import Ui_OverlaySettings
|
|
from rare.utils import config_helper as config
|
|
|
|
logger = getLogger("GameOverlays")
|
|
|
|
|
|
class OverlayLineEdit(QLineEdit):
|
|
def __init__(self, parent=None):
|
|
super(OverlayLineEdit, self).__init__(parent=parent)
|
|
self.valueChanged = self.textChanged
|
|
self.setValue = self.setText
|
|
|
|
def setDefault(self):
|
|
self.setText("")
|
|
|
|
def getValue(self):
|
|
return self.text()
|
|
|
|
|
|
class OverlayComboBox(QComboBox):
|
|
def __init__(self, parent=None):
|
|
super(OverlayComboBox, self).__init__(parent=parent)
|
|
self.valueChanged = self.currentIndexChanged
|
|
self.getValue = self.currentText
|
|
self.setValue = self.setCurrentText
|
|
|
|
def setDefault(self):
|
|
self.setCurrentIndex(0)
|
|
|
|
|
|
class CustomOption:
|
|
option: str
|
|
widget: Union[OverlayLineEdit, OverlayComboBox]
|
|
|
|
@classmethod
|
|
def string_input(cls, option: str, placeholder: str):
|
|
tmp = cls()
|
|
tmp.option = option
|
|
tmp.widget = OverlayLineEdit()
|
|
tmp.widget.setPlaceholderText(placeholder)
|
|
return tmp
|
|
|
|
@classmethod
|
|
def number_input(cls, option: str, placeholder: Any, is_float: bool = False):
|
|
tmp = cls()
|
|
tmp.option = option
|
|
tmp.widget = OverlayLineEdit()
|
|
tmp.widget.setPlaceholderText(str(placeholder))
|
|
validator = QDoubleValidator() if is_float else QIntValidator()
|
|
tmp.widget.setValidator(validator)
|
|
return tmp
|
|
|
|
@classmethod
|
|
def select_input(cls, option: str, values: List[str]):
|
|
"""options: default value in options[0]"""
|
|
tmp = cls()
|
|
tmp.option = option
|
|
tmp.widget = OverlayComboBox()
|
|
tmp.widget.addItems(values)
|
|
return tmp
|
|
|
|
|
|
class ActivationStates(IntEnum):
|
|
DEFAULT = -1
|
|
HIDDEN = 0
|
|
ENABLED = 1
|
|
|
|
|
|
class OverlaySettings(QGroupBox):
|
|
# str: option key
|
|
environ_changed = pyqtSignal(str)
|
|
|
|
def __init__(self, parent=None):
|
|
super(OverlaySettings, self).__init__(parent=parent)
|
|
self.ui = Ui_OverlaySettings()
|
|
self.ui.setupUi(self)
|
|
|
|
self.core = LegendaryCoreSingleton()
|
|
self.envvar_name: str = None
|
|
self.force_disabled: str = None
|
|
self.app_name: str = "default"
|
|
self.checkboxes: Dict[str, QCheckBox] = {}
|
|
self.values: Dict[str, Union[OverlayLineEdit, OverlayComboBox]] = {}
|
|
|
|
self.ui.options_group.setTitle(self.tr("Custom options"))
|
|
self.ui.show_overlay_combo.currentIndexChanged.connect(self.update_settings)
|
|
|
|
def setupWidget(
|
|
self,
|
|
checkbox_map: List[Tuple[str, str]],
|
|
custom_map: List[Tuple[CustomOption, str]],
|
|
envvar_name: str,
|
|
force_disabled: str,
|
|
):
|
|
self.envvar_name = envvar_name
|
|
self.force_disabled = force_disabled
|
|
|
|
for i, (variable, text) in enumerate(checkbox_map):
|
|
checkbox = QCheckBox(text)
|
|
self.ui.options_grid.addWidget(checkbox, i // 4, i % 4)
|
|
self.checkboxes[variable] = checkbox
|
|
checkbox.stateChanged.connect(self.update_settings)
|
|
|
|
for option, text in custom_map:
|
|
widget = option.widget
|
|
self.ui.options_form.addRow(text, widget)
|
|
self.values[option.option] = widget
|
|
widget.valueChanged.connect(self.update_settings)
|
|
|
|
@abstractmethod
|
|
def set_activation_state(self, state: ActivationStates):
|
|
raise NotImplemented
|
|
|
|
def update_settings(self):
|
|
|
|
if self.ui.show_overlay_combo.currentIndex() == 0:
|
|
# System default
|
|
config.remove_envvar(self.app_name, self.envvar_name)
|
|
self.environ_changed.emit(self.envvar_name)
|
|
self.ui.options_group.setDisabled(True)
|
|
self.set_activation_state(ActivationStates.DEFAULT)
|
|
return
|
|
|
|
elif self.ui.show_overlay_combo.currentIndex() == 1:
|
|
# hidden
|
|
config.set_envvar(self.app_name, self.envvar_name, self.force_disabled)
|
|
self.environ_changed.emit(self.envvar_name)
|
|
self.ui.options_group.setDisabled(True)
|
|
self.set_activation_state(ActivationStates.HIDDEN)
|
|
return
|
|
elif self.ui.show_overlay_combo.currentIndex() == 2:
|
|
self.ui.options_group.setDisabled(False)
|
|
# custom options
|
|
var_names = []
|
|
for var_name, cb in self.checkboxes.items():
|
|
if cb.isChecked():
|
|
var_names.append(var_name)
|
|
|
|
for var_name, widget in self.values.items():
|
|
text = widget.getValue()
|
|
if text not in ["default", ""]:
|
|
var_names.append(f"{var_name}={text}")
|
|
|
|
if not var_names:
|
|
list(self.checkboxes.values())[0].setChecked(True)
|
|
var_names.append(list(self.checkboxes.keys())[0])
|
|
|
|
config.set_envvar(self.app_name, self.envvar_name, ",".join(var_names))
|
|
self.environ_changed.emit(self.envvar_name)
|
|
self.set_activation_state(ActivationStates.ENABLED)
|
|
|
|
def showEvent(self, a0: QShowEvent):
|
|
if a0.spontaneous():
|
|
return super().showEvent(a0)
|
|
|
|
for checkbox in self.checkboxes.values():
|
|
checkbox.setChecked(False)
|
|
for widget in self.values.values():
|
|
widget.setDefault()
|
|
|
|
options = config.get_envvar(self.app_name, self.envvar_name, fallback=None)
|
|
if options is None:
|
|
logger.debug(f"No Overlay settings found {self.envvar_name}")
|
|
self.ui.show_overlay_combo.setCurrentIndex(0)
|
|
self.ui.options_group.setDisabled(True)
|
|
|
|
elif options == self.force_disabled:
|
|
# not visible
|
|
self.ui.options_group.setDisabled(True)
|
|
self.ui.show_overlay_combo.setCurrentIndex(1)
|
|
|
|
else:
|
|
self.ui.show_overlay_combo.setCurrentIndex(2)
|
|
for option in options.split(","):
|
|
try:
|
|
if "=" in option:
|
|
key, value = option.split("=")
|
|
if key in self.checkboxes.keys():
|
|
self.checkboxes[key].setChecked(False)
|
|
else:
|
|
self.values[key].setValue(value)
|
|
else:
|
|
self.checkboxes[option].setChecked(True)
|
|
except Exception as e:
|
|
logger.warning(e)
|
|
|
|
self.ui.options_group.setDisabled(False)
|
|
|
|
return super().showEvent(a0)
|
|
|
|
|
|
class DxvkSettings(OverlaySettings):
|
|
def __init__(self, parent=None):
|
|
super(DxvkSettings, self).__init__(parent=parent)
|
|
self.setTitle(self.tr("DXVK Settings"))
|
|
self.setupWidget(
|
|
[
|
|
("fps", QCoreApplication.translate("DxvkSettings", "FPS")),
|
|
("frametime", QCoreApplication.translate("DxvkSettings", "Frametime")),
|
|
("memory", QCoreApplication.translate("DxvkSettings", "Memory usage")),
|
|
("gpuload", QCoreApplication.translate("DxvkSettings", "GPU usage")),
|
|
("devinfo", QCoreApplication.translate("DxvkSettings", "Show Device info")),
|
|
("version", QCoreApplication.translate("DxvkSettings", "DXVK Version")),
|
|
("api", QCoreApplication.translate("DxvkSettings", "D3D feature level")),
|
|
("compiler", QCoreApplication.translate("DxvkSettings", "Compiler activity")),
|
|
],
|
|
[
|
|
(
|
|
CustomOption.number_input("scale", 1, True),
|
|
QCoreApplication.translate("DxvkSettings", "Scale"),
|
|
)
|
|
],
|
|
"DXVK_HUD",
|
|
"0",
|
|
)
|
|
|
|
def set_activation_state(self, state: ActivationStates):
|
|
pass
|
|
|
|
|
|
mangohud_position = [
|
|
"default",
|
|
"top-left",
|
|
"top-right",
|
|
"middle-left",
|
|
"middle-right",
|
|
"bottom-left",
|
|
"bottom-right",
|
|
"top-center",
|
|
]
|
|
|
|
|
|
class MangoHudSettings(OverlaySettings):
|
|
def __init__(self, parent=None):
|
|
super(MangoHudSettings, self).__init__(parent=parent)
|
|
self.setTitle(self.tr("MangoHud Settings"))
|
|
self.setupWidget(
|
|
[
|
|
("fps", QCoreApplication.translate("MangoSettings", "FPS")),
|
|
("frame_timing", QCoreApplication.translate("MangoSettings", "Frame Time")),
|
|
("cpu_stats", QCoreApplication.translate("MangoSettings", "CPU Load")),
|
|
("gpu_stats", QCoreApplication.translate("MangoSettings", "GPU Load")),
|
|
("cpu_temp", QCoreApplication.translate("MangoSettings", "CPU Temp")),
|
|
("gpu_temp", QCoreApplication.translate("MangoSettings", "GPU Temp")),
|
|
("ram", QCoreApplication.translate("MangoSettings", "Memory usage")),
|
|
("vram", QCoreApplication.translate("MangoSettings", "VRAM usage")),
|
|
("time", QCoreApplication.translate("MangoSettings", "Local Time")),
|
|
("version", QCoreApplication.translate("MangoSettings", "MangoHud Version")),
|
|
("arch", QCoreApplication.translate("MangoSettings", "System architecture")),
|
|
("histogram", QCoreApplication.translate("MangoSettings", "FPS Graph")),
|
|
("gpu_name", QCoreApplication.translate("MangoSettings", "GPU Name")),
|
|
("cpu_power", QCoreApplication.translate("MangoSettings", "CPU Power consumption")),
|
|
("gpu_power", QCoreApplication.translate("MangoSettings", "GPU Power consumption")),
|
|
],
|
|
[
|
|
(
|
|
CustomOption.number_input("font_size", 24, is_float=False),
|
|
QCoreApplication.translate("MangoSettings", "Font size"),
|
|
),
|
|
(
|
|
CustomOption.select_input("position", mangohud_position),
|
|
QCoreApplication.translate("MangoSettings", "Position"),
|
|
),
|
|
],
|
|
"MANGOHUD_CONFIG",
|
|
"no_display",
|
|
)
|
|
|
|
def showEvent(self, a0: QShowEvent):
|
|
if a0.spontaneous():
|
|
return super().showEvent(a0)
|
|
|
|
# override
|
|
activated = bool(config.get_envvar(self.app_name, "MANGOHUD", None))
|
|
mango_config = config.get_envvar(self.app_name, "MANGOHUD_CONFIG", fallback="")
|
|
if not activated:
|
|
self.ui.options_group.setDisabled(True)
|
|
for i, checkbox in enumerate(list(self.checkboxes.values())):
|
|
checkbox.setChecked(i < 4)
|
|
self.ui.show_overlay_combo.setCurrentIndex(0)
|
|
return
|
|
self.ui.show_overlay_combo.setCurrentIndex(2)
|
|
self.ui.options_group.setDisabled(False)
|
|
for var_name, checkbox in list(self.checkboxes.items())[:4]:
|
|
checkbox.setChecked(f"{var_name}=0" not in mango_config)
|
|
|
|
return super().showEvent(a0)
|
|
|
|
def set_activation_state(self, state: IntEnum): # pylint: disable=E0202
|
|
if state == ActivationStates.DEFAULT:
|
|
config.remove_envvar(self.app_name, "MANGOHUD")
|
|
config.remove_envvar(self.app_name, "MANGOHUD_CONFIG")
|
|
self.ui.options_group.setDisabled(True)
|
|
|
|
elif state == ActivationStates.HIDDEN:
|
|
config.set_envvar(self.app_name, "MANGOHUD", "1")
|
|
config.set_envvar(self.app_name, "MANGOHUD_CONFIG", self.force_disabled)
|
|
|
|
elif state == ActivationStates.ENABLED:
|
|
|
|
mango_config = config.get_envvar(self.app_name, "MANGOHUD_CONFIG", fallback="")
|
|
|
|
split_config = mango_config.split(",")
|
|
for name in list(self.checkboxes.keys())[:4]:
|
|
if name in split_config:
|
|
split_config.remove(name)
|
|
mango_config = ",".join(split_config)
|
|
|
|
# first three are activated by default
|
|
for var_name, checkbox in list(self.checkboxes.items())[:4]:
|
|
if not checkbox.isChecked():
|
|
if mango_config:
|
|
mango_config += f",{var_name}=0"
|
|
else:
|
|
mango_config = f"{var_name}=0"
|
|
if mango_config:
|
|
config.set_envvar(self.app_name, "MANGOHUD", "1")
|
|
config.set_envvar(self.app_name, "MANGOHUD_CONFIG", mango_config)
|
|
else:
|
|
config.remove_envvar(self.app_name, "MANGOHUD")
|
|
config.remove_envvar(self.app_name, "MANGOHUD_CONFIG")
|
|
self.environ_changed.emit("MANGOHUD")
|
|
self.environ_changed.emit("MANGOHUD_CONFIG")
|