bastd.ui.settings.keyboard
Keyboard settings related UI functionality.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Keyboard settings related UI functionality.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import _ba 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any 14 15 16class ConfigKeyboardWindow(ba.Window): 17 """Window for configuring keyboards.""" 18 19 def __init__(self, c: ba.InputDevice, transition: str = 'in_right'): 20 self._r = 'configKeyboardWindow' 21 self._input = c 22 self._name = self._input.name 23 self._unique_id = self._input.unique_identifier 24 dname_raw = self._name 25 if self._unique_id != '#1': 26 dname_raw += ' ' + self._unique_id.replace('#', 'P') 27 self._displayname = ba.Lstr(translate=('inputDeviceNames', dname_raw)) 28 self._width = 700 29 if self._unique_id != '#1': 30 self._height = 480 31 else: 32 self._height = 375 33 self._spacing = 40 34 uiscale = ba.app.ui.uiscale 35 super().__init__(root_widget=ba.containerwidget( 36 size=(self._width, self._height), 37 scale=(1.6 if uiscale is ba.UIScale.SMALL else 38 1.3 if uiscale is ba.UIScale.MEDIUM else 1.0), 39 stack_offset=(0, 5) if uiscale is ba.UIScale.SMALL else (0, 0), 40 transition=transition)) 41 42 self._rebuild_ui() 43 44 def _rebuild_ui(self) -> None: 45 from ba.internal import get_device_value 46 for widget in self._root_widget.get_children(): 47 widget.delete() 48 49 # Fill our temp config with present values. 50 self._settings: dict[str, int] = {} 51 for button in [ 52 'buttonJump', 'buttonPunch', 'buttonBomb', 'buttonPickUp', 53 'buttonStart', 'buttonStart2', 'buttonUp', 'buttonDown', 54 'buttonLeft', 'buttonRight' 55 ]: 56 self._settings[button] = get_device_value(self._input, button) 57 58 cancel_button = ba.buttonwidget(parent=self._root_widget, 59 autoselect=True, 60 position=(38, self._height - 85), 61 size=(170, 60), 62 label=ba.Lstr(resource='cancelText'), 63 scale=0.9, 64 on_activate_call=self._cancel) 65 save_button = ba.buttonwidget(parent=self._root_widget, 66 autoselect=True, 67 position=(self._width - 190, 68 self._height - 85), 69 size=(180, 60), 70 label=ba.Lstr(resource='saveText'), 71 scale=0.9, 72 text_scale=0.9, 73 on_activate_call=self._save) 74 ba.containerwidget(edit=self._root_widget, 75 cancel_button=cancel_button, 76 start_button=save_button) 77 78 ba.widget(edit=cancel_button, right_widget=save_button) 79 ba.widget(edit=save_button, left_widget=cancel_button) 80 81 v = self._height - 74.0 82 ba.textwidget(parent=self._root_widget, 83 position=(self._width * 0.5, v + 15), 84 size=(0, 0), 85 text=ba.Lstr(resource=self._r + '.configuringText', 86 subs=[('${DEVICE}', self._displayname)]), 87 color=ba.app.ui.title_color, 88 h_align='center', 89 v_align='center', 90 maxwidth=270, 91 scale=0.83) 92 v -= 20 93 94 if self._unique_id != '#1': 95 v -= 20 96 v -= self._spacing 97 ba.textwidget(parent=self._root_widget, 98 position=(0, v + 19), 99 size=(self._width, 50), 100 text=ba.Lstr(resource=self._r + 101 '.keyboard2NoteText'), 102 scale=0.7, 103 maxwidth=self._width * 0.75, 104 max_height=110, 105 color=ba.app.ui.infotextcolor, 106 h_align='center', 107 v_align='top') 108 v -= 40 109 v -= 10 110 v -= self._spacing * 2.2 111 v += 25 112 v -= 42 113 h_offs = 160 114 dist = 70 115 d_color = (0.4, 0.4, 0.8) 116 self._capture_button(pos=(h_offs, v + 0.95 * dist), 117 color=d_color, 118 button='buttonUp', 119 texture=ba.gettexture('upButton'), 120 scale=1.0) 121 self._capture_button(pos=(h_offs - 1.2 * dist, v), 122 color=d_color, 123 button='buttonLeft', 124 texture=ba.gettexture('leftButton'), 125 scale=1.0) 126 self._capture_button(pos=(h_offs + 1.2 * dist, v), 127 color=d_color, 128 button='buttonRight', 129 texture=ba.gettexture('rightButton'), 130 scale=1.0) 131 self._capture_button(pos=(h_offs, v - 0.95 * dist), 132 color=d_color, 133 button='buttonDown', 134 texture=ba.gettexture('downButton'), 135 scale=1.0) 136 137 if self._unique_id == '#2': 138 self._capture_button(pos=(self._width * 0.5, v + 0.1 * dist), 139 color=(0.4, 0.4, 0.6), 140 button='buttonStart', 141 texture=ba.gettexture('startButton'), 142 scale=0.8) 143 144 h_offs = self._width - 160 145 146 self._capture_button(pos=(h_offs, v + 0.95 * dist), 147 color=(0.6, 0.4, 0.8), 148 button='buttonPickUp', 149 texture=ba.gettexture('buttonPickUp'), 150 scale=1.0) 151 self._capture_button(pos=(h_offs - 1.2 * dist, v), 152 color=(0.7, 0.5, 0.1), 153 button='buttonPunch', 154 texture=ba.gettexture('buttonPunch'), 155 scale=1.0) 156 self._capture_button(pos=(h_offs + 1.2 * dist, v), 157 color=(0.5, 0.2, 0.1), 158 button='buttonBomb', 159 texture=ba.gettexture('buttonBomb'), 160 scale=1.0) 161 self._capture_button(pos=(h_offs, v - 0.95 * dist), 162 color=(0.2, 0.5, 0.2), 163 button='buttonJump', 164 texture=ba.gettexture('buttonJump'), 165 scale=1.0) 166 167 def _capture_button(self, 168 pos: tuple[float, float], 169 color: tuple[float, float, float], 170 texture: ba.Texture, 171 button: str, 172 scale: float = 1.0) -> None: 173 base_size = 79 174 btn = ba.buttonwidget(parent=self._root_widget, 175 autoselect=True, 176 position=(pos[0] - base_size * 0.5 * scale, 177 pos[1] - base_size * 0.5 * scale), 178 size=(base_size * scale, base_size * scale), 179 texture=texture, 180 label='', 181 color=color) 182 183 # Do this deferred so it shows up on top of other buttons. (ew.) 184 def doit() -> None: 185 if not self._root_widget: 186 return 187 uiscale = 0.66 * scale * 2.0 188 maxwidth = 76.0 * scale 189 txt = ba.textwidget(parent=self._root_widget, 190 position=(pos[0] + 0.0 * scale, 191 pos[1] - (57.0 - 18.0) * scale), 192 color=(1, 1, 1, 0.3), 193 size=(0, 0), 194 h_align='center', 195 v_align='top', 196 scale=uiscale, 197 maxwidth=maxwidth, 198 text=self._input.get_button_name( 199 self._settings[button])) 200 ba.buttonwidget(edit=btn, 201 autoselect=True, 202 on_activate_call=ba.Call(AwaitKeyboardInputWindow, 203 button, txt, 204 self._settings)) 205 206 ba.pushcall(doit) 207 208 def _cancel(self) -> None: 209 from bastd.ui.settings.controls import ControlsSettingsWindow 210 ba.containerwidget(edit=self._root_widget, transition='out_right') 211 ba.app.ui.set_main_menu_window( 212 ControlsSettingsWindow(transition='in_left').get_root_widget()) 213 214 def _save(self) -> None: 215 from bastd.ui.settings.controls import ControlsSettingsWindow 216 from ba.internal import (get_input_device_config, 217 should_submit_debug_info, master_server_post) 218 219 ba.containerwidget(edit=self._root_widget, transition='out_right') 220 ba.playsound(ba.getsound('gunCocking')) 221 222 # There's a chance the device disappeared; handle that gracefully. 223 if not self._input: 224 return 225 226 dst = get_input_device_config(self._input, default=False) 227 dst2: dict[str, Any] = dst[0][dst[1]] 228 dst2.clear() 229 230 # Store any values that aren't -1. 231 for key, val in list(self._settings.items()): 232 if val != -1: 233 dst2[key] = val 234 235 # If we're allowed to phone home, send this config so we can generate 236 # more defaults in the future. 237 if should_submit_debug_info(): 238 master_server_post( 239 'controllerConfig', { 240 'ua': ba.app.user_agent_string, 241 'name': self._name, 242 'b': ba.app.build_number, 243 'config': dst2, 244 'v': 2 245 }) 246 ba.app.config.apply_and_commit() 247 ba.app.ui.set_main_menu_window( 248 ControlsSettingsWindow(transition='in_left').get_root_widget()) 249 250 251class AwaitKeyboardInputWindow(ba.Window): 252 """Window for capturing a keypress.""" 253 254 def __init__(self, button: str, ui: ba.Widget, settings: dict): 255 256 self._capture_button = button 257 self._capture_key_ui = ui 258 self._settings = settings 259 260 width = 400 261 height = 150 262 uiscale = ba.app.ui.uiscale 263 super().__init__(root_widget=ba.containerwidget( 264 size=(width, height), 265 transition='in_right', 266 scale=(2.0 if uiscale is ba.UIScale.SMALL else 267 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0))) 268 ba.textwidget(parent=self._root_widget, 269 position=(0, height - 60), 270 size=(width, 25), 271 text=ba.Lstr(resource='pressAnyKeyText'), 272 h_align='center', 273 v_align='top') 274 275 self._counter = 5 276 self._count_down_text = ba.textwidget(parent=self._root_widget, 277 h_align='center', 278 position=(0, height - 110), 279 size=(width, 25), 280 color=(1, 1, 1, 0.3), 281 text=str(self._counter)) 282 self._decrement_timer: ba.Timer | None = ba.Timer( 283 1.0, self._decrement, repeat=True, timetype=ba.TimeType.REAL) 284 _ba.capture_keyboard_input(ba.WeakCall(self._button_callback)) 285 286 def __del__(self) -> None: 287 _ba.release_keyboard_input() 288 289 def _die(self) -> None: 290 # This strong-refs us; killing it allows us to die now. 291 self._decrement_timer = None 292 if self._root_widget: 293 ba.containerwidget(edit=self._root_widget, transition='out_left') 294 295 def _button_callback(self, event: dict[str, Any]) -> None: 296 self._settings[self._capture_button] = event['button'] 297 if event['type'] == 'BUTTONDOWN': 298 bname = event['input_device'].get_button_name(event['button']) 299 ba.textwidget(edit=self._capture_key_ui, text=bname) 300 ba.playsound(ba.getsound('gunCocking')) 301 self._die() 302 303 def _decrement(self) -> None: 304 self._counter -= 1 305 if self._counter >= 1: 306 ba.textwidget(edit=self._count_down_text, text=str(self._counter)) 307 else: 308 self._die()
class
ConfigKeyboardWindow(ba.ui.Window):
17class ConfigKeyboardWindow(ba.Window): 18 """Window for configuring keyboards.""" 19 20 def __init__(self, c: ba.InputDevice, transition: str = 'in_right'): 21 self._r = 'configKeyboardWindow' 22 self._input = c 23 self._name = self._input.name 24 self._unique_id = self._input.unique_identifier 25 dname_raw = self._name 26 if self._unique_id != '#1': 27 dname_raw += ' ' + self._unique_id.replace('#', 'P') 28 self._displayname = ba.Lstr(translate=('inputDeviceNames', dname_raw)) 29 self._width = 700 30 if self._unique_id != '#1': 31 self._height = 480 32 else: 33 self._height = 375 34 self._spacing = 40 35 uiscale = ba.app.ui.uiscale 36 super().__init__(root_widget=ba.containerwidget( 37 size=(self._width, self._height), 38 scale=(1.6 if uiscale is ba.UIScale.SMALL else 39 1.3 if uiscale is ba.UIScale.MEDIUM else 1.0), 40 stack_offset=(0, 5) if uiscale is ba.UIScale.SMALL else (0, 0), 41 transition=transition)) 42 43 self._rebuild_ui() 44 45 def _rebuild_ui(self) -> None: 46 from ba.internal import get_device_value 47 for widget in self._root_widget.get_children(): 48 widget.delete() 49 50 # Fill our temp config with present values. 51 self._settings: dict[str, int] = {} 52 for button in [ 53 'buttonJump', 'buttonPunch', 'buttonBomb', 'buttonPickUp', 54 'buttonStart', 'buttonStart2', 'buttonUp', 'buttonDown', 55 'buttonLeft', 'buttonRight' 56 ]: 57 self._settings[button] = get_device_value(self._input, button) 58 59 cancel_button = ba.buttonwidget(parent=self._root_widget, 60 autoselect=True, 61 position=(38, self._height - 85), 62 size=(170, 60), 63 label=ba.Lstr(resource='cancelText'), 64 scale=0.9, 65 on_activate_call=self._cancel) 66 save_button = ba.buttonwidget(parent=self._root_widget, 67 autoselect=True, 68 position=(self._width - 190, 69 self._height - 85), 70 size=(180, 60), 71 label=ba.Lstr(resource='saveText'), 72 scale=0.9, 73 text_scale=0.9, 74 on_activate_call=self._save) 75 ba.containerwidget(edit=self._root_widget, 76 cancel_button=cancel_button, 77 start_button=save_button) 78 79 ba.widget(edit=cancel_button, right_widget=save_button) 80 ba.widget(edit=save_button, left_widget=cancel_button) 81 82 v = self._height - 74.0 83 ba.textwidget(parent=self._root_widget, 84 position=(self._width * 0.5, v + 15), 85 size=(0, 0), 86 text=ba.Lstr(resource=self._r + '.configuringText', 87 subs=[('${DEVICE}', self._displayname)]), 88 color=ba.app.ui.title_color, 89 h_align='center', 90 v_align='center', 91 maxwidth=270, 92 scale=0.83) 93 v -= 20 94 95 if self._unique_id != '#1': 96 v -= 20 97 v -= self._spacing 98 ba.textwidget(parent=self._root_widget, 99 position=(0, v + 19), 100 size=(self._width, 50), 101 text=ba.Lstr(resource=self._r + 102 '.keyboard2NoteText'), 103 scale=0.7, 104 maxwidth=self._width * 0.75, 105 max_height=110, 106 color=ba.app.ui.infotextcolor, 107 h_align='center', 108 v_align='top') 109 v -= 40 110 v -= 10 111 v -= self._spacing * 2.2 112 v += 25 113 v -= 42 114 h_offs = 160 115 dist = 70 116 d_color = (0.4, 0.4, 0.8) 117 self._capture_button(pos=(h_offs, v + 0.95 * dist), 118 color=d_color, 119 button='buttonUp', 120 texture=ba.gettexture('upButton'), 121 scale=1.0) 122 self._capture_button(pos=(h_offs - 1.2 * dist, v), 123 color=d_color, 124 button='buttonLeft', 125 texture=ba.gettexture('leftButton'), 126 scale=1.0) 127 self._capture_button(pos=(h_offs + 1.2 * dist, v), 128 color=d_color, 129 button='buttonRight', 130 texture=ba.gettexture('rightButton'), 131 scale=1.0) 132 self._capture_button(pos=(h_offs, v - 0.95 * dist), 133 color=d_color, 134 button='buttonDown', 135 texture=ba.gettexture('downButton'), 136 scale=1.0) 137 138 if self._unique_id == '#2': 139 self._capture_button(pos=(self._width * 0.5, v + 0.1 * dist), 140 color=(0.4, 0.4, 0.6), 141 button='buttonStart', 142 texture=ba.gettexture('startButton'), 143 scale=0.8) 144 145 h_offs = self._width - 160 146 147 self._capture_button(pos=(h_offs, v + 0.95 * dist), 148 color=(0.6, 0.4, 0.8), 149 button='buttonPickUp', 150 texture=ba.gettexture('buttonPickUp'), 151 scale=1.0) 152 self._capture_button(pos=(h_offs - 1.2 * dist, v), 153 color=(0.7, 0.5, 0.1), 154 button='buttonPunch', 155 texture=ba.gettexture('buttonPunch'), 156 scale=1.0) 157 self._capture_button(pos=(h_offs + 1.2 * dist, v), 158 color=(0.5, 0.2, 0.1), 159 button='buttonBomb', 160 texture=ba.gettexture('buttonBomb'), 161 scale=1.0) 162 self._capture_button(pos=(h_offs, v - 0.95 * dist), 163 color=(0.2, 0.5, 0.2), 164 button='buttonJump', 165 texture=ba.gettexture('buttonJump'), 166 scale=1.0) 167 168 def _capture_button(self, 169 pos: tuple[float, float], 170 color: tuple[float, float, float], 171 texture: ba.Texture, 172 button: str, 173 scale: float = 1.0) -> None: 174 base_size = 79 175 btn = ba.buttonwidget(parent=self._root_widget, 176 autoselect=True, 177 position=(pos[0] - base_size * 0.5 * scale, 178 pos[1] - base_size * 0.5 * scale), 179 size=(base_size * scale, base_size * scale), 180 texture=texture, 181 label='', 182 color=color) 183 184 # Do this deferred so it shows up on top of other buttons. (ew.) 185 def doit() -> None: 186 if not self._root_widget: 187 return 188 uiscale = 0.66 * scale * 2.0 189 maxwidth = 76.0 * scale 190 txt = ba.textwidget(parent=self._root_widget, 191 position=(pos[0] + 0.0 * scale, 192 pos[1] - (57.0 - 18.0) * scale), 193 color=(1, 1, 1, 0.3), 194 size=(0, 0), 195 h_align='center', 196 v_align='top', 197 scale=uiscale, 198 maxwidth=maxwidth, 199 text=self._input.get_button_name( 200 self._settings[button])) 201 ba.buttonwidget(edit=btn, 202 autoselect=True, 203 on_activate_call=ba.Call(AwaitKeyboardInputWindow, 204 button, txt, 205 self._settings)) 206 207 ba.pushcall(doit) 208 209 def _cancel(self) -> None: 210 from bastd.ui.settings.controls import ControlsSettingsWindow 211 ba.containerwidget(edit=self._root_widget, transition='out_right') 212 ba.app.ui.set_main_menu_window( 213 ControlsSettingsWindow(transition='in_left').get_root_widget()) 214 215 def _save(self) -> None: 216 from bastd.ui.settings.controls import ControlsSettingsWindow 217 from ba.internal import (get_input_device_config, 218 should_submit_debug_info, master_server_post) 219 220 ba.containerwidget(edit=self._root_widget, transition='out_right') 221 ba.playsound(ba.getsound('gunCocking')) 222 223 # There's a chance the device disappeared; handle that gracefully. 224 if not self._input: 225 return 226 227 dst = get_input_device_config(self._input, default=False) 228 dst2: dict[str, Any] = dst[0][dst[1]] 229 dst2.clear() 230 231 # Store any values that aren't -1. 232 for key, val in list(self._settings.items()): 233 if val != -1: 234 dst2[key] = val 235 236 # If we're allowed to phone home, send this config so we can generate 237 # more defaults in the future. 238 if should_submit_debug_info(): 239 master_server_post( 240 'controllerConfig', { 241 'ua': ba.app.user_agent_string, 242 'name': self._name, 243 'b': ba.app.build_number, 244 'config': dst2, 245 'v': 2 246 }) 247 ba.app.config.apply_and_commit() 248 ba.app.ui.set_main_menu_window( 249 ControlsSettingsWindow(transition='in_left').get_root_widget())
Window for configuring keyboards.
ConfigKeyboardWindow(c: _ba.InputDevice, transition: str = 'in_right')
20 def __init__(self, c: ba.InputDevice, transition: str = 'in_right'): 21 self._r = 'configKeyboardWindow' 22 self._input = c 23 self._name = self._input.name 24 self._unique_id = self._input.unique_identifier 25 dname_raw = self._name 26 if self._unique_id != '#1': 27 dname_raw += ' ' + self._unique_id.replace('#', 'P') 28 self._displayname = ba.Lstr(translate=('inputDeviceNames', dname_raw)) 29 self._width = 700 30 if self._unique_id != '#1': 31 self._height = 480 32 else: 33 self._height = 375 34 self._spacing = 40 35 uiscale = ba.app.ui.uiscale 36 super().__init__(root_widget=ba.containerwidget( 37 size=(self._width, self._height), 38 scale=(1.6 if uiscale is ba.UIScale.SMALL else 39 1.3 if uiscale is ba.UIScale.MEDIUM else 1.0), 40 stack_offset=(0, 5) if uiscale is ba.UIScale.SMALL else (0, 0), 41 transition=transition)) 42 43 self._rebuild_ui()
Inherited Members
- ba.ui.Window
- get_root_widget
class
AwaitKeyboardInputWindow(ba.ui.Window):
252class AwaitKeyboardInputWindow(ba.Window): 253 """Window for capturing a keypress.""" 254 255 def __init__(self, button: str, ui: ba.Widget, settings: dict): 256 257 self._capture_button = button 258 self._capture_key_ui = ui 259 self._settings = settings 260 261 width = 400 262 height = 150 263 uiscale = ba.app.ui.uiscale 264 super().__init__(root_widget=ba.containerwidget( 265 size=(width, height), 266 transition='in_right', 267 scale=(2.0 if uiscale is ba.UIScale.SMALL else 268 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0))) 269 ba.textwidget(parent=self._root_widget, 270 position=(0, height - 60), 271 size=(width, 25), 272 text=ba.Lstr(resource='pressAnyKeyText'), 273 h_align='center', 274 v_align='top') 275 276 self._counter = 5 277 self._count_down_text = ba.textwidget(parent=self._root_widget, 278 h_align='center', 279 position=(0, height - 110), 280 size=(width, 25), 281 color=(1, 1, 1, 0.3), 282 text=str(self._counter)) 283 self._decrement_timer: ba.Timer | None = ba.Timer( 284 1.0, self._decrement, repeat=True, timetype=ba.TimeType.REAL) 285 _ba.capture_keyboard_input(ba.WeakCall(self._button_callback)) 286 287 def __del__(self) -> None: 288 _ba.release_keyboard_input() 289 290 def _die(self) -> None: 291 # This strong-refs us; killing it allows us to die now. 292 self._decrement_timer = None 293 if self._root_widget: 294 ba.containerwidget(edit=self._root_widget, transition='out_left') 295 296 def _button_callback(self, event: dict[str, Any]) -> None: 297 self._settings[self._capture_button] = event['button'] 298 if event['type'] == 'BUTTONDOWN': 299 bname = event['input_device'].get_button_name(event['button']) 300 ba.textwidget(edit=self._capture_key_ui, text=bname) 301 ba.playsound(ba.getsound('gunCocking')) 302 self._die() 303 304 def _decrement(self) -> None: 305 self._counter -= 1 306 if self._counter >= 1: 307 ba.textwidget(edit=self._count_down_text, text=str(self._counter)) 308 else: 309 self._die()
Window for capturing a keypress.
AwaitKeyboardInputWindow(button: str, ui: _ba.Widget, settings: dict)
255 def __init__(self, button: str, ui: ba.Widget, settings: dict): 256 257 self._capture_button = button 258 self._capture_key_ui = ui 259 self._settings = settings 260 261 width = 400 262 height = 150 263 uiscale = ba.app.ui.uiscale 264 super().__init__(root_widget=ba.containerwidget( 265 size=(width, height), 266 transition='in_right', 267 scale=(2.0 if uiscale is ba.UIScale.SMALL else 268 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0))) 269 ba.textwidget(parent=self._root_widget, 270 position=(0, height - 60), 271 size=(width, 25), 272 text=ba.Lstr(resource='pressAnyKeyText'), 273 h_align='center', 274 v_align='top') 275 276 self._counter = 5 277 self._count_down_text = ba.textwidget(parent=self._root_widget, 278 h_align='center', 279 position=(0, height - 110), 280 size=(width, 25), 281 color=(1, 1, 1, 0.3), 282 text=str(self._counter)) 283 self._decrement_timer: ba.Timer | None = ba.Timer( 284 1.0, self._decrement, repeat=True, timetype=ba.TimeType.REAL) 285 _ba.capture_keyboard_input(ba.WeakCall(self._button_callback))
Inherited Members
- ba.ui.Window
- get_root_widget