bauiv1lib.creditslist
Provides a window to display game credits.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a window to display game credits.""" 4 5from __future__ import annotations 6 7import os 8import logging 9from typing import TYPE_CHECKING 10 11import bauiv1 as bui 12 13if TYPE_CHECKING: 14 from typing import Sequence 15 16 17class CreditsListWindow(bui.Window): 18 """Window for displaying game credits.""" 19 20 def __init__(self, origin_widget: bui.Widget | None = None): 21 # pylint: disable=too-many-locals 22 # pylint: disable=too-many-statements 23 import json 24 25 bui.set_analytics_screen('Credits Window') 26 27 # if they provided an origin-widget, scale up from that 28 scale_origin: tuple[float, float] | None 29 if origin_widget is not None: 30 self._transition_out = 'out_scale' 31 scale_origin = origin_widget.get_screen_space_center() 32 transition = 'in_scale' 33 else: 34 self._transition_out = 'out_right' 35 scale_origin = None 36 transition = 'in_right' 37 38 assert bui.app.classic is not None 39 uiscale = bui.app.ui_v1.uiscale 40 width = 870 if uiscale is bui.UIScale.SMALL else 670 41 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 42 height = 398 if uiscale is bui.UIScale.SMALL else 500 43 44 self._r = 'creditsWindow' 45 super().__init__( 46 root_widget=bui.containerwidget( 47 size=(width, height), 48 transition=transition, 49 toolbar_visibility='menu_minimal', 50 scale_origin_stack_offset=scale_origin, 51 scale=( 52 2.0 53 if uiscale is bui.UIScale.SMALL 54 else 1.3 55 if uiscale is bui.UIScale.MEDIUM 56 else 1.0 57 ), 58 stack_offset=(0, -8) 59 if uiscale is bui.UIScale.SMALL 60 else (0, 0), 61 ) 62 ) 63 64 if bui.app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 65 bui.containerwidget( 66 edit=self._root_widget, on_cancel_call=self._back 67 ) 68 else: 69 btn = bui.buttonwidget( 70 parent=self._root_widget, 71 position=( 72 40 + x_inset, 73 height - (68 if uiscale is bui.UIScale.SMALL else 62), 74 ), 75 size=(140, 60), 76 scale=0.8, 77 label=bui.Lstr(resource='backText'), 78 button_type='back', 79 on_activate_call=self._back, 80 autoselect=True, 81 ) 82 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 83 84 bui.buttonwidget( 85 edit=btn, 86 button_type='backSmall', 87 position=( 88 40 + x_inset, 89 height - (68 if uiscale is bui.UIScale.SMALL else 62) + 5, 90 ), 91 size=(60, 48), 92 label=bui.charstr(bui.SpecialChar.BACK), 93 ) 94 95 bui.textwidget( 96 parent=self._root_widget, 97 position=(0, height - (59 if uiscale is bui.UIScale.SMALL else 54)), 98 size=(width, 30), 99 text=bui.Lstr( 100 resource=self._r + '.titleText', 101 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 102 ), 103 h_align='center', 104 color=bui.app.ui_v1.title_color, 105 maxwidth=330, 106 v_align='center', 107 ) 108 109 scroll = bui.scrollwidget( 110 parent=self._root_widget, 111 position=(40 + x_inset, 35), 112 size=(width - (80 + 2 * x_inset), height - 100), 113 capture_arrows=True, 114 ) 115 116 if bui.app.ui_v1.use_toolbars: 117 bui.widget( 118 edit=scroll, 119 right_widget=bui.get_special_widget('party_button'), 120 ) 121 if uiscale is bui.UIScale.SMALL: 122 bui.widget( 123 edit=scroll, 124 left_widget=bui.get_special_widget('back_button'), 125 ) 126 127 def _format_names(names2: Sequence[str], inset: float) -> str: 128 sval = '' 129 # measure a series since there's overlaps and stuff.. 130 space_width = ( 131 bui.get_string_width(' ' * 10, suppress_warning=True) / 10.0 132 ) 133 spacing = 330.0 134 col1 = inset 135 col2 = col1 + spacing 136 col3 = col2 + spacing 137 line_width = 0.0 138 nline = '' 139 for name in names2: 140 # move to the next column (or row) and print 141 if line_width > col3: 142 sval += nline + '\n' 143 nline = '' 144 line_width = 0 145 146 if line_width > col2: 147 target = col3 148 elif line_width > col1: 149 target = col2 150 else: 151 target = col1 152 spacingstr = ' ' * int((target - line_width) / space_width) 153 nline += spacingstr 154 nline += name 155 line_width = bui.get_string_width(nline, suppress_warning=True) 156 if nline != '': 157 sval += nline + '\n' 158 return sval 159 160 sound_and_music = bui.Lstr( 161 resource=self._r + '.songCreditText' 162 ).evaluate() 163 sound_and_music = sound_and_music.replace( 164 '${TITLE}', "'William Tell (Trumpet Entry)'" 165 ) 166 sound_and_music = sound_and_music.replace( 167 '${PERFORMER}', 'The Apollo Symphony Orchestra' 168 ) 169 sound_and_music = sound_and_music.replace( 170 '${PERFORMER}', 'The Apollo Symphony Orchestra' 171 ) 172 sound_and_music = sound_and_music.replace( 173 '${COMPOSER}', 'Gioacchino Rossini' 174 ) 175 sound_and_music = sound_and_music.replace('${ARRANGER}', 'Chris Worth') 176 sound_and_music = sound_and_music.replace('${PUBLISHER}', 'BMI') 177 sound_and_music = sound_and_music.replace( 178 '${SOURCE}', 'www.AudioSparx.com' 179 ) 180 spc = ' ' 181 sound_and_music = spc + sound_and_music.replace('\n', '\n' + spc) 182 names = [ 183 'HubOfTheUniverseProd', 184 'Jovica', 185 'LG', 186 'Leady', 187 'Percy Duke', 188 'PhreaKsAccount', 189 'Pogotron', 190 'Rock Savage', 191 'anamorphosis', 192 'benboncan', 193 'cdrk', 194 'chipfork', 195 'guitarguy1985', 196 'jascha', 197 'joedeshon', 198 'loofa', 199 'm_O_m', 200 'mich3d', 201 'sandyrb', 202 'shakaharu', 203 'sirplus', 204 'stickman', 205 'thanvannispen', 206 'virotic', 207 'zimbot', 208 ] 209 names.sort(key=lambda x: x.lower()) 210 freesound_names = _format_names(names, 90) 211 212 try: 213 with open( 214 os.path.join( 215 bui.app.env.data_directory, 216 'ba_data', 217 'data', 218 'langdata.json', 219 ), 220 encoding='utf-8', 221 ) as infile: 222 translation_contributors = json.loads(infile.read())[ 223 'translation_contributors' 224 ] 225 except Exception: 226 logging.exception('Error reading translation contributors.') 227 translation_contributors = [] 228 229 translation_names = _format_names(translation_contributors, 60) 230 231 # Need to bake this out and chop it up since we're passing our 232 # 65535 vertex limit for meshes.. 233 # We can remove that limit once we drop support for GL ES2.. :-/ 234 # (or add mesh splitting under the hood) 235 credits_text = ( 236 ' ' 237 + bui.Lstr(resource=self._r + '.codingGraphicsAudioText') 238 .evaluate() 239 .replace('${NAME}', 'Eric Froemling') 240 + '\n' 241 '\n' 242 ' ' 243 + bui.Lstr(resource=self._r + '.additionalAudioArtIdeasText') 244 .evaluate() 245 .replace('${NAME}', 'Raphael Suter') 246 + '\n' 247 '\n' 248 ' ' 249 + bui.Lstr(resource=self._r + '.soundAndMusicText').evaluate() 250 + '\n' 251 '\n' + sound_and_music + '\n' 252 '\n' 253 ' ' 254 + bui.Lstr(resource=self._r + '.publicDomainMusicViaText') 255 .evaluate() 256 .replace('${NAME}', 'Musopen.com') 257 + '\n' 258 ' ' 259 + bui.Lstr(resource=self._r + '.thanksEspeciallyToText') 260 .evaluate() 261 .replace('${NAME}', 'the US Army, Navy, and Marine Bands') 262 + '\n' 263 '\n' 264 ' ' 265 + bui.Lstr(resource=self._r + '.additionalMusicFromText') 266 .evaluate() 267 .replace('${NAME}', 'The YouTube Audio Library') 268 + '\n' 269 '\n' 270 ' ' 271 + bui.Lstr(resource=self._r + '.soundsText') 272 .evaluate() 273 .replace('${SOURCE}', 'Freesound.org') 274 + '\n' 275 '\n' + freesound_names + '\n' 276 '\n' 277 ' ' 278 + bui.Lstr( 279 resource=self._r + '.languageTranslationsText' 280 ).evaluate() 281 + '\n' 282 '\n' 283 + '\n'.join(translation_names.splitlines()[:146]) 284 + '\n'.join(translation_names.splitlines()[146:]) 285 + '\n' 286 '\n' 287 ' Shout Out to Awesome Mods / Modders / Contributors:\n\n' 288 ' BombDash ModPack\n' 289 ' TheMikirog & SoK - BombSquad Joyride Modpack\n' 290 ' Mrmaxmeier - BombSquad-Community-Mod-Manager\n' 291 ' Ritiek Malhotra \n' 292 ' Dliwk\n' 293 ' vishal332008\n' 294 ' itsre3\n' 295 ' Drooopyyy\n' 296 '\n' 297 ' Holiday theme vector art designed by Freepik\n' 298 '\n' 299 ' ' 300 + bui.Lstr(resource=self._r + '.specialThanksText').evaluate() 301 + '\n' 302 '\n' 303 ' Todd, Laura, and Robert Froemling\n' 304 ' ' 305 + bui.Lstr(resource=self._r + '.allMyFamilyText') 306 .evaluate() 307 .replace('\n', '\n ') 308 + '\n' 309 ' ' 310 + bui.Lstr( 311 resource=self._r + '.whoeverInventedCoffeeText' 312 ).evaluate() 313 + '\n' 314 '\n' 315 ' ' + bui.Lstr(resource=self._r + '.legalText').evaluate() + '\n' 316 '\n' 317 ' ' 318 + bui.Lstr(resource=self._r + '.softwareBasedOnText') 319 .evaluate() 320 .replace('${NAME}', 'the Khronos Group') 321 + '\n' 322 '\n' 323 ' ' 324 ' www.ballistica.net\n' 325 ) 326 327 txt = credits_text 328 lines = txt.splitlines() 329 line_height = 20 330 331 scale = 0.55 332 self._sub_width = width - 80 333 self._sub_height = line_height * len(lines) + 40 334 335 container = self._subcontainer = bui.containerwidget( 336 parent=scroll, 337 size=(self._sub_width, self._sub_height), 338 background=False, 339 claims_left_right=False, 340 claims_tab=False, 341 ) 342 343 voffs = 0 344 for line in lines: 345 bui.textwidget( 346 parent=container, 347 padding=4, 348 color=(0.7, 0.9, 0.7, 1.0), 349 scale=scale, 350 flatness=1.0, 351 size=(0, 0), 352 position=(0, self._sub_height - 20 + voffs), 353 h_align='left', 354 v_align='top', 355 text=bui.Lstr(value=line), 356 ) 357 voffs -= line_height 358 359 def _back(self) -> None: 360 from bauiv1lib.mainmenu import MainMenuWindow 361 362 bui.containerwidget( 363 edit=self._root_widget, transition=self._transition_out 364 ) 365 assert bui.app.classic is not None 366 bui.app.ui_v1.set_main_menu_window( 367 MainMenuWindow(transition='in_left').get_root_widget() 368 )
class
CreditsListWindow(bauiv1._uitypes.Window):
18class CreditsListWindow(bui.Window): 19 """Window for displaying game credits.""" 20 21 def __init__(self, origin_widget: bui.Widget | None = None): 22 # pylint: disable=too-many-locals 23 # pylint: disable=too-many-statements 24 import json 25 26 bui.set_analytics_screen('Credits Window') 27 28 # if they provided an origin-widget, scale up from that 29 scale_origin: tuple[float, float] | None 30 if origin_widget is not None: 31 self._transition_out = 'out_scale' 32 scale_origin = origin_widget.get_screen_space_center() 33 transition = 'in_scale' 34 else: 35 self._transition_out = 'out_right' 36 scale_origin = None 37 transition = 'in_right' 38 39 assert bui.app.classic is not None 40 uiscale = bui.app.ui_v1.uiscale 41 width = 870 if uiscale is bui.UIScale.SMALL else 670 42 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 43 height = 398 if uiscale is bui.UIScale.SMALL else 500 44 45 self._r = 'creditsWindow' 46 super().__init__( 47 root_widget=bui.containerwidget( 48 size=(width, height), 49 transition=transition, 50 toolbar_visibility='menu_minimal', 51 scale_origin_stack_offset=scale_origin, 52 scale=( 53 2.0 54 if uiscale is bui.UIScale.SMALL 55 else 1.3 56 if uiscale is bui.UIScale.MEDIUM 57 else 1.0 58 ), 59 stack_offset=(0, -8) 60 if uiscale is bui.UIScale.SMALL 61 else (0, 0), 62 ) 63 ) 64 65 if bui.app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 66 bui.containerwidget( 67 edit=self._root_widget, on_cancel_call=self._back 68 ) 69 else: 70 btn = bui.buttonwidget( 71 parent=self._root_widget, 72 position=( 73 40 + x_inset, 74 height - (68 if uiscale is bui.UIScale.SMALL else 62), 75 ), 76 size=(140, 60), 77 scale=0.8, 78 label=bui.Lstr(resource='backText'), 79 button_type='back', 80 on_activate_call=self._back, 81 autoselect=True, 82 ) 83 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 84 85 bui.buttonwidget( 86 edit=btn, 87 button_type='backSmall', 88 position=( 89 40 + x_inset, 90 height - (68 if uiscale is bui.UIScale.SMALL else 62) + 5, 91 ), 92 size=(60, 48), 93 label=bui.charstr(bui.SpecialChar.BACK), 94 ) 95 96 bui.textwidget( 97 parent=self._root_widget, 98 position=(0, height - (59 if uiscale is bui.UIScale.SMALL else 54)), 99 size=(width, 30), 100 text=bui.Lstr( 101 resource=self._r + '.titleText', 102 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 103 ), 104 h_align='center', 105 color=bui.app.ui_v1.title_color, 106 maxwidth=330, 107 v_align='center', 108 ) 109 110 scroll = bui.scrollwidget( 111 parent=self._root_widget, 112 position=(40 + x_inset, 35), 113 size=(width - (80 + 2 * x_inset), height - 100), 114 capture_arrows=True, 115 ) 116 117 if bui.app.ui_v1.use_toolbars: 118 bui.widget( 119 edit=scroll, 120 right_widget=bui.get_special_widget('party_button'), 121 ) 122 if uiscale is bui.UIScale.SMALL: 123 bui.widget( 124 edit=scroll, 125 left_widget=bui.get_special_widget('back_button'), 126 ) 127 128 def _format_names(names2: Sequence[str], inset: float) -> str: 129 sval = '' 130 # measure a series since there's overlaps and stuff.. 131 space_width = ( 132 bui.get_string_width(' ' * 10, suppress_warning=True) / 10.0 133 ) 134 spacing = 330.0 135 col1 = inset 136 col2 = col1 + spacing 137 col3 = col2 + spacing 138 line_width = 0.0 139 nline = '' 140 for name in names2: 141 # move to the next column (or row) and print 142 if line_width > col3: 143 sval += nline + '\n' 144 nline = '' 145 line_width = 0 146 147 if line_width > col2: 148 target = col3 149 elif line_width > col1: 150 target = col2 151 else: 152 target = col1 153 spacingstr = ' ' * int((target - line_width) / space_width) 154 nline += spacingstr 155 nline += name 156 line_width = bui.get_string_width(nline, suppress_warning=True) 157 if nline != '': 158 sval += nline + '\n' 159 return sval 160 161 sound_and_music = bui.Lstr( 162 resource=self._r + '.songCreditText' 163 ).evaluate() 164 sound_and_music = sound_and_music.replace( 165 '${TITLE}', "'William Tell (Trumpet Entry)'" 166 ) 167 sound_and_music = sound_and_music.replace( 168 '${PERFORMER}', 'The Apollo Symphony Orchestra' 169 ) 170 sound_and_music = sound_and_music.replace( 171 '${PERFORMER}', 'The Apollo Symphony Orchestra' 172 ) 173 sound_and_music = sound_and_music.replace( 174 '${COMPOSER}', 'Gioacchino Rossini' 175 ) 176 sound_and_music = sound_and_music.replace('${ARRANGER}', 'Chris Worth') 177 sound_and_music = sound_and_music.replace('${PUBLISHER}', 'BMI') 178 sound_and_music = sound_and_music.replace( 179 '${SOURCE}', 'www.AudioSparx.com' 180 ) 181 spc = ' ' 182 sound_and_music = spc + sound_and_music.replace('\n', '\n' + spc) 183 names = [ 184 'HubOfTheUniverseProd', 185 'Jovica', 186 'LG', 187 'Leady', 188 'Percy Duke', 189 'PhreaKsAccount', 190 'Pogotron', 191 'Rock Savage', 192 'anamorphosis', 193 'benboncan', 194 'cdrk', 195 'chipfork', 196 'guitarguy1985', 197 'jascha', 198 'joedeshon', 199 'loofa', 200 'm_O_m', 201 'mich3d', 202 'sandyrb', 203 'shakaharu', 204 'sirplus', 205 'stickman', 206 'thanvannispen', 207 'virotic', 208 'zimbot', 209 ] 210 names.sort(key=lambda x: x.lower()) 211 freesound_names = _format_names(names, 90) 212 213 try: 214 with open( 215 os.path.join( 216 bui.app.env.data_directory, 217 'ba_data', 218 'data', 219 'langdata.json', 220 ), 221 encoding='utf-8', 222 ) as infile: 223 translation_contributors = json.loads(infile.read())[ 224 'translation_contributors' 225 ] 226 except Exception: 227 logging.exception('Error reading translation contributors.') 228 translation_contributors = [] 229 230 translation_names = _format_names(translation_contributors, 60) 231 232 # Need to bake this out and chop it up since we're passing our 233 # 65535 vertex limit for meshes.. 234 # We can remove that limit once we drop support for GL ES2.. :-/ 235 # (or add mesh splitting under the hood) 236 credits_text = ( 237 ' ' 238 + bui.Lstr(resource=self._r + '.codingGraphicsAudioText') 239 .evaluate() 240 .replace('${NAME}', 'Eric Froemling') 241 + '\n' 242 '\n' 243 ' ' 244 + bui.Lstr(resource=self._r + '.additionalAudioArtIdeasText') 245 .evaluate() 246 .replace('${NAME}', 'Raphael Suter') 247 + '\n' 248 '\n' 249 ' ' 250 + bui.Lstr(resource=self._r + '.soundAndMusicText').evaluate() 251 + '\n' 252 '\n' + sound_and_music + '\n' 253 '\n' 254 ' ' 255 + bui.Lstr(resource=self._r + '.publicDomainMusicViaText') 256 .evaluate() 257 .replace('${NAME}', 'Musopen.com') 258 + '\n' 259 ' ' 260 + bui.Lstr(resource=self._r + '.thanksEspeciallyToText') 261 .evaluate() 262 .replace('${NAME}', 'the US Army, Navy, and Marine Bands') 263 + '\n' 264 '\n' 265 ' ' 266 + bui.Lstr(resource=self._r + '.additionalMusicFromText') 267 .evaluate() 268 .replace('${NAME}', 'The YouTube Audio Library') 269 + '\n' 270 '\n' 271 ' ' 272 + bui.Lstr(resource=self._r + '.soundsText') 273 .evaluate() 274 .replace('${SOURCE}', 'Freesound.org') 275 + '\n' 276 '\n' + freesound_names + '\n' 277 '\n' 278 ' ' 279 + bui.Lstr( 280 resource=self._r + '.languageTranslationsText' 281 ).evaluate() 282 + '\n' 283 '\n' 284 + '\n'.join(translation_names.splitlines()[:146]) 285 + '\n'.join(translation_names.splitlines()[146:]) 286 + '\n' 287 '\n' 288 ' Shout Out to Awesome Mods / Modders / Contributors:\n\n' 289 ' BombDash ModPack\n' 290 ' TheMikirog & SoK - BombSquad Joyride Modpack\n' 291 ' Mrmaxmeier - BombSquad-Community-Mod-Manager\n' 292 ' Ritiek Malhotra \n' 293 ' Dliwk\n' 294 ' vishal332008\n' 295 ' itsre3\n' 296 ' Drooopyyy\n' 297 '\n' 298 ' Holiday theme vector art designed by Freepik\n' 299 '\n' 300 ' ' 301 + bui.Lstr(resource=self._r + '.specialThanksText').evaluate() 302 + '\n' 303 '\n' 304 ' Todd, Laura, and Robert Froemling\n' 305 ' ' 306 + bui.Lstr(resource=self._r + '.allMyFamilyText') 307 .evaluate() 308 .replace('\n', '\n ') 309 + '\n' 310 ' ' 311 + bui.Lstr( 312 resource=self._r + '.whoeverInventedCoffeeText' 313 ).evaluate() 314 + '\n' 315 '\n' 316 ' ' + bui.Lstr(resource=self._r + '.legalText').evaluate() + '\n' 317 '\n' 318 ' ' 319 + bui.Lstr(resource=self._r + '.softwareBasedOnText') 320 .evaluate() 321 .replace('${NAME}', 'the Khronos Group') 322 + '\n' 323 '\n' 324 ' ' 325 ' www.ballistica.net\n' 326 ) 327 328 txt = credits_text 329 lines = txt.splitlines() 330 line_height = 20 331 332 scale = 0.55 333 self._sub_width = width - 80 334 self._sub_height = line_height * len(lines) + 40 335 336 container = self._subcontainer = bui.containerwidget( 337 parent=scroll, 338 size=(self._sub_width, self._sub_height), 339 background=False, 340 claims_left_right=False, 341 claims_tab=False, 342 ) 343 344 voffs = 0 345 for line in lines: 346 bui.textwidget( 347 parent=container, 348 padding=4, 349 color=(0.7, 0.9, 0.7, 1.0), 350 scale=scale, 351 flatness=1.0, 352 size=(0, 0), 353 position=(0, self._sub_height - 20 + voffs), 354 h_align='left', 355 v_align='top', 356 text=bui.Lstr(value=line), 357 ) 358 voffs -= line_height 359 360 def _back(self) -> None: 361 from bauiv1lib.mainmenu import MainMenuWindow 362 363 bui.containerwidget( 364 edit=self._root_widget, transition=self._transition_out 365 ) 366 assert bui.app.classic is not None 367 bui.app.ui_v1.set_main_menu_window( 368 MainMenuWindow(transition='in_left').get_root_widget() 369 )
Window for displaying game credits.
CreditsListWindow(origin_widget: _bauiv1.Widget | None = None)
21 def __init__(self, origin_widget: bui.Widget | None = None): 22 # pylint: disable=too-many-locals 23 # pylint: disable=too-many-statements 24 import json 25 26 bui.set_analytics_screen('Credits Window') 27 28 # if they provided an origin-widget, scale up from that 29 scale_origin: tuple[float, float] | None 30 if origin_widget is not None: 31 self._transition_out = 'out_scale' 32 scale_origin = origin_widget.get_screen_space_center() 33 transition = 'in_scale' 34 else: 35 self._transition_out = 'out_right' 36 scale_origin = None 37 transition = 'in_right' 38 39 assert bui.app.classic is not None 40 uiscale = bui.app.ui_v1.uiscale 41 width = 870 if uiscale is bui.UIScale.SMALL else 670 42 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 43 height = 398 if uiscale is bui.UIScale.SMALL else 500 44 45 self._r = 'creditsWindow' 46 super().__init__( 47 root_widget=bui.containerwidget( 48 size=(width, height), 49 transition=transition, 50 toolbar_visibility='menu_minimal', 51 scale_origin_stack_offset=scale_origin, 52 scale=( 53 2.0 54 if uiscale is bui.UIScale.SMALL 55 else 1.3 56 if uiscale is bui.UIScale.MEDIUM 57 else 1.0 58 ), 59 stack_offset=(0, -8) 60 if uiscale is bui.UIScale.SMALL 61 else (0, 0), 62 ) 63 ) 64 65 if bui.app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 66 bui.containerwidget( 67 edit=self._root_widget, on_cancel_call=self._back 68 ) 69 else: 70 btn = bui.buttonwidget( 71 parent=self._root_widget, 72 position=( 73 40 + x_inset, 74 height - (68 if uiscale is bui.UIScale.SMALL else 62), 75 ), 76 size=(140, 60), 77 scale=0.8, 78 label=bui.Lstr(resource='backText'), 79 button_type='back', 80 on_activate_call=self._back, 81 autoselect=True, 82 ) 83 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 84 85 bui.buttonwidget( 86 edit=btn, 87 button_type='backSmall', 88 position=( 89 40 + x_inset, 90 height - (68 if uiscale is bui.UIScale.SMALL else 62) + 5, 91 ), 92 size=(60, 48), 93 label=bui.charstr(bui.SpecialChar.BACK), 94 ) 95 96 bui.textwidget( 97 parent=self._root_widget, 98 position=(0, height - (59 if uiscale is bui.UIScale.SMALL else 54)), 99 size=(width, 30), 100 text=bui.Lstr( 101 resource=self._r + '.titleText', 102 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 103 ), 104 h_align='center', 105 color=bui.app.ui_v1.title_color, 106 maxwidth=330, 107 v_align='center', 108 ) 109 110 scroll = bui.scrollwidget( 111 parent=self._root_widget, 112 position=(40 + x_inset, 35), 113 size=(width - (80 + 2 * x_inset), height - 100), 114 capture_arrows=True, 115 ) 116 117 if bui.app.ui_v1.use_toolbars: 118 bui.widget( 119 edit=scroll, 120 right_widget=bui.get_special_widget('party_button'), 121 ) 122 if uiscale is bui.UIScale.SMALL: 123 bui.widget( 124 edit=scroll, 125 left_widget=bui.get_special_widget('back_button'), 126 ) 127 128 def _format_names(names2: Sequence[str], inset: float) -> str: 129 sval = '' 130 # measure a series since there's overlaps and stuff.. 131 space_width = ( 132 bui.get_string_width(' ' * 10, suppress_warning=True) / 10.0 133 ) 134 spacing = 330.0 135 col1 = inset 136 col2 = col1 + spacing 137 col3 = col2 + spacing 138 line_width = 0.0 139 nline = '' 140 for name in names2: 141 # move to the next column (or row) and print 142 if line_width > col3: 143 sval += nline + '\n' 144 nline = '' 145 line_width = 0 146 147 if line_width > col2: 148 target = col3 149 elif line_width > col1: 150 target = col2 151 else: 152 target = col1 153 spacingstr = ' ' * int((target - line_width) / space_width) 154 nline += spacingstr 155 nline += name 156 line_width = bui.get_string_width(nline, suppress_warning=True) 157 if nline != '': 158 sval += nline + '\n' 159 return sval 160 161 sound_and_music = bui.Lstr( 162 resource=self._r + '.songCreditText' 163 ).evaluate() 164 sound_and_music = sound_and_music.replace( 165 '${TITLE}', "'William Tell (Trumpet Entry)'" 166 ) 167 sound_and_music = sound_and_music.replace( 168 '${PERFORMER}', 'The Apollo Symphony Orchestra' 169 ) 170 sound_and_music = sound_and_music.replace( 171 '${PERFORMER}', 'The Apollo Symphony Orchestra' 172 ) 173 sound_and_music = sound_and_music.replace( 174 '${COMPOSER}', 'Gioacchino Rossini' 175 ) 176 sound_and_music = sound_and_music.replace('${ARRANGER}', 'Chris Worth') 177 sound_and_music = sound_and_music.replace('${PUBLISHER}', 'BMI') 178 sound_and_music = sound_and_music.replace( 179 '${SOURCE}', 'www.AudioSparx.com' 180 ) 181 spc = ' ' 182 sound_and_music = spc + sound_and_music.replace('\n', '\n' + spc) 183 names = [ 184 'HubOfTheUniverseProd', 185 'Jovica', 186 'LG', 187 'Leady', 188 'Percy Duke', 189 'PhreaKsAccount', 190 'Pogotron', 191 'Rock Savage', 192 'anamorphosis', 193 'benboncan', 194 'cdrk', 195 'chipfork', 196 'guitarguy1985', 197 'jascha', 198 'joedeshon', 199 'loofa', 200 'm_O_m', 201 'mich3d', 202 'sandyrb', 203 'shakaharu', 204 'sirplus', 205 'stickman', 206 'thanvannispen', 207 'virotic', 208 'zimbot', 209 ] 210 names.sort(key=lambda x: x.lower()) 211 freesound_names = _format_names(names, 90) 212 213 try: 214 with open( 215 os.path.join( 216 bui.app.env.data_directory, 217 'ba_data', 218 'data', 219 'langdata.json', 220 ), 221 encoding='utf-8', 222 ) as infile: 223 translation_contributors = json.loads(infile.read())[ 224 'translation_contributors' 225 ] 226 except Exception: 227 logging.exception('Error reading translation contributors.') 228 translation_contributors = [] 229 230 translation_names = _format_names(translation_contributors, 60) 231 232 # Need to bake this out and chop it up since we're passing our 233 # 65535 vertex limit for meshes.. 234 # We can remove that limit once we drop support for GL ES2.. :-/ 235 # (or add mesh splitting under the hood) 236 credits_text = ( 237 ' ' 238 + bui.Lstr(resource=self._r + '.codingGraphicsAudioText') 239 .evaluate() 240 .replace('${NAME}', 'Eric Froemling') 241 + '\n' 242 '\n' 243 ' ' 244 + bui.Lstr(resource=self._r + '.additionalAudioArtIdeasText') 245 .evaluate() 246 .replace('${NAME}', 'Raphael Suter') 247 + '\n' 248 '\n' 249 ' ' 250 + bui.Lstr(resource=self._r + '.soundAndMusicText').evaluate() 251 + '\n' 252 '\n' + sound_and_music + '\n' 253 '\n' 254 ' ' 255 + bui.Lstr(resource=self._r + '.publicDomainMusicViaText') 256 .evaluate() 257 .replace('${NAME}', 'Musopen.com') 258 + '\n' 259 ' ' 260 + bui.Lstr(resource=self._r + '.thanksEspeciallyToText') 261 .evaluate() 262 .replace('${NAME}', 'the US Army, Navy, and Marine Bands') 263 + '\n' 264 '\n' 265 ' ' 266 + bui.Lstr(resource=self._r + '.additionalMusicFromText') 267 .evaluate() 268 .replace('${NAME}', 'The YouTube Audio Library') 269 + '\n' 270 '\n' 271 ' ' 272 + bui.Lstr(resource=self._r + '.soundsText') 273 .evaluate() 274 .replace('${SOURCE}', 'Freesound.org') 275 + '\n' 276 '\n' + freesound_names + '\n' 277 '\n' 278 ' ' 279 + bui.Lstr( 280 resource=self._r + '.languageTranslationsText' 281 ).evaluate() 282 + '\n' 283 '\n' 284 + '\n'.join(translation_names.splitlines()[:146]) 285 + '\n'.join(translation_names.splitlines()[146:]) 286 + '\n' 287 '\n' 288 ' Shout Out to Awesome Mods / Modders / Contributors:\n\n' 289 ' BombDash ModPack\n' 290 ' TheMikirog & SoK - BombSquad Joyride Modpack\n' 291 ' Mrmaxmeier - BombSquad-Community-Mod-Manager\n' 292 ' Ritiek Malhotra \n' 293 ' Dliwk\n' 294 ' vishal332008\n' 295 ' itsre3\n' 296 ' Drooopyyy\n' 297 '\n' 298 ' Holiday theme vector art designed by Freepik\n' 299 '\n' 300 ' ' 301 + bui.Lstr(resource=self._r + '.specialThanksText').evaluate() 302 + '\n' 303 '\n' 304 ' Todd, Laura, and Robert Froemling\n' 305 ' ' 306 + bui.Lstr(resource=self._r + '.allMyFamilyText') 307 .evaluate() 308 .replace('\n', '\n ') 309 + '\n' 310 ' ' 311 + bui.Lstr( 312 resource=self._r + '.whoeverInventedCoffeeText' 313 ).evaluate() 314 + '\n' 315 '\n' 316 ' ' + bui.Lstr(resource=self._r + '.legalText').evaluate() + '\n' 317 '\n' 318 ' ' 319 + bui.Lstr(resource=self._r + '.softwareBasedOnText') 320 .evaluate() 321 .replace('${NAME}', 'the Khronos Group') 322 + '\n' 323 '\n' 324 ' ' 325 ' www.ballistica.net\n' 326 ) 327 328 txt = credits_text 329 lines = txt.splitlines() 330 line_height = 20 331 332 scale = 0.55 333 self._sub_width = width - 80 334 self._sub_height = line_height * len(lines) + 40 335 336 container = self._subcontainer = bui.containerwidget( 337 parent=scroll, 338 size=(self._sub_width, self._sub_height), 339 background=False, 340 claims_left_right=False, 341 claims_tab=False, 342 ) 343 344 voffs = 0 345 for line in lines: 346 bui.textwidget( 347 parent=container, 348 padding=4, 349 color=(0.7, 0.9, 0.7, 1.0), 350 scale=scale, 351 flatness=1.0, 352 size=(0, 0), 353 position=(0, self._sub_height - 20 + voffs), 354 h_align='left', 355 v_align='top', 356 text=bui.Lstr(value=line), 357 ) 358 voffs -= line_height
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget