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

Window for editing audio settings.

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

Create a MainWindow given a root widget and transition info.

Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.

@override
def get_main_window_state(self) -> bauiv1.MainWindowState:
224    @override
225    def get_main_window_state(self) -> bui.MainWindowState:
226        # Support recreating our window for back/refresh purposes.
227        cls = type(self)
228        return bui.BasicMainWindowState(
229            create_call=lambda transition, origin_widget: cls(
230                transition=transition, origin_widget=origin_widget
231            )
232        )

Return a WindowState to recreate this window, if supported.

@override
def on_main_window_close(self) -> None:
234    @override
235    def on_main_window_close(self) -> None:
236        self._save_state()

Called before transitioning out a main window.

A good opportunity to save window state/etc.

Inherited Members
bauiv1._uitypes.MainWindow
main_window_back_state
main_window_close
can_change_main_window
main_window_back
main_window_replace
bauiv1._uitypes.Window
get_root_widget