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