bauiv1lib.settings.gamepadadvanced
UI functionality related to advanced gamepad configuring.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality related to advanced gamepad configuring.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import bauiv1 as bui 10 11if TYPE_CHECKING: 12 from typing import Any 13 from bauiv1lib.settings.gamepad import ( 14 GamepadSettingsWindow, 15 AwaitGamepadInputWindow, 16 ) 17 18 19class GamepadAdvancedSettingsWindow(bui.Window): 20 """Window for advanced gamepad configuration.""" 21 22 def __init__(self, parent_window: GamepadSettingsWindow): 23 # pylint: disable=too-many-statements 24 # pylint: disable=too-many-locals 25 self._parent_window = parent_window 26 27 app = bui.app 28 29 self._r = parent_window.get_r() 30 assert bui.app.classic is not None 31 uiscale = bui.app.ui_v1.uiscale 32 self._width = 900 if uiscale is bui.UIScale.SMALL else 700 33 self._x_inset = x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 34 self._height = 402 if uiscale is bui.UIScale.SMALL else 512 35 self._textwidgets: dict[str, bui.Widget] = {} 36 advb = parent_window.get_advanced_button() 37 super().__init__( 38 root_widget=bui.containerwidget( 39 transition='in_scale', 40 size=(self._width, self._height), 41 scale=1.06 42 * ( 43 1.6 44 if uiscale is bui.UIScale.SMALL 45 else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 46 ), 47 stack_offset=( 48 (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) 49 ), 50 scale_origin_stack_offset=(advb.get_screen_space_center()), 51 ) 52 ) 53 54 bui.textwidget( 55 parent=self._root_widget, 56 position=( 57 self._width * 0.5, 58 self._height - (40 if uiscale is bui.UIScale.SMALL else 34), 59 ), 60 size=(0, 0), 61 text=bui.Lstr(resource=f'{self._r}.advancedTitleText'), 62 maxwidth=320, 63 color=bui.app.ui_v1.title_color, 64 h_align='center', 65 v_align='center', 66 ) 67 68 back_button = btn = bui.buttonwidget( 69 parent=self._root_widget, 70 autoselect=True, 71 position=( 72 self._width - (176 + x_inset), 73 self._height - (60 if uiscale is bui.UIScale.SMALL else 55), 74 ), 75 size=(120, 48), 76 text_scale=0.8, 77 label=bui.Lstr(resource='doneText'), 78 on_activate_call=self._done, 79 ) 80 bui.containerwidget( 81 edit=self._root_widget, 82 start_button=btn, 83 on_cancel_call=btn.activate, 84 ) 85 86 self._scroll_width = self._width - (100 + 2 * x_inset) 87 self._scroll_height = self._height - 110 88 self._sub_width = self._scroll_width - 20 89 self._sub_height = ( 90 940 if self._parent_window.get_is_secondary() else 1040 91 ) 92 if app.env.vr: 93 self._sub_height += 50 94 self._scrollwidget = bui.scrollwidget( 95 parent=self._root_widget, 96 position=( 97 (self._width - self._scroll_width) * 0.5, 98 self._height - 65 - self._scroll_height, 99 ), 100 size=(self._scroll_width, self._scroll_height), 101 claims_left_right=True, 102 selection_loops_to_parent=True, 103 ) 104 self._subcontainer = bui.containerwidget( 105 parent=self._scrollwidget, 106 size=(self._sub_width, self._sub_height), 107 background=False, 108 claims_left_right=True, 109 selection_loops_to_parent=True, 110 ) 111 bui.containerwidget( 112 edit=self._root_widget, selected_child=self._scrollwidget 113 ) 114 115 h = 30 116 v = self._sub_height - 10 117 118 h2 = h + 12 119 120 # don't allow secondary joysticks to handle unassigned buttons 121 if not self._parent_window.get_is_secondary(): 122 v -= 40 123 cb1 = bui.checkboxwidget( 124 parent=self._subcontainer, 125 position=(h + 70, v), 126 size=(500, 30), 127 text=bui.Lstr(resource=f'{self._r}.unassignedButtonsRunText'), 128 textcolor=(0.8, 0.8, 0.8), 129 maxwidth=330, 130 scale=1.0, 131 on_value_change_call=( 132 self._parent_window.set_unassigned_buttons_run_value 133 ), 134 autoselect=True, 135 value=self._parent_window.get_unassigned_buttons_run_value(), 136 ) 137 bui.widget(edit=cb1, up_widget=back_button) 138 v -= 60 139 capb = self._capture_button( 140 pos=(h2, v), 141 name=bui.Lstr(resource=f'{self._r}.runButton1Text'), 142 control='buttonRun1' + self._parent_window.get_ext(), 143 ) 144 if self._parent_window.get_is_secondary(): 145 for widget in capb: 146 bui.widget(edit=widget, up_widget=back_button) 147 v -= 42 148 self._capture_button( 149 pos=(h2, v), 150 name=bui.Lstr(resource=f'{self._r}.runButton2Text'), 151 control='buttonRun2' + self._parent_window.get_ext(), 152 ) 153 bui.textwidget( 154 parent=self._subcontainer, 155 position=(self._sub_width * 0.5, v - 24), 156 size=(0, 0), 157 text=bui.Lstr(resource=f'{self._r}.runTriggerDescriptionText'), 158 color=(0.7, 1, 0.7, 0.6), 159 maxwidth=self._sub_width * 0.8, 160 scale=0.7, 161 h_align='center', 162 v_align='center', 163 ) 164 165 v -= 85 166 167 self._capture_button( 168 pos=(h2, v), 169 name=bui.Lstr(resource=f'{self._r}.runTrigger1Text'), 170 control='triggerRun1' + self._parent_window.get_ext(), 171 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 172 ) 173 v -= 42 174 self._capture_button( 175 pos=(h2, v), 176 name=bui.Lstr(resource=f'{self._r}.runTrigger2Text'), 177 control='triggerRun2' + self._parent_window.get_ext(), 178 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 179 ) 180 181 # in vr mode, allow assigning a reset-view button 182 if app.env.vr: 183 v -= 50 184 self._capture_button( 185 pos=(h2, v), 186 name=bui.Lstr(resource=f'{self._r}.vrReorientButtonText'), 187 control='buttonVRReorient' + self._parent_window.get_ext(), 188 ) 189 190 v -= 60 191 self._capture_button( 192 pos=(h2, v), 193 name=bui.Lstr(resource=f'{self._r}.extraStartButtonText'), 194 control='buttonStart2' + self._parent_window.get_ext(), 195 ) 196 v -= 60 197 self._capture_button( 198 pos=(h2, v), 199 name=bui.Lstr(resource=f'{self._r}.ignoredButton1Text'), 200 control='buttonIgnored' + self._parent_window.get_ext(), 201 ) 202 v -= 42 203 self._capture_button( 204 pos=(h2, v), 205 name=bui.Lstr(resource=f'{self._r}.ignoredButton2Text'), 206 control='buttonIgnored2' + self._parent_window.get_ext(), 207 ) 208 v -= 42 209 self._capture_button( 210 pos=(h2, v), 211 name=bui.Lstr(resource=f'{self._r}.ignoredButton3Text'), 212 control='buttonIgnored3' + self._parent_window.get_ext(), 213 ) 214 v -= 42 215 self._capture_button( 216 pos=(h2, v), 217 name=bui.Lstr(resource=f'{self._r}.ignoredButton4Text'), 218 control='buttonIgnored4' + self._parent_window.get_ext(), 219 ) 220 bui.textwidget( 221 parent=self._subcontainer, 222 position=(self._sub_width * 0.5, v - 14), 223 size=(0, 0), 224 text=bui.Lstr(resource=f'{self._r}.ignoredButtonDescriptionText'), 225 color=(0.7, 1, 0.7, 0.6), 226 scale=0.8, 227 maxwidth=self._sub_width * 0.8, 228 h_align='center', 229 v_align='center', 230 ) 231 232 v -= 80 233 pwin = self._parent_window 234 bui.checkboxwidget( 235 parent=self._subcontainer, 236 autoselect=True, 237 position=(h + 50, v), 238 size=(400, 30), 239 text=bui.Lstr( 240 resource=f'{self._r}.startButtonActivatesDefaultText' 241 ), 242 textcolor=(0.8, 0.8, 0.8), 243 maxwidth=450, 244 scale=0.9, 245 on_value_change_call=( 246 pwin.set_start_button_activates_default_widget_value 247 ), 248 value=pwin.get_start_button_activates_default_widget_value(), 249 ) 250 bui.textwidget( 251 parent=self._subcontainer, 252 position=(self._sub_width * 0.5, v - 12), 253 size=(0, 0), 254 text=bui.Lstr( 255 resource=f'{self._r}.startButtonActivatesDefaultDescriptionText' 256 ), 257 color=(0.7, 1, 0.7, 0.6), 258 maxwidth=self._sub_width * 0.8, 259 scale=0.7, 260 h_align='center', 261 v_align='center', 262 ) 263 264 v -= 80 265 bui.checkboxwidget( 266 parent=self._subcontainer, 267 autoselect=True, 268 position=(h + 50, v), 269 size=(400, 30), 270 text=bui.Lstr(resource=f'{self._r}.uiOnlyText'), 271 textcolor=(0.8, 0.8, 0.8), 272 maxwidth=450, 273 scale=0.9, 274 on_value_change_call=self._parent_window.set_ui_only_value, 275 value=self._parent_window.get_ui_only_value(), 276 ) 277 bui.textwidget( 278 parent=self._subcontainer, 279 position=(self._sub_width * 0.5, v - 12), 280 size=(0, 0), 281 text=bui.Lstr(resource=f'{self._r}.uiOnlyDescriptionText'), 282 color=(0.7, 1, 0.7, 0.6), 283 maxwidth=self._sub_width * 0.8, 284 scale=0.7, 285 h_align='center', 286 v_align='center', 287 ) 288 289 v -= 80 290 bui.checkboxwidget( 291 parent=self._subcontainer, 292 autoselect=True, 293 position=(h + 50, v), 294 size=(400, 30), 295 text=bui.Lstr(resource=f'{self._r}.ignoreCompletelyText'), 296 textcolor=(0.8, 0.8, 0.8), 297 maxwidth=450, 298 scale=0.9, 299 on_value_change_call=pwin.set_ignore_completely_value, 300 value=self._parent_window.get_ignore_completely_value(), 301 ) 302 bui.textwidget( 303 parent=self._subcontainer, 304 position=(self._sub_width * 0.5, v - 12), 305 size=(0, 0), 306 text=bui.Lstr( 307 resource=f'{self._r}.ignoreCompletelyDescriptionText' 308 ), 309 color=(0.7, 1, 0.7, 0.6), 310 maxwidth=self._sub_width * 0.8, 311 scale=0.7, 312 h_align='center', 313 v_align='center', 314 ) 315 316 v -= 80 317 318 cb1 = bui.checkboxwidget( 319 parent=self._subcontainer, 320 autoselect=True, 321 position=(h + 50, v), 322 size=(400, 30), 323 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateText'), 324 textcolor=(0.8, 0.8, 0.8), 325 maxwidth=450, 326 scale=0.9, 327 on_value_change_call=pwin.set_auto_recalibrate_analog_stick_value, 328 value=self._parent_window.get_auto_recalibrate_analog_stick_value(), 329 ) 330 bui.textwidget( 331 parent=self._subcontainer, 332 position=(self._sub_width * 0.5, v - 12), 333 size=(0, 0), 334 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateDescriptionText'), 335 color=(0.7, 1, 0.7, 0.6), 336 maxwidth=self._sub_width * 0.8, 337 scale=0.7, 338 h_align='center', 339 v_align='center', 340 ) 341 v -= 80 342 343 buttons = self._config_value_editor( 344 bui.Lstr(resource=f'{self._r}.analogStickDeadZoneText'), 345 control=('analogStickDeadZone' + self._parent_window.get_ext()), 346 position=(h + 40, v), 347 min_val=0, 348 max_val=10.0, 349 increment=0.1, 350 x_offset=100, 351 ) 352 bui.widget(edit=buttons[0], left_widget=cb1, up_widget=cb1) 353 bui.widget(edit=cb1, right_widget=buttons[0], down_widget=buttons[0]) 354 355 bui.textwidget( 356 parent=self._subcontainer, 357 position=(self._sub_width * 0.5, v - 12), 358 size=(0, 0), 359 text=bui.Lstr( 360 resource=f'{self._r}.analogStickDeadZoneDescriptionText' 361 ), 362 color=(0.7, 1, 0.7, 0.6), 363 maxwidth=self._sub_width * 0.8, 364 scale=0.7, 365 h_align='center', 366 v_align='center', 367 ) 368 v -= 100 369 370 # child joysticks cant have child joysticks.. that's just 371 # crazy talk 372 if not self._parent_window.get_is_secondary(): 373 bui.buttonwidget( 374 parent=self._subcontainer, 375 autoselect=True, 376 label=bui.Lstr(resource=f'{self._r}.twoInOneSetupText'), 377 position=(40, v), 378 size=(self._sub_width - 80, 50), 379 on_activate_call=self._parent_window.show_secondary_editor, 380 up_widget=buttons[0], 381 ) 382 383 # set a bigger bottom show-buffer for the widgets we just made 384 # so we can see the text below them when navigating with 385 # a gamepad 386 for child in self._subcontainer.get_children(): 387 bui.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30) 388 389 def _capture_button( 390 self, 391 pos: tuple[float, float], 392 name: bui.Lstr, 393 control: str, 394 message: bui.Lstr | None = None, 395 ) -> tuple[bui.Widget, bui.Widget]: 396 if message is None: 397 message = bui.Lstr( 398 resource=self._parent_window.get_r() + '.pressAnyButtonText' 399 ) 400 btn = bui.buttonwidget( 401 parent=self._subcontainer, 402 autoselect=True, 403 position=(pos[0], pos[1]), 404 label=name, 405 size=(250, 60), 406 scale=0.7, 407 ) 408 btn2 = bui.buttonwidget( 409 parent=self._subcontainer, 410 autoselect=True, 411 position=(pos[0] + 400, pos[1] + 2), 412 left_widget=btn, 413 color=(0.45, 0.4, 0.5), 414 textcolor=(0.65, 0.6, 0.7), 415 label=bui.Lstr(resource=f'{self._r}.clearText'), 416 size=(110, 50), 417 scale=0.7, 418 on_activate_call=bui.Call(self._clear_control, control), 419 ) 420 bui.widget(edit=btn, right_widget=btn2) 421 422 # make this in a timer so that it shows up on top of all 423 # other buttons 424 425 def doit() -> None: 426 from bauiv1lib.settings.gamepad import AwaitGamepadInputWindow 427 428 txt = bui.textwidget( 429 parent=self._subcontainer, 430 position=(pos[0] + 285, pos[1] + 20), 431 color=(1, 1, 1, 0.3), 432 size=(0, 0), 433 h_align='center', 434 v_align='center', 435 scale=0.7, 436 text=self._parent_window.get_control_value_name(control), 437 maxwidth=200, 438 ) 439 self._textwidgets[control] = txt 440 bui.buttonwidget( 441 edit=btn, 442 on_activate_call=bui.Call( 443 AwaitGamepadInputWindow, 444 self._parent_window.get_input(), 445 control, 446 self._gamepad_event, 447 message, 448 ), 449 ) 450 451 bui.pushcall(doit) 452 return btn, btn2 453 454 def _inc( 455 self, control: str, min_val: float, max_val: float, inc: float 456 ) -> None: 457 val = self._parent_window.get_settings().get(control, 1.0) 458 val = min(max_val, max(min_val, val + inc)) 459 if abs(1.0 - val) < 0.001: 460 if control in self._parent_window.get_settings(): 461 del self._parent_window.get_settings()[control] 462 else: 463 self._parent_window.get_settings()[control] = round(val, 1) 464 bui.textwidget( 465 edit=self._textwidgets[control], 466 text=self._parent_window.get_control_value_name(control), 467 ) 468 469 def _config_value_editor( 470 self, 471 name: bui.Lstr, 472 control: str, 473 position: tuple[float, float], 474 *, 475 min_val: float = 0.0, 476 max_val: float = 100.0, 477 increment: float = 1.0, 478 change_sound: bool = True, 479 x_offset: float = 0.0, 480 displayname: bui.Lstr | None = None, 481 ) -> tuple[bui.Widget, bui.Widget]: 482 if displayname is None: 483 displayname = name 484 bui.textwidget( 485 parent=self._subcontainer, 486 position=position, 487 size=(100, 30), 488 text=displayname, 489 color=(0.8, 0.8, 0.8, 1.0), 490 h_align='left', 491 v_align='center', 492 scale=1.0, 493 maxwidth=280, 494 ) 495 self._textwidgets[control] = bui.textwidget( 496 parent=self._subcontainer, 497 position=(246.0 + x_offset, position[1]), 498 size=(60, 28), 499 editable=False, 500 color=(0.3, 1.0, 0.3, 1.0), 501 h_align='right', 502 v_align='center', 503 text=self._parent_window.get_control_value_name(control), 504 padding=2, 505 ) 506 btn = bui.buttonwidget( 507 parent=self._subcontainer, 508 autoselect=True, 509 position=(330 + x_offset, position[1] + 4), 510 size=(28, 28), 511 label='-', 512 on_activate_call=bui.Call( 513 self._inc, control, min_val, max_val, -increment 514 ), 515 repeat=True, 516 enable_sound=(change_sound is True), 517 ) 518 btn2 = bui.buttonwidget( 519 parent=self._subcontainer, 520 autoselect=True, 521 position=(380 + x_offset, position[1] + 4), 522 size=(28, 28), 523 label='+', 524 on_activate_call=bui.Call( 525 self._inc, control, min_val, max_val, increment 526 ), 527 repeat=True, 528 enable_sound=(change_sound is True), 529 ) 530 return btn, btn2 531 532 def _clear_control(self, control: str) -> None: 533 if control in self._parent_window.get_settings(): 534 del self._parent_window.get_settings()[control] 535 bui.textwidget( 536 edit=self._textwidgets[control], 537 text=self._parent_window.get_control_value_name(control), 538 ) 539 540 def _gamepad_event( 541 self, 542 control: str, 543 event: dict[str, Any], 544 dialog: AwaitGamepadInputWindow, 545 ) -> None: 546 ext = self._parent_window.get_ext() 547 if control in ['triggerRun1' + ext, 'triggerRun2' + ext]: 548 if event['type'] == 'AXISMOTION': 549 # ignore small values or else we might get triggered 550 # by noise 551 if abs(event['value']) > 0.5: 552 self._parent_window.get_settings()[control] = event['axis'] 553 # update the button's text widget 554 if self._textwidgets[control]: 555 bui.textwidget( 556 edit=self._textwidgets[control], 557 text=self._parent_window.get_control_value_name( 558 control 559 ), 560 ) 561 bui.getsound('gunCocking').play() 562 dialog.die() 563 else: 564 if event['type'] == 'BUTTONDOWN': 565 value = event['button'] 566 self._parent_window.get_settings()[control] = value 567 # update the button's text widget 568 if self._textwidgets[control]: 569 bui.textwidget( 570 edit=self._textwidgets[control], 571 text=self._parent_window.get_control_value_name( 572 control 573 ), 574 ) 575 bui.getsound('gunCocking').play() 576 dialog.die() 577 578 def _done(self) -> None: 579 bui.containerwidget(edit=self._root_widget, transition='out_scale')
class
GamepadAdvancedSettingsWindow(bauiv1._uitypes.Window):
20class GamepadAdvancedSettingsWindow(bui.Window): 21 """Window for advanced gamepad configuration.""" 22 23 def __init__(self, parent_window: GamepadSettingsWindow): 24 # pylint: disable=too-many-statements 25 # pylint: disable=too-many-locals 26 self._parent_window = parent_window 27 28 app = bui.app 29 30 self._r = parent_window.get_r() 31 assert bui.app.classic is not None 32 uiscale = bui.app.ui_v1.uiscale 33 self._width = 900 if uiscale is bui.UIScale.SMALL else 700 34 self._x_inset = x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 35 self._height = 402 if uiscale is bui.UIScale.SMALL else 512 36 self._textwidgets: dict[str, bui.Widget] = {} 37 advb = parent_window.get_advanced_button() 38 super().__init__( 39 root_widget=bui.containerwidget( 40 transition='in_scale', 41 size=(self._width, self._height), 42 scale=1.06 43 * ( 44 1.6 45 if uiscale is bui.UIScale.SMALL 46 else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 47 ), 48 stack_offset=( 49 (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) 50 ), 51 scale_origin_stack_offset=(advb.get_screen_space_center()), 52 ) 53 ) 54 55 bui.textwidget( 56 parent=self._root_widget, 57 position=( 58 self._width * 0.5, 59 self._height - (40 if uiscale is bui.UIScale.SMALL else 34), 60 ), 61 size=(0, 0), 62 text=bui.Lstr(resource=f'{self._r}.advancedTitleText'), 63 maxwidth=320, 64 color=bui.app.ui_v1.title_color, 65 h_align='center', 66 v_align='center', 67 ) 68 69 back_button = btn = bui.buttonwidget( 70 parent=self._root_widget, 71 autoselect=True, 72 position=( 73 self._width - (176 + x_inset), 74 self._height - (60 if uiscale is bui.UIScale.SMALL else 55), 75 ), 76 size=(120, 48), 77 text_scale=0.8, 78 label=bui.Lstr(resource='doneText'), 79 on_activate_call=self._done, 80 ) 81 bui.containerwidget( 82 edit=self._root_widget, 83 start_button=btn, 84 on_cancel_call=btn.activate, 85 ) 86 87 self._scroll_width = self._width - (100 + 2 * x_inset) 88 self._scroll_height = self._height - 110 89 self._sub_width = self._scroll_width - 20 90 self._sub_height = ( 91 940 if self._parent_window.get_is_secondary() else 1040 92 ) 93 if app.env.vr: 94 self._sub_height += 50 95 self._scrollwidget = bui.scrollwidget( 96 parent=self._root_widget, 97 position=( 98 (self._width - self._scroll_width) * 0.5, 99 self._height - 65 - self._scroll_height, 100 ), 101 size=(self._scroll_width, self._scroll_height), 102 claims_left_right=True, 103 selection_loops_to_parent=True, 104 ) 105 self._subcontainer = bui.containerwidget( 106 parent=self._scrollwidget, 107 size=(self._sub_width, self._sub_height), 108 background=False, 109 claims_left_right=True, 110 selection_loops_to_parent=True, 111 ) 112 bui.containerwidget( 113 edit=self._root_widget, selected_child=self._scrollwidget 114 ) 115 116 h = 30 117 v = self._sub_height - 10 118 119 h2 = h + 12 120 121 # don't allow secondary joysticks to handle unassigned buttons 122 if not self._parent_window.get_is_secondary(): 123 v -= 40 124 cb1 = bui.checkboxwidget( 125 parent=self._subcontainer, 126 position=(h + 70, v), 127 size=(500, 30), 128 text=bui.Lstr(resource=f'{self._r}.unassignedButtonsRunText'), 129 textcolor=(0.8, 0.8, 0.8), 130 maxwidth=330, 131 scale=1.0, 132 on_value_change_call=( 133 self._parent_window.set_unassigned_buttons_run_value 134 ), 135 autoselect=True, 136 value=self._parent_window.get_unassigned_buttons_run_value(), 137 ) 138 bui.widget(edit=cb1, up_widget=back_button) 139 v -= 60 140 capb = self._capture_button( 141 pos=(h2, v), 142 name=bui.Lstr(resource=f'{self._r}.runButton1Text'), 143 control='buttonRun1' + self._parent_window.get_ext(), 144 ) 145 if self._parent_window.get_is_secondary(): 146 for widget in capb: 147 bui.widget(edit=widget, up_widget=back_button) 148 v -= 42 149 self._capture_button( 150 pos=(h2, v), 151 name=bui.Lstr(resource=f'{self._r}.runButton2Text'), 152 control='buttonRun2' + self._parent_window.get_ext(), 153 ) 154 bui.textwidget( 155 parent=self._subcontainer, 156 position=(self._sub_width * 0.5, v - 24), 157 size=(0, 0), 158 text=bui.Lstr(resource=f'{self._r}.runTriggerDescriptionText'), 159 color=(0.7, 1, 0.7, 0.6), 160 maxwidth=self._sub_width * 0.8, 161 scale=0.7, 162 h_align='center', 163 v_align='center', 164 ) 165 166 v -= 85 167 168 self._capture_button( 169 pos=(h2, v), 170 name=bui.Lstr(resource=f'{self._r}.runTrigger1Text'), 171 control='triggerRun1' + self._parent_window.get_ext(), 172 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 173 ) 174 v -= 42 175 self._capture_button( 176 pos=(h2, v), 177 name=bui.Lstr(resource=f'{self._r}.runTrigger2Text'), 178 control='triggerRun2' + self._parent_window.get_ext(), 179 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 180 ) 181 182 # in vr mode, allow assigning a reset-view button 183 if app.env.vr: 184 v -= 50 185 self._capture_button( 186 pos=(h2, v), 187 name=bui.Lstr(resource=f'{self._r}.vrReorientButtonText'), 188 control='buttonVRReorient' + self._parent_window.get_ext(), 189 ) 190 191 v -= 60 192 self._capture_button( 193 pos=(h2, v), 194 name=bui.Lstr(resource=f'{self._r}.extraStartButtonText'), 195 control='buttonStart2' + self._parent_window.get_ext(), 196 ) 197 v -= 60 198 self._capture_button( 199 pos=(h2, v), 200 name=bui.Lstr(resource=f'{self._r}.ignoredButton1Text'), 201 control='buttonIgnored' + self._parent_window.get_ext(), 202 ) 203 v -= 42 204 self._capture_button( 205 pos=(h2, v), 206 name=bui.Lstr(resource=f'{self._r}.ignoredButton2Text'), 207 control='buttonIgnored2' + self._parent_window.get_ext(), 208 ) 209 v -= 42 210 self._capture_button( 211 pos=(h2, v), 212 name=bui.Lstr(resource=f'{self._r}.ignoredButton3Text'), 213 control='buttonIgnored3' + self._parent_window.get_ext(), 214 ) 215 v -= 42 216 self._capture_button( 217 pos=(h2, v), 218 name=bui.Lstr(resource=f'{self._r}.ignoredButton4Text'), 219 control='buttonIgnored4' + self._parent_window.get_ext(), 220 ) 221 bui.textwidget( 222 parent=self._subcontainer, 223 position=(self._sub_width * 0.5, v - 14), 224 size=(0, 0), 225 text=bui.Lstr(resource=f'{self._r}.ignoredButtonDescriptionText'), 226 color=(0.7, 1, 0.7, 0.6), 227 scale=0.8, 228 maxwidth=self._sub_width * 0.8, 229 h_align='center', 230 v_align='center', 231 ) 232 233 v -= 80 234 pwin = self._parent_window 235 bui.checkboxwidget( 236 parent=self._subcontainer, 237 autoselect=True, 238 position=(h + 50, v), 239 size=(400, 30), 240 text=bui.Lstr( 241 resource=f'{self._r}.startButtonActivatesDefaultText' 242 ), 243 textcolor=(0.8, 0.8, 0.8), 244 maxwidth=450, 245 scale=0.9, 246 on_value_change_call=( 247 pwin.set_start_button_activates_default_widget_value 248 ), 249 value=pwin.get_start_button_activates_default_widget_value(), 250 ) 251 bui.textwidget( 252 parent=self._subcontainer, 253 position=(self._sub_width * 0.5, v - 12), 254 size=(0, 0), 255 text=bui.Lstr( 256 resource=f'{self._r}.startButtonActivatesDefaultDescriptionText' 257 ), 258 color=(0.7, 1, 0.7, 0.6), 259 maxwidth=self._sub_width * 0.8, 260 scale=0.7, 261 h_align='center', 262 v_align='center', 263 ) 264 265 v -= 80 266 bui.checkboxwidget( 267 parent=self._subcontainer, 268 autoselect=True, 269 position=(h + 50, v), 270 size=(400, 30), 271 text=bui.Lstr(resource=f'{self._r}.uiOnlyText'), 272 textcolor=(0.8, 0.8, 0.8), 273 maxwidth=450, 274 scale=0.9, 275 on_value_change_call=self._parent_window.set_ui_only_value, 276 value=self._parent_window.get_ui_only_value(), 277 ) 278 bui.textwidget( 279 parent=self._subcontainer, 280 position=(self._sub_width * 0.5, v - 12), 281 size=(0, 0), 282 text=bui.Lstr(resource=f'{self._r}.uiOnlyDescriptionText'), 283 color=(0.7, 1, 0.7, 0.6), 284 maxwidth=self._sub_width * 0.8, 285 scale=0.7, 286 h_align='center', 287 v_align='center', 288 ) 289 290 v -= 80 291 bui.checkboxwidget( 292 parent=self._subcontainer, 293 autoselect=True, 294 position=(h + 50, v), 295 size=(400, 30), 296 text=bui.Lstr(resource=f'{self._r}.ignoreCompletelyText'), 297 textcolor=(0.8, 0.8, 0.8), 298 maxwidth=450, 299 scale=0.9, 300 on_value_change_call=pwin.set_ignore_completely_value, 301 value=self._parent_window.get_ignore_completely_value(), 302 ) 303 bui.textwidget( 304 parent=self._subcontainer, 305 position=(self._sub_width * 0.5, v - 12), 306 size=(0, 0), 307 text=bui.Lstr( 308 resource=f'{self._r}.ignoreCompletelyDescriptionText' 309 ), 310 color=(0.7, 1, 0.7, 0.6), 311 maxwidth=self._sub_width * 0.8, 312 scale=0.7, 313 h_align='center', 314 v_align='center', 315 ) 316 317 v -= 80 318 319 cb1 = bui.checkboxwidget( 320 parent=self._subcontainer, 321 autoselect=True, 322 position=(h + 50, v), 323 size=(400, 30), 324 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateText'), 325 textcolor=(0.8, 0.8, 0.8), 326 maxwidth=450, 327 scale=0.9, 328 on_value_change_call=pwin.set_auto_recalibrate_analog_stick_value, 329 value=self._parent_window.get_auto_recalibrate_analog_stick_value(), 330 ) 331 bui.textwidget( 332 parent=self._subcontainer, 333 position=(self._sub_width * 0.5, v - 12), 334 size=(0, 0), 335 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateDescriptionText'), 336 color=(0.7, 1, 0.7, 0.6), 337 maxwidth=self._sub_width * 0.8, 338 scale=0.7, 339 h_align='center', 340 v_align='center', 341 ) 342 v -= 80 343 344 buttons = self._config_value_editor( 345 bui.Lstr(resource=f'{self._r}.analogStickDeadZoneText'), 346 control=('analogStickDeadZone' + self._parent_window.get_ext()), 347 position=(h + 40, v), 348 min_val=0, 349 max_val=10.0, 350 increment=0.1, 351 x_offset=100, 352 ) 353 bui.widget(edit=buttons[0], left_widget=cb1, up_widget=cb1) 354 bui.widget(edit=cb1, right_widget=buttons[0], down_widget=buttons[0]) 355 356 bui.textwidget( 357 parent=self._subcontainer, 358 position=(self._sub_width * 0.5, v - 12), 359 size=(0, 0), 360 text=bui.Lstr( 361 resource=f'{self._r}.analogStickDeadZoneDescriptionText' 362 ), 363 color=(0.7, 1, 0.7, 0.6), 364 maxwidth=self._sub_width * 0.8, 365 scale=0.7, 366 h_align='center', 367 v_align='center', 368 ) 369 v -= 100 370 371 # child joysticks cant have child joysticks.. that's just 372 # crazy talk 373 if not self._parent_window.get_is_secondary(): 374 bui.buttonwidget( 375 parent=self._subcontainer, 376 autoselect=True, 377 label=bui.Lstr(resource=f'{self._r}.twoInOneSetupText'), 378 position=(40, v), 379 size=(self._sub_width - 80, 50), 380 on_activate_call=self._parent_window.show_secondary_editor, 381 up_widget=buttons[0], 382 ) 383 384 # set a bigger bottom show-buffer for the widgets we just made 385 # so we can see the text below them when navigating with 386 # a gamepad 387 for child in self._subcontainer.get_children(): 388 bui.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30) 389 390 def _capture_button( 391 self, 392 pos: tuple[float, float], 393 name: bui.Lstr, 394 control: str, 395 message: bui.Lstr | None = None, 396 ) -> tuple[bui.Widget, bui.Widget]: 397 if message is None: 398 message = bui.Lstr( 399 resource=self._parent_window.get_r() + '.pressAnyButtonText' 400 ) 401 btn = bui.buttonwidget( 402 parent=self._subcontainer, 403 autoselect=True, 404 position=(pos[0], pos[1]), 405 label=name, 406 size=(250, 60), 407 scale=0.7, 408 ) 409 btn2 = bui.buttonwidget( 410 parent=self._subcontainer, 411 autoselect=True, 412 position=(pos[0] + 400, pos[1] + 2), 413 left_widget=btn, 414 color=(0.45, 0.4, 0.5), 415 textcolor=(0.65, 0.6, 0.7), 416 label=bui.Lstr(resource=f'{self._r}.clearText'), 417 size=(110, 50), 418 scale=0.7, 419 on_activate_call=bui.Call(self._clear_control, control), 420 ) 421 bui.widget(edit=btn, right_widget=btn2) 422 423 # make this in a timer so that it shows up on top of all 424 # other buttons 425 426 def doit() -> None: 427 from bauiv1lib.settings.gamepad import AwaitGamepadInputWindow 428 429 txt = bui.textwidget( 430 parent=self._subcontainer, 431 position=(pos[0] + 285, pos[1] + 20), 432 color=(1, 1, 1, 0.3), 433 size=(0, 0), 434 h_align='center', 435 v_align='center', 436 scale=0.7, 437 text=self._parent_window.get_control_value_name(control), 438 maxwidth=200, 439 ) 440 self._textwidgets[control] = txt 441 bui.buttonwidget( 442 edit=btn, 443 on_activate_call=bui.Call( 444 AwaitGamepadInputWindow, 445 self._parent_window.get_input(), 446 control, 447 self._gamepad_event, 448 message, 449 ), 450 ) 451 452 bui.pushcall(doit) 453 return btn, btn2 454 455 def _inc( 456 self, control: str, min_val: float, max_val: float, inc: float 457 ) -> None: 458 val = self._parent_window.get_settings().get(control, 1.0) 459 val = min(max_val, max(min_val, val + inc)) 460 if abs(1.0 - val) < 0.001: 461 if control in self._parent_window.get_settings(): 462 del self._parent_window.get_settings()[control] 463 else: 464 self._parent_window.get_settings()[control] = round(val, 1) 465 bui.textwidget( 466 edit=self._textwidgets[control], 467 text=self._parent_window.get_control_value_name(control), 468 ) 469 470 def _config_value_editor( 471 self, 472 name: bui.Lstr, 473 control: str, 474 position: tuple[float, float], 475 *, 476 min_val: float = 0.0, 477 max_val: float = 100.0, 478 increment: float = 1.0, 479 change_sound: bool = True, 480 x_offset: float = 0.0, 481 displayname: bui.Lstr | None = None, 482 ) -> tuple[bui.Widget, bui.Widget]: 483 if displayname is None: 484 displayname = name 485 bui.textwidget( 486 parent=self._subcontainer, 487 position=position, 488 size=(100, 30), 489 text=displayname, 490 color=(0.8, 0.8, 0.8, 1.0), 491 h_align='left', 492 v_align='center', 493 scale=1.0, 494 maxwidth=280, 495 ) 496 self._textwidgets[control] = bui.textwidget( 497 parent=self._subcontainer, 498 position=(246.0 + x_offset, position[1]), 499 size=(60, 28), 500 editable=False, 501 color=(0.3, 1.0, 0.3, 1.0), 502 h_align='right', 503 v_align='center', 504 text=self._parent_window.get_control_value_name(control), 505 padding=2, 506 ) 507 btn = bui.buttonwidget( 508 parent=self._subcontainer, 509 autoselect=True, 510 position=(330 + x_offset, position[1] + 4), 511 size=(28, 28), 512 label='-', 513 on_activate_call=bui.Call( 514 self._inc, control, min_val, max_val, -increment 515 ), 516 repeat=True, 517 enable_sound=(change_sound is True), 518 ) 519 btn2 = bui.buttonwidget( 520 parent=self._subcontainer, 521 autoselect=True, 522 position=(380 + x_offset, position[1] + 4), 523 size=(28, 28), 524 label='+', 525 on_activate_call=bui.Call( 526 self._inc, control, min_val, max_val, increment 527 ), 528 repeat=True, 529 enable_sound=(change_sound is True), 530 ) 531 return btn, btn2 532 533 def _clear_control(self, control: str) -> None: 534 if control in self._parent_window.get_settings(): 535 del self._parent_window.get_settings()[control] 536 bui.textwidget( 537 edit=self._textwidgets[control], 538 text=self._parent_window.get_control_value_name(control), 539 ) 540 541 def _gamepad_event( 542 self, 543 control: str, 544 event: dict[str, Any], 545 dialog: AwaitGamepadInputWindow, 546 ) -> None: 547 ext = self._parent_window.get_ext() 548 if control in ['triggerRun1' + ext, 'triggerRun2' + ext]: 549 if event['type'] == 'AXISMOTION': 550 # ignore small values or else we might get triggered 551 # by noise 552 if abs(event['value']) > 0.5: 553 self._parent_window.get_settings()[control] = event['axis'] 554 # update the button's text widget 555 if self._textwidgets[control]: 556 bui.textwidget( 557 edit=self._textwidgets[control], 558 text=self._parent_window.get_control_value_name( 559 control 560 ), 561 ) 562 bui.getsound('gunCocking').play() 563 dialog.die() 564 else: 565 if event['type'] == 'BUTTONDOWN': 566 value = event['button'] 567 self._parent_window.get_settings()[control] = value 568 # update the button's text widget 569 if self._textwidgets[control]: 570 bui.textwidget( 571 edit=self._textwidgets[control], 572 text=self._parent_window.get_control_value_name( 573 control 574 ), 575 ) 576 bui.getsound('gunCocking').play() 577 dialog.die() 578 579 def _done(self) -> None: 580 bui.containerwidget(edit=self._root_widget, transition='out_scale')
Window for advanced gamepad configuration.
GamepadAdvancedSettingsWindow(parent_window: bauiv1lib.settings.gamepad.GamepadSettingsWindow)
23 def __init__(self, parent_window: GamepadSettingsWindow): 24 # pylint: disable=too-many-statements 25 # pylint: disable=too-many-locals 26 self._parent_window = parent_window 27 28 app = bui.app 29 30 self._r = parent_window.get_r() 31 assert bui.app.classic is not None 32 uiscale = bui.app.ui_v1.uiscale 33 self._width = 900 if uiscale is bui.UIScale.SMALL else 700 34 self._x_inset = x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 35 self._height = 402 if uiscale is bui.UIScale.SMALL else 512 36 self._textwidgets: dict[str, bui.Widget] = {} 37 advb = parent_window.get_advanced_button() 38 super().__init__( 39 root_widget=bui.containerwidget( 40 transition='in_scale', 41 size=(self._width, self._height), 42 scale=1.06 43 * ( 44 1.6 45 if uiscale is bui.UIScale.SMALL 46 else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 47 ), 48 stack_offset=( 49 (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) 50 ), 51 scale_origin_stack_offset=(advb.get_screen_space_center()), 52 ) 53 ) 54 55 bui.textwidget( 56 parent=self._root_widget, 57 position=( 58 self._width * 0.5, 59 self._height - (40 if uiscale is bui.UIScale.SMALL else 34), 60 ), 61 size=(0, 0), 62 text=bui.Lstr(resource=f'{self._r}.advancedTitleText'), 63 maxwidth=320, 64 color=bui.app.ui_v1.title_color, 65 h_align='center', 66 v_align='center', 67 ) 68 69 back_button = btn = bui.buttonwidget( 70 parent=self._root_widget, 71 autoselect=True, 72 position=( 73 self._width - (176 + x_inset), 74 self._height - (60 if uiscale is bui.UIScale.SMALL else 55), 75 ), 76 size=(120, 48), 77 text_scale=0.8, 78 label=bui.Lstr(resource='doneText'), 79 on_activate_call=self._done, 80 ) 81 bui.containerwidget( 82 edit=self._root_widget, 83 start_button=btn, 84 on_cancel_call=btn.activate, 85 ) 86 87 self._scroll_width = self._width - (100 + 2 * x_inset) 88 self._scroll_height = self._height - 110 89 self._sub_width = self._scroll_width - 20 90 self._sub_height = ( 91 940 if self._parent_window.get_is_secondary() else 1040 92 ) 93 if app.env.vr: 94 self._sub_height += 50 95 self._scrollwidget = bui.scrollwidget( 96 parent=self._root_widget, 97 position=( 98 (self._width - self._scroll_width) * 0.5, 99 self._height - 65 - self._scroll_height, 100 ), 101 size=(self._scroll_width, self._scroll_height), 102 claims_left_right=True, 103 selection_loops_to_parent=True, 104 ) 105 self._subcontainer = bui.containerwidget( 106 parent=self._scrollwidget, 107 size=(self._sub_width, self._sub_height), 108 background=False, 109 claims_left_right=True, 110 selection_loops_to_parent=True, 111 ) 112 bui.containerwidget( 113 edit=self._root_widget, selected_child=self._scrollwidget 114 ) 115 116 h = 30 117 v = self._sub_height - 10 118 119 h2 = h + 12 120 121 # don't allow secondary joysticks to handle unassigned buttons 122 if not self._parent_window.get_is_secondary(): 123 v -= 40 124 cb1 = bui.checkboxwidget( 125 parent=self._subcontainer, 126 position=(h + 70, v), 127 size=(500, 30), 128 text=bui.Lstr(resource=f'{self._r}.unassignedButtonsRunText'), 129 textcolor=(0.8, 0.8, 0.8), 130 maxwidth=330, 131 scale=1.0, 132 on_value_change_call=( 133 self._parent_window.set_unassigned_buttons_run_value 134 ), 135 autoselect=True, 136 value=self._parent_window.get_unassigned_buttons_run_value(), 137 ) 138 bui.widget(edit=cb1, up_widget=back_button) 139 v -= 60 140 capb = self._capture_button( 141 pos=(h2, v), 142 name=bui.Lstr(resource=f'{self._r}.runButton1Text'), 143 control='buttonRun1' + self._parent_window.get_ext(), 144 ) 145 if self._parent_window.get_is_secondary(): 146 for widget in capb: 147 bui.widget(edit=widget, up_widget=back_button) 148 v -= 42 149 self._capture_button( 150 pos=(h2, v), 151 name=bui.Lstr(resource=f'{self._r}.runButton2Text'), 152 control='buttonRun2' + self._parent_window.get_ext(), 153 ) 154 bui.textwidget( 155 parent=self._subcontainer, 156 position=(self._sub_width * 0.5, v - 24), 157 size=(0, 0), 158 text=bui.Lstr(resource=f'{self._r}.runTriggerDescriptionText'), 159 color=(0.7, 1, 0.7, 0.6), 160 maxwidth=self._sub_width * 0.8, 161 scale=0.7, 162 h_align='center', 163 v_align='center', 164 ) 165 166 v -= 85 167 168 self._capture_button( 169 pos=(h2, v), 170 name=bui.Lstr(resource=f'{self._r}.runTrigger1Text'), 171 control='triggerRun1' + self._parent_window.get_ext(), 172 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 173 ) 174 v -= 42 175 self._capture_button( 176 pos=(h2, v), 177 name=bui.Lstr(resource=f'{self._r}.runTrigger2Text'), 178 control='triggerRun2' + self._parent_window.get_ext(), 179 message=bui.Lstr(resource=f'{self._r}.pressAnyAnalogTriggerText'), 180 ) 181 182 # in vr mode, allow assigning a reset-view button 183 if app.env.vr: 184 v -= 50 185 self._capture_button( 186 pos=(h2, v), 187 name=bui.Lstr(resource=f'{self._r}.vrReorientButtonText'), 188 control='buttonVRReorient' + self._parent_window.get_ext(), 189 ) 190 191 v -= 60 192 self._capture_button( 193 pos=(h2, v), 194 name=bui.Lstr(resource=f'{self._r}.extraStartButtonText'), 195 control='buttonStart2' + self._parent_window.get_ext(), 196 ) 197 v -= 60 198 self._capture_button( 199 pos=(h2, v), 200 name=bui.Lstr(resource=f'{self._r}.ignoredButton1Text'), 201 control='buttonIgnored' + self._parent_window.get_ext(), 202 ) 203 v -= 42 204 self._capture_button( 205 pos=(h2, v), 206 name=bui.Lstr(resource=f'{self._r}.ignoredButton2Text'), 207 control='buttonIgnored2' + self._parent_window.get_ext(), 208 ) 209 v -= 42 210 self._capture_button( 211 pos=(h2, v), 212 name=bui.Lstr(resource=f'{self._r}.ignoredButton3Text'), 213 control='buttonIgnored3' + self._parent_window.get_ext(), 214 ) 215 v -= 42 216 self._capture_button( 217 pos=(h2, v), 218 name=bui.Lstr(resource=f'{self._r}.ignoredButton4Text'), 219 control='buttonIgnored4' + self._parent_window.get_ext(), 220 ) 221 bui.textwidget( 222 parent=self._subcontainer, 223 position=(self._sub_width * 0.5, v - 14), 224 size=(0, 0), 225 text=bui.Lstr(resource=f'{self._r}.ignoredButtonDescriptionText'), 226 color=(0.7, 1, 0.7, 0.6), 227 scale=0.8, 228 maxwidth=self._sub_width * 0.8, 229 h_align='center', 230 v_align='center', 231 ) 232 233 v -= 80 234 pwin = self._parent_window 235 bui.checkboxwidget( 236 parent=self._subcontainer, 237 autoselect=True, 238 position=(h + 50, v), 239 size=(400, 30), 240 text=bui.Lstr( 241 resource=f'{self._r}.startButtonActivatesDefaultText' 242 ), 243 textcolor=(0.8, 0.8, 0.8), 244 maxwidth=450, 245 scale=0.9, 246 on_value_change_call=( 247 pwin.set_start_button_activates_default_widget_value 248 ), 249 value=pwin.get_start_button_activates_default_widget_value(), 250 ) 251 bui.textwidget( 252 parent=self._subcontainer, 253 position=(self._sub_width * 0.5, v - 12), 254 size=(0, 0), 255 text=bui.Lstr( 256 resource=f'{self._r}.startButtonActivatesDefaultDescriptionText' 257 ), 258 color=(0.7, 1, 0.7, 0.6), 259 maxwidth=self._sub_width * 0.8, 260 scale=0.7, 261 h_align='center', 262 v_align='center', 263 ) 264 265 v -= 80 266 bui.checkboxwidget( 267 parent=self._subcontainer, 268 autoselect=True, 269 position=(h + 50, v), 270 size=(400, 30), 271 text=bui.Lstr(resource=f'{self._r}.uiOnlyText'), 272 textcolor=(0.8, 0.8, 0.8), 273 maxwidth=450, 274 scale=0.9, 275 on_value_change_call=self._parent_window.set_ui_only_value, 276 value=self._parent_window.get_ui_only_value(), 277 ) 278 bui.textwidget( 279 parent=self._subcontainer, 280 position=(self._sub_width * 0.5, v - 12), 281 size=(0, 0), 282 text=bui.Lstr(resource=f'{self._r}.uiOnlyDescriptionText'), 283 color=(0.7, 1, 0.7, 0.6), 284 maxwidth=self._sub_width * 0.8, 285 scale=0.7, 286 h_align='center', 287 v_align='center', 288 ) 289 290 v -= 80 291 bui.checkboxwidget( 292 parent=self._subcontainer, 293 autoselect=True, 294 position=(h + 50, v), 295 size=(400, 30), 296 text=bui.Lstr(resource=f'{self._r}.ignoreCompletelyText'), 297 textcolor=(0.8, 0.8, 0.8), 298 maxwidth=450, 299 scale=0.9, 300 on_value_change_call=pwin.set_ignore_completely_value, 301 value=self._parent_window.get_ignore_completely_value(), 302 ) 303 bui.textwidget( 304 parent=self._subcontainer, 305 position=(self._sub_width * 0.5, v - 12), 306 size=(0, 0), 307 text=bui.Lstr( 308 resource=f'{self._r}.ignoreCompletelyDescriptionText' 309 ), 310 color=(0.7, 1, 0.7, 0.6), 311 maxwidth=self._sub_width * 0.8, 312 scale=0.7, 313 h_align='center', 314 v_align='center', 315 ) 316 317 v -= 80 318 319 cb1 = bui.checkboxwidget( 320 parent=self._subcontainer, 321 autoselect=True, 322 position=(h + 50, v), 323 size=(400, 30), 324 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateText'), 325 textcolor=(0.8, 0.8, 0.8), 326 maxwidth=450, 327 scale=0.9, 328 on_value_change_call=pwin.set_auto_recalibrate_analog_stick_value, 329 value=self._parent_window.get_auto_recalibrate_analog_stick_value(), 330 ) 331 bui.textwidget( 332 parent=self._subcontainer, 333 position=(self._sub_width * 0.5, v - 12), 334 size=(0, 0), 335 text=bui.Lstr(resource=f'{self._r}.autoRecalibrateDescriptionText'), 336 color=(0.7, 1, 0.7, 0.6), 337 maxwidth=self._sub_width * 0.8, 338 scale=0.7, 339 h_align='center', 340 v_align='center', 341 ) 342 v -= 80 343 344 buttons = self._config_value_editor( 345 bui.Lstr(resource=f'{self._r}.analogStickDeadZoneText'), 346 control=('analogStickDeadZone' + self._parent_window.get_ext()), 347 position=(h + 40, v), 348 min_val=0, 349 max_val=10.0, 350 increment=0.1, 351 x_offset=100, 352 ) 353 bui.widget(edit=buttons[0], left_widget=cb1, up_widget=cb1) 354 bui.widget(edit=cb1, right_widget=buttons[0], down_widget=buttons[0]) 355 356 bui.textwidget( 357 parent=self._subcontainer, 358 position=(self._sub_width * 0.5, v - 12), 359 size=(0, 0), 360 text=bui.Lstr( 361 resource=f'{self._r}.analogStickDeadZoneDescriptionText' 362 ), 363 color=(0.7, 1, 0.7, 0.6), 364 maxwidth=self._sub_width * 0.8, 365 scale=0.7, 366 h_align='center', 367 v_align='center', 368 ) 369 v -= 100 370 371 # child joysticks cant have child joysticks.. that's just 372 # crazy talk 373 if not self._parent_window.get_is_secondary(): 374 bui.buttonwidget( 375 parent=self._subcontainer, 376 autoselect=True, 377 label=bui.Lstr(resource=f'{self._r}.twoInOneSetupText'), 378 position=(40, v), 379 size=(self._sub_width - 80, 50), 380 on_activate_call=self._parent_window.show_secondary_editor, 381 up_widget=buttons[0], 382 ) 383 384 # set a bigger bottom show-buffer for the widgets we just made 385 # so we can see the text below them when navigating with 386 # a gamepad 387 for child in self._subcontainer.get_children(): 388 bui.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30)