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

modularHangarCamera.py (19296B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\camera\modularHangarCamera.py
      2 import math
      3 from eve.client.script.ui.camera.cameraUtil import GetInitialLookAtDistance
      4 import evecamera
      5 import uthread
      6 import logging
      7 import blue
      8 from eve.client.script.ui.camera.baseSpaceCamera import BaseSpaceCamera
      9 from gametime import GetSecondsSinceSimTime, GetSimTime
     10 import carbonui.const as uiconst
     11 import geo2
     12 from carbonui.uicore import uicore
     13 import eve.client.script.ui.view.hangarBehaviours.modularHangarBehavioursConstants as hc
     14 from uthread2 import call_after_simtime_delay
     15 logger = logging.getLogger(__name__)
     16 
     17 class ModularHangarCamera(BaseSpaceCamera):
     18     cameraID = evecamera.CAM_MODULARHANGAR
     19     isBobbingCamera = False
     20     name = 'ModularHangarCamera'
     21     kMaxPitch = math.pi / 2.0 + math.pi / 8.0
     22     minFov = 0.3
     23     maxFov = 1.0
     24     hangarMinZoom = 2050.0
     25     hangarMaxZoom = 10.0
     26 
     27     def __init__(self):
     28         BaseSpaceCamera.__init__(self)
     29         self.log = logger
     30         self.model = None
     31         self.atPosition = (0.0, 0.0, 0.0)
     32         self.typeID = 0
     33         self.zoomFactor = 0.5
     34         self.fov = 1.0
     35         self.fpShipSpawnTime = 0
     36         self.hangarEntryTime = 0
     37         self.simplifiedDirection = (0.0, 0.0, 0.0)
     38         self.camSpeed = (0.0, 0.0, 0.0)
     39         self.distanceToFP = 0
     40         self.isRotating = 0
     41         self.changingShip = False
     42         self.flightValueMap = []
     43         self.targetPoint = (0.0, 0.0, 0.0)
     44         self.lastShipLocation = None
     45         self.transitionAnimationEndedTime = 0
     46         self.hallwayTime = 0.4
     47         self.currentShipSizeClass = 1
     48         self.phase2finished = True
     49         self.changingSkinsTime = 0
     50 
     51     def SetCurrentShipSizeClass(self, sizeClass):
     52         self.currentShipSizeClass = sizeClass
     53 
     54     def SetRotating(self, isTrue):
     55         self.isRotating = isTrue
     56 
     57     def SetFlightValueMap(self, exit1, hallway1, hallway2, exit2, dockPos):
     58         hallwayLength = min(0.9, geo2.Vec3Length(geo2.Vec3Subtract(hallway1, hallway2)) / 10000)
     59         self.hallwayTime = 0.1 + hallwayLength
     60         if self.hallwayTime > 0.4 or not hc.TRANSITION_MODIFY_BY_HALLWAYTIME:
     61             self.flightValueMap = [self.GetEyePosition(),
     62              exit1,
     63              hallway1,
     64              hallway2,
     65              exit2,
     66              dockPos]
     67         else:
     68             modifiedHallway1 = geo2.Vec3Lerp(exit1, hallway1, self.hallwayTime)
     69             modifiedHallway2 = geo2.Vec3Lerp(exit2, hallway2, self.hallwayTime)
     70             self.flightValueMap = [self.GetEyePosition(),
     71              exit1,
     72              modifiedHallway1,
     73              modifiedHallway2,
     74              exit2,
     75              dockPos]
     76 
     77     def SetIsChangingSkin(self):
     78         self.changingSkinsTime = GetSimTime()
     79 
     80     def SetShip(self, model, typeID, changingShip = True):
     81         uicore.animations.StopAllAnimations(self)
     82         self.lastShipLocation = self.atPosition
     83         self.model = model
     84         self.typeID = typeID
     85         if changingShip:
     86             self.fov = 1.0
     87             self.fpShipSpawnTime = GetSimTime()
     88         self.targetPoint = self.GetEyePosition()
     89         self.changingShip = changingShip or self.changingShip
     90 
     91     def SkipFlight(self):
     92         time = GetSimTime() - (hc.SHIP_SWAP_DURATION + hc.TRANSITION_PADDING)
     93         self.fpShipSpawnTime = time
     94         self.changingSkinsTime = 0.0
     95         self.phase2finished = True
     96         self.changingShip = False
     97 
     98     def PlaceShip(self, pos):
     99         self.atPosition = pos
    100 
    101     def AnimEnterHangar(self, model, startPos, endPos, duration = 5.0):
    102         self.hangarEntryTime = GetSimTime()
    103         self.model = model
    104         self.atPosition = self._CalculateFocalPoint(model)
    105         self.changingShip = False
    106         self.SetEyePosition(self.CalculateTargetPoint())
    107         self.yaw = 0
    108         self.pitch = 0
    109 
    110         def AllignCamera():
    111             modelRotation = model.rotationCurve.currentValue
    112             extraYaw = geo2.QuaternionRotationGetYawPitchRoll(modelRotation)[0]
    113             self.yaw = extraYaw + 0.5 - math.pi
    114             self.pitch = 1.2
    115             self.zoomFactor = 0.9
    116 
    117         call_after_simtime_delay(AllignCamera, 0.3)
    118 
    119     def _AnimEnterHangarFOV(self, duration):
    120         pass
    121 
    122     def _AnimEnterHangarZoom(self, duration, model):
    123         pass
    124 
    125     def _AnimSwitchShipsZoom(self, duration, model):
    126         pass
    127 
    128     def _AnimZoom(self, duration, zoom0, zoom1):
    129         pass
    130 
    131     def UpdateMinMaxZoom(self):
    132         pass
    133 
    134     def SetZoom(self, proportion):
    135         pass
    136 
    137     def ClearRefs(self):
    138         self.model = None
    139 
    140     def CalculateTargetPoint(self):
    141         biggestEllipsoidAxis = max(self.model.generatedShapeEllipsoidRadius)
    142         roundFactor = hc.SHIELD_ELLIPSOID_ROUNDING_FACTOR + (1 - pow(1 - self.zoomFactor, 2.0)) * (1 - hc.SHIELD_ELLIPSOID_ROUNDING_FACTOR)
    143         cameraBoundLength, innerPaddingValue, outerPaddingValue = self.GetSizeDependantZoomConstants()
    144         platformCameraBounds = (cameraBoundLength, cameraBoundLength, cameraBoundLength)
    145         innerPadding = (innerPaddingValue, innerPaddingValue, innerPaddingValue)
    146         outerPadding = (outerPaddingValue, outerPaddingValue, outerPaddingValue)
    147         fullyRoundedEllipsoid = (biggestEllipsoidAxis, biggestEllipsoidAxis, biggestEllipsoidAxis)
    148         innerBoundRadius = geo2.Vec3Lerp(self.model.generatedShapeEllipsoidRadius, fullyRoundedEllipsoid, roundFactor)
    149         innerBoundRadius = geo2.Vec3Add(innerBoundRadius, innerPadding)
    150         preferredOuterBoundRadius = geo2.Vec3Add(geo2.Vec3Scale(innerBoundRadius, hc.SHIELD_ELLIPSOID_ZOOM_MULTIPLIER), outerPadding)
    151         outerBoundRadius = tuple((min(ele1, ele2) for ele1, ele2 in zip(preferredOuterBoundRadius, platformCameraBounds)))
    152         direction = self.GetLookAtDirection()
    153         invertedDirection = geo2.QuaternionInverse(self.model.rotationCurve.currentValue)
    154         self.simplifiedDirection = geo2.QuaternionTransformVector(invertedDirection, direction)
    155         invertedSimplifiedDirection = geo2.Vec3Scale(self.simplifiedDirection, -1)
    156         innerPoint = tuple((ele1 * ele2 for ele1, ele2 in zip(invertedSimplifiedDirection, innerBoundRadius)))
    157         outerPoint = tuple((ele1 * ele2 for ele1, ele2 in zip(invertedSimplifiedDirection, outerBoundRadius)))
    158         self.distanceToFP = geo2.Vec3Length(geo2.Vec3Lerp(innerPoint, outerPoint, self.zoomFactor))
    159         zoomVec = geo2.Vec3Scale(direction, self.distanceToFP)
    160         targetPos = geo2.Vec3Add(self.GetZoomToPoint(), zoomVec)
    161         return targetPos
    162 
    163     def GetSizeDependantZoomConstants(self):
    164         biggestEllipsoidAxis = max(self.model.generatedShapeEllipsoidRadius)
    165         if self.currentShipSizeClass == 0:
    166             cbl = hc.SMALL_PLATFORM_CAMERA_BOUNDS + hc.SMALL_PLATFORM_BOUNDING_PADDING * biggestEllipsoidAxis
    167             innerBoundsPadding = hc.SMALL_PLATFORM_INNER_PADDING_BOUNDING_SPHERE_FACTOR * biggestEllipsoidAxis
    168             return (cbl, hc.SMALL_PLATFORM_INNER_PADDING, hc.SMALL_PLATFORM_OUTER_PADDING)
    169         elif self.currentShipSizeClass == 1:
    170             cbl = hc.SMALL_PLATFORM_CAMERA_BOUNDS + hc.SMALL_PLATFORM_BOUNDING_PADDING * biggestEllipsoidAxis
    171             innerBoundsPadding = hc.SMALL_PLATFORM_INNER_PADDING_BOUNDING_SPHERE_FACTOR * biggestEllipsoidAxis
    172             return (cbl, hc.SMALL_PLATFORM_INNER_PADDING + innerBoundsPadding, hc.SMALL_PLATFORM_OUTER_PADDING)
    173         elif self.currentShipSizeClass == 2:
    174             cbl = hc.MEDIUM_PLATFORM_CAMERA_BOUNDS + hc.MEDIUM_PLATFORM_BOUNDING_PADDING * biggestEllipsoidAxis
    175             return (cbl, hc.MEDIUM_PLATFORM_INNER_PADDING, hc.MEDIUM_PLATFORM_OUTER_PADDING)
    176         elif self.currentShipSizeClass == 3:
    177             self.log.error('capital ship misplaced in the regular hangar')
    178             cbl = hc.SMALL_PLATFORM_CAMERA_BOUNDS + hc.SMALL_PLATFORM_BOUNDING_PADDING * biggestEllipsoidAxis
    179             innerBoundsPadding = hc.SMALL_PLATFORM_INNER_PADDING_BOUNDING_SPHERE_FACTOR * biggestEllipsoidAxis
    180             return (cbl, hc.SMALL_PLATFORM_INNER_PADDING + innerBoundsPadding, hc.SMALL_PLATFORM_OUTER_PADDING)
    181         else:
    182             return None
    183 
    184     def EnforceMaxZoom(self):
    185         if self.changingShip:
    186             cameraSpeed = hc.CAMERA_FOLLOW_SPEED / 100.0
    187             lerpedTarget = geo2.Vec3Lerp(self.GetEyePosition(), self.targetPoint, cameraSpeed)
    188             self.SetEyePosition(lerpedTarget)
    189             return
    190         if self.changingSkinsTime != 0:
    191             cameraSpeed = hc.CAMERA_FOLLOW_SPEED / 100.0
    192             lerpedTarget = geo2.Vec3Lerp(self.GetEyePosition(), self.CalculateTargetPoint(), cameraSpeed)
    193             self.SetEyePosition(lerpedTarget)
    194             return
    195         targetPos = self.CalculateTargetPoint()
    196         elapsedDuration = GetSecondsSinceSimTime(self.transitionAnimationEndedTime)
    197         timeSinceHangarEntry = GetSecondsSinceSimTime(self.hangarEntryTime)
    198         if timeSinceHangarEntry > 5 and not self.phase2finished and elapsedDuration < hc.PHASE_2_DURATION:
    199             target = geo2.Vec3Add(self.GetEyePosition(), self.camSpeed)
    200             blendRamp = (hc.PHASE_1_TO_2_BLEND_DURATION - elapsedDuration) / hc.PHASE_1_TO_2_BLEND_DURATION
    201             self.camSpeed = geo2.Vec3Scale(self.camSpeed, 0.6 + 0.4 * blendRamp)
    202             phase2Progress = (hc.PHASE_2_DURATION - elapsedDuration) / hc.PHASE_2_DURATION
    203             lerpedTarget = geo2.Vec3Lerp(target, targetPos, 1.0 - phase2Progress)
    204             self.SetEyePosition(lerpedTarget)
    205             if geo2.Vec3DistanceSqD(lerpedTarget, targetPos) < 5.0:
    206                 self.phase2finished = True
    207         else:
    208             self.SetEyePosition(geo2.Vec3Lerp(self.GetEyePosition(), targetPos, min(1.0, elapsedDuration)))
    209 
    210     def ClampPitch(self, pitch):
    211         if self.model is None:
    212             return pitch
    213         if self.model.translationCurve is None:
    214             return pitch
    215         extraPitch = 0
    216         try:
    217             if self.currentShipSizeClass < 2:
    218                 thresholds = [hc.SMALL_PLATFORM_GAP_INNER_EDGE, hc.SMALL_PLATFORM_GAP_OUTER_EDGE, hc.SMALL_PLATFORM_OUTER_EDGE]
    219                 extraAllowance = math.pi / 3.0
    220             else:
    221                 thresholds = [hc.MEDIUM_PLATFORM_GAP_INNER_EDGE, hc.MEDIUM_PLATFORM_GAP_OUTER_EDGE, hc.MEDIUM_PLATFORM_OUTER_EDGE]
    222                 extraAllowance = math.pi / 6.0
    223             lookingAtTheFront = pow(max(self.simplifiedDirection[2], 0.0), 2)
    224             frontOffset = self.model.translationCurve.curves[1].value[2]
    225             relativeCamPlacementFront = self.distanceToFP + frontOffset
    226             frontBoost = min(max(relativeCamPlacementFront * lookingAtTheFront - thresholds[0], 0.0) / thresholds[1], 1.0)
    227             lookingRight = -cmp(self.simplifiedDirection[0], 0)
    228             centerOffset = self.model.translationCurve.curves[1].value[0]
    229             relativeCamPlacement = (self.distanceToFP + lookingRight * centerOffset) * abs(self.simplifiedDirection[0])
    230             gapCenter = (thresholds[0] + thresholds[1]) / 2
    231             gapHalfWidth = abs(thresholds[1] - thresholds[0]) / 2
    232             closenessToGapCenter = max(gapHalfWidth - abs(relativeCamPlacement - gapCenter), 0.0) / gapHalfWidth
    233             closenessToGapCenter = closenessToGapCenter * min(2.0 * max(self.simplifiedDirection[2] + 0.8, 0.0), 1.0)
    234             distanceFromPlatformEdge = min(max((relativeCamPlacement - thresholds[2]) / (gapHalfWidth * 4), 0), 1.0)
    235             extraPitch = (closenessToGapCenter + distanceFromPlatformEdge + frontBoost) * extraAllowance
    236         except Exception as exc:
    237             logger.exception('ModularHangarCamera: Ship translationCurve not configured correctly')
    238 
    239         maxPitch = math.pi / 2.0 + extraPitch
    240         return max(self.kMinPitch, min(pitch, maxPitch))
    241 
    242     def GetShipOffset(self):
    243         if self.model is None:
    244             return (0.0, 0.0, 0.0)
    245         localBB = self.model.GetLocalBoundingBox()
    246         height = abs(localBB[0][0])
    247         width = abs(localBB[0][2])
    248         return (0.0, height, width)
    249 
    250     def _AnimEnterHangarYaw(self, duration):
    251         pass
    252 
    253     def _AnimEnterHangarPitch(self, duration):
    254         pass
    255 
    256     def AnimSwitchShips(self, model, startPos, endPos, duration = 5.0):
    257         pass
    258 
    259     def Orbit(self, *args):
    260         BaseSpaceCamera.Orbit(self, *args)
    261         uicore.animations.StopAnimation(self, 'yaw')
    262         uicore.animations.StopAnimation(self, 'pitch')
    263 
    264     def OnDeactivated(self):
    265         BaseSpaceCamera.OnDeactivated(self)
    266         self.model = None
    267 
    268     def Update(self):
    269         BaseSpaceCamera.Update(self)
    270         if self.model and self.model.translationCurve:
    271             if self.changingShip:
    272                 self._updateShipChangeLocations()
    273                 self.EnforceMaxZoom()
    274             else:
    275                 self._UpdateFocalPoint()
    276                 self.EnforceMaxZoom()
    277 
    278     def GetIsChangingShip(self):
    279         if self.changingShip or not self.phase2finished:
    280             return True
    281         return False
    282 
    283     def _updateShipChangeLocations(self):
    284         remappedTimings = hc.TRANSITION_TIME_REMAP
    285         swapDuration = hc.SHIP_SWAP_DURATION
    286         phase1Padding = hc.TRANSITION_PADDING
    287         if hc.TRANSITION_MODIFY_BY_HALLWAYTIME:
    288             swapDuration = 0.7 * swapDuration + 0.3 * swapDuration * self.hallwayTime
    289             phase1Padding = 0.7 * phase1Padding + 0.3 * phase1Padding * self.hallwayTime
    290         elapsedDuration = GetSecondsSinceSimTime(self.fpShipSpawnTime)
    291         travelProgress = min(elapsedDuration / swapDuration, 1.0)
    292 
    293         def _EndShipSwapping():
    294             self.changingShip = False
    295             self.zoomFactor = hc.PHASE_2_END_ZOOM_LEVEL
    296             self.transitionAnimationEndedTime = GetSimTime()
    297             cameraSpeed = hc.CAMERA_FOLLOW_SPEED / 100.0
    298             lerpedTarget = geo2.Vec3Lerp(self.GetEyePosition(), self.targetPoint, cameraSpeed)
    299             self.camSpeed = geo2.Vec3Subtract(lerpedTarget, self.GetEyePosition())
    300             self.phase2finished = False
    301 
    302         def _Relevancy(startRelevancy, endRelevancy, boost = 1.0):
    303             if boost is 0.0:
    304                 return 0.0
    305             spikeTime = endRelevancy - startRelevancy
    306             frontSpike = min(max(travelProgress - startRelevancy, 0.0) / spikeTime, 0.5)
    307             backSpike = min(max(travelProgress - (endRelevancy - spikeTime / 2.0), 0.0) / spikeTime, 0.5)
    308             return boost * pow(max(frontSpike - backSpike, 0.0), 1 + hc.PATH_BELL_CURVE_CONST / 100)
    309 
    310         points = [hc.PATH_ORIGINAL_POSITION_RELEVANCY,
    311          hc.PATH_FIRST_EXIT_RELEVANCY,
    312          hc.PATH_FIRST_HALLWAY_POINT_RELEVANCY,
    313          hc.PATH_END_HALLWAY_POINT_RELEVANCY,
    314          hc.PATH_END_EXIT_RELEVANCY,
    315          hc.PATH_END_DOCK_POINT_RELEVANCY]
    316         progressMap = []
    317         for point in points:
    318             progressMap.append(_Relevancy(point[0], point[1], point[2]))
    319 
    320         targetPoint = (0.0, 0.0, 0.0)
    321         for i, each in enumerate(self.flightValueMap):
    322             if progressMap[i] != 0:
    323                 addition = geo2.Vec3Scale(each, progressMap[i])
    324                 targetPoint = geo2.Vec3Add(targetPoint, addition)
    325 
    326         total = sum(progressMap)
    327         if total == 0:
    328             return
    329         self.targetPoint = geo2.Vec3Scale(targetPoint, 1 / total)
    330         if elapsedDuration > swapDuration:
    331             swapThreshold = pow(hc.PHASE_2_START_THRESHOLD * max(self.model.generatedShapeEllipsoidRadius), 2)
    332             if geo2.Vec3DistanceSqD(self.GetEyePosition(), self.targetPoint) < swapThreshold:
    333                 _EndShipSwapping()
    334             elif elapsedDuration > swapDuration + phase1Padding:
    335                 _EndShipSwapping()
    336         targetShipPos = self._CalculateFocalPoint(self.model)
    337         remappedTravelProgress = min(max(travelProgress - remappedTimings[0], 0.0) / (remappedTimings[1] - remappedTimings[0]), 1.0)
    338         if remappedTravelProgress < hc.FP_SWAP_TIMING:
    339             lerpValue = hc.FP_SWAP_VALUE * pow(1 / hc.FP_SWAP_TIMING * remappedTravelProgress, hc.FP_SWAP_SPEED)
    340         else:
    341             reductionValue = max(2 * hc.FP_SWAP_TIMING - remappedTravelProgress, 0.0)
    342             reduction = (1 - hc.FP_SWAP_VALUE) * pow(1 / hc.FP_SWAP_TIMING * reductionValue, hc.FP_SWAP_SPEED)
    343             lerpValue = 1 - reduction
    344         linearPointRelevancy = 1.0 - 0.2 * (0.5 - abs(0.5 - lerpValue))
    345         if lerpValue < 0.5:
    346             lerpValue = 2 * pow(lerpValue, 2.0)
    347         else:
    348             ajustedLerpValue = lerpValue - 0.5
    349             lerpValue = 0.5 + 2 * ajustedLerpValue * (1 - ajustedLerpValue)
    350         linearPoint = geo2.Vec3Lerp(self.lastShipLocation, targetShipPos, lerpValue)
    351         superFloor = geo2.Vec3Add(geo2.Vec3Lerp(self.lastShipLocation, targetShipPos, 0.5), (0.0, -(500.0 + 500 * self.hallwayTime), 0.0))
    352         FPtarget = geo2.Vec3Lerp(superFloor, linearPoint, linearPointRelevancy)
    353         self.atPosition = FPtarget
    354 
    355     def _UpdateFocalPoint(self):
    356         if self.changingSkinsTime != 0:
    357             totalDuration = 5.0
    358             elapsedTime = GetSecondsSinceSimTime(self.changingSkinsTime)
    359             lerpValue = 0.05 * (elapsedTime / totalDuration)
    360             self.atPosition = geo2.Vec3Lerp(self.atPosition, self._CalculateFocalPoint(self.model), lerpValue)
    361             timeSinceHangarEntry = GetSecondsSinceSimTime(self.hangarEntryTime)
    362             if elapsedTime > totalDuration or timeSinceHangarEntry < 5.0:
    363                 self.changingSkinsTime = 0
    364         else:
    365             self.atPosition = self._CalculateFocalPoint(self.model)
    366 
    367     def _CalculateFocalPoint(self, model):
    368         if model is None or model.translationCurve is None:
    369             return (0.0, 0.0, 0.0)
    370         modelTranslation = model.translationCurve.currentValue
    371         centerOffset = model.generatedShapeEllipsoidCenter
    372         rotatedCenterOffset = geo2.QuaternionTransformVector(self.model.rotationCurve.currentValue, centerOffset)
    373         return geo2.Add(modelTranslation, rotatedCenterOffset)
    374 
    375     def SetMinMaxZoomDefaults(self, minZoom, maxZoom):
    376         pass
    377 
    378     def SetHangarAnimationParameters(self, yaw, pitch, zoom, fov):
    379         pass
    380 
    381     def Zoom(self, dz):
    382         if self.zoomTarget is None:
    383             self.zoomTarget = self.zoomFactor
    384         self.zoomTarget = max(min(1.0, self.zoomTarget + 0.5 * dz), 0.0)
    385         if not self.zoomUpdateThread:
    386             self.zoomUpdateThread = uthread.new(self.ZoomUpdateThread)
    387 
    388     def SetZoomTarget(self, proportion):
    389         pass
    390 
    391     def ZoomUpdateThread(self):
    392         try:
    393             while True:
    394                 if self.zoomTarget is None:
    395                     break
    396                 distLeft = self.zoomTarget - self.zoomFactor
    397                 if not distLeft:
    398                     break
    399                 zoomSpeed = self._GetZoomSpeed()
    400                 moveProp = zoomSpeed / blue.os.fps
    401                 if math.fabs(distLeft) < self.kZoomStopDist:
    402                     moveProp *= self.kZoomStopDist / math.fabs(distLeft)
    403                 moveProp = min(moveProp, 1.0)
    404                 self.zoomFactor += distLeft * moveProp
    405                 self.SetZoom(self.zoomFactor)
    406                 if moveProp == 1.0:
    407                     break
    408                 self.SetPitch(self.GetPitch())
    409                 blue.synchro.Yield()
    410 
    411         finally:
    412             self.zoomUpdateThread = None
    413             self.zoomTarget = None