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

slot.py (16344B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fittingScreen\slot.py
      2 import logging
      3 import math
      4 import carbonui.const as uiconst
      5 import dogma.data as dogma_data
      6 import evetypes
      7 import inventorycommon.typeHelpers
      8 import localization
      9 import telemetry
     10 import utillib
     11 from carbonui.primitives.sprite import Sprite
     12 from dogma.const import effectRigSlot
     13 from eve.client.script.ui.control import eveIcon
     14 from eve.client.script.ui.inflight.shipModuleButton.moduleButtonTooltip import TooltipModuleWrapper
     15 from eve.client.script.ui.shared.fitting.baseSlot import FittingSlotBase
     16 from eve.client.script.ui.shared.fitting.fittingUtil import GetScaleFactor
     17 from eve.client.script.ui.shared.fitting.utilBtns import FittingUtilBtn, UtilBtnData
     18 from eve.client.script.ui.shared.fittingScreen.failedModuleTooltip import LoadGetFailedModuleTooltip
     19 from eve.client.script.ui.station.fitting.fittingTooltipUtils import SetFittingTooltipInfo
     20 from eve.common.lib import appConst as const
     21 from carbonui.uicore import uicore
     22 import inventorycommon.const as invConst
     23 MAXMODULEHINTWIDTH = 300
     24 logger = logging.getLogger(__name__)
     25 
     26 class FittingSlot(FittingSlotBase):
     27     __guid__ = 'xtriui.FittingSlot'
     28     __notifyevents__ = ['OnRefreshModuleBanks']
     29     default_name = 'fittingSlot'
     30     default_width = 44
     31     default_height = 54
     32     default_align = uiconst.TOPLEFT
     33     default_state = uiconst.UI_NORMAL
     34     isDragObject = True
     35     slotsToHintDict = {'hiSlot': ('UI/Fitting/EmptyHighPowerSlot', 'EmptyHighSlot'),
     36      'medSlot': ('UI/Fitting/EmptyMediumPowerSlot', 'EmptyMidSlot'),
     37      'loSlot': ('UI/Fitting/EmptyLowPowerSlot', 'EmptyLowSlot'),
     38      'subSystemSlot': ('UI/Fitting/EmptySubsystemSlot', ''),
     39      'rigSlot': ('UI/Fitting/EmptyRigSlot', '')}
     40 
     41     @telemetry.ZONE_METHOD
     42     def ApplyAttributes(self, attributes):
     43         FittingSlotBase.ApplyAttributes(self, attributes)
     44         self.groupMark = None
     45         self.chargeIndicator = None
     46         sm.RegisterNotify(self)
     47         self.radCosSin = attributes.radCosSin
     48         self.invReady = 1
     49         self.UpdateFitting()
     50         self.ChangeSignalConnection(connect=True)
     51 
     52     def ConstructFlagAndUnderlay(self):
     53         self.flagIcon = eveIcon.Icon(parent=self, name='flagIcon', align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=self.width, height=self.height)
     54         self.sr.underlay = Sprite(bgParent=self, name='underlay', state=uiconst.UI_DISABLED, padding=(-8, -4, -8, -4), texturePath='res:/UI/Texture/classes/Fitting/moduleFrame.png')
     55 
     56     def ConstructModuleSlotFill(self):
     57         if self.moduleSlotFill:
     58             return
     59         self.moduleSlotFill = Sprite(parent=self, name='moduleSlotFill', align=uiconst.TOALL, state=uiconst.UI_DISABLED, padding=(-8, -4, -8, -4), texturePath=self.slotActiveTexturePath, color=(1, 1, 1, 0.5))
     60         self.moduleSlotFill.display = False
     61 
     62     def ConstructWarningFill(self):
     63         if self.warningFill and not self.warningFill.destroyed:
     64             return
     65         self.warningFill = Sprite(parent=self, name='warningFill', align=uiconst.TOALL, state=uiconst.UI_DISABLED, padding=(-8, -4, -8, -4), texturePath=self.slotPassiveTexturePath, color=(1.0, 0.35, 0.0))
     66         self.warningFill.display = False
     67 
     68     def ConstructSkillSprite(self):
     69         if self.skillSprite:
     70             return
     71         self.skillSprite = Sprite(parent=self, name='skillSprite', align=uiconst.TOALL, state=uiconst.UI_DISABLED, padding=(-8, -4, -8, -4), texturePath='res:/UI/Texture/classes/Fitting/slotActive.png', color=(1, 1, 1, 0.5))
     72         self.skillSprite.display = False
     73 
     74     def ConstructGroupMark(self):
     75         if self.groupMark:
     76             return
     77         self.groupMark = Sprite(parent=self, name='groupMark', pos=(-10, 14, 16, 16), align=uiconst.CENTER, state=uiconst.UI_NORMAL, idx=0)
     78         self.groupMark.GetMenu = self.controller.GetGroupMenu
     79 
     80     def ConstructChargeIndicator(self):
     81         if self.chargeIndicator:
     82             return
     83         self.chargeIndicator = Sprite(parent=self, name='chargeIndicator', padTop=-2, height=7, align=uiconst.TOTOP_NOPUSH, state=uiconst.UI_HIDDEN, texturePath='res:/UI/Texture/Icons/81_64_2.png', ignoreSize=True)
     84         self.chargeIndicator.rectWidth = 44
     85         self.chargeIndicator.rectHeight = 7
     86 
     87     def ConstructFittingWarning(self):
     88         if self.fittingWarning and not self.fittingWarning.destroyed:
     89             return
     90         self.fittingWarning = Sprite(parent=self, name='fittingWarning', state=uiconst.UI_DISABLED, align=uiconst.BOTTOMLEFT, pos=(0, 0, 16, 16), texturePath='res:/UI/Texture/classes/Fitting/slotWarningIcon.png', idx=0)
     91         self.fittingWarning.rotation = -self.GetRotation()
     92 
     93     def OnRefreshModuleBanks(self):
     94         self.SetGroup()
     95 
     96     def SetGroup(self):
     97         try:
     98             if self.controller.GetModule() is not None and not self.controller.SlotExists():
     99                 self.controller.DestroyWeaponBank()
    100         except ReferenceError:
    101             pass
    102 
    103         parentID = self.controller.GetParentID()
    104         allGroupsDict = settings.user.ui.Get('linkedWeapons_groupsDict', {})
    105         groupDict = allGroupsDict.get(parentID, {})
    106         ret = self.GetBankGroup(groupDict)
    107         if ret is None:
    108             if self.groupMark:
    109                 self.groupMark.Hide()
    110             return
    111         groupNumber = ret.groupNumber
    112         self.ConstructGroupMark()
    113         self.groupMark.state = uiconst.UI_NORMAL
    114         self.groupMark.rotation = -self.GetRotation()
    115         if groupNumber < 0:
    116             availGroups = [1,
    117              2,
    118              3,
    119              4,
    120              5,
    121              6,
    122              7,
    123              8]
    124             for masterID, groupNum in groupDict.iteritems():
    125                 if groupNum in availGroups:
    126                     availGroups.remove(groupNum)
    127 
    128             groupNumber = availGroups[0] if availGroups else ''
    129         self.groupMark.texturePath = 'res:/UI/Texture/Icons/73_16_%s.png' % (176 + groupNumber)
    130         self.groupMark.hint = localization.GetByLabel('UI/Fitting/GroupNumber', groupNumber=groupNumber)
    131         groupDict[ret.masterID] = groupNumber
    132         allGroupsDict[parentID] = groupDict
    133         settings.user.ui.Set('linkedWeapons_groupsDict', allGroupsDict)
    134 
    135     def GetBankGroup(self, groupDict):
    136         module = self.controller.GetModule()
    137         try:
    138             if not module:
    139                 return None
    140         except ReferenceError:
    141             return None
    142 
    143         masterID = self.controller.IsInWeaponBank()
    144         if not masterID:
    145             return None
    146         if masterID in groupDict:
    147             groupNumber = groupDict.get(masterID)
    148         else:
    149             groupNumber = -1
    150         ret = utillib.KeyVal()
    151         ret.masterID = masterID
    152         ret.groupNumber = groupNumber
    153         return ret
    154 
    155     def PrepareUtilButtons(self):
    156         self.RemoveUtilButtons()
    157         self.utilButtons = []
    158         if not self.controller.GetModule():
    159             return
    160         myrad, cos, sin, cX, cY = self.radCosSin
    161         btns = self.GetUtilBtns()
    162         rad = myrad - 34
    163         i = 0
    164         for btnData in btns:
    165             left = int((rad - i * 16) * cos) + cX - 16 / 2
    166             top = int((rad - i * 16) * sin) + cY - 16 / 2
    167             utilBtn = FittingUtilBtn(parent=self.parent, icon=btnData.iconPath, left=left, top=top, btnData=btnData, mouseOverFunc=self.ShowUtilButtons, controller=self.controller, name='UtilIcon_%d' % i)
    168             if btnData.onlineBtn == 1:
    169                 self.sr.onlineButton = utilBtn
    170             self.utilButtons.append(utilBtn)
    171             i += 1
    172 
    173     def RemoveUtilButtons(self):
    174         for btn in self.utilButtons:
    175             btn.Close()
    176 
    177     def GetUtilBtns(self):
    178         btns = []
    179         if self.controller.GetCharge():
    180             btns += self.GetChargesBtns()
    181         isRig = False
    182         for effect in dogma_data.get_type_effects(self.controller.GetModuleTypeID()):
    183             if effect.effectID == effectRigSlot:
    184                 isRig = True
    185                 break
    186 
    187         isSubSystem = evetypes.GetCategoryID(self.controller.GetModuleTypeID()) == invConst.categorySubSystem
    188         isOnlinable = self.controller.IsOnlineable()
    189         if isRig:
    190             btns += self.GetRigsBtns()
    191         elif isSubSystem:
    192             btns += self.GetSubSystemBtns()
    193         else:
    194             btns += self.GetModuleBtns(isOnlinable)
    195         return btns
    196 
    197     def GetChargesBtns(self):
    198         moduleTypeID = self.controller.GetModuleTypeID()
    199         btns = [UtilBtnData(localization.GetByLabel('UI/Fitting/RemoveCharge'), 'ui_38_16_200', self.controller.Unfit, 1, 0), UtilBtnData(localization.GetByLabel('UI/Fitting/ShowChargeInfo'), 'ui_38_16_208', self.ShowChargeInfo, 1, 0), UtilBtnData(evetypes.GetName(moduleTypeID), inventorycommon.typeHelpers.GetIconFile(moduleTypeID), None, 1, 0)]
    200         return btns
    201 
    202     def GetSubSystemBtns(self):
    203         btns = [UtilBtnData(localization.GetByLabel('UI/Commands/ShowInfo'), 'ui_38_16_208', self.ShowInfo, 1, 0)]
    204         return btns
    205 
    206     @telemetry.ZONE_METHOD
    207     def UpdateFitting(self):
    208         if self.destroyed or not self.controller.CurrentShipIsLoaded():
    209             return
    210         if not self.controller.SlotExists() and not self.controller.GetModule():
    211             if self.controller.IsSubsystemSlot() and self.controller.parentController.HasStance():
    212                 self.HideSlot()
    213             else:
    214                 self.DisableSlot()
    215             self.HideChargeIndicator()
    216             self.RemoveUtilButtons()
    217             return
    218         self.EnableSlot()
    219         self.SetDragState()
    220         if self.controller.GetCharge():
    221             chargeQty = self.controller.GetChargeQuantity()
    222             if self.destroyed:
    223                 return
    224             if self.controller.GetModule() is None:
    225                 portion = 1.0
    226             else:
    227                 cap = self.controller.GetChargeCapacity()
    228                 if cap.capacity == 0:
    229                     portion = 1.0
    230                 else:
    231                     portion = cap.used / cap.capacity
    232             if self.destroyed:
    233                 return
    234             step = max(0, min(4, int(portion * 5.0)))
    235             self.ConstructChargeIndicator()
    236             self.chargeIndicator.rectTop = 10 * step
    237             self.chargeIndicator.state = uiconst.UI_NORMAL
    238             self.chargeIndicator.hint = '%s %d%%' % (evetypes.GetName(self.controller.GetCharge().typeID), portion * 100)
    239         elif not self.controller.GetModule():
    240             self.HideUtilButtons(1)
    241             self.HideChargeIndicator()
    242         elif self.controller.IsChargeable():
    243             self.ConstructChargeIndicator()
    244             self.chargeIndicator.rectTop = 0
    245             self.chargeIndicator.state = uiconst.UI_NORMAL
    246             self.chargeIndicator.hint = localization.GetByLabel('UI/Fitting/NoCharge')
    247         else:
    248             self.HideChargeIndicator()
    249             if self.chargeIndicator:
    250                 self.chargeIndicator.Hide()
    251         if self.controller.GetModule():
    252             self.tooltipPanelClassInfo = TooltipModuleWrapper()
    253             modulehint = evetypes.GetName(self.controller.GetModuleTypeID())
    254             if self.controller.GetCharge():
    255                 modulehint += '<br>%s' % localization.GetByLabel('UI/Fitting/ChargeQuantity', charge=self.controller.GetCharge().typeID, chargeQuantity=chargeQty)
    256             if not self.controller.SlotExists():
    257                 modulehint = localization.GetByLabel('UI/Fitting/SlotDoesNotExist')
    258             self.hint = modulehint
    259         elif self.controller.GetFailedTypeID():
    260             self.tooltipPanelClassInfo = None
    261         else:
    262             self.tooltipPanelClassInfo = None
    263             self.hint = self._emptyHint
    264             tooltipName = self._emptyTooltip
    265             if tooltipName:
    266                 SetFittingTooltipInfo(targetObject=self, tooltipName=tooltipName, includeDesc=False)
    267         self.PrepareUtilButtons()
    268         iconSize = int(48 * GetScaleFactor())
    269         self.flagIcon.SetSize(iconSize, iconSize)
    270         if self.controller.GetCharge() or self.controller.GetModule() or self.controller.IsModulePreviewModule():
    271             self.flagIcon.LoadIconByTypeID((self.controller.GetCharge() or self.controller.GetModuleOrPreview()).typeID, ignoreSize=True)
    272             self.flagIcon.rotation = -self.GetRotation()
    273         else:
    274             rev = 0
    275             slotIcon = {invConst.flagSubSystemSlot0: 'res:/UI/Texture/Icons/81_64_11.png',
    276              invConst.flagSubSystemSlot1: 'res:/UI/Texture/Icons/81_64_10.png',
    277              invConst.flagSubSystemSlot2: 'res:/UI/Texture/Icons/81_64_12.png',
    278              invConst.flagSubSystemSlot3: 'res:/UI/Texture/Icons/81_64_13.png'}.get(self.controller.GetFlagID(), None)
    279             if slotIcon is None:
    280                 slotIcon = {const.effectLoPower: 'res:/UI/Texture/Icons/81_64_5.png',
    281                  const.effectMedPower: 'res:/UI/Texture/Icons/81_64_6.png',
    282                  const.effectHiPower: 'res:/UI/Texture/Icons/81_64_7.png',
    283                  const.effectRigSlot: 'res:/UI/Texture/Icons/81_64_8.png'}.get(self.controller.GetPowerType(), None)
    284             else:
    285                 rev = 1
    286             if slotIcon is not None:
    287                 self.flagIcon.LoadIcon(slotIcon, ignoreSize=True)
    288             if rev:
    289                 self.flagIcon.rotation = math.radians(180.0)
    290             else:
    291                 self.flagIcon.rotation = 0.0
    292         self.SetGroup()
    293         self.UpdateOnlineDisplay()
    294         self.UpdateStatusDisplay()
    295         self.UpdateGhostFittingIcons(self.controller.GetModule())
    296         if not self.hilitedFromMathing:
    297             self.Hilite(0)
    298 
    299     def HideChargeIndicator(self):
    300         if self.chargeIndicator:
    301             self.chargeIndicator.Hide()
    302 
    303     def IsCharge(self, typeID):
    304         return evetypes.GetCategoryID(typeID) == invConst.categoryCharge
    305 
    306     def ShowChargeInfo(self, *args):
    307         self.controller.ShowChargeInfo()
    308 
    309     def _OnEndDrag(self, *args):
    310         self.left = self.top = -2
    311 
    312     def OnEndDrag(self, *args):
    313         if self.controller and self.controller.GetModule() is not None:
    314             sm.ScatterEvent('OnResetSlotLinkingMode', self.controller.GetModule().typeID)
    315 
    316     def GetTooltipPosition(self):
    317         rect, point = self.PositionHint()
    318         return rect
    319 
    320     def GetTooltipPointer(self):
    321         rect, point = self.PositionHint()
    322         return point
    323 
    324     def LoadTooltipPanel(self, tooltipPanel, *args):
    325         if self.controller.GetFailedTypeID():
    326             LoadGetFailedModuleTooltip(tooltipPanel, self.controller.GetFailedTypeID())
    327 
    328     def UpdateInfo_TimedCall(self, *args):
    329         if self.destroyed or self.moduleButtonHint.destroyed:
    330             self.moduleButtonHint = None
    331             self.updateTimer = None
    332             return
    333         if self.controller.GetModuleTypeID():
    334             if self.controller.GetCharge():
    335                 chargeItemID = self.controller.GetCharge().itemID
    336             else:
    337                 chargeItemID = None
    338             self.moduleButtonHint.UpdateAllInfo(self.controller.GetModuleID(), chargeItemID, fromWhere='fitting')
    339 
    340     def PositionHint(self, *args):
    341         myRotation = self.rotation + 2 * math.pi
    342         myRotation = -myRotation
    343         sl, st, sw, sh = self.parent.GetAbsolute()
    344         cX = sl + sw / 2.0
    345         cY = st + sh / 2.0
    346         rad, cos, sin, oldcX, oldcY = self.radCosSin
    347         hintLeft = int(round(rad * cos))
    348         hintTop = int(round(rad * sin))
    349         cap = rad * 0.7
    350         if hintLeft < -cap:
    351             point = uiconst.POINT_RIGHT_2
    352         elif hintLeft > cap:
    353             point = uiconst.POINT_LEFT_2
    354         elif hintTop < -cap:
    355             if hintLeft < 0:
    356                 point = uiconst.POINT_BOTTOM_3
    357             else:
    358                 point = uiconst.POINT_BOTTOM_1
    359         elif hintLeft < 0:
    360             point = uiconst.POINT_TOP_3
    361         else:
    362             point = uiconst.POINT_TOP_1
    363         return ((hintLeft + cX - 15,
    364           hintTop + cY - 15,
    365           30,
    366           30), point)
    367 
    368     def _OnClose(self, *args):
    369         self.updateTimer = None
    370         moduleButtonHint = getattr(uicore.layer.hint, 'moduleButtonHint', None)
    371         if moduleButtonHint and not moduleButtonHint.destroyed:
    372             if moduleButtonHint.fromWhere == 'fitting':
    373                 uicore.layer.hint.moduleButtonHint.FadeOpacity(0.0)