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

shipOrbitCamera.py (19873B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\camera\shipOrbitCamera.py
      2 import math
      3 import destiny
      4 import gametime
      5 import uthread2
      6 from eve.client.script.environment.spaceObject.spaceObject import SpaceObject
      7 from eve.client.script.parklife import states
      8 from eve.client.script.ui.camera.cameraUtil import GetDurationByDistance, GetBallPosition, GetBall, GetBallMaxZoom, Vector3Chaser, VectorLerper, IsAutoTrackingEnabled, CheckShowModelTurrets, GetSpeedDirection, GetInitialLookAtDistance, IsDynamicCameraMovementEnabled, IsNanVector3, IsValidSpaceCameraPosition
      9 from eve.client.script.ui.camera.baseSpaceCamera import BaseSpaceCamera
     10 import evecamera
     11 import blue
     12 import geo2
     13 import evetypes
     14 import uthread
     15 import evegraphics.settings as gfxsettings
     16 import inventorycommon.const as invconst
     17 from eve.client.script.ui.camera.util.cameraSpeedOffsetter import CameraSpeedOffsetter
     18 from evegraphics.explosions.spaceObjectExplosionManager import SpaceObjectExplosionManager
     19 from carbonui.uicore import uicore
     20 from destructionEffect import destructionType as destructionEffectType
     21 TRACK_RESET_SPEED = 60.0
     22 TRACK_DEFAULT_SPEED = 30.0
     23 
     24 class ShipOrbitCamera(BaseSpaceCamera):
     25     __notifyevents__ = BaseSpaceCamera.__notifyevents__[:] + ['OnBallparkSetState',
     26      'OnStateChange',
     27      'OnDungeonCameraInterest',
     28      'OnBallAdded']
     29     cameraID = evecamera.CAM_SHIPORBIT
     30     isBobbingCamera = True
     31     minFov = 0.8
     32     maxFov = 1.2
     33     minZoom = 800000
     34     name = 'ShipOrbitCamera'
     35 
     36     def __init__(self):
     37         BaseSpaceCamera.__init__(self)
     38         self.lookAtBall = None
     39         self.trackBall = None
     40         self.trackPendingItemIDSpeedDuration = None
     41         self.orbitFreezeProp = 0.0
     42         self._zoomPropCache = None
     43         self._eyeOffsetChaser = Vector3Chaser()
     44         self._trackOffsetChaser = Vector3Chaser()
     45         self.trackLerper = VectorLerper(duration=1.5)
     46         self.speedOffsetter = CameraSpeedOffsetter()
     47         self.isManualFovEnabled = False
     48         self._trackSpeedMultiplier = 1.0
     49         self._trackSpeed = TRACK_DEFAULT_SPEED
     50         self._handleTargetKilledThread = None
     51         self.speedDir = None
     52 
     53     def OnActivated(self, itemID = None, lastCamera = None, **kwargs):
     54         BaseSpaceCamera.OnActivated(self, **kwargs)
     55         self.speedOffsetter.OnActivated()
     56         self.RegisterActivated()
     57         if lastCamera and lastCamera.cameraID in (evecamera.CAM_TACTICAL,
     58          evecamera.CAM_SHIPPOV,
     59          evecamera.CAM_JUMP,
     60          evecamera.CAM_UNDOCK,
     61          evecamera.CAM_ENTERSPACE,
     62          evecamera.CAM_EXPLOSION):
     63             itemID = itemID or getattr(lastCamera, 'lastLookAtID', None) or self.ego
     64             self._SetLookAtBall(itemID)
     65             atPos1 = self.GetTrackPosition(self.lookAtBall)
     66             direction = lastCamera.GetLookAtDirection()
     67             if IsNanVector3(direction):
     68                 direction = geo2.Vec3Direction(self.default_eyePosition, self.default_atPosition)
     69             eyePos1 = geo2.Vec3Add(atPos1, geo2.Vec3Scale(direction, self.GetInitialZoomDist(lastCamera)))
     70             canTransitFromLastCamera = IsValidSpaceCameraPosition(lastCamera.atPosition) and IsValidSpaceCameraPosition(lastCamera.eyePosition)
     71             if canTransitFromLastCamera and lastCamera.cameraID in (evecamera.CAM_TACTICAL,
     72              evecamera.CAM_JUMP,
     73              evecamera.CAM_UNDOCK,
     74              evecamera.CAM_ENTERSPACE,
     75              evecamera.CAM_EXPLOSION):
     76                 if hasattr(lastCamera, 'transitionDelay'):
     77                     duration = lastCamera.transitionDelay
     78                 else:
     79                     duration = GetDurationByDistance(lastCamera.eyePosition, eyePos1, 0.4, 0.6)
     80                 self.Transit(lastCamera.atPosition, lastCamera.eyePosition, atPos1, eyePos1, duration=duration, smoothing=0.0)
     81                 currFov = self.fov
     82                 self.fov = lastCamera.fov
     83                 if not IsDynamicCameraMovementEnabled():
     84                     self.SetFovTarget(currFov)
     85             else:
     86                 self.SetAtPosition(atPos1)
     87                 self.SetEyePosition(eyePos1)
     88         elif itemID:
     89             self._SetLookAtBall(itemID)
     90         elif not self.lookAtBall:
     91             self._SetLookAtBall(self.ego)
     92 
     93     def RegisterActivated(self):
     94         settings.char.ui.Set('spaceCameraID', evecamera.CAM_SHIPORBIT)
     95 
     96     def GetInitialZoomDist(self, lastCamera):
     97         if lastCamera.cameraID == evecamera.CAM_ENTERSPACE:
     98             dist = lastCamera.GetZoomDistance()
     99         elif self._zoomPropCache is not None:
    100             dist = self.GetZoomDistanceByZoomProportion(self._zoomPropCache)
    101         else:
    102             dist = self.GetLookAtDistance()
    103         return dist
    104 
    105     def StopHandleTargetKilledThread(self):
    106         if self._handleTargetKilledThread:
    107             self._handleTargetKilledThread.kill()
    108         self._handleTargetKilledThread = None
    109 
    110     def GetLookAtItemID(self):
    111         return self.GetItemID()
    112 
    113     def LookAt(self, itemID, forceUpdate = False, objRadius = None):
    114         lookAtBall = self._TrySetLookAtBall(itemID, forceUpdate, objRadius)
    115         if lookAtBall:
    116             radius = self.GetLookAtDistance(objRadius)
    117             self._LookAtAnimate(itemID, radius)
    118         self.StopHandleTargetKilledThread()
    119 
    120     def _TrySetLookAtBall(self, itemID, forceUpdate = False, objRadius = None):
    121         if not self.IsLookAtAllowed(itemID):
    122             return
    123         self.Track(None, speed=TRACK_RESET_SPEED)
    124         self.DisableManualFov()
    125         isAlreadyLookingAt = self.lookAtBall and self.lookAtBall.id == itemID
    126         if not forceUpdate and isAlreadyLookingAt and not objRadius:
    127             if itemID != self.ego:
    128                 self._SetLookAtBall(self.ego)
    129                 return self.lookAtBall
    130             else:
    131                 return
    132         self._ScatterLookAtEvent(itemID)
    133         if self.CheckObjectTooFar(itemID):
    134             self.Track(itemID)
    135             return
    136         self._SetLookAtBall(itemID)
    137         return self.lookAtBall
    138 
    139     def _ScatterLookAtEvent(self, itemID):
    140         sm.ScatterEvent('OnCameraLookAt', itemID == self.ego, itemID)
    141 
    142     def IsLookAtAllowed(self, itemID):
    143         if not self.IsManualControlEnabled():
    144             return False
    145         if self.IsBallWarping(itemID) and itemID != self.ego:
    146             return False
    147         return True
    148 
    149     def LookAtMaintainDistance(self, itemID):
    150         lookAtBall = self._TrySetLookAtBall(itemID)
    151         if lookAtBall:
    152             radius = self.GetZoomDistance()
    153             self._LookAtAnimate(itemID, radius)
    154 
    155     def IsBallWarping(self, itemID):
    156         trackBall = GetBall(itemID)
    157         return trackBall is None or trackBall.mode == destiny.DSTBALL_WARP
    158 
    159     def DisableManualFov(self):
    160         self.isManualFovEnabled = False
    161 
    162     def _SetLookAtBall(self, itemID):
    163         self.lookAtBall = GetBall(itemID)
    164         if self.lookAtBall:
    165             sm.StartService('stateSvc').SetState(self.lookAtBall.id, states.lookingAt, True)
    166             CheckShowModelTurrets(self.lookAtBall)
    167         self.Track(None, speed=TRACK_RESET_SPEED)
    168         if not self.lookAtBall:
    169             self.ResetAnchorPos()
    170             return
    171         self.UpdateMaxZoom()
    172         self.ConstructAnchorBall()
    173         if isinstance(self.lookAtBall, SpaceObject):
    174             self.lookAtBall.RegisterForModelLoad(self.OnLookAtItemModelLoaded)
    175 
    176     def UpdateMaxZoom(self):
    177         ball = self.lookAtBall
    178         nearClip = self.nearClip
    179         if ball is not None and nearClip is not None:
    180             self.SetMaxZoom(GetBallMaxZoom(ball, nearClip))
    181 
    182     def _LookAtAnimate(self, itemID, radius):
    183         atPos1 = GetBallPosition(self.lookAtBall)
    184         eyePos1 = self._GetNewLookAtEyePos(atPos1, itemID, radius)
    185         duration = GetDurationByDistance(self.eyePosition, eyePos1, 0.5, 1.5)
    186         self.speedOffsetter.Reset()
    187         self.TransitTo(atPos1, eyePos1, duration=duration, smoothing=0.0)
    188 
    189     def _GetNewLookAtEyePos(self, atPos1, itemID, radius):
    190         typeID = self.lookAtBall.typeID
    191         if typeID and evetypes.GetGroupID(typeID) == invconst.groupBillboard:
    192             direction = self._GetBillboardLookAtDirection()
    193             radius = self.lookAtBall.radius * 5
    194         else:
    195             direction = self.GetLookAtDirection()
    196         eyePos1 = geo2.Vec3Add(atPos1, geo2.Vec3Scale(direction, radius))
    197         return eyePos1
    198 
    199     def _GetBillboardLookAtDirection(self):
    200         direction = GetSpeedDirection(self.lookAtBall)
    201         if geo2.Vec3Dot(self.GetLookAtDirection(), direction) < 0:
    202             direction = geo2.Vec3Scale(direction, -1)
    203         return direction
    204 
    205     def GetLookAtDistance(self, objRadius = None):
    206         return GetInitialLookAtDistance(self.maxZoom, self.minZoom, objRadius)
    207 
    208     def _UpdateAtOffset(self):
    209         if not self.lookAtBall:
    210             self._trackOffsetChaser.ResetValue()
    211             return
    212         atOffset = None
    213         self.speedDir = GetSpeedDirection(self.lookAtBall)
    214         self._UpdateTrackOffset()
    215         trackOffset = self._trackOffsetChaser.GetValue()
    216         self.speedOffsetter._Update(self.lookAtBall, self.maxZoom, self.IsTracking())
    217         speedOffset = self.speedOffsetter.GetSpeedOffset()
    218         self._AddToAtOffset(geo2.Vec3Add(trackOffset, speedOffset))
    219 
    220     def _UpdateTrackOffset(self):
    221         if self.IsTracking() and IsDynamicCameraMovementEnabled():
    222             trackOffset = self._GetTrackAtOffset()
    223             self._trackOffsetChaser.SetTargetValue(trackOffset, self._trackSpeed * self._trackSpeedMultiplier)
    224         else:
    225             self._trackOffsetChaser.ResetValue(TRACK_RESET_SPEED * self._trackSpeedMultiplier)
    226 
    227     def _GetTrackAtOffset(self):
    228         trackOffset = geo2.Vec3Subtract(self.GetTrackPosition(self.trackBall), self._atPosition)
    229         length = geo2.Vec3Length(trackOffset)
    230         maxLen = 250000
    231         if length > maxLen:
    232             trackOffset = geo2.Vec3Scale(trackOffset, maxLen / length)
    233         return trackOffset
    234 
    235     def _GetTrackEyeOffset(self):
    236         offsetProp = 1.0 - self.GetZoomProportion() ** self.kZoomPower
    237         offsetDir = self._GetTrackEyeOffsetDirection()
    238         offsetAmount = offsetProp * self.maxZoom
    239         offset = geo2.Vec3Scale(offsetDir, offsetAmount)
    240         return offset
    241 
    242     def _GetTrackEyeOffsetDirection(self):
    243         pitch = math.pi - self.GetPitch()
    244         rotMat = geo2.MatrixRotationAxis(self.GetZAxis(), -pitch)
    245         return geo2.Vec3Transform(self.GetYAxis(), rotMat)
    246 
    247     def _UpdateEyeOffset(self):
    248         if self.IsChasing():
    249             offset = (0, 0.5 * self.maxZoom, 0)
    250             eyeOffset = self.GetChaseEyeOffset()
    251             offset = geo2.Vec3Subtract(offset, eyeOffset)
    252             self._eyeOffsetChaser.SetTargetValue(offset, 1.0)
    253         elif self.IsTracking() and IsDynamicCameraMovementEnabled():
    254             offset = self._GetTrackEyeOffset()
    255             self._eyeOffsetChaser.SetTargetValue(offset, self._trackSpeed * self._trackSpeedMultiplier)
    256         else:
    257             self._eyeOffsetChaser.ResetValue(self._trackSpeed * self._trackSpeedMultiplier)
    258         self._AddToEyeOffset(self._eyeOffsetChaser.GetValue())
    259 
    260     def Update(self):
    261         self._UpdateAnchorPosition()
    262         BaseSpaceCamera.Update(self)
    263         if not self.lookAtBall or not self.ego:
    264             return
    265         zoomProp = self.GetZoomProportion()
    266         self._UpdateAtOffset()
    267         self._UpdateEyeOffset()
    268         newAtPos = self.GetTrackPosition(self.lookAtBall)
    269         atDiff = geo2.Vec3Subtract(newAtPos, self._atPosition)
    270         self.SetAtPosition(newAtPos)
    271         if self.IsChasing():
    272             self.TrySetEyePosition(self.trackLerper.GetValue(self._eyePosition, self.GetChaseEyePosition()))
    273         elif self.IsTracking():
    274             self.TrySetEyePosition(self.trackLerper.GetValue(self._eyePosition, self.GetTrackingEyePosition()))
    275         else:
    276             prop = self._GetEyePosDriftProporition()
    277             eyeOffset = geo2.Vec3Scale(atDiff, prop)
    278             self.TrySetEyePosition(geo2.Vec3Add(self._eyePosition, eyeOffset))
    279         if not self.IsInTransit():
    280             if self.GetItemID() == self.ego or self.IsTracking() or self.IsChasing():
    281                 self.SetZoom(zoomProp)
    282             self.EnforceMinZoom()
    283         if not self.isManualFovEnabled and IsDynamicCameraMovementEnabled():
    284             self.SetFovTarget(self.GetDynamicFov())
    285 
    286     def _UpdateAnchorPosition(self):
    287         if self.lookAtBall and self.lookAtBall.mode == destiny.DSTBALL_WARP:
    288             self.ResetAnchorPos()
    289         elif not self._anchorBall or geo2.Vec3Length(GetBallPosition(self._anchorBall)) > evecamera.LOOKATRANGE_MAX_NEW:
    290             self.ConstructAnchorBall()
    291 
    292     def GetTrackingEyePosition(self):
    293         trackPos = self.GetTrackPosition(self.trackBall)
    294         direction = geo2.Vec3Subtract(self._atPosition, trackPos)
    295         if geo2.Vec3Length(direction) == 0.0:
    296             direction = self.GetLookAtDirection()
    297         direction = geo2.Vec3Normalize(direction)
    298         offset = geo2.Vec3Scale(direction, self.GetZoomDistance())
    299         return geo2.Vec3Add(self._atPosition, offset)
    300 
    301     def GetChaseEyePosition(self):
    302         offset = geo2.Vec3Scale(self.speedDir, -self.GetZoomDistance())
    303         return geo2.Vec3Add(self._atPosition, offset)
    304 
    305     def IsTracking(self):
    306         return self.trackBall is not None and self.trackBall != self.lookAtBall
    307 
    308     def GetChaseEyeOffset(self):
    309         offsetAmount = geo2.Vec3Length(self.speedOffsetter.GetSpeedOffset())
    310         eyeOffset = geo2.Vec3Scale(self.speedDir, offsetAmount)
    311         return eyeOffset
    312 
    313     def Track(self, itemID = None, speed = None, duration = 1.5, **kwargs):
    314         if not speed:
    315             speed = TRACK_DEFAULT_SPEED if itemID else TRACK_RESET_SPEED
    316         self.trackPendingItemIDSpeedDuration = None
    317         if self.trackBall and self.trackBall.id == itemID:
    318             return
    319         if not self.trackBall and itemID is None:
    320             return
    321         self.StopUpdateThreads()
    322         if itemID and self.trackBall is None:
    323             self._TrackZoomOutIfTooClose()
    324         self.trackBall = GetBall(itemID)
    325         self._trackSpeed = speed
    326         self._RampUpTrackSpeed(duration)
    327         self.trackLerper.Reset(duration)
    328         self.StopHandleTargetKilledThread()
    329         sm.ScatterEvent('OnCameraTrack', itemID)
    330 
    331     def _TrackZoomOutIfTooClose(self):
    332         if self.GetZoomProportion() < 0.45:
    333             self.SetZoomTarget(0.45)
    334 
    335     def _RampUpTrackSpeed(self, duration = 1.5):
    336         self._trackSpeedMultiplier = 0.0
    337         uicore.animations.MorphScalar(self, '_trackSpeedMultiplier', 0.0, 1.0, duration=duration)
    338 
    339     def _GetEyePosDriftProporition(self):
    340         if not IsDynamicCameraMovementEnabled():
    341             return 1.0
    342         elif self.GetItemID() == self.ego:
    343             return 0.999
    344         else:
    345             zoomProp = self.GetZoomProportion()
    346             prop = 0.7 * (1.0 - zoomProp)
    347             prop = max(0.5, prop)
    348             if prop < 1.0:
    349                 prop += self.orbitFreezeProp * (1.0 - prop)
    350             prop = min(prop, 1.0)
    351             return prop
    352 
    353     def IsChasing(self):
    354         return self.lookAtBall == self.trackBall and self.speedDir and geo2.Vec3Length(self.speedDir) > 0.0
    355 
    356     def GetTrackItemID(self):
    357         if self.IsTracking():
    358             return self.trackBall.id
    359 
    360     def ResetCamera(self, *args):
    361         self.LookAt(self.ego, forceUpdate=True)
    362 
    363     def ResetCameraPosition(self):
    364         BaseSpaceCamera.ResetCameraPosition(self)
    365         self._SetLookAtBall(self.ego)
    366 
    367     def Orbit(self, dx = 0, dy = 0):
    368         if self.IsTransitioningToOrFromTracking() and IsDynamicCameraMovementEnabled():
    369             return
    370         BaseSpaceCamera.Orbit(self, dx, dy)
    371         if self.IsTracking() or self.IsChasing():
    372             self.Track(None, speed=TRACK_RESET_SPEED)
    373 
    374     def IsTransitioningToOrFromTracking(self):
    375         return self._trackSpeedMultiplier < 0.4
    376 
    377     def OnDeactivated(self):
    378         BaseSpaceCamera.OnDeactivated(self)
    379         self._zoomPropCache = self.GetZoomProportion()
    380         self.lookAtBall = None
    381         self._trackOffsetChaser.ResetValue()
    382         self.speedOffsetter.Reset()
    383         self.ResetAnchorPos()
    384         self.DisableManualFov()
    385         self._trackSpeed = 1.0
    386         self._trackSpeedMultiplier = 1.0
    387         self.ResetRotate()
    388         self.StopHandleTargetKilledThread()
    389 
    390     def GetItemID(self):
    391         if self.lookAtBall:
    392             return self.lookAtBall.id
    393 
    394     def ClearCameraParent(self):
    395         self._SetLookAtBall(self.ego)
    396 
    397     def OnBallRemoved(self, ball):
    398         if ball == self.lookAtBall:
    399             if not self.isActive or ball.id == self.ego:
    400                 self._SetLookAtBall(None)
    401             elif ball.id != self.ego and destructionEffectType.isExplosionOrOverride(ball.destructionEffectId):
    402                 if gfxsettings.Get(gfxsettings.UI_EXPLOSION_EFFECTS_ENABLED) and IsDynamicCameraMovementEnabled():
    403                     sm.GetService('sceneManager').SetPrimaryCamera(evecamera.CAM_EXPLOSION, itemID=ball.id)
    404                 else:
    405                     self.LookAt(self.ego)
    406             else:
    407                 self.LookAt(self.ego)
    408         if ball == self.trackBall:
    409             SpaceObjectExplosionManager.GetExplosionTimesWhenAvailable(ball.id, lambda t1, t2: self.StartHandleTargetKilledThread(ball.id, t1, t2))
    410 
    411     def StartHandleTargetKilledThread(self, ballID, globalExplosionStart, wreckSwitchTime):
    412         self._handleTargetKilledThread = uthread.new(self._HandleTargetKilled, ballID, globalExplosionStart, wreckSwitchTime)
    413 
    414     def _HandleTargetKilled(self, ballID, globalExplosionStart, wreckSwitchTime):
    415         blue.synchro.SleepUntilSim(wreckSwitchTime + 5 * gametime.SEC)
    416         self.Track(None, speed=TRACK_RESET_SPEED)
    417 
    418     def OnBallparkSetState(self):
    419         if self.isActive:
    420             self._SetLookAtBall(self.ego)
    421         else:
    422             self._SetLookAtBall(None)
    423 
    424     def OnCurrentShipWarping(self):
    425         if self.GetLookAtItemID() is not None and self.GetLookAtItemID() != self.ego:
    426             self.LookAt(self.ego)
    427 
    428     def OnMouseDown(self, button):
    429         if self.IsTracking() or self.IsChasing():
    430             return
    431         if button == 0:
    432             uicore.animations.MorphScalar(self, 'orbitFreezeProp', self.orbitFreezeProp, 1.0, duration=0.5, timeOffset=0.0)
    433 
    434     def OnMouseUp(self, button):
    435         if button == 0:
    436             uicore.animations.MorphScalar(self, 'orbitFreezeProp', self.orbitFreezeProp, 0.0, duration=2.0, timeOffset=0.0)
    437 
    438     def FovZoom(self, dz):
    439         self.minFov = 0.3
    440         self.maxFov = 1.3
    441         BaseSpaceCamera.FovZoom(self, dz)
    442         self.isManualFovEnabled = True
    443 
    444     def OnStateChange(self, itemID, flag, flagState, *args):
    445         if flagState and flag == states.selected and IsAutoTrackingEnabled():
    446             if not uicore.cmd.IsSomeCombatCommandLoaded():
    447                 self.Track(itemID)
    448 
    449     def OnDungeonCameraInterest(self, itemID, speed, duration):
    450         if not (self.isActive and IsDynamicCameraMovementEnabled()):
    451             return
    452         ball = GetBall(itemID)
    453         if ball:
    454             self.Track(itemID, speed, duration)
    455         else:
    456             self.trackPendingItemIDSpeedDuration = (itemID, speed, duration)
    457 
    458     def OnBallAdded(self, slimItem):
    459         if self.trackPendingItemIDSpeedDuration and slimItem.itemID == self.trackPendingItemIDSpeedDuration[0]:
    460             self.Track(*self.trackPendingItemIDSpeedDuration)
    461 
    462     def GetZoomToPoint(self):
    463         offset = BaseSpaceCamera.GetZoomToPoint(self)
    464         speedOffset = self.speedOffsetter.GetSpeedOffset()
    465         if speedOffset:
    466             offset = geo2.Vec3AddD(offset, speedOffset)
    467         return offset
    468 
    469     def OnLookAtItemModelLoaded(self):
    470         self.UpdateMaxZoom()
    471         if self.GetZoomDistance() < self.maxZoom:
    472             self.SetZoom(0.0)