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