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

shipSceneContainer.py (14549B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fitting\shipSceneContainer.py
      2 import math
      3 import eveui
      4 import geo2
      5 from eve.client.script.ui.control.scenecontainer import SceneContainer
      6 from eveSpaceObject import spaceobjanimation
      7 import evetypes
      8 from fsdBuiltData.common.graphicIDs import GetSofFactionName
      9 from iconrendering2.renderers.renderer_hologram import ApplyIsisEffect
     10 import log
     11 from eve.client.script.environment.model.turretSet import TurretSet, StructureMoonMiningTurretSet
     12 import trinity
     13 import uthread
     14 import blue
     15 from inventorycommon.util import IsModularShip
     16 from uthread2.callthrottlers import CallCombiner
     17 from evegraphics.controllers.clientControllerRegistry import ChangeControllerStateFromSlimItem
     18 from evegraphics.CosmeticsLoader import CosmeticsLoader
     19 from shipcosmetics.client.fittingsgateway.fittingsSignals import on_ship_cosmetics_changed
     20 import telemetry
     21 import logging
     22 from eve.client.script.environment.spaceObject.spaceObject import modify_dna
     23 from eve.client.script.environment.spaceObject.cosmeticsManager import CosmeticsManager
     24 from cosmetics.common.structures.const import StructurePaintSlot
     25 from cosmetics.common.structures.fitting import StructurePaintwork
     26 import paints.data.dataLoader as dl
     27 from inventorycommon.const import categoryStructure
     28 from eve.common.script.sys.idCheckers import IsStructure, IsShipType
     29 from cosmetics.common.ships.skins.static_data.slot_configuration import is_skinnable_ship
     30 from cosmetics.common.ships.skins.static_data.skin_type import ShipSkinType
     31 logger = logging.getLogger(__name__)
     32 
     33 class ShipSceneContainer(SceneContainer):
     34     __notifyevents__ = ['ProcessFittingWindowStartMinimize',
     35      'ProcessFittingWindowEndMinimize',
     36      'OnSessionChanged',
     37      'OnCorpLogoReady',
     38      'OnAllianceLogoReady']
     39 
     40     @telemetry.ZONE_METHOD
     41     def ApplyAttributes(self, attributes):
     42         SceneContainer.ApplyAttributes(self, attributes)
     43         self.controller = attributes.controller
     44         self.model = None
     45         if hasattr(self.controller, 'on_new_itemID'):
     46             self.controller.on_new_itemID.connect(self.ReloadShipWhenChangingShips)
     47         if hasattr(self.controller, 'on_subsystem_fitted'):
     48             self.controller.on_subsystem_fitted.connect(self.ReloadShipModelWithoutAnimation)
     49         if hasattr(self.controller, 'on_hardpoints_fitted'):
     50             self.controller.on_hardpoints_fitted.connect(self.UpdateHardpoints)
     51         if hasattr(self.controller, 'on_module_online_state'):
     52             self.controller.on_module_online_state.connect(self.ProcessOnlineStateChange)
     53         if hasattr(self.controller, 'on_skin_material_changed'):
     54             self.controller.on_skin_material_changed.connect(self.OnSkinChanged)
     55         if hasattr(self.controller, 'on_stance_activated'):
     56             self.controller.on_stance_activated.connect(self.OnStanceActive)
     57         on_ship_cosmetics_changed.connect(self.OnShipCosmeticsChanged)
     58         self.CreateActiveShipModelThrottled = CallCombiner(self.CreateActiveShipModel, 1.0)
     59         sm.RegisterNotify(self)
     60 
     61     def LoadShipModel(self):
     62         uthread.new(self.ReloadShipModel)
     63 
     64     def _SetModelOffsetWhenReady(self, model):
     65         if model is None:
     66             return
     67         maxDelay = 2.0
     68         currentDelay = 0.0
     69         checkDelay = 50.0
     70         while not max(model.generatedShapeEllipsoidRadius) != -1:
     71             if self.destroyed:
     72                 return
     73             if currentDelay > maxDelay:
     74                 return
     75             blue.synchro.SleepWallclock(checkDelay)
     76             currentDelay += checkDelay / 1000.0
     77 
     78         modelOffset = getattr(model, 'generatedShapeEllipsoidCenter', (0.0, 0.0, 0.0))
     79         locatorSets = getattr(model, 'locatorSets', None)
     80         if locatorSets:
     81             lookAtLocator = locatorSets.FindByName('camera_look_at')
     82             if lookAtLocator is not None and len(lookAtLocator.locators) > 0:
     83                 modelOffset = lookAtLocator.locators[0][0]
     84         if model.translationCurve is None:
     85             model.translationCurve = trinity.Tr2CurveConstant()
     86         invertedModelOffset = geo2.Vec3Scale(modelOffset, -1.0)
     87         model.translationCurve.value = invertedModelOffset
     88 
     89     def PrepareSpaceScene(self, maxPitch = None, scenePath = None, offscreen = False, resetZoom = True):
     90         super(ShipSceneContainer, self).PrepareSpaceScene(maxPitch=None, scenePath='res:/dx9/scene/fitting/fitting.red', resetZoom=True, offscreen=False)
     91         if IsStructure(evetypes.GetCategoryID(self.controller.typeID)):
     92             self.scene.sunDirection = (0.6198, -0.1016, -0.7781)
     93             self.scene.nebulaIntensity = 1.25
     94             self.scene.reflectionIntensity = 1.55
     95             self.scene.sunDiffuseColor = (1.0,
     96              205.0 / 255.0,
     97              170.0 / 255.0,
     98              1.0)
     99             self.scene.postprocess.taa = None
    100 
    101     @eveui.skip_if_destroyed
    102     def OnSkinChanged(self):
    103         if self.controller.itemID != session.shipid:
    104             return
    105         self.ReloadShipModel(animate=False)
    106 
    107     def _get_material_name(self, slot):
    108         if slot is not None:
    109             return dl.get_paint_material_name(slot)
    110 
    111     def OnShipCosmeticsChanged(self, _, cosmetics_types):
    112         if self.controller.itemID != session.shipid:
    113             return
    114         enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid)
    115         cosmeticsLoader = CosmeticsLoader((CosmeticsLoader.ALLIANCE, CosmeticsLoader.CORP))
    116         uthread.new(cosmeticsLoader.SetCosmeticsOnShip, self.model, enabledCosmetics)
    117 
    118     def OnCorpLogoReady(self, _corpID, _size):
    119         self._UpdateShipCosmetics()
    120 
    121     def OnAllianceLogoReady(self, _allianceID, _size):
    122         self._UpdateShipCosmetics()
    123 
    124     def OnSessionChanged(self, _isremote, _session, change):
    125         if 'corpid' in change or 'allianceid' in change:
    126             self._UpdateShipCosmetics()
    127 
    128     def _UpdateShipCosmetics(self):
    129         enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid)
    130         self.OnShipCosmeticsChanged(session.shipid, enabledCosmetics)
    131 
    132     @eveui.skip_if_destroyed
    133     def ReloadShipModelWithoutAnimation(self, *args, **kwargs):
    134         self.ReloadShipModel(animate=False)
    135 
    136     @eveui.skip_if_destroyed
    137     def ReloadShipWhenChangingShips(self, shipID, oldShipID, shipTypeID, oldShipTypeID):
    138         animate = True
    139         if self.controller.IsSimulated() and shipTypeID == oldShipTypeID:
    140             animate = False
    141         self.ReloadShipModel(animate=animate)
    142 
    143     def _SearchAndRemoveObservers(self):
    144         while len(self.model.observers) > 0:
    145             self.model.observers.pop()
    146 
    147         emitters = [ observer.name for observer in self.model.Find('trinity.TriObserverLocal') ]
    148         childContainers = self.model.effectChildren.Find('trinity.EveChildContainer')
    149         for container in childContainers:
    150             if hasattr(container, 'observers'):
    151                 while len(container.observers) > 0:
    152                     popped = container.observers.pop()
    153                     if popped.name in emitters:
    154                         emitters.remove(popped.name)
    155 
    156             if len(emitters) == 0:
    157                 break
    158 
    159     @telemetry.ZONE_METHOD
    160     def ReloadShipModel(self, throttle = False, animate = True):
    161         if self.destroyed:
    162             return
    163         with self._reloadLock:
    164             self.model = None
    165             if throttle:
    166                 self.model = self.CreateActiveShipModelThrottled()
    167             else:
    168                 self.model = self.CreateActiveShipModel()
    169             if not self.model:
    170                 try:
    171                     if IsModularShip(self.controller.typeID) and self.controller.IsSimulated():
    172                         del self.scene.objects[:]
    173                 except Exception:
    174                     pass
    175 
    176                 return
    177             if IsStructure(evetypes.GetCategoryID(self.controller.typeID)):
    178                 sof = sm.GetService('sofService').spaceObjectFactory
    179                 dna = self.model.dna
    180                 paintwork = sm.GetService('cosmeticsSvc').get_structure_cosmetic_state(session.structureid, session.solarsystemid, force_refresh=False)
    181                 if paintwork is not None:
    182                     mat1 = self._get_material_name(paintwork.get_slot(StructurePaintSlot.PRIMARY))
    183                     mat2 = self._get_material_name(paintwork.get_slot(StructurePaintSlot.SECONDARY))
    184                     mat3 = self._get_material_name(paintwork.get_slot(StructurePaintSlot.DETAILING))
    185                     dna = modify_dna(base_dna=dna, mat1=mat1, mat2=mat2, mat3=mat3, isStructure=True)
    186                 self.model = sof.BuildFromDNA(dna)
    187             self._SearchAndRemoveObservers()
    188             trinity.WaitForResourceLoads()
    189             self.model.FreezeHighDetailMesh()
    190             self.ModifyCameraToFitShip(animate, self.model)
    191             self.AddToScene(self.model)
    192             if self.controller.IsSimulated():
    193                 ApplyIsisEffect(self.model)
    194                 if self.controller.ControllerForCategory() != const.categoryStructure:
    195                     self._AddGridToScene(self.scene, self.model)
    196             if animate:
    197                 self.AnimEntry(yaw1=1.2 * math.pi, pitch0=0.3, pitch1=0.5)
    198             shipTypeID = self.controller.typeID
    199             stanceBtnControllerClass = self.controller.GetStanceBtnControllerClass()
    200             if stanceBtnControllerClass is None:
    201                 return
    202             stanceID = stanceBtnControllerClass().get_ship_stance(self.controller.itemID, shipTypeID)
    203             if not self.controller.IsSimulated():
    204                 slimItem = sm.GetService('michelle').GetItem(self.controller.itemID)
    205                 if slimItem is not None:
    206                     ChangeControllerStateFromSlimItem(shipTypeID, self.model, slimItem)
    207                     cosmeticsLoader = CosmeticsLoader((CosmeticsLoader.ALLIANCE, CosmeticsLoader.CORP))
    208                     cosmeticsLoader.Load(self.model, slimItem)
    209             spaceobjanimation.SetShipAnimationStance(self.model, stanceID)
    210             spaceobjanimation.TriggerDefaultStates(self.model)
    211             enabledCosmetics = sm.GetService('cosmeticsSvc').get_enabled_ship_cosmetics(session.shipid)
    212             cosmeticsLoader = CosmeticsLoader((CosmeticsLoader.ALLIANCE, CosmeticsLoader.CORP))
    213             uthread.new(cosmeticsLoader.SetCosmeticsOnShip, self.model, enabledCosmetics)
    214             if self.controller.IsSimulated():
    215                 for eachEffect in getattr(self.model, 'effectChildren', []):
    216                     eachEffect.display = False
    217 
    218             else:
    219                 self.UpdateHardpoints(self.model)
    220 
    221     def _AddGridToScene(self, scene, shipModel):
    222         rad = shipModel.GetBoundingSphereRadius()
    223         scaling = (4, 4, 4)
    224         translation = (0, -rad / 2, 0)
    225         grid = trinity.Load('res:/dx9/model/UI/ScanGrid.red')
    226         grid.scaling = scaling
    227         grid.translation = translation
    228         scene.objects.append(grid)
    229         grid2 = trinity.Load('res:/dx9/model/UI/ScanGrid.red')
    230         grid2.rotation = (0, 0, 1, 0)
    231         grid2.scaling = scaling
    232         grid2.translation = translation
    233         scene.objects.append(grid2)
    234 
    235     def ModifyCameraToFitShip(self, animate, shipModel):
    236         camera = self.camera
    237         if shipModel is not None and hasattr(shipModel, 'GetBoundingSphereCenter'):
    238             rad = shipModel.GetBoundingSphereRadius() + geo2.Vec3Length(shipModel.GetBoundingSphereCenter())
    239         else:
    240             rad = 1000.0
    241         minZoom = rad + camera.nearClip
    242         alpha = camera.fov / 2.0
    243         maxZoom = min(self.backClip - rad, rad * (1 / math.tan(alpha)) * 2)
    244         oldZoomDistance = self.minZoom + (self.maxZoom - self.minZoom) * self.zoom
    245         defaultZoom = minZoom / (maxZoom - minZoom)
    246         self.SetMinMaxZoom(minZoom, maxZoom)
    247         if animate or oldZoomDistance < minZoom or oldZoomDistance > maxZoom:
    248             self.SetZoom(defaultZoom)
    249 
    250     @telemetry.ZONE_METHOD
    251     def CreateActiveShipModel(self):
    252         newModel = self.controller.model
    253         if not newModel:
    254             return
    255         if hasattr(newModel, 'ChainAnimationEx'):
    256             newModel.ChainAnimationEx('NormalLoop', 0, 0, 1.0)
    257         newModel.display = 1
    258         newModel.name = str(self.controller.itemID)
    259         translation = trinity.Tr2CurveConstant()
    260         newModel.translationCurve = translation
    261         translation.value = geo2.Vec3Scale(newModel.GetBoundingSphereCenter(), -1)
    262         uthread.new(self._SetModelOffsetWhenReady, newModel)
    263         return newModel
    264 
    265     @telemetry.ZONE_METHOD
    266     @eveui.skip_if_destroyed
    267     def UpdateHardpoints(self, newModel = None):
    268         if newModel is None:
    269             newModel = self.GetSceneShip()
    270         if newModel is None:
    271             log.LogError('UpdateHardpoints - No model!')
    272             return
    273         factionName = GetSofFactionName(evetypes.GetGraphicID(self.controller.typeID))
    274         fittetTurretSets = TurretSet.FitTurrets(self.controller.itemID, newModel, factionName)
    275         for ts in fittetTurretSets.values():
    276             if isinstance(ts, StructureMoonMiningTurretSet):
    277                 ts.Display()
    278 
    279     @telemetry.ZONE_METHOD
    280     def GetSceneShip(self):
    281         for model in self.scene.objects:
    282             if getattr(model, 'name', None) == str(self.controller.itemID):
    283                 return model
    284 
    285     @telemetry.ZONE_METHOD
    286     def PlayDeploymentAnimation(self, slot, dogmaItem):
    287         sceneShip = self.GetSceneShip()
    288         if sceneShip is not None:
    289             for turret in getattr(sceneShip, 'turretSets', []):
    290                 if turret.slotNumber != slot:
    291                     continue
    292                 if dogmaItem.IsOnline():
    293                     turret.EnterStateIdle()
    294                 else:
    295                     turret.EnterStateDeactive()
    296                     break
    297 
    298     @eveui.skip_if_destroyed
    299     def OnStanceActive(self, stanceID):
    300         spaceobjanimation.SetShipAnimationStance(self.GetSceneShip(), stanceID)
    301 
    302     def _OnClose(self, *args):
    303         sm.UnregisterNotify(self)
    304         SceneContainer._OnClose(self)
    305 
    306     @eveui.skip_if_destroyed
    307     def ProcessOnlineStateChange(self, dogmaItem):
    308         if self.destroyed:
    309             return
    310         slot = dogmaItem.flagID - const.flagHiSlot0 + 1
    311         if slot is not None:
    312             self.PlayDeploymentAnimation(slot, dogmaItem)
    313 
    314     def ProcessFittingWindowStartMinimize(self):
    315         self.Hide()
    316 
    317     def ProcessFittingWindowEndMinimize(self):
    318         self.Show()