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 bauiv1lib.popup import PopupMenu 8import bascenev1 as bs 9import bauiv1 as bui 10 11 12class ControlsSettingsWindow(bui.Window): 13 """Top level control settings window.""" 14 15 def __init__( 16 self, 17 transition: str = 'in_right', 18 origin_widget: bui.Widget | None = None, 19 ): 20 # FIXME: should tidy up here. 21 # pylint: disable=too-many-statements 22 # pylint: disable=too-many-branches 23 # pylint: disable=too-many-locals 24 # pylint: disable=cyclic-import 25 26 self._have_selected_child = False 27 28 scale_origin: tuple[float, float] | None 29 30 # If they provided an origin-widget, scale up from that. 31 if origin_widget is not None: 32 self._transition_out = 'out_scale' 33 scale_origin = origin_widget.get_screen_space_center() 34 transition = 'in_scale' 35 else: 36 self._transition_out = 'out_right' 37 scale_origin = None 38 39 self._r = 'configControllersWindow' 40 app = bui.app 41 assert app.classic is not None 42 43 spacing = 50.0 44 button_width = 350.0 45 width = 460.0 46 height = 130.0 47 48 space_height = spacing * 0.3 49 50 # FIXME: should create vis settings under platform or app-adapter 51 # to determine whether to show this stuff; not hard code it. 52 53 show_gamepads = False 54 platform = app.classic.platform 55 subplatform = app.classic.subplatform 56 non_vr_windows = platform == 'windows' and ( 57 subplatform != 'oculus' or not app.env.vr 58 ) 59 if platform in ('linux', 'android', 'mac') or non_vr_windows: 60 show_gamepads = True 61 height += spacing 62 63 show_touch = False 64 if bs.have_touchscreen_input(): 65 show_touch = True 66 height += spacing 67 68 show_space_1 = False 69 if show_gamepads or show_touch: 70 show_space_1 = True 71 height += space_height 72 73 show_keyboard = False 74 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 75 show_keyboard = True 76 height += spacing 77 show_keyboard_p2 = False if app.env.vr else show_keyboard 78 if show_keyboard_p2: 79 height += spacing 80 81 show_space_2 = False 82 if show_keyboard: 83 show_space_2 = True 84 height += space_height 85 86 if bool(True): 87 show_remote = True 88 height += spacing 89 else: 90 show_remote = False 91 92 # On windows (outside of oculus/vr), show an option to disable xinput. 93 show_xinput_toggle = False 94 if platform == 'windows' and not app.env.vr: 95 show_xinput_toggle = True 96 97 # On mac builds, show an option to switch between generic and 98 # made-for-iOS/Mac systems 99 # (we can run into problems where devices register as one of each 100 # type otherwise).. 101 # UPDATE: We always use the apple system these days (which should 102 # support older controllers). So no need for a switch. 103 show_mac_controller_subsystem = False 104 # if platform == 'mac' and bui.is_xcode_build(): 105 # show_mac_controller_subsystem = True 106 107 if show_mac_controller_subsystem: 108 height += spacing * 1.5 109 110 if show_xinput_toggle: 111 height += spacing 112 113 assert bui.app.classic is not None 114 uiscale = bui.app.ui_v1.uiscale 115 smallscale = 1.7 if show_keyboard else 2.2 116 super().__init__( 117 root_widget=bui.containerwidget( 118 size=(width, height), 119 transition=transition, 120 scale_origin_stack_offset=scale_origin, 121 stack_offset=( 122 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 123 ), 124 scale=( 125 smallscale 126 if uiscale is bui.UIScale.SMALL 127 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 128 ), 129 ) 130 ) 131 self._back_button = btn = bui.buttonwidget( 132 parent=self._root_widget, 133 position=(35, height - 60), 134 size=(140, 65), 135 scale=0.8, 136 text_scale=1.2, 137 autoselect=True, 138 label=bui.Lstr(resource='backText'), 139 button_type='back', 140 on_activate_call=self._back, 141 ) 142 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 143 144 # We need these vars to exist even if the buttons don't. 145 self._gamepads_button: bui.Widget | None = None 146 self._touch_button: bui.Widget | None = None 147 self._keyboard_button: bui.Widget | None = None 148 self._keyboard_2_button: bui.Widget | None = None 149 self._idevices_button: bui.Widget | None = None 150 151 bui.textwidget( 152 parent=self._root_widget, 153 position=(0, height - 49), 154 size=(width, 25), 155 text=bui.Lstr(resource=f'{self._r}.titleText'), 156 color=bui.app.ui_v1.title_color, 157 h_align='center', 158 v_align='top', 159 ) 160 bui.buttonwidget( 161 edit=btn, 162 button_type='backSmall', 163 size=(60, 60), 164 label=bui.charstr(bui.SpecialChar.BACK), 165 ) 166 167 v = height - 75 168 v -= spacing 169 170 if show_touch: 171 self._touch_button = btn = bui.buttonwidget( 172 parent=self._root_widget, 173 position=((width - button_width) / 2, v), 174 size=(button_width, 43), 175 autoselect=True, 176 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 177 on_activate_call=self._do_touchscreen, 178 ) 179 if bui.app.ui_v1.use_toolbars: 180 bui.widget( 181 edit=btn, 182 right_widget=bui.get_special_widget('party_button'), 183 ) 184 if not self._have_selected_child: 185 bui.containerwidget( 186 edit=self._root_widget, selected_child=self._touch_button 187 ) 188 bui.widget( 189 edit=self._back_button, down_widget=self._touch_button 190 ) 191 self._have_selected_child = True 192 v -= spacing 193 194 if show_gamepads: 195 self._gamepads_button = btn = bui.buttonwidget( 196 parent=self._root_widget, 197 position=((width - button_width) / 2 - 7, v), 198 size=(button_width, 43), 199 autoselect=True, 200 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 201 on_activate_call=self._do_gamepads, 202 ) 203 if bui.app.ui_v1.use_toolbars: 204 bui.widget( 205 edit=btn, 206 right_widget=bui.get_special_widget('party_button'), 207 ) 208 if not self._have_selected_child: 209 bui.containerwidget( 210 edit=self._root_widget, selected_child=self._gamepads_button 211 ) 212 bui.widget( 213 edit=self._back_button, down_widget=self._gamepads_button 214 ) 215 self._have_selected_child = True 216 v -= spacing 217 else: 218 self._gamepads_button = None 219 220 if show_space_1: 221 v -= space_height 222 223 if show_keyboard: 224 self._keyboard_button = btn = bui.buttonwidget( 225 parent=self._root_widget, 226 position=((width - button_width) / 2 - 5, v), 227 size=(button_width, 43), 228 autoselect=True, 229 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 230 on_activate_call=self._config_keyboard, 231 ) 232 bui.widget( 233 edit=self._keyboard_button, left_widget=self._keyboard_button 234 ) 235 if bui.app.ui_v1.use_toolbars: 236 bui.widget( 237 edit=btn, 238 right_widget=bui.get_special_widget('party_button'), 239 ) 240 if not self._have_selected_child: 241 bui.containerwidget( 242 edit=self._root_widget, selected_child=self._keyboard_button 243 ) 244 bui.widget( 245 edit=self._back_button, down_widget=self._keyboard_button 246 ) 247 self._have_selected_child = True 248 v -= spacing 249 if show_keyboard_p2: 250 self._keyboard_2_button = bui.buttonwidget( 251 parent=self._root_widget, 252 position=((width - button_width) / 2 - 3, v), 253 size=(button_width, 43), 254 autoselect=True, 255 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 256 on_activate_call=self._config_keyboard2, 257 ) 258 v -= spacing 259 bui.widget( 260 edit=self._keyboard_2_button, 261 left_widget=self._keyboard_2_button, 262 ) 263 if show_space_2: 264 v -= space_height 265 if show_remote: 266 self._idevices_button = btn = bui.buttonwidget( 267 parent=self._root_widget, 268 position=((width - button_width) / 2 - 5, v), 269 size=(button_width, 43), 270 autoselect=True, 271 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 272 on_activate_call=self._do_mobile_devices, 273 ) 274 bui.widget( 275 edit=self._idevices_button, left_widget=self._idevices_button 276 ) 277 if bui.app.ui_v1.use_toolbars: 278 bui.widget( 279 edit=btn, 280 right_widget=bui.get_special_widget('party_button'), 281 ) 282 if not self._have_selected_child: 283 bui.containerwidget( 284 edit=self._root_widget, selected_child=self._idevices_button 285 ) 286 bui.widget( 287 edit=self._back_button, down_widget=self._idevices_button 288 ) 289 self._have_selected_child = True 290 v -= spacing 291 292 if show_xinput_toggle: 293 294 def do_toggle(value: bool) -> None: 295 bui.screenmessage( 296 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 297 color=(1, 1, 0), 298 ) 299 bui.getsound('gunCocking').play() 300 bui.set_low_level_config_value('enablexinput', not value) 301 302 xinput_checkbox = bui.checkboxwidget( 303 parent=self._root_widget, 304 position=(100, v + 3), 305 size=(120, 30), 306 value=(not bui.get_low_level_config_value('enablexinput', 1)), 307 maxwidth=200, 308 on_value_change_call=do_toggle, 309 text=bui.Lstr(resource='disableXInputText'), 310 autoselect=True, 311 ) 312 bui.textwidget( 313 parent=self._root_widget, 314 position=(width * 0.5, v - 5), 315 size=(0, 0), 316 text=bui.Lstr(resource='disableXInputDescriptionText'), 317 scale=0.5, 318 h_align='center', 319 v_align='center', 320 color=bui.app.ui_v1.infotextcolor, 321 maxwidth=width * 0.8, 322 ) 323 bui.widget( 324 edit=xinput_checkbox, 325 left_widget=xinput_checkbox, 326 right_widget=xinput_checkbox, 327 ) 328 v -= spacing 329 330 if show_mac_controller_subsystem: 331 PopupMenu( 332 parent=self._root_widget, 333 position=(260, v - 10), 334 width=160, 335 button_size=(150, 50), 336 scale=1.5, 337 choices=['Classic', 'MFi', 'Both'], 338 choices_display=[ 339 bui.Lstr(resource='macControllerSubsystemClassicText'), 340 bui.Lstr(resource='macControllerSubsystemMFiText'), 341 bui.Lstr(resource='macControllerSubsystemBothText'), 342 ], 343 current_choice=bui.app.config.resolve( 344 'Mac Controller Subsystem' 345 ), 346 on_value_change_call=self._set_mac_controller_subsystem, 347 ) 348 bui.textwidget( 349 parent=self._root_widget, 350 position=(245, v + 13), 351 size=(0, 0), 352 text=bui.Lstr(resource='macControllerSubsystemTitleText'), 353 scale=1.0, 354 h_align='right', 355 v_align='center', 356 color=bui.app.ui_v1.infotextcolor, 357 maxwidth=180, 358 ) 359 bui.textwidget( 360 parent=self._root_widget, 361 position=(width * 0.5, v - 20), 362 size=(0, 0), 363 text=bui.Lstr(resource='macControllerSubsystemDescriptionText'), 364 scale=0.5, 365 h_align='center', 366 v_align='center', 367 color=bui.app.ui_v1.infotextcolor, 368 maxwidth=width * 0.8, 369 ) 370 v -= spacing * 1.5 371 372 self._restore_state() 373 374 def _set_mac_controller_subsystem(self, val: str) -> None: 375 cfg = bui.app.config 376 cfg['Mac Controller Subsystem'] = val 377 cfg.apply_and_commit() 378 379 def _config_keyboard(self) -> None: 380 # pylint: disable=cyclic-import 381 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 382 383 # no-op if our underlying widget is dead or on its way out. 384 if not self._root_widget or self._root_widget.transitioning_out: 385 return 386 387 self._save_state() 388 bui.containerwidget(edit=self._root_widget, transition='out_left') 389 assert bui.app.classic is not None 390 bui.app.ui_v1.set_main_menu_window( 391 ConfigKeyboardWindow( 392 bs.getinputdevice('Keyboard', '#1') 393 ).get_root_widget(), 394 from_window=self._root_widget, 395 ) 396 397 def _config_keyboard2(self) -> None: 398 # pylint: disable=cyclic-import 399 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 400 401 # no-op if our underlying widget is dead or on its way out. 402 if not self._root_widget or self._root_widget.transitioning_out: 403 return 404 405 self._save_state() 406 bui.containerwidget(edit=self._root_widget, transition='out_left') 407 assert bui.app.classic is not None 408 bui.app.ui_v1.set_main_menu_window( 409 ConfigKeyboardWindow( 410 bs.getinputdevice('Keyboard', '#2') 411 ).get_root_widget(), 412 from_window=self._root_widget, 413 ) 414 415 def _do_mobile_devices(self) -> None: 416 # pylint: disable=cyclic-import 417 from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow 418 419 # no-op if our underlying widget is dead or on its way out. 420 if not self._root_widget or self._root_widget.transitioning_out: 421 return 422 423 self._save_state() 424 bui.containerwidget(edit=self._root_widget, transition='out_left') 425 assert bui.app.classic is not None 426 bui.app.ui_v1.set_main_menu_window( 427 RemoteAppSettingsWindow().get_root_widget(), 428 from_window=self._root_widget, 429 ) 430 431 def _do_gamepads(self) -> None: 432 # pylint: disable=cyclic-import 433 from bauiv1lib.settings.gamepadselect import GamepadSelectWindow 434 435 # no-op if our underlying widget is dead or on its way out. 436 if not self._root_widget or self._root_widget.transitioning_out: 437 return 438 439 self._save_state() 440 bui.containerwidget(edit=self._root_widget, transition='out_left') 441 assert bui.app.classic is not None 442 bui.app.ui_v1.set_main_menu_window( 443 GamepadSelectWindow().get_root_widget(), 444 from_window=self._root_widget, 445 ) 446 447 def _do_touchscreen(self) -> None: 448 # pylint: disable=cyclic-import 449 from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow 450 451 # no-op if our underlying widget is dead or on its way out. 452 if not self._root_widget or self._root_widget.transitioning_out: 453 return 454 455 self._save_state() 456 bui.containerwidget(edit=self._root_widget, transition='out_left') 457 assert bui.app.classic is not None 458 bui.app.ui_v1.set_main_menu_window( 459 TouchscreenSettingsWindow().get_root_widget(), 460 from_window=self._root_widget, 461 ) 462 463 def _save_state(self) -> None: 464 sel = self._root_widget.get_selected_child() 465 if sel == self._gamepads_button: 466 sel_name = 'GamePads' 467 elif sel == self._touch_button: 468 sel_name = 'Touch' 469 elif sel == self._keyboard_button: 470 sel_name = 'Keyboard' 471 elif sel == self._keyboard_2_button: 472 sel_name = 'Keyboard2' 473 elif sel == self._idevices_button: 474 sel_name = 'iDevices' 475 else: 476 sel_name = 'Back' 477 assert bui.app.classic is not None 478 bui.app.ui_v1.window_states[type(self)] = sel_name 479 480 def _restore_state(self) -> None: 481 assert bui.app.classic is not None 482 sel_name = bui.app.ui_v1.window_states.get(type(self)) 483 if sel_name == 'GamePads': 484 sel = self._gamepads_button 485 elif sel_name == 'Touch': 486 sel = self._touch_button 487 elif sel_name == 'Keyboard': 488 sel = self._keyboard_button 489 elif sel_name == 'Keyboard2': 490 sel = self._keyboard_2_button 491 elif sel_name == 'iDevices': 492 sel = self._idevices_button 493 elif sel_name == 'Back': 494 sel = self._back_button 495 else: 496 sel = ( 497 self._gamepads_button 498 if self._gamepads_button is not None 499 else self._back_button 500 ) 501 bui.containerwidget(edit=self._root_widget, selected_child=sel) 502 503 def _back(self) -> None: 504 # pylint: disable=cyclic-import 505 from bauiv1lib.settings.allsettings import AllSettingsWindow 506 507 # no-op if our underlying widget is dead or on its way out. 508 if not self._root_widget or self._root_widget.transitioning_out: 509 return 510 511 self._save_state() 512 bui.containerwidget( 513 edit=self._root_widget, transition=self._transition_out 514 ) 515 assert bui.app.classic is not None 516 bui.app.ui_v1.set_main_menu_window( 517 AllSettingsWindow(transition='in_left').get_root_widget(), 518 from_window=self._root_widget, 519 )
class
ControlsSettingsWindow(bauiv1._uitypes.Window):
13class ControlsSettingsWindow(bui.Window): 14 """Top level control settings window.""" 15 16 def __init__( 17 self, 18 transition: str = '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 scale_origin: tuple[float, float] | None 30 31 # If they provided an origin-widget, scale up from that. 32 if origin_widget is not None: 33 self._transition_out = 'out_scale' 34 scale_origin = origin_widget.get_screen_space_center() 35 transition = 'in_scale' 36 else: 37 self._transition_out = 'out_right' 38 scale_origin = None 39 40 self._r = 'configControllersWindow' 41 app = bui.app 42 assert app.classic is not None 43 44 spacing = 50.0 45 button_width = 350.0 46 width = 460.0 47 height = 130.0 48 49 space_height = spacing * 0.3 50 51 # FIXME: should create vis settings under platform or app-adapter 52 # to determine whether to show this stuff; not hard code it. 53 54 show_gamepads = False 55 platform = app.classic.platform 56 subplatform = app.classic.subplatform 57 non_vr_windows = platform == 'windows' and ( 58 subplatform != 'oculus' or not app.env.vr 59 ) 60 if platform in ('linux', 'android', 'mac') or non_vr_windows: 61 show_gamepads = True 62 height += spacing 63 64 show_touch = False 65 if bs.have_touchscreen_input(): 66 show_touch = True 67 height += spacing 68 69 show_space_1 = False 70 if show_gamepads or show_touch: 71 show_space_1 = True 72 height += space_height 73 74 show_keyboard = False 75 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 76 show_keyboard = True 77 height += spacing 78 show_keyboard_p2 = False if app.env.vr else show_keyboard 79 if show_keyboard_p2: 80 height += spacing 81 82 show_space_2 = False 83 if show_keyboard: 84 show_space_2 = True 85 height += space_height 86 87 if bool(True): 88 show_remote = True 89 height += spacing 90 else: 91 show_remote = False 92 93 # On windows (outside of oculus/vr), show an option to disable xinput. 94 show_xinput_toggle = False 95 if platform == 'windows' and not app.env.vr: 96 show_xinput_toggle = True 97 98 # On mac builds, show an option to switch between generic and 99 # made-for-iOS/Mac systems 100 # (we can run into problems where devices register as one of each 101 # type otherwise).. 102 # UPDATE: We always use the apple system these days (which should 103 # support older controllers). So no need for a switch. 104 show_mac_controller_subsystem = False 105 # if platform == 'mac' and bui.is_xcode_build(): 106 # show_mac_controller_subsystem = True 107 108 if show_mac_controller_subsystem: 109 height += spacing * 1.5 110 111 if show_xinput_toggle: 112 height += spacing 113 114 assert bui.app.classic is not None 115 uiscale = bui.app.ui_v1.uiscale 116 smallscale = 1.7 if show_keyboard else 2.2 117 super().__init__( 118 root_widget=bui.containerwidget( 119 size=(width, height), 120 transition=transition, 121 scale_origin_stack_offset=scale_origin, 122 stack_offset=( 123 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 124 ), 125 scale=( 126 smallscale 127 if uiscale is bui.UIScale.SMALL 128 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 129 ), 130 ) 131 ) 132 self._back_button = btn = bui.buttonwidget( 133 parent=self._root_widget, 134 position=(35, height - 60), 135 size=(140, 65), 136 scale=0.8, 137 text_scale=1.2, 138 autoselect=True, 139 label=bui.Lstr(resource='backText'), 140 button_type='back', 141 on_activate_call=self._back, 142 ) 143 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 144 145 # We need these vars to exist even if the buttons don't. 146 self._gamepads_button: bui.Widget | None = None 147 self._touch_button: bui.Widget | None = None 148 self._keyboard_button: bui.Widget | None = None 149 self._keyboard_2_button: bui.Widget | None = None 150 self._idevices_button: bui.Widget | None = None 151 152 bui.textwidget( 153 parent=self._root_widget, 154 position=(0, height - 49), 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 bui.buttonwidget( 162 edit=btn, 163 button_type='backSmall', 164 size=(60, 60), 165 label=bui.charstr(bui.SpecialChar.BACK), 166 ) 167 168 v = height - 75 169 v -= spacing 170 171 if show_touch: 172 self._touch_button = btn = bui.buttonwidget( 173 parent=self._root_widget, 174 position=((width - button_width) / 2, v), 175 size=(button_width, 43), 176 autoselect=True, 177 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 178 on_activate_call=self._do_touchscreen, 179 ) 180 if bui.app.ui_v1.use_toolbars: 181 bui.widget( 182 edit=btn, 183 right_widget=bui.get_special_widget('party_button'), 184 ) 185 if not self._have_selected_child: 186 bui.containerwidget( 187 edit=self._root_widget, selected_child=self._touch_button 188 ) 189 bui.widget( 190 edit=self._back_button, down_widget=self._touch_button 191 ) 192 self._have_selected_child = True 193 v -= spacing 194 195 if show_gamepads: 196 self._gamepads_button = btn = bui.buttonwidget( 197 parent=self._root_widget, 198 position=((width - button_width) / 2 - 7, v), 199 size=(button_width, 43), 200 autoselect=True, 201 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 202 on_activate_call=self._do_gamepads, 203 ) 204 if bui.app.ui_v1.use_toolbars: 205 bui.widget( 206 edit=btn, 207 right_widget=bui.get_special_widget('party_button'), 208 ) 209 if not self._have_selected_child: 210 bui.containerwidget( 211 edit=self._root_widget, selected_child=self._gamepads_button 212 ) 213 bui.widget( 214 edit=self._back_button, down_widget=self._gamepads_button 215 ) 216 self._have_selected_child = True 217 v -= spacing 218 else: 219 self._gamepads_button = None 220 221 if show_space_1: 222 v -= space_height 223 224 if show_keyboard: 225 self._keyboard_button = btn = bui.buttonwidget( 226 parent=self._root_widget, 227 position=((width - button_width) / 2 - 5, v), 228 size=(button_width, 43), 229 autoselect=True, 230 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 231 on_activate_call=self._config_keyboard, 232 ) 233 bui.widget( 234 edit=self._keyboard_button, left_widget=self._keyboard_button 235 ) 236 if bui.app.ui_v1.use_toolbars: 237 bui.widget( 238 edit=btn, 239 right_widget=bui.get_special_widget('party_button'), 240 ) 241 if not self._have_selected_child: 242 bui.containerwidget( 243 edit=self._root_widget, selected_child=self._keyboard_button 244 ) 245 bui.widget( 246 edit=self._back_button, down_widget=self._keyboard_button 247 ) 248 self._have_selected_child = True 249 v -= spacing 250 if show_keyboard_p2: 251 self._keyboard_2_button = bui.buttonwidget( 252 parent=self._root_widget, 253 position=((width - button_width) / 2 - 3, v), 254 size=(button_width, 43), 255 autoselect=True, 256 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 257 on_activate_call=self._config_keyboard2, 258 ) 259 v -= spacing 260 bui.widget( 261 edit=self._keyboard_2_button, 262 left_widget=self._keyboard_2_button, 263 ) 264 if show_space_2: 265 v -= space_height 266 if show_remote: 267 self._idevices_button = btn = bui.buttonwidget( 268 parent=self._root_widget, 269 position=((width - button_width) / 2 - 5, v), 270 size=(button_width, 43), 271 autoselect=True, 272 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 273 on_activate_call=self._do_mobile_devices, 274 ) 275 bui.widget( 276 edit=self._idevices_button, left_widget=self._idevices_button 277 ) 278 if bui.app.ui_v1.use_toolbars: 279 bui.widget( 280 edit=btn, 281 right_widget=bui.get_special_widget('party_button'), 282 ) 283 if not self._have_selected_child: 284 bui.containerwidget( 285 edit=self._root_widget, selected_child=self._idevices_button 286 ) 287 bui.widget( 288 edit=self._back_button, down_widget=self._idevices_button 289 ) 290 self._have_selected_child = True 291 v -= spacing 292 293 if show_xinput_toggle: 294 295 def do_toggle(value: bool) -> None: 296 bui.screenmessage( 297 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 298 color=(1, 1, 0), 299 ) 300 bui.getsound('gunCocking').play() 301 bui.set_low_level_config_value('enablexinput', not value) 302 303 xinput_checkbox = bui.checkboxwidget( 304 parent=self._root_widget, 305 position=(100, v + 3), 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 if show_mac_controller_subsystem: 332 PopupMenu( 333 parent=self._root_widget, 334 position=(260, v - 10), 335 width=160, 336 button_size=(150, 50), 337 scale=1.5, 338 choices=['Classic', 'MFi', 'Both'], 339 choices_display=[ 340 bui.Lstr(resource='macControllerSubsystemClassicText'), 341 bui.Lstr(resource='macControllerSubsystemMFiText'), 342 bui.Lstr(resource='macControllerSubsystemBothText'), 343 ], 344 current_choice=bui.app.config.resolve( 345 'Mac Controller Subsystem' 346 ), 347 on_value_change_call=self._set_mac_controller_subsystem, 348 ) 349 bui.textwidget( 350 parent=self._root_widget, 351 position=(245, v + 13), 352 size=(0, 0), 353 text=bui.Lstr(resource='macControllerSubsystemTitleText'), 354 scale=1.0, 355 h_align='right', 356 v_align='center', 357 color=bui.app.ui_v1.infotextcolor, 358 maxwidth=180, 359 ) 360 bui.textwidget( 361 parent=self._root_widget, 362 position=(width * 0.5, v - 20), 363 size=(0, 0), 364 text=bui.Lstr(resource='macControllerSubsystemDescriptionText'), 365 scale=0.5, 366 h_align='center', 367 v_align='center', 368 color=bui.app.ui_v1.infotextcolor, 369 maxwidth=width * 0.8, 370 ) 371 v -= spacing * 1.5 372 373 self._restore_state() 374 375 def _set_mac_controller_subsystem(self, val: str) -> None: 376 cfg = bui.app.config 377 cfg['Mac Controller Subsystem'] = val 378 cfg.apply_and_commit() 379 380 def _config_keyboard(self) -> None: 381 # pylint: disable=cyclic-import 382 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 383 384 # no-op if our underlying widget is dead or on its way out. 385 if not self._root_widget or self._root_widget.transitioning_out: 386 return 387 388 self._save_state() 389 bui.containerwidget(edit=self._root_widget, transition='out_left') 390 assert bui.app.classic is not None 391 bui.app.ui_v1.set_main_menu_window( 392 ConfigKeyboardWindow( 393 bs.getinputdevice('Keyboard', '#1') 394 ).get_root_widget(), 395 from_window=self._root_widget, 396 ) 397 398 def _config_keyboard2(self) -> None: 399 # pylint: disable=cyclic-import 400 from bauiv1lib.settings.keyboard import ConfigKeyboardWindow 401 402 # no-op if our underlying widget is dead or on its way out. 403 if not self._root_widget or self._root_widget.transitioning_out: 404 return 405 406 self._save_state() 407 bui.containerwidget(edit=self._root_widget, transition='out_left') 408 assert bui.app.classic is not None 409 bui.app.ui_v1.set_main_menu_window( 410 ConfigKeyboardWindow( 411 bs.getinputdevice('Keyboard', '#2') 412 ).get_root_widget(), 413 from_window=self._root_widget, 414 ) 415 416 def _do_mobile_devices(self) -> None: 417 # pylint: disable=cyclic-import 418 from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow 419 420 # no-op if our underlying widget is dead or on its way out. 421 if not self._root_widget or self._root_widget.transitioning_out: 422 return 423 424 self._save_state() 425 bui.containerwidget(edit=self._root_widget, transition='out_left') 426 assert bui.app.classic is not None 427 bui.app.ui_v1.set_main_menu_window( 428 RemoteAppSettingsWindow().get_root_widget(), 429 from_window=self._root_widget, 430 ) 431 432 def _do_gamepads(self) -> None: 433 # pylint: disable=cyclic-import 434 from bauiv1lib.settings.gamepadselect import GamepadSelectWindow 435 436 # no-op if our underlying widget is dead or on its way out. 437 if not self._root_widget or self._root_widget.transitioning_out: 438 return 439 440 self._save_state() 441 bui.containerwidget(edit=self._root_widget, transition='out_left') 442 assert bui.app.classic is not None 443 bui.app.ui_v1.set_main_menu_window( 444 GamepadSelectWindow().get_root_widget(), 445 from_window=self._root_widget, 446 ) 447 448 def _do_touchscreen(self) -> None: 449 # pylint: disable=cyclic-import 450 from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow 451 452 # no-op if our underlying widget is dead or on its way out. 453 if not self._root_widget or self._root_widget.transitioning_out: 454 return 455 456 self._save_state() 457 bui.containerwidget(edit=self._root_widget, transition='out_left') 458 assert bui.app.classic is not None 459 bui.app.ui_v1.set_main_menu_window( 460 TouchscreenSettingsWindow().get_root_widget(), 461 from_window=self._root_widget, 462 ) 463 464 def _save_state(self) -> None: 465 sel = self._root_widget.get_selected_child() 466 if sel == self._gamepads_button: 467 sel_name = 'GamePads' 468 elif sel == self._touch_button: 469 sel_name = 'Touch' 470 elif sel == self._keyboard_button: 471 sel_name = 'Keyboard' 472 elif sel == self._keyboard_2_button: 473 sel_name = 'Keyboard2' 474 elif sel == self._idevices_button: 475 sel_name = 'iDevices' 476 else: 477 sel_name = 'Back' 478 assert bui.app.classic is not None 479 bui.app.ui_v1.window_states[type(self)] = sel_name 480 481 def _restore_state(self) -> None: 482 assert bui.app.classic is not None 483 sel_name = bui.app.ui_v1.window_states.get(type(self)) 484 if sel_name == 'GamePads': 485 sel = self._gamepads_button 486 elif sel_name == 'Touch': 487 sel = self._touch_button 488 elif sel_name == 'Keyboard': 489 sel = self._keyboard_button 490 elif sel_name == 'Keyboard2': 491 sel = self._keyboard_2_button 492 elif sel_name == 'iDevices': 493 sel = self._idevices_button 494 elif sel_name == 'Back': 495 sel = self._back_button 496 else: 497 sel = ( 498 self._gamepads_button 499 if self._gamepads_button is not None 500 else self._back_button 501 ) 502 bui.containerwidget(edit=self._root_widget, selected_child=sel) 503 504 def _back(self) -> None: 505 # pylint: disable=cyclic-import 506 from bauiv1lib.settings.allsettings import AllSettingsWindow 507 508 # no-op if our underlying widget is dead or on its way out. 509 if not self._root_widget or self._root_widget.transitioning_out: 510 return 511 512 self._save_state() 513 bui.containerwidget( 514 edit=self._root_widget, transition=self._transition_out 515 ) 516 assert bui.app.classic is not None 517 bui.app.ui_v1.set_main_menu_window( 518 AllSettingsWindow(transition='in_left').get_root_widget(), 519 from_window=self._root_widget, 520 )
Top level control settings window.
ControlsSettingsWindow( transition: str = 'in_right', origin_widget: _bauiv1.Widget | None = None)
16 def __init__( 17 self, 18 transition: str = '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 scale_origin: tuple[float, float] | None 30 31 # If they provided an origin-widget, scale up from that. 32 if origin_widget is not None: 33 self._transition_out = 'out_scale' 34 scale_origin = origin_widget.get_screen_space_center() 35 transition = 'in_scale' 36 else: 37 self._transition_out = 'out_right' 38 scale_origin = None 39 40 self._r = 'configControllersWindow' 41 app = bui.app 42 assert app.classic is not None 43 44 spacing = 50.0 45 button_width = 350.0 46 width = 460.0 47 height = 130.0 48 49 space_height = spacing * 0.3 50 51 # FIXME: should create vis settings under platform or app-adapter 52 # to determine whether to show this stuff; not hard code it. 53 54 show_gamepads = False 55 platform = app.classic.platform 56 subplatform = app.classic.subplatform 57 non_vr_windows = platform == 'windows' and ( 58 subplatform != 'oculus' or not app.env.vr 59 ) 60 if platform in ('linux', 'android', 'mac') or non_vr_windows: 61 show_gamepads = True 62 height += spacing 63 64 show_touch = False 65 if bs.have_touchscreen_input(): 66 show_touch = True 67 height += spacing 68 69 show_space_1 = False 70 if show_gamepads or show_touch: 71 show_space_1 = True 72 height += space_height 73 74 show_keyboard = False 75 if bs.getinputdevice('Keyboard', '#1', doraise=False) is not None: 76 show_keyboard = True 77 height += spacing 78 show_keyboard_p2 = False if app.env.vr else show_keyboard 79 if show_keyboard_p2: 80 height += spacing 81 82 show_space_2 = False 83 if show_keyboard: 84 show_space_2 = True 85 height += space_height 86 87 if bool(True): 88 show_remote = True 89 height += spacing 90 else: 91 show_remote = False 92 93 # On windows (outside of oculus/vr), show an option to disable xinput. 94 show_xinput_toggle = False 95 if platform == 'windows' and not app.env.vr: 96 show_xinput_toggle = True 97 98 # On mac builds, show an option to switch between generic and 99 # made-for-iOS/Mac systems 100 # (we can run into problems where devices register as one of each 101 # type otherwise).. 102 # UPDATE: We always use the apple system these days (which should 103 # support older controllers). So no need for a switch. 104 show_mac_controller_subsystem = False 105 # if platform == 'mac' and bui.is_xcode_build(): 106 # show_mac_controller_subsystem = True 107 108 if show_mac_controller_subsystem: 109 height += spacing * 1.5 110 111 if show_xinput_toggle: 112 height += spacing 113 114 assert bui.app.classic is not None 115 uiscale = bui.app.ui_v1.uiscale 116 smallscale = 1.7 if show_keyboard else 2.2 117 super().__init__( 118 root_widget=bui.containerwidget( 119 size=(width, height), 120 transition=transition, 121 scale_origin_stack_offset=scale_origin, 122 stack_offset=( 123 (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) 124 ), 125 scale=( 126 smallscale 127 if uiscale is bui.UIScale.SMALL 128 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 129 ), 130 ) 131 ) 132 self._back_button = btn = bui.buttonwidget( 133 parent=self._root_widget, 134 position=(35, height - 60), 135 size=(140, 65), 136 scale=0.8, 137 text_scale=1.2, 138 autoselect=True, 139 label=bui.Lstr(resource='backText'), 140 button_type='back', 141 on_activate_call=self._back, 142 ) 143 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 144 145 # We need these vars to exist even if the buttons don't. 146 self._gamepads_button: bui.Widget | None = None 147 self._touch_button: bui.Widget | None = None 148 self._keyboard_button: bui.Widget | None = None 149 self._keyboard_2_button: bui.Widget | None = None 150 self._idevices_button: bui.Widget | None = None 151 152 bui.textwidget( 153 parent=self._root_widget, 154 position=(0, height - 49), 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 bui.buttonwidget( 162 edit=btn, 163 button_type='backSmall', 164 size=(60, 60), 165 label=bui.charstr(bui.SpecialChar.BACK), 166 ) 167 168 v = height - 75 169 v -= spacing 170 171 if show_touch: 172 self._touch_button = btn = bui.buttonwidget( 173 parent=self._root_widget, 174 position=((width - button_width) / 2, v), 175 size=(button_width, 43), 176 autoselect=True, 177 label=bui.Lstr(resource=f'{self._r}.configureTouchText'), 178 on_activate_call=self._do_touchscreen, 179 ) 180 if bui.app.ui_v1.use_toolbars: 181 bui.widget( 182 edit=btn, 183 right_widget=bui.get_special_widget('party_button'), 184 ) 185 if not self._have_selected_child: 186 bui.containerwidget( 187 edit=self._root_widget, selected_child=self._touch_button 188 ) 189 bui.widget( 190 edit=self._back_button, down_widget=self._touch_button 191 ) 192 self._have_selected_child = True 193 v -= spacing 194 195 if show_gamepads: 196 self._gamepads_button = btn = bui.buttonwidget( 197 parent=self._root_widget, 198 position=((width - button_width) / 2 - 7, v), 199 size=(button_width, 43), 200 autoselect=True, 201 label=bui.Lstr(resource=f'{self._r}.configureControllersText'), 202 on_activate_call=self._do_gamepads, 203 ) 204 if bui.app.ui_v1.use_toolbars: 205 bui.widget( 206 edit=btn, 207 right_widget=bui.get_special_widget('party_button'), 208 ) 209 if not self._have_selected_child: 210 bui.containerwidget( 211 edit=self._root_widget, selected_child=self._gamepads_button 212 ) 213 bui.widget( 214 edit=self._back_button, down_widget=self._gamepads_button 215 ) 216 self._have_selected_child = True 217 v -= spacing 218 else: 219 self._gamepads_button = None 220 221 if show_space_1: 222 v -= space_height 223 224 if show_keyboard: 225 self._keyboard_button = btn = bui.buttonwidget( 226 parent=self._root_widget, 227 position=((width - button_width) / 2 - 5, v), 228 size=(button_width, 43), 229 autoselect=True, 230 label=bui.Lstr(resource=f'{self._r}.configureKeyboardText'), 231 on_activate_call=self._config_keyboard, 232 ) 233 bui.widget( 234 edit=self._keyboard_button, left_widget=self._keyboard_button 235 ) 236 if bui.app.ui_v1.use_toolbars: 237 bui.widget( 238 edit=btn, 239 right_widget=bui.get_special_widget('party_button'), 240 ) 241 if not self._have_selected_child: 242 bui.containerwidget( 243 edit=self._root_widget, selected_child=self._keyboard_button 244 ) 245 bui.widget( 246 edit=self._back_button, down_widget=self._keyboard_button 247 ) 248 self._have_selected_child = True 249 v -= spacing 250 if show_keyboard_p2: 251 self._keyboard_2_button = bui.buttonwidget( 252 parent=self._root_widget, 253 position=((width - button_width) / 2 - 3, v), 254 size=(button_width, 43), 255 autoselect=True, 256 label=bui.Lstr(resource=f'{self._r}.configureKeyboard2Text'), 257 on_activate_call=self._config_keyboard2, 258 ) 259 v -= spacing 260 bui.widget( 261 edit=self._keyboard_2_button, 262 left_widget=self._keyboard_2_button, 263 ) 264 if show_space_2: 265 v -= space_height 266 if show_remote: 267 self._idevices_button = btn = bui.buttonwidget( 268 parent=self._root_widget, 269 position=((width - button_width) / 2 - 5, v), 270 size=(button_width, 43), 271 autoselect=True, 272 label=bui.Lstr(resource=f'{self._r}.configureMobileText'), 273 on_activate_call=self._do_mobile_devices, 274 ) 275 bui.widget( 276 edit=self._idevices_button, left_widget=self._idevices_button 277 ) 278 if bui.app.ui_v1.use_toolbars: 279 bui.widget( 280 edit=btn, 281 right_widget=bui.get_special_widget('party_button'), 282 ) 283 if not self._have_selected_child: 284 bui.containerwidget( 285 edit=self._root_widget, selected_child=self._idevices_button 286 ) 287 bui.widget( 288 edit=self._back_button, down_widget=self._idevices_button 289 ) 290 self._have_selected_child = True 291 v -= spacing 292 293 if show_xinput_toggle: 294 295 def do_toggle(value: bool) -> None: 296 bui.screenmessage( 297 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 298 color=(1, 1, 0), 299 ) 300 bui.getsound('gunCocking').play() 301 bui.set_low_level_config_value('enablexinput', not value) 302 303 xinput_checkbox = bui.checkboxwidget( 304 parent=self._root_widget, 305 position=(100, v + 3), 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 if show_mac_controller_subsystem: 332 PopupMenu( 333 parent=self._root_widget, 334 position=(260, v - 10), 335 width=160, 336 button_size=(150, 50), 337 scale=1.5, 338 choices=['Classic', 'MFi', 'Both'], 339 choices_display=[ 340 bui.Lstr(resource='macControllerSubsystemClassicText'), 341 bui.Lstr(resource='macControllerSubsystemMFiText'), 342 bui.Lstr(resource='macControllerSubsystemBothText'), 343 ], 344 current_choice=bui.app.config.resolve( 345 'Mac Controller Subsystem' 346 ), 347 on_value_change_call=self._set_mac_controller_subsystem, 348 ) 349 bui.textwidget( 350 parent=self._root_widget, 351 position=(245, v + 13), 352 size=(0, 0), 353 text=bui.Lstr(resource='macControllerSubsystemTitleText'), 354 scale=1.0, 355 h_align='right', 356 v_align='center', 357 color=bui.app.ui_v1.infotextcolor, 358 maxwidth=180, 359 ) 360 bui.textwidget( 361 parent=self._root_widget, 362 position=(width * 0.5, v - 20), 363 size=(0, 0), 364 text=bui.Lstr(resource='macControllerSubsystemDescriptionText'), 365 scale=0.5, 366 h_align='center', 367 v_align='center', 368 color=bui.app.ui_v1.infotextcolor, 369 maxwidth=width * 0.8, 370 ) 371 v -= spacing * 1.5 372 373 self._restore_state()
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget