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

bracketMgr.py (59519B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\parklife\bracketMgr.py
      2 import math
      3 import sys
      4 import stackless
      5 import blue
      6 import collections
      7 import evetypes
      8 import fsd.schemas.binaryLoader as fsdBinaryLoader
      9 import localization
     10 import mining
     11 import overviewPresets.overviewSettingsConst as osConst
     12 import telemetry
     13 import uthread
     14 from caching.memoize import Memoize
     15 from carbon.common.script.sys import service
     16 from carbon.common.script.util import logUtil as log
     17 from carbon.common.script.util.timerstuff import AutoTimer
     18 from carbonui import uiconst
     19 from carbonui.uicore import uicore
     20 from carbonui.util import colorblind
     21 from carbonui.util.various_unsorted import SortListOfTuples
     22 from eve.client.script.parklife import states as state
     23 from eve.client.script.parklife.bracketConst import SHOW_NONE, SHOW_DEFAULT, SHOW_ALL
     24 from eve.client.script.parklife.bracketSettings import bracket_display_override_setting, bracket_showing_specials_setting
     25 from eve.client.script.remote.michelle import GetMichelle
     26 from eve.client.script.ui.control.eveLabel import EveLabelSmall
     27 from eve.client.script.ui.inflight.bracketsAndTargets import bracketVarious
     28 from eve.client.script.ui.inflight.bracketsAndTargets.phaseStabilizerBracket import PhaseStabilizerBracket
     29 from eve.client.script.ui.inflight.bracketsAndTargets.asteroid_bracket import AsteroidBracket
     30 from eve.client.script.ui.inflight.bracketsAndTargets.bracketNameFormatting import TagWithBold, TagWithColor, TagWithItalic, TagWithSize, TagWithUnderLine
     31 from eve.client.script.ui.inflight.bracketsAndTargets.breach_point_asteroid_bracket import BreachPointAsteroidBracket
     32 from eve.client.script.ui.inflight.bracketsAndTargets.haulerBracket import HaulerBracket
     33 from eve.client.script.ui.inflight.bracketsAndTargets.inSpaceBracket import InSpaceBracket
     34 from eve.client.script.ui.inflight.bracketsAndTargets.my_ship_bracket import MyShipBracket
     35 from eve.client.script.ui.inflight.bracketsAndTargets.navigationBracket import NavigationBracket
     36 from eve.client.script.ui.inflight.bracketsAndTargets.siphonBracket import SiphonSiloBracket
     37 from eve.client.script.ui.inflight.bracketsAndTargets.skyhookBracket import SkyhookBracket
     38 from eve.client.script.ui.inflight.bracketsAndTargets.structureBracket import StructureBracket
     39 from eve.client.script.ui.inflight.bracketsAndTargets.targetInBar import TargetInBar
     40 from eve.client.script.ui.inflight.bracketsAndTargets.timedBracket import TimedBracket
     41 from eve.client.script.ui.inflight.overview import overviewConst
     42 from eve.client.script.ui.inflight.squadrons.shipFighterState import GetShipFighterState
     43 from eve.client.script.ui.util import uix
     44 from eve.common.lib import appConst
     45 from eve.common.script.sys import idCheckers
     46 from eve.common.script.sys.idCheckers import IsSkyhook
     47 from eveInflight.componentBracketController import ComponentBracketController
     48 from eveprefs import prefs
     49 from spacecomponents.client.messages import MSG_ON_BRACKET_CREATED
     50 from spacecomponents.common import componentConst
     51 from spacecomponents.common.data import type_has_space_component
     52 from stargate.client.gate_signals import on_lock_removed
     53 from uthread2 import call_after_simtime_delay
     54 RED = (0.8, 0, 0, 1.0)
     55 ORANGE = (0.75, 0.4, 0, 1.0)
     56 YELLOW = (1.0, 1.0, 0, 0.3)
     57 RECORDED_DAMAGE_PERIOD_SECONDS = 120
     58 NUMBER_OF_DAMAGEDEALERS = 5
     59 INF = 1e+32
     60 BRACKET_CATEGORIES_WITH_RANGE_MARKER = (appConst.categoryShip,
     61  appConst.categoryEntity,
     62  appConst.categoryDrone,
     63  appConst.categoryFighter)
     64 ONLY_VISIBLE_WHEN_SELECTED_GROUPS = (appConst.groupHarvestableCloud,)
     65 ONLY_VISIBLE_WHEN_SELECTED_CATEGORIES = []
     66 DEBUG_BRACKET = 0
     67 
     68 def GetBracketMgr():
     69     return sm.GetService('bracket')
     70 
     71 
     72 class BracketMgr(service.Service):
     73     __guid__ = 'svc.bracket'
     74     __update_on_reload__ = 0
     75     __exportedcalls__ = {'GetBracketName': [],
     76      'GetBracketName2': [],
     77      'ResetOverlaps': [],
     78      'CheckOverlaps': [],
     79      'CleanUp': [],
     80      'ClearBracket': [],
     81      'GetBracketProps': [],
     82      'Reload': [],
     83      'GetScanSpeed': [],
     84      'GetCaptureData': []}
     85     __notifyevents__ = ['DoBallsAdded',
     86      'DoBallRemove',
     87      'DoBallClear',
     88      'ProcessSessionChange',
     89      'OnFleetStateChange',
     90      'OnStateChange',
     91      'OnDestinationSet',
     92      'OnPostCfgDataChanged',
     93      'OnBallparkCall',
     94      'OnSlimItemChange',
     95      'OnAttribute',
     96      'OnAttributes',
     97      'OnCaptureChanged',
     98      'ProcessBountyInfoUpdated',
     99      'OnUIScalingChange',
    100      'OnFleetJoin_Local',
    101      'OnFleetLeave_Local',
    102      'OnDamageMessage',
    103      'OnDamageMessages',
    104      'DoBallsRemove',
    105      'OnStructureVisibilityUpdated',
    106      'OnHaulerQuantityChangedInClient',
    107      'OnRefreshWhenDockingRequestDenied',
    108      'OnStructureAccessUpdated',
    109      'OnDockingAccessChangedForCurrentSolarSystem_Local',
    110      'OnStateSetupChange',
    111      'OnMyFleetInited',
    112      'OnClientEvent_WarpStarted',
    113      'OnClientEvent_WarpFinished',
    114      'OnOverviewOverrideChanged',
    115      'OnBracketIconUpdated',
    116      'OnEmanationLockUpdated']
    117     __startupdependencies__ = ['wreck', 'overviewPresetSvc']
    118     __dependencies__ = ['michelle',
    119      'tactical',
    120      'map',
    121      'settings',
    122      'target',
    123      'fighters',
    124      'stateSvc']
    125 
    126     def __init__(self):
    127         super(BracketMgr, self).__init__()
    128         self.specials = (appConst.groupLargeCollidableStructure, appConst.groupMoon)
    129         self.renewingBracketFlags = False
    130         self.pendingBracketRenewal = False
    131         self.filterLCS = ['wall_x',
    132          'wall_z',
    133          ' wall',
    134          ' barricade',
    135          ' fence',
    136          ' barrier',
    137          ' junction',
    138          ' elevator',
    139          ' lookout',
    140          ' neon sign']
    141         self.showState = SHOW_DEFAULT
    142         self.showingSpecials = False
    143         self.componentBracketController = ComponentBracketController()
    144         bracket_display_override_setting.on_change.connect(self.OnBracketDisplaySettingChanged)
    145         bracket_showing_specials_setting.on_change.connect(self.OnBracketDisplaySettingChanged)
    146         on_lock_removed.connect(self.OnEmanationGateLockRemoved)
    147         colorblind.on_colorblind_mode_changed.connect(self.OnColorBlindModeChanged)
    148 
    149     def OnBracketDisplaySettingChanged(self, *args):
    150         self.SoftReload()
    151 
    152     def Run(self, memStream = None):
    153         service.Service.Run(self, memStream)
    154         self.scenarioMgr = sm.StartService('scenario')
    155         self.shipFighterState = GetShipFighterState()
    156         self.shipFighterState.signalOnFighterInSpaceUpdate.connect(self.OnFighterInSpaceUpdate)
    157         self.Reload()
    158         self.CreateBracketIndexes()
    159 
    160     def CreateBracketIndexes(self):
    161         self.bracketDataByCategoryID = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/bracketsByCategory.static', optimize=False)
    162         self.bracketDataByGroupID = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/bracketsByGroup.static', optimize=False)
    163         self.bracketDataByTypeID = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/bracketsByType.static', optimize=False)
    164         self.bracketsData = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/brackets.static', optimize=False)
    165 
    166     def GetBrackeDatatByID(self, bracketID):
    167         return self.bracketsData.get(bracketID, None)
    168 
    169     def GetBracketDataByTypeID(self, typeID):
    170         try:
    171             bracketID = self.bracketDataByTypeID[typeID]
    172         except KeyError:
    173             try:
    174                 bracketID = self.bracketDataByGroupID[evetypes.GetGroupID(typeID)]
    175             except KeyError:
    176                 try:
    177                     bracketID = self.bracketDataByCategoryID[evetypes.GetCategoryID(typeID)]
    178                 except KeyError:
    179                     return None
    180 
    181         return self.GetBrackeDatatByID(bracketID)
    182 
    183     def GetBracketDataByGroupID(self, groupID):
    184         if groupID in self.bracketDataByGroupID:
    185             bracketID = self.bracketDataByGroupID[groupID]
    186             return self.GetBrackeDatatByID(bracketID)
    187         categoryID = evetypes.GetCategoryIDByGroup(groupID)
    188         if categoryID in self.bracketDataByCategoryID:
    189             bracketID = self.bracketDataByCategoryID[categoryID]
    190             return self.GetBrackeDatatByID(bracketID)
    191 
    192     def GetBracketIcon(self, typeID, isEmpty = None, itemID = None):
    193         bracket = self.GetBracketDataByTypeID(typeID)
    194         return self._GetBracketIcon(bracket, isEmpty, typeID, itemID)
    195 
    196     def _GetBracketIcon(self, bracket, isEmpty, typeID = None, itemID = None):
    197         if bracket:
    198             componentBracketIcon = self.componentBracketController.GetBracketIcon(bracket, self.michelle.GetBallpark(), typeID, itemID)
    199             if componentBracketIcon:
    200                 return componentBracketIcon
    201             elif isEmpty and hasattr(bracket, 'texturePathEmpty'):
    202                 return bracket.texturePathEmpty
    203             else:
    204                 return bracket.texturePath
    205 
    206     def GetBracketIconByGroupID(self, groupID, isEmpty = None):
    207         bracket = self.GetBracketDataByGroupID(groupID)
    208         return self._GetBracketIcon(bracket, isEmpty)
    209 
    210     def Stop(self, stream):
    211         self.CleanUp()
    212 
    213     def CleanUp(self):
    214         self.brackets = {}
    215         self.updateBrackets = {}
    216         self.damageByBracketID = {}
    217         self.biggestDamageDealers = []
    218         self.shipLabels = None
    219         self.overlaps = []
    220         self.overlapsHidden = []
    221         self.checkingOverlaps = 0
    222         self.showHiddenTimer = None
    223         self.hairlinesTimer = None
    224         self.shipLabels = None
    225         self.inTargetRangeTimer = None
    226         self.damageDealerTimer = None
    227         uicore.layer.bracket.Flush()
    228         self.fleetBracketColor = (0.6, 0.15, 0.9, 0.5)
    229 
    230     def Hide(self):
    231         l_bracket = uicore.layer.bracket
    232         if l_bracket:
    233             l_bracket.state = uiconst.UI_HIDDEN
    234 
    235     def Show(self):
    236         l_bracket = uicore.layer.bracket
    237         if l_bracket:
    238             l_bracket.state = uiconst.UI_PICKCHILDREN
    239 
    240     @telemetry.ZONE_METHOD
    241     def Reload(self, *args, **kwds):
    242         self.CleanUp()
    243         overviewPresetSvc = sm.GetService('overviewPresetSvc')
    244         showInTargetRange = overviewPresetSvc.GetSettingValueOrDefaultFromName(osConst.SETTING_TARGET_RANGE, True)
    245         if showInTargetRange:
    246             self.inTargetRangeTimer = AutoTimer(1000, self.ShowInTargetRange)
    247         showBiggestDamageDealers = overviewPresetSvc.GetSettingValueOrDefaultFromName(osConst.SETTING_BIGGEST_DMG_DEALER, True)
    248         if showBiggestDamageDealers:
    249             self.damageDealerTimer = AutoTimer(1000, self.ShowBiggestDamageDealers_thread)
    250         uthread.new(self.SoftReload)
    251         self.UpdateFleetColor()
    252 
    253     @telemetry.ZONE_METHOD
    254     def SoftReload(self, showSpecials = None, bracketShowState = None):
    255         if bracketShowState is not None:
    256             self.showState = bracketShowState
    257         if showSpecials is not None:
    258             self.showingSpecials = showSpecials
    259         ballPark = sm.GetService('michelle').GetBallpark(doWait=True)
    260         if not ballPark:
    261             return
    262         for slimItem in ballPark.slimItems.itervalues():
    263             self.AddBracketIfWanted(slimItem)
    264 
    265     def ShowOwnShip(self):
    266         if not self.showHiddenTimer:
    267             myShipBracket = self.brackets.get(session.shipid, None)
    268             if myShipBracket:
    269                 myShipBracket.ShowOwnShip()
    270                 self.showHiddenTimer = AutoTimer(100, self.StopShowingHidden)
    271 
    272     def StopShowingHidden(self):
    273         alt = uicore.uilib.Key(uiconst.VK_MENU)
    274         if not alt:
    275             self.showHiddenTimer = None
    276             bracket = self.brackets.get(session.shipid, None)
    277             if bracket:
    278                 bracket.SetNormalInvisibleStateForOwnShip()
    279 
    280     def IsShowingAll(self):
    281         return bracket_display_override_setting.is_equal(SHOW_ALL)
    282 
    283     def IsHidingAll(self):
    284         return bracket_display_override_setting.is_equal(SHOW_NONE)
    285 
    286     def IsShowingSpecials(self):
    287         return bracket_showing_specials_setting.is_enabled()
    288 
    289     @telemetry.ZONE_METHOD
    290     def IsWanted(self, ballID, typeID = None, groupID = None, categoryID = None, slimItem = None, filtered = None):
    291         if typeID and not self.GetBracketDataByTypeID(typeID):
    292             return False
    293         else:
    294             if typeID is None or groupID is None or categoryID is None:
    295                 slimItem = slimItem or sm.GetService('michelle').GetBallpark().GetInvItem(ballID)
    296                 if slimItem is None:
    297                     log.LogWarn('IsWanted - ball', ballID, 'not found in park')
    298                     return False
    299                 typeID = slimItem.typeID
    300                 groupID = slimItem.groupID
    301                 categoryID = slimItem.categoryID
    302             if groupID == appConst.groupDeadspaceOverseersStructure:
    303                 checkName = evetypes.GetName(typeID).lower()
    304                 if checkName in self.filterLCS:
    305                     return False
    306             if categoryID == appConst.categoryStructure:
    307                 if not sm.GetService('structureProximityTracker').IsStructureVisible(ballID):
    308                     return False
    309             if groupID in ONLY_VISIBLE_WHEN_SELECTED_GROUPS or categoryID in ONLY_VISIBLE_WHEN_SELECTED_CATEGORIES:
    310                 return self.IsSelectedOrTargeted(ballID)
    311             isSpecial = groupID in self.specials
    312             if isSpecial:
    313                 if self.IsShowingSpecials():
    314                     return True
    315                 return self.IsSelectedOrTargeted(ballID)
    316             if self.IsShowingAll():
    317                 return True
    318             isSelectedOrTargeted = self.IsSelectedOrTargeted(ballID)
    319             if self.IsHidingAll():
    320                 return isSelectedOrTargeted
    321             if isSelectedOrTargeted:
    322                 return True
    323             slimItem = slimItem or sm.GetService('michelle').GetBallpark().GetInvItem(ballID)
    324             filtered = filtered or sm.GetService('tactical').GetFilteredStatesFunctionNames(isBracket=True)
    325             alwaysShown = sm.GetService('tactical').GetAlwaysShownStatesFunctionNames()
    326             return sm.GetService('tactical').WantIt(slimItem, filtered, alwaysShown, isBracket=True)
    327 
    328     @telemetry.ZONE_METHOD
    329     def IsSelectedOrTargeted(self, ballID):
    330         for isWanted in self.stateSvc.GetStates(ballID, [state.selected,
    331          state.targeted,
    332          state.targeting,
    333          state.activeTarget]):
    334             if isWanted:
    335                 return True
    336 
    337         return sm.GetService('target').IsTarget(ballID)
    338 
    339     def GetBracketName(self, objectID):
    340         if objectID in self.brackets:
    341             return self.brackets[objectID].displayName
    342         return ''
    343 
    344     def GetBracket(self, objectID):
    345         return self.brackets.get(objectID, None)
    346 
    347     def GetBracketName2(self, objectID):
    348         if not objectID:
    349             return ''
    350         ret = self.GetBracketName(objectID)
    351         if ret != '':
    352             ret = ret.replace('<br>', ' ')
    353             return ret
    354         ballpark = sm.GetService('michelle').GetBallpark()
    355         if not ballpark:
    356             return ''
    357         slimItem = ballpark.slimItems.get(objectID, None)
    358         if slimItem is None:
    359             return ''
    360         ret = self.GetDisplayNameForBracket(slimItem)
    361         if ret:
    362             ret = ret.replace('<br>', ' ')
    363         return ret
    364 
    365     def GetDisplayNameWithShipLabels(self, slimItem, displayName):
    366         shipLabelList = []
    367         if not self.shipLabels:
    368             self.shipLabels = self.stateSvc.GetShipLabels()
    369             self.hideCorpTicker = sm.GetService('overviewPresetSvc').GetSettingValueOrDefaultFromName(osConst.SETTING_HIDE_CORP_TICKER, True)
    370         for label in self.shipLabels:
    371             isVisible = label[overviewConst.LABEL_STATE]
    372             labelType = label[overviewConst.LABEL_TYPE]
    373             if labelType != overviewConst.LABEL_TYPE_LINEBREAK and not isVisible:
    374                 continue
    375             pre = label[overviewConst.PRE]
    376             post = label[overviewConst.POST]
    377             labelText = None
    378             if labelType is overviewConst.LABEL_TYPE_NONE:
    379                 if slimItem.corpID and not idCheckers.IsNPC(slimItem.corpID):
    380                     shipLabelList.append(pre)
    381             elif labelType == overviewConst.LABEL_TYPE_LINEBREAK:
    382                 if shipLabelList and shipLabelList[-1] != overviewConst.CHAR_BR:
    383                     shipLabelList.append(overviewConst.CHAR_BR)
    384             elif labelType == overviewConst.LABEL_TYPE_CORP:
    385                 if slimItem.corpID and not idCheckers.IsNPC(slimItem.corpID) and not (self.hideCorpTicker and slimItem.allianceID):
    386                     labelText = cfg.corptickernames.Get(slimItem.corpID).tickerName
    387             elif labelType == overviewConst.LABEL_TYPE_ALLIANCE:
    388                 if slimItem.allianceID:
    389                     try:
    390                         labelText = cfg.allianceshortnames.Get(slimItem.allianceID).shortName
    391                     except:
    392                         log.LogError('Failed to get allianceName, itemID:', slimItem.itemID, 'allianceID:', slimItem.allianceID)
    393 
    394             elif labelType == overviewConst.LABEL_TYPE_PILOT:
    395                 labelText = displayName
    396             elif labelType == overviewConst.LABEL_TYPE_SHIP_TYPE:
    397                 labelText = evetypes.GetName(slimItem.typeID)
    398             elif labelType == overviewConst.LABEL_TYPE_SHIP_NAME:
    399                 labelText = cfg.evelocations.Get(slimItem.itemID).name
    400             if labelText:
    401                 labelsForType = [labelText]
    402                 isBold = label.get(overviewConst.LABEL_BOLD, False)
    403                 isUnderlined = label.get(overviewConst.LABEL_UNDERLINE, False)
    404                 isItalic = label.get(overviewConst.LABEL_ITALIC, False)
    405                 labelsForType = TagWithBold(labelsForType, isBold)
    406                 labelsForType = TagWithUnderLine(labelsForType, isUnderlined)
    407                 labelsForType = TagWithItalic(labelsForType, isItalic)
    408                 labelsForType.insert(0, pre)
    409                 labelsForType.append(post)
    410                 color = label.get(overviewConst.LABEL_COLOR, None)
    411                 fontsize = label.get(overviewConst.LABEL_SIZE)
    412                 labelsForType = TagWithColor(labelsForType, color)
    413                 labelsForType = TagWithSize(labelsForType, fontsize)
    414                 shipLabelList += labelsForType
    415 
    416         return ''.join(shipLabelList)
    417 
    418     def OnSlimItemChange(self, oldSlim, newSlim):
    419         bracket = self.GetBracket(newSlim.itemID)
    420         if not bracket:
    421             return
    422         if hasattr(bracket, 'OnSlimItemChange'):
    423             bracket.OnSlimItemChange(oldSlim, newSlim)
    424         bracket.slimItem = newSlim
    425         bracket.displayName = None
    426         if idCheckers.IsStarbase(newSlim.categoryID):
    427             if newSlim.posState == oldSlim.posState and newSlim.posTimestamp == oldSlim.posTimestamp and newSlim.incapacitated == oldSlim.incapacitated and newSlim.controllerID == oldSlim.controllerID and newSlim.ownerID == oldSlim.ownerID:
    428                 return
    429             bracket.UpdateStructureState(newSlim)
    430         elif idCheckers.IsOrbital(newSlim.categoryID):
    431             if newSlim.orbitalState == oldSlim.orbitalState and newSlim.orbitalTimestamp == oldSlim.orbitalTimestamp and newSlim.ownerID == oldSlim.ownerID and newSlim.orbitalHackerID == oldSlim.orbitalHackerID and newSlim.orbitalHackerProgress == oldSlim.orbitalHackerProgress:
    432                 return
    433             bracket.UpdateOrbitalState(newSlim)
    434         if newSlim.corpID != oldSlim.corpID:
    435             uthread.pool('BracketMgr::OnSlimItemChange --> UpdateStates', bracket.UpdateFlagAndBackground, newSlim)
    436         if newSlim.groupID in appConst.environmentContainers:
    437             if newSlim.groupID == appConst.groupWreck and newSlim.isEmpty and not oldSlim.isEmpty:
    438                 self.stateSvc.SetState(newSlim.itemID, state.flagWreckEmpty, True)
    439             bracket.Load_update(newSlim)
    440         self.UpdateCaptureFromSlim(newSlim)
    441 
    442     def UpdateCaptureFromSlim(self, slimItem):
    443         if getattr(slimItem, 'capturePoint', None):
    444             if not hasattr(self, 'capturePoints'):
    445                 self.capturePoints = {}
    446             slimItem.capturePoint['lastIncident'] = blue.os.GetSimTime()
    447             self.capturePoints[slimItem.itemID] = slimItem.capturePoint
    448             bracket = self.GetBracket(slimItem.itemID)
    449             if bracket:
    450                 bracket.UpdateCaptureProgress(slimItem.capturePoint)
    451 
    452     def ProcessSessionChange(self, isremote, session, change):
    453         if not sm.GetService('connection').IsConnected() or session.stationid is not None or session.charid is None:
    454             self.CleanUp()
    455         elif 'solarsystemid' not in change and 'shipid' in change and change['shipid'][0] is not None:
    456             oldShipID, shipID = change['shipid']
    457             slimItem = sm.GetService('michelle').GetItem(oldShipID)
    458             if slimItem is not None:
    459                 self._RecreateBracket(slimItem)
    460             slimItem = sm.GetService('michelle').GetItem(shipID)
    461             if slimItem is not None:
    462                 self._RecreateBracket(slimItem)
    463 
    464     def RecreateBracket(self, itemID):
    465         slimItem = sm.GetService('michelle').GetItem(itemID)
    466         if slimItem:
    467             self._RecreateBracket(slimItem)
    468 
    469     def _RecreateBracket(self, slimItem):
    470         self.RemoveBracket(slimItem.itemID)
    471         self.AddBracketIfWanted(slimItem)
    472 
    473     def GetBracketProps(self, slimItem, ball = None):
    474         bracketData = self.GetBracketDataByTypeID(slimItem.typeID)
    475         texturePath = self._GetBracketIcon(bracketData, getattr(slimItem, 'isEmpty', False), slimItem.typeID, slimItem.itemID)
    476         minVisibleDistance = getattr(bracketData, 'minVisibleDistance', 0.0)
    477         maxVisibleDistance = getattr(bracketData, 'maxVisibleDistance', INF)
    478         iconOffset = getattr(bracketData, 'iconOffset', 0)
    479         return (texturePath,
    480          1,
    481          minVisibleDistance,
    482          maxVisibleDistance,
    483          iconOffset,
    484          0)
    485 
    486     def PrimeLocations(self, slimItem):
    487         locations = []
    488         for each in slimItem.jumps:
    489             if each.locationID not in locations:
    490                 locations.append(each.locationID)
    491             if each.toCelestialID not in locations:
    492                 locations.append(each.toCelestialID)
    493 
    494         if len(locations):
    495             cfg.evelocations.Prime(locations)
    496 
    497     def DoBallsAdded(self, balls_slimItems, *args, **kw):
    498         t = stackless.getcurrent()
    499         timer = t.PushTimer(blue.pyos.taskletTimer.GetCurrent() + '::BracketMgr')
    500         try:
    501             uthread.new(self._AddBrackets, balls_slimItems).context = blue.pyos.taskletTimer.GetCurrent() + '::_AddBrackets'
    502         finally:
    503             t.PopTimer(timer)
    504 
    505     @telemetry.ZONE_METHOD
    506     def _AddBrackets(self, balls_slimItems):
    507         for ball, slimItem in balls_slimItems:
    508             self.AddBracketIfWanted(slimItem, ball)
    509 
    510     @telemetry.ZONE_METHOD
    511     def RemoveBracket(self, itemID):
    512         if itemID in self.brackets:
    513             self.LogInfo('DoBallRemove::bracketMgr removing item', itemID)
    514             bracket = self.brackets[itemID]
    515             if bracket is not None and not bracket.destroyed:
    516                 bracket.Close()
    517             del self.brackets[itemID]
    518         if itemID in self.updateBrackets:
    519             del self.updateBrackets[itemID]
    520 
    521     @telemetry.ZONE_METHOD
    522     def AddBracketIfWanted(self, slimItem, ball = None):
    523         try:
    524             itemID = slimItem.itemID
    525             groupID = slimItem.groupID
    526             categoryID = slimItem.categoryID
    527             typeID = slimItem.typeID
    528             if not self.IsWanted(itemID, typeID=typeID, groupID=groupID, categoryID=categoryID, slimItem=slimItem):
    529                 bracket = self.brackets.get(itemID, None)
    530                 if bracket:
    531                     bracket.Hide()
    532                 return
    533             bracket = self.brackets.get(itemID, None)
    534             if bracket:
    535                 if not bracket.display:
    536                     bracket.Show()
    537                 return
    538             ball = ball or sm.GetService('michelle').GetBall(itemID)
    539             if not ball:
    540                 return
    541             bracket_cls = self.GetBracketClass(categoryID, groupID, slimItem.typeID, itemID)
    542             is_update_item = self.stateSvc.CheckIfUpdateItem(slimItem) and itemID != session.shipid
    543             bracket_ui = bracket_cls(parent=uicore.layer.bracket, name='__inflightbracket_%s' % itemID, align=uiconst.NOALIGN, state=uiconst.UI_NORMAL, ball=ball, slimItem=slimItem, is_update_item=is_update_item)
    544             if itemID in self.brackets:
    545                 bracket_ui.Close()
    546                 return
    547             self.brackets[itemID] = bracket_ui
    548             if is_update_item:
    549                 self.updateBrackets[itemID] = bracket_ui
    550             bracket_ui.Load_update(slimItem)
    551             if categoryID == appConst.categoryFighter and slimItem.ownerID == session.charid:
    552                 self.UpdateSquadronNumber(itemID, bracket_ui)
    553             if hasattr(self, 'capturePoints') and itemID in self.capturePoints.keys():
    554                 bracket_ui.UpdateCaptureProgress(self.capturePoints[itemID])
    555             else:
    556                 self.UpdateCaptureFromSlim(slimItem)
    557             if idCheckers.IsOrbital(categoryID):
    558                 bracket_ui.UpdateOrbitalState(slimItem)
    559             self.michelle.GetBallpark().componentRegistry.SendMessageToItem(itemID, MSG_ON_BRACKET_CREATED, bracket_ui, slimItem)
    560         except AttributeError as e:
    561             log.LogException(e)
    562             sys.exc_clear()
    563 
    564     def OnFighterInSpaceUpdate(self, fighterID, tubeFlagID):
    565         try:
    566             fighterBracket = self.brackets[fighterID]
    567         except KeyError:
    568             pass
    569         else:
    570             fighterInSpace = self.shipFighterState.GetFighterInSpaceByID(fighterID)
    571             if fighterInSpace:
    572                 fighterBracket.UpdateSquadronNumber(fighterInSpace.tubeFlagID)
    573             else:
    574                 self.RecreateBracket(fighterID)
    575 
    576     def UpdateSquadronNumber(self, fighterID, fighterBracket):
    577         fighterInSpace = self.shipFighterState.GetFighterInSpaceByID(fighterID)
    578         if fighterInSpace is None:
    579             tubeFlagID = None
    580         else:
    581             tubeFlagID = fighterInSpace.tubeFlagID
    582         fighterBracket.UpdateSquadronNumber(tubeFlagID)
    583 
    584     def GetBracketClass(self, categoryID, groupID, typeID, itemID):
    585         if categoryID == appConst.categoryStructure:
    586             return StructureBracket
    587         else:
    588             if mining.is_harvestable(typeID):
    589                 if type_has_space_component(typeID, componentConst.BREACH_POINT_ASTEROID):
    590                     return BreachPointAsteroidBracket
    591                 else:
    592                     return AsteroidBracket
    593             else:
    594                 if typeID == appConst.typeMobileShippingUnit:
    595                     return TimedBracket
    596                 if groupID == appConst.groupSiphonPseudoSilo:
    597                     return SiphonSiloBracket
    598                 if groupID == appConst.groupNpcIndustrialCommand:
    599                     return HaulerBracket
    600                 if itemID == session.shipid:
    601                     return MyShipBracket
    602                 if self.IsMyFighterInSpace(categoryID, itemID):
    603                     return NavigationBracket
    604                 if IsSkyhook(typeID):
    605                     return SkyhookBracket
    606             if groupID == appConst.groupMobilePhaseAnchor:
    607                 return PhaseStabilizerBracket
    608             return InSpaceBracket
    609 
    610     def IsMyFighterInSpace(self, categoryID, itemID):
    611         return categoryID == appConst.categoryFighter and sm.GetService('fighters').shipFighterState.IsMyFighterInSpace(itemID)
    612 
    613     @telemetry.ZONE_METHOD
    614     def GetDisplayNameForBracket(self, slimItem):
    615         try:
    616             displayName = uix.GetSlimItemName(slimItem)
    617         except Exception as e:
    618             if slimItem:
    619                 self.LogException('Couldnt generate name for bracket, slimItem is not None')
    620             else:
    621                 self.LogException('Couldnt generate name for bracket, slimItem is None')
    622             return
    623 
    624         groupID = slimItem.groupID
    625         categoryID = slimItem.categoryID
    626         if groupID == appConst.groupStation:
    627             displayName = uix.EditStationName(displayName, usename=1)
    628         elif groupID == appConst.groupStargate:
    629             uthread.new(self.PrimeLocations, slimItem)
    630         elif groupID == appConst.groupHarvestableCloud:
    631             displayName = localization.GetByLabel('UI/Generic/HarvestableCloud', item=slimItem.typeID)
    632         if not idCheckers.IsOrbital(categoryID) and getattr(slimItem, 'corpID', None):
    633             displayName = self.GetDisplayNameWithShipLabels(slimItem, displayName)
    634         return displayName
    635 
    636     @telemetry.ZONE_METHOD
    637     def UpdateLabels(self):
    638         self.shipLabels = self.stateSvc.GetShipLabels()
    639         self.hideCorpTicker = sm.GetService('overviewPresetSvc').GetSettingValueOrDefaultFromName(osConst.SETTING_HIDE_CORP_TICKER, True)
    640         for bracket in self.brackets:
    641             slimItem = self.brackets[bracket].slimItem
    642             if not slimItem:
    643                 continue
    644             if slimItem.corpID:
    645                 self.brackets[slimItem.itemID].displayName = self.GetDisplayNameForBracket(slimItem)
    646 
    647     @telemetry.ZONE_METHOD
    648     def RenewFlags(self):
    649         if self.renewingBracketFlags:
    650             self.pendingBracketRenewal = True
    651             return
    652         self.renewingBracketFlags = True
    653         self.pendingBracketRenewal = False
    654         uthread.pool('BracketMgr::RenewFlags', self._RenewAllFlags)
    655 
    656     def _RenewAllFlags(self):
    657         try:
    658             self._DoRenewAllFlags()
    659         finally:
    660             self.renewingBracketFlags = False
    661 
    662         if self.pendingBracketRenewal:
    663             self.RenewFlags()
    664 
    665     def _DoRenewAllFlags(self):
    666         for bracket in self.brackets.values():
    667             if not self._ShouldRenewBracket(bracket):
    668                 continue
    669             bracket.Load_update(bracket.slimItem)
    670             blue.pyos.BeNice()
    671 
    672     def _ShouldRenewBracket(self, bracket):
    673         if bracket.destroyed:
    674             return False
    675         if bracket.itemID not in self.updateBrackets:
    676             if bracket.slimItem is None or bracket.slimItem.groupID not in appConst.containerGroupIDs:
    677                 return False
    678         return True
    679 
    680     def RenewFlagForItemIDs(self, itemIDs):
    681         uthread.new(self._RenewFlagForItemIDs, itemIDs)
    682 
    683     def _RenewFlagForItemIDs(self, itemIDs):
    684         for eachItemID in itemIDs:
    685             bracket = self.GetBracket(eachItemID)
    686             if bracket is None:
    687                 continue
    688             if not self._ShouldRenewBracket(bracket):
    689                 continue
    690             bracket.Load_update(bracket.slimItem)
    691             blue.pyos.BeNice()
    692 
    693     def RenewSingleFlagForCharID(self, charID):
    694         uthread.new(self._RenewSingleFlag, charID)
    695 
    696     def _RenewSingleFlag(self, charID):
    697         bp = sm.GetService('michelle').GetBallpark()
    698         if not bp:
    699             return
    700         for bracket in self.brackets.itervalues():
    701             slimItem = bracket.slimItem
    702             if slimItem is None:
    703                 continue
    704             if bracket.itemID not in self.updateBrackets:
    705                 if slimItem.groupID not in appConst.containerGroupIDs:
    706                     continue
    707             if getattr(slimItem, 'ownerID', None) == charID:
    708                 bracket.Load_update(slimItem)
    709             elif getattr(slimItem, 'charID', None) == charID:
    710                 bracket.Load_update(slimItem)
    711             blue.pyos.BeNice()
    712 
    713     def OnBallparkCall(self, funcName, args):
    714         if funcName == 'SetBallFree':
    715             itemID, isFree = args
    716             bracket = self.GetBracket(itemID)
    717             if bracket and bracket.slimItem:
    718                 bracket.SetBracketAnchoredState(bracket.slimItem)
    719 
    720     def OnClientEvent_WarpStarted(self, *args):
    721         for itemID, bracket in self.brackets.iteritems():
    722             if isinstance(bracket, StructureBracket) and bracket.slimItem.timer is not None:
    723                 bracket.Update()
    724                 call_after_simtime_delay(bracket.Update, 10)
    725 
    726     def OnClientEvent_WarpFinished(self, *args):
    727         for itemID, bracket in self.brackets.iteritems():
    728             if isinstance(bracket, StructureBracket) and bracket.slimItem.timer is not None:
    729                 bracket.Update()
    730 
    731     def OnOverviewOverrideChanged(self):
    732         self.SoftReload()
    733 
    734     def OnBracketIconUpdated(self, itemID):
    735         bracket = self.brackets.get(itemID, None)
    736         if bracket and hasattr(bracket, 'UpdateIcon'):
    737             bracket.UpdateIcon()
    738 
    739     @telemetry.ZONE_METHOD
    740     def DoBallsRemove(self, pythonBalls, isRelease):
    741         if isRelease:
    742             for itemID, bracket in self.brackets.iteritems():
    743                 if bracket is not None and not bracket.destroyed:
    744                     bracket.Close()
    745 
    746             self.capturePoints = {}
    747             self.brackets = {}
    748             self.updateBrackets = {}
    749             return
    750         for ball, slimItem, terminal in pythonBalls:
    751             self.DoBallRemove(ball, slimItem, terminal)
    752 
    753     def DoBallRemove(self, ball, slimItem, terminal):
    754         if ball is None:
    755             return
    756         self.RemoveBracket(ball.id)
    757         if ball.id in getattr(self, 'capturePoints', {}):
    758             del self.capturePoints[ball.id]
    759 
    760     def DoBallClear(self, solitem):
    761         self.brackets = {}
    762         self.updateBrackets = {}
    763         for bracket in uicore.layer.bracket.children:
    764             bracket.Close()
    765 
    766     def OnUIScalingChange(self, *args):
    767         self.Reload()
    768 
    769     def OnColorBlindModeChanged(self):
    770         self.Reload()
    771 
    772     def OnDestinationSet(self, destinationID = None):
    773         focusOn = []
    774         updateGroups = (appConst.groupStation, appConst.groupStargate)
    775         updateCategories = (appConst.categoryStructure,)
    776         for each in uicore.layer.bracket.children:
    777             if not getattr(each, 'IsBracket', 0) or each.destroyed:
    778                 continue
    779             if not each.slimItem or each.slimItem.groupID not in updateGroups and each.slimItem.categoryID not in updateCategories:
    780                 continue
    781             each.UpdateIconColor(each.slimItem)
    782             if each.sr.icon and each.sr.icon.GetRGB() != overviewConst.OVERVIEW_NORMAL_COLOR:
    783                 focusOn.append(each)
    784 
    785         for each in focusOn:
    786             each.SetOrder(0)
    787 
    788     def OnFleetStateChange(self, fleetState):
    789         if fleetState:
    790             for itemID, tag in fleetState.targetTags.iteritems():
    791                 bracket = self.GetBracket(itemID)
    792                 if not bracket:
    793                     continue
    794                 if bracket.slimItem:
    795                     bracket.Load_update(bracket.slimItem)
    796 
    797     def OnFleetJoin_Local(self, member, *args):
    798         self.UpdateWrecksAndContainers(member)
    799 
    800     def OnFleetLeave_Local(self, member, *args):
    801         self.UpdateWrecksAndContainers(member)
    802 
    803     def UpdateWrecksAndContainers(self, member):
    804         if member.charID == session.charid:
    805             for bracket in self.brackets.values():
    806                 if bracket.slimItem and bracket.slimItem.groupID in (appConst.groupWreck, appConst.groupCargoContainer):
    807                     bracket.Load_update(bracket.slimItem)
    808 
    809     def OnStateChange(self, itemID, flag, flagState, *args):
    810         if flag in (state.selected, state.targeted, state.targeting):
    811             slimItem = uix.GetBallparkRecord(itemID)
    812             if not slimItem:
    813                 return
    814             IsWanted = self.IsWanted(slimItem.itemID, slimItem=slimItem)
    815             if flagState:
    816                 self.AddBracketIfWanted(slimItem)
    817             elif not IsWanted:
    818                 self.RemoveBracket(slimItem.itemID)
    819                 return
    820         bracket = self.GetBracket(itemID)
    821         if bracket:
    822             try:
    823                 bracket.OnStateChange(itemID, flag, flagState, *args)
    824             except AttributeError:
    825                 if DEBUG_BRACKET:
    826                     log.LogException('failure to update bracket')
    827 
    828     def OnStructureVisibilityUpdated(self, structureID):
    829         self.RecreateBracket(structureID)
    830 
    831     def OnHaulerQuantityChangedInClient(self, haulerID, qty, totalQty, ownerID, typeID):
    832         if haulerID in self.brackets:
    833             self.brackets[haulerID].UpdateQuantity(totalQty)
    834 
    835     def OnRefreshWhenDockingRequestDenied(self, structureID):
    836         bracket = self.GetBracket(structureID)
    837         if bracket and getattr(bracket, 'slimItem', None):
    838             bracket.UpdateFlagAndBackground(bracket.slimItem)
    839 
    840     def OnStructureAccessUpdated(self):
    841         self._RefreshStructureBracketIcons()
    842 
    843     def OnDockingAccessChangedForCurrentSolarSystem_Local(self):
    844         self._RefreshStructureBracketIcons()
    845 
    846     def _RefreshStructureBracketIcons(self):
    847         for eachBracket in self.brackets.itervalues():
    848             if getattr(eachBracket, 'slimItem', None) and eachBracket.slimItem.categoryID == appConst.categoryStructure:
    849                 eachBracket.UpdateFlagAndBackground(eachBracket.slimItem)
    850 
    851     def OnAttribute(self, attributeName, item, newValue):
    852         if item.itemID == session.shipid and attributeName == 'scanResolution':
    853             for targetID in sm.GetService('target').GetTargeting():
    854                 bracket = self.GetBracket(targetID)
    855                 if bracket and hasattr(bracket, 'OnAttribute'):
    856                     bracket.OnAttribute(attributeName, item, newValue)
    857 
    858     def OnAttributes(self, changeList):
    859         for t in changeList:
    860             self.OnAttribute(*t)
    861 
    862     def OnPostCfgDataChanged(self, what, data):
    863         if what == 'evelocations':
    864             bracket = self.GetBracket(data[0])
    865             if bracket is not None:
    866                 bracket.displayName = None
    867 
    868     def OnCaptureChanged(self, ballID, captureID, lastIncident, points, captureTime, lastCapturing):
    869         bracket = self.GetBracket(ballID)
    870         if not hasattr(self, 'capturePoints'):
    871             self.capturePoints = {}
    872         self.capturePoints[ballID] = {'captureID': captureID,
    873          'lastIncident': blue.os.GetSimTime(),
    874          'points': points,
    875          'captureTime': captureTime,
    876          'lastCapturing': lastCapturing}
    877         if bracket:
    878             bracket.UpdateCaptureProgress(self.capturePoints[ballID])
    879 
    880     def ResetOverlaps(self):
    881         for each in self.overlaps:
    882             if not getattr(each, 'IsBracket', 0):
    883                 continue
    884             projectBracket = each.projectBracket
    885             if projectBracket:
    886                 projectBracket.bracket = each.GetRenderObject()
    887                 each.KillLabel()
    888                 each.opacity = getattr(each, '_pervious_opacity', 1.0)
    889                 each.SetAlign(uiconst.NOALIGN)
    890 
    891         for each in self.overlapsHidden:
    892             bubble = each.sr.bubble
    893             if bubble:
    894                 bubble.state = uiconst.UI_PICKCHILDREN
    895 
    896         self.overlaps = []
    897         self.overlapsHidden = []
    898 
    899     def GetOverlapOverlap(self, sameX, minY, maxY):
    900         overlaps = []
    901         stillLeft = []
    902         for bracket in sameX:
    903             if bracket.absoluteTop > minY - 16 and bracket.absoluteBottom < maxY + 16:
    904                 if bracket.displayName:
    905                     overlaps.append((bracket.displayName.lower(), bracket))
    906                 else:
    907                     overlaps.append(('', bracket))
    908             else:
    909                 stillLeft.append(bracket)
    910 
    911         return (overlaps, stillLeft)
    912 
    913     def CheckingOverlaps(self):
    914         return self.checkingOverlaps
    915 
    916     @telemetry.ZONE_METHOD
    917     def CheckOverlaps(self, sender, hideRest = 0):
    918         self.checkingOverlaps = sender.itemID
    919         self.ResetOverlaps()
    920         overlaps = []
    921         excludedC = (appConst.categoryAsteroid,)
    922         excludedG = (appConst.groupHarvestableCloud,)
    923         sameX = []
    924         LEFT = 0
    925         TOP = 1
    926         BOTTOM = 2
    927         RIGHT = 3
    928         BRACKETSIZE = 16
    929         MAXEXPANDED = 15
    930 
    931         @Memoize
    932         def GetAbsolute(bracket):
    933             ro = bracket.GetRenderObject()
    934             x, y = uicore.ReverseScaleDpi(ro.displayX), uicore.ReverseScaleDpi(ro.displayY)
    935             centerX = x + bracket.width / 2
    936             centerY = y + bracket.height / 2
    937             return (centerX - 8,
    938              centerY - 8,
    939              centerY + 8,
    940              centerX + 8)
    941 
    942         s = GetAbsolute(sender)
    943         topMargin, bottomMargin = sender.GetLockedPositionTopBottomMargin()
    944         sender._topMargin = topMargin
    945         sender._bottomMargin = bottomMargin
    946         totalHeight = BRACKETSIZE + topMargin
    947         for bracket in sender.parent.children:
    948             if not getattr(bracket, 'IsBracket', 0) or not bracket.display or bracket.invisible or bracket.categoryID in excludedC or bracket.groupID in excludedG or bracket == sender:
    949                 continue
    950             b = GetAbsolute(bracket)
    951             overlapx = not (b[RIGHT] <= s[LEFT] or b[LEFT] >= s[RIGHT])
    952             overlapy = not (b[BOTTOM] <= s[TOP] or b[TOP] >= s[BOTTOM])
    953             if overlapx and overlapy and bracket.displayName:
    954                 topMargin, bottomMargin = bracket.GetLockedPositionTopBottomMargin()
    955                 bracket._topMargin = topMargin
    956                 bracket._bottomMargin = bottomMargin
    957                 totalHeight += topMargin + BRACKETSIZE + bottomMargin
    958                 overlaps.append((bracket.displayName.lower(), bracket))
    959             elif overlapx and not overlapy:
    960                 sameX.append(bracket)
    961             if len(overlaps) == MAXEXPANDED:
    962                 break
    963 
    964         if not overlaps:
    965             self.checkingOverlaps = None
    966             sender.parent.state = uiconst.UI_PICKCHILDREN
    967             return
    968         if sameX:
    969             while len(overlaps) < MAXEXPANDED:
    970                 minY = s[TOP] - totalHeight
    971                 maxY = s[BOTTOM]
    972                 oo, sameX = self.GetOverlapOverlap(sameX, minY, maxY)
    973                 if not oo or not sameX:
    974                     break
    975                 for overlap in oo:
    976                     overlaps.append(overlap)
    977                     topMargin, bottomMargin = overlap[1].GetLockedPositionTopBottomMargin()
    978                     overlap[1]._topMargin = topMargin
    979                     overlap[1]._bottomMargin = bottomMargin
    980                     totalHeight += topMargin + BRACKETSIZE + bottomMargin
    981                     if len(overlaps) == MAXEXPANDED:
    982                         break
    983 
    984         overlaps = SortListOfTuples(overlaps, reverse=True)
    985 
    986         def LockBracketPosition(bracket, left, top):
    987             projectBracket = bracket.projectBracket
    988             if projectBracket:
    989                 projectBracket.bracket = None
    990             bracket.SetAlign(uiconst.TOPLEFT)
    991             bracket.left = left - bracket.width / 2
    992             lockedTopPos = top - (bracket.height - 16) / 2
    993             bracket.top = lockedTopPos
    994             bracket._lockedTopPos = lockedTopPos
    995             bracket.displayX = left
    996             bracket._pervious_opacity = bracket.opacity
    997             bracket.opacity = 1.0
    998             bracket.SetOrder(0)
    999             if hasattr(bracket, 'update_attached_objects'):
   1000                 bracket.update_attached_objects()
   1001 
   1002         top = s[TOP]
   1003         left = s[LEFT] + BRACKETSIZE / 2
   1004         sender._lockedTopPos = top
   1005         self.overlaps = [sender] + overlaps
   1006         for overlapBracket in self.overlaps:
   1007             hasBubble = bool(overlapBracket.sr.bubble)
   1008             if not hasBubble:
   1009                 overlapBracket.ShowLabel()
   1010             if overlapBracket is not sender:
   1011                 top -= overlapBracket._bottomMargin
   1012             LockBracketPosition(overlapBracket, left, top)
   1013             top -= overlapBracket._topMargin + BRACKETSIZE
   1014 
   1015         self.overlapsHidden = []
   1016         if hideRest:
   1017             for bracket in sender.parent.children:
   1018                 if bracket is sender or bracket in overlaps or not getattr(bracket, 'IsBracket', 0) or bracket.state != uiconst.UI_PICKCHILDREN or bracket.invisible:
   1019                     continue
   1020                 bubble = bracket.sr.bubble
   1021                 if bubble:
   1022                     bubble.state = uiconst.UI_HIDDEN
   1023                     self.overlapsHidden.append(bracket)
   1024 
   1025         if top < 0:
   1026             for overlapBracket in self.overlaps:
   1027                 overlapBracket.top = -top + overlapBracket._lockedTopPos - BRACKETSIZE
   1028 
   1029         sender.parent.state = uiconst.UI_PICKCHILDREN
   1030         self.checkingOverlaps = None
   1031         uicore.uilib.RegisterForTriuiEvents(uiconst.UI_MOUSEDOWN, self.OnGlobalMouseDown)
   1032 
   1033     def OnGlobalMouseDown(self, *args):
   1034         mo = uicore.uilib.mouseOver
   1035         for bracket in self.overlaps:
   1036             if mo in (bracket, bracket.label):
   1037                 return True
   1038 
   1039         self.ResetOverlaps()
   1040 
   1041     def GetBracket(self, bracketID):
   1042         if getattr(self, 'brackets', None) is not None:
   1043             return self.brackets.get(bracketID, None)
   1044 
   1045     def ClearBracket(self, id, *args, **kwds):
   1046         self.RemoveBracket(id)
   1047 
   1048     def GetScanSpeed(self, source = None, target = None):
   1049         if source is None:
   1050             source = session.shipid
   1051         if not source:
   1052             return
   1053         myitem = sm.GetService('godma').GetItem(source)
   1054         scanSpeed = None
   1055         if myitem.scanResolution and target:
   1056             slimItem = target
   1057             targetitem = sm.GetService('godma').GetType(slimItem.typeID)
   1058             if targetitem.AttributeExists('signatureRadius'):
   1059                 radius = targetitem.signatureRadius
   1060             else:
   1061                 radius = 0
   1062             if radius <= 0.0:
   1063                 bp = sm.GetService('michelle').GetBallpark()
   1064                 radius = bp.GetBall(slimItem.itemID).radius
   1065                 if radius <= 0.0:
   1066                     radius = evetypes.GetRadius(targetitem.typeID)
   1067                     if radius <= 0.0:
   1068                         radius = 1.0
   1069             scanSpeed = 40000000.0 / myitem.scanResolution / math.log(radius + math.sqrt(radius * radius + 1)) ** 2.0
   1070         if scanSpeed is None:
   1071             scanSpeed = 2000
   1072             log.LogWarn('GetScanSpeed returned the defauly scanspeed of %s ms ... missing scanResolution?' % scanSpeed)
   1073         return min(scanSpeed, 180000)
   1074 
   1075     def GetCaptureData(self, ballID):
   1076         if hasattr(self, 'capturePoints'):
   1077             return self.capturePoints.get(ballID, None)
   1078 
   1079     def ProcessBountyInfoUpdated(self, itemIDs):
   1080         for itemID in itemIDs:
   1081             try:
   1082                 self.brackets[itemID].RefreshBounty()
   1083             except KeyError:
   1084                 pass
   1085 
   1086     @telemetry.ZONE_METHOD
   1087     def OnDamageMessages(self, dmgmsgs):
   1088         for msg in dmgmsgs:
   1089             self.OnDamageMessage(*msg[1:])
   1090 
   1091     @telemetry.ZONE_METHOD
   1092     def OnDamageMessage(self, damageMessagesArgs):
   1093         attackerID = damageMessagesArgs.get('attackerID', None)
   1094         if attackerID is None:
   1095             attackType = damageMessagesArgs.get('attackType', 'me')
   1096             if attackType != 'me':
   1097                 self.LogWarn('No attacker found! - damageMessagesArgs = ', damageMessagesArgs)
   1098             return
   1099         damage = damageMessagesArgs['damage']
   1100         s = blue.os.GetSimTime() / appConst.SEC
   1101         if attackerID not in self.damageByBracketID:
   1102             self.damageByBracketID[attackerID] = collections.defaultdict(long)
   1103         self.damageByBracketID[attackerID][s] += int(damage)
   1104         if damage:
   1105             self.TryBlinkAttacker(attackerID)
   1106 
   1107     def DisableShowingDamageDealers(self, *args):
   1108         if self.damageDealerTimer is None:
   1109             return
   1110         self.damageDealerTimer = None
   1111         if not session.shipid:
   1112             return
   1113         oldDamageDealers = self.biggestDamageDealers[:]
   1114         self.RemoveDamageIndicatorFromBrackets(oldDamageDealers, [])
   1115 
   1116     def EnableShowingDamageDealers(self, *args):
   1117         if self.damageDealerTimer is None:
   1118             self.ShowBiggestDamageDealers_thread()
   1119             self.damageDealerTimer = AutoTimer(1000, self.ShowBiggestDamageDealers_thread)
   1120 
   1121     def TryBlinkAttacker(self, attackerID, *args):
   1122         if attackerID not in self.biggestDamageDealers:
   1123             return
   1124         bracket = self.GetBracket(attackerID)
   1125         if not bracket:
   1126             return
   1127         sprite = bracket.GetHitSprite(create=False)
   1128         if sprite:
   1129             uicore.animations.FadeTo(sprite, startVal=sprite.baseOpacity + 0.05, endVal=sprite.baseOpacity, duration=0.75, loops=1, curveType=uiconst.ANIM_OVERSHOT)
   1130 
   1131     def ShowBiggestDamageDealers_thread(self, *args):
   1132         oldDamageDealers = self.biggestDamageDealers[:]
   1133         newDamageDealers = self.FindBiggestDamageDealers()
   1134         alphas = [0.25,
   1135          0.2,
   1136          0.15,
   1137          0.12,
   1138          0.08]
   1139         size = [100,
   1140          90,
   1141          80,
   1142          75,
   1143          70]
   1144         counter = 0
   1145         self.biggestDamageDealers = []
   1146         for damage, bracketID in newDamageDealers:
   1147             bracket = self.GetBracket(bracketID)
   1148             if bracket:
   1149                 sprite = bracket.GetHitSprite()
   1150                 currentPlace = getattr(sprite, 'currentPlace', None)
   1151                 duration = 0.2
   1152                 newOpacity = alphas[counter]
   1153                 sprite.baseOpacity = newOpacity
   1154                 newSize = size[counter]
   1155                 if currentPlace is None:
   1156                     sprite.width = sprite.height = newSize
   1157                     uicore.animations.FadeTo(sprite, startVal=0, endVal=newOpacity, duration=duration)
   1158                 else:
   1159                     uicore.animations.FadeTo(sprite, startVal=sprite.opacity, endVal=newOpacity, duration=duration)
   1160                     uicore.animations.MorphScalar(sprite, 'width', startVal=sprite.width, endVal=newSize, duration=duration)
   1161                     uicore.animations.MorphScalar(sprite, 'height', startVal=sprite.height, endVal=newSize, duration=duration)
   1162                 sprite.currentPlace = counter
   1163                 self.biggestDamageDealers.append(bracketID)
   1164                 if getattr(prefs, 'showDamageOnTarget', False):
   1165                     label = getattr(bracket, 'debugLabel', None)
   1166                     if not label:
   1167                         label = bracket.debugLabel = EveLabelSmall(text='', parent=bracket, top=42, align=uiconst.CENTERTOP, state=uiconst.UI_DISABLED)
   1168                     label.text = damage
   1169             counter += 1
   1170 
   1171         self.RemoveDamageIndicatorFromBrackets(oldDamageDealers, self.biggestDamageDealers)
   1172 
   1173     def RemoveDamageIndicatorFromBrackets(self, oldDamageDealers, newDamageDealers, *args):
   1174         for bracketID in oldDamageDealers:
   1175             if bracketID in newDamageDealers:
   1176                 continue
   1177             bracket = self.GetBracket(bracketID)
   1178             if bracket is None:
   1179                 continue
   1180             sprite = bracket.GetHitSprite(create=False)
   1181             if sprite:
   1182                 sprite.Close()
   1183             label = getattr(bracket, 'debugLabel', None)
   1184             if label:
   1185                 label.Close()
   1186 
   1187     def FindBiggestDamageDealers(self, *args):
   1188         numDamageDealers = NUMBER_OF_DAMAGEDEALERS
   1189         now = blue.os.GetSimTime() / appConst.SEC
   1190         timeline = now - RECORDED_DAMAGE_PERIOD_SECONDS
   1191         attackersToRemove = []
   1192         damageSumAndAttackerID = []
   1193         for attackerID in self.damageByBracketID:
   1194             latestAttacks = collections.defaultdict(long)
   1195             for timestamp, value in self.damageByBracketID[attackerID].iteritems():
   1196                 if timestamp > timeline:
   1197                     latestAttacks[timestamp] = value
   1198 
   1199             if len(latestAttacks) == 0:
   1200                 attackersToRemove.append(attackerID)
   1201                 continue
   1202             self.damageByBracketID[attackerID] = latestAttacks
   1203             if attackerID in self.brackets:
   1204                 totalDamage = sum(latestAttacks.itervalues())
   1205                 if totalDamage == 0:
   1206                     continue
   1207                 attackersDamageTuple = (totalDamage, attackerID)
   1208                 damageSumAndAttackerID.append(attackersDamageTuple)
   1209 
   1210         for attackerID in attackersToRemove:
   1211             del self.damageByBracketID[attackerID]
   1212 
   1213         damageSumAndAttackerID.sort(reverse=True)
   1214         results = damageSumAndAttackerID[:numDamageDealers]
   1215         return results
   1216 
   1217     def DisableInTargetRange(self, *args):
   1218         if self.inTargetRangeTimer is None:
   1219             return
   1220         self.inTargetRangeTimer = None
   1221         if not session.shipid:
   1222             return
   1223         for key, bracket in self.brackets.items():
   1224             canTargetSprite = bracket.GetCanTargetSprite(create=False)
   1225             if canTargetSprite:
   1226                 canTargetSprite.Close()
   1227 
   1228     def EnableInTargetRange(self, *args):
   1229         if self.inTargetRangeTimer is None:
   1230             self.ShowInTargetRange()
   1231             self.inTargetRangeTimer = AutoTimer(1000, self.ShowInTargetRange)
   1232 
   1233     def ShowInTargetRange(self, *args):
   1234         if not session.shipid:
   1235             return
   1236         bp = sm.GetService('michelle').GetBallpark()
   1237         ship = sm.GetService('godma').GetItem(session.shipid)
   1238         if ship is None:
   1239             return
   1240         maxTargetRange = ship.maxTargetRange
   1241         for key, bracket in self.brackets.items():
   1242             if not bracket or bracket.destroyed or key == session.shipid:
   1243                 continue
   1244             if bracket.categoryID not in BRACKET_CATEGORIES_WITH_RANGE_MARKER:
   1245                 continue
   1246             settingConfigName = 'showCategoryInTargetRange_%s' % bracket.categoryID
   1247             showCategory = sm.GetService('overviewPresetSvc').GetSettingValueOrDefaultFromName(settingConfigName, True)
   1248             distance = self.GetBallDistanceFromBracketKey(bp, key)
   1249             if distance is None:
   1250                 continue
   1251             canTargetSprite = bracket.GetCanTargetSprite()
   1252             if canTargetSprite is not None:
   1253                 if distance > maxTargetRange or not showCategory:
   1254                     newOpacity = 0.0
   1255                     canTargetSprite.display = False
   1256                     continue
   1257                 elif getattr(bracket, 'brighterForRange', False):
   1258                     newOpacity = 1.0
   1259                 else:
   1260                     newOpacity = 0.15
   1261                 canTargetSprite.display = True
   1262                 if canTargetSprite.opacity != newOpacity:
   1263                     canTargetSprite.opacity = newOpacity or 0
   1264 
   1265     def ShowModuleRange(self, moduleID, rangeDistance, *args):
   1266         showInTargetRange = sm.GetService('overviewPresetSvc').GetSettingValueOrDefaultFromName(osConst.SETTING_TARGET_RANGE, True)
   1267         if not showInTargetRange:
   1268             return
   1269         bp = sm.GetService('michelle').GetBallpark()
   1270         maxTargetRange = sm.GetService('godma').GetItem(session.shipid).maxTargetRange
   1271         for key, bracket in self.brackets.items():
   1272             if not bracket or bracket.destroyed or key == session.shipid:
   1273                 continue
   1274             if bracket.categoryID not in BRACKET_CATEGORIES_WITH_RANGE_MARKER:
   1275                 continue
   1276             distance = self.GetBallDistanceFromBracketKey(bp, key)
   1277             if distance is None:
   1278                 continue
   1279             if distance <= rangeDistance and distance <= maxTargetRange:
   1280                 bracket.brighterForRange = True
   1281                 canTargetSprite = bracket.GetCanTargetSprite()
   1282                 if canTargetSprite is not None:
   1283                     canTargetSprite.opacity = 1.0
   1284 
   1285     def ShowHairlinesForModule(self, moduleID, reverse = False):
   1286         showHairlines = sm.GetService('overviewPresetSvc').GetSettingValueOrDefaultFromName(osConst.SETTING_MODULE_HAIRLINES, True)
   1287         if not showHairlines:
   1288             if self.hairlinesTimer:
   1289                 self.hairlinesTimer = None
   1290                 self.StopShowingHairlines()
   1291                 ship = sm.GetService('michelle').GetBall(session.shipid)
   1292                 for moduleID in ship.modules:
   1293                     self.ResetModuleIcon(moduleID)
   1294 
   1295             return
   1296         for target in sm.GetService('target').targetsByID.itervalues():
   1297             if not isinstance(target, TargetInBar):
   1298                 continue
   1299             if target is None or target.destroyed:
   1300                 continue
   1301             if moduleID in target.activeModules:
   1302                 weapon = target.GetWeapon(moduleID)
   1303                 icon = weapon.icon
   1304                 icon.SetAlpha(1.5)
   1305                 bracket = self.brackets.get(target.itemID)
   1306                 if bracket is None:
   1307                     return
   1308                 self.ShowHairlines(moduleID, bracket, target, reverse)
   1309                 return
   1310 
   1311     def ShowHairlines(self, moduleID, bracket, target, reverse, *args):
   1312         if getattr(self, 'vectorLines', None) is None:
   1313             self.vectorLines = bracketVarious.TargetingHairlines()
   1314             self.vectorLines.CreateHairlines(moduleID, bracket, target)
   1315         self.vectorLines.UpdateHairlinePoints(moduleID, bracket, target)
   1316         self.vectorLines.StartAnimation(reverse=reverse)
   1317         self.hairlinesTimer = AutoTimer(50, self.AnimateVectorLine, moduleID, bracket, target)
   1318 
   1319     def AnimateVectorLine(self, moduleID, bracket, target, *args):
   1320         if getattr(self, 'vectorLines', None) is None:
   1321             return
   1322         if bracket.destroyed:
   1323             self.vectorLines.StopAnimations()
   1324             self.vectorLines.HideLines()
   1325             self.hairlinesTimer = None
   1326             return
   1327         self.vectorLines.UpdateHairlinePoints(moduleID, bracket, target)
   1328 
   1329     def StopShowingModuleRange(self, moduleID, *args):
   1330         for key, bracket in self.brackets.items():
   1331             if not bracket or bracket.destroyed:
   1332                 continue
   1333             if getattr(bracket, 'brighterForRange', False):
   1334                 canTargetSprite = bracket.GetCanTargetSprite()
   1335                 if canTargetSprite is not None:
   1336                     canTargetSprite.opacity = 0.3
   1337                 bracket.brighterForRange = False
   1338 
   1339         self.StopShowingHairlines()
   1340         self.ResetModuleIcon(moduleID)
   1341 
   1342     def ResetModuleIcon(self, moduleID, *args):
   1343         for target in sm.GetService('target').GetTargets().itervalues():
   1344             if not isinstance(target, TargetInBar):
   1345                 continue
   1346             target.ResetModuleIcon(moduleID)
   1347 
   1348     def StopShowingHairlines(self, *args):
   1349         self.hairlinesTimer = None
   1350         if getattr(self, 'vectorLines', None) is not None:
   1351             self.vectorLines.HideLines()
   1352             self.vectorLines.StopAnimations()
   1353 
   1354     def GetBallDistanceFromBracketKey(self, bp, bracketKey, *args):
   1355         ball = bp.GetBall(bracketKey)
   1356         if ball is None:
   1357             return
   1358         try:
   1359             distance = int(ball.surfaceDist)
   1360         except ValueError:
   1361             return
   1362 
   1363         return distance
   1364 
   1365     def OnMyFleetInited(self):
   1366         self.UpdateFleetColor()
   1367 
   1368     def OnStateSetupChange(self, *args):
   1369         self.UpdateFleetColor()
   1370 
   1371     def UpdateFleetColor(self):
   1372         flagInfo = self.stateSvc.GetStatePropsColorAndBlink(state.flagSameFleet)
   1373         self.fleetBracketColor = flagInfo.flagColor[:3] + (0.5,)
   1374 
   1375     def GetFleetBracketColor(self):
   1376         return self.fleetBracketColor
   1377 
   1378     def OnEmanationLockUpdated(self, lockDetails):
   1379         if not lockDetails or lockDetails.solar_system_id != session.solarsystemid2:
   1380             return
   1381         self._UpdateEmanationLock()
   1382 
   1383     def OnEmanationGateLockRemoved(self, *args):
   1384         if not session.solarsystemid:
   1385             return
   1386         self._UpdateEmanationLock()
   1387 
   1388     def _UpdateEmanationLock(self):
   1389         systemInfo = cfg.mapSolarSystemContentCache.get(session.solarsystemid2, None)
   1390         if not systemInfo:
   1391             return
   1392         self.RenewFlagForItemIDs(systemInfo.stargates.keys())