spaceCamera.py (14443B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\camera\spaceCamera.py 2 from math import sin, cos 3 from eve.client.script.parklife import states as state 4 from eve.client.script.ui.camera.cameraBase import CameraBase 5 from eve.client.script.ui.camera.cameraUtil import GetCameraMaxLookAtRange 6 from destructionEffect import destructionType as destructionEffectType 7 import evecamera 8 import audio2 9 import blue 10 import trinity 11 import uthread 12 import destiny 13 import localization 14 import telemetry 15 import evecamera.shaker as shaker 16 import evecamera.utils as camutils 17 import evecamera.cameratarget as camtarget 18 import evecamera.animation as camanim 19 import evegraphics.settings as gfxsettings 20 import evespacescene 21 from player_messaging.client.ui_message import message_player 22 SIZEFACTOR = 1e-07 23 TRANSLATION_MAX = 1000000.0 24 25 class SpaceCamera(CameraBase): 26 cameraID = 'default' 27 __notifyevents__ = ['OnSpecialFX', 28 'DoBallClear', 29 'DoBallRemove', 30 'OnSessionChanged', 31 'OnSetDevice', 32 'OnGraphicSettingsChanged', 33 'DoBallsRemove', 34 'DoSimClockRebase', 35 'OnBallparkSetState'] 36 37 def __init__(self): 38 CameraBase.__init__(self) 39 sm.RegisterNotify(self) 40 self.ResetConfiguration() 41 self.noise = gfxsettings.Get(gfxsettings.UI_CAMERA_SHAKE_ENABLED) 42 self.UpdateCameraBobbing() 43 self.checkDistToEgoThread = None 44 self.cachedCameraTranslation = -1 45 self.shakeController = shaker.ShakeController(self) 46 self.animationController = camanim.AnimationController(self) 47 self.lookingAt = None 48 49 def UpdateCameraBobbing(self): 50 self.idleMove = gfxsettings.Get(gfxsettings.UI_CAMERA_BOBBING_ENABLED) 51 52 def ResetConfiguration(self): 53 self.fieldOfView = evecamera.FOV_MAX 54 self.friction = evecamera.DEFAULT_FRICTION 55 self.maxSpeed = evecamera.DEFAULT_MAX_SPEED 56 self.frontClip = evecamera.DEFAULT_FRONT_CLIP 57 self.backClip = evecamera.DEFAULT_BACK_CLIP 58 self.idleScale = evecamera.DEFAULT_IDLE_SCALE 59 self.translationFromParent = -30.0 60 self.idleSpeed = 0.5 61 self.noiseScale = -2.010956 62 self.noiseScaleCurve = trinity.Tr2CurveScalar() 63 self.noiseScaleCurve.AddKey(0.0, 0.0, trinity.Tr2CurveInterpolation.LINEAR) 64 self.noiseScaleCurve.AddKey(0.5, -2.2945609, trinity.Tr2CurveInterpolation.LINEAR) 65 self.noiseScaleCurve.AddKey(5.0, 0.0, trinity.Tr2CurveInterpolation.LINEAR) 66 self.zoomCurve = trinity.Tr2CurveScalar() 67 self.zoomCurve.AddKey(0.0, evecamera.FOV_MAX, trinity.Tr2CurveInterpolation.HERMITE, 0.0, 1.0, trinity.Tr2CurveTangentType.FREE_SPLIT) 68 self.zoomCurve.AddKey(0.224, evecamera.FOV_MAX, trinity.Tr2CurveInterpolation.HERMITE, 0.0, -7.0, trinity.Tr2CurveTangentType.FREE_SPLIT) 69 self.zoomCurve.AddKey(0.45, evecamera.FOV_MAX, trinity.Tr2CurveInterpolation.HERMITE, 0.0, -9.0, trinity.Tr2CurveTangentType.FREE_SPLIT) 70 self.zoomCurve.AddKey(0.6, evecamera.FOV_MAX, trinity.Tr2CurveInterpolation.HERMITE, 0.0, 20.0, trinity.Tr2CurveTangentType.FREE_SPLIT) 71 self.zoomCurve.AddKey(0.0, evecamera.FOV_MAX, trinity.Tr2CurveInterpolation.HERMITE, 0.0, 1.0, trinity.Tr2CurveTangentType.FREE_SPLIT) 72 73 def DoBallClear(self, solitem): 74 cameraParent = self.GetCameraParent() 75 if cameraParent is not None: 76 cameraParent.parent = None 77 78 @telemetry.ZONE_METHOD 79 def DoBallsRemove(self, pythonBalls, isRelease): 80 for ball, slimItem, terminal in pythonBalls: 81 self.DoBallRemove(ball, slimItem, terminal) 82 83 def DoBallRemove(self, ball, slimItem, terminal): 84 if session.shipid is not None: 85 lookingAtID = self.GetLookAtItemID() 86 if lookingAtID is not None and ball.id == lookingAtID: 87 if ball.destructionEffectId != destructionEffectType.NONE and ball.id != session.shipid: 88 uthread.new(self._HandleTargetKilled, ball) 89 else: 90 uthread.new(self._AdjustLookAtTarget, ball) 91 elif self.cameraInterestID == ball.id and ball.destructionEffectId is not destructionEffectType.NONE: 92 uthread.new(self._HandleTargetKilled, ball) 93 94 def DoSimClockRebase(self, times): 95 self.animationController.DoSimClockRebase(times) 96 97 def _HandleTargetKilled(self, ball): 98 delay = ball.GetExplosionLookAtDelay() 99 blue.synchro.SleepSim(delay) 100 lookingAtID = self.GetLookAtItemID() 101 if lookingAtID == ball.id: 102 self.LookAt(session.shipid) 103 if self.cameraInterestID == ball.id: 104 self.Track(None) 105 106 def _AdjustLookAtTarget(self, ball): 107 if session.shipid is None: 108 return 109 cameraParent = self.GetCameraParent() 110 lookingAtID = self.GetLookAtItemID() 111 if cameraParent and cameraParent.parent and cameraParent.parent == ball.model: 112 cameraParent.parent = None 113 if lookingAtID and ball.id == lookingAtID and lookingAtID != session.shipid: 114 self.LookAt(session.shipid) 115 116 def OnSpecialFX(self, shipID, moduleID, moduleTypeID, targetID, otherTypeID, guid, isOffensive, start, active, duration = -1, repeat = None, startTime = None, timeFromStart = 0, graphicInfo = None): 117 if guid == 'effects.Warping': 118 if shipID == session.shipid: 119 if self.GetLookAtItemID() is not None and self.GetLookAtItemID() != session.shipid: 120 self.LookAt(session.shipid) 121 122 def OnSetDevice(self, *args): 123 if session.stationid: 124 return 125 blue.synchro.Yield() 126 self.translationFromParent = self.CheckTranslationFromParent(self.translationFromParent) 127 128 def OnBallparkSetState(self, *args): 129 uthread.new(self.LookAt, session.shipid, self.cachedCameraTranslation, smooth=False) 130 131 def OnSessionChanged(self, isRemote, sess, change): 132 if 'shipid' in change: 133 oldID = change['shipid'][0] 134 newID = change['shipid'][1] 135 bp = sm.GetService('michelle').GetBallpark() 136 if bp is None: 137 return 138 if newID is not None and newID not in bp.slimItems and oldID is not None: 139 self.lookingAt = newID 140 else: 141 self.LookAt(newID, self.cachedCameraTranslation) 142 143 def _GetTrackableCurve(self, itemID): 144 item = sm.StartService('michelle').GetBall(itemID) 145 if item is None or getattr(item, 'model', None) is None: 146 return 147 if item.model.__bluetype__ in evespacescene.EVESPACE_TRINITY_CLASSES: 148 behavior = trinity.EveLocalPositionBehavior.centerBounds 149 tracker = trinity.EveLocalPositionCurve(behavior) 150 tracker.parent = item.model 151 return tracker 152 return item 153 154 def Track(self, itemID, **kwargs): 155 self.cameraInterestID = itemID 156 cameraInterest = self.GetCameraInterest() 157 if itemID is None: 158 cameraInterest.translationCurve = None 159 trackable = self._GetTrackableCurve(itemID) 160 cameraInterest.translationCurve = trackable 161 162 def GetTrackItemID(self): 163 return self.cameraInterestID 164 165 def _AbortLookAtOther(self): 166 self.ResetCamera() 167 self.checkDistToEgoThread = None 168 169 def _CheckDistanceToEgo(self): 170 while self.checkDistToEgoThread is not None: 171 if self.lookingAt is not None: 172 lookingAtItem = sm.GetService('michelle').GetBall(self.lookingAt) 173 if lookingAtItem is None or lookingAtItem.surfaceDist > GetCameraMaxLookAtRange(): 174 self._AbortLookAtOther() 175 blue.synchro.Yield() 176 177 def _LookingAtSelf(self): 178 scene = sm.GetService('sceneManager').GetRegisteredScene('default') 179 if scene and scene.cameraAttachments.FindByName('dustfield'): 180 scene.cameraAttachments.FindByName('dustfield').display = True 181 self.checkDistToEgoThread = None 182 183 def _IsLookingAtOtherOK(self, item): 184 obs = sm.GetService('target').IsObserving() 185 if item is None: 186 return False 187 if item.mode == destiny.DSTBALL_WARP: 188 return False 189 if not obs and item.surfaceDist > GetCameraMaxLookAtRange(): 190 message_player(localization.GetByLabel('UI/Camera/OutsideLookingRange')) 191 return False 192 return True 193 194 def _LookingAtOther(self): 195 scene = sm.GetService('sceneManager').GetRegisteredScene('default') 196 if scene is not None: 197 if scene.cameraAttachments.FindByName('dustfield'): 198 scene.cameraAttachments.FindByName('dustfield').display = False 199 if self.checkDistToEgoThread is None: 200 self.checkDistToEgoThread = uthread.pool('MenuSvc>checkDistToEgoThread', self._CheckDistanceToEgo) 201 return True 202 203 def LookAt(self, itemID, setZ = None, resetCamera = False, smooth = True, **kwargs): 204 item = sm.StartService('michelle').GetBallAndWaitForModel(itemID) 205 if not hasattr(item, 'GetModel') or item.GetModel() is None: 206 return 207 itemIdIsMyShip = itemID == session.shipid 208 if itemIdIsMyShip: 209 self._LookingAtSelf() 210 elif self._IsLookingAtOtherOK(item): 211 self._LookingAtOther() 212 else: 213 return 214 cameraParent = self.GetCameraParent() 215 if cameraParent is None: 216 return 217 self.GetCameraInterest().translationCurve = None 218 sm.GetService('stateSvc').SetState(itemID, state.lookingAt, 1) 219 self.lookingAt = itemID 220 cache = itemIdIsMyShip 221 item.LookAtMe() 222 if itemIdIsMyShip is False: 223 sm.ScatterEvent('OnCameraLookAt', False, itemID) 224 trackableItem = self._GetTrackableCurve(itemID) 225 if not smooth: 226 self.animationController.Schedule(camutils.SetTranslationCurve(trackableItem)) 227 self.animationController.Schedule(camutils.LookAt_Pan(setZ, 0.0, cache=cache)) 228 else: 229 self._DoAnimatedLookAt(item, setZ, resetCamera, trackableItem, cache=cache) 230 231 def _DoAnimatedLookAt(self, item, setZ = None, resetCamera = False, trackableItem = None, cache = False): 232 if item.model.__bluetype__ not in evespacescene.EVESPACE_TRINITY_CLASSES: 233 self.animationController.Schedule(camutils.SetTranslationCurve(trackableItem)) 234 return 235 behavior = trinity.EveLocalPositionBehavior.centerBounds 236 tracker = trinity.EveLocalPositionCurve(behavior) 237 tracker.parent = item.model 238 self.animationController.Schedule(camutils.LookAt_Translation(tracker)) 239 self.animationController.Schedule(camutils.LookAt_FOV(resetCamera)) 240 self.animationController.Schedule(camutils.LookAt_Pan(setZ, cache=cache)) 241 242 def PanCameraBy(self, percentage, time = 0.0, cache = False): 243 beg = self.translationFromParent 244 end = beg + beg * percentage 245 self.PanCamera(beg, end, time, cache) 246 247 def PanCamera(self, cambeg = None, camend = None, time = 0.5, cache = False, source = None): 248 cacheTranslation = cache and self.GetLookAtItemID() == session.shipid 249 self.animationController.Schedule(camutils.PanCamera(cambeg, camend, time, cacheTranslation, source)) 250 251 def TranslateFromParentAccelerated(self, begin, end, durationSec, accelerationPower = 2.0): 252 self.animationController.Schedule(camutils.PanCameraAccelerated(begin, end, durationSec, accelerationPower)) 253 254 def ClearAnimations(self): 255 self.animationController.ClearAll() 256 257 def CacheCameraTranslation(self): 258 self.cachedCameraTranslation = self.translationFromParent 259 260 def ClearCameraParent(self): 261 if self.cameraParent: 262 self.cameraParent.translationCurve = None 263 self.cameraParent = None 264 265 def GetCameraParent(self): 266 if self.cameraParent is None: 267 self.cameraParent = camtarget.CameraTarget(self) 268 return self.cameraParent 269 270 def GetCameraInterest(self): 271 if self.cameraInterest is None: 272 self.cameraInterest = camtarget.CameraTarget(self, 'interest') 273 return self.cameraInterest 274 275 def ResetCamera(self, *args): 276 sm.ScatterEvent('OnCameraLookAt', True, session.shipid) 277 self.LookAt(session.shipid, resetCamera=True) 278 279 def GetLookAtItemID(self): 280 return self.lookingAt 281 282 def _GetTranslationFromParentForItem(self, itemID): 283 ballpark = sm.GetService('michelle').GetBallpark() 284 if ballpark is None: 285 return 286 ball = ballpark.GetBall(itemID) 287 ball, model, ballRadius = ball, getattr(ball, 'model', None), getattr(ball, 'radius', None) 288 if model is None: 289 return 290 rad = None 291 if model.__bluetype__ in evespacescene.EVESPACE_TRINITY_CLASSES: 292 rad = model.GetBoundingSphereRadius() 293 zoomMultiplier = 1.1 * camutils.GetARZoomMultiplier(trinity.GetAspectRatio()) 294 return (rad + self.frontClip) * zoomMultiplier + 2 295 if len(getattr(model, 'children', [])) > 0: 296 rad = ball.model.children[0].GetBoundingSphereRadius() 297 if rad is None or rad <= 0.0: 298 rad = ballRadius 299 camangle = self.fieldOfView * 0.5 300 return max(15.0, rad / sin(camangle) * cos(camangle)) 301 302 def CheckTranslationFromParent(self, distance, distanceIsScale = False): 303 mn, mx = self._GetMinMaxTranslationFromParent() 304 if distanceIsScale: 305 distance = mn * distance 306 retval = max(mn, min(distance, mx)) 307 return retval 308 309 def _GetMinMaxTranslationFromParent(self): 310 lookingAt = self.GetLookAtItemID() or session.shipid 311 mn = self._GetTranslationFromParentForItem(lookingAt) 312 mx = TRANSLATION_MAX 313 return (mn, mx) 314 315 def ShakeCamera(self, magnitude, position, key = None): 316 behavior = camutils.CreateBehaviorFromMagnitudeAndPosition(magnitude, position, self) 317 if behavior is None: 318 return 319 behavior.key = key 320 self.shakeController.DoCameraShake(behavior) 321 322 def OnGraphicSettingsChanged(self, changes): 323 if gfxsettings.UI_CAMERA_SHAKE_ENABLED in changes: 324 self.shakeController.Enable(gfxsettings.Get(gfxsettings.UI_CAMERA_SHAKE_ENABLED)) 325 if gfxsettings.UI_CAMERA_BOBBING_ENABLED in changes: 326 self.UpdateCameraBobbing()