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

Window for advanced gamepad configuration.

GamepadAdvancedSettingsWindow(parent_window: bastd.ui.settings.gamepad.GamepadSettingsWindow)
 20    def __init__(self, parent_window: gpsui.GamepadSettingsWindow):
 21        # pylint: disable=too-many-statements
 22        # pylint: disable=too-many-locals
 23        self._parent_window = parent_window
 24
 25        app = ba.app
 26
 27        self._r = parent_window.get_r()
 28        uiscale = ba.app.ui.uiscale
 29        self._width = 900 if uiscale is ba.UIScale.SMALL else 700
 30        self._x_inset = x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
 31        self._height = 402 if uiscale is ba.UIScale.SMALL else 512
 32        self._textwidgets: dict[str, ba.Widget] = {}
 33        advb = parent_window.get_advanced_button()
 34        super().__init__(
 35            root_widget=ba.containerwidget(
 36                transition='in_scale',
 37                size=(self._width, self._height),
 38                scale=1.06
 39                * (
 40                    1.85
 41                    if uiscale is ba.UIScale.SMALL
 42                    else 1.35
 43                    if uiscale is ba.UIScale.MEDIUM
 44                    else 1.0
 45                ),
 46                stack_offset=(0, -25)
 47                if uiscale is ba.UIScale.SMALL
 48                else (0, 0),
 49                scale_origin_stack_offset=(advb.get_screen_space_center()),
 50            )
 51        )
 52
 53        ba.textwidget(
 54            parent=self._root_widget,
 55            position=(
 56                self._width * 0.5,
 57                self._height - (40 if uiscale is ba.UIScale.SMALL else 34),
 58            ),
 59            size=(0, 0),
 60            text=ba.Lstr(resource=self._r + '.advancedTitleText'),
 61            maxwidth=320,
 62            color=ba.app.ui.title_color,
 63            h_align='center',
 64            v_align='center',
 65        )
 66
 67        back_button = btn = ba.buttonwidget(
 68            parent=self._root_widget,
 69            autoselect=True,
 70            position=(
 71                self._width - (176 + x_inset),
 72                self._height - (60 if uiscale is ba.UIScale.SMALL else 55),
 73            ),
 74            size=(120, 48),
 75            text_scale=0.8,
 76            label=ba.Lstr(resource='doneText'),
 77            on_activate_call=self._done,
 78        )
 79        ba.containerwidget(
 80            edit=self._root_widget,
 81            start_button=btn,
 82            on_cancel_call=btn.activate,
 83        )
 84
 85        self._scroll_width = self._width - (100 + 2 * x_inset)
 86        self._scroll_height = self._height - 110
 87        self._sub_width = self._scroll_width - 20
 88        self._sub_height = (
 89            940 if self._parent_window.get_is_secondary() else 1040
 90        )
 91        if app.vr_mode:
 92            self._sub_height += 50
 93        self._scrollwidget = ba.scrollwidget(
 94            parent=self._root_widget,
 95            position=(
 96                (self._width - self._scroll_width) * 0.5,
 97                self._height - 65 - self._scroll_height,
 98            ),
 99            size=(self._scroll_width, self._scroll_height),
100            claims_left_right=True,
101            claims_tab=True,
102            selection_loops_to_parent=True,
103        )
104        self._subcontainer = ba.containerwidget(
105            parent=self._scrollwidget,
106            size=(self._sub_width, self._sub_height),
107            background=False,
108            claims_left_right=True,
109            claims_tab=True,
110            selection_loops_to_parent=True,
111        )
112        ba.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 = ba.checkboxwidget(
125                parent=self._subcontainer,
126                position=(h + 70, v),
127                size=(500, 30),
128                text=ba.Lstr(resource=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            ba.widget(edit=cb1, up_widget=back_button)
139        v -= 60
140        capb = self._capture_button(
141            pos=(h2, v),
142            name=ba.Lstr(resource=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                ba.widget(edit=widget, up_widget=back_button)
148        v -= 42
149        self._capture_button(
150            pos=(h2, v),
151            name=ba.Lstr(resource=self._r + '.runButton2Text'),
152            control='buttonRun2' + self._parent_window.get_ext(),
153        )
154        ba.textwidget(
155            parent=self._subcontainer,
156            position=(self._sub_width * 0.5, v - 24),
157            size=(0, 0),
158            text=ba.Lstr(resource=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=ba.Lstr(resource=self._r + '.runTrigger1Text'),
171            control='triggerRun1' + self._parent_window.get_ext(),
172            message=ba.Lstr(resource=self._r + '.pressAnyAnalogTriggerText'),
173        )
174        v -= 42
175        self._capture_button(
176            pos=(h2, v),
177            name=ba.Lstr(resource=self._r + '.runTrigger2Text'),
178            control='triggerRun2' + self._parent_window.get_ext(),
179            message=ba.Lstr(resource=self._r + '.pressAnyAnalogTriggerText'),
180        )
181
182        # in vr mode, allow assigning a reset-view button
183        if app.vr_mode:
184            v -= 50
185            self._capture_button(
186                pos=(h2, v),
187                name=ba.Lstr(resource=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=ba.Lstr(resource=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=ba.Lstr(resource=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=ba.Lstr(resource=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=ba.Lstr(resource=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=ba.Lstr(resource=self._r + '.ignoredButton4Text'),
219            control='buttonIgnored4' + self._parent_window.get_ext(),
220        )
221        ba.textwidget(
222            parent=self._subcontainer,
223            position=(self._sub_width * 0.5, v - 14),
224            size=(0, 0),
225            text=ba.Lstr(resource=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        ba.checkboxwidget(
236            parent=self._subcontainer,
237            autoselect=True,
238            position=(h + 50, v),
239            size=(400, 30),
240            text=ba.Lstr(resource=self._r + '.startButtonActivatesDefaultText'),
241            textcolor=(0.8, 0.8, 0.8),
242            maxwidth=450,
243            scale=0.9,
244            on_value_change_call=(
245                pwin.set_start_button_activates_default_widget_value
246            ),
247            value=pwin.get_start_button_activates_default_widget_value(),
248        )
249        ba.textwidget(
250            parent=self._subcontainer,
251            position=(self._sub_width * 0.5, v - 12),
252            size=(0, 0),
253            text=ba.Lstr(
254                resource=self._r + '.startButtonActivatesDefaultDescriptionText'
255            ),
256            color=(0.7, 1, 0.7, 0.6),
257            maxwidth=self._sub_width * 0.8,
258            scale=0.7,
259            h_align='center',
260            v_align='center',
261        )
262
263        v -= 80
264        ba.checkboxwidget(
265            parent=self._subcontainer,
266            autoselect=True,
267            position=(h + 50, v),
268            size=(400, 30),
269            text=ba.Lstr(resource=self._r + '.uiOnlyText'),
270            textcolor=(0.8, 0.8, 0.8),
271            maxwidth=450,
272            scale=0.9,
273            on_value_change_call=self._parent_window.set_ui_only_value,
274            value=self._parent_window.get_ui_only_value(),
275        )
276        ba.textwidget(
277            parent=self._subcontainer,
278            position=(self._sub_width * 0.5, v - 12),
279            size=(0, 0),
280            text=ba.Lstr(resource=self._r + '.uiOnlyDescriptionText'),
281            color=(0.7, 1, 0.7, 0.6),
282            maxwidth=self._sub_width * 0.8,
283            scale=0.7,
284            h_align='center',
285            v_align='center',
286        )
287
288        v -= 80
289        ba.checkboxwidget(
290            parent=self._subcontainer,
291            autoselect=True,
292            position=(h + 50, v),
293            size=(400, 30),
294            text=ba.Lstr(resource=self._r + '.ignoreCompletelyText'),
295            textcolor=(0.8, 0.8, 0.8),
296            maxwidth=450,
297            scale=0.9,
298            on_value_change_call=pwin.set_ignore_completely_value,
299            value=self._parent_window.get_ignore_completely_value(),
300        )
301        ba.textwidget(
302            parent=self._subcontainer,
303            position=(self._sub_width * 0.5, v - 12),
304            size=(0, 0),
305            text=ba.Lstr(resource=self._r + '.ignoreCompletelyDescriptionText'),
306            color=(0.7, 1, 0.7, 0.6),
307            maxwidth=self._sub_width * 0.8,
308            scale=0.7,
309            h_align='center',
310            v_align='center',
311        )
312
313        v -= 80
314
315        cb1 = ba.checkboxwidget(
316            parent=self._subcontainer,
317            autoselect=True,
318            position=(h + 50, v),
319            size=(400, 30),
320            text=ba.Lstr(resource=self._r + '.autoRecalibrateText'),
321            textcolor=(0.8, 0.8, 0.8),
322            maxwidth=450,
323            scale=0.9,
324            on_value_change_call=pwin.set_auto_recalibrate_analog_stick_value,
325            value=self._parent_window.get_auto_recalibrate_analog_stick_value(),
326        )
327        ba.textwidget(
328            parent=self._subcontainer,
329            position=(self._sub_width * 0.5, v - 12),
330            size=(0, 0),
331            text=ba.Lstr(resource=self._r + '.autoRecalibrateDescriptionText'),
332            color=(0.7, 1, 0.7, 0.6),
333            maxwidth=self._sub_width * 0.8,
334            scale=0.7,
335            h_align='center',
336            v_align='center',
337        )
338        v -= 80
339
340        buttons = self._config_value_editor(
341            ba.Lstr(resource=self._r + '.analogStickDeadZoneText'),
342            control=('analogStickDeadZone' + self._parent_window.get_ext()),
343            position=(h + 40, v),
344            min_val=0,
345            max_val=10.0,
346            increment=0.1,
347            x_offset=100,
348        )
349        ba.widget(edit=buttons[0], left_widget=cb1, up_widget=cb1)
350        ba.widget(edit=cb1, right_widget=buttons[0], down_widget=buttons[0])
351
352        ba.textwidget(
353            parent=self._subcontainer,
354            position=(self._sub_width * 0.5, v - 12),
355            size=(0, 0),
356            text=ba.Lstr(
357                resource=self._r + '.analogStickDeadZoneDescriptionText'
358            ),
359            color=(0.7, 1, 0.7, 0.6),
360            maxwidth=self._sub_width * 0.8,
361            scale=0.7,
362            h_align='center',
363            v_align='center',
364        )
365        v -= 100
366
367        # child joysticks cant have child joysticks.. that's just
368        # crazy talk
369        if not self._parent_window.get_is_secondary():
370            ba.buttonwidget(
371                parent=self._subcontainer,
372                autoselect=True,
373                label=ba.Lstr(resource=self._r + '.twoInOneSetupText'),
374                position=(40, v),
375                size=(self._sub_width - 80, 50),
376                on_activate_call=self._parent_window.show_secondary_editor,
377                up_widget=buttons[0],
378            )
379
380        # set a bigger bottom show-buffer for the widgets we just made
381        # so we can see the text below them when navigating with
382        # a gamepad
383        for child in self._subcontainer.get_children():
384            ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30)
Inherited Members
ba.ui.Window
get_root_widget