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)