NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

panelSkills.py (31858B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\info\shipInfoPanels\panelSkills.py
      2 import evetypes
      3 import expertSystems.client
      4 import eveicon
      5 import localization
      6 import threadutils
      7 import uthread2
      8 from eve.client.script.ui.shared.tooltip.skill import LoadSkillEntryTooltip
      9 from eve.common.script.sys import idCheckers
     10 from eve.common.lib import appConst
     11 from carbon.common.script.sys.serviceConst import ROLE_GML
     12 from carbon.common.script.util.format import IntToRoman
     13 from carbon.common.script.util.commonutils import StripTags
     14 from clientsettings.setting import UserSettingBool
     15 from carbonui import Align, TextColor, uiconst
     16 from carbonui.text.styles import TextHeadline, TextBody, TextDetail
     17 from carbonui.control.scrollContainer import ScrollContainer
     18 from carbonui.primitives.container import Container
     19 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     20 from carbonui.primitives.sprite import Sprite
     21 from carbonui.control.contextMenu.menuData import MenuData
     22 from carbonui.control.checkbox import Checkbox
     23 from carbonui.control.buttonIcon import ButtonIcon
     24 from eve.client.script.ui.control.infoIcon import CheckMarkGlyphIcon
     25 from eve.client.script.ui.control.skillBar.skillBar import SkillBar
     26 from eve.client.script.ui.control.toggleButtonGroup import ToggleButtonGroup
     27 from eve.client.script.ui.control.toggleButtonGroupButton import ToggleButtonGroupButtonIcon
     28 from eve.client.script.ui.control.toggleButtonUnderlay import ToggleButtonUnderlay, FrameType
     29 from eve.client.script.ui.shared.info.shipInfoCollapsibleGroup import _CollapsibleGroupBase
     30 from eve.client.script.ui.shared.info.shipInfoConst import UNLOCKED_ICON, MASTERY_ICONS, ANGLE_SKILLS, TAB_SKILLS, get_mastery_level_icon_and_message
     31 from eve.client.script.ui.shared.info.shipInfoListEntries import _ListEntryBase
     32 from eve.client.script.ui.shared.info.shipInfoPanels.panelBase import PanelBase
     33 from eve.client.script.ui.shared.neocom.skillConst import COLOR_SKILL_1
     34 from eve.client.script.ui.shared.tooltip.itemObject import ItemObject
     35 from eve.client.script.ui.shared.tooltip.skillBtns import SkillActionContainer
     36 from eve.client.script.ui.shared.tooltip.skill_requirement import OmegaTrainingTimeContainer, AlphaTrainingTimeContainer, GetActivityTextForType
     37 from menu import MenuLabel
     38 from omega.client.clone_grade_svc import get_clone_grade_svc
     39 from utillib import KeyVal
     40 from skills.client.skillController import SkillController
     41 _filter_acquired_setting = UserSettingBool('masteries_filter_acquired', False)
     42 _collapsed_certificates = set()
     43 
     44 class PanelSkills(PanelBase):
     45     __notifyevents__ = ['OnSkillsChanged']
     46     _selectedTabID = None
     47 
     48     def ApplyAttributes(self, attributes):
     49         super(PanelSkills, self).ApplyAttributes(attributes)
     50         self._load_task = None
     51         self.LoadAssociatedExpertSystems()
     52         self.LoadCurrentMastery()
     53         self.rightNav.SelectByID(0)
     54         _filter_acquired_setting.on_change.connect(self._filter_acquired_setting_changed)
     55 
     56     def Close(self):
     57         super(PanelSkills, self).Close()
     58         _filter_acquired_setting.on_change.disconnect(self._filter_acquired_setting_changed)
     59 
     60     def _enable_minimized_view(self):
     61         self.mastery_level_cont_minimized.SetParent(self.minimizedCont, idx=0)
     62         self.minimizedNav.SetParent(self.minimizedCont, idx=1)
     63         self._filter_container.SetParent(self.minimizedCont, idx=2)
     64         self.training_time_cont.SetParent(self.minimizedCont, idx=3)
     65         self.list_cont.SetParent(self.content_scroll_minimized)
     66 
     67     def _enable_expanded_view(self):
     68         self.training_time_cont.SetParent(self.rightCont)
     69         self._filter_container.SetParent(self.rightCont)
     70         self.list_cont.SetParent(self.scroll_cont)
     71         self.scroll_cont.SetParent(self.rightCont)
     72 
     73     def _construct_content_minimized(self):
     74         self.mastery_level_cont_minimized = Container(name='mastery_level_cont_minimized', parent=self.minimizedCont, align=Align.TOTOP, height=32, padBottom=4)
     75         self.mastery_level_icon_minimized = Sprite(name='mastery_level_sprite', parent=self.mastery_level_cont_minimized, align=Align.CENTERLEFT, width=40, height=32, padLeft=8, texturePath=eveicon.mastery_locked, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.1, state=uiconst.UI_DISABLED)
     76         self.mastery_level_label_minimized = TextBody(name='masteryLevelLabel', parent=self.mastery_level_cont_minimized, align=Align.CENTERLEFT, padLeft=48, text='You have mastery level 5', state=uiconst.UI_DISABLED)
     77 
     78     def _construct_content(self):
     79         uthread2.Yield()
     80         self.right_nav_cont = Container(name='rightNavCont', parent=self.rightCont, align=Align.TOTOP, height=64, padBottom=8)
     81         self.training_time_cont = ContainerAutoSize(name='trainingTimeCont', parent=self.rightCont, align=Align.TOBOTTOM, padTop=8)
     82         self._filter_container = Container(parent=self.rightCont, align=Align.TOTOP, height=24, padBottom=4)
     83         ButtonIcon(parent=self._filter_container, align=Align.TORIGHT, texturePath=eveicon.collapse, hint=localization.GetByLabel('UI/Common/Buttons/CollapseAll'), func=self._collapse_all, opacity=TextColor.NORMAL.opacity)
     84         checkbox_container = Container(parent=self._filter_container, align=Align.TOALL, clipChildren=True)
     85         Checkbox(parent=checkbox_container, align=Align.CENTERLEFT, setting=_filter_acquired_setting, text=localization.GetByLabel('UI/InfoWindow/MasteryFilterAcquired'))
     86         self.scroll_cont = ScrollContainer(name='scrollCont', parent=self.rightCont, align=Align.TOALL)
     87         self.list_cont = ContainerAutoSize(name='listCont', parent=self.scroll_cont, align=Align.TOTOP)
     88         self._construct_navigation()
     89         self._construct_expert_system()
     90         self._construct_mastery()
     91 
     92     def _construct_navigation(self):
     93         self.rightNav = ToggleButtonGroup(name='rightNav', parent=self.right_nav_cont, align=uiconst.TOTOP, callback=self.OnNavButtonPressed, height=64, btnClass=SkillPanelToggleButtonLarge)
     94         self.minimizedNav = ToggleButtonGroup(name='minimizedNav', parent=self.minimizedCont, align=uiconst.TOTOP, idx=0, callback=self.OnNavButtonPressed, height=42, btnClass=SkillPanelToggleButtonSmall, padBottom=8)
     95         self.nav_buttons = {}
     96         self.nav_buttons[0] = self.rightNav.AddButton(0, iconPath=UNLOCKED_ICON, iconSize=48, hint=localization.GetByLabel('UI/InfoWindow/TabNames/Requirements'), getMenu=self._get_tab_group_menu)
     97         self.nav_buttons_minimized = {}
     98         self.nav_buttons_minimized[0] = self.minimizedNav.AddButton(0, iconPath=UNLOCKED_ICON, iconSize=32, hint=localization.GetByLabel('UI/InfoWindow/TabNames/Requirements'), getMenu=self._get_tab_group_menu)
     99         for level in range(6):
    100             if level > 0:
    101                 self.nav_buttons[level] = self.rightNav.AddButton(level, iconPath=MASTERY_ICONS[level], iconSize=48, hint=localization.GetByLabel('UI/InfoWindow/MasteryLevelButtonHint', level=level), getMenu=self._get_tab_group_menu)
    102                 self.nav_buttons_minimized[level] = self.minimizedNav.AddButton(level, iconPath=MASTERY_ICONS[level], iconSize=32, hint=localization.GetByLabel('UI/InfoWindow/MasteryLevelButtonHint', level=level), getMenu=self._get_tab_group_menu)
    103 
    104     def OnNavButtonPressed(self, btnID, oldBtnID):
    105         self._selectedTabID = btnID
    106         self.LoadPage()
    107         self.rightNav.SetSelected(btnID)
    108         self.minimizedNav.SetSelected(btnID)
    109 
    110     def _get_tab_group_menu(self, btnID):
    111         if not session.role & ROLE_GML:
    112             return None
    113         m = MenuData()
    114         if btnID == 0:
    115             m.AddEntry('GM: Give all skills', lambda : _qa_give_required_skills(self.typeID))
    116         else:
    117             m.AddEntry('GM: Give all skills', lambda : _qa_give_all_cert_skills(self.typeID, btnID))
    118         return m
    119 
    120     _MASTERY_CONT_HEIGHT = 140
    121     _OMEGA_MASTERY_CONT_HEIGHT = 160
    122 
    123     def _construct_mastery(self):
    124         self.mastery_level_cont = Container(name='masteryLevelCont', parent=self.leftCont, align=Align.TOBOTTOM, height=self._MASTERY_CONT_HEIGHT, padding=(16, 0, 16, 24), state=uiconst.UI_DISABLED)
    125         self.mastery_level_label = TextHeadline(name='masteryLevelLabel', parent=self.mastery_level_cont, align=Align.CENTERBOTTOM, text='', state=uiconst.UI_DISABLED)
    126         self.mastery_level_icon = Sprite(name='masteryLevelSprite', parent=self.mastery_level_cont, align=Align.CENTERTOP, width=128, height=128, texturePath=eveicon.mastery_locked, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.1, state=uiconst.UI_DISABLED)
    127 
    128     def _construct_expert_system(self):
    129         self.expert_system_cont = Container(name='expertSystemCont', parent=self.leftCont, align=Align.TOBOTTOM, height=68, padding=(16, 0, 16, 24))
    130         TextDetail(name='expertSystemInfoLabel', parent=self.expert_system_cont, align=Align.TOPLEFT, text=localization.GetByLabel('UI/InfoWindow/ExpertSystemAvailable'), color=TextColor.SECONDARY)
    131         expert_system_subcont = Container(name='expertSystemSubCont', parent=self.expert_system_cont, align=Align.TOBOTTOM, state=uiconst.UI_PICKCHILDREN, height=46)
    132         expertSystemSprite = Sprite(name='expertSystemIcon', parent=expert_system_subcont, align=Align.CENTERLEFT, state=uiconst.UI_NORMAL, width=46, height=46, texturePath='res:/UI/Texture/Icons/Inventory/ExpertSystems/CoreShipSystems.png')
    133         splitCont = Container(parent=expert_system_subcont, align=Align.TOALL, padLeft=60, state=uiconst.UI_PICKCHILDREN)
    134         self.expert_system_label = TextBody(name='expertSystemLabel', parent=Container(parent=splitCont, align=Align.TOTOP_PROP, height=0.5, clipChildren=True), align=Align.BOTTOMLEFT, text=None, autoFadeSides=16, state=uiconst.UI_NORMAL)
    135         self.expert_system_value_label = TextDetail(name='expertSystemValueLabel', parent=Container(parent=splitCont, align=Align.TOBOTTOM_PROP, height=0.5, clipChildren=True), align=Align.TOPLEFT, color=TextColor.SECONDARY, text=localization.GetByLabel('UI/InfoWindow/ExpertSystemUnlocksShips', num=3), state=uiconst.UI_DISABLED, autoFadeSides=16)
    136         expertSystemSprite.OnClick = self.on_expert_system_clicked
    137         self.expert_system_label.OnClick = self.on_expert_system_clicked
    138 
    139     def on_expert_system_clicked(self, *args):
    140         from eve.client.script.ui.shared.neocom.characterSheetWindow import CharacterSheetWindow
    141         CharacterSheetWindow.OpenExpertSystems()
    142 
    143     def LoadRequirements(self):
    144         self.list_cont.Flush()
    145         requiredSkills = sm.GetService('skills').GetRequiredSkills(self.typeID)
    146         for typeID, requiredLevel in requiredSkills.iteritems():
    147             self._DrawSkillTree(typeID, requiredLevel, self.list_cont, 1, 6)
    148 
    149     def _DrawSkillTree(self, skillID, requiredLvl, parent, indentIdx, indentStep):
    150         ListEntrySkill(skillID=skillID, requiredLevel=requiredLvl, parent=parent, indent=indentIdx * indentStep)
    151         for prereqId, lvl in sm.GetService('skills').GetRequiredSkills(skillID).iteritems():
    152             if prereqId == skillID:
    153                 continue
    154             self._DrawSkillTree(prereqId, lvl, parent, indentIdx + 1, indentStep)
    155 
    156     @threadutils.threaded
    157     def LoadPage(self):
    158         pageID = self._selectedTabID
    159         self.LoadTrainingTimeAndSkillActions(pageID)
    160         if pageID == 0:
    161             self._filter_container.display = False
    162             self.LoadRequirements()
    163         else:
    164             self._filter_container.display = True
    165             self.LoadMasteryLevel(pageID)
    166 
    167     def LoadMasteryLevel(self, level):
    168         self.list_cont.Flush()
    169         certificates = [ (cert.GetName(), cert) for cert in sm.GetService('certificates').GetCertificatesForShipByMasteryLevel(self.typeID, level) ]
    170         for name, certificate in sorted(certificates, key=lambda cert: cert[0]):
    171             uthread2.Yield()
    172             if level != self._selectedTabID:
    173                 break
    174             self.LoadCertificate(certificate, level, name)
    175 
    176     def LoadCertificate(self, certificate, level, name):
    177         certificateCont = CollapsibleGroupCertificate(name=name, parent=self.list_cont, align=Align.TOTOP, groupIcon=eveicon.skill_book, groupName=name, padBottom=4, certificate=certificate, level=level)
    178         collapsed = (certificate.certificateID, level) in _collapsed_certificates or certificate.GetLevel() >= level
    179         if collapsed:
    180             certificateCont.SetCollapsed(True)
    181         skillSvc = sm.GetService('skills')
    182         filter_acquired = _filter_acquired_setting.get()
    183         for skillID, level in certificate.SkillsByTypeAndLevel(level):
    184             if filter_acquired:
    185                 skill = skillSvc.GetSkill(skillID)
    186                 if skill and skill.trainedSkillLevel >= level:
    187                     continue
    188             ListEntrySkill(skillID=skillID, requiredLevel=level, parent=certificateCont.mainCont, indent=8, hint=skillSvc.GetSkillToolTip(skillID, level))
    189 
    190     def LoadCurrentMastery(self):
    191         certSvc = sm.GetService('certificates')
    192         masteryLevel = certSvc.GetCurrCharMasteryLevel(self.typeID)
    193         canFly = sm.GetService('skills').IsSkillRequirementMet(self.typeID)
    194         texturePath, message, onClick = get_mastery_level_icon_and_message(self.typeID)
    195         self.mastery_level_icon.SetTexturePath(texturePath)
    196         self.mastery_level_icon.OnClick = onClick
    197         self.mastery_level_label.SetText(message)
    198         self.mastery_level_icon_minimized.SetTexturePath(texturePath)
    199         self.mastery_level_icon_minimized.OnClick = onClick
    200         self.mastery_level_label_minimized.SetText(message)
    201         if not canFly:
    202             for lvl, btn in self.nav_buttons.iteritems():
    203                 btn.set_unlocked(False)
    204 
    205             for lvl, btn in self.nav_buttons_minimized.iteritems():
    206                 btn.set_unlocked(False)
    207 
    208         else:
    209             for lvl, btn in self.nav_buttons.iteritems():
    210                 btn.set_unlocked(masteryLevel >= lvl)
    211 
    212             for lvl, btn in self.nav_buttons_minimized.iteritems():
    213                 btn.set_unlocked(masteryLevel >= lvl)
    214 
    215     def LoadAssociatedExpertSystems(self):
    216         self.expert_system_cont.display = False
    217         if not expertSystems.has_associated_expert_system(self.typeID):
    218             self.mastery_level_cont.padBottom = 56
    219             return
    220         associatedExpertSystems = expertSystems.get_associated_expert_systems(self.typeID)
    221         relevantExpertSystems = filter(lambda system: expertSystems.expert_system_benefits_player(system.type_id), associatedExpertSystems)
    222         if len(relevantExpertSystems):
    223             expertSystem = relevantExpertSystems[0]
    224             self.expert_system_label.text = expertSystem.name
    225             if expertSystem.associated_type_ids:
    226                 self.expert_system_value_label.text = localization.GetByLabel('UI/InfoWindow/ExpertSystemUnlocksShips', num=len(expertSystem.associated_type_ids))
    227             else:
    228                 self.expert_system_value_label.Hide()
    229             self.expert_system_cont.display = True
    230         else:
    231             self.mastery_level_cont.padBottom = 56
    232 
    233     def LoadTrainingTimeAndSkillActions(self, level):
    234         self.training_time_cont.Flush()
    235         if level == 0:
    236             self._LoadTrainingTimeAndSkillActionsForRequirements()
    237         else:
    238             self._LoadTrainingTimeAndSkillActionsForMastery(level)
    239 
    240     def _LoadTrainingTimeAndSkillActionsForRequirements(self):
    241         if sm.GetService('skills').IsSkillRequirementMet(self.typeID):
    242             return
    243         totalTime = sm.GetService('skills').GetSkillTrainingTimeLeftToUseType(self.typeID, includeBoosters=False)
    244         omegaRestricted = ItemObject(self.typeID, None).NeedsOmegaUpgrade()
    245         if get_clone_grade_svc().is_omega_with_grace_period():
    246             OmegaTrainingTimeContainer(parent=self.training_time_cont, omegaTime=totalTime)
    247         else:
    248             omegaTime = totalTime / 2
    249             AlphaTrainingTimeContainer(parent=self.training_time_cont, isOmegaRestricted=omegaRestricted, alphaTime=totalTime, omegaTime=omegaTime, activityText=GetActivityTextForType(self.typeID))
    250         if not omegaRestricted:
    251             SkillActionContainer(parent=self.training_time_cont, padTop=8, align=uiconst.TOTOP, typeID=self.typeID)
    252 
    253     def _LoadTrainingTimeAndSkillActionsForMastery(self, masteryLevel):
    254         skillSvc = sm.GetService('skills')
    255         certSvc = sm.GetService('certificates')
    256         trainingTime = certSvc.GetShipTrainingTimeForMasteryLevel(self.typeID, masteryLevel)
    257         isOmegaRestricted = False
    258         requiredSkillsList = []
    259         for skillID, skillLevel in certSvc.GetSkillsRequiredForMasteryLevel(self.typeID, masteryLevel).iteritems():
    260             skill = skillSvc.GetSkill(skillID)
    261             if not isOmegaRestricted:
    262                 isOmegaRestricted = get_clone_grade_svc().is_requirements_restricted(skillID)
    263                 if not isOmegaRestricted:
    264                     isOmegaRestricted = get_clone_grade_svc().is_skill_level_restricted(skillID, skillLevel)
    265             if not skill or skill.trainedSkillLevel < skillLevel:
    266                 requiredSkillsList.append((skillID, skillLevel))
    267 
    268         if not isOmegaRestricted:
    269             isOmegaRestricted = ItemObject(self.typeID).NeedsOmegaUpgrade()
    270         requiredSkillsList = list(set(requiredSkillsList))
    271         requiredSkillsList = skillSvc.GetSkillsMissingToUseAllSkillsFromListRecursiveAsList(requiredSkillsList)
    272         missingSkills = sm.GetService('skills').GetMissingSkillBooksFromList(requiredSkillsList)
    273         if len(requiredSkillsList) > 0:
    274             if get_clone_grade_svc().is_omega_with_grace_period():
    275                 OmegaTrainingTimeContainer(parent=self.training_time_cont, omegaTime=long(trainingTime), padBottom=8)
    276             else:
    277                 omegaTime = long(trainingTime) / 2
    278                 AlphaTrainingTimeContainer(parent=self.training_time_cont, isOmegaRestricted=isOmegaRestricted, alphaTime=long(trainingTime), omegaTime=omegaTime, activityText=localization.GetByLabel('Tooltips/SkillPlanner/ActivityTrainMasteryLevel'), padBottom=8, clipChildren=True)
    279             if not isOmegaRestricted:
    280                 typeName = evetypes.GetName(self.typeID)
    281                 level = IntToRoman(masteryLevel)
    282                 skillPlanName = localization.GetByLabel('UI/SkillPlan/CreateMasterySkillPlanName', typeName=typeName, level=level)
    283                 SkillActionContainer(parent=self.training_time_cont, align=uiconst.TOTOP, requiredSkills=requiredSkillsList, missingSkills=missingSkills, skillPlanName=skillPlanName)
    284 
    285     @classmethod
    286     def get_name(cls):
    287         return localization.GetByLabel('UI/InfoWindow/TabNames/Skills')
    288 
    289     @classmethod
    290     def get_icon(cls):
    291         return eveicon.skill_book
    292 
    293     @classmethod
    294     def is_visible(cls, typeID, itemID = None, rec = None):
    295         return not idCheckers.IsCapsule(evetypes.GetGroupID(typeID))
    296 
    297     def get_camera_position(self):
    298         return ANGLE_SKILLS
    299 
    300     def get_tab_type(self):
    301         return TAB_SKILLS
    302 
    303     def OnSkillsChanged(self, *args):
    304         self.LoadCurrentMastery()
    305         self.LoadPage()
    306 
    307     def _filter_acquired_setting_changed(self, *args, **kwargs):
    308         self.LoadPage()
    309 
    310     def _collapse_all(self):
    311         for entry in self.list_cont.children:
    312             if hasattr(entry, 'SetCollapsed'):
    313                 entry.SetCollapsed(True)
    314 
    315 
    316 class ListEntrySkill(_ListEntryBase):
    317     default_height = 32
    318     isDragObject = True
    319 
    320     def __init__(self, skillID, requiredLevel, indent = 0, **kw):
    321         self.skillID = skillID
    322         self.requiredLevel = requiredLevel
    323         self.skillController = SkillController(skillID)
    324         super(ListEntrySkill, self).__init__(indent=indent, **kw)
    325         self.refresh()
    326 
    327     def construct_layout(self):
    328         super(ListEntrySkill, self).construct_layout()
    329         self.iconCont = Container(name='iconCont', parent=self.content, align=Align.TORIGHT, width=16, left=8)
    330         self.icon = None
    331         self.completedIcon = None
    332         skillBarCont = Container(name='skillBarCont', parent=self.content, align=Align.TOLEFT, width=70)
    333         self.skillBar = SkillBar(name='skillBar', parent=skillBarCont, align=Align.CENTERLEFT, state=uiconst.UI_DISABLED, skillID=self.skillID, boxSize=8)
    334         skillAndLevelCont = Container(name='skillAndLevelCont', parent=self.content, align=Align.TOALL, padLeft=8, clipChildren=True)
    335         self.skillAndLevelLabel = TextBody(name='skillAndLevelLabel', parent=skillAndLevelCont, align=Align.CENTERLEFT, autoFadeSides=16)
    336         self.backgroundFill = None
    337 
    338     def refresh(self):
    339         text = self.skillController.GetRequiredSkillNameAndLevelComparedToTrainedLevel(self.requiredLevel)
    340         self.skillAndLevelLabel.SetText(text)
    341         self.skillBar.SetRequiredLevel(self.requiredLevel)
    342         if not self.skillController.IsInjected():
    343             if self.skillController.IsSkillAvailableForPurchase():
    344                 self.set_icon(texturePath='res:/ui/Texture/classes/Skills/SkillBookNotInjected.png', color=COLOR_SKILL_1, hint=localization.GetByLabel('UI/SkillQueue/SkillBookMissing'))
    345             else:
    346                 self.set_icon(texturePath='res:/ui/Texture/classes/Skills/RareSkillBookNotInjected.png', color=COLOR_SKILL_1, hint=localization.GetByLabel('UI/SkillQueue/RareSkillBookMissing'))
    347         elif self.skillController.GetMyLevel() >= self.requiredLevel:
    348             self.set_completed()
    349             self.skillAndLevelLabel.SetRGBA(1.0, 1.0, 1.0, 0.5)
    350             self.hide_background()
    351         else:
    352             self.set_icon(texturePath='res:/ui/Texture/classes/Skills/SkillRequirementNotMet.png', color=COLOR_SKILL_1, hint=localization.GetByLabel('UI/InfoWindow/SkillNotTrainedToRequiredLevel'))
    353             self.hide_background()
    354 
    355     def set_completed(self):
    356         if self.completedIcon is None:
    357             self.completedIcon = CheckMarkGlyphIcon(parent=self.iconCont, align=Align.CENTER, hint=localization.GetByLabel('UI/InfoWindow/SkillTrainedToRequiredLevel'))
    358         else:
    359             self.completedIcon.Show()
    360         if self.icon:
    361             self.icon.Hide()
    362 
    363     def set_icon(self, texturePath, color, hint):
    364         if self.icon is None:
    365             self.icon = Sprite(parent=self.iconCont, align=Align.CENTER, texturePath=texturePath, width=16, height=16, color=color, hint=hint)
    366         else:
    367             self.icon.SetTexturePath(texturePath)
    368             self.icon.SetRGBA(*color)
    369             self.icon.hint = hint
    370         if self.completedIcon:
    371             self.completedIcon.Hide()
    372 
    373     def hide_background(self):
    374         if self.backgroundFill is not None:
    375             self.backgroundFill.Close()
    376             self.backgroundFill = None
    377 
    378     def GetMenu(self):
    379         return self.skillController.GetMenu()
    380 
    381     def GetDragData(self):
    382         return self.skillController.GetDragData()
    383 
    384     def LoadTooltipPanel(self, tooltip_panel, *args):
    385         LoadSkillEntryTooltip(tooltip_panel, self.skillID, self.requiredLevel)
    386 
    387     def OnDblClick(self, *args, **kwargs):
    388         self._show_info()
    389 
    390     def _show_info(self):
    391         sm.GetService('info').ShowInfo(typeID=self.skillID)
    392 
    393 
    394 class SkillPanelToggleButtonUnderlay(ToggleButtonUnderlay):
    395 
    396     def _get_texture_path(self):
    397         if self.frame_type == FrameType.LEFT:
    398             return 'res:/UI/Texture/classes/ToggleButtonGroup/toggle_button_frame_left_64px.png'
    399         if self.frame_type == FrameType.RIGHT:
    400             return 'res:/UI/Texture/classes/ToggleButtonGroup/toggle_button_frame_right_64px.png'
    401         return 'res:/UI/Texture/classes/ToggleButtonGroup/toggle_button_frame_64px.png'
    402 
    403 
    404 class SkillPanelToggleButtonLarge(ToggleButtonGroupButtonIcon):
    405     default_clipChildren = True
    406 
    407     def _layout(self):
    408         self._icon = Sprite(parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, texturePath=self.iconPath, color=self._get_icon_color(), pos=(0,
    409          -8,
    410          self.iconSize,
    411          self.iconSize))
    412         self._underlay = SkillPanelToggleButtonUnderlay(bgParent=self, selected=self.isSelected, enabled=not self.isDisabled, selected_color_override=self.colorSelected)
    413         self.unlocked_icon = Sprite(parent=self, align=Align.CENTER, state=uiconst.UI_DISABLED, pos=(0, 18, 16, 16), texturePath=eveicon.circle_checkmark, color=(1, 1, 1, 0.6))
    414         self.unlocked_icon.Hide()
    415         self.locked_icon = Sprite(parent=self, align=Align.CENTER, state=uiconst.UI_DISABLED, pos=(0, 18, 12, 12), texturePath='res:/UI/Texture/classes/PieCircle/circle16.png', color=(0, 0, 0, 0.4))
    416 
    417     def set_unlocked(self, unlocked):
    418         if unlocked:
    419             self.unlocked_icon.Show()
    420             self.locked_icon.Hide()
    421         else:
    422             self.unlocked_icon.Hide()
    423             self.locked_icon.Show()
    424 
    425 
    426 class SkillPanelToggleButtonSmall(ToggleButtonGroupButtonIcon):
    427 
    428     def _layout(self):
    429         self._icon = Sprite(parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, texturePath=self.iconPath, color=self._get_icon_color(), pos=(0,
    430          -8,
    431          self.iconSize,
    432          self.iconSize))
    433         self._underlay = ToggleButtonUnderlay(bgParent=self, selected=self.isSelected, enabled=not self.isDisabled, selected_color_override=self.colorSelected)
    434         self.unlocked_icon = Sprite(parent=self, align=Align.CENTER, state=uiconst.UI_DISABLED, pos=(0, 10, 16, 16), texturePath=eveicon.circle_checkmark, color=(1, 1, 1, 0.6))
    435         self.unlocked_icon.Hide()
    436         self.locked_icon = Sprite(parent=self, align=Align.CENTER, state=uiconst.UI_DISABLED, pos=(0, 10, 12, 12), texturePath='res:/UI/Texture/classes/PieCircle/circle16.png', color=(0, 0, 0, 0.4))
    437 
    438     def set_unlocked(self, unlocked):
    439         if unlocked:
    440             self.unlocked_icon.Show()
    441             self.locked_icon.Hide()
    442         else:
    443             self.unlocked_icon.Hide()
    444             self.locked_icon.Show()
    445 
    446 
    447 class CollapsibleGroupCertificate(_CollapsibleGroupBase):
    448     default_expanderAlign = Align.TOLEFT
    449     default_expanderWidth = 20
    450     default_expanderPadding = (4, 0, 0, 0)
    451     isDragObject = True
    452 
    453     def ApplyAttributes(self, attributes):
    454         self.certificate = attributes.certificate
    455         self.level = attributes.level
    456         self.label = self.certificate.GetLabel(self.level)
    457         super(CollapsibleGroupCertificate, self).ApplyAttributes(attributes)
    458         self.update_progress()
    459 
    460     def SetCollapsed(self, collapsed):
    461         if collapsed:
    462             _collapsed_certificates.add((self.certificate.certificateID, self.level))
    463         else:
    464             _collapsed_certificates.discard((self.certificate.certificateID, self.level))
    465         super(CollapsibleGroupCertificate, self).SetCollapsed(collapsed)
    466 
    467     def _construct_expander(self):
    468         super(CollapsibleGroupCertificate, self)._construct_expander()
    469         certLevelCont = Container(name='certLevelCont', parent=self.headerCont, align=Align.TOLEFT, width=22, padLeft=4)
    470         Sprite(name='certLevelIcon', parent=certLevelCont, align=Align.CENTER, width=22, height=22, texturePath=_get_certificate_level_icon(self.level), state=uiconst.UI_DISABLED)
    471         progressCont = Container(name='progressCont', parent=self.headerCont, align=Align.TORIGHT, width=16, padRight=8)
    472         self.completedIcon = CheckMarkGlyphIcon(parent=progressCont, align=Align.CENTER, hint=localization.GetByLabel('UI/InfoWindow/TrainedAndOfRequiredLevel'))
    473         self.progressIcon = Sprite(name='progressIcon', parent=progressCont, align=Align.CENTER, width=16, height=16, texturePath='res:/ui/Texture/classes/Skills/SkillRequirementNotMet.png', hint=localization.GetByLabel('UI/InfoWindow/NotTrained'))
    474         self.completedIcon.Hide()
    475         self.progressIcon.Hide()
    476         titleCont = ContainerAutoSize(name='titleCont', parent=self.headerCont, align=Align.TOALL, padLeft=4, clipChildren=True)
    477         self.titleLabel = TextBody(name='title', parent=titleCont, align=Align.CENTERLEFT, text=self.label, autoFadeSides=16)
    478 
    479     def update_progress(self):
    480         currLevel = self.certificate.GetLevel()
    481         if currLevel >= self.level:
    482             self.completedIcon.Show()
    483             self.progressIcon.Hide()
    484         else:
    485             self.completedIcon.Hide()
    486             self.progressIcon.Show()
    487 
    488     def GetMenu(self):
    489         m = MenuData()
    490         m.AddEntry(MenuLabel('UI/Commands/ShowInfo'), self._show_info)
    491         if session.role & ROLE_GML == ROLE_GML:
    492             m.AddEntry('GM: Give all skills', lambda : _qa_give_cert_skills(self.certificate.certificateID, self.level))
    493         return m
    494 
    495     def _show_info(self, *args, **kwargs):
    496         abstractinfo = KeyVal(certificateID=self.certificate.certificateID, level=self.level)
    497         sm.GetService('info').ShowInfo(appConst.typeCertificate, abstractinfo=abstractinfo)
    498 
    499     def GetHint(self):
    500         return self.certificate.GetDescription()
    501 
    502     def GetDragData(self, *args):
    503         entry = KeyVal()
    504         entry.__guid__ = 'listentry.CertEntry'
    505         entry.typeID = appConst.typeCertificate
    506         entry.certID = self.certificate.certificateID
    507         entry.level = self.level
    508         entry.genericDisplayLabel = StripTags(self.certificate.GetName())
    509         return [entry]
    510 
    511     def GetTooltipPointer(self):
    512         return uiconst.POINT_RIGHT_2
    513 
    514 
    515 def _get_certificate_level_icon(level):
    516     return 'res:/UI/Texture/Classes/Certificates/level%sSmall.png' % level
    517 
    518 
    519 def _qa_give_required_skills(type_id):
    520     from collections import defaultdict
    521     train_skills = defaultdict(int)
    522 
    523     def add_skills(skill_type_id, required_level):
    524         if sm.GetService('skills').MySkillLevel(skill_type_id) < required_level:
    525             train_skills[skill_type_id] = max(train_skills[skill_type_id], required_level)
    526         for skill_id, level in sm.GetService('skills').GetRequiredSkills(skill_type_id).iteritems():
    527             if skill_id == skill_type_id:
    528                 continue
    529             add_skills(skill_id, level)
    530 
    531     required_skills = sm.GetService('skills').GetRequiredSkills(type_id)
    532     for skill_type_id, required_level in required_skills.iteritems():
    533         add_skills(skill_type_id, required_level)
    534 
    535     _qa_give_skills(train_skills)
    536 
    537 
    538 def _qa_give_all_cert_skills(type_id, mastery_level):
    539     from collections import defaultdict
    540     train_skills = defaultdict(int)
    541     certificates = sm.GetService('certificates').GetCertificatesForShipByMasteryLevel(type_id, mastery_level)
    542     for cert in certificates:
    543         skills = sm.GetService('certificates').GetCertificate(cert.certificateID).SkillsByTypeAndLevel(mastery_level)
    544         for skill_type_id, required_level in skills:
    545             if sm.GetService('skills').MySkillLevel(skill_type_id) < required_level:
    546                 train_skills[skill_type_id] = max(train_skills[skill_type_id], required_level)
    547 
    548     _qa_give_skills(train_skills)
    549 
    550 
    551 def _qa_give_cert_skills(certificate_id, certificate_level):
    552     from collections import defaultdict
    553     train_skills = defaultdict(int)
    554     skills = sm.GetService('certificates').GetCertificate(certificate_id).SkillsByTypeAndLevel(certificate_level)
    555     for skill_type_id, required_level in skills:
    556         if sm.GetService('skills').MySkillLevel(skill_type_id) < required_level:
    557             train_skills[skill_type_id] = max(train_skills[skill_type_id], required_level)
    558 
    559     _qa_give_skills(train_skills)
    560 
    561 
    562 def _qa_give_skills(skills):
    563     cntFrom = 1
    564     cntTo = len(skills) + 1
    565     sm.GetService('loading').ProgressWnd('GM Skill Gift', '', cntFrom, cntTo)
    566     for typeID, level in skills.iteritems():
    567         cntFrom = cntFrom + 1
    568         sm.GetService('loading').ProgressWnd('GM Skill Gift', 'Training of the skill %s to level %d has been completed' % (evetypes.GetName(typeID), level), cntFrom, cntTo)
    569         sm.RemoteSvc('slash').SlashCmd('/giveskill me %s %s' % (typeID, level))
    570 
    571     sm.GetService('loading').ProgressWnd('Done', '', cntTo, cntTo)
    572     sm.GetService('skills').ForceRefresh()