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