bastd.ui.playlist.editcontroller
Defines a controller for wrangling playlist edit UIs.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defines a controller for wrangling playlist edit UIs.""" 4 5from __future__ import annotations 6 7import copy 8from typing import TYPE_CHECKING 9 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any 14 15 16class PlaylistEditController: 17 """Coordinates various UIs involved in playlist editing.""" 18 19 def __init__(self, 20 sessiontype: type[ba.Session], 21 existing_playlist_name: str | None = None, 22 transition: str = 'in_right', 23 playlist: list[dict[str, Any]] | None = None, 24 playlist_name: str | None = None): 25 from ba.internal import preload_map_preview_media, filter_playlist 26 from bastd.ui.playlist import PlaylistTypeVars 27 from bastd.ui.playlist.edit import PlaylistEditWindow 28 29 appconfig = ba.app.config 30 31 # Since we may be showing our map list momentarily, 32 # lets go ahead and preload all map preview textures. 33 preload_map_preview_media() 34 self._sessiontype = sessiontype 35 36 self._editing_game = False 37 self._editing_game_type: type[ba.GameActivity] | None = None 38 self._pvars = PlaylistTypeVars(sessiontype) 39 self._existing_playlist_name = existing_playlist_name 40 self._config_name_full = self._pvars.config_name + ' Playlists' 41 42 # Make sure config exists. 43 if self._config_name_full not in appconfig: 44 appconfig[self._config_name_full] = {} 45 46 self._selected_index = 0 47 if existing_playlist_name: 48 self._name = existing_playlist_name 49 50 # Filter out invalid games. 51 self._playlist = filter_playlist( 52 appconfig[self._pvars.config_name + 53 ' Playlists'][existing_playlist_name], 54 sessiontype=sessiontype, 55 remove_unowned=False) 56 self._edit_ui_selection = None 57 else: 58 if playlist is not None: 59 self._playlist = playlist 60 else: 61 self._playlist = [] 62 if playlist_name is not None: 63 self._name = playlist_name 64 else: 65 66 # Find a good unused name. 67 i = 1 68 while True: 69 self._name = ( 70 self._pvars.default_new_list_name.evaluate() + 71 ((' ' + str(i)) if i > 1 else '')) 72 if self._name not in appconfig[self._pvars.config_name + 73 ' Playlists']: 74 break 75 i += 1 76 77 # Also we want it to start with 'add' highlighted since its empty 78 # and that's all they can do. 79 self._edit_ui_selection = 'add_button' 80 81 ba.app.ui.set_main_menu_window( 82 PlaylistEditWindow(editcontroller=self, 83 transition=transition).get_root_widget()) 84 85 def get_config_name(self) -> str: 86 """(internal)""" 87 return self._pvars.config_name 88 89 def get_existing_playlist_name(self) -> str | None: 90 """(internal)""" 91 return self._existing_playlist_name 92 93 def get_edit_ui_selection(self) -> str | None: 94 """(internal)""" 95 return self._edit_ui_selection 96 97 def set_edit_ui_selection(self, selection: str) -> None: 98 """(internal)""" 99 self._edit_ui_selection = selection 100 101 def getname(self) -> str: 102 """(internal)""" 103 return self._name 104 105 def setname(self, name: str) -> None: 106 """(internal)""" 107 self._name = name 108 109 def get_playlist(self) -> list[dict[str, Any]]: 110 """Return the current state of the edited playlist.""" 111 return copy.deepcopy(self._playlist) 112 113 def set_playlist(self, playlist: list[dict[str, Any]]) -> None: 114 """Set the playlist contents.""" 115 self._playlist = copy.deepcopy(playlist) 116 117 def get_session_type(self) -> type[ba.Session]: 118 """Return the ba.Session type for this edit-session.""" 119 return self._sessiontype 120 121 def get_selected_index(self) -> int: 122 """Return the index of the selected playlist.""" 123 return self._selected_index 124 125 def get_default_list_name(self) -> ba.Lstr: 126 """(internal)""" 127 return self._pvars.default_list_name 128 129 def set_selected_index(self, index: int) -> None: 130 """Sets the selected playlist index.""" 131 self._selected_index = index 132 133 def add_game_pressed(self) -> None: 134 """(internal)""" 135 from bastd.ui.playlist.addgame import PlaylistAddGameWindow 136 ba.app.ui.clear_main_menu_window(transition='out_left') 137 ba.app.ui.set_main_menu_window( 138 PlaylistAddGameWindow(editcontroller=self).get_root_widget()) 139 140 def edit_game_pressed(self) -> None: 141 """Should be called by supplemental UIs when a game is to be edited.""" 142 from ba.internal import getclass 143 if not self._playlist: 144 return 145 self._show_edit_ui(gametype=getclass( 146 self._playlist[self._selected_index]['type'], 147 subclassof=ba.GameActivity), 148 settings=self._playlist[self._selected_index]) 149 150 def add_game_cancelled(self) -> None: 151 """(internal)""" 152 from bastd.ui.playlist.edit import PlaylistEditWindow 153 ba.app.ui.clear_main_menu_window(transition='out_right') 154 ba.app.ui.set_main_menu_window( 155 PlaylistEditWindow(editcontroller=self, 156 transition='in_left').get_root_widget()) 157 158 def _show_edit_ui(self, gametype: type[ba.GameActivity], 159 settings: dict[str, Any] | None) -> None: 160 self._editing_game = (settings is not None) 161 self._editing_game_type = gametype 162 assert self._sessiontype is not None 163 gametype.create_settings_ui(self._sessiontype, copy.deepcopy(settings), 164 self._edit_game_done) 165 166 def add_game_type_selected(self, gametype: type[ba.GameActivity]) -> None: 167 """(internal)""" 168 self._show_edit_ui(gametype=gametype, settings=None) 169 170 def _edit_game_done(self, config: dict[str, Any] | None) -> None: 171 from bastd.ui.playlist.edit import PlaylistEditWindow 172 from bastd.ui.playlist.addgame import PlaylistAddGameWindow 173 from ba.internal import get_type_name 174 if config is None: 175 # If we were editing, go back to our list. 176 if self._editing_game: 177 ba.playsound(ba.getsound('powerdown01')) 178 ba.app.ui.clear_main_menu_window(transition='out_right') 179 ba.app.ui.set_main_menu_window( 180 PlaylistEditWindow(editcontroller=self, 181 transition='in_left').get_root_widget()) 182 183 # Otherwise we were adding; go back to the add type choice list. 184 else: 185 ba.app.ui.clear_main_menu_window(transition='out_right') 186 ba.app.ui.set_main_menu_window( 187 PlaylistAddGameWindow( 188 editcontroller=self, 189 transition='in_left').get_root_widget()) 190 else: 191 # Make sure type is in there. 192 assert self._editing_game_type is not None 193 config['type'] = get_type_name(self._editing_game_type) 194 195 if self._editing_game: 196 self._playlist[self._selected_index] = copy.deepcopy(config) 197 else: 198 # Add a new entry to the playlist. 199 insert_index = min(len(self._playlist), 200 self._selected_index + 1) 201 self._playlist.insert(insert_index, copy.deepcopy(config)) 202 self._selected_index = insert_index 203 204 ba.playsound(ba.getsound('gunCocking')) 205 ba.app.ui.clear_main_menu_window(transition='out_right') 206 ba.app.ui.set_main_menu_window( 207 PlaylistEditWindow(editcontroller=self, 208 transition='in_left').get_root_widget())
class
PlaylistEditController:
17class PlaylistEditController: 18 """Coordinates various UIs involved in playlist editing.""" 19 20 def __init__(self, 21 sessiontype: type[ba.Session], 22 existing_playlist_name: str | None = None, 23 transition: str = 'in_right', 24 playlist: list[dict[str, Any]] | None = None, 25 playlist_name: str | None = None): 26 from ba.internal import preload_map_preview_media, filter_playlist 27 from bastd.ui.playlist import PlaylistTypeVars 28 from bastd.ui.playlist.edit import PlaylistEditWindow 29 30 appconfig = ba.app.config 31 32 # Since we may be showing our map list momentarily, 33 # lets go ahead and preload all map preview textures. 34 preload_map_preview_media() 35 self._sessiontype = sessiontype 36 37 self._editing_game = False 38 self._editing_game_type: type[ba.GameActivity] | None = None 39 self._pvars = PlaylistTypeVars(sessiontype) 40 self._existing_playlist_name = existing_playlist_name 41 self._config_name_full = self._pvars.config_name + ' Playlists' 42 43 # Make sure config exists. 44 if self._config_name_full not in appconfig: 45 appconfig[self._config_name_full] = {} 46 47 self._selected_index = 0 48 if existing_playlist_name: 49 self._name = existing_playlist_name 50 51 # Filter out invalid games. 52 self._playlist = filter_playlist( 53 appconfig[self._pvars.config_name + 54 ' Playlists'][existing_playlist_name], 55 sessiontype=sessiontype, 56 remove_unowned=False) 57 self._edit_ui_selection = None 58 else: 59 if playlist is not None: 60 self._playlist = playlist 61 else: 62 self._playlist = [] 63 if playlist_name is not None: 64 self._name = playlist_name 65 else: 66 67 # Find a good unused name. 68 i = 1 69 while True: 70 self._name = ( 71 self._pvars.default_new_list_name.evaluate() + 72 ((' ' + str(i)) if i > 1 else '')) 73 if self._name not in appconfig[self._pvars.config_name + 74 ' Playlists']: 75 break 76 i += 1 77 78 # Also we want it to start with 'add' highlighted since its empty 79 # and that's all they can do. 80 self._edit_ui_selection = 'add_button' 81 82 ba.app.ui.set_main_menu_window( 83 PlaylistEditWindow(editcontroller=self, 84 transition=transition).get_root_widget()) 85 86 def get_config_name(self) -> str: 87 """(internal)""" 88 return self._pvars.config_name 89 90 def get_existing_playlist_name(self) -> str | None: 91 """(internal)""" 92 return self._existing_playlist_name 93 94 def get_edit_ui_selection(self) -> str | None: 95 """(internal)""" 96 return self._edit_ui_selection 97 98 def set_edit_ui_selection(self, selection: str) -> None: 99 """(internal)""" 100 self._edit_ui_selection = selection 101 102 def getname(self) -> str: 103 """(internal)""" 104 return self._name 105 106 def setname(self, name: str) -> None: 107 """(internal)""" 108 self._name = name 109 110 def get_playlist(self) -> list[dict[str, Any]]: 111 """Return the current state of the edited playlist.""" 112 return copy.deepcopy(self._playlist) 113 114 def set_playlist(self, playlist: list[dict[str, Any]]) -> None: 115 """Set the playlist contents.""" 116 self._playlist = copy.deepcopy(playlist) 117 118 def get_session_type(self) -> type[ba.Session]: 119 """Return the ba.Session type for this edit-session.""" 120 return self._sessiontype 121 122 def get_selected_index(self) -> int: 123 """Return the index of the selected playlist.""" 124 return self._selected_index 125 126 def get_default_list_name(self) -> ba.Lstr: 127 """(internal)""" 128 return self._pvars.default_list_name 129 130 def set_selected_index(self, index: int) -> None: 131 """Sets the selected playlist index.""" 132 self._selected_index = index 133 134 def add_game_pressed(self) -> None: 135 """(internal)""" 136 from bastd.ui.playlist.addgame import PlaylistAddGameWindow 137 ba.app.ui.clear_main_menu_window(transition='out_left') 138 ba.app.ui.set_main_menu_window( 139 PlaylistAddGameWindow(editcontroller=self).get_root_widget()) 140 141 def edit_game_pressed(self) -> None: 142 """Should be called by supplemental UIs when a game is to be edited.""" 143 from ba.internal import getclass 144 if not self._playlist: 145 return 146 self._show_edit_ui(gametype=getclass( 147 self._playlist[self._selected_index]['type'], 148 subclassof=ba.GameActivity), 149 settings=self._playlist[self._selected_index]) 150 151 def add_game_cancelled(self) -> None: 152 """(internal)""" 153 from bastd.ui.playlist.edit import PlaylistEditWindow 154 ba.app.ui.clear_main_menu_window(transition='out_right') 155 ba.app.ui.set_main_menu_window( 156 PlaylistEditWindow(editcontroller=self, 157 transition='in_left').get_root_widget()) 158 159 def _show_edit_ui(self, gametype: type[ba.GameActivity], 160 settings: dict[str, Any] | None) -> None: 161 self._editing_game = (settings is not None) 162 self._editing_game_type = gametype 163 assert self._sessiontype is not None 164 gametype.create_settings_ui(self._sessiontype, copy.deepcopy(settings), 165 self._edit_game_done) 166 167 def add_game_type_selected(self, gametype: type[ba.GameActivity]) -> None: 168 """(internal)""" 169 self._show_edit_ui(gametype=gametype, settings=None) 170 171 def _edit_game_done(self, config: dict[str, Any] | None) -> None: 172 from bastd.ui.playlist.edit import PlaylistEditWindow 173 from bastd.ui.playlist.addgame import PlaylistAddGameWindow 174 from ba.internal import get_type_name 175 if config is None: 176 # If we were editing, go back to our list. 177 if self._editing_game: 178 ba.playsound(ba.getsound('powerdown01')) 179 ba.app.ui.clear_main_menu_window(transition='out_right') 180 ba.app.ui.set_main_menu_window( 181 PlaylistEditWindow(editcontroller=self, 182 transition='in_left').get_root_widget()) 183 184 # Otherwise we were adding; go back to the add type choice list. 185 else: 186 ba.app.ui.clear_main_menu_window(transition='out_right') 187 ba.app.ui.set_main_menu_window( 188 PlaylistAddGameWindow( 189 editcontroller=self, 190 transition='in_left').get_root_widget()) 191 else: 192 # Make sure type is in there. 193 assert self._editing_game_type is not None 194 config['type'] = get_type_name(self._editing_game_type) 195 196 if self._editing_game: 197 self._playlist[self._selected_index] = copy.deepcopy(config) 198 else: 199 # Add a new entry to the playlist. 200 insert_index = min(len(self._playlist), 201 self._selected_index + 1) 202 self._playlist.insert(insert_index, copy.deepcopy(config)) 203 self._selected_index = insert_index 204 205 ba.playsound(ba.getsound('gunCocking')) 206 ba.app.ui.clear_main_menu_window(transition='out_right') 207 ba.app.ui.set_main_menu_window( 208 PlaylistEditWindow(editcontroller=self, 209 transition='in_left').get_root_widget())
Coordinates various UIs involved in playlist editing.
PlaylistEditController( sessiontype: type[ba._session.Session], existing_playlist_name: str | None = None, transition: str = 'in_right', playlist: list[dict[str, typing.Any]] | None = None, playlist_name: str | None = None)
20 def __init__(self, 21 sessiontype: type[ba.Session], 22 existing_playlist_name: str | None = None, 23 transition: str = 'in_right', 24 playlist: list[dict[str, Any]] | None = None, 25 playlist_name: str | None = None): 26 from ba.internal import preload_map_preview_media, filter_playlist 27 from bastd.ui.playlist import PlaylistTypeVars 28 from bastd.ui.playlist.edit import PlaylistEditWindow 29 30 appconfig = ba.app.config 31 32 # Since we may be showing our map list momentarily, 33 # lets go ahead and preload all map preview textures. 34 preload_map_preview_media() 35 self._sessiontype = sessiontype 36 37 self._editing_game = False 38 self._editing_game_type: type[ba.GameActivity] | None = None 39 self._pvars = PlaylistTypeVars(sessiontype) 40 self._existing_playlist_name = existing_playlist_name 41 self._config_name_full = self._pvars.config_name + ' Playlists' 42 43 # Make sure config exists. 44 if self._config_name_full not in appconfig: 45 appconfig[self._config_name_full] = {} 46 47 self._selected_index = 0 48 if existing_playlist_name: 49 self._name = existing_playlist_name 50 51 # Filter out invalid games. 52 self._playlist = filter_playlist( 53 appconfig[self._pvars.config_name + 54 ' Playlists'][existing_playlist_name], 55 sessiontype=sessiontype, 56 remove_unowned=False) 57 self._edit_ui_selection = None 58 else: 59 if playlist is not None: 60 self._playlist = playlist 61 else: 62 self._playlist = [] 63 if playlist_name is not None: 64 self._name = playlist_name 65 else: 66 67 # Find a good unused name. 68 i = 1 69 while True: 70 self._name = ( 71 self._pvars.default_new_list_name.evaluate() + 72 ((' ' + str(i)) if i > 1 else '')) 73 if self._name not in appconfig[self._pvars.config_name + 74 ' Playlists']: 75 break 76 i += 1 77 78 # Also we want it to start with 'add' highlighted since its empty 79 # and that's all they can do. 80 self._edit_ui_selection = 'add_button' 81 82 ba.app.ui.set_main_menu_window( 83 PlaylistEditWindow(editcontroller=self, 84 transition=transition).get_root_widget())
def
get_playlist(self) -> list[dict[str, typing.Any]]:
110 def get_playlist(self) -> list[dict[str, Any]]: 111 """Return the current state of the edited playlist.""" 112 return copy.deepcopy(self._playlist)
Return the current state of the edited playlist.
def
set_playlist(self, playlist: list[dict[str, typing.Any]]) -> None:
114 def set_playlist(self, playlist: list[dict[str, Any]]) -> None: 115 """Set the playlist contents.""" 116 self._playlist = copy.deepcopy(playlist)
Set the playlist contents.
def
get_session_type(self) -> type[ba._session.Session]:
118 def get_session_type(self) -> type[ba.Session]: 119 """Return the ba.Session type for this edit-session.""" 120 return self._sessiontype
Return the ba.Session type for this edit-session.
def
get_selected_index(self) -> int:
122 def get_selected_index(self) -> int: 123 """Return the index of the selected playlist.""" 124 return self._selected_index
Return the index of the selected playlist.
def
set_selected_index(self, index: int) -> None:
130 def set_selected_index(self, index: int) -> None: 131 """Sets the selected playlist index.""" 132 self._selected_index = index
Sets the selected playlist index.
def
edit_game_pressed(self) -> None:
141 def edit_game_pressed(self) -> None: 142 """Should be called by supplemental UIs when a game is to be edited.""" 143 from ba.internal import getclass 144 if not self._playlist: 145 return 146 self._show_edit_ui(gametype=getclass( 147 self._playlist[self._selected_index]['type'], 148 subclassof=ba.GameActivity), 149 settings=self._playlist[self._selected_index])
Should be called by supplemental UIs when a game is to be edited.