mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-08 00:30:22 +08:00
... button
This commit is contained in:
parent
a9b587b5e7
commit
4d6dc231c7
@ -1,5 +1,6 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
|
# pylint: disable=too-many-lines
|
||||||
"""Settings UI functionality related to gamepads."""
|
"""Settings UI functionality related to gamepads."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@ -12,7 +13,9 @@ import bauiv1 as bui
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
from bauiv1lib.popup import PopupWindow
|
||||||
|
|
||||||
|
from bauiv1lib.popup import PopupMenuWindow
|
||||||
|
|
||||||
class GamepadSettingsWindow(bui.Window):
|
class GamepadSettingsWindow(bui.Window):
|
||||||
"""Window for configuring a gamepad."""
|
"""Window for configuring a gamepad."""
|
||||||
@ -43,7 +46,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
self._is_main_menu = is_main_menu
|
self._is_main_menu = is_main_menu
|
||||||
self._displayname = self._name
|
self._displayname = self._name
|
||||||
self._width = 700 if self._is_secondary else 730
|
self._width = 700 if self._is_secondary else 730
|
||||||
self._height = 440 if self._is_secondary else 490
|
self._height = 440 if self._is_secondary else 450
|
||||||
self._spacing = 40
|
self._spacing = 40
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
@ -136,7 +139,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
if val != -1:
|
if val != -1:
|
||||||
self._settings[button] = val
|
self._settings[button] = val
|
||||||
|
|
||||||
def _rebuild_ui(self, reset: bool = False) -> None:
|
def _rebuild_ui(self, is_reset: bool = False) -> None:
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
|
|
||||||
@ -169,7 +172,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
else:
|
else:
|
||||||
cancel_button = bui.buttonwidget(
|
cancel_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(51, self._height - 115),
|
position=(51, self._height - 65),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
size=(160, 60),
|
size=(160, 60),
|
||||||
label=bui.Lstr(resource='cancelText'),
|
label=bui.Lstr(resource='cancelText'),
|
||||||
@ -179,29 +182,12 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, cancel_button=cancel_button
|
edit=self._root_widget, cancel_button=cancel_button
|
||||||
)
|
)
|
||||||
reset_button: bui.Widget | None
|
|
||||||
if not self._is_secondary:
|
|
||||||
reset_button = bui.buttonwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
autoselect=True,
|
|
||||||
position=((self._width / 2) - 80, self._height - 115),
|
|
||||||
size=(180, 60),
|
|
||||||
label=bui.Lstr(resource='settingsWindowAdvanced.resetText'),
|
|
||||||
scale=0.9,
|
|
||||||
text_scale=0.9,
|
|
||||||
color=(0.4, 0.4, 0.9),
|
|
||||||
textcolor=(1.0, 1.0, 1.0),
|
|
||||||
on_activate_call=self._reset,
|
|
||||||
)
|
|
||||||
if reset:
|
|
||||||
bui.containerwidget(
|
|
||||||
edit=self._root_widget, selected_child=reset_button
|
|
||||||
)
|
|
||||||
save_button: bui.Widget | None
|
save_button: bui.Widget | None
|
||||||
if not self._is_secondary:
|
if not self._is_secondary:
|
||||||
save_button = bui.buttonwidget(
|
save_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(self._width - 195, self._height - 115),
|
position=(self._width - 195, self._height - 65),
|
||||||
size=(180, 60),
|
size=(180, 60),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label=bui.Lstr(resource='saveText'),
|
label=bui.Lstr(resource='saveText'),
|
||||||
@ -218,7 +204,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
v = self._height - 59
|
v = self._height - 59
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(0, v + 10),
|
position=(0, v + 5),
|
||||||
size=(self._width, 25),
|
size=(self._width, 25),
|
||||||
text=bui.Lstr(resource=self._r + '.titleText'),
|
text=bui.Lstr(resource=self._r + '.titleText'),
|
||||||
color=bui.app.ui_v1.title_color,
|
color=bui.app.ui_v1.title_color,
|
||||||
@ -226,11 +212,11 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
)
|
)
|
||||||
v -= 95
|
v -= 48
|
||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(0, v - 5),
|
position=(0, v + 3),
|
||||||
size=(self._width, 25),
|
size=(self._width, 25),
|
||||||
text=self._name,
|
text=self._name,
|
||||||
color=bui.app.ui_v1.infotextcolor,
|
color=bui.app.ui_v1.infotextcolor,
|
||||||
@ -242,7 +228,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(50, v + 5),
|
position=(50, v + 10),
|
||||||
size=(self._width - 100, 30),
|
size=(self._width - 100, 30),
|
||||||
text=bui.Lstr(resource=self._r + '.appliesToAllText'),
|
text=bui.Lstr(resource=self._r + '.appliesToAllText'),
|
||||||
maxwidth=330,
|
maxwidth=330,
|
||||||
@ -384,40 +370,27 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
scale=1.0,
|
scale=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
self._advanced_button = bui.buttonwidget(
|
self._more_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label=bui.Lstr(resource=self._r + '.advancedText'),
|
label='...',
|
||||||
text_scale=0.9,
|
text_scale=0.9,
|
||||||
color=(0.45, 0.4, 0.5),
|
color=(0.45, 0.4, 0.5),
|
||||||
textcolor=(0.65, 0.6, 0.7),
|
textcolor=(0.65, 0.6, 0.7),
|
||||||
position=(self._width - 300, 30),
|
position=(self._width - 300, 30),
|
||||||
size=(130, 40),
|
size=(130, 40),
|
||||||
on_activate_call=self._do_advanced,
|
on_activate_call=self._do_more,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bui.widget(
|
if cancel_button is not None and save_button is not None:
|
||||||
edit=cancel_button,
|
bui.widget(edit=cancel_button, right_widget=save_button)
|
||||||
right_widget=reset_button
|
bui.widget(edit=save_button, left_widget=cancel_button)
|
||||||
if reset_button
|
if is_reset:
|
||||||
else save_button
|
bui.containerwidget(
|
||||||
if save_button
|
edit=self._root_widget,
|
||||||
else None,
|
selected_child=self._more_button,
|
||||||
)
|
)
|
||||||
bui.widget(
|
|
||||||
edit=reset_button,
|
|
||||||
left_widget=cancel_button if cancel_button else None,
|
|
||||||
right_widget=save_button if save_button else None,
|
|
||||||
)
|
|
||||||
bui.widget(
|
|
||||||
edit=save_button,
|
|
||||||
left_widget=reset_button
|
|
||||||
if reset_button
|
|
||||||
else cancel_button
|
|
||||||
if cancel_button
|
|
||||||
else None,
|
|
||||||
)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception('Error wiring up gamepad config window.')
|
logging.exception('Error wiring up gamepad config window.')
|
||||||
|
|
||||||
@ -427,7 +400,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
def get_advanced_button(self) -> bui.Widget:
|
def get_advanced_button(self) -> bui.Widget:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
return self._advanced_button
|
return self._more_button
|
||||||
|
|
||||||
def get_is_secondary(self) -> bool:
|
def get_is_secondary(self) -> bool:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
@ -849,19 +822,71 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
ConfirmWindow(
|
ConfirmWindow(
|
||||||
# TODO: Implement a translation string for this!
|
# TODO: Implement a translation string for this!
|
||||||
'Are you sure you want to reset your button mapping?\n'
|
'Are you sure you want to reset your button mapping?\n'
|
||||||
'(This will include your advanced settings)',
|
'This will also reset your advanced mappings\n'
|
||||||
|
'and secondary controller button mappings.',
|
||||||
self._do_reset,
|
self._do_reset,
|
||||||
width=480,
|
width=490,
|
||||||
height=110,
|
height=150,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_reset(self) -> None:
|
def _do_reset(self) -> None:
|
||||||
"""Resets the input's mapping settings."""
|
"""Resets the input's mapping settings."""
|
||||||
|
from babase import InputDeviceNotFoundError
|
||||||
self._settings: dict[str, int] = {}
|
self._settings: dict[str, int] = {}
|
||||||
self._get_config_mapping(default=True)
|
# Unplugging the controller while performing a
|
||||||
self._rebuild_ui(reset=True)
|
# mapping reset makes things go bonkers a little.
|
||||||
|
try:
|
||||||
|
self._get_config_mapping(default=True)
|
||||||
|
except InputDeviceNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._rebuild_ui(is_reset=True)
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
|
|
||||||
|
def _do_more(self) -> None:
|
||||||
|
"""Show a burger menu with extra settings."""
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
choices: list[str] = [
|
||||||
|
'advanced',
|
||||||
|
'reset',
|
||||||
|
]
|
||||||
|
choices_display: list[bui.Lstr] = [
|
||||||
|
bui.Lstr(resource=self._r + '.advancedText'),
|
||||||
|
bui.Lstr(resource='settingsWindowAdvanced.resetText'),
|
||||||
|
]
|
||||||
|
|
||||||
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
PopupMenuWindow(
|
||||||
|
position=self._more_button.get_screen_space_center(),
|
||||||
|
scale=(
|
||||||
|
2.3
|
||||||
|
if uiscale is bui.UIScale.SMALL
|
||||||
|
else 1.65
|
||||||
|
if uiscale is bui.UIScale.MEDIUM
|
||||||
|
else 1.23
|
||||||
|
),
|
||||||
|
width=150,
|
||||||
|
choices=choices,
|
||||||
|
choices_display=choices_display,
|
||||||
|
current_choice='advanced',
|
||||||
|
delegate=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
def popup_menu_selected_choice(
|
||||||
|
self, popup_window: PopupMenuWindow, choice: str
|
||||||
|
) -> None:
|
||||||
|
"""Called when a choice is selected in the popup."""
|
||||||
|
del popup_window # unused
|
||||||
|
if choice == 'reset':
|
||||||
|
self._reset()
|
||||||
|
elif choice == 'advanced':
|
||||||
|
self._do_advanced()
|
||||||
|
else:
|
||||||
|
print(f'invalid choice: {choice}')
|
||||||
|
|
||||||
|
def popup_menu_closing(self, popup_window: PopupWindow) -> None:
|
||||||
|
"""Called when the popup is closing."""
|
||||||
|
|
||||||
def _save(self) -> None:
|
def _save(self) -> None:
|
||||||
classic = bui.app.classic
|
classic = bui.app.classic
|
||||||
assert classic is not None
|
assert classic is not None
|
||||||
|
|||||||
@ -11,7 +11,9 @@ import bascenev1 as bs
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from bauiv1lib.popup import PopupWindow
|
||||||
|
|
||||||
|
from bauiv1lib.popup import PopupMenuWindow
|
||||||
|
|
||||||
class ConfigKeyboardWindow(bui.Window):
|
class ConfigKeyboardWindow(bui.Window):
|
||||||
"""Window for configuring keyboards."""
|
"""Window for configuring keyboards."""
|
||||||
@ -27,10 +29,9 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
self._displayname = bui.Lstr(translate=('inputDeviceNames', dname_raw))
|
self._displayname = bui.Lstr(translate=('inputDeviceNames', dname_raw))
|
||||||
self._width = 700
|
self._width = 700
|
||||||
if self._unique_id != '#1':
|
if self._unique_id != '#1':
|
||||||
self._height = 490
|
self._height = 480
|
||||||
else:
|
else:
|
||||||
self._height = 375
|
self._height = 375
|
||||||
self._height += 45
|
|
||||||
self._spacing = 40
|
self._spacing = 40
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
@ -73,7 +74,7 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
self._input, button, default
|
self._input, button, default
|
||||||
)
|
)
|
||||||
|
|
||||||
def _rebuild_ui(self, reset: bool = False) -> None:
|
def _rebuild_ui(self, is_reset: bool = False) -> None:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
for widget in self._root_widget.get_children():
|
for widget in self._root_widget.get_children():
|
||||||
@ -83,32 +84,16 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
cancel_button = bui.buttonwidget(
|
cancel_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
position=(38, self._height - 115 - b_off),
|
position=(38, self._height - 85),
|
||||||
size=(170, 60),
|
size=(170, 60),
|
||||||
label=bui.Lstr(resource='cancelText'),
|
label=bui.Lstr(resource='cancelText'),
|
||||||
scale=0.9,
|
scale=0.9,
|
||||||
on_activate_call=self._cancel,
|
on_activate_call=self._cancel,
|
||||||
)
|
)
|
||||||
reset_button = bui.buttonwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
autoselect=True,
|
|
||||||
position=((self._width / 2) - 80, self._height - 115 - b_off),
|
|
||||||
size=(180, 60),
|
|
||||||
label=bui.Lstr(resource='settingsWindowAdvanced.resetText'),
|
|
||||||
scale=0.9,
|
|
||||||
text_scale=0.9,
|
|
||||||
color=(0.4, 0.4, 0.9),
|
|
||||||
textcolor=(1.0, 1.0, 1.0),
|
|
||||||
on_activate_call=self._reset,
|
|
||||||
)
|
|
||||||
if reset:
|
|
||||||
bui.containerwidget(
|
|
||||||
edit=self._root_widget, selected_child=reset_button
|
|
||||||
)
|
|
||||||
save_button = bui.buttonwidget(
|
save_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
position=(self._width - 190, self._height - 115 - b_off),
|
position=(self._width - 190, self._height - 85),
|
||||||
size=(180, 60),
|
size=(180, 60),
|
||||||
label=bui.Lstr(resource='saveText'),
|
label=bui.Lstr(resource='saveText'),
|
||||||
scale=0.9,
|
scale=0.9,
|
||||||
@ -121,19 +106,10 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
start_button=save_button,
|
start_button=save_button,
|
||||||
)
|
)
|
||||||
|
|
||||||
bui.widget(edit=cancel_button, right_widget=reset_button)
|
|
||||||
bui.widget(
|
|
||||||
edit=reset_button,
|
|
||||||
left_widget=cancel_button,
|
|
||||||
right_widget=save_button,
|
|
||||||
)
|
|
||||||
bui.widget(edit=save_button, left_widget=reset_button)
|
|
||||||
|
|
||||||
v = self._height - 74.0
|
v = self._height - 74.0
|
||||||
t_off = 0 if self._unique_id != '#1' else -10
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(self._width * 0.5, v + 41 + t_off),
|
position=(self._width * 0.5, v + 15),
|
||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
text=bui.Lstr(
|
text=bui.Lstr(
|
||||||
resource=self._r + '.configuringText',
|
resource=self._r + '.configuringText',
|
||||||
@ -143,12 +119,12 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
maxwidth=270,
|
maxwidth=270,
|
||||||
scale=0.99,
|
scale=0.83,
|
||||||
)
|
)
|
||||||
v -= 20
|
v -= 20
|
||||||
|
|
||||||
if self._unique_id != '#1':
|
if self._unique_id != '#1':
|
||||||
v -= 60
|
v -= 20
|
||||||
v -= self._spacing
|
v -= self._spacing
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
@ -166,9 +142,9 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
v -= 10
|
v -= 10
|
||||||
v -= self._spacing * 2.2
|
v -= self._spacing * 2.2
|
||||||
v += 25
|
v += 25
|
||||||
v -= 45 if self._unique_id != '#1' else 86
|
v -= 42
|
||||||
h_offs = 160
|
h_offs = 160
|
||||||
dist = 68
|
dist = 70
|
||||||
d_color = (0.4, 0.4, 0.8)
|
d_color = (0.4, 0.4, 0.8)
|
||||||
self._capture_button(
|
self._capture_button(
|
||||||
pos=(h_offs, v + 0.95 * dist),
|
pos=(h_offs, v + 0.95 * dist),
|
||||||
@ -239,6 +215,24 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
scale=1.0,
|
scale=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._more_button = bui.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
autoselect=True,
|
||||||
|
label='...',
|
||||||
|
text_scale=0.9,
|
||||||
|
color=(0.45, 0.4, 0.5),
|
||||||
|
textcolor=(0.65, 0.6, 0.7),
|
||||||
|
position=(self._width * 0.5 - 65, 30),
|
||||||
|
size=(130, 40),
|
||||||
|
on_activate_call=self._do_more,
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_reset:
|
||||||
|
bui.containerwidget(
|
||||||
|
edit=self._root_widget,
|
||||||
|
selected_child=self._more_button,
|
||||||
|
)
|
||||||
|
|
||||||
def _pretty_button_name(self, button_name: str) -> bui.Lstr:
|
def _pretty_button_name(self, button_name: str) -> bui.Lstr:
|
||||||
button_id = self._settings[button_name]
|
button_id = self._settings[button_name]
|
||||||
if button_id == -1:
|
if button_id == -1:
|
||||||
@ -324,9 +318,49 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
"""Resets the input's mapping settings."""
|
"""Resets the input's mapping settings."""
|
||||||
self._settings: dict[str, int] = {}
|
self._settings: dict[str, int] = {}
|
||||||
self._get_config_mapping(default=True)
|
self._get_config_mapping(default=True)
|
||||||
self._rebuild_ui(reset=True)
|
self._rebuild_ui(is_reset=True)
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
|
|
||||||
|
def _do_more(self) -> None:
|
||||||
|
"""Show a burger menu with extra settings."""
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
choices: list[str] = [
|
||||||
|
'reset',
|
||||||
|
]
|
||||||
|
choices_display: list[bui.Lstr] = [
|
||||||
|
bui.Lstr(resource='settingsWindowAdvanced.resetText'),
|
||||||
|
]
|
||||||
|
|
||||||
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
PopupMenuWindow(
|
||||||
|
position=self._more_button.get_screen_space_center(),
|
||||||
|
scale=(
|
||||||
|
2.3
|
||||||
|
if uiscale is bui.UIScale.SMALL
|
||||||
|
else 1.65
|
||||||
|
if uiscale is bui.UIScale.MEDIUM
|
||||||
|
else 1.23
|
||||||
|
),
|
||||||
|
width=150,
|
||||||
|
choices=choices,
|
||||||
|
choices_display=choices_display,
|
||||||
|
current_choice='reset',
|
||||||
|
delegate=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
def popup_menu_selected_choice(
|
||||||
|
self, popup_window: PopupMenuWindow, choice: str
|
||||||
|
) -> None:
|
||||||
|
"""Called when a choice is selected in the popup."""
|
||||||
|
del popup_window # unused
|
||||||
|
if choice == 'reset':
|
||||||
|
self._reset()
|
||||||
|
else:
|
||||||
|
print(f'invalid choice: {choice}')
|
||||||
|
|
||||||
|
def popup_menu_closing(self, popup_window: PopupWindow) -> None:
|
||||||
|
"""Called when the popup is closing."""
|
||||||
|
|
||||||
def _save(self) -> None:
|
def _save(self) -> None:
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user