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

map2D.py (47476B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\maps\map2D.py
      2 import sys
      3 import math
      4 from math import pi
      5 import evetypes
      6 import carbon.client.script.util.lg as lg
      7 import trinity
      8 import uthread
      9 import carbonui.const as uiconst
     10 import localization
     11 import geo2
     12 from carbon.common.script.util import timerstuff
     13 from carbonui.primitives import vectorline, vectorarc
     14 from carbonui.primitives.container import Container
     15 from carbonui.primitives.polygon import Polygon
     16 from carbonui.primitives.sprite import Sprite
     17 from carbonui.primitives.transform import Transform
     18 from carbonui.uicore import uicore
     19 from carbonui.util.various_unsorted import FlushList, SortListOfTuples
     20 from eve.client.script.ui.control.eveLabel import EveLabelMedium
     21 from eve.client.script.ui.util import uix
     22 from eve.common.lib import appConst as const
     23 from eveservices.menu import GetMenuService
     24 from menu import MenuLabel
     25 DRAW_REGIONS = 1
     26 DRAW_CONSTELLATIONS = 2
     27 DRAW_SOLARSYSTEMS = 3
     28 DRAW_SOLARSYSTEM_INTERIOR = 4
     29 FLIPMAP = -1
     30 
     31 class Map2D(Container):
     32     __guid__ = 'xtriui.Map2D'
     33     __nonpersistvars__ = []
     34     __notifyevents__ = ['OnDestinationSet']
     35     tooltipPositionRect = None
     36 
     37     def ApplyAttributes(self, attributes):
     38         Container.ApplyAttributes(self, attributes)
     39         sm.RegisterNotify(self)
     40         self.sr.sizefactor = None
     41         self.sr.sizefactorsize = None
     42         self.sr.marks = None
     43         self.Reset()
     44         self.overlays = Container(name='overlays', parent=self, clipChildren=1, pos=(0, 0, 0, 0))
     45         self.sr.areas = Container(name='areas', parent=self, clipChildren=1, pos=(0, 0, 0, 0))
     46         self.hilite = Sprite(parent=self.overlays, pos=(0, 0, 16, 16), color=(1.0, 1.0, 1.0, 0.4), name='hilite', state=uiconst.UI_HIDDEN, texturePath='res:/UI/Texture/Shared/circleThin16.png', align=uiconst.RELATIVE)
     47         self.imhere = Container(name='imhere', parent=self.overlays, state=uiconst.UI_HIDDEN, align=uiconst.TOPLEFT, width=16, height=16)
     48         circle = Sprite(parent=self.imhere, idx=0, pos=(0, 0, 16, 16), color=(1.0, 0.0, 0.0, 1.0), name='imhere_sprite', texturePath='res:/UI/Texture/Shared/circleThin16.png', align=uiconst.RELATIVE)
     49         self.destination = Sprite(parent=self.overlays, pos=(0, 0, 16, 16), color=(1.0, 1.0, 0.0, 1.0), state=uiconst.UI_HIDDEN, name='destination', texturePath='res:/UI/Texture/Shared/circleThin16.png', align=uiconst.RELATIVE)
     50         self.sprite = Container(name='mapsprite', parent=self, align=uiconst.TOALL, clipChildren=1)
     51         self.bgSprite = None
     52         self.dragging = 0
     53         self.ditherIn = 1
     54         self.dragAllowed = 0
     55         self.dataLayer = None
     56         self.dataToggle = 0
     57         self.dataArgs = {}
     58         self.dataLoaded = None
     59         self.needsize = None
     60         self.allowAbstract = 1
     61         self.fillSize = 0.8
     62         self.mouseHoverGroups = []
     63         self.cordsAsPortion = {}
     64         self.fov = None
     65         self.tempAngleFov = None
     66 
     67     def SetInfoMode(self):
     68         self.updatemylocationtimer = None
     69         FlushList(self.imhere.children[1:])
     70         for each in self.children:
     71             if each.name == 'frame':
     72                 each.Close()
     73 
     74     def MarkAreas(self, areas = []):
     75         uthread.pool('Map2D::_MarkAreas', self._MarkAreas, areas)
     76 
     77     def _MarkAreas(self, areas):
     78         size = self.absoluteRight - self.absoluteLeft
     79         self.sr.areas.Flush()
     80         for area in areas:
     81             id, hint, (absX, absY, absZ), radius, color = area
     82             maxdist = self.GetMaxDist()
     83             sizefactor = size / 2 / maxdist * self.fillSize
     84             x = FLIPMAP * absX * sizefactor / float(size) + 0.5
     85             y = absZ * sizefactor / float(size) + 0.5
     86             rad = radius * sizefactor / float(size)
     87             mark = Sprite(parent=self.sr.areas, name='area', left=int(int(x * size) - mark.width / 2), top=int(int(y * size) - mark.height / 2 + 1), width=int(rad * size * 2), height=int(rad * size * 2), state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/circle_full.png', color=(1.0, 0.2, 0.2, 1.0))
     88             mark.sr.x = x
     89             mark.sr.y = y
     90             mark.sr.rad = rad
     91 
     92     def SetMarks(self, marks = []):
     93         uthread.pool('Map2D::SetMarks', self._SetMarks, marks)
     94 
     95     def _SetMarks(self, marks):
     96         if not self.IsUnder(uicore.desktop):
     97             return
     98         for i in xrange(0, len(marks), 4):
     99             id = marks[i]
    100             hint = marks[i + 1]
    101             size = max(1, self.absoluteRight - self.absoluteLeft)
    102             x, y = self.GetCordsByKeyAsPortion(id, size)
    103             if x is None or y is None:
    104                 return
    105             if self.sr.marks is None:
    106                 self.sr.marks = Container(name='marks', parent=self, align=uiconst.TOALL, pos=(0, 0, 0, 0), idx=0, state=uiconst.UI_DISABLED)
    107             mark = Sprite(parent=self.sr.marks, name='area', left=x - mark.width / 2, top=y - mark.height / 2 + 1, width=128, height=128, state=uiconst.UI_PICKCHILDREN, texturePath='res:/UI/Texture/circle_full.png', color=(1.0, 1.0, 1.0, 0.21))
    108             if hint:
    109                 EveLabelMedium(text=hint, parent=self.sr.marks, left=mark.left + mark.width, top=mark.top + 2, width=min(128, max(64, size - mark.left - mark.width)), state=uiconst.UI_NORMAL)
    110 
    111     def OnDestinationSet(self, destinationID, *args):
    112         if self is None or self.destroyed:
    113             return
    114         self.CheckDestination()
    115 
    116     def Reset(self):
    117         self.portion = 0.75
    118         self.areas = []
    119         self.orbs = []
    120         self.hilite = None
    121         self.imhere = None
    122         self.overlays = None
    123         self.lasthilite = None
    124         self.pickradius = 6
    125         self.mapitems = []
    126         self.outsideitems = []
    127         self.ids = None
    128         self.idlevel = None
    129         self.drawlevel = None
    130         self.clipped = 0
    131         self.updatemylocationtimer = None
    132         self.showingtempangle = None
    133         self.settings = None
    134 
    135     def _OnClose(self):
    136         sm.UnregisterNotify(self)
    137         self.updatemylocationtimer = None
    138         for each in self.overlays.children:
    139             if each.name == 'destinationline':
    140                 if hasattr(each, 'renderObject') and each.renderObject and len(each.renderObject.children):
    141                     for _each in each.renderObject.children:
    142                         _each.object.numPoints = 0
    143                         del _each.object.vectorCurve.keys[:]
    144                         each.renderObject.children.remove(_each)
    145 
    146                 each.renderObject = None
    147                 each.Close()
    148 
    149         self.OnSelectItem = None
    150         self.Reset()
    151 
    152     def Draw(self, ids, idlevel, drawlevel, needsize, sprite = None, solarsystem = None, lineColors = None, dotColor = None, dotSizeMultiplier = None):
    153         _settings = (ids,
    154          idlevel,
    155          drawlevel,
    156          needsize)
    157         if _settings == self.settings:
    158             return
    159         self.settings = _settings
    160         lg.Info('2Dmaps', 'Drawing map, ids/idlevel/drawlevel:', ids, idlevel, drawlevel)
    161         if drawlevel <= idlevel:
    162             return
    163         if drawlevel == DRAW_SOLARSYSTEM_INTERIOR and len(ids) > 1:
    164             ids = ids[:1]
    165         SIZE = needsize
    166         if sprite is None:
    167             sprite = self.sprite
    168         sprite.Flush()
    169         _ids = {}
    170         for id in ids:
    171             _ids[id] = ''
    172 
    173         ids = _ids.keys()
    174         endid = ''
    175         if len(ids) > 1:
    176             endid = '%s_' % ids[-1]
    177         self.ids = ids
    178         self.idlevel = idlevel
    179         self.drawlevel = drawlevel
    180         self.needsize = needsize
    181         imageid = '%s_%s_%s_%s_%s_%s' % (ids[0],
    182          '_' * max(0, len(ids) - 2),
    183          endid,
    184          idlevel,
    185          drawlevel,
    186          self.fillSize)
    187         imageid = imageid.replace('.', '')
    188         if self.drawlevel == DRAW_SOLARSYSTEM_INTERIOR:
    189             imageid += '_' + str(settings.user.ui.Get('solarsystemmapabstract', 0))
    190         lg.Info('2Dmaps', 'MapID is: %s' % imageid)
    191         for each in self.overlays.children:
    192             if each.name == 'destinationline':
    193                 each.renderObject = None
    194                 each.Close()
    195 
    196         self.cordsAsPortion = {}
    197         mapitems = self.mapitems = self.GetMapData(ids, idlevel, drawlevel)
    198         if drawlevel == 4:
    199             self.DrawSolarsystem(sprite, ids, imageid, mapitems, SIZE)
    200             self.CheckMyLocation(solarsystem=solarsystem)
    201             return
    202         connections, outsideitems = self.GetConnectionData(ids, idlevel, drawlevel)
    203         self.outsideitems = outsideitems
    204         minx = 1e+100
    205         maxx = -1e+100
    206         minz = 1e+100
    207         maxz = -1e+100
    208         for item in mapitems:
    209             minx = min(minx, item.x)
    210             maxx = max(maxx, item.x)
    211             minz = min(minz, item.z)
    212             maxz = max(maxz, item.z)
    213 
    214         mw = -minx + maxx
    215         mh = -minz + maxz
    216         if not mw:
    217             mw = 1e-07
    218         if not mh:
    219             mh = 1e-07
    220         dotrad = [2,
    221          3,
    222          4,
    223          5,
    224          6][idlevel]
    225         sizefactor = min(SIZE / mw, SIZE / mh) * self.portion
    226         cords = {}
    227         for item in mapitems[:]:
    228             if item.groupID == const.groupRegion:
    229                 if drawlevel != 1:
    230                     continue
    231             if item.groupID == const.groupConstellation:
    232                 if drawlevel != 2:
    233                     continue
    234             x = int(item.x * sizefactor - int(minx * sizefactor) + (SIZE - mw * sizefactor) / 2)
    235             y = int(item.z * sizefactor - int(minz * sizefactor) + (SIZE - mh * sizefactor) / 2)
    236             cords[item.itemID] = (x,
    237              SIZE - y,
    238              dotrad,
    239              1,
    240              16777215)
    241 
    242         for item in self.outsideitems:
    243             x = int(item.x * sizefactor - int(minx * sizefactor) + (SIZE - mw * sizefactor) / 2)
    244             y = int(item.z * sizefactor - int(minz * sizefactor) + (SIZE - mh * sizefactor) / 2)
    245             cords[item.itemID] = (x,
    246              SIZE - y,
    247              dotrad,
    248              0,
    249              None)
    250 
    251         for x, y, dotrad, cordtype, col in cords.itervalues():
    252             if cordtype == 0:
    253                 dotrad = dotrad / 2
    254             if dotSizeMultiplier is not None:
    255                 dotrad = dotrad * dotSizeMultiplier
    256             Sprite(parent=sprite, align=uiconst.TOPLEFT, left=x - dotrad, top=y - dotrad, width=2 * dotrad, height=2 * dotrad, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED, color=dotColor)
    257 
    258         done = []
    259         i = 0
    260         lineWidth = 1.0
    261         if lineColors is None:
    262             lineColors = [(0, 0.7, 0, 1), (0, 0, 1, 1), (1, 0, 0, 1)]
    263         for jumptype in connections:
    264             for pair in jumptype:
    265                 fr, to = pair
    266                 if (fr, to) in done:
    267                     continue
    268                 if fr in cords and to in cords:
    269                     color = lineColors[i]
    270                     vectorline.VectorLine(parent=sprite, translationFrom=cords[fr], widthFrom=lineWidth, translationTo=cords[to], widthTo=lineWidth, colorFrom=color, colorTo=color, align=uiconst.TOPLEFT)
    271 
    272             i += 1
    273 
    274         self.areas = [ (cords[id][0],
    275          cords[id][1],
    276          cords[id][2],
    277          id) for id in cords.iterkeys() ]
    278         self.cordsAsPortion = {}
    279         for id in cords.iterkeys():
    280             self.cordsAsPortion[id] = (cords[id][0] / float(SIZE), cords[id][1] / float(SIZE))
    281 
    282         self.CheckMyLocation(solarsystem=solarsystem)
    283         self.CheckDestination()
    284 
    285     def CheckDestination(self):
    286         if self is None or self.destroyed:
    287             return
    288         destination = sm.GetService('starmap').GetDestination()
    289         if destination and self.drawlevel == DRAW_SOLARSYSTEMS:
    290             x, y = self.GetCordsByKeyAsPortion(destination)
    291             if x is None or y is None:
    292                 return
    293             self.destination.sr.x, self.destination.sr.y = x, y
    294             self.destination.state = uiconst.UI_DISABLED
    295             self.RefreshOverlays(1)
    296         else:
    297             for each in self.overlays.children:
    298                 if each.name == 'destinationline':
    299                     each.renderObject = None
    300                     each.Close()
    301 
    302     def GetMapData(self, ids, idlevel, drawlevel):
    303         if idlevel != 3 and drawlevel != idlevel + 1:
    304             raise Exception('map2d.py GetMapData: Unexpected usage pattern for this function! idlevel: %i, drawLevel: %i' % (idlevel, drawlevel))
    305         if len(ids) != 1:
    306             raise Exception('map2d.py GetMapData: Unexpected usage pattern for this function! Many IDs:' + str(ids))
    307         if drawlevel == DRAW_REGIONS:
    308             return GetMap2DItemsForUniverse()
    309         elif drawlevel == DRAW_CONSTELLATIONS:
    310             return GetMap2DItemsForRegion(ids[0])
    311         elif drawlevel == DRAW_SOLARSYSTEMS:
    312             return GetMap2DItemsForConstellation(ids[0])
    313         else:
    314             return GetMap2DItemsForSolarSystem(ids[0])
    315 
    316     def GetConnectionData(self, ids, idlevel, drawlevel):
    317         if len(ids) != 1:
    318             raise Exception('unexpectedly many IDs passed to GetConnectionData: %s' % str(ids))
    319         if drawlevel == DRAW_REGIONS:
    320             return GetMap2DConnectionsForUniverse()
    321         if drawlevel == DRAW_CONSTELLATIONS:
    322             return GetMap2DConstellationConnectionsForRegion(ids[0])
    323         if drawlevel == DRAW_SOLARSYSTEMS:
    324             return GetMap2DConnectionsForConstellation(ids[0])
    325         raise Exception('map2D GetConnectionData unexpectedly asked for connections for drawlevel %i', drawlevel)
    326 
    327     def Width(self):
    328         return self.absoluteRight - self.absoluteLeft
    329 
    330     def Height(self):
    331         return self.absoluteBottom - self.absoluteTop
    332 
    333     def MyHierarchy(self):
    334         return (session.regionid,
    335          session.constellationid,
    336          session.solarsystemid2,
    337          session.stationid)
    338 
    339     def CheckMyLocation(self, solarsystem = None):
    340         if self is None or self.destroyed:
    341             return
    342         self.updatemylocationtimer = None
    343         self.imhere.sr.x = self.imhere.sr.y = None
    344         self.imhere.state = uiconst.UI_HIDDEN
    345         self.destination.sr.x = self.destination.sr.y = None
    346         self.destination.state = uiconst.UI_HIDDEN
    347         destination = sm.GetService('starmap').GetDestination()
    348         if self.drawlevel < DRAW_SOLARSYSTEM_INTERIOR or session.stationid:
    349             for locationID in self.cordsAsPortion.iterkeys():
    350                 if locationID in self.MyHierarchy() or locationID == solarsystem:
    351                     self.imhere.sr.x, self.imhere.sr.y = self.cordsAsPortion[locationID]
    352                     self.imhere.state = uiconst.UI_DISABLED
    353                 if destination and locationID == destination:
    354                     self.destination.sr.x, self.destination.sr.y = self.cordsAsPortion[locationID]
    355                     self.destination.state = uiconst.UI_DISABLED
    356 
    357         elif self.ids[0] == session.solarsystemid2:
    358             self.updatemylocationtimer = timerstuff.AutoTimer(100, self.UpdateMyLocation)
    359             uthread.new(self.UpdateMyLocation)
    360         self.RefreshOverlays(1)
    361 
    362     def UpdateMyLocation(self):
    363         if not self.IsUnder(uicore.desktop):
    364             return
    365         bp = sm.GetService('michelle').GetBallpark()
    366         if bp is None or self is None or self.destroyed:
    367             self.updatemylocationtimer = None
    368             return
    369         myball = bp.GetBall(session.shipid)
    370         if myball is None:
    371             self.updatemylocationtimer = None
    372             return
    373         size = max(1, self.absoluteRight - self.absoluteLeft)
    374         if size == 1:
    375             size = max(1, self.absoluteRight - self.absoluteLeft)
    376         x = y = None
    377         if self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0):
    378             if not len(self.orbs):
    379                 return
    380             x, y = self.GetAbstractPosition((myball.x, 0.0, myball.z), 1)
    381         elif self.sr.sizefactor is not None and self.sr.sizefactorsize is not None:
    382             maxdist = self.GetMaxDist()
    383             sizefactor = size / 2 / maxdist * self.fillSize
    384             x = FLIPMAP * myball.x * sizefactor / float(size) + 0.5
    385             y = -(myball.z * sizefactor) / float(size) + 0.5
    386         if x is not None and y is not None:
    387             self.imhere.sr.x = x
    388             self.imhere.sr.y = y
    389             self.imhere.state = uiconst.UI_DISABLED
    390         scene = sm.GetService('sceneManager').GetRegisteredScene('default')
    391         camera = sm.GetService('sceneManager').GetActiveCamera()
    392         if camera is None:
    393             return
    394         yaw = camera.GetYaw()
    395         if not self.fov:
    396             self.fov = Fov(parent=self.imhere)
    397         self.fov.SetRotation(yaw)
    398         actualfov = camera.fov * (uicore.desktop.width / float(uicore.desktop.height))
    399         degfov = actualfov - pi / 2
    400         self.fov.SetFovAngle(actualfov)
    401         if self.showingtempangle:
    402             if not self.tempAngleFov:
    403                 self.tempAngleFov = Fov(parent=self.imhere, state=uiconst.UI_DISABLED, blendMode=trinity.TR2_SBM_ADDX2)
    404                 self.tempAngleFov.SetColor((0.0, 0.3, 0.0, 1.0))
    405             self.tempAngleFov.display = True
    406             self.tempAngleFov.SetRotation(yaw)
    407             angle = self.showingtempangle
    408             self.tempAngleFov.SetFovAngle(angle)
    409         elif self.tempAngleFov:
    410             self.tempAngleFov.display = False
    411         self.RefreshOverlays()
    412 
    413     def SetTempAngle(self, angle):
    414         if self.imhere is None or self.imhere.destroyed or len(self.imhere.children) <= 1:
    415             return
    416         self.showingtempangle = angle
    417 
    418     def GetRegionColor(self, regionID):
    419         color = trinity.TriColor()
    420         color.SetHSV(float(regionID) * 21 % 360.0, 0.5, 0.8)
    421         color.a = 0.75
    422         return color
    423 
    424     def GetAbstractPosition(self, pos, asPortion = 0, size = None):
    425         if not len(self.orbs):
    426             return (None, None)
    427         dist = geo2.Vec3Length(pos)
    428         maxorb = None
    429         minorb = (0.0, 0)
    430         for orbdist, pixelrad, orbititem, SIZE in self.orbs:
    431             if orbdist < dist:
    432                 minorb = (orbdist, pixelrad)
    433             elif orbdist > dist and maxorb is None:
    434                 maxorb = (orbdist, pixelrad)
    435 
    436         mindist, minpixelrad = minorb
    437         distInPixels = minpixelrad
    438         if maxorb:
    439             maxdist, maxpixelrad = maxorb
    440             rnge = maxdist - mindist
    441             pixelrnge = maxpixelrad - minpixelrad
    442             posWithinRange = dist - mindist
    443             distInPixels += pixelrnge * (posWithinRange / rnge)
    444         sizefactor = float(distInPixels) / dist
    445         if asPortion:
    446             size = max(1, self.absoluteRight - self.absoluteLeft)
    447             return (float(size) / (FLIPMAP * pos[0] * sizefactor + SIZE / 2), float(size) / (pos[2] * sizefactor + SIZE / 2))
    448         return (int(FLIPMAP * pos[0] * sizefactor) + SIZE / 2, int(pos[2] * sizefactor) + SIZE / 2)
    449 
    450     def GetPick(self):
    451         areas = []
    452         size = max(1, self.absoluteRight - self.absoluteLeft)
    453         radius = 2
    454         isAbstract = self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0) == 1
    455         for locationID in self.cordsAsPortion.iterkeys():
    456             if len(self.mouseHoverGroups) and not isAbstract:
    457                 locationrec = self.GetItemRecord(locationID)[0]
    458                 if not locationrec or locationrec.groupID not in self.mouseHoverGroups:
    459                     continue
    460             x, y = self.GetCordsByKeyAsPortion(locationID, size)
    461             if x is None or y is None:
    462                 continue
    463             if int(x - radius - 3) <= uicore.uilib.x - self.absoluteLeft <= int(x + radius + 3) and int(y - radius - 3) <= uicore.uilib.y - self.absoluteTop <= int(y + radius + 3):
    464                 areas.append(locationID)
    465 
    466         return areas
    467 
    468     def GetItemRecord(self, getkey):
    469         for each in self.mapitems:
    470             if not hasattr(each, 'itemID'):
    471                 continue
    472             if each.itemID == getkey:
    473                 return (each, 1)
    474 
    475         for each in self.outsideitems:
    476             if not hasattr(each, 'itemID'):
    477                 continue
    478             if each.itemID == getkey:
    479                 return (each, 0)
    480 
    481         return (None, None)
    482 
    483     def GetCordsByKeyAsPortion(self, locationID, size = None):
    484         if size is None:
    485             return self.cordsAsPortion.get(locationID, (None, None))
    486         x, y = self.cordsAsPortion.get(locationID, (None, None))
    487         if x is not None and y is not None:
    488             return (int(x * size), int(y * size))
    489         return (None, None)
    490 
    491     def ToggleAbstract(self, setTo):
    492         uthread.new(self._ToggleAbstract, setTo)
    493 
    494     def _ToggleAbstract(self, setTo):
    495         settings.user.ui.Set('solarsystemmapabstract', setTo)
    496         self.settings = None
    497         self.Draw(self.ids, self.idlevel, self.drawlevel, self.needsize)
    498 
    499     def SetSelected(self, ids):
    500         if self is None or self.destroyed:
    501             return
    502         for each in self.overlays.children[:]:
    503             if each.name == 'selected':
    504                 each.Close()
    505 
    506         for id in ids:
    507             x, y = self.GetCordsByKeyAsPortion(id)
    508             if x is not None and y is not None:
    509                 newsel = Container(parent=self.overlays, name='selected', align=uiconst.TOPLEFT, width=16, height=16, state=uiconst.UI_DISABLED)
    510                 pointer = Sprite(parent=newsel, pos=(0, 0, 16, 32), state=uiconst.UI_PICKCHILDREN, texturePath='res:/UI/Texture/Shared/circlePointerDown.png', color=(1.0, 1.0, 1.0, 0.4))
    511                 newsel.sr.x = x
    512                 newsel.sr.y = y
    513 
    514         self.RefreshOverlays(1)
    515 
    516     def _OnResize(self):
    517         if self.align == uiconst.TOTOP:
    518             self.height = self.absoluteRight - self.absoluteLeft
    519         elif self.align in (uiconst.TOLEFT, uiconst.TORIGHT):
    520             self.width = self.absoluteBottom - self.absoluteTop
    521         try:
    522             self.RefreshOverlays(1)
    523         except:
    524             sys.exc_clear()
    525 
    526     def RefreshOverlays(self, update = 0):
    527         if not self.IsUnder(uicore.desktop):
    528             return
    529         if self is None or self.destroyed or not uicore.uilib:
    530             return
    531         size = self.absoluteRight - self.absoluteLeft
    532         for each in self.sr.areas.children:
    533             if not hasattr(each, 'sr') or getattr(each.sr, 'x', None) is None and getattr(each.sr, 'y', None) is None:
    534                 continue
    535             each.width = each.height = int(each.sr.rad * size * 2)
    536             each.left = int(getattr(each.sr, 'x', 0) * size) - each.width / 2 + 1
    537             each.top = int(getattr(each.sr, 'y', 0) * size) - each.height / 2 + 1
    538 
    539         for each in self.overlays.children:
    540             if not hasattr(each, 'sr') or getattr(each.sr, 'x', None) is None and getattr(each.sr, 'y', None) is None:
    541                 continue
    542             each.left = int(getattr(each.sr, 'x', 0) * size) - each.width / 2 + 1
    543             each.top = int(getattr(each.sr, 'y', 0) * size) - each.height / 2 + 1
    544 
    545     def OnClick(self, *args):
    546         areas = self.GetPick()
    547         if areas:
    548             self.OnSelectItem(self, areas[0])
    549 
    550     def OnMouseDown(self, *args):
    551         if self.dragAllowed:
    552             self.dragging = 1
    553 
    554     def OnMouseUp(self, *args):
    555         if self.dragging:
    556             self.left = max(-self.width + 24, min(self.parent.absoluteRight - self.parent.absoluteLeft - 24, self.left))
    557             self.top = max(-self.height + 24, min(self.parent.absoluteBottom - self.parent.absoluteTop - 24, self.top))
    558             self.SetOrder(-1)
    559         self.dragging = 0
    560 
    561     def SetHint(self, hint):
    562         self.hilite.state = uiconst.UI_HIDDEN
    563         refresh = self.sr.hint != hint
    564         self.sr.hint = hint
    565         self.hilite.state = uiconst.UI_DISABLED
    566         if refresh:
    567             uicore.uilib.tooltipHandler.RefreshTooltipForOwner(self)
    568 
    569     def GetTooltipPosition(self):
    570         if self.tooltipPositionRect:
    571             return self.tooltipPositionRect
    572 
    573     def OnMouseMove(self, *args):
    574         if self.dragging:
    575             self.left = max(-self.width + 24, min(self.parent.absoluteRight - self.parent.absoluteLeft - 24, self.left))
    576             self.top = max(-self.height + 24, min(self.parent.absoluteBottom - self.parent.absoluteTop - 24, self.top))
    577             return
    578         areas = self.GetPick()
    579         if areas:
    580             if (areas[0], len(areas)) == self.lasthilite:
    581                 return
    582             self.lasthilite = (areas[0], len(areas))
    583             x, y = self.GetCordsByKeyAsPortion(areas[0], self.absoluteRight - self.absoluteLeft)
    584             if x is not None and y is not None:
    585                 self.hilite.left = x - self.hilite.width / 2
    586                 self.hilite.top = y - self.hilite.height / 2 + 1
    587                 self.hilite.state = uiconst.UI_DISABLED
    588                 locStr = ''
    589                 locStrList = []
    590                 for id in areas:
    591                     datarec, datahint = self.GetDataArgs(id)
    592                     item, insider = self.GetItemRecord(id)
    593                     if item:
    594                         groupname = evetypes.GetGroupNameByGroup(item.groupID)
    595                         if item.itemName.lower().find(groupname.lower()) >= 0:
    596                             groupname = ''
    597                         locStrList.append(localization.GetByLabel('UI/Map/Map2D/hintMouseMoveFormating', locationName=item.itemName, dataHint=datahint, locationGroupName=groupname))
    598                         if not insider:
    599                             parent = sm.GetService('map').GetItem(item.locationID)
    600                             linkTo = '<br>'.join(locStrList)
    601                             locStrList = [localization.GetByLabel('UI/Map/Map2D/hintMouseMove', group=evetypes.GetGroupNameByGroup(parent.groupID), parent=parent.itemName, linkTo=linkTo)]
    602 
    603                 locStr = '<br>'.join(locStrList)
    604                 self.SetHint(locStr)
    605                 self.tooltipPositionRect = (uicore.uilib.x - 6,
    606                  uicore.uilib.y - 6,
    607                  12,
    608                  12)
    609                 return
    610         self.SetHint('')
    611         self.hilite.state = uiconst.UI_HIDDEN
    612         self.lasthilite = None
    613 
    614     def OnMouseExit(self, *args):
    615         self.hilite.state = uiconst.UI_HIDDEN
    616 
    617     def GetMenu(self):
    618         m = []
    619         pick = self.GetPick()
    620         if len(pick) == 1:
    621             item, insider = self.GetItemRecord(pick[0])
    622             m += GetMenuService().CelestialMenu(pick[0], item)
    623         else:
    624             for itemID in pick:
    625                 item, insider = self.GetItemRecord(itemID)
    626                 if item:
    627                     submenu = GetMenuService().CelestialMenu(itemID, item)
    628                     if len(submenu):
    629                         if item.groupID == const.groupStation:
    630                             locationName = uix.EditStationName(item.itemName)
    631                         else:
    632                             locationName = item.itemName
    633                         groupname = evetypes.GetGroupNameByGroup(item.groupID)
    634                         if locationName.lower().find(groupname.lower()) >= 0:
    635                             groupname = ''
    636                         locationName = MenuLabel('UI/Map/Map2D/menuLocationEntry', {'locationName': locationName,
    637                          'groupName': groupname})
    638                         m.append((locationName, submenu))
    639 
    640             m.sort()
    641         if not m:
    642             m = self.GetParentMenu()
    643         if self.drawlevel == DRAW_SOLARSYSTEM_INTERIOR:
    644             if self.allowAbstract:
    645                 isAbstract = settings.user.ui.Get('solarsystemmapabstract', 0) == 1
    646                 if isAbstract:
    647                     lbl = MenuLabel('UI/Map/Map2D/menuShowNonAbstract')
    648                 else:
    649                     lbl = MenuLabel('UI/Map/Map2D/menuShowAbstract')
    650                 m += [None, (lbl, self.ToggleAbstract, (not isAbstract,))]
    651         return m
    652 
    653     def GetParentMenu(self):
    654         return []
    655 
    656     def GetMaxDist(self):
    657         maxdist = 0.0
    658         for item in self.mapitems:
    659             pos = (item.x, 0.0, item.z)
    660             maxdist = max(maxdist, geo2.Vec3Length(pos))
    661 
    662         return maxdist
    663 
    664     def DrawSolarsystem(self, sprite, ids, imageid, mapitems, SIZE):
    665         if not len(mapitems):
    666             return
    667         planets = []
    668         stargates = []
    669         asteroidbelts = []
    670         for item in mapitems:
    671             if item.groupID == const.groupPlanet:
    672                 planets.append(item)
    673             elif item.groupID == const.groupStargate:
    674                 stargates.append(item)
    675             elif item.groupID == const.groupAsteroidBelt:
    676                 asteroidbelts.append(item)
    677 
    678         cords = {}
    679         maxdist = 0.0
    680         for item in mapitems:
    681             pos = (item.x, 0.0, item.z)
    682             maxdist = max(maxdist, geo2.Vec3Length(pos))
    683             if item.groupID == const.groupSun:
    684                 Sprite(parent=sprite, align=uiconst.TOPLEFT, left=SIZE / 2 - 4, top=SIZE / 2 - 4, width=8, height=8, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED)
    685 
    686         sizefactor = SIZE / 2 / maxdist * self.fillSize
    687         self.sr.sizefactor = sizefactor
    688         self.sr.sizefactorsize = SIZE
    689         if self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0):
    690             _planets = []
    691             for planet in planets:
    692                 pos = (planet.x, planet.y, planet.z)
    693                 dist = geo2.Vec3Length(pos)
    694                 _planets.append([dist, planet])
    695 
    696             _planets = SortListOfTuples(_planets)
    697             planet = _planets
    698         i = 1
    699         for item in planets:
    700             pos = (item.x, 0.0, item.z)
    701             dist = geo2.Vec3Length(pos)
    702             if self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0):
    703                 planetscale = i * (maxdist / len(planets)) / dist
    704                 pos = geo2.Vec3Scale(pos, planetscale)
    705             x = FLIPMAP * pos[0] * sizefactor + SIZE / 2
    706             y = pos[2] * sizefactor + SIZE / 2
    707             radius = 1
    708             cords[item.itemID] = (x, SIZE - y, radius)
    709             Sprite(parent=sprite, align=uiconst.TOPLEFT, left=x - 4, top=SIZE - y - 4, width=8, height=8, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED, color=self.GetColorByGroupID(const.groupPlanet))
    710             self.AddChilds(x, y, radius, item.itemID, SIZE, sprite, cords, item)
    711             i += 1
    712 
    713         self.orbs = []
    714         for orbit in planets:
    715             if orbit.itemID in cords:
    716                 x, y, radius = cords[orbit.itemID]
    717                 center = SIZE / 2
    718                 frompos = geo2.Vector(float(center), 0.0, float(center))
    719                 topos = geo2.Vector(float(x), 0.0, float(y))
    720                 diff = topos - frompos
    721                 rad = int(geo2.Vec3Length(diff))
    722                 vectorarc.VectorArc(parent=sprite, align=uiconst.TOPLEFT, radius=rad, fill=False, left=center, lineWidth=1, top=center, width=SIZE, height=SIZE, color=self.GetColorByGroupID(const.groupPlanet), spriteEffect=trinity.TR2_SFX_FILL_AA)
    723                 orbpos = (orbit.x, 0.0, orbit.z)
    724                 orbdist = geo2.Vec3Length(orbpos)
    725                 self.orbs.append([orbdist, (orbdist,
    726                   rad,
    727                   orbit,
    728                   SIZE)])
    729 
    730         self.orbs = SortListOfTuples(self.orbs)
    731         for item in stargates:
    732             if self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0):
    733                 if not len(self.orbs):
    734                     return
    735                 x, y = self.GetAbstractPosition((item.x, 0.0, item.z))
    736             else:
    737                 x = FLIPMAP * self.sr.sizefactor * item.x + self.sr.sizefactorsize / 2
    738                 y = self.sr.sizefactor * item.z + self.sr.sizefactorsize / 2
    739             x += 6
    740             radius = 1
    741             Sprite(parent=sprite, align=uiconst.TOPLEFT, left=x - 4, top=SIZE - y - 4, width=8, height=8, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED, color=self.GetColorByGroupID(const.groupStargate))
    742             cords[item.itemID] = (x, SIZE - y, radius)
    743 
    744         self.areas = [ (cords[id][0],
    745          cords[id][1],
    746          cords[id][2],
    747          id) for id in cords.iterkeys() ]
    748         self.cordsAsPortion = {}
    749         for id in cords.iterkeys():
    750             self.cordsAsPortion[id] = (cords[id][0] / float(SIZE), cords[id][1] / float(SIZE))
    751 
    752         if self.destroyed:
    753             return
    754         self.PlaceBackground('res:/UI/Texture/map_ssunderlay.png')
    755 
    756     def AddChilds(self, parentX, parentY, parentRad, parentID, SIZE, sprite, cords, parent, _x = None, _y = None):
    757         parentpos = geo2.Vector(parent.x, parent.y, parent.z)
    758         sorted = []
    759         allchilds = self.GetChilds(parentID, [], 0)
    760         for child in allchilds:
    761             childpos = geo2.Vector(child.x, child.y, child.z)
    762             diff = childpos - parentpos
    763             dist = geo2.Vec3Length(diff)
    764             sorted.append((dist, child))
    765 
    766         sorted = SortListOfTuples(sorted)
    767         if self.allowAbstract and settings.user.ui.Get('solarsystemmapabstract', 0):
    768             done = []
    769             i = 1
    770             xi = 0
    771             for child in sorted:
    772                 if child.itemID in done:
    773                     continue
    774                 radius = 1
    775                 step = max(12, radius * 4) - 2
    776                 y = _y or parentY + parentRad + i * step
    777                 x = _x or parentX + xi
    778                 if y + step > SIZE:
    779                     i = 0
    780                     xi += step
    781                 done.append(child.itemID)
    782                 fill = self.GetColorByGroupID(child.groupID)
    783                 Sprite(parent=sprite, align=uiconst.TOPLEFT, left=x - 2, top=SIZE - y - 2, width=4, height=4, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED, color=self.GetColorByGroupID(child.groupID))
    784                 cords[child.itemID] = (x, SIZE - y, radius)
    785                 i += 1
    786 
    787         else:
    788             for child in sorted:
    789                 radius = 1
    790                 pos = geo2.Vector(child.x, 0.0, child.z)
    791                 pos = pos + (pos - parentpos) * max(1.0, 4096 / SIZE)
    792                 x = FLIPMAP * pos.x * self.sr.sizefactor + SIZE / 2
    793                 y = pos.z * self.sr.sizefactor + SIZE / 2
    794                 fill = self.GetColorByGroupID(child.groupID)
    795                 Sprite(parent=sprite, align=uiconst.TOPLEFT, left=x - 2, top=SIZE - y - 2, width=4, height=4, texturePath='res:/UI/Texture/classes/graph/point.png', state=uiconst.UI_DISABLED, color=self.GetColorByGroupID(child.groupID))
    796                 cords[child.itemID] = (x, SIZE - y, radius)
    797 
    798     def GetChilds(self, parentID, childs, i):
    799         i += 1
    800         if i == 20 or len(childs) > 1000:
    801             return childs
    802         _childs = [ child for child in self.mapitems if child.orbitID == parentID and child not in childs ]
    803         if len(_childs):
    804             childs += _childs
    805             for granchild in _childs:
    806                 childs = self.GetChilds(granchild.itemID, childs, i)
    807 
    808         return childs
    809 
    810     def GetColorByGroupID(self, groupID):
    811         col = {const.groupAsteroidBelt: (0, 0, 1),
    812          const.groupPlanet: (0.53, 0.53, 0.53),
    813          const.groupStargate: (0, 0.53, 0),
    814          const.groupStation: (1, 0.2, 0.2)}.get(groupID, (0.6, 0.6, 0.6))
    815         return col
    816 
    817     def GetDataArgs(self, locationID):
    818         if locationID in self.dataArgs:
    819             return self.dataArgs[locationID]
    820         return (None, '')
    821 
    822     def PlaceBackground(self, imagepath):
    823         if self is None or self.destroyed:
    824             return
    825         imagepath = str(imagepath)
    826         if self.bgSprite is None:
    827             self.bgSprite = Sprite(name='bgSprite', parent=self, align=uiconst.TOALL, state=uiconst.UI_DISABLED, color=(1.0, 1.0, 1.0, 1.0), texturePath=imagepath, filter=True)
    828 
    829     def OnSelectItem(self, _self, arg, *args):
    830         pass
    831 
    832 
    833 class Fov(Transform):
    834     default_name = 'fov'
    835     default_left = 0
    836     default_top = 0
    837     default_width = 128
    838     default_height = 128
    839     default_align = uiconst.CENTER
    840     default_state = uiconst.UI_NORMAL
    841 
    842     def ApplyAttributes(self, attributes):
    843         Transform.ApplyAttributes(self, attributes)
    844         blendMode = attributes.get('blendMode', trinity.TR2_SBM_BLEND)
    845         self.angle = math.pi
    846         self.color = (1.0, 1.0, 1.0, 0.5)
    847         self.polygon = Polygon(parent=self, align=uiconst.TOALL, blendMode=trinity.TR2_SBM_ADD)
    848         self.RenderGradient()
    849 
    850     def RenderGradient(self):
    851         self.polygon.Flush()
    852         directionAngle = math.pi / 2
    853         fromDeg = directionAngle - self.angle / 2
    854         toDeg = directionAngle + self.angle / 2
    855         numSegments = 40
    856         segmentStep = (toDeg - fromDeg) / float(numSegments)
    857         c = self.color
    858         innerColor = c
    859         outerColor = (c[0],
    860          c[1],
    861          c[2],
    862          0.0)
    863         radius = 50
    864         ro = self.polygon.GetRenderObject()
    865         for i in xrange(numSegments + 1):
    866             a = fromDeg + i * segmentStep
    867             x = math.cos(a)
    868             y = -math.sin(a)
    869             innerVertex = trinity.Tr2Sprite2dVertex()
    870             innerVertex.position = (self.width / 2 * uicore.desktop.dpiScaling, self.height / 2 * uicore.desktop.dpiScaling)
    871             innerVertex.color = innerColor
    872             ro.vertices.append(innerVertex)
    873             outerVertex = trinity.Tr2Sprite2dVertex()
    874             outerVertex.position = ((self.width / 2 + radius * x) * uicore.desktop.dpiScaling, (self.height / 2 + radius * y) * uicore.desktop.dpiScaling)
    875             outerVertex.color = outerColor
    876             ro.vertices.append(outerVertex)
    877 
    878         for i in xrange(numSegments * 2):
    879             triangle = trinity.Tr2Sprite2dTriangle()
    880             triangle.index0 = i
    881             triangle.index1 = i + 1
    882             triangle.index2 = i + 2
    883             ro.triangles.append(triangle)
    884 
    885     def SetColor(self, color):
    886         self.color = color
    887         self.RenderGradient()
    888 
    889     def SetFovAngle(self, angle):
    890         self.angle = angle
    891         self.RenderGradient()
    892 
    893 
    894 import collections
    895 Map2DItemInfoType = collections.namedtuple('Map2DItemInfoType', ['itemID',
    896  'typeID',
    897  'locationID',
    898  'itemName',
    899  'groupID',
    900  'x',
    901  'y',
    902  'z'])
    903 Map2DCelestialItemInfoType = collections.namedtuple('Map2DItemInfoType', ['itemID',
    904  'typeID',
    905  'orbitID',
    906  'orbitIndex',
    907  'celestialIndex',
    908  'locationID',
    909  'itemName',
    910  'groupID',
    911  'x',
    912  'y',
    913  'z'])
    914 
    915 def GetMap2DConnectionsForUniverse():
    916     connections = []
    917     for regionID, regionData in cfg.mapRegionCache.iteritems():
    918         if regionID > const.mapWormholeRegionMin:
    919             continue
    920         for neighbourID in regionData.neighbours:
    921             connections.append((regionID, neighbourID))
    922 
    923     return ((connections, [], []), [])
    924 
    925 
    926 def GetMap2DConstellationConnectionsForRegion(regionID):
    927     connectionsToOtherRegions = []
    928     connectionsWithinRegion = []
    929     externalItems = []
    930     regionInfo = cfg.mapRegionCache[regionID]
    931     constellationsInRegion = set(regionInfo.constellationIDs)
    932     for constellationID in constellationsInRegion:
    933         constellation = cfg.mapConstellationCache[constellationID]
    934         for neighbourID in constellation.neighbours:
    935             if neighbourID not in constellationsInRegion:
    936                 nei = cfg.mapConstellationCache[neighbourID]
    937                 i = Map2DItemInfoType(itemID=neighbourID, locationID=nei.regionID, itemName=localization.GetByMessageID(nei.nameID), groupID=const.groupConstellation, typeID=const.typeConstellation, x=nei.center.x, y=nei.center.y, z=nei.center.z)
    938                 externalItems.append(i)
    939                 connectionsToOtherRegions.append((constellationID, neighbourID))
    940             else:
    941                 connectionsWithinRegion.append((constellationID, neighbourID))
    942 
    943     return ((connectionsToOtherRegions, connectionsWithinRegion, []), externalItems)
    944 
    945 
    946 def GetMap2DConnectionsForConstellation(constellationID):
    947     connectionsToOtherRegions = []
    948     connectionsToOtherConstellations = []
    949     connectionsWithinConstellation = []
    950     externalItems = []
    951     constellationInfo = cfg.mapConstellationCache[constellationID]
    952     systemsInConstellation = set(constellationInfo.solarSystemIDs)
    953     regionInfo = cfg.mapRegionCache[constellationInfo.regionID]
    954     systemsInRegion = set(regionInfo.solarSystemIDs)
    955     for solarSystemID in systemsInConstellation:
    956         ssInfo = cfg.mapSystemCache[solarSystemID]
    957         for neighbour in ssInfo.neighbours:
    958             neighbourID = neighbour.solarSystemID
    959             if neighbourID in systemsInConstellation:
    960                 connectionsWithinConstellation.append((solarSystemID, neighbourID))
    961             else:
    962                 nei = cfg.mapSystemCache[neighbourID]
    963                 externalItems.append(Map2DItemInfoType(itemID=neighbourID, locationID=nei.constellationID, itemName=localization.GetByMessageID(nei.nameID), groupID=const.groupSolarSystem, typeID=const.typeSolarSystem, x=nei.center.x, y=nei.center.y, z=nei.center.z))
    964                 if neighbourID not in systemsInRegion:
    965                     connectionsToOtherRegions.append((solarSystemID, neighbourID))
    966                 elif neighbourID not in systemsInConstellation:
    967                     connectionsToOtherConstellations.append((solarSystemID, neighbourID))
    968 
    969     return ((connectionsToOtherRegions, connectionsToOtherConstellations, connectionsWithinConstellation), externalItems)
    970 
    971 
    972 def GetMap2DItemsForUniverse():
    973     items = []
    974     for regionID, regionData in cfg.mapRegionCache.iteritems():
    975         if regionID > const.mapWormholeRegionMin:
    976             continue
    977         i = Map2DItemInfoType(itemID=regionID, locationID=9, itemName=localization.GetByMessageID(regionData.nameID), groupID=const.groupRegion, typeID=const.typeRegion, x=regionData.center.x, y=regionData.center.y, z=regionData.center.z)
    978         items.append(i)
    979 
    980     return items
    981 
    982 
    983 def GetMap2DItemsForRegion(regionID):
    984     items = []
    985     regionData = cfg.mapRegionCache[regionID]
    986     items.append(Map2DItemInfoType(itemID=regionID, locationID=9, itemName=localization.GetByMessageID(regionData.nameID), groupID=const.groupRegion, typeID=const.typeRegion, x=regionData.center.x, y=regionData.center.y, z=regionData.center.z))
    987     for constellationID in regionData.constellationIDs:
    988         constellationData = cfg.mapConstellationCache[constellationID]
    989         items.append(Map2DItemInfoType(itemID=constellationID, locationID=constellationData.regionID, itemName=localization.GetByMessageID(constellationData.nameID), groupID=const.groupConstellation, typeID=const.typeConstellation, x=constellationData.center.x, y=constellationData.center.y, z=constellationData.center.z))
    990 
    991     return items
    992 
    993 
    994 def GetMap2DItemsForConstellation(constellationID):
    995     items = []
    996     constellationData = cfg.mapConstellationCache[constellationID]
    997     items.append(Map2DItemInfoType(itemID=constellationID, locationID=constellationData.regionID, itemName=localization.GetByMessageID(constellationData.nameID), groupID=const.groupConstellation, typeID=const.typeConstellation, x=constellationData.center.x, y=constellationData.center.y, z=constellationData.center.z))
    998     for solarSystemID in constellationData.solarSystemIDs:
    999         solarSystemData = cfg.mapSystemCache[solarSystemID]
   1000         items.append(Map2DItemInfoType(itemID=solarSystemID, locationID=solarSystemData.constellationID, itemName=localization.GetByMessageID(solarSystemData.nameID), groupID=const.groupSolarSystem, typeID=const.typeSolarSystem, x=solarSystemData.center.x, y=solarSystemData.center.y, z=solarSystemData.center.z))
   1001 
   1002     return items
   1003 
   1004 
   1005 def GetMap2DItemsForSolarSystem(solarSystemID):
   1006     items = []
   1007     try:
   1008         ssContents = cfg.mapSolarSystemContentCache[solarSystemID]
   1009     except (IndexError, KeyError):
   1010         return []
   1011 
   1012     sm.GetService('map').GetSolarsystemItems(solarSystemID)
   1013     primables = ssContents.stargates.keys() + ssContents.planets.keys()
   1014     for planet in ssContents.planets.itervalues():
   1015         moons = getattr(planet, 'moons', {})
   1016         primables += getattr(planet, 'asteroidBelts', {}).keys() + getattr(planet, 'npcStations', {}).keys() + moons.keys()
   1017         for moon in moons.itervalues():
   1018             primables += getattr(moon, 'asteroidBelts', {}).keys() + getattr(moon, 'npcStations', {}).keys()
   1019 
   1020     cfg.evelocations.Prime(primables)
   1021     for stargateID, stargate in ssContents.stargates.iteritems():
   1022         items.append(Map2DCelestialItemInfoType(itemID=stargateID, orbitID=1, orbitIndex=1, locationID=solarSystemID, celestialIndex=0, itemName=cfg.evelocations.Get(stargateID).locationName, groupID=const.groupStargate, typeID=stargate.typeID, x=stargate.position.x, y=stargate.position.y, z=stargate.position.z))
   1023 
   1024     for planetID, planet in ssContents.planets.iteritems():
   1025         items.append(Map2DCelestialItemInfoType(itemID=planetID, orbitID=1, orbitIndex=1, locationID=solarSystemID, celestialIndex=planet.celestialIndex, itemName=cfg.evelocations.Get(planetID).locationName, groupID=const.groupPlanet, typeID=planet.typeID, x=planet.position.x, y=planet.position.y, z=planet.position.z))
   1026         asteroidBelts = getattr(planet, 'asteroidBelts', {})
   1027         for asteroidBeltID, asteroidBelt in asteroidBelts.iteritems():
   1028             items.append(Map2DCelestialItemInfoType(itemID=asteroidBeltID, orbitID=planetID, orbitIndex=1, celestialIndex=planet.celestialIndex, locationID=solarSystemID, itemName=cfg.evelocations.Get(asteroidBeltID).locationName, groupID=9, typeID=asteroidBelt.typeID, x=asteroidBelt.position.x, y=asteroidBelt.position.y, z=asteroidBelt.position.z))
   1029 
   1030         npcStations = getattr(planet, 'npcStations', {})
   1031         for npcStationID, npcStation in npcStations.iteritems():
   1032             items.append(Map2DCelestialItemInfoType(itemID=npcStationID, orbitID=planetID, orbitIndex=1, celestialIndex=planet.celestialIndex, locationID=solarSystemID, itemName=cfg.evelocations.Get(npcStationID).locationName, groupID=const.groupStation, typeID=npcStation.typeID, x=npcStation.position.x, y=npcStation.position.y, z=npcStation.position.z))
   1033 
   1034         moons = getattr(planet, 'moons', {})
   1035         for moonID, moon in moons.iteritems():
   1036             items.append(Map2DCelestialItemInfoType(itemID=moonID, orbitID=planetID, orbitIndex=1, locationID=solarSystemID, celestialIndex=planet.celestialIndex, itemName=cfg.evelocations.Get(moonID).locationName, groupID=const.groupMoon, typeID=moon.typeID, x=moon.position.x, y=moon.position.y, z=moon.position.z))
   1037             asteroidBelts = getattr(moon, 'asteroidBelts', {})
   1038             for asteroidBeltID, asteroidBelt in asteroidBelts.iteritems():
   1039                 items.append(Map2DCelestialItemInfoType(itemID=asteroidBeltID, orbitID=moonID, orbitIndex=1, celestialIndex=planet.celestialIndex, locationID=solarSystemID, itemName=cfg.evelocations.Get(asteroidBeltID).locationName, groupID=9, typeID=asteroidBelt.typeID, x=asteroidBelt.position.x, y=asteroidBelt.position.y, z=asteroidBelt.position.z))
   1040 
   1041             npcStations = getattr(moon, 'npcStations', {})
   1042             for npcStationID, npcStation in npcStations.iteritems():
   1043                 items.append(Map2DCelestialItemInfoType(itemID=npcStationID, orbitID=planetID, orbitIndex=1, celestialIndex=planet.celestialIndex, locationID=solarSystemID, itemName=cfg.evelocations.Get(npcStationID).locationName, groupID=const.groupStation, typeID=npcStation.typeID, x=npcStation.position.x, y=npcStation.position.y, z=npcStation.position.z))
   1044 
   1045     return items