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

sceneManager.py (38344B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\parklife\sceneManager.py
      2 import logging
      3 import sys
      4 import blue
      5 import uthread
      6 from carbon.common.script.sys.service import Service
      7 from carbonui import uiconst
      8 from carbonui.primitives.containerAutoSize import ContainerAutoSize
      9 from carbonui.uicore import uicore
     10 from eve.client.script.environment.spaceObject.ExplosionManager import ExplosionManager
     11 from eve.client.script.parklife.sceneManagerConsts import SCENE_TYPE_CHARACTER_CREATION, SCENE_TYPE_SPACE, SYSTEM_WIDE_CLOUD_NAME
     12 from eve.client.script.ui.control.eveLabel import EveCaptionLarge, EveLabelLarge
     13 from eve.common.script.sys import idCheckers
     14 from evecamera import INSPACE_CAMERAS, CAM_SHIPORBIT_RESTRICTED, CAM_VCS_CONSUMER, INSPACE_CAMERA_MODES
     15 from evecamera.locationalcamera import get_orbit_camera_by_solar_system
     16 from evegraphics.explosions.spaceObjectExplosionManager import SpaceObjectExplosionManager
     17 import evegraphics.settings as gfxsettings
     18 from eve.common.script.sys.idCheckers import IsKnownSpaceSystem, IsAbyssalSpaceSystem
     19 from eve.client.script.ui.camera import get_camera_class
     20 from eve.client.script.ui.camera.baseCamera import DestinyBallInvalid
     21 from eve.client.script.ui.camera.baseSpaceCamera import BaseSpaceCamera
     22 from eve.client.script.ui.camera.cameraBase import CameraBase
     23 from eve.client.script.ui.view.viewStateConst import ViewState
     24 from fsdBuiltData.common.graphicIDs import GetGraphicFile
     25 import locks
     26 import log
     27 import telemetry
     28 import trinity
     29 from localization import GetByLabel
     30 from trinity.sceneRenderJobSpace import DEFAULT_POSTPROCESS_PATH
     31 stdlog = logging.getLogger(__name__)
     32 MAX_INVALID_CAMERA_FRAMES = 10
     33 
     34 class SceneContext():
     35 
     36     def __init__(self, scene = None, camera = None, sceneKey = 'default', sceneType = None, renderJob = None):
     37         self.scene = scene
     38         self.camera = camera
     39         self.sceneKey = sceneKey
     40         self.sceneType = sceneType
     41         self.renderJob = renderJob
     42 
     43 
     44 def GetSceneManager():
     45     return sm.GetService('sceneManager')
     46 
     47 
     48 class SceneManager(Service):
     49     __guid__ = 'svc.sceneManager'
     50     __exportedcalls__ = {'LoadScene': [],
     51      'GetScene': []}
     52     __startupdependencies__ = ['settings', 'device']
     53     __notifyevents__ = ['OnGraphicSettingsChanged',
     54      'OnSessionChanged',
     55      'OnCameraLookAt',
     56      'OnViewStateChanged']
     57 
     58     def Run(self, ms):
     59         Service.Run(self, ms)
     60         self.registeredScenes = {}
     61         self.registeredCameras = {}
     62         self.sceneLoadedEvents = {}
     63         self.cameraBeforeRestriction = None
     64         self.registeredJobs = []
     65         self.cameraOffsetOverride = None
     66         self.characterBackdropUIRoot = None
     67         self.ProcessImportsAndCreateScenes()
     68         self.primaryJob = SceneContext()
     69         self.secondaryJob = None
     70         self.loadingClearJob = trinity.CreateRenderJob()
     71         self.loadingClearJob.name = 'loadingClear'
     72         self.loadingClearJob.Clear((0, 0, 0, 1))
     73         self.loadingClearJob.enabled = False
     74         self.overlaySceneKeys = [ViewState.StarMap,
     75          ViewState.SystemMap,
     76          ViewState.StarMapNew,
     77          ViewState.SystemMapNew,
     78          ViewState.Planet,
     79          ViewState.ShipTree,
     80          ViewState.DockPanel]
     81         self.overlayForcePostProcessing = {ViewState.StarMap: 0,
     82          ViewState.SystemMap: 0}
     83         self._sharedResources = {}
     84         self.routeVisualizer = None
     85         self.podDeathScene = None
     86         self._persistedSpaceObjects = {}
     87         self._updateCameras = []
     88         self._cameraInvalidFrameCounts = {}
     89         if '/skiprun' not in blue.pyos.GetArg():
     90             self._EnableLoadingClear()
     91         limit = gfxsettings.Get(gfxsettings.GFX_LOD_QUALITY) * 30
     92         self.explosionManager = ExplosionManager(limit)
     93         self.currentFadeIntensity = 0.0
     94         self.currentDesaturateLevel = 1.0
     95         self.enable3DView = True
     96 
     97     def ProcessImportsAndCreateScenes(self):
     98         from trinity.sceneRenderJobSpace import CreateSceneRenderJobSpace
     99         from trinity.sceneRenderJobCharacters import CreateSceneRenderJobCharacters
    100         self.fisRenderJob = CreateSceneRenderJobSpace('SpaceScenePrimary')
    101         self.characterRenderJob = CreateSceneRenderJobCharacters()
    102         self._CreateJobCharCreation()
    103         self._CreateJobFiS()
    104 
    105     def _UpdateSecondaryCameras(self):
    106         for camera in self._updateCameras:
    107             self._UpdateCamera(camera)
    108 
    109     def _UpdateActiveCamera(self):
    110         cam = self.GetActiveCamera()
    111         if cam:
    112             self._UpdateCamera(cam)
    113         self._UpdateSecondaryCameras()
    114 
    115     def _UpdateCamera(self, camera):
    116         try:
    117             camera._Update()
    118         except DestinyBallInvalid as e:
    119             self._OnCameraUpdateInvalid(camera, e)
    120         except Exception:
    121             stdlog.error('Unexpected exception raised from UpdateCamera', exc_info=1, extra={'sample_rate': 0.01})
    122         else:
    123             self._cameraInvalidFrameCounts.pop(camera, None)
    124 
    125     def _OnCameraUpdateInvalid(self, camera, exc):
    126         count = self._cameraInvalidFrameCounts.get(camera, 0) + 1
    127         self._cameraInvalidFrameCounts[camera] = count
    128         if count == MAX_INVALID_CAMERA_FRAMES:
    129             stdlog.warning('Camera failed to update for %s frames, resetting it. e=%s', count, exc)
    130             self._ResetCamera(camera)
    131 
    132     def _ResetCamera(self, camera):
    133         resetCameraPosition = getattr(camera, 'ResetCameraPosition', None)
    134         if resetCameraPosition is None:
    135             return
    136         try:
    137             resetCameraPosition()
    138         except Exception:
    139             stdlog.exception('Failed to reset camera %s', camera)
    140 
    141     def RegisterForCameraUpdate(self, camera):
    142         if camera not in self._updateCameras:
    143             self._updateCameras.append(camera)
    144 
    145     def UnregisterForCameraUpdate(self, camera):
    146         if camera in self._updateCameras:
    147             self._updateCameras.remove(camera)
    148 
    149     def _EnableLoadingClear(self):
    150         if not self.loadingClearJob.enabled:
    151             self.loadingClearJob.enabled = True
    152             trinity.renderJobs.recurring.insert(0, self.loadingClearJob)
    153 
    154     def _DisableLoadingClear(self):
    155         if self.loadingClearJob.enabled:
    156             self.loadingClearJob.enabled = False
    157             trinity.renderJobs.recurring.remove(self.loadingClearJob)
    158 
    159     def RefreshJob(self, camera):
    160         sceneType = self.primaryJob.sceneType
    161         if sceneType == SCENE_TYPE_CHARACTER_CREATION:
    162             self.primaryJob.renderJob.SetActiveCamera(camera)
    163             uicore.uilib.SetSceneView(camera.viewMatrix, camera.projectionMatrix)
    164 
    165     def DeactivateFISCamera(self):
    166         currCam = self.GetActivePrimaryCamera()
    167         if currCam and hasattr(currCam, 'OnDeactivated'):
    168             currCam.OnDeactivated()
    169 
    170     def _CreateJobCharCreation(self):
    171         self.characterRenderJob.CreateBasicRenderSteps()
    172         self.characterRenderJob.EnableScatter(True)
    173         self.characterRenderJob.EnableSculpting(True)
    174         self.characterRenderJob.Set2DBackdropUIRoot(self.characterBackdropUIRoot)
    175         self.characterRenderJob.AddStep('UPDATE_SECONDARY_CAMERAS', trinity.TriStepPythonCB(self._UpdateSecondaryCameras))
    176 
    177     def _CreateJobFiS(self, rj = None):
    178         if rj is None:
    179             rj = self.fisRenderJob
    180         rj.CreateBasicRenderSteps()
    181         rj.SetCameraCallback(self._UpdateActiveCamera)
    182 
    183     def GetFisRenderJob(self):
    184         return self.fisRenderJob
    185 
    186     def GetFiSPostProcess(self):
    187         return self.fisRenderJob.postProcess
    188 
    189     def OnGraphicSettingsChanged(self, changes):
    190         if len(gfxsettings.GFX_SETTINGS.intersection(changes)) == 0:
    191             return
    192         self.fisRenderJob.SetSettingsBasedOnPerformancePreferences()
    193         self.characterRenderJob.SetSettingsBasedOnPerformancePreferences()
    194         activeScene = self.GetActiveScene()
    195         if activeScene is not None and isinstance(activeScene, trinity.EveSpaceScene):
    196             self.fisRenderJob.SetScene(activeScene)
    197         if self.HasSecondaryScene():
    198             self.secondaryJob.renderJob.SetSettingsBasedOnPerformancePreferences()
    199         for each in self.registeredJobs:
    200             each.object.SetSettingsBasedOnPerformancePreferences()
    201 
    202         if gfxsettings.GFX_LOD_QUALITY in changes:
    203             limit = gfxsettings.Get(gfxsettings.GFX_LOD_QUALITY) * 30
    204             self.explosionManager.SetLimit(limit)
    205         if gfxsettings.UI_CAMERA_OFFSET in changes:
    206             self.UpdateCameraOffset()
    207         if session.userid is not None:
    208             effectsEnabled = gfxsettings.Get(gfxsettings.UI_EFFECTS_ENABLED)
    209             if gfxsettings.UI_TRAILS_ENABLED in changes or gfxsettings.UI_EFFECTS_ENABLED in changes:
    210                 trailsEnabled = effectsEnabled and gfxsettings.Get(gfxsettings.UI_TRAILS_ENABLED)
    211                 trinity.settings.SetValue('eveSpaceObjectTrailsEnabled', trailsEnabled)
    212 
    213     @telemetry.ZONE_METHOD
    214     def OnSessionChanged(self, isremote, session, change):
    215         if 'locationid' in change:
    216             newLocationID = change['locationid'][1]
    217             if idCheckers.IsSolarSystem(newLocationID) and self.primaryJob.sceneType != SCENE_TYPE_SPACE:
    218                 log.LogWarn('SceneManager: I detected a session change into space but no one has bothered to update my scene type!')
    219                 self.SetSceneType(SCENE_TYPE_SPACE)
    220         SpaceObjectExplosionManager.ClearWaiters()
    221 
    222     @telemetry.ZONE_METHOD
    223     def SetSceneType(self, sceneType):
    224         if self.primaryJob.sceneType == sceneType:
    225             return
    226         if sceneType != SCENE_TYPE_SPACE:
    227             self.DeactivateFISCamera()
    228         self.primaryJob = SceneContext(sceneType=sceneType)
    229         if sceneType == SCENE_TYPE_CHARACTER_CREATION:
    230             log.LogInfo('Setting up character creation scene rendering')
    231             self.primaryJob.renderJob = self.characterRenderJob
    232             self.fisRenderJob.SetActiveScene(None)
    233             self.fisRenderJob.Disable()
    234             self._DisableLoadingClear()
    235             self.characterRenderJob.Enable()
    236         elif sceneType == SCENE_TYPE_SPACE:
    237             log.LogInfo('Setting up space scene rendering')
    238             self.primaryJob.renderJob = self.fisRenderJob
    239             self.characterRenderJob.SetScene(None)
    240             self.characterRenderJob.Disable()
    241             for each in self.registeredJobs:
    242                 if hasattr(each.object, 'UseFXAA'):
    243                     each.object.UseFXAA(False)
    244 
    245             self._DisableLoadingClear()
    246             if not self.HasSecondaryScene():
    247                 self.fisRenderJob.Enable()
    248 
    249     @telemetry.ZONE_METHOD
    250     def Initialize(self, scene):
    251         self.primaryJob = SceneContext(scene=scene, renderJob=self.fisRenderJob)
    252 
    253     def CreateCharacterBackdropUIRoot(self):
    254         if self.characterBackdropUIRoot:
    255             return
    256         self.characterBackdropUIRoot = uicore.uilib.CreateRootObject(name='ccBackgroundUI', renderJob=None, state=uiconst.UI_DISABLED)
    257         self.characterRenderJob.Set2DBackdropUIRoot(self.characterBackdropUIRoot)
    258 
    259     def _ApplyCamera(self, jobContext, camera, **kwargs):
    260         if jobContext == self.primaryJob:
    261             currCam = self.GetActivePrimaryCamera()
    262         else:
    263             currCam = self.GetActiveSecondaryCamera()
    264         jobContext.camera = camera
    265         if jobContext.renderJob is not None:
    266             if isinstance(camera, CameraBase):
    267                 jobContext.renderJob.SetActiveCamera(camera.GetTrinityCamera())
    268             elif isinstance(camera, trinity.EveCamera):
    269                 jobContext.renderJob.SetActiveCamera(camera)
    270             else:
    271                 jobContext.renderJob.SetActiveCamera(None, camera.viewMatrix, camera.projectionMatrix)
    272         if hasattr(camera, 'cameraID'):
    273             sm.ScatterEvent('OnActiveCameraChanged', camera.cameraID)
    274             if camera.cameraID in INSPACE_CAMERAS:
    275                 self.UpdateSceneCameraReferences(camera)
    276         if hasattr(camera, 'OnActivated'):
    277             try:
    278                 camera.OnActivated(lastCamera=currCam, **kwargs)
    279             except Exception:
    280                 stdlog.exception('Camera %s failed to activate, resetting it', camera)
    281                 self._ResetCamera(camera)
    282 
    283         if currCam and hasattr(currCam, 'OnDeactivated') and currCam != camera:
    284             currCam.OnDeactivated()
    285         self.UpdateBracketProjectionCamera()
    286 
    287     def OnCameraLookAt(self, isEgo, itemID):
    288         scene = self.GetRegisteredScene('default')
    289         if scene is None:
    290             return
    291         for each in scene.cameraAttachments:
    292             try:
    293                 each.display = isEgo
    294             except AttributeError:
    295                 pass
    296 
    297     def UpdateSceneCameraReferences(self, camera):
    298         scene = self.GetRegisteredScene('default')
    299         if not scene:
    300             return
    301         for distanceField in scene.distanceFields:
    302             distanceField.cameraView = camera.viewMatrix
    303 
    304     def UpdateBracketProjectionCamera(self):
    305         camera = self.GetActiveCamera()
    306         if camera:
    307             uicore.uilib.SetSceneCamera(camera)
    308 
    309     def SetPrimaryCamera(self, cameraID, force = False, **kwargs):
    310         activeCam = self.GetActivePrimaryCamera()
    311         if activeCam and activeCam.cameraID == cameraID and not force:
    312             return activeCam
    313         camera = self.GetOrCreateCamera(cameraID)
    314         self._ApplyCamera(self.primaryJob, camera, **kwargs)
    315         return camera
    316 
    317     def SetSecondaryCamera(self, cameraID, **kwargs):
    318         activeCam = self.GetActiveSecondaryCamera()
    319         if activeCam and activeCam.cameraID == cameraID:
    320             return activeCam
    321         camera = self.GetOrCreateCamera(cameraID)
    322         self._ApplyCamera(self.secondaryJob, camera, **kwargs)
    323         return camera
    324 
    325     def HasSecondaryScene(self):
    326         return self.secondaryJob is not None
    327 
    328     @telemetry.ZONE_METHOD
    329     def SetSecondaryScene(self, scene, sceneKey, sceneType):
    330         if sceneType == SCENE_TYPE_SPACE:
    331             newJob = not self.HasSecondaryScene()
    332             if newJob:
    333                 from trinity.sceneRenderJobSpace import CreateSceneRenderJobSpace
    334                 self.secondaryJob = SceneContext(scene=scene, sceneKey=sceneKey, sceneType=sceneType)
    335                 self.secondaryJob.renderJob = CreateSceneRenderJobSpace('SpaceSceneSecondary')
    336                 self._CreateJobFiS(self.secondaryJob.renderJob)
    337             else:
    338                 self.secondaryJob.scene = scene
    339                 self.secondaryJob.sceneKey = sceneKey
    340             if sceneKey in self.overlayForcePostProcessing:
    341                 self.secondaryJob.renderJob.overrideSettings.postProcessingQuality = self.overlayForcePostProcessing[sceneKey]
    342                 self.secondaryJob.renderJob.overrideSettings.antiAliasingQuality = gfxsettings.AA_QUALITY_DISABLED
    343                 self.secondaryJob.renderJob.overrideSettings.enableUpscaling = False
    344             else:
    345                 self.secondaryJob.renderJob.overrideSettings.postProcessingQuality = None
    346                 self.secondaryJob.renderJob.overrideSettings.antiAliasingQuality = None
    347                 self.secondaryJob.renderJob.overrideSettings.enableUpscaling = None
    348             if newJob:
    349                 self.secondaryJob.renderJob.Enable()
    350             self.secondaryJob.renderJob.SetActiveScene(scene, sceneKey)
    351 
    352     def ClearSecondaryScene(self):
    353         if not self.HasSecondaryScene():
    354             return
    355         if self.secondaryJob.renderJob is not None:
    356             self.secondaryJob.renderJob.Disable()
    357         self.secondaryJob = None
    358 
    359     def SetActiveScene(self, scene, sceneKey = None):
    360         sceneType = SCENE_TYPE_CHARACTER_CREATION
    361         if getattr(scene, '__bluetype__', None) == 'trinity.EveSpaceScene':
    362             sceneType = SCENE_TYPE_SPACE
    363         if sceneKey in self.overlaySceneKeys:
    364             fadeObject = self.GetFadeObject(scene=self.primaryJob.scene)
    365             if fadeObject is not None:
    366                 fadeObject.intensity = 0.0
    367             self.primaryJob.renderJob.SuspendRendering()
    368             self.SetSecondaryScene(scene, sceneKey, sceneType)
    369         elif sceneType == SCENE_TYPE_SPACE:
    370             self.primaryJob.sceneKey = sceneKey
    371             self.primaryJob.scene = scene
    372             self.primaryJob.renderJob.SetActiveScene(scene, sceneKey)
    373         else:
    374             self.primaryJob.scene = scene
    375             self.primaryJob.renderJob.SetScene(scene)
    376         self.UpdateBracketProjectionCamera()
    377 
    378     def RefreshSecondarySceneToRenderJob(self):
    379         self.secondaryJob.renderJob.SetScene(self.secondaryJob.scene)
    380 
    381     def RegisterJob(self, job):
    382         wr = blue.BluePythonWeakRef(job)
    383 
    384         def ClearDereferenced():
    385             self.registeredJobs.remove(wr)
    386 
    387         wr.callback = ClearDereferenced
    388         self.registeredJobs.append(wr)
    389 
    390     def GetRegisteredCamera(self, key):
    391         if key in self.registeredCameras:
    392             return self.registeredCameras[key]
    393         self.LogNotice('No camera registered for:', key, self.registeredCameras)
    394 
    395     def GetActiveSpaceCamera(self):
    396         return self.GetActivePrimaryCamera()
    397 
    398     def GetActivePrimaryCamera(self):
    399         return self.primaryJob.camera
    400 
    401     def GetActiveCamera(self):
    402         if self.HasSecondaryScene():
    403             return self.GetActiveSecondaryCamera()
    404         return self.GetActivePrimaryCamera()
    405 
    406     def GetActiveSecondaryCamera(self):
    407         return self.secondaryJob.camera
    408 
    409     def UnregisterCamera(self, key):
    410         if key in self.registeredCameras:
    411             self.LogNotice('sceneManager::UnregisterCamera', key, self.registeredCameras[key])
    412             cam = self.registeredCameras[key]
    413             if cam == self.GetActiveCamera():
    414                 sm.ScatterEvent('OnActiveCameraChanged', None)
    415             if cam and hasattr(cam, 'OnDeactivated'):
    416                 cam.OnDeactivated()
    417             del self.registeredCameras[key]
    418 
    419     def RegisterCamera(self, camera):
    420         cameraID = camera.cameraID
    421         if cameraID in self.registeredCameras:
    422             return
    423         self.LogNotice('sceneManager::RegisterCamera', cameraID, camera)
    424         self.registeredCameras[camera.cameraID] = camera
    425         camera.centerOffset = self.GetCameraOffset()
    426 
    427     def GetCameraOffset(self):
    428         if self.cameraOffsetOverride:
    429             return self.cameraOffsetOverride * -0.01
    430         elif gfxsettings.IsInitialized(gfxsettings.SETTINGS_GROUP_UI):
    431             return gfxsettings.Get(gfxsettings.UI_CAMERA_OFFSET) * -0.01
    432         else:
    433             return 0.0
    434 
    435     def SetCameraOffsetOverride(self, cameraOffsetOverride):
    436         self.cameraOffsetOverride = cameraOffsetOverride
    437         self.UpdateCameraOffset()
    438 
    439     def UpdateCameraOffset(self):
    440         offset = self.GetCameraOffset()
    441         for cam in self.registeredCameras.itervalues():
    442             cam.centerOffset = offset
    443 
    444         sm.ScatterEvent('OnSetCameraOffset', offset)
    445 
    446     def UnregisterScene(self, key, ignoreCamera = False):
    447         if key in self.registeredScenes:
    448             del self.registeredScenes[key]
    449             if not ignoreCamera and key == 'default':
    450                 cam = self.GetActivePrimaryCamera()
    451                 if cam:
    452                     cam.OnDeactivated()
    453 
    454     def RegisterScene(self, scene, key):
    455         self.registeredScenes[key] = scene
    456         self._Update3DViewDisplayState()
    457 
    458     def GetRegisteredScene(self, key, defaultOnActiveScene = False, allowBlocking = True):
    459         if key in self.registeredScenes:
    460             return self.registeredScenes[key]
    461         if self.IsLoadingScene(key) and allowBlocking:
    462             self.sceneLoadedEvents[key].wait()
    463             return self.registeredScenes[key]
    464         if defaultOnActiveScene:
    465             return self.primaryJob.scene
    466 
    467     def IsLoadingScene(self, key):
    468         return key in self.sceneLoadedEvents and not self.sceneLoadedEvents[key].is_set()
    469 
    470     def SetRegisteredScenes(self, key):
    471         if key == 'default' and 'transition' in self.registeredScenes:
    472             key = 'transition'
    473         if key in ('default', 'transition') and self.HasSecondaryScene():
    474             if self.primaryJob.renderJob.enabled:
    475                 self.primaryJob.renderJob.Start()
    476             else:
    477                 self.primaryJob.renderJob.Enable()
    478             self.ClearSecondaryScene()
    479         scene = self.registeredScenes.get(key, None)
    480         self.SetActiveScene(scene, key)
    481 
    482     def GetActiveScene(self):
    483         if self.HasSecondaryScene():
    484             return self.secondaryJob.scene
    485         return self.primaryJob.scene
    486 
    487     def Get2DBackdropScene(self):
    488         return self.characterBackdropUIRoot.GetRenderObject()
    489 
    490     @telemetry.ZONE_METHOD
    491     def Show2DBackdropScene(self, updateRenderJob = False):
    492         self.showUIBackdropScene = True
    493         if updateRenderJob:
    494             self.characterRenderJob.Set2DBackdropUIRoot(self.characterBackdropUIRoot)
    495 
    496     @telemetry.ZONE_METHOD
    497     def Hide2DBackdropScene(self, updateRenderJob = False):
    498         self.showUIBackdropScene = False
    499         if updateRenderJob:
    500             self.characterRenderJob.Set2DBackdropUIRoot(None)
    501 
    502     def GetScene(self, location = None):
    503         if location is None:
    504             location = (session.solarsystemid2, session.constellationid, session.regionid)
    505         return self.GetResPathForLocation(location)
    506 
    507     def GetResPathForLocation(self, location):
    508         resPath = None
    509         if IsAbyssalSpaceSystem(location[0]):
    510             resPath = sm.GetService('abyss').get_nebula_res_path()
    511         if resPath is None:
    512             return cfg.GetNebula(*location)
    513         return resPath
    514 
    515     def GetSceneForSystem(self, solarSystemID):
    516         _, regionID, constellationID, _, _ = sm.GetService('map').GetParentLocationID(solarSystemID)
    517         return self.GetScene((solarSystemID, constellationID, regionID))
    518 
    519     def GetNebulaPathForSystem(self, solarSystemID):
    520         scene = trinity.Load(self.GetSceneForSystem(solarSystemID))
    521         return scene.envMapResPath
    522 
    523     def ReplaceNebulaFromResPath(self, nebulaGraphicsResPath):
    524         newScene = trinity.Load(nebulaGraphicsResPath)
    525         scene = self.GetRegisteredScene('default')
    526         scene.backgroundEffect = newScene.backgroundEffect
    527         scene.envMapResPath = newScene.envMapResPath
    528         scene.envMap1ResPath = newScene.envMap1ResPath
    529         scene.envMap2ResPath = newScene.envMap2ResPath
    530 
    531     def DeriveTextureFromSceneName(self, scenePath):
    532         scene = trinity.Load(scenePath)
    533         if scene is None:
    534             return {}
    535         d = {'envMap1ResPath': scene.envMap1ResPath,
    536          'lowQualityNebulaResPath': scene.lowQualityNebulaResPath,
    537          'lowQualityNebulaMixResPath': scene.lowQualityNebulaMixResPath}
    538         return d
    539 
    540     def CleanupSpaceResources(self):
    541         self._sharedResources = {}
    542 
    543     def RegisterPersistentUIObject(self, key, object):
    544         if key in self._persistedSpaceObjects:
    545             self.RemovePersistentUIObject(key)
    546         self._persistedSpaceObjects[key] = object
    547         scene = self.GetRegisteredScene('default', False)
    548         if scene is not None:
    549             scene.uiObjects.append(object)
    550 
    551     def GetPersistentUIObject(self, key):
    552         obj = None
    553         if key in self._persistedSpaceObjects:
    554             obj = self._persistedSpaceObjects[obj]
    555         return obj
    556 
    557     def RemovePersistentUIObject(self, key):
    558         obj = self._persistedSpaceObjects[key]
    559         scene = self.GetRegisteredScene('default', False)
    560         if scene is not None:
    561             scene.uiObjects.fremove(obj)
    562         del self._persistedSpaceObjects[key]
    563 
    564     def _GetSharedResource(self, path, key = None):
    565         comboKey = (path, key)
    566         if comboKey not in self._sharedResources:
    567             self._sharedResources[comboKey] = trinity.Load(path)
    568         return self._sharedResources[comboKey]
    569 
    570     def _PrepareBackgroundLandscapes(self, scene, solarSystemID, constellationID = None):
    571         starSeed = 0
    572         securityStatus = 1
    573         if constellationID is None:
    574             constellationID = sm.GetService('map').GetConstellationForSolarSystem(solarSystemID)
    575         if bool(solarSystemID) and bool(constellationID):
    576             starSeed = int(constellationID)
    577             securityStatus = sm.GetService('map').GetSecurityStatus(solarSystemID)
    578         scene.starfield = self._GetSharedResource('res:/dx9/scene/starfield/spritestars.red')
    579         if scene.starfield is not None:
    580             scene.starfield.seed = starSeed
    581             scene.starfield.minDist = 40
    582             scene.starfield.maxDist = 80
    583             if IsKnownSpaceSystem(solarSystemID):
    584                 scene.starfield.numStars = 500 + int(250 * securityStatus)
    585             else:
    586                 scene.starfield.numStars = 0
    587 
    588     def _SetupUniverseStars(self, scene, solarsystemID):
    589         if gfxsettings.Get(gfxsettings.UI_EFFECTS_ENABLED) and solarsystemID is not None:
    590             universe = self._GetSharedResource('res:/dx9/scene/starfield/universe.red')
    591             scene.backgroundObjects.append(universe)
    592             here = sm.GetService('map').GetItem(solarsystemID)
    593             if here:
    594                 scale = 10000000000.0
    595                 position = (here.x / scale, here.y / scale, -here.z / scale)
    596                 universe.children[0].translation = position
    597 
    598     def AddPersistentUIObjects(self, scene):
    599         for spaceObject in self._persistedSpaceObjects.values():
    600             if spaceObject not in scene.uiObjects:
    601                 scene.uiObjects.append(spaceObject)
    602 
    603     def ApplySolarsystemAttributes(self, scene, solarsystemID = None):
    604         if solarsystemID is None:
    605             solarsystemID = session.solarsystemid
    606         if not scene.cameraAttachments.FindByName('dustfield'):
    607             dustfield = self._GetSharedResource('res:/dx9/scene/dustfield.red')
    608             dustfield.name = 'dustfield'
    609             scene.cameraAttachments.append(dustfield)
    610         scene.sunDiffuseColor = (1.5, 1.5, 1.5, 1.0)
    611         if hasattr(cfg.mapSolarSystemContentCache[solarsystemID], 'systemWideCloud'):
    612             systemWideCloudGID = cfg.mapSolarSystemContentCache[solarsystemID].systemWideCloud
    613             if systemWideCloudGID > 0:
    614                 systemWideCloudGraphicPath = GetGraphicFile(systemWideCloudGID)
    615                 systemWideCloud = self._GetSharedResource(systemWideCloudGraphicPath)
    616                 if systemWideCloud is not None:
    617                     systemWideCloud.name = SYSTEM_WIDE_CLOUD_NAME
    618                     systemWideCloud.StartControllers()
    619                     scene.objects.append(systemWideCloud)
    620         self._SetupUniverseStars(scene, solarsystemID)
    621         self._PrepareBackgroundLandscapes(scene, solarsystemID)
    622 
    623     def ApplySceneInflightAttributes(self, scene, bp = None):
    624         if bp is None:
    625             bp = sm.GetService('michelle').GetBallpark()
    626         scene.ballpark = bp
    627 
    628     def SetVignette(self, vignette, vignetteSettings):
    629         index = 0
    630         if isinstance(vignette, trinity.Tr2PPVignetteEffect):
    631             index = 1
    632         for nametuple, value in vignetteSettings.iteritems():
    633             setattr(vignette, nametuple[index], value)
    634 
    635     def GetVignetteObject(self, vignetteSettings, scene = None, create = False):
    636         if scene is None:
    637             scene = self.GetActiveScene()
    638         if isinstance(scene, trinity.EveSpaceScene):
    639             if scene.postprocess is not None and scene.postprocess.vignette is not None:
    640                 return scene.postprocess.vignette
    641             if create:
    642                 if scene.postprocess is None:
    643                     scene.postprocess = trinity.Load(DEFAULT_POSTPROCESS_PATH)
    644                 if scene.postprocess.vignette is None:
    645                     scene.postprocess.vignette = trinity.Tr2PPVignetteEffect()
    646                 self.SetVignette(scene.postprocess.vignette, vignetteSettings)
    647                 return scene.postprocess.vignette
    648 
    649     def GetFadeObject(self, scene = None, create = False):
    650         if scene is None:
    651             scene = self.GetActiveScene()
    652         if isinstance(scene, trinity.EveSpaceScene):
    653             if scene.postprocess is not None and scene.postprocess.fade is not None:
    654                 return scene.postprocess.fade
    655             if create:
    656                 if scene.postprocess is None:
    657                     scene.postprocess = trinity.Load(DEFAULT_POSTPROCESS_PATH)
    658                 if scene.postprocess.fade is None:
    659                     scene.postprocess.fade = trinity.Tr2PPFadeEffect()
    660                 return scene.postprocess.fade
    661 
    662     def GetDesaturateObject(self, scene = None, create = False):
    663         if scene is None:
    664             scene = self.GetActiveScene()
    665         if scene is None:
    666             return
    667         if isinstance(scene, trinity.EveSpaceScene):
    668             if scene.postprocess is not None and scene.postprocess.desaturate is not None:
    669                 return scene.postprocess.desaturate
    670             if create:
    671                 if scene.postprocess is None:
    672                     scene.postprocess = trinity.Load(DEFAULT_POSTPROCESS_PATH)
    673                 if scene.postprocess.desaturate is None:
    674                     scene.postprocess.desaturate = trinity.Tr2PPDesaturateEffect()
    675                 return scene.postprocess.desaturate
    676 
    677     def ApplyScene(self, scene, registerKey = None):
    678         fadeObject = self.GetFadeObject(scene=scene, create=True)
    679         desaturateObject = self.GetDesaturateObject(scene=scene, create=True)
    680         if fadeObject:
    681             fadeObject.intensity = self.currentFadeIntensity
    682         if desaturateObject:
    683             desaturateObject.intensity = self.currentDesaturateLevel
    684         if registerKey is not None:
    685             self.RegisterScene(scene, registerKey)
    686         self.SetActiveScene(scene, registerKey)
    687         sm.ScatterEvent('OnLoadScene', scene, registerKey)
    688 
    689     def GetOrCreateCamera(self, cameraID):
    690         if cameraID in self.registeredCameras:
    691             return self.GetRegisteredCamera(cameraID)
    692         else:
    693             return self._CreateAndRegisterCamera(cameraID)
    694 
    695     def _CreateAndRegisterCamera(self, key, **kwargs):
    696         cameraCls = get_camera_class(key)
    697         camera = cameraCls(**kwargs)
    698         self.RegisterCamera(camera)
    699         return camera
    700 
    701     @telemetry.ZONE_METHOD
    702     def LoadScene(self, scenefile, registerKey = None, applyScene = True):
    703         scene = None
    704         try:
    705             if registerKey:
    706                 self.sceneLoadedEvents[registerKey] = locks.Event(registerKey)
    707             self.SetSceneType(SCENE_TYPE_SPACE)
    708             sceneFromFile = trinity.Load(scenefile)
    709             if sceneFromFile is None:
    710                 return
    711             scene = sceneFromFile
    712             if applyScene:
    713                 self.ApplyScene(scene, registerKey)
    714         except Exception:
    715             log.LogException('sceneManager::LoadScene')
    716             sys.exc_clear()
    717         finally:
    718             if registerKey and registerKey in self.sceneLoadedEvents:
    719                 self.sceneLoadedEvents.pop(registerKey).set()
    720 
    721         return (scene, None)
    722 
    723     def ApplySpaceScene(self):
    724         scene = self.primaryJob.scene
    725         if not scene:
    726             return
    727         self.ApplySolarsystemAttributes(scene)
    728         self.ApplySceneInflightAttributes(scene)
    729         self.AddPersistentUIObjects(scene)
    730 
    731     def SwitchToRestrictedCamera(self, minZoom = None, maxZoom = None, minPitch = BaseSpaceCamera.kMinPitch, maxPitch = BaseSpaceCamera.kMaxPitch, isRotationEnabled = True, initialZoomDistance = None):
    732         lastCamera = self.GetActivePrimaryCamera()
    733         if lastCamera and lastCamera.cameraID != CAM_SHIPORBIT_RESTRICTED:
    734             if lastCamera.cameraID in INSPACE_CAMERAS:
    735                 self.cameraBeforeRestriction = lastCamera.cameraID
    736         self.SetPrimaryCamera(CAM_SHIPORBIT_RESTRICTED, force=True)
    737         restrictedCam = self.GetActivePrimaryCamera()
    738         restrictedCam.Lock(minZoom, maxZoom, minPitch, maxPitch, isRotationEnabled)
    739         restrictedCam.LookAt(session.shipid)
    740         if initialZoomDistance is not None:
    741             restrictedCam.SetZoomDistance(initialZoomDistance)
    742 
    743     def SwitchFromRestrictedCamera(self):
    744         newCamera = get_orbit_camera_by_solar_system(session.solarsystemid)
    745         if self.cameraBeforeRestriction is not None and self.cameraBeforeRestriction in INSPACE_CAMERA_MODES:
    746             newCamera = self.cameraBeforeRestriction
    747         activeCamera = self.GetActivePrimaryCamera()
    748         activeCameraID = activeCamera.cameraID if activeCamera else None
    749         if activeCameraID == CAM_SHIPORBIT_RESTRICTED:
    750             activeCamera.Unlock()
    751             self.SetPrimaryCamera(newCamera)
    752         elif settings.char.ui.Get('spaceCameraID', None) == CAM_SHIPORBIT_RESTRICTED:
    753             settings.char.ui.Set('spaceCameraID', newCamera)
    754         self.cameraBeforeRestriction = None
    755 
    756     def GetVirtualCamera(self):
    757         return self.GetOrCreateCamera(CAM_VCS_CONSUMER)
    758 
    759     def SwitchToVirtualCamera(self):
    760         lastCamera = self.GetActivePrimaryCamera()
    761         if lastCamera and lastCamera.cameraID == CAM_VCS_CONSUMER:
    762             return
    763         self.cameraBeforeVirtual = lastCamera.cameraID
    764         self.SetPrimaryCamera(CAM_VCS_CONSUMER, force=True)
    765 
    766     def SwitchFromVirtualCamera(self):
    767         lastCamera = self.GetActivePrimaryCamera()
    768         if not lastCamera or lastCamera.cameraID != CAM_VCS_CONSUMER:
    769             self.cameraBeforeVirtual = None
    770             return
    771         if self.cameraBeforeVirtual is not None:
    772             camera = self.SetPrimaryCamera(self.cameraBeforeVirtual)
    773         else:
    774             orbitCamera = get_orbit_camera_by_solar_system(session.solarsystemid)
    775             camera = self.SetPrimaryCamera(orbitCamera)
    776         self.cameraBeforeVirtual = None
    777 
    778     def SnapLastCameraToVirtualCamera(self):
    779         if self.cameraBeforeVirtual:
    780             virtualCamera = self.GetVirtualCamera()
    781             camera = self.GetOrCreateCamera(self.cameraBeforeVirtual)
    782             camera.eyePosition = virtualCamera.eyePosition
    783             camera.atPosition = virtualCamera.atPosition
    784 
    785     def EnableRestrictedCameraRotation(self):
    786         activeCamera = self.GetActivePrimaryCamera()
    787         if activeCamera and activeCamera.cameraID == CAM_SHIPORBIT_RESTRICTED:
    788             activeCamera.EnableRotation()
    789 
    790     def FadeOut(self, duration, sleep = False):
    791         self.FadeTo(duration, fromValue=1.0, toValue=0.0, sleep=sleep)
    792 
    793     def FadeIn(self, duration, color = (0.0, 0.0, 0.0, 1.0), sleep = False):
    794         self.FadeTo(duration, color, fromValue=0.0, toValue=1.0, sleep=sleep)
    795 
    796     def FadeTo(self, duration, color = None, fromValue = 0.0, toValue = 1.0, sleep = False):
    797         fadeObject = self.GetFadeObject(create=True)
    798         self.currentFadeIntensity = toValue
    799         if fadeObject is not None:
    800             if color is not None:
    801                 fadeObject.color = color
    802             uicore.animations.MorphScalar(fadeObject, 'intensity', startVal=fromValue, endVal=toValue, duration=duration, sleep=sleep)
    803 
    804     def FadeVignetteToIntensityAndOpacity(self, duration, vignetteSettings, color = None, fromIntensity = 0.0, toIntensity = 1.0, fromOpacity = 0.0, toOpacity = 1.0, sleep = False):
    805         vignetteObject = self.GetVignetteObject(vignetteSettings, create=True)
    806         self.currentFadeIntensity = toIntensity
    807         if vignetteObject is not None:
    808             if color is not None:
    809                 vignetteObject.color = color
    810         uicore.animations.MorphScalar(vignetteObject, 'intensity', startVal=fromIntensity, endVal=toIntensity, duration=duration, sleep=sleep)
    811         uicore.animations.MorphScalar(vignetteObject, 'opacity', startVal=fromOpacity, endVal=toOpacity, duration=duration, sleep=sleep)
    812 
    813     def Saturate(self, duration, saturateLevel):
    814         uthread.new(self._Saturate, duration, saturateLevel)
    815 
    816     def _Saturate(self, duration, saturateLevel):
    817         effect = self.GetDesaturateObject(create=True)
    818         if effect is not None:
    819             level = effect.intensity
    820             self.currentDesaturateLevel = saturateLevel
    821             uicore.animations.MorphScalar(effect, 'intensity', startVal=level, endVal=saturateLevel, duration=duration)
    822 
    823     def ToggleEnable3DView(self):
    824         self.enable3DView = not self.enable3DView
    825         self._Update3DViewDisplayState()
    826 
    827     def _Update3DViewDisplayState(self):
    828         scenesToToggle = ['default', 'hangar', 'transition']
    829         for sceneName in scenesToToggle:
    830             if sceneName in self.registeredScenes:
    831                 self.registeredScenes[sceneName].display = self.enable3DView
    832 
    833         if hasattr(self, 'hidden3DViewWarningContainer') and self.hidden3DViewWarningContainer is not None:
    834             self.hidden3DViewWarningContainer.Close()
    835             self.hidden3DViewWarningContainer = None
    836         if not self.enable3DView:
    837             self.hidden3DViewWarningContainer = Toggled3DViewWarning(parent=uicore.desktop, name='exterior_view_hider')
    838             self.hidden3DViewWarningContainer.Show()
    839             uicore.animations.FadeOut(self.hidden3DViewWarningContainer, 4.0, timeOffset=20.0, callback=self.hidden3DViewWarningContainer.Hide)
    840 
    841     def OnViewStateChanged(self, from_view, to_view):
    842         self._Update3DViewDisplayState()
    843         if from_view != ViewState.CharacterCreation and to_view == ViewState.CharacterSelector:
    844             self.SetActiveScene(trinity.EveSpaceScene())
    845             self.ClearSecondaryScene()
    846 
    847     def SwitchFromRestrictedCameraOnReset(self):
    848         self.cameraBeforeVirtual = None
    849         self.cameraBeforeRestriction = None
    850         self.SwitchFromRestrictedCamera()
    851 
    852 
    853 class Toggled3DViewWarning(ContainerAutoSize):
    854     default_align = uiconst.CENTERTOP
    855     default_state = uiconst.UI_DISABLED
    856 
    857     def ApplyAttributes(self, attributes):
    858         super(Toggled3DViewWarning, self).ApplyAttributes(attributes)
    859         mainCont = ContainerAutoSize(parent=self, align=uiconst.CENTERTOP, alignMode=uiconst.TOTOP, top=230, width=400, bgColor=(0.1, 0.1, 0.1, 0.5))
    860         EveCaptionLarge(parent=mainCont, align=uiconst.TOTOP, text='<center>%s</center>' % GetByLabel('UI/Shared/ExteriorViewDisabled'), padding=(4, 4, 4, 4))
    861         command = uicore.cmd.commandMap.GetCommandByName('CmdToggle3DView')
    862         EveLabelLarge(parent=mainCont, align=uiconst.TOTOP, text='<center>%s</center>' % GetByLabel('UI/Shared/PressToRestoreView', shortcut=command.GetShortcutAsString()), padding=(4, 4, 4, 4))