bastd.ui.settings.graphics
Provides UI for graphics settings.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides UI for graphics settings.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import ba 10import ba.internal 11 12if TYPE_CHECKING: 13 pass 14 15 16class GraphicsSettingsWindow(ba.Window): 17 """Window for graphics settings.""" 18 19 def __init__( 20 self, 21 transition: str = 'in_right', 22 origin_widget: ba.Widget | None = None, 23 ): 24 # pylint: disable=too-many-locals 25 # pylint: disable=too-many-branches 26 # pylint: disable=too-many-statements 27 from bastd.ui import popup 28 from bastd.ui.config import ConfigCheckBox, ConfigNumberEdit 29 30 # if they provided an origin-widget, scale up from that 31 scale_origin: tuple[float, float] | None 32 if origin_widget is not None: 33 self._transition_out = 'out_scale' 34 scale_origin = origin_widget.get_screen_space_center() 35 transition = 'in_scale' 36 else: 37 self._transition_out = 'out_right' 38 scale_origin = None 39 40 self._r = 'graphicsSettingsWindow' 41 app = ba.app 42 43 spacing = 32 44 self._have_selected_child = False 45 uiscale = app.ui.uiscale 46 width = 450.0 47 height = 302.0 48 49 self._show_fullscreen = False 50 fullscreen_spacing_top = spacing * 0.2 51 fullscreen_spacing = spacing * 1.2 52 if uiscale == ba.UIScale.LARGE and app.platform != 'android': 53 self._show_fullscreen = True 54 height += fullscreen_spacing + fullscreen_spacing_top 55 56 show_gamma = False 57 gamma_spacing = spacing * 1.3 58 if ba.internal.has_gamma_control(): 59 show_gamma = True 60 height += gamma_spacing 61 62 show_vsync = False 63 if app.platform == 'mac': 64 show_vsync = True 65 66 show_resolution = True 67 if app.vr_mode: 68 show_resolution = ( 69 app.platform == 'android' and app.subplatform == 'cardboard' 70 ) 71 72 uiscale = ba.app.ui.uiscale 73 base_scale = ( 74 2.4 75 if uiscale is ba.UIScale.SMALL 76 else 1.5 77 if uiscale is ba.UIScale.MEDIUM 78 else 1.0 79 ) 80 popup_menu_scale = base_scale * 1.2 81 v = height - 50 82 v -= spacing * 1.15 83 super().__init__( 84 root_widget=ba.containerwidget( 85 size=(width, height), 86 transition=transition, 87 scale_origin_stack_offset=scale_origin, 88 scale=base_scale, 89 stack_offset=(0, -30) 90 if uiscale is ba.UIScale.SMALL 91 else (0, 0), 92 ) 93 ) 94 95 btn = ba.buttonwidget( 96 parent=self._root_widget, 97 position=(35, height - 50), 98 size=(120, 60), 99 scale=0.8, 100 text_scale=1.2, 101 autoselect=True, 102 label=ba.Lstr(resource='backText'), 103 button_type='back', 104 on_activate_call=self._back, 105 ) 106 107 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 108 109 ba.textwidget( 110 parent=self._root_widget, 111 position=(0, height - 44), 112 size=(width, 25), 113 text=ba.Lstr(resource=self._r + '.titleText'), 114 color=ba.app.ui.title_color, 115 h_align='center', 116 v_align='top', 117 ) 118 119 ba.buttonwidget( 120 edit=btn, 121 button_type='backSmall', 122 size=(60, 60), 123 label=ba.charstr(ba.SpecialChar.BACK), 124 ) 125 126 self._fullscreen_checkbox: ba.Widget | None 127 if self._show_fullscreen: 128 v -= fullscreen_spacing_top 129 self._fullscreen_checkbox = ConfigCheckBox( 130 parent=self._root_widget, 131 position=(100, v), 132 maxwidth=200, 133 size=(300, 30), 134 configkey='Fullscreen', 135 displayname=ba.Lstr( 136 resource=self._r 137 + ( 138 '.fullScreenCmdText' 139 if app.platform == 'mac' 140 else '.fullScreenCtrlText' 141 ) 142 ), 143 ).widget 144 if not self._have_selected_child: 145 ba.containerwidget( 146 edit=self._root_widget, 147 selected_child=self._fullscreen_checkbox, 148 ) 149 self._have_selected_child = True 150 v -= fullscreen_spacing 151 else: 152 self._fullscreen_checkbox = None 153 154 self._gamma_controls: ConfigNumberEdit | None 155 if show_gamma: 156 self._gamma_controls = gmc = ConfigNumberEdit( 157 parent=self._root_widget, 158 position=(90, v), 159 configkey='Screen Gamma', 160 displayname=ba.Lstr(resource=self._r + '.gammaText'), 161 minval=0.1, 162 maxval=2.0, 163 increment=0.1, 164 xoffset=-70, 165 textscale=0.85, 166 ) 167 if ba.app.ui.use_toolbars: 168 ba.widget( 169 edit=gmc.plusbutton, 170 right_widget=ba.internal.get_special_widget('party_button'), 171 ) 172 if not self._have_selected_child: 173 ba.containerwidget( 174 edit=self._root_widget, selected_child=gmc.minusbutton 175 ) 176 self._have_selected_child = True 177 v -= gamma_spacing 178 else: 179 self._gamma_controls = None 180 181 self._selected_color = (0.5, 1, 0.5, 1) 182 self._unselected_color = (0.7, 0.7, 0.7, 1) 183 184 # quality 185 ba.textwidget( 186 parent=self._root_widget, 187 position=(60, v), 188 size=(160, 25), 189 text=ba.Lstr(resource=self._r + '.visualsText'), 190 color=ba.app.ui.heading_color, 191 scale=0.65, 192 maxwidth=150, 193 h_align='center', 194 v_align='center', 195 ) 196 popup.PopupMenu( 197 parent=self._root_widget, 198 position=(60, v - 50), 199 width=150, 200 scale=popup_menu_scale, 201 choices=['Auto', 'Higher', 'High', 'Medium', 'Low'], 202 choices_disabled=['Higher', 'High'] 203 if ba.internal.get_max_graphics_quality() == 'Medium' 204 else [], 205 choices_display=[ 206 ba.Lstr(resource='autoText'), 207 ba.Lstr(resource=self._r + '.higherText'), 208 ba.Lstr(resource=self._r + '.highText'), 209 ba.Lstr(resource=self._r + '.mediumText'), 210 ba.Lstr(resource=self._r + '.lowText'), 211 ], 212 current_choice=ba.app.config.resolve('Graphics Quality'), 213 on_value_change_call=self._set_quality, 214 ) 215 216 # texture controls 217 ba.textwidget( 218 parent=self._root_widget, 219 position=(230, v), 220 size=(160, 25), 221 text=ba.Lstr(resource=self._r + '.texturesText'), 222 color=ba.app.ui.heading_color, 223 scale=0.65, 224 maxwidth=150, 225 h_align='center', 226 v_align='center', 227 ) 228 textures_popup = popup.PopupMenu( 229 parent=self._root_widget, 230 position=(230, v - 50), 231 width=150, 232 scale=popup_menu_scale, 233 choices=['Auto', 'High', 'Medium', 'Low'], 234 choices_display=[ 235 ba.Lstr(resource='autoText'), 236 ba.Lstr(resource=self._r + '.highText'), 237 ba.Lstr(resource=self._r + '.mediumText'), 238 ba.Lstr(resource=self._r + '.lowText'), 239 ], 240 current_choice=ba.app.config.resolve('Texture Quality'), 241 on_value_change_call=self._set_textures, 242 ) 243 if ba.app.ui.use_toolbars: 244 ba.widget( 245 edit=textures_popup.get_button(), 246 right_widget=ba.internal.get_special_widget('party_button'), 247 ) 248 v -= 80 249 250 h_offs = 0 251 252 if show_resolution: 253 # resolution 254 ba.textwidget( 255 parent=self._root_widget, 256 position=(h_offs + 60, v), 257 size=(160, 25), 258 text=ba.Lstr(resource=self._r + '.resolutionText'), 259 color=ba.app.ui.heading_color, 260 scale=0.65, 261 maxwidth=150, 262 h_align='center', 263 v_align='center', 264 ) 265 266 # on standard android we have 'Auto', 'Native', and a few 267 # HD standards 268 if app.platform == 'android': 269 # on cardboard/daydream android we have a few 270 # render-target-scale options 271 if app.subplatform == 'cardboard': 272 current_res_cardboard = ( 273 str( 274 min( 275 100, 276 max( 277 10, 278 int( 279 round( 280 ba.app.config.resolve( 281 'GVR Render Target Scale' 282 ) 283 * 100.0 284 ) 285 ), 286 ), 287 ) 288 ) 289 + '%' 290 ) # yapf: disable 291 popup.PopupMenu( 292 parent=self._root_widget, 293 position=(h_offs + 60, v - 50), 294 width=120, 295 scale=popup_menu_scale, 296 choices=['100%', '75%', '50%', '35%'], 297 current_choice=current_res_cardboard, 298 on_value_change_call=self._set_gvr_render_target_scale, 299 ) 300 else: 301 native_res = ba.internal.get_display_resolution() 302 assert native_res is not None 303 choices = ['Auto', 'Native'] 304 choices_display = [ 305 ba.Lstr(resource='autoText'), 306 ba.Lstr(resource='nativeText'), 307 ] 308 for res in [1440, 1080, 960, 720, 480]: 309 # nav bar is 72px so lets allow for that in what 310 # choices we show 311 if native_res[1] >= res - 72: 312 res_str = str(res) + 'p' 313 choices.append(res_str) 314 choices_display.append(ba.Lstr(value=res_str)) 315 current_res_android = ba.app.config.resolve( 316 'Resolution (Android)' 317 ) 318 popup.PopupMenu( 319 parent=self._root_widget, 320 position=(h_offs + 60, v - 50), 321 width=120, 322 scale=popup_menu_scale, 323 choices=choices, 324 choices_display=choices_display, 325 current_choice=current_res_android, 326 on_value_change_call=self._set_android_res, 327 ) 328 else: 329 # if we're on a system that doesn't allow setting resolution, 330 # set pixel-scale instead 331 current_res = ba.internal.get_display_resolution() 332 if current_res is None: 333 current_res2 = ( 334 str( 335 min( 336 100, 337 max( 338 10, 339 int( 340 round( 341 ba.app.config.resolve( 342 'Screen Pixel Scale' 343 ) 344 * 100.0 345 ) 346 ), 347 ), 348 ) 349 ) 350 + '%' 351 ) # yapf: disable 352 popup.PopupMenu( 353 parent=self._root_widget, 354 position=(h_offs + 60, v - 50), 355 width=120, 356 scale=popup_menu_scale, 357 choices=['100%', '88%', '75%', '63%', '50%'], 358 current_choice=current_res2, 359 on_value_change_call=self._set_pixel_scale, 360 ) 361 else: 362 raise Exception( 363 'obsolete path; discrete resolutions' 364 ' no longer supported' 365 ) 366 367 # vsync 368 if show_vsync: 369 ba.textwidget( 370 parent=self._root_widget, 371 position=(230, v), 372 size=(160, 25), 373 text=ba.Lstr(resource=self._r + '.verticalSyncText'), 374 color=ba.app.ui.heading_color, 375 scale=0.65, 376 maxwidth=150, 377 h_align='center', 378 v_align='center', 379 ) 380 381 popup.PopupMenu( 382 parent=self._root_widget, 383 position=(230, v - 50), 384 width=150, 385 scale=popup_menu_scale, 386 choices=['Auto', 'Always', 'Never'], 387 choices_display=[ 388 ba.Lstr(resource='autoText'), 389 ba.Lstr(resource=self._r + '.alwaysText'), 390 ba.Lstr(resource=self._r + '.neverText'), 391 ], 392 current_choice=ba.app.config.resolve('Vertical Sync'), 393 on_value_change_call=self._set_vsync, 394 ) 395 396 v -= 90 397 fpsc = ConfigCheckBox( 398 parent=self._root_widget, 399 position=(69, v - 6), 400 size=(210, 30), 401 scale=0.86, 402 configkey='Show FPS', 403 displayname=ba.Lstr(resource=self._r + '.showFPSText'), 404 maxwidth=130, 405 ) 406 407 # (tv mode doesnt apply to vr) 408 if not ba.app.vr_mode: 409 tvc = ConfigCheckBox( 410 parent=self._root_widget, 411 position=(240, v - 6), 412 size=(210, 30), 413 scale=0.86, 414 configkey='TV Border', 415 displayname=ba.Lstr(resource=self._r + '.tvBorderText'), 416 maxwidth=130, 417 ) 418 # grumble.. 419 ba.widget(edit=fpsc.widget, right_widget=tvc.widget) 420 try: 421 pass 422 423 except Exception: 424 ba.print_exception('Exception wiring up graphics settings UI:') 425 426 v -= spacing 427 428 # make a timer to update our controls in case the config changes 429 # under us 430 self._update_timer = ba.Timer( 431 0.25, 432 ba.WeakCall(self._update_controls), 433 repeat=True, 434 timetype=ba.TimeType.REAL, 435 ) 436 437 def _back(self) -> None: 438 from bastd.ui.settings import allsettings 439 440 ba.containerwidget( 441 edit=self._root_widget, transition=self._transition_out 442 ) 443 ba.app.ui.set_main_menu_window( 444 allsettings.AllSettingsWindow( 445 transition='in_left' 446 ).get_root_widget() 447 ) 448 449 def _set_quality(self, quality: str) -> None: 450 cfg = ba.app.config 451 cfg['Graphics Quality'] = quality 452 cfg.apply_and_commit() 453 454 def _set_textures(self, val: str) -> None: 455 cfg = ba.app.config 456 cfg['Texture Quality'] = val 457 cfg.apply_and_commit() 458 459 def _set_android_res(self, val: str) -> None: 460 cfg = ba.app.config 461 cfg['Resolution (Android)'] = val 462 cfg.apply_and_commit() 463 464 def _set_pixel_scale(self, res: str) -> None: 465 cfg = ba.app.config 466 cfg['Screen Pixel Scale'] = float(res[:-1]) / 100.0 467 cfg.apply_and_commit() 468 469 def _set_gvr_render_target_scale(self, res: str) -> None: 470 cfg = ba.app.config 471 cfg['GVR Render Target Scale'] = float(res[:-1]) / 100.0 472 cfg.apply_and_commit() 473 474 def _set_vsync(self, val: str) -> None: 475 cfg = ba.app.config 476 cfg['Vertical Sync'] = val 477 cfg.apply_and_commit() 478 479 def _update_controls(self) -> None: 480 if self._show_fullscreen: 481 ba.checkboxwidget( 482 edit=self._fullscreen_checkbox, 483 value=ba.app.config.resolve('Fullscreen'), 484 )
class
GraphicsSettingsWindow(ba.ui.Window):
17class GraphicsSettingsWindow(ba.Window): 18 """Window for graphics settings.""" 19 20 def __init__( 21 self, 22 transition: str = 'in_right', 23 origin_widget: ba.Widget | None = None, 24 ): 25 # pylint: disable=too-many-locals 26 # pylint: disable=too-many-branches 27 # pylint: disable=too-many-statements 28 from bastd.ui import popup 29 from bastd.ui.config import ConfigCheckBox, ConfigNumberEdit 30 31 # if they provided an origin-widget, scale up from that 32 scale_origin: tuple[float, float] | None 33 if origin_widget is not None: 34 self._transition_out = 'out_scale' 35 scale_origin = origin_widget.get_screen_space_center() 36 transition = 'in_scale' 37 else: 38 self._transition_out = 'out_right' 39 scale_origin = None 40 41 self._r = 'graphicsSettingsWindow' 42 app = ba.app 43 44 spacing = 32 45 self._have_selected_child = False 46 uiscale = app.ui.uiscale 47 width = 450.0 48 height = 302.0 49 50 self._show_fullscreen = False 51 fullscreen_spacing_top = spacing * 0.2 52 fullscreen_spacing = spacing * 1.2 53 if uiscale == ba.UIScale.LARGE and app.platform != 'android': 54 self._show_fullscreen = True 55 height += fullscreen_spacing + fullscreen_spacing_top 56 57 show_gamma = False 58 gamma_spacing = spacing * 1.3 59 if ba.internal.has_gamma_control(): 60 show_gamma = True 61 height += gamma_spacing 62 63 show_vsync = False 64 if app.platform == 'mac': 65 show_vsync = True 66 67 show_resolution = True 68 if app.vr_mode: 69 show_resolution = ( 70 app.platform == 'android' and app.subplatform == 'cardboard' 71 ) 72 73 uiscale = ba.app.ui.uiscale 74 base_scale = ( 75 2.4 76 if uiscale is ba.UIScale.SMALL 77 else 1.5 78 if uiscale is ba.UIScale.MEDIUM 79 else 1.0 80 ) 81 popup_menu_scale = base_scale * 1.2 82 v = height - 50 83 v -= spacing * 1.15 84 super().__init__( 85 root_widget=ba.containerwidget( 86 size=(width, height), 87 transition=transition, 88 scale_origin_stack_offset=scale_origin, 89 scale=base_scale, 90 stack_offset=(0, -30) 91 if uiscale is ba.UIScale.SMALL 92 else (0, 0), 93 ) 94 ) 95 96 btn = ba.buttonwidget( 97 parent=self._root_widget, 98 position=(35, height - 50), 99 size=(120, 60), 100 scale=0.8, 101 text_scale=1.2, 102 autoselect=True, 103 label=ba.Lstr(resource='backText'), 104 button_type='back', 105 on_activate_call=self._back, 106 ) 107 108 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 109 110 ba.textwidget( 111 parent=self._root_widget, 112 position=(0, height - 44), 113 size=(width, 25), 114 text=ba.Lstr(resource=self._r + '.titleText'), 115 color=ba.app.ui.title_color, 116 h_align='center', 117 v_align='top', 118 ) 119 120 ba.buttonwidget( 121 edit=btn, 122 button_type='backSmall', 123 size=(60, 60), 124 label=ba.charstr(ba.SpecialChar.BACK), 125 ) 126 127 self._fullscreen_checkbox: ba.Widget | None 128 if self._show_fullscreen: 129 v -= fullscreen_spacing_top 130 self._fullscreen_checkbox = ConfigCheckBox( 131 parent=self._root_widget, 132 position=(100, v), 133 maxwidth=200, 134 size=(300, 30), 135 configkey='Fullscreen', 136 displayname=ba.Lstr( 137 resource=self._r 138 + ( 139 '.fullScreenCmdText' 140 if app.platform == 'mac' 141 else '.fullScreenCtrlText' 142 ) 143 ), 144 ).widget 145 if not self._have_selected_child: 146 ba.containerwidget( 147 edit=self._root_widget, 148 selected_child=self._fullscreen_checkbox, 149 ) 150 self._have_selected_child = True 151 v -= fullscreen_spacing 152 else: 153 self._fullscreen_checkbox = None 154 155 self._gamma_controls: ConfigNumberEdit | None 156 if show_gamma: 157 self._gamma_controls = gmc = ConfigNumberEdit( 158 parent=self._root_widget, 159 position=(90, v), 160 configkey='Screen Gamma', 161 displayname=ba.Lstr(resource=self._r + '.gammaText'), 162 minval=0.1, 163 maxval=2.0, 164 increment=0.1, 165 xoffset=-70, 166 textscale=0.85, 167 ) 168 if ba.app.ui.use_toolbars: 169 ba.widget( 170 edit=gmc.plusbutton, 171 right_widget=ba.internal.get_special_widget('party_button'), 172 ) 173 if not self._have_selected_child: 174 ba.containerwidget( 175 edit=self._root_widget, selected_child=gmc.minusbutton 176 ) 177 self._have_selected_child = True 178 v -= gamma_spacing 179 else: 180 self._gamma_controls = None 181 182 self._selected_color = (0.5, 1, 0.5, 1) 183 self._unselected_color = (0.7, 0.7, 0.7, 1) 184 185 # quality 186 ba.textwidget( 187 parent=self._root_widget, 188 position=(60, v), 189 size=(160, 25), 190 text=ba.Lstr(resource=self._r + '.visualsText'), 191 color=ba.app.ui.heading_color, 192 scale=0.65, 193 maxwidth=150, 194 h_align='center', 195 v_align='center', 196 ) 197 popup.PopupMenu( 198 parent=self._root_widget, 199 position=(60, v - 50), 200 width=150, 201 scale=popup_menu_scale, 202 choices=['Auto', 'Higher', 'High', 'Medium', 'Low'], 203 choices_disabled=['Higher', 'High'] 204 if ba.internal.get_max_graphics_quality() == 'Medium' 205 else [], 206 choices_display=[ 207 ba.Lstr(resource='autoText'), 208 ba.Lstr(resource=self._r + '.higherText'), 209 ba.Lstr(resource=self._r + '.highText'), 210 ba.Lstr(resource=self._r + '.mediumText'), 211 ba.Lstr(resource=self._r + '.lowText'), 212 ], 213 current_choice=ba.app.config.resolve('Graphics Quality'), 214 on_value_change_call=self._set_quality, 215 ) 216 217 # texture controls 218 ba.textwidget( 219 parent=self._root_widget, 220 position=(230, v), 221 size=(160, 25), 222 text=ba.Lstr(resource=self._r + '.texturesText'), 223 color=ba.app.ui.heading_color, 224 scale=0.65, 225 maxwidth=150, 226 h_align='center', 227 v_align='center', 228 ) 229 textures_popup = popup.PopupMenu( 230 parent=self._root_widget, 231 position=(230, v - 50), 232 width=150, 233 scale=popup_menu_scale, 234 choices=['Auto', 'High', 'Medium', 'Low'], 235 choices_display=[ 236 ba.Lstr(resource='autoText'), 237 ba.Lstr(resource=self._r + '.highText'), 238 ba.Lstr(resource=self._r + '.mediumText'), 239 ba.Lstr(resource=self._r + '.lowText'), 240 ], 241 current_choice=ba.app.config.resolve('Texture Quality'), 242 on_value_change_call=self._set_textures, 243 ) 244 if ba.app.ui.use_toolbars: 245 ba.widget( 246 edit=textures_popup.get_button(), 247 right_widget=ba.internal.get_special_widget('party_button'), 248 ) 249 v -= 80 250 251 h_offs = 0 252 253 if show_resolution: 254 # resolution 255 ba.textwidget( 256 parent=self._root_widget, 257 position=(h_offs + 60, v), 258 size=(160, 25), 259 text=ba.Lstr(resource=self._r + '.resolutionText'), 260 color=ba.app.ui.heading_color, 261 scale=0.65, 262 maxwidth=150, 263 h_align='center', 264 v_align='center', 265 ) 266 267 # on standard android we have 'Auto', 'Native', and a few 268 # HD standards 269 if app.platform == 'android': 270 # on cardboard/daydream android we have a few 271 # render-target-scale options 272 if app.subplatform == 'cardboard': 273 current_res_cardboard = ( 274 str( 275 min( 276 100, 277 max( 278 10, 279 int( 280 round( 281 ba.app.config.resolve( 282 'GVR Render Target Scale' 283 ) 284 * 100.0 285 ) 286 ), 287 ), 288 ) 289 ) 290 + '%' 291 ) # yapf: disable 292 popup.PopupMenu( 293 parent=self._root_widget, 294 position=(h_offs + 60, v - 50), 295 width=120, 296 scale=popup_menu_scale, 297 choices=['100%', '75%', '50%', '35%'], 298 current_choice=current_res_cardboard, 299 on_value_change_call=self._set_gvr_render_target_scale, 300 ) 301 else: 302 native_res = ba.internal.get_display_resolution() 303 assert native_res is not None 304 choices = ['Auto', 'Native'] 305 choices_display = [ 306 ba.Lstr(resource='autoText'), 307 ba.Lstr(resource='nativeText'), 308 ] 309 for res in [1440, 1080, 960, 720, 480]: 310 # nav bar is 72px so lets allow for that in what 311 # choices we show 312 if native_res[1] >= res - 72: 313 res_str = str(res) + 'p' 314 choices.append(res_str) 315 choices_display.append(ba.Lstr(value=res_str)) 316 current_res_android = ba.app.config.resolve( 317 'Resolution (Android)' 318 ) 319 popup.PopupMenu( 320 parent=self._root_widget, 321 position=(h_offs + 60, v - 50), 322 width=120, 323 scale=popup_menu_scale, 324 choices=choices, 325 choices_display=choices_display, 326 current_choice=current_res_android, 327 on_value_change_call=self._set_android_res, 328 ) 329 else: 330 # if we're on a system that doesn't allow setting resolution, 331 # set pixel-scale instead 332 current_res = ba.internal.get_display_resolution() 333 if current_res is None: 334 current_res2 = ( 335 str( 336 min( 337 100, 338 max( 339 10, 340 int( 341 round( 342 ba.app.config.resolve( 343 'Screen Pixel Scale' 344 ) 345 * 100.0 346 ) 347 ), 348 ), 349 ) 350 ) 351 + '%' 352 ) # yapf: disable 353 popup.PopupMenu( 354 parent=self._root_widget, 355 position=(h_offs + 60, v - 50), 356 width=120, 357 scale=popup_menu_scale, 358 choices=['100%', '88%', '75%', '63%', '50%'], 359 current_choice=current_res2, 360 on_value_change_call=self._set_pixel_scale, 361 ) 362 else: 363 raise Exception( 364 'obsolete path; discrete resolutions' 365 ' no longer supported' 366 ) 367 368 # vsync 369 if show_vsync: 370 ba.textwidget( 371 parent=self._root_widget, 372 position=(230, v), 373 size=(160, 25), 374 text=ba.Lstr(resource=self._r + '.verticalSyncText'), 375 color=ba.app.ui.heading_color, 376 scale=0.65, 377 maxwidth=150, 378 h_align='center', 379 v_align='center', 380 ) 381 382 popup.PopupMenu( 383 parent=self._root_widget, 384 position=(230, v - 50), 385 width=150, 386 scale=popup_menu_scale, 387 choices=['Auto', 'Always', 'Never'], 388 choices_display=[ 389 ba.Lstr(resource='autoText'), 390 ba.Lstr(resource=self._r + '.alwaysText'), 391 ba.Lstr(resource=self._r + '.neverText'), 392 ], 393 current_choice=ba.app.config.resolve('Vertical Sync'), 394 on_value_change_call=self._set_vsync, 395 ) 396 397 v -= 90 398 fpsc = ConfigCheckBox( 399 parent=self._root_widget, 400 position=(69, v - 6), 401 size=(210, 30), 402 scale=0.86, 403 configkey='Show FPS', 404 displayname=ba.Lstr(resource=self._r + '.showFPSText'), 405 maxwidth=130, 406 ) 407 408 # (tv mode doesnt apply to vr) 409 if not ba.app.vr_mode: 410 tvc = ConfigCheckBox( 411 parent=self._root_widget, 412 position=(240, v - 6), 413 size=(210, 30), 414 scale=0.86, 415 configkey='TV Border', 416 displayname=ba.Lstr(resource=self._r + '.tvBorderText'), 417 maxwidth=130, 418 ) 419 # grumble.. 420 ba.widget(edit=fpsc.widget, right_widget=tvc.widget) 421 try: 422 pass 423 424 except Exception: 425 ba.print_exception('Exception wiring up graphics settings UI:') 426 427 v -= spacing 428 429 # make a timer to update our controls in case the config changes 430 # under us 431 self._update_timer = ba.Timer( 432 0.25, 433 ba.WeakCall(self._update_controls), 434 repeat=True, 435 timetype=ba.TimeType.REAL, 436 ) 437 438 def _back(self) -> None: 439 from bastd.ui.settings import allsettings 440 441 ba.containerwidget( 442 edit=self._root_widget, transition=self._transition_out 443 ) 444 ba.app.ui.set_main_menu_window( 445 allsettings.AllSettingsWindow( 446 transition='in_left' 447 ).get_root_widget() 448 ) 449 450 def _set_quality(self, quality: str) -> None: 451 cfg = ba.app.config 452 cfg['Graphics Quality'] = quality 453 cfg.apply_and_commit() 454 455 def _set_textures(self, val: str) -> None: 456 cfg = ba.app.config 457 cfg['Texture Quality'] = val 458 cfg.apply_and_commit() 459 460 def _set_android_res(self, val: str) -> None: 461 cfg = ba.app.config 462 cfg['Resolution (Android)'] = val 463 cfg.apply_and_commit() 464 465 def _set_pixel_scale(self, res: str) -> None: 466 cfg = ba.app.config 467 cfg['Screen Pixel Scale'] = float(res[:-1]) / 100.0 468 cfg.apply_and_commit() 469 470 def _set_gvr_render_target_scale(self, res: str) -> None: 471 cfg = ba.app.config 472 cfg['GVR Render Target Scale'] = float(res[:-1]) / 100.0 473 cfg.apply_and_commit() 474 475 def _set_vsync(self, val: str) -> None: 476 cfg = ba.app.config 477 cfg['Vertical Sync'] = val 478 cfg.apply_and_commit() 479 480 def _update_controls(self) -> None: 481 if self._show_fullscreen: 482 ba.checkboxwidget( 483 edit=self._fullscreen_checkbox, 484 value=ba.app.config.resolve('Fullscreen'), 485 )
Window for graphics settings.
GraphicsSettingsWindow( transition: str = 'in_right', origin_widget: _ba.Widget | None = None)
20 def __init__( 21 self, 22 transition: str = 'in_right', 23 origin_widget: ba.Widget | None = None, 24 ): 25 # pylint: disable=too-many-locals 26 # pylint: disable=too-many-branches 27 # pylint: disable=too-many-statements 28 from bastd.ui import popup 29 from bastd.ui.config import ConfigCheckBox, ConfigNumberEdit 30 31 # if they provided an origin-widget, scale up from that 32 scale_origin: tuple[float, float] | None 33 if origin_widget is not None: 34 self._transition_out = 'out_scale' 35 scale_origin = origin_widget.get_screen_space_center() 36 transition = 'in_scale' 37 else: 38 self._transition_out = 'out_right' 39 scale_origin = None 40 41 self._r = 'graphicsSettingsWindow' 42 app = ba.app 43 44 spacing = 32 45 self._have_selected_child = False 46 uiscale = app.ui.uiscale 47 width = 450.0 48 height = 302.0 49 50 self._show_fullscreen = False 51 fullscreen_spacing_top = spacing * 0.2 52 fullscreen_spacing = spacing * 1.2 53 if uiscale == ba.UIScale.LARGE and app.platform != 'android': 54 self._show_fullscreen = True 55 height += fullscreen_spacing + fullscreen_spacing_top 56 57 show_gamma = False 58 gamma_spacing = spacing * 1.3 59 if ba.internal.has_gamma_control(): 60 show_gamma = True 61 height += gamma_spacing 62 63 show_vsync = False 64 if app.platform == 'mac': 65 show_vsync = True 66 67 show_resolution = True 68 if app.vr_mode: 69 show_resolution = ( 70 app.platform == 'android' and app.subplatform == 'cardboard' 71 ) 72 73 uiscale = ba.app.ui.uiscale 74 base_scale = ( 75 2.4 76 if uiscale is ba.UIScale.SMALL 77 else 1.5 78 if uiscale is ba.UIScale.MEDIUM 79 else 1.0 80 ) 81 popup_menu_scale = base_scale * 1.2 82 v = height - 50 83 v -= spacing * 1.15 84 super().__init__( 85 root_widget=ba.containerwidget( 86 size=(width, height), 87 transition=transition, 88 scale_origin_stack_offset=scale_origin, 89 scale=base_scale, 90 stack_offset=(0, -30) 91 if uiscale is ba.UIScale.SMALL 92 else (0, 0), 93 ) 94 ) 95 96 btn = ba.buttonwidget( 97 parent=self._root_widget, 98 position=(35, height - 50), 99 size=(120, 60), 100 scale=0.8, 101 text_scale=1.2, 102 autoselect=True, 103 label=ba.Lstr(resource='backText'), 104 button_type='back', 105 on_activate_call=self._back, 106 ) 107 108 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 109 110 ba.textwidget( 111 parent=self._root_widget, 112 position=(0, height - 44), 113 size=(width, 25), 114 text=ba.Lstr(resource=self._r + '.titleText'), 115 color=ba.app.ui.title_color, 116 h_align='center', 117 v_align='top', 118 ) 119 120 ba.buttonwidget( 121 edit=btn, 122 button_type='backSmall', 123 size=(60, 60), 124 label=ba.charstr(ba.SpecialChar.BACK), 125 ) 126 127 self._fullscreen_checkbox: ba.Widget | None 128 if self._show_fullscreen: 129 v -= fullscreen_spacing_top 130 self._fullscreen_checkbox = ConfigCheckBox( 131 parent=self._root_widget, 132 position=(100, v), 133 maxwidth=200, 134 size=(300, 30), 135 configkey='Fullscreen', 136 displayname=ba.Lstr( 137 resource=self._r 138 + ( 139 '.fullScreenCmdText' 140 if app.platform == 'mac' 141 else '.fullScreenCtrlText' 142 ) 143 ), 144 ).widget 145 if not self._have_selected_child: 146 ba.containerwidget( 147 edit=self._root_widget, 148 selected_child=self._fullscreen_checkbox, 149 ) 150 self._have_selected_child = True 151 v -= fullscreen_spacing 152 else: 153 self._fullscreen_checkbox = None 154 155 self._gamma_controls: ConfigNumberEdit | None 156 if show_gamma: 157 self._gamma_controls = gmc = ConfigNumberEdit( 158 parent=self._root_widget, 159 position=(90, v), 160 configkey='Screen Gamma', 161 displayname=ba.Lstr(resource=self._r + '.gammaText'), 162 minval=0.1, 163 maxval=2.0, 164 increment=0.1, 165 xoffset=-70, 166 textscale=0.85, 167 ) 168 if ba.app.ui.use_toolbars: 169 ba.widget( 170 edit=gmc.plusbutton, 171 right_widget=ba.internal.get_special_widget('party_button'), 172 ) 173 if not self._have_selected_child: 174 ba.containerwidget( 175 edit=self._root_widget, selected_child=gmc.minusbutton 176 ) 177 self._have_selected_child = True 178 v -= gamma_spacing 179 else: 180 self._gamma_controls = None 181 182 self._selected_color = (0.5, 1, 0.5, 1) 183 self._unselected_color = (0.7, 0.7, 0.7, 1) 184 185 # quality 186 ba.textwidget( 187 parent=self._root_widget, 188 position=(60, v), 189 size=(160, 25), 190 text=ba.Lstr(resource=self._r + '.visualsText'), 191 color=ba.app.ui.heading_color, 192 scale=0.65, 193 maxwidth=150, 194 h_align='center', 195 v_align='center', 196 ) 197 popup.PopupMenu( 198 parent=self._root_widget, 199 position=(60, v - 50), 200 width=150, 201 scale=popup_menu_scale, 202 choices=['Auto', 'Higher', 'High', 'Medium', 'Low'], 203 choices_disabled=['Higher', 'High'] 204 if ba.internal.get_max_graphics_quality() == 'Medium' 205 else [], 206 choices_display=[ 207 ba.Lstr(resource='autoText'), 208 ba.Lstr(resource=self._r + '.higherText'), 209 ba.Lstr(resource=self._r + '.highText'), 210 ba.Lstr(resource=self._r + '.mediumText'), 211 ba.Lstr(resource=self._r + '.lowText'), 212 ], 213 current_choice=ba.app.config.resolve('Graphics Quality'), 214 on_value_change_call=self._set_quality, 215 ) 216 217 # texture controls 218 ba.textwidget( 219 parent=self._root_widget, 220 position=(230, v), 221 size=(160, 25), 222 text=ba.Lstr(resource=self._r + '.texturesText'), 223 color=ba.app.ui.heading_color, 224 scale=0.65, 225 maxwidth=150, 226 h_align='center', 227 v_align='center', 228 ) 229 textures_popup = popup.PopupMenu( 230 parent=self._root_widget, 231 position=(230, v - 50), 232 width=150, 233 scale=popup_menu_scale, 234 choices=['Auto', 'High', 'Medium', 'Low'], 235 choices_display=[ 236 ba.Lstr(resource='autoText'), 237 ba.Lstr(resource=self._r + '.highText'), 238 ba.Lstr(resource=self._r + '.mediumText'), 239 ba.Lstr(resource=self._r + '.lowText'), 240 ], 241 current_choice=ba.app.config.resolve('Texture Quality'), 242 on_value_change_call=self._set_textures, 243 ) 244 if ba.app.ui.use_toolbars: 245 ba.widget( 246 edit=textures_popup.get_button(), 247 right_widget=ba.internal.get_special_widget('party_button'), 248 ) 249 v -= 80 250 251 h_offs = 0 252 253 if show_resolution: 254 # resolution 255 ba.textwidget( 256 parent=self._root_widget, 257 position=(h_offs + 60, v), 258 size=(160, 25), 259 text=ba.Lstr(resource=self._r + '.resolutionText'), 260 color=ba.app.ui.heading_color, 261 scale=0.65, 262 maxwidth=150, 263 h_align='center', 264 v_align='center', 265 ) 266 267 # on standard android we have 'Auto', 'Native', and a few 268 # HD standards 269 if app.platform == 'android': 270 # on cardboard/daydream android we have a few 271 # render-target-scale options 272 if app.subplatform == 'cardboard': 273 current_res_cardboard = ( 274 str( 275 min( 276 100, 277 max( 278 10, 279 int( 280 round( 281 ba.app.config.resolve( 282 'GVR Render Target Scale' 283 ) 284 * 100.0 285 ) 286 ), 287 ), 288 ) 289 ) 290 + '%' 291 ) # yapf: disable 292 popup.PopupMenu( 293 parent=self._root_widget, 294 position=(h_offs + 60, v - 50), 295 width=120, 296 scale=popup_menu_scale, 297 choices=['100%', '75%', '50%', '35%'], 298 current_choice=current_res_cardboard, 299 on_value_change_call=self._set_gvr_render_target_scale, 300 ) 301 else: 302 native_res = ba.internal.get_display_resolution() 303 assert native_res is not None 304 choices = ['Auto', 'Native'] 305 choices_display = [ 306 ba.Lstr(resource='autoText'), 307 ba.Lstr(resource='nativeText'), 308 ] 309 for res in [1440, 1080, 960, 720, 480]: 310 # nav bar is 72px so lets allow for that in what 311 # choices we show 312 if native_res[1] >= res - 72: 313 res_str = str(res) + 'p' 314 choices.append(res_str) 315 choices_display.append(ba.Lstr(value=res_str)) 316 current_res_android = ba.app.config.resolve( 317 'Resolution (Android)' 318 ) 319 popup.PopupMenu( 320 parent=self._root_widget, 321 position=(h_offs + 60, v - 50), 322 width=120, 323 scale=popup_menu_scale, 324 choices=choices, 325 choices_display=choices_display, 326 current_choice=current_res_android, 327 on_value_change_call=self._set_android_res, 328 ) 329 else: 330 # if we're on a system that doesn't allow setting resolution, 331 # set pixel-scale instead 332 current_res = ba.internal.get_display_resolution() 333 if current_res is None: 334 current_res2 = ( 335 str( 336 min( 337 100, 338 max( 339 10, 340 int( 341 round( 342 ba.app.config.resolve( 343 'Screen Pixel Scale' 344 ) 345 * 100.0 346 ) 347 ), 348 ), 349 ) 350 ) 351 + '%' 352 ) # yapf: disable 353 popup.PopupMenu( 354 parent=self._root_widget, 355 position=(h_offs + 60, v - 50), 356 width=120, 357 scale=popup_menu_scale, 358 choices=['100%', '88%', '75%', '63%', '50%'], 359 current_choice=current_res2, 360 on_value_change_call=self._set_pixel_scale, 361 ) 362 else: 363 raise Exception( 364 'obsolete path; discrete resolutions' 365 ' no longer supported' 366 ) 367 368 # vsync 369 if show_vsync: 370 ba.textwidget( 371 parent=self._root_widget, 372 position=(230, v), 373 size=(160, 25), 374 text=ba.Lstr(resource=self._r + '.verticalSyncText'), 375 color=ba.app.ui.heading_color, 376 scale=0.65, 377 maxwidth=150, 378 h_align='center', 379 v_align='center', 380 ) 381 382 popup.PopupMenu( 383 parent=self._root_widget, 384 position=(230, v - 50), 385 width=150, 386 scale=popup_menu_scale, 387 choices=['Auto', 'Always', 'Never'], 388 choices_display=[ 389 ba.Lstr(resource='autoText'), 390 ba.Lstr(resource=self._r + '.alwaysText'), 391 ba.Lstr(resource=self._r + '.neverText'), 392 ], 393 current_choice=ba.app.config.resolve('Vertical Sync'), 394 on_value_change_call=self._set_vsync, 395 ) 396 397 v -= 90 398 fpsc = ConfigCheckBox( 399 parent=self._root_widget, 400 position=(69, v - 6), 401 size=(210, 30), 402 scale=0.86, 403 configkey='Show FPS', 404 displayname=ba.Lstr(resource=self._r + '.showFPSText'), 405 maxwidth=130, 406 ) 407 408 # (tv mode doesnt apply to vr) 409 if not ba.app.vr_mode: 410 tvc = ConfigCheckBox( 411 parent=self._root_widget, 412 position=(240, v - 6), 413 size=(210, 30), 414 scale=0.86, 415 configkey='TV Border', 416 displayname=ba.Lstr(resource=self._r + '.tvBorderText'), 417 maxwidth=130, 418 ) 419 # grumble.. 420 ba.widget(edit=fpsc.widget, right_widget=tvc.widget) 421 try: 422 pass 423 424 except Exception: 425 ba.print_exception('Exception wiring up graphics settings UI:') 426 427 v -= spacing 428 429 # make a timer to update our controls in case the config changes 430 # under us 431 self._update_timer = ba.Timer( 432 0.25, 433 ba.WeakCall(self._update_controls), 434 repeat=True, 435 timetype=ba.TimeType.REAL, 436 )
Inherited Members
- ba.ui.Window
- get_root_widget