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

droneEntry.py (25574B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\drones\droneEntry.py
      2 import carbonui.const as uiconst
      3 import eveicon
      4 import evetypes
      5 import localization
      6 import mathext
      7 import trinity
      8 import uthread
      9 import uthread2
     10 from carbon.common.script.util.timerstuff import AutoTimer
     11 from carbonui import TextColor, uiconst
     12 from carbonui.control.buttonIcon import ButtonIcon
     13 from carbonui.primitives.container import Container
     14 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     15 from carbonui.primitives.fill import Fill
     16 from carbonui.primitives.sprite import Sprite
     17 from carbonui.uianimations import animations
     18 from carbonui.uicore import uicore
     19 from carbonui.util.bunch import Bunch
     20 from carbonui.util.color import Color
     21 from carbonui.util.various_unsorted import IsUnder
     22 from eve.client.script.environment import invControllers
     23 from eve.client.script.parklife import states as state
     24 from eve.client.script.ui import eveColor
     25 from eve.client.script.ui.control.entries.generic import Generic
     26 from eve.client.script.ui.control.eveLabel import EveLabelMedium
     27 from eve.client.script.ui.control.itemIcon import ItemIcon
     28 from eve.client.script.ui.inflight.drones import droneSignals, dronesDragData
     29 from eve.client.script.ui.inflight.drones.buttonSeperatorLine import ButtonSeperatorLine
     30 from eve.client.script.ui.inflight.drones.droneSettings import drones_view_mode_setting, VIEW_MODE_ICONS, drones_view_mode_compact_setting
     31 from eve.client.script.ui.inflight.drones.dronesConst import DRONE_STATES, COLOR_BY_STATE, DRONESTATE_INBAY, DRONESTATE_INSPACE, damageIconInfo, DRONE_STATES_TEXTURES
     32 from eve.client.script.ui.inflight.drones.dronesDragData import DroneEntryInSpaceDragData, DroneEntryInBayDragData, HasInBayDroneIDs, HasInSpaceDroneIDs
     33 from eve.client.script.ui.inflight.drones.dronesUtil import GetPrimaryActionName
     34 from eve.client.script.ui.inflight.shipHud import shipHudConst
     35 from eve.client.script.ui.services.menuSvcExtras import droneFunctions
     36 from eve.client.script.ui.shared.fittingScreen.droneTooltip import DroneTooltipWrapper
     37 from eve.client.script.ui.util import uix
     38 from eve.client.script.util import eveMisc
     39 from eve.client.script.util.bubble import InBubble
     40 from eveDrones.droneConst import DAMAGESTATE_NOT_READY
     41 from eveInflight.damageStateValue import CalculateCurrentDamageStateValues
     42 from eveservices.menu import GetMenuService
     43 from localization import GetByLabel
     44 from menu import MenuList, MenuLabel
     45 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     46 HEALTH_GAUGE_HEIGHT = 4
     47 ENTRY_HEIGHT = 24
     48 ENTRY_HEIGHT_COMPACT = 22
     49 
     50 class HealthGauge(Container):
     51     default_width = 32
     52 
     53     def ApplyAttributes(self, attributes):
     54         super(HealthGauge, self).ApplyAttributes(attributes)
     55         self.healthBar = Fill(parent=self, name='droneGaugeBar', align=uiconst.TOLEFT, color=shipHudConst.COLOR_HEALTH, blendMode=trinity.TR2_SBM_ADD)
     56         self.damageNeedle = Fill(name='damageNeedle', parent=self, align=uiconst.TOLEFT, width=2, color=eveColor.WHITE)
     57         Fill(parent=self, name='droneGaugeBarDmg', color=shipHudConst.COLOR_DAMAGE)
     58 
     59     def UpdateDamage(self, value):
     60         if value is None:
     61             return
     62         healthProp = round(value, 3)
     63         healthProp = mathext.clamp(healthProp, 0.0, 1.0)
     64         self.damageNeedle.display = healthProp > 0 and healthProp < 1.0
     65         self.healthBar.width = int(self.width * healthProp)
     66 
     67 
     68 class DroneEntry(Generic):
     69     __guid__ = 'listentry.DroneEntry'
     70     isDragObject = True
     71     __notifyevents__ = ['OnStateChange', 'OnDroneStateChange2', 'OnDroneActivityChange']
     72 
     73     def OnMouseDown(self, *args):
     74         uthread.new(self.OnMouseDown_thread)
     75 
     76     def OnMouseDown_thread(self):
     77         selelectedDrones = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
     78         droneState = self.sr.node.droneState
     79         displayLabel = self.sr.node.label
     80         if len(selelectedDrones) > 1:
     81             displayLabel += '<fontsize=14> + %s' % (len(selelectedDrones) - 1)
     82         if droneState == DRONESTATE_INBAY:
     83             nodesData = [ (drone.invItem, 0, None) for drone in selelectedDrones if drone.invItem is not None ]
     84             manyItemsData = Bunch(menuFunction=GetMenuService().InvItemMenu, itemData=nodesData, displayName='<b>%s</b>' % displayLabel)
     85         elif droneState == DRONESTATE_INSPACE:
     86             if len(selelectedDrones) > 1:
     87                 nodesData = [ (drone.itemID,
     88                  drone.typeID,
     89                  drone.ownerID,
     90                  drone.locationID) for drone in selelectedDrones if drone.typeID ]
     91                 manyItemsData = Bunch(menuFunction=GetMenuService().DroneMenu, itemData=nodesData, displayName='<b>%s</b>' % displayLabel)
     92             else:
     93                 manyItemsData = None
     94         else:
     95             return
     96         GetMenuService().TryExpandActionMenu(itemID=self.sr.node.itemID, typeID=self.sr.node.typeID, clickedObject=self, manyItemsData=manyItemsData)
     97 
     98     def Startup(self, *args):
     99         super(DroneEntry, self).Startup(*args)
    100         sm.RegisterNotify(self)
    101         self.activityID = None
    102         self.activity = None
    103         mainCont = Container(name='mainCont', parent=self, idx=0)
    104         gaugesParent = ContainerAutoSize(name='gaugesParent', parent=mainCont, align=uiconst.TORIGHT, padright=8)
    105         self.buttonCont = ContainerAutoSize(name='buttonParent', parent=mainCont, align=uiconst.TORIGHT, state=uiconst.UI_HIDDEN, opacity=0.0, padRight=4)
    106         self.ConstructButtons()
    107         self.gaugesCont = ContainerAutoSize(name='gaugesContainer', parent=gaugesParent, align=uiconst.CENTERRIGHT, state=uiconst.UI_NORMAL, height=HEALTH_GAUGE_HEIGHT, opacity=0.05)
    108         self.gaugesCont.LoadTooltipPanel = self.LoadDamageGaugeTooltipPanel
    109         self.gaugesCont.DelegateEventsNotImplemented(self)
    110         self.ConstructGauges()
    111         tClip = Container(name='textClipper', parent=mainCont, state=uiconst.UI_PICKCHILDREN, clipChildren=1)
    112         self.sr.label.SetParent(tClip)
    113         self.tooltipPanelClassInfo = DroneTooltipWrapper()
    114 
    115     def ConstructButtons(self):
    116         pass
    117 
    118     def Load(self, node):
    119         preselected = node.selected
    120         selected, = sm.GetService('stateSvc').GetStates(node.itemID, [state.selected])
    121         node.selected = selected
    122         Generic.Load(self, node)
    123         self.sr.label.left = self.GetLabelLeft()
    124         self.sr.label.autoFadeSides = 16
    125         self.sr.label.rgba = TextColor.HIGHLIGHT
    126         self.sr.label.Update()
    127         if preselected and not node.selected:
    128             node.selected = 1
    129             node.scroll.UpdateSelection(node)
    130         if self.sr.node.droneState == DRONESTATE_INSPACE:
    131             self.UpdateState()
    132         uthread2.StartTasklet(self.UpdateDamageThread)
    133 
    134     def GetLabelLeft(self):
    135         return 4 + 8 * self.sr.node.sublevel
    136 
    137     def UpdateState(self, droneState = None):
    138         michelle = sm.GetService('michelle')
    139         droneRow = michelle.GetDroneState(self.sr.node.itemID)
    140         droneActivity = michelle.GetDroneActivity(self.sr.node.itemID)
    141         if droneActivity:
    142             self.activity, self.activityID = droneActivity
    143         if droneState is None and droneRow is not None:
    144             droneState = droneRow.activityState
    145         stateText = self._GetStateText(droneState)
    146         self.sr.label.text = '%s %s' % (self.sr.node.label, stateText)
    147         return droneState
    148 
    149     def GetDroneActivityDescription(self):
    150         if self.sr.node.droneState != DRONESTATE_INBAY and self.activityID and self.activity:
    151             activity = ''
    152             if self.activity == 'guard':
    153                 activity = localization.GetByLabel('UI/Inflight/Drone/Guarding')
    154             elif self.activity == 'assist':
    155                 activity = localization.GetByLabel('UI/Inflight/Drone/Assisting')
    156             return localization.GetByLabel('UI/Inflight/Drone/Activity', activity=activity, idInfo=cfg.eveowners.Get(self.activityID).name)
    157 
    158     def GetDroneStateDescription(self):
    159         michelle = sm.GetService('michelle')
    160         droneRow = michelle.GetDroneState(self.sr.node.itemID)
    161         if droneRow is None:
    162             return
    163         droneState = droneRow.activityState
    164         target = None
    165         if droneState in [const.entityCombat, const.entityEngage, const.entityMining]:
    166             targetID = droneRow.targetID
    167             targetTypeName = None
    168             pilotName = None
    169             if targetID:
    170                 targetSlim = michelle.GetItem(targetID)
    171                 if targetSlim:
    172                     if targetSlim.groupID == const.categoryShip:
    173                         pilotID = michelle.GetCharIDFromShipID(targetSlim.itemID)
    174                         if pilotID:
    175                             pilotName = cfg.eveowners.Get(pilotID).name
    176                     targetTypeName = uix.GetSlimItemName(targetSlim)
    177             if pilotName:
    178                 target = pilotName
    179             elif targetTypeName:
    180                 target = targetTypeName
    181             else:
    182                 target = localization.GetByLabel('UI/Generic/Unknown')
    183         state = self._GetStateText(droneState)
    184         if target is not None:
    185             return u'{state} {target}'.format(state=state, target=target)
    186         else:
    187             return state
    188 
    189     def _GetStateText(self, droneState):
    190         stateText = localization.GetByLabel(DRONE_STATES.get(droneState, 'UI/Inflight/Drone/Incapacitated'))
    191         if droneState in COLOR_BY_STATE:
    192             stateText = '<color=%s>%s</color>' % (COLOR_BY_STATE[droneState], stateText)
    193         return stateText
    194 
    195     def GetHeight(self, node, width):
    196         node.height = ENTRY_HEIGHT_COMPACT if node.isWindowCompact else ENTRY_HEIGHT
    197         return node.height
    198 
    199     def OnDroneStateChange2(self, droneID, oldActivityState, newActivityState):
    200         if self.sr.node and self.sr.node.droneState == DRONESTATE_INSPACE and droneID == self.sr.node.itemID:
    201             droneRow = sm.GetService('michelle').GetDroneState(self.sr.node.itemID)
    202             if droneRow:
    203                 self.sr.node.controllerID = droneRow.controllerID
    204                 self.sr.node.controllerOwnerID = droneRow.controllerOwnerID
    205                 self.UpdateState(newActivityState)
    206 
    207     def OnDroneActivityChange(self, droneID, activityID, activity):
    208         if self.sr.node and self.sr.node.droneState in DRONESTATE_INSPACE and droneID == self.sr.node.itemID:
    209             self.activity = activity
    210             self.activityID = activityID
    211             self.UpdateState()
    212 
    213     def OnClick(self, *args):
    214         if self.sr.node:
    215             self.sr.node.scroll.SelectNode(self.sr.node)
    216             prompt_player_fsd_dialog('ListEntryClick')
    217             if not uicore.uilib.Key(uiconst.VK_CONTROL):
    218                 if not uicore.uilib.Key(uiconst.VK_SHIFT):
    219                     sm.GetService('stateSvc').SetState(self.sr.node.itemID, state.selected, 1)
    220             else:
    221                 sm.GetService('target').TryLockTarget(self.sr.node.itemID)
    222 
    223     def GetSelected(self):
    224         ids = []
    225         sel = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    226         for node in sel:
    227             if node.Get('typeID', None) is None:
    228                 continue
    229             if evetypes.GetGroupID(node.typeID) == evetypes.GetGroupID(self.sr.node.typeID):
    230                 ids.append(node.itemID)
    231 
    232         return ids
    233 
    234     def GetSelectedItems(self):
    235         items = []
    236         sel = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    237         for node in sel:
    238             items.append(node.invItem)
    239 
    240         return items
    241 
    242     def GetMenu(self):
    243         m = MenuList()
    244         if self.sr.node.customMenu:
    245             m += self.sr.node.customMenu(self.sr.node)
    246         if self.sr.node.droneState != DRONESTATE_INBAY:
    247             args = []
    248             selected = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    249             for node in selected:
    250                 if node.Get('typeID', None) is None:
    251                     continue
    252                 args.append((node.itemID,
    253                  None,
    254                  None,
    255                  node.typeID,
    256                  None))
    257 
    258             m += GetMenuService().CelestialMenu(args)
    259         else:
    260             selected = self.GetSelectedItems()
    261             args = []
    262             for rec in selected:
    263                 if rec is None:
    264                     continue
    265                 args.append((rec, 0, 0))
    266 
    267             m += GetMenuService().InvItemMenu(args).filter([MenuLabel('UI/Inventory/ItemActions/BuyThisType'),
    268              MenuLabel('UI/Inventory/ItemActions/AddTypeToMarketQuickbar'),
    269              MenuLabel('UI/Inventory/ItemActions/ViewTypesMarketDetails'),
    270              MenuLabel('UI/Inventory/ItemActions/FindInContracts')])
    271         return m
    272 
    273     def SelectAll(self):
    274         self.sr.node.scroll.SelectAll()
    275         sel = self.GetSelected()
    276         if len(sel) > 1:
    277             sm.ScatterEvent('OnDronesSelected', sel)
    278 
    279     def ConstructGauges(self):
    280         self.gaugeStruct = HealthGauge(parent=self.gaugesCont, name='structGauge', align=uiconst.TOLEFT, padRight=2)
    281         self.gaugeArmor = HealthGauge(parent=self.gaugesCont, name='armorGauge', align=uiconst.TOLEFT, padRight=2)
    282         self.gaugeShield = HealthGauge(parent=self.gaugesCont, name='shieldGauge', align=uiconst.TOLEFT)
    283 
    284     def LoadDamageGaugeTooltipPanel(self, tooltipPanel, *args):
    285         tooltipPanel.LoadStandardSpacing()
    286         self._LoadTooltipPanel_thread(tooltipPanel)
    287         self.tooltipThread = AutoTimer(500, self._LoadTooltipPanel_thread, tooltipPanel)
    288 
    289     def _LoadTooltipPanel_thread(self, tooltipPanel):
    290         currentMouseOver = uicore.uilib.mouseOver
    291         if self.destroyed or currentMouseOver != self and not currentMouseOver.IsUnder(self):
    292             self.tooltipThread = None
    293             return
    294         tooltipPanel.Flush()
    295         dmg = self.GetDamageTuple()
    296         if dmg in (DAMAGESTATE_NOT_READY, None):
    297             return
    298         dmgList = []
    299         for eachLayerDmgPerc in dmg[:3]:
    300             layerDmg = eachLayerDmgPerc * 100
    301             layerDmg = int(round(layerDmg))
    302             layerDmg = mathext.clamp(layerDmg, 0.0, 100)
    303             layerDmgText = localization.GetByLabel('UI/Common/Formatting/Percentage', percentage=layerDmg)
    304             dmgList.append(layerDmgText)
    305 
    306         dmgList.reverse()
    307         iconCont = Container(name='iconCont', parent=tooltipPanel, align=uiconst.CENTER, height=16, width=120, padTop=4)
    308         textCont = Container(name='textCont', parent=tooltipPanel, align=uiconst.CENTER, height=16, width=120, padTop=2)
    309         for i in xrange(len(dmgList)):
    310             Sprite(name='healthBar', parent=Container(parent=iconCont, align=uiconst.TOLEFT, width=40, height=16), align=uiconst.CENTER, width=16, height=16, texturePath=damageIconInfo.get(i, None))
    311             EveLabelMedium(parent=Container(parent=textCont, align=uiconst.TOLEFT, height=16, width=40), align=uiconst.CENTER, text=dmgList[i])
    312 
    313     def GetDragData(self, *args):
    314         return [ self._GetDragData(node.itemID, node.typeID) for node in self.sr.node.scroll.GetSelectedNodes(self.sr.node) ]
    315 
    316     def _GetDragData(self):
    317         raise NotImplementedError
    318 
    319     def Close(self):
    320         self.tooltipThread = None
    321         super(DroneEntry, self).Close()
    322 
    323     def UpdateDamageThread(self):
    324         while not self.destroyed:
    325             self.UpdateDamage()
    326             uthread2.Sleep(1.0)
    327 
    328     def UpdateDamage(self):
    329         pass
    330 
    331     def HideDamageDisplay(self):
    332         self.UpdateDamageGauges(1, 1, 1)
    333         self.gaugesCont.opacity = 0.05
    334 
    335     def GetDamageTuple(self):
    336         pass
    337 
    338     def GetShipID(self):
    339         if self.sr.node:
    340             return self.sr.node.itemID
    341 
    342     def OnMouseEnter(self, *args):
    343         super(DroneEntry, self).OnMouseEnter(*args)
    344         if self.sr.node:
    345             sm.GetService('stateSvc').SetState(self.GetIdForItem(), state.mouseOver, 1)
    346         self.ShowButtonCont()
    347         uicore.uilib.RegisterForTriuiEvents(uiconst.UI_MOUSEENTER, self.OnGlobalMouseEnter)
    348 
    349     def OnGlobalMouseEnter(self, obj, *args):
    350         if obj and not (IsUnder(obj, self) or obj == self):
    351             self.HideButtonCont()
    352             return False
    353         else:
    354             return True
    355 
    356     def OnMouseExit(self, *args):
    357         Generic.OnMouseExit(self, *args)
    358         if self.sr.node:
    359             sm.GetService('stateSvc').SetState(self.GetIdForItem(), state.mouseOver, 0)
    360 
    361     def ShowButtonCont(self):
    362         self.buttonCont.Show()
    363         animations.FadeTo(self.buttonCont, self.buttonCont.opacity, 1.0, duration=0.1)
    364 
    365     def HideButtonCont(self):
    366         animations.FadeTo(self.buttonCont, self.buttonCont.opacity, 0.0, duration=0.1, callback=self.buttonCont.Hide)
    367 
    368     def GetIdForItem(self):
    369         return self.sr.node.itemID
    370 
    371     def Select(self, *args):
    372         Generic.Select(self, *args)
    373         self.sr.node.selected = True
    374 
    375     def OnStateChange(self, itemID, flag, isActive, *args):
    376         if self.sr.node.itemID != itemID:
    377             return
    378         if flag == state.mouseOver:
    379             if isActive:
    380                 self.ShowHilite()
    381             else:
    382                 self.HideHilite()
    383         elif flag == state.selected:
    384             if isActive:
    385                 self.Select()
    386             else:
    387                 self.sr.node.scroll.DeselectAll()
    388 
    389     def Deselect(self, *args):
    390         Generic.Deselect(self, *args)
    391         self.sr.node.selected = False
    392 
    393     def UpdateDamageGauges(self, shield, armor, struct):
    394         self.gaugesCont.opacity = 1.0
    395         self.gaugeShield.UpdateDamage(shield)
    396         self.gaugeArmor.UpdateDamage(armor)
    397         self.gaugeStruct.UpdateDamage(struct)
    398 
    399 
    400 ICONSIZE = 32
    401 buttonSize = 20
    402 
    403 class DroneInBayEntry(DroneEntry):
    404     fetchingDamageValue = False
    405 
    406     def ConstructButtons(self):
    407         ButtonIcon(parent=self.buttonCont, align=uiconst.TORIGHT, width=buttonSize, iconSize=16, texturePath=eveicon.launch_drones, func=self.OnLaunchDronesButton, hint=GetByLabel('UI/Drones/LaunchDrone', numDrones=1), blendMode=trinity.TR2_SBM_ADD)
    408 
    409     def OnLaunchDronesButton(self, *args):
    410         droneInvItem = invControllers.ShipDroneBay().GetItem(self.sr.node.itemID)
    411         if droneInvItem:
    412             eveMisc.LaunchFromShip([droneInvItem])
    413 
    414     def UpdateDamage(self):
    415         dmg = self.GetDamageTuple()
    416         if dmg in (None, DAMAGESTATE_NOT_READY):
    417             self.HideDamageDisplay()
    418         else:
    419             self.UpdateDamageGauges(*dmg)
    420 
    421     def GetDamageTuple(self):
    422         if self.sr.node.damageState == DAMAGESTATE_NOT_READY:
    423             if not self.fetchingDamageValue:
    424                 self.fetchingDamageValue = True
    425                 itemID = self.GetShipID()
    426                 uthread.new(self.SetDamageValue_thread, itemID)
    427             return DAMAGESTATE_NOT_READY
    428         if self.sr.node.damageState:
    429             damageInMichelleFormat = self.sr.node.damageState.GetInfoInMichelleFormat()
    430             time = self.sr.node.damageState.timestamp
    431             ret = CalculateCurrentDamageStateValues(damageInMichelleFormat, time)
    432             return ret
    433 
    434     def SetDamageValue_thread(self, droneID):
    435         self.sr.node.damageState = sm.GetService('tactical').GetInBayDroneDamageTracker().GetDamageStateForDrone(droneID)
    436         self.fetchingDamageValue = False
    437         self.UpdateDamage()
    438 
    439     def OnDragEnter(self, dragSource, dragData):
    440         super(DroneInBayEntry, self).OnDragEnter(dragSource, dragData)
    441         if HasInSpaceDroneIDs(dragData):
    442             droneSignals.on_in_bay_entry_drag_enter()
    443 
    444     def _GetDragData(self, itemID, typeID):
    445         return DroneEntryInBayDragData(itemID, typeID)
    446 
    447     def OnDropData(self, dragSource, dragData):
    448         droneIDs = dronesDragData.GetInSpaceDroneIDs(dragData)
    449         if droneIDs:
    450             droneFunctions.ReturnToDroneBay(droneIDs)
    451 
    452 
    453 def IsIconsViewMode(isWindowCompact):
    454     if isWindowCompact:
    455         return drones_view_mode_compact_setting.is_equal(VIEW_MODE_ICONS)
    456     else:
    457         return drones_view_mode_setting.is_equal(VIEW_MODE_ICONS)
    458 
    459 
    460 class DroneInSpaceEntry(DroneEntry):
    461     STATE_SPRITE_PADDING = 20
    462 
    463     def Startup(self, *args):
    464         super(DroneInSpaceEntry, self).Startup(*args)
    465         self.stateSprite = Sprite(name='stateSprite', parent=self, align=uiconst.CENTERLEFT, pos=(2, 0, 16, 16))
    466         self.icon = ItemIcon(parent=self, align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, pos=(0,
    467          0,
    468          ICONSIZE,
    469          ICONSIZE))
    470         self.icon.Hide()
    471 
    472     def Load(self, node):
    473         super(DroneInSpaceEntry, self).Load(node)
    474         normalLabelLeft = super(DroneInSpaceEntry, self).GetLabelLeft()
    475         if IsIconsViewMode(node.isWindowCompact):
    476             self.icon.SetTypeID(self.sr.node.typeID)
    477             self.icon.left = normalLabelLeft + self.STATE_SPRITE_PADDING
    478             self.icon.Show()
    479         self.stateSprite.left = normalLabelLeft
    480 
    481     def GetHeight(self, node, width):
    482         if IsIconsViewMode(node.isWindowCompact):
    483             if node.isWindowCompact:
    484                 return ICONSIZE + 4
    485             return ICONSIZE + 8
    486         elif node.isWindowCompact:
    487             return ENTRY_HEIGHT_COMPACT
    488         else:
    489             return ENTRY_HEIGHT
    490 
    491     def GetLabelLeft(self):
    492         labelLeft = super(DroneInSpaceEntry, self).GetLabelLeft() + self.STATE_SPRITE_PADDING
    493         if IsIconsViewMode(self.sr.node.isWindowCompact):
    494             labelLeft = labelLeft + ICONSIZE + 4
    495         return labelLeft
    496 
    497     def ConstructButtons(self):
    498         ButtonIcon(parent=self.buttonCont, align=uiconst.TORIGHT, width=buttonSize, iconSize=16, texturePath=eveicon.recall_drones, func=self.OnRecallDronesButton, hint=GetByLabel('UI/Drones/ReturnDroneToBay'), blendMode=trinity.TR2_SBM_ADD)
    499         ButtonSeperatorLine(parent=self.buttonCont, align=uiconst.TORIGHT)
    500         ButtonIcon(parent=self.buttonCont, align=uiconst.TORIGHT, width=buttonSize, iconSize=16, texturePath=eveicon.return_and_orbit, func=self.OnReturnAndOrbitButton, hint=GetByLabel('UI/Drones/ReturnDroneAndOrbit'), blendMode=trinity.TR2_SBM_ADD)
    501         ButtonIcon(parent=self.buttonCont, align=uiconst.TORIGHT, width=buttonSize, iconSize=16, texturePath=eveicon.engage_target, func=self.OnPrimaryActionButton, hint=GetPrimaryActionName(self.sr.node.typeID), blendMode=trinity.TR2_SBM_ADD)
    502 
    503     def OnReturnAndOrbitButton(self, *args):
    504         droneFunctions.ReturnAndOrbit([self.sr.node.itemID])
    505 
    506     def OnPrimaryActionButton(self, *args):
    507         droneFunctions.PerformPrimaryAction([(self.sr.node.itemID, self.sr.node.typeID)])
    508 
    509     def OnRecallDronesButton(self, *args):
    510         droneFunctions.ReturnToDroneBay([self.sr.node.itemID])
    511 
    512     def GetDamageTuple(self):
    513         bp = sm.GetService('michelle').GetBallpark()
    514         if bp is None:
    515             return
    516         return bp.GetDamageState(self.GetShipID())
    517 
    518     def UpdateDamage(self):
    519         if not InBubble(self.GetShipID()):
    520             self.HideDamageDisplay()
    521             return
    522         if not getattr(self.sr.node, 'slimItem', None):
    523             categoryID = evetypes.GetCategoryID(self.sr.node.typeID)
    524         else:
    525             slimItem = self.sr.node.slimItem()
    526             if not slimItem:
    527                 self.HideDamageDisplay()
    528                 return
    529             categoryID = slimItem.categoryID
    530         shipID = self.GetShipID()
    531         if shipID and categoryID in (const.categoryShip, const.categoryDrone):
    532             dmg = self.GetDamageTuple()
    533             if dmg is not None:
    534                 self.UpdateDamageGauges(*dmg[:3])
    535             else:
    536                 self.HideDamageDisplay()
    537 
    538     def OnDragEnter(self, dragSource, dragData):
    539         super(DroneInSpaceEntry, self).OnDragEnter(dragSource, dragData)
    540         if HasInBayDroneIDs(dragData):
    541             droneSignals.on_in_space_entry_drag_enter()
    542 
    543     def _GetDragData(self, itemID, typeID):
    544         return DroneEntryInSpaceDragData(itemID, typeID)
    545 
    546     def OnDropData(self, dragSource, dragData):
    547         droneIDs = dronesDragData.GetInBayDroneIDs(dragData)
    548         if droneIDs:
    549             droneFunctions.LaunchDrones(droneIDs)
    550             droneSignals.on_drones_dropped_in_space()
    551 
    552     def UpdateState(self, droneState = None):
    553         droneState = super(DroneInSpaceEntry, self).UpdateState(droneState)
    554         texturePath = DRONE_STATES_TEXTURES.get(droneState, '')
    555         self.stateSprite.SetTexturePath(texturePath)
    556         stateLablePath = DRONE_STATES.get(droneState, None)
    557         stateText = localization.GetByLabel(stateLablePath) if stateLablePath else ''
    558         if droneState in COLOR_BY_STATE:
    559             colorHex = COLOR_BY_STATE[droneState]
    560             colorRGB = Color.HextoRGBA(colorHex)
    561         else:
    562             colorRGB = TextColor.NORMAL
    563         self.stateSprite.SetRGBA(*colorRGB)
    564         self.stateSprite.hint = stateText
    565 
    566 
    567 class NoDroneInBayEntry(Generic):
    568 
    569     def OnDropData(self, dragObj, dragData):
    570         droneIDs = dronesDragData.GetInSpaceDroneIDs(dragData)
    571         if droneIDs:
    572             droneFunctions.ReturnToDroneBay(droneIDs)
    573             droneSignals.on_drones_dropped_to_bay()
    574 
    575     def OnDragEnter(self, dragSource, dragData):
    576         if dronesDragData.HasInSpaceDroneIDs(dragData):
    577             droneSignals.on_in_bay_entry_drag_enter()
    578 
    579 
    580 class NoDroneInSpaceEntry(Generic):
    581 
    582     def OnDropData(self, dragObj, dragData):
    583         droneIDs = dronesDragData.GetInBayDroneIDs(dragData)
    584         if droneIDs:
    585             droneFunctions.LaunchDrones(droneIDs)
    586             droneSignals.on_drones_dropped_in_space()
    587 
    588     def OnDragEnter(self, dragSource, dragData):
    589         if dronesDragData.HasInBayDroneIDs(dragData):
    590             droneSignals.on_in_space_entry_drag_enter()