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

baseSpaceCamera.py (12131B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\camera\baseSpaceCamera.py
      2 import audio2
      3 import blue
      4 import evetypes
      5 from carbon.common.script.util.mathCommon import GetAngleBetweenTwoVectors, IsWithinFrustum
      6 from eve.client.script.parklife import states
      7 from eve.client.script.ui.camera.baseCamera import Camera
      8 from eve.client.script.ui.camera.cameraUtil import IsBobbingEnabled, GetCameraMaxLookAtRange, GetBallPosition, GetBall, IsAutoTrackingEnabled, FOV_MIN, FOV_MAX
      9 from eve.client.script.ui.camera.util.cameraBobbingOffsetter import CameraBobbingOffsetter
     10 from eve.common.lib import appConst
     11 from evecamera.animation import AnimationController
     12 from evecamera.shaker import ShakeController
     13 from evecamera.utils import CreateBehaviorFromMagnitudeAndPosition, PanCameraAccelerated
     14 import evegraphics.settings as gfxsettings
     15 import geo2
     16 import logging
     17 import math
     18 import random
     19 import uthread
     20 log = logging.getLogger(__name__)
     21 MAX_NOISE = 160.0
     22 
     23 class BaseSpaceCamera(Camera):
     24     isBobbingCamera = False
     25     name = 'BaseSpaceCamera'
     26     minZoom = 700000
     27     __notifyevents__ = Camera.__notifyevents__[:] + ['OnSpecialFX',
     28      'DoBallsRemove',
     29      'DoBallRemove',
     30      'DoClientSideBallRemove']
     31 
     32     def __init__(self):
     33         Camera.__init__(self)
     34         self.noiseCurve = None
     35         self.noiseScaleCurve = None
     36         self.noiseScale = 0.0
     37         self.noiseDampCurve = None
     38         self.noiseDamp = 1.1
     39         self._noiseX = 0.0
     40         self._noiseY = 0.0
     41         self._noiseOffset = None
     42         self._anchorBall = None
     43         self._anchorOffset = None
     44         self.trackTarget = None
     45         self.cachedCameraTranslation = None
     46         self.shakeController = ShakeController(self)
     47         self.animationController = AnimationController(self)
     48         self.isManualControlEnabled = True
     49         self.audioListener = None
     50         self._startTime = 0
     51         if self.isBobbingCamera:
     52             self.bobbingOfsetter = CameraBobbingOffsetter()
     53         else:
     54             self.bobbingOfsetter = None
     55 
     56     @property
     57     def ego(self):
     58         return session.structureid or session.shipid
     59 
     60     def ShakeCamera(self, magnitude, position, key = None):
     61         behavior = CreateBehaviorFromMagnitudeAndPosition(magnitude, position, self)
     62         if behavior is None:
     63             return
     64         behavior.key = key
     65         self.shakeController.DoCameraShake(behavior)
     66 
     67     def StopShaking(self):
     68         self.shakeController.ClearCurrentShake()
     69 
     70     def Update(self):
     71         Camera.Update(self)
     72         if self.IsNoiseEnabled():
     73             self._UpdateCameraNoiseOffset()
     74         if self.bobbingOfsetter:
     75             self._UpdateBobbingOffset()
     76         self.UpdateAnchorOffset()
     77 
     78     def IsNoiseEnabled(self):
     79         try:
     80             return gfxsettings.Get(gfxsettings.UI_CAMERA_SHAKE_ENABLED)
     81         except gfxsettings.UninitializedSettingsGroupError:
     82             return False
     83 
     84     def ResetCurveStartTime(self):
     85         self._startTime = blue.os.GetSimTime()
     86 
     87     def _UpdateCameraNoiseOffset(self):
     88         if self._startTime == 0:
     89             self._startTime = blue.os.GetSimTime()
     90         localTime = blue.os.TimeAsDouble(blue.os.GetSimTime() - self._startTime)
     91         if self.noiseScaleCurve:
     92             self.noiseScale = self.noiseScaleCurve.UpdateScalar(localTime)
     93         if self.noiseScale == 0:
     94             return
     95         if self.noiseDampCurve:
     96             self.noiseDamp = self.noiseDampCurve.UpdateScalar(localTime)
     97         dT = 1.0 / blue.os.fps
     98         ran = random.random() - 0.5
     99         self._noiseX = (self._noiseX + self.noiseDamp * ran) / (1.0 + self.noiseDamp * dT)
    100         self._noiseX = max(-MAX_NOISE, min(self._noiseX, MAX_NOISE))
    101         ran = random.random() - 0.5
    102         self._noiseY = (self._noiseY + self.noiseDamp * ran) / (1.0 + self.noiseDamp * dT)
    103         self._noiseY = max(-MAX_NOISE, min(self._noiseY, MAX_NOISE))
    104         noiseScale = self.GetZoomDistance() / 100.0 * self.noiseScale
    105         direction = self.GetLookAtDirection()
    106         vecX = geo2.Vec3Cross(direction, self._upDirection)
    107         vecY = geo2.Vec3Cross(direction, vecX)
    108         vecX = geo2.Vec3Scale(vecX, self._noiseX * noiseScale)
    109         vecY = geo2.Vec3Scale(vecY, self._noiseY * noiseScale)
    110         noiseOffset = geo2.Vec3Add(vecX, vecY)
    111         self._AddToAtOffset(noiseOffset)
    112 
    113     def ClearCameraParent(self):
    114         self.LookAt(self.ego)
    115         self.ResetAnchorPos()
    116 
    117     def Track(self, itemID, **kwargs):
    118         pass
    119 
    120     def OnAutoTrackingChanged(self):
    121         if not self.isActive:
    122             return
    123         if IsAutoTrackingEnabled():
    124             itemID = sm.GetService('stateSvc').GetExclState(states.selected)
    125             self.Track(itemID)
    126         else:
    127             self.Track(None)
    128 
    129     def GetCameraParent(self):
    130         return self.trackTarget
    131 
    132     def DisableManualControl(self):
    133         self.StopUpdateThreads()
    134         self.isManualControlEnabled = False
    135 
    136     def EnableManualControl(self):
    137         self.isManualControlEnabled = True
    138 
    139     def IsManualControlEnabled(self):
    140         return self.isManualControlEnabled and not self.IsInTransit()
    141 
    142     def Pan(self, *args):
    143         if self.IsManualControlEnabled():
    144             Camera.Pan(self, *args)
    145 
    146     def Zoom(self, dz):
    147         if self.IsManualControlEnabled():
    148             Camera.Zoom(self, dz)
    149 
    150     def Orbit(self, *args):
    151         if self.IsManualControlEnabled():
    152             Camera.Orbit(self, *args)
    153 
    154     def GetTrackPosition(self, ball):
    155         if not ball:
    156             ret = (0, 0, 0)
    157         elif not ball.ballpark:
    158             ret = self._atPosition
    159             self.ResetCamera()
    160         else:
    161             ret = GetBallPosition(ball)
    162         if self._anchorOffset:
    163             ret = geo2.Vec3Subtract(ret, self._anchorOffset)
    164         return ret
    165 
    166     def _UpdateBobbingOffset(self):
    167         if not IsBobbingEnabled():
    168             return
    169         offset = self.bobbingOfsetter.UpdateOffset(self.atPosition, self.eyePosition)
    170         self._AddToEyeAndAtOffset(offset)
    171 
    172     def CheckObjectTooFar(self, itemID):
    173         ball = GetBall(itemID)
    174         if not ball:
    175             return False
    176         if getattr(ball, 'typeID', None) and self._IsBallTypeDisallowedForLookAt(ball.typeID):
    177             return True
    178         ballPos = GetBallPosition(ball)
    179         return geo2.Vec3Length(ballPos) > GetCameraMaxLookAtRange()
    180 
    181     def _IsBallTypeDisallowedForLookAt(self, typeID):
    182         return evetypes.GetGroupID(typeID) in (appConst.groupPlanet, appConst.groupMoon)
    183 
    184     def ConstructAnchorBall(self):
    185         bp = sm.GetService('michelle').GetBallpark()
    186         if not bp or not bp.ego:
    187             return
    188         pos = bp.GetCurrentEgoPos()
    189         self._anchorBall = bp.AddClientSideBall(pos)
    190 
    191     def ResetAnchorPos(self):
    192         if self._anchorOffset:
    193             self.eyePosition = geo2.Vec3Add(self.eyePosition, self._anchorOffset)
    194             self.atPosition = geo2.Vec3Add(self.atPosition, self._anchorOffset)
    195         self._anchorBall = None
    196         self._anchorOffset = None
    197 
    198     def UpdateAnchorOffset(self):
    199         if self._anchorBall:
    200             self._anchorOffset = GetBallPosition(self._anchorBall)
    201             self._AddToEyeAndAtOffset(self._anchorOffset)
    202         else:
    203             self._anchorOffset = None
    204 
    205     def OnSpecialFX(self, shipID, moduleID, moduleTypeID, targetID, otherTypeID, guid, isOffensive, start, active, duration = -1, repeat = None, startTime = None, timeFromStart = 0, graphicInfo = None):
    206         if guid == 'effects.Warping':
    207             if shipID in (self.ego, self.GetLookAtItemID()):
    208                 self.OnCurrentShipWarping()
    209 
    210     def GetLookAtItemID(self):
    211         return self.ego
    212 
    213     def GetItemID(self):
    214         return self.GetLookAtItemID()
    215 
    216     def OnCurrentShipWarping(self):
    217         pass
    218 
    219     def OnActivated(self, **kwargs):
    220         Camera.OnActivated(self, **kwargs)
    221         uthread.new(self.AudioUpdateThread)
    222         settings.char.Subscribe('ui', 'orbitCameraAutoTracking', self.OnAutoTrackingChanged)
    223         if self.bobbingOfsetter:
    224             self.bobbingOfsetter.OnActivated()
    225 
    226     def OnDeactivated(self):
    227         super(BaseSpaceCamera, self).OnDeactivated()
    228         settings.char.Unsubscribe('ui', 'orbitCameraAutoTracking', self.OnAutoTrackingChanged)
    229 
    230     def AudioUpdateThread(self):
    231         self.audioListener = audio2.GetListener()
    232         while self.isActive:
    233             self.audioListener.SetPosition(self.GetLookAtDirection(), self.upDirection, self.eyePosition)
    234             blue.synchro.Yield()
    235 
    236         self.audioListener = None
    237 
    238     def TranslateFromParentAccelerated(self, begin, end, durationSec, accelerationPower = 2.0):
    239         self.animationController.Schedule(PanCameraAccelerated(begin, end, durationSec, accelerationPower))
    240 
    241     def IsLocked(self):
    242         return False
    243 
    244     def DoClientSideBallRemove(self, ball):
    245         self.DoBallRemove(ball)
    246         if ball == self._anchorBall:
    247             self.ResetAnchorPos()
    248 
    249     def DoBallsRemove(self, pythonBalls, isRelease):
    250         for ball, _, _ in pythonBalls:
    251             self.DoBallRemove(ball)
    252 
    253     def DoBallRemove(self, ball, *args, **kwargs):
    254         self.OnBallRemoved(ball)
    255 
    256     def OnBallRemoved(self, ball):
    257         pass
    258 
    259     def GetDynamicFovByDistance(self, dist):
    260         prop = max(0.0, min(dist / self.minZoom, 1.0))
    261         return FOV_MIN + prop ** 0.35 * (FOV_MAX - FOV_MIN)
    262 
    263     def GetDynamicFov(self):
    264         if self._atTransitOffset:
    265             atPos = geo2.Vec3Subtract(self.atPosition, self._atTransitOffset)
    266         else:
    267             atPos = self.atPosition
    268         dist = geo2.Vec3Distance(self.eyePosition, atPos)
    269         return self.GetDynamicFovByDistance(dist)
    270 
    271     def ResetFOV(self):
    272         self.SetFovTarget(self.default_fov)
    273 
    274     def GetItemPosition(self, itemID):
    275         itemBall = GetBall(itemID)
    276         if not itemBall:
    277             raise RuntimeError('Failed to find position for item %s. Item is not in the current ballpark.' % itemID)
    278         return GetBallPosition(itemBall)
    279 
    280     def GetLookAtItemDirection(self, itemID):
    281         itemPosition = self.GetItemPosition(itemID)
    282         eyePosition = geo2.Vec3AddD(self._eyePosition, self._eyeOffset) if self._eyeOffset else self._eyePosition
    283         return geo2.Vec3Direction(eyePosition, itemPosition)
    284 
    285     def IsWithinViewAngle(self, itemID, angleInDegrees):
    286         try:
    287             cameraLookAtDirection = self.GetLookAtDirectionWithOffset()
    288             itemLookAtDirection = self.GetLookAtItemDirection(itemID)
    289             angleFromCameraToItem = GetAngleBetweenTwoVectors(cameraLookAtDirection, itemLookAtDirection)
    290             angleToCheck = math.radians(angleInDegrees)
    291             return angleFromCameraToItem <= angleToCheck
    292         except Exception as exc:
    293             log.exception('Error when checking if item %s is in %s degree view angle: %s', itemID, angleInDegrees, exc)
    294             return False
    295 
    296     def IsWithinViewFrustum(self, itemID):
    297         try:
    298             itemPosition = self.GetItemPosition(itemID)
    299             return IsWithinFrustum(itemPosition, self.viewMatrix.transform, self.projectionMatrix.transform)
    300         except Exception as exc:
    301             log.exception('Error when checking whether item is within view frustum: %s', exc)
    302             return False
    303 
    304     def GetLookAtPointDirection(self, pointLocation):
    305         eyePosition = geo2.Vec3AddD(self._eyePosition, self._eyeOffset) if self._eyeOffset else self._eyePosition
    306         return geo2.Vec3Direction(eyePosition, pointLocation)
    307 
    308     def IsPointWithinViewAngle(self, pointLocation, angleInDegrees):
    309         try:
    310             cameraLookAtDirection = self.GetLookAtDirectionWithOffset()
    311             itemLookAtDirection = self.GetLookAtPointDirection(pointLocation)
    312             angleFromCameraToPoint = GetAngleBetweenTwoVectors(cameraLookAtDirection, itemLookAtDirection)
    313             angleToCheck = math.radians(angleInDegrees)
    314             return angleFromCameraToPoint <= angleToCheck
    315         except Exception as exc:
    316             log.exception('Error when checking if point %s is in %s degree view angle: %s', pointLocation, angleInDegrees, exc)
    317             return False