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