bauiv1lib.coop.gamebutton
Defines button for co-op games.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defines button for co-op games.""" 4 5from __future__ import annotations 6 7import random 8from typing import TYPE_CHECKING 9 10import bauiv1 as bui 11 12if TYPE_CHECKING: 13 from bauiv1lib.coop.browser import CoopBrowserWindow 14 15 16class GameButton: 17 """Button for entering co-op games.""" 18 19 def __init__( 20 self, 21 window: CoopBrowserWindow, 22 parent: bui.Widget, 23 game: str, 24 x: float, 25 y: float, 26 select: bool, 27 row: str, 28 ): 29 # pylint: disable=too-many-statements 30 # pylint: disable=too-many-locals 31 32 assert bui.app.classic is not None 33 self._game = game 34 sclx = 195.0 35 scly = 195.0 36 37 campaignname, levelname = game.split(':') 38 39 # Hack: The Last Stand doesn't actually exist in the easy 40 # tourney. We just want it for display purposes. Map it to 41 # the hard-mode version. 42 if game == 'Easy:The Last Stand': 43 campaignname = 'Default' 44 45 rating: float | None 46 campaign = bui.app.classic.getcampaign(campaignname) 47 rating = campaign.getlevel(levelname).rating 48 49 if game == 'Easy:The Last Stand': 50 rating = None 51 52 if rating is None or rating == 0.0: 53 stars = 0 54 elif rating >= 9.5: 55 stars = 3 56 elif rating >= 7.5: 57 stars = 2 58 else: 59 stars = 1 60 61 self._button = btn = bui.buttonwidget( 62 parent=parent, 63 position=(x + 23, y + 4), 64 size=(sclx, scly), 65 label='', 66 on_activate_call=bui.Call(window.run_game, game), 67 button_type='square', 68 autoselect=True, 69 on_select_call=bui.Call(window.sel_change, row, game), 70 ) 71 bui.widget( 72 edit=btn, 73 show_buffer_bottom=50, 74 show_buffer_top=50, 75 show_buffer_left=400, 76 show_buffer_right=200, 77 ) 78 if select: 79 bui.containerwidget( 80 edit=parent, selected_child=btn, visible_child=btn 81 ) 82 image_width = sclx * 0.85 * 0.75 83 self._preview_widget = bui.imagewidget( 84 parent=parent, 85 draw_controller=btn, 86 position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104), 87 size=(image_width, image_width * 0.5), 88 mesh_transparent=window.lsbt, 89 mesh_opaque=window.lsbo, 90 texture=bui.gettexture( 91 campaign.getlevel(levelname).preview_texture_name 92 ), 93 mask_texture=bui.gettexture('mapPreviewMask'), 94 ) 95 96 translated = campaign.getlevel(levelname).displayname 97 self._achievements = bui.app.classic.ach.achievements_for_coop_level( 98 game 99 ) 100 101 self._name_widget = bui.textwidget( 102 parent=parent, 103 draw_controller=btn, 104 position=(x + 20 + sclx * 0.5, y + scly - 27), 105 size=(0, 0), 106 h_align='center', 107 text=translated, 108 v_align='center', 109 maxwidth=sclx * 0.76, 110 scale=0.85, 111 ) 112 xscl = x + (67 if self._achievements else 50) 113 yscl = y + scly - (137 if self._achievements else 157) 114 115 starscale = 35.0 if self._achievements else 45.0 116 117 self._star_widgets: list[bui.Widget] = [] 118 for _i in range(stars): 119 imw = bui.imagewidget( 120 parent=parent, 121 draw_controller=btn, 122 position=(xscl, yscl), 123 size=(starscale, starscale), 124 texture=window.star_tex, 125 ) 126 self._star_widgets.append(imw) 127 xscl += starscale 128 for _i in range(3 - stars): 129 bui.imagewidget( 130 parent=parent, 131 draw_controller=btn, 132 position=(xscl, yscl), 133 size=(starscale, starscale), 134 color=(0, 0, 0), 135 texture=window.star_tex, 136 opacity=0.3, 137 ) 138 xscl += starscale 139 140 xach = x + 69 141 yach = y + scly - 168 142 a_scale = 30.0 143 self._achievement_widgets: list[tuple[bui.Widget, bui.Widget]] = [] 144 for ach in self._achievements: 145 a_complete = ach.complete 146 imw = bui.imagewidget( 147 parent=parent, 148 draw_controller=btn, 149 position=(xach, yach), 150 size=(a_scale, a_scale), 151 color=( 152 tuple(ach.get_icon_color(a_complete)[:3]) 153 if a_complete 154 else (1.2, 1.2, 1.2) 155 ), 156 texture=ach.get_icon_ui_texture(a_complete), 157 ) 158 imw2 = bui.imagewidget( 159 parent=parent, 160 draw_controller=btn, 161 position=(xach, yach), 162 size=(a_scale, a_scale), 163 color=(2, 1.4, 0.4), 164 texture=window.a_outline_tex, 165 mesh_transparent=window.a_outline_mesh, 166 ) 167 self._achievement_widgets.append((imw, imw2)) 168 # if a_complete: 169 xach += a_scale * 1.2 170 171 # if not unlocked: 172 self._lock_widget = bui.imagewidget( 173 parent=parent, 174 draw_controller=btn, 175 position=(x - 8 + sclx * 0.5, y + scly * 0.5 - 20), 176 size=(60, 60), 177 opacity=0.0, 178 texture=bui.gettexture('lock'), 179 ) 180 181 # give a quasi-random update increment to spread the load.. 182 self._update_timer = bui.AppTimer( 183 0.001 * (900 + random.randrange(200)), 184 bui.WeakCall(self._update), 185 repeat=True, 186 ) 187 self._update() 188 189 def get_button(self) -> bui.Widget: 190 """Return the underlying button bui.Widget.""" 191 return self._button 192 193 def _update(self) -> None: 194 # pylint: disable=too-many-boolean-expressions 195 196 plus = bui.app.plus 197 assert plus is not None 198 199 classic = bui.app.classic 200 assert classic is not None 201 202 # In case we stick around after our UI... 203 if not self._button: 204 return 205 206 game = self._game 207 campaignname, levelname = game.split(':') 208 209 # Hack - The Last Stand doesn't actually exist in the 210 # easy tourney; we just want it for display purposes. Map it to 211 # the hard-mode version. 212 if game == 'Easy:The Last Stand': 213 campaignname = 'Default' 214 215 campaign = classic.getcampaign(campaignname) 216 217 # If this campaign is sequential, make sure we've unlocked 218 # everything up to here. 219 unlocked = True 220 if campaign.sequential: 221 for level in campaign.levels: 222 if level.name == levelname: 223 break 224 if not level.complete: 225 unlocked = False 226 break 227 228 # We never actually allow playing last-stand on easy mode. 229 if game == 'Easy:The Last Stand': 230 unlocked = False 231 232 # Hard-code games we haven't unlocked. 233 assert bui.app.classic is not None 234 if ( 235 ( 236 game 237 in ( 238 'Challenges:Infinite Runaround', 239 'Challenges:Infinite Onslaught', 240 ) 241 and not bui.app.classic.accounts.have_pro() 242 ) 243 or ( 244 game in ('Challenges:Meteor Shower',) 245 and not plus.get_purchased('games.meteor_shower') 246 ) 247 or ( 248 game 249 in ( 250 'Challenges:Target Practice', 251 'Challenges:Target Practice B', 252 ) 253 and not plus.get_purchased('games.target_practice') 254 ) 255 or ( 256 game in ('Challenges:Ninja Fight',) 257 and not plus.get_purchased('games.ninja_fight') 258 ) 259 or ( 260 game in ('Challenges:Pro Ninja Fight',) 261 and not plus.get_purchased('games.ninja_fight') 262 ) 263 or ( 264 game 265 in ( 266 'Challenges:Easter Egg Hunt', 267 'Challenges:Pro Easter Egg Hunt', 268 ) 269 and not plus.get_purchased('games.easter_egg_hunt') 270 ) 271 ): 272 unlocked = False 273 274 # Let's tint levels a slightly different color when easy mode 275 # is selected. 276 unlocked_color = ( 277 (0.85, 0.95, 0.5) if game.startswith('Easy:') else (0.5, 0.7, 0.2) 278 ) 279 280 bui.buttonwidget( 281 edit=self._button, 282 color=unlocked_color if unlocked else (0.5, 0.5, 0.5), 283 ) 284 285 bui.imagewidget( 286 edit=self._lock_widget, opacity=0.0 if unlocked else 1.0 287 ) 288 bui.imagewidget( 289 edit=self._preview_widget, opacity=1.0 if unlocked else 0.3 290 ) 291 bui.textwidget( 292 edit=self._name_widget, 293 color=(0.8, 1.0, 0.8, 1.0) if unlocked else (0.7, 0.7, 0.7, 0.7), 294 ) 295 for widget in self._star_widgets: 296 bui.imagewidget( 297 edit=widget, 298 opacity=1.0 if unlocked else 0.3, 299 color=(2.2, 1.2, 0.3) if unlocked else (1, 1, 1), 300 ) 301 for i, ach in enumerate(self._achievements): 302 a_complete = ach.complete 303 bui.imagewidget( 304 edit=self._achievement_widgets[i][0], 305 opacity=1.0 if (a_complete and unlocked) else 0.3, 306 ) 307 bui.imagewidget( 308 edit=self._achievement_widgets[i][1], 309 opacity=( 310 1.0 311 if (a_complete and unlocked) 312 else 0.2 if a_complete else 0.0 313 ), 314 )
class
GameButton:
17class GameButton: 18 """Button for entering co-op games.""" 19 20 def __init__( 21 self, 22 window: CoopBrowserWindow, 23 parent: bui.Widget, 24 game: str, 25 x: float, 26 y: float, 27 select: bool, 28 row: str, 29 ): 30 # pylint: disable=too-many-statements 31 # pylint: disable=too-many-locals 32 33 assert bui.app.classic is not None 34 self._game = game 35 sclx = 195.0 36 scly = 195.0 37 38 campaignname, levelname = game.split(':') 39 40 # Hack: The Last Stand doesn't actually exist in the easy 41 # tourney. We just want it for display purposes. Map it to 42 # the hard-mode version. 43 if game == 'Easy:The Last Stand': 44 campaignname = 'Default' 45 46 rating: float | None 47 campaign = bui.app.classic.getcampaign(campaignname) 48 rating = campaign.getlevel(levelname).rating 49 50 if game == 'Easy:The Last Stand': 51 rating = None 52 53 if rating is None or rating == 0.0: 54 stars = 0 55 elif rating >= 9.5: 56 stars = 3 57 elif rating >= 7.5: 58 stars = 2 59 else: 60 stars = 1 61 62 self._button = btn = bui.buttonwidget( 63 parent=parent, 64 position=(x + 23, y + 4), 65 size=(sclx, scly), 66 label='', 67 on_activate_call=bui.Call(window.run_game, game), 68 button_type='square', 69 autoselect=True, 70 on_select_call=bui.Call(window.sel_change, row, game), 71 ) 72 bui.widget( 73 edit=btn, 74 show_buffer_bottom=50, 75 show_buffer_top=50, 76 show_buffer_left=400, 77 show_buffer_right=200, 78 ) 79 if select: 80 bui.containerwidget( 81 edit=parent, selected_child=btn, visible_child=btn 82 ) 83 image_width = sclx * 0.85 * 0.75 84 self._preview_widget = bui.imagewidget( 85 parent=parent, 86 draw_controller=btn, 87 position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104), 88 size=(image_width, image_width * 0.5), 89 mesh_transparent=window.lsbt, 90 mesh_opaque=window.lsbo, 91 texture=bui.gettexture( 92 campaign.getlevel(levelname).preview_texture_name 93 ), 94 mask_texture=bui.gettexture('mapPreviewMask'), 95 ) 96 97 translated = campaign.getlevel(levelname).displayname 98 self._achievements = bui.app.classic.ach.achievements_for_coop_level( 99 game 100 ) 101 102 self._name_widget = bui.textwidget( 103 parent=parent, 104 draw_controller=btn, 105 position=(x + 20 + sclx * 0.5, y + scly - 27), 106 size=(0, 0), 107 h_align='center', 108 text=translated, 109 v_align='center', 110 maxwidth=sclx * 0.76, 111 scale=0.85, 112 ) 113 xscl = x + (67 if self._achievements else 50) 114 yscl = y + scly - (137 if self._achievements else 157) 115 116 starscale = 35.0 if self._achievements else 45.0 117 118 self._star_widgets: list[bui.Widget] = [] 119 for _i in range(stars): 120 imw = bui.imagewidget( 121 parent=parent, 122 draw_controller=btn, 123 position=(xscl, yscl), 124 size=(starscale, starscale), 125 texture=window.star_tex, 126 ) 127 self._star_widgets.append(imw) 128 xscl += starscale 129 for _i in range(3 - stars): 130 bui.imagewidget( 131 parent=parent, 132 draw_controller=btn, 133 position=(xscl, yscl), 134 size=(starscale, starscale), 135 color=(0, 0, 0), 136 texture=window.star_tex, 137 opacity=0.3, 138 ) 139 xscl += starscale 140 141 xach = x + 69 142 yach = y + scly - 168 143 a_scale = 30.0 144 self._achievement_widgets: list[tuple[bui.Widget, bui.Widget]] = [] 145 for ach in self._achievements: 146 a_complete = ach.complete 147 imw = bui.imagewidget( 148 parent=parent, 149 draw_controller=btn, 150 position=(xach, yach), 151 size=(a_scale, a_scale), 152 color=( 153 tuple(ach.get_icon_color(a_complete)[:3]) 154 if a_complete 155 else (1.2, 1.2, 1.2) 156 ), 157 texture=ach.get_icon_ui_texture(a_complete), 158 ) 159 imw2 = bui.imagewidget( 160 parent=parent, 161 draw_controller=btn, 162 position=(xach, yach), 163 size=(a_scale, a_scale), 164 color=(2, 1.4, 0.4), 165 texture=window.a_outline_tex, 166 mesh_transparent=window.a_outline_mesh, 167 ) 168 self._achievement_widgets.append((imw, imw2)) 169 # if a_complete: 170 xach += a_scale * 1.2 171 172 # if not unlocked: 173 self._lock_widget = bui.imagewidget( 174 parent=parent, 175 draw_controller=btn, 176 position=(x - 8 + sclx * 0.5, y + scly * 0.5 - 20), 177 size=(60, 60), 178 opacity=0.0, 179 texture=bui.gettexture('lock'), 180 ) 181 182 # give a quasi-random update increment to spread the load.. 183 self._update_timer = bui.AppTimer( 184 0.001 * (900 + random.randrange(200)), 185 bui.WeakCall(self._update), 186 repeat=True, 187 ) 188 self._update() 189 190 def get_button(self) -> bui.Widget: 191 """Return the underlying button bui.Widget.""" 192 return self._button 193 194 def _update(self) -> None: 195 # pylint: disable=too-many-boolean-expressions 196 197 plus = bui.app.plus 198 assert plus is not None 199 200 classic = bui.app.classic 201 assert classic is not None 202 203 # In case we stick around after our UI... 204 if not self._button: 205 return 206 207 game = self._game 208 campaignname, levelname = game.split(':') 209 210 # Hack - The Last Stand doesn't actually exist in the 211 # easy tourney; we just want it for display purposes. Map it to 212 # the hard-mode version. 213 if game == 'Easy:The Last Stand': 214 campaignname = 'Default' 215 216 campaign = classic.getcampaign(campaignname) 217 218 # If this campaign is sequential, make sure we've unlocked 219 # everything up to here. 220 unlocked = True 221 if campaign.sequential: 222 for level in campaign.levels: 223 if level.name == levelname: 224 break 225 if not level.complete: 226 unlocked = False 227 break 228 229 # We never actually allow playing last-stand on easy mode. 230 if game == 'Easy:The Last Stand': 231 unlocked = False 232 233 # Hard-code games we haven't unlocked. 234 assert bui.app.classic is not None 235 if ( 236 ( 237 game 238 in ( 239 'Challenges:Infinite Runaround', 240 'Challenges:Infinite Onslaught', 241 ) 242 and not bui.app.classic.accounts.have_pro() 243 ) 244 or ( 245 game in ('Challenges:Meteor Shower',) 246 and not plus.get_purchased('games.meteor_shower') 247 ) 248 or ( 249 game 250 in ( 251 'Challenges:Target Practice', 252 'Challenges:Target Practice B', 253 ) 254 and not plus.get_purchased('games.target_practice') 255 ) 256 or ( 257 game in ('Challenges:Ninja Fight',) 258 and not plus.get_purchased('games.ninja_fight') 259 ) 260 or ( 261 game in ('Challenges:Pro Ninja Fight',) 262 and not plus.get_purchased('games.ninja_fight') 263 ) 264 or ( 265 game 266 in ( 267 'Challenges:Easter Egg Hunt', 268 'Challenges:Pro Easter Egg Hunt', 269 ) 270 and not plus.get_purchased('games.easter_egg_hunt') 271 ) 272 ): 273 unlocked = False 274 275 # Let's tint levels a slightly different color when easy mode 276 # is selected. 277 unlocked_color = ( 278 (0.85, 0.95, 0.5) if game.startswith('Easy:') else (0.5, 0.7, 0.2) 279 ) 280 281 bui.buttonwidget( 282 edit=self._button, 283 color=unlocked_color if unlocked else (0.5, 0.5, 0.5), 284 ) 285 286 bui.imagewidget( 287 edit=self._lock_widget, opacity=0.0 if unlocked else 1.0 288 ) 289 bui.imagewidget( 290 edit=self._preview_widget, opacity=1.0 if unlocked else 0.3 291 ) 292 bui.textwidget( 293 edit=self._name_widget, 294 color=(0.8, 1.0, 0.8, 1.0) if unlocked else (0.7, 0.7, 0.7, 0.7), 295 ) 296 for widget in self._star_widgets: 297 bui.imagewidget( 298 edit=widget, 299 opacity=1.0 if unlocked else 0.3, 300 color=(2.2, 1.2, 0.3) if unlocked else (1, 1, 1), 301 ) 302 for i, ach in enumerate(self._achievements): 303 a_complete = ach.complete 304 bui.imagewidget( 305 edit=self._achievement_widgets[i][0], 306 opacity=1.0 if (a_complete and unlocked) else 0.3, 307 ) 308 bui.imagewidget( 309 edit=self._achievement_widgets[i][1], 310 opacity=( 311 1.0 312 if (a_complete and unlocked) 313 else 0.2 if a_complete else 0.0 314 ), 315 )
Button for entering co-op games.
GameButton( window: bauiv1lib.coop.browser.CoopBrowserWindow, parent: _bauiv1.Widget, game: str, x: float, y: float, select: bool, row: str)
20 def __init__( 21 self, 22 window: CoopBrowserWindow, 23 parent: bui.Widget, 24 game: str, 25 x: float, 26 y: float, 27 select: bool, 28 row: str, 29 ): 30 # pylint: disable=too-many-statements 31 # pylint: disable=too-many-locals 32 33 assert bui.app.classic is not None 34 self._game = game 35 sclx = 195.0 36 scly = 195.0 37 38 campaignname, levelname = game.split(':') 39 40 # Hack: The Last Stand doesn't actually exist in the easy 41 # tourney. We just want it for display purposes. Map it to 42 # the hard-mode version. 43 if game == 'Easy:The Last Stand': 44 campaignname = 'Default' 45 46 rating: float | None 47 campaign = bui.app.classic.getcampaign(campaignname) 48 rating = campaign.getlevel(levelname).rating 49 50 if game == 'Easy:The Last Stand': 51 rating = None 52 53 if rating is None or rating == 0.0: 54 stars = 0 55 elif rating >= 9.5: 56 stars = 3 57 elif rating >= 7.5: 58 stars = 2 59 else: 60 stars = 1 61 62 self._button = btn = bui.buttonwidget( 63 parent=parent, 64 position=(x + 23, y + 4), 65 size=(sclx, scly), 66 label='', 67 on_activate_call=bui.Call(window.run_game, game), 68 button_type='square', 69 autoselect=True, 70 on_select_call=bui.Call(window.sel_change, row, game), 71 ) 72 bui.widget( 73 edit=btn, 74 show_buffer_bottom=50, 75 show_buffer_top=50, 76 show_buffer_left=400, 77 show_buffer_right=200, 78 ) 79 if select: 80 bui.containerwidget( 81 edit=parent, selected_child=btn, visible_child=btn 82 ) 83 image_width = sclx * 0.85 * 0.75 84 self._preview_widget = bui.imagewidget( 85 parent=parent, 86 draw_controller=btn, 87 position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104), 88 size=(image_width, image_width * 0.5), 89 mesh_transparent=window.lsbt, 90 mesh_opaque=window.lsbo, 91 texture=bui.gettexture( 92 campaign.getlevel(levelname).preview_texture_name 93 ), 94 mask_texture=bui.gettexture('mapPreviewMask'), 95 ) 96 97 translated = campaign.getlevel(levelname).displayname 98 self._achievements = bui.app.classic.ach.achievements_for_coop_level( 99 game 100 ) 101 102 self._name_widget = bui.textwidget( 103 parent=parent, 104 draw_controller=btn, 105 position=(x + 20 + sclx * 0.5, y + scly - 27), 106 size=(0, 0), 107 h_align='center', 108 text=translated, 109 v_align='center', 110 maxwidth=sclx * 0.76, 111 scale=0.85, 112 ) 113 xscl = x + (67 if self._achievements else 50) 114 yscl = y + scly - (137 if self._achievements else 157) 115 116 starscale = 35.0 if self._achievements else 45.0 117 118 self._star_widgets: list[bui.Widget] = [] 119 for _i in range(stars): 120 imw = bui.imagewidget( 121 parent=parent, 122 draw_controller=btn, 123 position=(xscl, yscl), 124 size=(starscale, starscale), 125 texture=window.star_tex, 126 ) 127 self._star_widgets.append(imw) 128 xscl += starscale 129 for _i in range(3 - stars): 130 bui.imagewidget( 131 parent=parent, 132 draw_controller=btn, 133 position=(xscl, yscl), 134 size=(starscale, starscale), 135 color=(0, 0, 0), 136 texture=window.star_tex, 137 opacity=0.3, 138 ) 139 xscl += starscale 140 141 xach = x + 69 142 yach = y + scly - 168 143 a_scale = 30.0 144 self._achievement_widgets: list[tuple[bui.Widget, bui.Widget]] = [] 145 for ach in self._achievements: 146 a_complete = ach.complete 147 imw = bui.imagewidget( 148 parent=parent, 149 draw_controller=btn, 150 position=(xach, yach), 151 size=(a_scale, a_scale), 152 color=( 153 tuple(ach.get_icon_color(a_complete)[:3]) 154 if a_complete 155 else (1.2, 1.2, 1.2) 156 ), 157 texture=ach.get_icon_ui_texture(a_complete), 158 ) 159 imw2 = bui.imagewidget( 160 parent=parent, 161 draw_controller=btn, 162 position=(xach, yach), 163 size=(a_scale, a_scale), 164 color=(2, 1.4, 0.4), 165 texture=window.a_outline_tex, 166 mesh_transparent=window.a_outline_mesh, 167 ) 168 self._achievement_widgets.append((imw, imw2)) 169 # if a_complete: 170 xach += a_scale * 1.2 171 172 # if not unlocked: 173 self._lock_widget = bui.imagewidget( 174 parent=parent, 175 draw_controller=btn, 176 position=(x - 8 + sclx * 0.5, y + scly * 0.5 - 20), 177 size=(60, 60), 178 opacity=0.0, 179 texture=bui.gettexture('lock'), 180 ) 181 182 # give a quasi-random update increment to spread the load.. 183 self._update_timer = bui.AppTimer( 184 0.001 * (900 + random.randrange(200)), 185 bui.WeakCall(self._update), 186 repeat=True, 187 ) 188 self._update()