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

mapViewWorld.py (41120B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\mapView\mapViewWorld.py
      2 import math
      3 from datetime import datetime
      4 import collections
      5 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst
      6 import eveicon
      7 import geo2
      8 import localization
      9 import uthread
     10 from caching import Memoize
     11 from carbon.common.script.util.timerstuff import AutoTimer
     12 from carbonui import uiconst, PickState, TextColor
     13 from carbonui.text.styles import TextHeader
     14 from carbonui.control.buttonIcon import ButtonIcon
     15 from carbonui.primitives.container import Container
     16 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     17 from carbonui.primitives.gradientSprite import GradientSprite
     18 from carbonui.uicore import uicore
     19 from carbonui.util.dpi import ScaleDpi
     20 from eve.client.script.ui.shared.mapView.colorModeSettingsButton import MapViewColorModeSettingButton
     21 from eve.client.script.ui.shared.mapView.controls.mapViewFilterNav import MapViewFilterNav
     22 from eve.client.script.ui.shared.mapView.colorModes.colorModeInfoBase import ColorModeInfoBase
     23 from eve.client.script.ui.shared.mapView.controls.mapViewFilterSettingsPanel import FilterSettingsPanel
     24 from eve.client.script.ui.shared.mapView.controls.mapViewLegend import MapViewLegend
     25 from eve.client.script.ui.shared.mapView.controls.mapViewNavButtons import MapViewNavButtons
     26 from eve.client.script.ui.shared.mapView.controls.selectedFilterWidget import SelectedFilterWidget, BaseSelectedFilterWidget
     27 from eve.client.script.ui.shared.mapView.controls.mapViewLayoutWidget import MapLayoutWidget, MapLayoutWidgetCompact, WIDGET_STYLE_COMPACT, WIDGET_STYLE_NORMAL
     28 from eve.client.script.ui.shared.mapView.filters.mapFilterConst import MARKER_BIG, MARKER_MEDIUM, MARKER_NONE
     29 from eve.client.script.ui.shared.mapView.mapCompass import MapCompass
     30 from eve.client.script.ui.shared.mapView.mapDebugContainer import MapDebugContainer
     31 from eve.client.script.ui.shared.mapView.mapSignals import focus_map_on_location, on_map_location_selected, on_map_zoom_changed
     32 from eve.client.script.ui.shared.mapView.mapView import MapView
     33 from eve.client.script.ui.shared.mapView import mapViewSignals as map_signals, mapViewConst
     34 from eve.client.script.ui.shared.mapView.mapViewConst import VIEWMODE_COLOR_SETTINGS, MAP2D_ZOOM_TUBE_MARKER, MAP2D_ZOOM_TUBE_BUBBLE, VIEWMODE_LAYOUT_SHOW_JUMP_RANGE_SETTINGS, MARKERID_VULNERABLE_SKYHOOK_SOLARSYSTEM, VIEWMODE_MARKERS_SETTINGS, MARKERS_OPTION_VULNERABLE_SKYHOOK, MARKERID_VULNERABLE_SKYHOOK, MAX_CAMERA_DISTANCE_2DVIEW
     35 from eve.client.script.ui.shared.mapView.mapViewFiltered import MapViewFiltered
     36 from eve.client.script.ui.shared.mapView.mapViewSearch import MapViewSearchControl
     37 from eve.client.script.ui.shared.mapView.mapViewSettings import mapDebugModeActive, GetMapViewSetting, mapPreviewModeActive, map2dEyeDistYSetting, jumpRangeExcludeIneligibleSystem
     38 from eve.client.script.ui.shared.mapView.mapViewUtil import PARTICLE_SPRITE_TUBE_TEXTURE, GetSizeForUIElement, PREVIEW_PICKER_SIZE, JUMP_RANGE_OUTSIDE, JUMP_RANGE_INSIDE, JUMP_RANGE_OFF, GetSolarSystemCoordinates, TUBE_BUBBLE_SIZE, SolarSystemPosToMapPos, SpriteValues, EXTRA_BUBBLE_MEDIUM_SIZE_FACTOR, EXTRA_BUBBLE_BIG_SIZE_FACTOR, JUMP_RANGE_INSIDE_EXCLUDED, IsValidJumpTarget
     39 from eve.client.script.ui.shared.mapView.mapViewWorldNavigation import MapViewWorldNavigation
     40 from eve.client.script.ui.shared.mapView.markers.mapMarkerSolarSystem import MarkerLabelSolarSystem
     41 from eve.client.script.ui.shared.mapView.markers.mapMarkerVulnerableSkyhook import MarkerVulnerableSkyhook
     42 from eve.client.script.ui.shared.mapView.selectedInfoCont import SelectedInfoCont
     43 from eve.client.script.ui.shared.maps.mapcommon import REGION_JUMP
     44 from eve.client.script.ui.shared.maps import mapcommon
     45 from eve.client.script.ui.shared.mapView.sidePanel.sidePanel import MapSidePanel
     46 from eve.common.script.sys.idCheckers import IsKnownSpaceSystem, IsSolarSystem
     47 from eve.client.script.ui.shared.mapView import mapViewUtil
     48 from sovereignty.resource.shared.planetary_resources_cache import DataUnavailableError
     49 from sovereignty.skyhook.client.theft_vulnerability_filters import filter_current_vulnerable_skyhooks
     50 STATE_NORMAL = 'normal'
     51 STATE_COMPACT = 'compact'
     52 STATE_FULLY_COMPACT = 'fully_compact'
     53 
     54 class MapViewWorld(MapViewFiltered):
     55     previewBubbleMarkerIDs = None
     56     debugCircleCont = None
     57     nav_buttons = None
     58     updatePreviewMarkers_thread = None
     59     keyDownCookie = None
     60     keyUpCookie = None
     61     __notifyevents__ = MapViewFiltered.__notifyevents__ + ['On2dMapLayoutChange']
     62 
     63     def ApplyAttributes(self, attributes):
     64         self.currentSpriteValues = None
     65         self.last_zoom_value = 0
     66         self._is_compact = False
     67         self.default_clipChildren = True
     68         self._state = STATE_NORMAL
     69         super(MapViewWorld, self).ApplyAttributes(attributes)
     70         self.update()
     71         self.ConstructDebugContainer()
     72         self.keyDownCookie = uicore.event.RegisterForTriuiEvents(uiconst.UI_KEYDOWN, self.OnGlobalKeyCallback)
     73         self.keyUpCookie = uicore.event.RegisterForTriuiEvents(uiconst.UI_KEYUP, self.OnGlobalKeyCallback)
     74         mapDebugModeActive.on_change.connect(self.OnDebugModeChanged)
     75         sm.ScatterEvent('OnClientEvent_OpenMap')
     76         focus_map_on_location.connect(self.OnFocusMapOnLocation)
     77         jumpRangeExcludeIneligibleSystem.on_change.connect(self.OnJumpRangeSettingsChanged)
     78 
     79     def update(self):
     80         self.update_compact_state()
     81         self.selected_filter_widget.update()
     82 
     83     def ConstructMapNavigation(self):
     84         self.mapNavigation = MapViewWorldNavigation(parent=self, align=uiconst.TOALL, state=uiconst.UI_NORMAL, mapView=self)
     85 
     86     def ConstructDebugContainer(self):
     87         if mapDebugModeActive.get() and getattr(self, 'mapDebugContainer', None) is None:
     88             self.mapDebugContainer = MapDebugContainer(parent=self, align=uiconst.TOPLEFT, idx=0, top=30, mapView=self)
     89 
     90     def ConstructOverlayTools(self):
     91         self.ConstructExpandedOverlay()
     92         self.ConstructMinimizedOverlay()
     93         self.ConstructGradientOverlay()
     94 
     95     def ConstructExpandedOverlay(self):
     96         self._expanded_container = Container(name='_expanded_container', parent=self, align=uiconst.TOALL)
     97         self.layout_widget = MapLayoutWidget(parent=self._expanded_container, align=uiconst.BOTTOMLEFT, pos=(0, 0, 120, 120), on_settings_changed_callback=self.OnMapViewSettingChanged, map_view_id=self.mapViewID)
     98         self._compact_layout_widget = MapLayoutWidgetCompact(parent=self._expanded_container, align=uiconst.BOTTOMLEFT, pos=(0, 0, 90, 90), on_settings_changed_callback=self.OnMapViewSettingChanged, map_view_id=self.mapViewID)
     99         self.layout_widget_pointer_cont = Container(name='layout_widget_pointer_cont', parent=self, align=uiconst.BOTTOMLEFT, pos=(0, 0, 36, 36), uniqueUiName=pConst.UNIQUE_NAME_MAP_LAYOUT, state=uiconst.UI_NORMAL)
    100         self._filter_settings = FilterSettingsPanel(parent=self._expanded_container, align=uiconst.BOTTOMLEFT, pos=(80, 80, 360, 414), state=uiconst.UI_HIDDEN)
    101         self._legend = MapViewLegend(parent=self._expanded_container, align=uiconst.BOTTOMLEFT, pos=(40, 130, 200, 200), open_settings_callback=self._ShowFilterSettingsPanel)
    102         self.overlayTools = Container(parent=self._expanded_container, name='overlayTools')
    103         self.sidePanel = MapSidePanel(parent=self._expanded_container, map_view_id=self.mapViewID)
    104         self.sidePanel.Hide()
    105         self.searchField = MapViewSearchControl(parent=self.overlayTools, mapView=self, align=uiconst.TOPRIGHT)
    106         self.colorModeInfoPanel = ColorModeInfoBase(parent=self.overlayTools, align=uiconst.TOPRIGHT, padTop=40, mapView=self)
    107         self._compact_layout_widget.Hide()
    108         self.selectedInfoCont = SelectedInfoCont(parent=self._expanded_container, align=uiconst.CENTERTOP, setActiveCallback=self.OnSelectedInfoLocationClicked, top=30)
    109         self.nav_buttons = MapViewNavButtons(parent=self.overlayTools, map_view_id=self.mapViewID, on_abstract_mode_toggled=self.UpdateAbstractMode, on_focus_home_callback=self.focus_home, on_focus_current_position_callback=self.focus_current_position, on_jump_range_callback=self.change_jump_range_display, jump_range_func=self.GetJumpDriveRange)
    110         mapPreviewModeActive.on_change.connect(self.OnPreviewModeSettingChanged)
    111         self.mapCompass = MapCompass(parent=self.overlayTools, align=uiconst.BOTTOMRIGHT, pos=(0, 90, 65, 65), onClickCallback=self.OnMapCompassClicked)
    112         self.UpdateMapCompassDisplay()
    113         self.filter_nav = MapViewFilterNav(parent=self.overlayTools, map_view_id=self.mapViewID)
    114         self.selected_filter_widget = SelectedFilterWidget(parent=self.overlayTools, map_view_id=self.mapViewID, align=uiconst.CENTERBOTTOM)
    115 
    116     def ConstructMinimizedOverlay(self):
    117         self._minimized_container = Container(parent=self, name='minimized_overlay', align=uiconst.TOALL, padTop=30)
    118         self._minimized_search_field = MapViewSearchControl(parent=self._minimized_container, mapView=self, align=uiconst.TOPRIGHT)
    119         self._bottom_container = Container(parent=self._minimized_container, align=uiconst.TOBOTTOM, height=22, padding=(4, 0, 2, 4))
    120         self._minimized_nav_container = ContainerAutoSize(parent=self._bottom_container, align=uiconst.TORIGHT, padLeft=4)
    121         self._minimized_selection_container = Container(parent=self._bottom_container, align=uiconst.TOALL)
    122         self._minimized_selected_filter_widget = BaseSelectedFilterWidget(parent=self._minimized_selection_container, map_view_id=self.mapViewID, align=uiconst.TOALL)
    123 
    124         def get_minimzied_button_cont():
    125             return Container(parent=self._minimized_nav_container, align=uiconst.TORIGHT, width=20, height=20, padLeft=4)
    126 
    127         self._minimized_home_button = ButtonIcon(parent=get_minimzied_button_cont(), align=uiconst.CENTER, iconSize=16, texturePath=eveicon.find_home_station, iconColor=TextColor.SECONDARY, hint=localization.GetByLabel('UI/Map/MapPallet/buttonTooltipFocusHome'), soundClick='map_home_station_play', func=self.focus_home)
    128         self._minimized_position_button = ButtonIcon(parent=get_minimzied_button_cont(), align=uiconst.CENTER, iconSize=16, texturePath=eveicon.focus_viewfinder, iconColor=TextColor.SECONDARY, hint=localization.GetByLabel('UI/Map/MapPallet/buttonTooltipFocusCurrentPosition'), func=self.focus_current_position, soundClick='map_current_location_play')
    129         self._minimized_filter_button = MapViewColorModeSettingButton(parent=get_minimzied_button_cont(), align=uiconst.CENTER, iconSize=16, mapViewID=self.mapViewID, settingGroupKey=VIEWMODE_COLOR_SETTINGS, callback=self.OnMapViewSettingChanged)
    130         self._minimized_container.Hide()
    131 
    132     def ConstructGradientOverlay(self):
    133         self._bottom_gradient = GradientSprite(parent=self, align=uiconst.TOBOTTOM_NOPUSH, pickState=PickState.OFF, height=250, rgbData=((0, (0.0, 0.0, 0.0)), (1.0, (0.0, 0.0, 0.0))), alphaData=((0.0, 0.0), (1.0, 0.85)), rotation=3 * math.pi / 2)
    134         self._top_gradient = GradientSprite(parent=self, align=uiconst.TOTOP_NOPUSH, pickState=PickState.OFF, height=250, rgbData=((0, (0.0, 0.0, 0.0)), (1.0, (0.0, 0.0, 0.0))), alphaData=((0.0, 0.0), (1.0, 0.85)), rotation=math.pi / 2.0)
    135 
    136     def OnMapViewSettingChanged(self, settingKey, settingValue, *args, **kwds):
    137         if settingKey == VIEWMODE_MARKERS_SETTINGS and not self.currentSolarsystem:
    138             self.UpdateVulnerableSkyhooks()
    139         super(MapViewWorld, self).OnMapViewSettingChanged(settingKey, settingValue, *args, **kwds)
    140 
    141     def RegisterListeners(self):
    142         super(MapViewWorld, self).RegisterListeners()
    143         map_signals.color_mode_changed.connect(self.UpdateMapViewColorMode)
    144 
    145     def UnregisterListeners(self):
    146         super(MapViewWorld, self).UnregisterListeners()
    147         map_signals.color_mode_changed.disconnect(self.UpdateMapViewColorMode)
    148 
    149     def UpdateColorModeInfoPanel(self, filter):
    150         self.colorModeInfoPanel.LoadColorModeInfo(filter)
    151         self.sidePanel.OnFilterChanged(filter)
    152         self._legend.on_filter_updated(filter)
    153         self._filter_settings.load_filter(filter)
    154 
    155     def _OnFilterDataUpdated(self):
    156         self.UpdateVulnerableSkyhooks()
    157 
    158     def SetActiveItemID(self, itemID, localID = None, zoomToItem = False, animate = True, *args, **kwds):
    159         MapView.SetActiveItemID(self, itemID, localID, zoomToItem, animate, *args, **kwds)
    160         self.selectedInfoCont.Update(self.activeSolarSystemID, self.activeConstellationID, self.activeRegionID)
    161         on_map_location_selected(itemID)
    162         sm.ScatterEvent('OnMapLocationSelected', itemID)
    163 
    164     def OnWindowResize(self, width, height):
    165         if width > 600 or self.isFullScreen:
    166             self.selectedInfoCont.SetShouldShow(True)
    167         else:
    168             self.selectedInfoCont.SetShouldShow(False)
    169         self.selectedInfoCont.UpdateDisplayState()
    170         MapView.OnWindowResize(self, width, height)
    171         self.set_state(self.get_state(width))
    172         if self.isFullScreen:
    173             window_width = uicore.uilib.desktop.width
    174             window_height = uicore.uilib.desktop.height
    175         else:
    176             window_width = width
    177             window_height = height
    178         self.sidePanel.OnWindowResize(self._state, window_width, window_height)
    179 
    180     def get_state(self, width):
    181         if self.isFullScreen:
    182             if uicore.uilib.desktop.width < 1700:
    183                 return STATE_COMPACT
    184             return STATE_NORMAL
    185         elif width < 640:
    186             return STATE_FULLY_COMPACT
    187         else:
    188             return STATE_COMPACT
    189 
    190     def OnCameraUpdate(self):
    191         MapView.OnCameraUpdate(self)
    192         if self.camera:
    193             self.mapCompass.Update(self.camera.yaw)
    194 
    195     def toggle_abstract_mode(self):
    196         self.UpdateAbstractMode()
    197 
    198     def focus_home(self):
    199         self.LookAtHomeStation(playSound=False)
    200         self.UpdateLines()
    201 
    202     def focus_current_position(self):
    203         if not IsKnownSpaceSystem(session.solarsystemid2):
    204             mapViewUtil.OpenSolarSystemMap()
    205         else:
    206             self.LookAtCurrentLocation(playSound=False)
    207             self.UpdateLines()
    208 
    209     def change_jump_range_display(self):
    210         self.ReconstructMyLocationMarker()
    211         self.UpdateJumpRangeDisplay()
    212 
    213     def UpdateMyLocation(self):
    214         super(MapViewWorld, self).UpdateMyLocation()
    215         if self.nav_buttons:
    216             self.nav_buttons.update_jump_range_state()
    217 
    218     @property
    219     def is_compact(self):
    220         return self._is_compact or not self.isFullScreen
    221 
    222     def set_state(self, state):
    223         if self._state == state:
    224             return
    225         self._state = state
    226         self.update_compact_state()
    227 
    228     def update_compact_state(self):
    229         if self._state == STATE_NORMAL:
    230             self._expanded_container.Show()
    231             self._minimized_container.Hide()
    232             self.filter_nav.update_compact_mode(False)
    233             self.selected_filter_widget.update_compact_mode(False)
    234             self.nav_buttons.update_compact_mode(False)
    235             self.mapCompass.update_compact_mode(False)
    236             self.layout_widget.Show()
    237             self._compact_layout_widget.Hide()
    238         elif self._state == STATE_COMPACT:
    239             self._expanded_container.Show()
    240             self._minimized_container.Hide()
    241             self.filter_nav.update_compact_mode(True)
    242             self.selected_filter_widget.update_compact_mode(True)
    243             self.nav_buttons.update_compact_mode(True)
    244             self.mapCompass.update_compact_mode(True)
    245             self.layout_widget.Hide()
    246             self._compact_layout_widget.Show()
    247         else:
    248             self._expanded_container.Hide()
    249             self._minimized_container.Show()
    250         self.update_gradient_state()
    251         self.update_layout_pointer_cont()
    252 
    253     def update_gradient_state(self):
    254         if self._state == STATE_NORMAL:
    255             self._top_gradient.height = 250
    256             self._bottom_gradient.height = 250
    257         elif self._state == STATE_COMPACT:
    258             self._top_gradient.height = 125
    259             self._bottom_gradient.height = 150
    260         else:
    261             self._top_gradient.height = 75
    262             self._bottom_gradient.height = 75
    263 
    264     def update_layout_pointer_cont(self):
    265         if self._state == STATE_COMPACT:
    266             layout = WIDGET_STYLE_COMPACT
    267         else:
    268             layout = WIDGET_STYLE_NORMAL
    269         self.layout_widget_pointer_cont.left = layout.get('button_offset_x', 32)
    270         self.layout_widget_pointer_cont.top = layout.get('button_offset_y', 32)
    271 
    272     def UpdateMapViewColorMode(self):
    273         super(MapViewWorld, self).UpdateMapViewColorMode()
    274         self.UpdateVulnerableSkyhooks()
    275         self.update()
    276 
    277     def PickSceneNearMouse(self):
    278         mouseX, mouseY = uicore.uilib.x, uicore.uilib.y
    279         if self.ShouldShowPreviewForAll():
    280             return
    281         nearMouse = self.GetObjectsNearMouse(mouseX, mouseY)
    282         self.OnPreviewMarkersUpdated(set(nearMouse))
    283 
    284     def ClearNearMouse(self, showSelected = True):
    285         if self.ShouldShowPreviewForAll():
    286             return
    287         markerIDs = set()
    288         if showSelected and IsSolarSystem(self.activeItemID):
    289             markerIDs.add(self.activeItemID)
    290         self.OnPreviewMarkersUpdated(markerIDs)
    291 
    292     def ShouldShowPreviewForAll(self):
    293         if mapPreviewModeActive.get():
    294             return True
    295         CTRL = uicore.uilib.Key(uiconst.VK_CONTROL)
    296         return bool(CTRL)
    297 
    298     def OnPreviewMarkersUpdated(self, markerIDsSet):
    299         if not self.markersHandler:
    300             return
    301         if markerIDsSet and len(markerIDsSet) > 2000:
    302             return
    303         if self.previewBubbleMarkerIDs != markerIDsSet:
    304             previousMarkerIDs = self.previewBubbleMarkerIDs
    305             self.previewBubbleMarkerIDs = markerIDsSet
    306             self.UpdateParticles(previousMarkerIDs, markerIDsSet)
    307             if markerIDsSet:
    308                 self.markersHandler.SetPreviewBubbleMarkers(markerIDsSet)
    309             else:
    310                 self.markersHandler.SetPreviewBubbleMarkers(None)
    311 
    312     def UpdateParticles(self, previousMarkerIDs, newMarkerIDsSet):
    313         previous = previousMarkerIDs or set()
    314         new = newMarkerIDsSet or set()
    315         diff = previous.symmetric_difference(new)
    316         if diff:
    317             spriteValues = self._GetSpriteEffectPathAndStaticSize()
    318             boldSystemIDs = self.GetBoldSystemsForShape()
    319             for solarSystemID in diff:
    320                 node = self.layoutHandler.GetNodeBySolarSystemID(solarSystemID)
    321                 if not node:
    322                     continue
    323                 (self._UpdateDataShapeAndSizeForSolarSystem(node.particleID, solarSystemID, spriteValues, boldSystemIDs),)
    324 
    325             self.starParticles.UpdateData()
    326 
    327     def _GetModifiedStarColor(self, solarSystemID, boldSystemIDs, spriteMode):
    328         if solarSystemID not in boldSystemIDs:
    329             return
    330         originalStarColor = self.starColorByID.get(solarSystemID, None)
    331         if not originalStarColor:
    332             return
    333         if spriteMode:
    334             return originalStarColor
    335         alpha = originalStarColor[3]
    336         updatedStarColor = originalStarColor[:3] + (3.0 * alpha,)
    337         return updatedStarColor
    338 
    339     def _GetDataTextureShape(self, boldSystemIDs, solarSystemID, markerSizeType):
    340         if markerSizeType == MARKER_MEDIUM:
    341             if self.previewBubbleMarkerIDs is None or solarSystemID not in self.previewBubbleMarkerIDs:
    342                 return 4.0
    343             elif solarSystemID == self.activeItemID:
    344                 if solarSystemID in boldSystemIDs:
    345                     return 8.0
    346                 return 6.0
    347             elif solarSystemID in boldSystemIDs:
    348                 return 7.0
    349             else:
    350                 return 5.0
    351         elif markerSizeType == MARKER_BIG:
    352             if solarSystemID == self.activeItemID:
    353                 if solarSystemID in boldSystemIDs:
    354                     return 3.0
    355                 return 1.0
    356             elif solarSystemID in boldSystemIDs:
    357                 return 2.0
    358             else:
    359                 return 0.0
    360         return 0.0
    361 
    362     def UpdatePartilesForActiveItem(self, previousActiveItemID, currentActiveItemID):
    363         previousValue = self.__GetActiveItemValue(previousActiveItemID)
    364         currentValue = self.__GetActiveItemValue(currentActiveItemID)
    365         self.UpdateParticles(previousValue, currentValue)
    366 
    367     def __GetActiveItemValue(self, activeItemID):
    368         if activeItemID is None:
    369             return
    370         if isinstance(activeItemID, list):
    371             return set(activeItemID)
    372         return {activeItemID}
    373 
    374     def ApplyStarColors(self):
    375         super(MapViewFiltered, self).ApplyStarColors()
    376         if self.IsAbstractModeActive():
    377             self.extraStarParticleController.ChangeDisplayState(True)
    378         else:
    379             self.extraStarParticleController.ChangeDisplayState(False)
    380 
    381     def GetObjectsNearMouse(self, mouseX, mouseY):
    382         if not self.markersHandler:
    383             return []
    384         if not self.IsAbstractModeActive():
    385             return []
    386         if not self._CanPreviewMarkers():
    387             return []
    388         boxSize = self._GetNearMouseDistance()
    389         boxSizeSqrd = boxSize ** 2
    390         x, y = ScaleDpi(mouseX), ScaleDpi(mouseY)
    391         vx, vy = self.sceneContainer.viewport.x, self.sceneContainer.viewport.y
    392         vw = self.sceneContainer.viewport.width
    393         vh = self.sceneContainer.viewport.height
    394         bufferValue = 20
    395         maxXinView = vw + bufferValue
    396         maxYinView = vh + bufferValue
    397         self.TryShowDebugCircle(x, y)
    398         pickedWithDistance = []
    399         for markerID, marker in self.markersHandler.projectBrackets.iteritems():
    400             if not marker.projectBracket.isInFront or not marker.positionPickable:
    401                 continue
    402             mx, my = marker.projectBracket.rawProjectedPosition
    403             if mx < -bufferValue or mx > maxXinView:
    404                 continue
    405             if my < -bufferValue or my > maxYinView:
    406                 continue
    407             bracketPosX = vx + mx
    408             bracketPosY = vy + my
    409             diffX = abs(bracketPosX - x)
    410             diffY = abs(bracketPosY - y)
    411             distanceSquared = diffX * diffX + diffY * diffY
    412             if distanceSquared < boxSizeSqrd or markerID == self.activeItemID:
    413                 pickedWithDistance.append((distanceSquared, markerID))
    414 
    415         if not pickedWithDistance:
    416             return []
    417         sortedPickedWithDistance = sorted(pickedWithDistance, key=lambda data: data[0])
    418         return [ x[1] for x in sortedPickedWithDistance ]
    419 
    420     def _UpdateDistanceRangeValues(self, cameraDistance):
    421         if self.IsAbstractModeActive():
    422             fadeOutFar = max(100.0, cameraDistance * 4)
    423             self.distanceRangeStars.value = (cameraDistance,
    424              fadeOutFar,
    425              0,
    426              0)
    427             if self.distanceRangeLines:
    428                 fadeOutNear = MAX_CAMERA_DISTANCE_2DVIEW
    429                 fadeOutFar = MAX_CAMERA_DISTANCE_2DVIEW * 10000
    430                 self.distanceRangeLines.value = (fadeOutNear,
    431                  fadeOutFar,
    432                  0,
    433                  0)
    434         else:
    435             super(MapViewFiltered, self)._UpdateDistanceRangeValues(cameraDistance)
    436 
    437     def _TryUpdateStarDataTexturePath(self):
    438         if self.waiting_for_layout_change:
    439             return
    440         if not getattr(self, 'activeFilter', None):
    441             return
    442         spriteValues = self._GetSpriteEffectPathAndStaticSize()
    443         if self.currentSpriteValues == spriteValues:
    444             return
    445         self.currentSpriteValues = spriteValues
    446         self.OnPreviewMarkersUpdated(set())
    447         self.starDataTexture.resourcePath = spriteValues.spriteTexture
    448         self._UpdateDataShapeAndSize()
    449         self.starParticles.UpdateData()
    450         self.extraStarParticleController.UpdateStarParticleData()
    451         self.dirtyLineIDs.clear()
    452         self.UpdateLineColorData()
    453         self.UpdateAutopilotJumpRoute()
    454         self.solarSystemJumpLineSet.SubmitChanges()
    455         self._UpdatePreviewMarkers()
    456 
    457     def _GetSpriteEffectPathAndStaticSize(self):
    458         if self.IsAbstractModeActive():
    459             zoomValue = self.camera.GetZoomValue()
    460             if zoomValue < MAP2D_ZOOM_TUBE_MARKER:
    461                 return SpriteValues(MARKER_BIG, PARTICLE_SPRITE_TUBE_TEXTURE, TUBE_BUBBLE_SIZE, 1.0, EXTRA_BUBBLE_BIG_SIZE_FACTOR)
    462             if zoomValue < MAP2D_ZOOM_TUBE_BUBBLE:
    463                 return SpriteValues(MARKER_MEDIUM, PARTICLE_SPRITE_TUBE_TEXTURE, TUBE_BUBBLE_SIZE, 1.0, EXTRA_BUBBLE_MEDIUM_SIZE_FACTOR)
    464         return SpriteValues(MARKER_NONE, self.activeFilter.GetSpriteEffectPath(), None, 0.0, 0.0)
    465 
    466     def _GetBoldSystems(self):
    467         if not GetMapViewSetting(VIEWMODE_LAYOUT_SHOW_JUMP_RANGE_SETTINGS, self.mapViewID):
    468             return set()
    469         driveRange = self.GetJumpDriveRange()
    470         if driveRange <= 0:
    471             return set()
    472         boldSystems = {k for k, v in self._GetSystemsInJumpRange(driveRange).iteritems() if v == JUMP_RANGE_INSIDE}
    473         return boldSystems
    474 
    475     def GetBoldSystemsForShape(self):
    476         return self._GetBoldSystems()
    477 
    478     def GetBoldSystemsForOpacityModifcation(self):
    479         if self.IsAbstractModeActive():
    480             zoomValue = self.camera.GetZoomValue()
    481             if zoomValue < MAP2D_ZOOM_TUBE_BUBBLE:
    482                 return set()
    483         return self._GetBoldSystems()
    484 
    485     def _GetNearMouseDistance(self):
    486         cameraProjectionFovConst = self.camera.GetProjectionFovConst(self.camera.GetAspectRatio())
    487         return GetSizeForUIElement(PREVIEW_PICKER_SIZE, self.sceneContainer.viewport.height, cameraProjectionFovConst)
    488 
    489     def TryShowDebugCircle(self, x, y):
    490         if not mapDebugModeActive.get():
    491             return
    492         self.ConstructDebugCircle(x, y)
    493         self.debugCircleCont.left = x - 0.5 * self.debugCircleCont.width
    494         self.debugCircleCont.top = y - 0.5 * self.debugCircleCont.height
    495 
    496     def ConstructDebugCircle(self, x, y):
    497         nearMouseDist = self._GetNearMouseDistance()
    498         if self.debugCircleCont:
    499             if self.debugCircleCont == 2 * nearMouseDist:
    500                 return
    501             self._KillDebugCircle()
    502         from carbonui.primitives.vectorlinetrace import DashedCircle
    503         self.debugCircleCont = Container(name='debugCircleCont', parent=uicore.layer.abovemain, align=uiconst.TOPLEFT, pos=(0,
    504          0,
    505          2 * nearMouseDist,
    506          2 * nearMouseDist))
    507         debugCircle = DashedCircle(parent=self.debugCircleCont, radius=nearMouseDist, left=0, top=0, range=math.radians(360.0), lineWidth=1.0)
    508         self.debugCircleCont.debugCircle = debugCircle
    509         debugLabel = TextHeader(parent=self.debugCircleCont, text=nearMouseDist, bold=True, align=uiconst.CENTER)
    510         self.debugCircleCont.debugLabel = debugLabel
    511 
    512     def OnDebugModeChanged(self, value, *args):
    513         if value:
    514             self.ConstructDebugContainer()
    515         else:
    516             self._KillDebugContainers()
    517 
    518     def UpdateAbstractMode(self):
    519         self.extraStarParticleController.ChangeDisplayState(False)
    520         super(MapViewWorld, self).UpdateAbstractMode()
    521         self.TryStartUpdatePreviewMarkersThread()
    522         self.UpdateMapCompassDisplay()
    523 
    524     def UpdateMapCompassDisplay(self):
    525         if self.IsAbstractModeActive():
    526             self.mapCompass.Hide()
    527         else:
    528             self.mapCompass.Show()
    529 
    530     def OnGlobalKeyCallback(self, wnd, eventID, param):
    531         vkey, flag = param
    532         if vkey != uiconst.VK_CONTROL:
    533             return True
    534         if eventID == uiconst.UI_KEYDOWN and flag & 1073741824:
    535             return True
    536         try:
    537             self.TryStartUpdatePreviewMarkersThread()
    538         finally:
    539             return True
    540 
    541     def TryStartUpdatePreviewMarkersThread(self):
    542         if self.updatePreviewMarkers_thread:
    543             return
    544         if not self.ShouldShowPreviewForAll():
    545             return
    546         self._UpdatePreviewMarkers()
    547         self.updatePreviewMarkers_thread = AutoTimer(200, self.UpdatePreviewMarkers_thread)
    548 
    549     def UpdatePreviewMarkers_thread(self):
    550         if self.destroyed:
    551             self.updatePreviewMarkers_thread = None
    552             return
    553         continueUpdating = self._UpdatePreviewMarkers()
    554         if not continueUpdating:
    555             self.updatePreviewMarkers_thread = None
    556 
    557     def _UpdatePreviewMarkers(self):
    558         if not self.IsAbstractModeActive():
    559             return False
    560         if not self._CanPreviewMarkers():
    561             return True
    562         showAllPreview = self.ShouldShowPreviewForAll()
    563         if not showAllPreview:
    564             self.PickSceneNearMouse()
    565             return False
    566         vw = self.sceneContainer.viewport.width
    567         vh = self.sceneContainer.viewport.height
    568         bufferValue = 20
    569         maxXinView = vw + bufferValue
    570         maxYinView = vh + bufferValue
    571         toShow = set()
    572         for markerID, marker in self.markersHandler.projectBrackets.iteritems():
    573             if not IsSolarSystem(markerID):
    574                 continue
    575             mx, my = marker.projectBracket.rawProjectedPosition
    576             if mx < -bufferValue or mx > maxXinView:
    577                 continue
    578             if my < -bufferValue or my > maxYinView:
    579                 continue
    580             toShow.add(markerID)
    581 
    582         self.OnPreviewMarkersUpdated(toShow)
    583         return True
    584 
    585     def _CanPreviewMarkers(self):
    586         zoomValue = self.camera.GetZoomValue()
    587         if zoomValue < MAP2D_ZOOM_TUBE_MARKER:
    588             return False
    589         if zoomValue > MAP2D_ZOOM_TUBE_BUBBLE:
    590             return False
    591         return True
    592 
    593     def OnPreviewModeSettingChanged(self, value):
    594         self.TryStartUpdatePreviewMarkersThread()
    595 
    596     def LayoutChangeStarting(self, changedSolarSystems):
    597         super(MapViewWorld, self).LayoutChangeStarting(changedSolarSystems)
    598         self.nav_buttons.on_layout_transition_started()
    599 
    600     def LayoutAnimationStarted(self, changedSolarSystems):
    601         if self.IsAbstractModeActive():
    602             self.markersHandler.SetDisplayStateOverrideFilterFalseForSystems()
    603         self.UpdateCameraForAbstractView()
    604 
    605     def LayoutChangeCompleted(self, changedSolarSystems):
    606         super(MapViewWorld, self).LayoutChangeCompleted(changedSolarSystems)
    607         if self.destroyed:
    608             return
    609         self.nav_buttons.on_layout_transition_completed()
    610         if self.IsAbstractModeActive():
    611             self.UpdateMarkersFilter()
    612             self.TryStartUpdatePreviewMarkersThread()
    613         if isinstance(self.activeItemID, collections.Iterable):
    614             self.UpdateCameraFocus(zoomToItem=False)
    615         else:
    616             self.FocusCameraOnActiveEntity(zoomToItem=False)
    617 
    618     def LayoutChanging(self, progress, changedSolarSystems):
    619         super(MapViewWorld, self).LayoutChanging(progress, changedSolarSystems)
    620         if isinstance(self.activeItemID, collections.Iterable):
    621             return
    622         activeItemNode = changedSolarSystems.get(self.activeItemID, None)
    623         if activeItemNode:
    624             animPosition = activeItemNode.animPosition
    625             self.camera.LookAtPoint(animPosition, animate=False)
    626 
    627     def InitCameraFocus(self, zoomToItem = True):
    628         if self.IsAbstractModeActive():
    629             zoomToItem = False
    630         super(MapViewWorld, self).InitCameraFocus(zoomToItem)
    631 
    632     def UpdateInitCameraDistance(self):
    633         if self.IsAbstractModeActive():
    634             defaultPos = self.camera.default_eyePosition
    635             distY = map2dEyeDistYSetting.get()
    636             distY = distY or defaultPos[1]
    637             newEyePos = (defaultPos[0], distY, defaultPos[2])
    638             self.camera.SetEyePosition(newEyePos)
    639 
    640     def UpdateCameraForAbstractView(self):
    641         abstracModeActive = self.IsAbstractModeActive()
    642         is2dCamera = self.sceneContainer.camera.is2dCamera
    643         if abstracModeActive and not is2dCamera:
    644             self.sceneContainer.camera.Make2DCamera()
    645         elif not abstracModeActive and is2dCamera:
    646             self.sceneContainer.camera.Make3DCamera()
    647         else:
    648             return
    649 
    650     def DoesZoomOnSelection(self):
    651         return not self.IsAbstractModeActive()
    652 
    653     def AreMarkersAbstractMode(self):
    654         return self.IsAbstractModeActive()
    655 
    656     def UpdateJumpDriveRangeMarkers(self, driveRange):
    657         if GetMapViewSetting(VIEWMODE_LAYOUT_SHOW_JUMP_RANGE_SETTINGS, self.mapViewID):
    658             systemIDsInRange = self._GetSystemsInJumpRange(driveRange)
    659         else:
    660             systemIDsInRange = {}
    661             driveRange = None
    662         self.UpdateMarkersForJumpRange(systemIDsInRange, driveRange)
    663 
    664     def _GetSystemsInJumpRange(self, driveRange):
    665         excludeIneligibleSystems = jumpRangeExcludeIneligibleSystem.get()
    666         return self._GetSystemsInJumpRangeFromSystem(driveRange, session.solarsystemid2, excludeIneligibleSystems)
    667 
    668     @Memoize(5)
    669     def _GetSystemsInJumpRangeFromSystem(self, driveRange, sourceSystemID, excludeIneligibleSystems):
    670         lyDistFinder = sm.GetService('clientPathfinderService').GetLightYearDistanceFinder()
    671         systemsInRange = {}
    672         for systemID in self._GetKnownUniverseSolarSystems().iterkeys():
    673             if systemID == sourceSystemID:
    674                 continue
    675             isInRange = lyDistFinder.IsInRange(driveRange, sourceSystemID, systemID)
    676             if isInRange:
    677                 if excludeIneligibleSystems and not IsValidJumpTarget(systemID):
    678                     systemsInRange[systemID] = JUMP_RANGE_INSIDE_EXCLUDED
    679                 else:
    680                     systemsInRange[systemID] = JUMP_RANGE_INSIDE
    681 
    682         return systemsInRange
    683 
    684     def UpdateMarkersForJumpRange(self, systemsInRange, driveRange):
    685         for markerID, marker in self.markersHandler.projectBrackets.iteritems():
    686             if not isinstance(marker, MarkerLabelSolarSystem):
    687                 continue
    688             if not driveRange:
    689                 jumpRangeMode = JUMP_RANGE_OFF
    690             elif markerID in systemsInRange:
    691                 jumpRangeMode = systemsInRange[markerID]
    692             else:
    693                 jumpRangeMode = JUMP_RANGE_OUTSIDE
    694             marker.SetJumpRangeMode(jumpRangeMode)
    695 
    696     def OnJumpRangeSettingsChanged(self, *args):
    697         self.UpdateJumpRangeDisplay()
    698 
    699     def On2dMapLayoutChange(self):
    700         self.layoutHandler.ReloadLayout()
    701         self.UpdateRegionAndConstellationMarkerPositions()
    702         self.UpdateLandmarkPositions()
    703 
    704     def ExpandSelectedSolarSystem(self, solarSystemID):
    705         if self.IsAbstractModeActive():
    706             return
    707         super(MapViewWorld, self).ExpandSelectedSolarSystem(solarSystemID)
    708 
    709     def _KillDebugContainers(self):
    710         self._KillDebugCircle()
    711         if getattr(self, 'mapDebugContainer', None):
    712             self.mapDebugContainer.Close()
    713             self.mapDebugContainer = None
    714 
    715     def _KillDebugCircle(self):
    716         if self.debugCircleCont:
    717             self.debugCircleCont.Close()
    718             self.debugCircleCont = None
    719 
    720     def LoadLineIndicators(self):
    721         for lineID, lineData in self.jumpLineInfoByLineID.iteritems():
    722             if lineData.jumpType != REGION_JUMP:
    723                 continue
    724             fromMarkerObject = self.markersHandler.GetMarkerByID(lineData.fromSolarSystemID)
    725             toMarkerObject = self.markersHandler.GetMarkerByID(lineData.toSolarSystemID)
    726             if not fromMarkerObject and not toMarkerObject:
    727                 continue
    728             try:
    729                 fx, fy, fz = GetSolarSystemCoordinates(True, lineData.fromSolarSystemID, None)
    730                 tx, ty, tz = GetSolarSystemCoordinates(True, lineData.toSolarSystemID, None)
    731             except AttributeError as e:
    732                 continue
    733 
    734             angleBetweenPoints = self._GetRadiansAngleBetweenPoints(fx, fz, tx, tz)
    735             if toMarkerObject:
    736                 toMarkerObject.UpdateRegionGatesInfo(lineData.fromSolarSystemID, angleBetweenPoints)
    737             if fromMarkerObject:
    738                 fromMarkerObject.UpdateRegionGatesInfo(lineData.toSolarSystemID, math.pi + angleBetweenPoints)
    739 
    740     def _GetRadiansAngleBetweenPoints(self, x1, y1, x2, y2):
    741         dx = x2 - x1
    742         dy = y2 - y1
    743         angleRad = math.atan2(dy, dx)
    744         angleRad += math.pi / 2
    745         if angleRad < 0:
    746             angleRad += 2 * math.pi
    747         return angleRad
    748 
    749     def Close(self, *args, **kwds):
    750         super(MapViewWorld, self).Close(*args, **kwds)
    751         self._GetSystemsInJumpRangeFromSystem.clear_memoized()
    752         mapDebugModeActive.on_change.disconnect(self.OnDebugModeChanged)
    753         mapPreviewModeActive.on_change.disconnect(self.OnPreviewModeSettingChanged)
    754         focus_map_on_location.disconnect(self.OnFocusMapOnLocation)
    755         jumpRangeExcludeIneligibleSystem.on_change.disconnect(self.OnJumpRangeSettingsChanged)
    756         self._KillDebugContainers()
    757         if self.keyDownCookie:
    758             uicore.event.UnregisterForTriuiEvents(self.keyDownCookie)
    759         if self.keyUpCookie:
    760             uicore.event.UnregisterForTriuiEvents(self.keyUpCookie)
    761 
    762     def ConstructExpandedSolarsystem(self, solarSystemID, solarSystemPosition):
    763         super(MapViewWorld, self).ConstructExpandedSolarsystem(solarSystemID, solarSystemPosition)
    764         self._ConstructSolarSystemVulnerableSkyhooks(solarSystemID, solarSystemPosition)
    765 
    766     def _ConstructSolarSystemVulnerableSkyhooks(self, solar_system_id, solar_system_position):
    767         try:
    768             info_by_skyhook = sm.GetService('sovereigntyResourceSvc').GetPlanetIDsAndTheftVulnerabilityData(solar_system_id)
    769             now = datetime.utcnow()
    770             planets = [ skyhook.planet_id for skyhook in info_by_skyhook if skyhook.start < now ]
    771         except DataUnavailableError:
    772             return
    773 
    774         if len(planets) == 0:
    775             return
    776         marker_id = (MARKERID_VULNERABLE_SKYHOOK, solar_system_id)
    777         self.markersHandler.RemoveMarker(marker_id)
    778         for planet_id in planets:
    779             planet = cfg.mapSolarSystemContentCache.planets[planet_id]
    780             planet_position = (planet.position.x, planet.position.y, planet.position.z)
    781             planet_position = SolarSystemPosToMapPos(planet_position)
    782             planet_position = geo2.Vec3ScaleD(planet_position, mapViewConst.SCALING_SOLARSYSTEMINWORLDMAP)
    783             marker_id = (MARKERID_VULNERABLE_SKYHOOK_SOLARSYSTEM, solar_system_id)
    784             self.markersHandler.AddSolarSystemBasedMarker(marker_id, MarkerVulnerableSkyhook, solarSystemID=solar_system_id, mapPositionLocal=planet_position, mapPositionSolarSystem=solar_system_position, distanceFadeAlphaNearFar=None)
    785 
    786     def UpdateVulnerableSkyhooks(self):
    787         uthread.new(self._UpdateVulnerableSkyhooks)
    788 
    789     def _UpdateVulnerableSkyhooks(self):
    790         if self.destroyed:
    791             return
    792         if self.mapRoot is None:
    793             return
    794         self.markersHandler.RemoveMarkersByType(MARKERID_VULNERABLE_SKYHOOK_SOLARSYSTEM)
    795         filterID, _ = self.GetFilterIDAndItemID()
    796         skyhook_settings = GetMapViewSetting(VIEWMODE_MARKERS_SETTINGS, self.mapViewID)
    797         skyhooks_enabled = filterID == mapcommon.STARMODE_VULNERABLE_SKYHOOKS and MARKERS_OPTION_VULNERABLE_SKYHOOK in skyhook_settings
    798         if not skyhooks_enabled:
    799             self.markersHandler.RemoveMarkersByType(MARKERID_VULNERABLE_SKYHOOK)
    800             return
    801         try:
    802             skyhook_info = sm.GetService('sovereigntyResourceSvc').GetTheftVulnerableSkyhookInfo()
    803             now = datetime.utcnow()
    804             vulnerable_skyhooks = filter_current_vulnerable_skyhooks(skyhook_info, now)
    805             solar_systems = vulnerable_skyhooks.iterkeys()
    806         except DataUnavailableError:
    807             return
    808 
    809         if self.destroyed:
    810             return
    811         if self.mapRoot is None:
    812             return
    813         for solar_system_id in solar_systems:
    814             map_node = self.layoutHandler.GetNodeBySolarSystemID(solar_system_id)
    815             position = map_node.position
    816             marker_id = (MARKERID_VULNERABLE_SKYHOOK, solar_system_id)
    817             self.markersHandler.AddSolarSystemBasedMarker(marker_id, MarkerVulnerableSkyhook, solarSystemID=solar_system_id, mapPositionLocal=(0, 0, 0), mapPositionSolarSystem=position, distanceFadeAlphaNearFar=None, skyhook_list=vulnerable_skyhooks[solar_system_id])
    818 
    819     def _SetActiveFilter(self, filter):
    820         if self.activeFilter == filter:
    821             return
    822         super(MapViewWorld, self)._SetActiveFilter(filter)
    823         self.sidePanel.OnFilterChanged(filter)
    824         self._legend.on_filter_updated(filter)
    825         self._filter_settings.load_filter(filter)
    826         self._filter_settings.Hide()
    827 
    828     def OnMouseWheel(self, *args):
    829         super(MapViewWorld, self).OnMouseWheel(*args)
    830         zoom_value = self.camera.GetZoomDistance()
    831         if zoom_value != self.last_zoom_value:
    832             self.last_zoom_value = zoom_value
    833             on_map_zoom_changed(zoom_value)
    834             sm.ScatterEvent('OnMapZoomChanged', zoom_value)
    835 
    836     def OnFocusMapOnLocation(self, locationID):
    837         if not IsKnownSpaceSystem(locationID):
    838             return
    839         self.FocusCameraOnMultipleSystems([locationID], animate=True)
    840 
    841     def _ShowFilterSettingsPanel(self):
    842         self._filter_settings.Toggle()