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

expeditedTransferUI.py (19500B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\planet\expeditedTransferUI.py
      2 import math
      3 import blue
      4 import carbonui.const as uiconst
      5 import eve.common.script.util.planetCommon as planetCommon
      6 import evetypes
      7 import localization
      8 from carbon.common.script.util import timerstuff
      9 from carbonui.button.const import HEIGHT_NORMAL
     10 from carbonui.primitives.container import Container
     11 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     12 from carbonui.uicore import uicore
     13 from eve.client.script.ui.control import eveLabel, eveScroll
     14 from carbonui.button.group import ButtonGroup
     15 from eve.client.script.ui.control.entries.item import Item
     16 from eve.client.script.ui.control.entries.status_bar import StatusBar
     17 from eve.client.script.ui.control.entries.util import GetFromClass
     18 from carbonui.control.window import Window
     19 from eve.client.script.ui.control.gauge import Gauge
     20 from eve.client.script.ui.shared.planet import planetCommon as planetCommonUI
     21 from eve.client.script.ui.util import uix
     22 from eveexceptions import UserError
     23 from fsdBuiltData.common.planet import get_schematic_name
     24 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     25 
     26 class ExpeditedTransferManagementWindow(Window):
     27     __guid__ = 'form.ExpeditedTransferManagementWindow'
     28     default_windowID = 'createTransfer'
     29     default_iconNum = 'res:/ui/Texture/WindowIcons/items.png'
     30     default_minSize = (500, 400)
     31     default_width = 800
     32     default_height = 500
     33     default_isStackable = False
     34 
     35     def ApplyAttributes(self, attributes):
     36         Window.ApplyAttributes(self, attributes)
     37         self.planet = attributes.planet
     38         self.path = attributes.path
     39         if not self.path or len(self.path) < 2:
     40             raise UserError('CreateRouteTooShort')
     41         colony = self.planet.GetColony(session.charid)
     42         self.sourcePin = colony.GetPin(self.path[0])
     43         self.destinationPin = None
     44         minBandwidth = None
     45         prevID = None
     46         for pinID in self.path:
     47             pin = colony.GetPin(pinID)
     48             if not pin:
     49                 raise UserError('RouteFailedValidationPinDoesNotExist')
     50             if prevID is None:
     51                 prevID = pinID
     52                 continue
     53             link = colony.GetLink(pin.id, prevID)
     54             if link is None:
     55                 raise UserError('RouteFailedValidationLinkDoesNotExist')
     56             if minBandwidth is None or minBandwidth > link.GetTotalBandwidth():
     57                 minBandwidth = link.GetTotalBandwidth()
     58             prevID = pinID
     59 
     60         self.availableBandwidth = minBandwidth
     61         sourceName = planetCommon.GetGenericPinName(self.sourcePin.typeID, self.sourcePin.id)
     62         self.SetCaption(localization.GetByLabel('UI/PI/Common/ExpeditedTransferFrom', sourceName=sourceName))
     63         self.ConstructLayout()
     64         self.SetSourcePinGaugeInfo()
     65         self.scope = uiconst.SCOPE_INGAME
     66         self.ResetPinContents()
     67         self.SetDestination(colony.GetPin(self.path[-1]))
     68         self.OnResizeUpdate()
     69         self.updateTimer = timerstuff.AutoTimer(100, self.SetNextTransferText)
     70 
     71     def ConstructLayout(self):
     72         self.bottomCont = Container(name='bottomCont', parent=self.sr.main, align=uiconst.TOBOTTOM, height=HEIGHT_NORMAL, padding=(0, 8, 0, 0))
     73         self.leftCont = Container(name='leftCont', parent=self.sr.main, align=uiconst.TOLEFT_PROP, width=0.33, clipChildren=True)
     74         self.middleCont = Container(name='middleCont', parent=self.sr.main, align=uiconst.TOLEFT_PROP, width=0.33, padding=(16, 0, 0, 0), clipChildren=True)
     75         self.rightCont = Container(name='rightCont', parent=self.sr.main, align=uiconst.TOALL, padding=(16, 0, 0, 0), clipChildren=True)
     76         colTopHeight = 80
     77         self.sourcePinHeader = Container(name='pinHeader', parent=self.leftCont, align=uiconst.TOTOP, height=colTopHeight)
     78         self.sourcePinList = Container(name='pinList', parent=self.leftCont, align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN)
     79         self.transferHeader = ContainerAutoSize(name='transferHeader', parent=self.middleCont, align=uiconst.TOTOP, height=colTopHeight)
     80         eveLabel.EveHeaderLarge(text=localization.GetByLabel('UI/PI/Common/ToBeTransferred'), parent=self.transferHeader, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
     81         self.volumeText = eveLabel.EveLabelSmall(parent=self.transferHeader, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, padTop=8)
     82         self.timeText = eveLabel.EveLabelSmall(parent=self.transferHeader, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, hint=localization.GetByLabel('UI/PI/Common/ExpeditedTransferProcessingHint'))
     83         self.cooldownTimeText = eveLabel.EveLabelSmall(parent=self.transferHeader, align=uiconst.TOTOP, hint=localization.GetByLabel('UI/PI/Common/CoolDownTimeHint'))
     84         self.transferListScroll = eveScroll.Scroll(parent=self.middleCont, name='transferList')
     85         self.transferListScroll.sr.id = 'transferListScroll'
     86         content = self.transferListScroll.sr.content
     87         content.OnDropData = self.OnTransferScrollDropData
     88         self.destPinHeader = Container(name='destPinHeader', parent=self.rightCont, align=uiconst.TOTOP, height=colTopHeight)
     89         self.destPinList = Container(name='destPinList', parent=self.rightCont, align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN)
     90         self.footerLeft = Container(name='footerLeft', parent=self.bottomCont, align=uiconst.TOLEFT_PROP, width=0.66)
     91         self.footerRight = Container(name='footerRight', parent=self.bottomCont, align=uiconst.TOALL)
     92         btns = [(localization.GetByLabel('UI/PI/Common/ExecuteTransfer'),
     93           self.GoForTransfer,
     94           (),
     95           None)]
     96         ButtonGroup(btns=btns, parent=self.footerRight)
     97         hint = localization.GetByLabel('UI/PI/Common/ExpeditedTransferSplitHint')
     98         btns = [(localization.GetByLabel('UI/PI/Common/Add'),
     99           self.AddBtnClicked,
    100           (),
    101           None,
    102           False,
    103           False,
    104           False,
    105           hint), (localization.GetByLabel('UI/PI/Common/Remove'),
    106           self.RemoveBtnClicked,
    107           (),
    108           None,
    109           False,
    110           False,
    111           False,
    112           hint)]
    113         ButtonGroup(btns=btns, parent=self.footerLeft)
    114         self.OnResizeUpdate()
    115         eveLabel.EveHeaderLarge(text=planetCommon.GetGenericPinName(self.sourcePin.typeID, self.sourcePin.id), parent=self.sourcePinHeader, align=uiconst.TOTOP, maxLines=1, state=uiconst.UI_NORMAL)
    116         self.sourcePinSubGauge = Gauge(parent=self.sourcePinHeader, value=0.0, color=planetCommonUI.PLANET_COLOR_STORAGE, label=localization.GetByLabel('UI/PI/Common/Capacity'), left=0, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, padTop=8)
    117         self.sourcePinListScroll = eveScroll.Scroll(parent=self.sourcePinList, name='pinList')
    118         self.sourcePinListScroll.sr.id = 'sourcePinListScroll'
    119         content = self.sourcePinListScroll.sr.content
    120         content.OnDropData = self.OnSourceScrollDropData
    121         self.destPinText = eveLabel.EveHeaderLarge(text='', parent=self.destPinHeader, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, maxLines=1, padBottom=8)
    122         self.destPinSubText = eveLabel.EveLabelLarge(text='', parent=self.destPinHeader, align=uiconst.TOTOP, top=5, state=uiconst.UI_HIDDEN)
    123         self.destPinSubGauge = Gauge(parent=self.destPinHeader, value=0.0, color=planetCommonUI.PLANET_COLOR_STORAGE, label=localization.GetByLabel('UI/PI/Common/Capacity'), align=uiconst.TOTOP, state=uiconst.UI_HIDDEN, padTop=2)
    124         self.destPinListScroll = eveScroll.Scroll(parent=self.destPinList)
    125         self.destPinListScroll.sr.id = 'destPinListScroll'
    126 
    127     def OnTransferScrollDropData(self, dragObj, nodes, *args):
    128         if nodes[0].scroll.name == 'pinList':
    129             self.AddCommodity(nodes)
    130 
    131     def OnSourceScrollDropData(self, dragObj, nodes, *args):
    132         if nodes[0].scroll.name == 'transferList':
    133             self.RemoveCommodity(nodes)
    134 
    135     def AddBtnClicked(self, *args):
    136         selected = self.sourcePinListScroll.GetSelected()
    137         self.AddCommodity(selected)
    138 
    139     def RemoveBtnClicked(self, *args):
    140         selected = self.transferListScroll.GetSelected()
    141         self.RemoveCommodity(selected)
    142 
    143     def AddCommodity(self, selected):
    144         toMove = {}
    145         if len(selected) == 1 and uicore.uilib.Key(uiconst.VK_SHIFT):
    146             typeID = selected[0].typeID
    147             typeName = planetCommonUI.GetProductNameAndTier(typeID)
    148             ret = uix.QtyPopup(self.pinContents[typeID], 1, 1, None, localization.GetByLabel('UI/PI/Common/QuantityToTransfer', typeName=typeName))
    149             if ret and 'qty' in ret:
    150                 toMove[typeID] = min(self.pinContents[typeID], max(1, ret['qty']))
    151         else:
    152             for entry in selected:
    153                 toMove[entry.typeID] = self.pinContents[entry.typeID]
    154 
    155         if self.destPin.IsConsumer():
    156             toMove = self._ApplyConsumerFilter(toMove)
    157             if not toMove:
    158                 raise UserError('ConsumerCantAcceptCommodities')
    159         elif self.destPin.IsStorage():
    160             toMove = self._ApplyMaxAmountFilter(toMove)
    161         for typeID, qty in toMove.iteritems():
    162             self.pinContents[typeID] -= qty
    163             if self.pinContents[typeID] <= 0:
    164                 del self.pinContents[typeID]
    165             if typeID not in self.transferContents:
    166                 self.transferContents[typeID] = 0
    167             self.transferContents[typeID] += qty
    168 
    169         self.RefreshLists()
    170 
    171     def _ApplyConsumerFilter(self, toMove):
    172         newToMove = {}
    173         for typeID, qty in toMove.iteritems():
    174             remainingSpace = self.destPin.CanAccept(typeID, -1)
    175             alreadyInTransfer = self.transferContents.get(typeID, 0)
    176             if remainingSpace:
    177                 amount = min(remainingSpace - alreadyInTransfer, qty)
    178                 if amount > 0:
    179                     newToMove[typeID] = amount
    180 
    181         return newToMove
    182 
    183     def _ApplyMaxAmountFilter(self, toMove):
    184         availableVolume = self.destPin.GetCapacity() - self.destPin.capacityUsed
    185         availableVolume -= planetCommon.GetCommodityTotalVolume(self.transferContents)
    186         transferVolume = planetCommon.GetCommodityTotalVolume(toMove)
    187         if transferVolume >= availableVolume:
    188             newToMove = {}
    189             if len(toMove) == 1:
    190                 for typeID, quantity in toMove.iteritems():
    191                     commodityVolume = evetypes.GetVolume(typeID)
    192                     maxAmount = int(math.floor(availableVolume / commodityVolume))
    193                     newToMove[typeID] = maxAmount
    194 
    195             prompt_player_fsd_dialog('ExpeditedTransferNotEnoughSpace')
    196             return newToMove
    197         else:
    198             return toMove
    199 
    200     def RemoveCommodity(self, selected):
    201         toMove = {}
    202         if len(selected) == 1 and uicore.uilib.Key(uiconst.VK_SHIFT):
    203             typeID = selected[0].typeID
    204             typeName = planetCommonUI.GetProductNameAndTier(typeID)
    205             ret = uix.QtyPopup(self.transferContents[typeID], 1, 1, None, localization.GetByLabel('UI/PI/Common/QuantityToRemove', typeName=typeName))
    206             if ret and 'qty' in ret:
    207                 toMove[typeID] = min(self.transferContents[typeID], max(1, ret['qty']))
    208         else:
    209             for entry in selected:
    210                 toMove[entry.typeID] = self.transferContents[entry.typeID]
    211 
    212         for typeID, qty in toMove.iteritems():
    213             self.transferContents[typeID] -= qty
    214             if self.transferContents[typeID] <= 0:
    215                 del self.transferContents[typeID]
    216             if typeID not in self.pinContents:
    217                 self.pinContents[typeID] = 0
    218             self.pinContents[typeID] += qty
    219 
    220         self.RefreshLists()
    221 
    222     def GoForTransfer(self, *args):
    223         if len(self.transferContents) < 1:
    224             raise UserError('PleaseSelectCommoditiesToTransfer')
    225         for typeID, quantity in self.transferContents.iteritems():
    226             if typeID not in self.sourcePin.contents:
    227                 raise UserError('RouteFailedValidationExpeditedSourceLacksCommodity', {'typeName': evetypes.GetName(typeID)})
    228             if quantity > self.sourcePin.contents[typeID]:
    229                 raise UserError('RouteFailedValidationExpeditedSourceLacksCommodityQty', {'typeName': evetypes.GetName(typeID),
    230                  'qty': quantity})
    231 
    232         if not self.sourcePin.CanTransfer(self.transferContents):
    233             raise UserError('RouteFailedValidationExpeditedSourceNotReady')
    234         if len(self.transferContents) > 0:
    235             self.ShowLoad()
    236             try:
    237                 self.planet.TransferCommodities(self.path, self.transferContents)
    238             finally:
    239                 self.ResetPinContents()
    240                 self.HideLoad()
    241 
    242             self.CloseByUser()
    243 
    244     def ResetPinContents(self, *args):
    245         self.pinContents = self.sourcePin.contents.copy()
    246         self.transferContents = {}
    247         self.RefreshLists()
    248 
    249     def RefreshLists(self, *args):
    250         pinListItems = []
    251         for typeID, qty in self.pinContents.iteritems():
    252             pinListItems.append(GetFromClass(ExpeditedDraggableItem, {'itemID': None,
    253              'typeID': typeID,
    254              'label': '<t>%d<t>%s' % (qty, planetCommonUI.GetProductNameAndTier(typeID)),
    255              'getIcon': 1,
    256              'quantity': qty,
    257              'OnDropData': self.OnSourceScrollDropData}))
    258 
    259         transferListItems = []
    260         for typeID, qty in self.transferContents.iteritems():
    261             transferListItems.append(GetFromClass(ExpeditedDraggableItem, {'itemID': None,
    262              'typeID': typeID,
    263              'label': '<t>%d<t>%s' % (qty, planetCommonUI.GetProductNameAndTier(typeID)),
    264              'getIcon': 1,
    265              'quantity': qty,
    266              'OnDropData': self.OnTransferScrollDropData}))
    267 
    268         self.sourcePinListScroll.Load(contentList=pinListItems, noContentHint=localization.GetByLabel('UI/PI/Common/StorehouseIsEmpty'), headers=[localization.GetByLabel('UI/Common/Type'), localization.GetByLabel('UI/Common/Quantity'), localization.GetByLabel('UI/Common/Name')])
    269         self.transferListScroll.Load(contentList=transferListItems, noContentHint=localization.GetByLabel('UI/PI/Common/NoItemsFound'), headers=[localization.GetByLabel('UI/Common/Type'), localization.GetByLabel('UI/Common/Quantity'), localization.GetByLabel('UI/Common/Name')])
    270         transferVolume = planetCommon.GetCommodityTotalVolume(self.transferContents)
    271         self.volumeText.text = localization.GetByLabel('UI/PI/Common/VolumeAmount', amount=transferVolume)
    272         self.SetNextTransferText()
    273         self.SetCooldownTimeText()
    274 
    275     def SetNextTransferText(self):
    276         if self.sourcePin.lastRunTime is None or self.sourcePin.lastRunTime <= blue.os.GetWallclockTime():
    277             self.timeText.text = localization.GetByLabel('UI/PI/Common/NextTransferNow')
    278         else:
    279             self.timeText.text = localization.GetByLabel('UI/PI/Common/NextTransferTime', time=self.sourcePin.lastRunTime - blue.os.GetWallclockTime())
    280 
    281     def SetCooldownTimeText(self):
    282         time = planetCommon.GetExpeditedTransferTime(self.availableBandwidth, self.transferContents)
    283         self.cooldownTimeText.text = localization.GetByLabel('UI/PI/Common/CooldownTime', time=time)
    284 
    285     def SetSourcePinGaugeInfo(self):
    286         self.sourcePinSubGauge.state = uiconst.UI_DISABLED
    287         self.sourcePinSubGauge.SetText(localization.GetByLabel('UI/PI/Common/Capacity'))
    288         usageRatio = self.sourcePin.capacityUsed / self.sourcePin.GetCapacity()
    289         self.sourcePinSubGauge.SetSubText(localization.GetByLabel('UI/PI/Common/CapacityProportionUsed', capacityUsed=self.sourcePin.capacityUsed, capacityMax=self.sourcePin.GetCapacity(), percentage=usageRatio * 100.0))
    290         self.sourcePinSubGauge.SetValue(usageRatio)
    291 
    292     def RefreshDestinationPinInfo(self):
    293         self.destPinSubText.state = uiconst.UI_HIDDEN
    294         self.destPinSubGauge.state = uiconst.UI_HIDDEN
    295         if not self.destPin:
    296             self.destPinText.text = localization.GetByLabel('UI/PI/Common/NoOriginSelected')
    297             self.destPinSubText.text = ''
    298             self.destPinSubText.state = uiconst.UI_DISABLED
    299             self.destPinListScroll.Load(contentList=[], noContentHint=localization.GetByLabel('UI/PI/Common/NoOriginSelected'))
    300             return
    301         self.destPinText.text = localization.GetByLabel('UI/PI/Common/TransferDestinationName', typeName=planetCommon.GetGenericPinName(self.destPin.typeID, self.destPin.id))
    302         scrollHeaders = []
    303         scrollContents = []
    304         scrollNoContentText = ''
    305         if self.destPin.IsConsumer():
    306             self.destPinSubText.state = uiconst.UI_DISABLED
    307             if self.destPin.schematicID is None:
    308                 self.destPinSubText.text = localization.GetByLabel('UI/PI/Common/NoSchematicInstalled')
    309                 scrollNoContentText = localization.GetByLabel('UI/PI/Common/NoSchematicInstalled')
    310             else:
    311                 self.destPinSubText.text = localization.GetByLabel('UI/PI/Common/SchematicName', schematicName=get_schematic_name(self.destPin.schematicID))
    312                 scrollHeaders = []
    313                 demands = self.destPin.GetConsumables()
    314                 for typeID, qty in demands.iteritems():
    315                     remainingSpace = self.destPin.CanAccept(typeID, -1)
    316                     load = qty - remainingSpace
    317                     fraction = load / float(qty)
    318                     entry = GetFromClass(StatusBar, {'label': planetCommonUI.GetProductNameAndTier(typeID),
    319                      'text': localization.GetByLabel('UI/PI/Common/UnitQuantityAndDemand', quantity=load, demand=qty),
    320                      'value': fraction,
    321                      'iconID': evetypes.GetIconID(typeID)})
    322                     scrollContents.append(entry)
    323 
    324         elif self.destPin.IsStorage():
    325             self.destPinSubGauge.state = uiconst.UI_DISABLED
    326             self.destPinSubGauge.SetText(localization.GetByLabel('UI/PI/Common/Capacity'))
    327             usageRatio = self.destPin.capacityUsed / self.destPin.GetCapacity()
    328             self.destPinSubGauge.SetSubText(localization.GetByLabel('UI/PI/Common/CapacityProportionUsed', capacityUsed=self.destPin.capacityUsed, capacityMax=self.destPin.GetCapacity(), percentage=usageRatio * 100.0))
    329             self.destPinSubGauge.SetValue(usageRatio)
    330             scrollHeaders = [localization.GetByLabel('UI/Common/Type'), localization.GetByLabel('UI/Common/Quantity'), localization.GetByLabel('UI/Common/Name')]
    331             contents = self.destPin.GetContents()
    332             for typeID, qty in contents.iteritems():
    333                 lbl = '<t>%d<t>%s' % (qty, planetCommonUI.GetProductNameAndTier(typeID))
    334                 scrollContents.append(GetFromClass(ExpeditedDraggableItem, {'itemID': None,
    335                  'typeID': typeID,
    336                  'label': lbl,
    337                  'getIcon': 1,
    338                  'quantity': qty}))
    339 
    340             scrollNoContentText = localization.GetByLabel('UI/PI/Common/StorehouseIsEmpty')
    341         self.destPinListScroll.Load(contentList=scrollContents, headers=scrollHeaders, noContentHint=scrollNoContentText)
    342 
    343     def SetDestination(self, destinationPin):
    344         self.destPin = destinationPin
    345         self.RefreshDestinationPinInfo()
    346 
    347 
    348 class ExpeditedDraggableItem(Item):
    349     __guid__ = 'listentry.CustomsItem'
    350 
    351     def LoadTooltipPanel(self, tooltipPanel, *args):
    352         planetCommonUI.LoadProductTooltipPanel(tooltipPanel, self.sr.node.typeID)