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