bauiv1lib.settings.devtools

UI functionality for Modding Tools.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""UI functionality for Modding Tools."""
  4
  5from __future__ import annotations
  6
  7from typing import override
  8
  9import babase
 10import bauiv1 as bui
 11from bauiv1lib.popup import PopupMenu
 12from bauiv1lib.confirm import ConfirmWindow
 13from bauiv1lib.config import ConfigCheckBox
 14
 15
 16class DevToolsWindow(bui.MainWindow):
 17    """Window for accessing modding tools."""
 18
 19    def __init__(
 20        self,
 21        transition: str | None = 'in_right',
 22        origin_widget: bui.Widget | None = None,
 23    ):
 24
 25        app = bui.app
 26        assert app.classic is not None
 27
 28        uiscale = app.ui_v1.uiscale
 29        self._width = 1200.0 if uiscale is bui.UIScale.SMALL else 670.0
 30        self._height = (
 31            800
 32            if uiscale is bui.UIScale.SMALL
 33            else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0
 34        )
 35        self._spacing = 32
 36
 37        # Do some fancy math to fill all available screen area up to the
 38        # size of our backing container. This lets us fit to the exact
 39        # screen shape at small ui scale.
 40        screensize = bui.get_virtual_screen_size()
 41        scale = (
 42            2.13
 43            if uiscale is bui.UIScale.SMALL
 44            else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 45        )
 46        # Calc screen size in our local container space and clamp to a
 47        # bit smaller than our container size.
 48        target_width = min(self._width - 80, screensize[0] / scale)
 49        target_height = min(self._height - 90, screensize[1] / scale)
 50
 51        # To get top/left coords, go to the center of our window and
 52        # offset by half the width/height of our target area.
 53        yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
 54
 55        self._scroll_width = target_width
 56        self._scroll_height = target_height - 35
 57        self._scroll_bottom = yoffs - 64 - self._scroll_height
 58
 59        self._sub_width = self._scroll_width * 0.95
 60        self._sub_height = 300.0
 61
 62        super().__init__(
 63            root_widget=bui.containerwidget(
 64                size=(self._width, self._height),
 65                toolbar_visibility=(
 66                    'menu_minimal'
 67                    if uiscale is bui.UIScale.SMALL
 68                    else 'menu_full'
 69                ),
 70                scale=scale,
 71            ),
 72            transition=transition,
 73            origin_widget=origin_widget,
 74            # We're affected by screen size only at small ui-scale.
 75            refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
 76        )
 77
 78        self._r = 'settingsDevTools'
 79
 80        if uiscale is bui.UIScale.SMALL:
 81            bui.containerwidget(
 82                edit=self._root_widget, on_cancel_call=self.main_window_back
 83            )
 84            self._back_button = None
 85        else:
 86            self._back_button = bui.buttonwidget(
 87                parent=self._root_widget,
 88                position=(53, yoffs - 50),
 89                size=(140, 60),
 90                scale=0.8,
 91                autoselect=True,
 92                label=bui.Lstr(resource='backText'),
 93                button_type='back',
 94                on_activate_call=self.main_window_back,
 95            )
 96            bui.containerwidget(
 97                edit=self._root_widget, cancel_button=self._back_button
 98            )
 99
100        self._title_text = bui.textwidget(
101            parent=self._root_widget,
102            position=(
103                self._width * 0.5,
104                yoffs - (60 if uiscale is bui.UIScale.SMALL else 42),
105            ),
106            size=(0, 25),
107            scale=(0.8 if uiscale is bui.UIScale.SMALL else 1.0),
108            maxwidth=self._width - 200,
109            text=bui.Lstr(resource='settingsWindowAdvanced.devToolsText'),
110            color=app.ui_v1.title_color,
111            h_align='center',
112            v_align='center',
113        )
114
115        if self._back_button is not None:
116            bui.buttonwidget(
117                edit=self._back_button,
118                button_type='backSmall',
119                size=(60, 60),
120                label=bui.charstr(bui.SpecialChar.BACK),
121            )
122
123        self._scrollwidget = bui.scrollwidget(
124            parent=self._root_widget,
125            position=(
126                self._width * 0.5 - self._scroll_width * 0.5,
127                self._scroll_bottom,
128            ),
129            simple_culling_v=20.0,
130            highlight=False,
131            size=(self._scroll_width, self._scroll_height),
132            selection_loops_to_parent=True,
133            border_opacity=0.4,
134        )
135        bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
136        self._subcontainer = bui.containerwidget(
137            parent=self._scrollwidget,
138            size=(self._sub_width, self._sub_height),
139            background=False,
140            selection_loops_to_parent=True,
141        )
142
143        v = self._sub_height - 35
144        this_button_width = 410
145
146        v -= self._spacing * 2.5
147        self._show_dev_console_button_check_box = ConfigCheckBox(
148            parent=self._subcontainer,
149            position=(90, v + 40),
150            size=(self._sub_width - 100, 30),
151            configkey='Show Dev Console Button',
152            displayname=bui.Lstr(
153                resource='settingsWindowAdvanced.showDevConsoleButtonText'
154            ),
155            scale=1.0,
156            maxwidth=400,
157        )
158        if self._back_button is not None:
159            bui.widget(
160                edit=self._show_dev_console_button_check_box.widget,
161                up_widget=self._back_button,
162            )
163
164        v -= self._spacing * 1.2
165        self._create_user_system_scripts_button = bui.buttonwidget(
166            parent=self._subcontainer,
167            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
168            size=(this_button_width, 60),
169            autoselect=True,
170            label=bui.Lstr(resource='userSystemScriptsCreateText'),
171            text_scale=1.0,
172            on_activate_call=babase.modutils.create_user_system_scripts,
173        )
174
175        v -= self._spacing * 2.5
176        self._delete_user_system_scripts_button = bui.buttonwidget(
177            parent=self._subcontainer,
178            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
179            size=(this_button_width, 60),
180            autoselect=True,
181            label=bui.Lstr(resource='userSystemScriptsDeleteText'),
182            text_scale=1.0,
183            on_activate_call=lambda: ConfirmWindow(
184                action=babase.modutils.delete_user_system_scripts,
185            ),
186        )
187
188        # Currently this is not wired up. The current official way to test
189        # UIScales is either to use the switcher in the dev-console or to
190        # set the BA_UI_SCALE env var.
191        if bool(False):
192            v -= self._spacing * 2.5
193            bui.textwidget(
194                parent=self._subcontainer,
195                position=(170, v + 10),
196                size=(0, 0),
197                text=bui.Lstr(resource='uiScaleText'),
198                color=app.ui_v1.title_color,
199                h_align='center',
200                v_align='center',
201            )
202
203            PopupMenu(
204                parent=self._subcontainer,
205                position=(230, v - 20),
206                button_size=(200.0, 60.0),
207                width=100.0,
208                choices=[
209                    'auto',
210                    'small',
211                    'medium',
212                    'large',
213                ],
214                choices_display=[
215                    bui.Lstr(resource='autoText'),
216                    bui.Lstr(resource='sizeSmallText'),
217                    bui.Lstr(resource='sizeMediumText'),
218                    bui.Lstr(resource='sizeLargeText'),
219                ],
220                current_choice=app.config.get('UI Scale', 'auto'),
221                on_value_change_call=self._set_uiscale,
222            )
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    def _set_uiscale(self, val: str) -> None:
235        cfg = bui.app.config
236        cfg['UI Scale'] = val
237        cfg.apply_and_commit()
238        if bui.app.ui_v1.uiscale.name != val.upper():
239            bui.screenmessage(
240                bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
241                color=(1.0, 0.5, 0.0),
242            )
class DevToolsWindow(bauiv1._uitypes.MainWindow):
 17class DevToolsWindow(bui.MainWindow):
 18    """Window for accessing modding tools."""
 19
 20    def __init__(
 21        self,
 22        transition: str | None = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25
 26        app = bui.app
 27        assert app.classic is not None
 28
 29        uiscale = app.ui_v1.uiscale
 30        self._width = 1200.0 if uiscale is bui.UIScale.SMALL else 670.0
 31        self._height = (
 32            800
 33            if uiscale is bui.UIScale.SMALL
 34            else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0
 35        )
 36        self._spacing = 32
 37
 38        # Do some fancy math to fill all available screen area up to the
 39        # size of our backing container. This lets us fit to the exact
 40        # screen shape at small ui scale.
 41        screensize = bui.get_virtual_screen_size()
 42        scale = (
 43            2.13
 44            if uiscale is bui.UIScale.SMALL
 45            else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 46        )
 47        # Calc screen size in our local container space and clamp to a
 48        # bit smaller than our container size.
 49        target_width = min(self._width - 80, screensize[0] / scale)
 50        target_height = min(self._height - 90, screensize[1] / scale)
 51
 52        # To get top/left coords, go to the center of our window and
 53        # offset by half the width/height of our target area.
 54        yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
 55
 56        self._scroll_width = target_width
 57        self._scroll_height = target_height - 35
 58        self._scroll_bottom = yoffs - 64 - self._scroll_height
 59
 60        self._sub_width = self._scroll_width * 0.95
 61        self._sub_height = 300.0
 62
 63        super().__init__(
 64            root_widget=bui.containerwidget(
 65                size=(self._width, self._height),
 66                toolbar_visibility=(
 67                    'menu_minimal'
 68                    if uiscale is bui.UIScale.SMALL
 69                    else 'menu_full'
 70                ),
 71                scale=scale,
 72            ),
 73            transition=transition,
 74            origin_widget=origin_widget,
 75            # We're affected by screen size only at small ui-scale.
 76            refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
 77        )
 78
 79        self._r = 'settingsDevTools'
 80
 81        if uiscale is bui.UIScale.SMALL:
 82            bui.containerwidget(
 83                edit=self._root_widget, on_cancel_call=self.main_window_back
 84            )
 85            self._back_button = None
 86        else:
 87            self._back_button = bui.buttonwidget(
 88                parent=self._root_widget,
 89                position=(53, yoffs - 50),
 90                size=(140, 60),
 91                scale=0.8,
 92                autoselect=True,
 93                label=bui.Lstr(resource='backText'),
 94                button_type='back',
 95                on_activate_call=self.main_window_back,
 96            )
 97            bui.containerwidget(
 98                edit=self._root_widget, cancel_button=self._back_button
 99            )
100
101        self._title_text = bui.textwidget(
102            parent=self._root_widget,
103            position=(
104                self._width * 0.5,
105                yoffs - (60 if uiscale is bui.UIScale.SMALL else 42),
106            ),
107            size=(0, 25),
108            scale=(0.8 if uiscale is bui.UIScale.SMALL else 1.0),
109            maxwidth=self._width - 200,
110            text=bui.Lstr(resource='settingsWindowAdvanced.devToolsText'),
111            color=app.ui_v1.title_color,
112            h_align='center',
113            v_align='center',
114        )
115
116        if self._back_button is not None:
117            bui.buttonwidget(
118                edit=self._back_button,
119                button_type='backSmall',
120                size=(60, 60),
121                label=bui.charstr(bui.SpecialChar.BACK),
122            )
123
124        self._scrollwidget = bui.scrollwidget(
125            parent=self._root_widget,
126            position=(
127                self._width * 0.5 - self._scroll_width * 0.5,
128                self._scroll_bottom,
129            ),
130            simple_culling_v=20.0,
131            highlight=False,
132            size=(self._scroll_width, self._scroll_height),
133            selection_loops_to_parent=True,
134            border_opacity=0.4,
135        )
136        bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
137        self._subcontainer = bui.containerwidget(
138            parent=self._scrollwidget,
139            size=(self._sub_width, self._sub_height),
140            background=False,
141            selection_loops_to_parent=True,
142        )
143
144        v = self._sub_height - 35
145        this_button_width = 410
146
147        v -= self._spacing * 2.5
148        self._show_dev_console_button_check_box = ConfigCheckBox(
149            parent=self._subcontainer,
150            position=(90, v + 40),
151            size=(self._sub_width - 100, 30),
152            configkey='Show Dev Console Button',
153            displayname=bui.Lstr(
154                resource='settingsWindowAdvanced.showDevConsoleButtonText'
155            ),
156            scale=1.0,
157            maxwidth=400,
158        )
159        if self._back_button is not None:
160            bui.widget(
161                edit=self._show_dev_console_button_check_box.widget,
162                up_widget=self._back_button,
163            )
164
165        v -= self._spacing * 1.2
166        self._create_user_system_scripts_button = bui.buttonwidget(
167            parent=self._subcontainer,
168            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
169            size=(this_button_width, 60),
170            autoselect=True,
171            label=bui.Lstr(resource='userSystemScriptsCreateText'),
172            text_scale=1.0,
173            on_activate_call=babase.modutils.create_user_system_scripts,
174        )
175
176        v -= self._spacing * 2.5
177        self._delete_user_system_scripts_button = bui.buttonwidget(
178            parent=self._subcontainer,
179            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
180            size=(this_button_width, 60),
181            autoselect=True,
182            label=bui.Lstr(resource='userSystemScriptsDeleteText'),
183            text_scale=1.0,
184            on_activate_call=lambda: ConfirmWindow(
185                action=babase.modutils.delete_user_system_scripts,
186            ),
187        )
188
189        # Currently this is not wired up. The current official way to test
190        # UIScales is either to use the switcher in the dev-console or to
191        # set the BA_UI_SCALE env var.
192        if bool(False):
193            v -= self._spacing * 2.5
194            bui.textwidget(
195                parent=self._subcontainer,
196                position=(170, v + 10),
197                size=(0, 0),
198                text=bui.Lstr(resource='uiScaleText'),
199                color=app.ui_v1.title_color,
200                h_align='center',
201                v_align='center',
202            )
203
204            PopupMenu(
205                parent=self._subcontainer,
206                position=(230, v - 20),
207                button_size=(200.0, 60.0),
208                width=100.0,
209                choices=[
210                    'auto',
211                    'small',
212                    'medium',
213                    'large',
214                ],
215                choices_display=[
216                    bui.Lstr(resource='autoText'),
217                    bui.Lstr(resource='sizeSmallText'),
218                    bui.Lstr(resource='sizeMediumText'),
219                    bui.Lstr(resource='sizeLargeText'),
220                ],
221                current_choice=app.config.get('UI Scale', 'auto'),
222                on_value_change_call=self._set_uiscale,
223            )
224
225    @override
226    def get_main_window_state(self) -> bui.MainWindowState:
227        # Support recreating our window for back/refresh purposes.
228        cls = type(self)
229        return bui.BasicMainWindowState(
230            create_call=lambda transition, origin_widget: cls(
231                transition=transition, origin_widget=origin_widget
232            )
233        )
234
235    def _set_uiscale(self, val: str) -> None:
236        cfg = bui.app.config
237        cfg['UI Scale'] = val
238        cfg.apply_and_commit()
239        if bui.app.ui_v1.uiscale.name != val.upper():
240            bui.screenmessage(
241                bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
242                color=(1.0, 0.5, 0.0),
243            )

Window for accessing modding tools.

DevToolsWindow( 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
 26        app = bui.app
 27        assert app.classic is not None
 28
 29        uiscale = app.ui_v1.uiscale
 30        self._width = 1200.0 if uiscale is bui.UIScale.SMALL else 670.0
 31        self._height = (
 32            800
 33            if uiscale is bui.UIScale.SMALL
 34            else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0
 35        )
 36        self._spacing = 32
 37
 38        # Do some fancy math to fill all available screen area up to the
 39        # size of our backing container. This lets us fit to the exact
 40        # screen shape at small ui scale.
 41        screensize = bui.get_virtual_screen_size()
 42        scale = (
 43            2.13
 44            if uiscale is bui.UIScale.SMALL
 45            else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 46        )
 47        # Calc screen size in our local container space and clamp to a
 48        # bit smaller than our container size.
 49        target_width = min(self._width - 80, screensize[0] / scale)
 50        target_height = min(self._height - 90, screensize[1] / scale)
 51
 52        # To get top/left coords, go to the center of our window and
 53        # offset by half the width/height of our target area.
 54        yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
 55
 56        self._scroll_width = target_width
 57        self._scroll_height = target_height - 35
 58        self._scroll_bottom = yoffs - 64 - self._scroll_height
 59
 60        self._sub_width = self._scroll_width * 0.95
 61        self._sub_height = 300.0
 62
 63        super().__init__(
 64            root_widget=bui.containerwidget(
 65                size=(self._width, self._height),
 66                toolbar_visibility=(
 67                    'menu_minimal'
 68                    if uiscale is bui.UIScale.SMALL
 69                    else 'menu_full'
 70                ),
 71                scale=scale,
 72            ),
 73            transition=transition,
 74            origin_widget=origin_widget,
 75            # We're affected by screen size only at small ui-scale.
 76            refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
 77        )
 78
 79        self._r = 'settingsDevTools'
 80
 81        if uiscale is bui.UIScale.SMALL:
 82            bui.containerwidget(
 83                edit=self._root_widget, on_cancel_call=self.main_window_back
 84            )
 85            self._back_button = None
 86        else:
 87            self._back_button = bui.buttonwidget(
 88                parent=self._root_widget,
 89                position=(53, yoffs - 50),
 90                size=(140, 60),
 91                scale=0.8,
 92                autoselect=True,
 93                label=bui.Lstr(resource='backText'),
 94                button_type='back',
 95                on_activate_call=self.main_window_back,
 96            )
 97            bui.containerwidget(
 98                edit=self._root_widget, cancel_button=self._back_button
 99            )
100
101        self._title_text = bui.textwidget(
102            parent=self._root_widget,
103            position=(
104                self._width * 0.5,
105                yoffs - (60 if uiscale is bui.UIScale.SMALL else 42),
106            ),
107            size=(0, 25),
108            scale=(0.8 if uiscale is bui.UIScale.SMALL else 1.0),
109            maxwidth=self._width - 200,
110            text=bui.Lstr(resource='settingsWindowAdvanced.devToolsText'),
111            color=app.ui_v1.title_color,
112            h_align='center',
113            v_align='center',
114        )
115
116        if self._back_button is not None:
117            bui.buttonwidget(
118                edit=self._back_button,
119                button_type='backSmall',
120                size=(60, 60),
121                label=bui.charstr(bui.SpecialChar.BACK),
122            )
123
124        self._scrollwidget = bui.scrollwidget(
125            parent=self._root_widget,
126            position=(
127                self._width * 0.5 - self._scroll_width * 0.5,
128                self._scroll_bottom,
129            ),
130            simple_culling_v=20.0,
131            highlight=False,
132            size=(self._scroll_width, self._scroll_height),
133            selection_loops_to_parent=True,
134            border_opacity=0.4,
135        )
136        bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
137        self._subcontainer = bui.containerwidget(
138            parent=self._scrollwidget,
139            size=(self._sub_width, self._sub_height),
140            background=False,
141            selection_loops_to_parent=True,
142        )
143
144        v = self._sub_height - 35
145        this_button_width = 410
146
147        v -= self._spacing * 2.5
148        self._show_dev_console_button_check_box = ConfigCheckBox(
149            parent=self._subcontainer,
150            position=(90, v + 40),
151            size=(self._sub_width - 100, 30),
152            configkey='Show Dev Console Button',
153            displayname=bui.Lstr(
154                resource='settingsWindowAdvanced.showDevConsoleButtonText'
155            ),
156            scale=1.0,
157            maxwidth=400,
158        )
159        if self._back_button is not None:
160            bui.widget(
161                edit=self._show_dev_console_button_check_box.widget,
162                up_widget=self._back_button,
163            )
164
165        v -= self._spacing * 1.2
166        self._create_user_system_scripts_button = bui.buttonwidget(
167            parent=self._subcontainer,
168            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
169            size=(this_button_width, 60),
170            autoselect=True,
171            label=bui.Lstr(resource='userSystemScriptsCreateText'),
172            text_scale=1.0,
173            on_activate_call=babase.modutils.create_user_system_scripts,
174        )
175
176        v -= self._spacing * 2.5
177        self._delete_user_system_scripts_button = bui.buttonwidget(
178            parent=self._subcontainer,
179            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
180            size=(this_button_width, 60),
181            autoselect=True,
182            label=bui.Lstr(resource='userSystemScriptsDeleteText'),
183            text_scale=1.0,
184            on_activate_call=lambda: ConfirmWindow(
185                action=babase.modutils.delete_user_system_scripts,
186            ),
187        )
188
189        # Currently this is not wired up. The current official way to test
190        # UIScales is either to use the switcher in the dev-console or to
191        # set the BA_UI_SCALE env var.
192        if bool(False):
193            v -= self._spacing * 2.5
194            bui.textwidget(
195                parent=self._subcontainer,
196                position=(170, v + 10),
197                size=(0, 0),
198                text=bui.Lstr(resource='uiScaleText'),
199                color=app.ui_v1.title_color,
200                h_align='center',
201                v_align='center',
202            )
203
204            PopupMenu(
205                parent=self._subcontainer,
206                position=(230, v - 20),
207                button_size=(200.0, 60.0),
208                width=100.0,
209                choices=[
210                    'auto',
211                    'small',
212                    'medium',
213                    'large',
214                ],
215                choices_display=[
216                    bui.Lstr(resource='autoText'),
217                    bui.Lstr(resource='sizeSmallText'),
218                    bui.Lstr(resource='sizeMediumText'),
219                    bui.Lstr(resource='sizeLargeText'),
220                ],
221                current_choice=app.config.get('UI Scale', 'auto'),
222                on_value_change_call=self._set_uiscale,
223            )

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

Return a WindowState to recreate this window, if supported.