bauiv1lib.settings.controls
Provides a top level control settings window.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a top level control settings window.""" 4 5from __future__ import annotations 6 7from typing import override 8 9import bascenev1 as bs 10import bauiv1 as bui 11 12 13class ControlsSettingsWindow(bui.MainWindow): 14 """Top level control settings window.""" 15 16 def __init__( 17 self, 18 transition: str | None = 'in_right', 19 origin_widget: bui.Widget | None = None, 20 ): 21 # FIXME: should tidy up here. 22 # pylint: disable=too-many-statements 23 # pylint: disable=too-many-branches 24 # pylint: disable=too-many-locals 25 # pylint: disable=cyclic-import 26 27 self._have_selected_child = False 28 29 self._r = 'configControllersWindow' 30 uiscale = bui.app.ui_v1.uiscale 31 app = bui.app 32 assert app.classic is not None 33 34 spacing = 50.0 35 button_width = 350.0 36 width = 800.0 if uiscale is bui.UIScale.SMALL else 460.0 37 height = 300 if uiscale is bui.UIScale.SMALL else 130.0 38 39 yoffs = -60 if uiscale is bui.UIScale.SMALL else 0 40 space_height = spacing * 0.3 41 42 # FIXME: should create vis settings under platform or 43 # app-adapter to determine whether to show this stuff; not hard 44 # code it. 45 46 show_gamepads = False 47 platform = app.classic.platform 48 subplatform = app.classic.subplatform 49 non_vr_windows = platform == 'windows' and ( 50 subplatform != 'oculus' or not app.env.vr 51 ) 52 if platform in ('linux', 'android', 'mac') or non_vr_windows: 53 show_gamepads = True 54 height += spacing 55 56 show_touch = False 57 if bs.have_touchscreen_input(): 58 show_touch = True 59 height += spacing 60 61 show_space_1 = False 62 if show_gamepads or show_touch: 63 show_space_1 = True 64 height += space_height 65 66 show_keyboard = False 67 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 68 show_keyboard = True 69 height += spacing 70 show_keyboard_p2 = False if app.env.vr else show_keyboard 71 if show_keyboard_p2: 72 height += spacing 73 74 show_space_2 = False 75 if show_keyboard: 76 show_space_2 = True 77 height += space_height 78 79 if bool(True): 80 show_remote = True 81 height += spacing 82 else: 83 show_remote = False 84 85 # On windows (outside of oculus/vr), show an option to disable xinput. 86 show_xinput_toggle = False 87 if platform == 'windows' and not app.env.vr: 88 show_xinput_toggle = True 89 90 if show_xinput_toggle: 91 height += spacing 92 93 assert bui.app.classic is not None 94 smallscale = 1.7 95 super().__init__( 96 root_widget=bui.containerwidget( 97 size=(width, height), 98 stack_offset=( 99 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 100 ), 101 scale=( 102 smallscale 103 if uiscale is bui.UIScale.SMALL 104 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 105 ), 106 toolbar_visibility=( 107 'menu_minimal' 108 if uiscale is bui.UIScale.SMALL 109 else 'menu_full' 110 ), 111 ), 112 transition=transition, 113 origin_widget=origin_widget, 114 ) 115 116 self._back_button: bui.Widget | None 117 if uiscale is bui.UIScale.SMALL: 118 bui.containerwidget( 119 edit=self._root_widget, on_cancel_call=self.main_window_back 120 ) 121 self._back_button = None 122 else: 123 self._back_button = btn = bui.buttonwidget( 124 parent=self._root_widget, 125 position=(35, height - 60), 126 size=(140, 65), 127 scale=0.8, 128 text_scale=1.2, 129 autoselect=True, 130 label=bui.Lstr(resource='backText'), 131 button_type='back', 132 on_activate_call=self.main_window_back, 133 ) 134 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 135 bui.buttonwidget( 136 edit=btn, 137 button_type='backSmall', 138 size=(60, 60), 139 label=bui.charstr(bui.SpecialChar.BACK), 140 ) 141 142 # We need these vars to exist even if the buttons don't. 143 self._gamepads_button: bui.Widget | None = None 144 self._touch_button: bui.Widget | None = None 145 self._keyboard_button: bui.Widget | None = None 146 self._keyboard_2_button: bui.Widget | None = None 147 self._idevices_button: bui.Widget | None = None 148 149 bui.textwidget( 150 parent=self._root_widget, 151 position=( 152 0, 153 height + yoffs - (53 if uiscale is bui.UIScale.SMALL else 50), 154 ), 155 size=(width, 25), 156 text=bui.Lstr(resource=f'{self._r}.titleText'), 157 color=bui.app.ui_v1.title_color, 158 h_align='center', 159 v_align='top', 160 ) 161 162 v = height - (85 if uiscale is bui.UIScale.SMALL else 75) + yoffs 163 v -= spacing 164 165 if show_touch: 166 self._touch_button = btn = bui.buttonwidget( 167 parent=self._root_widget, 168 position=((width - button_width) / 2, v), 169 size=(button_width, 43), 170 autoselect=True, 171 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 172 on_activate_call=self._do_touchscreen, 173 ) 174 bui.widget( 175 edit=btn, 176 right_widget=bui.get_special_widget('squad_button'), 177 ) 178 if not self._have_selected_child: 179 bui.containerwidget( 180 edit=self._root_widget, selected_child=self._touch_button 181 ) 182 if self._back_button is not None: 183 bui.widget( 184 edit=self._back_button, down_widget=self._touch_button 185 ) 186 self._have_selected_child = True 187 v -= spacing 188 189 if show_gamepads: 190 self._gamepads_button = btn = bui.buttonwidget( 191 parent=self._root_widget, 192 position=((width - button_width) / 2 - 7, v), 193 size=(button_width, 43), 194 autoselect=True, 195 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 196 on_activate_call=self._do_gamepads, 197 ) 198 bui.widget( 199 edit=btn, 200 right_widget=bui.get_special_widget('squad_button'), 201 ) 202 if not self._have_selected_child: 203 bui.containerwidget( 204 edit=self._root_widget, selected_child=self._gamepads_button 205 ) 206 if self._back_button is not None: 207 bui.widget( 208 edit=self._back_button, 209 down_widget=self._gamepads_button, 210 ) 211 self._have_selected_child = True 212 v -= spacing 213 else: 214 self._gamepads_button = None 215 216 if show_space_1: 217 v -= space_height 218 219 if show_keyboard: 220 self._keyboard_button = btn = bui.buttonwidget( 221 parent=self._root_widget, 222 position=((width - button_width) / 2 - 5, v), 223 size=(button_width, 43), 224 autoselect=True, 225 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 226 on_activate_call=self._config_keyboard, 227 ) 228 bui.widget( 229 edit=self._keyboard_button, left_widget=self._keyboard_button 230 ) 231 bui.widget( 232 edit=btn, 233 right_widget=bui.get_special_widget('squad_button'), 234 ) 235 if not self._have_selected_child: 236 bui.containerwidget( 237 edit=self._root_widget, selected_child=self._keyboard_button 238 ) 239 if self._back_button is not None: 240 bui.widget( 241 edit=self._back_button, 242 down_widget=self._keyboard_button, 243 ) 244 self._have_selected_child = True 245 v -= spacing 246 if show_keyboard_p2: 247 self._keyboard_2_button = bui.buttonwidget( 248 parent=self._root_widget, 249 position=((width - button_width) / 2 - 3, v), 250 size=(button_width, 43), 251 autoselect=True, 252 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 253 on_activate_call=self._config_keyboard2, 254 ) 255 v -= spacing 256 bui.widget( 257 edit=self._keyboard_2_button, 258 left_widget=self._keyboard_2_button, 259 ) 260 if show_space_2: 261 v -= space_height 262 if show_remote: 263 self._idevices_button = btn = bui.buttonwidget( 264 parent=self._root_widget, 265 position=((width - button_width) / 2 - 5, v), 266 size=(button_width, 43), 267 autoselect=True, 268 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 269 on_activate_call=self._do_mobile_devices, 270 ) 271 bui.widget( 272 edit=self._idevices_button, left_widget=self._idevices_button 273 ) 274 bui.widget( 275 edit=btn, 276 right_widget=bui.get_special_widget('squad_button'), 277 ) 278 if not self._have_selected_child: 279 bui.containerwidget( 280 edit=self._root_widget, selected_child=self._idevices_button 281 ) 282 if self._back_button is not None: 283 bui.widget( 284 edit=self._back_button, 285 down_widget=self._idevices_button, 286 ) 287 self._have_selected_child = True 288 v -= spacing 289 290 if show_xinput_toggle: 291 292 def do_toggle(value: bool) -> None: 293 bui.screenmessage( 294 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 295 color=(1, 1, 0), 296 ) 297 bui.getsound('gunCocking').play() 298 bui.set_low_level_config_value('enablexinput', not value) 299 300 xinput_checkbox = bui.checkboxwidget( 301 parent=self._root_widget, 302 position=( 303 width * (0.35 if uiscale is bui.UIScale.SMALL else 0.25), 304 v + 3, 305 ), 306 size=(120, 30), 307 value=(not bui.get_low_level_config_value('enablexinput', 1)), 308 maxwidth=200, 309 on_value_change_call=do_toggle, 310 text=bui.Lstr(resource='disableXInputText'), 311 autoselect=True, 312 ) 313 bui.textwidget( 314 parent=self._root_widget, 315 position=(width * 0.5, v - 5), 316 size=(0, 0), 317 text=bui.Lstr(resource='disableXInputDescriptionText'), 318 scale=0.5, 319 h_align='center', 320 v_align='center', 321 color=bui.app.ui_v1.infotextcolor, 322 maxwidth=width * 0.8, 323 ) 324 bui.widget( 325 edit=xinput_checkbox, 326 left_widget=xinput_checkbox, 327 right_widget=xinput_checkbox, 328 ) 329 v -= spacing 330 331 self._restore_state() 332 333 @override 334 def get_main_window_state(self) -> bui.MainWindowState: 335 # Support recreating our window for back/refresh purposes. 336 cls = type(self) 337 return bui.BasicMainWindowState( 338 create_call=lambda transition, origin_widget: cls( 339 transition=transition, origin_widget=origin_widget 340 ) 341 ) 342 343 @override 344 def on_main_window_close(self) -> None: 345 self._save_state() 346 347 def _set_mac_controller_subsystem(self, val: str) -> None: 348 cfg = bui.app.config 349 cfg['Mac Controller Subsystem'] = val 350 cfg.apply_and_commit() 351 352 def _config_keyboard(self) -> None: 353 # pylint: disable=cyclic-import 354 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 355 356 # no-op if we're not in control. 357 if not self.main_window_has_control(): 358 return 359 360 self.main_window_replace( 361 ConfigKeyboardWindow(bs.getinputdevice('Keyboard', '#1')) 362 ) 363 364 def _config_keyboard2(self) -> None: 365 # pylint: disable=cyclic-import 366 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 367 368 # no-op if we're not in control. 369 if not self.main_window_has_control(): 370 return 371 372 self.main_window_replace( 373 ConfigKeyboardWindow(bs.getinputdevice('Keyboard', '#2')) 374 ) 375 376 def _do_mobile_devices(self) -> None: 377 # pylint: disable=cyclic-import 378 from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow 379 380 # no-op if we're not in control. 381 if not self.main_window_has_control(): 382 return 383 384 self.main_window_replace(RemoteAppSettingsWindow()) 385 386 def _do_gamepads(self) -> None: 387 # pylint: disable=cyclic-import 388 from bauiv1lib.settings.gamepadselect import GamepadSelectWindow 389 390 # no-op if we're not in control. 391 if not self.main_window_has_control(): 392 return 393 394 self.main_window_replace(GamepadSelectWindow()) 395 396 def _do_touchscreen(self) -> None: 397 # pylint: disable=cyclic-import 398 from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow 399 400 # no-op if we're not in control. 401 if not self.main_window_has_control(): 402 return 403 404 self.main_window_replace(TouchscreenSettingsWindow()) 405 406 def _save_state(self) -> None: 407 sel = self._root_widget.get_selected_child() 408 if sel == self._gamepads_button: 409 sel_name = 'GamePads' 410 elif sel == self._touch_button: 411 sel_name = 'Touch' 412 elif sel == self._keyboard_button: 413 sel_name = 'Keyboard' 414 elif sel == self._keyboard_2_button: 415 sel_name = 'Keyboard2' 416 elif sel == self._idevices_button: 417 sel_name = 'iDevices' 418 else: 419 sel_name = 'Back' 420 assert bui.app.classic is not None 421 bui.app.ui_v1.window_states[type(self)] = sel_name 422 423 def _restore_state(self) -> None: 424 assert bui.app.classic is not None 425 sel_name = bui.app.ui_v1.window_states.get(type(self)) 426 if sel_name == 'GamePads': 427 sel = self._gamepads_button 428 elif sel_name == 'Touch': 429 sel = self._touch_button 430 elif sel_name == 'Keyboard': 431 sel = self._keyboard_button 432 elif sel_name == 'Keyboard2': 433 sel = self._keyboard_2_button 434 elif sel_name == 'iDevices': 435 sel = self._idevices_button 436 elif sel_name == 'Back': 437 sel = self._back_button 438 else: 439 sel = ( 440 self._gamepads_button 441 if self._gamepads_button is not None 442 else self._back_button 443 ) 444 bui.containerwidget(edit=self._root_widget, selected_child=sel)
class
ControlsSettingsWindow(bauiv1._uitypes.MainWindow):
14class ControlsSettingsWindow(bui.MainWindow): 15 """Top level control settings window.""" 16 17 def __init__( 18 self, 19 transition: str | None = 'in_right', 20 origin_widget: bui.Widget | None = None, 21 ): 22 # FIXME: should tidy up here. 23 # pylint: disable=too-many-statements 24 # pylint: disable=too-many-branches 25 # pylint: disable=too-many-locals 26 # pylint: disable=cyclic-import 27 28 self._have_selected_child = False 29 30 self._r = 'configControllersWindow' 31 uiscale = bui.app.ui_v1.uiscale 32 app = bui.app 33 assert app.classic is not None 34 35 spacing = 50.0 36 button_width = 350.0 37 width = 800.0 if uiscale is bui.UIScale.SMALL else 460.0 38 height = 300 if uiscale is bui.UIScale.SMALL else 130.0 39 40 yoffs = -60 if uiscale is bui.UIScale.SMALL else 0 41 space_height = spacing * 0.3 42 43 # FIXME: should create vis settings under platform or 44 # app-adapter to determine whether to show this stuff; not hard 45 # code it. 46 47 show_gamepads = False 48 platform = app.classic.platform 49 subplatform = app.classic.subplatform 50 non_vr_windows = platform == 'windows' and ( 51 subplatform != 'oculus' or not app.env.vr 52 ) 53 if platform in ('linux', 'android', 'mac') or non_vr_windows: 54 show_gamepads = True 55 height += spacing 56 57 show_touch = False 58 if bs.have_touchscreen_input(): 59 show_touch = True 60 height += spacing 61 62 show_space_1 = False 63 if show_gamepads or show_touch: 64 show_space_1 = True 65 height += space_height 66 67 show_keyboard = False 68 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 69 show_keyboard = True 70 height += spacing 71 show_keyboard_p2 = False if app.env.vr else show_keyboard 72 if show_keyboard_p2: 73 height += spacing 74 75 show_space_2 = False 76 if show_keyboard: 77 show_space_2 = True 78 height += space_height 79 80 if bool(True): 81 show_remote = True 82 height += spacing 83 else: 84 show_remote = False 85 86 # On windows (outside of oculus/vr), show an option to disable xinput. 87 show_xinput_toggle = False 88 if platform == 'windows' and not app.env.vr: 89 show_xinput_toggle = True 90 91 if show_xinput_toggle: 92 height += spacing 93 94 assert bui.app.classic is not None 95 smallscale = 1.7 96 super().__init__( 97 root_widget=bui.containerwidget( 98 size=(width, height), 99 stack_offset=( 100 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 101 ), 102 scale=( 103 smallscale 104 if uiscale is bui.UIScale.SMALL 105 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 106 ), 107 toolbar_visibility=( 108 'menu_minimal' 109 if uiscale is bui.UIScale.SMALL 110 else 'menu_full' 111 ), 112 ), 113 transition=transition, 114 origin_widget=origin_widget, 115 ) 116 117 self._back_button: bui.Widget | None 118 if uiscale is bui.UIScale.SMALL: 119 bui.containerwidget( 120 edit=self._root_widget, on_cancel_call=self.main_window_back 121 ) 122 self._back_button = None 123 else: 124 self._back_button = btn = bui.buttonwidget( 125 parent=self._root_widget, 126 position=(35, height - 60), 127 size=(140, 65), 128 scale=0.8, 129 text_scale=1.2, 130 autoselect=True, 131 label=bui.Lstr(resource='backText'), 132 button_type='back', 133 on_activate_call=self.main_window_back, 134 ) 135 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 136 bui.buttonwidget( 137 edit=btn, 138 button_type='backSmall', 139 size=(60, 60), 140 label=bui.charstr(bui.SpecialChar.BACK), 141 ) 142 143 # We need these vars to exist even if the buttons don't. 144 self._gamepads_button: bui.Widget | None = None 145 self._touch_button: bui.Widget | None = None 146 self._keyboard_button: bui.Widget | None = None 147 self._keyboard_2_button: bui.Widget | None = None 148 self._idevices_button: bui.Widget | None = None 149 150 bui.textwidget( 151 parent=self._root_widget, 152 position=( 153 0, 154 height + yoffs - (53 if uiscale is bui.UIScale.SMALL else 50), 155 ), 156 size=(width, 25), 157 text=bui.Lstr(resource=f'{self._r}.titleText'), 158 color=bui.app.ui_v1.title_color, 159 h_align='center', 160 v_align='top', 161 ) 162 163 v = height - (85 if uiscale is bui.UIScale.SMALL else 75) + yoffs 164 v -= spacing 165 166 if show_touch: 167 self._touch_button = btn = bui.buttonwidget( 168 parent=self._root_widget, 169 position=((width - button_width) / 2, v), 170 size=(button_width, 43), 171 autoselect=True, 172 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 173 on_activate_call=self._do_touchscreen, 174 ) 175 bui.widget( 176 edit=btn, 177 right_widget=bui.get_special_widget('squad_button'), 178 ) 179 if not self._have_selected_child: 180 bui.containerwidget( 181 edit=self._root_widget, selected_child=self._touch_button 182 ) 183 if self._back_button is not None: 184 bui.widget( 185 edit=self._back_button, down_widget=self._touch_button 186 ) 187 self._have_selected_child = True 188 v -= spacing 189 190 if show_gamepads: 191 self._gamepads_button = btn = bui.buttonwidget( 192 parent=self._root_widget, 193 position=((width - button_width) / 2 - 7, v), 194 size=(button_width, 43), 195 autoselect=True, 196 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 197 on_activate_call=self._do_gamepads, 198 ) 199 bui.widget( 200 edit=btn, 201 right_widget=bui.get_special_widget('squad_button'), 202 ) 203 if not self._have_selected_child: 204 bui.containerwidget( 205 edit=self._root_widget, selected_child=self._gamepads_button 206 ) 207 if self._back_button is not None: 208 bui.widget( 209 edit=self._back_button, 210 down_widget=self._gamepads_button, 211 ) 212 self._have_selected_child = True 213 v -= spacing 214 else: 215 self._gamepads_button = None 216 217 if show_space_1: 218 v -= space_height 219 220 if show_keyboard: 221 self._keyboard_button = btn = bui.buttonwidget( 222 parent=self._root_widget, 223 position=((width - button_width) / 2 - 5, v), 224 size=(button_width, 43), 225 autoselect=True, 226 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 227 on_activate_call=self._config_keyboard, 228 ) 229 bui.widget( 230 edit=self._keyboard_button, left_widget=self._keyboard_button 231 ) 232 bui.widget( 233 edit=btn, 234 right_widget=bui.get_special_widget('squad_button'), 235 ) 236 if not self._have_selected_child: 237 bui.containerwidget( 238 edit=self._root_widget, selected_child=self._keyboard_button 239 ) 240 if self._back_button is not None: 241 bui.widget( 242 edit=self._back_button, 243 down_widget=self._keyboard_button, 244 ) 245 self._have_selected_child = True 246 v -= spacing 247 if show_keyboard_p2: 248 self._keyboard_2_button = bui.buttonwidget( 249 parent=self._root_widget, 250 position=((width - button_width) / 2 - 3, v), 251 size=(button_width, 43), 252 autoselect=True, 253 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 254 on_activate_call=self._config_keyboard2, 255 ) 256 v -= spacing 257 bui.widget( 258 edit=self._keyboard_2_button, 259 left_widget=self._keyboard_2_button, 260 ) 261 if show_space_2: 262 v -= space_height 263 if show_remote: 264 self._idevices_button = btn = bui.buttonwidget( 265 parent=self._root_widget, 266 position=((width - button_width) / 2 - 5, v), 267 size=(button_width, 43), 268 autoselect=True, 269 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 270 on_activate_call=self._do_mobile_devices, 271 ) 272 bui.widget( 273 edit=self._idevices_button, left_widget=self._idevices_button 274 ) 275 bui.widget( 276 edit=btn, 277 right_widget=bui.get_special_widget('squad_button'), 278 ) 279 if not self._have_selected_child: 280 bui.containerwidget( 281 edit=self._root_widget, selected_child=self._idevices_button 282 ) 283 if self._back_button is not None: 284 bui.widget( 285 edit=self._back_button, 286 down_widget=self._idevices_button, 287 ) 288 self._have_selected_child = True 289 v -= spacing 290 291 if show_xinput_toggle: 292 293 def do_toggle(value: bool) -> None: 294 bui.screenmessage( 295 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 296 color=(1, 1, 0), 297 ) 298 bui.getsound('gunCocking').play() 299 bui.set_low_level_config_value('enablexinput', not value) 300 301 xinput_checkbox = bui.checkboxwidget( 302 parent=self._root_widget, 303 position=( 304 width * (0.35 if uiscale is bui.UIScale.SMALL else 0.25), 305 v + 3, 306 ), 307 size=(120, 30), 308 value=(not bui.get_low_level_config_value('enablexinput', 1)), 309 maxwidth=200, 310 on_value_change_call=do_toggle, 311 text=bui.Lstr(resource='disableXInputText'), 312 autoselect=True, 313 ) 314 bui.textwidget( 315 parent=self._root_widget, 316 position=(width * 0.5, v - 5), 317 size=(0, 0), 318 text=bui.Lstr(resource='disableXInputDescriptionText'), 319 scale=0.5, 320 h_align='center', 321 v_align='center', 322 color=bui.app.ui_v1.infotextcolor, 323 maxwidth=width * 0.8, 324 ) 325 bui.widget( 326 edit=xinput_checkbox, 327 left_widget=xinput_checkbox, 328 right_widget=xinput_checkbox, 329 ) 330 v -= spacing 331 332 self._restore_state() 333 334 @override 335 def get_main_window_state(self) -> bui.MainWindowState: 336 # Support recreating our window for back/refresh purposes. 337 cls = type(self) 338 return bui.BasicMainWindowState( 339 create_call=lambda transition, origin_widget: cls( 340 transition=transition, origin_widget=origin_widget 341 ) 342 ) 343 344 @override 345 def on_main_window_close(self) -> None: 346 self._save_state() 347 348 def _set_mac_controller_subsystem(self, val: str) -> None: 349 cfg = bui.app.config 350 cfg['Mac Controller Subsystem'] = val 351 cfg.apply_and_commit() 352 353 def _config_keyboard(self) -> None: 354 # pylint: disable=cyclic-import 355 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 356 357 # no-op if we're not in control. 358 if not self.main_window_has_control(): 359 return 360 361 self.main_window_replace( 362 ConfigKeyboardWindow(bs.getinputdevice('Keyboard', '#1')) 363 ) 364 365 def _config_keyboard2(self) -> None: 366 # pylint: disable=cyclic-import 367 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 368 369 # no-op if we're not in control. 370 if not self.main_window_has_control(): 371 return 372 373 self.main_window_replace( 374 ConfigKeyboardWindow(bs.getinputdevice('Keyboard', '#2')) 375 ) 376 377 def _do_mobile_devices(self) -> None: 378 # pylint: disable=cyclic-import 379 from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow 380 381 # no-op if we're not in control. 382 if not self.main_window_has_control(): 383 return 384 385 self.main_window_replace(RemoteAppSettingsWindow()) 386 387 def _do_gamepads(self) -> None: 388 # pylint: disable=cyclic-import 389 from bauiv1lib.settings.gamepadselect import GamepadSelectWindow 390 391 # no-op if we're not in control. 392 if not self.main_window_has_control(): 393 return 394 395 self.main_window_replace(GamepadSelectWindow()) 396 397 def _do_touchscreen(self) -> None: 398 # pylint: disable=cyclic-import 399 from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow 400 401 # no-op if we're not in control. 402 if not self.main_window_has_control(): 403 return 404 405 self.main_window_replace(TouchscreenSettingsWindow()) 406 407 def _save_state(self) -> None: 408 sel = self._root_widget.get_selected_child() 409 if sel == self._gamepads_button: 410 sel_name = 'GamePads' 411 elif sel == self._touch_button: 412 sel_name = 'Touch' 413 elif sel == self._keyboard_button: 414 sel_name = 'Keyboard' 415 elif sel == self._keyboard_2_button: 416 sel_name = 'Keyboard2' 417 elif sel == self._idevices_button: 418 sel_name = 'iDevices' 419 else: 420 sel_name = 'Back' 421 assert bui.app.classic is not None 422 bui.app.ui_v1.window_states[type(self)] = sel_name 423 424 def _restore_state(self) -> None: 425 assert bui.app.classic is not None 426 sel_name = bui.app.ui_v1.window_states.get(type(self)) 427 if sel_name == 'GamePads': 428 sel = self._gamepads_button 429 elif sel_name == 'Touch': 430 sel = self._touch_button 431 elif sel_name == 'Keyboard': 432 sel = self._keyboard_button 433 elif sel_name == 'Keyboard2': 434 sel = self._keyboard_2_button 435 elif sel_name == 'iDevices': 436 sel = self._idevices_button 437 elif sel_name == 'Back': 438 sel = self._back_button 439 else: 440 sel = ( 441 self._gamepads_button 442 if self._gamepads_button is not None 443 else self._back_button 444 ) 445 bui.containerwidget(edit=self._root_widget, selected_child=sel)
Top level control settings window.
ControlsSettingsWindow( transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
17 def __init__( 18 self, 19 transition: str | None = 'in_right', 20 origin_widget: bui.Widget | None = None, 21 ): 22 # FIXME: should tidy up here. 23 # pylint: disable=too-many-statements 24 # pylint: disable=too-many-branches 25 # pylint: disable=too-many-locals 26 # pylint: disable=cyclic-import 27 28 self._have_selected_child = False 29 30 self._r = 'configControllersWindow' 31 uiscale = bui.app.ui_v1.uiscale 32 app = bui.app 33 assert app.classic is not None 34 35 spacing = 50.0 36 button_width = 350.0 37 width = 800.0 if uiscale is bui.UIScale.SMALL else 460.0 38 height = 300 if uiscale is bui.UIScale.SMALL else 130.0 39 40 yoffs = -60 if uiscale is bui.UIScale.SMALL else 0 41 space_height = spacing * 0.3 42 43 # FIXME: should create vis settings under platform or 44 # app-adapter to determine whether to show this stuff; not hard 45 # code it. 46 47 show_gamepads = False 48 platform = app.classic.platform 49 subplatform = app.classic.subplatform 50 non_vr_windows = platform == 'windows' and ( 51 subplatform != 'oculus' or not app.env.vr 52 ) 53 if platform in ('linux', 'android', 'mac') or non_vr_windows: 54 show_gamepads = True 55 height += spacing 56 57 show_touch = False 58 if bs.have_touchscreen_input(): 59 show_touch = True 60 height += spacing 61 62 show_space_1 = False 63 if show_gamepads or show_touch: 64 show_space_1 = True 65 height += space_height 66 67 show_keyboard = False 68 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 69 show_keyboard = True 70 height += spacing 71 show_keyboard_p2 = False if app.env.vr else show_keyboard 72 if show_keyboard_p2: 73 height += spacing 74 75 show_space_2 = False 76 if show_keyboard: 77 show_space_2 = True 78 height += space_height 79 80 if bool(True): 81 show_remote = True 82 height += spacing 83 else: 84 show_remote = False 85 86 # On windows (outside of oculus/vr), show an option to disable xinput. 87 show_xinput_toggle = False 88 if platform == 'windows' and not app.env.vr: 89 show_xinput_toggle = True 90 91 if show_xinput_toggle: 92 height += spacing 93 94 assert bui.app.classic is not None 95 smallscale = 1.7 96 super().__init__( 97 root_widget=bui.containerwidget( 98 size=(width, height), 99 stack_offset=( 100 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 101 ), 102 scale=( 103 smallscale 104 if uiscale is bui.UIScale.SMALL 105 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 106 ), 107 toolbar_visibility=( 108 'menu_minimal' 109 if uiscale is bui.UIScale.SMALL 110 else 'menu_full' 111 ), 112 ), 113 transition=transition, 114 origin_widget=origin_widget, 115 ) 116 117 self._back_button: bui.Widget | None 118 if uiscale is bui.UIScale.SMALL: 119 bui.containerwidget( 120 edit=self._root_widget, on_cancel_call=self.main_window_back 121 ) 122 self._back_button = None 123 else: 124 self._back_button = btn = bui.buttonwidget( 125 parent=self._root_widget, 126 position=(35, height - 60), 127 size=(140, 65), 128 scale=0.8, 129 text_scale=1.2, 130 autoselect=True, 131 label=bui.Lstr(resource='backText'), 132 button_type='back', 133 on_activate_call=self.main_window_back, 134 ) 135 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 136 bui.buttonwidget( 137 edit=btn, 138 button_type='backSmall', 139 size=(60, 60), 140 label=bui.charstr(bui.SpecialChar.BACK), 141 ) 142 143 # We need these vars to exist even if the buttons don't. 144 self._gamepads_button: bui.Widget | None = None 145 self._touch_button: bui.Widget | None = None 146 self._keyboard_button: bui.Widget | None = None 147 self._keyboard_2_button: bui.Widget | None = None 148 self._idevices_button: bui.Widget | None = None 149 150 bui.textwidget( 151 parent=self._root_widget, 152 position=( 153 0, 154 height + yoffs - (53 if uiscale is bui.UIScale.SMALL else 50), 155 ), 156 size=(width, 25), 157 text=bui.Lstr(resource=f'{self._r}.titleText'), 158 color=bui.app.ui_v1.title_color, 159 h_align='center', 160 v_align='top', 161 ) 162 163 v = height - (85 if uiscale is bui.UIScale.SMALL else 75) + yoffs 164 v -= spacing 165 166 if show_touch: 167 self._touch_button = btn = bui.buttonwidget( 168 parent=self._root_widget, 169 position=((width - button_width) / 2, v), 170 size=(button_width, 43), 171 autoselect=True, 172 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 173 on_activate_call=self._do_touchscreen, 174 ) 175 bui.widget( 176 edit=btn, 177 right_widget=bui.get_special_widget('squad_button'), 178 ) 179 if not self._have_selected_child: 180 bui.containerwidget( 181 edit=self._root_widget, selected_child=self._touch_button 182 ) 183 if self._back_button is not None: 184 bui.widget( 185 edit=self._back_button, down_widget=self._touch_button 186 ) 187 self._have_selected_child = True 188 v -= spacing 189 190 if show_gamepads: 191 self._gamepads_button = btn = bui.buttonwidget( 192 parent=self._root_widget, 193 position=((width - button_width) / 2 - 7, v), 194 size=(button_width, 43), 195 autoselect=True, 196 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 197 on_activate_call=self._do_gamepads, 198 ) 199 bui.widget( 200 edit=btn, 201 right_widget=bui.get_special_widget('squad_button'), 202 ) 203 if not self._have_selected_child: 204 bui.containerwidget( 205 edit=self._root_widget, selected_child=self._gamepads_button 206 ) 207 if self._back_button is not None: 208 bui.widget( 209 edit=self._back_button, 210 down_widget=self._gamepads_button, 211 ) 212 self._have_selected_child = True 213 v -= spacing 214 else: 215 self._gamepads_button = None 216 217 if show_space_1: 218 v -= space_height 219 220 if show_keyboard: 221 self._keyboard_button = btn = bui.buttonwidget( 222 parent=self._root_widget, 223 position=((width - button_width) / 2 - 5, v), 224 size=(button_width, 43), 225 autoselect=True, 226 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 227 on_activate_call=self._config_keyboard, 228 ) 229 bui.widget( 230 edit=self._keyboard_button, left_widget=self._keyboard_button 231 ) 232 bui.widget( 233 edit=btn, 234 right_widget=bui.get_special_widget('squad_button'), 235 ) 236 if not self._have_selected_child: 237 bui.containerwidget( 238 edit=self._root_widget, selected_child=self._keyboard_button 239 ) 240 if self._back_button is not None: 241 bui.widget( 242 edit=self._back_button, 243 down_widget=self._keyboard_button, 244 ) 245 self._have_selected_child = True 246 v -= spacing 247 if show_keyboard_p2: 248 self._keyboard_2_button = bui.buttonwidget( 249 parent=self._root_widget, 250 position=((width - button_width) / 2 - 3, v), 251 size=(button_width, 43), 252 autoselect=True, 253 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 254 on_activate_call=self._config_keyboard2, 255 ) 256 v -= spacing 257 bui.widget( 258 edit=self._keyboard_2_button, 259 left_widget=self._keyboard_2_button, 260 ) 261 if show_space_2: 262 v -= space_height 263 if show_remote: 264 self._idevices_button = btn = bui.buttonwidget( 265 parent=self._root_widget, 266 position=((width - button_width) / 2 - 5, v), 267 size=(button_width, 43), 268 autoselect=True, 269 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 270 on_activate_call=self._do_mobile_devices, 271 ) 272 bui.widget( 273 edit=self._idevices_button, left_widget=self._idevices_button 274 ) 275 bui.widget( 276 edit=btn, 277 right_widget=bui.get_special_widget('squad_button'), 278 ) 279 if not self._have_selected_child: 280 bui.containerwidget( 281 edit=self._root_widget, selected_child=self._idevices_button 282 ) 283 if self._back_button is not None: 284 bui.widget( 285 edit=self._back_button, 286 down_widget=self._idevices_button, 287 ) 288 self._have_selected_child = True 289 v -= spacing 290 291 if show_xinput_toggle: 292 293 def do_toggle(value: bool) -> None: 294 bui.screenmessage( 295 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 296 color=(1, 1, 0), 297 ) 298 bui.getsound('gunCocking').play() 299 bui.set_low_level_config_value('enablexinput', not value) 300 301 xinput_checkbox = bui.checkboxwidget( 302 parent=self._root_widget, 303 position=( 304 width * (0.35 if uiscale is bui.UIScale.SMALL else 0.25), 305 v + 3, 306 ), 307 size=(120, 30), 308 value=(not bui.get_low_level_config_value('enablexinput', 1)), 309 maxwidth=200, 310 on_value_change_call=do_toggle, 311 text=bui.Lstr(resource='disableXInputText'), 312 autoselect=True, 313 ) 314 bui.textwidget( 315 parent=self._root_widget, 316 position=(width * 0.5, v - 5), 317 size=(0, 0), 318 text=bui.Lstr(resource='disableXInputDescriptionText'), 319 scale=0.5, 320 h_align='center', 321 v_align='center', 322 color=bui.app.ui_v1.infotextcolor, 323 maxwidth=width * 0.8, 324 ) 325 bui.widget( 326 edit=xinput_checkbox, 327 left_widget=xinput_checkbox, 328 right_widget=xinput_checkbox, 329 ) 330 v -= spacing 331 332 self._restore_state()
Create a MainWindow given a root widget and transition info.
Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.
334 @override 335 def get_main_window_state(self) -> bui.MainWindowState: 336 # Support recreating our window for back/refresh purposes. 337 cls = type(self) 338 return bui.BasicMainWindowState( 339 create_call=lambda transition, origin_widget: cls( 340 transition=transition, origin_widget=origin_widget 341 ) 342 )
Return a WindowState to recreate this window, if supported.