bauiv1lib.settings.audio

Provides audio settings UI.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides audio settings UI."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8import logging
  9
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    pass
 14
 15
 16class AudioSettingsWindow(bui.Window):
 17    """Window for editing audio settings."""
 18
 19    def __init__(
 20        self,
 21        transition: str = 'in_right',
 22        origin_widget: bui.Widget | None = None,
 23    ):
 24        # pylint: disable=too-many-statements
 25        # pylint: disable=too-many-locals
 26        # pylint: disable=cyclic-import
 27        from bauiv1lib.popup import PopupMenu
 28        from bauiv1lib.config import ConfigNumberEdit
 29
 30        assert bui.app.classic is not None
 31        music = bui.app.classic.music
 32
 33        # If they provided an origin-widget, scale up from that.
 34        scale_origin: tuple[float, float] | None
 35        if origin_widget is not None:
 36            self._transition_out = 'out_scale'
 37            scale_origin = origin_widget.get_screen_space_center()
 38            transition = 'in_scale'
 39        else:
 40            self._transition_out = 'out_right'
 41            scale_origin = None
 42
 43        self._r = 'audioSettingsWindow'
 44
 45        spacing = 50.0
 46        width = 460.0
 47        height = 210.0
 48
 49        # Update: hard-coding head-relative audio to true now,
 50        # so not showing options.
 51        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 52        show_vr_head_relative_audio = False
 53
 54        if show_vr_head_relative_audio:
 55            height += 70
 56
 57        show_soundtracks = False
 58        if music.have_music_player():
 59            show_soundtracks = True
 60            height += spacing * 2.0
 61
 62        uiscale = bui.app.ui_v1.uiscale
 63        base_scale = (
 64            2.05
 65            if uiscale is bui.UIScale.SMALL
 66            else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0
 67        )
 68        popup_menu_scale = base_scale * 1.2
 69
 70        super().__init__(
 71            root_widget=bui.containerwidget(
 72                size=(width, height),
 73                transition=transition,
 74                scale=base_scale,
 75                scale_origin_stack_offset=scale_origin,
 76                stack_offset=(
 77                    (0, -20) if uiscale is bui.UIScale.SMALL else (0, 0)
 78                ),
 79            )
 80        )
 81
 82        self._back_button = back_button = btn = bui.buttonwidget(
 83            parent=self._root_widget,
 84            position=(35, height - 55),
 85            size=(120, 60),
 86            scale=0.8,
 87            text_scale=1.2,
 88            label=bui.Lstr(resource='backText'),
 89            button_type='back',
 90            on_activate_call=self._back,
 91            autoselect=True,
 92        )
 93        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 94        v = height - 60
 95        v -= spacing * 1.0
 96        bui.textwidget(
 97            parent=self._root_widget,
 98            position=(width * 0.5, height - 32),
 99            size=(0, 0),
100            text=bui.Lstr(resource=self._r + '.titleText'),
101            color=bui.app.ui_v1.title_color,
102            maxwidth=180,
103            h_align='center',
104            v_align='center',
105        )
106
107        bui.buttonwidget(
108            edit=self._back_button,
109            button_type='backSmall',
110            size=(60, 60),
111            label=bui.charstr(bui.SpecialChar.BACK),
112        )
113
114        self._sound_volume_numedit = svne = ConfigNumberEdit(
115            parent=self._root_widget,
116            position=(40, v),
117            xoffset=10,
118            configkey='Sound Volume',
119            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
120            minval=0.0,
121            maxval=1.0,
122            increment=0.05,
123            as_percent=True,
124        )
125        if bui.app.ui_v1.use_toolbars:
126            bui.widget(
127                edit=svne.plusbutton,
128                right_widget=bui.get_special_widget('party_button'),
129            )
130        v -= spacing
131        self._music_volume_numedit = ConfigNumberEdit(
132            parent=self._root_widget,
133            position=(40, v),
134            xoffset=10,
135            configkey='Music Volume',
136            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
137            minval=0.0,
138            maxval=1.0,
139            increment=0.05,
140            callback=music.music_volume_changed,
141            changesound=False,
142            as_percent=True,
143        )
144
145        v -= 0.5 * spacing
146
147        self._vr_head_relative_audio_button: bui.Widget | None
148        if show_vr_head_relative_audio:
149            v -= 40
150            bui.textwidget(
151                parent=self._root_widget,
152                position=(40, v + 24),
153                size=(0, 0),
154                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
155                color=(0.8, 0.8, 0.8),
156                maxwidth=230,
157                h_align='left',
158                v_align='center',
159            )
160
161            popup = PopupMenu(
162                parent=self._root_widget,
163                position=(290, v),
164                width=120,
165                button_size=(135, 50),
166                scale=popup_menu_scale,
167                choices=['Auto', 'On', 'Off'],
168                choices_display=[
169                    bui.Lstr(resource='autoText'),
170                    bui.Lstr(resource='onText'),
171                    bui.Lstr(resource='offText'),
172                ],
173                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
174                on_value_change_call=self._set_vr_head_relative_audio,
175            )
176            self._vr_head_relative_audio_button = popup.get_button()
177            bui.textwidget(
178                parent=self._root_widget,
179                position=(width * 0.5, v - 11),
180                size=(0, 0),
181                text=bui.Lstr(
182                    resource=self._r + '.headRelativeVRAudioInfoText'
183                ),
184                scale=0.5,
185                color=(0.7, 0.8, 0.7),
186                maxwidth=400,
187                flatness=1.0,
188                h_align='center',
189                v_align='center',
190            )
191            v -= 30
192        else:
193            self._vr_head_relative_audio_button = None
194
195        self._soundtrack_button: bui.Widget | None
196        if show_soundtracks:
197            v -= 1.2 * spacing
198            self._soundtrack_button = bui.buttonwidget(
199                parent=self._root_widget,
200                position=((width - 310) / 2, v),
201                size=(310, 50),
202                autoselect=True,
203                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
204                on_activate_call=self._do_soundtracks,
205            )
206            v -= spacing * 0.5
207            bui.textwidget(
208                parent=self._root_widget,
209                position=(0, v),
210                size=(width, 20),
211                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
212                flatness=1.0,
213                h_align='center',
214                scale=0.5,
215                color=(0.7, 0.8, 0.7, 1.0),
216                maxwidth=400,
217            )
218        else:
219            self._soundtrack_button = None
220
221        # Tweak a few navigation bits.
222        try:
223            bui.widget(edit=back_button, down_widget=svne.minusbutton)
224        except Exception:
225            logging.exception('Error wiring AudioSettingsWindow.')
226
227        self._restore_state()
228
229    def _set_vr_head_relative_audio(self, val: str) -> None:
230        cfg = bui.app.config
231        cfg['VR Head Relative Audio'] = val
232        cfg.apply_and_commit()
233
234    def _do_soundtracks(self) -> None:
235        # pylint: disable=cyclic-import
236        from bauiv1lib.soundtrack import browser as stb
237
238        # no-op if our underlying widget is dead or on its way out.
239        if not self._root_widget or self._root_widget.transitioning_out:
240            return
241
242        # We require disk access for soundtracks;
243        # if we don't have it, request it.
244        if not bui.have_permission(bui.Permission.STORAGE):
245            bui.getsound('ding').play()
246            bui.screenmessage(
247                bui.Lstr(resource='storagePermissionAccessText'),
248                color=(0.5, 1, 0.5),
249            )
250            bui.apptimer(
251                1.0, bui.Call(bui.request_permission, bui.Permission.STORAGE)
252            )
253            return
254
255        self._save_state()
256        bui.containerwidget(edit=self._root_widget, transition='out_left')
257        assert bui.app.classic is not None
258        bui.app.ui_v1.set_main_menu_window(
259            stb.SoundtrackBrowserWindow(
260                origin_widget=self._soundtrack_button
261            ).get_root_widget(),
262            from_window=self._root_widget,
263        )
264
265    def _back(self) -> None:
266        # pylint: disable=cyclic-import
267        from bauiv1lib.settings import allsettings
268
269        # no-op if our underlying widget is dead or on its way out.
270        if not self._root_widget or self._root_widget.transitioning_out:
271            return
272
273        self._save_state()
274        bui.containerwidget(
275            edit=self._root_widget, transition=self._transition_out
276        )
277        assert bui.app.classic is not None
278        bui.app.ui_v1.set_main_menu_window(
279            allsettings.AllSettingsWindow(
280                transition='in_left'
281            ).get_root_widget(),
282            from_window=self._root_widget,
283        )
284
285    def _save_state(self) -> None:
286        try:
287            sel = self._root_widget.get_selected_child()
288            if sel == self._sound_volume_numedit.minusbutton:
289                sel_name = 'SoundMinus'
290            elif sel == self._sound_volume_numedit.plusbutton:
291                sel_name = 'SoundPlus'
292            elif sel == self._music_volume_numedit.minusbutton:
293                sel_name = 'MusicMinus'
294            elif sel == self._music_volume_numedit.plusbutton:
295                sel_name = 'MusicPlus'
296            elif sel == self._soundtrack_button:
297                sel_name = 'Soundtrack'
298            elif sel == self._back_button:
299                sel_name = 'Back'
300            elif sel == self._vr_head_relative_audio_button:
301                sel_name = 'VRHeadRelative'
302            else:
303                raise ValueError(f'unrecognized selection \'{sel}\'')
304            assert bui.app.classic is not None
305            bui.app.ui_v1.window_states[type(self)] = sel_name
306        except Exception:
307            logging.exception('Error saving state for %s.', self)
308
309    def _restore_state(self) -> None:
310        try:
311            assert bui.app.classic is not None
312            sel_name = bui.app.ui_v1.window_states.get(type(self))
313            sel: bui.Widget | None
314            if sel_name == 'SoundMinus':
315                sel = self._sound_volume_numedit.minusbutton
316            elif sel_name == 'SoundPlus':
317                sel = self._sound_volume_numedit.plusbutton
318            elif sel_name == 'MusicMinus':
319                sel = self._music_volume_numedit.minusbutton
320            elif sel_name == 'MusicPlus':
321                sel = self._music_volume_numedit.plusbutton
322            elif sel_name == 'VRHeadRelative':
323                sel = self._vr_head_relative_audio_button
324            elif sel_name == 'Soundtrack':
325                sel = self._soundtrack_button
326            elif sel_name == 'Back':
327                sel = self._back_button
328            else:
329                sel = self._back_button
330            if sel:
331                bui.containerwidget(edit=self._root_widget, selected_child=sel)
332        except Exception:
333            logging.exception('Error restoring state for %s.', self)
class AudioSettingsWindow(bauiv1._uitypes.Window):
 17class AudioSettingsWindow(bui.Window):
 18    """Window for editing audio settings."""
 19
 20    def __init__(
 21        self,
 22        transition: str = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27        # pylint: disable=cyclic-import
 28        from bauiv1lib.popup import PopupMenu
 29        from bauiv1lib.config import ConfigNumberEdit
 30
 31        assert bui.app.classic is not None
 32        music = bui.app.classic.music
 33
 34        # If they provided an origin-widget, scale up from that.
 35        scale_origin: tuple[float, float] | None
 36        if origin_widget is not None:
 37            self._transition_out = 'out_scale'
 38            scale_origin = origin_widget.get_screen_space_center()
 39            transition = 'in_scale'
 40        else:
 41            self._transition_out = 'out_right'
 42            scale_origin = None
 43
 44        self._r = 'audioSettingsWindow'
 45
 46        spacing = 50.0
 47        width = 460.0
 48        height = 210.0
 49
 50        # Update: hard-coding head-relative audio to true now,
 51        # so not showing options.
 52        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 53        show_vr_head_relative_audio = False
 54
 55        if show_vr_head_relative_audio:
 56            height += 70
 57
 58        show_soundtracks = False
 59        if music.have_music_player():
 60            show_soundtracks = True
 61            height += spacing * 2.0
 62
 63        uiscale = bui.app.ui_v1.uiscale
 64        base_scale = (
 65            2.05
 66            if uiscale is bui.UIScale.SMALL
 67            else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0
 68        )
 69        popup_menu_scale = base_scale * 1.2
 70
 71        super().__init__(
 72            root_widget=bui.containerwidget(
 73                size=(width, height),
 74                transition=transition,
 75                scale=base_scale,
 76                scale_origin_stack_offset=scale_origin,
 77                stack_offset=(
 78                    (0, -20) if uiscale is bui.UIScale.SMALL else (0, 0)
 79                ),
 80            )
 81        )
 82
 83        self._back_button = back_button = btn = bui.buttonwidget(
 84            parent=self._root_widget,
 85            position=(35, height - 55),
 86            size=(120, 60),
 87            scale=0.8,
 88            text_scale=1.2,
 89            label=bui.Lstr(resource='backText'),
 90            button_type='back',
 91            on_activate_call=self._back,
 92            autoselect=True,
 93        )
 94        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 95        v = height - 60
 96        v -= spacing * 1.0
 97        bui.textwidget(
 98            parent=self._root_widget,
 99            position=(width * 0.5, height - 32),
100            size=(0, 0),
101            text=bui.Lstr(resource=self._r + '.titleText'),
102            color=bui.app.ui_v1.title_color,
103            maxwidth=180,
104            h_align='center',
105            v_align='center',
106        )
107
108        bui.buttonwidget(
109            edit=self._back_button,
110            button_type='backSmall',
111            size=(60, 60),
112            label=bui.charstr(bui.SpecialChar.BACK),
113        )
114
115        self._sound_volume_numedit = svne = ConfigNumberEdit(
116            parent=self._root_widget,
117            position=(40, v),
118            xoffset=10,
119            configkey='Sound Volume',
120            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
121            minval=0.0,
122            maxval=1.0,
123            increment=0.05,
124            as_percent=True,
125        )
126        if bui.app.ui_v1.use_toolbars:
127            bui.widget(
128                edit=svne.plusbutton,
129                right_widget=bui.get_special_widget('party_button'),
130            )
131        v -= spacing
132        self._music_volume_numedit = ConfigNumberEdit(
133            parent=self._root_widget,
134            position=(40, v),
135            xoffset=10,
136            configkey='Music Volume',
137            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
138            minval=0.0,
139            maxval=1.0,
140            increment=0.05,
141            callback=music.music_volume_changed,
142            changesound=False,
143            as_percent=True,
144        )
145
146        v -= 0.5 * spacing
147
148        self._vr_head_relative_audio_button: bui.Widget | None
149        if show_vr_head_relative_audio:
150            v -= 40
151            bui.textwidget(
152                parent=self._root_widget,
153                position=(40, v + 24),
154                size=(0, 0),
155                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
156                color=(0.8, 0.8, 0.8),
157                maxwidth=230,
158                h_align='left',
159                v_align='center',
160            )
161
162            popup = PopupMenu(
163                parent=self._root_widget,
164                position=(290, v),
165                width=120,
166                button_size=(135, 50),
167                scale=popup_menu_scale,
168                choices=['Auto', 'On', 'Off'],
169                choices_display=[
170                    bui.Lstr(resource='autoText'),
171                    bui.Lstr(resource='onText'),
172                    bui.Lstr(resource='offText'),
173                ],
174                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
175                on_value_change_call=self._set_vr_head_relative_audio,
176            )
177            self._vr_head_relative_audio_button = popup.get_button()
178            bui.textwidget(
179                parent=self._root_widget,
180                position=(width * 0.5, v - 11),
181                size=(0, 0),
182                text=bui.Lstr(
183                    resource=self._r + '.headRelativeVRAudioInfoText'
184                ),
185                scale=0.5,
186                color=(0.7, 0.8, 0.7),
187                maxwidth=400,
188                flatness=1.0,
189                h_align='center',
190                v_align='center',
191            )
192            v -= 30
193        else:
194            self._vr_head_relative_audio_button = None
195
196        self._soundtrack_button: bui.Widget | None
197        if show_soundtracks:
198            v -= 1.2 * spacing
199            self._soundtrack_button = bui.buttonwidget(
200                parent=self._root_widget,
201                position=((width - 310) / 2, v),
202                size=(310, 50),
203                autoselect=True,
204                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
205                on_activate_call=self._do_soundtracks,
206            )
207            v -= spacing * 0.5
208            bui.textwidget(
209                parent=self._root_widget,
210                position=(0, v),
211                size=(width, 20),
212                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
213                flatness=1.0,
214                h_align='center',
215                scale=0.5,
216                color=(0.7, 0.8, 0.7, 1.0),
217                maxwidth=400,
218            )
219        else:
220            self._soundtrack_button = None
221
222        # Tweak a few navigation bits.
223        try:
224            bui.widget(edit=back_button, down_widget=svne.minusbutton)
225        except Exception:
226            logging.exception('Error wiring AudioSettingsWindow.')
227
228        self._restore_state()
229
230    def _set_vr_head_relative_audio(self, val: str) -> None:
231        cfg = bui.app.config
232        cfg['VR Head Relative Audio'] = val
233        cfg.apply_and_commit()
234
235    def _do_soundtracks(self) -> None:
236        # pylint: disable=cyclic-import
237        from bauiv1lib.soundtrack import browser as stb
238
239        # no-op if our underlying widget is dead or on its way out.
240        if not self._root_widget or self._root_widget.transitioning_out:
241            return
242
243        # We require disk access for soundtracks;
244        # if we don't have it, request it.
245        if not bui.have_permission(bui.Permission.STORAGE):
246            bui.getsound('ding').play()
247            bui.screenmessage(
248                bui.Lstr(resource='storagePermissionAccessText'),
249                color=(0.5, 1, 0.5),
250            )
251            bui.apptimer(
252                1.0, bui.Call(bui.request_permission, bui.Permission.STORAGE)
253            )
254            return
255
256        self._save_state()
257        bui.containerwidget(edit=self._root_widget, transition='out_left')
258        assert bui.app.classic is not None
259        bui.app.ui_v1.set_main_menu_window(
260            stb.SoundtrackBrowserWindow(
261                origin_widget=self._soundtrack_button
262            ).get_root_widget(),
263            from_window=self._root_widget,
264        )
265
266    def _back(self) -> None:
267        # pylint: disable=cyclic-import
268        from bauiv1lib.settings import allsettings
269
270        # no-op if our underlying widget is dead or on its way out.
271        if not self._root_widget or self._root_widget.transitioning_out:
272            return
273
274        self._save_state()
275        bui.containerwidget(
276            edit=self._root_widget, transition=self._transition_out
277        )
278        assert bui.app.classic is not None
279        bui.app.ui_v1.set_main_menu_window(
280            allsettings.AllSettingsWindow(
281                transition='in_left'
282            ).get_root_widget(),
283            from_window=self._root_widget,
284        )
285
286    def _save_state(self) -> None:
287        try:
288            sel = self._root_widget.get_selected_child()
289            if sel == self._sound_volume_numedit.minusbutton:
290                sel_name = 'SoundMinus'
291            elif sel == self._sound_volume_numedit.plusbutton:
292                sel_name = 'SoundPlus'
293            elif sel == self._music_volume_numedit.minusbutton:
294                sel_name = 'MusicMinus'
295            elif sel == self._music_volume_numedit.plusbutton:
296                sel_name = 'MusicPlus'
297            elif sel == self._soundtrack_button:
298                sel_name = 'Soundtrack'
299            elif sel == self._back_button:
300                sel_name = 'Back'
301            elif sel == self._vr_head_relative_audio_button:
302                sel_name = 'VRHeadRelative'
303            else:
304                raise ValueError(f'unrecognized selection \'{sel}\'')
305            assert bui.app.classic is not None
306            bui.app.ui_v1.window_states[type(self)] = sel_name
307        except Exception:
308            logging.exception('Error saving state for %s.', self)
309
310    def _restore_state(self) -> None:
311        try:
312            assert bui.app.classic is not None
313            sel_name = bui.app.ui_v1.window_states.get(type(self))
314            sel: bui.Widget | None
315            if sel_name == 'SoundMinus':
316                sel = self._sound_volume_numedit.minusbutton
317            elif sel_name == 'SoundPlus':
318                sel = self._sound_volume_numedit.plusbutton
319            elif sel_name == 'MusicMinus':
320                sel = self._music_volume_numedit.minusbutton
321            elif sel_name == 'MusicPlus':
322                sel = self._music_volume_numedit.plusbutton
323            elif sel_name == 'VRHeadRelative':
324                sel = self._vr_head_relative_audio_button
325            elif sel_name == 'Soundtrack':
326                sel = self._soundtrack_button
327            elif sel_name == 'Back':
328                sel = self._back_button
329            else:
330                sel = self._back_button
331            if sel:
332                bui.containerwidget(edit=self._root_widget, selected_child=sel)
333        except Exception:
334            logging.exception('Error restoring state for %s.', self)

Window for editing audio settings.

AudioSettingsWindow( transition: str = 'in_right', origin_widget: _bauiv1.Widget | None = None)
 20    def __init__(
 21        self,
 22        transition: str = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27        # pylint: disable=cyclic-import
 28        from bauiv1lib.popup import PopupMenu
 29        from bauiv1lib.config import ConfigNumberEdit
 30
 31        assert bui.app.classic is not None
 32        music = bui.app.classic.music
 33
 34        # If they provided an origin-widget, scale up from that.
 35        scale_origin: tuple[float, float] | None
 36        if origin_widget is not None:
 37            self._transition_out = 'out_scale'
 38            scale_origin = origin_widget.get_screen_space_center()
 39            transition = 'in_scale'
 40        else:
 41            self._transition_out = 'out_right'
 42            scale_origin = None
 43
 44        self._r = 'audioSettingsWindow'
 45
 46        spacing = 50.0
 47        width = 460.0
 48        height = 210.0
 49
 50        # Update: hard-coding head-relative audio to true now,
 51        # so not showing options.
 52        # show_vr_head_relative_audio = True if bui.app.vr_mode else False
 53        show_vr_head_relative_audio = False
 54
 55        if show_vr_head_relative_audio:
 56            height += 70
 57
 58        show_soundtracks = False
 59        if music.have_music_player():
 60            show_soundtracks = True
 61            height += spacing * 2.0
 62
 63        uiscale = bui.app.ui_v1.uiscale
 64        base_scale = (
 65            2.05
 66            if uiscale is bui.UIScale.SMALL
 67            else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0
 68        )
 69        popup_menu_scale = base_scale * 1.2
 70
 71        super().__init__(
 72            root_widget=bui.containerwidget(
 73                size=(width, height),
 74                transition=transition,
 75                scale=base_scale,
 76                scale_origin_stack_offset=scale_origin,
 77                stack_offset=(
 78                    (0, -20) if uiscale is bui.UIScale.SMALL else (0, 0)
 79                ),
 80            )
 81        )
 82
 83        self._back_button = back_button = btn = bui.buttonwidget(
 84            parent=self._root_widget,
 85            position=(35, height - 55),
 86            size=(120, 60),
 87            scale=0.8,
 88            text_scale=1.2,
 89            label=bui.Lstr(resource='backText'),
 90            button_type='back',
 91            on_activate_call=self._back,
 92            autoselect=True,
 93        )
 94        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 95        v = height - 60
 96        v -= spacing * 1.0
 97        bui.textwidget(
 98            parent=self._root_widget,
 99            position=(width * 0.5, height - 32),
100            size=(0, 0),
101            text=bui.Lstr(resource=self._r + '.titleText'),
102            color=bui.app.ui_v1.title_color,
103            maxwidth=180,
104            h_align='center',
105            v_align='center',
106        )
107
108        bui.buttonwidget(
109            edit=self._back_button,
110            button_type='backSmall',
111            size=(60, 60),
112            label=bui.charstr(bui.SpecialChar.BACK),
113        )
114
115        self._sound_volume_numedit = svne = ConfigNumberEdit(
116            parent=self._root_widget,
117            position=(40, v),
118            xoffset=10,
119            configkey='Sound Volume',
120            displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
121            minval=0.0,
122            maxval=1.0,
123            increment=0.05,
124            as_percent=True,
125        )
126        if bui.app.ui_v1.use_toolbars:
127            bui.widget(
128                edit=svne.plusbutton,
129                right_widget=bui.get_special_widget('party_button'),
130            )
131        v -= spacing
132        self._music_volume_numedit = ConfigNumberEdit(
133            parent=self._root_widget,
134            position=(40, v),
135            xoffset=10,
136            configkey='Music Volume',
137            displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
138            minval=0.0,
139            maxval=1.0,
140            increment=0.05,
141            callback=music.music_volume_changed,
142            changesound=False,
143            as_percent=True,
144        )
145
146        v -= 0.5 * spacing
147
148        self._vr_head_relative_audio_button: bui.Widget | None
149        if show_vr_head_relative_audio:
150            v -= 40
151            bui.textwidget(
152                parent=self._root_widget,
153                position=(40, v + 24),
154                size=(0, 0),
155                text=bui.Lstr(resource=self._r + '.headRelativeVRAudioText'),
156                color=(0.8, 0.8, 0.8),
157                maxwidth=230,
158                h_align='left',
159                v_align='center',
160            )
161
162            popup = PopupMenu(
163                parent=self._root_widget,
164                position=(290, v),
165                width=120,
166                button_size=(135, 50),
167                scale=popup_menu_scale,
168                choices=['Auto', 'On', 'Off'],
169                choices_display=[
170                    bui.Lstr(resource='autoText'),
171                    bui.Lstr(resource='onText'),
172                    bui.Lstr(resource='offText'),
173                ],
174                current_choice=bui.app.config.resolve('VR Head Relative Audio'),
175                on_value_change_call=self._set_vr_head_relative_audio,
176            )
177            self._vr_head_relative_audio_button = popup.get_button()
178            bui.textwidget(
179                parent=self._root_widget,
180                position=(width * 0.5, v - 11),
181                size=(0, 0),
182                text=bui.Lstr(
183                    resource=self._r + '.headRelativeVRAudioInfoText'
184                ),
185                scale=0.5,
186                color=(0.7, 0.8, 0.7),
187                maxwidth=400,
188                flatness=1.0,
189                h_align='center',
190                v_align='center',
191            )
192            v -= 30
193        else:
194            self._vr_head_relative_audio_button = None
195
196        self._soundtrack_button: bui.Widget | None
197        if show_soundtracks:
198            v -= 1.2 * spacing
199            self._soundtrack_button = bui.buttonwidget(
200                parent=self._root_widget,
201                position=((width - 310) / 2, v),
202                size=(310, 50),
203                autoselect=True,
204                label=bui.Lstr(resource=self._r + '.soundtrackButtonText'),
205                on_activate_call=self._do_soundtracks,
206            )
207            v -= spacing * 0.5
208            bui.textwidget(
209                parent=self._root_widget,
210                position=(0, v),
211                size=(width, 20),
212                text=bui.Lstr(resource=self._r + '.soundtrackDescriptionText'),
213                flatness=1.0,
214                h_align='center',
215                scale=0.5,
216                color=(0.7, 0.8, 0.7, 1.0),
217                maxwidth=400,
218            )
219        else:
220            self._soundtrack_button = None
221
222        # Tweak a few navigation bits.
223        try:
224            bui.widget(edit=back_button, down_widget=svne.minusbutton)
225        except Exception:
226            logging.exception('Error wiring AudioSettingsWindow.')
227
228        self._restore_state()
Inherited Members
bauiv1._uitypes.Window
get_root_widget