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

securityOfficeWindow.py (18056B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\securityOfficeWindow.py
      2 import math
      3 from carbonui.primitives.frame import Frame
      4 from collections import defaultdict
      5 import localization
      6 import uthread
      7 from carbon.common.script.util.timerstuff import AutoTimer
      8 from carbonui import TextAlign, TextColor, uiconst
      9 from carbonui.primitives.container import Container
     10 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     11 from carbonui.primitives.fill import Fill
     12 from carbonui.primitives.line import Line
     13 from carbonui.primitives.sprite import Sprite
     14 from carbonui.uicore import uicore
     15 from carbonui.util.color import Color
     16 from crimewatch.const import securityLevelsPerTagType
     17 from crimewatch.util import CalculateTagRequirementsForSecIncrease
     18 from eve.client.script.ui.control import eveIcon, eveLabel
     19 from carbonui.control.button import Button
     20 from carbonui.control.window import Window
     21 from eve.client.script.ui.control.themeColored import SpriteThemeColored
     22 from eve.client.script.ui.station.securityOfficeConst import BAR_HEIGHT, BAR_PADDING, BAR_WIDTH, BOX_WIDTH, DRAGBAR_COLOR_NOTAVAILABLE, SEC_BAND_DATA, SEC_METER_HEIGHT, SLIDER_COLOR_AVAILABLE, SLIDER_COLOR_AVAILABLE_ALT, SLIDER_COLOR_CURRENT, SLIDER_COLOR_NOTAVAILABLE, SLIDER_COLOR_NOTAVAILABLE_ALT, SLIDER_COLOR_WANTED, SLIDER_COLOR_WANTED_ALT, TAG_BUCKETS, WINDOW_HEIGHT, WINDOW_WIDTH
     23 from eve.common.lib import appConst as const
     24 from eve.common.script.net import eveMoniker
     25 from eveservices.menu import GetMenuService
     26 
     27 def GetBucketAndRatioForSec(secStatus):
     28     for i, data in enumerate(TAG_BUCKETS):
     29         if data.minSec <= secStatus < data.maxSec:
     30             leftover = secStatus - data.minSec
     31             ratio = leftover / (data.maxSec - data.minSec)
     32             return (i, leftover, ratio)
     33 
     34     return (len(TAG_BUCKETS) - 1, secStatus - TAG_BUCKETS[-1].minSec, 1.0)
     35 
     36 
     37 class SecurityOfficeWindow(Window):
     38     __notifyevents__ = ['OnSecurityForTagSelectionChanged',
     39      'OnSecurityStatusUpdate',
     40      'OnItemChange',
     41      'OnAccountChange']
     42     default_windowID = 'securityoffice'
     43     default_fixedHeight = WINDOW_HEIGHT
     44     default_fixedWidth = WINDOW_WIDTH
     45     default_captionLabelPath = 'UI/SecurityOffice/StationServiceName'
     46     default_iconNum = 'res:/UI/Texture/WindowIcons/concord.png'
     47     default_scope = uiconst.SCOPE_STATION
     48     default_isStackable = False
     49 
     50     def ApplyAttributes(self, attributes):
     51         super(SecurityOfficeWindow, self).ApplyAttributes(attributes)
     52         self.crimewatchSvc = sm.GetService('crimewatchSvc')
     53         self.godmaSvc = sm.GetService('godma')
     54         self.walletSvc = sm.GetService('wallet')
     55         self.topParent = ContainerAutoSize(name='topParent', parent=self.GetMainArea(), align=uiconst.TOTOP, clipChildren=True, padding=(0, 10, 0, 10))
     56         self.currentSecurityStatus = 0
     57         self.targetSecurityStatus = 0
     58         self.ConstructLayout()
     59 
     60     def ConstructTopCont(self):
     61         eveLabel.EveCaptionMedium(name='caption', parent=self.topParent, text=localization.GetByLabel('UI/SecurityOffice/HeaderCaption'), align=uiconst.TOTOP, textAlign=TextAlign.CENTER)
     62         eveLabel.EveLabelMedium(name='subcaption', parent=self.topParent, text=localization.GetByLabel('UI/SecurityOffice/WindowSubheaderDescription'), align=uiconst.TOTOP, textAlign=TextAlign.CENTER, color=TextColor.SECONDARY)
     63 
     64     def ConstructLayout(self):
     65         self.ConstructTopCont()
     66         self.securityTagBar = SecurityTagBar(parent=self.sr.main)
     67         bottomContainer = Container(name='bottomContainer', parent=self.sr.main, align=uiconst.TOBOTTOM, height=40)
     68         self.iskCostText = eveLabel.EveLabelMediumBold(parent=bottomContainer, align=uiconst.CENTERLEFT, left=8)
     69         self.submitButton = Button(parent=bottomContainer, align=uiconst.CENTERRIGHT, left=8, label=localization.GetByLabel('UI/SecurityOffice/ExchangeTags'), func=self.Submit)
     70         self.CreateTextFeedback()
     71 
     72     def CreateTextFeedback(self):
     73         self.pveText = eveLabel.EveLabelMedium(parent=self.sr.main, name='goodEffectText', align=uiconst.CENTERBOTTOM, top=66)
     74         self.pvpText = eveLabel.EveLabelMedium(parent=self.sr.main, name='badEffectText', align=uiconst.CENTERBOTTOM, top=48)
     75 
     76     def OnSecurityForTagSelectionChanged(self, targetSecurityStatus, tagsToSpend, sufficientTags):
     77         self.targetSecurityStatus = targetSecurityStatus
     78         self.currentSecurityStatus = self.crimewatchSvc.GetMySecurityStatus()
     79         noSelection = targetSecurityStatus == self.currentSecurityStatus
     80         if noSelection:
     81             self.submitButton.Disable()
     82         else:
     83             self.submitButton.Enable()
     84         iskTotal = 0
     85         for typeID, quantity in tagsToSpend.iteritems():
     86             iskTotal += self.godmaSvc.GetTypeAttribute(typeID, const.attributeSecurityProcessingFee, 0) * quantity
     87 
     88         myBalance = self.walletSvc.GetWealth()
     89         text = localization.GetByLabel('UI/SecurityOffice/AdditionalCost', cost=iskTotal)
     90         if myBalance < iskTotal:
     91             text = '<font color=%s>%s</font>' % (SEC_BAND_DATA[3].color.GetHex(), text)
     92             self.submitButton.Disable()
     93         elif not noSelection:
     94             self.submitButton.Enable()
     95         if not sufficientTags:
     96             self.submitButton.Disable()
     97         self.iskCostText.SetText(text)
     98         for data in SEC_BAND_DATA:
     99             if data.minSec <= targetSecurityStatus < data.maxSec:
    100                 self.pvpText.SetText(localization.GetByLabel(data.pvpHintLabel))
    101                 self.pveText.SetText(localization.GetByLabel(data.pveHintLable))
    102                 break
    103         else:
    104             data = SEC_BAND_DATA[-1]
    105             self.pvpText.SetText(localization.GetByLabel(data.pvpHintLabel))
    106             self.pveText.SetText(localization.GetByLabel(data.pveHintLable))
    107 
    108     def Submit(self, button):
    109         try:
    110             eveMoniker.CharGetCrimewatchLocation().ApplyTagsForSecStatus(self.targetSecurityStatus, self.currentSecurityStatus)
    111         finally:
    112             self.UpdateSecurityTagBar()
    113 
    114     def OnItemChange(self, item, change, location):
    115         if item.typeID in securityLevelsPerTagType:
    116             if item.locationID == session.stationid or change.get(const.ixLocationID) == session.stationid:
    117                 self.UpdateSecurityTagBar()
    118 
    119     def UpdateSecurityTagBar(self):
    120         self.updateTimer = AutoTimer(100, self._UpdateSecurityTagBar)
    121 
    122     def _UpdateSecurityTagBar(self):
    123         self.updateTimer = None
    124         self.securityTagBar.UpdateCurrentSecAndTags(self.targetSecurityStatus)
    125 
    126     def OnSecurityStatusUpdate(self, newSecurityStatus):
    127         self.UpdateSecurityTagBar()
    128 
    129     def OnAccountChange(self, accountKey, ownerID, balance):
    130         if accountKey == 'cash' and ownerID == session.charid:
    131             self.UpdateSecurityTagBar()
    132 
    133 
    134 class SecurityTagBar(Container):
    135     default_height = 120
    136     default_width = BAR_WIDTH
    137     default_align = uiconst.TOTOP
    138     default_state = uiconst.UI_PICKCHILDREN
    139     default_padLeft = 0
    140     default_padRight = 0
    141 
    142     def ApplyAttributes(self, attributes):
    143         Container.ApplyAttributes(self, attributes)
    144         self.crimewatchSvc = sm.GetService('crimewatchSvc')
    145         self.securityOfficeSvc = sm.GetService('securityOfficeSvc')
    146         self.isDragging = False
    147         self.CreateDragBar()
    148         self.CreateBar()
    149         self.CreateSlider()
    150         uthread.new(self.SetCurrentSecStatus, self.crimewatchSvc.GetMySecurityStatus())
    151 
    152     def GetSecAtMouseOffset(self, mouseOffset):
    153         bucketIndex = int(mouseOffset) / BOX_WIDTH
    154         if bucketIndex >= len(TAG_BUCKETS):
    155             return 10.0
    156         elif bucketIndex < 0:
    157             return -10.0
    158         else:
    159             leftover = mouseOffset % BOX_WIDTH
    160             ratio = leftover / float(BOX_WIDTH)
    161             data = TAG_BUCKETS[bucketIndex]
    162             return data.minSec + ratio * (data.maxSec - data.minSec)
    163 
    164     def SetCurrentSecStatus(self, currentSecurityStatus, mouseOffset = 0):
    165         self.currentSecStatus = currentSecurityStatus
    166         bucketIndex, leftover, ratio = GetBucketAndRatioForSec(currentSecurityStatus)
    167         offset = bucketIndex * BOX_WIDTH + ratio * BOX_WIDTH
    168         for fill in self.sliderContainer.children[1:]:
    169             fill.width = 0
    170 
    171         self.sliderContainer.children[0].width = offset
    172         self.locator.left = offset + BAR_PADDING - self.locator.width / 2
    173         targetSecurityStatus = self.GetSecAtMouseOffset(mouseOffset)
    174         tags = self.securityOfficeSvc.GetTagsInHangar()
    175         tagsToSpend = defaultdict(int)
    176         altCount = 0
    177         secTarget = currentSecurityStatus
    178         tempOffset = offset
    179         targetOffset = offset
    180         targetSliceSec = currentSecurityStatus
    181         sufficientTags = True
    182         if bucketIndex < 4:
    183             allTagsNeeded = CalculateTagRequirementsForSecIncrease(currentSecurityStatus, TAG_BUCKETS[-1].minSec)
    184             for i in xrange(bucketIndex, 4):
    185                 data = TAG_BUCKETS[i]
    186                 numTagsNeeded = allTagsNeeded.get(data.typeID, 0)
    187                 numTagsOwned = min(tags.get(data.typeID, 0), numTagsNeeded)
    188                 for n in xrange(numTagsNeeded):
    189                     secTarget += const.securityGainPerTag
    190                     _bucketIndex, _leftover, _ratio = GetBucketAndRatioForSec(secTarget)
    191                     newOffset = _bucketIndex * BOX_WIDTH + _ratio * BOX_WIDTH
    192                     sliceWidth = newOffset - tempOffset
    193                     altColor = altCount % 2 == 1
    194                     sliceIsWanted = targetSecurityStatus > secTarget
    195                     tagIsAvailable = n < numTagsOwned
    196                     if sliceIsWanted:
    197                         if tagIsAvailable:
    198                             color = SLIDER_COLOR_WANTED if altColor else SLIDER_COLOR_WANTED_ALT
    199                         else:
    200                             color = SLIDER_COLOR_NOTAVAILABLE if altColor else SLIDER_COLOR_NOTAVAILABLE_ALT
    201                             sufficientTags = False
    202                         tagsToSpend[data.typeID] += 1
    203                         targetSliceSec = secTarget
    204                         targetOffset = newOffset
    205                     elif tagIsAvailable:
    206                         color = SLIDER_COLOR_AVAILABLE if altColor else SLIDER_COLOR_AVAILABLE_ALT
    207                     else:
    208                         color = None
    209                     fill = self.sliderContainer.children[1 + altCount]
    210                     if color is None:
    211                         fill.color.SetAlpha(0)
    212                     else:
    213                         fill.SetRGBA(*color)
    214                         self.SetDragBarColor(color)
    215                     fill.width = sliceWidth
    216                     tempOffset = newOffset
    217                     altCount += 1
    218 
    219         if sufficientTags:
    220             self.SetDragBarColor(None)
    221         else:
    222             self.SetDragBarColor(DRAGBAR_COLOR_NOTAVAILABLE)
    223         self.locator.left = targetOffset + BAR_PADDING - self.locator.width / 2
    224         self.sliderSecText.SetText('%2.1f' % targetSliceSec)
    225         if targetOffset == 0:
    226             self.sliderSecText.SetAlign(uiconst.BOTTOMLEFT)
    227         elif targetOffset == BAR_WIDTH:
    228             self.sliderSecText.SetAlign(uiconst.BOTTOMRIGHT)
    229         else:
    230             self.sliderSecText.SetAlign(uiconst.CENTERBOTTOM)
    231         for i, data in enumerate(TAG_BUCKETS):
    232             if data.typeID is not None:
    233                 quantity = tagsToSpend[data.typeID]
    234                 self.buckets[i].SetQuantity(quantity)
    235 
    236         sm.ScatterEvent('OnSecurityForTagSelectionChanged', targetSliceSec, tagsToSpend, sufficientTags)
    237 
    238     def CreateBar(self):
    239         self.barContainer = Container(name='barContainer', parent=self, align=uiconst.TOTOP, height=BAR_HEIGHT, padTop=20, padLeft=BAR_PADDING, padRight=BAR_PADDING)
    240         Frame(parent=self.barContainer, color=(0.5, 0.5, 0.5, 0.5), offset=1)
    241         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPLEFT, text='-10', padTop=3, left=1, color=(1, 1, 1, 1))
    242         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-8', padTop=3, left=4 * BOX_WIDTH - 3, color=(1, 1, 1, 1))
    243         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-5', padTop=3, left=3 * BOX_WIDTH - 3, color=(1, 1, 1, 1))
    244         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-2', padTop=3, left=2 * BOX_WIDTH - 3, color=(1, 1, 1, 1))
    245         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='0', padTop=3, left=BOX_WIDTH - 3, color=(1, 1, 1, 1))
    246         eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='10', padTop=3, left=1, color=(1, 1, 1, 1))
    247         bucketContainer = Container(name='bucketContainer', parent=self.barContainer, align=uiconst.TOPLEFT, height=BAR_HEIGHT, width=BAR_WIDTH)
    248         self.buckets = []
    249         for data in TAG_BUCKETS:
    250             if data.typeID is None:
    251                 bucket = LastBucket(parent=bucketContainer)
    252             else:
    253                 bucket = BucketOfTags(parent=bucketContainer, name='bucket_%s' % data.typeID, typeID=data.typeID, minSec=data.minSec, maxSec=data.maxSec)
    254             self.buckets.append(bucket)
    255 
    256         self.sliderContainer = Container(name='sliderContainer', parent=self.barContainer, align=uiconst.TOALL)
    257 
    258     def CreateDragBar(self):
    259         self.locator = Container(name='locator', parent=self, align=uiconst.TOPLEFT, left=0, width=8, height=self.height, state=uiconst.UI_NORMAL, padLeft=0, cursor=uiconst.UICURSOR_LEFT_RIGHT_DRAG)
    260         self.locator.OnMouseDown = (self.OnSliderMouseDown, self.locator)
    261         self.locator.OnMouseMove = (self.OnSliderMouseMove, self.locator)
    262         Fill(parent=self.locator, color=(1, 1, 1, 1), height=82, width=2, align=uiconst.CENTER)
    263         Sprite(name='topTriangle', parent=self.locator, texturePath='res:/ui/texture/icons/105_32_15.png', align=uiconst.CENTER, rotation=math.pi / 2, width=32, height=32, top=-43, state=uiconst.UI_DISABLED)
    264         Sprite(name='bottomTriangle', parent=self.locator, texturePath='res:/ui/texture/icons/105_32_15.png', align=uiconst.CENTER, rotation=-math.pi / 2, width=32, height=32, top=43, state=uiconst.UI_DISABLED)
    265         self.sliderSecText = eveLabel.EveLabelLargeBold(parent=self.locator, name='secStatus', align=uiconst.CENTERBOTTOM, top=-4)
    266 
    267     def SetDragBarColor(self, color = None):
    268         if color is None:
    269             color = Color.WHITE
    270         self.locator.children[0].SetRGBA(*color)
    271         self.locator.children[1].SetRGBA(*color)
    272         self.locator.children[2].SetRGBA(*color)
    273 
    274     def CreateSlider(self):
    275         for x in xrange(21):
    276             Fill(parent=self.sliderContainer, align=uiconst.TOLEFT, width=0, display=True)
    277 
    278         self.sliderContainer.children[0].SetRGBA(*SLIDER_COLOR_CURRENT)
    279 
    280     def OnSliderMouseDown(self, *args):
    281         self.isDragging = True
    282 
    283     def OnSliderMouseMove(self, *args):
    284         if not (self.isDragging and uicore.uilib.leftbtn):
    285             self.isDragging = False
    286             return
    287         x, y = self.barContainer.GetAbsolutePosition()
    288         offset = uicore.uilib.x - x
    289         self.SetCurrentSecStatus(self.crimewatchSvc.GetMySecurityStatus(), offset)
    290 
    291     def UpdateCurrentSecAndTags(self, targetSecurityStatus):
    292         bucketIndex, leftover, ratio = GetBucketAndRatioForSec(targetSecurityStatus)
    293         offset = bucketIndex * BOX_WIDTH + ratio * BOX_WIDTH
    294         currentSecurityStatus = self.crimewatchSvc.GetMySecurityStatus()
    295         if targetSecurityStatus != currentSecurityStatus:
    296             offset += 1
    297         self.SetCurrentSecStatus(currentSecurityStatus, offset)
    298 
    299 
    300 class BucketOfTags(Container):
    301     default_width = BOX_WIDTH
    302     default_align = uiconst.TOLEFT
    303     default_state = uiconst.UI_PICKCHILDREN
    304 
    305     def ApplyAttributes(self, attributes):
    306         Container.ApplyAttributes(self, attributes)
    307         self.minSec = attributes.minSec
    308         self.maxSec = attributes.maxSec
    309         self.secRange = self.maxSec - self.minSec
    310         self.typeID = attributes.typeID
    311         self.numSecSections = int(self.secRange / 0.5)
    312         sectionWidth = self.width / self.numSecSections
    313         Line(parent=self, align=uiconst.TORIGHT, color=(0, 0, 0, 0.5))
    314         icon = eveIcon.Icon(parent=self, typeID=self.typeID, size=48, align=uiconst.CENTER, ignoreSize=True, OnClick=self.OnIconClick, state=uiconst.UI_NORMAL)
    315         icon.GetMenu = lambda : GetMenuService().GetMenuFromItemIDTypeID(None, self.typeID, includeMarketDetails=True)
    316         secMeter = Container(parent=self, align=uiconst.TOTOP, height=SEC_METER_HEIGHT)
    317         for n in xrange(self.numSecSections):
    318             sec = self.minSec + n * const.securityGainPerTag
    319             for data in SEC_BAND_DATA:
    320                 if sec < data.maxSec:
    321                     break
    322 
    323             if data.altColor is not None and n % 2 == 1:
    324                 color = data.altColor
    325             else:
    326                 color = data.color
    327             Fill(parent=secMeter, align=uiconst.TOLEFT, width=sectionWidth, color=color.GetRGBA(), hint=localization.GetByLabel(data.pveHintLable) + '<br>' + localization.GetByLabel(data.pvpHintLabel), state=uiconst.UI_NORMAL)
    328 
    329         self.quantitySpentText = eveLabel.EveLabelSmallBold(parent=self, align=uiconst.CENTER, top=30, color=(1, 1, 1, 1))
    330         self.SetQuantity(0)
    331 
    332     def SetQuantity(self, quantity):
    333         self.quantitySpentText.SetText(str(quantity))
    334 
    335     def OnIconClick(self):
    336         sm.GetService('info').ShowInfo(self.typeID)
    337 
    338 
    339 class LastBucket(Container):
    340     default_width = BOX_WIDTH + 2
    341     default_align = uiconst.TOLEFT
    342     default_state = uiconst.UI_NORMAL
    343 
    344     def ApplyAttributes(self, attributes):
    345         Container.ApplyAttributes(self, attributes)
    346         data = SEC_BAND_DATA[-1]
    347         Fill(parent=self, align=uiconst.TOTOP, height=SEC_METER_HEIGHT, color=data.color.GetRGBA(), hint=localization.GetByLabel(data.pveHintLable) + '<br>' + localization.GetByLabel(data.pvpHintLabel), state=uiconst.UI_NORMAL)