bastd.ui.continues
Provides a popup window to continue a game.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a popup window to continue a game.""" 4 5from __future__ import annotations 6 7import weakref 8from typing import TYPE_CHECKING 9 10import ba 11import ba.internal 12 13if TYPE_CHECKING: 14 from typing import Any, Callable 15 16 17class ContinuesWindow(ba.Window): 18 """A window to continue a game.""" 19 20 def __init__( 21 self, 22 activity: ba.Activity, 23 cost: int, 24 continue_call: Callable[[], Any], 25 cancel_call: Callable[[], Any], 26 ): 27 self._activity = weakref.ref(activity) 28 self._cost = cost 29 self._continue_call = continue_call 30 self._cancel_call = cancel_call 31 self._start_count = self._count = 20 32 self._width = 300 33 self._height = 200 34 self._transitioning_out = False 35 super().__init__( 36 ba.containerwidget( 37 size=(self._width, self._height), 38 background=False, 39 toolbar_visibility='menu_currency', 40 transition='in_scale', 41 scale=1.5, 42 ) 43 ) 44 txt = ( 45 ba.Lstr(resource='continuePurchaseText') 46 .evaluate() 47 .split('${PRICE}') 48 ) 49 t_left = txt[0] 50 t_left_width = ba.internal.get_string_width( 51 t_left, suppress_warning=True 52 ) 53 t_price = ba.charstr(ba.SpecialChar.TICKET) + str(self._cost) 54 t_price_width = ba.internal.get_string_width( 55 t_price, suppress_warning=True 56 ) 57 t_right = txt[-1] 58 t_right_width = ba.internal.get_string_width( 59 t_right, suppress_warning=True 60 ) 61 width_total_half = (t_left_width + t_price_width + t_right_width) * 0.5 62 63 ba.textwidget( 64 parent=self._root_widget, 65 text=t_left, 66 flatness=1.0, 67 shadow=1.0, 68 size=(0, 0), 69 h_align='left', 70 v_align='center', 71 position=(self._width * 0.5 - width_total_half, self._height - 30), 72 ) 73 ba.textwidget( 74 parent=self._root_widget, 75 text=t_price, 76 flatness=1.0, 77 shadow=1.0, 78 color=(0.2, 1.0, 0.2), 79 size=(0, 0), 80 position=( 81 self._width * 0.5 - width_total_half + t_left_width, 82 self._height - 30, 83 ), 84 h_align='left', 85 v_align='center', 86 ) 87 ba.textwidget( 88 parent=self._root_widget, 89 text=t_right, 90 flatness=1.0, 91 shadow=1.0, 92 size=(0, 0), 93 h_align='left', 94 v_align='center', 95 position=( 96 self._width * 0.5 97 - width_total_half 98 + t_left_width 99 + t_price_width 100 + 5, 101 self._height - 30, 102 ), 103 ) 104 105 self._tickets_text_base: str | None 106 self._tickets_text: ba.Widget | None 107 if not ba.app.ui.use_toolbars: 108 self._tickets_text_base = ba.Lstr( 109 resource='getTicketsWindow.youHaveShortText', 110 fallback_resource='getTicketsWindow.youHaveText', 111 ).evaluate() 112 self._tickets_text = ba.textwidget( 113 parent=self._root_widget, 114 text='', 115 flatness=1.0, 116 color=(0.2, 1.0, 0.2), 117 shadow=1.0, 118 position=( 119 self._width * 0.5 + width_total_half, 120 self._height - 50, 121 ), 122 size=(0, 0), 123 scale=0.35, 124 h_align='right', 125 v_align='center', 126 ) 127 else: 128 self._tickets_text_base = None 129 self._tickets_text = None 130 131 self._counter_text = ba.textwidget( 132 parent=self._root_widget, 133 text=str(self._count), 134 color=(0.7, 0.7, 0.7), 135 scale=1.2, 136 size=(0, 0), 137 big=True, 138 position=(self._width * 0.5, self._height - 80), 139 flatness=1.0, 140 shadow=1.0, 141 h_align='center', 142 v_align='center', 143 ) 144 self._cancel_button = ba.buttonwidget( 145 parent=self._root_widget, 146 position=(30, 30), 147 size=(120, 50), 148 label=ba.Lstr(resource='endText', fallback_resource='cancelText'), 149 autoselect=True, 150 enable_sound=False, 151 on_activate_call=self._on_cancel_press, 152 ) 153 self._continue_button = ba.buttonwidget( 154 parent=self._root_widget, 155 label=ba.Lstr(resource='continueText'), 156 autoselect=True, 157 position=(self._width - 130, 30), 158 size=(120, 50), 159 on_activate_call=self._on_continue_press, 160 ) 161 ba.containerwidget( 162 edit=self._root_widget, 163 cancel_button=self._cancel_button, 164 start_button=self._continue_button, 165 selected_child=self._cancel_button, 166 ) 167 168 self._counting_down = True 169 self._countdown_timer = ba.Timer( 170 1.0, ba.WeakCall(self._tick), repeat=True, timetype=ba.TimeType.REAL 171 ) 172 173 # If there is foreground activity, suspend it. 174 ba.app.pause() 175 self._tick() 176 177 def __del__(self) -> None: 178 # If there is suspended foreground activity, resume it. 179 ba.app.resume() 180 181 def _tick(self) -> None: 182 # if our target activity is gone or has ended, go away 183 activity = self._activity() 184 if activity is None or activity.has_ended(): 185 self._on_cancel() 186 return 187 188 if ba.internal.get_v1_account_state() == 'signed_in': 189 sval = ba.charstr(ba.SpecialChar.TICKET) + str( 190 ba.internal.get_v1_account_ticket_count() 191 ) 192 else: 193 sval = '?' 194 if self._tickets_text is not None: 195 assert self._tickets_text_base is not None 196 ba.textwidget( 197 edit=self._tickets_text, 198 text=self._tickets_text_base.replace('${COUNT}', sval), 199 ) 200 201 if self._counting_down: 202 self._count -= 1 203 ba.playsound(ba.getsound('tick')) 204 if self._count <= 0: 205 self._on_cancel() 206 else: 207 ba.textwidget(edit=self._counter_text, text=str(self._count)) 208 209 def _on_cancel_press(self) -> None: 210 # disallow for first second 211 if self._start_count - self._count < 2: 212 ba.playsound(ba.getsound('error')) 213 else: 214 self._on_cancel() 215 216 def _on_continue_press(self) -> None: 217 from bastd.ui import getcurrency 218 219 # Disallow for first second. 220 if self._start_count - self._count < 2: 221 ba.playsound(ba.getsound('error')) 222 else: 223 # If somehow we got signed out... 224 if ba.internal.get_v1_account_state() != 'signed_in': 225 ba.screenmessage( 226 ba.Lstr(resource='notSignedInText'), color=(1, 0, 0) 227 ) 228 ba.playsound(ba.getsound('error')) 229 return 230 231 # If it appears we don't have enough tickets, offer to buy more. 232 tickets = ba.internal.get_v1_account_ticket_count() 233 if tickets < self._cost: 234 # FIXME: Should we start the timer back up again after? 235 self._counting_down = False 236 ba.textwidget(edit=self._counter_text, text='') 237 ba.playsound(ba.getsound('error')) 238 getcurrency.show_get_tickets_prompt() 239 return 240 if not self._transitioning_out: 241 ba.playsound(ba.getsound('swish')) 242 self._transitioning_out = True 243 ba.containerwidget( 244 edit=self._root_widget, transition='out_scale' 245 ) 246 self._continue_call() 247 248 def _on_cancel(self) -> None: 249 if not self._transitioning_out: 250 ba.playsound(ba.getsound('swish')) 251 self._transitioning_out = True 252 ba.containerwidget(edit=self._root_widget, transition='out_scale') 253 self._cancel_call()
class
ContinuesWindow(ba.ui.Window):
18class ContinuesWindow(ba.Window): 19 """A window to continue a game.""" 20 21 def __init__( 22 self, 23 activity: ba.Activity, 24 cost: int, 25 continue_call: Callable[[], Any], 26 cancel_call: Callable[[], Any], 27 ): 28 self._activity = weakref.ref(activity) 29 self._cost = cost 30 self._continue_call = continue_call 31 self._cancel_call = cancel_call 32 self._start_count = self._count = 20 33 self._width = 300 34 self._height = 200 35 self._transitioning_out = False 36 super().__init__( 37 ba.containerwidget( 38 size=(self._width, self._height), 39 background=False, 40 toolbar_visibility='menu_currency', 41 transition='in_scale', 42 scale=1.5, 43 ) 44 ) 45 txt = ( 46 ba.Lstr(resource='continuePurchaseText') 47 .evaluate() 48 .split('${PRICE}') 49 ) 50 t_left = txt[0] 51 t_left_width = ba.internal.get_string_width( 52 t_left, suppress_warning=True 53 ) 54 t_price = ba.charstr(ba.SpecialChar.TICKET) + str(self._cost) 55 t_price_width = ba.internal.get_string_width( 56 t_price, suppress_warning=True 57 ) 58 t_right = txt[-1] 59 t_right_width = ba.internal.get_string_width( 60 t_right, suppress_warning=True 61 ) 62 width_total_half = (t_left_width + t_price_width + t_right_width) * 0.5 63 64 ba.textwidget( 65 parent=self._root_widget, 66 text=t_left, 67 flatness=1.0, 68 shadow=1.0, 69 size=(0, 0), 70 h_align='left', 71 v_align='center', 72 position=(self._width * 0.5 - width_total_half, self._height - 30), 73 ) 74 ba.textwidget( 75 parent=self._root_widget, 76 text=t_price, 77 flatness=1.0, 78 shadow=1.0, 79 color=(0.2, 1.0, 0.2), 80 size=(0, 0), 81 position=( 82 self._width * 0.5 - width_total_half + t_left_width, 83 self._height - 30, 84 ), 85 h_align='left', 86 v_align='center', 87 ) 88 ba.textwidget( 89 parent=self._root_widget, 90 text=t_right, 91 flatness=1.0, 92 shadow=1.0, 93 size=(0, 0), 94 h_align='left', 95 v_align='center', 96 position=( 97 self._width * 0.5 98 - width_total_half 99 + t_left_width 100 + t_price_width 101 + 5, 102 self._height - 30, 103 ), 104 ) 105 106 self._tickets_text_base: str | None 107 self._tickets_text: ba.Widget | None 108 if not ba.app.ui.use_toolbars: 109 self._tickets_text_base = ba.Lstr( 110 resource='getTicketsWindow.youHaveShortText', 111 fallback_resource='getTicketsWindow.youHaveText', 112 ).evaluate() 113 self._tickets_text = ba.textwidget( 114 parent=self._root_widget, 115 text='', 116 flatness=1.0, 117 color=(0.2, 1.0, 0.2), 118 shadow=1.0, 119 position=( 120 self._width * 0.5 + width_total_half, 121 self._height - 50, 122 ), 123 size=(0, 0), 124 scale=0.35, 125 h_align='right', 126 v_align='center', 127 ) 128 else: 129 self._tickets_text_base = None 130 self._tickets_text = None 131 132 self._counter_text = ba.textwidget( 133 parent=self._root_widget, 134 text=str(self._count), 135 color=(0.7, 0.7, 0.7), 136 scale=1.2, 137 size=(0, 0), 138 big=True, 139 position=(self._width * 0.5, self._height - 80), 140 flatness=1.0, 141 shadow=1.0, 142 h_align='center', 143 v_align='center', 144 ) 145 self._cancel_button = ba.buttonwidget( 146 parent=self._root_widget, 147 position=(30, 30), 148 size=(120, 50), 149 label=ba.Lstr(resource='endText', fallback_resource='cancelText'), 150 autoselect=True, 151 enable_sound=False, 152 on_activate_call=self._on_cancel_press, 153 ) 154 self._continue_button = ba.buttonwidget( 155 parent=self._root_widget, 156 label=ba.Lstr(resource='continueText'), 157 autoselect=True, 158 position=(self._width - 130, 30), 159 size=(120, 50), 160 on_activate_call=self._on_continue_press, 161 ) 162 ba.containerwidget( 163 edit=self._root_widget, 164 cancel_button=self._cancel_button, 165 start_button=self._continue_button, 166 selected_child=self._cancel_button, 167 ) 168 169 self._counting_down = True 170 self._countdown_timer = ba.Timer( 171 1.0, ba.WeakCall(self._tick), repeat=True, timetype=ba.TimeType.REAL 172 ) 173 174 # If there is foreground activity, suspend it. 175 ba.app.pause() 176 self._tick() 177 178 def __del__(self) -> None: 179 # If there is suspended foreground activity, resume it. 180 ba.app.resume() 181 182 def _tick(self) -> None: 183 # if our target activity is gone or has ended, go away 184 activity = self._activity() 185 if activity is None or activity.has_ended(): 186 self._on_cancel() 187 return 188 189 if ba.internal.get_v1_account_state() == 'signed_in': 190 sval = ba.charstr(ba.SpecialChar.TICKET) + str( 191 ba.internal.get_v1_account_ticket_count() 192 ) 193 else: 194 sval = '?' 195 if self._tickets_text is not None: 196 assert self._tickets_text_base is not None 197 ba.textwidget( 198 edit=self._tickets_text, 199 text=self._tickets_text_base.replace('${COUNT}', sval), 200 ) 201 202 if self._counting_down: 203 self._count -= 1 204 ba.playsound(ba.getsound('tick')) 205 if self._count <= 0: 206 self._on_cancel() 207 else: 208 ba.textwidget(edit=self._counter_text, text=str(self._count)) 209 210 def _on_cancel_press(self) -> None: 211 # disallow for first second 212 if self._start_count - self._count < 2: 213 ba.playsound(ba.getsound('error')) 214 else: 215 self._on_cancel() 216 217 def _on_continue_press(self) -> None: 218 from bastd.ui import getcurrency 219 220 # Disallow for first second. 221 if self._start_count - self._count < 2: 222 ba.playsound(ba.getsound('error')) 223 else: 224 # If somehow we got signed out... 225 if ba.internal.get_v1_account_state() != 'signed_in': 226 ba.screenmessage( 227 ba.Lstr(resource='notSignedInText'), color=(1, 0, 0) 228 ) 229 ba.playsound(ba.getsound('error')) 230 return 231 232 # If it appears we don't have enough tickets, offer to buy more. 233 tickets = ba.internal.get_v1_account_ticket_count() 234 if tickets < self._cost: 235 # FIXME: Should we start the timer back up again after? 236 self._counting_down = False 237 ba.textwidget(edit=self._counter_text, text='') 238 ba.playsound(ba.getsound('error')) 239 getcurrency.show_get_tickets_prompt() 240 return 241 if not self._transitioning_out: 242 ba.playsound(ba.getsound('swish')) 243 self._transitioning_out = True 244 ba.containerwidget( 245 edit=self._root_widget, transition='out_scale' 246 ) 247 self._continue_call() 248 249 def _on_cancel(self) -> None: 250 if not self._transitioning_out: 251 ba.playsound(ba.getsound('swish')) 252 self._transitioning_out = True 253 ba.containerwidget(edit=self._root_widget, transition='out_scale') 254 self._cancel_call()
A window to continue a game.
ContinuesWindow( activity: ba._activity.Activity, cost: int, continue_call: Callable[[], Any], cancel_call: Callable[[], Any])
21 def __init__( 22 self, 23 activity: ba.Activity, 24 cost: int, 25 continue_call: Callable[[], Any], 26 cancel_call: Callable[[], Any], 27 ): 28 self._activity = weakref.ref(activity) 29 self._cost = cost 30 self._continue_call = continue_call 31 self._cancel_call = cancel_call 32 self._start_count = self._count = 20 33 self._width = 300 34 self._height = 200 35 self._transitioning_out = False 36 super().__init__( 37 ba.containerwidget( 38 size=(self._width, self._height), 39 background=False, 40 toolbar_visibility='menu_currency', 41 transition='in_scale', 42 scale=1.5, 43 ) 44 ) 45 txt = ( 46 ba.Lstr(resource='continuePurchaseText') 47 .evaluate() 48 .split('${PRICE}') 49 ) 50 t_left = txt[0] 51 t_left_width = ba.internal.get_string_width( 52 t_left, suppress_warning=True 53 ) 54 t_price = ba.charstr(ba.SpecialChar.TICKET) + str(self._cost) 55 t_price_width = ba.internal.get_string_width( 56 t_price, suppress_warning=True 57 ) 58 t_right = txt[-1] 59 t_right_width = ba.internal.get_string_width( 60 t_right, suppress_warning=True 61 ) 62 width_total_half = (t_left_width + t_price_width + t_right_width) * 0.5 63 64 ba.textwidget( 65 parent=self._root_widget, 66 text=t_left, 67 flatness=1.0, 68 shadow=1.0, 69 size=(0, 0), 70 h_align='left', 71 v_align='center', 72 position=(self._width * 0.5 - width_total_half, self._height - 30), 73 ) 74 ba.textwidget( 75 parent=self._root_widget, 76 text=t_price, 77 flatness=1.0, 78 shadow=1.0, 79 color=(0.2, 1.0, 0.2), 80 size=(0, 0), 81 position=( 82 self._width * 0.5 - width_total_half + t_left_width, 83 self._height - 30, 84 ), 85 h_align='left', 86 v_align='center', 87 ) 88 ba.textwidget( 89 parent=self._root_widget, 90 text=t_right, 91 flatness=1.0, 92 shadow=1.0, 93 size=(0, 0), 94 h_align='left', 95 v_align='center', 96 position=( 97 self._width * 0.5 98 - width_total_half 99 + t_left_width 100 + t_price_width 101 + 5, 102 self._height - 30, 103 ), 104 ) 105 106 self._tickets_text_base: str | None 107 self._tickets_text: ba.Widget | None 108 if not ba.app.ui.use_toolbars: 109 self._tickets_text_base = ba.Lstr( 110 resource='getTicketsWindow.youHaveShortText', 111 fallback_resource='getTicketsWindow.youHaveText', 112 ).evaluate() 113 self._tickets_text = ba.textwidget( 114 parent=self._root_widget, 115 text='', 116 flatness=1.0, 117 color=(0.2, 1.0, 0.2), 118 shadow=1.0, 119 position=( 120 self._width * 0.5 + width_total_half, 121 self._height - 50, 122 ), 123 size=(0, 0), 124 scale=0.35, 125 h_align='right', 126 v_align='center', 127 ) 128 else: 129 self._tickets_text_base = None 130 self._tickets_text = None 131 132 self._counter_text = ba.textwidget( 133 parent=self._root_widget, 134 text=str(self._count), 135 color=(0.7, 0.7, 0.7), 136 scale=1.2, 137 size=(0, 0), 138 big=True, 139 position=(self._width * 0.5, self._height - 80), 140 flatness=1.0, 141 shadow=1.0, 142 h_align='center', 143 v_align='center', 144 ) 145 self._cancel_button = ba.buttonwidget( 146 parent=self._root_widget, 147 position=(30, 30), 148 size=(120, 50), 149 label=ba.Lstr(resource='endText', fallback_resource='cancelText'), 150 autoselect=True, 151 enable_sound=False, 152 on_activate_call=self._on_cancel_press, 153 ) 154 self._continue_button = ba.buttonwidget( 155 parent=self._root_widget, 156 label=ba.Lstr(resource='continueText'), 157 autoselect=True, 158 position=(self._width - 130, 30), 159 size=(120, 50), 160 on_activate_call=self._on_continue_press, 161 ) 162 ba.containerwidget( 163 edit=self._root_widget, 164 cancel_button=self._cancel_button, 165 start_button=self._continue_button, 166 selected_child=self._cancel_button, 167 ) 168 169 self._counting_down = True 170 self._countdown_timer = ba.Timer( 171 1.0, ba.WeakCall(self._tick), repeat=True, timetype=ba.TimeType.REAL 172 ) 173 174 # If there is foreground activity, suspend it. 175 ba.app.pause() 176 self._tick()
Inherited Members
- ba.ui.Window
- get_root_widget