"""Plugins Folder.""" #by Froshlee14 # ba_meta require api 7 from __future__ import annotations from typing import TYPE_CHECKING import _ba, ba, os from bastd.ui import mainmenu, popup from bastd.ui.settings.plugins import PluginSettingsWindow from bastd.ui.mainmenu import MainMenuWindow from ba import charstr, SpecialChar as SpCh from ba._plugin import Plugin from bastd.ui.confirm import ConfirmWindow if TYPE_CHECKING: from typing import Tuple, Any, Optional, List, Dict def doMenu(self): ba.containerwidget(edit=self._root_widget,transition='out_left') ba.app.ui.set_main_menu_window( PluginSettingsWindow( origin_widget=self._plugins_button).get_root_widget()) def openInfo(text,pluginName,link,linkDesc): InformationWindow(text,pluginName,link,linkDesc) def getTranslation(text): actLan = _ba.app.lang.language Dictionary = { "All_text":{ "Spanish":'Todos', "English":'All' }, "Plugins_text":{ "Spanish":'Utilidades', "English":'Tools' }, "Characters_text":{ "Spanish":'Personajes', "English":'Characters' }, "Maps_text":{ "Spanish":'Mapas', "English":'Maps' }, "Extras_text":{ "Spanish":'Extras', "English":'Extras' }, "Information_text":{ "Spanish":'Información', "English":'Information' }, "No_Plugins_Available_text":{ "Spanish":'No hay plugins disponibles.', "English":'No plugins available.' }, "Site_default_desc_text":{ "Spanish":'Mi sitio web', "English":'My website' }, "open_website_text":{ "Spanish":'Seras dirigido a un sitio web\n¿Deseas continuar?', "English":'You will be directed to a website,\nDo you want to continue?' }, "Mod_settings_status":{ "Spanish":"Ajustes de plugin no disponibles.", "English":"Plugin settings not available." }, "Mod_info_status":{ "Spanish":"Información de plugin no disponible.", "English":"Plugin information not available." }, "Mod_description":{ "Spanish":"Administra tus mods y plugins.", "English":"Manage your mods and plugins." }, } lans = ["Spanish","English"] if actLan not in lans: actLan = "English" return Dictionary[text][actLan] def newInit(self,transition: str = 'in_right', origin_widget: ba.Widget = None): app = ba.app scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._pluglist = ba.app.plugins.potential_plugins self.plugins_order = "A-Z" self.actual_type = 'all' uiscale = ba.app.ui.uiscale self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0 x_inset = 100 if uiscale is ba.UIScale.SMALL else 0 self._height = (390.0 if uiscale is ba.UIScale.SMALL else 450.0 if uiscale is ba.UIScale.MEDIUM else 520.0) top_extra = 10 if uiscale is ba.UIScale.SMALL else 0 self._root_widget=ba.containerwidget( size=(self._width, self._height + top_extra), transition=transition, toolbar_visibility='menu_minimal', scale_origin_stack_offset=scale_origin, scale=(2.06 if uiscale is ba.UIScale.SMALL else 1.4 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)) self._scroll_width = self._width - (100 + 2 * x_inset) self._scroll_height = self._height - 115.0 self._sub_width = self._scroll_width * 0.95 self._sub_height = 100.0 if app.ui.use_toolbars and uiscale is ba.UIScale.SMALL: ba.containerwidget(edit=self._root_widget,on_cancel_call=self._do_back) self._back_button = None else: self._back_button = ba.buttonwidget( parent=self._root_widget, position=(53 + x_inset, self._height - 60), size=(140, 60), scale=0.8, autoselect=True, label=ba.Lstr(resource='backText'), button_type='back', on_activate_call=self._do_back) ba.containerwidget(edit=self._root_widget, cancel_button=self._back_button) self._title_text = ba.textwidget(parent=self._root_widget, position=(0, self._height - 42), size=(self._width, 25), text=ba.Lstr(resource='pluginsText'), color=app.ui.title_color, h_align='center', v_align='top') if self._back_button is not None: ba.buttonwidget(edit=self._back_button, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) self._scrollwidget = ba.scrollwidget(parent=self._root_widget, position=(50 + x_inset, 50), simple_culling_v=20.0, highlight=False, size=(self._scroll_width, self._scroll_height), selection_loops_to_parent=True) ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) self._subcontainer = None _refresh(self,self._pluglist) ba.containerwidget(edit=self._root_widget,selected_child=self._scrollwidget) self._restore_state() #plugin_filter can be 'mod','character','map' or 'extra' - NOT USED YET def _refresh(self,pluglist=""): if self._subcontainer is not None and self._subcontainer.exists(): self._subcontainer.delete() self._tabData = {} buttomWidth = self._scroll_width - 40 buttomHeight = 90.0 logowitdh = buttomHeight - 40 app = ba.app if ba.app.meta.scanresults is None: ba.screenmessage('Still scanning plugins; please try again.', color=(1, 0, 0)) ba.playsound(ba.getsound('error')) pluglist = pluglist #print(pluglist) def printStatus(stat): ba.screenmessage(getTranslation(stat)) plugstates: Dict[str, Dict] = ba.app.config.setdefault('Plugins', {}) assert isinstance(plugstates, dict) self._sub_height = len(pluglist) * buttomHeight + 10 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False, selection_loops_to_parent=True) y = self._sub_height - (buttomHeight +15) h = 10 n = 0 for i, availplug in enumerate(pluglist): active = availplug.class_path in ba.app.plugins.active_plugins from ba._general import getclass check = None pInfoBttn = None pSettBttn = None try: cls = getclass(availplug.class_path,Plugin) plugin = cls() except Exception: print("Class not founded") plugstate = plugstates.setdefault(availplug.class_path, {}) checked = plugstate.get('enabled', False) assert isinstance(checked, bool) displayName = str(availplug.class_path) splitter = displayName.split('.') file = splitter[0] pluginName = splitter[1] filename = file +'.py' ver = '??' #type = None settings = False logoTex = 'file' logoColor = (1,1,1) info = None btn_color = (0.63, 0.55, 0.78) link = None linkDesc = ba.Lstr(translate=("",getTranslation("Site_default_desc_text"))) if plugin: print(" Scanning data from "+pluginName+":") try: ver = plugin.version except Exception: print(" Can't found version") #try: type = str(plugin.plugin_type) #except Exception: print(" Can't found plugin type") try: logoTex = plugin.logo except Exception: print(" Can't found logo") try: settings = plugin.settings except Exception: print(" Can't found settings") try: logoColor = plugin.logo_color except Exception: print(" Can't found logo color") try: info = plugin.information except Exception: print(" Can't found information") try: link = plugin.external_link except Exception: print(" Can't found external link") try: linkDesc = plugin.external_link_desc except Exception: print(" Can't found external link description") print("\n") h2 = h else: #type = 'extra' filename = 'File not founded' logoTex = 'file' btn_color =(0.6,0.6,0.6) n+=1 btn = ba.buttonwidget( parent=self._subcontainer, position=(h, y), size=(buttomWidth, buttomHeight), enable_sound=False, color=btn_color, selectable=False, enabled=False, label='') logoImg = ba.imagewidget(parent=self._subcontainer, position=(h+20,y +20), size=(logowitdh,logowitdh), color = logoColor, texture=ba.gettexture(logoTex)) check = ba.checkboxwidget( parent=self._subcontainer, text=pluginName+' - v'+ver, value=checked, position=(h+logowitdh+25, y+buttomHeight-55), maxwidth=buttomWidth-220, size=(buttomWidth- 220, 50), on_value_change_call=ba.Call(self._check_value_changed,availplug), textcolor=((0.8, 0.1, 0.1) if not availplug.available else (0, 1, 0) if active else (0.6, 0.6, 0.6))) pInfoBttn = ba.buttonwidget( parent=self._subcontainer, position=(h2+buttomWidth-80, y+25), size=(45, 45), on_activate_call=ba.Call(printStatus,"Mod_info_status"), button_type="square", label=None, iconscale=1.25, color=(0.4,0.4,0.4), icon_color=(2,2,2), icon=ba.gettexture("achievementEmpty")) h2 -= 60 if info != None: ba.buttonwidget(edit=pInfoBttn,color=(0.2,0.5,1), on_activate_call=ba.Call(openInfo,info,pluginName,link,linkDesc)) pSettBttn = ba.buttonwidget( parent=self._subcontainer, position=(h2+buttomWidth-80, y+25), size=(45, 45), button_type="square", on_activate_call=ba.Call(printStatus,"Mod_settings_status"), label=None, color=(0.4,0.4,0.4), iconscale=1.25, icon=ba.gettexture("settingsIcon")) if settings: ba.buttonwidget(edit=pSettBttn,color=(0.2,0.5,1), on_activate_call=plugin.openWindow) filepath = ba.textwidget(parent=self._subcontainer, position=(h+logowitdh+35, y+15), size=(buttomWidth - 200, 10), maxwidth=buttomWidth - 200, text=filename, scale=0.8, color=(0.7,0.7,0.7), h_align='left', v_align='bottom') # Make sure we scroll all the way to the end when using # keyboard/button nav. ba.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40) # Keep last from looping to back button when down is pressed. if i == len(pluglist) - 1: ba.widget(edit=check, down_widget=check) y-= buttomHeight #print(n) if n == 0: no_available = ba.textwidget(parent=self._subcontainer, position=(0, y), size=(self._sub_width, 25), text=getTranslation("No_Plugins_Available_text"), scale=1.1, color=(0.7,0.7,0.7), h_align='center', v_align='bottom') def _new_do_back(self) -> None: # pylint: disable=cyclic-import from bastd.ui.settings.advanced import AdvancedSettingsWindow self._save_state() ba.containerwidget(edit=self._root_widget,transition=self._transition_out) from bastd.mainmenu import MainMenuSession self._in_game = not isinstance(_ba.get_foreground_host_session(), MainMenuSession) if self._in_game: ba.app.main_menu_window = (mainmenu.MainMenuWindow(transition='in_left').get_root_widget()) else: ba.app.ui.set_main_menu_window(AdvancedSettingsWindow(transition='in_left').get_root_widget()) class InformationWindow(popup.PopupWindow): def __init__(self,info='',mod='',link=None,linkDesc=''): uiscale = ba.app.ui.uiscale scale = (2.3 if uiscale is ba.UIScale.SMALL else 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) self._transitioning_out = False self._width = width = 400 self._height = (250 if uiscale is ba.UIScale.SMALL else 300 if uiscale is ba.UIScale.MEDIUM else 350) bg_color = (0.4, 0.4, 0.6) # creates our _root_widget popup.PopupWindow.__init__(self, position=(0,0), size=(self._width, self._height), scale=scale, bg_color=bg_color) self._cancel_button = ba.buttonwidget( parent=self.root_widget, position=(50, self._height - 30), size=(50, 50), scale=0.5, label='', color=bg_color, on_activate_call=self._on_cancel_press, autoselect=True, icon=ba.gettexture('crossOut'), iconscale=1.2) #if link != None: # available_link = link.strip() # if available_link: # self._external_button = ba.buttonwidget( # parent=self.root_widget, # position=((self._width*0.5)-100,0), # size=(200,30), # scale=1.0, # label=linkDesc, #color=(0,0,1), # on_activate_call=ba.Call(self.confirm_open_url,link), # autoselect=True) self._title_text = ba.textwidget(parent=self.root_widget, position=(self._width * 0.5,self._height - 20), size=(0, 0), h_align='center', v_align='center', scale=0.6, text=mod+' - '+getTranslation("Information_text"), maxwidth=200, color=(1, 1, 1, 0.4)) self._scrollwidget = ba.scrollwidget(parent=self.root_widget, size=(self._width - 60,self._height - 70), position=(30, 30), capture_arrows=True, simple_culling_v=10) ba.widget(edit=self._scrollwidget, autoselect=True) ba.containerwidget(edit=self.root_widget, cancel_button=self._cancel_button) lines = info.splitlines() line_height = 20 scale = 0.7 sub_width = width - 65 sub_height = line_height * len(lines) + 20 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(sub_width, sub_height), background=False,claims_left_right=False,claims_tab=False) voffs = 0 for line in lines: ba.textwidget(parent=self._subcontainer, padding=1, color=(0.7, 0.9, 0.7, 1.0), scale=scale, flatness=1.0, size=(sub_width, line_height), position=(0, sub_height - 25 + voffs), h_align='left', v_align='top', corner_scale=0.7, maxwidth=sub_width, text=ba.Lstr(value=line)) voffs -= line_height def confirm_open_url(self,link): text = ba.Lstr() ConfirmWindow(ba.Lstr(translate=("",getTranslation("open_website_text"))), width=350, height=100, action=ba.Call(ba.open_url,link), ok_text=ba.Lstr(resource='okText')) def _on_cancel_press(self) -> None: self._transition_out() def _transition_out(self) -> None: if not self._transitioning_out: self._transitioning_out = True ba.containerwidget(edit=self.root_widget, transition='out_scale') def on_popup_cancel(self) -> None: ba.playsound(ba.getsound('swish')) self._transition_out() # ba_meta export plugin class PluginsPlus(ba.Plugin): version = "1.0.3" #plugin_type = 'mod' logo = 'folder' logo_color = (1,0.9,0.1) information = getTranslation("Mod_description") #external_link = "https://bombsquadmods-froshlee14.blogspot.com/" #external_link_desc = "Froshlee's mods website" def on_app_running(self) -> None: PluginSettingsWindow.__init__ = newInit PluginSettingsWindow._do_back = _new_do_back MainMenuWindow.oldRefresh = MainMenuWindow._refresh def newRefresh(self): self.oldRefresh() if self._in_game and not _ba.is_in_replay(): self._plugins_button = ba.buttonwidget(parent=self._root_widget, autoselect=True, position=(self._width+15,self._height-75), size=(50,50), scale=0.8, text_scale=1.5, label=None, on_activate_call=ba.Call(doMenu,self), iconscale=1.25, icon=ba.gettexture("settingsIcon"), button_type="square") MainMenuWindow._refresh = newRefresh