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

myPinManager.py (34084B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\planet\myPinManager.py
      2 from collections import defaultdict
      3 import evetypes
      4 import threadutils
      5 import utillib
      6 from carbon.common.script.util.format import FmtDist
      7 from carbonui.primitives.container import Container
      8 from carbonui.primitives.fill import Fill
      9 from eve.client.script.ui.control import eveLabel
     10 from eve.client.script.ui.shared.planet.planetConst import GetPinNameShort
     11 from eve.client.script.ui.util import uix
     12 import carbonui.const as uiconst
     13 import log
     14 import geo2
     15 import trinity
     16 import localization
     17 import eve.common.script.util.planetCommon as planetCommon
     18 from eve.client.script.ui.shared.planet import planetConst
     19 from eve.client.script.ui.shared.planet.planetCommon import GetPickIntersectionPoint, GetSchematicDataForID
     20 from eve.client.script.ui.shared.planet.planetUILinks import Link
     21 from eve.common.script.planet.surfacePoint import SurfacePoint
     22 from eve.client.script.ui.shared.planet import planetCommon as planetCommonUI
     23 from eve.client.script.ui.shared.planet.planetUIPins import CommandCenterPin, ExtractorPin, ProcessorPin, LaunchpadPin, StorageFacilityPin, EcuPin, DepletionPin, BuildIndicatorPin
     24 from carbonui.uicore import uicore
     25 from eve.client.script.ui.shared.planet.surveyUI import SurveyWindow
     26 from eve.common.lib import appConst as const
     27 from eveexceptions import UserError
     28 from evelink.client import type_link
     29 from eveplanet.client.installSchematicMenu import MultiPinMenuProvider
     30 from eveplanet.client.routeReplace import GetRouteToDeleteAndNewRouteData
     31 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     32 
     33 class MyPinManager:
     34     __notifyevents__ = ['OnPlanetPinsChanged',
     35      'OnRefreshPins',
     36      'OnEditModeBuiltOrDestroyed',
     37      'OnPlanetPinPlaced']
     38 
     39     def __init__(self):
     40         sm.RegisterNotify(self)
     41         self.planetUISvc = None
     42         self.linkParentID = None
     43         self.routeParentID = None
     44         self.currentRoute = []
     45         self.routeHoverPath = []
     46         self.oneoffRoute = False
     47         self.isEdit = False
     48         self.currRouteVolume = None
     49         self.newPinType = None
     50         self.canMoveHeads = None
     51         self.depletionPoints = []
     52         self.extractionHeadDragged = None
     53         self.pinsByID = {}
     54         self.linksByPinIDs = {}
     55         self.linksByGraphicID = {}
     56         self.links = []
     57         self.buildIndicatorPin = None
     58         self.currentEcuPinID = None
     59         self.bracketCurveSet = trinity.TriCurveSet()
     60         self.bracketCurveSet.name = 'PlanetBrackets'
     61         uicore.desktop.GetRenderObject().curveSets.append(self.bracketCurveSet)
     62 
     63     def Close(self):
     64         sm.UnregisterNotify(self)
     65         self.planetUISvc = None
     66         self.linkParentID = None
     67         self.routeParentID = None
     68         self.currentRoute = None
     69         self.routeHoverPath = None
     70         self.currRouteVolume = None
     71         self.newPinType = None
     72         self.canMoveHeads = None
     73         self.depletionPoints = None
     74         self.pinsByID = None
     75         self.linksByPinIDs = None
     76         self.linksByGraphicID = None
     77         self.links = None
     78         self.buildIndicatorPin = None
     79         self.currentEcuPinID = None
     80         self.bracketCurveSet = None
     81 
     82     def OnPlanetViewOpened(self):
     83         self.planetUISvc = sm.GetService('planetUI')
     84         self.eventManager = self.planetUISvc.eventManager
     85         sp = SurfacePoint()
     86         rubberColor = (1.0, 1.0, 1.0, 1.0)
     87         self.rubberLink = self.planetUISvc.curveLineDrawer.DrawArc('rubberLink', sp, sp, 2.0, rubberColor, rubberColor)
     88         self.InitRubberLinkLabels()
     89         self.ReRender()
     90         self.depletionPoints = []
     91         self.bracketCurveSet.Play()
     92 
     93     def OnPlanetViewClosed(self):
     94         self.ClearPinsFromScene()
     95         self.ClearLinksFromScene()
     96         self.bracketCurveSet.Stop()
     97         self.isEdit = False
     98 
     99     def ReRender(self):
    100         if not sm.GetService('viewState').IsViewActive('planet'):
    101             return
    102         self.RenderPins()
    103         self.RenderLinks()
    104         self.ResetPinData()
    105 
    106     def ReRenderPin(self, pin):
    107         if not sm.GetService('viewState').IsViewActive('planet'):
    108             return
    109         uiPin = self.pinsByID.get(pin.id, None)
    110         if uiPin is None:
    111             return
    112         uiPin.Remove()
    113         self.RenderPin(pin)
    114 
    115     def InitRubberLinkLabels(self):
    116         self.rubberLinkLabelContainer = Container(name='rubberLinkLabels', parent=self.planetUISvc.planetUIContainer, pos=(400, 400, 110, 55), padding=(4, 4, 4, 4), align=uiconst.TOPLEFT, state=uiconst.UI_HIDDEN)
    117         self.rubberLinkLabels = utillib.KeyVal()
    118         self.rubberLinkLabels.padding = 3
    119         self.rubberLinkLabels.columnPadding = 9
    120         white = (1.0, 1.0, 1.0, 1.0)
    121         gray = (1.0, 1.0, 1.0, 0.6)
    122         self.rubberLinkLabels.distanceLbl = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Common/Distance'), parent=self.rubberLinkLabelContainer, left=self.rubberLinkLabels.padding, height=16, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, color=gray)
    123         maxLabelWidth = uix.GetTextWidth(localization.GetByLabel('UI/Common/Distance'))
    124         self.rubberLinkLabels.powerLbl = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Common/Power'), parent=self.rubberLinkLabelContainer, top=16, left=self.rubberLinkLabels.padding, height=16, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, color=gray)
    125         maxLabelWidth = max(maxLabelWidth, uix.GetTextWidth(localization.GetByLabel('UI/Common/Power')))
    126         self.rubberLinkLabels.cpuLbl = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Common/Cpu'), parent=self.rubberLinkLabelContainer, top=32, left=self.rubberLinkLabels.padding, height=16, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, color=gray)
    127         maxLabelWidth = max(maxLabelWidth, uix.GetTextWidth(localization.GetByLabel('UI/Common/Cpu')))
    128         maxLabelWidth += self.rubberLinkLabels.columnPadding
    129         self.rubberLinkLabels.distance = eveLabel.EveLabelMedium(text='', parent=self.rubberLinkLabelContainer, left=2, align=uiconst.TOPRIGHT, state=uiconst.UI_DISABLED, color=white)
    130         self.rubberLinkLabels.power = eveLabel.EveLabelMedium(text='', parent=self.rubberLinkLabelContainer, left=2, top=16, align=uiconst.TOPRIGHT, state=uiconst.UI_DISABLED, color=white)
    131         self.rubberLinkLabels.cpu = eveLabel.EveLabelMedium(text='', parent=self.rubberLinkLabelContainer, left=2, top=32, align=uiconst.TOPRIGHT, state=uiconst.UI_DISABLED, color=white)
    132         Fill(parent=self.rubberLinkLabelContainer, color=(0.0, 0.0, 0.0, 0.5))
    133 
    134     def OnPlanetPinsChanged(self, planetID):
    135         if sm.GetService('viewState').IsViewActive('planet') and self.planetUISvc and self.planetUISvc.GetCurrentPlanet().planetID == planetID:
    136             self.planetUISvc.SetPlanet(planetID)
    137             self.ReRender()
    138             self.linkParentID = None
    139             self.routeParentID = None
    140         self.currentRoute = []
    141 
    142     def ResetPinData(self):
    143         if self.planetUISvc.planet.colony is None:
    144             return
    145         pinData = self.planetUISvc.planet.colony.colonyData.pins
    146         for pinID, pinUI in self.pinsByID.iteritems():
    147             pinUI.ResetPinData(pinData[pinID])
    148 
    149     def OnRefreshPins(self, pinIDs = None):
    150         for p in self.pinsByID.values():
    151             p.OnRefreshPins()
    152 
    153         for l in self.linksByPinIDs.values():
    154             l.OnRefreshPins()
    155 
    156     def OnEditModeBuiltOrDestroyed(self, planetID):
    157         currentPlanet = self.planetUISvc.GetCurrentPlanet()
    158         if currentPlanet and currentPlanet.planetID == planetID:
    159             self._OnEditModeBuiltOrDestroyed()
    160 
    161     @threadutils.throttled(0.1)
    162     def _OnEditModeBuiltOrDestroyed(self):
    163         self.OnRefreshPins()
    164 
    165     def OnPlanetPinPlaced(self, pinID):
    166         planet = sm.GetService('planetUI').GetCurrentPlanet()
    167         if planet is None:
    168             return
    169         colony = planet.GetColony(session.charid)
    170         if colony is None:
    171             return
    172         pin = colony.GetPin(pinID)
    173         if pin is None:
    174             return
    175         UIpin = self.RenderPin(pin)
    176         UIpin.PlacementAnimation()
    177 
    178     def OnPlanetEnteredEditMode(self):
    179         sm.ScatterEvent('OnEditModeChanged', True)
    180 
    181     def OnPlanetExitedEditMode(self):
    182         self.ReRender()
    183         sm.ScatterEvent('OnEditModeChanged', False)
    184         if self.planetUISvc.currentContainer is not None:
    185             self.planetUISvc.eventManager.DeselectCurrentlySelected()
    186 
    187     def SetLinkParent(self, parentID):
    188         self.eventManager.SetStateCreateLinkEnd()
    189         self.linkParams = planetCommon.GetUsageParametersForLinkType(const.typeTestPlanetaryLink)
    190         pin = self.pinsByID[parentID]
    191         self.planetUISvc.curveLineDrawer.ChangeLinePosition('rubberLink', self.rubberLink, pin.surfacePoint, pin.surfacePoint)
    192         self.planetUISvc.curveLineDrawer.ChangeLineSetWidth('rubberLink', 2.0)
    193         self.rubberLinkLabelContainer.state = uiconst.UI_DISABLED
    194         surfacePoint = planetCommonUI.GetPickIntersectionPoint()
    195         self.linkParentID = parentID
    196         self.UpdateRubberLink(surfacePoint)
    197 
    198     def EndLinkCreation(self):
    199         self.linkParentID = None
    200         self.planetUISvc.curveLineDrawer.ChangeLineSetWidth('rubberLink', 0.0)
    201         self.rubberLinkLabelContainer.state = uiconst.UI_HIDDEN
    202 
    203     def LaunchCommodities(self, pinID, commoditiesToLaunch):
    204         self.planetUISvc.planet.LaunchCommodities(pinID, commoditiesToLaunch)
    205 
    206     def EnterRouteMode(self, pinID, typeID = None, oneoff = False):
    207         if typeID or oneoff:
    208             self.typeToRoute = typeID
    209         else:
    210             pin = self.pinsByID[pinID]
    211             products = pin.pin.GetProductMaxOutput()
    212             if not products:
    213                 return
    214             self.typeToRoute = products.keys()[0]
    215         self.eventManager.SetStateCreateRoute()
    216         self.routeHoverPath = []
    217         self.currentRoute = [pinID]
    218         self.oneoffRoute = oneoff
    219         selectedPin = self.eventManager.selectedPin
    220         if selectedPin:
    221             selectedPin.HideHologramModel()
    222 
    223     def LeaveRouteMode(self):
    224         links = self.GetLinksFromPath(self.currentRoute)
    225         for l, id in links:
    226             l.RemoveAsRoute(id)
    227 
    228         if len(self.routeHoverPath) > 0:
    229             links = self.GetLinksFromPath(self.routeHoverPath)
    230             for l, id in links:
    231                 l.RemoveAsRoute(id)
    232 
    233         self.routeHoverPath = []
    234         self.currentRoute = []
    235         self.typeToRoute = None
    236         self.currRouteVolume = None
    237         selectedPin = self.eventManager.selectedPin
    238         if selectedPin:
    239             selectedPin.ShowHologramModel()
    240 
    241     def SetRouteWaypoint(self, childID):
    242         if childID in self.currentRoute:
    243             i = self.currentRoute.index(childID)
    244             path = self.currentRoute[i:]
    245             links = self.GetLinksFromPath(path)
    246             for l, id in links:
    247                 l.RemoveAsRoute(id)
    248 
    249             self.currentRoute = self.currentRoute[:i + 1]
    250         else:
    251             lastWaypoint = self.currentRoute[-1]
    252             colony = self.planetUISvc.planet.GetColonyByPinID(lastWaypoint)
    253             shortestPath = colony.FindShortestPathIDs(lastWaypoint, childID)
    254             if not shortestPath:
    255                 raise UserError('CreateRoutePathNotFound')
    256             self.currentRoute.extend(shortestPath[1:])
    257         self.routeHoverPath = []
    258         sm.GetService('audio').SendUIEvent('msg_pi_routes_waypoint_play')
    259 
    260     def _CleanRoute(self, route):
    261         pinIDSet = set(route)
    262         for pinID in pinIDSet:
    263             if pinID not in route:
    264                 continue
    265             if route.count(pinID) > 1:
    266                 firstPos = route.index(pinID)
    267                 pos = lastPos = firstPos
    268                 while True:
    269                     try:
    270                         pos = route.index(pinID, pos + 1)
    271                         lastPos = pos
    272                     except ValueError:
    273                         break
    274 
    275                 deletedPath = route[firstPos:lastPos + 1]
    276                 links = self.GetLinksFromPath(deletedPath)
    277                 for l, id in links:
    278                     l.RemoveAsRoute(id)
    279 
    280                 route = route[0:firstPos + 1] + route[lastPos + 1:]
    281 
    282     def GetPinGraphicsClassForType(self, typeID):
    283         if not evetypes.Exists(typeID):
    284             raise RuntimeError('Unable to find inventory type for typeID', typeID)
    285         groupID = evetypes.GetGroupID(typeID)
    286         if groupID == const.groupCommandPins:
    287             return CommandCenterPin
    288         if groupID == const.groupExtractorPins:
    289             return ExtractorPin
    290         if groupID == const.groupProcessPins:
    291             return ProcessorPin
    292         if groupID == const.groupSpaceportPins:
    293             return LaunchpadPin
    294         if groupID == const.groupStoragePins:
    295             return StorageFacilityPin
    296         if groupID == const.groupExtractionControlUnitPins:
    297             return EcuPin
    298         raise RuntimeError('Unable to resolve UI container class for pin of type', typeID)
    299 
    300     def RenderPins(self):
    301         if self.planetUISvc.planet.colony is None:
    302             return
    303         newPinData = self.planetUISvc.planet.colony.colonyData.pins
    304         newPinIDs = newPinData.keys()
    305         oldPinIDs = self.pinsByID.keys()
    306         pinsToDelete = [ pinID for pinID in oldPinIDs if pinID not in newPinIDs ]
    307         for pinID in pinsToDelete:
    308             pin = self.pinsByID.pop(pinID)
    309             pin.Remove()
    310 
    311         pinsToAdd = [ pinID for pinID in newPinIDs if pinID not in oldPinIDs ]
    312         for pinID in pinsToAdd:
    313             pin = newPinData[pinID]
    314             self.RenderPin(pin)
    315 
    316     def RenderPin(self, pin):
    317         if pin.id in self.pinsByID:
    318             self.pinsByID[pin.id].Remove()
    319         surfacePoint = SurfacePoint(phi=pin.latitude, theta=pin.longitude)
    320         pinClass = self.GetPinGraphicsClassForType(pin.typeID)
    321         UIpin = pinClass(surfacePoint, pin, self.planetUISvc.pinTransform)
    322         self.pinsByID[pin.id] = UIpin
    323         return UIpin
    324 
    325     def RenderLinks(self):
    326         self.ClearLinksFromScene()
    327         if session.charid not in self.planetUISvc.planet.colonies:
    328             return
    329         if self.planetUISvc.planet.colony is not None:
    330             for linkID, linkObj in self.planetUISvc.planet.colony.colonyData.links.iteritems():
    331                 ep1ID, ep2ID = linkID
    332                 self.AddLink(ep1ID, ep2ID, linkObj.typeID)
    333 
    334     def AddLink(self, parentID, childID, linkTypeID):
    335         colony = self.planetUISvc.planet.GetColony(session.charid)
    336         if colony is None:
    337             log.LogError('Unable to render link for planet without a colony')
    338             return
    339         par = colony.GetPin(parentID)
    340         child = colony.GetPin(childID)
    341         if par is None or child is None:
    342             log.LogWarn('Trying to render link for non-existing pin', parentID, childID)
    343             return
    344         p1 = SurfacePoint(theta=par.longitude, phi=par.latitude)
    345         p2 = SurfacePoint(theta=child.longitude, phi=child.latitude)
    346         planetLink = colony.colonyData.GetLink(parentID, childID)
    347         link = Link(p1, p2, parentID, childID, linkTypeID, planetLink)
    348         self.linksByPinIDs[parentID, childID] = link
    349         self.linksByPinIDs[childID, parentID] = link
    350         self.links.append(link)
    351         linkGraphicID1, linkGraphicID2 = link.GetGraphicIDs()
    352         self.linksByGraphicID[linkGraphicID1] = link
    353         self.linksByGraphicID[linkGraphicID2] = link
    354 
    355     def AddDepletionPoint(self, point):
    356         index = len(self.depletionPoints)
    357         self.depletionPoints.append(DepletionPin(point, index, self.planetUISvc.pinOthersTransform))
    358 
    359     def ClearPinsFromScene(self):
    360         for pin in self.pinsByID.values():
    361             pin.Remove()
    362 
    363         self.pinsByID = {}
    364 
    365     def ClearLinksFromScene(self):
    366         for link in self.links:
    367             link.Remove()
    368 
    369         self.planetUISvc.curveLineDrawer.ClearLines('links')
    370         self.planetUISvc.curveLineDrawer.ChangeLineSetWidth('rubberLink', 0.0)
    371         self.linksByPinIDs = {}
    372         self.links = []
    373         self.linksByGraphicID = {}
    374 
    375     def GetPinMenu(self, pinID):
    376         pin = self.pinsByID.get(pinID)
    377         if pin:
    378             return pin.GetMenu()
    379 
    380     def GetLinkMenu(self, linkGraphicID):
    381         if linkGraphicID in self.linksByGraphicID:
    382             link = self.linksByGraphicID[linkGraphicID]
    383             return link.GetMenu()
    384 
    385     def EndPlacingPin(self):
    386         self._RemoveBuildIndicatorPin()
    387 
    388     def _RemoveBuildIndicatorPin(self):
    389         if self.buildIndicatorPin is not None:
    390             self.buildIndicatorPin.Remove()
    391             self.buildIndicatorPin = None
    392         self.DisplayECUExtractionAreas(show=False)
    393 
    394     def DisplayECUExtractionAreas(self, show = True):
    395         for pin in self.pinsByID.values():
    396             if evetypes.GetGroupID(pin.pin.typeID) == const.groupExtractionControlUnitPins:
    397                 if show:
    398                     pin.ShowMaxDistanceCircle()
    399                 else:
    400                     pin.HideMaxDistanceCircle()
    401 
    402     def ShowECUExtractionAreas(self):
    403         for pin in self.pinsByID.values():
    404             if evetypes.GetGroupID(pin.typeID) == const.groupExtractionControlUnitPins:
    405                 pin.ShowMaxDistanceCircle(1.0)
    406 
    407     def GetLinksFromPath(self, path):
    408         links = []
    409         last = None
    410         for pinID in path:
    411             if last is None:
    412                 last = pinID
    413                 continue
    414             id = (last, pinID)
    415             if id in self.linksByPinIDs:
    416                 links.append((self.linksByPinIDs[id], id))
    417             else:
    418                 log.LogWarn('Trying to fetch a non-existing link:', id)
    419             last = pinID
    420 
    421         return links
    422 
    423     def CreateRoute(self, amount = None):
    424         if self.oneoffRoute:
    425             self.planetUISvc.planet.OpenTransferWindow(self.currentRoute)
    426             self.planetUISvc.eventManager.DeselectCurrentlySelected()
    427         else:
    428             route = self.currentRoute
    429             links = self.GetLinksFromPath(self.currentRoute)
    430             typeToRoute = self.typeToRoute
    431             try:
    432                 self.planetUISvc.planet.CreateRoute(self.currentRoute, self.typeToRoute, amount)
    433             except UserError:
    434                 if self.currentRoute:
    435                     self.currentRoute = [self.currentRoute[0]]
    436                 raise
    437             finally:
    438                 for link, id in links:
    439                     link.RemoveAsRoute(id)
    440 
    441         sm.GetService('audio').SendUIEvent('msg_pi_routes_destination_play')
    442         self.currentRoute = []
    443 
    444     def UpdateRubberLink(self, surfacePoint):
    445         surfacePoint = GetPickIntersectionPoint(scale=planetConst.SCALE_RUBBERLINK)
    446         pin = self.pinsByID.get(self.linkParentID)
    447         if not pin:
    448             return
    449         if not surfacePoint:
    450             surfacePoint = pin.surfacePoint
    451         self.planetUISvc.curveLineDrawer.ChangeLinePosition('rubberLink', self.rubberLink, pin.surfacePoint, surfacePoint)
    452         self.UpdateRubberLinkLabels(pin.surfacePoint, surfacePoint)
    453 
    454     def GetCommandCenterPin(self):
    455         for p in self.pinsByID.values():
    456             if evetypes.GetGroupID(p.pin.typeID) == const.groupCommandPins:
    457                 return p
    458 
    459     def GetPinsByGroupTypeIDs(self):
    460         pinsByGroupTypeID = defaultdict(list)
    461         for p in self.pinsByID.values():
    462             pinsByGroupTypeID[evetypes.GetGroupID(p.pin.typeID)].append(p)
    463 
    464         return pinsByGroupTypeID
    465 
    466     def UpdateRubberLinkLabels(self, surfacePointA, surfacePointB):
    467         self.rubberLinkLabelContainer.left = uicore.uilib.x + 3
    468         self.rubberLinkLabelContainer.top = uicore.uilib.y + 3
    469         if surfacePointA == surfacePointB:
    470             length = 0.0
    471         else:
    472             length = surfacePointA.GetDistanceToOther(surfacePointB) * self.planetUISvc.planet.radius
    473         self.rubberLinkLabels.distance.text = FmtDist(length)
    474         powerUsage = planetCommon.GetPowerUsageForLink(const.typeTestPlanetaryLink, length, 0, self.linkParams)
    475         cpuUsage = planetCommon.GetCpuUsageForLink(const.typeTestPlanetaryLink, length, 0, self.linkParams)
    476         self.rubberLinkLabels.power.text = localization.GetByLabel('UI/PI/Common/MegaWattsAmount', amount=powerUsage)
    477         self.rubberLinkLabels.cpu.text = localization.GetByLabel('UI/PI/Common/TeraFlopsAmount', amount=cpuUsage)
    478 
    479     def OnRouteVolumeChanged(self, volume):
    480         self.currRouteVolume = volume
    481         for link, linkID in self.GetLinksFromPath(self.currentRoute):
    482             link.SetCurrentRouteVolume(volume)
    483 
    484     def DistanceToOtherPinsOK(self, surfacePoint):
    485         minDistance = 0.012
    486         for pin in self.pinsByID.values():
    487             if surfacePoint.GetDistanceToOther(pin.surfacePoint) < minDistance:
    488                 return False
    489 
    490         return True
    491 
    492     def PlacePinOnNextClick(self, pinTypeID):
    493         self.eventManager.SetStateBuildPin()
    494         self._RemoveBuildIndicatorPin()
    495         self.newPinType = pinTypeID
    496         groupID = evetypes.GetGroupID(pinTypeID)
    497         self.buildIndicatorPin = BuildIndicatorPin(SurfacePoint(), pinTypeID, groupID, self.planetUISvc.pinOthersTransform)
    498         if groupID == const.groupExtractionControlUnitPins:
    499             self.DisplayECUExtractionAreas(show=True)
    500 
    501     def VerifySimulation(self):
    502         self.planetUISvc.planet.GMVerifySimulation()
    503 
    504     def HighlightLink(self, pinID, linkID, removeOld = True):
    505         link = self.linksByPinIDs[linkID]
    506         link.HighlightLink()
    507 
    508     def RemoveHighlightLink(self, linkID):
    509         self.linksByPinIDs[linkID].RemoveHighlightLink()
    510 
    511     def ShowRoute(self, routeID):
    512         route = self.planetUISvc.planet.colony.colonyData.GetRoute(routeID)
    513         path = route.path
    514         for link, linkID in self.GetLinksFromPath(path):
    515             link.ShowAsRoute(linkID, 1, 1)
    516 
    517     def StopShowingRoute(self, routeID):
    518         route = self.planetUISvc.planet.colony.colonyData.GetRoute(routeID)
    519         path = route.path
    520         for link, linkID in self.GetLinksFromPath(path):
    521             link.RemoveAsRoute(linkID)
    522 
    523     def GetCommandCenter(self):
    524         if not self.planetUISvc.planet:
    525             return None
    526         if not self.planetUISvc.planet.colony:
    527             return None
    528         if not self.planetUISvc.planet.colony.colonyData:
    529             return None
    530         return self.planetUISvc.planet.colony.colonyData.commandPin
    531 
    532     def RemovePin(self, pinID):
    533         self.planetUISvc.GetCurrentPlanet().RemovePin(pinID)
    534         pin = self.pinsByID.get(pinID, None)
    535         if pin:
    536             if pin.pin.IsCommandCenter():
    537                 for p in self.pinsByID.values():
    538                     p.Remove()
    539 
    540                 self.pinsByID = {}
    541                 self.eventManager.SetStateNormal()
    542             else:
    543                 pin.Remove()
    544                 self.pinsByID.pop(pinID)
    545         self.RenderLinks()
    546         self.linkParentID = None
    547         self.eventManager.DeselectCurrentlySelected()
    548 
    549     def RemoveLink(self, linkID):
    550         link = self.linksByPinIDs[linkID]
    551         link.Remove()
    552         self.links.remove(link)
    553         self.planetUISvc.planet.RemoveLink(*linkID)
    554         self.RenderLinks()
    555         self.eventManager.DeselectCurrentlySelected()
    556 
    557     def UpgradeLink(self, *args):
    558         self.planetUISvc.planet.SetLinkLevel(*args)
    559 
    560     def InstallSchematic(self, pinID, schematicID):
    561         self.planetUISvc.planet.InstallSchematic(pinID, schematicID)
    562         pin = self.pinsByID[pinID]
    563         pin.OnRefreshPins()
    564 
    565     def RemoveRoute(self, routeID):
    566         route = self.planetUISvc.planet.colony.colonyData.GetRoute(routeID)
    567         if not route:
    568             return
    569         path = route.path
    570         self.planetUISvc.planet.RemoveRoute(routeID)
    571         for link, pinIDs in self.GetLinksFromPath(path):
    572             link.RenderAccordingToState()
    573 
    574     def PlacePin(self, surfacePoint):
    575         newPinType = self.newPinType
    576         return self.PlacePinType(surfacePoint, newPinType)
    577 
    578     def PlacePinType(self, surfacePoint, newPinType):
    579         if not self.DistanceToOtherPinsOK(surfacePoint):
    580             raise UserError('CannotBuildPinCloseToOthers')
    581         if not self or self.planetUISvc.planet is None:
    582             return
    583         self.planetUISvc.planet.CreatePin(newPinType, surfacePoint.phi, surfacePoint.theta)
    584         if evetypes.GetGroupID(newPinType) == const.groupCommandPins:
    585             sm.GetService('audio').SendUIEvent('msg_pi_build_command_play')
    586             self.eventManager.SetStateNormal()
    587         else:
    588             sm.GetService('audio').SendUIEvent('msg_pi_build_pin_play')
    589 
    590     def SetLinkChild(self, parentID, childID, setState = True):
    591         try:
    592             self.planetUISvc.planet.CreateLink(parentID, childID, const.typeTestPlanetaryLink)
    593             self.AddLink(childID, parentID, const.typeTestPlanetaryLink)
    594             sm.GetService('audio').SendUIEvent('msg_pi_build_link_play')
    595         finally:
    596             if setState:
    597                 self.eventManager.SetStateCreateLinkStart()
    598 
    599     def EnterSurveyMode(self, ecuPinID):
    600         self.eventManager.SetStateSurvey()
    601         self.planetUISvc.GetSurveyWindow(ecuPinID)
    602         self.currentEcuPinID = ecuPinID
    603         ecuPin = self.pinsByID[ecuPinID]
    604         ecuPin.EnterSurveyMode()
    605 
    606     def LeaveSurveyMode(self):
    607         if self.currentEcuPinID is not None:
    608             ecuPin = self.pinsByID.get(self.currentEcuPinID, None)
    609             if ecuPin:
    610                 ecuPin.ExitSurveyMode()
    611         self.currentEcuPinID = None
    612         self.planetUISvc.CloseSurveyWindow()
    613 
    614     def PlaceExtractionHead(self, ecuPinID, surfacePoint, headID = None):
    615         ecuPin = self.pinsByID[self.currentEcuPinID]
    616         if ecuPin.pin.IsActive():
    617             return
    618         headID = self.planetUISvc.planet.AddExtractorHead(ecuPinID, headID, surfacePoint.phi, surfacePoint.theta)
    619         ecuPin.AddHead(headID, surfacePoint)
    620         newHead = ecuPin.GetExtractionHead(headID)
    621         newHead.ShowUnlocked()
    622         wnd = SurveyWindow.GetIfOpen()
    623         if wnd:
    624             wnd.OnExtractionHeadAdded(headID, surfacePoint)
    625 
    626     def SetExtractionHeadRadius(self, ecuPinID, radius):
    627         ecuPin = self.pinsByID[ecuPinID]
    628         ecuPin.pin.headRadius = radius
    629         ecuPin.SetExtractionHeadRadius(radius)
    630 
    631     def RemoveExtractionHead(self, ecuPinID, headID):
    632         ecuPin = self.pinsByID[ecuPinID]
    633         if ecuPin.pin.IsActive():
    634             return
    635         self.planetUISvc.planet.RemoveExtractorHead(ecuPinID, headID)
    636         ecuPin.RemoveHead(headID)
    637         wnd = SurveyWindow.GetIfOpen()
    638         if wnd:
    639             wnd.OnExtractionHeadRemoved(headID)
    640 
    641     def BeginDragExtractionHead(self, ecuPinID, headID):
    642         if ecuPinID != self.currentEcuPinID:
    643             return
    644         ecuPin = self.pinsByID[ecuPinID]
    645         if ecuPinID != self.canMoveHeads:
    646             return
    647         self.extractionHeadDragged = (ecuPin, headID)
    648         self.eventManager.SetSubStateMoveExtractionHead()
    649         surfacePoint = ecuPin.GetExtractionHead(headID).surfacePoint
    650         wnd = self.planetUISvc.GetSurveyWindow(self.currentEcuPinID)
    651         wnd.OnBeginDragExtractionHead(headID, surfacePoint)
    652 
    653     def DragExtractionHeadTo(self, surfacePoint):
    654         ecuPin, headID = self.extractionHeadDragged
    655         distanceFactor = self._EnforceMaximumDinstance(surfacePoint, ecuPin)
    656         ecuPin.SetDistanceFactor(distanceFactor)
    657         ecuPin.MoveExtractionHeadTo(headID, surfacePoint)
    658         wnd = SurveyWindow.GetIfOpen()
    659         if wnd:
    660             wnd.OnExtractionHeadMoved(headID, surfacePoint)
    661 
    662     def IsDraggingExtractionHead(self):
    663         return bool(self.extractionHeadDragged)
    664 
    665     def _EnforceMaximumDinstance(self, headSurfacePoint, uiPin):
    666         SAFETYFACTOR = 0.99
    667         ecuSurfacePoint = uiPin.surfacePoint
    668         distance = headSurfacePoint.GetDistanceToOther(ecuSurfacePoint)
    669         areaOfInfluence = uiPin.pin.GetAreaOfInfluence()
    670         if distance < areaOfInfluence * SAFETYFACTOR:
    671             return distance / areaOfInfluence
    672         ecuVector = ecuSurfacePoint.GetAsXYZTuple()
    673         v = headSurfacePoint.GetAsXYZTuple()
    674         normal = geo2.Vec3Cross(ecuVector, v)
    675         rotMat = geo2.MatrixRotationAxis(normal, areaOfInfluence * SAFETYFACTOR)
    676         newV = geo2.Multiply(rotMat, ecuVector)
    677         headSurfacePoint.SetXYZ(*newV[:3])
    678         return 1.0
    679 
    680     def EndDragExtractionHead(self):
    681         uiPin, headID = self.extractionHeadDragged
    682         headPin = uiPin.extractionHeadsByNum[headID]
    683         self._EnforceMaximumDinstance(headPin.surfacePoint, uiPin)
    684         sm.GetService('planetUI').GetCurrentPlanet().MoveExtractorHead(uiPin.pin.id, headID, headPin.surfacePoint.phi, headPin.surfacePoint.theta)
    685         self.extractionHeadDragged = None
    686         self.eventManager.SetSubStateNormal()
    687         wnd = self.planetUISvc.GetSurveyWindow(self.currentEcuPinID)
    688         wnd.OnEndDragExtractionHead()
    689 
    690     def OnExtractionHeadMouseEnter(self, ecuPinID, headID):
    691         if ecuPinID != self.currentEcuPinID:
    692             return
    693         ecuPin = self.pinsByID[ecuPinID]
    694         if ecuPinID != self.canMoveHeads:
    695             return
    696         head = ecuPin.GetExtractionHead(headID)
    697         if head:
    698             head.OnMouseEnter()
    699         wnd = self.planetUISvc.GetSurveyWindow(self.currentEcuPinID)
    700         wnd.OnHeadEntryMouseEnter(headID)
    701 
    702     def OnExtractionHeadMouseExit(self, ecuPinID, headID):
    703         if ecuPinID != self.currentEcuPinID:
    704             return
    705         ecuPin = self.pinsByID[ecuPinID]
    706         head = ecuPin.GetExtractionHead(headID)
    707         if head:
    708             head.OnMouseExit()
    709         wnd = self.planetUISvc.GetSurveyWindow(self.currentEcuPinID)
    710         wnd.OnHeadEntryMouseExit(headID)
    711 
    712     def SetEcuOverlapValues(self, ecuPinID, overlapVals):
    713         ecuPin = self.pinsByID.get(ecuPinID, None)
    714         if ecuPin:
    715             ecuPin.SetOverlapValues(overlapVals)
    716 
    717     def UnlockHeads(self, pinID):
    718         self.canMoveHeads = pinID
    719         ecuPin = self.pinsByID.get(pinID, None)
    720         if ecuPin:
    721             ecuPin.OnHeadsUnlocked()
    722 
    723     def LockHeads(self):
    724         ecuPin = self.pinsByID.get(self.canMoveHeads, None)
    725         self.canMoveHeads = None
    726         if ecuPin:
    727             ecuPin.OnHeadsLocked()
    728 
    729     def GMRunDepletionSim(self, totalDuration):
    730         points = []
    731         for point in self.depletionPoints:
    732             points.append(utillib.KeyVal(longitude=point.surfacePoint.theta, latitude=point.surfacePoint.phi, amount=point.GetAmount(), duration=point.GetDuration(), headRadius=point.GetHeadRadius()))
    733 
    734         info = utillib.KeyVal(totalDuration=totalDuration, points=points)
    735         sm.GetService('planetUI').GetCurrentPlanet().GMRunDepletionSim(self.planetUISvc.selectedResourceTypeID, info)
    736 
    737     def GetMultiPinMenu(self, currentPin):
    738         selectedPinIDs = self.eventManager.selectedPinIDs
    739         if currentPin.pin.id not in selectedPinIDs:
    740             selectedPinIDs.add(currentPin.pin.id)
    741             currentPin.SetMultiSelectedDisplay(True)
    742         pins = [ self.planetUISvc.planet.GetPin(x) for x in selectedPinIDs ]
    743         mp = MultiPinMenuProvider(self.InstallSchematicForMultiplePins)
    744         return mp.GetMenu(pins)
    745 
    746     def InstallSchematicForMultiplePins(self, schematicID, pins):
    747         resultsByPinID = self._GetRouteToDeleteAndNewRouteData(schematicID, pins)
    748         outputRouteFailures = defaultdict(list)
    749         inputRouteFailures = defaultdict(list)
    750         for pID, results in resultsByPinID.iteritems():
    751             self.InstallSchematic(pID, schematicID)
    752             for routeID in results.outputRouteIDsToDelete.union(results.inputRouteIDsToDelete):
    753                 self.RemoveRoute(routeID)
    754 
    755             for routeInfo, errorDict in ((results.newOutputRouteData, outputRouteFailures), (results.newInputRouteData, inputRouteFailures)):
    756                 for typeID, qty, path in routeInfo:
    757                     try:
    758                         self.planetUISvc.planet.CreateRoute(path, typeID, qty)
    759                     except UserError:
    760                         errorDict[typeID].append(path)
    761 
    762         if outputRouteFailures or inputRouteFailures:
    763             self._DisplayRouteFailureMessage(outputRouteFailures, inputRouteFailures)
    764 
    765     def _DisplayRouteFailureMessage(self, outputRouteFailures, inputRouteFailures):
    766         colony = self.eventManager.GetColony()
    767         infoTextList = []
    768         for routeFailures, headerText in ((outputRouteFailures, localization.GetByLabel('UI/PI/FailedToCreateOutgoingRoutes')), (inputRouteFailures, localization.GetByLabel('UI/PI/FailedToCreateIncomingRoutes'))):
    769             if not routeFailures:
    770                 continue
    771             infoTextList.append(headerText)
    772             for typeID, failedRoutePaths in routeFailures.iteritems():
    773                 infoTextList.append(u'\u2022 %s' % type_link(typeID))
    774                 for path in failedRoutePaths:
    775                     sourcePinID, destPinID = path
    776                     sourcePin = colony.GetPin(sourcePinID)
    777                     if sourcePin is None:
    778                         continue
    779                     destPin = colony.GetPin(destPinID)
    780                     if destPin is None:
    781                         continue
    782                     sourcePinName = GetPinNameShort(sourcePin.typeID, sourcePinID)
    783                     destPinName = GetPinNameShort(destPin.typeID, destPinID)
    784                     text = '<t>%s => %s' % (sourcePinName, destPinName)
    785                     infoTextList.append(text)
    786 
    787         infoText = '<br>'.join(infoTextList)
    788         prompt_player_fsd_dialog('CustomInfo', {'info': infoText}, modal=False)
    789 
    790     def _GetRouteToDeleteAndNewRouteData(self, schematicID, pins):
    791         colony = self.eventManager.GetColony()
    792         return GetRouteToDeleteAndNewRouteData(schematicID, pins, GetSchematicDataForID, colony.colonyData.GetSourceRoutesForPin, self.GetDestRoutesForPin)
    793 
    794     def GetDestRoutesForPin(self, pinID):
    795         colony = self.eventManager.GetColony()
    796         routesIDsTo = colony.colonyData.GetDestinationRoutesForPin(pinID)
    797         return [ colony.GetRoute(routeID) for routeID in routesIDsTo ]