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

applySkillPointsWindow.py (16591B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\skilltrading\applySkillPointsWindow.py
      2 import telemetry
      3 import evetypes
      4 import localization
      5 import uthread2
      6 from carbon.client.script.environment.AudioUtil import PlaySound
      7 from carbon.common.script.util.format import IntToRoman
      8 from carbon.common.script.util.timerstuff import AutoTimer
      9 from carbonui import uiconst, fontconst
     10 from carbonui.control.scrollContainer import ScrollContainer
     11 from carbonui.control.scrollentries import SE_BaseClassCore
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     14 from carbonui.primitives.frame import Frame
     15 from carbonui.primitives.sprite import Sprite
     16 from carbonui.uianimations import animations
     17 from carbonui.util.color import Color
     18 from characterskills import GetSPForLevelRaw
     19 from characterskills.util import GetLevelProgress
     20 from carbonui.button.group import ButtonGroup
     21 from eve.client.script.ui.control.eveLabel import Label, EveLabelMedium
     22 from carbonui.control.window import Window
     23 from eve.client.script.ui.control.gauge import Gauge
     24 from skills.skillConst import ICON_BY_GROUPID
     25 from eve.client.script.ui.shared.neocom.skillConst import COLOR_UNALLOCATED_1
     26 from gametime import GetWallclockTime
     27 
     28 class ApplySkillPointsWindow(Window):
     29     default_windowID = 'ApplySkillPointsWindow'
     30     default_captionLabelPath = 'UI/SkillTrading/ApplySkillPointsWindowCaption'
     31     default_iconNum = 'res:/UI/Texture/WindowIcons/augmentations.png'
     32     default_width = 600
     33     default_height = 350
     34     default_fixedWidth = 600
     35     default_minSize = (600, 200)
     36     default_clipChildren = True
     37     default_isCollapseable = False
     38     default_isLightBackgroundConfigurable = False
     39     default_isStackable = False
     40     default_isLockable = False
     41     default_isOverlayable = False
     42     default_isMinimizable = False
     43     __notifyevents__ = ['OnClientEvent_SkillAddedToQueue',
     44      'OnClientEvent_SkillPrioritized',
     45      'OnClientEvent_SkillsRemovedFromQueue',
     46      'OnFreeSkillPointsChanged_Local',
     47      'OnSkillsChanged']
     48 
     49     def ApplyAttributes(self, attributes):
     50         super(ApplySkillPointsWindow, self).ApplyAttributes(attributes)
     51         self.skillTypeIDsAndLevels = attributes.get('skillTypeIDsAndLevels', None)
     52         self.mainArea = self.GetMainArea()
     53         self.skillQueueSvc = sm.GetService('skillqueue')
     54         self.skillSvc = sm.GetService('skills')
     55         self.skillEntriesByTypeIDAndLevel = {}
     56         self.isSaving = False
     57         self.isApplying = False
     58         self.isFinished = False
     59         self.skillPointsToBeUsed = 0
     60         self.SaveChanges(activate=self.IsTraining())
     61         self.ConstructLayout()
     62         self.PopulateScroll()
     63         self.SetDescriptionLabel()
     64 
     65     def CloseByUser(self, *args):
     66         if not self.skillQueueSvc.IsTransactionOpen():
     67             self.skillQueueSvc.BeginTransaction()
     68         super(ApplySkillPointsWindow, self).CloseByUser()
     69 
     70     def ConstructLayout(self):
     71         self.HideHeader()
     72         self.ConstructHeader()
     73         self.ConstructFooter()
     74         self.mainContainer = Container(name='MainContainer', parent=self.mainArea, padding=(4, 0, 4, 0))
     75         descriptionCont = Container(name='DescriptionCont', parent=self.mainContainer, align=uiconst.TOTOP, height=50)
     76         self.descriptionLabel = EveLabelMedium(name='Description', parent=descriptionCont, align=uiconst.CENTER)
     77         self.scrollContainer = ScrollContainer(name='SkillEntryScroll', parent=self.mainContainer, align=uiconst.TOALL)
     78 
     79     def ConstructHeader(self):
     80         headerContainer = Container(name='HeaderContainer', parent=self.mainArea, align=uiconst.TOTOP, height=35, bgColor=(0.133, 0.133, 0.141, 0.7), padding=(4, 4, 4, 0))
     81         iconContainer = Container(name='IconContainer', parent=headerContainer, align=uiconst.TOLEFT, width=32, height=32)
     82         Sprite(name='ApplySkillsIcon', parent=iconContainer, align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=26, height=26, left=5, opacity=0.7, texturePath='res:/UI/Texture/classes/skilltrading/applySkillpoints.png')
     83         labelContainer = ContainerAutoSize(name='HeaderLabelContainer', parent=headerContainer, align=uiconst.TOLEFT, left=10)
     84         Label(name='ApplySkillsWindowCaption', parent=labelContainer, align=uiconst.CENTERLEFT, text=localization.GetByLabel('UI/SkillTrading/ApplySkillPointsWindowCaption'))
     85 
     86     def ConstructFooter(self):
     87         footerContainer = Container(name='footerContainer', parent=self.mainArea, align=uiconst.TOBOTTOM, height=35, bgColor=(0.133, 0.133, 0.141, 0.7), padding=(4, 0, 4, 4))
     88         self.buttonGroup = ButtonGroup(name='buttonGroup', parent=footerContainer, align=uiconst.CENTER)
     89         self.buttonGroup.AddButton(localization.GetByLabel('UI/SkillTrading/ConfirmInjectionLabel'), self.ApplySkillPoints, uiName='confirm_skill_injection')
     90         self.buttonGroup.AddButton(localization.GetByLabel('UI/SkillTrading/CancelInjectionLabel'), self.CloseByUser, uiName='cancel_skill_injection')
     91 
     92     def SetDescriptionLabel(self):
     93         self.descriptionLabel.SetText(localization.GetByLabel('UI/SkillTrading/ApplySkillPointsDescription', color=Color.RGBtoHex(*COLOR_UNALLOCATED_1), points=self.skillPointsToBeUsed, amount=len(self.skillEntriesByTypeIDAndLevel)))
     94 
     95     def _GetPointsBySkillTypeID(self):
     96         handler = self.skillSvc.GetSkillHandler()
     97         if self.skillTypeIDsAndLevels is None:
     98             return handler.GetFreeSkillPointsAppliedToQueue()
     99         return handler.GetFreeSkillPointsAppliedToSkills(self.skillTypeIDsAndLevels)
    100 
    101     def _GetIterationSet(self):
    102         if self.skillTypeIDsAndLevels is None:
    103             return [ (s.trainingTypeID, s.trainingToLevel) for s in self.skillQueueSvc.GetQueue() ]
    104         return self.skillTypeIDsAndLevels
    105 
    106     def PopulateScroll(self):
    107         pointsBySkillTypeID = self._GetPointsBySkillTypeID()
    108         if not pointsBySkillTypeID:
    109             self.buttonGroup.buttons[0].Disable()
    110         else:
    111             self.buttonGroup.buttons[0].Enable()
    112         levelAndProgressBySkillTypeID = self.skillQueueSvc.GetSkillLevelAndProgressWithFreePoints(pointsBySkillTypeID)
    113         self.skillPointsToBeUsed = sum(pointsBySkillTypeID.itervalues())
    114         queue = self.skillQueueSvc.GetQueue()
    115         for skillID, skillLevel in self._GetIterationSet():
    116             levelReachedWithFreePoints, progressWithFreePoints = levelAndProgressBySkillTypeID[skillID] if skillID in levelAndProgressBySkillTypeID else (0, 0)
    117             if (skillID, skillLevel) in self.skillEntriesByTypeIDAndLevel:
    118                 continue
    119             entry = ApplySkillPointsListEntry(parent=self.scrollContainer, align=uiconst.TOTOP, skillTypeID=skillID, progressWithFreePoints=progressWithFreePoints, levelReachedWithFreePoints=levelReachedWithFreePoints, trainingToLevel=skillLevel)
    120             self.skillEntriesByTypeIDAndLevel[skillID, skillLevel] = entry
    121 
    122     @telemetry.ZONE_METHOD
    123     def ApplySkillPoints(self, *args):
    124         if self.isApplying:
    125             return
    126         self.isApplying = True
    127         try:
    128             self.AnimateBars()
    129             isTraining = self.IsTraining()
    130             self.SaveChanges(activate=isTraining)
    131             if self.skillTypeIDsAndLevels is None:
    132                 self.skillQueueSvc.ApplyFreeSkillPointsToQueue()
    133             else:
    134                 self.skillQueueSvc.ApplyFreeSkillPointsToSkills(self.skillTypeIDsAndLevels)
    135             self.skillQueueSvc.BeginTransaction()
    136             PlaySound('st_allocate_skillpoints_play')
    137         finally:
    138             self.isApplying = False
    139             self.isFinished = True
    140             animations.FadeOut(self.buttonGroup, callback=self.FlushButtonsAndCreateCloseButton)
    141 
    142     def FlushButtonsAndCreateCloseButton(self):
    143         self.buttonGroup.FlushButtons()
    144         self.buttonGroup.AddButton(localization.GetByLabel('UI/SkillTrading/CloseInjectionLabel'), self.CloseByUser, uiName='close_skill_injection')
    145         animations.FadeIn(self.buttonGroup)
    146 
    147     def IsTraining(self):
    148         return self.skillQueueSvc.SkillInTraining() is not None
    149 
    150     def AnimateBars(self):
    151         for entry in self.skillEntriesByTypeIDAndLevel.values():
    152             entry.OnSkillPointsApplied()
    153 
    154     def Reconstruct(self):
    155         if self.isApplying:
    156             return
    157         if self.isFinished:
    158             return
    159         self.skillEntriesByTypeIDAndLevel.clear()
    160         self.scrollContainer.Flush()
    161         self.PopulateScroll()
    162         self.SetDescriptionLabel()
    163 
    164     def OnClientEvent_SkillAddedToQueue(self, skillTypeID, skillLevel):
    165         self.CloseByUser()
    166 
    167     def OnClientEvent_SkillsRemovedFromQueue(self, skillRequirements):
    168         self.CloseByUser()
    169 
    170     def OnClientEvent_SkillPrioritized(self, skillTypeID):
    171         self.CloseByUser()
    172 
    173     def OnFreeSkillPointsChanged_Local(self):
    174         if self.isApplying:
    175             return
    176         self.Reconstruct()
    177 
    178     def OnSkillsChanged(self, skillInfo):
    179         self.Reconstruct()
    180 
    181     def SaveChanges(self, activate = True):
    182         if self.isSaving:
    183             return
    184         self.isSaving = True
    185         try:
    186             self.skillQueueSvc.CommitTransaction(activate=activate)
    187         finally:
    188             self.isSaving = False
    189 
    190 
    191 class ApplySkillPointsListEntry(SE_BaseClassCore):
    192     default_name = 'ApplySkillPointsListEntry'
    193     __guid__ = 'listentry.ApplySkillPointsListEntry'
    194     default_height = 55
    195     default_padTop = 10
    196     default_padLeft = 5
    197     default_padRight = 5
    198     default_complete_color = (0.239, 0.647, 0.278, 0.7)
    199     default_skillbook_green_color = (0.239, 0.647, 0.278, 1.0)
    200 
    201     def ApplyAttributes(self, attributes):
    202         super(ApplySkillPointsListEntry, self).ApplyAttributes(attributes)
    203         self.skillTypeID = attributes.skillTypeID
    204         self.levelReachedWithFreePoints = attributes.levelReachedWithFreePoints
    205         self.trainingToLevel = attributes.trainingToLevel
    206         self.progressWithFreePoints = attributes.progressWithFreePoints
    207         self.applyingSkillPoints = False
    208         self.skillSvc = sm.GetService('skills')
    209         self.skillQueueSvc = sm.GetService('skillqueue')
    210         self._progress = self.GetProgress()
    211         self.AdjustProgressWithFreePoints()
    212         self.ConstructLayout()
    213         self.SetSkillName()
    214         self.SetSkillGroupIcon()
    215         self.SetGaugesToCurrentProgress()
    216         self.Update()
    217         self.timeSavedUpdateThread = AutoTimer(method=self.Update, interval=1000)
    218 
    219     def AdjustProgressWithFreePoints(self):
    220         if self.levelReachedWithFreePoints >= self.trainingToLevel:
    221             self.progressWithFreePoints = 1.0
    222         elif self.levelReachedWithFreePoints + 1 < self.trainingToLevel:
    223             self.progressWithFreePoints = 0.0
    224 
    225     def ConstructLayout(self):
    226         iconCont = ContainerAutoSize(name='iconCont', parent=self, align=uiconst.TOLEFT)
    227         self.skillGroupIcon = Sprite(name='SkillGroupIcon', parent=iconCont, align=uiconst.CENTERTOP, width=32, height=32)
    228         skillBookIconCont = ContainerAutoSize(name='skillBookIconCont', parent=self, align=uiconst.TORIGHT)
    229         self.skillBookIcon = Sprite(parent=skillBookIconCont, align=uiconst.CENTERTOP, width=32, height=32, texturePath='res:/UI/Texture/Classes/Skills/doNotHave.png')
    230         middleCont = Container(name='MiddleContainer', parent=self, align=uiconst.TOALL, pos=(10, 0, 5, 0))
    231         gaugeCont = Container(name='GaugeContainer', parent=middleCont, align=uiconst.TOTOP, height=32)
    232         Frame(parent=gaugeCont, texturePath='res:/UI/Texture/classes/skilltrading/frame.png', cornerSize=3, opacity=0.5)
    233         self.skillName = Label(name='SkillName', parent=gaugeCont, align=uiconst.CENTER)
    234         self.alreadyTrainedGauge = Gauge(name='alreadyTrainedGauge', parent=gaugeCont, align=uiconst.TOTOP_NOPUSH, state=uiconst.UI_DISABLED, height=30, gaugeHeight=30, top=1, color=COLOR_UNALLOCATED_1, opacity=0.7, backgroundColor=(1.0, 1.0, 0.0, 0.0))
    235         self.aboutToBeTrainedGauge = Gauge(name='aboutToBeTrainedGauge', parent=gaugeCont, align=uiconst.TOTOP_NOPUSH, state=uiconst.UI_DISABLED, height=30, gaugeHeight=30, top=1, color=(0.21, 0.62, 0.74, 0.4), backgroundColor=(1.0, 1.0, 0.0, 0.0))
    236         timeSavedContainer = Container(name='timeSavedContainer', parent=middleCont, align=uiconst.TOALL, top=3)
    237         Frame(parent=timeSavedContainer, texturePath='res:/UI/Texture/classes/skilltrading/frame.png', cornerSize=3, opacity=0.5)
    238         self.timeSavedLabel = Label(name='timeSavedLabel', parent=timeSavedContainer, align=uiconst.CENTER, fontsize=fontconst.EVE_SMALL_FONTSIZE, opacity=0.7)
    239         self.percentageTrainedLabel = Label(name='percentageTrainedLabel', parent=timeSavedContainer, align=uiconst.CENTERRIGHT, fontsize=fontconst.EVE_SMALL_FONTSIZE, left=5)
    240 
    241     @property
    242     def progress(self):
    243         if self.applyingSkillPoints:
    244             return self._progress
    245         else:
    246             return self.GetProgress()
    247 
    248     @progress.setter
    249     def progress(self, value):
    250         self._progress = value
    251         self.UpdateProgressLabel()
    252 
    253     def Close(self):
    254         self.timeSavedUpdateThread = None
    255         super(ApplySkillPointsListEntry, self).Close()
    256 
    257     def Update(self):
    258         self.UpdateLabels()
    259         self.UpdateAlreadyTrainedGauge()
    260         self.UpdateAboutToBeTrainedGauge()
    261 
    262     def SetSkillGroupIcon(self):
    263         self.skillGroupIcon.SetTexturePath(ICON_BY_GROUPID.get(evetypes.GetGroupID(self.skillTypeID)))
    264 
    265     def SetSkillName(self):
    266         self.skillName.SetText('%s %s' % (evetypes.GetName(self.skillTypeID), IntToRoman(self.trainingToLevel)))
    267 
    268     def UpdateAboutToBeTrainedGauge(self):
    269         self.aboutToBeTrainedGauge.SetValue(self.progressWithFreePoints, animate=False)
    270 
    271     def UpdateAlreadyTrainedGauge(self):
    272         self.alreadyTrainedGauge.SetValue(self.progress, animate=False)
    273 
    274     def SetGaugesToCurrentProgress(self):
    275         self.alreadyTrainedGauge.SetValue(self.progress, animate=False)
    276         self.aboutToBeTrainedGauge.SetValue(self.progress, animate=False)
    277 
    278     def GetProgress(self):
    279         progress = 0
    280         currentSkillLevel = self.skillSvc.MySkillLevel(self.skillTypeID)
    281         if currentSkillLevel == self.trainingToLevel - 1 and self.skillQueueSvc.FindInQueue(self.skillTypeID, self.trainingToLevel) == 0:
    282             currentPoints = self.skillQueueSvc.GetEstimatedSkillPointsTrained(self.skillTypeID)
    283             rank = self.skillSvc.GetSkillRank(self.skillTypeID)
    284             progress = GetLevelProgress(currentPoints, rank)
    285         return progress
    286 
    287     def OnSkillPointsApplied(self):
    288         self.applyingSkillPoints = True
    289         self.timeSavedUpdateThread = None
    290         self.AlignGauges()
    291         animations.MorphScalar(self, 'progress', startVal=self.progress, endVal=self.progressWithFreePoints, callback=lambda : setattr(self, 'progress', self.progressWithFreePoints))
    292 
    293     def AlignGauges(self):
    294         self.alreadyTrainedGauge.SetValueTimed(value=self.aboutToBeTrainedGauge.value, duration=0.6, callback=self.OnGaugeProgressSet)
    295 
    296     def OnGaugeProgressSet(self):
    297         if self.progressWithFreePoints == 1.0:
    298             self.alreadyTrainedGauge.SetColor(self.default_complete_color, animDuration=0.3)
    299             self.skillBookIcon.SetTexturePath('res:/UI/Texture/Classes/Skills/skillTrainingComplete.png')
    300             self.skillBookIcon.SetRGBA(*self.default_skillbook_green_color)
    301             animations.FadeTo(self.alreadyTrainedGauge, startVal=1.0, endVal=1.0, curveType=uiconst.ANIM_OVERSHOT3)
    302 
    303     def GetTimeSaved(self):
    304         skill = self.skillSvc.GetSkill(self.skillTypeID)
    305         trainingTimeCalculator = self.skillSvc.GetSkillTrainingTimeCalculator()
    306         skillPointsPreviousLevel = GetSPForLevelRaw(skill.skillRank, self.trainingToLevel - 1)
    307         _, totalTimeToTrain = trainingTimeCalculator.get_skill_points_and_time_to_train_given_existing_skill_points(self.skillTypeID, self.trainingToLevel, GetWallclockTime(), skillPointsPreviousLevel)
    308         return (self.progressWithFreePoints - self.progress) * totalTimeToTrain
    309 
    310     def UpdateLabels(self):
    311         self.UpdateTimeSavedLabel()
    312         self.UpdateProgressLabel()
    313 
    314     def UpdateTimeSavedLabel(self):
    315         text = localization.GetByLabel('UI/SkillTrading/EstimatedSkillTimeSaved', timeSaved=long(self.GetTimeSaved()))
    316         self.timeSavedLabel.SetText(text)
    317 
    318     def UpdateProgressLabel(self):
    319         text = localization.GetByLabel('UI/SkillTrading/SkillProgressLabel', progress=round(self.progress * 100, 1), progressWithFreePoints=round(self.progressWithFreePoints * 100, 1))
    320         self.percentageTrainedLabel.SetText(text)