itemShip.py (25618B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\itemShip.py 2 from __future__ import absolute_import 3 import blue 4 import eveicon 5 import evetypes 6 import localization 7 import uthread2 8 from collections import OrderedDict, defaultdict 9 from carbonui.control.buttonIcon import ButtonIcon 10 from carbonui.primitives.container import Container 11 from carbonui.primitives.frame import Frame 12 from carbonui.primitives.sprite import Sprite 13 from carbonui.primitives.transform import Transform 14 from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal 15 from carbonui.uianimations import animations 16 from carbonui import TextColor, uiconst, Align, PickState 17 from carbonui.text.styles import TextBody, TextDetail 18 from carbonui.primitives.containerAutoSize import ContainerAutoSize 19 from characterdata.factions import get_faction_logo_flat 20 from dogma import data as dogma_data 21 import dogma.const as dogmaConst 22 from eve.client.script.ui.shared.neocom.neocom.highlightState import HighlightState, GetIndicatorColor 23 from eve.common.script.sys import idCheckers 24 from menucheckers.itemCheckers import ItemChecker 25 from inventoryutil.client.inventory import get_fitting_flags_for_ship_type 26 from inventorycommon.util import IsModularShip 27 from fsdBuiltData.common.iconIDs import GetIconFile 28 from eve.common.lib import appConst 29 from eve.common.script.sys import eveCfg 30 from eve.client.script.ui import eveThemeColor, eveColor 31 from omega.client.clone_grade_svc import get_clone_grade_svc 32 from shipgroup import get_ship_group_name 33 from eve.client.script.ui.shared.traits import TraitAttributeIcon 34 from eve.client.script.ui.util import uix 35 from eve.client.script.ui.shared.cloneGrade import ORIGIN_INVENTORY 36 from eve.client.script.ui.shared.cloneGrade.omegaCloneOverlayIcon import OmegaCloneOverlayIcon 37 from eve.client.script.ui.control.itemIcon import ItemIcon 38 from eve.client.script.ui.control import tooltipConst 39 from eve.client.script.ui.shared.item import InvItem, ItemSelectionFrame 40 from featuremanagement.client.flag import flag_bool 41 CARD_STATE_NORMAL = 1 42 CARD_STATE_ACTIVE = 2 43 CARD_STATE_PACKAGED = 3 44 SHIP_CARD_FITTING_ICON_ENABLED = 'ship-card-fitting-icon-enabled' 45 SHIP_CARD_FITTING_ICON_ENABLED_DEFAULT = True 46 _should_display_fitting_icon = SHIP_CARD_FITTING_ICON_ENABLED_DEFAULT 47 48 def _refresh_fitting_flag(evaluate_flag): 49 global _should_display_fitting_icon 50 _should_display_fitting_icon = evaluate_flag() 51 52 53 flag_bool(key=SHIP_CARD_FITTING_ICON_ENABLED, default_value=SHIP_CARD_FITTING_ICON_ENABLED_DEFAULT, callback=_refresh_fitting_flag) 54 55 class ShipItemIcon(InvItem): 56 57 def AddIconContainer(self): 58 self.groupIcon = Sprite(parent=self.mainContainer, pickState=PickState.OFF, align=Align.TOPRIGHT, width=16, height=16, left=1, top=1, opacity=1, shadowOffset=(1, 1), shadowColor=(0, 0, 0)) 59 super(ShipItemIcon, self).AddIconContainer() 60 61 def Load(self, node): 62 super(ShipItemIcon, self).Load(node) 63 self.groupIcon.texturePath = sm.GetService('bracket').GetBracketIcon(self.typeID) 64 65 66 class ShipItemCard(InvItem): 67 FACTION_LOGO_ANIMATION_DURATION = 0.25 68 FACTION_LOGO_MIN_SIZE = 96 69 FACTION_LOGO_MAX_SIZE = 108 70 OPACITY_IDLE = 0.2 71 OPACITY_HOVER = 0.3 72 OPACITY_MOUSEDOWN = 0.5 73 MAIN_PADDING = 3 74 fittedItems = [] 75 76 @classmethod 77 def GetEntryHeight(cls): 78 return 106 79 80 @classmethod 81 def GetEntryWidth(cls): 82 return 235 83 84 @classmethod 85 def GetEntryColMargin(cls): 86 return 6 87 88 @classmethod 89 def IsFixedWidth(cls): 90 return False 91 92 def ConstructLayout(self): 93 self.card_state = CARD_STATE_NORMAL 94 self.mainContainer = Container(name='MainContainer', parent=self, clipChildren=True, padding=self.MAIN_PADDING) 95 self.ConstructBottom() 96 self.ConstructContent() 97 self.ConstructBackground() 98 self.ConstructIndicator() 99 100 def ConstructContent(self): 101 iconWrapper = Container(name='iconWrapper', parent=self.mainContainer, align=Align.TOLEFT, width=self.ICON_SIZE, padding=2) 102 self.iconCont = Container(name='iconCont', parent=iconWrapper, align=Align.CENTER, width=self.ICON_SIZE, height=self.ICON_SIZE) 103 self._processing_click = False 104 self.hoverIcon = ButtonIcon(name='hoverIcon', parent=self.iconCont, width=self.ICON_SIZE, height=self.ICON_SIZE, iconSize=32, texturePath=eveicon.soldier_of_fortune, opacity=0, func=self.OnDblClick) 105 self.hoverBg = Sprite(name='hoverBg', parent=self.iconCont, width=self.ICON_SIZE, height=self.ICON_SIZE, texturePath='res:/UI/Texture/Classes/ShipTree/groups/bgWhite.png', color=(0, 0, 0, 0), opacity=0) 106 content = Container(name='content', parent=self.mainContainer, align=Align.TOALL, padding=(6, 6, 6, 2), clipChildren=True) 107 groupCont = Container(name='groupCont', parent=content, align=Align.TOTOP, height=16) 108 self.groupIcon = Sprite(parent=groupCont, pickState=PickState.OFF, align=Align.CENTERLEFT, width=16, height=16, color=TextColor.NORMAL) 109 self.groupLabel = TextDetail(parent=groupCont, align=Align.CENTERLEFT, text='', color=TextColor.SECONDARY, left=20) 110 self.fittingIcon = FittedItemsIcon(parent=groupCont, align=Align.CENTERRIGHT, width=16, height=16, display=False) 111 nameCont = ContainerAutoSize(name='nameCont', parent=content, align=Align.VERTICALLY_CENTERED) 112 self.sr.label = TextBody(parent=nameCont, align=Align.TOTOP, color=TextColor.HIGHLIGHT, bold=True, maxLines=1, autoFadeSides=16) 113 self.typeNameLabel = TextDetail(parent=nameCont, align=Align.TOTOP, text='', color=TextColor.SECONDARY, maxLines=1, autoFadeSides=16) 114 115 def ConstructOmegaIcon(self): 116 if self.omegaIcon: 117 return 118 self.omegaIcon = OmegaCloneOverlayIcon(parent=self.iconCont, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, width=self.ICON_SIZE, height=self.ICON_SIZE, opacity=self.OMEGAICON_OPACITY, origin=ORIGIN_INVENTORY, reason=self.typeID, idx=0) 119 120 def ConstructBottom(self): 121 bottomCont = Container(name='bottom', parent=self.mainContainer, align=Align.TOBOTTOM, height=30, padding=(2, 0, 2, 2)) 122 self.ConstructActiveState(bottomCont) 123 self.ConstructPackagedState(bottomCont) 124 self.traitCont = Container(name='traits', parent=bottomCont, align=uiconst.TOALL, padLeft=8, padRight=8, clipChildren=True) 125 self.bottomBG = StretchSpriteHorizontal(name='bottomBG', parent=bottomCont, align=Align.TOALL, texturePath='res:/UI/Texture/classes/Button/background_cut_bottom_left_right.png', leftEdgeSize=9, rightEdgeSize=9, color=eveColor.WHITE, opacity=0.05) 126 self.AddTag(bottomCont, Align.TOTOP_NOPUSH) 127 128 def ConstructActiveState(self, parent): 129 self.activeStateContainer = ContainerAutoSize(name='activeState', parent=parent, align=Align.TORIGHT, padLeft=2) 130 TextBody(parent=self.activeStateContainer, name='label', align=Align.CENTER, color=TextColor.SUCCESS, text=localization.GetByLabel('UI/Ship/Active'), padLeft=12, padRight=12) 131 Frame(bgParent=self.activeStateContainer, name='bg', align=Align.TOALL, texturePath='res:/UI/Texture/classes/Button/background_cut_bottom_right.png', cornerSize=9, color=(0, 0, 0, 0.6)) 132 133 def ConstructPackagedState(self, parent): 134 self.packagedStateContainer = ContainerAutoSize(name='packagedState', parent=parent, align=Align.TORIGHT, alignMode=Align.TORIGHT) 135 labelCont = ContainerAutoSize(parent=self.packagedStateContainer, align=Align.TORIGHT, padRight=9) 136 self.packagedLabelCont = ContainerAutoSize(parent=labelCont, align=Align.TORIGHT) 137 self.packagedLabelCont.DisableAutoSize() 138 self.packagedLabel = TextBody(parent=self.packagedLabelCont, align=Align.CENTERLEFT, color=TextColor.WARNING, text=localization.GetByLabel('UI/Ship/Packaged'), opacity=0, padLeft=4) 139 qtyContainer = ContainerAutoSize(parent=labelCont, align=Align.TORIGHT) 140 self.packagedQtyLabel = TextBody(parent=qtyContainer, align=Align.CENTERLEFT, text='') 141 Frame(bgParent=self.packagedStateContainer, name='bg', align=Align.TOALL, texturePath='res:/UI/Texture/classes/Button/background_cut_bottom_right.png', cornerSize=9, color=(0, 0, 0, 0.6)) 142 Sprite(parent=self.packagedStateContainer, texturePath='res:/UI/Texture/classes/Hangar/card_footer_triangle.png', color=(0, 0, 0, 0.6), align=Align.CENTERLEFT, height=30, width=30, left=-30) 143 144 def ConstructBackground(self): 145 self.factionIconCont = Transform(parent=self.mainContainer, align=Align.CENTERRIGHT, height=75, width=90, padRight=45) 146 self.factionIcon = Sprite(name='factionIcon', parent=self.factionIconCont, align=Align.CENTER, width=self.FACTION_LOGO_MIN_SIZE, height=self.FACTION_LOGO_MIN_SIZE, pickState=PickState.OFF, color=(1, 1, 1, 0.05), top=0) 147 Frame(name='card_mask_frame', bgParent=self, align=Align.TOALL, texturePath='res:/UI/Texture/classes/Hangar/card_fill.png', cornerSize=16, color=(0, 0, 0, 0.9), padding=self.MAIN_PADDING) 148 self.backgroundFrame = Frame(parent=self, name='background_frame', align=Align.TOALL, texturePath='res:/UI/Texture/classes/Hangar/card_fill.png', cornerSize=9, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.1, color=eveThemeColor.THEME_FOCUS, padding=self.MAIN_PADDING, opacity=self.OPACITY_IDLE) 149 150 def ConstructIndicator(self): 151 self.cardIndicator = Frame(parent=self, name='indicator', align=Align.TOALL, texturePath='res:/UI/Texture/classes/Hangar/card_indicator.png', cornerSize=9, opacity=0, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.8, padding=self.MAIN_PADDING) 152 self.tagContainer = Frame(parent=self, name='tag', align=Align.TOALL, texturePath='res:/UI/Texture/classes/Hangar/card_indicator.png', cornerSize=9, padding=self.MAIN_PADDING, state=uiconst.UI_HIDDEN, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.6, color=GetIndicatorColor(HighlightState.important)) 153 154 def ConstructSelectionFrame(self): 155 self._selection_frame = CardSelectionFrame(parent=self, align=uiconst.TOALL, idx=0, active=self._isSelected and self._showHilite) 156 157 def UpdateTag(self): 158 super(ShipItemCard, self).UpdateTag() 159 if self.shouldShowTag: 160 animations.MorphScalar(self.tagContainer, 'glowBrightness', 0.6, 1, duration=1.5, loops=10, curveType=uiconst.ANIM_WAVE) 161 else: 162 animations.StopAllAnimations(self.tagContainer) 163 164 def UpdateCardState(self): 165 item = ItemChecker(self.rec) 166 if item.IsActiveShip(): 167 self.SetCardState(CARD_STATE_ACTIVE) 168 elif item.IsAssembledShip(): 169 self.SetCardState(CARD_STATE_NORMAL) 170 else: 171 self.SetCardState(CARD_STATE_PACKAGED) 172 173 def SetCardState(self, state): 174 self.card_state = state 175 if state == CARD_STATE_NORMAL: 176 self.bottomBG.texturePath = 'res:/UI/Texture/classes/Button/background_cut_bottom_left_right.png' 177 self.bottomBG.rightEdgeSize = 9 178 self.activeStateContainer.Hide() 179 self.packagedStateContainer.Hide() 180 self.cardIndicator.color = eveThemeColor.THEME_FOCUS 181 self.cardIndicator.opacity = 0 182 elif state == CARD_STATE_ACTIVE: 183 self.bottomBG.texturePath = 'res:/UI/Texture/classes/Button/background_cut_bottom_left.png' 184 self.bottomBG.rightEdgeSize = 9 185 self.activeStateContainer.Show() 186 self.packagedStateContainer.Hide() 187 self.cardIndicator.color = TextColor.SUCCESS 188 else: 189 self.bottomBG.texturePath = 'res:/UI/Texture/classes/Hangar/card_footer_stripes.png' 190 self.bottomBG.rightEdgeSize = 110 191 self.activeStateContainer.Hide() 192 self.packagedStateContainer.Show() 193 self.cardIndicator.color = eveThemeColor.THEME_FOCUS 194 self.cardIndicator.opacity = 0 195 196 def Load(self, node): 197 self._processing_click = False 198 super(ShipItemCard, self).Load(node) 199 self.UpdateCardState() 200 self.UpdateFittingIcon() 201 if self.card_state == CARD_STATE_PACKAGED: 202 quantity = uix.GetItemQty(self.sr.node, 'ss') 203 self.packagedQtyLabel.text = u'x{qty}'.format(qty=quantity) 204 self.groupLabel.text = get_ship_group_name(self.typeID) 205 self.groupIcon.texturePath = sm.GetService('bracket').GetBracketIcon(self.typeID) 206 factionID = evetypes.GetFactionID(self.typeID) 207 factionLogo = get_faction_logo_flat(factionID) 208 if factionLogo: 209 self.factionIcon.texturePath = factionLogo.resolve(64) 210 else: 211 self.factionIconCont.Hide() 212 if self.typeID not in cfg.infoBubbleTypeElements: 213 return 214 self.traitCont.Flush() 215 data = cfg.infoBubbleTypeElements[self.typeID] 216 attributeIDs = [ x[1] for x in sorted(data.items(), key=lambda d: int(d[0])) ] 217 for index, attributeID in enumerate(attributeIDs): 218 icon = TraitAttributeIcon(parent=self.traitCont, align=uiconst.CENTERLEFT, attributeID=attributeID, width=16, height=16, left=24 * index) 219 icon.OnClick = self.OnClick 220 icon.GetMenu = self.GetMenu 221 icon.isDragObject = True 222 icon.GetDragData = self.GetDragData 223 icon.OnDropData = self.OnDropData 224 225 def UpdateFittingIcon(self): 226 self.fittingIcon.display = False 227 if self.card_state == CARD_STATE_PACKAGED: 228 return 229 self.fittingIcon.Update(self.id, self.typeID) 230 231 def UpdateLabel(self, new = 0): 232 super(ShipItemCard, self).UpdateLabel(new) 233 item = ItemChecker(self.rec) 234 if item.IsAssembledShip(): 235 self.typeNameLabel.text = evetypes.GetName(self.typeID) 236 237 def OnMouseEnter(self, *args): 238 super(ShipItemCard, self).OnMouseEnter(*args) 239 animations.StopAllAnimations(self.factionIcon) 240 animations.MorphScalar(self.factionIcon, 'width', startVal=self.factionIcon.width, endVal=self.FACTION_LOGO_MAX_SIZE, duration=self.FACTION_LOGO_ANIMATION_DURATION) 241 animations.MorphScalar(self.factionIcon, 'height', startVal=self.factionIcon.height, endVal=self.FACTION_LOGO_MAX_SIZE, duration=self.FACTION_LOGO_ANIMATION_DURATION) 242 animations.FadeTo(self.factionIcon, self.factionIcon.opacity, endVal=0.025, duration=self.FACTION_LOGO_ANIMATION_DURATION) 243 animations.FadeTo(self.backgroundFrame, self.backgroundFrame.opacity, endVal=self.OPACITY_HOVER, duration=self.FACTION_LOGO_ANIMATION_DURATION) 244 animations.StopAllAnimations(self.packagedLabel) 245 self.packagedLabelCont.ExpandWidth() 246 animations.FadeIn(self.packagedLabel, duration=self.FACTION_LOGO_ANIMATION_DURATION) 247 if self.card_state != CARD_STATE_ACTIVE: 248 animations.FadeIn(self.cardIndicator, duration=0.1) 249 self.hoverIcon.SetTexturePath(eveicon.board) 250 else: 251 self.hoverIcon.SetTexturePath('res:/UI/Texture/WindowIcons/fitting.png') 252 if self.typeID is None: 253 return 254 if not get_clone_grade_svc().is_restricted(self.typeID): 255 animations.FadeIn(self.hoverIcon, duration=self.FACTION_LOGO_ANIMATION_DURATION) 256 animations.FadeIn(self.hoverBg, endVal=0.5, duration=self.FACTION_LOGO_ANIMATION_DURATION / 2) 257 258 def OnDblClick(self, *args): 259 if self._processing_click: 260 return 261 self._processing_click = True 262 super(ShipItemCard, self).OnDblClick(*args) 263 uthread2.start_tasklet(self._reset_click) 264 265 def _reset_click(self): 266 uthread2.sleep(2) 267 self._processing_click = False 268 269 def OnMouseExit(self, *args): 270 super(ShipItemCard, self).OnMouseExit(*args) 271 animations.StopAllAnimations(self.factionIcon) 272 animations.MorphScalar(self.factionIcon, 'width', startVal=self.factionIcon.width, endVal=self.FACTION_LOGO_MIN_SIZE, duration=self.FACTION_LOGO_ANIMATION_DURATION) 273 animations.MorphScalar(self.factionIcon, 'height', startVal=self.factionIcon.height, endVal=self.FACTION_LOGO_MIN_SIZE, duration=self.FACTION_LOGO_ANIMATION_DURATION) 274 animations.FadeTo(self.factionIcon, self.factionIcon.opacity, endVal=0.05, duration=self.FACTION_LOGO_ANIMATION_DURATION) 275 animations.FadeTo(self.backgroundFrame, self.backgroundFrame.opacity, endVal=self.OPACITY_IDLE, duration=self.FACTION_LOGO_ANIMATION_DURATION) 276 animations.StopAllAnimations(self.packagedLabel) 277 self.packagedLabelCont.CollapseWidth() 278 animations.FadeOut(self.packagedLabel, duration=self.FACTION_LOGO_ANIMATION_DURATION) 279 if self.card_state != CARD_STATE_ACTIVE: 280 animations.FadeOut(self.cardIndicator, duration=0.1) 281 animations.FadeOut(self.hoverIcon, duration=self.FACTION_LOGO_ANIMATION_DURATION) 282 animations.FadeOut(self.hoverBg, duration=self.FACTION_LOGO_ANIMATION_DURATION / 2) 283 284 def OnColorThemeChanged(self): 285 super(ShipItemCard, self).OnColorThemeChanged() 286 self.backgroundFrame.rgb = eveThemeColor.THEME_FOCUSDARK[:3] 287 if self.card_state != CARD_STATE_ACTIVE: 288 self.cardIndicator.rgb = eveThemeColor.THEME_FOCUS[:3] 289 290 291 class CardSelectionFrame(ItemSelectionFrame): 292 293 def _create_frames_if_missing(self): 294 if self._outer_frame is None: 295 self._outer_frame = Frame(parent=self, texturePath='res:/UI/Texture/classes/Hangar/card_outline.png', cornerSize=9, color=eveThemeColor.THEME_FOCUS, opacity=0.6, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.6) 296 297 def OnColorThemeChanged(self): 298 super(CardSelectionFrame, self).OnColorThemeChanged() 299 if self._outer_frame: 300 self._outer_frame.rgb = eveThemeColor.THEME_FOCUS[:3] 301 302 303 class FittedItemsIcon(Sprite): 304 default_width = 16 305 default_height = 16 306 default_texturePath = eveicon.fitting 307 default_color = TextColor.NORMAL 308 __notifyevents__ = ['OnDogmaItemChange', 'OnFittingStripped'] 309 310 def __init__(self, *args, **kwargs): 311 self._tasklet = None 312 self._itemID = None 313 self._typeID = None 314 self._fittedItems = [] 315 self._charges = [] 316 self._dronesInBay = [] 317 super(FittedItemsIcon, self).__init__(*args, **kwargs) 318 319 def ApplyAttributes(self, attributes): 320 super(FittedItemsIcon, self).ApplyAttributes(attributes) 321 sm.RegisterNotify(self) 322 323 def Close(self): 324 super(FittedItemsIcon, self).Close() 325 sm.UnregisterNotify(self) 326 327 def Update(self, itemID, typeID): 328 self._itemID = itemID 329 self._typeID = typeID 330 if self._tasklet: 331 self._tasklet.Kill() 332 self._tasklet = uthread2.start_tasklet(self._Update) 333 334 def _Update(self, delay = None): 335 if not self._should_display(): 336 self.display = False 337 return 338 if delay: 339 uthread2.sleep(delay) 340 self._update_items() 341 self.opacity = TextColor.HIGHLIGHT.opacity if self._fittedItems or self._dronesInBay else TextColor.SECONDARY.opacity 342 self.display = True 343 344 def _update_items(self): 345 self._fittedItems = [] 346 self._charges = [] 347 self._dronesInBay = [] 348 flags = get_fitting_flags_for_ship_type(self._typeID) 349 if not flags: 350 return 351 if dogma_data.get_type_attribute(self._typeID, dogmaConst.attributeDroneCapacity) or IsModularShip(self._typeID): 352 flags.append(appConst.flagDroneBay) 353 inventory = sm.GetService('invCache').GetInventoryFromId(self._itemID) 354 items = inventory.ListByFlags(flags) 355 for item in items: 356 if item.flagID in appConst.fittingFlags: 357 if idCheckers.IsModule(item.categoryID) or item.flagID in appConst.subsystemSlotFlags: 358 self._fittedItems.append(item) 359 elif idCheckers.IsCharge(item.categoryID): 360 self._charges.append(item) 361 elif item.flagID == appConst.flagDroneBay: 362 self._dronesInBay.append(item) 363 364 def _should_display(self): 365 if self._itemID == session.shipid: 366 return True 367 if not _should_display_fitting_icon: 368 return False 369 return blue.os.desiredSimDilation > 0.9 370 371 def LoadTooltipPanel(self, tooltipPanel, *args): 372 if self._itemID == session.shipid: 373 self._update_items() 374 tooltipPanel.LoadGeneric1ColumnTemplate() 375 groupedEntries = OrderedDict() 376 for attributeID, flagID in ((dogmaConst.attributeHiSlots, appConst.flagHiSlot0), 377 (dogmaConst.attributeMedSlots, appConst.flagMedSlot0), 378 (dogmaConst.attributeLowSlots, appConst.flagLoSlot0), 379 (dogmaConst.attributeSubSystemSlot, appConst.flagSubSystemSlot0), 380 (dogmaConst.attributeRigSlots, appConst.flagRigSlot0)): 381 totalNum = int(dogma_data.get_type_attribute(self._typeID, attributeID, 0)) 382 groupedEntries[eveCfg.GetShipFlagLocationName(flagID)] = {'icon': GetIconFile(dogma_data.get_attribute_icon_id(attributeID)), 383 'totalNum': totalNum, 384 'fitted': defaultdict(int), 385 'fittedAmount': 0, 386 'charges': dict()} 387 388 for fittedItem in self._fittedItems: 389 slotName = eveCfg.GetShipFlagLocationName(fittedItem.flagID) 390 if slotName in groupedEntries: 391 groupedEntries[slotName]['fitted'][fittedItem.typeID] += 1 392 groupedEntries[slotName]['fittedAmount'] += 1 393 394 if self._charges: 395 moduleTypesBySlot = {item.flagID:item.typeID for item in self._fittedItems} 396 for charge in self._charges: 397 moduleTypeID = moduleTypesBySlot.get(charge.flagID, None) 398 if moduleTypeID: 399 slotName = eveCfg.GetShipFlagLocationName(charge.flagID) 400 if slotName in groupedEntries: 401 charges = groupedEntries[slotName]['charges'] 402 if moduleTypeID not in charges: 403 charges[moduleTypeID] = defaultdict(int) 404 charges[moduleTypeID][charge.typeID] += charge.stacksize 405 406 for slotName, groupInfo in groupedEntries.iteritems(): 407 if groupInfo['totalNum'] == 0 and groupInfo['fittedAmount'] == 0: 408 continue 409 if groupInfo['totalNum'] > 0: 410 text = u'{} [{}/{}]'.format(slotName, groupInfo['fittedAmount'], groupInfo['totalNum']) 411 else: 412 text = u'{} [{}]'.format(slotName, groupInfo['fittedAmount']) 413 tooltipPanel.AddCell(self._ConstructGroupEntry(groupInfo['icon'], text)) 414 for typeID, amount in sorted(groupInfo['fitted'].iteritems(), key=lambda entry: evetypes.GetName(entry[0])): 415 tooltipPanel.AddCell(self._ConstructTypeEntry(typeID, amount)) 416 charges = groupInfo['charges'].get(typeID, {}) 417 for chargeTypeID, amount in sorted(charges.iteritems(), key=lambda entry: evetypes.GetName(entry[0])): 418 tooltipPanel.AddCell(self._ConstructTypeEntry(chargeTypeID, amount, padLeft=16)) 419 420 tooltipPanel.AddSpacer() 421 422 if self._dronesInBay: 423 dronesDict = defaultdict(int) 424 for item in self._dronesInBay: 425 dronesDict[item.typeID] += item.stacksize 426 427 usedVolume = sum([ evetypes.GetVolume(typeID) * amount for typeID, amount in dronesDict.iteritems() ]) 428 totalVolume = dogma_data.get_type_attribute(self._typeID, dogmaConst.attributeDroneCapacity) 429 tooltipPanel.AddCell(self._ConstructGroupEntry(eveicon.drones, u'{} [{}]'.format(localization.GetByLabel('UI/Drones/Drones'), localization.GetByLabel('UI/Inventory/ContainerQuantityAndCapacity', quantity=usedVolume, capacity=totalVolume)))) 430 for typeID, amount in dronesDict.iteritems(): 431 tooltipPanel.AddCell(self._ConstructTypeEntry(typeID, amount)) 432 433 self.tooltipPanelMenu = tooltipPanel 434 435 def _ConstructGroupEntry(self, icon, text): 436 entryHeight = 24 437 container = ContainerAutoSize(align=Align.CENTERLEFT, height=entryHeight, bgColor=(1, 1, 1, 0.1)) 438 Sprite(parent=container, align=Align.TOLEFT, width=entryHeight, height=entryHeight, texturePath=icon, color=TextColor.NORMAL) 439 labelCont = ContainerAutoSize(parent=container, align=Align.TOLEFT) 440 TextBody(parent=labelCont, text=text, align=Align.CENTERLEFT, left=8, width=tooltipConst.LABEL_WRAP_WIDTH) 441 return container 442 443 def _ConstructTypeEntry(self, typeID, amount, padLeft = 0): 444 entryHeight = 24 445 container = ContainerAutoSize(align=Align.CENTERLEFT, height=entryHeight, padLeft=padLeft) 446 ItemIcon(parent=container, align=Align.TOLEFT, width=entryHeight, height=entryHeight, showOmegaOverlay=False, typeID=typeID) 447 labelCont = ContainerAutoSize(parent=container, align=Align.TOLEFT) 448 text = evetypes.GetName(typeID) 449 if amount > 1: 450 text = localization.GetByLabel('UI/InfoWindow/FittingItemLabelWithQuantity', quantity=amount, itemName=text) 451 TextBody(parent=labelCont, text=text, align=Align.CENTERLEFT, left=8, width=tooltipConst.LABEL_WRAP_WIDTH - padLeft) 452 return container 453 454 def OnDogmaItemChange(self, item, change): 455 if self._itemID != session.shipid: 456 return 457 self._Update() 458 459 def OnFittingStripped(self, shipID): 460 if self._itemID != shipID: 461 return 462 if self._tasklet: 463 self._tasklet.Kill() 464 self._tasklet = uthread2.start_tasklet(self._Update, delay=0.5)